Browse Source

feat(nc-gui): show active dates

pull/7611/head
DarkPhoenix2704 9 months ago
parent
commit
59ce391bde
  1. 75
      packages/nc-gui/components/dlg/ViewCreate.vue
  2. 15
      packages/nc-gui/components/smartsheet/calendar/DayView.vue
  3. 7
      packages/nc-gui/components/smartsheet/calendar/SideMenu.vue
  4. 7
      packages/nc-gui/components/smartsheet/calendar/WeekView.vue
  5. 12
      packages/nc-gui/components/smartsheet/calendar/YearView.vue
  6. 81
      packages/nc-gui/composables/useCalendarViewStore.ts
  7. 4
      packages/nc-gui/lang/en.json
  8. 2
      packages/nc-gui/plugins/a.dayjs.ts

75
packages/nc-gui/components/dlg/ViewCreate.vue

@ -424,53 +424,42 @@ onMounted(async () => {
/>
</a-form-item>
<template v-if="form.type === ViewTypes.CALENDAR">
<div v-for="(range, index) in form.calendarRange" :key="`range-${index}`" class="flex w-full gap-3">
<div class="flex flex-col gap-2 w-1/2">
<div v-for="(range, index) in form.calendarRange" :key="`range-${index}`" class="flex w-full items-center gap-2">
<span>
{{ $t('labels.organizeBy') }}
</span>
<NcSelect
v-model:value="range.fk_from_column_id"
:disabled="isMetaLoading"
:loading="isMetaLoading"
:options="viewSelectFieldOptions"
/>
<div
v-if="range.fk_to_column_id === null && isEeUI"
class="cursor-pointer flex items-center gap-1 mb-1"
@click="range.fk_to_column_id = ''"
>
<component :is="iconMap.plus" class="h-4 w-4" />
{{ $t('activity.setEndDate') }}
</div>
<template v-else-if="isEeUI">
<span>
{{ $t('labels.organizeRecordsBy') }}
{{ $t('activity.withEndDate') }}
</span>
<NcSelect
v-model:value="range.fk_from_column_id"
:disabled="isMetaLoading"
:loading="isMetaLoading"
:options="viewSelectFieldOptions"
class="w-full"
/>
</div>
<div v-if="range.fk_to_column_id === null && isEeUI" class="flex flex-col justify-end w-1/2">
<div class="cursor-pointer flex items-center font-medium gap-1 mb-1" @click="range.fk_to_column_id = ''">
<component :is="iconMap.plus" class="h-4 w-4" />
{{ $t('activity.setEndDate') }}
</div>
</div>
<div v-else-if="isEeUI" class="flex gap-2 flex-col w-1/2">
<div class="flex flex-row justify-between">
<span>
{{ $t('labels.endDateField') }}
</span>
<component
:is="iconMap.delete"
class="h-4 w-4 cursor-pointer text-red-500"
@click="
() => {
range.fk_to_column_id = null
}
"
<div class="flex">
<NcSelect
v-model:value="range.fk_to_column_id"
:disabled="isMetaLoading"
:loading="isMetaLoading"
:options="viewSelectFieldOptions"
:placeholder="$t('placeholder.notSelected')"
class="!rounded-r-none nc-to-select"
/>
<NcButton class="!rounded-l-none" size="small" type="secondary" @click="range.fk_to_column_id = null">
<component :is="iconMap.delete" class="h-4 w-4" />
</NcButton>
</div>
<NcSelect
v-model:value="range.fk_to_column_id"
:disabled="isMetaLoading"
:loading="isMetaLoading"
:options="
viewSelectFieldOptions.filter(
(el) => el.uidt === viewSelectFieldOptions.find((el) => el.id === range.fk_from_column_id),
)
"
:placeholder="$t('placeholder.notSelected')"
class="w-full"
/>
</div>
</template>
</div>
</template>
</a-form>

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

@ -1,6 +1,6 @@
<script lang="ts" setup>
import { UITypes } from 'nocodb-sdk';
import { computed, ref, type Row } from '#imports';
import { UITypes } from 'nocodb-sdk'
import { type Row, computed, ref } from '#imports'
interface Props {
isEmbed?: boolean
@ -20,7 +20,7 @@ const data = toRefs(props).data
const displayField = computed(() => meta.value?.columns?.find((c) => c.pv && fields.value.includes(c)) ?? null)
const { pageDate, selectedDate, calDataType, formattedData, calendarRange } = useCalendarViewStoreOrThrow()
const { pageDate, selectedDate, calDataType, filteredData, calendarRange } = useCalendarViewStoreOrThrow()
const hours = computed(() => {
const hours = []
@ -33,15 +33,14 @@ const hours = computed(() => {
const renderData = computed(() => {
console.log(data.value)
if (data.value) {
return data.value
}
return formattedData.value
return filteredData.value
})
</script>
<template>
<template v-if="formattedData.length">
<template v-if="filteredData && filteredData.length">
<div
v-if="calDataType === UITypes.Date"
:class="{
@ -70,7 +69,9 @@ const renderData = computed(() => {
class="flex flex-col mt-3 gap-2 w-full px-1"
></div>
</template>
<div v-else-if="!data" class="w-full h-full flex text-md font-bold text-gray-500 items-center justify-center">No Records in this day</div>
<div v-else-if="!data" class="w-full h-full flex text-md font-bold text-gray-500 items-center justify-center">
No Records in this day
</div>
</template>
<style lang="scss" scoped></style>

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

@ -7,6 +7,8 @@ const emit = defineEmits(['expand-record'])
const { t } = useI18n()
const { pageDate, selectedDate, selectedDateRange, activeDates, activeCalendarView } = useCalendarViewStoreOrThrow()
const options = computed(() => {
switch (activeCalendarView.value) {
case 'day' as const:
@ -39,8 +41,6 @@ const options = computed(() => {
]
}
})
const { pageDate, selectedDate, selectedDateRange, activeDates, activeCalendarView } = useCalendarViewStoreOrThrow()
</script>
<template>
@ -53,12 +53,13 @@ const { pageDate, selectedDate, selectedDateRange, activeDates, activeCalendarVi
>
<NcDateWeekSelector
v-if="activeCalendarView === ('day' as const)"
v-model:active-dates="activeDates"
v-model:page-date="pageDate"
v-model:selected-date="selectedDate"
:active-dates="activeDates"
/>
<NcDateWeekSelector
v-else-if="activeCalendarView === ('week' as const)"
v-model:active-dates="activeDatess"
v-model:page-date="pageDate"
v-model:selected-week="selectedDateRange"
week-picker

7
packages/nc-gui/components/smartsheet/calendar/WeekView.vue

@ -1,7 +1,7 @@
<script lang="ts" setup>
import dayjs from 'dayjs';
import dayjs from 'dayjs'
const { selectedDateRange, formattedData, calendarRange } = useCalendarViewStoreOrThrow()
const { selectedDateRange, filteredData, calendarRange } = useCalendarViewStoreOrThrow()
const weekDates = computed(() => {
const startOfWeek = new Date(selectedDateRange.value.start)
@ -16,7 +16,8 @@ const weekDates = computed(() => {
const getData = (date: Date) => {
const range = calendarRange.value[0]
return formattedData.value.filter((record) => dayjs(date).isSame(dayjs(record.row[range.fk_from_col.title])))
if (!filteredData.value) return []
return filteredData.value.filter((record) => dayjs(date).isSame(dayjs(record.row[range.fk_from_col.title])))
}
</script>

12
packages/nc-gui/components/smartsheet/calendar/YearView.vue

@ -1,11 +1,10 @@
<script setup lang="ts">
const { pageDate, selectedDate, selectedDateRange } = useCalendarViewStoreOrThrow()
<script lang="ts" setup>
const { selectedDate, activeDates } = useCalendarViewStoreOrThrow()
const months = computed(() => {
const date = new Date()
const months = []
for (let i = 0; i < 12; i++) {
months.push(new Date(date.getFullYear(), i, selectedDate.value.getDate()))
months.push(new Date(selectedDate.value.getFullYear(), i, selectedDate.value.getDate()))
}
return months
})
@ -16,12 +15,13 @@ const months = computed(() => {
<NcDateWeekSelector
v-for="(month, index) in months"
:key="month"
v-model:active-dates="activeDates"
v-model:page-date="months[index]"
v-model:selected-date="selectedDate"
disable-pagination
class="max-w-[350px]"
disable-pagination
/>
</div>
</template>
<style scoped lang="scss"></style>
<style lang="scss" scoped></style>

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

@ -1,7 +1,7 @@
import type { ComputedRef, Ref } from 'vue'
import type { CalendarType, PaginatedType, UITypes, ViewType } from 'nocodb-sdk'
import dayjs from 'dayjs'
import { addDays, addMonths, addYears } from '../utils'
import { addDays, addMonths, addYears } from '~/utils'
import { IsPublicInj, type Row, ref, storeToRefs, useBase, useInjectionState } from '#imports'
const formatData = (list: Record<string, any>[]) =>
@ -75,32 +75,41 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
return calendarMetaData.value.calendar_range.map((range) => {
// Get the column data for the calendar range
return {
fk_from_col: meta.value.columns.find((col) => col.id === range.fk_from_column_id),
fk_to_col: meta.value.columns.find((col) => col.id === range.fk_to_column_id),
fk_from_col: meta.value!.columns!.find((col) => col.id === range.fk_from_column_id),
fk_to_col: meta.value!.columns!.find((col) => col.id === range.fk_to_column_id),
}
})
})
const xWhere = computed(() => {
if (!meta.value || !meta.value.columns || !calendarMetaData.value || !calendarMetaData.value.calendar_range) return ''
console.log(meta.value.columns.find((col) => col.id === calendarMetaData.value.calendar_range[0].fk_from_column_id))
// If CalendarView, then we need to add the date filter to the where clause
let whereClause = where?.value ?? ''
if (whereClause.length > 0) {
whereClause += '~and('
}
if (activeCalendarView.value === 'week') {
whereClause += `(${
meta.value.columns.find((col) => col.id === calendarMetaData.value.calendar_range[0].fk_from_column_id).title
},gte,exactDate,${dayjs(selectedDateRange.value.start).format('YYYY-MM-DD')})`
whereClause += `~and(${
meta.value.columns.find((col) => col.id === calendarMetaData.value.calendar_range[0].fk_from_column_id).title
},lte,exactDate,${dayjs(selectedDateRange.value.end).format('YYYY-MM-DD')})`
whereClause += `(${calendarRange.value[0].fk_from_col.title},gte,exactDate,${dayjs(selectedDateRange.value.start).format(
'YYYY-MM-DD',
)})`
whereClause += `~and(${calendarRange.value[0].fk_from_col.title},lte,exactDate,${dayjs(
selectedDateRange.value.end,
).format('YYYY-MM-DD')})`
return whereClause
} else if (activeCalendarView.value === 'day') {
return `(${
meta.value.columns.find((col) => col.id === calendarMetaData.value.calendar_range[0].fk_from_column_id).title
},eq,exactDate,${dayjs(selectedDate.value).format('YYYY-MM-DD')})`
return `(${calendarRange.value[0].fk_from_col.title},eq,exactDate,${dayjs(selectedDate.value).format('YYYY-MM-DD')})`
} else if (activeCalendarView.value === 'month') {
return `(${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')})`
} else if (activeCalendarView.value === 'year') {
return `(${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')})`
}
})
@ -108,8 +117,22 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const activeDates = computed(() => {
const dates = new Set<Date>()
formattedData.value.forEach((row) => {
const date = dayjs(row.row[calendarMetaData.value.calendar_range![0].fk_from_column_id!]).toDate()
dates.add(date)
const start = row.row[calendarRange.value[0].fk_from_col.title]
let end
if (calendarRange.value[0].fk_to_col) {
end = row.row[calendarRange.value[0].fk_to_col.title]
}
if (start && end) {
const startDate = dayjs(start)
const endDate = dayjs(end)
let currentDate = startDate
while (currentDate.isSameOrBefore(endDate)) {
dates.add(currentDate.toDate())
currentDate = currentDate.add(1, 'day')
}
} else if (start) {
dates.add(new Date(start))
}
})
return Array.from(dates)
})
@ -136,8 +159,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
? (sharedView.value?.view as CalendarType)
: await $api.dbView.calendarRead(viewMeta.value.id)
activeCalendarView.value = JSON.parse(calendarMetaData.value?.meta ?? '{}')?.active_view ?? 'month'
calDataType.value = meta.value.columns.find((col) => col.id === calendarMetaData.value.calendar_range[0].fk_from_column_id)
?.uidt as UITypes.Date | UITypes.DateTime
calDataType.value = calendarRange.value[0].fk_from_col.uidt
}
async function loadCalendarData() {
@ -154,6 +176,28 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
isCalendarDataLoading.value = false
}
const filteredData = computed(() => {
if (!formattedData.value) return []
if (activeCalendarView === 'week') {
return formattedData.value.filter((row) => {
const startDate = dayjs(row.row[calendarRange.value[0].fk_from_col.title])
const endDate = dayjs(row.row[calendarRange.value[0].fk_to_col.title])
return startDate.isSameOrBefore(selectedDateRange.value.end) && endDate.isSameOrAfter(selectedDateRange.value.start)
})
} else if (activeCalendarView === 'day') {
return formattedData.value.filter((row) => {
const startDate = dayjs(row.row[calendarRange.value[0].fk_from_col.title])
return startDate.isSame(selectedDate.value)
})
} else if (activeCalendarView === 'month') {
return formattedData.value.filter((row) => {
const startDate = dayjs(row.row[calendarRange.value[0].fk_from_col.title])
const endDate = dayjs(row.row[calendarRange.value[0].fk_to_col.title])
return startDate.isSameOrBefore(selectedDate.value) && endDate.isSameOrAfter(selectedDate.value)
})
}
})
async function updateCalendarMeta(updateObj: Partial<CalendarType>) {
if (!viewMeta?.value?.id || !isUIAllowed('dataEdit')) return
await $api.dbView.calendarUpdate(viewMeta.value.id, updateObj)
@ -200,6 +244,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
}
watch(selectedDate, async () => {
if (activeCalendarView.value === 'year') return
await loadCalendarData()
})
@ -213,7 +258,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
})
return {
formattedData,
filteredData,
activeDates,
isCalendarDataLoading,
changeCalendarView,

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

@ -436,6 +436,7 @@
"generalSettings": "General Settings",
"ssoSettings": "SSO Settings",
"organizeRecordsBy": "Organize records by",
"organizeBy": "Organize by",
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
@ -681,7 +682,8 @@
}
},
"activity": {
"setEndDate": "Set end date",
"setEndDate": "Set End Date",
"withEndDate": "with end date",
"calendar": "Calendar",
"viewSettings": "View settings",
"googleOAuth": "Google OAuth",

2
packages/nc-gui/plugins/a.dayjs.ts

@ -6,6 +6,7 @@ import utc from 'dayjs/plugin/utc.js'
import weekday from 'dayjs/plugin/weekday.js'
import timezone from 'dayjs/plugin/timezone.js'
import updateLocale from 'dayjs/plugin/updateLocale'
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
import { defineNuxtPlugin } from '#imports'
export default defineNuxtPlugin(() => {
@ -16,6 +17,7 @@ export default defineNuxtPlugin(() => {
extend(weekday)
extend(timezone)
extend(updateLocale)
extend(isSameOrBefore)
dayjs.updateLocale('en', {
weekStart: 1,
})

Loading…
Cancel
Save