Dieses Tutorial erklärt, wie Sie dhtmlxGantt in eine Salesforce Lightning Web Component integrieren.
Wenn Sie mit einer anderen Technologie arbeiten, finden Sie unten weitere Integrationsmöglichkeiten:
Der Prozess beinhaltet die Verwendung der Salesforce CLI, um eine Lightning Web Component zu erstellen und in eine Salesforce-Organisation zu deployen. Für eine reibungslosere Entwicklungserfahrung empfiehlt sich die Installation des Salesforce Extension Pack in Visual Studio Code.
Der vollständige Quellcode ist auf GitHub verfügbar.
Es gibt außerdem ein Video-Tutorial, das zeigt, wie Sie ein Gantt-Diagramm mit Salesforce LWC erstellen.
Stellen Sie sicher, dass die Salesforce CLI installiert ist, falls dies noch nicht geschehen ist. Eine Anleitung zur Installation finden Sie in diesem Leitfaden.
Falls Sie noch keinen Account haben, erstellen Sie ein kostenloses Entwicklerkonto durch Registrierung. Hilfe dazu finden Sie in diesem Leitfaden.
Suchen Sie in Salesforce über die Suchleiste links nach Dev Hub und wählen Sie diesen aus:
Aktivieren Sie auf der sich öffnenden Einstellungsseite die Dev Hub-Funktion:
Erstellen Sie anschließend ein Verzeichnis für Ihr Salesforce DX-Projekt:
$ mkdir ~/salesforce
Generieren Sie mit der CLI ein Salesforce DX-Projekt:
$ cd ~/salesforce
$ sfdx project generate -n gantt-salesforce-app
target dir = C:\Users\User\salesforce
create gantt-salesforce-app\config\project-scratch-def.json
create gantt-salesforce-app\README.md
create gantt-salesforce-app\sfdx-project.json
create gantt-salesforce-app\.husky\pre-commit
create gantt-salesforce-app\.vscode\extensions.json
create gantt-salesforce-app\.vscode\launch.json
create gantt-salesforce-app\.vscode\settings.json
create gantt-salesforce-app\force-app\main\default\lwc\.eslintrc.json
create gantt-salesforce-app\force-app\main\default\aura\.eslintrc.json
create gantt-salesforce-app\scripts\soql\account.soql
create gantt-salesforce-app\scripts\apex\hello.apex
create gantt-salesforce-app\.eslintignore
create gantt-salesforce-app\.forceignore
create gantt-salesforce-app\.gitignore
create gantt-salesforce-app\.prettierignore
create gantt-salesforce-app\.prettierrc
create gantt-salesforce-app\jest.config.js
create gantt-salesforce-app\package.json
Wechseln Sie in den neu erstellten Projektordner:
$ cd gantt-salesforce-app
Verwenden Sie den Web Server Flow, um eine Organisation zu autorisieren:
$ sfdx org login web -d
Successfully authorized ... with org ID ...
Aktualisieren Sie anschließend Ihre Projektkonfigurationsdatei (sfdx-project.json), indem Sie den Parameter "sfdcLoginUrl" auf die "My Domain URL" Ihrer Organisation setzen. Diese URL finden Sie auf der Seite "My Domain" in den Einstellungen. Zum Beispiel:
gantt-salesforce-app/sfdx-project.json
"sfdcLoginUrl" : "https://xbs2-dev-ed.my.salesforce.com"
Erstellen Sie eine Scratch-Org mit folgendem Befehl:
$ sfdx org create scratch -f config/project-scratch-def.json -d
Creating Scratch Org...
RequestId: 2SR5j0000006JhCGAU
(https://xbsoftware2-dev-ed.my.salesforce.com/2SR5j0000006JhCGAU)
OrgId: 00DH40000000s0D
Username: test-tc0telfqhudt@example.com
✓ Prepare Request
✓ Send Request
✓ Wait For Org
✓ Available
✓ Authenticate
✓ Deploy Settings
Done
Your scratch org is ready.
Um die Bibliothek zu verwenden, muss sie als Statische Ressource in Salesforce hochgeladen werden. Öffnen Sie Ihre Scratch-Org:
$ sfdx org open
Navigieren Sie zum Tab "Static Resources" und klicken Sie auf "Neu":
Vergeben Sie einen aussagekräftigen Namen (z.B. "dhtmlxgantt7111"), laden Sie das ZIP-Archiv mit den Bibliotheksdateien (dhtmlxgantt.js und dhtmlxgantt.css) hoch und setzen Sie "Cache Control" auf "Public", um die Performance zu verbessern. Speichern Sie anschließend Ihre Änderungen.
Nun steht die dhtmlxGantt-Bibliothek innerhalb von Salesforce zur Verfügung.
Die wichtigsten Komponenten von dhtmlxGantt sind Tasks und Links. Eine praktikable Methode zur Verwaltung ist es, deren Eigenschaften als JSON in Salesforce zu speichern. Beginnen Sie mit der Erstellung benutzerdefinierter Objekte für Tasks und Links. Gehen Sie dazu in den Object Manager, wählen Sie "Erstellen" und dann "Custom Object":
Benennen Sie das Task-Objekt, zum Beispiel GanttTask oder GanttTasks.
Stellen Sie sicher, dass der Datensatzname dem Objektnamen entspricht, zum Beispiel:
Object Name: GanttTask => Record Name: GanttTask Name
Speichern Sie das neue Objekt.
Öffnen Sie anschließend den Tab "Fields & Relationships" und klicken Sie auf "Neu", um Felder hinzuzufügen:
Wählen Sie als Datentyp "Number" und fahren Sie fort.
Benennen Sie das Feld "Duration". Dieses Feld speichert die als JSON serialisierten Eigenschaften der Aufgabe. Klicken Sie so oft auf "Weiter", bis die Schaltfläche "Speichern & Neu" erscheint.
Übernehmen Sie die Standardeinstellungen, indem Sie auf "Weiter" klicken, bis Sie speichern oder ein neues Feld hinzufügen können.
Erstellen Sie ein Feld "Parent" mit dem Datentyp "Text".
Fahren Sie fort, indem Sie auf "Weiter" klicken, bis die Schaltfläche "Speichern & Neu" verfügbar ist.
Fügen Sie ein Feld "Progress" hinzu und wählen Sie als Datentyp "Number".
Klicken Sie weiterhin auf "Weiter", bis Sie speichern oder ein weiteres Feld hinzufügen können.
Erstellen Sie ein Feld "Start Date" mit dem Datentyp "Date/Time".
Klicken Sie sich durch die Standardeinstellungen, bis Sie die Schaltfläche "Speichern" erreichen.
Am Ende sollten Ihre Objektfelder wie folgt aussehen:
Öffnen Sie zunächst den Objekt-Manager und wählen Sie „Erstellen“ gefolgt von „Benutzerdefiniertes Objekt“:
Benennen Sie das Link-Objekt als GanttLink/GanttLinks.
Stellen Sie sicher, dass der Datensatzname dem Objektnamen entspricht, zum Beispiel:
Objektname: GanttLink => Datensatzname: GanttLink Name
Fahren Sie fort und erstellen Sie die benötigten Felder.
Fügen Sie ein Feld „Source“ hinzu und wählen Sie als Datentyp „Text“.
Klicken Sie jeweils auf „Weiter“ (behalten Sie die Standardeinstellungen bei), bis die Schaltfläche „Speichern & Neu“ erscheint.
Fügen Sie ein Feld „Target“ hinzu, ebenfalls mit dem Datentyp „Text“.
Klicken Sie jeweils auf „Weiter“ (mit den Standardeinstellungen), bis „Speichern & Neu“ verfügbar ist.
Fügen Sie ein Feld „Type“ hinzu, ebenfalls mit dem Datentyp „Text“.
Klicken Sie jeweils auf „Weiter“ (mit den Standardeinstellungen), bis die Schaltfläche „Speichern“ angezeigt wird.
Am Ende sollte es wie folgt aussehen:
Um eine Lightning Web-Komponente zu generieren, führen Sie diesen Befehl aus:
$ sfdx lightning generate component --type lwc -n gantt -d force-app/main/default/lwc
target dir =
C:\Users\User\source\salesforce\gantt-salesforce-app\force-app\main\default\lwc
create force-app\main\default\lwc\gantt\gantt.js
create force-app\main\default\lwc\gantt\gantt.html
create force-app\main\default\lwc\gantt\gantt.js-meta.xml
Aktualisieren Sie die Komponentendefinition in gantt.js-meta.xml, um sie im Lightning App Builder verfügbar zu machen:
force-app/main/default/lwc/gantt/gantt.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__AppPage">
<property name="height" label="Height" type="Integer" default="800" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
Öffnen Sie gantt.html und fügen Sie folgenden Code ein:
force-app/main/default/lwc/gantt/gantt.html
<template>
<div class="thegantt" lwc:dom="manual" style='width: 100%;'></div>
</template>
Fügen Sie in gantt.js diesen Code hinzu:
force-app/main/default/lwc/gantt/gantt.js
/* eslint-disable guard-for-in */
/* eslint-disable no-undef */
import { LightningElement, api } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { loadStyle, loadScript } from "lightning/platformResourceLoader";
import { createRecord, updateRecord, deleteRecord } from "lightning/uiRecordApi";
// Static resources
import GanttFiles from "@salesforce/resourceUrl/dhtmlxgantt7111";
// Controllers
import getTasks from "@salesforce/apex/GanttData.getTasks";
function unwrap(fromSF) {
const data = fromSF.tasks.map((a) => ({
id: a.Id,
text: a.Name,
start_date: a.Start_Date__c,
duration: a.Duration__c,
parent: a.Parent__c,
progress: a.Progress__c,
type: a.Task_Type__c,
}));
const links = fromSF.links.map((a) => ({
id: a.Id,
source: a.Source__c,
target: a.Target__c,
type: a.Type__c
}));
return { data, links};
}
export default class GanttView extends LightningElement {
static delegatesFocus = true;
@api height;
ganttInitialized = false;
renderedCallback() {
if (this.ganttInitialized) {
return;
}
this.ganttInitialized = true;
Promise.all([
loadScript(this, GanttFiles + "/dhtmlxgantt.js"),
loadStyle(this, GanttFiles + "/dhtmlxgantt.css")
])
.then(() => {
this.initializeUI();
})
.catch((error) => {
this.dispatchEvent(
new ShowToastEvent({
title: "Error loading Gantt",
message: error.message,
variant: "error"
})
);
});
}
initializeUI() {
const root = this.template.querySelector(".thegantt");
root.style.height = this.height + "px";
//uncomment the following line if you use the Enterprise or Ultimate version
//const gantt = window.Gantt.getGanttInstance();
gantt.templates.parse_date = (date) => new Date(date);
gantt.templates.format_date = (date) => date.toISOString();
gantt.init(root);
getTasks().then((d) => {
const chartData = unwrap(d);
gantt.parse({
tasks: chartData.data,
links: chartData.links
});
});
///↓↓↓ saving changes back to SF backend ↓↓↓
gantt.createDataProcessor({
task: {
create: (data) => {
console.log("createTask",data);
const insert = {
apiName: "GanttTask__c",
fields: {
Name: data.text,
Start_Date__c: data.start_date,
Duration__c: data.duration,
Parent__c: String(data.parent),
Progress__c: data.progress
}
};
gantt.config.readonly = true; // suppress changes
// until saving is complete
return createRecord(insert).then((res) => {
gantt.config.readonly = false;
return { tid: res.id, ...res };
});
},
update: (data, id) => {
console.log("updateTask",data);
const update = {
fields: {
Id: id,
Name: data.text,
Start_Date__c: data.start_date,
Duration__c: data.duration,
Parent__c: String(data.parent),
Progress__c: data.progress
}
};
return updateRecord(update).then(() => ({}));
},
delete: (id) => {
return deleteRecord(id).then(() => ({}));
}
},
link: {
create: (data) => {
const insert = {
apiName: "GanttLink__c",
fields: {
Source__c: data.source,
Target__c: data.target,
Type__c: data.type
}
};
return createRecord(insert).then((res) => {
return { tid: res.id };
});
},
update: (data, id) => {
const update = {
apiName: "GanttLink__c",
fields: {
Id: id,
Source__c: data.source,
Target__c: data.target,
Type__c: data.type
}
};
return updateRecord(update).then(() => ({}));
},
delete: (id) => {
return deleteRecord(id).then(() => ({}));
}
}
});
}
}
Erstellen Sie als Nächstes eine Klasse, die die Kommunikation zwischen der Lightning-Komponente und dem Datenmodell übernimmt.
$ sfdx apex generate class -n GanttData -d force-app/main/default/classes
target dir =
C:\Users\User\salesforce\gantt-salesforce-app\force-app\main\default\classes
create force-app\main\default\classes\GanttData.cls
create force-app\main\default\classes\GanttData.cls-meta.xml
Öffnen Sie nach dem Erstellen der Klasse GanttData.cls und fügen Sie folgenden Code ein:
force-app/main/default/classes/GanttData.cls
public with sharing class GanttData {
@RemoteAction
@AuraEnabled(cacheable=true)
public static Map<String, Object> getTasks() {
// fetching the Records via SOQL
List<GanttTask__c> Tasks = new List<GanttTask__c>();
Tasks = [SELECT Id, Name, Start_Date__c, Duration__c,
Parent__c FROM GanttTask__c];
List<GanttLink__c> Links = new List<GanttLink__c>();
Links = [SELECT Id, Type__c, Source__c, Target__c FROM GanttLink__c];
Map<String, Object> result = new Map<String, Object>{
'tasks' => Tasks, 'links' => Links };
return result;
}
}
Ziehen Sie den Quellcode aus der Scratch-Org in Ihr Projekt:
$ sfdx project retrieve start
Und deployen Sie die Quellen anschließend zurück in die Scratch-Org:
$ sfdx project deploy start
Starten Sie den „Lightning App Builder“ und erstellen Sie eine neue Lightning-Seite.
Wählen Sie „App Page“ und geben Sie den Namen sowie das Layout der Seite an.
Die benutzerdefinierte Gantt-Komponente sollte nun für die neue Seite verfügbar sein. Fügen Sie sie einem beliebigen Abschnitt hinzu und speichern Sie.
Aktivieren Sie die Seite.
Speichern Sie Ihre Änderungen.
Öffnen Sie die Anwendungsseite. Sie ist über den App-Launcher durch Eingabe von Gantt auffindbar.
Wenn alles korrekt eingerichtet ist, erscheint eine einfache Gantt-Demo auf der Lightning-Seite.
Gantt selbst bietet keinen integrierten Schutz gegen Bedrohungen wie SQL-Injection, XSS oder CSRF-Angriffe. Die Gewährleistung der Anwendungssicherheit liegt in der Verantwortung der Entwickler, die Gantt implementieren. Weitere Details finden Sie im zugehörigen Artikel. Salesforce bietet leistungsstarke Sicherheitsfunktionen zum Schutz Ihrer Daten und Anwendungen. Sie können Ihre Sicherheitsstrategie auch an die Struktur und Anforderungen Ihrer Organisation anpassen. Weitere Hinweise finden Sie im Salesforce Security Guide. Zusätzliche Informationen zur Absicherung von Lightning-Komponenten finden Sie hier.
Wenn Sie alle Schritte durchgeführt haben, aber das Gantt-Diagramm keine Aufgaben und Verknüpfungen auf der Seite anzeigt, lesen Sie den Artikel Fehlerbehebung bei Backend-Integrationsproblemen. Dort finden Sie Methoden zur Diagnose und Behebung häufiger Probleme.
Mit dem vollständig eingerichteten Gantt können Sie den vollständigen Code auf GitHub einsehen, wo er zum Klonen oder Herunterladen für Ihre Projekte bereitsteht.
Außerdem können Sie Anleitungen zu verschiedenen Gantt-Funktionen oder Tutorials zur Integration von Gantt mit anderen Backend-Frameworks erkunden.
Zurück nach oben