Browse Source

feat(nc-gui): sidebar data loading

pull/7611/head
DarkPhoenix2704 5 months ago
parent
commit
5d83c47355
  1. 77
      packages/nc-gui/components/smartsheet/calendar/SideMenu.vue
  2. 157
      packages/nc-gui/composables/useCalendarViewStore.ts

77
packages/nc-gui/components/smartsheet/calendar/SideMenu.vue

@ -1,13 +1,41 @@
<script lang="ts" setup>
import type { VNodeRef } from '@vue/runtime-core'
import { UITypes } from 'nocodb-sdk'
import { computed, ref } from '#imports'
const props = defineProps<{
visible: boolean
}>()
const emit = defineEmits(['expand-record'])
const INFINITY_SCROLL_THRESHOLD = 100
const { appInfo } = useGlobal()
const { t } = useI18n()
const { pageDate, selectedDate, selectedDateRange, activeDates, activeCalendarView } = useCalendarViewStoreOrThrow()
const {
pageDate,
selectedDate,
calendarRange,
selectedDateRange,
activeDates,
activeCalendarView,
formattedSideBarData,
calDataType,
loadMoreSidebarData,
searchQuery,
sideBarFilterOption,
} = useCalendarViewStoreOrThrow()
const meta = inject(MetaInj, ref())
const fields = inject(FieldsInj, ref([]))
const sideBarListRef = ref<VNodeRef | null>(null)
const displayField = computed(() => meta.value?.columns?.find((c) => c.pv && fields.value.includes(c)) ?? null)
const options = computed(() => {
switch (activeCalendarView.value) {
@ -17,7 +45,7 @@ const options = computed(() => {
{ label: 'without dates', value: 'withoutDates' },
{ label: 'in selected hours', value: 'selectedHours' },
{ label: 'all records', value: 'allRecords' },
]
].filter((o) => o.value !== 'selectedHours' && calDataType.value === UITypes.Date)
case 'week' as const:
return [
{ label: 'in this week', value: 'week' },
@ -41,6 +69,22 @@ const options = computed(() => {
]
}
})
watch(displayField, () => {
if (!displayField) return
searchQuery.field = displayField.value?.title ?? ''
})
const sideBarListScrollHandle = useDebounceFn(async (e: Event) => {
const target = e.target as HTMLElement
if (target.clientHeight + target.scrollTop + INFINITY_SCROLL_THRESHOLD >= target.scrollHeight) {
const pageSize = appInfo.value?.defaultLimit ?? 25
const page = Math.floor(formattedSideBarData.value.length / pageSize)
await loadMoreSidebarData({
offset: page * pageSize,
})
}
})
</script>
<template>
@ -59,7 +103,7 @@ const options = computed(() => {
/>
<NcDateWeekSelector
v-else-if="activeCalendarView === ('week' as const)"
v-model:active-dates="activeDatess"
v-model:active-dates="activeDates"
v-model:page-date="pageDate"
v-model:selected-week="selectedDateRange"
week-picker
@ -79,29 +123,36 @@ const options = computed(() => {
<div class="px-4 flex flex-col gap-y-6 pt-4">
<div class="flex justify-between items-center">
<span class="text-2xl font-bold">{{ t('objects.Records') }}</span>
<NcSelect :options="options" value="all records" />
<NcSelect v-model:value="sideBarFilterOption" :options="options" />
</div>
<a-input class="!rounded-lg !border-gray-200 !px-4 !py-2" placeholder="Search your records">
<a-input
v-model:value="searchQuery.value"
class="!rounded-lg !border-gray-200 !px-4 !py-2"
placeholder="Search your records"
>
<template #prefix>
<component :is="iconMap.search" class="h-4 w-4 mr-1 text-gray-500" />
</template>
</a-input>
<div
v-if="displayField && calendarRange && calendarRange.length"
:ref="sideBarListRef"
:class="{
'h-[calc(100vh-40rem)]': activeCalendarView === ('day' as const) || activeCalendarView === ('week' as const),
'h-[calc(100vh-29rem)]': activeCalendarView === ('month' as const) || activeCalendarView === ('year' as const),
}"
class="gap-2 flex flex-col nc-scrollbar-md overflow-y-auto nc-calendar-top-height"
@scroll="sideBarListScrollHandle"
>
<LazySmartsheetCalendarSideRecordCard
v-for="(x, id) in Array(50)"
:key="id"
:color="x % 2 === 0 ? 'maroon' : 'blue'"
date="27 April 2003"
name="Saturday HackNight"
@click="emit('expand-record', id)"
/>
<LazySmartsheetRow v-for="(record, rowIndex) in formattedSideBarData" :key="rowIndex" :row="record">
<LazySmartsheetCalendarSideRecordCard
:date="record.row[calendarRange[0].fk_from_col.title]"
:name="record.row[displayField.title]"
color="blue"
@click="emit('expand-record', record)"
/>
</LazySmartsheetRow>
</div>
</div>
</div>

157
packages/nc-gui/composables/useCalendarViewStore.ts

@ -1,5 +1,5 @@
import type { ComputedRef, Ref } from 'vue'
import type { CalendarType, PaginatedType, UITypes, ViewType } from 'nocodb-sdk'
import type { Api, CalendarType, PaginatedType, UITypes, ViewType } from 'nocodb-sdk'
import dayjs from 'dayjs'
import { addDays, addMonths, addYears } from '~/utils'
import { IsPublicInj, type Row, ref, storeToRefs, useBase, useInjectionState } from '#imports'
@ -31,6 +31,11 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const calDataType = ref<UITypes.Date | UITypes.DateTime>()
const searchQuery = reactive({
value: '',
field: '',
})
const selectedDate = ref<Date>(new Date())
const isCalendarDataLoading = ref<boolean>(false)
@ -43,10 +48,14 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
end: dayjs(selectedDate.value).startOf('week').add(6, 'day').toDate(), // This will be the following Saturday
})
const defaultPageSize = 1000
const defaultPageSize = 25
const formattedData = ref<Row[]>([])
const formattedSideBarData = ref<Row[]>([])
const sideBarFilterOption = ref<string>(activeCalendarView.value)
const { api } = useApi()
const { base } = storeToRefs(useBase())
@ -81,12 +90,123 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
})
})
const sideBarxWhere = computed(() => {
if (!calendarRange.value) return ''
let whereClause = ''
if (activeCalendarView.value === 'day') {
switch (sideBarFilterOption.value) {
case 'day':
whereClause = `(${calendarRange.value[0].fk_from_col.title},eq,exactDate,${dayjs(selectedDate.value).format(
'YYYY-MM-DD',
)})`
break
case 'withoutDates':
whereClause = `(${calendarRange.value[0].fk_from_col.title},is,blank)`
break
case 'allRecords':
whereClause = ''
break
}
} else if (activeCalendarView.value === 'week') {
switch (sideBarFilterOption.value) {
case 'week':
whereClause = `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(
selectedDateRange.value.start,
).format('YYYY-MM-DD')})~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(
selectedDateRange.value.end,
).format('YYYY-MM-DD')})`
break
case 'withoutDates':
whereClause = `(${calendarRange.value[0].fk_from_col.title},is,blank)`
break
case 'allRecords':
whereClause = ''
break
case 'selectedDate':
whereClause = `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDate.value).format(
'YYYY-MM-DD',
)})~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(selectedDate.value).format('YYYY-MM-DD')})`
break
}
} else if (activeCalendarView.value === 'month') {
switch (sideBarFilterOption.value) {
case 'month':
whereClause = `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDate.value)
.startOf('month')
.format('YYYY-MM-DD')})~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(selectedDate.value)
.endOf('month')
.format('YYYY-MM-DD')})`
break
case 'withoutDates':
whereClause = `(${calendarRange.value[0].fk_from_col.title},is,blank)`
break
case 'allRecords':
whereClause = ''
break
case 'selectedDate':
whereClause = `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDate.value).format(
'YYYY-MM-DD',
)})~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(selectedDate.value).format('YYYY-MM-DD')})`
break
}
} else if (activeCalendarView.value === 'year') {
switch (sideBarFilterOption.value) {
case 'year':
whereClause = `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDate.value)
.startOf('year')
.format('YYYY-MM-DD')})~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(selectedDate.value)
.endOf('year')
.format('YYYY-MM-DD')})`
break
case 'withoutDates':
whereClause = `(${calendarRange.value[0].fk_from_col.title},is,blank)`
break
case 'allRecords':
whereClause = ''
break
case 'selectedDate':
whereClause = `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDate.value).format(
'YYYY-MM-DD',
)})~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(selectedDate.value).format('YYYY-MM-DD')})`
break
}
}
if (searchQuery.field && searchQuery.value) {
if (whereClause.length > 0) {
whereClause += '~and'
}
whereClause += `(${searchQuery.field},like,${searchQuery.value})`
}
return whereClause
})
async function loadMoreSidebarData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) {
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return
const response = !isPublic.value
? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value!.id!, {
...params,
...{},
...{},
where: sideBarxWhere.value,
})
: await fetchSharedViewData({
...params,
sortsArr: sorts.value,
filtersArr: nestedFilters.value,
offset: params.offset,
where: sideBarxWhere.value,
})
formattedSideBarData.value = [...formattedSideBarData.value, ...formatData(response!.list)]
}
const xWhere = computed(() => {
if (!meta.value || !meta.value.columns || !calendarMetaData.value || !calendarMetaData.value.calendar_range) return ''
// If CalendarView, then we need to add the date filter to the where clause
let whereClause = where?.value ?? ''
if (whereClause.length > 0) {
whereClause += '~and('
whereClause += '~and'
}
if (activeCalendarView.value === 'week') {
whereClause += `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDateRange.value.start).format(
@ -243,22 +363,49 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
}
}
const loadSidebarData = async () => {
if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) return
const res = await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value!.id!, {
...queryParams.value,
...{},
where: sideBarxWhere?.value,
})
formattedSideBarData.value = formatData(res!.list)
}
watch(selectedDate, async () => {
if (activeCalendarView.value === 'year') return
await loadCalendarData()
if (activeCalendarView.value !== 'year') {
await loadCalendarData()
}
await loadSidebarData()
})
watch(selectedDateRange, async () => {
if (activeCalendarView.value !== 'week') return
await loadCalendarData()
await loadSidebarData()
})
watch(activeCalendarView, async () => {
sideBarFilterOption.value = activeCalendarView.value ?? 'allRecords'
await loadCalendarData()
await loadSidebarData()
})
watch(sideBarFilterOption, async () => {
await loadSidebarData()
})
watch(searchQuery, async () => {
await loadSidebarData()
})
return {
filteredData,
formattedSideBarData,
loadMoreSidebarData,
sideBarFilterOption,
searchQuery,
activeDates,
isCalendarDataLoading,
changeCalendarView,

Loading…
Cancel
Save