Browse Source

feat(gui): improve row navigation option in expanded form

- Add tooltip
- Show warning if out of bound
- Hide option from nested
- Implement it in Gallery view

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4861/head
Pranav C 2 years ago
parent
commit
90bfa2dec2
  1. 5
      packages/nc-gui/components/smartsheet/Gallery.vue
  2. 51
      packages/nc-gui/components/smartsheet/Grid.vue
  3. 19
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  4. 12
      packages/nc-gui/composables/useSharedView.ts
  5. 52
      packages/nc-gui/composables/useViewData.ts
  6. 7
      packages/nc-gui/lang/en.json
  7. 5
      packages/nc-gui/lib/enums.ts

5
packages/nc-gui/components/smartsheet/Gallery.vue

@ -13,6 +13,7 @@ import {
ReloadRowDataHookInj,
ReloadViewDataHookInj,
ReloadViewMetaHookInj,
RowNavDir,
computed,
createEventHook,
extractPkFromRow,
@ -48,6 +49,7 @@ const {
galleryData,
changePage,
addEmptyRow,
navigateToSiblingRow,
} = useViewData(meta, view)
provide(IsFormInj, ref(false))
@ -270,6 +272,9 @@ watch(view, async (nextView) => {
:meta="meta"
:row-id="route.query.rowId"
:view="view"
show-next-prev-icons
@next="navigateToSiblingRow(RowNavDir.NEXT)"
@prev="navigateToSiblingRow(RowNavDir.PREV)"
/>
</Suspense>
</div>

51
packages/nc-gui/components/smartsheet/Grid.vue

@ -17,6 +17,7 @@ import {
ReadonlyInj,
ReloadRowDataHookInj,
ReloadViewDataHookInj,
RowNavDir,
SmartsheetStoreEvents,
computed,
createEventHook,
@ -117,6 +118,7 @@ const {
deleteSelectedRows,
selectedAllRecords,
removeRowIfNew,
navigateToSiblingRow,
} = useViewData(meta, view, xWhere)
const { getMeta } = useMetas()
@ -638,50 +640,6 @@ const closeAddColumnDropdown = () => {
columnOrder.value = null
addColumnDropdown.value = false
}
enum NavDir {
NEXT,
PREV,
}
const navigateToSiblingRow = async (dir: NavDir) => {
// get current expanded row index
const expandedRowIndex = data.value.findIndex(
(row) => routeQuery.rowId === extractPkFromRow(row.row, meta.value?.columns as ColumnType[]),
)
// calculate next row index based on direction
let siblingRowIndex = expandedRowIndex + (dir === NavDir.NEXT ? 1 : -1)
const currentPage = paginationData?.value?.page || 1
// if next row index is less than 0, go to previous page and point to last element
if (siblingRowIndex < 0) {
// if first page, do nothing
if (currentPage === 1) return
await changePage(currentPage - 1)
siblingRowIndex = data.value.length - 1
// if next row index is greater than total rows in current view
// then load next page of data and set next row index to 0
} else if (siblingRowIndex >= data.value.length) {
siblingRowIndex = 0
await changePage(currentPage + 1)
}
// extract the row id of the sibling row
const rowId = extractPkFromRow(data.value[siblingRowIndex].row, meta.value?.columns as ColumnType[])
if (rowId) {
router.push({
query: {
...routeQuery,
rowId,
},
})
}
}
</script>
<template>
@ -962,8 +920,9 @@ const navigateToSiblingRow = async (dir: NavDir) => {
:meta="meta"
:row-id="routeQuery.rowId"
:view="view"
@next="navigateToSiblingRow(NavDir.NEXT)"
@prev="navigateToSiblingRow(NavDir.PREV)"
show-next-prev-icons
@next="navigateToSiblingRow(RowNavDir.NEXT)"
@prev="navigateToSiblingRow(RowNavDir.PREV)"
/>
</Suspense>
</div>

19
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -32,11 +32,12 @@ interface Props {
useMetaFields?: boolean
rowId?: string
view?: ViewType
showNextPrevIcons?: boolean
}
const props = defineProps<Props>()
const emits = defineEmits(['update:modelValue', 'cancel'])
const emits = defineEmits(['update:modelValue', 'cancel', 'next', 'prev'])
const row = ref(props.row)
@ -150,8 +151,20 @@ export default {
<SmartsheetExpandedFormHeader :view="props.view" @cancel="onClose" />
<div class="!bg-gray-100 rounded flex-1 relative">
<MdiChevronRight class="cursor-pointer nc-next-arrow" @click="$emit('next')" />
<MdiChevronLeft class="cursor-pointer nc-prev-arrow" @click="$emit('prev')" />
<template v-if="props.showNextPrevIcons">
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.nextRow') }}
</template>
<MdiChevronRight class="cursor-pointer nc-next-arrow" @click="$emit('next')" />
</a-tooltip>
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.prevRow') }}
</template>
<MdiChevronLeft class="cursor-pointer nc-prev-arrow" @click="$emit('prev')" />
</a-tooltip>
</template>
<div class="flex h-full nc-form-wrapper items-stretch min-h-[max(70vh,100%)]">
<div class="flex-1 overflow-auto scrollbar-thin-dull nc-form-fields-container">

12
packages/nc-gui/composables/useSharedView.ts

@ -1,14 +1,4 @@
import type {
Api,
ExportTypes,
FilterType,
KanbanType,
PaginatedType,
RequestParams,
SortType,
TableType,
ViewType,
} from 'nocodb-sdk'
import type { ExportTypes, FilterType, KanbanType, PaginatedType, RequestParams, SortType, TableType, ViewType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import { computed, useGlobal, useMetas, useNuxtApp, useState } from '#imports'

52
packages/nc-gui/composables/useViewData.ts

@ -4,6 +4,7 @@ import type { ComputedRef, Ref } from 'vue'
import {
IsPublicInj,
NOCO,
RowNavDir,
computed,
extractPkFromRow,
extractSdkResponseErrorMsg,
@ -18,6 +19,8 @@ import {
useMetas,
useNuxtApp,
useProject,
useRoute,
useRouter,
useSharedView,
useSmartsheetStoreOrThrow,
useUIPermission,
@ -44,6 +47,10 @@ export function useViewData(
const { api, isLoading, error } = useApi()
const router = useRouter()
const route = useRoute()
const { appInfo } = $(useGlobal())
const { getMeta } = useMetas()
@ -74,6 +81,8 @@ export function useViewData(
const { isUIAllowed } = useUIPermission()
const routeQuery = $computed(() => route.query as Record<string, string>)
const paginationData = computed({
get: () => (isPublic.value ? sharedPaginationData.value : _paginationData.value),
set: (value) => {
@ -469,6 +478,48 @@ export function useViewData(
}
}
const navigateToSiblingRow = async (dir: RowNavDir) => {
// get current expanded row index
const expandedRowIndex = formattedData.value.findIndex(
(row: Row) => routeQuery.rowId === extractPkFromRow(row.row, meta.value?.columns as ColumnType[]),
)
// calculate next row index based on direction
let siblingRowIndex = expandedRowIndex + (dir === RowNavDir.NEXT ? 1 : -1)
const currentPage = paginationData?.value?.page || 1
// if next row index is less than 0, go to previous page and point to last element
if (siblingRowIndex < 0) {
// if first page, do nothing
if (currentPage === 1) return message.info(t('msg.info.noMoreRecords'))
await changePage(currentPage - 1)
siblingRowIndex = formattedData.value.length - 1
// if next row index is greater than total rows in current view
// then load next page of formattedData and set next row index to 0
} else if (siblingRowIndex >= formattedData.value.length) {
console.log(paginationData?.value)
if (paginationData?.value?.isLastPage) return message.info(t('msg.info.noMoreRecords'))
await changePage(currentPage + 1)
siblingRowIndex = 0
}
// extract the row id of the sibling row
const rowId = extractPkFromRow(formattedData.value[siblingRowIndex].row, meta.value?.columns as ColumnType[])
if (rowId) {
router.push({
query: {
...routeQuery,
rowId,
},
})
}
}
return {
error,
isLoading,
@ -496,5 +547,6 @@ export function useViewData(
loadAggCommentsCount,
removeLastEmptyRow,
removeRowIfNew,
navigateToSiblingRow,
}
}

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

@ -312,7 +312,9 @@
"signInWithGoogle": "Sign in with Google",
"agreeToTos": "By signing up, you agree to the Terms of Service",
"welcomeToNc": "Welcome to NocoDB!",
"inviteOnlySignup": "Allow signup only using invite url"
"inviteOnlySignup": "Allow signup only using invite url",
"nextRow": "Next Row",
"prevRow": "Previous Row"
},
"activity": {
"createProject": "Create Project",
@ -629,7 +631,8 @@
"showM2mTables": "Show M2M Tables",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content."
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",
"noMoreRecords": "No more records"
},
"error": {
"searchProject": "Your search for {search} found no results",

5
packages/nc-gui/lib/enums.ts

@ -98,3 +98,8 @@ export enum DataSourcesSubTab {
Misc = 'Misc',
Edit = 'Edit',
}
export enum RowNavDir {
NEXT,
PREV,
}

Loading…
Cancel
Save