UNPKG

devexpress-reporting

Version:

DevExpress Reporting provides the capability to develop a reporting application to create and customize reports.

926 lines 102 kB
/** * 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