@eclipse-scout/core
Version:
Eclipse Scout runtime
295 lines (256 loc) • 11.1 kB
text/typescript
/*
* Copyright (c) 2010, 2025 BSI Business Systems Integration AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
import {
arrays, BaseDoEntity, BookmarkDo, BookmarkDoBuilderModel, BookmarkSupport, BookmarkTableRowIdentifierDo, ChartTableControlConfigHelper, Desktop, Form, IBookmarkDefinitionDo, IBookmarkDo, IBookmarkPageDo, IChartTableControlConfigDo,
InitModelOf, NodeBookmarkPageDo, objects, ObjectWithType, OutlineBookmarkDefinitionDo, Page, PageBookmarkDefinitionDo, PageWithTable, scout, Session, strings, TableBookmarkPageDo, TableClientUiPreferencesDo, TableUiPreferences,
tableUiPreferences
} from '../index';
export class BookmarkDoBuilder implements ObjectWithType, BookmarkDoBuilderModel {
declare model: BookmarkDoBuilderModel;
static ERROR_MISSING_OUTLINE = 'missing-outline';
static ERROR_MISSING_PAGE_PARAM = 'missing-page-param';
static ERROR_UNSUPPORTED_NODE_TYPE = 'unsupported-node-type';
static ERROR_PAGE_NOT_BOOKMARKABLE = 'page-not-bookmarkable';
static ERROR_PAGE_PATH_NOT_BOOKMARKABLE = 'page-path-not-bookmarkable';
static ERROR_MISSING_ROW_BOOKMARK_IDENTIFIER = 'missing-row-bookmark-identifier';
objectType: string;
desktop: Desktop;
page: Page;
// builder options
createOutline: boolean;
persistableRequired: boolean;
fallbackAllowed: boolean;
createTitle: boolean;
createDescription: boolean;
createTablePreferences: boolean;
createTableRowSelections: boolean;
// --------------------------------------
constructor() {
this.createOutline = true;
this.persistableRequired = true;
this.fallbackAllowed = true;
this.createTitle = true;
this.createDescription = true;
this.createTablePreferences = true;
this.createTableRowSelections = true;
}
init(model: InitModelOf<this>) {
Object.assign(this, model);
scout.assertValue(this.desktop);
}
get session(): Session {
return this.desktop.session;
}
// --------------------------------------
build(): JQuery.Promise<IBookmarkDo> {
return $.when(this._build());
}
protected async _build(): Promise<IBookmarkDo> {
let bookmarkDefinition = await this._createBookmarkDefinition();
return this._createBookmark(bookmarkDefinition);
}
protected async _createBookmarkDefinition(): Promise<IBookmarkDefinitionDo> {
let page = this.page;
let outline = page?.outline || this.desktop.outline;
let outlineId = outline?.buildUuid();
if (!outlineId) {
throw BookmarkDoBuilder.ERROR_MISSING_OUTLINE;
}
if (page === undefined) {
page = outline.activePage();
}
let createOutlineBookmarkDefinition = this.createOutline;
// Create page definition for page to bookmark (used by both bookmark definition types)
let bookmarkedPage = page ? await this._pageToBookmarkPage(page, null) : null;
// Create page path (only for outline bookmark definition type)
let pagePath: IBookmarkPageDo[] = [];
if (createOutlineBookmarkDefinition && page) {
let parentPage = page.parentNode;
let childPage = page;
while (parentPage && !parentPage.compactRoot) {
let pathEntry = await this._pageToBookmarkPage(parentPage, childPage);
if (!pathEntry) {
// non-bookmarkable page
if (this.fallbackAllowed) {
createOutlineBookmarkDefinition = false; // fall back to PageBookmarkDefinitionDo
break;
}
throw BookmarkDoBuilder.ERROR_PAGE_PATH_NOT_BOOKMARKABLE;
}
// Add bookmarkPage to front of path and repeat for parent page
pagePath.unshift(pathEntry);
childPage = parentPage;
parentPage = parentPage.parentNode;
}
}
let bookmarkDefinition;
if (createOutlineBookmarkDefinition) {
bookmarkDefinition = scout.create(OutlineBookmarkDefinitionDo, {
outlineId: outlineId,
bookmarkedPage: bookmarkedPage,
pagePath: pagePath
});
} else {
bookmarkDefinition = scout.create(PageBookmarkDefinitionDo, {
bookmarkedPage: bookmarkedPage
});
}
return bookmarkDefinition;
}
// This method is called multiple times from bottom to top. On the first invocation, the childPage is not set,
// but later calls pass the childPage for resolving the corresponding row of a table page.
protected async _pageToBookmarkPage(page: Page, childPage: Page): Promise<IBookmarkPageDo> {
if (!page.pageParam) {
throw BookmarkDoBuilder.ERROR_MISSING_PAGE_PARAM;
}
if (page.nodeType === Page.NodeType.NODES) {
return this._pageToNodeBookmarkPage(page, childPage);
}
if (page.nodeType === Page.NodeType.TABLE) {
return this._pageToTableBookmarkPage(page, childPage);
}
throw BookmarkDoBuilder.ERROR_UNSUPPORTED_NODE_TYPE;
}
protected async _pageToNodeBookmarkPage(page: Page, childPage?: Page): Promise<NodeBookmarkPageDo> {
return scout.create(NodeBookmarkPageDo, {
pageParam: page.pageParam,
displayText: page.getDisplayText()
});
}
protected async _pageToTableBookmarkPage(page: Page, childPage?: Page): Promise<TableBookmarkPageDo> {
if (page instanceof PageWithTable) {
return this._tablePageToTableBookmarkPage(page, childPage);
}
throw BookmarkDoBuilder.ERROR_PAGE_NOT_BOOKMARKABLE;
}
protected async _tablePageToTableBookmarkPage(page: PageWithTable, childPage?: Page): Promise<TableBookmarkPageDo> {
let expandedChildRowIdentifier = this._createExpandedTableRowIdentifier(page, childPage);
let selectedChildRowIdentifiers = this._createSelectedTableRowIdentifiers(page);
let searchFilterComplete = true;
let searchData = await this._createSearchFilterForBookmark(page);
let tablePreferences = await this._createTablePreferencesForBookmark(page);
let chartTableControlConfig = await this._createChartTableControlConfigForBookmark(page);
if (childPage && !expandedChildRowIdentifier && !childPage.pageParam) {
// child row not identifiable
throw BookmarkDoBuilder.ERROR_MISSING_ROW_BOOKMARK_IDENTIFIER;
}
return scout.create(TableBookmarkPageDo, {
pageParam: page.pageParam,
displayText: page.getDisplayText(),
expandedChildRow: expandedChildRowIdentifier,
selectedChildRows: selectedChildRowIdentifiers,
searchFilterComplete: searchFilterComplete,
searchData: searchData,
tablePreferences: tablePreferences,
chartTableControlConfig: chartTableControlConfig
});
}
protected _createExpandedTableRowIdentifier(page: PageWithTable, childPage: Page): BookmarkTableRowIdentifierDo {
// If child page is linked to a table row, check if a special table row identifier is needed.
// Otherwise, we assume that the page param is enough to identify the child page.
if (childPage && childPage.row) {
return page.getTableRowIdentifier(childPage.row, !this.persistableRequired);
}
return null;
}
protected _createSelectedTableRowIdentifiers(page: PageWithTable): BookmarkTableRowIdentifierDo[] {
if (!this.createTableRowSelections) {
return [];
}
if (page.childrenLoaded) {
return page.detailTable.selectedRows
.map(row => page.getTableRowIdentifier(row, !this.persistableRequired));
}
return [];
}
protected async _createSearchFilterForBookmark(page: PageWithTable): Promise<any> {
let searchForm = page.getSearchForm();
if (!searchForm) {
return null;
}
return this._exportSearchFormData(searchForm);
}
protected async _exportSearchFormData(searchForm: Form): Promise<any> {
return searchForm.exportData();
}
protected async _createTablePreferencesForBookmark(page: PageWithTable): Promise<TableClientUiPreferencesDo> {
if (!this.createTablePreferences) {
return null;
}
if (!page.detailTable) {
return null;
}
let table = page.detailTable;
let prefs = tableUiPreferences.create(table);
let profile = tableUiPreferences.createProfile(table, {includeUserFilters: true});
prefs.tablePreferenceProfiles = new Map([
[TableUiPreferences.PROFILE_ID_BOOKMARK, profile]
]);
return prefs;
}
protected async _createChartTableControlConfigForBookmark(page: PageWithTable): Promise<IChartTableControlConfigDo> {
const helper = scout.create(ChartTableControlConfigHelper);
return helper.exportConfig(page);
}
// --------------------------------------
protected async _createBookmark(bookmarkDefinition: IBookmarkDefinitionDo): Promise<IBookmarkDo> {
let bookmarkTitle = await this._createBookmarkTitle(bookmarkDefinition);
let bookmarkDescription = await this._createBookmarkDescription(bookmarkDefinition);
return scout.create(BookmarkDo, {
definition: bookmarkDefinition,
title: bookmarkTitle || undefined,
description: bookmarkDescription || undefined
});
}
protected async _createBookmarkTitle(bookmarkDefinition: IBookmarkDefinitionDo): Promise<string> {
if (!this.createTitle) {
return null;
}
let titleSegments: string[] = [];
if (bookmarkDefinition instanceof OutlineBookmarkDefinitionDo) {
let outline = BookmarkSupport.get(this.session).resolveOutline(bookmarkDefinition.outlineId);
if (outline) {
titleSegments.push(outline.title);
}
bookmarkDefinition.pagePath
.map(p => p.displayText)
.forEach(s => titleSegments.push(s));
}
if (bookmarkDefinition.bookmarkedPage) {
titleSegments.push(bookmarkDefinition.bookmarkedPage.displayText);
}
titleSegments = titleSegments.filter(s => strings.hasText(s));
return arrays.hasElements(titleSegments) ? titleSegments.join(' - ') : this.session.text('Bookmark');
}
protected async _createBookmarkDescription(bookmarkDefinition: IBookmarkDefinitionDo): Promise<string> {
if (!this.createDescription) {
return null;
}
let pagePath = [
...(bookmarkDefinition instanceof OutlineBookmarkDefinitionDo ? bookmarkDefinition.pagePath : []),
bookmarkDefinition.bookmarkedPage
].filter(Boolean);
let lines = [];
pagePath.forEach((bookmarkPage, index) => {
let prefix = strings.repeat(' ', index);
let displayText = bookmarkPage.displayText || this.session.text('Node');
lines.push(prefix + displayText);
if (bookmarkPage instanceof TableBookmarkPageDo && bookmarkPage.searchData) {
let searchData = bookmarkPage.searchData instanceof BaseDoEntity ? bookmarkPage.searchData.toPojo() : bookmarkPage.searchData;
Object.keys(searchData)
.filter(key => !strings.startsWith(key, '_'))
.filter(key => !objects.isNullOrUndefinedOrEmpty(searchData[key]))
.map(key => key + ': ' + JSON.stringify((searchData)[key]))
.forEach(searchLine => lines.push(prefix + ' ' + searchLine));
}
});
return lines.join('\n');
}
}