Skip to main content

Calendar Component in CargoXplorer TMS

Introduction

The Calendar Component is a powerful and flexible element in CargoXplorer TMS used for displaying and managing calendar-based data. Built on top of FullCalendar.io, it provides comprehensive calendar functionality including event management, date selection, multiple view types, and interactive features essential for logistics and transportation management systems.

YAML Structure

component: calendar
props:
calendarId: "{{ number calendarId }}"
initialView: "dayGridMonth"
height: 600
options:
headerToolbar:
left: "prev,next today"
center: "title"
right: "dayGridMonth,timeGridWeek,timeGridDay"
selectable: true
editable: true
events:
onDateClick:
- notification:
message: "Date clicked: {{ event.dateStr }}"
onEventClick:
- navigate:
to: "/orders/{{ event.event.extendedProps.orderId }}"
onSelect:
- setVariables:
selectedStart: "{{ event.startStr }}"
selectedEnd: "{{ event.endStr }}"

Attribute Description

  • component: (string) Must be set to "calendar" to use this component type.
  • props: (object) Contains the configuration properties for the calendar component.
    • calendarId: (number) Required - Unique integer identifier for the calendar instance. The system automatically loads all events associated with this calendar ID from the backend.
    • initialView: (string) The initial view to display. Options include:
      • dayGridMonth - Month view with day grid (default)
      • timeGridWeek - Week view with time slots
      • timeGridDay - Day view with time slots
      • listWeek - List view for the week
      • listMonth - List view for the month
      • multiMonthYear - Multi-month year view
    • height: (number|string) Calendar height in pixels or "auto"
    • aspectRatio: (number) Width-to-height ratio (default: 1.35)
    • options: (object) FullCalendar configuration options
      • headerToolbar: (object) Toolbar configuration
        • left: (string) Left toolbar buttons
        • center: (string) Center toolbar content
        • right: (string) Right toolbar buttons
      • footerToolbar: (object) Footer toolbar configuration
      • selectable: (boolean) Allow date/time selection
      • selectMirror: (boolean) Show selection preview
      • editable: (boolean) Allow event editing
      • droppable: (boolean) Allow dropping external elements
      • weekends: (boolean) Display weekends (default: true)
      • locale: (string) Language/locale setting
      • timeZone: (string) Time zone setting
      • nowIndicator: (boolean) Show current time indicator
      • slotMinTime: (string) Earliest time slot (e.g., "06:00:00")
      • slotMaxTime: (string) Latest time slot (e.g., "22:00:00")
      • slotDuration: (string) Duration of each time slot (e.g., "00:30:00")
      • eventDisplay: (string) How events are displayed ("auto", "block", "list-item")
      • dayMaxEvents: (number|boolean) Maximum events per day before "+more" link
      • moreLinkClick: (string) Action when clicking "+more" link
      • events: (array) Static event data (optional - events are typically loaded via calendarId)
      • eventSources: (array) Multiple event sources configuration using GraphQL queries (optional)
  • events: (object) Event handlers for calendar interactions using Component Actions
    • onDateClick: (array) Actions to execute when a date/time is clicked
    • onEventClick: (array) Actions to execute when an event is clicked
    • onSelect: (array) Actions to execute when a date/time range is selected
    • onUnselect: (array) Actions to execute when selection is cleared
    • onEventDrop: (array) Actions to execute when an event is dragged/dropped
    • onEventResize: (array) Actions to execute when an event is resized
    • onEventChange: (array) Actions to execute when an event is modified
    • onDatesSet: (array) Actions to execute when view/date range changes
    • onLoading: (array) Actions to execute when loading state changes

Examples

Basic Calendar

component: calendar
props:
calendarId: 1001
initialView: "dayGridMonth"
height: 500

Calendar with Static Events

component: calendar
props:
calendarId: 1003
initialView: "dayGridMonth"
height: 500
options:
events:
- id: "shipment-001"
title: "Pickup - ABC Corp"
start: "2024-01-15T09:00:00"
end: "2024-01-15T10:00:00"
color: "#ff6b6b"
extendedProps:
type: "pickup"
orderId: "ORD-12345"
customer: "ABC Corporation"
location: "123 Main St, New York"
driver: "John Smith"
- id: "shipment-002"
title: "Delivery - XYZ Ltd"
start: "2024-01-15T14:00:00"
end: "2024-01-15T15:30:00"
color: "#4ecdc4"
extendedProps:
type: "delivery"
orderId: "ORD-12346"
customer: "XYZ Limited"
location: "456 Oak Ave, Boston"
driver: "Jane Doe"
- id: "maintenance-001"
title: "Truck Maintenance"
start: "2024-01-16T08:00:00"
end: "2024-01-16T12:00:00"
color: "#ffa726"
allDay: false
extendedProps:
type: "maintenance"
vehicleId: "TRUCK-001"
serviceType: "Regular Service"
location: "Main Garage"
events:
onEventClick:
- setActionsVariables:
eventId: "{{ event.event.id }}"
eventType: "{{ event.event.extendedProps.type }}"
- if: "{{ eval eventType === 'pickup' || eventType === 'delivery' }}"
then:
- navigate:
to: "/orders/{{ event.event.extendedProps.orderId }}"
else:
- navigate:
to: "/maintenance/{{ event.event.extendedProps.vehicleId }}"

Calendar with Multiple Event Sources

component: calendar
props:
calendarId: 1002
initialView: "dayGridMonth"
height: 600
options:
eventSources:
- query:
command: "query GetShipmentEvents($organizationId: ID!, $start: String!, $end: String!) { shipmentEvents(organizationId: $organizationId, start: $start, end: $end) { id title start end color extendedProps } }"
variables:
organizationId: "{{ organizationId }}"
start: "{{ currentViewStart }}"
end: "{{ currentViewEnd }}"
color: "#3788d8"
textColor: "white"
- query:
command: "query GetWarehouseEvents($warehouseId: ID!, $start: String!, $end: String!) { warehouseEvents(warehouseId: $warehouseId, start: $start, end: $end) { id title start end color extendedProps } }"
variables:
warehouseId: "{{ warehouseId }}"
start: "{{ currentViewStart }}"
end: "{{ currentViewEnd }}"
color: "#ffa726"
textColor: "white"
- events: "{{ maintenance.schedule }}"
color: "#e53e3e"
textColor: "white"
- events:
- title: "Weekly Team Meeting"
start: "2024-01-15T10:00:00"
end: "2024-01-15T11:00:00"
color: "#9c27b0"
rrule: "FREQ=WEEKLY;BYDAY=MO"
extendedProps:
type: "meeting"
location: "Conference Room A"
events:
onEventClick:
- setActionsVariables:
eventType: "{{ event.event.extendedProps.type }}"
eventId: "{{ event.event.id }}"
- navigate:
to: "/events/{{ eventType }}/{{ eventId }}"

Advanced Shipment Calendar

component: calendar
props:
calendarId: 1004
initialView: "timeGridWeek"
height: 600
options:
headerToolbar:
left: "prev,next today"
center: "title"
right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek"
selectable: true
selectMirror: true
editable: true
droppable: true
weekends: true
slotMinTime: "06:00:00"
slotMaxTime: "22:00:00"
slotDuration: "00:30:00"
nowIndicator: true
dayMaxEvents: 3
moreLinkClick: "popover"
locale: "en-US"
timeZone: "America/New_York"
events:
onDateClick:
- consoleLog:
message: "Date clicked: {{ event.dateStr }}"
- setVariables:
selectedDate: "{{ event.dateStr }}"
onEventClick:
- setActionsVariables:
orderId: "{{ event.event.extendedProps.orderId }}"
- navigate:
to: "/shipments/{{ orderId }}"
onSelect:
- setVariables:
selectedStart: "{{ event.startStr }}"
selectedEnd: "{{ event.endStr }}"
- dialog:
name: "createShipmentDialog"
props:
title: "Create New Shipment"
startDate: "{{ selectedStart }}"
endDate: "{{ selectedEnd }}"
onEventDrop:
- mutation:
command: "mutation UpdateShipmentSchedule($id: ID!, $start: String!, $end: String!) { updateShipmentSchedule(id: $id, start: $start, end: $end) { id start end } }"
variables:
id: "{{ event.event.extendedProps.orderId }}"
start: "{{ event.event.startStr }}"
end: "{{ event.event.endStr }}"
onSuccess:
- notification:
message: "Shipment schedule updated successfully"
onError:
- notification:
message: "Failed to update shipment schedule"
variant: "error"
onEventResize:
- mutation:
command: "mutation UpdateShipmentDuration($id: ID!, $end: String!) { updateShipmentDuration(id: $id, end: $end) { id end } }"
variables:
id: "{{ event.event.extendedProps.orderId }}"
end: "{{ event.event.endStr }}"
onSuccess:
- notification:
message: "Shipment duration updated"
onError:
- notification:
message: "Failed to update duration"
variant: "error"

Delivery Schedule Calendar

component: calendar
props:
calendarId: 1005
initialView: "listWeek"
height: "auto"
options:
headerToolbar:
left: "prev,next"
center: "title"
right: "listWeek,listMonth"
events:
onEventClick:
- setActionsVariables:
orderId: "{{ event.event.extendedProps.orderId }}"
eventType: "{{ event.event.extendedProps.type }}"
- navigate:
to: "/orders/{{ orderId }}"
onDateClick:
- setVariables:
selectedDate: "{{ event.dateStr }}"
- query:
command: "query GetDeliveriesForDate($date: String!) { deliveriesForDate(date: $date) { id title customer status } }"
variables:
date: "{{ selectedDate }}"
onSuccess:
- setStore:
dailyDeliveries: "{{ result.deliveriesForDate }}"
- dialog:
name: "dailyDeliveriesDialog"
props:
title: "Deliveries for {{ selectedDate }}"
deliveries: "{{ dailyDeliveries }}"

Operations Calendar with Loading States

component: calendar
props:
calendarId: 1006
initialView: "dayGridMonth"
height: 650
options:
headerToolbar:
left: "prev,next today"
center: "title"
right: "dayGridMonth,timeGridWeek"
events:
onEventClick:
- setActionsVariables:
eventId: "{{ event.event.id }}"
eventType: "{{ event.event.extendedProps.type }}"
- if: "{{ eval eventType === 'shipment' }}"
then:
- navigate:
to: "/shipments/{{ eventId }}"
else:
- if: "{{ eval eventType === 'warehouse' }}"
then:
- navigate:
to: "/warehouse/activities/{{ eventId }}"
else:
- navigate:
to: "/maintenance/{{ eventId }}"
onLoading:
- if: "{{ event.isLoading }}"
then:
- setVariables:
calendarLoading: true
- notification:
message: "Loading calendar events..."
else:
- setVariables:
calendarLoading: false
onDatesSet:
- setVariables:
currentViewStart: "{{ event.startStr }}"
currentViewEnd: "{{ event.endStr }}"
currentView: "{{ event.view.type }}"
- consoleLog:
message: "Calendar view changed to {{ currentView }} ({{ currentViewStart }} - {{ currentViewEnd }})"

Resource-Based Vehicle Calendar

component: calendar
props:
calendarId: 1007
initialView: "resourceTimeGridDay"
height: 700
options:
headerToolbar:
left: "prev,next today"
center: "title"
right: "resourceTimeGridDay,resourceTimeGridWeek"
resources:
- id: "truck-01"
title: "Truck 01 (ABC-123)"
eventColor: "#3788d8"
- id: "truck-02"
title: "Truck 02 (DEF-456)"
eventColor: "#ffa726"
- id: "truck-03"
title: "Truck 03 (GHI-789)"
eventColor: "#4caf50"
editable: true
selectable: true
events:
onEventDrop:
- setActionsVariables:
assignmentId: "{{ event.event.id }}"
newResourceId: "{{ event.newResource.id }}"
newStart: "{{ event.event.startStr }}"
newEnd: "{{ event.event.endStr }}"
- mutation:
command: "mutation UpdateVehicleAssignment($id: ID!, $vehicleId: String!, $start: String!, $end: String!) { updateVehicleAssignment(id: $id, vehicleId: $vehicleId, start: $start, end: $end) { id vehicleId start end } }"
variables:
id: "{{ assignmentId }}"
vehicleId: "{{ newResourceId }}"
start: "{{ newStart }}"
end: "{{ newEnd }}"
onSuccess:
- notification:
message: "Vehicle assignment updated successfully"
onError:
- notification:
message: "Failed to update vehicle assignment"
variant: "error"
- refresh: "calendar"
onSelect:
- setActionsVariables:
resourceId: "{{ event.resource.id }}"
selectedStart: "{{ event.startStr }}"
selectedEnd: "{{ event.endStr }}"
- dialog:
name: "createVehicleAssignmentDialog"
props:
title: "Create Vehicle Assignment"
vehicleId: "{{ resourceId }}"
startTime: "{{ selectedStart }}"
endTime: "{{ selectedEnd }}"
onClose:
- if: "{{ result.success }}"
then:
- refresh: "calendar"
- notification:
message: "New vehicle assignment created"
onEventClick:
- setActionsVariables:
assignmentId: "{{ event.event.id }}"
- navigate:
to: "/vehicle-assignments/{{ assignmentId }}"

Advanced Usage

Custom Event Rendering

Basic Custom Event Layout

component: calendar
props:
calendarId: 2001
options:
eventContent:
component: layout
props:
type: "div"
options:
className: "custom-event"
children:
- component: text
props:
type: "strong"
value: "{{ event.title }}"
- component: text
props:
type: "div"
value: "{{ event.extendedProps.customer || '' }}"
options:
className: "event-details"

Advanced Shipment Event Rendering

component: calendar
props:
calendarId: 2002
options:
eventContent:
component: layout
props:
type: "div"
options:
className: "shipment-event {{ event.extendedProps.status }}"
children:
- component: layout
props:
type: "div"
options:
className: "event-header"
children:
- component: badge
props:
text: "{{ event.extendedProps.type }}"
variant: "{{ eval event.extendedProps.type === 'pickup' ? 'warning' : 'success' }}"
- component: text
props:
type: "span"
value: "{{ event.title }}"
options:
className: "event-title"
- component: layout
props:
type: "div"
options:
className: "event-body"
children:
- component: text
props:
type: "div"
value: "📍 {{ event.extendedProps.location }}"
options:
className: "event-location"
- component: text
props:
type: "div"
value: "🏢 {{ event.extendedProps.customer }}"
options:
className: "event-customer"
- component: text
props:
type: "div"
value: "📦 {{ event.extendedProps.commodities }} items"
options:
className: "event-commodities"

Resource-Based Event Rendering

component: calendar
props:
calendarId: 2003
options:
eventContent:
component: layout
props:
type: "div"
options:
className: "vehicle-assignment-event"
children:
- component: layout
props:
type: "div"
options:
className: "assignment-header"
children:
- component: text
props:
type: "strong"
value: "{{ event.title }}"
- component: badge
props:
text: "{{ event.extendedProps.priority }}"
variant: "{{ eval event.extendedProps.priority === 'high' ? 'danger' : event.extendedProps.priority === 'medium' ? 'warning' : 'info' }}"
- component: layout
props:
type: "div"
options:
className: "assignment-details"
children:
- component: text
props:
type: "div"
value: "🚛 {{ event.extendedProps.vehicleType }}"
- component: text
props:
type: "div"
value: "👤 {{ event.extendedProps.driverName }}"
- component: text
props:
type: "div"
value: "📍 {{ event.extendedProps.route }}"

Conditional Event Rendering

component: calendar
props:
calendarId: 2004
options:
eventContent:
component: layout
props:
type: "div"
options:
className: "status-event {{ event.extendedProps.status }}"
children:
- component: text
props:
type: "div"
value: "{{ event.title }}"
options:
className: "event-title"
- component: layout
if: "{{ eval event.extendedProps.status === 'delayed' }}"
props:
type: "div"
options:
className: "delay-warning"
children:
- component: text
props:
type: "span"
value: "⚠️ Delayed"
options:
className: "delay-text"
- component: text
props:
type: "div"
value: "New ETA: {{ event.extendedProps.newEta }}"
- component: layout
if: "{{ eval event.extendedProps.status === 'completed' }}"
props:
type: "div"
options:
className: "completion-info"
children:
- component: text
props:
type: "span"
value: "✅ Completed"
options:
className: "completion-text"

### Dynamic Options Based on User Role

```yaml
component: calendar
props:
calendarId: 2005
options:
editable: "{{ eval user.role === 'manager' }}"
selectable: "{{ eval user.permissions.includes('schedule_create') }}"

Custom Rendering Benefits

Using component definitions for custom event rendering provides several advantages:

  1. Consistency: Maintains the same YAML-based component structure used throughout CargoXplorer
  2. Reusability: Custom rendering components can be reused across different calendars
  3. Maintainability: Easier to update and maintain without JavaScript knowledge
  4. Security: Avoids potential XSS vulnerabilities from raw HTML injection
  5. Type Safety: Leverages the existing component validation system
  6. Localization: Automatic support for multi-language text content
  7. Conditional Rendering: Built-in support for conditional display logic

Additional Custom Rendering Hooks

Custom Day Header Rendering

component: calendar
props:
calendarId: 3001
options:
dayHeaderContent:
component: layout
props:
type: "div"
options:
className: "custom-day-header"
children:
- component: text
props:
type: "div"
value: "{{ date.format('ddd') }}"
options:
className: "day-name"
- component: text
props:
type: "div"
value: "{{ date.format('DD') }}"
options:
className: "day-number"
- component: badge
if: "{{ eval date.format('E') === '1' }}"
props:
text: "Week Start"
variant: "info"
size: "sm"

Custom Day Cell Rendering

component: calendar
props:
calendarId: 3002
options:
dayCellContent:
component: layout
props:
type: "div"
options:
className: "custom-day-cell {{ eval date.format('E') === '6' || date.format('E') === '7' ? 'weekend' : 'weekday' }}"
children:
- component: text
props:
type: "div"
value: "{{ date.format('D') }}"
options:
className: "day-number"
- component: layout
if: "{{ eval date.isSame(moment(), 'day') }}"
props:
type: "div"
options:
className: "today-indicator"
children:
- component: text
props:
type: "span"
value: "Today"
options:
className: "today-text"
component: calendar
props:
calendarId: 3003
options:
moreLinkContent:
component: button
props:
text: "+ {{ num }} more events"
variant: "link"
size: "sm"
options:
className: "more-events-link"

Standard Events and Handlers

Event Handler Parameters

All event handlers receive detailed information about the calendar interaction:

  • onDateClick: { date, dateStr, allDay, dayEl, jsEvent, view }
  • onEventClick: { event, el, jsEvent, view }
  • onSelect: { start, end, startStr, endStr, allDay, jsEvent, view }
  • onEventDrop: { event, delta, revert, jsEvent, view }
  • onEventResize: { event, startDelta, endDelta, revert, jsEvent, view }

Common Event Handler Examples

# Date Click Handler - Log and set variables
onDateClick:
- consoleLog:
message: "Date clicked: {{ event.dateStr }}"
- setVariables:
selectedDate: "{{ event.dateStr }}"
selectedAllDay: "{{ event.allDay }}"

# Event Click Handler - Navigate to order details
onEventClick:
- setActionsVariables:
orderId: "{{ event.event.extendedProps.orderId }}"
- navigate:
to: "/orders/{{ orderId }}"

# Date Selection Handler - Open creation modal
onSelect:
- setVariables:
newEventStart: "{{ event.startStr }}"
newEventEnd: "{{ event.endStr }}"
isAllDay: "{{ event.allDay }}"
- dialog:
name: "createEventModal"
props:
title: "Create New Event"
startDate: "{{ newEventStart }}"
endDate: "{{ newEventEnd }}"
allDay: "{{ isAllDay }}"

# Event Drop Handler - Update schedule in database
onEventDrop:
- setActionsVariables:
orderId: "{{ event.event.extendedProps.orderId }}"
newStart: "{{ event.event.startStr }}"
newEnd: "{{ event.event.endStr }}"
- mutation:
command: "mutation UpdateOrderSchedule($id: ID!, $start: String!, $end: String!) { updateOrderSchedule(id: $id, scheduledStart: $start, scheduledEnd: $end) { id scheduledStart scheduledEnd } }"
variables:
id: "{{ orderId }}"
start: "{{ newStart }}"
end: "{{ newEnd }}"
onSuccess:
- notification:
message: "Schedule updated successfully"
- refresh: "calendar"
onError:
- notification:
message: "Failed to update schedule"
variant: "error"
- refresh: "calendar"

# Loading State Handler - Show/hide loading indicator
onLoading:
- if: "{{ event.isLoading }}"
then:
- setVariables:
isCalendarLoading: true
else:
- setVariables:
isCalendarLoading: false

Best Practices

  1. Performance Optimization:

    • Use lazyFetching: true for large datasets
    • Implement server-side pagination for events
    • Set appropriate dayMaxEvents to avoid overcrowding
  2. User Experience:

    • Provide clear visual feedback for different event types using colors
    • Use meaningful event titles and descriptions
    • Implement proper loading states
  3. Data Management:

    • Use calendarId consistently across related components
    • Implement proper error handling for event sources
    • Cache frequently accessed calendar data
  4. Accessibility:

    • Ensure keyboard navigation works properly
    • Provide alt text for custom event content
    • Use sufficient color contrast for events
  5. Mobile Responsiveness:

    • Test calendar behavior on mobile devices
    • Consider using different views for mobile (e.g., listWeek)
    • Ensure touch interactions work properly
  6. Localization:

    • Set appropriate locale and timeZone based on user preferences
    • Localize button text and date formats
    • Consider different calendar systems for international users

Integration with CargoXplorer TMS

Event Loading Strategies

The calendar component supports multiple approaches for loading events:

Events are automatically loaded from the backend using the calendarId parameter:

component: calendar
props:
calendarId: 5001
# Events are automatically fetched based on calendar ID

Benefits:

  • Centralized Management: Events managed in the backend calendar system
  • Real-time Updates: Automatic synchronization with backend changes
  • Filtering: Server-side filtering based on view and date range
  • Caching: Optimal performance through intelligent caching
  • Business Hours: Automatically loaded from calendar configuration

2. Static Event Configuration

Define events directly in the component configuration:

component: calendar
props:
calendarId: 5002
options:
events:
- title: "Meeting"
start: "2024-01-15T10:00:00"
# ... event properties

Use Cases:

  • Development/Testing: Quick prototyping and testing
  • Static Schedules: Fixed recurring events that don't change
  • Demo Purposes: Sample data for demonstrations

3. Multiple Event Sources with Queries

Combine events from various sources using GraphQL queries (see Variables for query syntax):

component: calendar
props:
calendarId: 5003
options:
eventSources:
- query: # Shipment events query
command: "query GetShipmentEvents($organizationId: ID!, $start: String!, $end: String!) { shipmentEvents(organizationId: $organizationId, start: $start, end: $end) { id title start end color extendedProps } }"
variables:
organizationId: "{{ organizationId }}"
start: "{{ currentViewStart }}"
end: "{{ currentViewEnd }}"
color: "#3788d8"
textColor: "white"
- query: # Warehouse events query
command: "query GetWarehouseEvents($warehouseId: ID!, $dateRange: DateRangeInput!) { warehouseEvents(warehouseId: $warehouseId, dateRange: $dateRange) { id title start end extendedProps } }"
variables:
warehouseId: "{{ number warehouseId }}"
dateRange:
start: "{{ currentViewStart }}"
end: "{{ currentViewEnd }}"
color: "#ffa726"
textColor: "white"
- events: "{{ staticEvents }}" # Variable data
color: "#e53e3e"
- events: [] # Inline events

Query Features:

  • Variable Interpolation: Use {{ variable }} syntax from Variables documentation
  • Type Casting: Use {{ number value }} for integer parameters
  • Date Formatting: Use {{ format date 'YYYY-MM-DD' }} for date parameters
  • Dynamic Variables: Calendar automatically provides currentViewStart and currentViewEnd

Use Cases:

  • Data Integration: Combining data from multiple GraphQL endpoints
  • Mixed Sources: Query data + static events + variable data
  • Conditional Loading: Different queries based on user permissions or selections
  • Real-time Data: GraphQL subscriptions for live event updates

4. Dynamic Event Loading

Load events from variables or computed data:

component: calendar
props:
calendarId: 5004
options:
events: "{{ userSchedule.events }}"
# or
eventSources:
- events: "{{ eval filterEventsByRole(allEvents, user.role) }}"
color: "#3788d8"
- events: "{{ personalTasks }}"
color: "#ffa726"

Use Cases:

  • Role-based Filtering: Different events based on user permissions
  • Computed Events: Events calculated from other data
  • Variable Data: Events stored in application variables
  • Conditional Loading: Events based on user selections or filters

Event Persistence and Updates

CalendarId-based Events (Backend Managed)

  • Persistence: Events are stored in the backend calendar system
  • Updates: Changes via drag/drop, resize, or actions are automatically saved
  • Real-time: Multiple users see updates immediately
  • Validation: Server-side validation and business rules apply

Static/Manual Events (Component Managed)

  • Persistence: Events exist only in the component configuration
  • Updates: Changes are local to the current session
  • Refresh: Events reset to original configuration on page reload
  • Use Case: Temporary events, demos, or read-only displays

Hybrid Approach

component: calendar
props:
calendarId: 6001 # Loads persistent events
options:
eventSources:
- events: "{{ temporaryEvents }}" # Session-based events
editable: false # Read-only overlay events
color: "#cccccc"
display: "background" # Background events

Automatic Data Loading

The calendar component automatically loads all calendar-related data from the backend using the calendarId parameter. The system handles:

  • Event Fetching: Events are automatically retrieved based on the calendar ID
  • Business Hours: Business hours are loaded from the calendar configuration
  • Calendar Settings: Time zones, working days, and display preferences are loaded automatically
  • Real-time Updates: Changes to calendar events and settings are reflected in real-time
  • Filtering: Events are filtered based on the current view and date range
  • Caching: Frequently accessed calendar data is cached for optimal performance

Calendar ID Guidelines

Important: Calendar IDs must always be integers in CargoXplorer TMS:

# Correct - Integer calendar IDs
calendarId: 1001 # Direct integer
calendarId: "{{ number calendarId }}" # Variable with type casting

# Incorrect - String calendar IDs
calendarId: "shipment-calendar" # ❌ String not allowed
calendarId: "{{ calendarId }}" # ❌ Without number casting

Recommended ID Patterns:

  • 1000-1999: Organization-level calendars
  • 2000-2999: Department-specific calendars
  • 3000-3999: User-specific calendars
  • 4000-4999: Vehicle/equipment calendars
  • 5000+: Custom application calendars

Event Object Structure

All calendar events follow a standardized structure regardless of loading method:

# Basic Event Structure
- id: "unique-event-id" # Unique identifier
title: "Event Title" # Display title
start: "2024-01-15T09:00:00" # Start date/time (ISO format)
end: "2024-01-15T10:00:00" # End date/time (optional)
allDay: false # All-day event flag
color: "#ff6b6b" # Event background color
textColor: "#ffffff" # Text color
borderColor: "#ff6b6b" # Border color
classNames: ["custom-class"] # CSS classes
display: "auto" # Display mode: auto, block, list-item, background

# Extended Properties (TMS-specific data)
extendedProps:
type: "pickup" # Event type
orderId: "ORD-12345" # Related order ID
customer: "ABC Corporation" # Customer name
location: "123 Main St, New York" # Location
driver: "John Smith" # Assigned driver
vehicleId: "TRUCK-001" # Vehicle identifier
status: "scheduled" # Current status
priority: "high" # Priority level
commodities: 5 # Number of items
weight: "2500kg" # Total weight
notes: "Special handling required" # Additional notes

# Recurring Events (optional)
rrule: "FREQ=WEEKLY;BYDAY=MO" # Recurrence rule
duration: "01:00:00" # Duration for recurring events

Event Types for TMS Operations

  • Pickups: Origin collection events
    • Color: #ff6b6b (Red variants)
    • Extended props: orderId, customer, pickupLocation, driver
  • Deliveries: Destination delivery events
    • Color: #4ecdc4 (Teal variants)
    • Extended props: orderId, customer, deliveryLocation, driver
  • Transit: In-transit milestones
    • Color: #3788d8 (Blue variants)
    • Extended props: orderId, checkpoint, vehicleId, eta
  • Warehouse: Storage and handling operations
    • Color: #ffa726 (Orange variants)
    • Extended props: warehouseId, operation, commodities, zone
  • Maintenance: Vehicle and equipment servicing
    • Color: #e53e3e (Dark red variants)
    • Extended props: vehicleId, serviceType, mechanicId, location
  • Customs: Clearance and inspection events
    • Color: #9c27b0 (Purple variants)
    • Extended props: orderId, customsOffice, documentType, inspector