devexpress-reporting
Version:
DevExpress Reporting provides the capability to develop a reporting application to create and customize reports.
926 lines • 102 kB
JavaScript
/**
* DevExpress HTML/JS Reporting (designer\tools\generator\_inititalizer.js)
* Version: 24.2.6
* Build date: Mar 18, 2025
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* License: https://www.devexpress.com/Support/EULAs/universal.xml
*/
import { $dx, ActionLists, addDisposeCallback, appendStaticContextToRootViewModel, BaseAction, CombinedObject, CommonDesignerGenerator, ContextMenuProvider, createActionWrappingFunction, DesignerBaseElements, DimensionNotationsModel, DragDropHandler, DragHelperContent, DxDeferred, extend, FieldListProvider, findFirstItemMatchesCondition, formatUnicorn, getControlFullName, getControlTypeName, InlineTextEdit, localizeNoneString, NotifyType, ObjectExplorerProvider, processErrorEvent, ShowMessage, SnapLinesHelper, staticContext, SurfaceSelection, updateSurfaceContentSize } from '@devexpress/analytics-core/analytics-internal';
import { ActionId as AnalyticActionId } from '@devexpress/analytics-core/analytics-tools';
import { getLocalization, ModelSerializer, TabInfo } from '@devexpress/analytics-core/analytics-utils';
import { editorTemplates, ObjectProperties, unwrapEditor } from '@devexpress/analytics-core/analytics-widgets';
import { aceAvailable, availableFonts, formatStringStandardPatterns, propertiesGridEditorsPaddingLeft, TreeListController } from '@devexpress/analytics-core/analytics-widgets-internal';
import { FullscreenDataSourceWizard, FullscreenWizard, _createDefaultDataSourceWizardState } from '@devexpress/analytics-core/analytics-wizard';
import config from 'devextreme/core/config';
import dxScrollView from 'devextreme/ui/scroll_view';
import * as ko from 'knockout';
import { HandlerUri as ChartInternalHandlerUri } from '../../../chart/_handlerUri';
import { defaultCulture } from '../../../common/defaultCulture';
import { convertMapToKeyValuePair } from '../../../common/types';
import { createFullscreenComputed, cultureInfo } from '../../../common/utils/_utils';
import { createPreview } from '../../../viewer/internal/_initializer';
import { getDockedElementCallback } from '../../../viewer/internal/_sizeUtils';
import { formatSearchResult } from '../../../viewer/search/_utils';
import { ActionId } from '../../actions/actionId';
import { CrossTabActions } from '../../actions/crossTabActions';
import { ElementsGroupActions } from '../../actions/elementsGroupActions';
import { PdfContentActions } from '../../actions/pdfContentActions';
import { PivotGridActions } from '../../actions/pivotGridActions';
import { ReportActions } from '../../actions/reportActions';
import { ReportElementActions } from '../../actions/reportElementActions';
import { TableCellActions } from '../../actions/tableCellActions';
import { TableCellGroupActions } from '../../actions/tableCellGroupActions';
import { TableRowActions } from '../../actions/tableRowActions';
import { TextElementAction } from '../../actions/textElementAction';
import { JsonDataSourceEditor } from '../../actions/_jsonDataSourceEditor';
import { BandViewModel } from '../../bands/xrBand';
import { formattingRuleSerializationsInfo } from '../../controls/metadata/properties/formattingrules';
import { PivotGridFieldViewModel } from '../../controls/pivotgrid/pivotgridfield';
import { SortBySummaryInfoCondition } from '../../controls/pivotgrid/sortBySummary';
import { ComponentsModel } from '../../controls/properties/components';
import { registerRichEditInline } from '../../controls/richEdit';
import { createChartDesignerOptions } from '../../controls/utils/_chartUtils';
import { XRChartViewModel } from '../../controls/xrChart';
import { XRPivotGridViewModel } from '../../controls/xrPivotgrid';
import { ReportViewModel } from '../../controls/xrReport';
import { TableOfContentsLevel } from '../../controls/xrTableOfContentsLevel';
import { calculatedFieldScripts } from '../../dataObjects/metadata/calculatedField';
import { createNewObjectItem } from '../../dataObjects/objectItemCreation';
import { LookUpValue } from '../../dataObjects/parameters/lookUpValue';
import { DataSourceHelper } from '../../helpers/_dataSourceHelper';
import { ReportDesignerControlsHelper } from '../../helpers/_reportDesignerControlsHelper';
import { FieldListDragDropHandler } from '../../internal/dragdrop/_fieldListDragDropHandler';
import { ReportExplorerDragDropHandler } from '../../internal/dragdrop/_reportExplorerDragDropHandler';
import { ReportSnapLinesCollector } from '../../internal/dragdrop/_reportSnapLinesCollector';
import { ReportToolboxDragDropHandler } from '../../internal/dragdrop/_reportToolboxDragDropHandler';
import { SelectionDragDropHandler } from '../../internal/dragdrop/_selectionDragDropHandler';
import { ErrorPanelViewModel } from '../../internal/errorPanel/_errorPanelViewModel';
import { FieldListController } from '../../internal/fieldlist/_fieldListController';
import { FieldListDataSourcesHelper } from '../../internal/fieldlist/_fieldListDataSourcesHelper';
import { ParametersViewModel } from '../../internal/fieldlist/_parametersViewModel';
import { FieldListItemFactory } from '../../internal/fieldlist/_treelistFactory';
import { ReportExplorerModel } from '../../internal/reportExplorer/_reportExplorer';
import { ScriptsEditor } from '../../internal/scripting/_scriptsEditor';
import { ControlScrollingTool } from '../../internal/_controlScrollingTool';
import { reportCopyPasteStrategy } from '../../internal/_copyPasteStrategy';
import { CrossTabConverter, PivotGridConverter } from '../../internal/_crossTabConverter';
import { CustomMergingEngine } from '../../internal/_customMergingEngine';
import { DataBindingMode } from '../../internal/_dataBindingMode';
import { ExpressionEditorAddOn, ValueEditorAddOn } from '../../internal/_designerEditorAddOn';
import { StringId } from '../../internal/_localizationStringId';
import { ReportConverter } from '../../internal/_reportConverter';
import { reportStorageWebIsRegister } from '../../internal/_settings';
import { createReportViewModel, isControl, updateDataSourceRefs, updateSurfaceContentSizeLocalizationMode } from '../../internal/_utils';
import { WizardRunner } from '../../internal/_wizardRunner';
import { LocalizationEditor } from '../../localization/_localizationEditor';
import { LocaliziblePropertiesAccessibilityProvider } from '../../localization/_localiziblePropertiesAccessibilityProvider';
import { ReportStorageWeb } from '../../services/reportStorageWeb';
import { ReportDataSourceService } from '../../services/_reportDataSourceService';
import { ReportPreviewService } from '../../services/_reportPreviewService';
import { ReportWizardService } from '../../services/_reportWizardService';
import { defaultParameterEditingSettings } from '../../utils/inititalizer';
import { ReportDesignerAddOns, ReportDesignerElements } from '../../utils/reportDesignerElements';
import { controlsFactory, DataBindingMode as UtilsDataBindingMode, DefaultCrossTabControl, formatStringEditorCustomSet, HandlerUri as UtilsHandlerUri, smartTagFactory as UtilsSmartTagFactory } from '../../utils/settings';
import { registerControls } from '../../utils/_registerControls';
import { registerCustomControls } from '../../utils/_registerCustomControls';
import { registerCustomGlobalExpressions, registerCustomReportExpressions } from '../../utils/_registerCustomExpressions';
import { StylesEditorHeaderModel } from '../../widgets/styleseditor';
import { FullscreenReportWizard } from '../../wizard/fullscreenReportWizard';
import { _convertToStateDataSource, _restoreDataSourceFromState } from '../../wizard/pages/chooseAvailableDataSourcePage';
import { CustomizeLabelPage } from '../../wizard/pages/customizeLabelPage';
import { ReportType } from '../../wizard/reportWizardState';
import { createReportWizardState } from '../../wizard/reportWizardStateCreating';
import { NavigateByReports } from '../navigation/navigateByReports';
import { ExpressionSmartTag, TasksSmartTag } from '../smartTags/expressionSmartTag';
import { SmartTagModel } from '../smartTags/smartTagContainer';
import { ReportMenuSettings } from './_reportMenuSettings';
import { ReportDialogSettings, WizardsInitializerSettings } from './_settings';
import { ChartActions } from '../../actions/chartActions';
import { ContextMenusEnabled, SmartTagsEnabled, PropertyGrid, DimensionNotationsEnabled } from '../../settings';
import { FullScreenActionBase } from '../../../viewer/internal/_actions';
import { Parameter } from '../../dataObjects/parameters/parameter';
import { createDeferred } from '@devexpress/analytics-core/analytics-internal-native';
export class ReportDesignerInitializer extends CommonDesignerGenerator {
get reportContext() {
return this._reportcontext;
}
get buildingModel() {
return this.getModel();
}
get _designerCallbacks() {
return this._callbacks && this._callbacks.designer;
}
getModel() {
return super.getModel();
}
subscribeIncomeReport(report, reportUrl, dataSourceRefs, knownEnums, _parameterEditingSettings) {
this._addDisposable(report.subscribe((newValue) => {
const newModel = new ReportViewModel(newValue, undefined, knownEnums);
updateDataSourceRefs(newModel, dataSourceRefs);
if (this.buildingModel.navigateByReports.tabs().length === 0) {
this.buildingModel.navigateByReports.addTab(newModel, reportUrl, () => newModel.dispose());
}
else {
this.buildingModel.model(newModel);
}
}));
return this;
}
_addDisposable(object) {
this._disposables.push(object);
}
_tryAddScriptEditor(isScriptsDisabled) {
isScriptsDisabled = isScriptsDisabled || !aceAvailable;
if (!isScriptsDisabled) {
const scriptsEditor = new ScriptsEditor(this.buildingModel.model, this.buildingModel.controlsHelper.allControls);
this._addDisposable(scriptsEditor.editorVisible.subscribe((newValue) => {
if (newValue) {
const focusedControl = this.buildingModel.selection.focused();
if (focusedControl && focusedControl.getControlModel) {
const controlModel = focusedControl.getControlModel();
scriptsEditor.selectedControl(!!controlModel.scripts ? controlModel : controlModel.parentModel());
}
const resizeFunction = () => setTimeout(() => {
scriptsEditor.editorContainer().resize();
}, 1);
if (!scriptsEditor.editorContainer()) {
const innerSubscription = scriptsEditor.editorContainer.subscribe((newVal) => {
innerSubscription.dispose();
resizeFunction();
});
}
else
resizeFunction();
}
this.buildingModel.designMode(!newValue);
}));
this.addElement('scriptsEditor', () => scriptsEditor);
this.addElement('events', () => ko.pureComputed(() => { return this.buildingModel.scriptsEditor.allFunctionNames; }));
this.addElement('gotoEvent', () => (functionName, eventName, model) => {
scriptsEditor.editorVisible(true);
scriptsEditor.ensureEvent(eventName.substring(2), functionName, model);
});
return true;
}
else {
const controlTypes = Object.keys(controlsFactory().controlsMap);
for (let index = 0; index < controlTypes.length; index++) {
['scripts', 'scriptReferencesString', 'scriptLanguage'].forEach((propertyDisplayName) => {
const propertyInfo = controlsFactory().getPropertyInfo(controlTypes[index], propertyDisplayName);
propertyInfo && (propertyInfo.visible = false);
});
}
calculatedFieldScripts.visible = false;
}
return false;
}
_getControls(controls, filter, isNoneItemAdded = true) {
return ko.pureComputed(() => {
let result = controls();
if (filter) {
result = result.filter(filter);
}
const allControls = result.map((item) => {
return { displayName: ko.unwrap(item.name), value: item };
});
if (isNoneItemAdded)
allControls.splice(0, 0, { displayName: localizeNoneString('(none)'), value: null });
return allControls;
}).extend({ throttle: 1 });
}
_createEmptyReportItemsProvider() {
const reportModel = new ReportViewModel({});
const parameters = new ParametersViewModel(reportModel);
const dataSourceHelper = new DataSourceHelper(reportModel.objectStorage, reportModel.dataSourceRefs, undefined);
reportModel.dataSourceHelper(dataSourceHelper);
const fieldListDataSourceHelper = new FieldListDataSourcesHelper();
fieldListDataSourceHelper.updateDataSources(dataSourceHelper, reportModel, parameters.parameters);
const wrappedCallback = fieldListDataSourceHelper.wrapFieldsCallback(ReportDataSourceService.fieldListCallback, () => undefined);
return new FieldListProvider(wrappedCallback, fieldListDataSourceHelper.fieldListDataSources, [parameters]);
}
addReportDialogs(func) {
const settings = new ReportDialogSettings(this._designerCallbacks);
func(settings);
settings.saveReportDialog && this.addElement('saveReportDialog', () => settings.saveReportDialog);
if (settings.saveReportDialogLight) {
this.addElement('saveReportDialogLight', () => settings.saveReportDialogLight);
this.buildingModel.navigateByReports.save = (tab) => {
this.buildingModel.saveReportDialogLight.show(tab);
};
}
settings.openReportDialog && this.addElement('openReportDialog', () => settings.openReportDialog);
return this;
}
addErrorPanelViewModel(element, options) {
this.addElement('errorPanelViewModel', () => {
const getRightPositionSize = () => {
return this.buildingModel.designMode() ?
this.buildingModel.tabPanel.headerWidth :
this.buildingModel.reportPreviewModel && this.buildingModel.reportPreviewModel.tabPanel.headerWidth;
};
const rightPosition = ko.observable(0);
let dispose = null;
const subscribeDesignMode = () => {
dispose && dispose();
if (this.buildingModel.designMode()) {
dispose = this.buildingModel.tabPanel.events.on('headerWidthChanged', (args) => {
rightPosition(getRightPositionSize());
});
}
else {
dispose = this.buildingModel.reportPreviewModel.tabPanel.events.on('headerWidthChanged', (args) => {
rightPosition(getRightPositionSize());
});
}
rightPosition(getRightPositionSize());
};
subscribeDesignMode();
this._addDisposable(this.buildingModel.designMode.subscribe(() => subscribeDesignMode()));
const leftPosition = ko.computed(() => {
return this.buildingModel.designMode() ? 96 : 0;
});
const errorPanel = new ErrorPanelViewModel({
...options,
controlScrollingTool: this.buildingModel.controlScrollingTool,
controlsHelper: this.buildingModel.controlsHelper,
editableObject: this.buildingModel.editableObject,
selection: this.buildingModel.selection,
undoEngine: () => this.buildingModel.undoEngine(),
onClick: () => {
if (!this.buildingModel.designMode()) {
this.buildingModel.reportPreviewModel.reportPreview.previewVisible = false;
this.buildingModel.reportPreviewModel.reportPreview.deactivate();
}
this.buildingModel.tabPanel.selectTab({
model: this.buildingModel.tabPanel.getTabByName('Properties')
});
},
position: {
left: leftPosition,
right: rightPosition
},
rtl: this.buildingModel.rtl
});
errorPanel._disposables.push({ dispose }, leftPosition);
this._addDisposable(this._reportcontext.subscribe((newVal) => {
errorPanel.clear();
if (newVal != null) {
errorPanel.subscribeProvider(newVal.reportErrorProvider);
errorPanel.subscribeProvider(newVal.runtimeErrorProvider);
errorPanel._providers.forEach(provider => provider.collectErrors());
}
}));
const $root = $dx(element);
const $progress = $dx(element).find('.dxrd-error-panel');
const updateProgressBarPosition = getDockedElementCallback($progress, $root, window, '.dxrd-error-panel', { bottom: true });
this._addDisposable(errorPanel.collapsed.subscribe(() => {
updateProgressBarPosition(element);
}));
const wrapped = () => updateProgressBarPosition(element);
this._onAfterRenderCallbacks.push(() => updateProgressBarPosition(element));
window.addEventListener('scroll', wrapped);
this._addDisposable({
dispose: () => {
window.removeEventListener('scroll', wrapped);
}
});
return errorPanel;
});
return this;
}
addNavigateToControl(element) {
this.addElement('controlScrollingTool', () => {
return new ControlScrollingTool(element);
});
return this;
}
addFlagsAndInitProperties(element) {
this.addElement('validationMode', () => ko.computed({
read: () => {
return this.buildingModel.surface() && this.buildingModel.surface().validationMode();
}, write: (newVal) => {
this.buildingModel.surface().validationMode(newVal);
}
}));
this.addElement('isDirty', () => ko.computed({
read: () => {
return this.buildingModel.navigateByReports.currentTab() && this.buildingModel.navigateByReports.currentTab().isDirty();
},
write: (newVal) => {
this.buildingModel.navigateByReports.currentTab() && this.buildingModel.navigateByReports.currentTab().isDirty(newVal);
}
}));
this.addElement('designMode', () => ko.observable(true));
this.addIsLoading(() => {
const isLoading = ko.observable(true);
this.buildingModel.navigateByReports.init(isLoading);
return isLoading;
});
this.addElement('rootStyle', () => 'dxrd-designer dxd-back-primary-invariant');
this.addElement('selectedPath', () => ko.observable(null));
this.addElement('actionsGroupTitle', () => () => formatUnicorn(getLocalization('{0} {1}', 'ReportStringId.STag_Capt_Format'), getControlTypeName(this.getModel().editableObject()), getLocalization('Tasks', 'ReportStringId.STag_Capt_Tasks')));
this.addElement('updateFont', () => (values) => {
availableFonts({
...availableFonts(),
...values
});
});
this.addElement('afterRender', () => () => {
this._onAfterRenderCallbacks.forEach(x => x());
this._onAfterRenderCallbacks.splice(0);
delete this.buildingModel.afterRender;
});
this.addElement('sortFont', () => () => {
const sortedObj = {};
const fonts = availableFonts.peek();
Object.keys(fonts).sort((a, b) => { return a.localeCompare(b); }).forEach(key => sortedObj[key] = fonts[key]);
availableFonts(sortedObj);
});
this.addElement('zoomStep', () => ko.observable(0.05));
this.addElement('surfaceSize', () => ko.observable(0));
if (!element)
return this;
this.addElement('fullScreen', () => createFullscreenComputed(element, this));
this.addElement('drawCrossbandContent', () => ko.observable(true));
return this;
}
addPreview(options) {
const errorsAction = (response) => {
if (!!response.errors)
this.reportContext() && this.reportContext().runtimeErrorProvider.errors(response.errors);
};
createPreview({
model: {
parametersInfo: options.parametersInfo,
handlerUri: options.handlerUri,
previewVisible: false,
rtl: options.rtl,
accessibilityCompliant: false,
exportSettings: options.exportSettings,
progressBarSettings: options.progressBarSettings,
searchSettings: options.searchSettings
},
element: options.element,
callbacks: {
...options.callbacks,
_onGetBuildStatus: errorsAction,
_onGetDocumentDetails: errorsAction
}
})
.done((reportPreviewModel) => {
this.addElement('reportPreviewModel', () => {
this._addDisposable({
dispose: reportPreviewModel.reportPreview.events.on('previewVisibleChanged', (args) => {
const newValue = args.newValue;
this.buildingModel.designMode(!newValue);
if (!newValue && this._updateCallback)
this._updateCallback();
})
});
return reportPreviewModel;
});
this._addDisposable(reportPreviewModel);
});
return this;
}
addReportUrls(subreports) {
this.addElement('reportUrls', () => {
return ko.observableArray(convertMapToKeyValuePair(subreports));
});
return this;
}
_wrapActionProvider(actionsProvider) {
return {
getActions: (context) => {
return actionsProvider() && actionsProvider().getActions(context) || [];
}
};
}
initializeFieldListActionProviders(func = () => {
const providers = [];
if (this._calculatedFieldsSource)
providers.push(this._wrapActionProvider(this._calculatedFieldsSource));
if (this._watermarks)
providers.push(this._wrapActionProvider(this._watermarks));
if (this._parameters)
providers.push(this._wrapActionProvider(this._parameters));
if (this._dataSourceActionProvider)
providers.push(this._dataSourceActionProvider);
if (this.options.data?.dataSourceSettings?.allowEditDataSource ?? true) {
if (this._jsonDataSourceEditor)
providers.push(this._jsonDataSourceEditor);
if (this._sqlDataSourceEditor)
providers.push(this._sqlDataSourceEditor);
if (this._federationDataSourceEditor)
providers.push(this._federationDataSourceEditor);
if (this._objectDataSourceEditor)
providers.push(this._objectDataSourceEditor);
}
return providers;
}) {
this.addElement('fieldListActionProviders', func);
return this;
}
initializeCalculatedFieldsSource() {
const calculatedFieldsSource = ko.computed(() => this._reportcontext() && this._reportcontext().calcFieldsSource);
this.addElement('calculatedFieldsSource', () => calculatedFieldsSource);
this._calculatedFieldsSource = calculatedFieldsSource;
return this;
}
initializeWatermarks() {
const watermarks = ko.computed(() => this._reportcontext() && this._reportcontext().watermarks);
this.addElement('watermarks', () => watermarks);
this._watermarks = watermarks;
return this;
}
initializeFieldListItemsExtenders() {
const fieldListItemsExtenders = ko.computed(() => this._reportcontext() && this._reportcontext().fieldListItemsExtenders);
this.addElement('fieldListItemsExtenders', () => fieldListItemsExtenders);
return this;
}
initializeParameters(_parameterEditingSettings = defaultParameterEditingSettings) {
const parameters = ko.computed(() => this._reportcontext() && this._reportcontext().parameters);
this.addElement('parameters', () => parameters);
this._parameters = parameters;
this.addElement('parameterEditingSettings', () => _parameterEditingSettings);
return this;
}
initializeFieldListProvider() {
const fieldListProvider = ko.computed(() => this._reportcontext() && this._reportcontext().fieldListProvider);
this.addElement('fieldListProvider', () => fieldListProvider);
return this;
}
initializeReportItemsProvider() {
const reportItemsProvider = ko.computed(() => this._reportcontext() && this._reportcontext().reportItemsProvider);
this.addElement('reportItemsProvider', () => reportItemsProvider);
return this;
}
initializeDataBindingsProvider() {
const dataBindingsProvider = ko.computed(() => this._reportcontext() && this._reportcontext().dataBindingsProvider);
this.addElement('dataBindingsProvider', () => dataBindingsProvider);
return this;
}
initializeDisplayNameProvider() {
const displayNameProvider = ko.computed(() => this._reportcontext() && this._reportcontext().displayNameProvider);
this.addElement('displayNameProvider', () => displayNameProvider);
this.addElement('getDisplayNameByPath', () => (path, value) => { return displayNameProvider().getDisplayNameByPath(path, value); });
return this;
}
initializeExpressionDisplayNameProvider() {
const expressionDisplayNameProvider = ko.computed(() => this._reportcontext() && this._reportcontext().expressionDisplayNameProvider);
this.addElement('expressionDisplayNameProvider', () => expressionDisplayNameProvider);
return this;
}
initializeDataSourceHelper() {
const dataSourceHelper = ko.computed(() => this._reportcontext() && this._reportcontext().dataSourceHelper);
this.addElement('dataSourceHelper', () => dataSourceHelper);
const fieldListDataSourceHelper = ko.computed(() => this._reportcontext() && this._reportcontext().fieldListDataSourceHelper);
this.addElement('fieldListDataSources', () => ko.computed(() => fieldListDataSourceHelper() && fieldListDataSourceHelper().fieldListDataSources()));
this._addDisposable(fieldListDataSourceHelper);
return this;
}
addSelection(func = (settings) => {
settings.selection = this._selection;
const rtl = ko.computed(() => { return this.buildingModel.surface() && this.buildingModel.surface().rtl(); });
const snapLinesCollector = new ReportSnapLinesCollector(rtl);
this._addDisposable(rtl);
settings.snapHelper = new SnapLinesHelper(this.buildingModel.surface, SnapLinesHelper.snapTolerance, snapLinesCollector);
settings.editableObject = CombinedObject.getEditableObject(settings.selection, this.buildingModel.undoEngine, (propertyName, controls, undoEngune) => this._customMergeEngine.customMerge(propertyName, controls, undoEngune)).extend({ throttle: 1 });
settings.addDragDrop((dragDropSettings) => {
dragDropSettings.dragHelperContent = new DragHelperContent(settings.selection);
dragDropSettings.dragDropStarted = DragDropHandler.started;
dragDropSettings.addDragDropHandler('dragHandler', new SelectionDragDropHandler(this.buildingModel.canAddItems, this.buildingModel.surface, settings.selection, this.buildingModel.undoEngine, settings.snapHelper, dragDropSettings.dragHelperContent));
dragDropSettings.addDragDropHandler('toolboxDragHandler', new ReportToolboxDragDropHandler(this.buildingModel.surface, this._selection, this.buildingModel.undoEngine, settings.snapHelper, dragDropSettings.dragHelperContent, controlsFactory(), this._designerCallbacks.componentAdded));
dragDropSettings.addDragDropHandler('fieldDragHandler', new FieldListDragDropHandler(this.buildingModel.canAddItems, this.buildingModel.surface, this._selection, this.buildingModel.undoEngine, settings.snapHelper, dragDropSettings.dragHelperContent, this.buildingModel.fieldListDataSources, this._designerCallbacks.componentAdded));
});
settings.addResize((resizeSettings) => {
this.addElement('dimensionNotationsModel', () => new DimensionNotationsModel({
enabled: DimensionNotationsEnabled,
surface: this.buildingModel.surface,
isHorizontalAxisVisible: (controlModel) => {
return !(controlModel instanceof BandViewModel);
},
isVerticalAxisVisible: (controlModel) => {
return !(controlModel instanceof BandViewModel);
},
isLocatedInsideContainer: (controlModel) => {
return controlModel instanceof BandViewModel;
}
}));
resizeSettings.handler = {
starting: (event, element) => {
this.buildingModel.inlineTextEdit.visible() &&
this.buildingModel.inlineTextEdit['_showInline'](false);
this.buildingModel['richInlineControl'] &&
this.buildingModel['richInlineControl'].visible() &&
this.buildingModel['richInlineControl']['_showInline'](false);
this.buildingModel['smartTagModel']?.visible(false);
this.buildingModel['dimensionNotationsModel']?.start(element);
this._selection.expectClick = true;
this.buildingModel.undoEngine().start();
},
stopped: () => {
this.buildingModel['dimensionNotationsModel']?.stop();
this.buildingModel['smartTagModel']?.visible(true);
this.buildingModel.undoEngine().end();
setTimeout(() => { this._selection.expectClick = false; }, 100);
},
resizing: (boundsDiff) => {
this.buildingModel['dimensionNotationsModel']?.updateSize(boundsDiff);
},
disabled: DragDropHandler.started,
snapHelper: settings.snapHelper
};
});
}) {
super.addSelection(func);
return this;
}
addToolboxItems(items) {
super.addToolboxItems(items);
return this;
}
addGroupedToolboxItems() {
super.addGroupedToolboxItems();
return this;
}
addControlProperties(editors, groups, accessibilityProvider) {
super.addControlProperties(editors, groups, this._accessibilityProvider);
return this;
}
createControlProperties(editors, groups, accessibilityProvider) {
const properties = super.createControlProperties(editors, groups, accessibilityProvider);
properties.createEditorAddOn = (_editor) => {
const editor = unwrapEditor(_editor);
const template = {
templateName: 'dx-editor-addons',
data: []
};
if (ko.unwrap(editor._model) instanceof Parameter && ko.unwrap(editor.disabled)) {
return template;
}
const editorAddOn = new ValueEditorAddOn(editor, properties.popupService);
const editorExression = new ExpressionEditorAddOn(editor, properties.popupService, 'dxrd-svg-properties-propertyexpression');
template.data.push(editorAddOn, editorExression);
editor._disposables.push(editorAddOn, editorExression);
return template;
};
return properties;
}
addMenu(func = (settings) => void 0) {
const settings = new ReportMenuSettings();
func(settings);
this._disposables.push(settings);
extend(this.getModel(), settings.generate());
return this;
}
addControlsHelper(func = (settings) => {
const helper = ko.computed(() => this._reportcontext() && this._reportcontext().controlsHelper);
this._addDisposable(helper);
const controlHelper = new ReportDesignerControlsHelper(helper);
settings
.addControlsHelper(controlHelper)
.addControlsStore();
}) {
super.addControlsHelper(func);
return this;
}
addSmartTagModel() {
let smartTagFactory = { ...UtilsSmartTagFactory() };
extend(smartTagFactory, {
'default': (reportElement) => {
const result = [];
if (SmartTagsEnabled())
result.push(new TasksSmartTag(reportElement, this.buildingModel.popularProperties));
if (UtilsDataBindingMode() !== DataBindingMode.Bindings)
result.push(new ExpressionSmartTag(reportElement, this.buildingModel.activatedExpressionEditor));
return result;
}
});
const smartTagHelper = new SmartTagModel(this._selection, this.buildingModel.surface, this.buildingModel['verticalScrollOffset'], smartTagFactory, this.buildingModel.rtl);
this.addElement('smartTagModel', () => smartTagHelper);
this._disposables.push({
dispose: () => smartTagFactory = {},
});
return this;
}
setControlsHelperFilter(filter) {
this.buildingModel.controlsStore.setFilter(filter);
return this;
}
_createPropertiesTab() {
const getVisible = () => { return !!this.buildingModel.model(); };
const getDisabled = () => {
return this.buildingModel.propertyGrid.focusedItem() instanceof Array ||
(!(this.options.data?.dataSourceSettings?.allowEditDataSource ?? true) && this.buildingModel.propertyGrid.focusedItem() instanceof ComponentsModel);
};
const tabInfo = new TabInfo({
text: 'Properties',
template: 'dxrd-propertiestab',
model: this.buildingModel.propertyGrid,
localizationId: 'AnalyticsCoreStringId.Cmd_Properties',
visible: getVisible(),
disabled: getDisabled()
});
this._addDisposable(this.buildingModel.model.subscribe((newVal) => {
tabInfo.visible = getVisible();
}));
this._addDisposable(this.buildingModel.propertyGrid.focusedItem.subscribe((newVal) => {
tabInfo.disabled = getDisabled();
}));
return tabInfo;
}
_createExpressionsTab(context) {
const expressionGridModel = ko.computed(() => {
const editableObject = this.buildingModel.editableObject();
return editableObject && editableObject.expressionObj;
});
let expressionGrid = null;
this._addDisposable(context.subscribe((newVal) => {
expressionGrid.cleanEditors();
}));
expressionGrid = new ObjectProperties(expressionGridModel);
this._addDisposable(expressionGrid);
this._addDisposable(expressionGridModel);
const getVisible = () => { return this.buildingModel.model() && this.buildingModel.model()._dataBindingMode() !== DataBindingMode.Bindings; };
const getDisabled = () => {
return !expressionGridModel() || ko.unwrap(this.buildingModel.editableObject().lockedInUserDesigner);
};
const expressionTab = new TabInfo({
text: 'Expressions',
template: 'dxrd-expressions-tab',
model: expressionGrid,
localizationId: 'DevExpress.XtraReports.UI.XRControl.Expressions',
imageClassName: 'expressions',
imageTemplateName: 'dxrd-svg-tabs-expressions',
visible: getVisible(),
disabled: getDisabled(),
});
this._addDisposable(this.buildingModel.model.subscribe((newVal) => {
if (newVal)
this._addDisposable(newVal._dataBindingMode.subscribe((newVal) => {
expressionTab.visible = getVisible();
}));
expressionTab.visible = getVisible();
}));
this._addDisposable(expressionGridModel.subscribe((newVal) => {
expressionTab.disabled = getDisabled();
}));
let currentFilter = undefined;
this._addDisposable({
dispose: expressionTab.events.on('activeChanged', (args) => {
if (expressionTab.active && expressionTab.visible) {
currentFilter = this.buildingModel.controlsStore.getFilter();
this.buildingModel.controlsStore.setFilter(isControl);
}
else if (currentFilter !== undefined)
this.buildingModel.controlsStore.setFilter(currentFilter);
})
});
return expressionTab;
}
_createReportExplorerTab() {
const reportExplorer = new ReportExplorerModel(this.buildingModel.model, this.buildingModel.editableObject, (targetObject) => {
const propertiesTab = this.buildingModel.tabPanel.getTabByName('Properties');
propertiesTab.model.focusedItem(targetObject);
this.buildingModel.tabPanel.selectTab({ model: propertiesTab });
}, new ReportExplorerDragDropHandler(this.buildingModel.canAddItems, this.buildingModel.surface, this.buildingModel.selection, this.buildingModel.undoEngine, this.buildingModel.dragHelperContent), this.buildingModel.selection, this.options.data?.dataSourceSettings);
this._addDisposable(reportExplorer);
const getVisible = () => { return !!this.buildingModel.model(); };
const tabInfo = new TabInfo({
text: 'Report Explorer',
template: 'dxrd-reportexplorerwrapper',
model: reportExplorer,
localizationId: 'ReportStringId.UD_Title_ReportExplorer',
imageClassName: 'reportexplorer',
imageTemplateName: 'dxrd-svg-tabs-reportexplorer',
visible: getVisible()
});
this._addDisposable(this.buildingModel.model.subscribe(() => {
tabInfo.visible = getVisible();
}));
return tabInfo;
}
_createFieldListTab(designerCallbacks, startDataSourceWizard) {
const treeListOptions = {
itemsProvider: this.buildingModel.fieldListProvider,
factory: new FieldListItemFactory(),
selectedPath: this.buildingModel.selectedPath,
treeListController: new FieldListController(this.buildingModel.fieldListActionProviders, createActionWrappingFunction('WrapForFieldList', (model, handler) => {
this.buildingModel.undoEngine().start();
const result = handler(model);
this.buildingModel.undoEngine().end();
if (result && result.name) {
this.buildingModel.selectedPath(model.path + '.' + ko.unwrap(result.name));
}
}), this.buildingModel.fieldDragHandler, designerCallbacks.customizeFieldListActions)
};
const useContextMenu = ko.observable(true);
const actions = ko.observable([]);
this.addDisposable(treeListOptions.treeListController.subscribeOnSelectedItemChange(() => {
useContextMenu(this.getModel().parts?.some(part => part.id === ReportDesignerElements.ContextMenu) ?? true);
if (useContextMenu() && treeListOptions.treeListController.selectedItem)
actions(treeListOptions.treeListController.getActions(treeListOptions.treeListController.selectedItem));
else
actions([]);
}));
if (!this.getModel().ContextMenusEnabled)
this.getModel().ContextMenusEnabled = ko.observable(true);
const fieldListContextMenu = new ContextMenuProvider({
actions: actions,
target: '.' + this.buildingModel.containerClass + ' .dxrd-fieldslist-context-menu-container',
getClickActionParams: () => treeListOptions.treeListController.selectedItem && treeListOptions.treeListController.selectedItem.getViewModel(),
contextMenusEnabled: this.getModel().ContextMenusEnabled,
fullScreen: this.getModel().fullScreen
});
this.addContextMenu(fieldListContextMenu);
this.addDisposable(fieldListContextMenu);
const fieldListModel = {
treeListOptions: treeListOptions,
startWizard: () => {
startDataSourceWizard();
},
visible: () => {
const model = this.getModel();
return model != null && model.multiQueryDataSourceWizard.canRunWizard();
},
addDataSourceButtonText: getLocalization('Add Data Source', 'ASPxReportsStringId.ReportDesigner_FieldList_AddDataSource'),
allowAddDataSource: this.options.data?.dataSourceSettings?.allowAddDataSource ?? true,
fieldListContextMenu: fieldListContextMenu,
useContextMenu: useContextMenu
};
const getVisible = () => { return !!this.buildingModel.model(); };
const tabInfo = new TabInfo({
text: 'Fields',
template: 'dxrd-fieldlistwrapper',
model: fieldListModel,
localizationId: 'ReportStringId.UD_Title_FieldList',
imageClassName: 'fieldlist',
imageTemplateName: 'dxrd-svg-tabs-fieldlist',
visible: getVisible()
});
this._addDisposable(this.buildingModel.model.subscribe(() => {
tabInfo.visible = getVisible();
}));
return tabInfo;
}
addTabPanel(panel, addTabInfo = () => {
return [
this._createPropertiesTab(),
this._createExpressionsTab(this._reportcontext),
this._createFieldListTab(this._designerCallbacks, () => {
this.buildingModel._wizardRunner.run('DataSourceWizard');
}),
this._createReportExplorerTab()
];
}) {
super.addTabPanel(panel, addTabInfo);
const contextSubscription = this._reportcontext.subscribe((newVal) => {
if (!!newVal) {
contextSubscription.dispose();
this.buildingModel.tabPanel.collapsed = false;
}
});
this._addDisposable(contextSubscription);
return this;
}
_createActionsStorage(actions) {
const object = {};
for (let i = actions.length - 1; i > -1; i--) {
object[actions[i].id] = actions[i].clickAction;
}
return object;
}
addOpenReportMethod() {
this.addElement('openReport', () => (url) => {
this.buildingModel.navigateByReports.addTab(null, ko.observable(url));
});
return this;
}
addShowPreviewMethod() {
this.addElement('showPreview', () => () => {
const reportPreview = this.buildingModel.reportPreviewModel.reportPreview;
reportPreview.previewVisible = true;
if (!this.buildingModel.model()) {
const subscription = this.buildingModel.model.subscribe((newVal) => {
subscription.dispose();
reportPreview.initialize(ReportPreviewService.initializePreview(this.buildingModel.model()));
});
}
else {
reportPreview.initialize(ReportPreviewService.initializePreview(this.buildingModel.model()));
}
});
return this;
}
initializeUIEffects(applyBindings, element) {
this._addDisposable(this.buildingModel.editableObject.subscribe(() => {
const $scrollView = $dx('.dxrd-designer .dxrd-properties-wrapper').find('.dx-scrollview');
if ($scrollView.length) {
const scrollViewInstance = dxScrollView['getInstance']($scrollView.get(0));
scrollViewInstance && scrollViewInstance['scrollTo'] && scrollViewInstance['scrollTo'](0);
}
}));
const updateSurfaceContentSize__ = updateSurfaceContentSize(this.buildingModel.surfaceSize, element, this.rtl);
const updateSurfaceContentSizeLocalizationMode__ = updateSurfaceContentSizeLocalizationMode(this.buildingModel.surfaceSize, element, this.rtl);
const updateSurfaceContentSize_ = () => {
if (!this.buildingModel)
return;
if (this.buildingModel.localizationMode()) {
updateSurfaceContentSizeLocalizationMode__();
}
else {
updateSurfaceContentSize__();
}
const $root = $dx(element).find('.dxrd-designer');
const $contentPanel = $root.find('.dxrd-surface-wrapper .dxrd-content-panel-wrapper');
areaHeight($contentPanel.height());
areaWidth($contentPanel.width());
};
let updateContentSizeTimeout = null;
const updateSurfaceContentSize_async = () => {
updateContentSizeTimeout && clearTimeout(updateContentSizeTimeout);
updateContentSizeTimeout = setTimeout(() => {
updateSurfaceContentSize_();
}, 1);
};
const reportHeight = ko.computed(() => {
if (this.buildingModel.surface()) {
updateSurfaceContentSize_async();
return this.buildingModel.surface().effectiveHeight();
}
});
const reportWidth = ko.computed(() => {
if (this.buildingModel.surface()) {
updateSurfaceContentSize_async();
return this.buildingModel.surface().pageWidth();
}
});
const areaHeight = ko.observable(reportHeight());
const areaWidth = ko.observable(reportWidth());
const verticalScrollOffset = ko.observable(0);
const horizontalScrollOffset = ko.observable(0);
this._addDisposable(ko.computed(() => {
let horizontalOffset = 0;
let verticalOffset = 0;
[0, 0].forEach(() => {
verticalOffset = reportHeight() - (areaHeight() - horizontalOffset) > 0.5 ? 20 : 0;
horizontalOffset = reportWidth() - (areaWidth() - verticalOffset) > 0.5 ? 20 : 0;
});
horizontalScrollOffset(horizontalOffset);
verticalScrollOffset(verticalOffset);
}));
this._updateCallback = () => {
if (!this.buildingModel.reportPreviewModel.reportPreview.previewVisible)
updateSurfaceContentSize_();
};
window.addEventListener('resize', this._updateCallback);
this.buildingModel.onViewPortScroll = (viewPort) => {
const $viewPort = $dx(viewPort), $surface = $viewPort.closest('.dxrd-surface');
$surface.find('.dxrd-bands-panel-wrapper').scrollTop($viewPort.scrollTop());
$surface.find('.dxrd-hruler-wrapper').scrollLeft($viewPort.scrollLeft());
};
this.addElement('verticalScrollOffset', () => verticalScrollOffset);
this.addElement('horizontalScrollOffset', () => horizontalScrollOffset);
this._addDisposable(reportHeight);
this._addDisposable(reportWidth);
this._addDisposable({
dispose: this.buildingModel.tabPanel.events.on('widthChanged', (args) => {
updateSurfaceContentSize_async();
})
});
this._addDisposable(this.buildingModel.localizationEditor.width.subscribe(() => {
updateSurfaceContentSize_async();
}));
this._addDisposable(this.buildingModel.localizationMode.subscribe((newVal) => {
updateSurfaceContentSize_async();
}));
this.buildingModel.updateSurfaceSize = () => {
updateSurfaceContentSize_();
};
this._addDisposable(this.buildingModel.navigateByReports.height.subscribe(() => {
updateSurfaceContentSize_async();
}));
if (applyBindings) {
this.buildingModel.updateSurfaceSize();
}
return this;
}
_createNewReportFromWizardState(reportWizard, designerModel, wizardState, state, deferred) {
ReportWizardService.generateReportFromWizardState(wizardState, reportWizard._requestModelType, state(), (wizardModel) => {
reportWizard.events.call('beforeFinish', { state: wizardState, wizardModel: wizardModel });
})
.done((result) => {
const modelJson = JSON.parse(result.reportModel);
const newReport = new ReportViewModel(modelJson, undefined, result.knownEnums);
newReport.dataSourceRefs = result.dataSourceRefs;
designerModel.navigateByReports.addTab(newReport, ko.observable(''), undefined, newReport.displayNameObject() || newReport.name());
designerModel.isDirty(true);
designerModel.isLoading(false);
deferred.resolve(newReport);
})
.fail(() => { deferred.reject(); });
}
_createNewViaWizardAction(reportWizard, designerModel, state) {
const menuAction = {
id: ActionId.N