Взаимодействие компонента Gant с бэкенд-сервисами
Компонент Gant поддерживает следующие способы взаимодействия с бэкенд-сервисами:
- REST API;
- веб-сокеты.
REST API
По умолчанию используется взаимодействие через REST API.
В свойстве endpointData
, вложенном в свойство GraphSettings
, должен быть описан метод fetch
по следующему образцу:
const fetch = async ({ requestType, params }) => {
return sendDataSet(requestType, params, { showWaitingContainer: false });
};
requestType
описывает тип запроса и принимает значения, описанные в следующей таблице.
Контракты взаимодействия с бэкенд-сервисами
Тип запроса | Выполняемое действие |
---|---|
getCount(): number | Возвращает количество работ |
getIds(skip: number, take: number): INodeIdWithVersion[] | Возвращает массив работ в диапазоне строк с идентификаторами и версиями |
getData(nodes: INodeIdWithVersion[], columns: ColumnId[]): IDataResult[] | Возвращает значения в указанных столбцах по указанным работам |
getFilterState(nodes: INodeIdWithVersion[], filters: Filters): IFilterState[] | Возвращает признак того, удовлетворяет ли работа параметрам фильтра |
getGraph(nodes: INodeIdWithVersion[]): IDataResult[] | Возвращает полосы диаграммы Ганта |
getRelations(nodes: INodeIdWithVersion[]): IRelationsResult[] | Возвращает стрелки диаграммы Ганта |
getMetrics(nodes: INodeIdWithVersion[], columns: ColumnId[], scale: CalendarScale, from: string, to: string): IDataResult[] | Возвращает значения в календарной сетке, сгруппированные по датам |
getRowsUpdateSince(skip: number, take: number, since: number): GetRowsUpdateSinceResult | Возвращает список работ (с идентификаторами и версиями), изм енившихся с определенного момента |
Данные для компонента Gant могут иметь объем в сотни тысяч записей в базе данных. При использовании взаимодействия с бэкенд-ервисами через REST API объем передаваемых данных ограничен. Для преодоления этого ограничения данные компоненту передаются частями размером chunkSize
и отправляются на сервер в количестве не более requestsLimit
запросов одновременно.
Следующий фрагмент кода демонстрирует свойства компонента для управления передачей данных при взаимодействии через REST API с бэкенд-сервисами. В примере показаны значения по умолчанию.
chunkSize: 10000,
requestsLimit: 2,
Следующий фрагмент кода экранной формы демонстрирует взаимодействие через REST API:
<Container
Name="GantRest"
ContainerType="Page"
Scripts={[
async () => {
const viewModel = await sendDataSet('getViewModel');
const { mainGridId, tables, filterOperations } = viewModel.model;
const fetch = async ({ requestType, params }) => {
return sendDataSet(requestType, params, { showWaitingContainer: false });
};
const settings = {};
settings.groupingVisible = true;
settings.headers = tables[mainGridId].columns;
// максимально возможная глубина вложенности, приходит с бэкенда.
// чем она меньше - тем выше контрастность между цветами уровней
// однако можно задать индивидуальные цвета для каждого уровня
// с помощью свойств getLevelBGColor и getLevelTextColor.
// наличие этого свойства также важно для правильного выделения цветом кликнутой строки
settings.maxDeepLevel = tables[mainGridId].maxDeepLevel + 1;
settings.endpointData = { fetch };
// во viewModel должны прийти поддерживаемые бэкендом операции фильтрации,
// но можно просто передать {}, тогда будут использоваться дефолтные
// более подробное описание в контракте
settings.filterOperations = filterOperations;
// поиск пока реализован только по строковым колонкам
settings.searchEnabled = true;
// отображение контрола разворота узлов до определенного уровня
settings.wbsEnabled = true;
const graphSettings = {};
graphSettings[mainGridId] = settings;
const pallete = {};
// ширина смещения уровня в пикселях
pallete.stripeWidth = 15;
// задание индивидуальных цветов уровням
// pallete.getLevelBGColor = (level, maxLevel) => {
// const levels = {
// 0: '#BBBBBB',
// 4: 'red',
// 20: 'rgba(1, 1, 1, 0.5)',
// };
// return levels[level];
// };
// pallete.getLevelTextColor = (level, maxLevel) => level > maxLevel / 2 ? 'red' : 'black';
setState({ mainGridId, graphSettings, pallete });
},
]}
>
<Gant
Visible-var="mainGridId"
Pallete-var="pallete"
MainGridId-var="mainGridId"
GraphSettings-var="graphSettings"
/>
</Container>;
Веб-сокеты
Для переключения на взаимодействие через веб-сокеты, в свойство endpointData
, вложенное в свойство GraphSettings
, должен быть передан параметр networkServiceType: 'socket'
.
В свойстве endpointData
, вложенном в свойство GraphSettings
, должен быть описан метод stream
по следующему образцу:
const stream = p => {
return {
stream: connection.stream(p.requestType, p?.params || {}),
postProcess: data => data,
};
};
requestType
описывает тип запроса и принимает значения, описанные в следующей таблице.
Контракты взаимодействия с бэкенд-сервисами
Тип запроса | Выполняемое действие |
---|---|
getData(nodes: Nullable<INodeIdWithVersion[]>, columns: ColumnId[], useZip?: boolean, since?: number): SocketDataResult | Возвращает значения в указанных столбцах по указанным работам |
getFilterState(nodes: Nullable<INodeIdWithVersion[]>, filters: Filters): IFilterState[] | Возвращает признак того, удовлетворяет ли работа параметрам фильтра |
Взаимодействие с бэкенд-сервисами через веб-сокеты происходит быстрее, чем через REST API.
При использовании взаимодействия через веб-сокеты можно включить кэширование данных на клиентской стороне. Для включения кэширования используется свойство cache
, вложенное в GraphSettings
. Данные сохраняются в хранилище данных внутри браузера — IndexedDB. При обновлении версии компонента Gant содержимое кэша сбрасывается.
Поскольку взаимодействие через веб-сокеты является ненадежным, для контроля целостности данных компо нент Gant периодически запрашивает через REST API все работы, которые изменились с момента последнего обновления кэша. С этой целью компонент Gant отправляет запрос getRowsUpdateSince
(см. описание в разделе выше). В связи с большим объемом данных, например, вследствие массового импорта данных из внешней системы, данные отправляются клиенту постранично. Для управления разбивкой на страницы используются параметры skip
и take
запроса getRowsUpdateSince
. Метод возвращает работы, у которых значение параметра since
больше переданного значения, и количество таких работ.
Параметр since
представляет собой версию моментального снимка базы данных источника данных. Следующая таблица демонстрирует отличие версии работы от версии моментального снимка базы данных источника данных.
Идентификатор работы | Версия работы | Версия моментального снимка БД | Комментарий |
---|---|---|---|
1 | 1 | 1 | Работы 1, 2, 3 и 4 появились в БД при генерации данных. Начальные значения версии для этих работ — 1 и значение моментального снимка БД — 1. |
2 | 2 | 2 | Пользователь изменил работу 2, в результате чего работа 2 получила версию 2, версия моментального снимка БД приняла значение 2. |
3 | 2 | 3 | Далее в одной транзакции пользователь изменил работы 3 и 4. Обе работы получили версию 2. |
4 | 2 | 3 | Версия моментального снимка БД приняла значение 3. |
5 | 1 | 4 | Далее в следующей транзакции пользователь создал работу 5. Версия работы 5 — 1, версия моментального снимка БД приняла значение 4. |
Следующий фрагмент кода демонстрирует настройку параметров для использования метода getRowsUpdateSince
с периодичностью timeoutUpdateSince
.
timeoutUpdateSince: 60000, // частота отправки запроса данных в миллисекундах
checkMissedNotificationsEnabled: true, // при установке в true этого параметра используется тип запроса getRowsUpdateSince
Фрагмент кода экранной формы с использованием взаимодействия через веб-сокеты показан в следующем примере:
<Container
Name="GantSocket"
ContainerType="Page"
Scripts={[
async () => {
const viewModel = await sendDataSet('getViewModel');
const { mainGridId, tables } = viewModel.model;
const connection = createConnection({
hubUrl: '',
eventName: '',
});
const stream = p => {
return {
stream: connection.stream(p.requestType, p?.params || {}),
postProcess: data => data,
};
};
const settings = {};
settings.headers = tables[mainGridId].columns;
settings.maxDeepLevel = tables[mainGridId].maxDeepLevel + 1;
settings.endpointData = {};
settings.endpointData.stream = stream;
settings.endpointData.onEditTransactionUpdate = () => {};
settings.endpointData.networkServiceType = 'socket';
settings.filterOperations = {};
settings.wbsEnabled = true;
const graphSettings = {};
graphSettings[mainGridId] = settings;
setState({ mainGridId, graphSettings });
},
]}
>
<Gant
Visible-var="mainGridId"
Pallete={{}}
MainGridId-var="mainGridId"
GraphSettings-var="graphSettings"
/>
</Container>;