@ -52,6 +52,146 @@ const hours = computed(() => {
return hours
return hours
} )
} )
const calculateNewDates = ( {
endDate ,
startDate ,
scheduleStart ,
scheduleEnd ,
} : {
endDate : dayjs . Dayjs
startDate : dayjs . Dayjs
scheduleStart : dayjs . Dayjs
scheduleEnd : dayjs . Dayjs
} ) => {
/ / I f t h e r e i s n o e n d d a t e , w e a d d 1 5 m i n u t e s t o t h e s t a r t d a t e a n d u s e t h a t a s t h e e n d d a t e
if ( ! endDate . isValid ( ) ) {
endDate = startDate . clone ( ) . add ( 15 , 'minutes' )
}
/ / I f t h e s t a r t d a t e i s b e f o r e t h e o p e n e d d a t e , w e u s e t h e s c h e d u l e s t a r t a s t h e s t a r t d a t e
/ / T h i s i s t o e n s u r e t h e g e n e r a t e d s t y l e o f t h e r e c o r d i s n o t o u t s i d e t h e b o u n d s o f t h e c a l e n d a r
if ( startDate . isSameOrBefore ( scheduleStart ) ) {
startDate = scheduleStart
}
/ / I f t h e e n d d a t e i s a f t e r t h e s c h e d u l e e n d , w e u s e t h e s c h e d u l e e n d a s t h e e n d d a t e
/ / T h i s i s t o e n s u r e t h e g e n e r a t e d s t y l e o f t h e r e c o r d i s n o t o u t s i d e t h e b o u n d s o f t h e c a l e n d a r
if ( endDate . isAfter ( scheduleEnd ) ) {
endDate = scheduleEnd
}
return { endDate , startDate }
}
/ * c o n s t g e t G r i d T i m e = ( d a t e : d a y j s . D a y j s , r o u n d = f a l s e ) = > {
const gridCalc = date . hour ( ) * 60 + date . minute ( )
if ( round ) {
return Math . ceil ( gridCalc )
} else {
return Math . floor ( gridCalc )
}
}
const getGridTimeSlots = ( from : dayjs . Dayjs , to : dayjs . Dayjs ) => {
return {
from : getGridTime ( from , false ) ,
to : getGridTime ( to , true ) - 1 ,
}
} * /
/ * c o n s t h a s S l o t F o r R e c o r d = (
record : Row ,
columnArray : Row [ ] ,
dates : {
fromDate : dayjs . Dayjs
toDate : dayjs . Dayjs
} ,
) => {
const { fromDate , toDate } = dates
if ( ! fromDate || ! toDate ) return false
for ( const column of columnArray ) {
const columnFromCol = column . rowMeta . range ? . fk _from _col
const columnToCol = column . rowMeta . range ? . fk _to _col
if ( ! columnFromCol ) return false
const { startDate : columnFromDate , endDate : columnToDate } = calculateNewDates ( {
startDate : dayjs ( column . row [ columnFromCol . title ! ] ) ,
endDate : columnToCol ? dayjs ( column . row [ columnToCol . title ! ] ) : dayjs ( column . row [ columnFromCol . title ! ] ) . add ( 1 , 'hour' ) ,
scheduleStart : dayjs ( selectedDate . value ) . startOf ( 'day' ) ,
scheduleEnd : dayjs ( selectedDate . value ) . endOf ( 'day' ) ,
} )
if (
fromDate . isBetween ( columnFromDate , columnToDate , null , '[]' ) ||
toDate . isBetween ( columnFromDate , columnToDate , null , '[]' )
) {
return false
}
}
return true
} * /
/ * c o n s t g e t M a x O f G r i d = (
{
fromDate ,
toDate ,
} : {
fromDate : dayjs . Dayjs
toDate : dayjs . Dayjs
} ,
gridTimeMap : Map < number , number > ,
) => {
let max = 0
const gridTimes = getGridTimeSlots ( fromDate , toDate )
for ( let gridCounter = gridTimes . from ; gridCounter <= gridTimes . to ; gridCounter ++ ) {
if ( gridTimeMap . has ( gridCounter ) && gridTimeMap . get ( gridCounter ) > max ) {
max = gridTimeMap . get ( gridCounter )
}
}
return max
} * /
/ * c o n s t i s O v e r l a p s = ( r o w 1 : R o w , r o w 2 : R o w ) = > {
const fromCol1 = row1 . rowMeta . range ? . fk _from _col
const toCol1 = row1 . rowMeta . range ? . fk _to _col
const fromCol2 = row2 . rowMeta . range ? . fk _from _col
const toCol2 = row2 . rowMeta . range ? . fk _to _col
if ( ! fromCol1 || ! fromCol2 ) return false
const { startDate : startDate1 , endDate : endDate1 } = calculateNewDates ( {
endDate : toCol1 ? dayjs ( row1 . row [ toCol1 . title ! ] ) : dayjs ( row1 . row [ fromCol1 . title ! ] ) . add ( 1 , 'hour' ) ,
startDate : dayjs ( row1 . row [ fromCol1 . title ! ] ) ,
scheduleStart : dayjs ( selectedDate . value ) . startOf ( 'day' ) ,
scheduleEnd : dayjs ( selectedDate . value ) . endOf ( 'day' ) ,
} )
const { startDate : startDate2 , endDate : endDate2 } = calculateNewDates ( {
endDate : toCol2 ? dayjs ( row2 . row [ toCol2 . title ! ] ) : dayjs ( row2 . row [ fromCol2 . title ! ] ) . add ( 1 , 'hour' ) ,
startDate : dayjs ( row2 . row [ fromCol2 . title ! ] ) ,
scheduleStart : dayjs ( selectedDate . value ) . startOf ( 'day' ) ,
scheduleEnd : dayjs ( selectedDate . value ) . endOf ( 'day' ) ,
} )
return startDate1 . isBetween ( startDate2 , endDate2 , null , '[]' ) || endDate1 . isBetween ( startDate2 , endDate2 , null , '[]' )
} * /
/ * c o n s t g e t M a x O v e r l a p s = ( { r o w , r o w A r r a y } : { r o w : R o w ; r o w A r r a y : R o w [ ] } ) = > {
let maxOverlaps = row . rowMeta . numberOfOverlaps
for ( const record of rowArray ) {
if ( isOverlaps ( row , record ) ) {
if ( ! record . rowMeta . numberOfOverlaps || ! row . rowMeta . numberOfOverlaps ) continue
if ( record . rowMeta . numberOfOverlaps > row . rowMeta . numberOfOverlaps ) {
maxOverlaps = record . rowMeta . numberOfOverlaps
}
}
}
return maxOverlaps
} * /
const recordsAcrossAllRange = computed < {
const recordsAcrossAllRange = computed < {
record : Row [ ]
record : Row [ ]
count : {
count : {
@ -82,6 +222,9 @@ const recordsAcrossAllRange = computed<{
const perRecordHeight = 80
const perRecordHeight = 80
/ * c o n s t c o l u m n A r r a y : A r r a y < A r r a y < R o w > > = [ [ ] ]
const gridTimeMap = new Map ( ) * /
let recordsByRange : Array < Row > = [ ]
let recordsByRange : Array < Row > = [ ]
calendarRange . value . forEach ( ( range ) => {
calendarRange . value . forEach ( ( range ) => {
@ -90,48 +233,36 @@ const recordsAcrossAllRange = computed<{
/ / W e f e t c h a l l t h e r e c o r d s t h a t m a t c h t h e c a l e n d a r r a n g e s i n a s i n g l e t i m e .
/ / W e f e t c h a l l t h e r e c o r d s t h a t m a t c h t h e c a l e n d a r r a n g e s i n a s i n g l e t i m e .
/ / B u t n o t a l l f e t c h e d r e c o r d s a r e v a l i d f o r t h e c e r t a i n r a n g e , s o w e f i l t e r t h e m o u t & s o r t t h e m
/ / B u t n o t a l l f e t c h e d r e c o r d s a r e v a l i d f o r t h e c e r t a i n r a n g e , s o w e f i l t e r t h e m o u t & s o r t t h e m
const sortedFormattedData = [ ... formattedData . value ] . filter ( ( record ) => {
const sortedFormattedData = [ ... formattedData . value ]
. filter ( ( record ) => {
const fromDate = record . row [ fromCol ! . title ! ] ? dayjs ( record . row [ fromCol ! . title ! ] ) : null
const fromDate = record . row [ fromCol ! . title ! ] ? dayjs ( record . row [ fromCol ! . title ! ] ) : null
if ( fromCol && endCol ) {
if ( fromCol && endCol ) {
const fromDate = record . row [ fromCol . title ! ] ? dayjs ( record . row [ fromCol . title ! ] ) : null
const fromDate = record . row [ fromCol . title ! ] ? dayjs ( record . row [ fromCol . title ! ] ) : null
const toDate = record . row [ endCol . title ! ] ? dayjs ( record . row [ endCol . title ! ] ) : null
const toDate = record . row [ endCol . title ! ] ? dayjs ( record . row [ endCol . title ! ] ) : null
return fromDate && toDate ? . isValid ( ) ? fromDate . isBefore ( toDate ) : true
return fromDate && toDate ? . isValid ( ) ? fromDate . isSameOr Before ( toDate ) : true
} else if ( fromCol && ! endCol ) {
} else if ( fromCol && ! endCol ) {
return ! ! fromDate
return ! ! fromDate
}
}
return false
return false
} )
} )
. sort ( ( a , b ) => {
const aDate = dayjs ( a . row [ fromCol ! . title ! ] )
const bDate = dayjs ( b . row [ fromCol ! . title ! ] )
return aDate . isBefore ( bDate ) ? 1 : - 1
} )
/ / I f t h e r e i s a s t a r t a n d e n d c o l u m n , w e c a l c u l a t e t h e t o p a n d h e i g h t o f t h e r e c o r d b a s e d o n t h e s t a r t a n d e n d d a t e
if ( fromCol && endCol ) {
for ( const record of sortedFormattedData ) {
for ( const record of sortedFormattedData ) {
/ / W e u s e t h i s i d d u r i n g t h e d r a g a n d d r o p o p e r a t i o n a n d t o k e e p t r a c k o f t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
const id = record . rowMeta . id ? ? generateRandomNumber ( )
const id = generateRandomNumber ( )
let startDate = dayjs ( record . row [ fromCol . title ! ] )
let endDate = dayjs ( record . row [ endCol . title ! ] )
/ / I f n o s t a r t d a t e i s p r o v i d e d o r s t a r t D a t e i s a f t e r t h e e n d D a t e , w e s k i p t h e r e c o r d
if ( ! startDate . isValid ( ) || startDate . isAfter ( endDate ) ) continue
/ / I f t h e r e i s n o e n d d a t e , w e a d d 3 0 m i n u t e s t o t h e s t a r t d a t e a n d u s e t h a t a s t h e e n d d a t e
if ( ! endDate . isValid ( ) ) {
endDate = startDate . clone ( ) . add ( 30 , 'minutes' )
}
/ / I f t h e s t a r t d a t e i s b e f o r e t h e o p e n e d d a t e , w e u s e t h e s c h e d u l e s t a r t a s t h e s t a r t d a t e
/ / T h i s i s t o e n s u r e t h e g e n e r a t e d s t y l e o f t h e r e c o r d i s n o t o u t s i d e t h e b o u n d s o f t h e c a l e n d a r
if ( startDate . isBefore ( scheduleStart , 'minutes' ) ) {
startDate = scheduleStart
}
/ / I f t h e e n d d a t e i s a f t e r t h e s c h e d u l e e n d , w e u s e t h e s c h e d u l e e n d a s t h e e n d d a t e
/ / T h i s i s t o e n s u r e t h e g e n e r a t e d s t y l e o f t h e r e c o r d i s n o t o u t s i d e t h e b o u n d s o f t h e c a l e n d a r
if ( endDate . isAfter ( scheduleEnd , 'minutes' ) ) {
endDate = scheduleEnd
}
if ( fromCol && endCol ) {
const { endDate , startDate } = calculateNewDates ( {
endDate : dayjs ( record . row [ endCol . title ! ] ) ,
startDate : dayjs ( record . row [ fromCol . title ! ] ) ,
scheduleStart ,
scheduleEnd ,
} )
/ / T h e t o p o f t h e r e c o r d i s c a l c u l a t e d b a s e d o n t h e s t a r t h o u r a n d m i n u t e
/ / T h e t o p o f t h e r e c o r d i s c a l c u l a t e d b a s e d o n t h e s t a r t h o u r a n d m i n u t e
const topInPixels = ( startDate . hour ( ) + startDate . minute ( ) / 60 ) * 80
const topInPixels = ( startDate . hour ( ) + startDate . minute ( ) / 60 ) * 80
@ -140,7 +271,6 @@ const recordsAcrossAllRange = computed<{
const heightInPixels = Math . max ( ( endDate . diff ( startDate , 'minute' ) / 60 ) * 80 , perRecordHeight )
const heightInPixels = Math . max ( ( endDate . diff ( startDate , 'minute' ) / 60 ) * 80 , perRecordHeight )
const startHour = startDate . hour ( )
const startHour = startDate . hour ( )
let _startDate = startDate . clone ( )
let _startDate = startDate . clone ( )
const style : Partial < CSSStyleDeclaration > = {
const style : Partial < CSSStyleDeclaration > = {
@ -148,7 +278,7 @@ const recordsAcrossAllRange = computed<{
top : ` ${ topInPixels + 5 + startHour * 2 } px ` ,
top : ` ${ topInPixels + 5 + startHour * 2 } px ` ,
}
}
/ / W e l o o p t h r o u g h e v e r y 1 5 m i n u t e s b e t w e e n t h e s t a r t a n d e n d d a t e a n d k e e p t r a c k o f t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
/ / W e l o o p t h r o u g h e v e r y 1 m i n u t e s b e t w e e n t h e s t a r t a n d e n d d a t e a n d k e e p t r a c k o f t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
/ / I f t h e n u m b e r o f r e c o r d s e x c e e d s 4 , w e h i d e t h e r e c o r d a n d s h o w a b u t t o n t o v i e w m o r e r e c o r d s
/ / I f t h e n u m b e r o f r e c o r d s e x c e e d s 4 , w e h i d e t h e r e c o r d a n d s h o w a b u t t o n t o v i e w m o r e r e c o r d s
while ( _startDate . isBefore ( endDate ) ) {
while ( _startDate . isBefore ( endDate ) ) {
const timeKey = _startDate . format ( 'HH:mm' )
const timeKey = _startDate . format ( 'HH:mm' )
@ -199,18 +329,13 @@ const recordsAcrossAllRange = computed<{
range : range as any ,
range : range as any ,
} ,
} ,
} )
} )
}
} else if ( fromCol ) {
} else if ( fromCol ) {
for ( const record of sortedFormattedData ) {
const { startDate , endDate } = calculateNewDates ( {
const id = generateRandomNumber ( )
startDate : dayjs ( record . row [ fromCol . title ! ] ) ,
endDate : dayjs ( record . row [ fromCol . title ! ] ) . add ( 1 , 'hour' ) ,
const startDate = dayjs ( record . row [ fromCol . title ! ] )
scheduleStart ,
scheduleEnd ,
let endDate = dayjs ( record . row [ fromCol . title ! ] ) . add ( 1 , 'hour' )
} )
if ( endDate . isAfter ( scheduleEnd , 'minutes' ) ) {
endDate = scheduleEnd
}
const startHour = startDate . hour ( )
const startHour = startDate . hour ( )
@ -218,7 +343,7 @@ const recordsAcrossAllRange = computed<{
let _startDate = startDate . clone ( )
let _startDate = startDate . clone ( )
/ / W e l o o p t h r o u g h e v e r y m i n u t e b e t w e e n t h e s t a r t a n d e n d d a t e a n d k e e p t r a c k o f t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
/ / W e l o o p t h r o u g h e v e r y m i n u t e b e t w e e n t h e s t a r t a n d e n d d a t e a n d k e e p t r a c k o f t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
while ( _startDate . isBefore ( endDate ) ) {
while ( _startDate . isBefore ( endDate , 'minute' ) ) {
const timeKey = _startDate . format ( 'HH:mm' )
const timeKey = _startDate . format ( 'HH:mm' )
if ( ! overlaps [ timeKey ] ) {
if ( ! overlaps [ timeKey ] ) {
@ -239,6 +364,7 @@ const recordsAcrossAllRange = computed<{
display : 'none' ,
display : 'none' ,
}
}
}
}
_startDate = _startDate . add ( 1 , 'minute' )
_startDate = _startDate . add ( 1 , 'minute' )
}
}
@ -273,6 +399,13 @@ const recordsAcrossAllRange = computed<{
}
}
}
}
} )
} )
/ *
recordsByRange . sort ( ( a , b ) => {
const fromColA = a . rowMeta . range ? . fk _from _col
const fromColB = b . rowMeta . range ? . fk _from _col
if ( ! fromColA || ! fromColB ) return 0
return dayjs ( a . row [ fromColA . title ! ] ) . isBefore ( dayjs ( b . row [ fromColB . title ! ] ) ) ? - 1 : 1
} ) * /
/ / W e c a n ' t c a l c u l a t e t h e w i d t h & l e f t o f t h e r e c o r d s w i t h o u t k n o w i n g t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
/ / W e c a n ' t c a l c u l a t e t h e w i d t h & l e f t o f t h e r e c o r d s w i t h o u t k n o w i n g t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
/ / S o w e l o o p t h r o u g h t h e r e c o r d s a g a i n a n d c a l c u l a t e t h e w i d t h & l e f t o f t h e r e c o r d s b a s e d o n t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
/ / S o w e l o o p t h r o u g h t h e r e c o r d s a g a i n a n d c a l c u l a t e t h e w i d t h & l e f t o f t h e r e c o r d s b a s e d o n t h e n u m b e r o f r e c o r d s t h a t o v e r l a p a t a g i v e n t i m e
@ -287,12 +420,9 @@ const recordsAcrossAllRange = computed<{
overlapIndex = Math . max ( overlaps [ minutes ] . id . indexOf ( record . rowMeta . id ! ) , overlapIndex )
overlapIndex = Math . max ( overlaps [ minutes ] . id . indexOf ( record . rowMeta . id ! ) , overlapIndex )
}
}
}
}
const spacing = 0.25
const spacing = 0.25
const widthPerRecord = ( 100 - spacing * ( maxOverlaps - 1 ) ) / maxOverlaps
const widthPerRecord = ( 100 - spacing * ( maxOverlaps - 1 ) ) / maxOverlaps
const leftPerRecord = ( widthPerRecord + spacing ) * overlapIndex
const leftPerRecord = ( widthPerRecord + spacing ) * overlapIndex
record . rowMeta . style = {
record . rowMeta . style = {
... record . rowMeta . style ,
... record . rowMeta . style ,
left : ` ${ leftPerRecord - 0.08 } % ` ,
left : ` ${ leftPerRecord - 0.08 } % ` ,
@ -301,6 +431,92 @@ const recordsAcrossAllRange = computed<{
return record
return record
} )
} )
/ / T O D O : R e w r i t e t h e c a l c u l a t i o n s f o r t h e s t y l e o f t h e r e c o r d s
/ * f o r ( c o n s t r e c o r d o f r e c o r d s B y R a n g e ) {
const fromCol = record . rowMeta . range ? . fk _from _col
const toCol = record . rowMeta . range ? . fk _to _col
if ( ! fromCol ) continue
const { startDate , endDate } = calculateNewDates ( {
startDate : dayjs ( record . row [ fromCol . title ! ] ) ,
endDate : toCol ? dayjs ( record . row [ toCol . title ! ] ) : dayjs ( record . row [ fromCol . title ! ] ) . add ( 1 , 'hour' ) ,
scheduleStart ,
scheduleEnd ,
} )
const gridTimes = getGridTimeSlots ( startDate , endDate )
for ( let gridCounter = gridTimes . from ; gridCounter <= gridTimes . to ; gridCounter ++ ) {
if ( gridTimeMap . has ( gridCounter ) ) {
gridTimeMap . set ( gridCounter , gridTimeMap . get ( gridCounter ) + 1 )
} else {
gridTimeMap . set ( gridCounter , 1 )
}
}
let foundAColumn = false
for ( const column in columnArray ) {
if (
hasSlotForRecord ( record , columnArray [ column ] , {
fromDate : startDate ,
toDate : endDate ,
} )
) {
columnArray [ column ] . push ( record )
foundAColumn = true
break
}
}
if ( ! foundAColumn ) {
columnArray . push ( [ record ] )
}
}
for ( const columnIndex in columnArray ) {
for ( const record of columnArray [ columnIndex ] ) {
const recordRange = record . rowMeta . range
const fromCol = recordRange ? . fk _from _col
const toCol = recordRange ? . fk _to _col
if ( ! fromCol ) continue
const { startDate , endDate } = calculateNewDates ( {
startDate : dayjs ( record . row [ fromCol . title ! ] ) ,
endDate : toCol ? dayjs ( record . row [ toCol . title ! ] ) : dayjs ( record . row [ fromCol . title ! ] ) . add ( 1 , 'hour' ) ,
scheduleStart : dayjs ( selectedDate . value ) . startOf ( 'day' ) ,
scheduleEnd : dayjs ( selectedDate . value ) . endOf ( 'day' ) ,
} )
record . rowMeta . numberOfOverlaps =
getMaxOfGrid (
{
fromDate : startDate ,
toDate : endDate ,
} ,
gridTimeMap ,
) - 1
record . rowMeta . overLapIteration = parseInt ( columnIndex ) + 1
}
}
for ( const record of recordsByRange ) {
record . rowMeta . numberOfOverlaps = getMaxOverlaps ( {
row : record ,
rowArray : recordsByRange ,
} )
const width = 100 / columnArray . length
const left = width * ( record . rowMeta . overLapIteration - 1 )
record . rowMeta . style = {
... record . rowMeta . style ,
width : ` ${ width . toFixed ( 2 ) } % ` ,
left : ` ${ left } % ` ,
}
} * /
return {
return {
count : overlaps ,
count : overlaps ,
record : recordsByRange ,
record : recordsByRange ,
@ -328,6 +544,7 @@ const useDebouncedRowUpdate = useDebounceFn((row: Row, updateProperty: string[],
/ / W h e n t h e u s e r i s d r a g g i n g a r e c o r d , w e c a l c u l a t e t h e n e w s t a r t a n d e n d d a t e b a s e d o n t h e m o u s e p o s i t i o n
/ / W h e n t h e u s e r i s d r a g g i n g a r e c o r d , w e c a l c u l a t e t h e n e w s t a r t a n d e n d d a t e b a s e d o n t h e m o u s e p o s i t i o n
const calculateNewRow = ( event : MouseEvent ) => {
const calculateNewRow = ( event : MouseEvent ) => {
if ( ! container . value || ! dragRecord . value ) return { newRow : null , updateProperty : [ ] }
if ( ! container . value || ! dragRecord . value ) return { newRow : null , updateProperty : [ ] }
const { top } = container . value . getBoundingClientRect ( )
const { top } = container . value . getBoundingClientRect ( )
const { scrollHeight } = container . value
const { scrollHeight } = container . value
@ -391,10 +608,7 @@ const calculateNewRow = (event: MouseEvent) => {
if ( dragElement . value ) {
if ( dragElement . value ) {
formattedData . value = formattedData . value . map ( ( r ) => {
formattedData . value = formattedData . value . map ( ( r ) => {
const pk = extractPkFromRow ( r . row , meta . value ! . columns ! )
const pk = extractPkFromRow ( r . row , meta . value ! . columns ! )
if ( pk === newPk ) {
return pk === newPk ? newRow : r
return newRow
}
return r
} )
} )
} else {
} else {
/ / I f t h e o l d r o w i s n o t f o u n d , w e a d d t h e n e w r o w t o t h e f o r m a t t e d D a t a a r r a y a n d r e m o v e t h e o l d r o w f r o m t h e f o r m a t t e d S i d e B a r D a t a a r r a y
/ / I f t h e o l d r o w i s n o t f o u n d , w e a d d t h e n e w r o w t o t h e f o r m a t t e d D a t a a r r a y a n d r e m o v e t h e o l d r o w f r o m t h e f o r m a t t e d S i d e B a r D a t a a r r a y
@ -408,10 +622,9 @@ const calculateNewRow = (event: MouseEvent) => {
}
}
const onResize = ( event : MouseEvent ) => {
const onResize = ( event : MouseEvent ) => {
if ( ! isUIAllowed ( 'dataEdit' ) ) return
if ( ! isUIAllowed ( 'dataEdit' ) || ! container . value || ! resizeRecord . value ) return
if ( ! container . value || ! resizeRecord . value ) return
const { top , bottom } = container . value . getBoundingClientRect ( )
const { top , bottom } = container . value . getBoundingClientRect ( )
const { scrollHeight } = container . value
const { scrollHeight } = container . value
/ / I f t h e m o u s e p o s i t i o n i s n e a r t h e t o p o r b o t t o m o f t h e s c r o l l c o n t a i n e r , w e s c r o l l t h e c o n t a i n e r
/ / I f t h e m o u s e p o s i t i o n i s n e a r t h e t o p o r b o t t o m o f t h e s c r o l l c o n t a i n e r , w e s c r o l l t h e c o n t a i n e r
@ -425,26 +638,28 @@ const onResize = (event: MouseEvent) => {
const fromCol = resizeRecord . value . rowMeta . range ? . fk _from _col
const fromCol = resizeRecord . value . rowMeta . range ? . fk _from _col
const toCol = resizeRecord . value . rowMeta . range ? . fk _to _col
const toCol = resizeRecord . value . rowMeta . range ? . fk _to _col
if ( ! fromCol || ! toCol ) return
if ( ! fromCol || ! toCol ) return
const ogEndDate = dayjs ( resizeRecord . value . row [ toCol . title ! ] )
const ogEndDate = dayjs ( resizeRecord . value . row [ toCol . title ! ] )
const ogStartDate = dayjs ( resizeRecord . value . row [ fromCol . title ! ] )
const ogStartDate = dayjs ( resizeRecord . value . row [ fromCol . title ! ] )
const hour = Math . max ( Math . floor ( percentY * 23 ) , 0 )
const hour = Math . floor ( percentY * 24 ) / / R o u n d d o w n t o t h e n e a r e s t h o u r
const minutes = Math . round ( ( percentY * 24 * 60 ) % 60 )
let newRow : Row | null = null
let newRow : Row | null = null
let updateProperty : string [ ] = [ ]
let updateProperty : string [ ] = [ ]
if ( resizeDirection . value === 'right' ) {
if ( resizeDirection . value === 'right' ) {
/ / I f t h e u s e r i s r e s i z i n g t h e r e c o r d t o t h e r i g h t , w e c a l c u l a t e t h e n e w e n d d a t e b a s e d o n t h e m o u s e p o s i t i o n
/ / I f t h e u s e r i s r e s i z i n g t h e r e c o r d t o t h e r i g h t , w e c a l c u l a t e t h e n e w e n d d a t e b a s e d o n t h e m o u s e p o s i t i o n
let newEndDate = dayjs ( selectedDate . value ) . add ( hour , 'hour' )
let newEndDate = dayjs ( selectedDate . value ) . add ( hour , 'hour' ) . add ( minutes , 'minute' )
updateProperty = [ toCol . title ! ]
updateProperty = [ toCol . title ! ]
/ / I f t h e n e w e n d d a t e i s b e f o r e t h e s t a r t d a t e , w e s e t t h e n e w e n d d a t e t o t h e s t a r t d a t e
/ / I f t h e n e w e n d d a t e i s b e f o r e t h e s t a r t d a t e , w e s e t t h e n e w e n d d a t e t o t h e s t a r t d a t e
/ / T h i s i s t o e n s u r e t h e e n d d a t e i s a l w a y s s a m e o r a f t e r t h e s t a r t d a t e
/ / T h i s i s t o e n s u r e t h e e n d d a t e i s a l w a y s s a m e o r a f t e r t h e s t a r t d a t e
if ( dayjs ( newEndDate ) . isBefore ( ogStartDate , 'day' ) ) {
if ( dayjs ( newEndDate ) . isBefore ( ogStartDate . add ( 1 , 'hour' ) ) ) {
newEndDate = ogStartDate . clone ( )
newEndDate = ogStartDate . clone ( ) . add ( 1 , 'hour' )
}
}
if ( ! newEndDate . isValid ( ) ) return
if ( ! newEndDate . isValid ( ) ) return
@ -457,14 +672,14 @@ const onResize = (event: MouseEvent) => {
} ,
} ,
}
}
} else if ( resizeDirection . value === 'left' ) {
} else if ( resizeDirection . value === 'left' ) {
let newStartDate = dayjs ( selectedDate . value ) . add ( hour , 'hour' )
let newStartDate = dayjs ( selectedDate . value ) . add ( hour , 'hour' ) . add ( minutes , 'minute' )
updateProperty = [ fromCol . title ! ]
updateProperty = [ fromCol . title ! ]
/ / I f t h e n e w s t a r t d a t e i s a f t e r t h e e n d d a t e , w e s e t t h e n e w s t a r t d a t e t o t h e e n d d a t e
/ / I f t h e n e w s t a r t d a t e i s a f t e r t h e e n d d a t e , w e s e t t h e n e w s t a r t d a t e t o t h e e n d d a t e
/ / T h i s i s t o e n s u r e t h e s t a r t d a t e i s a l w a y s b e f o r e o r s a m e t h e e n d d a t e
/ / T h i s i s t o e n s u r e t h e s t a r t d a t e i s a l w a y s b e f o r e o r s a m e t h e e n d d a t e
if ( dayjs ( newStartDate ) . isAfter ( ogEndDate ) ) {
if ( dayjs ( newStartDate ) . isAfter ( ogEndDate . subtract ( 1 , 'hour' ) ) ) {
newStartDate = dayjs ( dayjs ( ogEndDate ) ) . clone ( )
newStartDate = dayjs ( dayjs ( ogEndDate ) ) . clone ( ) . add ( - 1 , 'hour' )
}
}
if ( ! newStartDate ) return
if ( ! newStartDate ) return
@ -532,6 +747,10 @@ const stopDrag = (event: MouseEvent) => {
dragElement . value = null
dragElement . value = null
}
}
if ( dragRecord . value ) {
dragRecord . value = undefined
}
if ( ! newRow ) return
if ( ! newRow ) return
updateRowProperty ( newRow , updateProperty , false )
updateRowProperty ( newRow , updateProperty , false )
@ -564,7 +783,6 @@ const dragStart = (event: MouseEvent, record: Row) => {
dragRecord . value = record
dragRecord . value = record
dragElement . value = target
dragElement . value = target
dragRecord . value = record
document . addEventListener ( 'mousemove' , onDrag )
document . addEventListener ( 'mousemove' , onDrag )
document . addEventListener ( 'mouseup' , stopDrag )
document . addEventListener ( 'mouseup' , stopDrag )
@ -615,11 +833,26 @@ const viewMore = (hour: dayjs.Dayjs) => {
selectedTime . value = hour
selectedTime . value = hour
showSideMenu . value = true
showSideMenu . value = true
}
}
const selectHour = ( hour : dayjs . Dayjs ) => {
selectedTime . value = hour
dragRecord . value = null
}
/ / T O D O : A d d S u p p o r t f o r m u l t i p l e r a n g e s w h e n m u l t i p l e r a n g e s a r e s u p p o r t e d
const newRecord = ( hour : dayjs . Dayjs ) => {
if ( ! isUIAllowed ( 'dataEdit' ) || ! calendarRange . value ? . length ) return
const record = {
row : {
[ calendarRange . value [ 0 ] . fk _from _col ! . title ! ] : hour . format ( 'YYYY-MM-DD HH:mm:ssZ' ) ,
} ,
}
emit ( 'newRecord' , record )
}
< / script >
< / script >
< template >
< template >
< div
< div
v - if = "recordsAcrossAllRange.record.length"
ref = "container"
ref = "container"
class = "w-full relative no-selection h-[calc(100vh-10rem)] overflow-y-auto nc-scrollbar-md"
class = "w-full relative no-selection h-[calc(100vh-10rem)] overflow-y-auto nc-scrollbar-md"
data - testid = "nc-calendar-day-view"
data - testid = "nc-calendar-day-view"
@ -632,7 +865,8 @@ const viewMore = (hour: dayjs.Dayjs) => {
} "
} "
class = "flex w-full min-h-20 relative border-1 group hover:bg-gray-50 border-white border-b-gray-100"
class = "flex w-full min-h-20 relative border-1 group hover:bg-gray-50 border-white border-b-gray-100"
data - testid = "nc-calendar-day-hour"
data - testid = "nc-calendar-day-hour"
@ click = "selectedTime = hour"
@ click = "selectHour(hour)"
@ dblclick = "newRecord(hour)"
>
>
< div class = "pt-2 px-4 text-xs text-gray-500 font-semibold h-20" >
< div class = "pt-2 px-4 text-xs text-gray-500 font-semibold h-20" >
{ { dayjs ( hour ) . format ( 'H A' ) } }
{ { dayjs ( hour ) . format ( 'H A' ) } }
@ -749,7 +983,8 @@ const viewMore = (hour: dayjs.Dayjs) => {
>
>
< LazySmartsheetRow :row ="record" >
< LazySmartsheetRow :row ="record" >
< LazySmartsheetCalendarVRecordCard
< LazySmartsheetCalendarVRecordCard
: hover = "hoverRecord === record.rowMeta.id"
: hover = "hoverRecord === record.rowMeta.id || record.rowMeta.id === dragRecord?.rowMeta?.id"
: selected = "record.rowMeta.id === dragRecord?.rowMeta?.id"
: position = "record.rowMeta!.position"
: position = "record.rowMeta!.position"
: record = "record"
: record = "record"
: resize = "!!record.rowMeta.range?.fk_to_col && isUIAllowed('dataEdit')"
: resize = "!!record.rowMeta.range?.fk_to_col && isUIAllowed('dataEdit')"
@ -761,13 +996,14 @@ const viewMore = (hour: dayjs.Dayjs) => {
v - if = "!isRowEmpty(record, displayField!)"
v - if = "!isRowEmpty(record, displayField!)"
v - model = "record.row[displayField!.title!]"
v - model = "record.row[displayField!.title!]"
: bold = "getFieldStyle(displayField!).bold"
: bold = "getFieldStyle(displayField!).bold"
: column = "displayField"
: column = "displayField! "
: italic = "getFieldStyle(displayField!).italic"
: italic = "getFieldStyle(displayField!).italic"
: underline = "getFieldStyle(displayField!).underline"
: underline = "getFieldStyle(displayField!).underline"
/ >
/ >
< / template >
< / template >
< template v-for ="(field, id) in fieldsWithoutDisplay" :key ="id" >
< template v-for ="(field, id) in fieldsWithoutDisplay" :key ="id" >
< LazySmartsheetCalendarCell
< LazySmartsheetCalendarCell
v - if = "!isRowEmpty(record, field!)"
v - model = "record.row[field!.title!]"
v - model = "record.row[field!.title!]"
: bold = "getFieldStyle(field).bold"
: bold = "getFieldStyle(field).bold"
: column = "field"
: column = "field"
@ -781,8 +1017,6 @@ const viewMore = (hour: dayjs.Dayjs) => {
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< div v -else class = "w-full h-full flex text-md font-bold text-gray-500 items-center justify-center" > No records in this day < / div >
< / template >
< / template >
< style lang = "scss" scoped >
< style lang = "scss" scoped >