Browse Source

feat(nc-gui): week view early preview

pull/7611/head
DarkPhoenix2704 7 months ago
parent
commit
cf52dd2c66
  1. 17
      packages/nc-gui/components/smartsheet/calendar/DayView.vue
  2. 194
      packages/nc-gui/components/smartsheet/calendar/WeekView.vue

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

@ -25,8 +25,14 @@ const data = toRefs(props).data
const displayField = computed(() => meta.value?.columns?.find((c) => c.pv && fields.value.includes(c)) ?? null)
const { pageDate, selectedTime, selectedDate, calDataType, formattedData, calendarRange, selectedDateRange } =
useCalendarViewStoreOrThrow()
const {
selectedTime,
selectedDate: _selectedDate,
calDataType,
formattedData,
calendarRange,
selectedDateRange,
} = useCalendarViewStoreOrThrow()
const renderData = computed(() => {
if (data.value) {
@ -35,6 +41,13 @@ const renderData = computed(() => {
return formattedData.value
})
const selectedDate = computed(() => {
if (props.isEmbed) {
return props.renderDate ?? renderData
}
return _selectedDate.value
})
const recordsAcrossAllRange = computed<Row[]>(() => {
if (!calendarRange.value) return []
const recordsByRange = []

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

@ -1,10 +1,15 @@
<script lang="ts" setup>
import dayjs from 'dayjs'
import type { ColumnType } from 'nocodb-sdk'
import type { Row } from '~/lib'
const emits = defineEmits(['expand-record'])
const { selectedDateRange, formattedData, calendarRange } = useCalendarViewStoreOrThrow()
const { selectedDateRange, formattedData, calendarRange, selectedDate, displayField } = useCalendarViewStoreOrThrow()
const container = ref(null)
const { width: containerWidth } = useElementSize(container)
const weekDates = computed(() => {
const startOfWeek = new Date(selectedDateRange.value.start)
@ -17,16 +22,143 @@ const weekDates = computed(() => {
return datesArray
})
const getData = (date: Date) => {
const range = calendarRange.value[0]
if (!range) return []
if (!formattedData.value) return []
return formattedData.value.filter((record) => dayjs(date).isSame(dayjs(record.row[range.fk_from_col.title])))
const getRecordPosition = (record: Row) => {
if (!calendarRange.value) return ''
if (!record.rowMeta.range) return ''
const range = record.rowMeta.range
const startCol = range.fk_from_col
const endCol = range.fk_to_col
if (!endCol && startCol) {
const startDate = dayjs(record.row[startCol.title])
return startDate.isBetween(selectedDateRange.value.start, selectedDateRange.value.end, 'day', '[]')
? 'rounded'
: startDate.isBefore(selectedDateRange.value.start)
? 'rightRounded'
: 'leftRounded'
} else if (endCol && startCol) {
const startDate = dayjs(record.row[startCol.title])
const endDate = dayjs(record.row[endCol.title])
// StartDate is same/after as selectedDateRange start and EndDate is same/before as selectedDateRange end -> No Spanning - none
// EndDate is same/after selectedDateRange start and StartDate is same/before selectedDateRange end -> No Spanning - none
// StartDate is same as selectedDateRange start and no EndDate -> no Spanning - none
// EndDate is same as selectedDateRange end and no StartDate -> no Spanning - none
// StartDate is same/after as selectedDateRange start and EndDate is after selectedDateRange end -> Spanning Right
// EndDate is same/after selectedDateRange start and StartDate is after selectedDateRange end -> Spanning Right
// StartDate is before selectedDateRange start and EndDate is before selectedDateRange end -> Spanning Left
// EndDate is before selectedDateRange start and StartDate is before selectedDateRange end -> Spanning Left
// StartDate is before selectedDateRange start and EndDate is after selectedDateRange end -> Spanning Both
// StartDate is after selectedDateRange end and EndDate is before selectedDateRange start -> Spanning Both
if (startDate.isSameOrAfter(selectedDateRange.value.start) && endDate.isSameOrBefore(selectedDateRange.value.end)) {
return 'rounded'
} else if (endDate.isSameOrAfter(selectedDateRange.value.start) && startDate.isSameOrBefore(selectedDateRange.value.end)) {
return 'rounded'
} else if ((startDate && !endDate) || (endDate && !startDate)) {
return 'rounded'
} else if (startDate.isSameOrAfter(selectedDateRange.value.start) && endDate.isAfter(selectedDateRange.value.end)) {
return 'leftRounded'
} else if (endDate.isSameOrAfter(selectedDateRange.value.start) && startDate.isAfter(selectedDateRange.value.end)) {
return 'leftRounded'
} else if (startDate.isBefore(selectedDateRange.value.start) && endDate.isBefore(selectedDateRange.value.end)) {
return 'rightRounded'
} else if (endDate.isBefore(selectedDateRange.value.start) && startDate.isBefore(selectedDateRange.value.end)) {
return 'rightRounded'
} else if (startDate.isBefore(selectedDateRange.value.start) && endDate.isAfter(selectedDateRange.value.end)) {
return 'rounded'
} else if (startDate.isAfter(selectedDateRange.value.end) && endDate.isBefore(selectedDateRange.value.start)) {
return 'rounded'
}
}
}
const calculateRecordStyle = (record: Row, id: number) => {
const range = record.rowMeta.range
if (!range) return {}
const startCol = range.fk_from_col
const endCol = range.fk_to_col
const perDayWidth = containerWidth.value / 7
const startDate = dayjs(record.row[startCol.title])
const startDay = dayjs(selectedDateRange.value.start)
const daysDiff = startDate.diff(startDay, 'day')
let widthStyle
if (endCol) {
const endDate = dayjs(record.row[endCol.title])
const endDaysDiff = endDate.diff(startDay, 'day')
const spanDays = endDaysDiff - daysDiff + 1
widthStyle = `calc(max(${spanDays} * ${perDayWidth}px, ${perDayWidth}px))`
} else {
widthStyle = `calc(${perDayWidth}px)`
}
return {
left: `${daysDiff * perDayWidth}px`,
top: `${id * 50}px`,
width: widthStyle,
}
}
const calendarData = computed(() => {
if (!formattedData.value || !calendarRange.value) return []
const recordsInRange: Array<Row> = []
calendarRange.value.forEach((range) => {
if (range.fk_from_col && range.fk_to_col) {
const fromCol = range.fk_from_col
const toCol = range.fk_to_col
for (const record of formattedData.value) {
const startDate = dayjs(record.row[fromCol])
const endDate = dayjs(record.row[toCol])
if (
(startDate.isSameOrAfter(selectedDateRange.value.start) && endDate.isSameOrBefore(selectedDateRange.value.end)) ||
(endDate.isSameOrAfter(selectedDateRange.value.start) && startDate.isSameOrBefore(selectedDateRange.value.end)) ||
(startDate.isSameOrAfter(selectedDateRange.value.start) && endDate.isAfter(selectedDateRange.value.end)) ||
(endDate.isSameOrAfter(selectedDateRange.value.start) && startDate.isAfter(selectedDateRange.value.end)) ||
(startDate.isBefore(selectedDateRange.value.start) && endDate.isBefore(selectedDateRange.value.end)) ||
(endDate.isBefore(selectedDateRange.value.start) && startDate.isBefore(selectedDateRange.value.end)) ||
(startDate.isBefore(selectedDateRange.value.start) && endDate.isAfter(selectedDateRange.value.end)) ||
(startDate.isAfter(selectedDateRange.value.end) && endDate.isBefore(selectedDateRange.value.start))
) {
recordsInRange.push({
...record,
rowMeta: {
...record.rowMeta,
range,
},
})
}
}
} else if (range.fk_from_col) {
const fromCol = range.fk_from_col
for (const record of formattedData.value) {
const startDate = dayjs(record.row[fromCol.title])
if (startDate.isBetween(selectedDateRange.value.start, selectedDateRange.value.end, 'day', '[]')) {
recordsInRange.push({
...record,
rowMeta: {
...record.rowMeta,
range,
},
})
}
}
}
})
return recordsInRange
})
</script>
<template>
<div class="flex flex-col">
<div class="flex relative flex-col">
<div class="flex">
<div
v-for="date in weekDates"
@ -36,19 +168,41 @@ const getData = (date: Date) => {
{{ dayjs(date).format('DD ddd') }}
</div>
</div>
<div class="flex overflow-auto nc-scrollbar-md h-[calc(100vh-12rem)]">
<!-- <div v-for="date in weekDates" :key="date.toISOString()" class="flex flex-col items-center w-1/7">
<LazySmartsheetCalendarDayView
:data="getData(date)"
:is-embed="true"
:render-date="date"
@expand-record="
(record:Row) => {
emits('expand-record', record)
}
"
/>
</div> -->
<div ref="container" class="flex h-[calc(100vh-11.6rem)]">
<div
v-for="date in weekDates"
:key="date.toISOString()"
:class="{
'!border-2 border-brand-500': dayjs(date).isSame(selectedDate, 'day'),
}"
class="flex flex-col border-r-1 last:border-r-0 items-center w-1/7"
@click="selectedDate = date"
></div>
</div>
<div class="absolute mt-9 inset-0">
<div
v-for="(record, id) in calendarData"
:key="id"
:class="{
'ml-3': getRecordPosition(record) === 'leftRounded',
'mr-3': getRecordPosition(record) === 'rightRounded',
'': getRecordPosition(record) === 'rounded',
}"
:style="calculateRecordStyle(record, id)"
class="absolute"
draggable="true"
@dragover.prevent
>
<LazySmartsheetRow :row="record">
<LazySmartsheetCalendarRecordCard
:date="record.row[record.rowMeta.range.fk_from_col.title]"
:position="getRecordPosition(record)"
:title="record.row[displayField.title]"
color="blue"
@click="emits('expand-record', record)"
/>
</LazySmartsheetRow>
</div>
</div>
</div>
</template>

Loading…
Cancel
Save