Advanced features

The following features provide additional functionality for Workshop's Dynamic Scheduling capability.

Custom save action

The Scheduling Gantt Chart widget is backed by Scenarios, enabling the creation and comparison of what-if analyses. Changes made in the widget are therefore not directly written to the Ontology; instead, they are, effectively, "staged" or "simulated" changes. A schedule save action is needed to write the changes to the Ontology.

To write proposed changes to the Ontology, a simple modify action (which can be configured via the OMA Wizard) is usually sufficient. If further edits are required after updating the Ontology, you can use a custom save action, backed by a Function.

Sample code snippets for types and example functions are provided below.

Types

The types below represent the serialized details of a schedule change, which includes information about both the old and new state of the given allocation.

 
/* Changelog types */

type ChangelogEntryType = "allocation";

interface IChangelogEntryBase {
    type: ChangelogEntryType;
    id: string;
    touchCounter: number;
    parentEntryId?: string;
}

interface IAllocationChangelogEntry extends IChangelogEntryBase {
    type: "allocation";
    puckId: string;
    allocatedTo: string | undefined;
    allocatedFrom: string | undefined;
    newStartTime: number | undefined;
    newEndTime: number | undefined;
    previousStartTime: number | undefined;
    previousEndTime: number | undefined;
    id: string;
    touchCounter: number;
    parentEntryId?: string;
}

export interface IEnhancedChangelog extends IAllocationChangelogEntry {
    fixedResourceObjectTypeId: string;
    puckId: string;
}

export interface ISubmitAllocationPayload {
    changelog: IEnhancedChangelog[];
    comment?: string;
}


Example function

import { IEnhancedChangelog, ISubmitAllocationPayload } from "./types";

export class MyFunctions {
    
     
    @Edits(scheduleObjectAPI)
    @OntologyEditFunction()
    public functionName(submissionPayload: string): void {
       const payload: ISubmitAllocationPayload = JSON.parse(serializedInput) as ISubmitAllocationPayload;
        const entries: IEnhancedChangelog[] = payload.changelog;
        const allocations = Objects.search().objectAPI().all();
        entries.forEach(entry => {
            const maybeAllocation = allocations.find(alloc => alloc.assignmentId === entry.puckId);
            if (maybeAllocation == null) {
                return;
            }
            maybeAllocation.endTimestamp = entry.newEndTime !== undefined ? Timestamp.fromJsDate(new Date(entry.newEndTime)) : undefined;
            maybeAllocation.startTimestamp = entry.newStartTime !== undefined ? Timestamp.fromJsDate(new Date(entry.newStartTime)) : undefined;
            if (entry.fixedResourceObjectTypeId === objectId) {
                maybeAllocation.fixedResourceKey = entry.allocatedTo
            } else {
                maybeAllocation.schedulableKey = entry.allocatedTo
            }
        });
    }

Custom allocation behavior

Allocation behavior refers to how pucks behave after they have been moved in the drag-and-drop interface. The Scheduling Gantt Chart widget comes with five predefined options intended to cover the majority of use cases. You can also define your own custom allocation behavior using a TypeScript function, as shown in the example below.

 
/* Changelog types */
/* Note: these are types also used for Custom Save Actions and may already be in 
   your functions repo. */


type ChangelogEntryType = "allocation";

interface IChangelogEntryBase {
    type: ChangelogEntryType;
    id: string;
    touchCounter: number;
    parentEntryId?: string;
}

interface IAllocationChangelogEntry extends IChangelogEntryBase {
    type: "allocation";
    puckId: string;
    allocatedTo: string | undefined;
    allocatedFrom: string | undefined;
    newStartTime: number | undefined;
    newEndTime: number | undefined;
    previousStartTime: number | undefined;
    previousEndTime: number | undefined;
    id: string;
    touchCounter: number;
    parentEntryId?: string;
}