Browse Source

Merge pull request #7995 from nocodb/nc-calendar-enable

Nc calendar enable
DarkPhoenix2704-patch-1
Anbarasu 8 months ago committed by GitHub
parent
commit
1251e9e1f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      packages/nc-gui/components/dashboard/TreeView/CreateViewBtn.vue
  2. 1
      packages/nc-gui/components/smartsheet/calendar/DayView/DateTimeField.vue
  3. 1
      packages/nc-gui/components/smartsheet/calendar/MonthView.vue
  4. 15
      packages/nc-gui/components/smartsheet/calendar/SideMenu.vue
  5. 1
      packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue
  6. 6
      packages/nc-gui/components/smartsheet/calendar/index.vue
  7. 4
      packages/nc-gui/components/smartsheet/toolbar/CalendarMode.vue
  8. 18
      packages/nc-gui/components/smartsheet/toolbar/CalendarRange.vue
  9. 10
      packages/nc-gui/composables/useCalendarViewStore.ts
  10. 19
      packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts
  11. 9
      packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts
  12. 8
      packages/nocodb/src/services/calendar-datas.service.ts
  13. 2
      tests/playwright/pages/Dashboard/Sidebar/index.ts
  14. 2
      tests/playwright/pages/Dashboard/ViewSidebar/index.ts
  15. 1
      tests/playwright/tests/db/views/viewCalendar.spec.ts

5
packages/nc-gui/components/dashboard/TreeView/CreateViewBtn.vue

@ -155,10 +155,7 @@ async function onOpenModal({
<GeneralIcon v-else class="plus" icon="plus" /> <GeneralIcon v-else class="plus" icon="plus" />
</div> </div>
</NcMenuItem> </NcMenuItem>
<NcMenuItem <NcMenuItem data-testid="sidebar-view-create-calendar" @click="onOpenModal({ type: ViewTypes.CALENDAR })">
data-testid="sidebar-view-create-calendar"
@click="onOpenModal({ type: ViewTypes.CALENDAR })"
>
<div class="item"> <div class="item">
<div class="item-inner"> <div class="item-inner">
<GeneralViewIcon :meta="{ type: ViewTypes.CALENDAR }" /> <GeneralViewIcon :meta="{ type: ViewTypes.CALENDAR }" />

1
packages/nc-gui/components/smartsheet/calendar/DayView/DateTimeField.vue

@ -953,6 +953,7 @@ const newRecord = (hour: dayjs.Dayjs) => {
<NcButton <NcButton
v-if="isOverflowAcrossHourRange(hour).isOverflow" v-if="isOverflowAcrossHourRange(hour).isOverflow"
v-e="`['c:calendar:week-view-more']`"
class="!absolute bottom-2 text-center w-15 mx-auto inset-x-0 z-3 text-gray-500" class="!absolute bottom-2 text-center w-15 mx-auto inset-x-0 z-3 text-gray-500"
size="xxsmall" size="xxsmall"
type="secondary" type="secondary"

1
packages/nc-gui/components/smartsheet/calendar/MonthView.vue

@ -759,6 +759,7 @@ const addRecord = (date: dayjs.Dayjs) => {
recordsToDisplay.count[dayjs(day).format('YYYY-MM-DD')]?.overflow && recordsToDisplay.count[dayjs(day).format('YYYY-MM-DD')]?.overflow &&
!draggingId !draggingId
" "
v-e="`['c:calendar:month-view-more']`"
class="!absolute bottom-1 right-1 text-center min-w-4.5 mx-auto z-3 text-gray-500" class="!absolute bottom-1 right-1 text-center min-w-4.5 mx-auto z-3 text-gray-500"
size="xxsmall" size="xxsmall"
type="secondary" type="secondary"

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

@ -369,7 +369,7 @@ onUnmounted(() => {
</div> </div>
<div <div
v-if="calendarRange" v-if="calendarRange?.length"
:ref="sideBarListRef" :ref="sideBarListRef"
:class="{ :class="{
'!h-[calc(100vh-10.5rem)]': width <= 1440, '!h-[calc(100vh-10.5rem)]': width <= 1440,
@ -383,7 +383,7 @@ onUnmounted(() => {
> >
<NcButton <NcButton
v-if="isUIAllowed('dataEdit') && props.visible" v-if="isUIAllowed('dataEdit') && props.visible"
v-e="['c:calendar:calendar-new-record-btn']" v-e="['c:calendar:calendar-sidemenu-new-record-btn']"
class="!absolute right-5 !border-brand-500 bottom-5 !h-12 !w-12" class="!absolute right-5 !border-brand-500 bottom-5 !h-12 !w-12"
data-testid="nc-calendar-side-menu-new-btn" data-testid="nc-calendar-side-menu-new-btn"
type="secondary" type="secondary"
@ -440,6 +440,17 @@ onUnmounted(() => {
</div> </div>
</template> </template>
</div> </div>
<div
v-else
:class="{
'!h-[calc(100vh-10.5rem)]': width <= 1440,
'h-[calc(100vh-36.2rem)]': activeCalendarView === ('day' as const) || activeCalendarView === ('week' as const) && width >= 1440,
'h-[calc(100vh-25.1rem)]': activeCalendarView === ('month' as const) || activeCalendarView === ('year' as const) && width >= 1440,
}"
class="flex items-center justify-center h-full"
>
{{ $t('activity.noRange') }}
</div>
</div> </div>
</div> </div>
</template> </template>

1
packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue

@ -785,6 +785,7 @@ const addRecord = (date: dayjs.Dayjs) => {
> >
<NcButton <NcButton
v-if="isOverflowAcrossHourRange(hour).isOverflow" v-if="isOverflowAcrossHourRange(hour).isOverflow"
v-e="`['c:calendar:week-view-more']`"
class="!absolute bottom-1 text-center w-15 ml-auto inset-x-0 z-3 text-gray-500" class="!absolute bottom-1 text-center w-15 ml-auto inset-x-0 z-3 text-gray-500"
size="xxsmall" size="xxsmall"
type="secondary" type="secondary"

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

@ -192,8 +192,8 @@ const headerText = computed(() => {
<NcDropdown v-model:visible="calendarRangeDropdown" :auto-close="false" :trigger="['click']"> <NcDropdown v-model:visible="calendarRangeDropdown" :auto-close="false" :trigger="['click']">
<NcButton :class="{ '!w-22': activeCalendarView === 'year' }" class="w-45" full-width size="small" type="secondary"> <NcButton :class="{ '!w-22': activeCalendarView === 'year' }" class="w-45" full-width size="small" type="secondary">
<div class="flex px-2 w-full items-center justify-between"> <div class="flex px-2 w-full items-center justify-between">
<div class="flex gap-1 text-brand-500"> <div class="flex gap-1 text-brand-500" data-testid="nc-calendar-active-date">
<span class="font-bold text-center" data-testid="nc-calendar-active-date">{{ <span class="font-bold text-center">{{
activeCalendarView === 'month' ? headerText.split(' ')[0] : headerText activeCalendarView === 'month' ? headerText.split(' ')[0] : headerText
}}</span> }}</span>
<span v-if="activeCalendarView === 'month'"> <span v-if="activeCalendarView === 'month'">
@ -282,7 +282,7 @@ const headerText = computed(() => {
</NcButton> </NcButton>
</NcTooltip> </NcTooltip>
</div> </div>
<template v-if="calendarRange"> <template v-if="calendarRange?.length">
<LazySmartsheetCalendarYearView v-if="activeCalendarView === 'year'" /> <LazySmartsheetCalendarYearView v-if="activeCalendarView === 'year'" />
<template v-if="!isCalendarDataLoading"> <template v-if="!isCalendarDataLoading">
<LazySmartsheetCalendarMonthView <LazySmartsheetCalendarMonthView

4
packages/nc-gui/components/smartsheet/toolbar/CalendarMode.vue

@ -44,7 +44,7 @@ watch(activeCalendarView, () => {
<div <div
v-for="mode in ['day', 'week', 'month', 'year']" v-for="mode in ['day', 'week', 'month', 'year']"
:key="mode" :key="mode"
v-e="`['c:calendar:change-calendar-range-${mode}']`" v-e="`['c:calendar:change-calendar-view-${mode}']`"
:class="{ active: activeCalendarView === mode }" :class="{ active: activeCalendarView === mode }"
:data-testid="`nc-calendar-view-mode-${mode}`" :data-testid="`nc-calendar-view-mode-${mode}`"
class="tab" class="tab"
@ -64,7 +64,7 @@ watch(activeCalendarView, () => {
<NcMenuItem <NcMenuItem
v-for="mode in ['day', 'week', 'month', 'year']" v-for="mode in ['day', 'week', 'month', 'year']"
:key="mode" :key="mode"
v-e="`['c:calendar:change-calendar-range-${mode}']`" v-e="`['c:calendar:change-calendar-view-${mode}']`"
@click="changeCalendarView(mode)" @click="changeCalendarView(mode)"
> >
{{ $t(`objects.${mode}`) }} {{ $t(`objects.${mode}`) }}

18
packages/nc-gui/components/smartsheet/toolbar/CalendarRange.vue

@ -92,15 +92,14 @@ const dateFieldOptions = computed<SelectProps['options']>(() => {
})) ?? [] })) ?? []
) )
}) })
const addCalendarRange = async () => {
/* const addCalendarRange = async () => {
_calendar_ranges.value.push({ _calendar_ranges.value.push({
fk_from_column_id: dateFieldOptions.value![0].value as string, fk_from_column_id: dateFieldOptions.value![0].value as string,
fk_to_column_id: null, fk_to_column_id: null,
}) })
await saveCalendarRanges() await saveCalendarRanges()
} }
/*
const removeRange = async (id: number) => { const removeRange = async (id: number) => {
_calendar_ranges.value = _calendar_ranges.value.filter((_, i) => i !== id) _calendar_ranges.value = _calendar_ranges.value.filter((_, i) => i !== id)
await saveCalendarRanges() await saveCalendarRanges()
@ -215,10 +214,17 @@ const saveCalendarRange = async (range: CalendarRangeType, value?) => {
</NcButton> </NcButton>
--> -->
</div> </div>
<!-- <NcButton class="mt-2" data-testid="nc-calendar-range-add-btn" size="small" type="secondary" @click="addCalendarRange"> <NcButton
v-if="_calendar_ranges.length === 0"
class="mt-2"
data-testid="nc-calendar-range-add-btn"
size="small"
type="secondary"
@click="addCalendarRange"
>
<component :is="iconMap.plus" /> <component :is="iconMap.plus" />
Add another date field Add date field
</NcButton> --> </NcButton>
</div> </div>
</template> </template>
</NcDropdown> </NcDropdown>

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

@ -312,7 +312,8 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
}) })
async function loadMoreSidebarData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) { async function loadMoreSidebarData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) {
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return if (((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) || !calendarRange.value?.length)
return
if (isSidebarLoading.value) return if (isSidebarLoading.value) return
try { try {
const response = !isPublic.value const response = !isPublic.value
@ -339,7 +340,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
} }
const fetchActiveDates = async () => { const fetchActiveDates = async () => {
if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id || !calendarRange.value) return if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id || !calendarRange.value?.length) return
let prevDate: dayjs.Dayjs | string | null = null let prevDate: dayjs.Dayjs | string | null = null
let nextDate: dayjs.Dayjs | string | null = null let nextDate: dayjs.Dayjs | string | null = null
let fromDate: dayjs.Dayjs | string | null = null let fromDate: dayjs.Dayjs | string | null = null
@ -433,7 +434,8 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
} }
async function loadCalendarData(showLoading = true) { async function loadCalendarData(showLoading = true) {
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic?.value) return if (((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic?.value) || !calendarRange.value?.length)
return
if (activeCalendarView.value === 'year') { if (activeCalendarView.value === 'year') {
return return
@ -593,7 +595,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
} }
const loadSidebarData = async (showLoading = true) => { const loadSidebarData = async (showLoading = true) => {
if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) return if (!base?.value?.id || !meta.value?.id || !viewMeta.value?.id || !calendarRange.value?.length) return
try { try {
if (showLoading) isSidebarLoading.value = true if (showLoading) isSidebarLoading.value = true
const res = !isPublic.value const res = !isPublic.value

19
packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts

@ -6,13 +6,13 @@ import { Injectable } from '@nestjs/common';
import { elapsedTime, initTime } from '../../helpers'; import { elapsedTime, initTime } from '../../helpers';
import type { BaseModelSqlv2 } from '~/db/BaseModelSqlv2'; import type { BaseModelSqlv2 } from '~/db/BaseModelSqlv2';
import type { View } from '~/models'; import type { View } from '~/models';
import { Base, Hook, Model, Source } from '~/models';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
import { getViewAndModelByAliasOrId } from '~/modules/datas/helpers'; import { getViewAndModelByAliasOrId } from '~/modules/datas/helpers';
import { clearPrefix, generateBaseIdMap } from '~/helpers/exportImportHelpers'; import { clearPrefix, generateBaseIdMap } from '~/helpers/exportImportHelpers';
import NcPluginMgrv2 from '~/helpers/NcPluginMgrv2'; import NcPluginMgrv2 from '~/helpers/NcPluginMgrv2';
import { NcError } from '~/helpers/catchError'; import { NcError } from '~/helpers/catchError';
import { DatasService } from '~/services/datas.service'; import { DatasService } from '~/services/datas.service';
import { Base, Hook, Model, Source } from '~/models';
import { parseMetaProp } from '~/utils/modelUtils'; import { parseMetaProp } from '~/utils/modelUtils';
@Injectable() @Injectable()
@ -233,6 +233,23 @@ export class ExportService {
view.view.meta = meta; view.view.meta = meta;
} }
break; break;
case 'calendar_range':
if (view.type === ViewTypes.CALENDAR) {
const range = view.view[k];
view.view[k] = range.map(
(r: {
fk_to_column_id?: string;
fk_from_column_id: string;
}) => {
return {
fk_to_column_id: idMap.get(r.fk_to_column_id),
fk_from_column_id: idMap.get(r.fk_from_column_id),
};
},
);
}
break;
case 'created_at': case 'created_at':
case 'updated_at': case 'updated_at':
case 'fk_view_id': case 'fk_view_id':

9
packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts

@ -1061,12 +1061,21 @@ export class ImportService {
(a) => a.fk_column_id === reverseGet(idMap, cl.fk_column_id), (a) => a.fk_column_id === reverseGet(idMap, cl.fk_column_id),
); );
if (!fcl) continue; if (!fcl) continue;
const calendarColProperties =
vw.type === ViewTypes.CALENDAR
? {
bold: fcl.bold,
italic: fcl.italic,
underline: fcl.underline,
}
: {};
await this.viewColumnsService.columnUpdate({ await this.viewColumnsService.columnUpdate({
viewId: vw.id, viewId: vw.id,
columnId: cl.id, columnId: cl.id,
column: { column: {
show: fcl.show, show: fcl.show,
order: fcl.order, order: fcl.order,
...calendarColProperties,
}, },
req: param.req, req: param.req,
}); });

8
packages/nocodb/src/services/calendar-datas.service.ts

@ -136,9 +136,9 @@ export class CalendarDatasService {
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 ranges = await CalendarRange.read(view.id);
if (!ranges.length) NcError.badRequest('No ranges found'); if (!ranges?.ranges.length) NcError.badRequest('No ranges found');
const filterArr = await this.buildFilterArr({ const filterArr = await this.buildFilterArr({
viewId, viewId,
@ -165,7 +165,7 @@ export class CalendarDatasService {
const columns = await model.getColumns(); const columns = await model.getColumns();
ranges.forEach((range: CalendarRangeType) => { ranges?.ranges?.forEach((range: CalendarRangeType) => {
const fromCol = columns.find( const fromCol = columns.find(
(c) => c.id === range.fk_from_column_id, (c) => c.id === range.fk_from_column_id,
)?.title; )?.title;
@ -203,7 +203,7 @@ export class CalendarDatasService {
children: [], children: [],
}; };
calendarRange.ranges.forEach((range: CalendarRange) => { calendarRange?.ranges.forEach((range: CalendarRange) => {
const fromColumn = range.fk_from_column_id; const fromColumn = range.fk_from_column_id;
let rangeFilter: any = []; let rangeFilter: any = [];
if (fromColumn) { if (fromColumn) {

2
tests/playwright/pages/Dashboard/Sidebar/index.ts

@ -113,8 +113,6 @@ export class SidebarPage extends BasePage {
} else if (type === ViewTypes.GALLERY) { } else if (type === ViewTypes.GALLERY) {
createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-gallery'); createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-gallery');
} else if (type === ViewTypes.CALENDAR) { } else if (type === ViewTypes.CALENDAR) {
// TODO: Remove this once the easter egg is removed
await this.rootPage.waitForTimeout(4500);
createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-calendar'); createViewTypeButton = this.rootPage.getByTestId('sidebar-view-create-calendar');
} }

2
tests/playwright/pages/Dashboard/ViewSidebar/index.ts

@ -205,7 +205,7 @@ export class ViewSidebarPage extends BasePage {
} }
private async createView({ title, type }: { title: string; type: ViewTypes }) { private async createView({ title, type }: { title: string; type: ViewTypes }) {
await this.rootPage.waitForTimeout(1000); await this.rootPage.waitForTimeout(500);
await this.dashboard.sidebar.createView({ title, type }); await this.dashboard.sidebar.createView({ title, type });
} }

1
tests/playwright/tests/db/views/viewCalendar.spec.ts

@ -112,7 +112,6 @@ const dateRecords = [
test.describe('Calendar View', () => { test.describe('Calendar View', () => {
let dashboard: DashboardPage, toolbar: ToolbarPage, topbar: TopbarPage; let dashboard: DashboardPage, toolbar: ToolbarPage, topbar: TopbarPage;
let context: any; let context: any;
test.skip();
test.beforeEach(async ({ page }) => { test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: true }); context = await setup({ page, isEmptyProject: true });

Loading…
Cancel
Save