В этом руководстве описан процесс интеграции dhtmlxScheduler в SalesForce Lightning Web Component.
Если вы работаете с другой технологией, ознакомьтесь с другими вариантами интеграции, приведёнными ниже:
Мы будем использовать SalesForce CLI для создания Lightning Web Component и его деплоя в вашу организацию. Для информации по установке обратитесь к этой статье. Дополнительно вы можете установить Salesforce Extension Pack для Visual Studio Code, чтобы упростить работу с организациями для разработки.
Полный исходный код доступен на GitHub.
Ниже приведён видеоурок, демонстрирующий создание Scheduler с использованием Salesforce LWC.
Убедитесь, что у вас установлен SalesForce CLI. Если нет — ознакомьтесь с этой статьёй для получения инструкций по установке.
Если у вас ещё нет аккаунта, зарегистрируйтесь для получения бесплатного аккаунта разработчика. Эта статья поможет вам в этом.
Используйте строку поиска слева, чтобы найти и выбрать Dev Hub:
Затем в открывшемся окне настроек включите Dev Hub:
Далее создайте базовую папку для вашего проекта Salesforce DX:
$ mkdir ~/salesforce
Сгенерируйте проект Salesforce DX с помощью CLI:
$ cd ~/salesforce
$ sfdx project generate -n scheduler-salesforce-app
target dir = C:\Users\User\salesforce
create scheduler-salesforce-app\config\project-scratch-def.json
create scheduler-salesforce-app\README.md
create scheduler-salesforce-app\sfdx-project.json
create scheduler-salesforce-app\.husky\pre-commit
create scheduler-salesforce-app\.vscode\extensions.json
create scheduler-salesforce-app\.vscode\launch.json
create scheduler-salesforce-app\.vscode\settings.json
create scheduler-salesforce-app\force-app\main\default\lwc\.eslintrc.json
create scheduler-salesforce-app\force-app\main\default\aura\.eslintrc.json
create scheduler-salesforce-app\scripts\soql\account.soql
create scheduler-salesforce-app\scripts\apex\hello.apex
create scheduler-salesforce-app\.eslintignore
create scheduler-salesforce-app\.forceignore
create scheduler-salesforce-app\.gitignore
create scheduler-salesforce-app\.prettierignore
create scheduler-salesforce-app\.prettierrc
create scheduler-salesforce-app\jest.config.js
create scheduler-salesforce-app\package.json
Перейдите в папку с новым проектом:
$ cd scheduler-salesforce-app
Авторизуйте свою организацию с помощью Web Server Flow, выполнив команду:
$ sfdx org login web -d
Successfully authorized ...@...com with org ID ...
Далее обновите файл конфигурации проекта (sfdx-project.json), установив параметр "sfdcLoginUrl" в значение вашего "My Domain URL". Найти этот URL можно на странице настроек "My Domain" вашей организации. Например:
scheduler-salesforce-app/sfdx-project.json
"sfdcLoginUrl" : "https://xbs2-dev-ed.my.salesforce.com"
Создайте Scratch Org с помощью следующей команды:
$ sfdx org create scratch -f config/project-scratch-def.json -d
Creating Scratch Org...
RequestId: 2SR8a000000PLf5GAG (https://xbs2-dev-ed.my.salesforce.com/2SR8a000000PLf5GAG)
OrgId: 00D8G000000EEMs
Username: test-3baxo2k0tpej@example.com
✓ Prepare Request
✓ Send Request
✓ Wait For Org
✓ Available
✓ Authenticate
✓ Deploy Settings
Done
Your scratch org is ready.
Чтобы использовать библиотеку, загрузите её в Salesforce как Static Resource. Откройте ваш scratch org, выполнив:
$ sfdx org open
Затем перейдите на вкладку "Static Resources" и нажмите кнопку "New":
Дайте ресурсу понятное имя (например, dhtmlxscheduler), загрузите ZIP-архив с файлами библиотеки (dhtmlxscheduler.js и dhtmlxscheduler.css) и установите Cache Control в "Public" для повышения производительности. Нажмите "Save".
Теперь dhtmlxScheduler доступен внутри Salesforce.
События — основные сущности в dhtmlxScheduler. Практичный способ их хранения — сохранять все их свойства в виде обычного JSON внутри Salesforce. Для этого создайте новый объект Event. Откройте Object Manager, затем выберите "Create" и далее "Custom Object":
Назовите объект события SchedulerEvent или SchedulerEvents.
Убедитесь, что имя записи совпадает с именем объекта, например:
Имя объекта: SchedulerEvent => Имя записи: SchedulerEvent Name
Нажмите кнопку “Сохранить”.
После создания объекта перейдите на вкладку "Fields & Relationships" и нажмите кнопку "New".
Выберите "Date/Time" в качестве типа данных и нажмите "Next".
Назовите это поле "Start Date". Это поле будет хранить JSON-сериализованные свойства задачи.
Нажмите "Next" и принимайте все настройки по умолчанию до появления кнопки "Save & New".
Добавьте поле "End Date", выбрав "Date/Time" как тип данных.
Нажмите "Next" и принимайте настройки по умолчанию до появления кнопки "Save & New".
Создайте поле "Text" и выберите "Text" как тип данных.
Нажмите "Next" и принимайте все настройки по умолчанию до появления кнопки "Save".
В результате поля должны выглядеть следующим образом:
Чтобы создать Lightning Web Component, используйте следующую команду:
$ sfdx lightning generate component --type lwc -n scheduler -d force-app/main/default/lwc
target dir = C:\Users\User\source\salesforce\scheduler-salesforce-app\force-app\main\default\lwc
create force-app\main\default\lwc\scheduler\scheduler.js
create force-app\main\default\lwc\scheduler\scheduler.html
create force-app\main\default\lwc\scheduler\__tests__\scheduler.test.js
create force-app\main\default\lwc\scheduler\scheduler.js-meta.xml
Измените определение компонента в scheduler.js-meta.xml, чтобы сделать его доступным в Lightning App Builder:
force-app/main/default/lwc/scheduler/scheduler.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>57.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>
Откройте scheduler.html и вставьте следующий код:
force-app/main/default/lwc/scheduler/scheduler.html
<template>
<div class="thescheduler" lwc:dom="manual" style='width: 100%;'></div>
</template>
Далее откройте scheduler.js и добавьте следующий код:
force-app/main/default/lwc/scheduler/scheduler.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 SchedulerFiles from "@salesforce/resourceUrl/dhtmlxscheduler";
// Controllers
import getEvents from "@salesforce/apex/SchedulerData.getEvents";
function unwrap(fromSF) {
const data = fromSF.events.map((a) => ({
id: a.Id,
info: a.Name,
start_date: a.Start_Date__c,
end_date: a.End_Date__c,
text: a.Text__c,
}));
return { data };
}
export default class SchedulerView extends LightningElement {
static delegatesFocus = true;
@api height;
schedulerInitialized = false;
renderedCallback() {
if (this.schedulerInitialized) {
return;
}
this.schedulerInitialized = true;
Promise.all([
loadScript(this, SchedulerFiles + "/dhtmlxscheduler.js"),
loadStyle(this, SchedulerFiles + "/dhtmlxscheduler.css")
])
.then(() => {
this.initializeUI();
})
.catch((error) => {
this.dispatchEvent(
new ShowToastEvent({
title: "Error loading scheduler",
message: error.message,
variant: "error"
})
);
});
}
initializeUI() {
const root = this.template.querySelector(".thescheduler");
root.style.height = this.height + "px";
const scheduler = window.Scheduler.getSchedulerInstance();
scheduler.templates.parse_date = (date) => new Date(date);
scheduler.templates.format_date = (date) => date.toISOString();
scheduler.config.header = [
"day",
"week",
"month",
"date",
"prev",
"today",
"next"
];
scheduler.init(root, new Date(), "week");
getEvents().then((d) => {
const chartData = unwrap(d);
scheduler.parse({
events: chartData.data,
});
});
///↓↓↓ saving changes back to SF backend ↓↓↓
scheduler.createDataProcessor(function (entity, action, data, id) {
switch (action) {
case "create":
console.log("createEvent", data);
const insert = {
apiName: "SchedulerEvent__c",
fields: {
Name: data.info,
Start_Date__c: data.start_date,
End_Date__c: data.end_date,
Text__c: data.text
}
};
scheduler.config.readonly = true; // suppress changes
//until saving is complete
return createRecord(insert).then((res) => {
scheduler.config.readonly = false;
return { tid: res.id, ...res };
});
case "update":
console.log("updateEvent", data);
const update = {
fields: {
Id: id,
Name: data.info,
Start_Date__c: data.start_date,
End_Date__c: data.end_date,
Text__c: data.text
}
};
return updateRecord(update).then(() => ({}));
case "delete":
return deleteRecord(id).then(() => ({}));
}
});
}
}
Следующий шаг — создать класс, который позволит взаимодействовать между Lightning Component и моделью данных.
$ sfdx apex generate class -n SchedulerData -d force-app/main/default/classes
target dir = C:\Users\User\salesforce\scheduler-salesforce-app\force-app\main\default\classes
create force-app\main\default\classes\SchedulerData.cls
create force-app\main\default\classes\SchedulerData.cls-meta.xml
После создания откройте SchedulerData.cls и добавьте следующий код:
force-app/main/default/classes/SchedulerData.cls
public with sharing class SchedulerData {
@RemoteAction
@AuraEnabled(cacheable=true)
public static Map<String, Object> getEvents() {
// fetching the Records via SOQL
List<SchedulerEvent__c> Events = new List<SchedulerEvent__c>();
Events = [SELECT Id, Name, Start_Date__c, End_Date__c,
Text__c FROM SchedulerEvent__c];
Map<String, Object> result = new Map<String, Object>{'events' => Events };
return result;
}
}
Получите исходный код из Scratch Org в ваш проект:
$ sfdx project retrieve start
Затем отправьте исходный код обратно в Scratch Org:
$ sfdx project deploy start
Откройте "Lightning App Builder" и создайте новую Lightning Page.
Выберите "App Page", затем введите имя страницы и выберите макет.
Пользовательский компонент Scheduler должен быть доступен для новой страницы. Добавьте его в любую область и сохраните.
Активируйте страницу.
Сохраните изменения.
Откройте страницу приложения. Она должна быть доступна в лаунчере приложений по запросу Scheduler.
Если всё настроено правильно, на Lightning Page отобразится простая демонстрация Scheduler.
Scheduler сам по себе не содержит встроенной защиты от угроз, таких как SQL-инъекции, XSS или CSRF-атаки. Обеспечение безопасности приложения лежит на разработчиках. Подробнее см. в соответствующей статье. Salesforce спроектирован с учетом безопасности для защиты ваших данных и приложений, и вы можете реализовать собственные меры безопасности, подходящие вашей организации. Дополнительную информацию смотрите в Salesforce Security Guide. Кроме того, этот ресурс содержит важные рекомендации по безопасности.
Если Scheduler не отображает события после завершения интеграции, обратитесь к статье Troubleshooting Backend Integration Issues. В ней содержатся рекомендации по выявлению и устранению распространённых проблем.
На этом этапе Scheduler полностью работоспособен. Полный исходный код доступен на GitHub для клонирования или загрузки для использования в ваших проектах.
Вы также можете ознакомиться с руководствами по возможностям Scheduler или с учебными материалами по интеграции Scheduler с другими backend-фреймворками.
Наверх