@@ -1,6 +1,7 @@ import { default as Form } from "antd/es/form" ; import { default as Input } from "antd/es/input" ; import { default as ColorPicker } from "antd/es/color-picker" ; import { default as Switch } from "antd/es/switch" ; import { trans , getCalendarLocale } from "../../i18n/comps" ; import { createRef , useContext , useRef , useState , useEffect , useCallback , useMemo , Suspense } from "react" ; import dayjs from "dayjs" ; Expand All @@ -11,14 +12,15 @@ import adaptivePlugin from "@fullcalendar/adaptive"; import dayGridPlugin from "@fullcalendar/daygrid" ; import multiMonthPlugin from '@fullcalendar/multimonth' ; import timeGridPlugin from "@fullcalendar/timegrid" ; import interactionPlugin from "@fullcalendar/interaction" ; import interactionPlugin , { EventResizeDoneArg } from "@fullcalendar/interaction" ; import listPlugin from "@fullcalendar/list" ; import allLocales from "@fullcalendar/core/locales-all" ; import { EventContentArg , DateSelectArg } from "@fullcalendar/core" ; import { EventContentArg , DateSelectArg , EventDropArg } from "@fullcalendar/core" ; import momentPlugin from "@fullcalendar/moment" ; import ErrorBoundary from "./errorBoundary" ; import { default as Tabs } from "antd/es/tabs" ; import { differenceBy , differenceWith , isEqual , filter , includes } from "lodash" ; import { isValidColor , Expand Down Expand Up @@ -54,6 +56,8 @@ import { migrateOldData , controlItem , depsConfig , stateComp , JSONObject , } from 'lowcoder-sdk' ; import { Expand All @@ -79,6 +83,7 @@ import { resourceTimeGridHeaderToolbar , } from "./calendarConstants" ; import { EventOptionControl } from "./eventOptionsControl" ; import { EventImpl } from "@fullcalendar/core/internal" ; function fixOldData ( oldData :any ) { if ( ! Boolean ( oldData ) ) return ; Expand Down Expand Up @@ -196,6 +201,10 @@ let childrenMap: any = { currentPremiumView :dropdownControl ( DefaultWithPremiumViewOptions , "resourceTimelineDay" ) , animationStyle :styleControl ( AnimationStyle , 'animationStyle' ) , showVerticalScrollbar :withDefault ( BoolControl , false ) , initialData :stateComp < JSONObject > ( { } ) , updatedEvents :stateComp < JSONObject > ( { } ) , insertedEvents :stateComp < JSONObject > ( { } ) , deletedEvents :stateComp < JSONObject > ( { } ) , } ; // this should ensure backwards compatibility with older versions of the SDK Expand Down Expand Up @@ -233,8 +242,9 @@ let CalendarBasicComp = (function () { currentFreeView ?:string ; currentPremiumView ?:string ; animationStyle ?:any ; modalStyle ?:any showVerticalScrollbar ?:boolean modalStyle ?:any ; showVerticalScrollbar ?:boolean ; initialData :Array < EventType > ; } , dispatch :any ) => { const comp = useContext ( EditorContext ) ?. getUICompByName ( useContext ( CompNameContext ) Expand All @@ -243,11 +253,13 @@ let CalendarBasicComp = (function () { const theme = useContext ( ThemeContext ) ; const ref = createRef < HTMLDivElement > ( ) ; const editEvent = useRef < EventType > ( ) ; const initData = useRef < boolean > ( false ) ; const [ form ] = Form . useForm ( ) ; const [ left , setLeft ] = useState < number | undefined > ( undefined ) ; const [ licensed , setLicensed ] = useState < boolean > ( props . licenseKey !== "" ) ; const [ currentSlotLabelFormat , setCurrentSlotLabelFormat ] = useState ( slotLabelFormat ) ; const [ initDataMap , setInitDataMap ] = useState < Record < string , number > > ( { } ) ; useEffect ( ( ) => { setLicensed ( props . licenseKey !== "" ) ; } , [ props . licenseKey ] ) ; Expand Down Expand Up @@ -290,27 +302,53 @@ let CalendarBasicComp = (function () { start :dayjs ( item . start , DateParser ) . format ( ) , end :dayjs ( item . end , DateParser ) . format ( ) , allDay :item . allDay , resourceId : item . resourceId ?item . resourceId : null , groupId : item . groupId ?item . groupId : null , ... ( item . resourceId ?{ resourceId : item . resourceId } : { } ) , ... ( item . groupId ?{ groupId : item . groupId } : { } ) , backgroundColor :item . backgroundColor , extendedProps :{ color :isValidColor ( item . color || "" ) ?item . color :theme ?. theme ?. primary , ... ( item . groupId ? { groupId :item . groupId } : { } ) , // Ensure color is in extendedProps detail : item . detail , titleColor :item . titleColor , detailColor :item . detailColor , titleFontWeight :item . titleFontWeight , titleFontStyle :item . titleFontStyle , detailFontWeight :item . detailFontWeight , detailFontStyle :item . detailFontStyle , animation :item ?. animation , animationDelay :item ?. animationDelay , animationDuration :item ?. animationDuration , animationIterationCount : item ?. animationIterationCount } } extendedProps :{ // Ensure color is in extendedProps color :isValidColor ( item . color || "" ) ?item . color :theme ?. theme ?. primary , detail :item . detail , titleColor : item . titleColor , detailColor :item . detailColor , titleFontWeight :item . titleFontWeight , titleFontStyle :item . titleFontStyle , detailFontWeight :item . detailFontWeight , detailFontStyle :item . detailFontStyle , animation :item ?. animation , animationDelay :item ?. animationDelay , animationDuration :item ?. animationDuration , animationIterationCount :item ?. animationIterationCount } } } ) :[ currentEvents ] ; } , [ currentEvents , theme ] ) useEffect ( ( ) => { const mapData :Record < string , number > = { } ; events ?. forEach ( ( item :any , index :number ) => { mapData [ `${ item . id } ` ] = index ; } ) if ( initData . current ) { const difference = differenceWith ( events , props . initialData , isEqual ) ; const inserted = differenceBy ( difference , Object . keys ( initDataMap ) ?. map ( id => ( { id} ) ) , 'id' ) const updated = filter ( difference , obj => includes ( Object . keys ( initDataMap ) , String ( obj . id ) ) ) ; const deleted = differenceBy ( props . initialData , Object . keys ( mapData ) ?. map ( id => ( { id} ) ) , 'id' ) comp . children ?. comp . children ?. updatedEvents . dispatchChangeValueAction ( updated ) ; comp . children ?. comp . children ?. insertedEvents . dispatchChangeValueAction ( inserted ) ; comp . children ?. comp . children ?. deletedEvents . dispatchChangeValueAction ( deleted ) ; } if ( ! initData . current && events ?. length && comp ?. children ?. comp ?. children ?. initialData ) { setInitDataMap ( mapData ) ; comp ?. children ?. comp ?. children ?. initialData ?. dispatch ?.( comp ?. children ?. comp ?. children ?. initialData ?. changeValueAction ?.( [ ...events ] ) ) ; initData . current = true ; } } , [ JSON . stringify ( events ) , comp ?. children ?. comp ?. children ?. initialData ] ) ; const resources = useMemo ( ( ) => props . resources . value , [ props . resources . value ] ) ; // list all plugins for Fullcalendar Expand Down Expand Up @@ -370,12 +408,12 @@ let CalendarBasicComp = (function () { } , [ slotLabelFormat , slotLabelFormatWeek , slotLabelFormatMonth ] ) ; const handleEventDataChange = useCallback ( ( data :Array < Record < string , any > > ) => { comp . children ?. comp . children . events . children . manual . children . manual . dispatch ( comp . children ?. comp . children . events . children . manual . children . manual . setChildrensAction ( comp ? .children ?. comp . children . events . children . manual . children . manual . dispatch ( comp ? .children ?. comp . children . events . children . manual . children . manual . setChildrensAction ( data ) ) ; comp . children ?. comp . children . events . children . mapData . children . data . dispatchChangeValueAction ( comp ? .children ?. comp . children . events . children . mapData . children . data . dispatchChangeValueAction ( JSON . stringify ( data ) ) ; props . onEvent ( "change" ) ; Expand Down Expand Up @@ -506,6 +544,24 @@ let CalendarBasicComp = (function () { > < Input /> </ Form . Item > < Form . Item label = { trans ( "calendar.eventStartTime" ) } name = "start" > < Input /> </ Form . Item > < Form . Item label = { trans ( "calendar.eventEndTime" ) } name = "end" > < Input /> </ Form . Item > < Form . Item label = { trans ( "calendar.eventAllDay" ) } name = "allDay" > < Switch /> </ Form . Item > </ FormWrapper > </ Tabs . TabPane > < Tabs . TabPane tab = { trans ( "calendar.colorStyles" ) } key = "2" > Expand Down Expand Up @@ -768,12 +824,35 @@ let CalendarBasicComp = (function () { showModal ( event , false ) ; } , [ editEvent , showModal ] ) ; const handleDrop = useCallback ( ( ) => { const updateEventsOnDragOrResize = useCallback ( ( eventInfo :EventImpl ) => { const { extendedProps, title, ...event } = eventInfo . toJSON ( ) ; let eventsList = [ ...props . events ] ; const eventIdx = eventsList . findIndex ( ( item :EventType ) => item . id === event . id ) ; if ( eventIdx > - 1 ) { eventsList [ eventIdx ] = { label :title , ...event , ...extendedProps , } ; handleEventDataChange ( eventsList ) ; } } , [ props . events , handleEventDataChange ] ) ; const handleDrop = useCallback ( ( eventInfo :EventDropArg ) => { updateEventsOnDragOrResize ( eventInfo . event ) ; if ( typeof props . onDropEvent === 'function' ) { props . onDropEvent ( "dropEvent " ) ; props . onDropEvent ( "drop " ) ; } } , [ props . onDropEvent ] ) ; } , [ props . onDropEvent , updateEventsOnDragOrResize ] ) ; const handleResize = useCallback ( ( eventInfo :EventResizeDoneArg ) => { updateEventsOnDragOrResize ( eventInfo . event ) ; } , [ props . onDropEvent , updateEventsOnDragOrResize ] ) ; return ( < Wrapper ref = { ref } Expand All @@ -790,7 +869,7 @@ let CalendarBasicComp = (function () { slotEventOverlap = { false } events = { events } dayHeaders = { true } dayHeaderFormat = { { weekday :'short' , month :'numeric' , day :'numeric' , omitCommas :true } } // dayHeaderFormat={{ weekday: 'short', month: 'numeric', day: 'numeric', omitCommas: true }}expandRows = { true } multiMonthMinWidth = { 250 } nowIndicator = { true } Expand Down Expand Up @@ -880,11 +959,13 @@ let CalendarBasicComp = (function () { props . onEvent ( "change" ) ; } } } eventDragStop = { ( info ) => { if ( info . view ) { handleDrop ( ) ; eventDragStart = { ( ) => { if ( typeof props . onDropEvent === 'function' ) { props . onDropEvent ( "drag" ) ; } } } eventDrop = { handleDrop } eventResize = { handleResize } /> </ ErrorBoundary > </ Wrapper > Expand Down Expand Up @@ -1007,6 +1088,30 @@ const TmpCalendarComp = withExposingConfigs(CalendarBasicComp, [ return input . events . filter ( event => Boolean ( event . resourceId ) ) ; } , } ) , depsConfig ( { name :"toUpdatedEvents" , desc :trans ( "calendar.updatedEvents" ) , depKeys :[ "updatedEvents" ] , func :( input :{ updatedEvents :any [ ] ; } ) => { return input . updatedEvents ; } , } ) , depsConfig ( { name :"toInsertedEvents" , desc :trans ( "calendar.insertedEvents" ) , depKeys :[ "insertedEvents" ] , func :( input :{ insertedEvents :any [ ] ; } ) => { return input . insertedEvents ; } , } ) , depsConfig ( { name :"toDeletedEvents" , desc :trans ( "calendar.deletedEvents" ) , depKeys :[ "deletedEvents" ] , func :( input :{ deletedEvents :any [ ] ; } ) => { return input . deletedEvents ; } , } ) , ] ) ; let CalendarComp = withMethodExposing ( TmpCalendarComp , [ Expand Down Expand Up @@ -1124,7 +1229,43 @@ let CalendarComp = withMethodExposing(TmpCalendarComp, [ const viewKey = comp . children . licenseKey . getView ( ) === "" ?'defaultFreeView' :'defaultPremiumView' ; comp . children [ "viewKey" ] . dispatchChangeValueAction ( "multiMonthYear" ) ; } } } , { method :{ name :"clearUpdatedEvents" , detail :"Clear updated events list" , params :[ ] , } , execute :( comp ) => { comp ?. children ?. updatedEvents . dispatch ( comp ?. children ?. updatedEvents . changeValueAction ( [ ] ) ) ; } } , { method :{ name :"clearInsertedEvents" , detail :"Clear inserted events list" , params :[ ] , } , execute :( comp ) => { comp ?. children ?. insertedEvents . dispatch ( comp ?. children ?. insertedEvents . changeValueAction ( [ ] ) ) ; } } , { method :{ name :"clearDeletedEvents" , detail :"Clear deleted events list" , params :[ ] , } , execute :( comp ) => { comp ?. children ?. deletedEvents . dispatch ( comp ?. children ?. deletedEvents . changeValueAction ( [ ] ) ) ; } } , ] ) ; Expand Down