Browse Source

feat(nc-gui): week view drag and drop

pull/7611/head
DarkPhoenix2704 9 months ago
parent
commit
9ad388bd79
  1. 84
      packages/nc-gui/components/smartsheet/calendar/WeekView.vue
  2. 46
      packages/nc-gui/composables/useCalendarViewStore.ts

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

@ -5,12 +5,15 @@ import type { Row } from '~/lib'
const emits = defineEmits(['expand-record']) const emits = defineEmits(['expand-record'])
const { selectedDateRange, formattedData, calendarRange, selectedDate, displayField, calDataType } = useCalendarViewStoreOrThrow() const { selectedDateRange, formattedData, calendarRange, selectedDate, displayField, calDataType, updateRowProperty } =
useCalendarViewStoreOrThrow()
const container = ref(null) const container = ref(null)
const { width: containerWidth } = useElementSize(container) const { width: containerWidth } = useElementSize(container)
const meta = inject(MetaInj, ref())
const weekDates = computed(() => { const weekDates = computed(() => {
const startOfWeek = new Date(selectedDateRange.value.start) const startOfWeek = new Date(selectedDateRange.value.start)
const endOfWeek = new Date(selectedDateRange.value.end) const endOfWeek = new Date(selectedDateRange.value.end)
@ -180,6 +183,81 @@ const calendarData = computed(() => {
return recordsInRange return recordsInRange
}) })
const dragStart = (event: DragEvent, record: Row) => {
const eventRect = (event.target as HTMLElement).getBoundingClientRect()
const initialClickOffsetX = event.clientX - eventRect.left
const initialClickOffsetY = event.clientY - eventRect.top
event.dataTransfer?.setData(
'text/plain',
JSON.stringify({
record,
initialClickOffsetY,
initialClickOffsetX,
}),
)
}
const dropEvent = (event: DragEvent) => {
event.preventDefault()
const data = event.dataTransfer?.getData('text/plain')
if (data) {
const {
record,
initialClickOffsetY,
initialClickOffsetX,
}: {
record: Row
initialClickOffsetY: number
initialClickOffsetX: number
} = JSON.parse(data)
const { top, height, width, left } = container.value.getBoundingClientRect()
const percentY = (event.clientY - top - initialClickOffsetY - window.scrollY) / height
const percentX = (event.clientX - left - initialClickOffsetX - window.scrollX) / width
const day = Math.floor(percentX * 7)
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day')
let endDate
const newRow = {
...record,
row: {
...record.row,
[record.rowMeta.range.fk_from_col.title]: dayjs(newStartDate).format('YYYY-MM-DD'),
},
}
const updateProperty = [record.rowMeta.range.fk_from_col.title]
if (record.rowMeta.range.fk_to_col) {
const diffDays = dayjs(record.row[record.rowMeta.range.fk_to_col.title]).diff(
record.row[record.rowMeta.range.fk_from_col.title],
'day',
)
endDate = dayjs(newStartDate).add(diffDays, 'day')
newRow.row[record.rowMeta.range.fk_to_col.title] = dayjs(endDate).format('YYYY-MM-DD')
updateProperty.push(record.rowMeta.range.fk_to_col.title)
}
if (!newRow) return
updateRowProperty(newRow, updateProperty, false)
formattedData.value = formattedData.value.map((r) => {
const pk = extractPkFromRow(r.row, meta.value.columns)
if (pk === extractPkFromRow(newRow.row, meta.value.columns)) {
return newRow
}
return r
})
}
}
</script> </script>
<template> <template>
@ -193,7 +271,7 @@ const calendarData = computed(() => {
{{ dayjs(date).format('DD ddd') }} {{ dayjs(date).format('DD ddd') }}
</div> </div>
</div> </div>
<div ref="container" class="flex h-[calc(100vh-11.6rem)]"> <div ref="container" class="flex h-[calc(100vh-11.6rem)]" @drop="dropEvent($event)">
<div <div
v-for="date in weekDates" v-for="date in weekDates"
:key="date.toISOString()" :key="date.toISOString()"
@ -211,7 +289,7 @@ const calendarData = computed(() => {
:style="record.rowMeta.style" :style="record.rowMeta.style"
class="absolute pointer-events-auto" class="absolute pointer-events-auto"
draggable="true" draggable="true"
@dragover.prevent @dragstart="dragStart($event, record)"
> >
<LazySmartsheetRow :row="record"> <LazySmartsheetRow :row="record">
<LazySmartsheetCalendarRecordCard <LazySmartsheetCalendarRecordCard

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

@ -9,8 +9,8 @@ import {
type ViewType, type ViewType,
} from 'nocodb-sdk' } from 'nocodb-sdk'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { addDays, addMonths, addYears } from '~/utils' import { addDays, addMonths, addYears, extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils'
import { IsPublicInj, type Row, ref, storeToRefs, useBase, useInjectionState } from '#imports' import { IsPublicInj, type Row, ref, storeToRefs, useBase, useInjectionState, useUndoRedo } from '#imports'
const formatData = (list: Record<string, any>[]) => const formatData = (list: Record<string, any>[]) =>
list.map( list.map(
@ -48,7 +48,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const selectedTime = ref<Date | null>(null) const selectedTime = ref<Date | null>(null)
const selectedMonth = ref<Date | null>(new Date()) const selectedMonth = ref<Date>(new Date())
const isCalendarDataLoading = ref<boolean>(false) const isCalendarDataLoading = ref<boolean>(false)
@ -76,6 +76,10 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { t } = useI18n()
const { addUndo, clone, defineViewScope } = useUndoRedo()
const { isUIAllowed } = useRoles() const { isUIAllowed } = useRoles()
const isPublic = ref(shared) || inject(IsPublicInj, ref(false)) const isPublic = ref(shared) || inject(IsPublicInj, ref(false))
@ -102,7 +106,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
const calDataType = computed(() => { const calDataType = computed(() => {
if (!calendarRange.value || !calendarRange.value[0]) return null if (!calendarRange.value || !calendarRange.value[0]) return null
return calendarRange.value[0].fk_from_col.uidt return calendarRange.value[0]!.fk_from_col.uidt
}) })
const sideBarFilter = computed(() => { const sideBarFilter = computed(() => {
@ -297,7 +301,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
if (isSidebarLoading.value) return if (isSidebarLoading.value) return
try { 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,
offset: params.offset, offset: params.offset,
...{}, ...{},
@ -503,7 +507,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
fk_from_col: meta.value?.columns!.find((col) => col.id === range.fk_from_column_id), fk_from_col: meta.value?.columns!.find((col) => col.id === range.fk_from_column_id),
fk_to_col: range.fk_to_column_id ? meta.value?.columns!.find((col) => col.id === range.fk_to_column_id) : null, fk_to_col: range.fk_to_column_id ? meta.value?.columns!.find((col) => col.id === range.fk_to_column_id) : null,
} }
}) }) as any
displayField.value = meta.value.columns.find((col) => col.pv) displayField.value = meta.value.columns.find((col) => col.pv)
} }
@ -584,6 +588,35 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
isSidebarLoading.value = false isSidebarLoading.value = false
} }
async function updateRowProperty(toUpdate: Row, property: [], undo = false) {
try {
const id = extractPkFromRow(toUpdate.row, meta?.value?.columns as ColumnType[])
const updateObj = property.reduce((acc, curr) => {
acc[curr] = toUpdate.row[curr]
return acc
}, {})
return await $api.dbViewRow.update(
NOCO,
base?.value.id as string,
meta.value?.id as string,
viewMeta?.value?.id as string,
id,
updateObj,
{
query: { ignoreWebhook: !undo },
},
// todo:
// {
// query: { ignoreWebhook: !saved }
// }
)
} catch (e: any) {
message.error(`${t('msg.error.rowUpdateFailed')} ${await extractSdkResponseErrorMsg(e)}`)
}
}
watch(selectedDate, async () => { watch(selectedDate, async () => {
if (activeCalendarView.value === 'month' || activeCalendarView.value === 'week') { if (activeCalendarView.value === 'month' || activeCalendarView.value === 'week') {
await loadSidebarData() await loadSidebarData()
@ -634,6 +667,7 @@ const [useProvideCalendarViewStore, useCalendarViewStore] = useInjectionState(
selectedTime, selectedTime,
updateCalendarMeta, updateCalendarMeta,
calendarMetaData, calendarMetaData,
updateRowProperty,
activeCalendarView, activeCalendarView,
pageDate, pageDate,
paginationData, paginationData,

Loading…
Cancel
Save