Browse Source

Merge pull request #7687 from nocodb/nc-feat/calendar-data-controller

fix(nc-gui): error handling
pull/7704/head
Pranav C 7 months ago committed by GitHub
parent
commit
5e00b832a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 69
      packages/nc-gui/components/smartsheet/calendar/index.vue
  2. 146
      packages/nc-gui/composables/useCalendarViewStore.ts
  3. 3
      packages/nc-gui/lang/en.json
  4. 6
      packages/nocodb/src/services/datas.service.ts
  5. 10
      packages/nocodb/src/services/public-datas.service.ts

69
packages/nc-gui/components/smartsheet/calendar/index.vue

@ -41,6 +41,7 @@ provide(IsKanbanInj, ref(false))
provide(IsCalendarInj, ref(true)) provide(IsCalendarInj, ref(true))
const { const {
calendarRange,
calDataType, calDataType,
loadCalendarMeta, loadCalendarMeta,
loadCalendarData, loadCalendarData,
@ -256,37 +257,45 @@ const headerText = computed(() => {
</NcButton> </NcButton>
</NcTooltip> </NcTooltip>
</div> </div>
<LazySmartsheetCalendarYearView v-if="activeCalendarView === 'year'" /> <template v-if="calendarRange">
<template v-if="!isCalendarDataLoading"> <LazySmartsheetCalendarYearView v-if="activeCalendarView === 'year'" />
<LazySmartsheetCalendarMonthView <template v-if="!isCalendarDataLoading">
v-if="activeCalendarView === 'month'" <LazySmartsheetCalendarMonthView
@expand-record="expandRecord" v-if="activeCalendarView === 'month'"
@new-record="newRecord" @expand-record="expandRecord"
/> @new-record="newRecord"
<LazySmartsheetCalendarWeekViewDateField />
v-else-if="activeCalendarView === 'week' && calDataType === UITypes.Date" <LazySmartsheetCalendarWeekViewDateField
@expand-record="expandRecord" v-else-if="activeCalendarView === 'week' && calDataType === UITypes.Date"
@new-record="newRecord" @expand-record="expandRecord"
/> @new-record="newRecord"
<LazySmartsheetCalendarWeekViewDateTimeField />
v-else-if="activeCalendarView === 'week' && calDataType === UITypes.DateTime" <LazySmartsheetCalendarWeekViewDateTimeField
@expand-record="expandRecord" v-else-if="activeCalendarView === 'week' && calDataType === UITypes.DateTime"
@new-record="newRecord" @expand-record="expandRecord"
/> @new-record="newRecord"
<LazySmartsheetCalendarDayViewDateField />
v-else-if="activeCalendarView === 'day' && calDataType === UITypes.Date" <LazySmartsheetCalendarDayViewDateField
@expand-record="expandRecord" v-else-if="activeCalendarView === 'day' && calDataType === UITypes.Date"
@new-record="newRecord" @expand-record="expandRecord"
/> @new-record="newRecord"
<LazySmartsheetCalendarDayViewDateTimeField />
v-else-if="activeCalendarView === 'day' && calDataType === UITypes.DateTime" <LazySmartsheetCalendarDayViewDateTimeField
@expand-record="expandRecord" v-else-if="activeCalendarView === 'day' && calDataType === UITypes.DateTime"
@new-record="newRecord" @expand-record="expandRecord"
/> @new-record="newRecord"
/>
</template>
<div v-if="isCalendarDataLoading && activeCalendarView !== 'year'" class="flex w-full items-center h-full justify-center">
<GeneralLoader size="xlarge" />
</div>
</template>
<template v-else>
<div class="flex w-full items-center h-full justify-center">
{{ $t('activity.noRange') }}
</div>
</template> </template>
<div v-if="isCalendarDataLoading && activeCalendarView !== 'year'" class="flex w-full items-center h-full justify-center">
<GeneralLoader size="xlarge" />
</div>
</div> </div>
<LazySmartsheetCalendarSideMenu <LazySmartsheetCalendarSideMenu
v-if="!isMobileMode" v-if="!isMobileMode"

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

@ -25,7 +25,14 @@ const formatData = (list: Record<string, any>[]) =>
const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState( const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
( (
meta: Ref<((CalendarType & { id: string }) | TableType) | undefined>, meta: Ref<((CalendarType & { id: string }) | TableType) | undefined>,
viewMeta: Ref<(ViewType | CalendarType | undefined) & { id: string }> | ComputedRef<(ViewType & { id: string }) | undefined>, viewMeta:
| Ref<(ViewType | CalendarType | undefined) & { id: string }>
| ComputedRef<
| (ViewType & {
id: string
})
| undefined
>,
shared = false, shared = false,
where?: ComputedRef<string | undefined>, where?: ComputedRef<string | undefined>,
) => { ) => {
@ -116,6 +123,8 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const sideBarFilter = computed(() => { const sideBarFilter = computed(() => {
let combinedFilters: any = [] let combinedFilters: any = []
if (!calendarRange.value) return []
if (sideBarFilterOption.value === 'allRecords') { if (sideBarFilterOption.value === 'allRecords') {
combinedFilters = [] combinedFilters = []
} else if (sideBarFilterOption.value === 'withoutDates') { } else if (sideBarFilterOption.value === 'withoutDates') {
@ -329,6 +338,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
} }
const filterJSON = computed(() => { const filterJSON = computed(() => {
if (!calendarRange.value) return []
const combinedFilters: any = { const combinedFilters: any = {
is_group: true, is_group: true,
logical_op: 'and', logical_op: 'and',
@ -514,21 +524,24 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
}) })
if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) return if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) return
const res = !isPublic.value
? await api.dbViewRow.calendarCount('noco', base.value.id!, meta.value!.id!, viewMeta.value.id, { try {
...queryParams.value, const res = !isPublic.value
...{}, ? await api.dbViewRow.calendarCount('noco', base.value.id!, meta.value!.id!, viewMeta.value.id, {
...{}, ...queryParams.value,
...{ filterArrJson: JSON.stringify([...activeDateFilter]) }, ...{},
}) ...{},
: await fetchSharedViewActiveDate({ ...{ filterArrJson: JSON.stringify([...activeDateFilter]) },
sortsArr: sorts.value, })
filtersArr: activeDateFilter, : await fetchSharedViewActiveDate({
}) sortsArr: sorts.value,
if (res) { filtersArr: activeDateFilter,
})
activeDates.value = res.map((dateObj: unknown) => dayjs(dateObj)) activeDates.value = res.map((dateObj: unknown) => dayjs(dateObj))
} else { } catch (e) {
activeDates.value = [] activeDates.value = []
message.error(`${t('msg.error.fetchingActiveDates')} ${await extractSdkResponseErrorMsg(e)}`)
console.log(e)
} }
} }
@ -554,44 +567,55 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
async function loadCalendarMeta() { async function loadCalendarMeta() {
if (!viewMeta?.value?.id || !meta?.value?.columns) return if (!viewMeta?.value?.id || !meta?.value?.columns) return
const res = isPublic.value ? (sharedView.value?.view as CalendarType) : await $api.dbView.calendarRead(viewMeta.value.id) try {
calendarMetaData.value = res const res = isPublic.value ? (sharedView.value?.view as CalendarType) : await $api.dbView.calendarRead(viewMeta.value.id)
const calMeta = typeof res.meta === 'string' ? JSON.parse(res.meta) : res.meta calendarMetaData.value = res
activeCalendarView.value = calMeta?.active_view const calMeta = typeof res.meta === 'string' ? JSON.parse(res.meta) : res.meta
if (!activeCalendarView.value) activeCalendarView.value = 'month' activeCalendarView.value = calMeta?.active_view
calendarRange.value = res?.calendar_range!.map((range: any) => { if (!activeCalendarView.value) activeCalendarView.value = 'month'
return { calendarRange.value = res?.calendar_range?.map((range: any) => {
fk_from_col: meta.value?.columns!.find((col) => col.id === range.fk_from_column_id), return {
fk_to_col: range.fk_to_column_id ? meta.value?.columns!.find((col) => col.id === range.fk_to_column_id) : null, fk_from_col: meta.value?.columns?.find((col) => col.id === range.fk_from_column_id),
} fk_to_col: range.fk_to_column_id ? meta.value?.columns?.find((col) => col.id === range.fk_to_column_id) : null,
}) as any }
}) as any
} catch (e) {
message.error(`Error loading calendar meta ${await extractSdkResponseErrorMsg(e)}`)
}
} }
async function loadCalendarData() { async function loadCalendarData() {
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id || !filterJSON.value) && !isPublic?.value) return if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id || !filterJSON.value) && !isPublic?.value) return
isCalendarDataLoading.value = true try {
const res = !isPublic.value isCalendarDataLoading.value = true
? await api.dbViewRow.list(
'noco', const res = !isPublic.value
base.value.id!, ? await api.dbViewRow.list(
meta.value!.id!, 'noco',
viewMeta.value!.id!, base.value.id!,
{ meta.value!.id!,
...queryParams.value, viewMeta.value!.id!,
...(isUIAllowed('filterSync') {
? { filterArrJson: JSON.stringify([...filterJSON.value]) } ...queryParams.value,
: { filterArrJson: JSON.stringify([nestedFilters.value, ...filterJSON.value]) }), ...(isUIAllowed('filterSync')
where: where?.value ?? '', ? { filterArrJson: JSON.stringify([...filterJSON.value]) }
}, : { filterArrJson: JSON.stringify([nestedFilters.value, ...filterJSON.value]) }),
{ where: where?.value ?? '',
headers: {
'xc-ignore-pagination': true,
}, },
}, {
) headers: {
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: filterJSON.value }) 'xc-ignore-pagination': true,
formattedData.value = formatData(res!.list) },
isCalendarDataLoading.value = false },
)
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: filterJSON.value })
formattedData.value = formatData(res!.list)
} catch (e) {
message.error(`${t('msg.error.fetchingCalendarData')} ${await extractSdkResponseErrorMsg(e)}`)
console.log(e)
} finally {
isCalendarDataLoading.value = false
}
} }
async function updateCalendarMeta(updateObj: Partial<CalendarType>) { async function updateCalendarMeta(updateObj: Partial<CalendarType>) {
@ -662,18 +686,24 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const loadSidebarData = async () => { const loadSidebarData = async () => {
if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) return if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) return
isSidebarLoading.value = true try {
const res = !isPublic.value isSidebarLoading.value = true
? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value.id, { const res = !isPublic.value
...queryParams.value, ? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value.id, {
...{}, ...queryParams.value,
...{}, ...{},
...{ filterArrJson: JSON.stringify([...sideBarFilter.value]) }, ...{},
}) ...{ filterArrJson: JSON.stringify([...sideBarFilter.value]) },
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: sideBarFilter.value }) })
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: sideBarFilter.value })
formattedSideBarData.value = formatData(res!.list) formattedSideBarData.value = formatData(res!.list)
isSidebarLoading.value = false } catch (e) {
message.error(`${t('msg.error.fetchingCalendarData')} ${await extractSdkResponseErrorMsg(e)}`)
console.log(e)
} finally {
isSidebarLoading.value = false
}
} }
async function updateRowProperty(toUpdate: Row, property: string[], undo = false) { async function updateRowProperty(toUpdate: Row, property: string[], undo = false) {

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

@ -692,6 +692,7 @@
"showFieldOnConditionsMet":"Shows field only when conditions are met" "showFieldOnConditionsMet":"Shows field only when conditions are met"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -1296,6 +1297,8 @@
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}" "upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",

6
packages/nocodb/src/services/datas.service.ts

@ -221,9 +221,9 @@ export class DatasService {
if (view.type !== ViewTypes.CALENDAR) if (view.type !== ViewTypes.CALENDAR)
NcError.badRequest('View is not a calendar view'); NcError.badRequest('View is not a calendar view');
const { ranges } = await CalendarRange.read(view.id); const calendarRange = await CalendarRange.read(view.id);
if (!ranges.length) NcError.badRequest('No ranges found'); if (!calendarRange?.ranges?.length) NcError.badRequest('No ranges found');
const model = await Model.getByIdOrName({ const model = await Model.getByIdOrName({
id: view.fk_model_id, id: view.fk_model_id,
@ -239,7 +239,7 @@ export class DatasService {
const dates: Array<string> = []; const dates: Array<string> = [];
ranges.forEach((range: any) => { calendarRange.ranges.forEach((range: any) => {
data.list.forEach((date) => { data.list.forEach((date) => {
const from = const from =
date[ date[

10
packages/nocodb/src/services/public-datas.service.ts

@ -12,7 +12,7 @@ import { nocoExecute } from 'nc-help';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import type { LinkToAnotherRecordColumn } from '~/models'; import type { LinkToAnotherRecordColumn } from '~/models';
import { CalendarRange } from '~/models'; import { CalendarRange, Column, Model, Source, View } from '~/models';
import { NcError } from '~/helpers/catchError'; import { NcError } from '~/helpers/catchError';
import getAst from '~/helpers/getAst'; import getAst from '~/helpers/getAst';
import NcPluginMgrv2 from '~/helpers/NcPluginMgrv2'; import NcPluginMgrv2 from '~/helpers/NcPluginMgrv2';
@ -20,7 +20,6 @@ import { PagedResponseImpl } from '~/helpers/PagedResponse';
import { getColumnByIdOrName } from '~/modules/datas/helpers'; import { getColumnByIdOrName } from '~/modules/datas/helpers';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
import { mimeIcons } from '~/utils/mimeTypes'; import { mimeIcons } from '~/utils/mimeTypes';
import { Column, Model, Source, View } from '~/models';
import { utf8ify } from '~/helpers/stringHelpers'; import { utf8ify } from '~/helpers/stringHelpers';
// todo: move to utils // todo: move to utils
@ -121,7 +120,10 @@ export class PublicDatasService {
if (view.type !== ViewTypes.CALENDAR) if (view.type !== ViewTypes.CALENDAR)
NcError.badRequest('View is not a calendar view'); NcError.badRequest('View is not a calendar view');
const { ranges } = await CalendarRange.read(view.id); const calendarRange = await CalendarRange.read(view.id);
if (!calendarRange?.ranges?.length)
NcError.notFound('Calendar ranges are required in a calendar view');
const model = await Model.getByIdOrName({ const model = await Model.getByIdOrName({
id: view.fk_model_id, id: view.fk_model_id,
@ -139,7 +141,7 @@ export class PublicDatasService {
const dates: Array<string> = []; const dates: Array<string> = [];
ranges.forEach((range: any) => { calendarRange.ranges.forEach((range: any) => {
data.list.forEach((date) => { data.list.forEach((date) => {
const from = const from =
date[columns.find((c) => c.id === range.fk_from_column_id).title]; date[columns.find((c) => c.id === range.fk_from_column_id).title];

Loading…
Cancel
Save