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