mirror of https://github.com/nocodb/nocodb
DarkPhoenix2704
10 months ago
6 changed files with 663 additions and 25 deletions
@ -0,0 +1,101 @@
|
||||
<script lang="ts" setup> |
||||
interface Props { |
||||
record: Record<string, string> |
||||
name: string |
||||
date?: string |
||||
color?: string |
||||
resize?: boolean |
||||
selected?: boolean |
||||
size?: 'small' | 'medium' | 'large' | 'auto' |
||||
showDate?: boolean |
||||
position?: 'leftRounded' | 'rightRounded' | 'rounded' | 'none' |
||||
} |
||||
|
||||
withDefaults(defineProps<Props>(), { |
||||
name: '', |
||||
date: '', |
||||
resize: true, |
||||
selected: false, |
||||
color: 'blue', |
||||
size: 'small', |
||||
showDate: true, |
||||
position: 'rounded', |
||||
}) |
||||
|
||||
const emit = defineEmits(['resize-start']) |
||||
</script> |
||||
|
||||
<template> |
||||
<div |
||||
:class="{ |
||||
'min-h-9': size === 'small', |
||||
'min-h-10': size === 'medium', |
||||
'min-h-12': size === 'large', |
||||
'h-full': size === 'auto', |
||||
'rounded-l-lg ml-3': position === 'leftRounded', |
||||
'rounded-r-lg mr-3': position === 'rightRounded', |
||||
'rounded-lg mx-3': position === 'rounded', |
||||
'rounded-none': position === 'none', |
||||
'bg-maroon-50': color === 'maroon', |
||||
'bg-blue-50': color === 'blue', |
||||
'bg-green-50': color === 'green', |
||||
'bg-yellow-50': color === 'yellow', |
||||
'bg-pink-50': color === 'pink', |
||||
'bg-purple-50': color === 'purple', |
||||
'group-hover:(border-brand-500 border-2)': resize, |
||||
'border-brand-500 border-2': selected, |
||||
}" |
||||
class="relative group" |
||||
> |
||||
<div class="h-full absolute py-2"> |
||||
<div |
||||
v-if="position === 'leftRounded' || position === 'rounded'" |
||||
:class="{ |
||||
'bg-maroon-500': color === 'maroon', |
||||
'bg-blue-500': color === 'blue', |
||||
'bg-green-500': color === 'green', |
||||
'bg-yellow-500': color === 'yellow', |
||||
'bg-pink-500': color === 'pink', |
||||
'bg-purple-500': color === 'purple', |
||||
}" |
||||
class="block h-full min-h-5 ml-1 w-1 rounded mr-2" |
||||
></div> |
||||
</div> |
||||
|
||||
<div |
||||
v-if="(position === 'leftRounded' || position === 'rounded') && resize" |
||||
:class="{ |
||||
'!block border-2 rounded-lg border-brand-500': selected, |
||||
}" |
||||
class="absolute mt-0.6 h-7.1 hidden -left-3 resize !group-hover:(border-brand-500 block border-2 rounded-lg)" |
||||
> |
||||
<NcButton size="xsmall" type="secondary" @mousedown.stop="emit('resize-start', 'left', $event, record)"> |
||||
<component :is="iconMap.drag" class="text-gray-400"></component> |
||||
</NcButton> |
||||
</div> |
||||
|
||||
<div class="ml-3 mt-2 pr-3 text-ellipsis overflow-hidden w-full h-6 absolute"> |
||||
<span v-if="position === 'rightRounded' || position === 'none'"> .... </span> |
||||
<span class="text-sm text-gray-800">{{ name }}</span> |
||||
<span v-if="showDate" class="text-xs ml-1 text-gray-600">{{ date }}</span> |
||||
<span v-if="position === 'leftRounded' || position === 'none'" class="absolute my-0 right-5"> .... </span> |
||||
</div> |
||||
<div |
||||
v-if="(position === 'rightRounded' || position === 'rounded') && resize" |
||||
:class="{ |
||||
'!block border-2 rounded-lg border-brand-500': selected, |
||||
}" |
||||
class="absolute mt-0.6 hidden h-7.1 -right-3 border-1 resize !group-hover:(border-brand-500 border-2 block rounded-lg)" |
||||
> |
||||
<NcButton size="xsmall" type="secondary" @mousedown.stop="emit('resize-start', 'right', $event, record)"> |
||||
<component :is="iconMap.drag" class="text-gray-400"></component> |
||||
</NcButton> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.resize { |
||||
cursor: ew-resize; |
||||
} |
||||
</style> |
@ -0,0 +1,545 @@
|
||||
<script lang="ts" setup> |
||||
import dayjs from 'dayjs' |
||||
import type { Row } from '~/lib' |
||||
import { ref } from '#imports' |
||||
|
||||
const emits = defineEmits(['expand-record']) |
||||
|
||||
const { selectedDateRange, formattedData, formattedSideBarData, calendarRange, selectedDate, displayField, updateRowProperty } = |
||||
useCalendarViewStoreOrThrow() |
||||
|
||||
const container = ref<null | HTMLElement>(null) |
||||
|
||||
const { width: containerWidth } = useElementSize(container) |
||||
|
||||
const { isUIAllowed } = useRoles() |
||||
|
||||
const meta = inject(MetaInj, ref()) |
||||
|
||||
const weekDates = computed(() => { |
||||
const startOfWeek = new Date(selectedDateRange.value.start!) |
||||
const endOfWeek = new Date(selectedDateRange.value.end!) |
||||
const datesArray = [] |
||||
while (startOfWeek.getTime() <= endOfWeek.getTime()) { |
||||
datesArray.push(new Date(startOfWeek)) |
||||
startOfWeek.setDate(startOfWeek.getDate() + 1) |
||||
} |
||||
return datesArray |
||||
}) |
||||
|
||||
function getRandomNumbers() { |
||||
const typedArray = new Uint8Array(10) |
||||
const randomValues = window.crypto.getRandomValues(typedArray) |
||||
return randomValues.join('') |
||||
} |
||||
|
||||
const findFirstSuitableColumn = (recordsInDay: any, startDayIndex: number, spanDays: number) => { |
||||
let column = 0 |
||||
while (true) { |
||||
let isColumnSuitable = true |
||||
for (let i = 0; i < spanDays; i++) { |
||||
const dayIndex = startDayIndex + i |
||||
if (!recordsInDay[dayIndex]) { |
||||
recordsInDay[dayIndex] = {} |
||||
} |
||||
if (recordsInDay[dayIndex][column]) { |
||||
isColumnSuitable = false |
||||
break |
||||
} |
||||
} |
||||
|
||||
if (isColumnSuitable) { |
||||
return column |
||||
} |
||||
column++ |
||||
} |
||||
} |
||||
|
||||
const calendarData = computed(() => { |
||||
if (!formattedData.value || !calendarRange.value) return [] |
||||
const recordsInDay: { |
||||
[key: number]: { |
||||
[key: number]: boolean |
||||
} |
||||
} = { |
||||
0: {}, |
||||
1: {}, |
||||
2: {}, |
||||
3: {}, |
||||
4: {}, |
||||
5: {}, |
||||
6: {}, |
||||
} |
||||
|
||||
const recordsInRange: Array<Row> = [] |
||||
const perDayWidth = containerWidth.value / 7 |
||||
|
||||
calendarRange.value.forEach((range) => { |
||||
const fromCol = range.fk_from_col |
||||
const toCol = range.fk_to_col |
||||
if (fromCol && toCol) { |
||||
for (const record of [...formattedData.value].filter((r) => { |
||||
const startDate = dayjs(r.row[fromCol.title!]) |
||||
const endDate = dayjs(r.row[toCol.title!]) |
||||
if (!startDate.isValid() || !endDate.isValid()) return false |
||||
return !endDate.isBefore(startDate) |
||||
})) { |
||||
const id = record.row.id ?? getRandomNumbers() |
||||
let startDate = dayjs(record.row[fromCol.title!]) |
||||
const ogStartDate = startDate.clone() |
||||
const endDate = dayjs(record.row[toCol.title!]) |
||||
|
||||
if (startDate.isBefore(selectedDateRange.value.start)) { |
||||
startDate = dayjs(selectedDateRange.value.start) |
||||
} |
||||
|
||||
const startDaysDiff = startDate.diff(selectedDateRange.value.start, 'day') |
||||
|
||||
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))` |
||||
|
||||
let suitableColumn = -1 |
||||
for (let i = 0; i < spanDays; i++) { |
||||
const dayIndex = startDaysDiff + i |
||||
|
||||
if (!recordsInDay[dayIndex]) { |
||||
recordsInDay[dayIndex] = {} |
||||
} |
||||
|
||||
if (suitableColumn === -1) { |
||||
suitableColumn = findFirstSuitableColumn(recordsInDay, dayIndex, spanDays) |
||||
} |
||||
} |
||||
|
||||
// Mark the suitable column as occupied for the entire span |
||||
for (let i = 0; i < spanDays; i++) { |
||||
const dayIndex = startDaysDiff + i |
||||
recordsInDay[dayIndex][suitableColumn] = true |
||||
} |
||||
|
||||
let position = 'none' |
||||
|
||||
const isStartInRange = |
||||
ogStartDate && ogStartDate.isBetween(selectedDateRange.value.start, selectedDateRange.value.end, 'day', '[]') |
||||
const isEndInRange = endDate && endDate.isBetween(selectedDateRange.value.start, selectedDateRange.value.end, 'day', '[]') |
||||
|
||||
if (isStartInRange && isEndInRange) { |
||||
position = 'rounded' |
||||
} else if ( |
||||
startDate && |
||||
endDate && |
||||
startDate.isBefore(selectedDateRange.value.start) && |
||||
endDate.isAfter(selectedDateRange.value.end) |
||||
) { |
||||
position = 'none' |
||||
} else if ( |
||||
startDate && |
||||
endDate && |
||||
(startDate.isAfter(selectedDateRange.value.end) || endDate.isBefore(selectedDateRange.value.start)) |
||||
) { |
||||
position = 'none' |
||||
} else if (isStartInRange) { |
||||
position = 'leftRounded' |
||||
} else if (isEndInRange) { |
||||
position = 'rightRounded' |
||||
} |
||||
|
||||
recordsInRange.push({ |
||||
...record, |
||||
rowMeta: { |
||||
...record.rowMeta, |
||||
range: range as any, |
||||
position, |
||||
id, |
||||
style: { |
||||
width: widthStyle, |
||||
left: `${startDaysDiff * perDayWidth}px`, |
||||
top: `${suitableColumn * 40}px`, |
||||
}, |
||||
}, |
||||
}) |
||||
} |
||||
} else if (fromCol) { |
||||
for (const record of formattedData.value) { |
||||
const id = record.row.id ?? getRandomNumbers() |
||||
|
||||
const startDate = dayjs(record.row[fromCol.title!]) |
||||
const startDaysDiff = Math.max(startDate.diff(selectedDateRange.value.start, 'day'), 0) |
||||
const suitableColumn = findFirstSuitableColumn(recordsInDay, startDaysDiff, 1) |
||||
recordsInDay[startDaysDiff][suitableColumn] = true |
||||
|
||||
recordsInRange.push({ |
||||
...record, |
||||
rowMeta: { |
||||
...record.rowMeta, |
||||
range: range as any, |
||||
id, |
||||
position: 'rounded', |
||||
style: { |
||||
width: `calc(${perDayWidth}px)`, |
||||
left: `${startDaysDiff * perDayWidth}px`, |
||||
top: `${suitableColumn * 40}px`, |
||||
}, |
||||
}, |
||||
}) |
||||
} |
||||
} |
||||
}) |
||||
|
||||
return recordsInRange |
||||
}) |
||||
|
||||
const dragElement = ref<HTMLElement | null>(null) |
||||
|
||||
const draggingId = ref<string | null>(null) |
||||
|
||||
const resizeInProgress = ref(false) |
||||
|
||||
const dragTimeout = ref<string | number | null | NodeJS.Timeout>(null) |
||||
|
||||
const isDragging = ref(false) |
||||
const dragRecord = ref<Row>() |
||||
|
||||
const onDrag = (event: MouseEvent) => { |
||||
if (!isUIAllowed('dataEdit')) return |
||||
if (!container.value || !dragRecord.value) return |
||||
const { width, left } = container.value.getBoundingClientRect() |
||||
|
||||
const percentX = (event.clientX - left - window.scrollX) / width |
||||
|
||||
const fromCol = dragRecord.value.rowMeta.range?.fk_from_col |
||||
const toCol = dragRecord.value.rowMeta.range?.fk_to_col |
||||
|
||||
if (!fromCol) return |
||||
|
||||
const day = Math.floor(percentX * 7) |
||||
|
||||
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day') |
||||
if (!newStartDate) return |
||||
|
||||
let endDate |
||||
|
||||
const newRow = { |
||||
...dragRecord.value, |
||||
row: { |
||||
...dragRecord.value.row, |
||||
[fromCol.title!]: dayjs(newStartDate).format('YYYY-MM-DD'), |
||||
}, |
||||
} |
||||
|
||||
if (toCol) { |
||||
const fromDate = dragRecord.value.row[fromCol.title!] ? dayjs(dragRecord.value.row[fromCol.title!]) : null |
||||
const toDate = dragRecord.value.row[toCol.title!] ? dayjs(dragRecord.value.row[toCol.title!]) : null |
||||
|
||||
if (fromDate && toDate) { |
||||
endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day') |
||||
} else if (fromDate && !toDate) { |
||||
endDate = dayjs(newStartDate).endOf('day') |
||||
} else if (!fromDate && toDate) { |
||||
endDate = dayjs(newStartDate).endOf('day') |
||||
} else { |
||||
endDate = newStartDate.clone() |
||||
} |
||||
|
||||
newRow.row[toCol.title!] = dayjs(endDate).format('YYYY-MM-DD') |
||||
} |
||||
|
||||
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 |
||||
}) |
||||
} |
||||
|
||||
const stopDrag = (event: MouseEvent) => { |
||||
event.preventDefault() |
||||
clearTimeout(dragTimeout.value!) |
||||
|
||||
if (!isUIAllowed('dataEdit')) return |
||||
if (!isDragging.value || !container.value || !dragRecord.value) return |
||||
|
||||
const { width, left } = container.value.getBoundingClientRect() |
||||
|
||||
const percentX = (event.clientX - left - window.scrollX) / width |
||||
|
||||
const fromCol = dragRecord.value.rowMeta.range?.fk_from_col |
||||
const toCol = dragRecord.value.rowMeta.range?.fk_to_col |
||||
|
||||
const day = Math.floor(percentX * 7) |
||||
|
||||
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day') |
||||
if (!newStartDate || !fromCol) return |
||||
|
||||
let endDate |
||||
|
||||
const newRow = { |
||||
...dragRecord.value, |
||||
row: { |
||||
...dragRecord.value.row, |
||||
[fromCol.title!]: dayjs(newStartDate).format('YYYY-MM-DD'), |
||||
}, |
||||
} |
||||
|
||||
const updateProperty = [fromCol.title!] |
||||
|
||||
if (toCol) { |
||||
const fromDate = dragRecord.value.row[fromCol.title!] ? dayjs(dragRecord.value.row[fromCol.title!]) : null |
||||
const toDate = dragRecord.value.row[toCol.title!] ? dayjs(dragRecord.value.row[toCol.title!]) : null |
||||
|
||||
if (fromDate && toDate) { |
||||
endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day') |
||||
} else if (fromDate && !toDate) { |
||||
endDate = dayjs(newStartDate).endOf('day') |
||||
} else if (!fromDate && toDate) { |
||||
endDate = dayjs(newStartDate).endOf('day') |
||||
} else { |
||||
endDate = newStartDate.clone() |
||||
} |
||||
|
||||
newRow.row[toCol.title!] = dayjs(endDate).format('YYYY-MM-DD') |
||||
|
||||
updateProperty.push(toCol.title!) |
||||
} |
||||
|
||||
if (!newRow) return |
||||
|
||||
if (dragElement.value) { |
||||
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 |
||||
}) |
||||
} else { |
||||
formattedData.value = [...formattedData.value, newRow] |
||||
formattedSideBarData.value = formattedSideBarData.value.filter((r) => { |
||||
const pk = extractPkFromRow(r.row, meta.value!.columns!) |
||||
|
||||
return pk !== extractPkFromRow(newRow.row, meta.value!.columns!) |
||||
}) |
||||
} |
||||
|
||||
const allRecords = document.querySelectorAll('.draggable-record') |
||||
allRecords.forEach((el) => { |
||||
el.style.visibility = '' |
||||
el.style.opacity = '100%' |
||||
}) |
||||
|
||||
if (dragElement.value) { |
||||
dragElement.value.style.boxShadow = 'none' |
||||
dragElement.value.classList.remove('hide') |
||||
// isDragging.value = false |
||||
draggingId.value = null |
||||
dragElement.value = null |
||||
} |
||||
|
||||
updateRowProperty(newRow, updateProperty, false) |
||||
|
||||
document.removeEventListener('mousemove', onDrag) |
||||
document.removeEventListener('mouseup', stopDrag) |
||||
} |
||||
|
||||
const dragStart = (event: MouseEvent, record: Row) => { |
||||
if (!isUIAllowed('dataEdit')) return |
||||
if (resizeInProgress.value) return |
||||
let target = event.target as HTMLElement |
||||
|
||||
isDragging.value = false |
||||
|
||||
dragTimeout.value = setTimeout(() => { |
||||
isDragging.value = true |
||||
while (!target.classList.contains('draggable-record')) { |
||||
target = target.parentElement as HTMLElement |
||||
} |
||||
|
||||
const allRecords = document.querySelectorAll('.draggable-record') |
||||
allRecords.forEach((el) => { |
||||
if (!el.getAttribute('data-unique-id').includes(record.rowMeta.id!)) { |
||||
// el.style.visibility = 'hidden' |
||||
el.style.opacity = '30%' |
||||
} |
||||
}) |
||||
|
||||
dragRecord.value = record |
||||
|
||||
isDragging.value = true |
||||
dragElement.value = target |
||||
draggingId.value = record.rowMeta.id! |
||||
dragRecord.value = record |
||||
|
||||
document.addEventListener('mousemove', onDrag) |
||||
document.addEventListener('mouseup', stopDrag) |
||||
}, 200) |
||||
|
||||
const onMouseUp = () => { |
||||
clearTimeout(dragTimeout.value!) |
||||
document.removeEventListener('mouseup', onMouseUp) |
||||
if (!isDragging.value) { |
||||
emits('expand-record', record) |
||||
} |
||||
} |
||||
|
||||
document.addEventListener('mouseup', onMouseUp) |
||||
} |
||||
|
||||
const dropEvent = (event: DragEvent) => { |
||||
if (!isUIAllowed('dataEdit')) return |
||||
event.preventDefault() |
||||
|
||||
const data = event.dataTransfer?.getData('text/plain') |
||||
if (data) { |
||||
const { |
||||
record, |
||||
}: { |
||||
record: Row |
||||
} = JSON.parse(data) |
||||
const { width, left } = container.value.getBoundingClientRect() |
||||
|
||||
const percentX = (event.clientX - left - window.scrollX) / width |
||||
|
||||
const fromCol = record.rowMeta.range?.fk_from_col |
||||
const toCol = record.rowMeta.range?.fk_to_col |
||||
|
||||
if (!fromCol) return |
||||
|
||||
const day = Math.floor(percentX * 7) |
||||
|
||||
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day') |
||||
|
||||
let endDate |
||||
|
||||
const newRow = { |
||||
...record, |
||||
row: { |
||||
...record.row, |
||||
[fromCol.title!]: dayjs(newStartDate).format('YYYY-MM-DD'), |
||||
}, |
||||
} |
||||
|
||||
const updateProperty = [fromCol.title!] |
||||
|
||||
if (toCol) { |
||||
const fromDate = record.row[fromCol.title!] ? dayjs(record.row[fromCol.title!]) : null |
||||
const toDate = record.row[toCol.title!] ? dayjs(record.row[toCol.title!]) : null |
||||
|
||||
if (fromDate && toDate) { |
||||
endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day') |
||||
} else if (fromDate && !toDate) { |
||||
endDate = dayjs(newStartDate).endOf('day') |
||||
} else if (!fromDate && toDate) { |
||||
endDate = dayjs(newStartDate).endOf('day') |
||||
} else { |
||||
endDate = newStartDate.clone() |
||||
} |
||||
newRow.row[toCol.title!] = dayjs(endDate).format('YYYY-MM-DD') |
||||
updateProperty.push(toCol.title!) |
||||
} |
||||
|
||||
if (!newRow) return |
||||
|
||||
if (dragElement.value) { |
||||
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 |
||||
}) |
||||
} else { |
||||
formattedData.value = [...formattedData.value, newRow] |
||||
formattedSideBarData.value = formattedSideBarData.value.filter((r) => { |
||||
const pk = extractPkFromRow(r.row, meta.value!.columns!) |
||||
|
||||
return pk !== extractPkFromRow(newRow.row, meta.value!.columns!) |
||||
}) |
||||
} |
||||
|
||||
if (dragElement.value) { |
||||
dragElement.value.style.boxShadow = 'none' |
||||
dragElement.value.classList.remove('hide') |
||||
|
||||
dragElement.value = null |
||||
} |
||||
updateRowProperty(newRow, updateProperty, false) |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<template> |
||||
<div class="flex relative flex-col prevent-select" @drop="dropEvent"> |
||||
<div class="flex"> |
||||
<div |
||||
v-for="date in weekDates" |
||||
:key="date.toISOString()" |
||||
class="w-1/7 text-center text-sm text-gray-500 w-full py-1 border-gray-200 border-b-1 border-r-1 bg-gray-50" |
||||
> |
||||
{{ dayjs(date).format('DD ddd') }} |
||||
</div> |
||||
</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 min-h-[100vh] last:border-r-0 items-center w-1/7" |
||||
@click="selectedDate = date" |
||||
></div> |
||||
</div> |
||||
<div class="absolute nc-scrollbar-md overflow-y-auto mt-9 pointer-events-none inset-0"> |
||||
<div |
||||
v-for="(record, id) in calendarData" |
||||
:key="id" |
||||
:data-unique-id="record.rowMeta.id" |
||||
:style="{ |
||||
...record.rowMeta.style, |
||||
boxShadow: |
||||
record.rowMeta.id === draggingId |
||||
? '0px 8px 8px -4px rgba(0, 0, 0, 0.04), 0px 20px 24px -4px rgba(0, 0, 0, 0.10)' |
||||
: 'none', |
||||
}" |
||||
class="absolute group draggable-record pointer-events-auto" |
||||
@mousedown="dragStart($event, record)" |
||||
> |
||||
<LazySmartsheetRow :row="record"> |
||||
<LazySmartsheetCalendarRecordCard |
||||
:date="dayjs(record.row[record.rowMeta.range!.fk_from_col.title!]).format('DD-MM-YYYY HH:mm')" |
||||
:name="record.row[displayField!.title!]" |
||||
:position="record.rowMeta.position" |
||||
:record="record" |
||||
:resize="!!record.rowMeta.range?.fk_to_col && isUIAllowed('dataEdit')" |
||||
color="blue" |
||||
@dblclick="emits('expand-record', record)" |
||||
/> |
||||
</LazySmartsheetRow> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<style lang="scss" scoped> |
||||
.hide { |
||||
transition: 0.01s; |
||||
transform: translateX(-9999px); |
||||
} |
||||
.prevent-select { |
||||
-webkit-user-select: none; /* Safari */ |
||||
-ms-user-select: none; /* IE 10 and IE 11 */ |
||||
user-select: none; /* Standard syntax */ |
||||
} |
||||
</style> |
Loading…
Reference in new issue