Browse Source

mobile optimisations - add mobile mode toggle button to left menu (WIP)

pull/4898/head
Daniel Spaude 2 years ago
parent
commit
0b9fe01d4e
No known key found for this signature in database
GPG Key ID: 654A3D1FA4F35FFE
  1. 1
      packages/nc-gui/components.d.ts
  2. 9
      packages/nc-gui/components/smartsheet/Toolbar.vue
  3. 38
      packages/nc-gui/components/smartsheet/qr-scanner-button/QrScannerButton.vue
  4. 6
      packages/nc-gui/composables/useGlobal/actions.ts
  5. 3
      packages/nc-gui/composables/useGlobal/state.ts
  6. 2
      packages/nc-gui/composables/useGlobal/types.ts
  7. 6
      packages/nc-gui/lang/en.json
  8. 31
      packages/nc-gui/pages/[projectType]/[projectId]/index.vue

1
packages/nc-gui/components.d.ts vendored

@ -102,6 +102,7 @@ declare module '@vue/runtime-core' {
MaterialSymbolsFileCopyOutline: typeof import('~icons/material-symbols/file-copy-outline')['default']
MaterialSymbolsKeyboardReturn: typeof import('~icons/material-symbols/keyboard-return')['default']
MaterialSymbolsLightModeOutline: typeof import('~icons/material-symbols/light-mode-outline')['default']
MaterialSymbolsMobileFriendly: typeof import('~icons/material-symbols/mobile-friendly')['default']
MaterialSymbolsRocketLaunchOutline: typeof import('~icons/material-symbols/rocket-launch-outline')['default']
MaterialSymbolsSendOutline: typeof import('~icons/material-symbols/send-outline')['default']
MaterialSymbolsTranslate: typeof import('~icons/material-symbols/translate')['default']

9
packages/nc-gui/components/smartsheet/Toolbar.vue

@ -14,8 +14,11 @@ const { allowCSVDownload } = useSharedView()
<template>
<div class="nc-table-toolbar w-full py-1 flex gap-2 items-center px-2 border-b overflow-x-hidden flex-wrap" style="z-index: 7">
<LazySmartsheetToolbarViewActions v-if="(isGrid || isGallery || isKanban) && !isPublic && isUIAllowed('dataInsert')"
:show-system-fields="false" class="ml-1" />
<LazySmartsheetToolbarViewActions
v-if="(isGrid || isGallery || isKanban) && !isPublic && isUIAllowed('dataInsert')"
:show-system-fields="false"
class="ml-1"
/>
<LazySmartsheetToolbarViewInfo v-if="!isUIAllowed('dataInsert') && !isPublic" />
@ -31,7 +34,7 @@ const { allowCSVDownload } = useSharedView()
<LazySmartsheetToolbarShareView v-if="(isForm || isGrid || isKanban || isGallery) && !isPublic" />
<LazySmartsheetQrScannerButton />
<LazySmartsheetQrScannerButton v-if="isGrid || isKanban || isGallery" />
<LazySmartsheetToolbarExport v-if="(!isPublic && !isUIAllowed('dataInsert')) || (isPublic && allowCSVDownload)" />
<div class="flex-1" />

38
packages/nc-gui/components/smartsheet/qr-scanner-button/QrScannerButton.vue

@ -7,6 +7,7 @@ import QrCodeScan from '~icons/mdi/qrcode-scan'
const meta = inject(MetaInj, ref())
const { t } = useI18n()
const route = useRoute()
const router = useRouter()
@ -15,18 +16,15 @@ const { project } = useProject()
const view = inject(ActiveViewInj, ref())
const codeFieldOptions = ref<SelectProps['options']>([])
onBeforeMount(init)
async function init() {
codeFieldOptions.value = meta?.value?.columns!.map((field) => {
return {
value: field.id,
label: field.title,
}
})
}
const codeFieldOptions = computed<SelectProps['options']>(
() =>
meta?.value?.columns!.map((field) => {
return {
value: field.id,
label: field.title,
}
}) || [],
)
const showCodeScannerOverlay = ref(false)
@ -66,11 +64,11 @@ const onDecode = async (codeValue: string) => {
}, 4000)
if (foundRowsForCode.length === 0) {
// extract into localisation file
message.info(`No row found for this code for column '${nameOfSelectedColumnToScanFor}'.`)
message.info(t('msg.info.codeScanner.noRowFoundForCode'))
}
if (foundRowsForCode.length > 1) {
// extract into localisation file
message.warn('More than one row found for this code. Currently only unique codes are supported.')
message.warn(t('msg.info.codeScanner.moreThanOneRowFoundForCode'))
}
return
}
@ -89,7 +87,6 @@ const onDecode = async (codeValue: string) => {
console.error(error)
}
}
</script>
<template>
@ -102,7 +99,6 @@ const onDecode = async (codeValue: string) => {
</a-button>
<a-modal
v-model:visible="showCodeScannerOverlay"
:class="{ active: showCodeScannerOverlay }"
:closable="false"
width="28rem"
centered
@ -113,21 +109,17 @@ const onDecode = async (codeValue: string) => {
>
<div class="relative flex flex-col h-full">
<a-form-item :label="$t('labels.columnToScanFor')">
<a-select
v-model:value="selectedCodeColumnIdToScanFor"
class="w-full"
:options="codeFieldOptions"
placeholder="Select a Code Field (QR or Barcode)"
/>
<a-select v-model:value="selectedCodeColumnIdToScanFor" class="w-full" :options="codeFieldOptions" />
</a-form-item>
<div>
<StreamBarcodeReader v-show="showScannerField" @decode="onDecode" @loaded="onLoaded"></StreamBarcodeReader>
<div v-if="showPleaseSelectColumnMessage" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
Please select a column
{{ $t('msg.info.codeScanner.selectColumn') }}
</div>
<div v-if="showScannerIsLoadingMessage" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
Loading the scanner...
{{ $t('msg.info.codeScanner.loadingScanner') }}
</div>
</div>
</div>

6
packages/nc-gui/composables/useGlobal/actions.ts

@ -2,6 +2,10 @@ import type { Actions, State } from './types'
import { message, useNuxtApp } from '#imports'
export function useGlobalActions(state: State): Actions {
const setIsMobileMode = (isMobileMode: boolean) => {
state.isMobileMode.value = isMobileMode
}
/** Sign out by deleting the token from localStorage */
const signOut: Actions['signOut'] = () => {
state.token.value = null
@ -43,5 +47,5 @@ export function useGlobalActions(state: State): Actions {
})
}
return { signIn, signOut, refreshToken }
return { signIn, signOut, refreshToken, setIsMobileMode }
}

3
packages/nc-gui/composables/useGlobal/state.ts

@ -114,6 +114,8 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
/** our local user object */
const user = ref<User | null>(null)
const isMobileMode = ref<boolean>(false)
return {
...toRefs(storage.value),
storage,
@ -124,5 +126,6 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
error,
user,
appInfo,
isMobileMode,
}
}

2
packages/nc-gui/composables/useGlobal/types.ts

@ -49,6 +49,7 @@ export type State = ToRefs<Omit<StoredState, 'token'>> & {
runningRequests: ReturnType<typeof useCounter>
error: Ref<any>
appInfo: Ref<AppInfo>
isMobileMode: Ref<boolean>
}
export interface Getters {
@ -60,6 +61,7 @@ export interface Actions {
signOut: () => void
signIn: (token: string) => void
refreshToken: () => void
setIsMobileMode: (isMobileMode: boolean) => void
}
export type ReadonlyState = Readonly<Pick<State, 'token' | 'user'>> & Omit<State, 'token' | 'user'>

6
packages/nc-gui/lang/en.json

@ -515,6 +515,12 @@
"orgCreator": "Creator can create new projects and access any invited project.",
"orgViewer": "Viewer is not allowed to create new projects but they can access any invited project."
},
"codeScanner": {
"loadingScanner": "Loading the scanner...",
"selectColumn": "Please select a column",
"moreThanOneRowFoundForCode": "More than one row found for this code. Currently only unique codes are supported.",
"noRowFoundForCode": "No row found for this code for the selected column"
},
"footerInfo": "Rows per page",
"upload": "Select file to Upload",
"upload_sub": "or drag and drop file",

31
packages/nc-gui/pages/[projectType]/[projectId]/index.vue

@ -44,7 +44,7 @@ const route = useRoute()
const router = useRouter()
const { appInfo, token, signOut, signedIn, user, currentVersion } = useGlobal()
const { appInfo, token, signOut, signedIn, user, currentVersion, isMobileMode, setIsMobileMode } = useGlobal()
const { project, isSharedBase, loadProjectMetaInfo, projectMetaInfo, saveTheme, loadProject, reset } = useProject()
@ -352,7 +352,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<!-- Swagger: Rest APIs -->
<a-menu-item key="api">
<div
v-if="isUIAllowed('apiDocs')"
v-if="isUIAllowed('apiDocs') && !isMobileMode"
v-e="['e:api-docs']"
class="nc-project-menu-item group"
@click.stop="openLink(`/api/v1/db/meta/projects/${route.params.projectId}/swagger`, appInfo.ncSiteUrl)"
@ -364,7 +364,12 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<!-- Copy Auth Token -->
<a-menu-item key="copy">
<div v-e="['a:navbar:user:copy-auth-token']" class="nc-project-menu-item group" @click.stop="copyAuthToken">
<div
v-if="!isMobileMode"
v-e="['a:navbar:user:copy-auth-token']"
class="nc-project-menu-item group"
@click.stop="copyAuthToken"
>
<MdiScriptTextKeyOutline class="group-hover:text-accent" />
{{ $t('activity.account.authToken') }}
</div>
@ -375,7 +380,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<!-- Team & Settings -->
<a-menu-item key="teamAndSettings">
<div
v-if="isUIAllowed('settings')"
v-if="isUIAllowed('settings') && !isMobileMode"
v-e="['c:navdraw:project-settings']"
class="nc-project-menu-item group"
@click="toggleDialog(true, 'teamAndAuth')"
@ -385,6 +390,20 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
</div>
</a-menu-item>
<!-- Mobile Mode -->
<a-menu-item key="mobile-mode">
<div
v-e="['e:set-mobile-mode']"
class="nc-project-menu-item group"
@click.stop="setIsMobileMode(!isMobileMode)"
>
<MaterialSymbolsMobileFriendly class="group-hover:text-accent" />
Toggle Mobile Mode
<!-- {{ $t('activity.account.swagger') }} -->
<!-- TODO: use i18n here -->
</div>
</a-menu-item>
<!-- Theme -->
<template v-if="isUIAllowed('projectTheme')">
<a-sub-menu key="theme">
@ -462,7 +481,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-divider />
<!-- Preview As -->
<a-sub-menu v-if="isUIAllowed('previewAs')" key="preview-as">
<a-sub-menu v-if="isUIAllowed('previewAs') && !isMobileMode" key="preview-as">
<template #title>
<div v-e="['c:navdraw:preview-as']" class="nc-project-menu-item group">
<MdiFileEyeOutline class="group-hover:text-accent" />
@ -589,7 +608,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
.nc-left-sidebar {
.nc-sidebar-left-toggle-icon {
@apply opacity-0 transition-opactity duration-200 transition-color text-white/80 hover:text-white/100;
@apply opacity-0 transition-opactity duration-200 transition-color text-white/80 hover: text-white/100;
.nc-left-sidebar {
@apply !border-r-0;

Loading…
Cancel
Save