From f1fad81273adeec84dc25e5223884a8a6578363a Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Mon, 19 Aug 2024 17:08:11 +0800 Subject: [PATCH 01/47] * [task#126489,start,0.3h] add index dock action lang. --- module/index/lang/de.php | 4 ++++ module/index/lang/en.php | 4 ++++ module/index/lang/fr.php | 4 ++++ module/index/lang/zh-cn.php | 4 ++++ module/index/lang/zh-tw.php | 4 ++++ 5 files changed, 20 insertions(+) diff --git a/module/index/lang/de.php b/module/index/lang/de.php index a379cf33f2..5ef7fb21a5 100644 --- a/module/index/lang/de.php +++ b/module/index/lang/de.php @@ -9,6 +9,10 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = 'Open'; $lang->index->dock->reload = 'Reload'; $lang->index->dock->close = 'Close'; +$lang->index->dock->move = 'Move'; +$lang->index->dock->save = 'Save order'; +$lang->index->dock->hide = 'Hide'; +$lang->index->dock->add = 'Add'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/en.php b/module/index/lang/en.php index 3ab80c0ced..0b9b7dafe4 100644 --- a/module/index/lang/en.php +++ b/module/index/lang/en.php @@ -9,6 +9,10 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = 'Open'; $lang->index->dock->reload = 'Reload'; $lang->index->dock->close = 'Close'; +$lang->index->dock->move = 'Move'; +$lang->index->dock->save = 'Save order'; +$lang->index->dock->hide = 'Hide'; +$lang->index->dock->add = 'Add'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/fr.php b/module/index/lang/fr.php index a379cf33f2..5ef7fb21a5 100644 --- a/module/index/lang/fr.php +++ b/module/index/lang/fr.php @@ -9,6 +9,10 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = 'Open'; $lang->index->dock->reload = 'Reload'; $lang->index->dock->close = 'Close'; +$lang->index->dock->move = 'Move'; +$lang->index->dock->save = 'Save order'; +$lang->index->dock->hide = 'Hide'; +$lang->index->dock->add = 'Add'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/zh-cn.php b/module/index/lang/zh-cn.php index f677680af2..e7082130fd 100644 --- a/module/index/lang/zh-cn.php +++ b/module/index/lang/zh-cn.php @@ -9,6 +9,10 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = '打开'; $lang->index->dock->reload = '刷新'; $lang->index->dock->close = '关闭'; +$lang->index->dock->move = '移动'; +$lang->index->dock->save = '保存顺序'; +$lang->index->dock->hide = '隐藏'; +$lang->index->dock->add = '添加'; $lang->index->upgradeVersion = '可升级版本'; $lang->index->upgradeNow = '现在升级'; diff --git a/module/index/lang/zh-tw.php b/module/index/lang/zh-tw.php index b138140c1b..bf5a597696 100644 --- a/module/index/lang/zh-tw.php +++ b/module/index/lang/zh-tw.php @@ -9,6 +9,10 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = '打開'; $lang->index->dock->reload = '刷新'; $lang->index->dock->close = '關閉'; +$lang->index->dock->move = '移動'; +$lang->index->dock->save = '保存順序'; +$lang->index->dock->hide = '隱藏'; +$lang->index->dock->add = '添加'; $lang->index->upgradeVersion = '可升級版本'; $lang->index->upgradeNow = '現在升級'; From abeded6d495c22df282bde7e30e00a605dfc0c73 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 20 Aug 2024 08:54:48 +0800 Subject: [PATCH 02/47] * [task#126489,1h] support to move menu. --- module/index/css/index.ui.css | 5 +- module/index/js/index.ui.js | 96 +++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/module/index/css/index.ui.css b/module/index/css/index.ui.css index 3fb0b88819..b47ce58d64 100644 --- a/module/index/css/index.ui.css +++ b/module/index/css/index.ui.css @@ -11,7 +11,7 @@ #menu {position: fixed; left: 0; top: 0; bottom: 0; background: var(--zt-menu-bg); width: var(--zt-menu-width); color: rgba(var(--color-canvas-rgb), .8); transition: width .1s; user-select: none; z-index: 10;} #menu .nav {flex-direction: column; align-items: stretch;} #menu .nav > li {display: block; height: var(--zt-menu-height, 38px); padding: 4px 8px; transition: padding .2s;} -#menu .nav > .divider {background: var(--color-canvas); opacity: .12; height: 1px; padding: 0; margin: 6px 12px; align-self: stretch} +#menu .nav > .divider {background: var(--color-canvas); opacity: .12; height: 1px; padding: 6px 4px; align-self: stretch; background-clip: content-box; box-sizing: content-box; border: none;} #menu .nav > li > a {color: inherit; display: flex; align-items: center; gap: 4px; padding: 0 6px; height: calc(var(--zt-menu-height, 38px) - 8px); transition: color .2s, background-color .2s; border-radius: var(--radius-md);} #menu .nav > li > a.active, #menu .nav > li > a:hover {background: var(--zt-menu-hover-bg, rgba(var(--color-primary-400-rgb), .4)); color: var(--color-canvas);} @@ -83,3 +83,6 @@ #upgradeContent {display: none; position: absolute; bottom: var(--zt-apps-bar-height); right: 10px; width: 370px; height: 322px; background-color: #fff; padding: 5px 0; border: 1px solid rgba(0,0,0,.15); border-color: rgba(0,0,0,.1); opacity: 1; border-radius: 4px; box-shadow: 0 6px 12px rgba(0,0,0,.12), 0 1px 3px rgba(0,0,0,.1);} .version-upgrade {width: 14px; height: 16px; float: left; background-repeat: no-repeat; background-position: center ; background-size: cover; display: block;} #latestVersionList {height: 270px; overflow: auto;} + +#menuMainNav[z-use-sortable] a[data-app]:hover {cursor: grab;} +#menuMainNav[z-use-sortable] li.divider:hover {cursor: grab;} \ No newline at end of file diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index b3b8f40d31..a44a5f07b8 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -819,6 +819,54 @@ setTimeout(refreshMenu, 500); $(document).on('click', '.menu-toggle', () => toggleMenu()); toggleMenu(!$('body').hasClass('hide-menu')); +$('#menuNav .divider').on('contextmenu', function(event) +{ + const $divider = $(this); + const $nav = $divider.closest('.nav'); + const isMoving = $nav.is('[z-use-sortable]'); + const items = []; + if(isMoving) + { + items.push( + { + text: langData.save, + onClick: () => { + $divider.closest('.nav').zui().destroy(); + } + } + ); + } + else + { + items.push( + { + text: langData.move, + onClick: () => { + const sortable = new zui.Sortable( + '#menuMainNav', + { + animation: 150, + ghostClass: 'bg-primary-pale', + } + ) + } + } + ); + } + + zui.ContextMenu.show( + { + hideOthers: true, + element: $divider[0], + placement: 'right-start', + items: items, + event: event, + onClickItem: (info) => info.event.preventDefault() + } + ); + event.preventDefault(); +}); + /* Bind events for app trigger */ $(document).on('click', '.open-in-app,.show-in-app', function(e) { @@ -837,14 +885,54 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) if(!code) return; const app = apps.openedMap[code]; - const items = [{text: langData.open, disabled: app && getLastAppCode() === code, onClick: function(){showApp(code)}}]; + const items = [{text: langData.open, disabled: app && getLastAppCode() === code, onClick: () => showApp(code)}]; if(app) { - items.push({text: langData.reload, onClick: function(){reloadApp(code)}}); - if(code !== 'my') items.push({text: langData.close, onClick: function(){closeApp(code)}}); + items.push({text: langData.reload, onClick: () => reloadApp(code)}); + if(code !== 'my') items.push({text: langData.close, onClick: () => closeApp(code)}); } - zui.ContextMenu.show({hideOthers: true, element: $btn[0], placement: $btn.closest('#appTabs').length ? 'top-start' : 'right-start', items: items, event: event, onClickItem: function(info){info.event.preventDefault();}}); + const $nav = $btn.closest('.nav'); + const isMoving = $nav.is('[z-use-sortable]'); + if(isMoving) + { + items.push( + { + text: langData.save, + onClick: () => { + $btn.closest('.nav').zui().destroy(); + } + } + ); + } + else + { + items.push( + { + text: langData.move, + onClick: () => { + const sortable = new zui.Sortable( + '#menuMainNav', + { + animation: 150, + ghostClass: 'bg-primary-pale', + } + ); + } + } + ); + } + + zui.ContextMenu.show( + { + hideOthers: true, + element: $btn[0], + placement: $btn.closest('#appTabs').length ? 'top-start' : 'right-start', + items: items, + event: event, + onClickItem: (info) => info.event.preventDefault() + } + ); event.preventDefault(); }); From 688ddab24390de537302679527a74ae2adeba338 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 20 Aug 2024 09:12:31 +0800 Subject: [PATCH 03/47] * [task#126485,start,0.2h] support to hide menu. --- module/index/js/index.ui.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index a44a5f07b8..fe266dcc89 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -853,6 +853,14 @@ $('#menuNav .divider').on('contextmenu', function(event) } ); } + items.push( + { + text: langData.hide, + onClick: () => { + $divider.closest('li').remove(); + } + } + ); zui.ContextMenu.show( { @@ -923,6 +931,14 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) ); } + items.push( + { + text: langData.hide, + onClick: () => { + $btn.closest('li').remove(); + } + } + ); zui.ContextMenu.show( { hideOthers: true, From 29296c2801eea6f02a40e8311af735e1aa84c482 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 20 Aug 2024 10:23:37 +0800 Subject: [PATCH 04/47] * [task#126485,0.5h] add getMenuNavData. --- module/index/js/index.ui.js | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index fe266dcc89..47a96ba111 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -819,6 +819,24 @@ setTimeout(refreshMenu, 500); $(document).on('click', '.menu-toggle', () => toggleMenu()); toggleMenu(!$('body').hasClass('hide-menu')); +function getMenuNavData() +{ + const data = []; + const $nav = $('#menuMainNav'); + $nav.children().each(function(index, element) { + const $elm = $(element); + if($elm.is('.divider')) + { + data[index] = '-'; + } + data[index] = $elm.is('.divider') + ? '-' + : $elm.data('app') + + }); + return data; +} + $('#menuNav .divider').on('contextmenu', function(event) { const $divider = $(this); @@ -832,6 +850,8 @@ $('#menuNav .divider').on('contextmenu', function(event) text: langData.save, onClick: () => { $divider.closest('.nav').zui().destroy(); + const data = getMenuNavData(); + console.log(data); } } ); @@ -857,7 +877,11 @@ $('#menuNav .divider').on('contextmenu', function(event) { text: langData.hide, onClick: () => { - $divider.closest('li').remove(); + const $li = $divider.closest('li'); + const appName = $li.data('app'); + $li.remove(); + const data = getMenuNavData(); + console.log(appName, data); } } ); @@ -908,7 +932,9 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) { text: langData.save, onClick: () => { - $btn.closest('.nav').zui().destroy(); + $btn.closest('.nav').zui().destroy(); + const data = getMenuNavData(); + console.log(data); } } ); @@ -935,7 +961,12 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) { text: langData.hide, onClick: () => { - $btn.closest('li').remove(); + const $li = $btn.closest('li'); + const appName = $li.data('app'); + $li.remove(); + const data = getMenuNavData(); + + console.log(appName, data); } } ); From 3e9274fc2ad4124d2a603e71fe2699a3f8614bb9 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 20 Aug 2024 10:30:50 +0800 Subject: [PATCH 05/47] * [task#126485,0.1h] refactor. --- module/index/js/index.ui.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 47a96ba111..712cdf1477 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -825,13 +825,9 @@ function getMenuNavData() const $nav = $('#menuMainNav'); $nav.children().each(function(index, element) { const $elm = $(element); - if($elm.is('.divider')) - { - data[index] = '-'; - } data[index] = $elm.is('.divider') ? '-' - : $elm.data('app') + : $elm.data('app'); }); return data; From b5b67962392bbc49ea9fcdcbc24deb870ea797c7 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 20 Aug 2024 16:20:13 +0800 Subject: [PATCH 06/47] * [task#126662,start,3h] support to add menu. --- module/index/control.php | 1 + module/index/js/index.ui.js | 138 ++++++++++++++++++++++++++++++++- module/index/ui/index.html.php | 1 + 3 files changed, 139 insertions(+), 1 deletion(-) diff --git a/module/index/control.php b/module/index/control.php index cf1b5357a9..3411feeb2b 100644 --- a/module/index/control.php +++ b/module/index/control.php @@ -45,6 +45,7 @@ class index extends control $this->view->showFeatures = $this->indexZen->checkShowFeatures(); $this->view->latestVersionList = $latestVersionList; $this->view->appsItems = commonModel::getMainNavList($this->app->rawModule); + $this->view->allAppsItems = commonModel::getMainNavList($this->app->rawModule); $this->view->browserMessage = $this->loadModel('message')->getBrowserMessageConfig(); $this->display(); diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 712cdf1477..f4eb307cd9 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -826,13 +826,47 @@ function getMenuNavData() $nav.children().each(function(index, element) { const $elm = $(element); data[index] = $elm.is('.divider') - ? '-' + ? 'divider' : $elm.data('app'); }); return data; } +function generateAddMenuNavItems(onClick) +{ + const items = [ + { + icon: 'icon-minus', + text: '分割线', + onClick: () => onClick('divider'), + }, + + ]; + + const allAppCodeSet = new Set(allAppsItemsMap.keys()); + const data = getMenuNavData(); + for(const name of data) + { + if(name === 'divider') continue; + allAppCodeSet.delete(name); + } + + if(allAppCodeSet.size === 0) return items; + for(const name of allAppCodeSet) + { + const [icon, title] = getAppItemIconAndTitle(name); + items.push( + { + icon, + text: title, + onClick: () => onClick(name) + } + ); + } + return items; +} + $('#menuNav .divider').on('contextmenu', function(event) { const $divider = $(this); @@ -881,6 +915,43 @@ $('#menuNav .divider').on('contextmenu', function(event) } } ); + items.push( + { + text: langData.add, + items: generateAddMenuNavItems( + (name) => { + const $li = $divider.closest('li'); + if(name === 'divider') return $li.after('
  • '); + + let item = allAppsItemsMap.get(name); + const oldItem = apps.map[item.code]; + if(oldItem !== item && oldItem) item = $.extend({}, oldItem, item, {active: false}); + item.external = item.external || item.url && item.url.includes('://'); + + const $link= $('') + .attr('data-app', item.notApp ? undefined : item.code) + .attr('href', item.url || '#') + .attr('target', item.notApp ? '_blank' : undefined) + .addClass('rounded' + (item.notApp ? '' : ' show-in-app')) + .html(item.title, false); + + item.icon = item.icon || ($link.find('.icon').attr('class') || '').replace('icon ', ''); + item.text = $link.text().trim(); + $link.html('' + item.text + '', false); + if(['devops', 'bi', 'safe'].includes(item.code)) $link.find('.text').addClass('font-brand'); + apps.map[item.code] = item; + + $('
  • ') + .attr({'data-app': item.code, 'data-hint': item.text}) + .append($link) + .insertAfter($li); + + if(!apps.defaultCode) apps.defaultCode = item.code; + } + ) + } + ); + zui.ContextMenu.show( { @@ -966,6 +1037,44 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) } } ); + + items.push( + { + text: langData.add, + items: generateAddMenuNavItems( + (name) => { + const $li = $btn.closest('li'); + if(name === 'divider') return $li.after('
  • '); + + let item = allAppsItemsMap.get(name); + const oldItem = apps.map[item.code]; + if(oldItem !== item && oldItem) item = $.extend({}, oldItem, item, {active: false}); + item.external = item.external || item.url && item.url.includes('://'); + + const $link= $('') + .attr('data-app', item.notApp ? undefined : item.code) + .attr('href', item.url || '#') + .attr('target', item.notApp ? '_blank' : undefined) + .addClass('rounded' + (item.notApp ? '' : ' show-in-app')) + .html(item.title, false); + + item.icon = item.icon || ($link.find('.icon').attr('class') || '').replace('icon ', ''); + item.text = $link.text().trim(); + $link.html('' + item.text + '', false); + if(['devops', 'bi', 'safe'].includes(item.code)) $link.find('.text').addClass('font-brand'); + apps.map[item.code] = item; + + $('
  • ') + .attr({'data-app': item.code, 'data-hint': item.text}) + .append($link) + .insertAfter($li); + + if(!apps.defaultCode) apps.defaultCode = item.code; + } + ) + } + ); + zui.ContextMenu.show( { hideOthers: true, @@ -1196,3 +1305,30 @@ $(document).on('click', e => $('#bizLink').removeClass('active'); } }); + +let allAppsItemsMap = new Map(); +void function generateAllAppsItemsMap() { + for(const item of allAppsItems) + { + if(item === 'divider') continue; + + allAppsItemsMap.set(item.code, item); + } +}(); + +function getAppItemIconAndTitle(name) +{ + if(!allAppsItemsMap.has(name)) return[]; + const item = allAppsItemsMap.get(name); + const str = item.title; + const regex = /class=["']icon (\S*)["']\>\<\/i\>\s(\S*)/; + const matches = str.match(regex); + + if(matches) + { + const icon = matches[1]; + const text = matches[2].trim(); + return [icon, text]; + } + return []; +} \ No newline at end of file diff --git a/module/index/ui/index.html.php b/module/index/ui/index.html.php index d8aa0ebbdd..b1917188a3 100644 --- a/module/index/ui/index.html.php +++ b/module/index/ui/index.html.php @@ -106,6 +106,7 @@ jsVar('vision', $config->vision); jsVar('navGroup', $lang->navGroup); jsVar('oldPages', $config->index->oldPages); jsVar('appsItems', $appsItems); +jsVar('allAppsItems', $allAppsItems); jsVar('defaultOpen', !empty($open) ? $open : ''); jsVar('manualText', $lang->manual); jsVar('manualUrl', ((!empty($config->isINT)) ? $config->manualUrl['int'] : $config->manualUrl['home']) . '&theme=' . $_COOKIE['theme']); From 95c33784ddd2291d559aa4f236b9c49ad844d85e Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 21 Aug 2024 15:48:38 +0800 Subject: [PATCH 07/47] * [task#126485,0.2h] disable actived and my nav to hide. --- module/index/js/index.ui.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index f4eb307cd9..4d3ebbaad0 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -1024,17 +1024,21 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) ); } + const hideDisabled = code === 'my' || $btn.is('.active'); items.push( { text: langData.hide, - onClick: () => { - const $li = $btn.closest('li'); - const appName = $li.data('app'); - $li.remove(); - const data = getMenuNavData(); - - console.log(appName, data); - } + onClick: hideDisabled + ? null + : () => { + const $li = $btn.closest('li'); + const appName = $li.data('app'); + $li.remove(); + const data = getMenuNavData(); + + console.log(appName, data); + }, + disabled: hideDisabled, } ); From a393ebedd6bce145f2e52c8139361df662a6b48c Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 21 Aug 2024 16:07:42 +0800 Subject: [PATCH 08/47] * [task#126485,0.2h] rm hidden menu from appsBar. --- module/index/js/index.ui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 4d3ebbaad0..b6c4ee2123 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -1031,6 +1031,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) onClick: hideDisabled ? null : () => { + closeApp(code); const $li = $btn.closest('li'); const appName = $li.data('app'); $li.remove(); From 548849f4e80156d8584982173accce1f6f1c12f9 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 21 Aug 2024 16:33:33 +0800 Subject: [PATCH 09/47] * [task#126662,0.5h] trigger refresh menu when change menu. --- module/index/js/index.ui.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index b6c4ee2123..86a31bf4f7 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -911,6 +911,7 @@ $('#menuNav .divider').on('contextmenu', function(event) const appName = $li.data('app'); $li.remove(); const data = getMenuNavData(); + refreshMenu(); console.log(appName, data); } } @@ -946,6 +947,7 @@ $('#menuNav .divider').on('contextmenu', function(event) .append($link) .insertAfter($li); + refreshMenu(); if(!apps.defaultCode) apps.defaultCode = item.code; } ) @@ -1036,7 +1038,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) const appName = $li.data('app'); $li.remove(); const data = getMenuNavData(); - + refreshMenu(); console.log(appName, data); }, disabled: hideDisabled, @@ -1074,6 +1076,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) .append($link) .insertAfter($li); + refreshMenu(); if(!apps.defaultCode) apps.defaultCode = item.code; } ) From 9338d329bc57518e299b7f83fada764d393c6c89 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 21 Aug 2024 16:54:24 +0800 Subject: [PATCH 10/47] * [task#126662,0.4h] refactor. --- module/index/js/index.ui.js | 98 +++++++++++++------------------------ 1 file changed, 34 insertions(+), 64 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 86a31bf4f7..f5c38ca072 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -919,38 +919,7 @@ $('#menuNav .divider').on('contextmenu', function(event) items.push( { text: langData.add, - items: generateAddMenuNavItems( - (name) => { - const $li = $divider.closest('li'); - if(name === 'divider') return $li.after('
  • '); - - let item = allAppsItemsMap.get(name); - const oldItem = apps.map[item.code]; - if(oldItem !== item && oldItem) item = $.extend({}, oldItem, item, {active: false}); - item.external = item.external || item.url && item.url.includes('://'); - - const $link= $('') - .attr('data-app', item.notApp ? undefined : item.code) - .attr('href', item.url || '#') - .attr('target', item.notApp ? '_blank' : undefined) - .addClass('rounded' + (item.notApp ? '' : ' show-in-app')) - .html(item.title, false); - - item.icon = item.icon || ($link.find('.icon').attr('class') || '').replace('icon ', ''); - item.text = $link.text().trim(); - $link.html('' + item.text + '', false); - if(['devops', 'bi', 'safe'].includes(item.code)) $link.find('.text').addClass('font-brand'); - apps.map[item.code] = item; - - $('
  • ') - .attr({'data-app': item.code, 'data-hint': item.text}) - .append($link) - .insertAfter($li); - - refreshMenu(); - if(!apps.defaultCode) apps.defaultCode = item.code; - } - ) + items: generateAddMenuNavItems(addMenuToMainNavCb($divider)) } ); @@ -1048,38 +1017,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) items.push( { text: langData.add, - items: generateAddMenuNavItems( - (name) => { - const $li = $btn.closest('li'); - if(name === 'divider') return $li.after('
  • '); - - let item = allAppsItemsMap.get(name); - const oldItem = apps.map[item.code]; - if(oldItem !== item && oldItem) item = $.extend({}, oldItem, item, {active: false}); - item.external = item.external || item.url && item.url.includes('://'); - - const $link= $('') - .attr('data-app', item.notApp ? undefined : item.code) - .attr('href', item.url || '#') - .attr('target', item.notApp ? '_blank' : undefined) - .addClass('rounded' + (item.notApp ? '' : ' show-in-app')) - .html(item.title, false); - - item.icon = item.icon || ($link.find('.icon').attr('class') || '').replace('icon ', ''); - item.text = $link.text().trim(); - $link.html('' + item.text + '', false); - if(['devops', 'bi', 'safe'].includes(item.code)) $link.find('.text').addClass('font-brand'); - apps.map[item.code] = item; - - $('
  • ') - .attr({'data-app': item.code, 'data-hint': item.text}) - .append($link) - .insertAfter($li); - - refreshMenu(); - if(!apps.defaultCode) apps.defaultCode = item.code; - } - ) + items: generateAddMenuNavItems(addMenuToMainNavCb($btn.closest('li'))) } ); @@ -1339,4 +1277,36 @@ function getAppItemIconAndTitle(name) return [icon, text]; } return []; +} + +function addMenuToMainNavCb($li) { + return (name) => { + if(name === 'divider') return $li.after('
  • '); + + let item = allAppsItemsMap.get(name); + const oldItem = apps.map[item.code]; + if(oldItem !== item && oldItem) item = $.extend({}, oldItem, item, {active: false}); + item.external = item.external || item.url && item.url.includes('://'); + + const $link= $('') + .attr('data-app', item.notApp ? undefined : item.code) + .attr('href', item.url || '#') + .attr('target', item.notApp ? '_blank' : undefined) + .addClass('rounded' + (item.notApp ? '' : ' show-in-app')) + .html(item.title, false); + + item.icon = item.icon || ($link.find('.icon').attr('class') || '').replace('icon ', ''); + item.text = $link.text().trim(); + $link.html('' + item.text + '', false); + if(['devops', 'bi', 'safe'].includes(item.code)) $link.find('.text').addClass('font-brand'); + apps.map[item.code] = item; + + $('
  • ') + .attr({'data-app': item.code, 'data-hint': item.text}) + .append($link) + .insertAfter($li); + + refreshMenu(); + if(!apps.defaultCode) apps.defaultCode = item.code; + }; } \ No newline at end of file From e8e787340a668165f71029894d7d6f7fb9ba7c0b Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 21 Aug 2024 17:02:51 +0800 Subject: [PATCH 11/47] * [task#126662,0.3h] fix divider contextmenu not work. --- module/index/js/index.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index f5c38ca072..2cfa1c9676 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -867,7 +867,7 @@ function generateAddMenuNavItems(onClick) return items; } -$('#menuNav .divider').on('contextmenu', function(event) +$(document).on('contextmenu', '#menuNav .divider', function(event) { const $divider = $(this); const $nav = $divider.closest('.nav'); From d8fbcd316590ca99ea655a7b6e5ea882e2b9bea2 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 11:01:07 +0800 Subject: [PATCH 12/47] * [task#126490,1.5h] init navbar menu contextmenu move. --- lib/zin/wg/navbar/css/v1.css | 2 ++ lib/zin/wg/navbar/js/v1.js | 63 ++++++++++++++++++++++++++++++++++++ lib/zin/wg/navbar/v1.php | 13 ++++++++ 3 files changed, 78 insertions(+) create mode 100644 lib/zin/wg/navbar/css/v1.css create mode 100644 lib/zin/wg/navbar/js/v1.js diff --git a/lib/zin/wg/navbar/css/v1.css b/lib/zin/wg/navbar/css/v1.css new file mode 100644 index 0000000000..a0586a1e87 --- /dev/null +++ b/lib/zin/wg/navbar/css/v1.css @@ -0,0 +1,2 @@ +#navbar .nav[z-use-sortable] > li:hover {cursor: grab !important;} +#navbar .nav[z-use-sortable] > li > a:hover {cursor: grab !important;} \ No newline at end of file diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js new file mode 100644 index 0000000000..3c413263ce --- /dev/null +++ b/lib/zin/wg/navbar/js/v1.js @@ -0,0 +1,63 @@ +$(document).on( + 'contextmenu', + '#navbar .nav-item > a, #navbar .nav-divider', + function(event) + { + console.log(langData); + const $item = $(this); + const $nav = $('#navbar .nav'); + const isMoving = $nav.is('[z-use-sortable]'); + const items = [ + isMoving + ? { + text: langData.save, + onClick: () => { + $item.closest('.nav').zui().destroy(); + } + } + : { + text: langData.move, + onClick: () => { + const sortable = new zui.Sortable( + '#navbar .nav', + { + animation: 150, + ghostClass: 'bg-primary-pale', + } + ); + } + }, + { + text: langData.hide, + disabled: $item.is('active'), + onClick: () => { + if($item.is('.nav-divider')) + { + $item.remove(); + } + else + { + $item.remove(); + } + } + }, + { + text: langData.add, + onClick: () => { + + } + } + ]; + zui.ContextMenu.show( + { + hideOthers: true, + element: $item[0], + placement: 'bottom-start', + items: items, + event: event, + onClickItem: (info) => info.event.preventDefault() + } + ); + event.preventDefault(); + } +); \ No newline at end of file diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 4d15ed409c..f0326589ae 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -10,6 +10,19 @@ class navbar extends wg 'items?: array' ); + public static function getPageCSS(): ?string + { + return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css'); + } + + public static function getPageJS(): ?string + { + global $lang, $app; + $app->loadLang('index'); + jsVar('langData', $lang->index->dock); + return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js'); + } + protected function getExecutionMoreItem($executionID) { if(defined('TUTORIAL')) return; From 9004ef798b8a3cb9312c769b915257e4b3a5729e Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 14:06:43 +0800 Subject: [PATCH 13/47] * [task#126490,0.5] add navbar items methods --- lib/zin/wg/navbar/js/v1.js | 77 +++++++++++++++++++++++++++++++------- lib/zin/wg/navbar/v1.php | 4 +- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 3c413263ce..1f945b584c 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -1,18 +1,68 @@ +function getAllNavbarItems() +{ + const items = []; + for(const item of allNavbarItems) + { + if(item.type === 'divider') + { + items.push('divider'); + continue; + } + + if (item.type === 'dropdown') + { + item.push(item.id); + continue; + } + + item.push(item['data-id']); + } + return items; +} + +function getCurrentNavbarItems() +{ + const items = []; + const $nav = $('#navbar .nav'); + $nav.children().each( + function(index, element) + { + const $elm = $(element) + if($elm.is('.nav-divider')) + { + items[index] = 'divider'; + return; + } + + const $a = $elm.find('a'); + if($elm.is('.nav-dropdown')) + { + items[index] = $a.prop('id'); + return; + } + + items[index] = $a.data('id'); + } + ); + return items; +} + $(document).on( 'contextmenu', - '#navbar .nav-item > a, #navbar .nav-divider', + '#navbar .nav-item:not(.nav-dropdown) > a, #navbar .nav-divider', function(event) { - console.log(langData); const $item = $(this); const $nav = $('#navbar .nav'); const isMoving = $nav.is('[z-use-sortable]'); + const hideDisabled = $item.is('.active'); const items = [ isMoving ? { text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); + console.log(getCurrentNavbarItems()); } } : { @@ -29,22 +79,23 @@ $(document).on( }, { text: langData.hide, - disabled: $item.is('active'), - onClick: () => { - if($item.is('.nav-divider')) - { - $item.remove(); + disabled: hideDisabled, + onClick: hideDisabled + ? null + : () => { + if($item.is('.nav-divider')) + { + $item.remove(); + } + else + { + $item.remove(); + } } - else - { - $item.remove(); - } - } }, { text: langData.add, onClick: () => { - } } ]; diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index f0326589ae..5bbbb002b9 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -310,12 +310,14 @@ class navbar extends wg */ protected function build() { + $items = $this->getItems(); + jsVar('allNavbarItems', $items); return h::nav ( set::id('navbar'), new nav ( - set::items($this->getItems()), + set::items($items), $this->children() ) ); From 04bddfdd6b4a73961d8fa42ff100842afcf284c8 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 14:42:54 +0800 Subject: [PATCH 14/47] * [task#126490,0.3h] refactor. --- lib/zin/wg/navbar/js/v1.js | 55 +++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 1f945b584c..d567ef1cea 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -1,24 +1,31 @@ -function getAllNavbarItems() -{ - const items = []; - for(const item of allNavbarItems) +const allNavbarItemIDs = []; +const allNavbarItemMap = new Map(); + +$(document).ready( + function() { - if(item.type === 'divider') - { - items.push('divider'); - continue; - } + allNavbarItemIDs.length = 0; - if (item.type === 'dropdown') + for(const item of allNavbarItems) { - item.push(item.id); - continue; - } + if(item.type === 'divider') + { + allNavbarItemIDs.push('divider'); + continue; + } - item.push(item['data-id']); + if (item.type === 'dropdown') + { + allNavbarItemIDs.push(item.id); + allNavbarItemMap.set(item.id, item); + continue; + } + + item.push(item['data-id']); + allNavbarItemMap.set(item['data-id'], item); + } } - return items; -} +); function getCurrentNavbarItems() { @@ -48,9 +55,9 @@ function getCurrentNavbarItems() } $(document).on( - 'contextmenu', - '#navbar .nav-item:not(.nav-dropdown) > a, #navbar .nav-divider', - function(event) + 'contextmenu', + '#navbar .nav-item:not(.nav-dropdown) > a, #navbar .nav-divider', + function(event) { const $item = $(this); const $nav = $('#navbar .nav'); @@ -101,11 +108,11 @@ $(document).on( ]; zui.ContextMenu.show( { - hideOthers: true, - element: $item[0], - placement: 'bottom-start', - items: items, - event: event, + hideOthers: true, + element: $item[0], + placement: 'bottom-start', + items: items, + event: event, onClickItem: (info) => info.event.preventDefault() } ); From 721506193ef4eb2d1f743ce2d0cef09f8e8ea367 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 15:45:44 +0800 Subject: [PATCH 15/47] * [task#126663,start,1h] init navbar menu contextmenu add. --- lib/zin/wg/navbar/js/v1.js | 58 ++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index d567ef1cea..66e3f3199a 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -5,6 +5,7 @@ $(document).ready( function() { allNavbarItemIDs.length = 0; + allNavbarItemMap.clear(); for(const item of allNavbarItems) { @@ -21,9 +22,10 @@ $(document).ready( continue; } - item.push(item['data-id']); + allNavbarItemIDs.push(item['data-id']); allNavbarItemMap.set(item['data-id'], item); } + console.log(allNavbarItemMap, allNavbarItemIDs); } ); @@ -54,6 +56,37 @@ function getCurrentNavbarItems() return items; } +function generateAddNavbarItems(onClick) +{ + const items = [ + { + text: '分割线', + onClick: () => onClick('divider') + } + ]; + + const allNavbarItemIDSet = new Set(allNavbarItemMap.keys()); + const curNavbarItems = getCurrentNavbarItems(); + for(const id of curNavbarItems) + { + if(id === 'divider') continue; + allNavbarItemIDSet.delete(id); + } + + if(allNavbarItemIDSet.size === 0) return items; + for(const id of allNavbarItemIDSet) + { + const item = allNavbarItemMap.get(id); + items.push( + { + text: item.text, + onClick: () => onClick(id), + } + ); + } + return items; +} + $(document).on( 'contextmenu', '#navbar .nav-item:not(.nav-dropdown) > a, #navbar .nav-divider', @@ -63,6 +96,7 @@ $(document).on( const $nav = $('#navbar .nav'); const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = $item.is('.active'); + const $li = $item.closest('li'); const items = [ isMoving ? { @@ -92,18 +126,32 @@ $(document).on( : () => { if($item.is('.nav-divider')) { - $item.remove(); + $li.remove(); } else { - $item.remove(); + $li.remove(); } + console.log(getCurrentNavbarItems()); } }, { text: langData.add, - onClick: () => { - } + items: generateAddNavbarItems((id) => { + if(id === 'divider') return $li.after(''); + + const item = allNavbarItemMap.get(id); + const $a = $('') + .attr('href', item.url) + .attr('target', item.target) + .attr('data-id', item['data-id']) + .append(`${item.text}`); + if(item.class) $a.attr('class', item.class); + const $navItem = $(''); + $navItem.append($a); + $li.after($navItem); + console.log(getCurrentNavbarItems()); + }), } ]; zui.ContextMenu.show( From 9025067ba889de1ab7667658d6ad4a46aa0ac2cc Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 16:26:44 +0800 Subject: [PATCH 16/47] * [task#126486,start,0.7h] init navbar contextmenu hide action. --- lib/zin/wg/navbar/js/v1.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 66e3f3199a..a679360d42 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -87,6 +87,18 @@ function generateAddNavbarItems(onClick) return items; } +function canHideCurrentNavbar($item) +{ + if($item.is('.nav-divider')) return true; + if($item.is('.active')) return false; + + const app = $.apps.getLastApp(); + const appDefaultUrl = app.url; + const itemUrl = $item.attr('href'); + if(itemUrl === appDefaultUrl) return false; + return true; +} + $(document).on( 'contextmenu', '#navbar .nav-item:not(.nav-dropdown) > a, #navbar .nav-divider', @@ -95,7 +107,7 @@ $(document).on( const $item = $(this); const $nav = $('#navbar .nav'); const isMoving = $nav.is('[z-use-sortable]'); - const hideDisabled = $item.is('.active'); + const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); const items = [ isMoving @@ -124,14 +136,7 @@ $(document).on( onClick: hideDisabled ? null : () => { - if($item.is('.nav-divider')) - { - $li.remove(); - } - else - { - $li.remove(); - } + $li.remove(); console.log(getCurrentNavbarItems()); } }, From e45ef60732b40a2e9e116de172742bb83dac9b09 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 16:38:59 +0800 Subject: [PATCH 17/47] * [task#126663,0.2h] add divider lang. --- lib/zin/wg/navbar/js/v1.js | 2 +- module/index/js/index.ui.js | 40 ++++++++++++++++++------------------- module/index/lang/de.php | 15 +++++++------- module/index/lang/en.php | 15 +++++++------- module/index/lang/fr.php | 15 +++++++------- module/index/lang/zh-cn.php | 15 +++++++------- module/index/lang/zh-tw.php | 15 +++++++------- 7 files changed, 61 insertions(+), 56 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index a679360d42..070f409441 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -60,7 +60,7 @@ function generateAddNavbarItems(onClick) { const items = [ { - text: '分割线', + text: langData.divider, onClick: () => onClick('divider') } ]; diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 2cfa1c9676..700a885c61 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -819,7 +819,7 @@ setTimeout(refreshMenu, 500); $(document).on('click', '.menu-toggle', () => toggleMenu()); toggleMenu(!$('body').hasClass('hide-menu')); -function getMenuNavData() +function getMenuNavData() { const data = []; const $nav = $('#menuMainNav'); @@ -838,7 +838,7 @@ function generateAddMenuNavItems(onClick) const items = [ { icon: 'icon-minus', - text: '分割线', + text: langData.divider, onClick: () => onClick('divider'), }, @@ -846,14 +846,14 @@ function generateAddMenuNavItems(onClick) const allAppCodeSet = new Set(allAppsItemsMap.keys()); const data = getMenuNavData(); - for(const name of data) + for(const name of data) { if(name === 'divider') continue; allAppCodeSet.delete(name); } if(allAppCodeSet.size === 0) return items; - for(const name of allAppCodeSet) + for(const name of allAppCodeSet) { const [icon, title] = getAppItemIconAndTitle(name); items.push( @@ -867,13 +867,13 @@ function generateAddMenuNavItems(onClick) return items; } -$(document).on('contextmenu', '#menuNav .divider', function(event) +$(document).on('contextmenu', '#menuNav .divider', function(event) { const $divider = $(this); const $nav = $divider.closest('.nav'); const isMoving = $nav.is('[z-use-sortable]'); const items = []; - if(isMoving) + if(isMoving) { items.push( { @@ -926,11 +926,11 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) zui.ContextMenu.show( { - hideOthers: true, - element: $divider[0], - placement: 'right-start', - items: items, - event: event, + hideOthers: true, + element: $divider[0], + placement: 'right-start', + items: items, + event: event, onClickItem: (info) => info.event.preventDefault() } ); @@ -977,7 +977,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) } ); } - else + else { items.push( { @@ -1023,11 +1023,11 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) zui.ContextMenu.show( { - hideOthers: true, - element: $btn[0], - placement: $btn.closest('#appTabs').length ? 'top-start' : 'right-start', - items: items, - event: event, + hideOthers: true, + element: $btn[0], + placement: $btn.closest('#appTabs').length ? 'top-start' : 'right-start', + items: items, + event: event, onClickItem: (info) => info.event.preventDefault() } ); @@ -1254,10 +1254,10 @@ $(document).on('click', e => let allAppsItemsMap = new Map(); void function generateAllAppsItemsMap() { - for(const item of allAppsItems) + for(const item of allAppsItems) { if(item === 'divider') continue; - + allAppsItemsMap.set(item.code, item); } }(); @@ -1270,7 +1270,7 @@ function getAppItemIconAndTitle(name) const regex = /class=["']icon (\S*)["']\>\<\/i\>\s(\S*)/; const matches = str.match(regex); - if(matches) + if(matches) { const icon = matches[1]; const text = matches[2].trim(); diff --git a/module/index/lang/de.php b/module/index/lang/de.php index 5ef7fb21a5..378a3b45c9 100644 --- a/module/index/lang/de.php +++ b/module/index/lang/de.php @@ -6,13 +6,14 @@ $lang->index->pleaseInput = 'Please input'; $lang->index->search = 'Search'; $lang->index->dock = new stdClass(); -$lang->index->dock->open = 'Open'; -$lang->index->dock->reload = 'Reload'; -$lang->index->dock->close = 'Close'; -$lang->index->dock->move = 'Move'; -$lang->index->dock->save = 'Save order'; -$lang->index->dock->hide = 'Hide'; -$lang->index->dock->add = 'Add'; +$lang->index->dock->open = 'Open'; +$lang->index->dock->reload = 'Reload'; +$lang->index->dock->close = 'Close'; +$lang->index->dock->move = 'Move'; +$lang->index->dock->save = 'Save order'; +$lang->index->dock->hide = 'Hide'; +$lang->index->dock->add = 'Add'; +$lang->index->dock->divider = 'Divider'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/en.php b/module/index/lang/en.php index 0b9b7dafe4..6390153c72 100644 --- a/module/index/lang/en.php +++ b/module/index/lang/en.php @@ -6,13 +6,14 @@ $lang->index->pleaseInput = 'Enter'; $lang->index->search = 'Search'; $lang->index->dock = new stdClass(); -$lang->index->dock->open = 'Open'; -$lang->index->dock->reload = 'Reload'; -$lang->index->dock->close = 'Close'; -$lang->index->dock->move = 'Move'; -$lang->index->dock->save = 'Save order'; -$lang->index->dock->hide = 'Hide'; -$lang->index->dock->add = 'Add'; +$lang->index->dock->open = 'Open'; +$lang->index->dock->reload = 'Reload'; +$lang->index->dock->close = 'Close'; +$lang->index->dock->move = 'Move'; +$lang->index->dock->save = 'Save order'; +$lang->index->dock->hide = 'Hide'; +$lang->index->dock->add = 'Add'; +$lang->index->dock->divider = 'Divider'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/fr.php b/module/index/lang/fr.php index 5ef7fb21a5..378a3b45c9 100644 --- a/module/index/lang/fr.php +++ b/module/index/lang/fr.php @@ -6,13 +6,14 @@ $lang->index->pleaseInput = 'Please input'; $lang->index->search = 'Search'; $lang->index->dock = new stdClass(); -$lang->index->dock->open = 'Open'; -$lang->index->dock->reload = 'Reload'; -$lang->index->dock->close = 'Close'; -$lang->index->dock->move = 'Move'; -$lang->index->dock->save = 'Save order'; -$lang->index->dock->hide = 'Hide'; -$lang->index->dock->add = 'Add'; +$lang->index->dock->open = 'Open'; +$lang->index->dock->reload = 'Reload'; +$lang->index->dock->close = 'Close'; +$lang->index->dock->move = 'Move'; +$lang->index->dock->save = 'Save order'; +$lang->index->dock->hide = 'Hide'; +$lang->index->dock->add = 'Add'; +$lang->index->dock->divider = 'Divider'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/zh-cn.php b/module/index/lang/zh-cn.php index e7082130fd..0b283ae5d0 100644 --- a/module/index/lang/zh-cn.php +++ b/module/index/lang/zh-cn.php @@ -6,13 +6,14 @@ $lang->index->pleaseInput = '请输入'; $lang->index->search = '搜索'; $lang->index->dock = new stdClass(); -$lang->index->dock->open = '打开'; -$lang->index->dock->reload = '刷新'; -$lang->index->dock->close = '关闭'; -$lang->index->dock->move = '移动'; -$lang->index->dock->save = '保存顺序'; -$lang->index->dock->hide = '隐藏'; -$lang->index->dock->add = '添加'; +$lang->index->dock->open = '打开'; +$lang->index->dock->reload = '刷新'; +$lang->index->dock->close = '关闭'; +$lang->index->dock->move = '移动'; +$lang->index->dock->save = '保存顺序'; +$lang->index->dock->hide = '隐藏'; +$lang->index->dock->add = '添加'; +$lang->index->dock->divider = '分割线'; $lang->index->upgradeVersion = '可升级版本'; $lang->index->upgradeNow = '现在升级'; diff --git a/module/index/lang/zh-tw.php b/module/index/lang/zh-tw.php index bf5a597696..4edb73e372 100644 --- a/module/index/lang/zh-tw.php +++ b/module/index/lang/zh-tw.php @@ -6,13 +6,14 @@ $lang->index->pleaseInput = '請輸入'; $lang->index->search = '搜索'; $lang->index->dock = new stdClass(); -$lang->index->dock->open = '打開'; -$lang->index->dock->reload = '刷新'; -$lang->index->dock->close = '關閉'; -$lang->index->dock->move = '移動'; -$lang->index->dock->save = '保存順序'; -$lang->index->dock->hide = '隱藏'; -$lang->index->dock->add = '添加'; +$lang->index->dock->open = '打開'; +$lang->index->dock->reload = '刷新'; +$lang->index->dock->close = '關閉'; +$lang->index->dock->move = '移動'; +$lang->index->dock->save = '保存順序'; +$lang->index->dock->hide = '隱藏'; +$lang->index->dock->add = '添加'; +$lang->index->dock->divider = '分割線'; $lang->index->upgradeVersion = '可升級版本'; $lang->index->upgradeNow = '現在升級'; From f5b8459090eb97e32457e14bdb1325cd72a3e3b2 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 17:13:50 +0800 Subject: [PATCH 18/47] * [task#126491,start,0.5h] init main navbar contextmenu move action. --- lib/zin/wg/mainnavbar/js/v1.js | 50 ++++++++++++++++++++++++++++++++++ lib/zin/wg/mainnavbar/v1.php | 10 +++++++ 2 files changed, 60 insertions(+) create mode 100644 lib/zin/wg/mainnavbar/js/v1.js diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js new file mode 100644 index 0000000000..2e0d372720 --- /dev/null +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -0,0 +1,50 @@ +$(document).on( + 'contextmenu', + '#mainNavbar .nav-item > a', + function(event) + { + const $item = $(this); + const $nav = $('#mainNavbar .nav'); + const isMoving = $nav.is('[z-use-sortable]'); + const $li = $item.closest('li'); + const items = [ + isMoving + ? { + text: langData.save, + onClick: () => { + $item.closest('.nav').zui().destroy(); + } + } + : { + text: langData.move, + onClick: () => { + const sortable = new zui.Sortable( + '#mainNavbar .nav', + { + animation: 150, + ghostClass: 'bg-primary-pale', + } + ); + } + }, + { + text: langData.hide, + }, + { + text: langData.add, + } + ]; + + zui.ContextMenu.show( + { + hideOthers: true, + element: $item[0], + placement: 'bottom-start', + items: items, + event: event, + onClickItem: (info) => info.event.preventDefault() + } + ); + event.preventDefault(); + } +); \ No newline at end of file diff --git a/lib/zin/wg/mainnavbar/v1.php b/lib/zin/wg/mainnavbar/v1.php index c71488aa8e..aa6763948f 100644 --- a/lib/zin/wg/mainnavbar/v1.php +++ b/lib/zin/wg/mainnavbar/v1.php @@ -63,9 +63,19 @@ class mainNavbar extends nav #mainNavbar .main-navbar-left #switcher .icon-angle-right {display: none;} #mainNavbar .main-navbar-left #switcher .caret {color: rgb(var(--color-link-hover-rgb));} #mainNavbar .main-navbar-left #switcher .text {color: rgb(var(--color-primary-500-rgb));} + #mainNavbar .nav[z-use-sortable] > li:hover {cursor: grab !important;} + #mainNavbar .nav[z-use-sortable] > li > a:hover {cursor: grab !important;} CSS; } + public static function getPageJS(): ?string + { + global $lang, $app; + $app->loadLang('index'); + jsVar('langData', $lang->index->dock); + return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js'); + } + protected function created() { global $app; From dade068c1179638e49ead5d7a65398510fee2750 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 22 Aug 2024 17:18:30 +0800 Subject: [PATCH 19/47] * [task#126490,0.1h] refactor. --- lib/zin/wg/navbar/css/v1.css | 2 -- lib/zin/wg/navbar/v1.php | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 lib/zin/wg/navbar/css/v1.css diff --git a/lib/zin/wg/navbar/css/v1.css b/lib/zin/wg/navbar/css/v1.css deleted file mode 100644 index a0586a1e87..0000000000 --- a/lib/zin/wg/navbar/css/v1.css +++ /dev/null @@ -1,2 +0,0 @@ -#navbar .nav[z-use-sortable] > li:hover {cursor: grab !important;} -#navbar .nav[z-use-sortable] > li > a:hover {cursor: grab !important;} \ No newline at end of file diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 5bbbb002b9..87e2242228 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -12,7 +12,10 @@ class navbar extends wg public static function getPageCSS(): ?string { - return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css'); + return <<<'CSS' + #navbar .nav[z-use-sortable] > li:hover {cursor: grab !important;} + #navbar .nav[z-use-sortable] > li > a:hover {cursor: grab !important;} + CSS; } public static function getPageJS(): ?string From 12da8259d655f9fb8b4784e22aa80601a81bdc9e Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 08:59:51 +0800 Subject: [PATCH 20/47] * [task#126487,start,0.5h] init main navbar contextmenu hide action. --- lib/zin/wg/mainnavbar/js/v1.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 2e0d372720..96777c1e30 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -1,3 +1,13 @@ +function canHideCurrentNavbar($item) +{ + if($item.is('.active')) return false; + + const $navbarActiveItem = $('#navbar .nav .active'); + if($item.attr('href') === $navbarActiveItem.attr('href')) return false; + + return true; +} + $(document).on( 'contextmenu', '#mainNavbar .nav-item > a', @@ -6,6 +16,7 @@ $(document).on( const $item = $(this); const $nav = $('#mainNavbar .nav'); const isMoving = $nav.is('[z-use-sortable]'); + const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); const items = [ isMoving @@ -29,6 +40,12 @@ $(document).on( }, { text: langData.hide, + disabled: hideDisabled, + onClick: hideDisabled + ? null + : () => { + $li.remove(); + } }, { text: langData.add, From 3092e8c122e738bed5d5676f2d205b1d8fcd63ca Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 10:09:33 +0800 Subject: [PATCH 21/47] * [task#126663,0.1h] refactor. --- lib/zin/wg/navbar/js/v1.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 070f409441..070fc07167 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -25,7 +25,6 @@ $(document).ready( allNavbarItemIDs.push(item['data-id']); allNavbarItemMap.set(item['data-id'], item); } - console.log(allNavbarItemMap, allNavbarItemIDs); } ); @@ -50,7 +49,7 @@ function getCurrentNavbarItems() return; } - items[index] = $a.data('id'); + items[index] = $a.attr('data-id'); } ); return items; From c0f4a4729da317d95a2d5520a42399c14f871aed Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 10:13:35 +0800 Subject: [PATCH 22/47] * [task#126664,start,1h] init main navbar contextmenu add action. --- lib/zin/wg/mainnavbar/js/v1.js | 85 ++++++++++++++++++++++++++++++++-- lib/zin/wg/mainnavbar/v1.php | 1 + 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 96777c1e30..2381941578 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -1,3 +1,60 @@ +const allMainNavbarItemIDs = []; +const allMainNavbarItemMap = new Map(); + +$(document).ready( + function() + { + allMainNavbarItemIDs.length = 0; + allMainNavbarItemMap.clear(); + console.log(allMainNavbarItems); + + for(const item of allMainNavbarItems) + { + allMainNavbarItemIDs.push(item['data-id']); + allMainNavbarItemMap.set(item['data-id'], item); + } + } +); + +function getCurrentMainNavbarItems() +{ + const items = []; + const $nav = $('#mainNavbar .nav'); + $nav.children().each( + function(index, element) + { + const $elm = $(element); + $a = $elm.find('a'); + items[index] = $a.attr('data-id'); + } + ); + return items; +} + +function generateAddMainNavbarItems(onClick) +{ + const items = []; + const allMainNavbarItemIDSet = new Set(allMainNavbarItemMap.keys()); + const curMainNavbarItems = getCurrentMainNavbarItems(); + for(const id of curMainNavbarItems) + { + allMainNavbarItemIDSet.delete(id); + } + + if(allMainNavbarItemIDSet.size === 0) return items; + for(const id of allMainNavbarItemIDSet) + { + const item = allMainNavbarItemMap.get(id); + items.push( + { + text: item.text, + onClick: () => onClick(id), + } + ); + } + return items; +} + function canHideCurrentNavbar($item) { if($item.is('.active')) return false; @@ -18,6 +75,22 @@ $(document).on( const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); + const itemsToAdded = generateAddMainNavbarItems((id) => { + const item = allMainNavbarItemMap.get(id); + const $a = $('') + .attr('href', item.url) + .attr('data-id', item['data-id']) + .attr('data-app', item['data-app']) + .append(`${item.text}`); + if(item.badge) + { + $a.append(`${item.badge.text}`); + } + const $navItem = $(''); + $navItem.append($a); + $li.after($navItem); + console.log(getCurrentMainNavbarItems()); + }); const items = [ isMoving ? { @@ -47,9 +120,15 @@ $(document).on( $li.remove(); } }, - { - text: langData.add, - } + itemsToAdded.length === 0 + ? { + text: langData.add, + disabled: true, + } + : { + text: langData.add, + items: itemsToAdded, + } ]; zui.ContextMenu.show( diff --git a/lib/zin/wg/mainnavbar/v1.php b/lib/zin/wg/mainnavbar/v1.php index aa6763948f..ea0c1b301f 100644 --- a/lib/zin/wg/mainnavbar/v1.php +++ b/lib/zin/wg/mainnavbar/v1.php @@ -161,6 +161,7 @@ class mainNavbar extends nav $leftBlock = $this->block('left'); $rightBlock = $this->block('right'); if(empty($leftBlock)) $leftBlock = $this->buildSwitcher(); + jsVar('allMainNavbarItems', $this->prop('items')); return div ( From ca6d5300e2b2f93cb7010d238a1a52ebd1fe9000 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 10:36:19 +0800 Subject: [PATCH 23/47] * [task#126664,0.1h] fix allMainNavbarItems not defined. --- lib/zin/wg/mainnavbar/js/v1.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 2381941578..4d79cfc1f8 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -6,12 +6,14 @@ $(document).ready( { allMainNavbarItemIDs.length = 0; allMainNavbarItemMap.clear(); - console.log(allMainNavbarItems); - for(const item of allMainNavbarItems) + if (typeof allMainNavbarItems !== 'undefined') { - allMainNavbarItemIDs.push(item['data-id']); - allMainNavbarItemMap.set(item['data-id'], item); + for(const item of allMainNavbarItems) + { + allMainNavbarItemIDs.push(item['data-id']); + allMainNavbarItemMap.set(item['data-id'], item); + } } } ); From 042216b9984ec665939ab85db9e2763844b0257f Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 10:43:43 +0800 Subject: [PATCH 24/47] * [task#126662,0.1h] rm new contextmenu action from appsBar. --- module/index/js/index.ui.js | 107 ++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 700a885c61..a677d5c561 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -962,64 +962,67 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) if(code !== 'my') items.push({text: langData.close, onClick: () => closeApp(code)}); } - const $nav = $btn.closest('.nav'); - const isMoving = $nav.is('[z-use-sortable]'); - if(isMoving) + if($btn.closest('#menuNav').length !== 0) { + const $nav = $btn.closest('.nav'); + const isMoving = $nav.is('[z-use-sortable]'); + if(isMoving) + { + items.push( + { + text: langData.save, + onClick: () => { + $btn.closest('.nav').zui().destroy(); + const data = getMenuNavData(); + console.log(data); + } + } + ); + } + else + { + items.push( + { + text: langData.move, + onClick: () => { + const sortable = new zui.Sortable( + '#menuMainNav', + { + animation: 150, + ghostClass: 'bg-primary-pale', + } + ); + } + } + ); + } + + const hideDisabled = code === 'my' || $btn.is('.active'); items.push( { - text: langData.save, - onClick: () => { - $btn.closest('.nav').zui().destroy(); - const data = getMenuNavData(); - console.log(data); - } + text: langData.hide, + onClick: hideDisabled + ? null + : () => { + closeApp(code); + const $li = $btn.closest('li'); + const appName = $li.data('app'); + $li.remove(); + const data = getMenuNavData(); + refreshMenu(); + console.log(appName, data); + }, + disabled: hideDisabled, + } + ); + + items.push( + { + text: langData.add, + items: generateAddMenuNavItems(addMenuToMainNavCb($btn.closest('li'))) } ); } - else - { - items.push( - { - text: langData.move, - onClick: () => { - const sortable = new zui.Sortable( - '#menuMainNav', - { - animation: 150, - ghostClass: 'bg-primary-pale', - } - ); - } - } - ); - } - - const hideDisabled = code === 'my' || $btn.is('.active'); - items.push( - { - text: langData.hide, - onClick: hideDisabled - ? null - : () => { - closeApp(code); - const $li = $btn.closest('li'); - const appName = $li.data('app'); - $li.remove(); - const data = getMenuNavData(); - refreshMenu(); - console.log(appName, data); - }, - disabled: hideDisabled, - } - ); - - items.push( - { - text: langData.add, - items: generateAddMenuNavItems(addMenuToMainNavCb($btn.closest('li'))) - } - ); zui.ContextMenu.show( { From cb5d80f5370bd64cd13f27b2bc16c8295a9368b1 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 11:01:27 +0800 Subject: [PATCH 25/47] * [task#126663,0.3h] fix navbar contextmenu add action. --- lib/zin/wg/navbar/js/v1.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 070fc07167..91baca8190 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -15,15 +15,17 @@ $(document).ready( continue; } - if (item.type === 'dropdown') - { - allNavbarItemIDs.push(item.id); - allNavbarItemMap.set(item.id, item); - continue; - } + const id = item['data-id'] || item.id; - allNavbarItemIDs.push(item['data-id']); - allNavbarItemMap.set(item['data-id'], item); + // if (item.type === 'dropdown') + // { + // allNavbarItemIDs.push(item.id); + // allNavbarItemMap.set(item.id, item); + // continue; + // } + + allNavbarItemIDs.push(id); + allNavbarItemMap.set(id, item); } } ); @@ -43,13 +45,13 @@ function getCurrentNavbarItems() } const $a = $elm.find('a'); - if($elm.is('.nav-dropdown')) - { - items[index] = $a.prop('id'); - return; - } + items[index] = $a.attr('data-id') || $a.attr('id'); - items[index] = $a.attr('data-id'); + // if($elm.is('.nav-dropdown')) + // { + // items[index] = $a.prop('id'); + // return; + // } } ); return items; From 2639926af9eb4b397f5551b428b40cc9d264d75f Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 11:26:25 +0800 Subject: [PATCH 26/47] * [task#126490,0.5h] increase grab area of nav-divider. --- lib/zin/wg/navbar/v1.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 87e2242228..478c5549be 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -15,6 +15,7 @@ class navbar extends wg return <<<'CSS' #navbar .nav[z-use-sortable] > li:hover {cursor: grab !important;} #navbar .nav[z-use-sortable] > li > a:hover {cursor: grab !important;} + #navbar .nav li.nav-divider.divider {border: none; width: 1px; background: currentColor; margin: 0; padding-left: var(--nav-divider-margin); padding-right: var(--nav-divider-margin); box-sizing: content-box; background-clip: content-box;} CSS; } From b72257b97acf3b78ad254a85f15f7c6b21bb3e0d Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Fri, 23 Aug 2024 13:24:58 +0800 Subject: [PATCH 27/47] * [task#126489,0.2h] change lang. --- lib/zin/wg/mainnavbar/js/v1.js | 2 +- lib/zin/wg/navbar/js/v1.js | 2 +- module/index/js/index.ui.js | 4 ++-- module/index/lang/de.php | 4 ++-- module/index/lang/en.php | 4 ++-- module/index/lang/fr.php | 4 ++-- module/index/lang/zh-cn.php | 4 ++-- module/index/lang/zh-tw.php | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 4d79cfc1f8..6bad15b629 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -102,7 +102,7 @@ $(document).on( } } : { - text: langData.move, + text: langData.sort, onClick: () => { const sortable = new zui.Sortable( '#mainNavbar .nav', diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 91baca8190..59a094b72e 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -120,7 +120,7 @@ $(document).on( } } : { - text: langData.move, + text: langData.sort, onClick: () => { const sortable = new zui.Sortable( '#navbar .nav', diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index a677d5c561..82fe2e5d39 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -890,7 +890,7 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) { items.push( { - text: langData.move, + text: langData.sort, onClick: () => { const sortable = new zui.Sortable( '#menuMainNav', @@ -983,7 +983,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) { items.push( { - text: langData.move, + text: langData.sort, onClick: () => { const sortable = new zui.Sortable( '#menuMainNav', diff --git a/module/index/lang/de.php b/module/index/lang/de.php index 378a3b45c9..1f0ebe69bf 100644 --- a/module/index/lang/de.php +++ b/module/index/lang/de.php @@ -9,8 +9,8 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = 'Open'; $lang->index->dock->reload = 'Reload'; $lang->index->dock->close = 'Close'; -$lang->index->dock->move = 'Move'; -$lang->index->dock->save = 'Save order'; +$lang->index->dock->sort = 'Sort'; +$lang->index->dock->save = 'Exit sort'; $lang->index->dock->hide = 'Hide'; $lang->index->dock->add = 'Add'; $lang->index->dock->divider = 'Divider'; diff --git a/module/index/lang/en.php b/module/index/lang/en.php index 6390153c72..799dae9f6b 100644 --- a/module/index/lang/en.php +++ b/module/index/lang/en.php @@ -9,8 +9,8 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = 'Open'; $lang->index->dock->reload = 'Reload'; $lang->index->dock->close = 'Close'; -$lang->index->dock->move = 'Move'; -$lang->index->dock->save = 'Save order'; +$lang->index->dock->sort = 'Sort'; +$lang->index->dock->save = 'Exit sort'; $lang->index->dock->hide = 'Hide'; $lang->index->dock->add = 'Add'; $lang->index->dock->divider = 'Divider'; diff --git a/module/index/lang/fr.php b/module/index/lang/fr.php index 378a3b45c9..1f0ebe69bf 100644 --- a/module/index/lang/fr.php +++ b/module/index/lang/fr.php @@ -9,8 +9,8 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = 'Open'; $lang->index->dock->reload = 'Reload'; $lang->index->dock->close = 'Close'; -$lang->index->dock->move = 'Move'; -$lang->index->dock->save = 'Save order'; +$lang->index->dock->sort = 'Sort'; +$lang->index->dock->save = 'Exit sort'; $lang->index->dock->hide = 'Hide'; $lang->index->dock->add = 'Add'; $lang->index->dock->divider = 'Divider'; diff --git a/module/index/lang/zh-cn.php b/module/index/lang/zh-cn.php index 0b283ae5d0..2ff00b66c1 100644 --- a/module/index/lang/zh-cn.php +++ b/module/index/lang/zh-cn.php @@ -9,8 +9,8 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = '打开'; $lang->index->dock->reload = '刷新'; $lang->index->dock->close = '关闭'; -$lang->index->dock->move = '移动'; -$lang->index->dock->save = '保存顺序'; +$lang->index->dock->sort = '排序'; +$lang->index->dock->save = '退出排序'; $lang->index->dock->hide = '隐藏'; $lang->index->dock->add = '添加'; $lang->index->dock->divider = '分割线'; diff --git a/module/index/lang/zh-tw.php b/module/index/lang/zh-tw.php index 4edb73e372..7d9e78ae4c 100644 --- a/module/index/lang/zh-tw.php +++ b/module/index/lang/zh-tw.php @@ -9,8 +9,8 @@ $lang->index->dock = new stdClass(); $lang->index->dock->open = '打開'; $lang->index->dock->reload = '刷新'; $lang->index->dock->close = '關閉'; -$lang->index->dock->move = '移動'; -$lang->index->dock->save = '保存順序'; +$lang->index->dock->sort = '排序'; +$lang->index->dock->save = '退出排序'; $lang->index->dock->hide = '隱藏'; $lang->index->dock->add = '添加'; $lang->index->dock->divider = '分割線'; From 5a570d73b28b9f209d67f62bc5c25559f16970e5 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 26 Aug 2024 05:45:57 +0000 Subject: [PATCH 28/47] * [task#126927,done,1h] support save custom nav menu. --- lib/zin/wg/mainnavbar/js/v1.js | 2 +- module/common/model.php | 37 +++++++++++++++++++++++++------ module/custom/control.php | 20 +++++++++++++++++ module/index/control.php | 2 +- module/index/js/index.ui.js | 40 +++++++++++++++++++++------------- 5 files changed, 77 insertions(+), 24 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 6bad15b629..d1e510b59f 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -145,4 +145,4 @@ $(document).on( ); event.preventDefault(); } -); \ No newline at end of file +); diff --git a/module/common/model.php b/module/common/model.php index af09993bff..f1a1bcebf0 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -604,12 +604,13 @@ class commonModel extends model * Get main nav items list * * @param string $moduleName + * @param bool $useDefault 是否使用语言项中的默认值 * * @static * @access public * @return array */ - public static function getMainNavList(string $moduleName): array + public static function getMainNavList(string $moduleName, bool $useDefault = false): array { global $lang, $app, $config; @@ -618,7 +619,18 @@ class commonModel extends model /* Ensure user has latest rights set. */ $app->user->rights = $app->control->loadModel('user')->authorize($app->user->account); - $menuOrder = $lang->mainNav->menuOrder; + $menuOrder = array(); + $hasCustomMenu = false; + if(isset($config->customMenu->nav) && !$useDefault) + { + $items = json_decode($config->customMenu->nav); + foreach($items as $item) $menuOrder[$item->order] = $item->name; + $hasCustomMenu = true; + } + else + { + $menuOrder = $lang->mainNav->menuOrder; + } ksort($menuOrder); $items = array(); @@ -627,18 +639,29 @@ class commonModel extends model foreach($menuOrder as $key => $group) { + // 如果有自定义菜单,则直接用自定义后的divider分隔符 + if($hasCustomMenu && $group == 'divider') + { + $items[] = 'divider'; + continue; + } + if($group != 'my' && !empty($app->user->rights['acls']['views']) && !isset($app->user->rights['acls']['views'][$group])) continue; // 后台权限分组中没有给导航视图 if(!isset($lang->mainNav->$group)) continue; $nav = $lang->mainNav->$group; list($title, $currentModule, $currentMethod, $vars) = explode('|', $nav); - /* When last divider is not used in mainNav, use it next menu. */ - $printDivider = ($printDivider or ($lastItem != $key) and strpos($lang->dividerMenu, ",{$group},") !== false) ? true : false; - if($printDivider and !empty($items)) + // 没有自定义过菜单,用默认语言项中的divider分隔符 + if(!$hasCustomMenu) { - $items[] = 'divider'; - $printDivider = false; + /* When last divider is not used in mainNav, use it next menu. */ + $printDivider = ($printDivider or ($lastItem != $key) and strpos($lang->dividerMenu, ",{$group},") !== false) ? true : false; + if($printDivider and !empty($items)) + { + $items[] = 'divider'; + $printDivider = false; + } } $display = false; diff --git a/module/custom/control.php b/module/custom/control.php index b3befc3ba6..65a593aa90 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -552,4 +552,24 @@ class custom extends control $this->display(); } + + /** + * Ajax set menu + *- + * @access public + * @return void + */ + public function ajaxSetMenu() + { + if($_POST) + { + $menu = $this->post->menu; // 导航类型,nav(左侧主导航)|main(顶部一级导航)|module(顶部二级导航) + $items = $this->post->items; // 导航项 + $account = $this->app->user->account; + + if($menu && $items) $this->loadModel('setting')->setItem("$account.common.customMenu.$menu@{$this->config->vision}", $items); + } + + $this->send(array('result' => 'success')); + } } diff --git a/module/index/control.php b/module/index/control.php index 3411feeb2b..4c94a17983 100644 --- a/module/index/control.php +++ b/module/index/control.php @@ -45,7 +45,7 @@ class index extends control $this->view->showFeatures = $this->indexZen->checkShowFeatures(); $this->view->latestVersionList = $latestVersionList; $this->view->appsItems = commonModel::getMainNavList($this->app->rawModule); - $this->view->allAppsItems = commonModel::getMainNavList($this->app->rawModule); + $this->view->allAppsItems = commonModel::getMainNavList($this->app->rawModule, true); $this->view->browserMessage = $this->loadModel('message')->getBrowserMessageConfig(); $this->display(); diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 82fe2e5d39..ed1d88c5bf 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -825,23 +825,29 @@ function getMenuNavData() const $nav = $('#menuMainNav'); $nav.children().each(function(index, element) { const $elm = $(element); - data[index] = $elm.is('.divider') - ? 'divider' - : $elm.data('app'); - + data.push( + { + name: $elm.is('.divider') ? 'divider' : $elm.data('app'), + order: index * 5 + } + ); }); return data; } function generateAddMenuNavItems(onClick) { + const customUrl = $.createLink('custom', 'ajaxSetMenu'); const items = [ { icon: 'icon-minus', text: langData.divider, - onClick: () => onClick('divider'), - }, - + onClick: () => { + onClick('divider'); + const data = getMenuNavData(); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + } + } ]; const allAppCodeSet = new Set(allAppsItemsMap.keys()); @@ -860,7 +866,11 @@ function generateAddMenuNavItems(onClick) { icon, text: title, - onClick: () => onClick(name) + onClick: () => { + onClick(name); + const data = getMenuNavData(); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + } } ); } @@ -873,6 +883,7 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) const $nav = $divider.closest('.nav'); const isMoving = $nav.is('[z-use-sortable]'); const items = []; + const customUrl = $.createLink('custom', 'ajaxSetMenu'); if(isMoving) { items.push( @@ -881,7 +892,7 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) onClick: () => { $divider.closest('.nav').zui().destroy(); const data = getMenuNavData(); - console.log(data); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); } } ); @@ -908,11 +919,10 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) text: langData.hide, onClick: () => { const $li = $divider.closest('li'); - const appName = $li.data('app'); $li.remove(); const data = getMenuNavData(); refreshMenu(); - console.log(appName, data); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); } } ); @@ -962,6 +972,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) if(code !== 'my') items.push({text: langData.close, onClick: () => closeApp(code)}); } + const customUrl = $.createLink('custom', 'ajaxSetMenu'); if($btn.closest('#menuNav').length !== 0) { const $nav = $btn.closest('.nav'); @@ -974,7 +985,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) onClick: () => { $btn.closest('.nav').zui().destroy(); const data = getMenuNavData(); - console.log(data); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); } } ); @@ -1006,11 +1017,10 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) : () => { closeApp(code); const $li = $btn.closest('li'); - const appName = $li.data('app'); $li.remove(); const data = getMenuNavData(); refreshMenu(); - console.log(appName, data); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); }, disabled: hideDisabled, } @@ -1312,4 +1322,4 @@ function addMenuToMainNavCb($li) { refreshMenu(); if(!apps.defaultCode) apps.defaultCode = item.code; }; -} \ No newline at end of file +} From 8b240a23f6a32c490e844a8e4343d833c430bbe0 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 26 Aug 2024 08:43:24 +0000 Subject: [PATCH 29/47] * [task#126927,doing,3h] support custom main menu. --- lib/zin/wg/mainnavbar/js/v1.js | 1 + lib/zin/wg/navbar/js/v1.js | 76 +++++++++++++++++++++++++--------- lib/zin/wg/navbar/v1.php | 9 +++- module/custom/model.php | 19 +++++++-- module/project/tao.php | 20 ++++++++- 5 files changed, 100 insertions(+), 25 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index d1e510b59f..1d47a4391f 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -99,6 +99,7 @@ $(document).on( text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); + console.log(getCurrentMainNavbarItems()); } } : { diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 59a094b72e..73bf707475 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -33,19 +33,18 @@ $(document).ready( function getCurrentNavbarItems() { const items = []; - const $nav = $('#navbar .nav'); + const $nav = $('#navbar .nav'); $nav.children().each( function(index, element) { const $elm = $(element) - if($elm.is('.nav-divider')) - { - items[index] = 'divider'; - return; - } - - const $a = $elm.find('a'); - items[index] = $a.attr('data-id') || $a.attr('id'); + const $a = $elm.find('a'); + items.push( + { + name: $elm.is('.nav-divider') ? 'divider' : ($a.attr('data-id') || $a.attr('id')), + order: index * 5 + } + ); // if($elm.is('.nav-dropdown')) // { @@ -59,10 +58,17 @@ function getCurrentNavbarItems() function generateAddNavbarItems(onClick) { + const customUrl = $.createLink('custom', 'ajaxSetMenu'); const items = [ { text: langData.divider, - onClick: () => onClick('divider') + onClick: () => { + onClick('divider'); + const items = getCurrentNavbarItems(); + const app = $.apps.getLastApp().code; + const menu = getMenuName(items, app); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + } } ]; @@ -81,7 +87,13 @@ function generateAddNavbarItems(onClick) items.push( { text: item.text, - onClick: () => onClick(id), + onClick: () => { + onClick(id); + const items = getCurrentNavbarItems(); + const app = $.apps.getLastApp().code; + const menu = getMenuName(items, app); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + } } ); } @@ -100,23 +112,45 @@ function canHideCurrentNavbar($item) return true; } +function getMenuName(items, app) +{ + const isHomeMenu = items.length <= 3 && ['program', 'project', 'product', 'execution'].includes(app); + + if(typeof projectModel !== 'undefined') + { + return `project-${projectModel}`; + } + else if(isHomeMenu) + { + return `${app}-home`; + } + else + { + return app; + } +} + $(document).on( 'contextmenu', '#navbar .nav-item:not(.nav-dropdown) > a, #navbar .nav-divider', function(event) { - const $item = $(this); - const $nav = $('#navbar .nav'); - const isMoving = $nav.is('[z-use-sortable]'); + const $item = $(this); + const $nav = $('#navbar .nav'); + const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); - const $li = $item.closest('li'); + const $li = $item.closest('li'); + const app = $.apps.getLastApp().code; + const customUrl = $.createLink('custom', 'ajaxSetMenu'); const items = [ isMoving ? { text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); - console.log(getCurrentNavbarItems()); + const items = getCurrentNavbarItems(); + const menu = getMenuName(items, app); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } } : { @@ -138,7 +172,9 @@ $(document).on( ? null : () => { $li.remove(); - console.log(getCurrentNavbarItems()); + const items = getCurrentNavbarItems(); + const menu = getMenuName(items, app); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } }, { @@ -156,7 +192,9 @@ $(document).on( const $navItem = $(''); $navItem.append($a); $li.after($navItem); - console.log(getCurrentNavbarItems()); + const items = getCurrentNavbarItems(); + const menu = getMenuName(items, app); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); }), } ]; @@ -172,4 +210,4 @@ $(document).on( ); event.preventDefault(); } -); \ No newline at end of file +); diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 478c5549be..4105076302 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -140,8 +140,8 @@ class navbar extends wg if($isTutorialMode and defined('WIZARD_MODULE')) $currentModule = WIZARD_MODULE; if($isTutorialMode and defined('WIZARD_METHOD')) $currentMethod = WIZARD_METHOD; - $menu = \customModel::getMainMenu(); $tab = $app->tab; + $menu = \customModel::getMainMenu(); $activeMenu = ''; $activeMenuID = data('activeMenuID'); $items = array(); @@ -181,6 +181,13 @@ class navbar extends wg $isActive = true; } + if($menuItem->link['module'] == 'project' and $menuItem->link['method'] == 'index') + { + $projectID = str_replace('project=', '', $menuItem->link['vars']); + $projectModel = $app->dbh->query("SELECT `model` FROM " . TABLE_PROJECT . " WHERE `id` = '$projectID'")->fetch(); + if($projectModel) jsVar('projectModel', $projectModel->model); + } + if($menuItem->link['module'] == 'execution' and $menuItem->link['method'] == 'more') { $executionID = $menuItem->link['vars']; diff --git a/module/custom/model.php b/module/custom/model.php index b88933618b..39dad69fc2 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -226,7 +226,7 @@ class customModel extends model else { $isFirst = false; - if(!isset($menu[$item->order]->divider))$menu[$item->order]->divider = false; + if(!isset($menu[$item->order]->divider)) $menu[$item->order]->divider = false; } } @@ -275,10 +275,14 @@ class customModel extends model } elseif(is_array($customMenu)) { + $prev = ''; foreach($customMenu as $customMenuItem) { + $name = $customMenuItem->name; if(!isset($customMenuItem->order)) $customMenuItem->order = $order; - $customMenuMap[$customMenuItem->name] = $customMenuItem; + if($prev == 'divider') $customMenuItem->divider = true; + if($name != 'divider') $customMenuMap[$name] = $customMenuItem; + $prev = $name; $order ++; } } @@ -327,6 +331,8 @@ class customModel extends model $module = $menuModuleName; foreach($allMenu as $name => $item) { + if($menuModuleName == 'main' && !isset($customMenuMap[$name])) continue; // 顶部一级导航,自定义过滤掉的菜单不显示。 + $name = (string)$name; if(is_object($item)) $item = (array)$item; @@ -387,6 +393,7 @@ class customModel extends model /* Process menu item's order and hidden attirbute. */ $menuItem = static::buildMenuItem($item, $customMenuMap, $name, $label, $itemLink, $isTutorialMode, $subMenu); $menuItem->order = (isset($customMenuMap[$name]) && isset($customMenuMap[$name]->order) ? $customMenuMap[$name]->order : $order ++); + if(isset($customMenuMap[$name]) && isset($customMenuMap[$name]->divider)) $menuItem->divider = true; if($app->viewType == 'mhtml' && isset($config->custom->moblieHidden[$menuModuleName]) && in_array($name, $config->custom->moblieHidden[$menuModuleName])) $menuItem->hidden = 1; // Hidden menu by config in mobile. while(isset($menu[$menuItem->order])) $menuItem->order ++; $menu[$menuItem->order] = $menuItem; @@ -474,8 +481,12 @@ class customModel extends model if($module == 'main' and !empty($lang->menu)) $allMenu = $lang->menu; if($module != 'main' and isset($lang->menu->$module) and isset($lang->menu->{$module}['subMenu'])) $allMenu = $lang->menu->{$module}['subMenu']; if($module == 'product' and isset($allMenu->branch)) $allMenu->branch = str_replace('@branch@', $lang->custom->branch, $allMenu->branch); - $flowModule = $config->global->flow . '_' . $module; - $customMenu = isset($config->customMenu->$flowModule) ? $config->customMenu->$flowModule : array(); + + /* 获取自定义过的导航。 */ + $isHomeMenu = in_array($app->tab, array('program', 'product', 'project', 'execution')) && count((array)$allMenu) <= 3; + $customKey = $isHomeMenu ? $app->tab . '-home' : $app->tab; + $customMenu = isset($config->customMenu->{$customKey}) ? $config->customMenu->{$customKey}: array(); + if(!empty($customMenu) && is_string($customMenu) && substr($customMenu, 0, 1) === '[') $customMenu = json_decode($customMenu); if($module == 'my' && empty($config->global->scoreStatus)) unset($allMenu->score); diff --git a/module/project/tao.php b/module/project/tao.php index 613eb1488c..d9e469fa19 100755 --- a/module/project/tao.php +++ b/module/project/tao.php @@ -964,7 +964,7 @@ class projectTao extends projectModel */ protected function setMenuByModel(string $projectModel): bool { - global $lang; + global $lang, $config; $model = 'scrum'; if(in_array($projectModel, $this->config->project->waterfallList)) { @@ -988,6 +988,24 @@ class projectTao extends projectModel if(isset($lang->$model)) { + $key = 'project-' . $model; + if(isset($config->customMenu->$key)) + { + $lang->{$model}->menuOrder = array(); + $lang->{$model}->dividerMenu = ''; + + $items = json_decode($config->customMenu->$key); + $prevItem = ''; + foreach($items as $item) + { + $lang->{$model}->menuOrder[$item->order] = $item->name; + if($prevItem == 'divider') $lang->{$model}->dividerMenu .= $item->name . ','; + $prevItem = $item->name; + } + + if($lang->{$model}->dividerMenu) $lang->{$model}->dividerMenu = ',' . trim($lang->{$model}->dividerMenu, ',') . ','; + } + $lang->project->menu = $lang->{$model}->menu; $lang->project->menuOrder = $lang->{$model}->menuOrder; $lang->project->dividerMenu = $lang->{$model}->dividerMenu; From 4a2a7caa2a138b5ab34258a25dd6d1bc2aa26f85 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Mon, 26 Aug 2024 17:39:37 +0800 Subject: [PATCH 30/47] + [task#126910,start,1h] init graph wg. --- lib/zin/func.php | 1 + lib/zin/wg/graph/v1.php | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 lib/zin/wg/graph/v1.php diff --git a/lib/zin/func.php b/lib/zin/func.php index 2686168438..4aeb431fba 100644 --- a/lib/zin/func.php +++ b/lib/zin/func.php @@ -134,6 +134,7 @@ function detailSide(): detailSide {return createWg('detailSide', func_get_args() function detailBody(): detailBody {return createWg('detailBody', func_get_args());} function detailForm(): detailForm {return createWg('detailForm', func_get_args());} function echarts(): echarts {return createWg('echarts', func_get_args());} +function graph(): graph {return createWg('graph', func_get_args());} function popovers(): popovers {return createWg('popovers', func_get_args());} function backBtn(): backBtn {return createWg('backBtn', func_get_args());} function collapseBtn(): collapseBtn {return createWg('collapseBtn', func_get_args());} diff --git a/lib/zin/wg/graph/v1.php b/lib/zin/wg/graph/v1.php new file mode 100644 index 0000000000..44e5eeb367 --- /dev/null +++ b/lib/zin/wg/graph/v1.php @@ -0,0 +1,26 @@ +prop(array('type', 'width', 'height', 'responsive')); + + return zui::graph( + set::_id('zin_graph_' . uniqid()), + set::type($type), + set::responsive($responsive), + set::_style(array('width' => is_int($width) ? "{$width}px" : $width, 'height' => is_int($height) ? "{$height}px" : $height)), + set($this->getRestProps()), + ); + } +} From e6b5f579dedea61b4cd203b38f0d09a1607f8183 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 27 Aug 2024 01:50:58 +0000 Subject: [PATCH 31/47] * [task#126928,done,1h] support save custom main nav menu. --- lib/zin/wg/mainnavbar/js/v1.js | 23 ++++++++---- lib/zin/wg/mainnavbar/v1.php | 9 ++--- module/custom/model.php | 64 +++++++--------------------------- 3 files changed, 33 insertions(+), 63 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 1d47a4391f..da7725bfa5 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -27,7 +27,12 @@ function getCurrentMainNavbarItems() { const $elm = $(element); $a = $elm.find('a'); - items[index] = $a.attr('data-id'); + items.push( + { + name: $a.attr('data-id'), + order: index * 5 + } + ); } ); return items; @@ -72,11 +77,13 @@ $(document).on( '#mainNavbar .nav-item > a', function(event) { - const $item = $(this); - const $nav = $('#mainNavbar .nav'); - const isMoving = $nav.is('[z-use-sortable]'); + const $item = $(this); + const $nav = $('#mainNavbar .nav'); + const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); - const $li = $item.closest('li'); + const $li = $item.closest('li'); + const menu = $item.data('group'); + const customUrl = $.createLink('custom', 'ajaxSetMenu'); const itemsToAdded = generateAddMainNavbarItems((id) => { const item = allMainNavbarItemMap.get(id); const $a = $('') @@ -91,7 +98,6 @@ $(document).on( const $navItem = $(''); $navItem.append($a); $li.after($navItem); - console.log(getCurrentMainNavbarItems()); }); const items = [ isMoving @@ -99,7 +105,8 @@ $(document).on( text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); - console.log(getCurrentMainNavbarItems()); + const items = getCurrentMainNavbarItems(); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } } : { @@ -121,6 +128,8 @@ $(document).on( ? null : () => { $li.remove(); + const items = getCurrentMainNavbarItems(); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } }, itemsToAdded.length === 0 diff --git a/lib/zin/wg/mainnavbar/v1.php b/lib/zin/wg/mainnavbar/v1.php index ea0c1b301f..2c6dd52bc8 100644 --- a/lib/zin/wg/mainnavbar/v1.php +++ b/lib/zin/wg/mainnavbar/v1.php @@ -112,10 +112,11 @@ class mainNavbar extends nav $item = array(); $link = $menuItem['link']; $name = $menuItem['name']; - $item['text'] = $menuItem['text']; - $item['url'] = commonModel::createMenuLink((object)$menuItem, $app->tab); - $item['data-id'] = $name; - $item['data-app'] = $app->tab; + $item['text'] = $menuItem['text']; + $item['url'] = commonModel::createMenuLink((object)$menuItem, $app->tab); + $item['data-id'] = $name; + $item['data-app'] = $app->tab; + $item['data-group'] = $app->tab . '-' . $activeMenu; $active = ''; if($activeItem && $activeItem == $name) diff --git a/module/custom/model.php b/module/custom/model.php index 39dad69fc2..9e36bfa8ee 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -248,43 +248,17 @@ class customModel extends model global $lang; $customMenuMap = array(); $order = 1; - if($customMenu) + if($customMenu && is_array($customMenu)) { - if(is_string($customMenu)) + $prev = ''; + foreach($customMenu as $customMenuItem) { - $customMenuItems = explode(',', $customMenu); - foreach($customMenuItems as $customMenuItem) - { - $item = new stdclass(); - $item->name = $customMenuItem; - $item->order = $order ++; - $item->hidden = false; - $customMenuMap[$item->name] = $item; - } - foreach($allMenu as $name => $item) - { - if(!isset($customMenuMap[$name])) - { - $item = new stdclass(); - $item->name = $name; - $item->hidden = true; - $item->order = $order ++; - $customMenuMap[$name] = $item; - } - } - } - elseif(is_array($customMenu)) - { - $prev = ''; - foreach($customMenu as $customMenuItem) - { - $name = $customMenuItem->name; - if(!isset($customMenuItem->order)) $customMenuItem->order = $order; - if($prev == 'divider') $customMenuItem->divider = true; - if($name != 'divider') $customMenuMap[$name] = $customMenuItem; - $prev = $name; - $order ++; - } + $name = $customMenuItem->name; + if(!isset($customMenuItem->order)) $customMenuItem->order = $order; + if($prev == 'divider') $customMenuItem->divider = true; + if($name != 'divider') $customMenuMap[$name] = $customMenuItem; + $prev = $name; + $order ++; } } elseif($module) @@ -331,7 +305,7 @@ class customModel extends model $module = $menuModuleName; foreach($allMenu as $name => $item) { - if($menuModuleName == 'main' && !isset($customMenuMap[$name])) continue; // 顶部一级导航,自定义过滤掉的菜单不显示。 + if(!empty($customMenuMap) && !isset($customMenuMap[$name])) continue; // 自定义过滤掉的菜单不显示。 $name = (string)$name; if(is_object($item)) $item = (array)$item; @@ -419,13 +393,6 @@ class customModel extends model */ public static function buildMenuItem(array|string $item, $customMenuMap, string $name = '', string $label = '', string|array $itemLink = '', bool $isTutorialMode = false, array $subMenu = array()): object { - if($item === '-') - { - $menuItem = new stdclass(); - $menuItem->type = 'divider'; - return $menuItem; - } - if(is_array($item) && (isset($item['subMenu']) || isset($item['dropMenu']))) { foreach(array('subMenu', 'dropMenu') as $key) @@ -435,13 +402,6 @@ class customModel extends model { if(isset($subItem->link['module']) && isset($subItem->link['method'])) $subItem->hidden = !common::hasPriv($subItem->link['module'], $subItem->link['method']); } - if(isset($customMenuMap[$name]->$key)) - { - foreach($customMenuMap[$name]->$key as $subItem) - { - if(isset($subItem->hidden) && isset($item[$key][$subItem->name])) $item[$key][$subItem->name]->hidden = $subItem->hidden; - } - } } } @@ -483,8 +443,8 @@ class customModel extends model if($module == 'product' and isset($allMenu->branch)) $allMenu->branch = str_replace('@branch@', $lang->custom->branch, $allMenu->branch); /* 获取自定义过的导航。 */ - $isHomeMenu = in_array($app->tab, array('program', 'product', 'project', 'execution')) && count((array)$allMenu) <= 3; - $customKey = $isHomeMenu ? $app->tab . '-home' : $app->tab; + $isHomeMenu = in_array($app->tab, array('program', 'product', 'project', 'execution')) && count((array)$allMenu) <= 3 && $module == 'main'; + $customKey = $isHomeMenu ? $app->tab . '-home' : ($module == 'main' ? $app->tab : $app->tab . '-' . $module); $customMenu = isset($config->customMenu->{$customKey}) ? $config->customMenu->{$customKey}: array(); if(!empty($customMenu) && is_string($customMenu) && substr($customMenu, 0, 1) === '[') $customMenu = json_decode($customMenu); From e832a02ade42436580e75c4438eb8d68aebee8cd Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 11:02:23 +0800 Subject: [PATCH 32/47] * [refac] add comments and fix add actions. --- lib/zin/wg/mainnavbar/js/v1.js | 44 +++++++++++++++----- lib/zin/wg/navbar/js/v1.js | 74 +++++++++++++++++++++------------- module/index/js/index.ui.js | 30 ++++++++++++-- 3 files changed, 106 insertions(+), 42 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index da7725bfa5..6484fb8b53 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -1,23 +1,35 @@ -const allMainNavbarItemIDs = []; +/** + * @type {string[]} + */ +const allMainNavbarItemNames = []; + +/** + * @type {Map} + */ const allMainNavbarItemMap = new Map(); $(document).ready( function() { - allMainNavbarItemIDs.length = 0; + allMainNavbarItemNames.length = 0; allMainNavbarItemMap.clear(); if (typeof allMainNavbarItems !== 'undefined') { for(const item of allMainNavbarItems) { - allMainNavbarItemIDs.push(item['data-id']); + allMainNavbarItemNames.push(item['data-id']); allMainNavbarItemMap.set(item['data-id'], item); } } } ); +/** + * Get current main navbar items data. + * + * @returns {Array<{name: string; order: number;}>} + */ function getCurrentMainNavbarItems() { const items = []; @@ -38,30 +50,42 @@ function getCurrentMainNavbarItems() return items; } +/** + * Generate main menu nav items to be added. + * + * @param {(name: string) => void} onClick + * @returns {Array<{text: string; onClick: () => void;}>} + */ function generateAddMainNavbarItems(onClick) { const items = []; const allMainNavbarItemIDSet = new Set(allMainNavbarItemMap.keys()); const curMainNavbarItems = getCurrentMainNavbarItems(); - for(const id of curMainNavbarItems) + for(const {name} of curMainNavbarItems) { - allMainNavbarItemIDSet.delete(id); + allMainNavbarItemIDSet.delete(name); } if(allMainNavbarItemIDSet.size === 0) return items; - for(const id of allMainNavbarItemIDSet) + for(const name of allMainNavbarItemIDSet) { - const item = allMainNavbarItemMap.get(id); + const item = allMainNavbarItemMap.get(name); items.push( { text: item.text, - onClick: () => onClick(id), + onClick: () => onClick(name), } ); } return items; } +/** + * Checks whether the current navbar item can be hidden. + * + * @param {Cash} $item + * @returns {boolean} + */ function canHideCurrentNavbar($item) { if($item.is('.active')) return false; @@ -84,8 +108,8 @@ $(document).on( const $li = $item.closest('li'); const menu = $item.data('group'); const customUrl = $.createLink('custom', 'ajaxSetMenu'); - const itemsToAdded = generateAddMainNavbarItems((id) => { - const item = allMainNavbarItemMap.get(id); + const itemsToAdded = generateAddMainNavbarItems((name) => { + const item = allMainNavbarItemMap.get(name); const $a = $('') .attr('href', item.url) .attr('data-id', item['data-id']) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 73bf707475..8b679f04ca 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -1,35 +1,40 @@ -const allNavbarItemIDs = []; +/** + * @type {string[]} + */ +const allNavbarItemNames = []; + +/** + * @type {Map} + */ const allNavbarItemMap = new Map(); $(document).ready( function() { - allNavbarItemIDs.length = 0; + allNavbarItemNames.length = 0; allNavbarItemMap.clear(); for(const item of allNavbarItems) { if(item.type === 'divider') { - allNavbarItemIDs.push('divider'); + allNavbarItemNames.push('divider'); continue; } - const id = item['data-id'] || item.id; + const name = item['data-id'] || item.id; - // if (item.type === 'dropdown') - // { - // allNavbarItemIDs.push(item.id); - // allNavbarItemMap.set(item.id, item); - // continue; - // } - - allNavbarItemIDs.push(id); - allNavbarItemMap.set(id, item); + allNavbarItemNames.push(name); + allNavbarItemMap.set(name, item); } } ); +/** + * Get current navbar items data. + * + * @returns {Array<{name: string; order: number;}>} + */ function getCurrentNavbarItems() { const items = []; @@ -45,17 +50,17 @@ function getCurrentNavbarItems() order: index * 5 } ); - - // if($elm.is('.nav-dropdown')) - // { - // items[index] = $a.prop('id'); - // return; - // } } ); return items; } +/** + * Generate navbar items to be added. + * + * @param {(item: string) => void} onClick click handler of navbar item. + * @returns {Array<{text: string; onClick: () => void;}>} + */ function generateAddNavbarItems(onClick) { const customUrl = $.createLink('custom', 'ajaxSetMenu'); @@ -74,21 +79,21 @@ function generateAddNavbarItems(onClick) const allNavbarItemIDSet = new Set(allNavbarItemMap.keys()); const curNavbarItems = getCurrentNavbarItems(); - for(const id of curNavbarItems) + for(const {name} of curNavbarItems) { - if(id === 'divider') continue; - allNavbarItemIDSet.delete(id); + if(name === 'divider') continue; + allNavbarItemIDSet.delete(name); } if(allNavbarItemIDSet.size === 0) return items; - for(const id of allNavbarItemIDSet) + for(const name of allNavbarItemIDSet) { - const item = allNavbarItemMap.get(id); + const item = allNavbarItemMap.get(name); items.push( { text: item.text, onClick: () => { - onClick(id); + onClick(name); const items = getCurrentNavbarItems(); const app = $.apps.getLastApp().code; const menu = getMenuName(items, app); @@ -100,6 +105,12 @@ function generateAddNavbarItems(onClick) return items; } +/** + * Checks whether the current navbar item can be hidden. + * + * @param {Cash} $item + * @returns {boolean} + */ function canHideCurrentNavbar($item) { if($item.is('.nav-divider')) return true; @@ -112,6 +123,13 @@ function canHideCurrentNavbar($item) return true; } +/** + * Get menu name by items and app. + * + * @param {Array<{name: string; order: number;}>} items + * @param {string} app + * @returns {string} + */ function getMenuName(items, app) { const isHomeMenu = items.length <= 3 && ['program', 'project', 'product', 'execution'].includes(app); @@ -179,10 +197,10 @@ $(document).on( }, { text: langData.add, - items: generateAddNavbarItems((id) => { - if(id === 'divider') return $li.after(''); + items: generateAddNavbarItems((name) => { + if(name === 'divider') return $li.after(''); - const item = allNavbarItemMap.get(id); + const item = allNavbarItemMap.get(name); const $a = $('') .attr('href', item.url) .attr('target', item.target) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index ed1d88c5bf..9de7c7587b 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -819,6 +819,11 @@ setTimeout(refreshMenu, 500); $(document).on('click', '.menu-toggle', () => toggleMenu()); toggleMenu(!$('body').hasClass('hide-menu')); +/** + * Get current menu nav data. + * + * @returns {Array<{name: string; order: number;}>} + */ function getMenuNavData() { const data = []; @@ -835,24 +840,29 @@ function getMenuNavData() return data; } +/** + * Generate menu nav items to be added. + * + * @param {(item: string) => void} onClick click handler of menu item. + * @returns {Array<{icon: string; text: string; onClick: () => void;}>} + */ function generateAddMenuNavItems(onClick) { const customUrl = $.createLink('custom', 'ajaxSetMenu'); + const data = getMenuNavData(); const items = [ { icon: 'icon-minus', text: langData.divider, onClick: () => { onClick('divider'); - const data = getMenuNavData(); $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); } } ]; const allAppCodeSet = new Set(allAppsItemsMap.keys()); - const data = getMenuNavData(); - for(const name of data) + for(const {name} of data) { if(name === 'divider') continue; allAppCodeSet.delete(name); @@ -909,7 +919,7 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) animation: 150, ghostClass: 'bg-primary-pale', } - ) + ); } } ); @@ -1275,6 +1285,12 @@ void function generateAllAppsItemsMap() { } }(); +/** + * Get icon and title of app item. + * + * @param {string} name app name + * @returns {[string, string]} + */ function getAppItemIconAndTitle(name) { if(!allAppsItemsMap.has(name)) return[]; @@ -1292,6 +1308,12 @@ function getAppItemIconAndTitle(name) return []; } +/** + * Add menu item to #mainNav callback, used by generateAddMenuNavItems. + * + * @param {Cash} $li menu item li + * @returns {(name: string) => void} + */ function addMenuToMainNavCb($li) { return (name) => { if(name === 'divider') return $li.after('
  • '); From 2f414cfbef69aed7004b090a0178c29984cf76a0 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 27 Aug 2024 03:06:21 +0000 Subject: [PATCH 33/47] Merge Code. --- lib/zin/wg/navbar/js/v1.js | 19 ++++++++++--------- lib/zin/wg/navbar/v1.php | 16 ++++++++++++---- module/admin/model.php | 19 +++++++++++++++++++ module/common/lang/menu.php | 3 ++- module/common/model.php | 16 +++++++++------- module/custom/model.php | 12 ++++++------ 6 files changed, 58 insertions(+), 27 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 8b679f04ca..f3bae57eed 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -71,7 +71,7 @@ function generateAddNavbarItems(onClick) onClick('divider'); const items = getCurrentNavbarItems(); const app = $.apps.getLastApp().code; - const menu = getMenuName(items, app); + const menu = getMenuName(app); $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } } @@ -96,7 +96,7 @@ function generateAddNavbarItems(onClick) onClick(name); const items = getCurrentNavbarItems(); const app = $.apps.getLastApp().code; - const menu = getMenuName(items, app); + const menu = getMenuName(app); $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } } @@ -126,14 +126,11 @@ function canHideCurrentNavbar($item) /** * Get menu name by items and app. * - * @param {Array<{name: string; order: number;}>} items * @param {string} app * @returns {string} */ -function getMenuName(items, app) +function getMenuName(app) { - const isHomeMenu = items.length <= 3 && ['program', 'project', 'product', 'execution'].includes(app); - if(typeof projectModel !== 'undefined') { return `project-${projectModel}`; @@ -142,6 +139,10 @@ function getMenuName(items, app) { return `${app}-home`; } + else if(app == 'admin') + { + return `admin-${adminMenuKey}`; + } else { return app; @@ -167,7 +168,7 @@ $(document).on( onClick: () => { $item.closest('.nav').zui().destroy(); const items = getCurrentNavbarItems(); - const menu = getMenuName(items, app); + const menu = getMenuName(app); $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } } @@ -191,7 +192,7 @@ $(document).on( : () => { $li.remove(); const items = getCurrentNavbarItems(); - const menu = getMenuName(items, app); + const menu = getMenuName(app); $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); } }, @@ -211,7 +212,7 @@ $(document).on( $navItem.append($a); $li.after($navItem); const items = getCurrentNavbarItems(); - const menu = getMenuName(items, app); + const menu = getMenuName(app); $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); }), } diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 4105076302..45a9108e19 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -78,6 +78,7 @@ class navbar extends wg 'text' => $lang->more, 'trigger' => 'hover', 'id' => 'navbarMoreMenu', + 'data-id' => 'more', 'menu' => array('style' => array('max-width' => '300px')) ); } @@ -128,11 +129,19 @@ class navbar extends wg if(!empty($items)) return $items; global $app, $lang, $config; - if($app->tab == 'admin') $app->control->loadModel('admin')->setMenu(); + if($app->tab == 'admin') + { + $app->control->loadModel('admin')->setMenu(); + $adminMenuKey = $app->control->loadModel('admin')->getMenuKey(); + jsVar('adminMenuKey', $adminMenuKey); + } + commonModel::replaceMenuLang(); - commonModel::setMainMenu(); + $isHomeMenu = commonModel::setMainMenu(); commonModel::checkMenuVarsReplaced(); + jsVar('isHomeMenu', $isHomeMenu); + $isTutorialMode = commonModel::isTutorialMode(); $currentModule = $app->rawModule; $currentMethod = $app->rawMethod; @@ -141,7 +150,7 @@ class navbar extends wg if($isTutorialMode and defined('WIZARD_METHOD')) $currentMethod = WIZARD_METHOD; $tab = $app->tab; - $menu = \customModel::getMainMenu(); + $menu = \customModel::getMainMenu($isHomeMenu); $activeMenu = ''; $activeMenuID = data('activeMenuID'); $items = array(); @@ -194,7 +203,6 @@ class navbar extends wg $executionMoreItem = $this->getExecutionMoreItem($executionID); if(!empty($executionMoreItem)) { - $items[] = array('type' => 'divider'); $items[] = $executionMoreItem; } } diff --git a/module/admin/model.php b/module/admin/model.php index d3b1e06ed5..97075b249d 100755 --- a/module/admin/model.php +++ b/module/admin/model.php @@ -111,6 +111,9 @@ class adminModel extends model $menuKey = $this->getMenuKey(); if(empty($menuKey)) return; + $customKey = "admin-$menuKey"; + $customMenu = isset($this->config->customMenu->{$customKey}) ? json_decode($this->config->customMenu->{$customKey}) : array(); + $this->setSwitcher($menuKey); if(isset($this->lang->admin->menuList->$menuKey)) { @@ -146,6 +149,22 @@ class adminModel extends model } } + if($customMenu) + { + $this->lang->admin->menuList->{$menuKey}['menuOrder'] = array(); + $this->lang->admin->menuList->{$menuKey}['dividerMenu'] = ''; + $prev = ''; + foreach($customMenu as $item) + { + $this->lang->admin->menuList->{$menuKey}['menuOrder'][$item->order] = $item->name; + if($prev == 'divider') $this->lang->admin->menuList->{$menuKey}['dividerMenu'] .= ',' . $item->name; + $prev = $item->name; + } + + if($this->lang->admin->menuList->{$menuKey}['dividerMenu']) $this->lang->admin->menuList->{$menuKey}['dividerMenu'] = ',' . trim($this->lang->admin->menuList->{$menuKey}['dividerMenu']) . ','; + ksort($this->lang->admin->menuList->{$menuKey}['menuOrder']); + } + if(isset($this->lang->admin->menuList->{$menuKey}['menuOrder'])) $this->lang->admin->menuOrder = $this->lang->admin->menuList->{$menuKey}['menuOrder']; if(isset($this->lang->admin->menuList->{$menuKey}['dividerMenu'])) $this->lang->admin->dividerMenu = $this->lang->admin->menuList->{$menuKey}['dividerMenu']; if(isset($this->lang->admin->menuList->{$menuKey}['tabMenu'])) $this->lang->admin->tabMenu = $this->lang->admin->menuList->{$menuKey}['tabMenu']; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index b3341ea340..f6c0f4e403 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -401,6 +401,7 @@ $lang->execution->menuOrder[55] = 'build'; $lang->execution->menuOrder[60] = 'release'; $lang->execution->menuOrder[65] = 'action'; $lang->execution->menuOrder[70] = 'settings'; +$lang->execution->menuOrder[75] = 'more'; $lang->execution->menu->view['subMenu'] = new stdclass(); $lang->execution->menu->view['subMenu']->groupTask = "$lang->groupView|execution|grouptask|executionID=%s"; @@ -437,7 +438,7 @@ $lang->execution->menu->settings['subMenu']->products = array('link' => "$lang- $lang->execution->menu->settings['subMenu']->team = array('link' => "{$lang->team->common}|execution|team|executionID=%s", 'alias' => 'managemembers'); $lang->execution->menu->settings['subMenu']->whitelist = array('link' => "$lang->whitelist|execution|whitelist|executionID=%s", 'subModule' => 'personnel', 'alias' => 'addwhitelist'); -$lang->execution->dividerMenu = ',story,build,'; +$lang->execution->dividerMenu = ',story,build,more,'; $lang->project->noMultiple = new stdclass(); $lang->project->noMultiple->scrum = new stdclass(); diff --git a/module/common/model.php b/module/common/model.php index f1a1bcebf0..c54d404478 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -2056,9 +2056,9 @@ eof; * * @static * @access public - * @return void + * @return bool */ - public static function setMainMenu() + public static function setMainMenu(): bool { global $app, $lang; $tab = $app->tab; @@ -2072,12 +2072,12 @@ eof; $lang->menu = isset($lang->$tab->menu) ? $lang->$tab->menu : array(); $lang->menuOrder = isset($lang->$tab->menuOrder) ? $lang->$tab->menuOrder : array(); - if(!isset($lang->$tab->homeMenu)) return; + if(!isset($lang->$tab->homeMenu)) return false; if($currentModule == $tab and $currentMethod == 'create') { $lang->menu = $lang->$tab->homeMenu; - return; + return true; } /* If the method is in homeMenu, display homeMenu. */ @@ -2090,7 +2090,7 @@ eof; if($method == $currentMethod) { $lang->menu = $lang->$tab->homeMenu; - return; + return true; } $alias = isset($menu['alias']) ? explode(',', strtolower($menu['alias'])) : array(); @@ -2098,15 +2098,17 @@ eof; if(in_array($currentMethod, $alias) && !in_array("{$currentModule}-{$currentMethod}", $exclude)) { $lang->menu = $lang->$tab->homeMenu; - return; + return true; } if(isset($menu['subModule']) and strpos(",{$menu['subModule']},", ",$currentModule,") !== false) { $lang->menu = $lang->$tab->homeMenu; - return; + return true; } } + + return false; } /** diff --git a/module/custom/model.php b/module/custom/model.php index 9e36bfa8ee..3500cdace0 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -1,5 +1,4 @@ -branch)) $allMenu->branch = str_replace('@branch@', $lang->custom->branch, $allMenu->branch); /* 获取自定义过的导航。 */ - $isHomeMenu = in_array($app->tab, array('program', 'product', 'project', 'execution')) && count((array)$allMenu) <= 3 && $module == 'main'; $customKey = $isHomeMenu ? $app->tab . '-home' : ($module == 'main' ? $app->tab : $app->tab . '-' . $module); $customMenu = isset($config->customMenu->{$customKey}) ? $config->customMenu->{$customKey}: array(); @@ -457,12 +456,13 @@ class customModel extends model * 获取主菜单数据。 * Get main menu data. * + * @param bool $isHomeMenu * @access public * @return array */ - public static function getMainMenu(): array + public static function getMainMenu($isHomeMenu = false): array { - return static::getModuleMenu('main'); + return static::getModuleMenu('main', $isHomeMenu); } /** From 89218f0328dd6e47049991c81895c48869e3f77b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 27 Aug 2024 03:18:05 +0000 Subject: [PATCH 34/47] * [misc] Add comment. --- module/custom/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/custom/control.php b/module/custom/control.php index 65a593aa90..662be11bc1 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -563,7 +563,7 @@ class custom extends control { if($_POST) { - $menu = $this->post->menu; // 导航类型,nav(左侧主导航)|main(顶部一级导航)|module(顶部二级导航) + $menu = $this->post->menu; // 导航类型,nav(左侧主导航)|$app(顶部一级导航)|$app-home(项目集、项目的首页导航)|$app-$subMenu(顶部二级导航)|admin-$menuKey(后台导航) $items = $this->post->items; // 导航项 $account = $this->app->user->account; From 3844cd9f68f801efe8592b1fb3edb3451049b298 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 14:35:25 +0800 Subject: [PATCH 35/47] * [task#126662,1h] refactor. --- module/index/js/index.ui.js | 48 ++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 9de7c7587b..4cde72e56e 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -840,6 +840,16 @@ function getMenuNavData() return data; } +/** + * Save menu nav to server. + */ +function saveMenuNavToServer() +{ + const customUrl = $.createLink('custom', 'ajaxSetMenu'); + const data = getMenuNavData(); + $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); +} + /** * Generate menu nav items to be added. * @@ -848,19 +858,18 @@ function getMenuNavData() */ function generateAddMenuNavItems(onClick) { - const customUrl = $.createLink('custom', 'ajaxSetMenu'); - const data = getMenuNavData(); const items = [ { icon: 'icon-minus', text: langData.divider, onClick: () => { onClick('divider'); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + saveMenuNavToServer(); } } ]; + const data = getMenuNavData(); const allAppCodeSet = new Set(allAppsItemsMap.keys()); for(const {name} of data) { @@ -878,8 +887,7 @@ function generateAddMenuNavItems(onClick) text: title, onClick: () => { onClick(name); - const data = getMenuNavData(); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + saveMenuNavToServer(); } } ); @@ -893,7 +901,6 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) const $nav = $divider.closest('.nav'); const isMoving = $nav.is('[z-use-sortable]'); const items = []; - const customUrl = $.createLink('custom', 'ajaxSetMenu'); if(isMoving) { items.push( @@ -901,8 +908,7 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) text: langData.save, onClick: () => { $divider.closest('.nav').zui().destroy(); - const data = getMenuNavData(); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + saveMenuNavToServer(); } } ); @@ -930,9 +936,8 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) onClick: () => { const $li = $divider.closest('li'); $li.remove(); - const data = getMenuNavData(); refreshMenu(); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + saveMenuNavToServer(); } } ); @@ -943,7 +948,6 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) } ); - zui.ContextMenu.show( { hideOthers: true, @@ -982,7 +986,6 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) if(code !== 'my') items.push({text: langData.close, onClick: () => closeApp(code)}); } - const customUrl = $.createLink('custom', 'ajaxSetMenu'); if($btn.closest('#menuNav').length !== 0) { const $nav = $btn.closest('.nav'); @@ -994,8 +997,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) text: langData.save, onClick: () => { $btn.closest('.nav').zui().destroy(); - const data = getMenuNavData(); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + saveMenuNavToServer(); } } ); @@ -1028,9 +1030,8 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) closeApp(code); const $li = $btn.closest('li'); $li.remove(); - const data = getMenuNavData(); refreshMenu(); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + saveMenuNavToServer(); }, disabled: hideDisabled, } @@ -1275,15 +1276,18 @@ $(document).on('click', e => } }); -let allAppsItemsMap = new Map(); -void function generateAllAppsItemsMap() { - for(const item of allAppsItems) +const allAppsItemsMap = new Map(); +$(document).ready( + function() { - if(item === 'divider') continue; + for(const item of allAppsItems) + { + if(item === 'divider') continue; - allAppsItemsMap.set(item.code, item); + allAppsItemsMap.set(item.code, item); + } } -}(); +); /** * Get icon and title of app item. From 5e329abc8b64dce6f999d496a88fa53dda44efbc Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 14:39:19 +0800 Subject: [PATCH 36/47] * [task#126976,start,0.8h] add restore action. --- module/index/js/index.ui.js | 19 ++++++++++++++++++- module/index/lang/de.php | 1 + module/index/lang/en.php | 1 + module/index/lang/fr.php | 1 + module/index/lang/zh-cn.php | 1 + module/index/lang/zh-tw.php | 1 + 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 4cde72e56e..4f5ab1e919 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -947,6 +947,15 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) items: generateAddMenuNavItems(addMenuToMainNavCb($divider)) } ); + items.push( + { + text: langData.restore, + onClick: () => { + initAppsMenu(allAppsItems); + saveMenuNavToServer(); + } + } + ); zui.ContextMenu.show( { @@ -1036,13 +1045,21 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) disabled: hideDisabled, } ); - items.push( { text: langData.add, items: generateAddMenuNavItems(addMenuToMainNavCb($btn.closest('li'))) } ); + items.push( + { + text: langData.restore, + onClick: () => { + initAppsMenu(allAppsItems); + saveMenuNavToServer(); + } + } + ); } zui.ContextMenu.show( diff --git a/module/index/lang/de.php b/module/index/lang/de.php index 1f0ebe69bf..cf17cb20ee 100644 --- a/module/index/lang/de.php +++ b/module/index/lang/de.php @@ -14,6 +14,7 @@ $lang->index->dock->save = 'Exit sort'; $lang->index->dock->hide = 'Hide'; $lang->index->dock->add = 'Add'; $lang->index->dock->divider = 'Divider'; +$lang->index->dock->restore = 'Restore defaults'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/en.php b/module/index/lang/en.php index 799dae9f6b..8e08d366ca 100644 --- a/module/index/lang/en.php +++ b/module/index/lang/en.php @@ -14,6 +14,7 @@ $lang->index->dock->save = 'Exit sort'; $lang->index->dock->hide = 'Hide'; $lang->index->dock->add = 'Add'; $lang->index->dock->divider = 'Divider'; +$lang->index->dock->restore = 'Restore defaults'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/fr.php b/module/index/lang/fr.php index 1f0ebe69bf..cf17cb20ee 100644 --- a/module/index/lang/fr.php +++ b/module/index/lang/fr.php @@ -14,6 +14,7 @@ $lang->index->dock->save = 'Exit sort'; $lang->index->dock->hide = 'Hide'; $lang->index->dock->add = 'Add'; $lang->index->dock->divider = 'Divider'; +$lang->index->dock->restore = 'Restore defaults'; $lang->index->upgradeVersion = 'Upgradable version'; $lang->index->upgradeNow = 'Upgrade now'; diff --git a/module/index/lang/zh-cn.php b/module/index/lang/zh-cn.php index 2ff00b66c1..4477d04327 100644 --- a/module/index/lang/zh-cn.php +++ b/module/index/lang/zh-cn.php @@ -14,6 +14,7 @@ $lang->index->dock->save = '退出排序'; $lang->index->dock->hide = '隐藏'; $lang->index->dock->add = '添加'; $lang->index->dock->divider = '分割线'; +$lang->index->dock->restore = '恢复默认'; $lang->index->upgradeVersion = '可升级版本'; $lang->index->upgradeNow = '现在升级'; diff --git a/module/index/lang/zh-tw.php b/module/index/lang/zh-tw.php index 7d9e78ae4c..9d20ab9547 100644 --- a/module/index/lang/zh-tw.php +++ b/module/index/lang/zh-tw.php @@ -14,6 +14,7 @@ $lang->index->dock->save = '退出排序'; $lang->index->dock->hide = '隱藏'; $lang->index->dock->add = '添加'; $lang->index->dock->divider = '分割線'; +$lang->index->dock->restore = '恢復預設'; $lang->index->upgradeVersion = '可升級版本'; $lang->index->upgradeNow = '現在升級'; From 36c0cb023aa3f7acec603e45b53412da2f20ec71 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 15:24:09 +0800 Subject: [PATCH 37/47] * [task#126489,0.3h] add onEnd callback for sortable. --- lib/zin/wg/mainnavbar/js/v1.js | 3 +++ lib/zin/wg/navbar/js/v1.js | 3 +++ module/index/js/index.ui.js | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 6484fb8b53..bd9d7e30a7 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -141,6 +141,9 @@ $(document).on( { animation: 150, ghostClass: 'bg-primary-pale', + onEnd(e) { + console.log('End of drag', e); + } } ); } diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index f3bae57eed..89d8e29829 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -180,6 +180,9 @@ $(document).on( { animation: 150, ghostClass: 'bg-primary-pale', + onEnd(e) { + console.log('End of drag', e); + }, } ); } diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 4f5ab1e919..22f1392f45 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -924,6 +924,9 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) { animation: 150, ghostClass: 'bg-primary-pale', + onEnd(e) { + console.log('End of drag', e); + }, } ); } @@ -1022,6 +1025,9 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) { animation: 150, ghostClass: 'bg-primary-pale', + onEnd(e) { + console.log('End of drag', e); + }, } ); } From c12d0ed1d8e82f6ae1aced66660b04227573824f Mon Sep 17 00:00:00 2001 From: sunguangming Date: Tue, 27 Aug 2024 08:28:06 +0000 Subject: [PATCH 38/47] * [customMenu] fix bugs. --- lib/zin/wg/mainnavbar/js/v1.js | 25 +++++++++++++-------- lib/zin/wg/mainnavbar/v1.php | 5 ++++- lib/zin/wg/navbar/js/v1.js | 40 +++++++++++++++------------------- lib/zin/wg/navbar/v1.php | 8 ++++--- module/custom/control.php | 20 ++++++++++++++++- module/custom/model.php | 3 +-- module/index/js/index.ui.js | 12 +++++----- 7 files changed, 68 insertions(+), 45 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index bd9d7e30a7..8897d0e15e 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -73,7 +73,10 @@ function generateAddMainNavbarItems(onClick) items.push( { text: item.text, - onClick: () => onClick(name), + onClick: () => { + onClick(name), + saveMenu($('#mainNavbar .nav-item > a').first()); + } } ); } @@ -106,8 +109,6 @@ $(document).on( const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); - const menu = $item.data('group'); - const customUrl = $.createLink('custom', 'ajaxSetMenu'); const itemsToAdded = generateAddMainNavbarItems((name) => { const item = allMainNavbarItemMap.get(name); const $a = $('') @@ -129,8 +130,7 @@ $(document).on( text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); - const items = getCurrentMainNavbarItems(); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu($item); } } : { @@ -141,8 +141,8 @@ $(document).on( { animation: 150, ghostClass: 'bg-primary-pale', - onEnd(e) { - console.log('End of drag', e); + onSort: () => { + saveMenu($item); } } ); @@ -155,8 +155,7 @@ $(document).on( ? null : () => { $li.remove(); - const items = getCurrentMainNavbarItems(); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu($item); } }, itemsToAdded.length === 0 @@ -183,3 +182,11 @@ $(document).on( event.preventDefault(); } ); + +function saveMenu($item) +{ + const items = getCurrentMainNavbarItems(); + const menu = $item.data('group'); + const customUrl = $.createLink('custom', 'ajaxSetMenu'); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); +} diff --git a/lib/zin/wg/mainnavbar/v1.php b/lib/zin/wg/mainnavbar/v1.php index 2c6dd52bc8..805d006c24 100644 --- a/lib/zin/wg/mainnavbar/v1.php +++ b/lib/zin/wg/mainnavbar/v1.php @@ -114,6 +114,7 @@ class mainNavbar extends nav $name = $menuItem['name']; $item['text'] = $menuItem['text']; $item['url'] = commonModel::createMenuLink((object)$menuItem, $app->tab); + $item['hidden'] = !empty($menuItem['hidden']); $item['data-id'] = $name; $item['data-app'] = $app->tab; $item['data-group'] = $app->tab . '-' . $activeMenu; @@ -140,6 +141,9 @@ class mainNavbar extends nav $items[] = $item; } + jsVar('allMainNavbarItems', $items); + $items = array_filter($items, function($item) { return empty($item['hidden']); }); + $this->setProp('items', $items); } } @@ -162,7 +166,6 @@ class mainNavbar extends nav $leftBlock = $this->block('left'); $rightBlock = $this->block('right'); if(empty($leftBlock)) $leftBlock = $this->buildSwitcher(); - jsVar('allMainNavbarItems', $this->prop('items')); return div ( diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 89d8e29829..2b964c5dc3 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -63,16 +63,12 @@ function getCurrentNavbarItems() */ function generateAddNavbarItems(onClick) { - const customUrl = $.createLink('custom', 'ajaxSetMenu'); const items = [ { text: langData.divider, onClick: () => { onClick('divider'); - const items = getCurrentNavbarItems(); - const app = $.apps.getLastApp().code; - const menu = getMenuName(app); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu(); } } ]; @@ -94,10 +90,7 @@ function generateAddNavbarItems(onClick) text: item.text, onClick: () => { onClick(name); - const items = getCurrentNavbarItems(); - const app = $.apps.getLastApp().code; - const menu = getMenuName(app); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu(); } } ); @@ -159,17 +152,13 @@ $(document).on( const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); - const app = $.apps.getLastApp().code; - const customUrl = $.createLink('custom', 'ajaxSetMenu'); const items = [ isMoving ? { text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); - const items = getCurrentNavbarItems(); - const menu = getMenuName(app); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu(); } } : { @@ -180,9 +169,9 @@ $(document).on( { animation: 150, ghostClass: 'bg-primary-pale', - onEnd(e) { - console.log('End of drag', e); - }, + onSort: () => { + saveMenu(); + } } ); } @@ -194,9 +183,7 @@ $(document).on( ? null : () => { $li.remove(); - const items = getCurrentNavbarItems(); - const menu = getMenuName(app); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu(); } }, { @@ -214,9 +201,7 @@ $(document).on( const $navItem = $(''); $navItem.append($a); $li.after($navItem); - const items = getCurrentNavbarItems(); - const menu = getMenuName(app); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + saveMenu(); }), } ]; @@ -233,3 +218,12 @@ $(document).on( event.preventDefault(); } ); + +function saveMenu() +{ + const customUrl = $.createLink('custom', 'ajaxSetMenu'); + const items = getCurrentNavbarItems(); + const app = $.apps.getLastApp().code; + const menu = getMenuName(app); + $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); +} diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 45a9108e19..40dfb56994 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -157,7 +157,6 @@ class navbar extends wg $flows = $config->edition != 'open' ? $app->control->loadModel('my')->getFlowPairs() : array(); foreach($menu as $menuItem) { - if(isset($menuItem->hidden) and $menuItem->hidden and (!isset($menuItem->tutorial) or !$menuItem->tutorial)) continue; if(isset($menuItem->class) && strpos($menuItem->class, 'automation-menu')) { if($menuItem->divider) $items[] = array('type' => 'divider'); @@ -306,7 +305,8 @@ class navbar extends wg 'active' => $isActive, 'target' => $target, 'data-id' => $menuItem->name, - 'data-app' => $dataApp + 'data-app' => $dataApp, + 'hidden' => (isset($menuItem->hidden) && $menuItem->hidden && (!isset($menuItem->tutorial) || !$menuItem->tutorial)) ); } } @@ -318,6 +318,9 @@ class navbar extends wg /* Set active menu to global data, make it accessible to other widgets */ data('activeMenu', $activeMenu); + jsVar('allNavbarItems', $items); + + $items = array_filter($items, function($item) { return empty($item['hidden']); }); return $items; } @@ -330,7 +333,6 @@ class navbar extends wg protected function build() { $items = $this->getItems(); - jsVar('allNavbarItems', $items); return h::nav ( set::id('navbar'), diff --git a/module/custom/control.php b/module/custom/control.php index 662be11bc1..5209e941a9 100644 --- a/module/custom/control.php +++ b/module/custom/control.php @@ -555,7 +555,7 @@ class custom extends control /** * Ajax set menu - *- + * * @access public * @return void */ @@ -572,4 +572,22 @@ class custom extends control $this->send(array('result' => 'success')); } + + /** + * Ajax restore menu + * + * @access public + * @return void + */ + public function ajaxRestoreMenu() + { + if($_POST) + { + $account = $this->app->user->account; + $menu = $this->post->menu; + $this->loadModel('setting')->deleteItems("owner={$account}&module=common§ion=customMenu&key=$menu"); + } + + $this->send(array('result' => 'success')); + } } diff --git a/module/custom/model.php b/module/custom/model.php index 3500cdace0..856d818889 100644 --- a/module/custom/model.php +++ b/module/custom/model.php @@ -304,8 +304,6 @@ class customModel extends model $module = $menuModuleName; foreach($allMenu as $name => $item) { - if(!empty($customMenuMap) && !isset($customMenuMap[$name])) continue; // 自定义过滤掉的菜单不显示。 - $name = (string)$name; if(is_object($item)) $item = (array)$item; @@ -366,6 +364,7 @@ class customModel extends model /* Process menu item's order and hidden attirbute. */ $menuItem = static::buildMenuItem($item, $customMenuMap, $name, $label, $itemLink, $isTutorialMode, $subMenu); $menuItem->order = (isset($customMenuMap[$name]) && isset($customMenuMap[$name]->order) ? $customMenuMap[$name]->order : $order ++); + if(!empty($customMenuMap) && !isset($customMenuMap[$name])) $menuItem->hidden = true; // 自定义过滤掉的菜单不显示。 if(isset($customMenuMap[$name]) && isset($customMenuMap[$name]->divider)) $menuItem->divider = true; if($app->viewType == 'mhtml' && isset($config->custom->moblieHidden[$menuModuleName]) && in_array($name, $config->custom->moblieHidden[$menuModuleName])) $menuItem->hidden = 1; // Hidden menu by config in mobile. while(isset($menu[$menuItem->order])) $menuItem->order ++; diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 22f1392f45..e48dfb8d41 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -924,9 +924,9 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) { animation: 150, ghostClass: 'bg-primary-pale', - onEnd(e) { - console.log('End of drag', e); - }, + onSort: () => { + saveMenuNavToServer(); + } } ); } @@ -1025,9 +1025,9 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) { animation: 150, ghostClass: 'bg-primary-pale', - onEnd(e) { - console.log('End of drag', e); - }, + onSort: () => { + saveMenuNavToServer(); + } } ); } From 99b2e364c77f7d40f8606f92062e87d53aaed0a4 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 16:41:58 +0800 Subject: [PATCH 39/47] * [task#126976,0.3h] refactor restore action. --- module/index/js/index.ui.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index e48dfb8d41..5a3de12bf8 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -845,9 +845,18 @@ function getMenuNavData() */ function saveMenuNavToServer() { - const customUrl = $.createLink('custom', 'ajaxSetMenu'); + const url = $.createLink('custom', 'ajaxSetMenu'); const data = getMenuNavData(); - $.ajaxSubmit({url: customUrl, data: {menu: 'nav', items: JSON.stringify(data)}}); + $.ajaxSubmit({url, data: {menu: 'nav', items: JSON.stringify(data)}}); +} + +/** + * Restore menu nav to server. + */ +function restoreMenuNavToServer() +{ + const url = $.createLink('custom', 'ajaxRestoreMenu'); + $.ajaxSubmit({url, data: {menu: 'nav'}}); } /** @@ -955,7 +964,7 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) text: langData.restore, onClick: () => { initAppsMenu(allAppsItems); - saveMenuNavToServer(); + restoreMenuNavToServer(); } } ); @@ -1062,7 +1071,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) text: langData.restore, onClick: () => { initAppsMenu(allAppsItems); - saveMenuNavToServer(); + restoreMenuNavToServer(); } } ); From d09643813d53b1b39e3236550a4f759a3393dcf0 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 17:06:45 +0800 Subject: [PATCH 40/47] * [task#126977,start,0.5h] add restore action. --- lib/zin/wg/navbar/js/v1.js | 53 +++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index 2b964c5dc3..b92f15caef 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -68,7 +68,7 @@ function generateAddNavbarItems(onClick) text: langData.divider, onClick: () => { onClick('divider'); - saveMenu(); + saveNavbarToServer(); } } ]; @@ -90,7 +90,7 @@ function generateAddNavbarItems(onClick) text: item.text, onClick: () => { onClick(name); - saveMenu(); + saveNavbarToServer(); } } ); @@ -128,18 +128,17 @@ function getMenuName(app) { return `project-${projectModel}`; } - else if(isHomeMenu) + + if(isHomeMenu) { return `${app}-home`; } - else if(app == 'admin') + + if(app == 'admin') { return `admin-${adminMenuKey}`; } - else - { - return app; - } + return app; } $(document).on( @@ -158,7 +157,7 @@ $(document).on( text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); - saveMenu(); + saveNavbarToServer(); } } : { @@ -170,7 +169,7 @@ $(document).on( animation: 150, ghostClass: 'bg-primary-pale', onSort: () => { - saveMenu(); + saveNavbarToServer(); } } ); @@ -183,7 +182,7 @@ $(document).on( ? null : () => { $li.remove(); - saveMenu(); + saveNavbarToServer(); } }, { @@ -201,8 +200,18 @@ $(document).on( const $navItem = $(''); $navItem.append($a); $li.after($navItem); - saveMenu(); + saveNavbarToServer(); }), + }, + { + text: langData.restore, + onClick: () => { + restoreNavbarToServer({ + onSuccess() { + loadCurrentPage('#navbar'); + } + }); + } } ]; zui.ContextMenu.show( @@ -219,11 +228,25 @@ $(document).on( } ); -function saveMenu() +/** + * Save navbar to server. + */ +function saveNavbarToServer() { - const customUrl = $.createLink('custom', 'ajaxSetMenu'); + const url = $.createLink('custom', 'ajaxSetMenu'); const items = getCurrentNavbarItems(); const app = $.apps.getLastApp().code; const menu = getMenuName(app); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + $.ajaxSubmit({url, data: {menu, items: JSON.stringify(items)}}); +} + +/** + * Restore navbar to server. + */ +function restoreNavbarToServer(options = {}) +{ + const url = $.createLink('custom', 'ajaxRestoreMenu'); + const app = $.apps.getLastApp().code; + const menu = getMenuName(app); + $.ajaxSubmit({url, data: {menu}, ...options}); } From 6fe6274aa213a4f4ebe21401a781a2ad23e687ad Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Tue, 27 Aug 2024 17:28:00 +0800 Subject: [PATCH 41/47] * [task#126978,start,0.5h] add restore action. --- lib/zin/wg/mainnavbar/js/v1.js | 37 +++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/zin/wg/mainnavbar/js/v1.js b/lib/zin/wg/mainnavbar/js/v1.js index 8897d0e15e..81d5340200 100644 --- a/lib/zin/wg/mainnavbar/js/v1.js +++ b/lib/zin/wg/mainnavbar/js/v1.js @@ -53,10 +53,11 @@ function getCurrentMainNavbarItems() /** * Generate main menu nav items to be added. * + * @param {Cash} $item * @param {(name: string) => void} onClick * @returns {Array<{text: string; onClick: () => void;}>} */ -function generateAddMainNavbarItems(onClick) +function generateAddMainNavbarItems($item, onClick) { const items = []; const allMainNavbarItemIDSet = new Set(allMainNavbarItemMap.keys()); @@ -75,7 +76,7 @@ function generateAddMainNavbarItems(onClick) text: item.text, onClick: () => { onClick(name), - saveMenu($('#mainNavbar .nav-item > a').first()); + saveMainNavbarToServer($item); } } ); @@ -109,7 +110,7 @@ $(document).on( const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); - const itemsToAdded = generateAddMainNavbarItems((name) => { + const itemsToAdded = generateAddMainNavbarItems($item, (name) => { const item = allMainNavbarItemMap.get(name); const $a = $('') .attr('href', item.url) @@ -130,7 +131,7 @@ $(document).on( text: langData.save, onClick: () => { $item.closest('.nav').zui().destroy(); - saveMenu($item); + saveMainNavbarToServer($item); } } : { @@ -142,7 +143,7 @@ $(document).on( animation: 150, ghostClass: 'bg-primary-pale', onSort: () => { - saveMenu($item); + saveMainNavbarToServer($item); } } ); @@ -155,7 +156,7 @@ $(document).on( ? null : () => { $li.remove(); - saveMenu($item); + saveMainNavbarToServer($item); } }, itemsToAdded.length === 0 @@ -166,7 +167,18 @@ $(document).on( : { text: langData.add, items: itemsToAdded, + }, + { + text: langData.restore, + onClick: () => { + restoreMainNavbarToServer($item, { + onSuccess() { + loadCurrentPage('#mainNavbar'); + } + }); } + } + ]; zui.ContextMenu.show( @@ -183,10 +195,17 @@ $(document).on( } ); -function saveMenu($item) +function saveMainNavbarToServer($item) { const items = getCurrentMainNavbarItems(); const menu = $item.data('group'); - const customUrl = $.createLink('custom', 'ajaxSetMenu'); - $.ajaxSubmit({url: customUrl, data: {menu: menu, items: JSON.stringify(items)}}); + const url = $.createLink('custom', 'ajaxSetMenu'); + $.ajaxSubmit({url, data: {menu, items: JSON.stringify(items)}}); } + +function restoreMainNavbarToServer($item, options = {}) +{ + const url = $.createLink('custom', 'ajaxRestoreMenu'); + const menu = $item.data('group'); + $.ajaxSubmit({url, data: {menu}, ...options}); +} \ No newline at end of file From 283e439be354aeb1afc891b4f9be42b1f99919cd Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 28 Aug 2024 10:22:14 +0800 Subject: [PATCH 42/47] * [bug#54551,0.3h] fix divider padding. --- module/index/css/index.ui.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/index/css/index.ui.css b/module/index/css/index.ui.css index b47ce58d64..b4b0fdb637 100644 --- a/module/index/css/index.ui.css +++ b/module/index/css/index.ui.css @@ -35,7 +35,7 @@ .hide-menu #menu {width: var(--zt-menu-fold-width)!important;} .hide-menu #menu .nav > li {padding: 4px} -.hide-menu #menu .nav > .divider {padding: 0; margin: 6px} +.hide-menu #menu .nav > .divider {padding: 6px;} .hide-menu #menu .nav > li > a {justify-content: center;} .hide-menu #menu .nav > li > a > .text {display: none;} .hide-menu #menu #menuMoreNav .nav > li > a > .text {display: flex;} From 62261a1fccc37565f734e454875287cd0ef12cef Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 28 Aug 2024 11:07:51 +0800 Subject: [PATCH 43/47] * [bug#54545,1h] fix add divider after divider. --- module/index/js/index.ui.js | 73 +++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 5a3de12bf8..c8d2fc02ba 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -862,21 +862,24 @@ function restoreMenuNavToServer() /** * Generate menu nav items to be added. * + * @param {Cash} $item * @param {(item: string) => void} onClick click handler of menu item. * @returns {Array<{icon: string; text: string; onClick: () => void;}>} */ -function generateAddMenuNavItems(onClick) +function generateAddMenuNavItems($item, onClick) { - const items = [ - { - icon: 'icon-minus', - text: langData.divider, - onClick: () => { - onClick('divider'); - saveMenuNavToServer(); + const items = canAddDivider($item) + ? [ + { + icon: 'icon-minus', + text: langData.divider, + onClick: () => { + onClick('divider'); + saveMenuNavToServer(); + } } - } - ]; + ] + : []; const data = getMenuNavData(); const allAppCodeSet = new Set(allAppsItemsMap.keys()); @@ -953,17 +956,24 @@ $(document).on('contextmenu', '#menuNav .divider', function(event) } } ); + const toAddedItems = generateAddMenuNavItems($divider, addMenuToMainNavCb($divider)); items.push( - { - text: langData.add, - items: generateAddMenuNavItems(addMenuToMainNavCb($divider)) - } + toAddedItems.length === 0 + ? { + text: langData.add, + disabled: true, + } + : { + text: langData.add, + items: toAddedItems, + } ); items.push( { text: langData.restore, onClick: () => { initAppsMenu(allAppsItems); + refreshMenu(); restoreMenuNavToServer(); } } @@ -1060,17 +1070,24 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) disabled: hideDisabled, } ); + const toAddedItems = generateAddMenuNavItems($btn, addMenuToMainNavCb($btn.closest('li'))); items.push( - { - text: langData.add, - items: generateAddMenuNavItems(addMenuToMainNavCb($btn.closest('li'))) - } + toAddedItems.length === 0 + ? { + text: langData.add, + disabled: true, + } + : { + text: langData.add, + items: toAddedItems, + } ); items.push( { text: langData.restore, onClick: () => { initAppsMenu(allAppsItems); + refreshMenu(); restoreMenuNavToServer(); } } @@ -1352,7 +1369,12 @@ function getAppItemIconAndTitle(name) */ function addMenuToMainNavCb($li) { return (name) => { - if(name === 'divider') return $li.after('
  • '); + if(name === 'divider') + { + $li.after('
  • '); + refreshMenu(); + return + } let item = allAppsItemsMap.get(name); const oldItem = apps.map[item.code]; @@ -1381,3 +1403,16 @@ function addMenuToMainNavCb($li) { if(!apps.defaultCode) apps.defaultCode = item.code; }; } + +/** + * Check whether current element can add a divider. + * @param {Cash} $item + * @returns {boolean} + */ +function canAddDivider($item) +{ + $item = $item.closest('li'); + if($item.is('.divider')) return false; + if($item.next().is('.divider')) return false; + return true; +} \ No newline at end of file From cb779c1d473efa9b34249af6d912fc74062db3fd Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 28 Aug 2024 11:28:21 +0800 Subject: [PATCH 44/47] * [task#126663,0.5h] fix add divider after divider. --- lib/zin/wg/navbar/js/v1.js | 67 ++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/lib/zin/wg/navbar/js/v1.js b/lib/zin/wg/navbar/js/v1.js index b92f15caef..60d00dac1d 100644 --- a/lib/zin/wg/navbar/js/v1.js +++ b/lib/zin/wg/navbar/js/v1.js @@ -57,21 +57,21 @@ function getCurrentNavbarItems() /** * Generate navbar items to be added. - * + * @param {Cash} $item * @param {(item: string) => void} onClick click handler of navbar item. * @returns {Array<{text: string; onClick: () => void;}>} */ -function generateAddNavbarItems(onClick) +function generateAddNavbarItems($item, onClick) { - const items = [ - { + const items = canAddDivider($item) + ? [{ text: langData.divider, onClick: () => { onClick('divider'); saveNavbarToServer(); } - } - ]; + }] + : []; const allNavbarItemIDSet = new Set(allNavbarItemMap.keys()); const curNavbarItems = getCurrentNavbarItems(); @@ -151,6 +151,21 @@ $(document).on( const isMoving = $nav.is('[z-use-sortable]'); const hideDisabled = !canHideCurrentNavbar($item); const $li = $item.closest('li'); + const toAddedItems = generateAddNavbarItems($item, (name) => { + if(name === 'divider') return $li.after(''); + + const item = allNavbarItemMap.get(name); + const $a = $('') + .attr('href', item.url) + .attr('target', item.target) + .attr('data-id', item['data-id']) + .append(`${item.text}`); + if(item.class) $a.attr('class', item.class); + const $navItem = $(''); + $navItem.append($a); + $li.after($navItem); + saveNavbarToServer(); + }); const items = [ isMoving ? { @@ -185,24 +200,15 @@ $(document).on( saveNavbarToServer(); } }, - { - text: langData.add, - items: generateAddNavbarItems((name) => { - if(name === 'divider') return $li.after(''); - - const item = allNavbarItemMap.get(name); - const $a = $('') - .attr('href', item.url) - .attr('target', item.target) - .attr('data-id', item['data-id']) - .append(`${item.text}`); - if(item.class) $a.attr('class', item.class); - const $navItem = $(''); - $navItem.append($a); - $li.after($navItem); - saveNavbarToServer(); - }), - }, + toAddedItems.length === 0 + ? { + text: langData.add, + disabled: true, + } + : { + text: langData.add, + items: toAddedItems, + }, { text: langData.restore, onClick: () => { @@ -250,3 +256,16 @@ function restoreNavbarToServer(options = {}) const menu = getMenuName(app); $.ajaxSubmit({url, data: {menu}, ...options}); } + +/** + * Check whether current element can add a divider. + * @param {Cash} $item + * @returns {boolean} + */ +function canAddDivider($item) +{ + $item = $item.closest('li'); + if($item.is('.divider')) return false; + if($item.next().is('.divider')) return false; + return true; +} \ No newline at end of file From bce51452fab6d22d90ae1f4cdddeb65c2f2d6b4d Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 28 Aug 2024 14:24:58 +0800 Subject: [PATCH 45/47] * [task#126662,0.2h] remove contextmenu of menuMoreNav. --- module/index/js/index.ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 7b538fc1ef..2b802f658a 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -907,7 +907,7 @@ function generateAddMenuNavItems($item, onClick) return items; } -$(document).on('contextmenu', '#menuNav .divider', function(event) +$(document).on('contextmenu', '#menuMainNav .divider', function(event) { const $divider = $(this); const $nav = $divider.closest('.nav'); @@ -1017,7 +1017,7 @@ $(document).on('click', '.open-in-app,.show-in-app', function(e) if(code !== 'my') items.push({text: langData.close, onClick: () => closeApp(code)}); } - if($btn.closest('#menuNav').length !== 0) + if($btn.closest('#menuMainNav').length !== 0) { const $nav = $btn.closest('.nav'); const isMoving = $nav.is('[z-use-sortable]'); From 070521b4a5f7c2e230fe09c5d007c680f3127195 Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Thu, 29 Aug 2024 13:45:33 +0800 Subject: [PATCH 46/47] * [bug#54533,0.1h] fix openedMenu. --- module/index/js/index.ui.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/index/js/index.ui.js b/module/index/js/index.ui.js index 2b802f658a..ce8e634bf6 100644 --- a/module/index/js/index.ui.js +++ b/module/index/js/index.ui.js @@ -979,7 +979,8 @@ $(document).on('contextmenu', '#menuMainNav .divider', function(event) } ); - zui.ContextMenu.show( + if(apps.openedMenu) apps.openedMenu.hide(); + apps.openedMenu = zui.ContextMenu.show( { hideOthers: true, element: $divider[0], From 8bf3dd8b3ed8aeb5baaf888fa261a2cba9817c88 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Mon, 2 Sep 2024 02:49:39 +0000 Subject: [PATCH 47/47] * [bug#54538,done,0.2h] fix bug. --- lib/zin/wg/navbar/v1.php | 3 ++- module/common/lang/menu.php | 2 +- module/common/model.php | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/zin/wg/navbar/v1.php b/lib/zin/wg/navbar/v1.php index 40dfb56994..87b2646e3d 100644 --- a/lib/zin/wg/navbar/v1.php +++ b/lib/zin/wg/navbar/v1.php @@ -172,7 +172,7 @@ class navbar extends wg } if(empty($menuItem->link)) continue; - if($menuItem->divider) $items[] = array('type' => 'divider'); + if($menuItem->divider && empty($menuItem->hidden)) $items[] = array('type' => 'divider'); /* Init the these vars. */ $subModule = isset($menuItem->subModule) ? explode(',', $menuItem->subModule) : array(); @@ -202,6 +202,7 @@ class navbar extends wg $executionMoreItem = $this->getExecutionMoreItem($executionID); if(!empty($executionMoreItem)) { + $items[] = array('type' => 'divider'); $items[] = $executionMoreItem; } } diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index f6c0f4e403..4547c422d7 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -438,7 +438,7 @@ $lang->execution->menu->settings['subMenu']->products = array('link' => "$lang- $lang->execution->menu->settings['subMenu']->team = array('link' => "{$lang->team->common}|execution|team|executionID=%s", 'alias' => 'managemembers'); $lang->execution->menu->settings['subMenu']->whitelist = array('link' => "$lang->whitelist|execution|whitelist|executionID=%s", 'subModule' => 'personnel', 'alias' => 'addwhitelist'); -$lang->execution->dividerMenu = ',story,build,more,'; +$lang->execution->dividerMenu = ',story,build,'; $lang->project->noMultiple = new stdclass(); $lang->project->noMultiple->scrum = new stdclass(); diff --git a/module/common/model.php b/module/common/model.php index 5aabfabbfb..fc3a658e19 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -730,8 +730,8 @@ class commonModel extends model $items[] = $item; } - /* Fix bug 14574. */ - if(end($items) == 'divider') array_pop($items); + // 如果最后一个是分割线,则删除 + while(!empty($items) && end($items) === 'divider') { array_pop($items); } return $items; }