mirror of https://github.com/nocodb/nocodb
DarkPhoenix2704
10 months ago
29 changed files with 1438 additions and 1325 deletions
@ -1,176 +1,179 @@
|
||||
<script lang="ts" setup> |
||||
|
||||
interface Props { |
||||
selectedDate?: Date | null; |
||||
isDisabled?: boolean; |
||||
pageDate?: Date; |
||||
yearPicker?: boolean; |
||||
selectedDate?: Date | null |
||||
isDisabled?: boolean |
||||
pageDate?: Date |
||||
yearPicker?: boolean |
||||
} |
||||
|
||||
const emit = defineEmits(['update:selected-date', 'update:page-date']); |
||||
const props = withDefaults(defineProps<Props>(), { |
||||
selectedDate: null, |
||||
isDisabled: false, |
||||
pageDate: new Date(), |
||||
yearPicker: false |
||||
}); |
||||
|
||||
const pageDate = useVModel(props, 'pageDate', emit); |
||||
const selectedDate = useVModel(props, 'selectedDate', emit); |
||||
yearPicker: false, |
||||
}) |
||||
const emit = defineEmits(['update:selected-date', 'update:page-date']) |
||||
const pageDate = useVModel(props, 'pageDate', emit) |
||||
const selectedDate = useVModel(props, 'selectedDate', emit) |
||||
|
||||
const years = computed(() => { |
||||
const date = new Date(pageDate.value); |
||||
const startYear = date.getFullYear(); |
||||
const endYear = date.getFullYear() + 11; |
||||
const years = []; |
||||
const date = new Date(pageDate.value) |
||||
const startYear = date.getFullYear() |
||||
const endYear = date.getFullYear() + 11 |
||||
const years = [] |
||||
for (let i = startYear; i <= endYear; i++) { |
||||
years.push({ |
||||
label: i, |
||||
value: new Date(i, 0, 1) |
||||
}); |
||||
value: new Date(i, 0, 1), |
||||
}) |
||||
} |
||||
return years; |
||||
}); |
||||
return years |
||||
}) |
||||
|
||||
const currentYear = computed(() => { |
||||
return pageDate.value.getFullYear(); |
||||
}); |
||||
return pageDate.value.getFullYear() |
||||
}) |
||||
|
||||
const months = computed(() => { |
||||
const date = new Date(pageDate.value); |
||||
const date = new Date(pageDate.value) |
||||
return [ |
||||
{ |
||||
label: 'January', |
||||
value: new Date(date.getFullYear(), 0, 1) |
||||
value: new Date(date.getFullYear(), 0, 1), |
||||
}, |
||||
{ |
||||
label: 'February', |
||||
value: new Date(date.getFullYear(), 1, 1) |
||||
value: new Date(date.getFullYear(), 1, 1), |
||||
}, |
||||
{ |
||||
label: 'March', |
||||
value: new Date(date.getFullYear(), 2, 1) |
||||
value: new Date(date.getFullYear(), 2, 1), |
||||
}, |
||||
{ |
||||
label: 'April', |
||||
value: new Date(date.getFullYear(), 3, 1) |
||||
value: new Date(date.getFullYear(), 3, 1), |
||||
}, |
||||
{ |
||||
label: 'May', |
||||
value: new Date(date.getFullYear(), 4, 1) |
||||
value: new Date(date.getFullYear(), 4, 1), |
||||
}, |
||||
{ |
||||
label: 'June', |
||||
value: new Date(date.getFullYear(), 5, 1) |
||||
value: new Date(date.getFullYear(), 5, 1), |
||||
}, |
||||
{ |
||||
label: 'July', |
||||
value: new Date(date.getFullYear(), 6, 1) |
||||
value: new Date(date.getFullYear(), 6, 1), |
||||
}, |
||||
{ |
||||
label: 'August', |
||||
value: new Date(date.getFullYear(), 7, 1) |
||||
value: new Date(date.getFullYear(), 7, 1), |
||||
}, |
||||
{ |
||||
label: 'September', |
||||
value: new Date(date.getFullYear(), 8, 1) |
||||
value: new Date(date.getFullYear(), 8, 1), |
||||
}, |
||||
{ |
||||
label: 'October', |
||||
value: new Date(date.getFullYear(), 9, 1) |
||||
value: new Date(date.getFullYear(), 9, 1), |
||||
}, |
||||
{ |
||||
label: 'November', |
||||
value: new Date(date.getFullYear(), 10, 1) |
||||
value: new Date(date.getFullYear(), 10, 1), |
||||
}, |
||||
{ |
||||
label: 'December', |
||||
value: new Date(date.getFullYear(), 11, 1) |
||||
} |
||||
value: new Date(date.getFullYear(), 11, 1), |
||||
}, |
||||
] |
||||
}) |
||||
|
||||
const compareDates = (date1: Date, date2: Date) => { |
||||
if (!date1 || !date2) return false; |
||||
return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth(); |
||||
if (!date1 || !date2) return false |
||||
return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() |
||||
} |
||||
|
||||
const isMonthSelected = (date: Date) => { |
||||
if (!selectedDate.value) return false; |
||||
return compareDates(date, selectedDate.value); |
||||
if (!selectedDate.value) return false |
||||
return compareDates(date, selectedDate.value) |
||||
} |
||||
|
||||
const paginateMonth = (action: 'next' | 'prev') => { |
||||
const date = new Date(pageDate.value); |
||||
const date = new Date(pageDate.value) |
||||
if (action === 'next') { |
||||
date.setFullYear(date.getFullYear() + 1); |
||||
date.setFullYear(date.getFullYear() + 1) |
||||
} else { |
||||
date.setFullYear(date.getFullYear() - 1); |
||||
date.setFullYear(date.getFullYear() - 1) |
||||
} |
||||
pageDate.value = date; |
||||
}; |
||||
pageDate.value = date |
||||
} |
||||
|
||||
const paginateYear = (action: 'next' | 'prev') => { |
||||
const date = new Date(pageDate.value); |
||||
const date = new Date(pageDate.value) |
||||
if (action === 'next') { |
||||
date.setFullYear(date.getFullYear() + 12); |
||||
date.setFullYear(date.getFullYear() + 12) |
||||
} else { |
||||
date.setFullYear(date.getFullYear() - 12); |
||||
date.setFullYear(date.getFullYear() - 12) |
||||
} |
||||
pageDate.value = date; |
||||
}; |
||||
pageDate.value = date |
||||
} |
||||
|
||||
const paginate = (action: 'next' | 'prev') => { |
||||
if (props.yearPicker) { |
||||
paginateYear(action); |
||||
paginateYear(action) |
||||
} else { |
||||
paginateMonth(action); |
||||
paginateMonth(action) |
||||
} |
||||
}; |
||||
} |
||||
|
||||
const compareYear = (date1: Date, date2: Date) => { |
||||
if (!date1 || !date2) return false; |
||||
return date1.getFullYear() === date2.getFullYear(); |
||||
if (!date1 || !date2) return false |
||||
return date1.getFullYear() === date2.getFullYear() |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="p-4 flex flex-col gap-4"> |
||||
<div class="flex justify-between items-center"> |
||||
<NcButton size="small" type="secondary" @click="paginate('prev')"> |
||||
<component :is="iconMap.doubleLeftArrow" class="h-4 w-4"/> |
||||
<component :is="iconMap.doubleLeftArrow" class="h-4 w-4" /> |
||||
</NcButton> |
||||
<span class="font-bold text-gray-700">{{ yearPicker ? 'Select Year' : currentYear }}</span> |
||||
<NcButton size="small" type="secondary" @click="paginate('next')"> |
||||
<component :is="iconMap.doubleRightArrow" class="h-4 w-4"/> |
||||
<component :is="iconMap.doubleRightArrow" class="h-4 w-4" /> |
||||
</NcButton> |
||||
</div> |
||||
<div class="border-1 border-gray-200 rounded-y-xl max-w-[350px]"> |
||||
<div class="grid grid-cols-4 gap-2 p-2"> |
||||
<span v-for="(month) in months" v-if="!yearPicker" :key="month.value" :class="{ |
||||
'!bg-brand-50 !border-2 !border-brand-500' : isMonthSelected(month.value), |
||||
}" |
||||
class="h-9 rounded-lg flex font-medium items-center justify-center hover:(border-1 border-gray-200 bg-gray-100) text-gray-500 cursor-pointer" |
||||
@click="selectedDate = month.value" |
||||
> |
||||
{{ month.label.slice(0, 3) }} |
||||
</span> |
||||
<span v-for="(year) in years" v-if="yearPicker" :key="year" :class="{ |
||||
'!bg-brand-50 !border-2 !border-brand-500' : compareYear(year.value, selectedDate) |
||||
}" |
||||
class="h-9 rounded-lg flex font-medium items-center justify-center hover:(border-1 border-gray-200 bg-gray-100) text-gray-500 cursor-pointer" |
||||
@click="selectedDate = year.value" |
||||
> |
||||
{{ year.label }} |
||||
</span> |
||||
<template v-if="!yearPicker"> |
||||
<span |
||||
v-for="month in months" |
||||
:key="month.value" |
||||
:class="{ |
||||
'!bg-brand-50 !border-2 !border-brand-500': isMonthSelected(month.value), |
||||
}" |
||||
class="h-9 rounded-lg flex font-medium items-center justify-center hover:(border-1 border-gray-200 bg-gray-100) text-gray-500 cursor-pointer" |
||||
@click="selectedDate = month.value" |
||||
> |
||||
{{ month.label.slice(0, 3) }} |
||||
</span> |
||||
</template> |
||||
<template v-else> |
||||
<span |
||||
v-for="year in years" |
||||
:key="year" |
||||
:class="{ |
||||
'!bg-brand-50 !border-2 !border-brand-500': compareYear(year.value, selectedDate), |
||||
}" |
||||
class="h-9 rounded-lg flex font-medium items-center justify-center hover:(border-1 border-gray-200 bg-gray-100) text-gray-500 cursor-pointer" |
||||
@click="selectedDate = year.value" |
||||
> |
||||
{{ year.label }} |
||||
</span> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
||||
<style lang="scss" scoped></style> |
||||
|
@ -1,33 +1,38 @@
|
||||
<script setup lang="ts"> |
||||
import { UITypes } from 'nocodb-sdk' |
||||
|
||||
import {UITypes} from "nocodb-sdk"; |
||||
const emit = defineEmits(['expand-record']) |
||||
|
||||
const { pageDate, selectedDate, calDataType } = useCalendarViewStoreOrThrow(); |
||||
|
||||
const emit = defineEmits(['expand-record']); |
||||
const { pageDate, selectedDate, calDataType } = useCalendarViewStoreOrThrow() |
||||
|
||||
const events = ref([ |
||||
{ |
||||
"Id": 1, |
||||
"Title": "Event 01", |
||||
"from_date_time": "2023-12-15", |
||||
"to_date_time": "2023-12-20" |
||||
Id: 1, |
||||
Title: 'Event 01', |
||||
from_date_time: '2023-12-15', |
||||
to_date_time: '2023-12-20', |
||||
}, |
||||
{ |
||||
"Id": 2, |
||||
"Title": "Event 02", |
||||
"from_date_time": "2023-12-20", |
||||
"to_date_time": "2023-12-25" |
||||
} |
||||
Id: 2, |
||||
Title: 'Event 02', |
||||
from_date_time: '2023-12-20', |
||||
to_date_time: '2023-12-25', |
||||
}, |
||||
]) |
||||
</script> |
||||
|
||||
<template> |
||||
<div v-if="calDataType === UITypes.Date" class="flex flex-col px-2 gap-4 pt-4"> |
||||
<LazySmartsheetCalendarRecordCard v-for="event in events" :name="event.Title" :date="event.from_date_time" color="blue" size="medium" @click="emit('expand-record', 'xxx')" /> |
||||
</div> |
||||
<div v-if="calDataType === UITypes.Date" class="flex flex-col px-2 gap-4 pt-4"> |
||||
<LazySmartsheetCalendarRecordCard |
||||
v-for="event in events" |
||||
:key="event.Id" |
||||
:name="event.Title" |
||||
:date="event.from_date_time" |
||||
color="blue" |
||||
size="medium" |
||||
@click="emit('expand-record', 'xxx')" |
||||
/> |
||||
</div> |
||||
</template> |
||||
|
||||
<style scoped lang="scss"> |
||||
|
||||
</style> |
||||
<style scoped lang="scss"></style> |
||||
|
@ -1,162 +1,175 @@
|
||||
<script setup lang="ts"> |
||||
|
||||
const { pageDate, selectedDate } = useCalendarViewStoreOrThrow(); |
||||
const { pageDate, selectedDate } = useCalendarViewStoreOrThrow() |
||||
|
||||
const events = ref([ |
||||
{ |
||||
"Id": 1, |
||||
"Title": "Event 01", |
||||
"from_date_time": "2023-12-15", |
||||
"to_date_time": "2023-12-20" |
||||
Id: 1, |
||||
Title: 'Event 01', |
||||
from_date_time: '2023-12-15', |
||||
to_date_time: '2023-12-20', |
||||
}, |
||||
{ |
||||
"Id": 2, |
||||
"Title": "Event 02", |
||||
"from_date_time": "2023-12-20", |
||||
"to_date_time": "2023-12-25" |
||||
} |
||||
Id: 2, |
||||
Title: 'Event 02', |
||||
from_date_time: '2023-12-20', |
||||
to_date_time: '2023-12-25', |
||||
}, |
||||
]) |
||||
|
||||
interface EventData { |
||||
id: string; |
||||
from_col_id: string; |
||||
to_col_id: string | null; |
||||
id: string |
||||
from_col_id: string |
||||
to_col_id: string | null |
||||
} |
||||
|
||||
const isMondayFirst = ref(false); |
||||
|
||||
const isMondayFirst = ref(false) |
||||
|
||||
const fields = inject(FieldsInj, ref([])) |
||||
|
||||
const days = computed(() => { |
||||
if (isMondayFirst.value) { |
||||
return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; |
||||
return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] |
||||
} else { |
||||
return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; |
||||
return ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] |
||||
} |
||||
}) |
||||
|
||||
const isDayInPagedMonth = (date: Date) => { |
||||
return date.getMonth() === pageDate.value.getMonth(); |
||||
return date.getMonth() === pageDate.value.getMonth() |
||||
} |
||||
|
||||
const dates = computed(() => { |
||||
const startOfMonth = new Date(pageDate.value.getFullYear(), pageDate.value.getMonth(), 1); |
||||
const dayOffset = isMondayFirst.value ? 1 : 0; |
||||
const dayOfWeek = (startOfMonth.getDay() - dayOffset + 7) % 7; |
||||
startOfMonth.setDate(startOfMonth.getDate() - dayOfWeek); |
||||
const datesArray = []; |
||||
const startOfMonth = new Date(pageDate.value.getFullYear(), pageDate.value.getMonth(), 1) |
||||
const dayOffset = isMondayFirst.value ? 1 : 0 |
||||
const dayOfWeek = (startOfMonth.getDay() - dayOffset + 7) % 7 |
||||
startOfMonth.setDate(startOfMonth.getDate() - dayOfWeek) |
||||
const datesArray = [] |
||||
while (datesArray.length < 42) { |
||||
datesArray.push(new Date(startOfMonth)); |
||||
startOfMonth.setDate(startOfMonth.getDate() + 1); |
||||
datesArray.push(new Date(startOfMonth)) |
||||
startOfMonth.setDate(startOfMonth.getDate() + 1) |
||||
} |
||||
return datesArray; |
||||
}); |
||||
return datesArray |
||||
}) |
||||
|
||||
const getGridPosition = (event) => { |
||||
const firstDayOfMonth = new Date(pageDate.value.getFullYear(), pageDate.value.getMonth(), 1).getDay() |
||||
|
||||
const firstDayOfMonth = new Date(pageDate.value.getFullYear(), pageDate.value.getMonth(), 1).getDay(); |
||||
|
||||
const startDate = new Date(event.from_date_time); |
||||
const startDayIndex = startDate.getDate() - 1 + firstDayOfMonth; |
||||
const endDate = new Date(event.to_date_time); |
||||
const endDayIndex = endDate.getDate() - 1 + firstDayOfMonth; |
||||
const startDate = new Date(event.from_date_time) |
||||
const startDayIndex = startDate.getDate() - 1 + firstDayOfMonth |
||||
const endDate = new Date(event.to_date_time) |
||||
const endDayIndex = endDate.getDate() - 1 + firstDayOfMonth |
||||
|
||||
const startRow = Math.floor(startDayIndex / 7) + 1; |
||||
let endRow = Math.floor(endDayIndex / 7) + 1; |
||||
const startRow = Math.floor(startDayIndex / 7) + 1 |
||||
let endRow = Math.floor(endDayIndex / 7) + 1 |
||||
|
||||
if (endDate.getMonth() !== pageDate.value.getMonth()) { |
||||
endRow = Math.ceil((new Date(pageDate.value.getFullYear(), pageDate.value.getMonth() + 1, 0).getDate() + firstDayOfMonth) / 7); |
||||
endRow = Math.ceil((new Date(pageDate.value.getFullYear(), pageDate.value.getMonth() + 1, 0).getDate() + firstDayOfMonth) / 7) |
||||
} |
||||
|
||||
const startCol = startDayIndex % 7 + 1; |
||||
let endCol = endDayIndex % 7 + 1; |
||||
const startCol = (startDayIndex % 7) + 1 |
||||
let endCol = (endDayIndex % 7) + 1 |
||||
|
||||
if (endCol === 1) { |
||||
endRow++; |
||||
endCol = 8; |
||||
endRow++ |
||||
endCol = 8 |
||||
} |
||||
|
||||
return { |
||||
colStart: startCol, |
||||
colEnd: endCol, |
||||
rowStart: startRow, |
||||
rowEnd: endRow |
||||
}; |
||||
}; |
||||
|
||||
rowEnd: endRow, |
||||
} |
||||
} |
||||
|
||||
const selectDate = (date: Date) => { |
||||
if (!date) return; |
||||
selectedDate.value = date; |
||||
if (!date) return |
||||
selectedDate.value = date |
||||
} |
||||
|
||||
const isSameDate = (date1: Date, date2: Date) => { |
||||
if(!date1 || !date2) return false; |
||||
return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate(); |
||||
if (!date1 || !date2) return false |
||||
return ( |
||||
date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate() |
||||
) |
||||
} |
||||
|
||||
const isDateSelected = (date: Date) => { |
||||
if (!selectedDate.value) return false; |
||||
const propDate = new Date(selectedDate.value); |
||||
return isSameDate(propDate, date); |
||||
if (!selectedDate.value) return false |
||||
const propDate = new Date(selectedDate.value) |
||||
return isSameDate(propDate, date) |
||||
} |
||||
|
||||
const handleScroll = (event) => { |
||||
if (event.deltaY > 0) { |
||||
pageDate.value.setMonth(pageDate.value.getMonth() + 1); |
||||
pageDate.value.setMonth(pageDate.value.getMonth() + 1) |
||||
} else { |
||||
pageDate.value.setMonth(pageDate.value.getMonth() - 1); |
||||
pageDate.value.setMonth(pageDate.value.getMonth() - 1) |
||||
} |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="h-full" @="handleScroll"> |
||||
<div class="grid grid-cols-7"> |
||||
<div v-for="day in days" :key="day" class="text-center bg-gray-50 py-1 text-sm border-b-1 border-r-1 last:border-r-0 border-gray-200 font-semibold text-gray-800"> |
||||
<div |
||||
v-for="day in days" |
||||
:key="day" |
||||
class="text-center bg-gray-50 py-1 text-sm border-b-1 border-r-1 last:border-r-0 border-gray-200 font-semibold text-gray-800" |
||||
> |
||||
{{ day }} |
||||
</div> |
||||
</div> |
||||
<div class="grid relative grid-cols-7 h-full" > |
||||
<div v-for="date in dates" :key="date" :class="{ |
||||
'!border-x-2 !border-y-2 border-brand-500': isDateSelected(date), |
||||
'!bg-gray-50 !text-gray-400': !isDayInPagedMonth(date), |
||||
|
||||
}" class="text-right !h-[100%] group grid-cell py-1 text-sm border-b-1 border-r-1 bg-white last:border-r-0 border-gray-200 font-semibold text-gray-800" |
||||
@click="selectDate(date)" |
||||
<div class="grid relative grid-cols-7 h-full"> |
||||
<div |
||||
v-for="date in dates" |
||||
:key="date" |
||||
:class="{ |
||||
'!border-x-2 !border-y-2 border-brand-500': isDateSelected(date), |
||||
'!bg-gray-50 !text-gray-400': !isDayInPagedMonth(date), |
||||
}" |
||||
class="text-right !h-[100%] group grid-cell py-1 text-sm border-b-1 border-r-1 bg-white last:border-r-0 border-gray-200 font-semibold text-gray-800" |
||||
@click="selectDate(date)" |
||||
> |
||||
<div class="h-full"> |
||||
<div class="flex justify-between p-1"> |
||||
<span :class="{ |
||||
'block': !isDateSelected(date), |
||||
'hidden': isDateSelected(date), |
||||
}" class="group-hover:hidden"></span> |
||||
<NcButton type="secondary" size="small" :class="{ |
||||
'!block': isDateSelected(date), |
||||
'!hidden': !isDateSelected(date), |
||||
}" class="!group-hover:block"> |
||||
<component :is="iconMap.plus" class="h-4 w-4"/> |
||||
</NcButton> |
||||
<span class="px-1 py-2">{{ date.getDate() }}</span> |
||||
</div> |
||||
|
||||
<div class="flex justify-between p-1"> |
||||
<span |
||||
:class="{ |
||||
block: !isDateSelected(date), |
||||
hidden: isDateSelected(date), |
||||
}" |
||||
class="group-hover:hidden" |
||||
></span> |
||||
<NcButton |
||||
type="secondary" |
||||
size="small" |
||||
:class="{ |
||||
'!block': isDateSelected(date), |
||||
'!hidden': !isDateSelected(date), |
||||
}" |
||||
class="!group-hover:block" |
||||
> |
||||
<component :is="iconMap.plus" class="h-4 w-4" /> |
||||
</NcButton> |
||||
<span class="px-1 py-2">{{ date.getDate() }}</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div v-for="event in events" :key="event.Id" :class="[ |
||||
'absolute w-full mt-16 px-2', |
||||
`!col-start-[${getGridPosition(event, pageDate).colStart}]`, |
||||
`!col-span-[${getGridPosition(event, pageDate).colEnd - getGridPosition(event, pageDate).colStart}]`, |
||||
`!row-start-[${getGridPosition(event, pageDate).rowStart}]`, |
||||
`!row-span-[${getGridPosition(event, pageDate).rowEnd - getGridPosition(event, pageDate).rowStart}]` |
||||
]" class="event-display"> |
||||
<LazySmartsheetCalendarRecordCard :name="event.Title" :date="event.from_date_time" color="blue" /> |
||||
<div |
||||
v-for="event in events" |
||||
:key="event.Id" |
||||
:class="[ |
||||
`!col-start-[${getGridPosition(event, pageDate).colStart}]`, |
||||
`!col-span-[${getGridPosition(event, pageDate).colEnd - getGridPosition(event, pageDate).colStart}]`, |
||||
`!row-start-[${getGridPosition(event, pageDate).rowStart}]`, |
||||
`!row-span-[${getGridPosition(event, pageDate).rowEnd - getGridPosition(event, pageDate).rowStart}]`, |
||||
]" |
||||
class="event-display absolute w-full mt-16 px-2" |
||||
> |
||||
<LazySmartsheetCalendarRecordCard :name="event.Title" :date="event.from_date_time" color="blue" /> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style scoped lang="scss"> |
||||
|
||||
</style> |
||||
<style scoped lang="scss"></style> |
||||
|
@ -1,91 +1,115 @@
|
||||
<script setup lang="ts"> |
||||
|
||||
import { CalendarViewTypeInj } from "#imports"; |
||||
import { CalendarViewTypeInj } from '#imports' |
||||
|
||||
const props = defineProps<{ |
||||
visible: boolean |
||||
}>() |
||||
|
||||
const activeCalendarView = inject(CalendarViewTypeInj, ref<'month' | 'day' | 'year' | 'week'>('month' as const)) |
||||
const emit = defineEmits(['expand-record']) |
||||
|
||||
const {t} = useI18n() |
||||
const activeCalendarView = inject(CalendarViewTypeInj, ref<'month' | 'day' | 'year' | 'week'>('month' as const)) |
||||
|
||||
const emit = defineEmits(['expand-record']); |
||||
const { t } = useI18n() |
||||
|
||||
const options = computed(() => { |
||||
switch (activeCalendarView.value) { |
||||
case 'day' as const: |
||||
return [ |
||||
{label: 'in this day', value: 'day'}, |
||||
{label: 'without dates', value: 'withoutDates'}, |
||||
{label: 'in selected hours', value: 'selectedHours'}, |
||||
{label: 'all records', value: 'allRecords'}, |
||||
{ label: 'in this day', value: 'day' }, |
||||
{ label: 'without dates', value: 'withoutDates' }, |
||||
{ label: 'in selected hours', value: 'selectedHours' }, |
||||
{ label: 'all records', value: 'allRecords' }, |
||||
] |
||||
case 'week' as const: |
||||
return [ |
||||
{label: 'in this week', value: 'week'}, |
||||
{label: 'without dates', value: 'withoutDates'}, |
||||
{label: 'in selected hours', value: 'selectedHours'}, |
||||
{label: 'all records', value: 'allRecords'}, |
||||
{ label: 'in this week', value: 'week' }, |
||||
{ label: 'without dates', value: 'withoutDates' }, |
||||
{ label: 'in selected hours', value: 'selectedHours' }, |
||||
{ label: 'all records', value: 'allRecords' }, |
||||
] |
||||
case 'month' as const: |
||||
return [ |
||||
{label: 'in this month', value: 'month'}, |
||||
{label: 'without dates', value: 'withoutDates'}, |
||||
{label: 'all records', value: 'allRecords'}, |
||||
{label: 'in selected date', value: 'selectedDate'}, |
||||
{ label: 'in this month', value: 'month' }, |
||||
{ label: 'without dates', value: 'withoutDates' }, |
||||
{ label: 'all records', value: 'allRecords' }, |
||||
{ label: 'in selected date', value: 'selectedDate' }, |
||||
] |
||||
case 'year' as const: |
||||
return [ |
||||
{label: 'in this year', value: 'year'}, |
||||
{label: 'without dates', value: 'withoutDates'}, |
||||
{label: 'all records', value: 'allRecords'}, |
||||
{label: 'in selected date', value: 'selectedDate'}, |
||||
{ label: 'in this year', value: 'year' }, |
||||
{ label: 'without dates', value: 'withoutDates' }, |
||||
{ label: 'all records', value: 'allRecords' }, |
||||
{ label: 'in selected date', value: 'selectedDate' }, |
||||
] |
||||
} |
||||
}) |
||||
|
||||
|
||||
const { pageDate, selectedDate, selectedDateRange } = useCalendarViewStoreOrThrow() |
||||
const { pageDate, selectedDate, selectedDateRange } = useCalendarViewStoreOrThrow() |
||||
|
||||
const activeDates = ref([new Date()]) |
||||
|
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div :class="{ |
||||
'w-0': !props.visible, |
||||
'w-1/4 min-w-[22.1rem]': props.visible, |
||||
'transition-all': true, |
||||
}" class="h-full border-l-1 border-gray-200"> |
||||
<NcDateWeekSelector v-if="activeCalendarView === ('day' as const)" v-model:page-date="pageDate" v-model:selected-date="selectedDate" :active-dates="activeDates" /> |
||||
<NcDateWeekSelector v-else-if="activeCalendarView === ('week' as const)" v-model:page-date="pageDate" week-picker v-model:selected-week="selectedDateRange" /> |
||||
<NcMonthYearSelector v-else-if="activeCalendarView === ('month' as const)" v-model:page-date="pageDate" v-model:selected-date="selectedDate" /> |
||||
<NcMonthYearSelector v-else-if="activeCalendarView === ('year' as const)" year-picker v-model:page-date="pageDate" v-model:selected-date="selectedDate" /> |
||||
<div |
||||
:class="{ |
||||
'w-0': !props.visible, |
||||
'w-1/4 min-w-[22.1rem]': props.visible, |
||||
}" |
||||
class="h-full border-l-1 border-gray-200 transition-all" |
||||
> |
||||
<NcDateWeekSelector |
||||
v-if="activeCalendarView === ('day' as const)" |
||||
v-model:page-date="pageDate" |
||||
v-model:selected-date="selectedDate" |
||||
:active-dates="activeDates" |
||||
/> |
||||
<NcDateWeekSelector |
||||
v-else-if="activeCalendarView === ('week' as const)" |
||||
v-model:page-date="pageDate" |
||||
v-model:selected-week="selectedDateRange" |
||||
week-picker |
||||
/> |
||||
<NcMonthYearSelector |
||||
v-else-if="activeCalendarView === ('month' as const)" |
||||
v-model:page-date="pageDate" |
||||
v-model:selected-date="selectedDate" |
||||
/> |
||||
<NcMonthYearSelector |
||||
v-else-if="activeCalendarView === ('year' as const)" |
||||
v-model:page-date="pageDate" |
||||
v-model:selected-date="selectedDate" |
||||
year-picker |
||||
/> |
||||
|
||||
<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 :options="options" value="all records" /> |
||||
</div> |
||||
<a-input class="!rounded-lg !border-gray-200 !px-4 !py-2" placeholder="Search your records"> |
||||
<a-input 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"/> |
||||
<component :is="iconMap.search" class="h-4 w-4 mr-1 text-gray-500" /> |
||||
</template> |
||||
</a-input> |
||||
|
||||
<div :class="{ |
||||
<div |
||||
: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"> |
||||
<LazySmartsheetCalendarSideRecordCard v-for="(x, id) in Array(50)" :color="x%2 === 0 ? 'maroon': 'blue'" |
||||
date="27 April 2003" name="Saturday HackNight" @click="emit('expand-record', id)"/> |
||||
}" |
||||
class="gap-2 flex flex-col nc-scrollbar-md overflow-y-auto nc-calendar-top-height" |
||||
> |
||||
<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)" |
||||
/> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style scoped lang="scss"> |
||||
|
||||
</style> |
||||
<style scoped lang="scss"></style> |
||||
|
@ -1,162 +1,169 @@
|
||||
import type { ComputedRef, Ref } from 'vue' |
||||
import {ColumnType, CalendarType, PaginatedType, TableType, ViewType, UITypes} from 'nocodb-sdk' |
||||
import type { CalendarType, PaginatedType, ViewType } from 'nocodb-sdk' |
||||
import { UITypes } from 'nocodb-sdk' |
||||
import { addDays, addMonths, addYears } from '../utils' |
||||
import { IsPublicInj, ref, storeToRefs, useBase, useInjectionState, useMetas } from '#imports' |
||||
import type { Row } from '#imports' |
||||
import {addDays, addMonths, addWeeks, addYears} from "../utils"; |
||||
|
||||
const formatData = (list: Record<string, any>[]) => |
||||
list.map( |
||||
(row) => |
||||
({ |
||||
row: { ...row }, |
||||
oldRow: { ...row }, |
||||
rowMeta: {}, |
||||
} as Row), |
||||
) |
||||
list.map( |
||||
(row) => |
||||
({ |
||||
row: { ...row }, |
||||
oldRow: { ...row }, |
||||
rowMeta: {}, |
||||
} as Row), |
||||
) |
||||
|
||||
const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState( |
||||
( |
||||
meta: Ref<(CalendarType & { id: string }) | undefined>, |
||||
viewMeta: Ref<(ViewType | CalendarType | undefined) & { id: string }> | ComputedRef<(ViewType & { id: string }) | undefined>, |
||||
shared = false, |
||||
where?: ComputedRef<string | undefined>, |
||||
) => { |
||||
if (!meta) { |
||||
throw new Error('Table meta is not available') |
||||
} |
||||
( |
||||
meta: Ref<(CalendarType & { id: string }) | undefined>, |
||||
viewMeta: Ref<(ViewType | CalendarType | undefined) & { id: string }> | ComputedRef<(ViewType & { id: string }) | undefined>, |
||||
shared = false, |
||||
where?: ComputedRef<string | undefined>, |
||||
) => { |
||||
if (!meta) { |
||||
throw new Error('Table meta is not available') |
||||
} |
||||
|
||||
const pageDate = ref<Date> (new Date()) |
||||
const pageDate = ref<Date>(new Date()) |
||||
|
||||
const activeCalendarView = ref<'month' | 'year' | 'day' | 'week'>('month') |
||||
const activeCalendarView = ref<'month' | 'year' | 'day' | 'week'>('month') |
||||
|
||||
const calDataType = ref<UITypes.Date | UITypes.DateTime>(UITypes.Date) |
||||
const calDataType = ref<UITypes.Date | UITypes.DateTime>(UITypes.Date) |
||||
|
||||
const selectedDate = ref<Date>(new Date()) |
||||
const selectedDateRange = ref<{ |
||||
start: Date | null |
||||
end: Date | null |
||||
}>({start: new Date(), end: null}) |
||||
const selectedDate = ref<Date>(new Date()) |
||||
const selectedDateRange = ref<{ |
||||
start: Date | null |
||||
end: Date | null |
||||
}>({ start: new Date(), end: null }) |
||||
|
||||
const defaultPageSize = 1000 |
||||
const defaultPageSize = 1000 |
||||
|
||||
const formattedData = ref<Row[]>([]) |
||||
const formattedData = ref<Row[]>([]) |
||||
|
||||
const { api } = useApi() |
||||
const { api } = useApi() |
||||
|
||||
const { base } = storeToRefs(useBase()) |
||||
const { base } = storeToRefs(useBase()) |
||||
|
||||
const { $api } = useNuxtApp() |
||||
const { $api } = useNuxtApp() |
||||
|
||||
const { isUIAllowed } = useRoles() |
||||
const { isUIAllowed } = useRoles() |
||||
|
||||
const isPublic = ref(shared) || inject(IsPublicInj, ref(false)) |
||||
const isPublic = ref(shared) || inject(IsPublicInj, ref(false)) |
||||
|
||||
const { sorts, nestedFilters } = useSmartsheetStoreOrThrow() |
||||
const { sorts, nestedFilters } = useSmartsheetStoreOrThrow() |
||||
|
||||
const { sharedView, fetchSharedViewData } = useSharedView() |
||||
const { sharedView, fetchSharedViewData } = useSharedView() |
||||
|
||||
const calendarMetaData = ref<CalendarType>({}) |
||||
const calendarMetaData = ref<CalendarType>({}) |
||||
|
||||
// Not Required in Calendar View TODO: Remove
|
||||
// const geoDataFieldColumn = ref<ColumnType | undefined>()
|
||||
// Not Required in Calendar View TODO: Remove
|
||||
// const geoDataFieldColumn = ref<ColumnType | undefined>()
|
||||
|
||||
const paginationData = ref<PaginatedType>({ page: 1, pageSize: defaultPageSize }) |
||||
const paginationData = ref<PaginatedType>({ page: 1, pageSize: defaultPageSize }) |
||||
|
||||
const queryParams = computed(() => ({ |
||||
limit: paginationData.value.pageSize ?? defaultPageSize, |
||||
where: where?.value ?? '', |
||||
})) |
||||
const queryParams = computed(() => ({ |
||||
limit: paginationData.value.pageSize ?? defaultPageSize, |
||||
where: where?.value ?? '', |
||||
})) |
||||
|
||||
const changeCalendarView = (view: 'month' | 'year' | 'day' | 'week') => { |
||||
activeCalendarView.value = view |
||||
} |
||||
const changeCalendarView = (view: 'month' | 'year' | 'day' | 'week') => { |
||||
activeCalendarView.value = view |
||||
} |
||||
|
||||
async function loadCalendarMeta() { |
||||
if (!viewMeta?.value?.id || !meta?.value?.columns) return |
||||
// TODO: Fetch Calendar Meta
|
||||
// calendarMetaData.value = isPublic.value ? (sharedView.value?.view as CalendarType) : await $api.dbView.calendarRead(viewMeta.value.id)
|
||||
calendarMetaData.value = isPublic.value ? (sharedView.value?.view as CalendarType) : await $api.dbView.mapRead(viewMeta.value.id) |
||||
async function loadCalendarMeta() { |
||||
if (!viewMeta?.value?.id || !meta?.value?.columns) return |
||||
// TODO: Fetch Calendar Meta
|
||||
// calendarMetaData.value = isPublic.value ? (sharedView.value?.view as CalendarType) : await $api.dbView.calendarRead(viewMeta.value.id)
|
||||
calendarMetaData.value = isPublic.value |
||||
? (sharedView.value?.view as CalendarType) |
||||
: await $api.dbView.mapRead(viewMeta.value.id) |
||||
|
||||
/*geoDataFieldColumn.value = |
||||
/* geoDataFieldColumn.value = |
||||
(meta.value.columns as ColumnType[]).filter((f) => f.id === mapMetaData.value.fk_geo_data_col_id)[0] || {} |
||||
*/ } |
||||
|
||||
async function loadCalendarData() { |
||||
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic?.value) return |
||||
|
||||
const res = !isPublic.value |
||||
? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value!.id!, { |
||||
...queryParams.value, |
||||
...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }), |
||||
where: where?.value, |
||||
}) |
||||
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: nestedFilters.value }) |
||||
formattedData.value = formatData(res!.list) |
||||
} |
||||
|
||||
async function updateCalendarMeta(updateObj: Partial<CalendarType>) { |
||||
if (!viewMeta?.value?.id || !isUIAllowed('dataEdit')) return |
||||
// await $api.dbView.calendarUpdate(viewMeta.value.id, updateObj)
|
||||
await $api.dbView.mapUpdate(viewMeta.value.id, updateObj) |
||||
} |
||||
|
||||
const paginateCalendarView = (action: 'next' | 'prev') => { |
||||
switch (activeCalendarView.value) { |
||||
case 'month': |
||||
selectedDate.value = action === 'next' ? addMonths(selectedDate.value, 1) : addMonths(selectedDate.value, -1) |
||||
if(pageDate.value.getFullYear() !== selectedDate.value.getFullYear()) { |
||||
pageDate.value = selectedDate.value |
||||
} |
||||
break |
||||
case 'year': |
||||
selectedDate.value = action === 'next' ? addYears(selectedDate.value, 1) : addYears(selectedDate.value, -1) |
||||
if(pageDate.value.getFullYear() !== selectedDate.value.getFullYear()) { |
||||
pageDate.value = selectedDate.value |
||||
} |
||||
break |
||||
case 'day': |
||||
selectedDate.value = action === 'next' ? addDays(selectedDate.value, 1) : addDays(selectedDate.value, -1) |
||||
if(pageDate.value.getFullYear() !== selectedDate.value.getFullYear()) { |
||||
pageDate.value = selectedDate.value |
||||
} else if(pageDate.value.getMonth() !== selectedDate.value.getMonth()) { |
||||
pageDate.value = selectedDate.value |
||||
} |
||||
break |
||||
case 'week': |
||||
selectedDateRange.value = action === 'next' ? { |
||||
start: addDays(selectedDateRange.value.start!, 7), |
||||
end: addDays(selectedDateRange.value.end!, 7) |
||||
} : { |
||||
start: addDays(selectedDateRange.value.start!, -7), |
||||
end: addDays(selectedDateRange.value.end!, -7) |
||||
} |
||||
break |
||||
} |
||||
} |
||||
|
||||
return { |
||||
formattedData, |
||||
changeCalendarView, |
||||
calDataType, |
||||
loadCalendarMeta, |
||||
updateCalendarMeta, |
||||
calendarMetaData, |
||||
activeCalendarView, |
||||
pageDate, |
||||
paginationData, |
||||
selectedDate, |
||||
selectedDateRange, |
||||
paginateCalendarView, |
||||
} |
||||
}, |
||||
*/ |
||||
} |
||||
|
||||
async function loadCalendarData() { |
||||
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic?.value) return |
||||
|
||||
const res = !isPublic.value |
||||
? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value!.id!, { |
||||
...queryParams.value, |
||||
...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }), |
||||
where: where?.value, |
||||
}) |
||||
: await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: nestedFilters.value }) |
||||
formattedData.value = formatData(res!.list) |
||||
} |
||||
|
||||
async function updateCalendarMeta(updateObj: Partial<CalendarType>) { |
||||
if (!viewMeta?.value?.id || !isUIAllowed('dataEdit')) return |
||||
// await $api.dbView.calendarUpdate(viewMeta.value.id, updateObj)
|
||||
await $api.dbView.mapUpdate(viewMeta.value.id, updateObj) |
||||
} |
||||
|
||||
const paginateCalendarView = (action: 'next' | 'prev') => { |
||||
switch (activeCalendarView.value) { |
||||
case 'month': |
||||
selectedDate.value = action === 'next' ? addMonths(selectedDate.value, 1) : addMonths(selectedDate.value, -1) |
||||
if (pageDate.value.getFullYear() !== selectedDate.value.getFullYear()) { |
||||
pageDate.value = selectedDate.value |
||||
} |
||||
break |
||||
case 'year': |
||||
selectedDate.value = action === 'next' ? addYears(selectedDate.value, 1) : addYears(selectedDate.value, -1) |
||||
if (pageDate.value.getFullYear() !== selectedDate.value.getFullYear()) { |
||||
pageDate.value = selectedDate.value |
||||
} |
||||
break |
||||
case 'day': |
||||
selectedDate.value = action === 'next' ? addDays(selectedDate.value, 1) : addDays(selectedDate.value, -1) |
||||
if (pageDate.value.getFullYear() !== selectedDate.value.getFullYear()) { |
||||
pageDate.value = selectedDate.value |
||||
} else if (pageDate.value.getMonth() !== selectedDate.value.getMonth()) { |
||||
pageDate.value = selectedDate.value |
||||
} |
||||
break |
||||
case 'week': |
||||
selectedDateRange.value = |
||||
action === 'next' |
||||
? { |
||||
start: addDays(selectedDateRange.value.start!, 7), |
||||
end: addDays(selectedDateRange.value.end!, 7), |
||||
} |
||||
: { |
||||
start: addDays(selectedDateRange.value.start!, -7), |
||||
end: addDays(selectedDateRange.value.end!, -7), |
||||
} |
||||
break |
||||
} |
||||
} |
||||
|
||||
return { |
||||
formattedData, |
||||
changeCalendarView, |
||||
calDataType, |
||||
loadCalendarMeta, |
||||
updateCalendarMeta, |
||||
calendarMetaData, |
||||
activeCalendarView, |
||||
pageDate, |
||||
paginationData, |
||||
selectedDate, |
||||
selectedDateRange, |
||||
paginateCalendarView, |
||||
} |
||||
}, |
||||
) |
||||
|
||||
export { useProvideCalendarViewStore } |
||||
|
||||
export function useCalendarViewStoreOrThrow() { |
||||
const calendarViewStore = useCalendarViewStore() |
||||
const calendarViewStore = useCalendarViewStore() |
||||
|
||||
if (calendarViewStore == null) throw new Error('Please call `useProvideCalendarViewStore` on the appropriate parent component') |
||||
if (calendarViewStore == null) throw new Error('Please call `useProvideCalendarViewStore` on the appropriate parent component') |
||||
|
||||
return calendarViewStore |
||||
return calendarViewStore |
||||
} |
||||
|
@ -1,145 +1,146 @@
|
||||
import type {CalendarRangeType} from 'nocodb-sdk'; |
||||
import type { CalendarRangeType } from 'nocodb-sdk'; |
||||
import Noco from '~/Noco'; |
||||
import NocoCache from '~/cache/NocoCache'; |
||||
import {extractProps} from '~/helpers/extractProps'; |
||||
import {CacheGetType, CacheScope, MetaTable} from '~/utils/globals'; |
||||
import { extractProps } from '~/helpers/extractProps'; |
||||
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; |
||||
|
||||
export default class CalendarRange implements CalendarRangeType { |
||||
id?: string; |
||||
fk_from_column_id?: string; |
||||
fk_to_column_id?: string | null; |
||||
fk_view_id?: string; |
||||
|
||||
constructor(data: Partial<CalendarRange>) { |
||||
Object.assign(this, data); |
||||
id?: string; |
||||
fk_from_column_id?: string; |
||||
fk_to_column_id?: string | null; |
||||
fk_view_id?: string; |
||||
|
||||
constructor(data: Partial<CalendarRange>) { |
||||
Object.assign(this, data); |
||||
} |
||||
|
||||
public static async insert( |
||||
data: Partial<CalendarRange>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const insertObj = extractProps(data, [ |
||||
'fk_from_column_id', |
||||
'fk_to_column_id', |
||||
'fk_view_id', |
||||
]); |
||||
|
||||
const { id } = await ncMeta.metaInsert2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
insertObj, |
||||
); |
||||
|
||||
await NocoCache.appendToList( |
||||
CacheScope.CALENDAR_VIEW_RANGE, |
||||
[data.fk_view_id], |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${id}`, |
||||
); |
||||
|
||||
return this.get(id, ncMeta); |
||||
} |
||||
|
||||
public static async bulkInsert( |
||||
data: Partial<CalendarRange>[], |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const insertObj = []; |
||||
|
||||
for (const d of data) { |
||||
const tempObj = extractProps(d, [ |
||||
'fk_from_column_id', |
||||
'fk_to_column_id', |
||||
'fk_view_id', |
||||
]); |
||||
insertObj.push(tempObj); |
||||
} |
||||
|
||||
public static async insert( |
||||
data: Partial<CalendarRange>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const insertObj = extractProps(data, [ |
||||
'fk_from_column_id', |
||||
'fk_to_column_id', |
||||
'fk_view_id', |
||||
]); |
||||
|
||||
const { id } = await ncMeta.metaInsert2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
insertObj, |
||||
); |
||||
|
||||
await NocoCache.appendToList( |
||||
CacheScope.CALENDAR_VIEW_RANGE, |
||||
[data.fk_view_id], |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${id}`, |
||||
); |
||||
|
||||
return this.get(id, ncMeta); |
||||
const bulkData = await ncMeta.bulkMetaInsert( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
insertObj, |
||||
); |
||||
|
||||
for (const d of bulkData) { |
||||
await NocoCache.appendToList( |
||||
CacheScope.CALENDAR_VIEW_RANGE, |
||||
[d.fk_view_id], |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${d.id}`, |
||||
); |
||||
await NocoCache.set(`${CacheScope.CALENDAR_VIEW_RANGE}:${d.id}`, d); |
||||
} |
||||
|
||||
public static async bulkInsert( |
||||
data: Partial<CalendarRange>[], |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const insertObj = []; |
||||
|
||||
for (const d of data) { |
||||
const tempObj = extractProps(d, [ |
||||
'fk_from_column_id', |
||||
'fk_to_column_id', |
||||
'fk_view_id', |
||||
]); |
||||
insertObj.push(tempObj); |
||||
} |
||||
|
||||
const bulkData = await ncMeta.bulkMetaInsert( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
insertObj, |
||||
); |
||||
|
||||
for (const d of bulkData) { |
||||
await NocoCache.appendToList( |
||||
CacheScope.CALENDAR_VIEW_RANGE, |
||||
[d.fk_view_id], |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${d.id}`, |
||||
); |
||||
await NocoCache.set(`${CacheScope.CALENDAR_VIEW_RANGE}:${d.id}`, d); |
||||
} |
||||
|
||||
return true; |
||||
return true; |
||||
} |
||||
|
||||
public static async get( |
||||
calendarRangeId: string, |
||||
ncMeta = Noco.ncMeta, |
||||
): Promise<CalendarRange> { |
||||
let data = |
||||
calendarRangeId && |
||||
(await NocoCache.get( |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${calendarRangeId}`, |
||||
CacheGetType.TYPE_OBJECT, |
||||
)); |
||||
if (!data) { |
||||
data = await ncMeta.metaGet2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
calendarRangeId, |
||||
); |
||||
await NocoCache.set( |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${calendarRangeId}`, |
||||
data, |
||||
); |
||||
} |
||||
|
||||
public static async get( |
||||
calendarRangeId: string, |
||||
ncMeta = Noco.ncMeta, |
||||
): Promise<CalendarRange> { |
||||
let data = |
||||
calendarRangeId && |
||||
(await NocoCache.get( |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${calendarRangeId}`, |
||||
CacheGetType.TYPE_OBJECT, |
||||
)); |
||||
if (!data) { |
||||
data = await ncMeta.metaGet2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
calendarRangeId, |
||||
); |
||||
await NocoCache.set( |
||||
`${CacheScope.CALENDAR_VIEW_RANGE}:${calendarRangeId}`, |
||||
data, |
||||
); |
||||
} |
||||
return data && new CalendarRange(data); |
||||
return data && new CalendarRange(data); |
||||
} |
||||
|
||||
public static async read(fk_view_id: string, ncMeta = Noco.ncMeta) { |
||||
const cachedList = await NocoCache.getList(CacheScope.CALENDAR_VIEW_RANGE, [ |
||||
fk_view_id, |
||||
]); |
||||
let { list: ranges } = cachedList; |
||||
const { isNoneList } = cachedList; |
||||
if (!isNoneList && !ranges.length) { |
||||
ranges = await ncMeta.metaList2( |
||||
null, //,
|
||||
null, //model.db_alias,
|
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
{ condition: { fk_view_id } }, |
||||
); |
||||
await NocoCache.setList( |
||||
CacheScope.CALENDAR_VIEW_RANGE, |
||||
[fk_view_id], |
||||
ranges.map(({ created_at, updated_at, ...others }) => others), |
||||
); |
||||
} |
||||
|
||||
public static async read(fk_view_id: string, ncMeta = Noco.ncMeta) { |
||||
const cachedList = await NocoCache.getList(CacheScope.CALENDAR_VIEW_RANGE, [ |
||||
fk_view_id, |
||||
]); |
||||
let { list: ranges } = cachedList; |
||||
const { isNoneList } = cachedList; |
||||
if (!isNoneList && !ranges.length) { |
||||
ranges = await ncMeta.metaList2( |
||||
null, //,
|
||||
null, //model.db_alias,
|
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
{ condition: { fk_view_id } }, |
||||
); |
||||
await NocoCache.setList( |
||||
CacheScope.CALENDAR_VIEW_RANGE, |
||||
[fk_view_id], |
||||
ranges.map(({ created_at, updated_at, ...others }) => others), |
||||
); |
||||
return ranges?.length |
||||
? { |
||||
ranges: ranges.map( |
||||
({ created_at, updated_at, ...c }) => new CalendarRange(c), |
||||
), |
||||
} |
||||
|
||||
return ranges?.length |
||||
? { |
||||
ranges: ranges |
||||
.map(({ created_at, updated_at, ...c }) => new CalendarRange(c)) |
||||
} |
||||
: null; |
||||
} |
||||
|
||||
public static async find( |
||||
fk_view_id: string, |
||||
ncMeta = Noco.ncMeta, |
||||
): Promise<CalendarRange> { |
||||
const data = await ncMeta.metaGet2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
{ |
||||
fk_view_id, |
||||
}, |
||||
); |
||||
|
||||
return data && new CalendarRange(data); |
||||
} |
||||
: null; |
||||
} |
||||
|
||||
public static async find( |
||||
fk_view_id: string, |
||||
ncMeta = Noco.ncMeta, |
||||
): Promise<CalendarRange> { |
||||
const data = await ncMeta.metaGet2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
{ |
||||
fk_view_id, |
||||
}, |
||||
); |
||||
|
||||
return data && new CalendarRange(data); |
||||
} |
||||
} |
||||
|
@ -1,115 +1,135 @@
|
||||
import type {CalendarType} from 'nocodb-sdk'; |
||||
import {BoolType, MetaType} from 'nocodb-sdk'; |
||||
import type { BoolType, MetaType } from 'nocodb-sdk'; |
||||
import type { CalendarType } from 'nocodb-sdk'; |
||||
import View from '~/models/View'; |
||||
import {extractProps} from '~/helpers/extractProps'; |
||||
import { extractProps } from '~/helpers/extractProps'; |
||||
import NocoCache from '~/cache/NocoCache'; |
||||
import Noco from '~/Noco'; |
||||
import {CacheGetType, CacheScope, MetaTable} from '~/utils/globals'; |
||||
import CalendarRange from "~/models/CalendarRange"; |
||||
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; |
||||
import CalendarRange from '~/models/CalendarRange'; |
||||
|
||||
export default class CalendarView implements CalendarType { |
||||
fk_view_id: string; |
||||
title: string; |
||||
base_id?: string; |
||||
source_id?: string; |
||||
meta?: MetaType; |
||||
calendar_range?: Array<Partial<CalendarRange>> |
||||
fk_cover_image_col_id?: string; |
||||
// below fields are not in use at this moment
|
||||
// keep them for time being
|
||||
show?: BoolType; |
||||
public?: BoolType; |
||||
password?: string; |
||||
show_all_fields?: BoolType; |
||||
fk_view_id: string; |
||||
title: string; |
||||
base_id?: string; |
||||
source_id?: string; |
||||
meta?: MetaType; |
||||
calendar_range?: Array<Partial<CalendarRange>>; |
||||
fk_cover_image_col_id?: string; |
||||
// below fields are not in use at this moment
|
||||
// keep them for time being
|
||||
show?: BoolType; |
||||
public?: BoolType; |
||||
password?: string; |
||||
show_all_fields?: BoolType; |
||||
|
||||
constructor(data: CalendarView) { |
||||
Object.assign(this, data); |
||||
} |
||||
|
||||
public static async get(viewId: string, ncMeta = Noco.ncMeta) { |
||||
let view = |
||||
viewId && |
||||
(await NocoCache.get( |
||||
`${CacheScope.CALENDAR_VIEW}:${viewId}`, |
||||
CacheGetType.TYPE_OBJECT, |
||||
)); |
||||
if (view) { |
||||
const calendarRange = await CalendarRange.read(viewId, ncMeta); |
||||
if (calendarRange) { |
||||
view.calendar_range = calendarRange.ranges; |
||||
} else { |
||||
view.calendar_range = []; |
||||
} |
||||
} else { |
||||
view = await ncMeta.metaGet2(null, null, MetaTable.CALENDAR_VIEW, { |
||||
fk_view_id: viewId, |
||||
}); |
||||
const calendarRange = await CalendarRange.read(viewId); |
||||
if (calendarRange) { |
||||
view.calendar_range = calendarRange.ranges; |
||||
} |
||||
await NocoCache.set(`${CacheScope.CALENDAR_VIEW}:${viewId}`, view); |
||||
} |
||||
constructor(data: CalendarView) { |
||||
Object.assign(this, data); |
||||
} |
||||
|
||||
return view && new CalendarView(view); |
||||
public static async get(viewId: string, ncMeta = Noco.ncMeta) { |
||||
let view = |
||||
viewId && |
||||
(await NocoCache.get( |
||||
`${CacheScope.CALENDAR_VIEW}:${viewId}`, |
||||
CacheGetType.TYPE_OBJECT, |
||||
)); |
||||
if (view) { |
||||
const calendarRange = await CalendarRange.read(viewId, ncMeta); |
||||
if (calendarRange) { |
||||
view.calendar_range = calendarRange.ranges; |
||||
} else { |
||||
view.calendar_range = []; |
||||
} |
||||
} else { |
||||
view = await ncMeta.metaGet2(null, null, MetaTable.CALENDAR_VIEW, { |
||||
fk_view_id: viewId, |
||||
}); |
||||
const calendarRange = await CalendarRange.read(viewId); |
||||
if (calendarRange) { |
||||
view.calendar_range = calendarRange.ranges; |
||||
} |
||||
await NocoCache.set(`${CacheScope.CALENDAR_VIEW}:${viewId}`, view); |
||||
} |
||||
|
||||
static async insert(view: Partial<CalendarView>, ncMeta = Noco.ncMeta) { |
||||
const insertObj = { |
||||
base_id: view.base_id, |
||||
source_id: view.source_id, |
||||
fk_view_id: view.fk_view_id, |
||||
meta: view.meta, |
||||
}; |
||||
return view && new CalendarView(view); |
||||
} |
||||
|
||||
const viewRef = await View.get(view.fk_view_id); |
||||
static async insert(view: Partial<CalendarView>, ncMeta = Noco.ncMeta) { |
||||
const insertObj = { |
||||
base_id: view.base_id, |
||||
source_id: view.source_id, |
||||
fk_view_id: view.fk_view_id, |
||||
meta: view.meta, |
||||
}; |
||||
|
||||
if (!(view.base_id && view.source_id)) { |
||||
insertObj.base_id = viewRef.base_id; |
||||
insertObj.source_id = viewRef.source_id; |
||||
} |
||||
const viewRef = await View.get(view.fk_view_id); |
||||
|
||||
await ncMeta.metaInsert2(null, null, MetaTable.CALENDAR_VIEW, insertObj, true); |
||||
|
||||
return this.get(view.fk_view_id, ncMeta); |
||||
if (!(view.base_id && view.source_id)) { |
||||
insertObj.base_id = viewRef.base_id; |
||||
insertObj.source_id = viewRef.source_id; |
||||
} |
||||
|
||||
static async update( |
||||
calendarId: string, |
||||
body: Partial<CalendarView>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
// get existing cache
|
||||
const key = `${CacheScope.CALENDAR_VIEW_COLUMN}:${calendarId}`; |
||||
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); |
||||
await ncMeta.metaInsert2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW, |
||||
insertObj, |
||||
true, |
||||
); |
||||
|
||||
return this.get(view.fk_view_id, ncMeta); |
||||
} |
||||
|
||||
const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']); |
||||
static async update( |
||||
calendarId: string, |
||||
body: Partial<CalendarView>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
// get existing cache
|
||||
const key = `${CacheScope.CALENDAR_VIEW_COLUMN}:${calendarId}`; |
||||
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); |
||||
|
||||
if (updateObj.meta && typeof updateObj.meta === 'object') { |
||||
updateObj.meta = JSON.stringify(updateObj.meta ?? {}); |
||||
} |
||||
const updateObj = extractProps(body, ['fk_cover_image_col_id', 'meta']); |
||||
|
||||
if (o) { |
||||
o = { ...o, ...updateObj }; |
||||
// set cache
|
||||
await NocoCache.set(key, o); |
||||
} |
||||
if (updateObj.meta && typeof updateObj.meta === 'object') { |
||||
updateObj.meta = JSON.stringify(updateObj.meta ?? {}); |
||||
} |
||||
|
||||
if (o) { |
||||
o = { ...o, ...updateObj }; |
||||
// set cache
|
||||
await NocoCache.set(key, o); |
||||
} |
||||
|
||||
if (body.calendar_range) { |
||||
await NocoCache.del(`${CacheScope.CALENDAR_VIEW_RANGE}:${calendarId}`); |
||||
await ncMeta.metaDelete(null, null, MetaTable.CALENDAR_VIEW_RANGE, {}, { |
||||
fk_view_id: calendarId, |
||||
}); |
||||
await CalendarRange.bulkInsert(body.calendar_range.map((range) => { |
||||
return { |
||||
fk_view_id: calendarId, |
||||
...range |
||||
} |
||||
})); |
||||
} |
||||
// update meta
|
||||
return await ncMeta.metaUpdate(null, null, MetaTable.CALENDAR_VIEW, updateObj, { |
||||
if (body.calendar_range) { |
||||
await NocoCache.del(`${CacheScope.CALENDAR_VIEW_RANGE}:${calendarId}`); |
||||
await ncMeta.metaDelete( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_RANGE, |
||||
{}, |
||||
{ |
||||
fk_view_id: calendarId, |
||||
}, |
||||
); |
||||
await CalendarRange.bulkInsert( |
||||
body.calendar_range.map((range) => { |
||||
return { |
||||
fk_view_id: calendarId, |
||||
}); |
||||
...range, |
||||
}; |
||||
}), |
||||
); |
||||
} |
||||
// update meta
|
||||
return await ncMeta.metaUpdate( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW, |
||||
updateObj, |
||||
{ |
||||
fk_view_id: calendarId, |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
|
@ -1,173 +1,180 @@
|
||||
import type {BoolType, MetaType,} from 'nocodb-sdk'; |
||||
import type { BoolType, MetaType } from 'nocodb-sdk'; |
||||
import View from '~/models/View'; |
||||
import Noco from '~/Noco'; |
||||
import NocoCache from '~/cache/NocoCache'; |
||||
import {extractProps} from '~/helpers/extractProps'; |
||||
import {deserializeJSON} from '~/utils/serialize'; |
||||
import {CacheGetType, CacheScope, MetaTable} from '~/utils/globals'; |
||||
import { extractProps } from '~/helpers/extractProps'; |
||||
import { deserializeJSON } from '~/utils/serialize'; |
||||
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals'; |
||||
|
||||
export default class CalendarViewColumn { |
||||
id?: string; |
||||
fk_view_id?: string; |
||||
fk_column_id?: string; |
||||
base_id?: string; |
||||
source_id?: string; |
||||
show?: BoolType; |
||||
underline?: BoolType; |
||||
bold?: BoolType; |
||||
italic?: BoolType; |
||||
order?: number; |
||||
meta?: MetaType; |
||||
|
||||
constructor(data: CalendarViewColumn) { |
||||
Object.assign(this, data); |
||||
id?: string; |
||||
fk_view_id?: string; |
||||
fk_column_id?: string; |
||||
base_id?: string; |
||||
source_id?: string; |
||||
show?: BoolType; |
||||
underline?: BoolType; |
||||
bold?: BoolType; |
||||
italic?: BoolType; |
||||
order?: number; |
||||
meta?: MetaType; |
||||
|
||||
constructor(data: CalendarViewColumn) { |
||||
Object.assign(this, data); |
||||
} |
||||
|
||||
public static async get(calendarViewColumnId: string, ncMeta = Noco.ncMeta) { |
||||
let viewColumn = |
||||
calendarViewColumnId && |
||||
(await NocoCache.get( |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${calendarViewColumnId}`, |
||||
CacheGetType.TYPE_OBJECT, |
||||
)); |
||||
if (!viewColumn) { |
||||
viewColumn = await ncMeta.metaGet2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
calendarViewColumnId, |
||||
); |
||||
viewColumn.meta = |
||||
viewColumn.meta && typeof viewColumn.meta === 'string' |
||||
? JSON.parse(viewColumn.meta) |
||||
: viewColumn.meta; |
||||
} |
||||
|
||||
public static async get(calendarViewColumnId: string, ncMeta = Noco.ncMeta) { |
||||
let viewColumn = |
||||
calendarViewColumnId && |
||||
(await NocoCache.get( |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${calendarViewColumnId}`, |
||||
CacheGetType.TYPE_OBJECT, |
||||
)); |
||||
if (!viewColumn) { |
||||
viewColumn = await ncMeta.metaGet2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
calendarViewColumnId, |
||||
); |
||||
viewColumn.meta = |
||||
viewColumn.meta && typeof viewColumn.meta === 'string' |
||||
? JSON.parse(viewColumn.meta) |
||||
: viewColumn.meta; |
||||
} |
||||
await NocoCache.set( |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${calendarViewColumnId}`, |
||||
viewColumn, |
||||
); |
||||
|
||||
return viewColumn && new CalendarViewColumn(viewColumn); |
||||
} |
||||
|
||||
static async insert(column: Partial<CalendarViewColumn>, ncMeta = Noco.ncMeta) { |
||||
const insertObj = extractProps(column, [ |
||||
'fk_view_id', |
||||
'fk_column_id', |
||||
'show', |
||||
'base_id', |
||||
'source_id', |
||||
'underline', |
||||
'bold', |
||||
'italic', |
||||
]); |
||||
|
||||
insertObj.order = await ncMeta.metaGetNextOrder( |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
{ |
||||
fk_view_id: insertObj.fk_view_id, |
||||
}, |
||||
); |
||||
|
||||
if (!(insertObj.base_id && insertObj.source_id)) { |
||||
const viewRef = await View.get(insertObj.fk_view_id, ncMeta); |
||||
insertObj.base_id = viewRef.base_id; |
||||
insertObj.source_id = viewRef.source_id; |
||||
} |
||||
|
||||
const { id, fk_column_id } = await ncMeta.metaInsert2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
insertObj, |
||||
); |
||||
|
||||
await NocoCache.set(`${CacheScope.CALENDAR_VIEW_COLUMN}:${fk_column_id}`, id); |
||||
|
||||
// if cache is not present skip pushing it into the list to avoid unexpected behaviour
|
||||
const { list } = await NocoCache.getList(CacheScope.CALENDAR_VIEW_COLUMN, [ |
||||
column.fk_view_id, |
||||
]); |
||||
|
||||
if (list?.length) |
||||
await NocoCache.appendToList( |
||||
CacheScope.CALENDAR_VIEW_COLUMN, |
||||
[column.fk_view_id], |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${id}`, |
||||
); |
||||
return this.get(id, ncMeta); |
||||
await NocoCache.set( |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${calendarViewColumnId}`, |
||||
viewColumn, |
||||
); |
||||
|
||||
return viewColumn && new CalendarViewColumn(viewColumn); |
||||
} |
||||
|
||||
static async insert( |
||||
column: Partial<CalendarViewColumn>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const insertObj = extractProps(column, [ |
||||
'fk_view_id', |
||||
'fk_column_id', |
||||
'show', |
||||
'base_id', |
||||
'source_id', |
||||
'underline', |
||||
'bold', |
||||
'italic', |
||||
]); |
||||
|
||||
insertObj.order = await ncMeta.metaGetNextOrder( |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
{ |
||||
fk_view_id: insertObj.fk_view_id, |
||||
}, |
||||
); |
||||
|
||||
if (!(insertObj.base_id && insertObj.source_id)) { |
||||
const viewRef = await View.get(insertObj.fk_view_id, ncMeta); |
||||
insertObj.base_id = viewRef.base_id; |
||||
insertObj.source_id = viewRef.source_id; |
||||
} |
||||
|
||||
public static async list( |
||||
viewId: string, |
||||
ncMeta = Noco.ncMeta, |
||||
): Promise<CalendarViewColumn[]> { |
||||
const cachedList = await NocoCache.getList(CacheScope.CALENDAR_VIEW_COLUMN, [ |
||||
viewId, |
||||
]); |
||||
let { list: viewColumns } = cachedList; |
||||
const { isNoneList } = cachedList; |
||||
if (!isNoneList && !viewColumns.length) { |
||||
viewColumns = await ncMeta.metaList2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
{ |
||||
condition: { |
||||
fk_view_id: viewId, |
||||
}, |
||||
orderBy: { |
||||
order: 'asc', |
||||
}, |
||||
}, |
||||
); |
||||
|
||||
for (const viewColumn of viewColumns) { |
||||
viewColumn.meta = deserializeJSON(viewColumn.meta); |
||||
} |
||||
|
||||
await NocoCache.setList( |
||||
CacheScope.CALENDAR_VIEW_COLUMN, |
||||
[viewId], |
||||
viewColumns, |
||||
); |
||||
} |
||||
viewColumns.sort( |
||||
(a, b) => |
||||
(a.order != null ? a.order : Infinity) - |
||||
(b.order != null ? b.order : Infinity), |
||||
); |
||||
return viewColumns?.map((v) => new CalendarViewColumn(v)); |
||||
const { id, fk_column_id } = await ncMeta.metaInsert2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
insertObj, |
||||
); |
||||
|
||||
await NocoCache.set( |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${fk_column_id}`, |
||||
id, |
||||
); |
||||
|
||||
// if cache is not present skip pushing it into the list to avoid unexpected behaviour
|
||||
const { list } = await NocoCache.getList(CacheScope.CALENDAR_VIEW_COLUMN, [ |
||||
column.fk_view_id, |
||||
]); |
||||
|
||||
if (list?.length) |
||||
await NocoCache.appendToList( |
||||
CacheScope.CALENDAR_VIEW_COLUMN, |
||||
[column.fk_view_id], |
||||
`${CacheScope.CALENDAR_VIEW_COLUMN}:${id}`, |
||||
); |
||||
return this.get(id, ncMeta); |
||||
} |
||||
|
||||
public static async list( |
||||
viewId: string, |
||||
ncMeta = Noco.ncMeta, |
||||
): Promise<CalendarViewColumn[]> { |
||||
const cachedList = await NocoCache.getList( |
||||
CacheScope.CALENDAR_VIEW_COLUMN, |
||||
[viewId], |
||||
); |
||||
let { list: viewColumns } = cachedList; |
||||
const { isNoneList } = cachedList; |
||||
if (!isNoneList && !viewColumns.length) { |
||||
viewColumns = await ncMeta.metaList2( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
{ |
||||
condition: { |
||||
fk_view_id: viewId, |
||||
}, |
||||
orderBy: { |
||||
order: 'asc', |
||||
}, |
||||
}, |
||||
); |
||||
|
||||
for (const viewColumn of viewColumns) { |
||||
viewColumn.meta = deserializeJSON(viewColumn.meta); |
||||
} |
||||
|
||||
await NocoCache.setList( |
||||
CacheScope.CALENDAR_VIEW_COLUMN, |
||||
[viewId], |
||||
viewColumns, |
||||
); |
||||
} |
||||
|
||||
static async update( |
||||
columnId: string, |
||||
body: Partial<CalendarViewColumn>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const updateObj = extractProps(body, [ |
||||
'show', |
||||
'order', |
||||
'underline', |
||||
'bold', |
||||
'italic', |
||||
]); |
||||
|
||||
// get existing cache
|
||||
const key = `${CacheScope.CALENDAR_VIEW_COLUMN}:${columnId}`; |
||||
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); |
||||
if (o) { |
||||
Object.assign(o, updateObj); |
||||
// set cache
|
||||
await NocoCache.set(key, o); |
||||
} |
||||
// update meta
|
||||
return await ncMeta.metaUpdate( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
updateObj, |
||||
columnId, |
||||
); |
||||
viewColumns.sort( |
||||
(a, b) => |
||||
(a.order != null ? a.order : Infinity) - |
||||
(b.order != null ? b.order : Infinity), |
||||
); |
||||
return viewColumns?.map((v) => new CalendarViewColumn(v)); |
||||
} |
||||
|
||||
static async update( |
||||
columnId: string, |
||||
body: Partial<CalendarViewColumn>, |
||||
ncMeta = Noco.ncMeta, |
||||
) { |
||||
const updateObj = extractProps(body, [ |
||||
'show', |
||||
'order', |
||||
'underline', |
||||
'bold', |
||||
'italic', |
||||
]); |
||||
|
||||
// get existing cache
|
||||
const key = `${CacheScope.CALENDAR_VIEW_COLUMN}:${columnId}`; |
||||
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); |
||||
if (o) { |
||||
Object.assign(o, updateObj); |
||||
// set cache
|
||||
await NocoCache.set(key, o); |
||||
} |
||||
// update meta
|
||||
return await ncMeta.metaUpdate( |
||||
null, |
||||
null, |
||||
MetaTable.CALENDAR_VIEW_COLUMNS, |
||||
updateObj, |
||||
columnId, |
||||
); |
||||
} |
||||
} |
||||
|
@ -1,85 +1,86 @@
|
||||
import {Injectable} from '@nestjs/common'; |
||||
import type {CalendarUpdateReqType, UserType, ViewCreateReqType,} from 'nocodb-sdk'; |
||||
import {AppEvents, ViewTypes} from 'nocodb-sdk'; |
||||
import type {NcRequest} from '~/interface/config'; |
||||
import {AppHooksService} from '~/services/app-hooks/app-hooks.service'; |
||||
import {validatePayload} from '~/helpers'; |
||||
import {NcError} from '~/helpers/catchError'; |
||||
import {CalendarView, View} from '~/models'; |
||||
import CalendarRange from "~/models/CalendarRange"; |
||||
import { Injectable } from '@nestjs/common'; |
||||
import { AppEvents, ViewTypes } from 'nocodb-sdk'; |
||||
import type { |
||||
CalendarUpdateReqType, |
||||
UserType, |
||||
ViewCreateReqType, |
||||
} from 'nocodb-sdk'; |
||||
import type { NcRequest } from '~/interface/config'; |
||||
import { AppHooksService } from '~/services/app-hooks/app-hooks.service'; |
||||
import { validatePayload } from '~/helpers'; |
||||
import { NcError } from '~/helpers/catchError'; |
||||
import { CalendarView, View } from '~/models'; |
||||
import CalendarRange from '~/models/CalendarRange'; |
||||
|
||||
@Injectable() |
||||
export class CalendarsService { |
||||
constructor(private readonly appHooksService: AppHooksService) { |
||||
} |
||||
|
||||
async calendarViewGet(param: { calendarViewId: string }) { |
||||
const calendarView = await CalendarView.get(param.calendarViewId); |
||||
if (!calendarView) { |
||||
NcError.badRequest('Calendar view not found'); |
||||
} |
||||
const calendarRanges = await CalendarRange.read(param.calendarViewId) |
||||
return { |
||||
...calendarView, |
||||
calendar_range: calendarRanges |
||||
}; |
||||
constructor(private readonly appHooksService: AppHooksService) {} |
||||
|
||||
async calendarViewGet(param: { calendarViewId: string }) { |
||||
const calendarView = await CalendarView.get(param.calendarViewId); |
||||
if (!calendarView) { |
||||
NcError.badRequest('Calendar view not found'); |
||||
} |
||||
const calendarRanges = await CalendarRange.read(param.calendarViewId); |
||||
return { |
||||
...calendarView, |
||||
calendar_range: calendarRanges, |
||||
}; |
||||
} |
||||
|
||||
async calendarViewCreate(param: { |
||||
tableId: string; |
||||
calendar: ViewCreateReqType; |
||||
user: UserType; |
||||
req: NcRequest; |
||||
}) { |
||||
- |
||||
validatePayload( |
||||
'swagger.json#/components/schemas/ViewCreateReq', |
||||
param.calendar, |
||||
); |
||||
async calendarViewCreate(param: { |
||||
tableId: string; |
||||
calendar: ViewCreateReqType; |
||||
user: UserType; |
||||
req: NcRequest; |
||||
}) { |
||||
-validatePayload( |
||||
'swagger.json#/components/schemas/ViewCreateReq', |
||||
param.calendar, |
||||
); |
||||
|
||||
const view = await View.insert({ |
||||
...param.calendar, |
||||
// todo: sanitize
|
||||
fk_model_id: param.tableId, |
||||
type: ViewTypes.CALENDAR, |
||||
}); |
||||
const view = await View.insert({ |
||||
...param.calendar, |
||||
// todo: sanitize
|
||||
fk_model_id: param.tableId, |
||||
type: ViewTypes.CALENDAR, |
||||
}); |
||||
|
||||
this.appHooksService.emit(AppEvents.VIEW_CREATE, { |
||||
view, |
||||
showAs: 'calendar', |
||||
user: param.user, |
||||
this.appHooksService.emit(AppEvents.VIEW_CREATE, { |
||||
view, |
||||
showAs: 'calendar', |
||||
user: param.user, |
||||
|
||||
req: param.req, |
||||
}); |
||||
req: param.req, |
||||
}); |
||||
|
||||
return view; |
||||
} |
||||
return view; |
||||
} |
||||
|
||||
async calendarViewUpdate(param: { |
||||
calendarViewId: string; |
||||
calendar: CalendarUpdateReqType; |
||||
req: NcRequest; |
||||
}) { |
||||
validatePayload( |
||||
'swagger.json#/components/schemas/CalendarUpdateReq', |
||||
param.calendar, |
||||
); |
||||
async calendarViewUpdate(param: { |
||||
calendarViewId: string; |
||||
calendar: CalendarUpdateReqType; |
||||
req: NcRequest; |
||||
}) { |
||||
validatePayload( |
||||
'swagger.json#/components/schemas/CalendarUpdateReq', |
||||
param.calendar, |
||||
); |
||||
|
||||
const view = await View.get(param.calendarViewId); |
||||
const view = await View.get(param.calendarViewId); |
||||
|
||||
if (!view) { |
||||
NcError.badRequest('View not found'); |
||||
} |
||||
if (!view) { |
||||
NcError.badRequest('View not found'); |
||||
} |
||||
|
||||
const res = await CalendarView.update(param.calendarViewId, param.calendar); |
||||
const res = await CalendarView.update(param.calendarViewId, param.calendar); |
||||
|
||||
this.appHooksService.emit(AppEvents.VIEW_UPDATE, { |
||||
view, |
||||
showAs: 'calendar', |
||||
req: param.req, |
||||
}); |
||||
this.appHooksService.emit(AppEvents.VIEW_UPDATE, { |
||||
view, |
||||
showAs: 'calendar', |
||||
req: param.req, |
||||
}); |
||||
|
||||
return res; |
||||
} |
||||
return res; |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue