Browse Source

fix: Show skelton loader immediatly when a table is opened

pull/7063/head
Muhammed Mustafa 11 months ago
parent
commit
3b4b15d57f
  1. 9
      packages/nc-gui/components/dashboard/TreeView/TableNode.vue
  2. 8
      packages/nc-gui/components/smartsheet/Pagination.vue
  3. 25
      packages/nc-gui/components/smartsheet/grid/Table.vue
  4. 9
      packages/nc-gui/composables/useTableNew.ts
  5. 2
      packages/nc-gui/composables/useViewData.ts
  6. 8
      packages/nc-gui/lib/types.ts
  7. 3
      packages/nc-gui/store/tables.ts
  8. 8
      packages/nc-gui/store/views.ts

9
packages/nc-gui/components/dashboard/TreeView/TableNode.vue

@ -5,11 +5,12 @@ import { message } from 'ant-design-vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { ProjectRoleInj, TreeViewInj, useNuxtApp, useRoles, useTabs } from '#imports' import { ProjectRoleInj, TreeViewInj, useNuxtApp, useRoles, useTabs } from '#imports'
import type { SidebarTableNode } from '~/lib'
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
base: BaseType base: BaseType
table: TableType & { isViewsLoading?: boolean } table: SidebarTableNode
sourceIndex: number sourceIndex: number
}>(), }>(),
{ sourceIndex: 0 }, { sourceIndex: 0 },
@ -44,7 +45,7 @@ provide(SidebarTableInj, table)
const { setMenuContext, openRenameTableDialog, duplicateTable } = inject(TreeViewInj)! const { setMenuContext, openRenameTableDialog, duplicateTable } = inject(TreeViewInj)!
const { loadViews: _loadViews } = useViewsStore() const { loadViews: _loadViews } = useViewsStore()
const { activeView } = storeToRefs(useViewsStore()) const { activeView, activeViewTitleOrId } = storeToRefs(useViewsStore())
const { isLeftSidebarOpen } = storeToRefs(useSidebarStore()) const { isLeftSidebarOpen } = storeToRefs(useSidebarStore())
// todo: temp // todo: temp
@ -135,7 +136,7 @@ watch(
) )
const isTableOpened = computed(() => { const isTableOpened = computed(() => {
return openedTableId.value === table.value?.id && activeView.value?.is_default return openedTableId.value === table.value?.id && (activeView.value?.is_default || !activeViewTitleOrId.value)
}) })
</script> </script>
@ -176,7 +177,7 @@ const isTableOpened = computed(() => {
> >
<GeneralLoader <GeneralLoader
v-if="table.isViewsLoading" v-if="table.isViewsLoading"
class="flex w-4 h-4 !text-gray-600" class="flex w-4 h-4 !text-gray-600 !mt-0.75"
:class="{ :class="{
'!visible': !isExpanded, '!visible': !isExpanded,
}" }"

8
packages/nc-gui/components/smartsheet/Pagination.vue

@ -48,15 +48,15 @@ const size = computed(() => vPaginationData.value?.pageSize ?? 25)
const page = computed({ const page = computed({
get: () => vPaginationData?.value?.page ?? 1, get: () => vPaginationData?.value?.page ?? 1,
set: async (p) => { set: async (p) => {
isViewDataLoading.value = true isPaginationLoading.value = true
try { try {
await changePage?.(p) await changePage?.(p)
isViewDataLoading.value = false isPaginationLoading.value = false
} catch (e) { } catch (e) {
if (axios.isCancel(e)) { if (axios.isCancel(e)) {
return return
} }
isViewDataLoading.value = false isPaginationLoading.value = false
} }
}, },
}) })
@ -100,7 +100,7 @@ const renderAltOrOptlKey = () => {
'ml-8': alignLeft, 'ml-8': alignLeft,
}" }"
> >
<div v-if="isPaginationLoading" class="flex flex-row justify-center item-center min-h-10 min-w-42"> <div v-if="isViewDataLoading" class="flex flex-row justify-center item-center min-h-10 min-w-42">
<a-skeleton :active="true" :title="true" :paragraph="false" class="-mt-1 max-w-60" /> <a-skeleton :active="true" :title="true" :paragraph="false" class="-mt-1 max-w-60" />
</div> </div>
<NcPagination <NcPagination

25
packages/nc-gui/components/smartsheet/grid/Table.vue

@ -1120,22 +1120,6 @@ onBeforeUnmount(async () => {
reloadViewDataHook?.on(reloadViewDataHandler) reloadViewDataHook?.on(reloadViewDataHandler)
openNewRecordFormHook?.on(openNewRecordHandler) openNewRecordFormHook?.on(openNewRecordHandler)
// TODO: Use CSS animations
const showLoaderAfterDelay = ref(false)
watch([isViewDataLoading, showSkeleton, isPaginationLoading], () => {
if (!isViewDataLoading.value && !showSkeleton.value && !isPaginationLoading.value) {
showLoaderAfterDelay.value = false
return
}
showLoaderAfterDelay.value = false
setTimeout(() => {
showLoaderAfterDelay.value = true
}, 500)
})
// #Watchers // #Watchers
// reset context menu target on hide // reset context menu target on hide
@ -1226,7 +1210,7 @@ const handleCellClick = (event: MouseEvent, row: number, col: number) => {
} }
const loaderText = computed(() => { const loaderText = computed(() => {
if (isViewDataLoading.value) { if (isPaginationLoading.value) {
if (paginationDataRef.value?.totalRows && paginationDataRef.value?.pageSize) { if (paginationDataRef.value?.totalRows && paginationDataRef.value?.pageSize) {
return `Loading page<br/>${paginationDataRef.value.page} of ${Math.ceil( return `Loading page<br/>${paginationDataRef.value.page} of ${Math.ceil(
paginationDataRef.value?.totalRows / paginationDataRef.value?.pageSize, paginationDataRef.value?.totalRows / paginationDataRef.value?.pageSize,
@ -1265,10 +1249,7 @@ onKeyStroke('ArrowDown', onDown)
></div> ></div>
</div> </div>
<div ref="gridWrapper" class="nc-grid-wrapper min-h-0 flex-1 relative" :class="gridWrapperClass"> <div ref="gridWrapper" class="nc-grid-wrapper min-h-0 flex-1 relative" :class="gridWrapperClass">
<div <div v-show="isPaginationLoading" class="flex items-center justify-center absolute l-0 t-0 w-full h-full z-10 pb-10">
v-show="showSkeleton && !isPaginationLoading && showLoaderAfterDelay"
class="flex items-center justify-center absolute l-0 t-0 w-full h-full z-10 pb-10"
>
<div class="flex flex-col justify-center gap-2"> <div class="flex flex-col justify-center gap-2">
<GeneralLoader size="xlarge" /> <GeneralLoader size="xlarge" />
<span class="text-center" v-html="loaderText"></span> <span class="text-center" v-html="loaderText"></span>
@ -1793,7 +1774,7 @@ onKeyStroke('ArrowDown', onDown)
:extra-style="paginationStyleRef?.extraStyle" :extra-style="paginationStyleRef?.extraStyle"
> >
<template #add-record> <template #add-record>
<div v-if="isAddingEmptyRowAllowed" class="flex ml-1"> <div v-if="isAddingEmptyRowAllowed && !showSkeleton && !isPaginationLoading" class="flex ml-1">
<NcButton <NcButton
v-if="isMobileMode" v-if="isMobileMode"
v-e="[isAddNewRecordGridMode ? 'c:row:add:grid' : 'c:row:add:form']" v-e="[isAddNewRecordGridMode ? 'c:row:add:grid' : 'c:row:add:form']"

9
packages/nc-gui/composables/useTableNew.ts

@ -1,5 +1,7 @@
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isSystemColumn } from 'nocodb-sdk' import { UITypes, isSystemColumn } from 'nocodb-sdk'
import type { SidebarTableNode } from '~/lib'
import { import {
Modal, Modal,
SYSTEM_COLUMNS, SYSTEM_COLUMNS,
@ -58,12 +60,7 @@ export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => v
const tables = computed(() => baseTables.value.get(param.baseId) || []) const tables = computed(() => baseTables.value.get(param.baseId) || [])
const base = computed(() => bases.value.get(param.baseId)) const base = computed(() => bases.value.get(param.baseId))
const openTable = async ( const openTable = async (table: SidebarTableNode) => {
table: TableType & {
isMetaLoading?: boolean
isViewsLoading?: boolean
},
) => {
if (!table.base_id) return if (!table.base_id) return
let base = bases.value.get(table.base_id) let base = bases.value.get(table.base_id)

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

@ -190,6 +190,8 @@ export function useViewData(
controller.value = CancelToken.source() controller.value = CancelToken.source()
isPaginationLoading.value = true
const response = !isPublic.value const response = !isPublic.value
? await api.dbViewRow.list( ? await api.dbViewRow.list(
'noco', 'noco',

8
packages/nc-gui/lib/types.ts

@ -1,4 +1,4 @@
import type { BaseType, ColumnType, FilterType, MetaType, PaginatedType, Roles, RolesObj, ViewTypes } from 'nocodb-sdk' import type { BaseType, ColumnType, FilterType, MetaType, PaginatedType, Roles, RolesObj, TableType, ViewTypes } from 'nocodb-sdk'
import type { I18n } from 'vue-i18n' import type { I18n } from 'vue-i18n'
import type { Theme as AntTheme } from 'ant-design-vue/es/config-provider' import type { Theme as AntTheme } from 'ant-design-vue/es/config-provider'
import type { UploadFile } from 'ant-design-vue' import type { UploadFile } from 'ant-design-vue'
@ -171,6 +171,11 @@ type ViewPageType = 'view' | 'webhook' | 'api' | 'field' | 'relation'
type NcButtonSize = 'xxsmall' | 'xsmall' | 'small' | 'medium' type NcButtonSize = 'xxsmall' | 'xsmall' | 'small' | 'medium'
interface SidebarTableNode extends TableType {
isMetaLoading?: boolean
isViewsLoading?: boolean
}
export { export {
User, User,
ProjectMetaInfo, ProjectMetaInfo,
@ -195,4 +200,5 @@ export {
Users, Users,
ViewPageType, ViewPageType,
NcButtonSize, NcButtonSize,
SidebarTableNode,
} }

3
packages/nc-gui/store/tables.ts

@ -1,6 +1,7 @@
import { acceptHMRUpdate, defineStore } from 'pinia' import { acceptHMRUpdate, defineStore } from 'pinia'
import type { TableType } from 'nocodb-sdk' import type { TableType } from 'nocodb-sdk'
import { useTitle } from '@vueuse/core' import { useTitle } from '@vueuse/core'
import type { SidebarTableNode } from '~/lib'
export const useTablesStore = defineStore('tablesStore', () => { export const useTablesStore = defineStore('tablesStore', () => {
const { includeM2M, ncNavigateTo } = useGlobal() const { includeM2M, ncNavigateTo } = useGlobal()
@ -12,7 +13,7 @@ export const useTablesStore = defineStore('tablesStore', () => {
const router = useRouter() const router = useRouter()
const route = router.currentRoute const route = router.currentRoute
const baseTables = ref<Map<string, TableType[]>>(new Map()) const baseTables = ref<Map<string, SidebarTableNode[]>>(new Map())
const basesStore = useBases() const basesStore = useBases()
// const baseStore = useBase() // const baseStore = useBase()

8
packages/nc-gui/store/views.ts

@ -184,9 +184,13 @@ export const useViewsStore = defineStore('viewsStore', () => {
isViewDataLoading.value = true isViewDataLoading.value = true
try { try {
if (tablesStore.activeTable) tablesStore.activeTable.isViewsLoading = true
await loadViews() await loadViews()
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} finally {
if (tablesStore.activeTable) tablesStore.activeTable.isViewsLoading = false
} }
}, },
{ immediate: true }, { immediate: true },
@ -271,10 +275,6 @@ export const useViewsStore = defineStore('viewsStore', () => {
} }
} }
watch(activeViewTitleOrId, () => {
isPaginationLoading.value = true
})
watch(activeView, (view) => { watch(activeView, (view) => {
if (!view) return if (!view) return
if (!view.base_id) return if (!view.base_id) return

Loading…
Cancel
Save