ru.coon 2.8.65 → 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 (130) hide show
  1. package/CHANGELOG.md +319 -6
  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/editor/EditorFactory.js +3 -1
  22. package/src/common/component/formeditor/UiCustomFilterForm.scss +0 -1
  23. package/src/common/component/settings/modules/settingClosePageConfirmation.js +1 -3
  24. package/src/common/component/settings/modules/settingFavoritePanelShow.js +21 -0
  25. package/src/common/component/settings/modules/settingReportCalculator.js +22 -0
  26. package/src/common/component/settings/modules/settingShowNeedReloadMessage.js +1 -3
  27. package/src/common/component/settings/modules/settingwindowHolder.js +2 -3
  28. package/src/common/panel/WindowWrap.js +19 -11
  29. package/src/common/tree/BaseContextMenu.js +4 -3
  30. package/src/log.js +4 -5
  31. package/src/nav/AppNavCalcButton.js +23 -0
  32. package/src/nav/AppNavCalcButton.scss +6 -0
  33. package/src/nav/AppNavigationBar.js +1 -1
  34. package/src/nav/AppNavigationMenuController.js +2 -2
  35. package/src/nav/AppNavigationMenuMinimized.js +61 -0
  36. package/src/nav/AppNavigationPanel.js +115 -0
  37. package/src/nav/AppNavigationPanel.scss +178 -0
  38. package/src/nav/AppNavigationPanelController.js +386 -0
  39. package/src/nav/FavoriteCfg.js +18 -0
  40. package/src/nav/MenuEntity.js +23 -15
  41. package/src/nav/MenuFavoritesBar.js +100 -0
  42. package/src/nav/MenuFavoritesBar.scss +92 -0
  43. package/src/nav/editor/NavigateElementEditorView.js +2 -2
  44. package/src/nav/editor/workspace/NavWorkspaceListView.js +1 -4
  45. package/src/nav/menu/WorkspaceMenuViewMinimized.js +22 -0
  46. package/src/overrides/panel/TabPanel.js +36 -0
  47. package/src/overrides/panel/TabPanel.scss +65 -0
  48. package/src/report/component/ClearFiltersButton.js +4 -1
  49. package/src/report/component/CopyCellValueMenuItem.js +18 -0
  50. package/src/report/component/ReportFieldMap.js +274 -0
  51. package/src/report/component/ReportPanel.js +73 -44
  52. package/src/report/component/ReportPanel.scss +2 -2
  53. package/src/report/component/ReportTagLookup.js +59 -2
  54. package/src/report/component/calculator/ReportCalculatorController.js +266 -0
  55. package/src/report/component/calculator/ReportCalculatorField.js +47 -0
  56. package/src/report/component/calculator/ReportCalculatorHistoryPlugin.js +128 -0
  57. package/src/report/component/calculator/ReportCalculatorHistoryPlugin.scss +33 -0
  58. package/src/report/component/calculator/ReportCalculatorMenuItem.js +101 -0
  59. package/src/report/component/calculator/ReportCalculatorMenuItem.scss +41 -0
  60. package/src/report/component/calculator/ReportCalculatorPanel.js +363 -0
  61. package/src/report/component/calculator/ReportCalculatorPanel.scss +86 -0
  62. package/src/report/component/reportpanel/CopyReportPanelController.js +1 -1
  63. package/src/report/component/reportpanel/FilterPanel.js +13 -15
  64. package/src/report/component/reportpanel/FilterPanel.scss +5 -1
  65. package/src/report/component/reportpanel/FormFieldFocusPlugin.js +157 -0
  66. package/src/report/component/reportpanel/FormFieldFocusPlugin.scss +14 -0
  67. package/src/report/component/reportpanel/NorthPanel.js +16 -17
  68. package/src/report/component/reportpanel/NorthPanel.scss +1 -1
  69. package/src/report/component/reportpanel/ReportContextMenu.js +219 -0
  70. package/src/report/component/reportpanel/ReportGrid.js +1 -0
  71. package/src/report/component/reportpanel/ReportGrid.scss +4 -0
  72. package/src/report/component/settings/field/ReportFormFieldsGrid.js +2 -2
  73. package/src/report/component/settings/field/ReportFormFieldsGridController.js +2 -2
  74. package/src/report/component/settings/property/ReportPropertiesPanelController.js +1 -1
  75. package/src/report/component/settings/property/ReportPropertyDictionary.js +7 -0
  76. package/src/report/plugin/configPanel/AddFilterConditionPluginConfigPanel.js +34 -11
  77. package/src/report/plugin/configPanel/GridFiltersPluginConfigPanelFiltersGrid.js +3 -2
  78. package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.js +274 -255
  79. package/src/report/plugin/configPanel/openCustomPanelButtonPlugin/OpenCustomPanelButtonPluginConfigPanel.scss +17 -0
  80. package/src/report/plugin/grid/AddFilterConditionPlugin.js +530 -87
  81. package/src/report/plugin/grid/CalculatorPlugin.js +90 -0
  82. package/src/report/plugin/grid/GridContextMenu.js +12 -10
  83. package/src/report/plugin/grid/GridRowCountPlugin.js +0 -1
  84. package/src/report/plugin/grid/GridToolbarButtonPlugin.js +11 -2
  85. package/src/report/plugin/grid/OpenCustomPanelButtonPlugin.js +126 -89
  86. package/src/report/plugin/grid/ReportCharacteristicBindPlugin.js +6 -4
  87. package/src/report/plugin/grid/ReportColumnStatePlugin.js +15 -3
  88. package/src/report/plugin/grid/SetSingleParameterPlugin.js +1 -1
  89. package/src/report/plugin/grid/ToolbarButtonPlugin.js +1 -1
  90. package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanel.js +55 -0
  91. package/src/report/plugin/grid/addFilterConditionPlugin/AdvancedSearchPanelController.js +226 -0
  92. package/src/report/plugin/grid/addFilterConditionPlugin/FilterConfigMixin.js +138 -0
  93. package/src/report/plugin/grid/addFilterConditionPlugin/FilterFieldFactory.js +223 -0
  94. package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.js +164 -0
  95. package/src/report/plugin/grid/addFilterConditionPlugin/FilterItem.scss +21 -0
  96. package/src/report/plugin/grid/addFilterConditionPlugin/FilterMenu.js +29 -0
  97. package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanel.js +53 -0
  98. package/src/report/plugin/grid/addFilterConditionPlugin/FilterWrapPanelController.js +57 -0
  99. package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.js +111 -0
  100. package/src/report/plugin/grid/addFilterConditionPlugin/InfoMenuItem.scss +83 -0
  101. package/src/report/plugin/grid/addFilterConditionPlugin/SelectColumnPanel.js +102 -0
  102. package/src/report/selectionModels/MixedRowSelectionModel.js +36 -45
  103. package/src/report/toolbar/dropdown/ToolbarOverflowButton.js +16 -5
  104. package/src/report/toolbar/dropdown/ToolbarOverflowPanel.scss +26 -14
  105. package/src/report/toolbar/layout/ReportToolbarOverflow.js +5 -2
  106. package/src/ringBuffer.js +7 -3
  107. package/src/uielement/command/GetUIElementCommand.js +0 -1
  108. package/src/uielement/component/UiCPWrapper.js +26 -36
  109. package/src/uielement/component/UiCustomController.js +7 -0
  110. package/src/uielement/component/UiCustomPanel.js +46 -2
  111. package/src/uielement/component/settings/UiCustomPanelEditorController.js +35 -29
  112. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.js +146 -33
  113. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGrid.scss +28 -0
  114. package/src/uielement/component/settings/plugin/UiCustomPanelPluginGridController.js +366 -22
  115. package/src/uielement/component/settings/plugin/UiCustomPanelPluginModel.js +1 -0
  116. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanel.js +10 -4
  117. package/src/uielement/component/settings/plugin/UiCustomPanelPluginPanelController.js +28 -30
  118. package/src/uielement/plugin/UnifiedButtonToolbarPlugin.js +203 -22
  119. package/src/uielement/plugin/configPanel/ExecuteFunctionPluginConfigPanelFormEditor.js +4 -36
  120. package/src/uielement/plugin/configPanel/FireEventPluginConfigPanelFormEditor.js +5 -36
  121. package/src/uielement/plugin/configPanel/MethodChainPluginConfigPanelFormEditor.js +4 -36
  122. package/src/uielement/plugin/configPanel/OpenPanelPluginConfigPanelFormEditor.js +2 -38
  123. package/src/uielement/plugin/configPanel/PrintPdfPluginConfigPanelFormEditor.js +2 -35
  124. package/src/uielement/plugin/configPanel/UiCPPluginFormPanel.js +54 -0
  125. package/src/uielement/plugin/configPanel/UnifiedButtonToolbarPluginConfigPanelFormEditor.js +28 -18
  126. package/src/userSettings.js +1 -0
  127. package/src/util/ContextManager.js +109 -0
  128. package/src/util.js +96 -15
  129. package/src/version.js +1 -1
  130. package/src/app/viewPort/CenterViewController.js +0 -158
@@ -0,0 +1,115 @@
1
+ Ext.define('Coon.nav.menu.AppNavigationPanel', {
2
+ extend: 'Ext.panel.Panel',
3
+ xtype: 'AppNavigationPanel',
4
+ cls: 'AppNavigationPanel',
5
+ padding: 0,
6
+ controller: 'AppNavigationPanelController',
7
+ layout: {
8
+ type: 'hbox',
9
+ align: 'stretch',
10
+ },
11
+
12
+ title: 'меню навигации',
13
+
14
+ mixin: [
15
+ 'Ext.mixin.Responsive'
16
+ ],
17
+ /* listeners: {
18
+ render: 'onRenderPanel',
19
+ },*/
20
+ viewModel: {
21
+ data: {
22
+ favorites: {},
23
+ map: [],
24
+ },
25
+ stores: {
26
+ spacesStore: {
27
+ type: 'json',
28
+ data: [],
29
+ },
30
+ searchStore: {
31
+ type: 'json',
32
+ data: [],
33
+ },
34
+ },
35
+ },
36
+ tbar: {
37
+ cls: 'no-shadow',
38
+ items: [
39
+ {
40
+ xtype: 'combo',
41
+ emptyText: 'Поиск',
42
+ width: 300,
43
+ margin: '0 40px 0 0',
44
+ bind: {
45
+ store: '{searchStore}',
46
+ },
47
+ queryMode: 'local',
48
+ valueField: 'MENU_ENTRY_CD',
49
+ displayField: 'text',
50
+ anyMatch: true,
51
+ caseSensitive: false,
52
+ listeners: {
53
+ select: 'onChangeSearchCombo',
54
+ },
55
+ clearFilterOnBlur: false,
56
+ tpl: Ext.create('Ext.XTemplate',
57
+ `<ul class="x-list-plain"><tpl for=".">
58
+ <li role="option" class="x-boundlist-item">{[this.getText(values.WORKSPACE_DESCR,values.text)]}</li>
59
+ </tpl></ul>`,
60
+ {
61
+ // XTemplate configuration:
62
+ disableFormats: true,
63
+ // member functions:
64
+ getText: function(space, text) {
65
+ const value = this.owner.ownerCmp.getValue() || '';
66
+ if (value) {
67
+ return `${space} / ` + text.replaceAll(value, `<span class="search-compare">${value}</span>`);
68
+ } else {
69
+ return `${space} / ${text}`;
70
+ }
71
+ },
72
+ }
73
+ ),
74
+ }
75
+ ],
76
+ },
77
+ items: [{
78
+
79
+ xtype: 'grid',
80
+ reference: 'spacesPanel',
81
+ cls: 'spaces-panel',
82
+ width: 300,
83
+ header: false,
84
+ bodyPadding: '0 10px',
85
+ bind: {
86
+ store: '{spacesStore}',
87
+ },
88
+ listeners: {
89
+ itemmouseup: 'onGridMouseUp',
90
+ },
91
+ columns: [{
92
+ xtype: 'templatecolumn',
93
+ tpl: '<i class="workspace-icon {iconCls}"></i><div class="workspace-text">{text}</div>',
94
+ flex: 1,
95
+ }],
96
+ }, {
97
+ xtype: 'panel',
98
+ reference: 'menuPanel',
99
+ cls: 'menu-panel',
100
+ flex: 1,
101
+ layout: 'card',
102
+ items: [],
103
+ }],
104
+
105
+ menuItemTpl: new Ext.XTemplate(
106
+ `<li class="ref-item {isSelected}" data-removed="{remove}">
107
+ <span class="item-icon" onclick="Ext.fireEvent('nav:menuitemtofavoriteclick','{MENU_ENTRY_CD}',this);">
108
+ <i class="star svg-icon svg-icon-star-16 icon-orange {isFavorite}"></i>
109
+ </span>
110
+ <span class="item-text" onclick="Ext.fireEvent('nav:menuitemclick', '{MENU_ENTRY_CD}');">
111
+ {text}</span>
112
+ </li>`
113
+ ),
114
+
115
+ });
@@ -0,0 +1,178 @@
1
+ .svg-icon-size-18{
2
+ mask-size: 18px;
3
+ }
4
+ .search-compare{
5
+ background-color: #ffcd29 !important;
6
+ }
7
+ .AppNavigationPanel{
8
+ .no-shadow{
9
+ box-shadow: none !important;
10
+ }
11
+ .x-grid-cell-inner{
12
+ margin: 2px 0;
13
+ display: flex;
14
+ align-items: center;
15
+ }
16
+ .activeToggle{
17
+ color: #A9A9A9;
18
+ }
19
+ .inactiveToggle{
20
+ color: #D0D0D0;
21
+ }
22
+ .btn-toggle{
23
+ height: 20px !important;
24
+ padding: 5px !important;
25
+ }
26
+
27
+ .x-btn-pressed{
28
+ background-color: transparent !important;
29
+ }
30
+
31
+ .favorite-title{
32
+ margin-left: 20px;
33
+ }
34
+
35
+ .workspace-icon{
36
+ display: inline-block;
37
+ width: 24px;
38
+ height: 24px;
39
+ background-color: #3D6780;
40
+ }
41
+ .workspace-text{
42
+ display: inline-block;
43
+ margin-left: 10px;
44
+ }
45
+ .x-grid-with-row-lines .x-grid-item{
46
+ border: none;
47
+ }
48
+
49
+ .selected-item {
50
+ .item-text{
51
+ color: black;
52
+ background-color: #F5F5F5;
53
+ padding-right: 16px;
54
+ }
55
+ .item-icon{
56
+ background-color: #F5F5F5;
57
+ }
58
+
59
+
60
+
61
+ }
62
+ .is-favorite-item{
63
+ background-color: #ff9800 !important;
64
+ }
65
+ .item-icon:hover{
66
+ i:not(.is-favorite-item) {
67
+ background-color: #b4b4b4 !important;
68
+ }
69
+ }
70
+ .flex-container .x-autocontainer-innerCt{
71
+ display: flex;
72
+ flex-wrap: wrap;
73
+ ul{
74
+ width: 400px;
75
+ list-style: none;
76
+ padding-left: 10px;
77
+ li{
78
+ margin: 10px 0;
79
+ color: #1E3B4C;
80
+ display: block;
81
+ .parent-menu-item{
82
+ color: #112b39;
83
+ font-weight: 600;
84
+ }
85
+ }
86
+ .item-icon{
87
+ width: 20px;
88
+ min-width: 20px;
89
+ height: 20px;
90
+ display: inline-block;
91
+ }
92
+ .star{
93
+ width: 20px;
94
+ height: 18px;
95
+ display: none;
96
+ }
97
+ .icon-orange {
98
+ background-color: #ff9800;
99
+ }
100
+
101
+ .item-text{
102
+ display: inline-block;
103
+ }
104
+ li.ref-item {
105
+ display: flex;
106
+ flex-wrap: nowrap;
107
+ cursor: pointer;
108
+ }
109
+ li.ref-item:hover {
110
+ .item-text{
111
+ //background-color: #F5F5F5;
112
+ color: black;
113
+ }
114
+ .item-icon{
115
+ //background-color: #F5F5F5;
116
+ }
117
+ .icon-orange{
118
+ background-color: #dddddd;
119
+ }
120
+ .star{
121
+ display: block;
122
+
123
+ }
124
+
125
+ }
126
+ .is-favorite-item{
127
+ display: block !important;
128
+ }
129
+ }
130
+ }
131
+
132
+ .spaces-panel{
133
+ .x-grid-body{
134
+ border: none;
135
+ }
136
+ .x-grid-item-selected{
137
+ background-color: #F5F5F5;
138
+ .x-grid-cell::before {
139
+ background-color: #9a2d2a;
140
+ content: " ";
141
+ position: absolute;
142
+ display: block;
143
+ left: 0;
144
+ top: 0;
145
+ width: 5px;
146
+ height: 100%;
147
+ }
148
+ .workspace-text {
149
+ color: #111111;
150
+ }
151
+ .workspace-icon{
152
+ background-color: #1E3B4C;
153
+ }
154
+ }
155
+ .x-grid-item-over{
156
+ background-color: #F5F5F5;
157
+ }
158
+ .workspace-text {
159
+ margin-right: 0;
160
+ font-size: 14px;
161
+ line-height: 20px;
162
+ font-weight: normal;
163
+ white-space: pre-wrap;
164
+ }
165
+ .x-grid-cell-inner{
166
+ i {
167
+ margin: 0 10px 0 10px;
168
+ }
169
+ cursor: pointer;
170
+ }
171
+ }
172
+
173
+ .menu-panel {
174
+ .x-panel-body {
175
+ overflow-x: hidden !important;
176
+ }
177
+ }
178
+ }
@@ -0,0 +1,386 @@
1
+ /* eslint-disable require-jsdoc */
2
+ Ext.define('Coon.nav.AppNavigationPanelController', {
3
+ extend: 'Ext.app.ViewController',
4
+ requires: [
5
+ 'Coon.nav.AppNavTab',
6
+ 'Coon.setup',
7
+ 'Coon.eventBus',
8
+ 'Coon.common.UserPropStorage'
9
+ ],
10
+ alias: 'controller.AppNavigationPanelController',
11
+ menuRendered: false,
12
+ mouseInFlag: true,
13
+ addWorkspaceToUrl: false,
14
+ menuReady: false,
15
+ router: null,
16
+ locals: {
17
+ data: null,
18
+ savedWsMenuLinks: {},
19
+ },
20
+
21
+ init() {
22
+ this.router = Ext.getApplication().appRouter;
23
+ this.lastRoute = this.router && this.router.lastRoute;
24
+ this.renderMenu();
25
+ this.getView().on('ownerShow', () => {
26
+ const panel = this.lookup('menuPanel').layout.getActiveItem();
27
+ if (panel) {
28
+ const cardId = panel.itemId;
29
+ const active = panel.down('[reference="menuInterface"]').layout.getActiveItem();
30
+ if (active && cardId) {
31
+ if (active.reference === 'menuView') {
32
+ this.updateMenuView(cardId, active);
33
+ } else {
34
+ this.updateFavoriteView(cardId, active);
35
+ }
36
+ }
37
+ }
38
+ }, this);
39
+ Ext.on({
40
+ 'nav:menuitemtofavoriteclick': {fn: this.onMenuItemToFavoriteClick, scope: this},
41
+ 'nav:menuitemclick': {fn: this.onMenuItemClick, scope: this},
42
+ 'nav:reload': {fn: this.updateMenu, scope: this},
43
+ 'route:change': {
44
+ fn: (route) => {
45
+ this.setActiveMenuItem(route.id);
46
+ },
47
+ scope: this,
48
+ },
49
+ 'route:unmatched': {fn: () => {
50
+ this.goTo(this.getFirstAvailable());
51
+ }, scope: this},
52
+ });
53
+ this.lookup('spacesPanel').on({
54
+ itemmouseenter: {fn: this.onGridMouseUp, scope: this, buffer: 600},
55
+ beforeitemmouseenter: {fn: this.mouseIn, scope: this},
56
+ beforeitemmouseleave: {fn: this.mouseOut, scope: this},
57
+ });
58
+ },
59
+ onMenuItemToFavoriteClick(menuEntryCd, cmp) {
60
+ const props = Coon.nav.menu.FavoriteCfg.get().favorite || [];
61
+ const index = props.indexOf(menuEntryCd);
62
+ index >= 0 ? props.splice(index, 1) : props.push(menuEntryCd);
63
+ const state = index >= 0 ? 'remove' : 'add';
64
+ Coon.nav.menu.FavoriteCfg.set({favorite: props});
65
+ if (cmp) {
66
+ if (index >= 0) {
67
+ if (cmp.parentNode.getAttribute('data-removed') === 'true') {
68
+ cmp.parentNode.parentNode.removeChild(cmp.parentNode);
69
+ } else {
70
+ cmp.firstElementChild.classList.remove('is-favorite-item');
71
+ }
72
+ } else if (!cmp.firstElementChild.classList.contains('is-favorite-item')) {
73
+ cmp.firstElementChild.classList.add('is-favorite-item');
74
+ }
75
+ }
76
+ Ext.fireEvent('nav:favoriteitemschange', menuEntryCd, state);
77
+ },
78
+
79
+ setActiveMenuItem(menuEntryCd) {
80
+ const item = this.locals.data.menu.find((el) => el.MENU_ENTRY_CD === menuEntryCd);
81
+ if (!item) {
82
+ return;
83
+ }
84
+ document.title = item.text;
85
+ Ext.fireEvent('nav:menuitemchange', item, this);
86
+ this.changeWorkSpace(item.WORKSPACE_CD);
87
+ },
88
+
89
+ changeWorkSpace(id) {
90
+ if (!this.menuReady || !id) {
91
+ return;
92
+ }
93
+ const index = this.getViewModel().get('map').indexOf(id);
94
+ const rec = this.getViewModel().getStore('spacesStore').getAt(index);
95
+ this.lookup('spacesPanel').setSelection(rec);
96
+ this.lookup('menuPanel').setActiveItem(index);
97
+ },
98
+
99
+ getFirstAvailable() {
100
+ const ws = [...this.locals.data.ws.values()][0];
101
+ const item = ws && this.locals.data.menu.find((el) => el.WORKSPACE_CD === ws.ws);
102
+ return ws && item && item.MENU_ENTRY_CD;
103
+ },
104
+
105
+ async onMenuReady() {
106
+ const isValidLastRoute = this.lastRoute && this.lastRoute.id && await Coon.nav.MenuEntity.isValid(this.lastRoute.id);
107
+ if (isValidLastRoute) {
108
+ this.setActiveMenuItem(this.lastRoute.id);
109
+ } else {
110
+ this.goTo(this.getFirstAvailable());
111
+ }
112
+ },
113
+ goTo(menuEntryCd, force = false) {
114
+ if (menuEntryCd) {
115
+ let prefix = '';
116
+ if (this.addWorkspaceToUrl) {
117
+ const ws = this.getViewModel().get('workspace') || this.getFirstAvailable().ws.ws;
118
+ prefix = ws && ws + '/';
119
+ }
120
+ this.router.redirectTo(prefix + menuEntryCd, {force});
121
+ }
122
+ },
123
+
124
+ onMenuItemClick(menuEntryCd) {
125
+ this.goTo(menuEntryCd);
126
+ },
127
+ mouseOut() {
128
+ this.mouseInFlag = false;
129
+ },
130
+ mouseIn() {
131
+ this.mouseInFlag = true;
132
+ },
133
+ onGridMouseUp(el, rec) {
134
+ if (!this.mouseInFlag) {
135
+ return false;
136
+ }
137
+ this.changeWorkSpace(rec.get('value'));
138
+ },
139
+
140
+ prepareMenuData(data) {
141
+ return data;
142
+ },
143
+
144
+ onMenuPanelBeforeActivate(panel) {
145
+ const activeView = panel.down('[reference="menuInterface"]').layout.getActiveItem();
146
+ if (activeView.reference === 'favoriteView') {
147
+ this.updateFavoriteView(panel.itemId, activeView);
148
+ } else {
149
+ this.updateMenuView(panel.itemId, activeView);
150
+ }
151
+ },
152
+
153
+ updateMenu: function() {
154
+ Coon.nav.MenuEntity.menuItems = null;
155
+ this.renderMenu();
156
+ },
157
+
158
+ renderMenu() {
159
+ this.menuReady = false;
160
+ // view.mask();
161
+ const vm = this.getViewModel();
162
+ vm.getStore('spacesStore').removeAll();
163
+ vm.getStore('searchStore').removeAll();
164
+ // this.lookup('menuPanel').removeAll();
165
+ Coon.nav.MenuEntity.get().then((menu) => {
166
+ if (Array.isArray(menu)) {
167
+ const dataList = this.prepareMenuData(menu);
168
+ const transformData = dataList.map((el) => {
169
+ return Coon.Function.convertObjectByMapping(el, {
170
+ MENU_ENTRY_ICON: 'iconCls',
171
+ MENU_ENTRY_DESCR: 'text',
172
+ });
173
+ });
174
+ this.locals.data = transformData.reduce((acc, el) => {
175
+ acc.ws.set(el.WORKSPACE_CD, {
176
+ ws: el.WORKSPACE_CD,
177
+ text: el.WORKSPACE_DESCR,
178
+ iconCls: el.WORKSPACE_ICON,
179
+ });
180
+ acc.items[el.WORKSPACE_CD] = acc.items[el.WORKSPACE_CD] || {};
181
+ acc.items[el.WORKSPACE_CD][el.MENU_ENTRY_CD] = el;
182
+ acc.menu.push(el);
183
+ return acc;
184
+ }, {ws: new Map(), items: {}, menu: []});
185
+
186
+ const items = [];
187
+ const me = this;
188
+ this.locals.data.ws.forEach((item) => {
189
+ items.push({
190
+ text: item.text,
191
+ width: this.getView().fullWidth,
192
+ value: item.ws,
193
+ iconCls: item.iconCls,
194
+ handler: function() {
195
+ me.changeWorkspace(this.value);
196
+ },
197
+ });
198
+ });
199
+ vm.getStore('spacesStore').loadData(items);
200
+ vm.getStore('searchStore').loadData(this.locals.data.menu);
201
+
202
+ const listToTree = (list) => {
203
+ const map = {}; const roots = [];
204
+ let node;
205
+ for (let i = 0; i < list.length; i += 1) {
206
+ map[list[i].MENU_ENTRY_CD] = i; // initialize the map
207
+ list[i].children = []; // initialize the children
208
+ }
209
+ for (let i = 0; i < list.length; i += 1) {
210
+ node = list[i];
211
+ node.PARENT_MENU_ENTRY_CD = node.PARENT_MENU_ENTRY_CD || '0';
212
+ if (node.PARENT_MENU_ENTRY_CD !== '0') {
213
+ // if you have dangling branches check that map[node.parentId] exists
214
+ list[map[node.PARENT_MENU_ENTRY_CD]].children.push(node);
215
+ } else {
216
+ roots.push(node);
217
+ }
218
+ }
219
+ return roots;
220
+ };
221
+
222
+ Object.entries(this.locals.data.items).forEach(function(workspace) {
223
+ const [workspaceId, workspaceItems] = workspace;
224
+ this.locals.data.items[workspaceId] = listToTree(Object.values(workspaceItems));
225
+ }, this);
226
+
227
+ const menuPanel = this.lookup('menuPanel');
228
+ const map = [];
229
+ this.locals.data.ws.forEach((workSpace) => {
230
+ map.push(workSpace.ws);
231
+ menuPanel.add({
232
+ xtype: 'panel',
233
+ bodyPadding: '10px 0 0 0',
234
+ style: {
235
+ border: '1px solid #dddddd',
236
+ },
237
+ title: workSpace.text,
238
+ scrollable: true,
239
+ listeners: {
240
+ activate: 'onMenuPanelBeforeActivate',
241
+ },
242
+ itemId: workSpace.ws,
243
+ items: [{
244
+ xtype: 'container',
245
+ colspan: 10,
246
+ layout: 'hbox',
247
+ items: [{
248
+ xtype: 'container',
249
+ margin: '8px 0 8px 8px',
250
+ html: '<span class="favorite-title">Избранное</span>',
251
+ }, {
252
+ xtype: 'button',
253
+ padding: '10px 16px 8px 6px',
254
+ focusOnToFront: false,
255
+ focusable: false,
256
+ overCls: '',
257
+ focusCls: '',
258
+ style: {
259
+ backgroundColor: 'transparent!important',
260
+ marginRight: '20px',
261
+ },
262
+ iconCls: 'x-fa fa-toggle-on inactiveToggle',
263
+ handler: this.onFavoriteClick.bind(this),
264
+ bind: {
265
+ // eslint-disable-next-line max-len
266
+ iconCls: `{favorites.${workSpace.ws} ? 'x-fa fa-toggle-on fa-rotate-180 activeToggle' : 'x-fa fa-toggle-on inactiveToggle'}`,
267
+ },
268
+ }],
269
+ }, {
270
+ xtype: 'panel',
271
+ reference: 'menuInterface',
272
+ layout: 'card',
273
+
274
+ items: [
275
+ {
276
+ xtype: 'panel',
277
+ reference: 'menuView',
278
+ cls: 'flex-container',
279
+ },
280
+ {
281
+ xtype: 'panel',
282
+ reference: 'favoriteView',
283
+ cls: 'flex-container',
284
+ }
285
+ ],
286
+ }],
287
+ });
288
+ });
289
+ this.getViewModel().set('map', map);
290
+ this.menuReady = true;
291
+ Ext.fireEvent('nav:ready');
292
+ this.onMenuReady();
293
+ }
294
+ // view.unmask();
295
+ });
296
+ },
297
+
298
+ getMenuItemHtml(menuItem) {
299
+ return this.getView().menuItemTpl.apply(menuItem);
300
+ },
301
+
302
+ updateMenuView(cardId, panel) {
303
+ const selected = this.router.lastRoute?.id || '';
304
+ const props = Coon.nav.menu.FavoriteCfg.get().favorite || [];
305
+ const createItemsTemplate = (item) => {
306
+ item.isFavorite = props.indexOf(item.MENU_ENTRY_CD) >= 0 ? 'is-favorite-item' : '';
307
+ item.isSelected = selected === item.MENU_ENTRY_CD ? 'selected-item' : '';
308
+ item.remove = false;
309
+ if (!item.children[0]) {
310
+ return this.getMenuItemHtml(item);
311
+ }
312
+ let res = `<li><span class="parent-menu-item">${item.text}</span><ul>`;
313
+ item.children.forEach((child) => {
314
+ res += createItemsTemplate(child);
315
+ });
316
+ res += '</ul></li>';
317
+ return res;
318
+ };
319
+
320
+ const panels = [];
321
+ const html = [];
322
+ this.locals.data.items[cardId].forEach((item) => {
323
+ item.remove = false;
324
+ if (item.children[0]) {
325
+ panels.push(`<ul>${createItemsTemplate(item)}</ul>`);
326
+ } else {
327
+ item.isFavorite = props.indexOf(item.MENU_ENTRY_CD) >= 0 ? 'is-favorite-item' : '';
328
+ item.isSelected = selected === item.MENU_ENTRY_CD ? 'selected-item' : '';
329
+ html.push(this.getMenuItemHtml(item));
330
+ }
331
+ });
332
+ if (html.length) {
333
+ panels.splice(0, 0, `<ul>${html.join('')}</ul>`);
334
+ }
335
+ panel.setHtml(`${panels.join('')}`);
336
+ },
337
+
338
+ updateFavoriteView(cardId, panel) {
339
+ const props = Coon.nav.menu.FavoriteCfg.get().favorite || [];
340
+ const selected = this.router.lastRoute?.id || '';
341
+ if (props.length) {
342
+ const createItemsTemplate = (item) => {
343
+ item.isFavorite = props.indexOf(item.MENU_ENTRY_CD) >= 0 ? 'is-favorite-item' : '';
344
+ item.isSelected = selected === item.MENU_ENTRY_CD ? 'selected-item' : '';
345
+ item.remove = true;
346
+ if (!item.children[0]) {
347
+ return item.isFavorite ? this.getMenuItemHtml(item) : '';
348
+ }
349
+ let res = '';
350
+ item.children.forEach((child) => {
351
+ res += createItemsTemplate(child);
352
+ });
353
+ return res;
354
+ };
355
+ let res = '';
356
+ this.locals.data.items[cardId].forEach((item) => {
357
+ res += createItemsTemplate(item);
358
+ });
359
+ panel.setHtml(`<ul>${res}</ul>`);
360
+ }
361
+ },
362
+
363
+ onFavoriteClick(cmp) {
364
+ const vm = this.getViewModel();
365
+ const favorites = vm.get('favorites');
366
+ const cardId = cmp.up('panel').itemId;
367
+ favorites[cardId] = !favorites[cardId];
368
+ vm.set('favorites', favorites);
369
+
370
+ const panel = cmp.up('panel').down('[reference="menuInterface"]');
371
+ if (favorites[cardId]) {
372
+ this.updateFavoriteView(cardId, panel.down('[reference="favoriteView"]'));
373
+ } else {
374
+ this.updateMenuView(cardId, panel.down('[reference="menuView"]'));
375
+ }
376
+ panel.setActiveItem(favorites[cardId] ? 1 : 0);
377
+ },
378
+
379
+ onChangeSearchCombo(cmp, rec) {
380
+ if (!rec || !rec.get('MENU_ENTRY_CD')) {
381
+ return false;
382
+ }
383
+ cmp.clearValue();
384
+ this.goTo(rec.get('MENU_ENTRY_CD'));
385
+ },
386
+ });
@@ -0,0 +1,18 @@
1
+ Ext.define('Coon.nav.menu.FavoriteCfg', {
2
+ singleton: true,
3
+ localStorage: Ext.create('Coon.common.UserPropStorage', {
4
+ component: 'AppNavigationPanelController',
5
+ componentId: 'AppNavigationPanelController',
6
+ module: 'AppNavigationPanelController',
7
+ propList: ['favorite'],
8
+ saveType: 'ls',
9
+ }),
10
+
11
+ get() {
12
+ return this.localStorage.getSavedProps();
13
+ },
14
+
15
+ set(data) {
16
+ this.localStorage.saveProps(data);
17
+ },
18
+ });