ru.coon 2.8.66 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CHANGELOG.md +317 -10
  2. package/package.json +1 -1
  3. package/src/Function.js +1 -1
  4. package/src/VisualLinker.js +610 -0
  5. package/src/VisualLinker.scss +219 -0
  6. package/src/app/Application.js +1 -0
  7. package/src/app/ApplicationSettings.js +49 -0
  8. package/src/app/Config.js +60 -0
  9. package/src/app/Router.js +37 -21
  10. package/src/app/viewPort/CVWrapperPanel.js +53 -0
  11. package/src/app/viewPort/CenterView.js +153 -46
  12. package/src/app/viewPort/CenterView.scss +151 -0
  13. package/src/app/viewPort/ComponentContextManager.js +24 -0
  14. package/src/app/viewPort/Main.js +4 -1
  15. package/src/app/viewPort/Routing.d2 +23 -0
  16. package/src/app/viewPort/TabHistory.js +81 -0
  17. package/src/common/ComponentFactory.js +167 -0
  18. package/src/common/button/DropdownContentButton.js +146 -0
  19. package/src/common/button/DropdownContentButton.scss +92 -0
  20. package/src/common/button/DropdownContentButtonController.js +60 -0
  21. package/src/common/component/formeditor/UiCustomFilterForm.scss +0 -1
  22. package/src/common/component/settings/modules/settingClosePageConfirmation.js +1 -3
  23. package/src/common/component/settings/modules/settingFavoritePanelShow.js +21 -0
  24. package/src/common/component/settings/modules/settingReportCalculator.js +22 -0
  25. package/src/common/component/settings/modules/settingShowNeedReloadMessage.js +1 -3
  26. package/src/common/component/settings/modules/settingwindowHolder.js +2 -3
  27. package/src/common/panel/WindowWrap.js +19 -11
  28. package/src/common/tree/BaseContextMenu.js +4 -3
  29. package/src/log.js +4 -5
  30. package/src/nav/AppNavCalcButton.js +23 -0
  31. package/src/nav/AppNavCalcButton.scss +6 -0
  32. package/src/nav/AppNavigationBar.js +1 -1
  33. package/src/nav/AppNavigationMenuController.js +2 -2
  34. package/src/nav/AppNavigationMenuMinimized.js +61 -0
  35. package/src/nav/AppNavigationPanel.js +115 -0
  36. package/src/nav/AppNavigationPanel.scss +178 -0
  37. package/src/nav/AppNavigationPanelController.js +386 -0
  38. package/src/nav/FavoriteCfg.js +18 -0
  39. package/src/nav/MenuEntity.js +23 -15
  40. package/src/nav/MenuFavoritesBar.js +100 -0
  41. package/src/nav/MenuFavoritesBar.scss +92 -0
  42. package/src/nav/editor/NavigateElementEditorView.js +2 -2
  43. package/src/nav/editor/workspace/NavWorkspaceListView.js +1 -4
  44. package/src/nav/menu/WorkspaceMenuViewMinimized.js +22 -0
  45. package/src/overrides/panel/TabPanel.js +36 -0
  46. package/src/overrides/panel/TabPanel.scss +65 -0
  47. package/src/report/component/ClearFiltersButton.js +4 -1
  48. package/src/report/component/CopyCellValueMenuItem.js +18 -0
  49. package/src/report/component/ReportFieldMap.js +274 -0
  50. package/src/report/component/ReportPanel.js +73 -44
  51. package/src/report/component/ReportPanel.scss +2 -2
  52. package/src/report/component/ReportTagLookup.js +59 -2
  53. package/src/report/component/calculator/ReportCalculatorController.js +266 -0
  54. package/src/report/component/calculator/ReportCalculatorField.js +47 -0
  55. package/src/report/component/calculator/ReportCalculatorHistoryPlugin.js +128 -0
  56. package/src/report/component/calculator/ReportCalculatorHistoryPlugin.scss +33 -0
  57. package/src/report/component/calculator/ReportCalculatorMenuItem.js +101 -0
  58. package/src/report/component/calculator/ReportCalculatorMenuItem.scss +41 -0
  59. package/src/report/component/calculator/ReportCalculatorPanel.js +363 -0
  60. package/src/report/component/calculator/ReportCalculatorPanel.scss +86 -0
  61. package/src/report/component/reportpanel/CopyReportPanelController.js +1 -1
  62. package/src/report/component/reportpanel/FilterPanel.js +13 -15
  63. package/src/report/component/reportpanel/FilterPanel.scss +5 -1
  64. package/src/report/component/reportpanel/FormFieldFocusPlugin.js +157 -0
  65. package/src/report/component/reportpanel/FormFieldFocusPlugin.scss +14 -0
  66. package/src/report/component/reportpanel/NorthPanel.js +16 -17
  67. package/src/report/component/reportpanel/NorthPanel.scss +1 -1
  68. package/src/report/component/reportpanel/ReportContextMenu.js +219 -0
  69. package/src/report/component/reportpanel/ReportGrid.js +1 -0
  70. package/src/report/component/reportpanel/ReportGrid.scss +4 -0
  71. package/src/report/component/settings/field/ReportFormFieldsGrid.js +2 -2
  72. package/src/report/component/settings/field/ReportFormFieldsGridController.js +2 -2
  73. package/src/report/component/settings/property/ReportPropertiesPanelController.js +1 -1
  74. package/src/report/component/settings/property/ReportPropertyDictionary.js +7 -0
  75. package/src/report/plugin/configPanel/AddFilterConditionPluginConfigPanel.js +34 -11
  76. package/src/report/plugin/configPanel/GridFiltersPluginConfigPanelFiltersGrid.js +3 -2
  77. package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.js +274 -255
  78. package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.scss +17 -0
  79. package/src/report/plugin/grid/AddFilterConditionPlugin.js +530 -87
  80. package/src/report/plugin/grid/CalculatorPlugin.js +90 -0
  81. package/src/report/plugin/grid/GridContextMenu.js +12 -10
  82. package/src/report/plugin/grid/GridRowCountPlugin.js +0 -1
  83. package/src/report/plugin/grid/GridToolbarButtonPlugin.js +11 -2
  84. package/src/report/plugin/grid/OpenCustomPanelButtonPlugin.js +126 -89
  85. package/src/report/plugin/grid/ReportColumnStatePlugin.js +15 -3
  86. package/src/report/plugin/grid/SetSingleParameterPlugin.js +1 -1
  87. package/src/report/plugin/grid/ToolbarButtonPlugin.js +1 -1
  88. package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanel.js +55 -0
  89. package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanelController.js +226 -0
  90. package/src/report/plugin/grid/addFilterConditionPlugin/FilterConfigMixin.js +138 -0
  91. package/src/report/plugin/grid/addFilterConditionPlugin/FilterFieldFactory.js +223 -0
  92. package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.js +164 -0
  93. package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.scss +21 -0
  94. package/src/report/plugin/grid/addFilterConditionPlugin/FilterMenu.js +29 -0
  95. package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanel.js +53 -0
  96. package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanelController.js +57 -0
  97. package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.js +111 -0
  98. package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.scss +83 -0
  99. package/src/report/plugin/grid/addFilterConditionPlugin/SelectColumnPanel.js +102 -0
  100. package/src/report/selectionModels/MixedRowSelectionModel.js +36 -45
  101. package/src/report/toolbar/dropdown/ToolbarOverflowButton.js +16 -5
  102. package/src/report/toolbar/dropdown/ToolbarOverflowPanel.scss +26 -14
  103. package/src/report/toolbar/layout/ReportToolbarOverflow.js +5 -2
  104. package/src/ringBuffer.js +7 -3
  105. package/src/uielement/command/GetUIElementCommand.js +0 -1
  106. package/src/uielement/component/UiCPWrapper.js +26 -36
  107. package/src/uielement/component/UiCustomController.js +7 -0
  108. package/src/uielement/component/UiCustomPanel.js +46 -2
  109. package/src/uielement/component/settings/UiCustomPanelEditorController.js +35 -29
  110. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.js +146 -33
  111. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.scss +28 -0
  112. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGridController.js +366 -22
  113. package/src/uielement/component/settings/plugin/UiCustomPanelPluginModel.js +1 -0
  114. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanel.js +10 -4
  115. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanelController.js +28 -30
  116. package/src/uielement/plugin/UnifiedButtonToolbarPlugin.js +203 -22
  117. package/src/uielement/plugin/configPanel/ExecuteFunctionPluginConfigPanelFormEditor.js +4 -36
  118. package/src/uielement/plugin/configPanel/FireEventPluginConfigPanelFormEditor.js +5 -36
  119. package/src/uielement/plugin/configPanel/MethodChainPluginConfigPanelFormEditor.js +4 -36
  120. package/src/uielement/plugin/configPanel/OpenPanelPluginConfigPanelFormEditor.js +2 -38
  121. package/src/uielement/plugin/configPanel/PrintPdfPluginConfigPanelFormEditor.js +2 -35
  122. package/src/uielement/plugin/configPanel/UiCPPluginFormPanel.js +54 -0
  123. package/src/uielement/plugin/configPanel/UnifiedButtonToolbarPluginConfigPanelFormEditor.js +28 -18
  124. package/src/userSettings.js +1 -0
  125. package/src/util/ContextManager.js +109 -0
  126. package/src/util.js +96 -15
  127. package/src/version.js +1 -1
  128. package/src/app/viewPort/CenterViewController.js +0 -158
@@ -1,65 +1,172 @@
1
1
  Ext.define('Coon.app.viewPort.CenterView', {
2
- extend: 'Ext.container.Container',
2
+ extend: 'Ext.tab.Panel',
3
3
  xtype: 'centerview',
4
- requires: ['Coon.util'],
5
- controller: 'CenterViewController',
6
- layout: 'card',
7
- viewModel: true,
4
+
5
+ requires: [
6
+ 'Coon.util',
7
+ 'Coon.common.ComponentFactory',
8
+ 'Ext.ux.TabReorderer'
9
+ ],
10
+
11
+ config: {
12
+ tabLimit: 50,
13
+ },
14
+
15
+ plugins: {
16
+ tabreorderer: {
17
+ animate: false,
18
+ },
19
+ },
20
+
21
+ frame: true,
22
+
23
+ cls: 'CenterView',
24
+ bodyCls: 'CenterView-body',
25
+
26
+ tabBar: {
27
+ cls: 'CenterViewTabBar',
28
+ },
29
+
8
30
  defaultComponentType: 'panel',
9
- style: {
10
- backgroundColor: 'white',
31
+
32
+ initComponent() {
33
+ this.callParent();
34
+
35
+ Ext.on('route:change', this.setMenuComponent, this);
36
+
37
+ this.on('beforeadd', function() {
38
+ return !this.isTabLimit();
39
+ }, this);
40
+
41
+ this.on('add', function(_, component) {
42
+ component.on('render', function() {
43
+ this.setScrollButtonVisibility();
44
+ }, this, {single: true});
45
+ }, this);
46
+ this.on('remove', function() {
47
+ this.setScrollButtonVisibility();
48
+ }, this);
11
49
  },
12
- constructor() {
13
- this.callParent(arguments);
14
- this.app = Ext.getApplication();
15
- Ext.on('route:change', this.display.bind(this));
50
+
51
+ setScrollButtonVisibility() {
52
+ if (!this.getTabBar().rendered) {
53
+ return;
54
+ }
55
+ const tabbarEl = this.getTabBar().getEl().down('.x-box-target')?.dom;
56
+ if (!tabbarEl) {
57
+ console.error('tabbar el not found');
58
+ return;
59
+ }
60
+ if (this.isOverflown(tabbarEl)) {
61
+ this.getTabBar().addCls('display-sliders');
62
+ } else {
63
+ this.getTabBar().removeCls('display-sliders');
64
+ }
65
+ },
66
+
67
+ isOverflown(element) {
68
+ return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
16
69
  },
70
+
17
71
  onRender() {
18
72
  this.callParent(arguments);
19
73
  const {initialRoute} = Ext.getApplication();
20
74
  if (initialRoute) {
21
- this.display(initialRoute);
75
+ this.setMenuComponent(initialRoute);
22
76
  }
23
77
  },
24
- findComponent(config) {
25
- return (
26
- this.items &&
27
- this.items.findBy((item) =>
28
- Coon.util.objectsIsEqual(item.initialConfig, config)
29
- )
30
- );
31
- },
32
- resolveComponentType(token) {
33
- let type;
34
- switch (String(token).toUpperCase()) {
35
- case 'R':
36
- type = 'report';
37
- break;
38
- case 'P':
39
- type = 'panel';
40
- break;
78
+
79
+ findComponent(componentContextId) {
80
+ const component = this.getTabComponents()
81
+ .find((cmp) => cmp.componentContextId === componentContextId);
82
+ if (component && !component.destroyed) {
83
+ return component;
41
84
  }
42
- return type || token;
43
85
  },
44
- display(cmp) {
45
- if (!cmp.id) {
86
+
87
+ setMenuComponent(route) {
88
+ Coon.log.debug('display', route);
89
+ if (!route.id) {
46
90
  return;
47
91
  }
48
- Coon.nav.MenuEntity.isValid(cmp.id).then(async (valid) => {
49
- if (valid === true) {
50
- const type = this.resolveComponentType(cmp.type) || this.defaultComponentType;
51
- const config = await this.getController().create(cmp.id, type, cmp.params);
52
- if (config) {
53
- Ext.fireEvent('nav:hide', !!config._preferFullScreen);
54
- const cmp = this.findComponent(config);
55
- const active = this.setActiveItem(
56
- cmp && !cmp.destroyed ? cmp : Ext.create(config)
57
- );
58
- active && active.fireEvent('router:activate', active);
59
- } else {
60
- Ext.fireEvent('route:unmatched');
61
- }
92
+ const existedComponent = this.findComponent(route.id);
93
+ if (existedComponent) {
94
+ this.setActiveTab(existedComponent);
95
+ return;
96
+ }
97
+ const component = Coon.common.ComponentFactory.createTabComponent(route);
98
+ const active = this.setActiveComponent(component);
99
+ active && active.fireEvent('activatecomponent', active);
100
+ },
101
+
102
+ setActiveComponent(component) {
103
+ const routeId = component.menuItem && component.menuItem.MENU_ENTRY_CD ||
104
+ component.reportId || component.uiElementCd;
105
+ Coon.log.debug(
106
+ 'setActiveComponent',
107
+ {
108
+ ui: component.uiElementCd,
109
+ reportId: component.reportId,
110
+ routeId,
111
+ ctx: Coon.util.ContextManager.getContext(component.componentContextId),
112
+ }
113
+
114
+ );
115
+ const previousView = this.getLayout().getActiveItem();
116
+ const isComponentExist = this.findComponent(component.componentContextId);
117
+ if (isComponentExist) {
118
+ return this.setActiveTab(isComponentExist);
119
+ }
120
+ if (previousView) {
121
+ component.prevComponentContextId = previousView.componentContextId;
122
+ }
123
+ this.add(component);
124
+
125
+ component.on('titlechange', function(view, title) {
126
+ if (view.tab) {
127
+ view.tab.setText(title);
62
128
  }
63
129
  });
130
+
131
+ component.on('destroy', function() {
132
+ const activeTab = this.getActiveTab();
133
+ if (!activeTab || !activeTab.menuItem) {
134
+ Ext.fireEvent('nav:menuitemchange');
135
+ Ext.getApplication().appRouter.redirectTo('/', {force: true});
136
+ return;
137
+ }
138
+ Ext.fireEvent('nav:menuitemclick', activeTab.menuItem.MENU_ENTRY_CD);
139
+ }, this);
140
+
141
+ if (!component.menuItem) {
142
+ component.on('close', function() {
143
+ const tab = component.tab;
144
+ this.remove(component);
145
+ this.getTabBar().remove(tab);
146
+ }, this);
147
+ }
148
+
149
+ return this.setActiveTab(component);
150
+ },
151
+
152
+ getTabComponents() {
153
+ return this.getLayout().getLayoutItems();
154
+ },
155
+
156
+ isTabLimit() {
157
+ const tabCount = this.getTabComponents().length;
158
+ if (tabCount === this.getTabLimit()) {
159
+ Ext.Msg.alert(
160
+ `Достигнут лимит`,
161
+ `Превышен лимит вкладок(${this.getTabLimit()}),<br />пожалуйста закройте неиспользуемые!`
162
+ );
163
+ return true;
164
+ }
165
+ },
166
+
167
+ onCloseActiveComponent(component) {
168
+ const previousView = this.findComponent(component.prevComponentContextId);
169
+ previousView && this.setActiveTab(previousView);
64
170
  },
171
+
65
172
  });
@@ -0,0 +1,151 @@
1
+ .CenterView {
2
+ border: none;
3
+ .CenterViewTabBar {
4
+ .x-box-target {
5
+ display: flex;
6
+ flex-flow: row;
7
+ justify-content: flex-start;
8
+ width: 100% !important;
9
+ }
10
+ .x-tab {
11
+ position: relative !important;
12
+ &:not(.x-dd-drag-current) {
13
+ left: 0 !important;
14
+ }
15
+ &.x-dd-drag-current {
16
+ position: absolute !important;
17
+ }
18
+ }
19
+ .x-tab-inner {
20
+ text-overflow: unset;
21
+ overflow: visible;
22
+ }
23
+ .x-tab-inner-default {
24
+ color: #111111;
25
+ font-weight: 400;
26
+ }
27
+ .x-tab-bar-body {
28
+ padding-left: 0;
29
+ }
30
+ .x-tab.x-tab-focus.x-tab-active.x-tab-default {
31
+ border-color: #DEDEDE;
32
+ }
33
+ .x-tab.x-tab-focus.x-tab-default {
34
+ border-color: #DEDEDE;
35
+ }
36
+ span.x-tab-close-btn {
37
+ color: #777!important;
38
+ font-size: 14px!important;
39
+ width: 36px;
40
+ height: 100%;
41
+ background: linear-gradient(90deg, rgba(245,245,245,0) 0%, #F5F5F5 30%);
42
+ &::before {
43
+ width: 100%;
44
+ height: 100%;
45
+ top: 4px;
46
+ position: relative;
47
+ }
48
+ }
49
+ span.x-tab-icon-el {
50
+ mask-size: 16px!important;
51
+ background-color: gray;
52
+ }
53
+ .x-tab-wrap {
54
+ text-transform: none!important;
55
+ display: flex;
56
+ }
57
+ .x-tab {
58
+ border-width: 1px 1px 0 0!important;
59
+ max-width: 300px;
60
+ min-width: 120px;
61
+ padding: 4px 36px 4px 10px;
62
+ border-color: #DEDEDE;
63
+ border-top: 1px solid transparent;
64
+ .x-tab-button {
65
+ display: flex;
66
+ width: 100%;
67
+ padding: 0;
68
+ }
69
+ .x-tab-inner-default {
70
+ text-overflow: ellipsis;
71
+ }
72
+ }
73
+ .x-tab-active {
74
+ background-color: #FFFFFF !important;
75
+ border-width: 1px 1px 0 0!important;
76
+ border-top: 1px solid #DEDEDE;
77
+ .x-tab-inner {
78
+ color: #000000;
79
+ }
80
+ span.x-tab-close-btn {
81
+ background: linear-gradient(90deg, rgba(245,245,245,0) 0%, #fff 30%);
82
+ }
83
+ &.x-tab-over {
84
+ span.x-tab-close-btn {
85
+ background: linear-gradient(90deg, rgba(245,245,245,0) 0%, #fff 30%);
86
+ }
87
+ }
88
+ }
89
+ .x-tab-over {
90
+ background-color: #ECECEC;
91
+ .x-tab-inner-default {
92
+ color: #111;
93
+ }
94
+ span.x-tab-close-btn {
95
+ background: linear-gradient(90deg, rgba(245,245,245,0) 0%, #ECECEC 30%);
96
+ }
97
+ &.x-tab-focus {
98
+ background-color: #ECECEC;
99
+ span.x-tab-close-btn {
100
+ background: linear-gradient(90deg, rgba(245,245,245,0) 0%, #ECECEC 30%);
101
+ }
102
+ }
103
+ &.x-tab-active {
104
+ span.x-tab-close-btn {
105
+ background: linear-gradient(90deg, rgba(245,245,245,0) 0%, #fff 30%);
106
+ }
107
+ }
108
+ }
109
+ .x-tab-focus {
110
+ background-color: #ECECEC;
111
+ }
112
+ }
113
+ .title-block:hover{
114
+ .add-to-favorite:not(.is-favorite-item):hover{
115
+ color: #b4b4b4 !important;
116
+ }
117
+ }
118
+ .title-block{
119
+ .add-to-favorite{
120
+ color: #dddddd !important;
121
+ cursor: pointer;
122
+ font-size: 14px !important;
123
+ }
124
+ .is-favorite-item{
125
+ color: #ff9800 !important;
126
+ }
127
+ }
128
+ .x-box-scroller {
129
+ display: none !important;
130
+ font: 13px / 26px Material Icons, "Font Awesome 5 Free";
131
+ height: 28px;
132
+ &.x-box-scroller-left {
133
+ border-right: solid 1px #dedede;
134
+ }
135
+ &.x-box-scroller-right {
136
+ border-left: solid 1px #dedede;
137
+ }
138
+ }
139
+ .x-box-scroller-body-horizontal {
140
+ margin: 0;
141
+ }
142
+ .display-sliders {
143
+ .x-box-scroller {
144
+ display: block !important;
145
+ }
146
+ .x-box-scroller-body-horizontal {
147
+ margin-left: 24px;
148
+ }
149
+ }
150
+ }
151
+
@@ -0,0 +1,24 @@
1
+ Ext.define('Coon.app.viewPort.ComponentContextManager', {
2
+ contextPropertyName: 'componentContextId',
3
+ alternateClassName: 'Coon.aka.CmpCtxManager',
4
+
5
+ statics: {
6
+ generateContectId(data) {
7
+ return Coon.util.generateHashFromObj(data);
8
+ },
9
+ },
10
+
11
+ constructor(config = {}) {
12
+ if (typeof config.rootId !== 'string' && !config.rootId) {
13
+ throw new Error('ComponentContextManager must have rootId');
14
+ }
15
+ const rootId = config.rootId;
16
+ this.getRootId = function() {
17
+ return rootId;
18
+ };
19
+ },
20
+
21
+ setComponent(component, context) {
22
+ // if
23
+ },
24
+ });
@@ -50,8 +50,11 @@ Ext.define('Coon.app.viewPort.Main', {
50
50
  xtype: 'AppNavigationToggleButton',
51
51
  },
52
52
  {
53
- xtype: 'AppNavigationBar',
53
+ xtype: 'container',
54
54
  flex: 1,
55
+ },
56
+ {
57
+ xtype: 'AppNavCalcButton',
55
58
  }
56
59
  ],
57
60
  },
@@ -0,0 +1,23 @@
1
+ changeUrl->Router.routes./\#r/ReportId{label: загрузить репорт в dev-режиме}
2
+ changeUrl->Router.routes./\#p/CustomPanelId{label: загрузить кастомную панель в dev-режиме}
3
+ changeUrl->Router.routes./\#UiElementCd{label: начитать uiElementCd для загрузки компонента пункта меню}
4
+
5
+ Router: {
6
+ routes: {
7
+ /\#r/ReportId
8
+ /\#p/CustomPanelId
9
+ /\#UiElementCd
10
+ }
11
+ routes./\#r/ReportId -> ReportPanel_create
12
+ routes./\#p/CustomPanelId -> loadUlElement(xtype=UiCustomPanel): async load
13
+ loadUlElement(xtype=UiCustomPanel) -> UiCustomPanel_instancing
14
+ routes./\#UiElementCd -> loadUlElement
15
+ loadUlElement -> 'xtype=ReportPanel'
16
+ loadUlElement -> 'xtype=UiCustomPanel' -> loadUlElement(xtype=UiCustomPanel)
17
+ }
18
+
19
+ Router.loadUlElement.'xtype=ReportPanel' -> ComponentFactory.createRootNavComponent
20
+
21
+ ComponentFactory: {
22
+ createRootNavComponent
23
+ }
@@ -0,0 +1,81 @@
1
+ Ext.define('Coon.app.viewPort.TabHistory', {
2
+ singleton: true,
3
+
4
+
5
+ getCenterView() {
6
+ if (!this.centerview) {
7
+ this.centerview = Ext.ComponentQuery.query('centerview')[0];
8
+ }
9
+ return this.centerview;
10
+ },
11
+
12
+ registerTab(component) {
13
+ const routeId = component.menuItem && component.menuItem.MENU_ENTRY_CD ||
14
+ component.reportId || component.uiElementCd;
15
+ const config = {
16
+ ui: component.uiElementCd,
17
+ reportId: component.reportId,
18
+ routeId,
19
+ ctxId: component.componentContextId,
20
+ text: component.getTitle && component.getTitle(),
21
+ ctx: Coon.util.ContextManager.getContext(component.componentContextId),
22
+ };
23
+ if (!this.inited && this.getHeaderCt()) {
24
+ this.inited = true;
25
+ this.ct.add(this.getHistoryComponent());
26
+ const menu = this.ct.down('#TabHistoryMenu');
27
+ menu.on('click', function(_, item) {
28
+ console.log('item.inHistory', item, item.inHistory);
29
+ if (item.inHistory) {
30
+ return;
31
+ }
32
+ this.getCenterView().setActiveComponent({componentContextId: item.ctxId});
33
+ }, this);
34
+ }
35
+ if (this.inited) {
36
+ const menu = this.ct.down('#TabHistoryMenu');
37
+ console.log('config', config, component);
38
+ component.on('titlechange', function(_, title) {
39
+ menu.down(`[menuItemId=${config.ctxId}]`).setText(title);
40
+ });
41
+ component.on('beforedestroy', function() {
42
+ const menuItem = menu.down(`[menuItemId=${config.ctxId}]`);
43
+ menuItem.inHistory = true;
44
+ menuItem.setIconCls('');
45
+ return true;
46
+ });
47
+ const menuItem = menu.down(`[menuItemId=${config.ctxId}]`);
48
+ if (menuItem) {
49
+ menuItem.inHistory = false;
50
+ menuItem.setIconCls('x-fa fa-home');
51
+ } else {
52
+ menu.add({
53
+ iconCls: 'x-fa fa-home',
54
+ text: config.text || config.routeId,
55
+ menuItemId: config.ctxId,
56
+ });
57
+ }
58
+ }
59
+ },
60
+
61
+ getHistoryComponent() {
62
+ return {
63
+ xtype: 'button',
64
+ text: '...',
65
+ menu: {
66
+ itemId: 'TabHistoryMenu',
67
+ maxWidth: 560,
68
+ margin: 4,
69
+ items: [],
70
+ },
71
+ };
72
+ },
73
+
74
+ getHeaderCt() {
75
+ if (this.ct) {
76
+ return this.ct;
77
+ }
78
+ this.ct = Ext.ComponentQuery.query('#headerFlexCt')[0];
79
+ return this.ct;
80
+ },
81
+ });
@@ -0,0 +1,167 @@
1
+ Ext.define('Coon.common.ComponentFactory', {
2
+ singleton: true,
3
+
4
+ requires: [
5
+ 'Coon.util.ContextManager'
6
+ ],
7
+
8
+ cache: new Map(),
9
+
10
+ triggerPlugin(pluginId, target) {
11
+ if (target && Array.isArray(target.plugins)) {
12
+ const triggerPlugin = target.plugins.find((p) => p.pluginId === pluginId);
13
+ if (triggerPlugin && typeof triggerPlugin.handler === 'function') {
14
+ triggerPlugin.handler.call(triggerPlugin);
15
+ }
16
+ }
17
+ },
18
+
19
+ onActivateComponent(params, cmp) {
20
+ if (cmp.xtype === 'ReportPanel') {
21
+ if (params) {
22
+ cmp.updateFilterDefaults(params);
23
+ if (params.plugin) {
24
+ if (!cmp.grid) {
25
+ cmp.on('gridReady', (reportPanel) => {
26
+ this.triggerPlugin(params.plugin, reportPanel.grid);
27
+ });
28
+ } else {
29
+ this.triggerPlugin(params.plugin, cmp.grid);
30
+ }
31
+ }
32
+ }
33
+ }
34
+ },
35
+
36
+ paramsToObject(params) {
37
+ const entries = [];
38
+ if (Array.isArray(params) && params.length > 1) {
39
+ for (let i = 0; i < Math.floor(params.length / 2); i++) {
40
+ entries.push([params[i * 2], params[i * 2 + 1]]);
41
+ }
42
+ }
43
+ return entries.length ? Object.fromEntries(entries) : null;
44
+ },
45
+
46
+ getRootComponentConfig(route, useCache = true) {
47
+ const {id, params = [], menuItem} = route;
48
+ if (!id) {
49
+ throw new Error('не задан id у пункта меню');
50
+ }
51
+ const uiElementCd = menuItem.UI_ELEMENT_CD;
52
+ const cacheKey = JSON.stringify({uiElementCd, params});
53
+ const cachedComponent = useCache && this.cache.get(cacheKey);
54
+ if (cachedComponent) {
55
+ return cachedComponent;
56
+ }
57
+ const config = route.uiElement;
58
+
59
+ const paramsObject = this.paramsToObject(params);
60
+ const filterDefaults =
61
+ (paramsObject && Object.assign(paramsObject, {doFilter: true})) || {};
62
+
63
+ if (!Ext.isObject(config)) {
64
+ throw new Error('неверный формат элемента пункта меню');
65
+ }
66
+ if (typeof config.propertyData === 'string') {
67
+ config.propertyData = JSON5.parse(
68
+ config.propertyData,
69
+ (key, value) => {
70
+ if (value === 'true') {
71
+ return true;
72
+ }
73
+ if (value === 'false') {
74
+ return false;
75
+ }
76
+ return value;
77
+ }
78
+ );
79
+ }
80
+ Object.assign(
81
+ config,
82
+ {xtype: config.xtype, itemId: uiElementCd},
83
+ config.propertyData
84
+ );
85
+ if (config.xtype === 'ReportPanel') {
86
+ Object.assign(config, {
87
+ filterDefaults,
88
+ listeners: {
89
+ activatecomponent: this.onActivateComponent.bind(
90
+ this,
91
+ paramsObject
92
+ ),
93
+ },
94
+ });
95
+ } else if (config.xtype === 'UiCustomPanel') {
96
+ Object.assign(config, {
97
+ listeners: {
98
+ activatecomponent: this.onActivateComponent.bind(
99
+ this,
100
+ paramsObject
101
+ ),
102
+ afterrender(panel) {
103
+ Coon.Function.executeComponentDoInit(panel, paramsObject);
104
+ },
105
+ },
106
+ });
107
+ } else {
108
+ Object.assign(config, {
109
+ listeners: {
110
+ afterrender(panel) {
111
+ Coon.Function.executeComponentDoInit(panel, paramsObject);
112
+ },
113
+ },
114
+ });
115
+ }
116
+
117
+ config.menuItem = menuItem;
118
+
119
+ config.ctxMgr = Coon.util.ContextManager;
120
+ config.componentContextId = config.ctxMgr.createContext(null, {
121
+ params,
122
+ menuItem,
123
+ }, route.id);
124
+ cacheKey && this.cache.set(cacheKey, config);
125
+ return config;
126
+ },
127
+
128
+ createTabComponent(route) {
129
+ const config = this.getRootComponentConfig(route);
130
+ const menuItem = config.menuItem;
131
+ config.layout = config.layout || 'fit';
132
+ const onIconClick = function() {
133
+ if (menuItem) {
134
+ Ext.fireEvent('nav:menuitemtofavoriteclick', menuItem.MENU_ENTRY_CD, false);
135
+ }
136
+ };
137
+ if (menuItem) {
138
+ config.title = {
139
+ xtype: 'title',
140
+ cls: 'title-block',
141
+ iconCls: 'fa fa-star add-to-favorite',
142
+ title: menuItem.MENU_ENTRY_DESCR,
143
+ listeners: {
144
+ click: onIconClick,
145
+ element: 'iconEl',
146
+ },
147
+ };
148
+ }
149
+ const instanceConfig = {
150
+ xtype: 'CVWrapperPanel',
151
+ closable: true,
152
+ componentContext: config.componentContext,
153
+ menuItem: config.menuItem,
154
+ componentContextId: route.id,
155
+ tabConfig: {
156
+ title: menuItem.MENU_ENTRY_DESCR,
157
+ tooltip: menuItem.MENU_ENTRY_DESCR,
158
+ iconCls: menuItem.MENU_ENTRY_ICON,
159
+ },
160
+ items: [config],
161
+ title: menuItem.MENU_ENTRY_DESCR,
162
+ };
163
+ const instance = Ext.create(instanceConfig);
164
+ return instance;
165
+ },
166
+
167
+ });