Browse Source

fix(nc-gui): some edge cases. updated some ui parts

pull/7611/head
DarkPhoenix2704 9 months ago
parent
commit
570ed5616e
  1. 152
      packages/nc-gui/components/smartsheet/calendar/SideMenu.vue
  2. 7
      packages/nc-gui/components/smartsheet/calendar/SideRecordCard.vue
  3. 18
      packages/nc-gui/components/smartsheet/calendar/WeekView.vue
  4. 38
      packages/nc-gui/composables/useCalendarViewStore.ts

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

@ -2,7 +2,7 @@
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import { UITypes } from 'nocodb-sdk' import { UITypes } from 'nocodb-sdk'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { computed, ref } from '#imports' import { type Row, computed, ref } from '#imports'
const props = defineProps<{ const props = defineProps<{
visible: boolean visible: boolean
@ -35,6 +35,124 @@ const {
const sideBarListRef = ref<VNodeRef | null>(null) const sideBarListRef = ref<VNodeRef | null>(null)
const pushToArray = (arr: Array<Row>, record: Row, range) => {
arr.push({
...record,
rowMeta: {
...record.rowMeta,
range,
},
})
}
const renderData = computed<Array<Row>>(() => {
if (!calendarRange.value) return []
const rangedData: Array<Row> = []
calendarRange.value.forEach((range) => {
const fromCol = range.fk_from_col
const toCol = range.fk_to_col
formattedSideBarData.value.forEach((record) => {
if (fromCol && toCol) {
const from = dayjs(record.row[fromCol.title!])
const to = dayjs(record.row[toCol.title!])
if (sideBarFilterOption.value === 'withoutDates') {
if (!from.isValid() || !to.isValid()) {
pushToArray(rangedData, record, range)
}
} else if (sideBarFilterOption.value === 'allRecords') {
pushToArray(rangedData, record, range)
} else if (
sideBarFilterOption.value === 'month' ||
sideBarFilterOption.value === 'year' ||
sideBarFilterOption.value === 'selectedDate' ||
sideBarFilterOption.value === 'week' ||
sideBarFilterOption.value === 'day'
) {
let fromDate: dayjs.Dayjs | null = null
let toDate: dayjs.Dayjs | null = null
switch (sideBarFilterOption.value) {
case 'month':
fromDate = dayjs(selectedMonth.value).startOf('month')
toDate = dayjs(selectedMonth.value).endOf('month')
break
case 'year':
fromDate = dayjs(selectedDate.value).startOf('year')
toDate = dayjs(selectedDate.value).endOf('year')
break
case 'selectedDate':
fromDate = dayjs(selectedDate.value).startOf('day')
toDate = dayjs(selectedDate.value).endOf('day')
break
case 'week':
fromDate = dayjs(selectedDateRange.value.start).startOf('week')
toDate = dayjs(selectedDateRange.value.end).endOf('week')
break
case 'day':
fromDate = dayjs(selectedDate.value).startOf('day')
toDate = dayjs(selectedDate.value).endOf('day')
break
}
if (from && to) {
if (
(from.isSameOrAfter(fromDate) && to.isSameOrBefore(toDate)) ||
(from.isSameOrBefore(fromDate) && to.isSameOrAfter(toDate)) ||
(from.isSameOrBefore(fromDate) && to.isSameOrAfter(fromDate)) ||
(from.isSameOrBefore(toDate) && to.isSameOrAfter(toDate))
) {
pushToArray(rangedData, record, range)
}
}
}
} else if (fromCol) {
const from = dayjs(record.row[fromCol.title!])
if (sideBarFilterOption.value === 'withoutDates') {
if (!from.isValid()) {
pushToArray(rangedData, record, range)
}
} else if (sideBarFilterOption.value === 'allRecords') {
pushToArray(rangedData, record, range)
} else if (sideBarFilterOption.value === 'selectedDate' || sideBarFilterOption.value === 'day') {
if (from.isSame(selectedDate.value, 'day')) {
pushToArray(rangedData, record, range)
}
} else if (
sideBarFilterOption.value === 'week' ||
sideBarFilterOption.value === 'month' ||
sideBarFilterOption.value === 'year'
) {
let fromDate: dayjs.Dayjs
let toDate: dayjs.Dayjs
switch (sideBarFilterOption.value) {
case 'week':
fromDate = dayjs(selectedDateRange.value.start).startOf('week')
toDate = dayjs(selectedDateRange.value.end).endOf('week')
break
case 'month':
fromDate = dayjs(selectedMonth.value).startOf('month')
toDate = dayjs(selectedMonth.value).endOf('month')
break
case 'year':
fromDate = dayjs(selectedDate.value).startOf('year')
toDate = dayjs(selectedDate.value).endOf('year')
break
}
if (from.isSameOrAfter(fromDate) && from.isSameOrBefore(toDate)) {
pushToArray(rangedData, record, range)
}
}
}
})
})
return rangedData
})
const options = computed(() => { const options = computed(() => {
switch (activeCalendarView.value) { switch (activeCalendarView.value) {
case 'day' as const: case 'day' as const:
@ -81,6 +199,7 @@ const sideBarListScrollHandle = useDebounceFn(async (e: Event) => {
if (target.clientHeight + target.scrollTop + INFINITY_SCROLL_THRESHOLD >= target.scrollHeight) { if (target.clientHeight + target.scrollTop + INFINITY_SCROLL_THRESHOLD >= target.scrollHeight) {
const pageSize = appInfo.value?.defaultLimit ?? 25 const pageSize = appInfo.value?.defaultLimit ?? 25
const page = Math.ceil(formattedSideBarData.value.length / pageSize) const page = Math.ceil(formattedSideBarData.value.length / pageSize)
await loadMoreSidebarData({ await loadMoreSidebarData({
offset: page * pageSize, offset: page * pageSize,
}) })
@ -154,28 +273,39 @@ const sideBarListScrollHandle = useDebounceFn(async (e: Event) => {
class="gap-2 flex flex-col nc-scrollbar-md overflow-y-auto nc-calendar-top-height" class="gap-2 flex flex-col nc-scrollbar-md overflow-y-auto nc-calendar-top-height"
@scroll="sideBarListScrollHandle" @scroll="sideBarListScrollHandle"
> >
<div v-if="formattedSideBarData.length === 0 || isSidebarLoading" class="flex h-full items-center justify-center"> <div v-if="renderData.length === 0 || isSidebarLoading" class="flex h-full items-center justify-center">
<GeneralLoader v-if="isSidebarLoading" size="large" /> <GeneralLoader v-if="isSidebarLoading" size="large" />
<div v-else class="text-gray-500"> <div v-else class="text-gray-500">
{{ t('msg.noRecordsFound') }} {{ t('msg.noRecordsFound') }}
</div> </div>
</div> </div>
<template v-else-if="formattedSideBarData.length > 0"> <template v-else-if="renderData.length > 0">
<LazySmartsheetRow v-for="(record, rowIndex) in formattedSideBarData" :key="rowIndex" :row="record"> <LazySmartsheetRow v-for="(record, rowIndex) in renderData" :key="rowIndex" :row="record">
<LazySmartsheetCalendarSideRecordCard <LazySmartsheetCalendarSideRecordCard
:date=" :from-date="
calDataType === UITypes.DateTime record.rowMeta.range?.fk_from_col
? dayjs(record.row[calendarRange[0] ? calendarRange[0].fk_from_col.title : '']).format('DD-MM-YYYY HH:mm') ? calDataType === UITypes.Date
: dayjs(record.row[calendarRange[0] ? calendarRange[0].fk_from_col.title : '']).format('DD-MM-YYYY') ? dayjs(record.row[record.rowMeta.range.fk_from_col.title!]).format('DD MMM')
: dayjs(record.row[record.rowMeta.range.fk_from_col.title!]).format('DD MMM•HH:MM A')
: null
" "
:invalid=" :invalid="
dayjs(record.row[calendarRange[0] ? calendarRange[0].fk_from_col.title : '']).isAfter( record.rowMeta.range!.fk_to_col &&
dayjs(record.row[calendarRange[0] ? calendarRange[0].fk_to_col.title : '']), dayjs(record.row[record.rowMeta.range!.fk_from_col.title!]).isAfter(
dayjs(record.row[record.rowMeta.range!.fk_to_col.title!]),
) )
" "
:name="record.row[displayField.title]" :name="record.row[displayField!.title!]"
:to-date="
record.rowMeta.range!.fk_to_col
? calDataType === UITypes.Date
? dayjs(record.row[record.rowMeta.range!.fk_to_col.title!]).format('DD MMM')
: dayjs(record.row[record.rowMeta.range!.fk_to_col.title!]).format('DD MMM•HH:MM A')
: null
"
color="blue" color="blue"
draggable="true"
@click="emit('expand-record', record)" @click="emit('expand-record', record)"
/> />
</LazySmartsheetRow> </LazySmartsheetRow>

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

@ -1,7 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
interface Props { interface Props {
name: string name: string
date?: string fromDate?: string
toDate?: string
color?: string color?: string
showDate?: boolean showDate?: boolean
invalid?: boolean invalid?: boolean
@ -9,7 +10,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
name: '', name: '',
date: '', fromDate: '',
color: 'blue', color: 'blue',
showDate: true, showDate: true,
invalid: false, invalid: false,
@ -32,7 +33,7 @@ const props = withDefaults(defineProps<Props>(), {
></span> ></span>
<div class="flex flex-col gap-1 ml-3"> <div class="flex flex-col gap-1 ml-3">
<span class="text-sm font-bold text-gray-700">{{ name }}</span> <span class="text-sm font-bold text-gray-700">{{ name }}</span>
<span v-if="showDate" class="text-xs text-gray-500">{{ date }}</span> <span v-if="showDate" class="text-xs text-gray-500">{{ fromDate }} {{ toDate ? ` - ${toDate}` : '' }}</span>
</div> </div>
</div> </div>

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

@ -81,7 +81,16 @@ const calendarData = computed(() => {
} }
const startDaysDiff = startDate.diff(selectedDateRange.value.start, 'day') const startDaysDiff = startDate.diff(selectedDateRange.value.start, 'day')
const spanDays = Math.max(Math.min(endDate.diff(startDate, 'day'), 6) + 1, 1)
let spanDays = Math.max(Math.min(endDate.diff(startDate, 'day'), 6) + 1, 1)
if (endDate.isAfter(startDate, 'month')) {
spanDays = 7 - startDaysDiff
}
if (startDaysDiff > 0) {
spanDays = Math.min(spanDays, 7 - startDaysDiff)
}
const widthStyle = `calc(max(${spanDays} * ${perDayWidth}px, ${perDayWidth}px))` const widthStyle = `calc(max(${spanDays} * ${perDayWidth}px, ${perDayWidth}px))`
let suitableColumn = -1 let suitableColumn = -1
@ -103,7 +112,7 @@ const calendarData = computed(() => {
recordsInDay[dayIndex][suitableColumn] = true recordsInDay[dayIndex][suitableColumn] = true
} }
let position = '' let position = 'none'
const isStartInRange = const isStartInRange =
ogStartDate && ogStartDate.isBetween(selectedDateRange.value.start, selectedDateRange.value.end, 'day', '[]') ogStartDate && ogStartDate.isBetween(selectedDateRange.value.start, selectedDateRange.value.end, 'day', '[]')
@ -198,11 +207,6 @@ const calendarData = computed(() => {
<div <div
v-for="(record, id) in calendarData" v-for="(record, id) in calendarData"
:key="id" :key="id"
:class="{
'ml-3': record.rowMeta.position === 'leftRounded',
'mr-3': record.rowMeta.position === 'rightRounded',
'': record.rowMeta.position === 'rounded',
}"
:style="record.rowMeta.style" :style="record.rowMeta.style"
class="absolute pointer-events-auto" class="absolute pointer-events-auto"
draggable="true" draggable="true"

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

@ -266,7 +266,8 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
if (displayField.value && searchQuery.value) { if (displayField.value && searchQuery.value) {
if (combinedFilters.length > 0) { if (combinedFilters.length > 0) {
combinedFilters.push({ combinedFilters = [
{
is_group: true, is_group: true,
logical_op: 'and', logical_op: 'and',
children: [ children: [
@ -277,7 +278,8 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
value: searchQuery.value, value: searchQuery.value,
}, },
], ],
}) },
]
} else { } else {
combinedFilters.push({ combinedFilters.push({
fk_column_id: displayField.value.id, fk_column_id: displayField.value.id,
@ -293,6 +295,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
async function loadMoreSidebarData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) { async function loadMoreSidebarData(params: Parameters<Api<any>['dbViewRow']['list']>[4] = {}) {
if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return if ((!base?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return
if (isSidebarLoading.value) return if (isSidebarLoading.value) return
try {
const response = !isPublic.value const response = !isPublic.value
? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value.id, { ? await api.dbViewRow.list('noco', base.value.id!, meta.value!.id!, viewMeta.value.id, {
...params, ...params,
@ -310,8 +313,10 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
offset: params.offset, offset: params.offset,
where: where?.value ?? '', where: where?.value ?? '',
}) })
formattedSideBarData.value = [...formattedSideBarData.value, ...formatData(response!.list)] formattedSideBarData.value = [...formattedSideBarData.value, ...formatData(response!.list)]
} catch (e) {
console.log(e)
}
} }
const filterJSON = computed(() => { const filterJSON = computed(() => {
@ -324,19 +329,25 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
let fromDate: dayjs.Dayjs | null | string = null let fromDate: dayjs.Dayjs | null | string = null
let toDate: dayjs.Dayjs | null | string = null let toDate: dayjs.Dayjs | null | string = null
if (activeCalendarView.value === 'week') { switch (activeCalendarView.value) {
case 'week':
fromDate = dayjs(selectedDateRange.value.start).startOf('day') fromDate = dayjs(selectedDateRange.value.start).startOf('day')
toDate = dayjs(selectedDateRange.value.end).endOf('day') toDate = dayjs(selectedDateRange.value.end).endOf('day')
} else if (activeCalendarView.value === 'day') { break
fromDate = dayjs(selectedDate.value).startOf('day') case 'month':
toDate = dayjs(selectedDate.value).endOf('day')
} else if (activeCalendarView.value === 'month') {
fromDate = dayjs(selectedMonth.value).startOf('month') fromDate = dayjs(selectedMonth.value).startOf('month')
toDate = dayjs(selectedMonth.value).endOf('month') toDate = dayjs(selectedMonth.value).endOf('month')
} else if (activeCalendarView.value === 'year') { break
case 'year':
fromDate = dayjs(selectedDate.value).startOf('year') fromDate = dayjs(selectedDate.value).startOf('year')
toDate = dayjs(selectedDate.value).endOf('year') toDate = dayjs(selectedDate.value).endOf('year')
break
case 'day':
fromDate = dayjs(selectedDate.value).startOf('day')
toDate = dayjs(selectedDate.value).endOf('day')
break
} }
if (calDataType.value === UITypes.Date) { if (calDataType.value === UITypes.Date) {
fromDate = dayjs(fromDate).format('YYYY-MM-DD') fromDate = dayjs(fromDate).format('YYYY-MM-DD')
toDate = dayjs(toDate).format('YYYY-MM-DD') toDate = dayjs(toDate).format('YYYY-MM-DD')
@ -361,7 +372,6 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
logical_op: 'or', logical_op: 'or',
children: [ children: [
{ {
// Check for overlap or within range
is_group: true, is_group: true,
logical_op: 'and', logical_op: 'and',
children: [ children: [
@ -432,11 +442,12 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
if (!formattedData.value || !calendarRange.value) return [] if (!formattedData.value || !calendarRange.value) return []
const dates = new Set<Date>() const dates = new Set<Date>()
calendarRange.value.forEach((range) => {
formattedData.value.forEach((row) => { formattedData.value.forEach((row) => {
const start = row.row[calendarRange.value[0].fk_from_col?.title ?? ''] const start = row.row[range.fk_from_col?.title ?? '']
let end let end
if (calendarRange.value[0].fk_to_col) { if (range.fk_to_col) {
end = row.row[calendarRange.value[0].fk_to_col.title ?? ''] end = row.row[range.fk_to_col.title ?? '']
} }
if (start && end) { if (start && end) {
const startDate = dayjs(start) const startDate = dayjs(start)
@ -455,6 +466,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
dates.add(new Date(start)) dates.add(new Date(start))
} }
}) })
})
return Array.from(dates) return Array.from(dates)
}) })

Loading…
Cancel
Save