From 6c20a15a0452d37a12bce64da712da6071e42bdd Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 6 Jun 2024 06:42:54 +0000 Subject: [PATCH 001/655] * [task#120060,done,3] Adjust style for close button. --- module/metric/css/preview.ui.css | 6 +++--- module/metric/js/preview.ui.js | 15 ++++++--------- module/metric/ui/previewmultiple.html.php | 8 ++++---- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/module/metric/css/preview.ui.css b/module/metric/css/preview.ui.css index 400fc73514..2b86ed74af 100644 --- a/module/metric/css/preview.ui.css +++ b/module/metric/css/preview.ui.css @@ -67,12 +67,12 @@ i.star {color: var(--color-warning-300);} .main .checked-content {position: sticky; top: 0px; transition: height 0.5s ease; height: 48px; padding-left: 8px; border-bottom: 1px solid var(--color-gray-300); background-color: #fff; z-index: 100;} .main .checked-label-content {height: 48px; padding-top: 3px; display: flex; flex-wrap: wrap;} .main .checked-label-right {height: 48px; padding-right: 12px; justify-content: flex-end; display: flex; align-items: center;} +.main .checked-label-content .picker-multi-selection{margin: 7px 4px; padding-top: 5px; padding-bottom: 4px; white-space: nowrap;} +.main .checked-label-content .picker-multi-selection > .text{line-height: 16px;} +.main .checked-label-content > span.label{margin: 12px 4px 11px; white-space: nowrap;} .main .checked-tip {padding-right: 6px; position: relative; color: var(--color-gray-600);} .main .checked-tip .checked-count {color: var(--color-gray-800);} .main .checked-tip:before {content: ""; position: absolute; top: 0px; left: -15px; bottom: 0px; width: 1px; background-color: var(--color-gray-300);} -.main .gray-pale {margin: 7px 4px; padding: 13px 12px; white-space: nowrap;} -.main .gray-pale-div {overflow: hidden;} -.main .gray-pale-withdelete {padding-right: 1px;} .visibility-hidden {visibility: hidden;} .gray-hidden {opacity: 0;} diff --git a/module/metric/js/preview.ui.js b/module/metric/js/preview.ui.js index 896f93bcf4..9a2e35ae07 100644 --- a/module/metric/js/preview.ui.js +++ b/module/metric/js/preview.ui.js @@ -330,7 +330,7 @@ window.renderEchart = function($obj, option) window.setDropDown = function() { - var $drop = $('.dropdown-icon'); + var $drop = $('.dropdown-icon'); $drop.toggleClass('rotate'); if($drop.hasClass('rotate')) { @@ -510,7 +510,7 @@ window.handleSidebarToggle = function(status) window.renderCheckedLabel = function() { - var $content = $('.checked-label-content'); + var $content = $('.picker-multi-selections'); if(!$content.length) return; $content.empty(); @@ -524,12 +524,9 @@ window.renderCheckedLabel = function() var nextLine = false; var lineCount = 1; - var labelClass = 'label circle gray-pale'; - if(multi) labelClass += ' gray-pale-withdelete'; - for(var i = 0; i < labels.length; i++) { - var classes = labelClass; + var classes = 'picker-multi-selection'; if(nextLine) classes += ' gray-next'; var label = labels[i]; @@ -547,12 +544,12 @@ window.renderCheckedLabel = function() var labelWidth = $label.width(); var labelLeft = parseInt($label.css('padding-left')) + parseInt($label.css('margin-left')); var labelRight = parseInt($label.css('padding-right')) + parseInt($label.css('margin-right')); - var labelWidth = Math.ceil(labelWidth + labelLeft + labelRight); + var labelWidth = Math.ceil(labelWidth + labelLeft + labelRight + 2); left = left - labelWidth; if(left <= 0) { - var $div = $label.find('.gray-pale-div'); + var $div = $label.find('.text'); var divWidth = $div.width(); if(divWidth < -left) @@ -583,7 +580,7 @@ window.renderCheckedLabel = function() if(!multi) { var maxSelectTipText = maxSelectTip.replace('%s', maxSelectNum); - $content.append(`${maxSelectTipText}`); + $content.append(`${maxSelectTipText}`); } else { diff --git a/module/metric/ui/previewmultiple.html.php b/module/metric/ui/previewmultiple.html.php index 325f77cf89..0d8280ed24 100644 --- a/module/metric/ui/previewmultiple.html.php +++ b/module/metric/ui/previewmultiple.html.php @@ -36,15 +36,15 @@ div ( setClass('{spanClass}'), set('metric-id', '{id}'), - div + span ( - setClass('gray-pale-div'), + setClass('text'), set('title', '{name}'), '{name}' ), button ( - setClass('picker-deselect-btn size-sm square ghost {multiple}'), + setClass('picker-deselect-btn btn size-xs ghost {multiple}'), set('onclick', 'window.handleRemoveLabel({id})'), span ( @@ -221,7 +221,7 @@ div set::align('center'), cell ( - setClass('checked-label-content'), + setClass('picker-multi-selections checked-label-content gap-0'), set::flex('auto') ), cell From df1df06a1bffee1dd4db67af8952a33920d1772b Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 6 Nov 2024 01:20:02 +0000 Subject: [PATCH 002/655] * [misc] Add doc template menu. --- module/common/lang/de.php | 1 + module/common/lang/en.php | 1 + module/common/lang/fr.php | 1 + module/common/lang/menu.php | 2 ++ module/common/lang/zh-cn.php | 1 + module/doc/control.php | 13 +++++++++++++ module/doc/ui/browsetemplate.html.php | 13 +++++++++++++ 7 files changed, 32 insertions(+) create mode 100644 module/doc/ui/browsetemplate.html.php diff --git a/module/common/lang/de.php b/module/common/lang/de.php index 05d7474394..8a862b57a8 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -398,6 +398,7 @@ $lang->doc->productSpace = "{$lang->productCommon} Space"; $lang->doc->projectSpace = "{$lang->projectCommon} Space"; $lang->doc->apiSpace = 'API Space'; $lang->doc->teamSpace = 'Team Space'; +$lang->doc->template = 'Document Template'; $lang->product->list = $lang->productCommon . ' List'; $lang->product->kanban = $lang->productCommon . ' Kanban'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 3517e836ab..09074dd6be 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -398,6 +398,7 @@ $lang->doc->productSpace = "{$lang->productCommon} Space"; $lang->doc->projectSpace = "{$lang->projectCommon} Space"; $lang->doc->apiSpace = 'API Space'; $lang->doc->teamSpace = 'Team Space'; +$lang->doc->template = 'Document Template'; $lang->product->list = $lang->productCommon . ' List'; $lang->product->kanban = $lang->productCommon . ' Kanban'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index 3394f2601b..613427f66f 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -398,6 +398,7 @@ $lang->doc->productSpace = "{$lang->productCommon} Space"; $lang->doc->projectSpace = "{$lang->projectCommon} Space"; $lang->doc->apiSpace = 'API Space'; $lang->doc->teamSpace = 'Team Space'; +$lang->doc->template = 'Document Template'; $lang->product->list = $lang->productCommon . ' List'; $lang->product->kanban = $lang->productCommon . ' Kanban'; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index c209c37f39..27be3c9e61 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -559,6 +559,7 @@ $lang->doc->menu->product = array('link' => "{$lang->doc->productSpace}|doc|pr $lang->doc->menu->project = array('link' => "{$lang->doc->projectSpace}|doc|projectSpace|", 'alias' => 'projectspace'); $lang->doc->menu->api = array('link' => "{$lang->doc->apiSpace}|api|index", 'alias' => '', 'exclude' => 'index'); $lang->doc->menu->team = array('link' => "{$lang->doc->teamSpace}|doc|teamSpace|", 'alias' => 'teamspace'); +$lang->doc->menu->template = array('link' => "{$lang->doc->template}|doc|browseTemplate|", 'alias' => 'browsetemplate'); $lang->doc->dividerMenu = ',product,'; @@ -570,6 +571,7 @@ $lang->doc->menuOrder[15] = 'team'; $lang->doc->menuOrder[20] = 'product'; $lang->doc->menuOrder[25] = 'project'; $lang->doc->menuOrder[30] = 'api'; +$lang->doc->menuOrder[35] = 'template'; /* BI menu.*/ $lang->bi->menu = new stdclass(); diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 21c55dd2e5..a7fcb2eb4b 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -398,6 +398,7 @@ $lang->doc->productSpace = "{$lang->productCommon}空间"; $lang->doc->projectSpace = "{$lang->projectCommon}空间"; $lang->doc->apiSpace = '接口空间'; $lang->doc->teamSpace = '团队空间'; +$lang->doc->template = '文档模板'; $lang->product->list = $lang->productCommon . '列表'; $lang->product->kanban = $lang->productCommon . '看板'; diff --git a/module/doc/control.php b/module/doc/control.php index c5da286f8c..5adbd23fdc 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -311,6 +311,19 @@ class doc extends control return $this->send(array('result' => 'success', 'load' => $browseLink, 'app' => $this->app->tab)); } + /** + * 文档模板列表。 + * Browse template list. + * + * @access public + * @return void + */ + public function browseTemplate() + { + $this->view->title = $this->lang->doc->template; + $this->display(); + } + /** * 上传文档。 * Upload docs. diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php new file mode 100644 index 0000000000..5f9de7b37c --- /dev/null +++ b/module/doc/ui/browsetemplate.html.php @@ -0,0 +1,13 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; + +render(); From 8b6ecbb1a30ed2760df6d6fb8c87b6b080eb62cc Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 6 Nov 2024 07:36:31 +0000 Subject: [PATCH 003/655] * [misc] Set doc template scopes. --- module/doc/config.php | 6 ++++++ module/doc/lang/de.php | 7 +++++++ module/doc/lang/en.php | 7 +++++++ module/doc/lang/fr.php | 7 +++++++ module/doc/lang/zh-cn.php | 7 +++++++ 5 files changed, 34 insertions(+) diff --git a/module/doc/config.php b/module/doc/config.php index 2185b2c3bd..4a7dd8488f 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -121,3 +121,9 @@ $config->doc->quickMenu['view'] = array('id' => 1, 'name' => $lang->doc->my $config->doc->quickMenu['createdby'] = array('id' => 2, 'name' => $lang->doc->myCreation); $config->doc->quickMenu['collect'] = array('id' => 3, 'name' => $lang->doc->myCollection); $config->doc->quickMenu['editedby'] = array('id' => 4, 'name' => $lang->doc->myEdited); + +$config->doc->templateMenu = array(); +$config->doc->templateMenu['product'] = array('id' => 1, 'scope' => 'product', 'name' => $lang->doc->templateScopes['product']); +$config->doc->templateMenu['project'] = array('id' => 2, 'scope' => 'project', 'name' => $lang->doc->templateScopes['project']); +$config->doc->templateMenu['execution'] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->doc->templateScopes['execution']); +$config->doc->templateMenu['personal'] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->doc->templateScopes['personal']); diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 7f8791aca4..f434744025 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -72,6 +72,13 @@ $lang->doclib->apiNameUnique['product'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $lang->projectCommon . ', '; $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; +$lang->docTemplate = new stdclass(); +$lang->docTemplate->scopes = array(); +$lang->docTemplate->scopes['product'] = 'Product'; +$lang->docTemplate->scopes['project'] = 'Project'; +$lang->docTemplate->scopes['execution'] = 'Execution'; +$lang->docTemplate->scopes['personal'] = 'Personal'; + /* Fields. */ $lang->doc->common = 'Dok'; $lang->doc->id = 'ID'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 74ee4a9bb6..acbc507284 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -72,6 +72,13 @@ $lang->doclib->apiNameUnique['product'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $lang->projectCommon . ', '; $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; +$lang->docTemplate = new stdclass(); +$lang->docTemplate->scopes = array(); +$lang->docTemplate->scopes['product'] = 'Product'; +$lang->docTemplate->scopes['project'] = 'Project'; +$lang->docTemplate->scopes['execution'] = 'Execution'; +$lang->docTemplate->scopes['personal'] = 'Personal'; + /* Fields. */ $lang->doc->common = 'Document'; $lang->doc->id = 'ID'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 7cc9dc6b45..07edbe0a2e 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -72,6 +72,13 @@ $lang->doclib->apiNameUnique['product'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $lang->projectCommon . ', '; $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; +$lang->docTemplate = new stdclass(); +$lang->docTemplate->scopes = array(); +$lang->docTemplate->scopes['product'] = 'Product'; +$lang->docTemplate->scopes['project'] = 'Project'; +$lang->docTemplate->scopes['execution'] = 'Execution'; +$lang->docTemplate->scopes['personal'] = 'Personal'; + /* Fields. */ $lang->doc->common = 'Gestion Documentaire'; $lang->doc->id = 'ID'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 778fa09391..ec78dab915 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -72,6 +72,13 @@ $lang->doclib->apiNameUnique['product'] = '同一' . $lang->productCommon . '下 $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下的接口库中'; $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; +$lang->docTemplate = new stdclass(); +$lang->docTemplate->scopes = array(); +$lang->docTemplate->scopes['product'] = '产品'; +$lang->docTemplate->scopes['project'] = '项目'; +$lang->docTemplate->scopes['execution'] = '执行'; +$lang->docTemplate->scopes['personal'] = '个人'; + /* 字段列表。*/ $lang->doc->common = '文档'; $lang->doc->id = 'ID'; From 03afdf254c7388429716670c9d6a924578208b12 Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 6 Nov 2024 07:37:56 +0000 Subject: [PATCH 004/655] * [misc] Set template info. --- module/doc/control.php | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 5adbd23fdc..309320dd87 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -315,12 +315,40 @@ class doc extends control * 文档模板列表。 * Browse template list. * + * @param string $scope + * @param string $type + * @param int $docID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID * @access public * @return void */ - public function browseTemplate() + public function browseTemplate(string $scope = '', string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1) { - $this->view->title = $this->lang->doc->template; + if(!isset($this->config->doc->templateMenu[$scope])) $scope = 'product'; + $menu = $this->config->doc->templateMenu[$scope]; + + $this->app->loadClass('pager', true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $templateList = $this->doc->getDocTemplateList($type, $orderBy, $pager); + foreach($templateList as $template) + { + $template->originLib = $template->lib; + $template->lib = $menu['id']; + } + + $this->view->title = $this->lang->doc->template; + $this->view->menu = $menu; + $this->view->scope = $scope; + $this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter'); + $this->view->templateList = $templateList; + $this->view->docID = $docID; + $this->view->orderBy = $orderBy; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; $this->display(); } From dab6a3b4096a6edd447536f301df95a880d37d4f Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 6 Nov 2024 07:40:17 +0000 Subject: [PATCH 005/655] * [misc] Add getDocTemplateList function. --- module/doc/model.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 7fbfd89099..8a4d62af47 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -643,6 +643,28 @@ class docModel extends model return $query; } + /** + * 获取文档模板列表。 + * Get document template list. + * + * @param string $type + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getDocTemplateList(string $type = 'all', string $orderBy = 'id_desc', object $pager = NULL): array + { + return $this->dao->select('*')->from(TABLE_DOC) + ->where('deleted')->eq('0') + ->beginIF($type == 'all')->andWhere('templateType')->ne('')->fi() + ->beginIF($type != 'all')->andWhere('templateType')->eq($type)->fi() + ->andWhere('lib')->eq('') + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + /** * 通过文档ID获取文档所属产品、项目、执行。 * Get projects, executions and products by docIdList. From a0d9418662ce019985fa3f08a9aaf3103d463997 Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 6 Nov 2024 07:41:08 +0000 Subject: [PATCH 006/655] * [misc] Set template list view. --- module/doc/ui/browsetemplate.html.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 5f9de7b37c..6259f6b766 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -10,4 +10,30 @@ declare(strict_types=1); */ namespace zin; +$spaceID = 1; +$libID = $menu['id']; +$data = array('spaceID' => $spaceID, 'docs' => array_values($templateList)); +$data['spaces'][] = array('name' => $lang->doc->template, 'id' => $spaceID); +foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); + +$privs = array(); +$langData = array(); + +docApp +( + set::data($data), + set::spaceID($spaceID), + set::libID($libID), + set::docID($docID), + set::noSpace(), + set::noModule(), + set::homeName(false), + set::mode($docID ? 'view' : 'list'), + set::privs($privs), + set::userMap($users), + set::spaceIcon('home'), + set::langData($langData), + set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)) +); + render(); From 9612e4fb3dc889536e4fc6030d719ff6d15ca0a5 Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 6 Nov 2024 09:19:53 +0000 Subject: [PATCH 007/655] * [task#131757,done,2h] Set template filters. --- lib/zin/wg/docapp/js/v1.js | 1 + module/doc/config.php | 8 ++++---- module/doc/lang/de.php | 6 ++++++ module/doc/lang/en.php | 6 ++++++ module/doc/lang/fr.php | 6 ++++++ module/doc/lang/zh-cn.php | 6 ++++++ module/doc/ui/browsetemplate.html.php | 5 +++++ 7 files changed, 34 insertions(+), 4 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index 2d52e37a93..ae26743e58 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -1072,6 +1072,7 @@ function isMatchFilter(type, filterType, item) if(filterType === 'editedByMe') return item.editedBy === currentUser; if(filterType === 'draft') return item.status === 'draft'; if(filterType === 'collect') return item.isCollector; + if(filterType === 'released') return item.status === 'normal'; } if(type === 'project' || type === 'product') { diff --git a/module/doc/config.php b/module/doc/config.php index 4a7dd8488f..84a43ab8bb 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -123,7 +123,7 @@ $config->doc->quickMenu['collect'] = array('id' => 3, 'name' => $lang->doc->my $config->doc->quickMenu['editedby'] = array('id' => 4, 'name' => $lang->doc->myEdited); $config->doc->templateMenu = array(); -$config->doc->templateMenu['product'] = array('id' => 1, 'scope' => 'product', 'name' => $lang->doc->templateScopes['product']); -$config->doc->templateMenu['project'] = array('id' => 2, 'scope' => 'project', 'name' => $lang->doc->templateScopes['project']); -$config->doc->templateMenu['execution'] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->doc->templateScopes['execution']); -$config->doc->templateMenu['personal'] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->doc->templateScopes['personal']); +$config->doc->templateMenu['product'] = array('id' => 1, 'scope' => 'product', 'name' => $lang->docTemplate->scopes['product']); +$config->doc->templateMenu['project'] = array('id' => 2, 'scope' => 'project', 'name' => $lang->docTemplate->scopes['project']); +$config->doc->templateMenu['execution'] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->docTemplate->scopes['execution']); +$config->doc->templateMenu['personal'] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->docTemplate->scopes['personal']); diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index f434744025..1b24d27a14 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -79,6 +79,12 @@ $lang->docTemplate->scopes['project'] = 'Project'; $lang->docTemplate->scopes['execution'] = 'Execution'; $lang->docTemplate->scopes['personal'] = 'Personal'; +$lang->docTemplate->filterTypes = array(); +$lang->docTemplate->filterTypes[] = array('all', 'All'); +$lang->docTemplate->filterTypes[] = array('draft', 'Draft'); +$lang->docTemplate->filterTypes[] = array('released', 'Released'); +$lang->docTemplate->filterTypes[] = array('createdByMe', 'Created By Me'); + /* Fields. */ $lang->doc->common = 'Dok'; $lang->doc->id = 'ID'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index acbc507284..17d24f963e 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -79,6 +79,12 @@ $lang->docTemplate->scopes['project'] = 'Project'; $lang->docTemplate->scopes['execution'] = 'Execution'; $lang->docTemplate->scopes['personal'] = 'Personal'; +$lang->docTemplate->filterTypes = array(); +$lang->docTemplate->filterTypes[] = array('all', 'All'); +$lang->docTemplate->filterTypes[] = array('draft', 'Draft'); +$lang->docTemplate->filterTypes[] = array('released', 'Released'); +$lang->docTemplate->filterTypes[] = array('createdByMe', 'Created By Me'); + /* Fields. */ $lang->doc->common = 'Document'; $lang->doc->id = 'ID'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 07edbe0a2e..1d0e647b90 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -79,6 +79,12 @@ $lang->docTemplate->scopes['project'] = 'Project'; $lang->docTemplate->scopes['execution'] = 'Execution'; $lang->docTemplate->scopes['personal'] = 'Personal'; +$lang->docTemplate->filterTypes = array(); +$lang->docTemplate->filterTypes[] = array('all', 'All'); +$lang->docTemplate->filterTypes[] = array('draft', 'Draft'); +$lang->docTemplate->filterTypes[] = array('released', 'Released'); +$lang->docTemplate->filterTypes[] = array('createdByMe', 'Created By Me'); + /* Fields. */ $lang->doc->common = 'Gestion Documentaire'; $lang->doc->id = 'ID'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index ec78dab915..b4c2bcb681 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -79,6 +79,12 @@ $lang->docTemplate->scopes['project'] = '项目'; $lang->docTemplate->scopes['execution'] = '执行'; $lang->docTemplate->scopes['personal'] = '个人'; +$lang->docTemplate->filterTypes = array(); +$lang->docTemplate->filterTypes[] = array('all', '全部'); +$lang->docTemplate->filterTypes[] = array('draft', '草稿'); +$lang->docTemplate->filterTypes[] = array('released', '已发布'); +$lang->docTemplate->filterTypes[] = array('createdByMe', '我创建的'); + /* 字段列表。*/ $lang->doc->common = '文档'; $lang->doc->id = 'ID'; diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 6259f6b766..93c333c678 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -17,7 +17,12 @@ $data['spaces'][] = array('name' => $lang->doc->template, 'id' => $spaceID); foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); $privs = array(); + +$filterTypes = $lang->docTemplate->filterTypes; +if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); + $langData = array(); +$langData['filterTypes'] = $filterTypes; docApp ( From f67db01dc9fb1f796245a49ab6b9bc76d49d837a Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 13:58:50 +0800 Subject: [PATCH 008/655] * [task#131755,doing,0.5h] add config of template modules. --- module/doc/config.php | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/module/doc/config.php b/module/doc/config.php index 84a43ab8bb..d75366845c 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -127,3 +127,40 @@ $config->doc->templateMenu['product'] = array('id' => 1, 'scope' => 'product', $config->doc->templateMenu['project'] = array('id' => 2, 'scope' => 'project', 'name' => $lang->docTemplate->scopes['project']); $config->doc->templateMenu['execution'] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->docTemplate->scopes['execution']); $config->doc->templateMenu['personal'] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->docTemplate->scopes['personal']); + +$config->doc->templateModule = array(); +$config->doc->templateModule['product'] = array(); +$config->doc->templateModule['product']['plan'] = array(); +$config->doc->templateModule['product']['plan']['softwareProductPlan'] = 'Software product plan'; +$config->doc->templateModule['product']['plan']['hardwareProductPlan'] = 'Hardware product plan'; +$config->doc->templateModule['product']['plan']['qualityAssurancePlan'] = 'Quality assurance plan'; + +$config->doc->templateModule['product']['desc'] = array(); +$config->doc->templateModule['product']['desc']['productDesign'] = 'Product design'; +$config->doc->templateModule['product']['desc']['requirementSpecification'] = 'Requirement specification'; +$config->doc->templateModule['product']['desc']['userManual'] = 'User manual'; + +$config->doc->templateModule['product']['report'] = array(); +$config->doc->templateModule['product']['report']['competitiveProductAnalysisReport'] = 'Competitive product analysis report'; +$config->doc->templateModule['product']['report']['productAcceptanceReport'] = 'Product acceptance report'; +$config->doc->templateModule['product']['report']['productSummaryReport'] = 'Product summary report'; +$config->doc->templateModule['product']['report']['productQualityReport'] = 'Product quality report'; + +$config->doc->templateModule['project'] = array(); +$config->doc->templateModule['project']['plan'] = array(); +$config->doc->templateModule['project']['desc'] = array(); +$config->doc->templateModule['project']['dev'] = array(); +$config->doc->templateModule['project']['test'] = array(); +$config->doc->templateModule['project']['report'] = array(); +$config->doc->templateModule['project']['other'] = array(); + +$config->doc->templateModule['execution'] = array(); +$config->doc->templateModule['execution']['plan'] = array(); +$config->doc->templateModule['execution']['desc'] = array(); +$config->doc->templateModule['execution']['dev'] = array(); +$config->doc->templateModule['execution']['test'] = array(); +$config->doc->templateModule['execution']['report'] = array(); + +$config->doc->templateModule['personal'] = array(); +$config->doc->templateModule['personal']['plan'] = array(); +$config->doc->templateModule['personal']['report'] = array(); From 0a5b739c696d01f78911a73f2a9151814bccf786 Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 7 Nov 2024 08:14:14 +0000 Subject: [PATCH 009/655] * [misc] Set return type. --- module/common/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/common/model.php b/module/common/model.php index c29c200b4b..84ca76ac26 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -2370,7 +2370,7 @@ eof; * @access public * @return string */ - public static function processMarkdown(string $markdown): string + public static function processMarkdown(string $markdown): string|bool { if(empty($markdown)) return false; From e3de114e62ffc11f5155d04ca7b616aedbe89d3e Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 7 Nov 2024 08:23:51 +0000 Subject: [PATCH 010/655] * [task#131763,done,1h] Add template language. --- module/doc/lang/de.php | 15 +++++++++++++++ module/doc/lang/en.php | 15 +++++++++++++++ module/doc/lang/fr.php | 15 +++++++++++++++ module/doc/lang/zh-cn.php | 15 +++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 1b24d27a14..6f8a1d2245 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -73,6 +73,21 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; + +$lang->docTemplate->create = 'Create Template'; +$lang->docTemplate->edit = 'Edit Template'; +$lang->docTemplate->delete = 'Delete Template'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = 'Product'; $lang->docTemplate->scopes['project'] = 'Project'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 17d24f963e..83b33dd530 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -73,6 +73,21 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; + +$lang->docTemplate->create = 'Create Template'; +$lang->docTemplate->edit = 'Edit Template'; +$lang->docTemplate->delete = 'Delete Template'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = 'Product'; $lang->docTemplate->scopes['project'] = 'Project'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 1d0e647b90..fcea777498 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -73,6 +73,21 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; + +$lang->docTemplate->create = 'Create Template'; +$lang->docTemplate->edit = 'Edit Template'; +$lang->docTemplate->delete = 'Delete Template'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = 'Product'; $lang->docTemplate->scopes['project'] = 'Project'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index b4c2bcb681..4eeaaf6315 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -73,6 +73,21 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequecy = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建时间'; +$lang->docTemplate->editedBy = '最后修改者'; +$lang->docTemplate->editedDate = '最后修改时间'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; + +$lang->docTemplate->create = '创建模板'; +$lang->docTemplate->edit = '编辑模板'; +$lang->docTemplate->delete = '删除模板'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = '产品'; $lang->docTemplate->scopes['project'] = '项目'; From f442cce2c24085aa0e028dbd00c96df8383b530f Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 7 Nov 2024 08:25:36 +0000 Subject: [PATCH 011/655] * [task#131763,done,2h] Adjust actions of document template. --- module/doc/js/browsetemplate.ui.js | 84 +++++++++++++++++++++++++++ module/doc/ui/browsetemplate.html.php | 20 ++++++- 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 module/doc/js/browsetemplate.ui.js diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js new file mode 100644 index 0000000000..5b5daf85d5 --- /dev/null +++ b/module/doc/js/browsetemplate.ui.js @@ -0,0 +1,84 @@ +/** + * 获取文档界面上的表格初始化选项。 + * Get the table initialization options on the doc UI. + * + * @param {object} options + * @param {object} info + * @returns {object} + */ +function getTableOptions(options, info) +{ + const lang = getDocAppLang(); + + options.cols = options.cols.filter(col => col.name !== 'collects'); + + options.cols.forEach(col => + { + if(col.name === 'actions' && col.actionsMap) + { + col.actions = col.actions.filter(action => action !== 'move'); + delete col.actionsMap.move; + + const actionHints = {edit: lang.editTemplate, delete: lang.deleteTemplate}; + $.each(col.actionsMap, (key, value) => + { + if(typeof actionHints[key] === 'string') value.hint = actionHints[key]; + if(key == 'edit') value.command = 'editTemplate/{id}'; + if(key == 'delete') value.command = 'deleteTemplate/{id}'; + }); + + } + }); + + return options; +} + +/** + * 重写文档应用的配置选项方法。 + * Override the method to set the doc app options. + */ +window._setDocAppOptions = window.setDocAppOptions; // Save the original method. +window.setDocAppOptions = function(_, options) // Override the method. +{ + options = window._setDocAppOptions(_, options); + return $.extend(options, + { + getTableOptions : getTableOptions + }); +}; + +/* 扩展文档模板命令定义。 Extend the doc app command definition. */ +$.extend(window.docAppCommands, +{ + /** + * 编辑文档模板。 + * Edit doc template. + */ + editTemplate: function(_, args) + { + const docApp = getDocApp(); + const templateID = args[0] || docApp.docID; + const url = $.createLink('doc', 'editTemplate', `templateID=${templateID}`); + zui.Modal.open({size: 'sm', url: url}); + }, + /** + * 删除文档模板。 + * Delete doc template. + */ + deleteTemplate: function(_, args) + { + const docApp = getDocApp(); + const lang = getDocAppLang(); + const templateID = args[0] || docApp.docID; + $.ajaxSubmit( + { + confirm: lang.confirmDelete, + url: $.createLink('doc', 'deleteTemplate', `templateID=${templateID}`), + load:false, + onSunccess: function() + { + getDocApp().delete('doc', templateID); + } + }) + } +}); diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 93c333c678..2f7cd0469f 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -21,8 +21,26 @@ $privs = array(); $filterTypes = $lang->docTemplate->filterTypes; if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); +$tableCols = array(); +$tableCols['id'] = $lang->docTemplate->id; +$tableCols['title'] = $lang->docTemplate->title; +$tableCols['frequency'] = $lang->docTemplate->frequency; +$tableCols['type'] = $lang->docTemplate->type; +$tableCols['addedBy'] = $lang->docTemplate->addedBy; +$tableCols['addedDate'] = $lang->docTemplate->addedDate; +$tableCols['editedBy'] = $lang->docTemplate->editedBy; +$tableCols['editedDate'] = $lang->docTemplate->editedDate; +$tableCols['views'] = $lang->docTemplate->views; + $langData = array(); -$langData['filterTypes'] = $filterTypes; +$langData['filterTypes'] = $filterTypes; +$langData['tableCols'] = $tableCols; +$langData['create'] = $lang->docTemplate->create; +$langData['edit'] = $lang->docTemplate->edit; +$langData['delete'] = $lang->docTemplate->delete; +$langData['editTemplate'] = $lang->docTemplate->edit; +$langData['deleteTemplate'] = $lang->docTemplate->delete; +$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; docApp ( From 47aec9c1e58723d943da901b88fd1b06e2bc8014 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 15:59:38 +0800 Subject: [PATCH 012/655] * [task#131755,doing,0.5h] add config of template modules. --- module/doc/config.php | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/module/doc/config.php b/module/doc/config.php index d75366845c..6ccfbe464c 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -148,19 +148,69 @@ $config->doc->templateModule['product']['report']['productQualityReport'] $config->doc->templateModule['project'] = array(); $config->doc->templateModule['project']['plan'] = array(); +$config->doc->templateModule['project']['plan']['projectPlan'] = 'Project plan'; +$config->doc->templateModule['project']['plan']['projectQualityAssurancePlan'] = 'Project quality assurance plan'; +$config->doc->templateModule['project']['plan']['projectConfigurationManagementPlan'] = 'Project configuration management plan'; +$config->doc->templateModule['project']['plan']['projectIntegrationTestPlan'] = 'Project integration test plan'; +$config->doc->templateModule['project']['plan']['projectSystemTestPlan'] = 'Project system test plan'; + $config->doc->templateModule['project']['desc'] = array(); +$config->doc->templateModule['project']['desc']['businessRequirementsStatement'] = 'Business requirements statement'; +$config->doc->templateModule['project']['desc']['projectUserRequirementsSpecification'] = 'Project user requirements specification'; +$config->doc->templateModule['project']['desc']['projectSoftwareRequirementsSpecification'] = 'Project software requirements specification'; +$config->doc->templateModule['project']['desc']['projectSummaryDesignSpecification'] = 'Project summary design specification'; +$config->doc->templateModule['project']['desc']['projectDetailedDesignSpecification'] = 'Project detailed design specification'; +$config->doc->templateModule['project']['desc']['projectUserManual'] = 'Project user manual'; + $config->doc->templateModule['project']['dev'] = array(); +$config->doc->templateModule['project']['dev']['projectCode'] = 'Project code'; +$config->doc->templateModule['project']['dev']['projectDatabaseDesignDocument'] = 'Project database design document'; +$config->doc->templateModule['project']['dev']['projectInterfaceDesignDocument'] = 'Project interface design document'; + $config->doc->templateModule['project']['test'] = array(); +$config->doc->templateModule['project']['test']['projectIntegrationTestCases'] = 'Project integration test cases'; +$config->doc->templateModule['project']['test']['projectSystemTestCases'] = 'Project system test cases'; + $config->doc->templateModule['project']['report'] = array(); +$config->doc->templateModule['project']['report']['projectProgressReport'] = 'Project progress report'; +$config->doc->templateModule['project']['report']['projectRiskReport'] = 'Project risk report'; +$config->doc->templateModule['project']['report']['projectAcceptanceReport'] = 'Project acceptance report'; +$config->doc->templateModule['project']['report']['projectSummaryReport'] = 'Project summary report'; +$config->doc->templateModule['project']['report']['projectQualityReport'] = 'Project quality report'; + $config->doc->templateModule['project']['other'] = array(); $config->doc->templateModule['execution'] = array(); $config->doc->templateModule['execution']['plan'] = array(); +$config->doc->templateModule['execution']['plan']['executionDevelopmentPlan'] = 'Execution development plan'; +$config->doc->templateModule['execution']['plan']['executionQualityAssurancePlan'] = 'Execution quality assurance plan'; +$config->doc->templateModule['execution']['plan']['executionTestPlan'] = 'Execution test plan'; + $config->doc->templateModule['execution']['desc'] = array(); +$config->doc->templateModule['execution']['desc']['executionSoftwareRequirementsSpecification'] = 'Execution software requirements specification'; +$config->doc->templateModule['execution']['desc']['executionArchitecturalDesignSpecification'] = 'Execution architectural design specification'; +$config->doc->templateModule['execution']['desc']['executionCodeDesignSpecification'] = 'Execution code design specification'; + $config->doc->templateModule['execution']['dev'] = array(); +$config->doc->templateModule['execution']['dev']['executionCode'] = 'Execution code'; +$config->doc->templateModule['execution']['dev']['executionDatabaseDesignDocument'] = 'Execution database design document'; +$config->doc->templateModule['execution']['dev']['executionInterfaceDesignDocument'] = 'Execution interface design document'; + $config->doc->templateModule['execution']['test'] = array(); +$config->doc->templateModule['execution']['test']['executionFunctionalTesting'] = 'Execution functional testing'; +$config->doc->templateModule['execution']['test']['executionTestCases'] = 'Execution test cases'; + $config->doc->templateModule['execution']['report'] = array(); +$config->doc->templateModule['execution']['report']['executionProgressReport'] = 'Execution progress report'; +$config->doc->templateModule['execution']['report']['executionRiskReport'] = 'Execution risk report'; +$config->doc->templateModule['execution']['report']['executionAcceptanceReport'] = 'Execution acceptance report'; +$config->doc->templateModule['execution']['report']['executionSummaryReport'] = 'Execution summary report'; +$config->doc->templateModule['execution']['report']['executionQualityReport'] = 'Execution quality report'; $config->doc->templateModule['personal'] = array(); $config->doc->templateModule['personal']['plan'] = array(); +$config->doc->templateModule['personal']['plan']['personalWorkPlan'] = 'Personal work plan'; + $config->doc->templateModule['personal']['report'] = array(); +$config->doc->templateModule['personal']['report']['personalWorkSummaryReport'] = 'Personal work summary report'; +$config->doc->templateModule['personal']['report']['personalValueAnalysisReport'] = 'Personal value analysis report'; From 1706449d8ee00df0f912bb5043c0eebc4a027370 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 16:19:04 +0800 Subject: [PATCH 013/655] * [task#131755,doing,0.5h] add lang of template modules. --- module/doc/lang/zh-cn.php | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 4eeaaf6315..51ae557442 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -587,3 +587,49 @@ $lang->doc->docLang->docTitleRequired = '文档标题不能为空。' $lang->doc->docLang->docTitlePlaceholder = '请输入文档标题'; $lang->doc->docLang->noDataYet = '暂无数据'; $lang->doc->docLang->position = $lang->doc->position; + +$lang->docTemplate->moduleName = array(); +$lang->docTemplate->moduleName['plan'] = '计划'; +$lang->docTemplate->moduleName['desc'] = '说明'; +$lang->docTemplate->moduleName['report'] = '报告'; +$lang->docTemplate->moduleName['dev'] = '开发'; +$lang->docTemplate->moduleName['test'] = '测试'; +$lang->docTemplate->moduleName['other'] = '其他'; + +$lang->docTemplate->moduleName['softwareProductPlan'] = '软件产品计划'; +$lang->docTemplate->moduleName['hardwareProductPlan'] = '硬件产品计划'; +$lang->docTemplate->moduleName['qualityAssurancePlan'] = '质量保证计划'; +$lang->docTemplate->moduleName['productDesign'] = '产品设计'; +$lang->docTemplate->moduleName['requirementSpecification'] = '需求说明'; +$lang->docTemplate->moduleName['userManual'] = '用户手册'; +$lang->docTemplate->moduleName['competitiveProductAnalysisReport'] = '竞品分析报告'; +$lang->docTemplate->moduleName['productAcceptanceReport'] = '产品验收报告'; +$lang->docTemplate->moduleName['productSummaryReport'] = '产品总结报告'; +$lang->docTemplate->moduleName['productQualityReport'] = '产品质量报告'; +$lang->docTemplate->moduleName['projectPlan'] = '项目计划'; +$lang->docTemplate->moduleName['projectQualityAssurancePlan'] = '质量保证计划'; +$lang->docTemplate->moduleName['projectConfigurationManagementPlan'] = '配置管理计划'; +$lang->docTemplate->moduleName['projectIntegrationTestPlan'] = '集成测试计划'; +$lang->docTemplate->moduleName['projectSystemTestPlan'] = '系统测试计划'; +$lang->docTemplate->moduleName['businessRequirementsStatement'] = '业务需求说明书'; +$lang->docTemplate->moduleName['projectUserRequirementsSpecification'] = '用户需求说明书'; +$lang->docTemplate->moduleName['projectSoftwareRequirementsSpecification'] = '软件需求规格说明书'; +$lang->docTemplate->moduleName['projectSummaryDesignSpecification'] = '概要设计说明书'; +$lang->docTemplate->moduleName['projectDetailedDesignSpecification'] = '详细设计说明书'; +$lang->docTemplate->moduleName['projectUserManual'] = '用户手册'; +$lang->docTemplate->moduleName['projectCode'] = '程序代码'; +$lang->docTemplate->moduleName['projectDatabaseDesignDocument'] = '数据库设计'; +$lang->docTemplate->moduleName['projectInterfaceDesignDocument'] = '接口设计'; +$lang->docTemplate->moduleName['projectIntegrationTestCases'] = '集成测试用例'; +$lang->docTemplate->moduleName['projectSystemTestCases'] = '系统测试用例'; +$lang->docTemplate->moduleName['projectProgressReport'] = '进度报告'; +$lang->docTemplate->moduleName['projectRiskReport'] = '风险报告'; +$lang->docTemplate->moduleName['projectAcceptanceReport'] = '验收报告'; +$lang->docTemplate->moduleName['projectSummaryReport'] = '总结报告'; +$lang->docTemplate->moduleName['projectQualityReport'] = '质量报告'; +$lang->docTemplate->moduleName['executionDevelopmentPlan'] = '开发计划'; +$lang->docTemplate->moduleName['executionQualityAssurancePlan'] = '质量保证计划'; +$lang->docTemplate->moduleName['executionTestPlan'] = '测试计划'; +$lang->docTemplate->moduleName['executionSoftwareRequirementsSpecification'] = '软件需求说明书'; +$lang->docTemplate->moduleName['executionArchitecturalDesignSpecification'] = '架构设计说明书'; +$lang->docTemplate->moduleName['executionCodeDesignSpecification'] = '代码设计说明书'; From bb2e77c56fbddb55d2c28e084db29d68b9333c74 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 16:27:18 +0800 Subject: [PATCH 014/655] * [task#131755,doing,0.5h] add lang of template modules. --- module/doc/lang/zh-cn.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 51ae557442..cf92f11f0e 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -633,3 +633,16 @@ $lang->docTemplate->moduleName['executionTestPlan'] = ' $lang->docTemplate->moduleName['executionSoftwareRequirementsSpecification'] = '软件需求说明书'; $lang->docTemplate->moduleName['executionArchitecturalDesignSpecification'] = '架构设计说明书'; $lang->docTemplate->moduleName['executionCodeDesignSpecification'] = '代码设计说明书'; +$lang->docTemplate->moduleName['executionCode'] = '程序代码'; +$lang->docTemplate->moduleName['executionDatabaseDesignDocument'] = '数据库设计'; +$lang->docTemplate->moduleName['executionInterfaceDesignDocument'] = '接口设计'; +$lang->docTemplate->moduleName['executionFunctionalTesting'] = '功能测试'; +$lang->docTemplate->moduleName['executionTestCases'] = '测试用例'; +$lang->docTemplate->moduleName['executionProgressReport'] = '进度报告'; +$lang->docTemplate->moduleName['executionRiskReport'] = '风险报告'; +$lang->docTemplate->moduleName['executionAcceptanceReport'] = '验收报告'; +$lang->docTemplate->moduleName['executionSummaryReport'] = '总结报告'; +$lang->docTemplate->moduleName['executionQualityReport'] = '质量报告'; +$lang->docTemplate->moduleName['personalWorkPlan'] = '工作计划'; +$lang->docTemplate->moduleName['personalWorkSummaryReport'] = '工作总结报告'; +$lang->docTemplate->moduleName['personalValueAnalysisReport'] = '价值分析报告'; From 8da50225b7a8488dfa174478720f7a7b3670ba67 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 17:03:38 +0800 Subject: [PATCH 015/655] * [task#131755,doing,0.5h] insert builtin template type to module table. --- module/doc/model.php | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 8a4d62af47..dd4d01d9bc 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3619,4 +3619,49 @@ class docModel extends model return !empty($docID); } + + public function insertBuiltinTemplateModule() + { + foreach($this->config->doc->templateModule as $scope => $moduleList) + { + $moduleOrder = 10; + foreach($moduleList as $moduleKey => $subModuleList) + { + $module = new stdclass(); + $module->root = $this->config->doc->templateMenu[$scope]['id']; + $module->name = $this->lang->docTemplate->moduleName[$moduleKey]; + $module->parent = 0; + $module->path = ''; + $module->grade = 1; + $module->order = ++ $moduleOrder; + $module->type = 'docTemplate'; + $module->short = ucfirst($scope) . ' ' . $moduleKey; + $this->dao->insert(TABLE_MODULE)->data($module)->exec(); + if(dao::isError()) return false; + + $moduleID = $this->dao->lastInsertID(); + $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},")->where('id')->eq($moduleID)->exec(); + + $subModuleOrder = 10; + foreach($subModuleList as $subModuleKey => $subModuleCode) + { + $subModule = new stdclass(); + $subModule->root = $this->config->doc->templateMenu[$scope]['id']; + $subModule->name = $this->lang->docTemplate->moduleName[$subModuleKey]; + $subModule->parent = $moduleID; + $subModule->path = ''; + $subModule->grade = 2; + $subModule->order = ++ $subModuleOrder; + $subModule->type = 'docTemplate'; + $subModule->short = $subModuleCode; + $this->dao->insert(TABLE_MODULE)->data($subModule)->exec(); + if(dao::isError()) return false; + + $subModuleID = $this->dao->lastInsertID(); + $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},{$subModuleID},")->where('id')->eq($subModuleID)->exec(); + } + } + } + return true; + } } From 7c96918bfea1eed1ab62cc14c29c586bd8bf67e1 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 17:07:52 +0800 Subject: [PATCH 016/655] * [task#131755,doing,0.1h] add commit. --- module/doc/model.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index dd4d01d9bc..614244272e 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3620,6 +3620,13 @@ class docModel extends model return !empty($docID); } + /** + * 插入内置文档模板类型数据。 + * insert doc template type. + * + * @access public + * @return bool + */ public function insertBuiltinTemplateModule() { foreach($this->config->doc->templateModule as $scope => $moduleList) From c331bc9138730d2d15f661ad2f55cc460d88e69a Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 7 Nov 2024 17:09:39 +0800 Subject: [PATCH 017/655] * [task#131755,doing,0.1h] insert builtin template type to module table. --- module/upgrade/control.php | 13 +++++++++++++ module/upgrade/model.php | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/module/upgrade/control.php b/module/upgrade/control.php index bc26e141d4..5fc8ddf6bd 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -820,4 +820,17 @@ class upgrade extends control $check = $this->loadModel('bi')->checkDuckdbInstall(); echo(json_encode($check)); } + + /** + * Insert template module. + * + * @access public + * @return void + */ + public function ajaxInsertBuiltinTemplateModule() + { + $result = $this->upgrade->insertBuiltinTemplateModule(); + if($result) echo 'ok'; + if(!$result) echo dao::getError(); + } } diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 71fc4f04f1..f3ca1ef362 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10044,6 +10044,17 @@ class upgradeModel extends model } } + /** + * Insert template module. + * + * @access public + * @return bool + */ + public function insertBuiltinTemplateModule() + { + return $this->loadModel('doc')->insertBuiltinTemplateModule(); + } + /** * 历史产品、项目绑定默认工作流模板。 * From d303a3fad8ceaa21eb3960e06df5ab5ae685ca9d Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 09:08:16 +0800 Subject: [PATCH 018/655] * [task#131755,doing,0.5h] add en lang of template modules. --- module/doc/lang/en.php | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 83b33dd530..e970707f0b 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -587,3 +587,62 @@ $lang->doc->docLang->docTitleRequired = 'Please enter the document ti $lang->doc->docLang->docTitlePlaceholder = 'Enter the document title'; $lang->doc->docLang->noDataYet = 'No data yet'; $lang->doc->docLang->position = $lang->doc->position; + +$lang->docTemplate->moduleName = array(); +$lang->docTemplate->moduleName['plan'] = 'plan'; +$lang->docTemplate->moduleName['desc'] = 'description'; +$lang->docTemplate->moduleName['report'] = 'report'; +$lang->docTemplate->moduleName['dev'] = 'dev'; +$lang->docTemplate->moduleName['test'] = 'test'; +$lang->docTemplate->moduleName['other'] = 'other'; + +$lang->docTemplate->moduleName['softwareProductPlan'] = 'software product plan'; +$lang->docTemplate->moduleName['hardwareProductPlan'] = 'hardware product plan'; +$lang->docTemplate->moduleName['qualityAssurancePlan'] = 'quality assurance plan'; +$lang->docTemplate->moduleName['productDesign'] = 'product design'; +$lang->docTemplate->moduleName['requirementSpecification'] = 'requirement specification'; +$lang->docTemplate->moduleName['userManual'] = 'user manual'; +$lang->docTemplate->moduleName['competitiveProductAnalysisReport'] = 'competitive product analysis report'; +$lang->docTemplate->moduleName['productAcceptanceReport'] = 'product acceptance report'; +$lang->docTemplate->moduleName['productSummaryReport'] = 'product summary report'; +$lang->docTemplate->moduleName['productQualityReport'] = 'product quality report'; +$lang->docTemplate->moduleName['projectPlan'] = 'project plan'; +$lang->docTemplate->moduleName['projectQualityAssurancePlan'] = 'project quality assurance plan'; +$lang->docTemplate->moduleName['projectConfigurationManagementPlan'] = 'project configuration management plan'; +$lang->docTemplate->moduleName['projectIntegrationTestPlan'] = 'project integration test plan'; +$lang->docTemplate->moduleName['projectSystemTestPlan'] = 'project system test plan'; +$lang->docTemplate->moduleName['businessRequirementsStatement'] = 'business requirements statement'; +$lang->docTemplate->moduleName['projectUserRequirementsSpecification'] = 'project user requirements specification'; +$lang->docTemplate->moduleName['projectSoftwareRequirementsSpecification'] = 'project software requirements specification'; +$lang->docTemplate->moduleName['projectSummaryDesignSpecification'] = 'project summary design specification'; +$lang->docTemplate->moduleName['projectDetailedDesignSpecification'] = 'project detailed design specification'; +$lang->docTemplate->moduleName['projectUserManual'] = 'project user manual'; +$lang->docTemplate->moduleName['projectCode'] = 'project code'; +$lang->docTemplate->moduleName['projectDatabaseDesignDocument'] = 'project database design document'; +$lang->docTemplate->moduleName['projectInterfaceDesignDocument'] = 'project interface design document'; +$lang->docTemplate->moduleName['projectIntegrationTestCases'] = 'project integration test cases'; +$lang->docTemplate->moduleName['projectSystemTestCases'] = 'project system test cases'; +$lang->docTemplate->moduleName['projectProgressReport'] = 'project progress report'; +$lang->docTemplate->moduleName['projectRiskReport'] = 'project risk report'; +$lang->docTemplate->moduleName['projectAcceptanceReport'] = 'project acceptance report'; +$lang->docTemplate->moduleName['projectSummaryReport'] = 'project summary report'; +$lang->docTemplate->moduleName['projectQualityReport'] = 'project quality report'; +$lang->docTemplate->moduleName['executionDevelopmentPlan'] = 'execution development plan'; +$lang->docTemplate->moduleName['executionQualityAssurancePlan'] = 'execution quality assurance plan'; +$lang->docTemplate->moduleName['executionTestPlan'] = 'execution test plan'; +$lang->docTemplate->moduleName['executionSoftwareRequirementsSpecification'] = 'execution software requirements specification'; +$lang->docTemplate->moduleName['executionArchitecturalDesignSpecification'] = 'execution architectural design specification'; +$lang->docTemplate->moduleName['executionCodeDesignSpecification'] = 'execution code design specification'; +$lang->docTemplate->moduleName['executionCode'] = 'execution code'; +$lang->docTemplate->moduleName['executionDatabaseDesignDocument'] = 'execution database design document'; +$lang->docTemplate->moduleName['executionInterfaceDesignDocument'] = 'execution interface design document'; +$lang->docTemplate->moduleName['executionFunctionalTesting'] = 'execution functional testing'; +$lang->docTemplate->moduleName['executionTestCases'] = 'execution test cases'; +$lang->docTemplate->moduleName['executionProgressReport'] = 'execution progress report'; +$lang->docTemplate->moduleName['executionRiskReport'] = 'execution risk report'; +$lang->docTemplate->moduleName['executionAcceptanceReport'] = 'execution acceptance report'; +$lang->docTemplate->moduleName['executionSummaryReport'] = 'execution summary report'; +$lang->docTemplate->moduleName['executionQualityReport'] = 'execution quality report'; +$lang->docTemplate->moduleName['personalWorkPlan'] = 'personal work plan'; +$lang->docTemplate->moduleName['personalWorkSummaryReport'] = 'personal work summary report'; +$lang->docTemplate->moduleName['personalValueAnalysisReport'] = 'personal value analysis report'; From 2762e271e0f06f03a4a008ad74c961b7a5af8153 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 09:16:02 +0800 Subject: [PATCH 019/655] * [task#131755,doing,0.1h] add fr lang of template modules. --- module/doc/lang/fr.php | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index fcea777498..55bb4743a7 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -587,3 +587,62 @@ $lang->doc->docLang->docTitleRequired = 'Please enter the document ti $lang->doc->docLang->docTitlePlaceholder = 'Enter the document title'; $lang->doc->docLang->noDataYet = 'No data yet'; $lang->doc->docLang->position = $lang->doc->position; + +$lang->docTemplate->moduleName = array(); +$lang->docTemplate->moduleName['plan'] = 'plan'; +$lang->docTemplate->moduleName['desc'] = 'description'; +$lang->docTemplate->moduleName['report'] = 'report'; +$lang->docTemplate->moduleName['dev'] = 'dev'; +$lang->docTemplate->moduleName['test'] = 'test'; +$lang->docTemplate->moduleName['other'] = 'other'; + +$lang->docTemplate->moduleName['softwareProductPlan'] = 'software product plan'; +$lang->docTemplate->moduleName['hardwareProductPlan'] = 'hardware product plan'; +$lang->docTemplate->moduleName['qualityAssurancePlan'] = 'quality assurance plan'; +$lang->docTemplate->moduleName['productDesign'] = 'product design'; +$lang->docTemplate->moduleName['requirementSpecification'] = 'requirement specification'; +$lang->docTemplate->moduleName['userManual'] = 'user manual'; +$lang->docTemplate->moduleName['competitiveProductAnalysisReport'] = 'competitive product analysis report'; +$lang->docTemplate->moduleName['productAcceptanceReport'] = 'product acceptance report'; +$lang->docTemplate->moduleName['productSummaryReport'] = 'product summary report'; +$lang->docTemplate->moduleName['productQualityReport'] = 'product quality report'; +$lang->docTemplate->moduleName['projectPlan'] = 'project plan'; +$lang->docTemplate->moduleName['projectQualityAssurancePlan'] = 'project quality assurance plan'; +$lang->docTemplate->moduleName['projectConfigurationManagementPlan'] = 'project configuration management plan'; +$lang->docTemplate->moduleName['projectIntegrationTestPlan'] = 'project integration test plan'; +$lang->docTemplate->moduleName['projectSystemTestPlan'] = 'project system test plan'; +$lang->docTemplate->moduleName['businessRequirementsStatement'] = 'business requirements statement'; +$lang->docTemplate->moduleName['projectUserRequirementsSpecification'] = 'project user requirements specification'; +$lang->docTemplate->moduleName['projectSoftwareRequirementsSpecification'] = 'project software requirements specification'; +$lang->docTemplate->moduleName['projectSummaryDesignSpecification'] = 'project summary design specification'; +$lang->docTemplate->moduleName['projectDetailedDesignSpecification'] = 'project detailed design specification'; +$lang->docTemplate->moduleName['projectUserManual'] = 'project user manual'; +$lang->docTemplate->moduleName['projectCode'] = 'project code'; +$lang->docTemplate->moduleName['projectDatabaseDesignDocument'] = 'project database design document'; +$lang->docTemplate->moduleName['projectInterfaceDesignDocument'] = 'project interface design document'; +$lang->docTemplate->moduleName['projectIntegrationTestCases'] = 'project integration test cases'; +$lang->docTemplate->moduleName['projectSystemTestCases'] = 'project system test cases'; +$lang->docTemplate->moduleName['projectProgressReport'] = 'project progress report'; +$lang->docTemplate->moduleName['projectRiskReport'] = 'project risk report'; +$lang->docTemplate->moduleName['projectAcceptanceReport'] = 'project acceptance report'; +$lang->docTemplate->moduleName['projectSummaryReport'] = 'project summary report'; +$lang->docTemplate->moduleName['projectQualityReport'] = 'project quality report'; +$lang->docTemplate->moduleName['executionDevelopmentPlan'] = 'execution development plan'; +$lang->docTemplate->moduleName['executionQualityAssurancePlan'] = 'execution quality assurance plan'; +$lang->docTemplate->moduleName['executionTestPlan'] = 'execution test plan'; +$lang->docTemplate->moduleName['executionSoftwareRequirementsSpecification'] = 'execution software requirements specification'; +$lang->docTemplate->moduleName['executionArchitecturalDesignSpecification'] = 'execution architectural design specification'; +$lang->docTemplate->moduleName['executionCodeDesignSpecification'] = 'execution code design specification'; +$lang->docTemplate->moduleName['executionCode'] = 'execution code'; +$lang->docTemplate->moduleName['executionDatabaseDesignDocument'] = 'execution database design document'; +$lang->docTemplate->moduleName['executionInterfaceDesignDocument'] = 'execution interface design document'; +$lang->docTemplate->moduleName['executionFunctionalTesting'] = 'execution functional testing'; +$lang->docTemplate->moduleName['executionTestCases'] = 'execution test cases'; +$lang->docTemplate->moduleName['executionProgressReport'] = 'execution progress report'; +$lang->docTemplate->moduleName['executionRiskReport'] = 'execution risk report'; +$lang->docTemplate->moduleName['executionAcceptanceReport'] = 'execution acceptance report'; +$lang->docTemplate->moduleName['executionSummaryReport'] = 'execution summary report'; +$lang->docTemplate->moduleName['executionQualityReport'] = 'execution quality report'; +$lang->docTemplate->moduleName['personalWorkPlan'] = 'personal work plan'; +$lang->docTemplate->moduleName['personalWorkSummaryReport'] = 'personal work summary report'; +$lang->docTemplate->moduleName['personalValueAnalysisReport'] = 'personal value analysis report'; From c8e8b40b1cdd76f98372ee5290f0809512731d95 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 09:17:17 +0800 Subject: [PATCH 020/655] * [task#131755,doing,0.1h] add de lang of template modules. --- module/doc/lang/de.php | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 6f8a1d2245..eeb4ba37a4 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -587,3 +587,62 @@ $lang->doc->docLang->docTitleRequired = 'Please enter the document ti $lang->doc->docLang->docTitlePlaceholder = 'Enter the document title'; $lang->doc->docLang->noDataYet = 'No data yet'; $lang->doc->docLang->position = $lang->doc->position; + +$lang->docTemplate->moduleName = array(); +$lang->docTemplate->moduleName['plan'] = 'plan'; +$lang->docTemplate->moduleName['desc'] = 'description'; +$lang->docTemplate->moduleName['report'] = 'report'; +$lang->docTemplate->moduleName['dev'] = 'dev'; +$lang->docTemplate->moduleName['test'] = 'test'; +$lang->docTemplate->moduleName['other'] = 'other'; + +$lang->docTemplate->moduleName['softwareProductPlan'] = 'software product plan'; +$lang->docTemplate->moduleName['hardwareProductPlan'] = 'hardware product plan'; +$lang->docTemplate->moduleName['qualityAssurancePlan'] = 'quality assurance plan'; +$lang->docTemplate->moduleName['productDesign'] = 'product design'; +$lang->docTemplate->moduleName['requirementSpecification'] = 'requirement specification'; +$lang->docTemplate->moduleName['userManual'] = 'user manual'; +$lang->docTemplate->moduleName['competitiveProductAnalysisReport'] = 'competitive product analysis report'; +$lang->docTemplate->moduleName['productAcceptanceReport'] = 'product acceptance report'; +$lang->docTemplate->moduleName['productSummaryReport'] = 'product summary report'; +$lang->docTemplate->moduleName['productQualityReport'] = 'product quality report'; +$lang->docTemplate->moduleName['projectPlan'] = 'project plan'; +$lang->docTemplate->moduleName['projectQualityAssurancePlan'] = 'project quality assurance plan'; +$lang->docTemplate->moduleName['projectConfigurationManagementPlan'] = 'project configuration management plan'; +$lang->docTemplate->moduleName['projectIntegrationTestPlan'] = 'project integration test plan'; +$lang->docTemplate->moduleName['projectSystemTestPlan'] = 'project system test plan'; +$lang->docTemplate->moduleName['businessRequirementsStatement'] = 'business requirements statement'; +$lang->docTemplate->moduleName['projectUserRequirementsSpecification'] = 'project user requirements specification'; +$lang->docTemplate->moduleName['projectSoftwareRequirementsSpecification'] = 'project software requirements specification'; +$lang->docTemplate->moduleName['projectSummaryDesignSpecification'] = 'project summary design specification'; +$lang->docTemplate->moduleName['projectDetailedDesignSpecification'] = 'project detailed design specification'; +$lang->docTemplate->moduleName['projectUserManual'] = 'project user manual'; +$lang->docTemplate->moduleName['projectCode'] = 'project code'; +$lang->docTemplate->moduleName['projectDatabaseDesignDocument'] = 'project database design document'; +$lang->docTemplate->moduleName['projectInterfaceDesignDocument'] = 'project interface design document'; +$lang->docTemplate->moduleName['projectIntegrationTestCases'] = 'project integration test cases'; +$lang->docTemplate->moduleName['projectSystemTestCases'] = 'project system test cases'; +$lang->docTemplate->moduleName['projectProgressReport'] = 'project progress report'; +$lang->docTemplate->moduleName['projectRiskReport'] = 'project risk report'; +$lang->docTemplate->moduleName['projectAcceptanceReport'] = 'project acceptance report'; +$lang->docTemplate->moduleName['projectSummaryReport'] = 'project summary report'; +$lang->docTemplate->moduleName['projectQualityReport'] = 'project quality report'; +$lang->docTemplate->moduleName['executionDevelopmentPlan'] = 'execution development plan'; +$lang->docTemplate->moduleName['executionQualityAssurancePlan'] = 'execution quality assurance plan'; +$lang->docTemplate->moduleName['executionTestPlan'] = 'execution test plan'; +$lang->docTemplate->moduleName['executionSoftwareRequirementsSpecification'] = 'execution software requirements specification'; +$lang->docTemplate->moduleName['executionArchitecturalDesignSpecification'] = 'execution architectural design specification'; +$lang->docTemplate->moduleName['executionCodeDesignSpecification'] = 'execution code design specification'; +$lang->docTemplate->moduleName['executionCode'] = 'execution code'; +$lang->docTemplate->moduleName['executionDatabaseDesignDocument'] = 'execution database design document'; +$lang->docTemplate->moduleName['executionInterfaceDesignDocument'] = 'execution interface design document'; +$lang->docTemplate->moduleName['executionFunctionalTesting'] = 'execution functional testing'; +$lang->docTemplate->moduleName['executionTestCases'] = 'execution test cases'; +$lang->docTemplate->moduleName['executionProgressReport'] = 'execution progress report'; +$lang->docTemplate->moduleName['executionRiskReport'] = 'execution risk report'; +$lang->docTemplate->moduleName['executionAcceptanceReport'] = 'execution acceptance report'; +$lang->docTemplate->moduleName['executionSummaryReport'] = 'execution summary report'; +$lang->docTemplate->moduleName['executionQualityReport'] = 'execution quality report'; +$lang->docTemplate->moduleName['personalWorkPlan'] = 'personal work plan'; +$lang->docTemplate->moduleName['personalWorkSummaryReport'] = 'personal work summary report'; +$lang->docTemplate->moduleName['personalValueAnalysisReport'] = 'personal value analysis report'; From 7aedc158a2956f6fadbead2854900a75819f386b Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 09:59:25 +0800 Subject: [PATCH 021/655] * [task#131755,doing,0.3h] show module tree of template type. --- module/doc/model.php | 15 +++++++++++++++ module/doc/ui/browsetemplate.html.php | 1 + 2 files changed, 16 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 614244272e..d7b29238e3 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3671,4 +3671,19 @@ class docModel extends model } return true; } + + /** + * 获取文档模板类型的模块。 + * Get modules of doc template type. + * + * @access public + * @return array + */ + public function getTemplateModules() + { + return $this->dao->select('*')->from(TABLE_MODULE) + ->where('deleted')->eq('0') + ->andWhere('type')->eq('docTemplate') + ->fetchAll(); + } } diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 2f7cd0469f..d93c6e1474 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -15,6 +15,7 @@ $libID = $menu['id']; $data = array('spaceID' => $spaceID, 'docs' => array_values($templateList)); $data['spaces'][] = array('name' => $lang->doc->template, 'id' => $spaceID); foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); +$data['modules'] = $this->doc->getTemplateModules(); $privs = array(); From 796f00fdae3d4af4f5a4d2ade196d2ccde658afa Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 10:23:29 +0800 Subject: [PATCH 022/655] * [refac,0.1h] fix sonar. --- module/doc/model.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index d7b29238e3..9cbc6c3747 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3640,7 +3640,7 @@ class docModel extends model $module->parent = 0; $module->path = ''; $module->grade = 1; - $module->order = ++ $moduleOrder; + $module->order = $moduleOrder; $module->type = 'docTemplate'; $module->short = ucfirst($scope) . ' ' . $moduleKey; $this->dao->insert(TABLE_MODULE)->data($module)->exec(); @@ -3649,6 +3649,7 @@ class docModel extends model $moduleID = $this->dao->lastInsertID(); $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},")->where('id')->eq($moduleID)->exec(); + $moduleOrder = $moduleOrder + 10; $subModuleOrder = 10; foreach($subModuleList as $subModuleKey => $subModuleCode) { @@ -3658,7 +3659,7 @@ class docModel extends model $subModule->parent = $moduleID; $subModule->path = ''; $subModule->grade = 2; - $subModule->order = ++ $subModuleOrder; + $subModule->order = $subModuleOrder; $subModule->type = 'docTemplate'; $subModule->short = $subModuleCode; $this->dao->insert(TABLE_MODULE)->data($subModule)->exec(); @@ -3666,6 +3667,8 @@ class docModel extends model $subModuleID = $this->dao->lastInsertID(); $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},{$subModuleID},")->where('id')->eq($subModuleID)->exec(); + + $subModuleOrder = $subModuleOrder + 10; } } } From f93168578a61d28126b9a8a61845b31cdd44daee Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 7 Nov 2024 08:49:43 +0000 Subject: [PATCH 023/655] * [bug] fix lang. --- module/doc/lang/zh-cn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index cf92f11f0e..29045d838e 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -75,7 +75,7 @@ $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); $lang->docTemplate->id = '编号'; $lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequecy = '频率'; +$lang->docTemplate->frequency = '频率'; $lang->docTemplate->type = '类型'; $lang->docTemplate->addedBy = '创建者'; $lang->docTemplate->addedDate = '创建时间'; From 46f023143ff9c4e7649e1b64446dab7cfcb303ad Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 8 Nov 2024 02:26:11 +0000 Subject: [PATCH 024/655] * [task#131752,done,1h] Add create template button. --- module/doc/js/browsetemplate.ui.js | 20 +++++++++++++++++++- module/doc/ui/browsetemplate.html.php | 4 +++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 5b5daf85d5..4020a54046 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -33,6 +33,23 @@ function getTableOptions(options, info) return options; } +const customRenders = +{ + /** + * 定义 API 文档列表工具栏渲染。 + * Define the API doc list toolbar render. + */ + toolbar: function() + { + if(this.mode === 'list') + { + const items = []; + items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', 'data-toggle': 'modal', 'data-size': 'lg', url: $.createLink('doc', 'createTemplate')}); + return {component: 'toolbar', props: {items: items}}; + } + } +} + /** * 重写文档应用的配置选项方法。 * Override the method to set the doc app options. @@ -43,7 +60,8 @@ window.setDocAppOptions = function(_, options) // Override the method. options = window._setDocAppOptions(_, options); return $.extend(options, { - getTableOptions : getTableOptions + getTableOptions : getTableOptions, + customRenders : customRenders }); }; diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index d93c6e1474..429a88a6e0 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -39,6 +39,7 @@ $langData['tableCols'] = $tableCols; $langData['create'] = $lang->docTemplate->create; $langData['edit'] = $lang->docTemplate->edit; $langData['delete'] = $lang->docTemplate->delete; +$langData['createTemplate'] = $lang->docTemplate->create; $langData['editTemplate'] = $lang->docTemplate->edit; $langData['deleteTemplate'] = $lang->docTemplate->delete; $langData['confirmDelete'] = $lang->docTemplate->confirmDelete; @@ -57,7 +58,8 @@ docApp set::userMap($users), set::spaceIcon('home'), set::langData($langData), - set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)) + set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)), + set('$options', jsRaw('window.setDocAppOptions')) ); render(); From 763ad96ba6acb7025cc9cfa1ec368d163df82cdc Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 11:02:20 +0800 Subject: [PATCH 025/655] * [task#131755,doing,0.1h] change module.short from varchar(30) to 60. --- db/update21.0.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 db/update21.0.sql diff --git a/db/update21.0.sql b/db/update21.0.sql new file mode 100644 index 0000000000..1bbd9a3916 --- /dev/null +++ b/db/update21.0.sql @@ -0,0 +1 @@ +ALTER TABLE zt_module MODIFY COLUMN short varchar(60); From 248979bfe9ba7dadfcf1514181232c952a5472bc Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 8 Nov 2024 05:50:31 +0000 Subject: [PATCH 026/655] * [misc] fix viewModelUrl. --- module/doc/config.php | 8 ++++---- module/doc/control.php | 12 +++++------- module/doc/ui/browsetemplate.html.php | 4 +++- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/module/doc/config.php b/module/doc/config.php index 6ccfbe464c..d465ba594c 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -123,10 +123,10 @@ $config->doc->quickMenu['collect'] = array('id' => 3, 'name' => $lang->doc->my $config->doc->quickMenu['editedby'] = array('id' => 4, 'name' => $lang->doc->myEdited); $config->doc->templateMenu = array(); -$config->doc->templateMenu['product'] = array('id' => 1, 'scope' => 'product', 'name' => $lang->docTemplate->scopes['product']); -$config->doc->templateMenu['project'] = array('id' => 2, 'scope' => 'project', 'name' => $lang->docTemplate->scopes['project']); -$config->doc->templateMenu['execution'] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->docTemplate->scopes['execution']); -$config->doc->templateMenu['personal'] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->docTemplate->scopes['personal']); +$config->doc->templateMenu[1] = array('id' => 1, 'scope' => 'product', 'name' => $lang->docTemplate->scopes['product']); +$config->doc->templateMenu[2] = array('id' => 2, 'scope' => 'project', 'name' => $lang->docTemplate->scopes['project']); +$config->doc->templateMenu[3] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->docTemplate->scopes['execution']); +$config->doc->templateMenu[4] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->docTemplate->scopes['personal']); $config->doc->templateModule = array(); $config->doc->templateModule['product'] = array(); diff --git a/module/doc/control.php b/module/doc/control.php index 309320dd87..88febfb719 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -315,7 +315,7 @@ class doc extends control * 文档模板列表。 * Browse template list. * - * @param string $scope + * @param int $libID * @param string $type * @param int $docID * @param string $orderBy @@ -325,10 +325,9 @@ class doc extends control * @access public * @return void */ - public function browseTemplate(string $scope = '', string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1) + public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1) { - if(!isset($this->config->doc->templateMenu[$scope])) $scope = 'product'; - $menu = $this->config->doc->templateMenu[$scope]; + if(!isset($this->config->doc->templateMenu[$libID])) $libID = 1; $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); @@ -337,12 +336,11 @@ class doc extends control foreach($templateList as $template) { $template->originLib = $template->lib; - $template->lib = $menu['id']; + $template->lib = $libID; } $this->view->title = $this->lang->doc->template; - $this->view->menu = $menu; - $this->view->scope = $scope; + $this->view->libID = $libID; $this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter'); $this->view->templateList = $templateList; $this->view->docID = $docID; diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 429a88a6e0..fa0a7023c3 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -11,7 +11,6 @@ declare(strict_types=1); namespace zin; $spaceID = 1; -$libID = $menu['id']; $data = array('spaceID' => $spaceID, 'docs' => array_values($templateList)); $data['spaces'][] = array('name' => $lang->doc->template, 'id' => $spaceID); foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); @@ -44,6 +43,8 @@ $langData['editTemplate'] = $lang->docTemplate->edit; $langData['deleteTemplate'] = $lang->docTemplate->delete; $langData['confirmDelete'] = $lang->docTemplate->confirmDelete; +$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}'); + docApp ( set::data($data), @@ -58,6 +59,7 @@ docApp set::userMap($users), set::spaceIcon('home'), set::langData($langData), + set::viewModeUrl($viewModeUrl), set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)), set('$options', jsRaw('window.setDocAppOptions')) ); From 755799b074e147aeac4d40e9a01f69c13cf488bc Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Fri, 8 Nov 2024 14:28:41 +0800 Subject: [PATCH 027/655] *[task#131751,2h,done]. --- module/doc/js/browsetemplate.ui.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 4020a54046..46b891e7e7 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -10,8 +10,18 @@ function getTableOptions(options, info) { const lang = getDocAppLang(); - options.cols = options.cols.filter(col => col.name !== 'collects'); + templateCols = []; + templateCols.push(options.cols.find(col => col.name == 'id')); + templateCols.push(options.cols.find(col => col.name == 'title')); + templateCols.push({name: 'type', title: lang.tableCols.type, type: 'string', sort: true}); + templateCols.push(options.cols.find(col => col.name == 'addedBy')); + templateCols.push(options.cols.find(col => col.name == 'addedDate')); + templateCols.push(options.cols.find(col => col.name == 'editedBy')); + templateCols.push(options.cols.find(col => col.name == 'editedDate')); + templateCols.push({name: 'views', title: lang.tableCols.views, type: 'number', sort: true}); + templateCols.push(options.cols.find(col => col.name == 'actions')); + options.cols = templateCols; options.cols.forEach(col => { if(col.name === 'actions' && col.actionsMap) From 89bf400bb6dc091ad39161fb743a2b6ae40ea9da Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Fri, 8 Nov 2024 14:51:27 +0800 Subject: [PATCH 028/655] +[task#131753,done,1h]. --- module/doc/control.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index 88febfb719..cfaa6cc902 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -574,6 +574,26 @@ class doc extends control return $this->sendSuccess(array('load' => $this->session->docList ? $this->session->docList : $this->createLink('doc', 'index'))); } + /** + * 删除一个文档模板。 + * Delete a doctemplate. + * + * @param int $templateID + * @access public + * @return void + */ + public function deleteTemplate(int $templateID) + { + $this->doc->delete(TABLE_DOC, $templateID); + + /* Delete template files. */ + $template = $this->doc->getByID($templateID); + if($template->files) $this->doc->deleteFiles(array_keys($template->files)); + + if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->sendSuccess(array()); + } + /** * 收藏一个文档。 * Collect a doc. From 7c4e546f7df80a9d344b38cbfe471a119fb01eb8 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 15:03:02 +0800 Subject: [PATCH 029/655] * [task#131756,doing,0.2h] add lang. --- module/doc/lang/de.php | 5 +++++ module/doc/lang/en.php | 5 +++++ module/doc/lang/fr.php | 5 +++++ module/doc/lang/zh-cn.php | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index eeb4ba37a4..3e82179c76 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -88,6 +88,11 @@ $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; $lang->docTemplate->delete = 'Delete Template'; +$lang->docTemplate->addModule = 'Add Template type'; +$lang->docTemplate->addSubModule = 'Add Sub Template type'; +$lang->docTemplate->editModule = 'Edit Template type'; +$lang->docTemplate->deleteModule = 'Delete Template type'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = 'Product'; $lang->docTemplate->scopes['project'] = 'Project'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index e970707f0b..f1588ecc3c 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -88,6 +88,11 @@ $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; $lang->docTemplate->delete = 'Delete Template'; +$lang->docTemplate->addModule = 'Add Template type'; +$lang->docTemplate->addSubModule = 'Add Sub Template type'; +$lang->docTemplate->editModule = 'Edit Template type'; +$lang->docTemplate->deleteModule = 'Delete Template type'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = 'Product'; $lang->docTemplate->scopes['project'] = 'Project'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 55bb4743a7..e7d091ae7a 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -88,6 +88,11 @@ $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; $lang->docTemplate->delete = 'Delete Template'; +$lang->docTemplate->addModule = 'Add Template type'; +$lang->docTemplate->addSubModule = 'Add Sub Template type'; +$lang->docTemplate->editModule = 'Edit Template type'; +$lang->docTemplate->deleteModule = 'Delete Template type'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = 'Product'; $lang->docTemplate->scopes['project'] = 'Project'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 29045d838e..c9d7716b51 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -88,6 +88,11 @@ $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; $lang->docTemplate->delete = '删除模板'; +$lang->docTemplate->addModule = '添加同级类型'; +$lang->docTemplate->addSubModule = '添加子类型'; +$lang->docTemplate->editModule = '编辑类型'; +$lang->docTemplate->deleteModule = '删除类型'; + $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes['product'] = '产品'; $lang->docTemplate->scopes['project'] = '项目'; From 03418ffa7f91218a1d6f1d569d068bf64fac2fba Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 15:04:14 +0800 Subject: [PATCH 030/655] * [task#131756,doing,0.1h] assign lang to ui. --- module/doc/ui/browsetemplate.html.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index fa0a7023c3..2ce61ae3d7 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -42,6 +42,10 @@ $langData['createTemplate'] = $lang->docTemplate->create; $langData['editTemplate'] = $lang->docTemplate->edit; $langData['deleteTemplate'] = $lang->docTemplate->delete; $langData['confirmDelete'] = $lang->docTemplate->confirmDelete; +$langData['addModule'] = $lang->docTemplate->addModule; +$langData['addSubModule'] = $lang->docTemplate->addSubModule; +$langData['editModule'] = $lang->docTemplate->editModule; +$langData['deleteModule'] = $lang->docTemplate->deleteModule; $viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}'); From ec16cd16b3a3a0957c660d2eae659c871dbbd71b Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 8 Nov 2024 15:05:21 +0800 Subject: [PATCH 031/655] * [task#131756,doing,0.5h] add button to doc template's module tree. --- module/doc/js/browsetemplate.ui.js | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 46b891e7e7..d264b3f12f 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -60,6 +60,43 @@ const customRenders = } } +/** + * 定义文档模板各个视图和 UI 元素的上的操作方法。 + * Define the operation methods on the views and UI elements of the doc template. + */ +const actionsMap = +{ + /** + * 定义分组的操作按钮。 + * Define the actions on the type group. + */ + module: function(info) + { + const items = []; + const module = info.data; + + items.push({text: getDocAppLang('addModule'), command: `addModule/${module.lib}`}); + if(module.grade == 1) items.push({text: getDocAppLang('addSubModule'), command: `addSubModule/${module.id}`}); + items.push({text: getDocAppLang('editModule'), command: `editModule/${module.id}`}); + items.push({text: getDocAppLang('deleteModule'), command: `deleteModule/${module.id}`}); + + if(info.ui === 'sidebar') + { + return [ + items.length ? {icon: 'ellipsis-v', caret: false, placement: 'bottom-end', size: 'xs', items: items} : null, + ]; + } + + return items; + }, +}; + +function getActions(type, info) +{ + const builder = actionsMap[type]; + if(builder) return builder.call(this, info); +} + /** * 重写文档应用的配置选项方法。 * Override the method to set the doc app options. @@ -71,6 +108,7 @@ window.setDocAppOptions = function(_, options) // Override the method. return $.extend(options, { getTableOptions : getTableOptions, + getActions : getActions, customRenders : customRenders }); }; From 94aa7b404186a4123a33877c5e7850eb844bcf1c Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 8 Nov 2024 07:20:56 +0000 Subject: [PATCH 032/655] * [story#68004,1h] add create modal. --- module/doc/control.php | 5 +++-- module/doc/js/browsetemplate.ui.js | 16 +++++++++++++++- module/doc/ui/browsetemplate.html.php | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index cfaa6cc902..b72c6cc5b2 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -325,7 +325,7 @@ class doc extends control * @access public * @return void */ - public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1) + public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') { if(!isset($this->config->doc->templateMenu[$libID])) $libID = 1; @@ -347,6 +347,7 @@ class doc extends control $this->view->orderBy = $orderBy; $this->view->recPerPage = $recPerPage; $this->view->pageID = $pageID; + $this->view->mode = $mode; $this->display(); } @@ -1736,7 +1737,7 @@ class doc extends control if(empty($docID)) { if(empty($objectID) && $lib) $objectID = $this->doc->getObjectIDByLib($lib); - if($lib) $objectType = $lib->type; + if($lib && $objectType != 'template') $objectType = $lib->type; $unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : ''; $libPairs = $this->doc->getLibs($objectType, "{$unclosed}", $libID, $objectID); diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index d264b3f12f..c8882bb369 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -54,7 +54,10 @@ const customRenders = if(this.mode === 'list') { const items = []; - items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', 'data-toggle': 'modal', 'data-size': 'lg', url: $.createLink('doc', 'createTemplate')}); + const {libID, filterType, docID, orderBy, pager, mode} = this.location; + const {recTotal, recPerPage, pageID} = pager; + const url = $.createLink('doc', 'browseTemplate', `libID=${libID}&filterType=${filterType}&docID=${docID}&orderBy=${orderBy}&recTotal=${recTotal}&recPerPage=${recPerPage}&pageID=${pageID}&mode=create`); + items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', url: url}); return {component: 'toolbar', props: {items: items}}; } } @@ -146,5 +149,16 @@ $.extend(window.docAppCommands, getDocApp().delete('doc', templateID); } }) + }, + saveNewDoc: function(_, args) + { + const docApp = getDocApp(); + const spaceType = docApp.spaceType; + const spaceID = docApp.spaceID; + const libID = docApp.libID; + const moduleID = docApp.moduleID; + const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=0&isDraft=no`); + zui.Modal.open({url: url}); + return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); } }); diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 2ce61ae3d7..71eac42e59 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -47,7 +47,7 @@ $langData['addSubModule'] = $lang->docTemplate->addSubModule; $langData['editModule'] = $lang->docTemplate->editModule; $langData['deleteModule'] = $lang->docTemplate->deleteModule; -$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}'); +$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); docApp ( @@ -58,7 +58,7 @@ docApp set::noSpace(), set::noModule(), set::homeName(false), - set::mode($docID ? 'view' : 'list'), + set::mode($mode), set::privs($privs), set::userMap($users), set::spaceIcon('home'), From 8810d713a28a7ff40a72c6e67ed32426e62f5eab Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Fri, 8 Nov 2024 15:23:35 +0800 Subject: [PATCH 033/655] *[misc] add templatehome and templatelist page. --- module/doc/ui/browsetemplate.html.php | 61 +---------------------- module/doc/ui/templatehome.html.php | 0 module/doc/ui/templatelist.html.php | 71 +++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 59 deletions(-) create mode 100644 module/doc/ui/templatehome.html.php create mode 100644 module/doc/ui/templatelist.html.php diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 71eac42e59..6454e1c814 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -10,62 +10,5 @@ declare(strict_types=1); */ namespace zin; -$spaceID = 1; -$data = array('spaceID' => $spaceID, 'docs' => array_values($templateList)); -$data['spaces'][] = array('name' => $lang->doc->template, 'id' => $spaceID); -foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); -$data['modules'] = $this->doc->getTemplateModules(); - -$privs = array(); - -$filterTypes = $lang->docTemplate->filterTypes; -if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); - -$tableCols = array(); -$tableCols['id'] = $lang->docTemplate->id; -$tableCols['title'] = $lang->docTemplate->title; -$tableCols['frequency'] = $lang->docTemplate->frequency; -$tableCols['type'] = $lang->docTemplate->type; -$tableCols['addedBy'] = $lang->docTemplate->addedBy; -$tableCols['addedDate'] = $lang->docTemplate->addedDate; -$tableCols['editedBy'] = $lang->docTemplate->editedBy; -$tableCols['editedDate'] = $lang->docTemplate->editedDate; -$tableCols['views'] = $lang->docTemplate->views; - -$langData = array(); -$langData['filterTypes'] = $filterTypes; -$langData['tableCols'] = $tableCols; -$langData['create'] = $lang->docTemplate->create; -$langData['edit'] = $lang->docTemplate->edit; -$langData['delete'] = $lang->docTemplate->delete; -$langData['createTemplate'] = $lang->docTemplate->create; -$langData['editTemplate'] = $lang->docTemplate->edit; -$langData['deleteTemplate'] = $lang->docTemplate->delete; -$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; -$langData['addModule'] = $lang->docTemplate->addModule; -$langData['addSubModule'] = $lang->docTemplate->addSubModule; -$langData['editModule'] = $lang->docTemplate->editModule; -$langData['deleteModule'] = $lang->docTemplate->deleteModule; - -$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); - -docApp -( - set::data($data), - set::spaceID($spaceID), - set::libID($libID), - set::docID($docID), - set::noSpace(), - set::noModule(), - set::homeName(false), - set::mode($mode), - set::privs($privs), - set::userMap($users), - set::spaceIcon('home'), - set::langData($langData), - set::viewModeUrl($viewModeUrl), - set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)), - set('$options', jsRaw('window.setDocAppOptions')) -); - -render(); +if($libID) include './templatelist.html.php'; +else include './templatehome.html.php'; diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php new file mode 100644 index 0000000000..e69de29bb2 diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php new file mode 100644 index 0000000000..2ce61ae3d7 --- /dev/null +++ b/module/doc/ui/templatelist.html.php @@ -0,0 +1,71 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; + +$spaceID = 1; +$data = array('spaceID' => $spaceID, 'docs' => array_values($templateList)); +$data['spaces'][] = array('name' => $lang->doc->template, 'id' => $spaceID); +foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); +$data['modules'] = $this->doc->getTemplateModules(); + +$privs = array(); + +$filterTypes = $lang->docTemplate->filterTypes; +if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); + +$tableCols = array(); +$tableCols['id'] = $lang->docTemplate->id; +$tableCols['title'] = $lang->docTemplate->title; +$tableCols['frequency'] = $lang->docTemplate->frequency; +$tableCols['type'] = $lang->docTemplate->type; +$tableCols['addedBy'] = $lang->docTemplate->addedBy; +$tableCols['addedDate'] = $lang->docTemplate->addedDate; +$tableCols['editedBy'] = $lang->docTemplate->editedBy; +$tableCols['editedDate'] = $lang->docTemplate->editedDate; +$tableCols['views'] = $lang->docTemplate->views; + +$langData = array(); +$langData['filterTypes'] = $filterTypes; +$langData['tableCols'] = $tableCols; +$langData['create'] = $lang->docTemplate->create; +$langData['edit'] = $lang->docTemplate->edit; +$langData['delete'] = $lang->docTemplate->delete; +$langData['createTemplate'] = $lang->docTemplate->create; +$langData['editTemplate'] = $lang->docTemplate->edit; +$langData['deleteTemplate'] = $lang->docTemplate->delete; +$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; +$langData['addModule'] = $lang->docTemplate->addModule; +$langData['addSubModule'] = $lang->docTemplate->addSubModule; +$langData['editModule'] = $lang->docTemplate->editModule; +$langData['deleteModule'] = $lang->docTemplate->deleteModule; + +$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}'); + +docApp +( + set::data($data), + set::spaceID($spaceID), + set::libID($libID), + set::docID($docID), + set::noSpace(), + set::noModule(), + set::homeName(false), + set::mode($docID ? 'view' : 'list'), + set::privs($privs), + set::userMap($users), + set::spaceIcon('home'), + set::langData($langData), + set::viewModeUrl($viewModeUrl), + set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)), + set('$options', jsRaw('window.setDocAppOptions')) +); + +render(); From 3f2bfa0fab11b0cae94094dac3eab9f2874a90eb Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 8 Nov 2024 09:50:01 +0000 Subject: [PATCH 034/655] * [misc] Use edit doc and delete doc command. --- module/doc/control.php | 4 ++-- module/doc/js/browsetemplate.ui.js | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index b72c6cc5b2..57441f28d9 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -335,8 +335,8 @@ class doc extends control $templateList = $this->doc->getDocTemplateList($type, $orderBy, $pager); foreach($templateList as $template) { - $template->originLib = $template->lib; - $template->lib = $libID; + $template->originLib = $template->lib; + $template->lib = $libID; } $this->view->title = $this->lang->doc->template; diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index c8882bb369..58b34b49c0 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -33,10 +33,7 @@ function getTableOptions(options, info) $.each(col.actionsMap, (key, value) => { if(typeof actionHints[key] === 'string') value.hint = actionHints[key]; - if(key == 'edit') value.command = 'editTemplate/{id}'; - if(key == 'delete') value.command = 'deleteTemplate/{id}'; }); - } }); From af8f6e3cf114c7365bc007f13a207bf49786d90d Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 09:36:32 +0800 Subject: [PATCH 035/655] * [task#131758,doing,0.2h] add lang. --- module/doc/lang/de.php | 24 ++++++++++++++---------- module/doc/lang/en.php | 24 ++++++++++++++---------- module/doc/lang/fr.php | 24 ++++++++++++++---------- module/doc/lang/zh-cn.php | 24 ++++++++++++++---------- 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 3e82179c76..301f01a431 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -73,16 +73,20 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index f1588ecc3c..3e5a5b017e 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -73,16 +73,20 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index e7d091ae7a..1cca380431 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -73,16 +73,20 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index c9d7716b51..7948c59b42 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -73,16 +73,20 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = '编号'; -$lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequency = '频率'; -$lang->docTemplate->type = '类型'; -$lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建时间'; -$lang->docTemplate->editedBy = '最后修改者'; -$lang->docTemplate->editedDate = '最后修改时间'; -$lang->docTemplate->views = '阅读次数'; -$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequency = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建时间'; +$lang->docTemplate->editedBy = '最后修改者'; +$lang->docTemplate->editedDate = '最后修改时间'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->scope = '范围'; +$lang->docTemplate->parentModule = '上级类型'; +$lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; From d950612060e4811401db76fb84777fedaab9ecb4 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 09:37:44 +0800 Subject: [PATCH 036/655] * [task#131758,doing,0.5h] add command of edit module. --- module/doc/js/browsetemplate.ui.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 58b34b49c0..00b558c8da 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -97,6 +97,21 @@ function getActions(type, info) if(builder) return builder.call(this, info); } +/** + * 定义界面操作命令。 + * Define the UI commands. + */ +const commands = +{ + editModule: function(_, args) + { + const docApp = getDocApp(); + const moduleID = args[0] || docApp.moduleID; + const url = $.createLink('doc', 'editTemplateType', `moduleID=${moduleID}`); + zui.Modal.open({size: 'sm', url: url}); + }, +}; + /** * 重写文档应用的配置选项方法。 * Override the method to set the doc app options. @@ -107,6 +122,7 @@ window.setDocAppOptions = function(_, options) // Override the method. options = window._setDocAppOptions(_, options); return $.extend(options, { + commands : commands, getTableOptions : getTableOptions, getActions : getActions, customRenders : customRenders From 5d021ba1d2f4034b4779b252e6d8d74df97a35e4 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 09:41:32 +0800 Subject: [PATCH 037/655] * [task#131758,doing,1h] add edit template page. --- module/doc/control.php | 14 ++++++++++++ module/tree/control.php | 42 ++++++++++++++++++++++++------------ module/tree/ui/edit.html.php | 12 +++++------ 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 57441f28d9..b570c928e0 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -351,6 +351,20 @@ class doc extends control $this->display(); } + + /** + * 编辑一个模板类型。 + * Edit a template type. + * + * @param int $moduleID + * @access public + * @return void + */ + public function editTemplateType(int $moduleID) + { + echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type=docTemplate"); + } + /** * 上传文档。 * Upload docs. diff --git a/module/tree/control.php b/module/tree/control.php index aa0b57d77b..03191531e5 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -187,31 +187,45 @@ class tree extends control $this->view->libs = $this->doc->getLibs($docLib->type, '', '', $objectID, 'book'); } - if($type == 'doc' || $type == 'api') + if($type == 'docTemplate') { - $name = $this->lang->tree->dir; - $title = $this->lang->tree->editDir; + $name = $this->lang->docTemplate->typeName; + $title = $this->lang->docTemplate->editTemplateType; + $parentLabel = $this->lang->docTemplate->parentModule; + + $scopes = array(); + foreach($this->config->doc->templateMenu as $scopeID => $scope) $scopes[$scopeID] = $scope['name']; + $this->view->scopes = $scopes; + } + elseif($type == 'doc' || $type == 'api') + { + $name = $this->lang->tree->dir; + $title = $this->lang->tree->editDir; + $parentLabel = $this->lang->tree->parentCate; } elseif($type == 'line') { - $name = $this->lang->tree->line; - $title = $this->lang->tree->manageLine; + $name = $this->lang->tree->line; + $title = $this->lang->tree->manageLine; + $parentLabel = $this->lang->tree->parent; } else { - $name = $this->lang->tree->name; - $title = $this->lang->tree->edit; + $name = $this->lang->tree->name; + $title = $this->lang->tree->edit; + $parentLabel = $this->lang->tree->parent; } if($type == 'host') $this->app->loadLang('host'); - $this->view->name = $name; - $this->view->title = $title; - $this->view->title = $type == 'host' ? $this->lang->host->groupMaintenance : $title; - $this->view->module = $module; - $this->view->type = $type; - $this->view->branch = $branch; - $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted', $module->owner); + $this->view->name = $name; + $this->view->title = $title; + $this->view->title = $type == 'host' ? $this->lang->host->groupMaintenance : $title; + $this->view->parentLabel = $parentLabel; + $this->view->module = $module; + $this->view->type = $type; + $this->view->branch = $branch; + $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted', $module->owner); $showProduct = strpos('story|bug|case', $type) !== false ? true : false; if($showProduct) diff --git a/module/tree/ui/edit.html.php b/module/tree/ui/edit.html.php index ba5c87cddf..3bd38e4107 100644 --- a/module/tree/ui/edit.html.php +++ b/module/tree/ui/edit.html.php @@ -58,14 +58,14 @@ formPanel ) ) ) : null, - $type == 'doc' ? formGroup + ($type == 'doc' || $type == 'docTemplate') ? formGroup ( - set::label($lang->doc->lib), + set::label($type == 'docTemplate' ? $lang->docTemplate->scope : $lang->doc->lib), picker ( set::name('root'), set::value($module->root), - set::items($libs), + set::items($type == 'docTemplate' ? $scopes : $libs), set::required(true), on::change('changeRoot') ) @@ -82,7 +82,7 @@ formPanel $module->type != 'line' ? formGroup ( set::className('moduleBox ', $hidden ? 'hidden' : ''), - set::label(($type == 'doc' or $type == 'api') ? $lang->tree->parentCate : $lang->tree->parent), + set::label($parentLabel), picker ( set::name('parent'), @@ -102,7 +102,7 @@ formPanel set::items($users) ) ) : null, - formGroup + $type != 'docTemplate' ? formGroup ( set::label($lang->tree->short), inputControl @@ -113,5 +113,5 @@ formPanel set::value($module->short) ) ) - ) + ) : null ); From 7abf8585f3da5cbd2608f2da4bc18bdb695e4e6d Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 09:42:21 +0800 Subject: [PATCH 038/655] * [task#131758,doing,0.5h] ajax load parent type by scope. --- module/tree/js/edit.ui.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/module/tree/js/edit.ui.js b/module/tree/js/edit.ui.js index 5bed556104..02a55c8c94 100644 --- a/module/tree/js/edit.ui.js +++ b/module/tree/js/edit.ui.js @@ -46,17 +46,24 @@ function changeRoot() var confirmRoot = type == 'doc' ? confirmRoot4Doc : confirmRoot; if(moduleRoot != root) { - zui.Modal.confirm(confirmRoot).then(result => + if(type == 'docTemplate') { - if(result) + ajaxLoadModules(root, 0, 'docTemplate', moduleID); + } + else + { + zui.Modal.confirm(confirmRoot).then(result => { - ajaxLoadModules(root, 0, type != 'doc' ? 'story' : type, moduleID); - } - else - { - $('[name=root]').zui('picker').$.setValue(moduleRoot); - } - }); + if(result) + { + ajaxLoadModules(root, 0, type != 'doc' ? 'story' : type, moduleID); + } + else + { + $('[name=root]').zui('picker').$.setValue(moduleRoot); + } + }); + } } else { From 921c313057189ef800a0c622b0116b7950ee0e38 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 10:15:25 +0800 Subject: [PATCH 039/655] * [task#131758,doing,0.5h] disabled form item when edit builtin module. --- module/doc/model.php | 28 ++++++++++++++++++++++++++++ module/tree/ui/edit.html.php | 3 +++ 2 files changed, 31 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 9cbc6c3747..7442a36744 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3689,4 +3689,32 @@ class docModel extends model ->andWhere('type')->eq('docTemplate') ->fetchAll(); } + + /** + * 判断一个模块是否是内置的文档模板类型。 + * Judge whether a module is builtin template type. + * + * @param object $module + * @access public + * @return bool + */ + public function isBuiltinTemplateModule($module) + { + if(!$module->short || $module->type != 'docTemplate') return false; + + foreach($this->config->doc->templateModule as $scope => $moduleList) + { + foreach($moduleList as $moduleKey => $subModuleList) + { + if($module->short == ucfirst($scope) . ' ' . $moduleKey) return true; + + foreach($subModuleList as $subModuleKey => $subModuleCode) + { + if($module->short == $subModuleCode) return true; + } + } + } + + return false; + } } diff --git a/module/tree/ui/edit.html.php b/module/tree/ui/edit.html.php index 3bd38e4107..22f88c780d 100644 --- a/module/tree/ui/edit.html.php +++ b/module/tree/ui/edit.html.php @@ -21,6 +21,7 @@ jsVar('type', $type); /* zin: Set variables to define control for form. */ $hidden = $type != 'story' && $module->type == 'story'; +$isBuiltinTemplateModule = $type == 'docTemplate' && $this->loadModel('doc')->isBuiltinTemplateModule($module); /* ====== Define the page structure with zin widgets ====== */ modalHeader(set::title($title)); @@ -63,6 +64,7 @@ formPanel set::label($type == 'docTemplate' ? $lang->docTemplate->scope : $lang->doc->lib), picker ( + set::disabled($isBuiltinTemplateModule), set::name('root'), set::value($module->root), set::items($type == 'docTemplate' ? $scopes : $libs), @@ -85,6 +87,7 @@ formPanel set::label($parentLabel), picker ( + set::disabled($isBuiltinTemplateModule), set::name('parent'), set::value($module->parent), set::items($optionMenu), From 08a78abd95947994085a7633ff035f926bb5e656 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 10:25:58 +0800 Subject: [PATCH 040/655] * [task#131758,doing,0.2h] show grade 1 type when edit template type. --- module/tree/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/tree/control.php b/module/tree/control.php index 03191531e5..c3da14b6f5 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -177,7 +177,7 @@ class tree extends control } elseif($type != 'chart') { - $this->view->optionMenu = $this->tree->getOptionMenu($module->root, $module->type, 0, (string)$module->branch, 'noMainBranch|nodeleted'); + $this->view->optionMenu = $this->tree->getOptionMenu($module->root, $module->type, 0, (string)$module->branch, 'noMainBranch|nodeleted', $type == 'docTemplate' ? '1' : 'all'); } if($type == 'doc') From 1366e1b1694261e7474718406ea08d19708960bc Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 8 Nov 2024 08:02:19 +0000 Subject: [PATCH 041/655] * [story#68004,1h] add lang. --- module/doc/lang/de.php | 10 ++++++---- module/doc/lang/en.php | 10 ++++++---- module/doc/lang/fr.php | 10 ++++++---- module/doc/lang/zh-cn.php | 12 +++++++----- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 301f01a431..9775df110b 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -84,6 +84,8 @@ $lang->docTemplate->editedDate = 'Edited Date'; $lang->docTemplate->views = 'Views'; $lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; $lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->editTemplateType = 'Edit template type'; @@ -98,10 +100,10 @@ $lang->docTemplate->editModule = 'Edit Template type'; $lang->docTemplate->deleteModule = 'Delete Template type'; $lang->docTemplate->scopes = array(); -$lang->docTemplate->scopes['product'] = 'Product'; -$lang->docTemplate->scopes['project'] = 'Project'; -$lang->docTemplate->scopes['execution'] = 'Execution'; -$lang->docTemplate->scopes['personal'] = 'Personal'; +$lang->docTemplate->scopes[1] = 'Product'; +$lang->docTemplate->scopes[2] = 'Project'; +$lang->docTemplate->scopes[3] = 'Execution'; +$lang->docTemplate->scopes[4] = 'Personal'; $lang->docTemplate->filterTypes = array(); $lang->docTemplate->filterTypes[] = array('all', 'All'); diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 3e5a5b017e..6cc1caba21 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -84,6 +84,8 @@ $lang->docTemplate->editedDate = 'Edited Date'; $lang->docTemplate->views = 'Views'; $lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; $lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->editTemplateType = 'Edit template type'; @@ -98,10 +100,10 @@ $lang->docTemplate->editModule = 'Edit Template type'; $lang->docTemplate->deleteModule = 'Delete Template type'; $lang->docTemplate->scopes = array(); -$lang->docTemplate->scopes['product'] = 'Product'; -$lang->docTemplate->scopes['project'] = 'Project'; -$lang->docTemplate->scopes['execution'] = 'Execution'; -$lang->docTemplate->scopes['personal'] = 'Personal'; +$lang->docTemplate->scopes[1] = 'Product'; +$lang->docTemplate->scopes[2] = 'Project'; +$lang->docTemplate->scopes[3] = 'Execution'; +$lang->docTemplate->scopes[4] = 'Personal'; $lang->docTemplate->filterTypes = array(); $lang->docTemplate->filterTypes[] = array('all', 'All'); diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 1cca380431..a5f5b0bba5 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -84,6 +84,8 @@ $lang->docTemplate->editedDate = 'Edited Date'; $lang->docTemplate->views = 'Views'; $lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; $lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->editTemplateType = 'Edit template type'; @@ -98,10 +100,10 @@ $lang->docTemplate->editModule = 'Edit Template type'; $lang->docTemplate->deleteModule = 'Delete Template type'; $lang->docTemplate->scopes = array(); -$lang->docTemplate->scopes['product'] = 'Product'; -$lang->docTemplate->scopes['project'] = 'Project'; -$lang->docTemplate->scopes['execution'] = 'Execution'; -$lang->docTemplate->scopes['personal'] = 'Personal'; +$lang->docTemplate->scopes[1] = 'Product'; +$lang->docTemplate->scopes[2] = 'Project'; +$lang->docTemplate->scopes[3] = 'Execution'; +$lang->docTemplate->scopes[4] = 'Personal'; $lang->docTemplate->filterTypes = array(); $lang->docTemplate->filterTypes[] = array('all', 'All'); diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 7948c59b42..b5cfc3acf5 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -83,7 +83,9 @@ $lang->docTemplate->editedBy = '最后修改者'; $lang->docTemplate->editedDate = '最后修改时间'; $lang->docTemplate->views = '阅读次数'; $lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; -$lang->docTemplate->scope = '范围'; +$lang->docTemplate->scope = '所属范围'; +$lang->docTemplate->module = '模板类型'; +$lang->docTemplate->desc = '模板简介'; $lang->docTemplate->parentModule = '上级类型'; $lang->docTemplate->typeName = '类型名称'; $lang->docTemplate->editTemplateType = '编辑文档模板类型'; @@ -98,10 +100,10 @@ $lang->docTemplate->editModule = '编辑类型'; $lang->docTemplate->deleteModule = '删除类型'; $lang->docTemplate->scopes = array(); -$lang->docTemplate->scopes['product'] = '产品'; -$lang->docTemplate->scopes['project'] = '项目'; -$lang->docTemplate->scopes['execution'] = '执行'; -$lang->docTemplate->scopes['personal'] = '个人'; +$lang->docTemplate->scopes[1] = '产品'; +$lang->docTemplate->scopes[2] = '项目'; +$lang->docTemplate->scopes[3] = '执行'; +$lang->docTemplate->scopes[4] = '个人'; $lang->docTemplate->filterTypes = array(); $lang->docTemplate->filterTypes[] = array('all', '全部'); From dabf0a5f4632db37ab8bc185e5454439103fe1be Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 8 Nov 2024 08:03:07 +0000 Subject: [PATCH 042/655] * [story#68004,1h] fix scope id. --- module/doc/config.php | 148 ++++++++++---------- module/doc/js/browsetemplate.ui.js | 4 +- module/doc/model.php | 6 +- module/doc/ui/setdocbasic.html.php | 6 + module/doc/ui/setdocbasic.template.html.php | 35 +++++ 5 files changed, 120 insertions(+), 79 deletions(-) create mode 100644 module/doc/ui/setdocbasic.template.html.php diff --git a/module/doc/config.php b/module/doc/config.php index d465ba594c..ea84c408ee 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -123,94 +123,94 @@ $config->doc->quickMenu['collect'] = array('id' => 3, 'name' => $lang->doc->my $config->doc->quickMenu['editedby'] = array('id' => 4, 'name' => $lang->doc->myEdited); $config->doc->templateMenu = array(); -$config->doc->templateMenu[1] = array('id' => 1, 'scope' => 'product', 'name' => $lang->docTemplate->scopes['product']); -$config->doc->templateMenu[2] = array('id' => 2, 'scope' => 'project', 'name' => $lang->docTemplate->scopes['project']); -$config->doc->templateMenu[3] = array('id' => 3, 'scope' => 'execution', 'name' => $lang->docTemplate->scopes['execution']); -$config->doc->templateMenu[4] = array('id' => 4, 'scope' => 'personal', 'name' => $lang->docTemplate->scopes['personal']); +$config->doc->templateMenu[1] = array('id' => 1, 'name' => $lang->docTemplate->scopes[1]); +$config->doc->templateMenu[2] = array('id' => 2, 'name' => $lang->docTemplate->scopes[2]); +$config->doc->templateMenu[3] = array('id' => 3, 'name' => $lang->docTemplate->scopes[3]); +$config->doc->templateMenu[4] = array('id' => 4, 'name' => $lang->docTemplate->scopes[4]); $config->doc->templateModule = array(); -$config->doc->templateModule['product'] = array(); -$config->doc->templateModule['product']['plan'] = array(); -$config->doc->templateModule['product']['plan']['softwareProductPlan'] = 'Software product plan'; -$config->doc->templateModule['product']['plan']['hardwareProductPlan'] = 'Hardware product plan'; -$config->doc->templateModule['product']['plan']['qualityAssurancePlan'] = 'Quality assurance plan'; +$config->doc->templateModule[1] = array(); +$config->doc->templateModule[1]['plan'] = array(); +$config->doc->templateModule[1]['plan']['softwareProductPlan'] = 'Software product plan'; +$config->doc->templateModule[1]['plan']['hardwareProductPlan'] = 'Hardware product plan'; +$config->doc->templateModule[1]['plan']['qualityAssurancePlan'] = 'Quality assurance plan'; -$config->doc->templateModule['product']['desc'] = array(); -$config->doc->templateModule['product']['desc']['productDesign'] = 'Product design'; -$config->doc->templateModule['product']['desc']['requirementSpecification'] = 'Requirement specification'; -$config->doc->templateModule['product']['desc']['userManual'] = 'User manual'; +$config->doc->templateModule[1]['desc'] = array(); +$config->doc->templateModule[1]['desc']['productDesign'] = 'Product design'; +$config->doc->templateModule[1]['desc']['requirementSpecification'] = 'Requirement specification'; +$config->doc->templateModule[1]['desc']['userManual'] = 'User manual'; -$config->doc->templateModule['product']['report'] = array(); -$config->doc->templateModule['product']['report']['competitiveProductAnalysisReport'] = 'Competitive product analysis report'; -$config->doc->templateModule['product']['report']['productAcceptanceReport'] = 'Product acceptance report'; -$config->doc->templateModule['product']['report']['productSummaryReport'] = 'Product summary report'; -$config->doc->templateModule['product']['report']['productQualityReport'] = 'Product quality report'; +$config->doc->templateModule[1]['report'] = array(); +$config->doc->templateModule[1]['report']['competitiveProductAnalysisReport'] = 'Competitive product analysis report'; +$config->doc->templateModule[1]['report']['productAcceptanceReport'] = 'Product acceptance report'; +$config->doc->templateModule[1]['report']['productSummaryReport'] = 'Product summary report'; +$config->doc->templateModule[1]['report']['productQualityReport'] = 'Product quality report'; -$config->doc->templateModule['project'] = array(); -$config->doc->templateModule['project']['plan'] = array(); -$config->doc->templateModule['project']['plan']['projectPlan'] = 'Project plan'; -$config->doc->templateModule['project']['plan']['projectQualityAssurancePlan'] = 'Project quality assurance plan'; -$config->doc->templateModule['project']['plan']['projectConfigurationManagementPlan'] = 'Project configuration management plan'; -$config->doc->templateModule['project']['plan']['projectIntegrationTestPlan'] = 'Project integration test plan'; -$config->doc->templateModule['project']['plan']['projectSystemTestPlan'] = 'Project system test plan'; +$config->doc->templateModule[2] = array(); +$config->doc->templateModule[2]['plan'] = array(); +$config->doc->templateModule[2]['plan']['projectPlan'] = 'Project plan'; +$config->doc->templateModule[2]['plan']['projectQualityAssurancePlan'] = 'Project quality assurance plan'; +$config->doc->templateModule[2]['plan']['projectConfigurationManagementPlan'] = 'Project configuration management plan'; +$config->doc->templateModule[2]['plan']['projectIntegrationTestPlan'] = 'Project integration test plan'; +$config->doc->templateModule[2]['plan']['projectSystemTestPlan'] = 'Project system test plan'; -$config->doc->templateModule['project']['desc'] = array(); -$config->doc->templateModule['project']['desc']['businessRequirementsStatement'] = 'Business requirements statement'; -$config->doc->templateModule['project']['desc']['projectUserRequirementsSpecification'] = 'Project user requirements specification'; -$config->doc->templateModule['project']['desc']['projectSoftwareRequirementsSpecification'] = 'Project software requirements specification'; -$config->doc->templateModule['project']['desc']['projectSummaryDesignSpecification'] = 'Project summary design specification'; -$config->doc->templateModule['project']['desc']['projectDetailedDesignSpecification'] = 'Project detailed design specification'; -$config->doc->templateModule['project']['desc']['projectUserManual'] = 'Project user manual'; +$config->doc->templateModule[2]['desc'] = array(); +$config->doc->templateModule[2]['desc']['businessRequirementsStatement'] = 'Business requirements statement'; +$config->doc->templateModule[2]['desc']['projectUserRequirementsSpecification'] = 'Project user requirements specification'; +$config->doc->templateModule[2]['desc']['projectSoftwareRequirementsSpecification'] = 'Project software requirements specification'; +$config->doc->templateModule[2]['desc']['projectSummaryDesignSpecification'] = 'Project summary design specification'; +$config->doc->templateModule[2]['desc']['projectDetailedDesignSpecification'] = 'Project detailed design specification'; +$config->doc->templateModule[2]['desc']['projectUserManual'] = 'Project user manual'; -$config->doc->templateModule['project']['dev'] = array(); -$config->doc->templateModule['project']['dev']['projectCode'] = 'Project code'; -$config->doc->templateModule['project']['dev']['projectDatabaseDesignDocument'] = 'Project database design document'; -$config->doc->templateModule['project']['dev']['projectInterfaceDesignDocument'] = 'Project interface design document'; +$config->doc->templateModule[2]['dev'] = array(); +$config->doc->templateModule[2]['dev']['projectCode'] = 'Project code'; +$config->doc->templateModule[2]['dev']['projectDatabaseDesignDocument'] = 'Project database design document'; +$config->doc->templateModule[2]['dev']['projectInterfaceDesignDocument'] = 'Project interface design document'; -$config->doc->templateModule['project']['test'] = array(); -$config->doc->templateModule['project']['test']['projectIntegrationTestCases'] = 'Project integration test cases'; -$config->doc->templateModule['project']['test']['projectSystemTestCases'] = 'Project system test cases'; +$config->doc->templateModule[2]['test'] = array(); +$config->doc->templateModule[2]['test']['projectIntegrationTestCases'] = 'Project integration test cases'; +$config->doc->templateModule[2]['test']['projectSystemTestCases'] = 'Project system test cases'; -$config->doc->templateModule['project']['report'] = array(); -$config->doc->templateModule['project']['report']['projectProgressReport'] = 'Project progress report'; -$config->doc->templateModule['project']['report']['projectRiskReport'] = 'Project risk report'; -$config->doc->templateModule['project']['report']['projectAcceptanceReport'] = 'Project acceptance report'; -$config->doc->templateModule['project']['report']['projectSummaryReport'] = 'Project summary report'; -$config->doc->templateModule['project']['report']['projectQualityReport'] = 'Project quality report'; +$config->doc->templateModule[2]['report'] = array(); +$config->doc->templateModule[2]['report']['projectProgressReport'] = 'Project progress report'; +$config->doc->templateModule[2]['report']['projectRiskReport'] = 'Project risk report'; +$config->doc->templateModule[2]['report']['projectAcceptanceReport'] = 'Project acceptance report'; +$config->doc->templateModule[2]['report']['projectSummaryReport'] = 'Project summary report'; +$config->doc->templateModule[2]['report']['projectQualityReport'] = 'Project quality report'; -$config->doc->templateModule['project']['other'] = array(); +$config->doc->templateModule[2]['other'] = array(); -$config->doc->templateModule['execution'] = array(); -$config->doc->templateModule['execution']['plan'] = array(); -$config->doc->templateModule['execution']['plan']['executionDevelopmentPlan'] = 'Execution development plan'; -$config->doc->templateModule['execution']['plan']['executionQualityAssurancePlan'] = 'Execution quality assurance plan'; -$config->doc->templateModule['execution']['plan']['executionTestPlan'] = 'Execution test plan'; +$config->doc->templateModule[3] = array(); +$config->doc->templateModule[3]['plan'] = array(); +$config->doc->templateModule[3]['plan']['executionDevelopmentPlan'] = 'Execution development plan'; +$config->doc->templateModule[3]['plan']['executionQualityAssurancePlan'] = 'Execution quality assurance plan'; +$config->doc->templateModule[3]['plan']['executionTestPlan'] = 'Execution test plan'; -$config->doc->templateModule['execution']['desc'] = array(); -$config->doc->templateModule['execution']['desc']['executionSoftwareRequirementsSpecification'] = 'Execution software requirements specification'; -$config->doc->templateModule['execution']['desc']['executionArchitecturalDesignSpecification'] = 'Execution architectural design specification'; -$config->doc->templateModule['execution']['desc']['executionCodeDesignSpecification'] = 'Execution code design specification'; +$config->doc->templateModule[3]['desc'] = array(); +$config->doc->templateModule[3]['desc']['executionSoftwareRequirementsSpecification'] = 'Execution software requirements specification'; +$config->doc->templateModule[3]['desc']['executionArchitecturalDesignSpecification'] = 'Execution architectural design specification'; +$config->doc->templateModule[3]['desc']['executionCodeDesignSpecification'] = 'Execution code design specification'; -$config->doc->templateModule['execution']['dev'] = array(); -$config->doc->templateModule['execution']['dev']['executionCode'] = 'Execution code'; -$config->doc->templateModule['execution']['dev']['executionDatabaseDesignDocument'] = 'Execution database design document'; -$config->doc->templateModule['execution']['dev']['executionInterfaceDesignDocument'] = 'Execution interface design document'; +$config->doc->templateModule[3]['dev'] = array(); +$config->doc->templateModule[3]['dev']['executionCode'] = 'Execution code'; +$config->doc->templateModule[3]['dev']['executionDatabaseDesignDocument'] = 'Execution database design document'; +$config->doc->templateModule[3]['dev']['executionInterfaceDesignDocument'] = 'Execution interface design document'; -$config->doc->templateModule['execution']['test'] = array(); -$config->doc->templateModule['execution']['test']['executionFunctionalTesting'] = 'Execution functional testing'; -$config->doc->templateModule['execution']['test']['executionTestCases'] = 'Execution test cases'; +$config->doc->templateModule[3]['test'] = array(); +$config->doc->templateModule[3]['test']['executionFunctionalTesting'] = 'Execution functional testing'; +$config->doc->templateModule[3]['test']['executionTestCases'] = 'Execution test cases'; -$config->doc->templateModule['execution']['report'] = array(); -$config->doc->templateModule['execution']['report']['executionProgressReport'] = 'Execution progress report'; -$config->doc->templateModule['execution']['report']['executionRiskReport'] = 'Execution risk report'; -$config->doc->templateModule['execution']['report']['executionAcceptanceReport'] = 'Execution acceptance report'; -$config->doc->templateModule['execution']['report']['executionSummaryReport'] = 'Execution summary report'; -$config->doc->templateModule['execution']['report']['executionQualityReport'] = 'Execution quality report'; +$config->doc->templateModule[3]['report'] = array(); +$config->doc->templateModule[3]['report']['executionProgressReport'] = 'Execution progress report'; +$config->doc->templateModule[3]['report']['executionRiskReport'] = 'Execution risk report'; +$config->doc->templateModule[3]['report']['executionAcceptanceReport'] = 'Execution acceptance report'; +$config->doc->templateModule[3]['report']['executionSummaryReport'] = 'Execution summary report'; +$config->doc->templateModule[3]['report']['executionQualityReport'] = 'Execution quality report'; -$config->doc->templateModule['personal'] = array(); -$config->doc->templateModule['personal']['plan'] = array(); -$config->doc->templateModule['personal']['plan']['personalWorkPlan'] = 'Personal work plan'; +$config->doc->templateModule[4] = array(); +$config->doc->templateModule[4]['plan'] = array(); +$config->doc->templateModule[4]['plan']['personalWorkPlan'] = 'Personal work plan'; -$config->doc->templateModule['personal']['report'] = array(); -$config->doc->templateModule['personal']['report']['personalWorkSummaryReport'] = 'Personal work summary report'; -$config->doc->templateModule['personal']['report']['personalValueAnalysisReport'] = 'Personal value analysis report'; +$config->doc->templateModule[4]['report'] = array(); +$config->doc->templateModule[4]['report']['personalWorkSummaryReport'] = 'Personal work summary report'; +$config->doc->templateModule[4]['report']['personalValueAnalysisReport'] = 'Personal value analysis report'; diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 00b558c8da..3ff1727d7c 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -52,8 +52,8 @@ const customRenders = { const items = []; const {libID, filterType, docID, orderBy, pager, mode} = this.location; - const {recTotal, recPerPage, pageID} = pager; - const url = $.createLink('doc', 'browseTemplate', `libID=${libID}&filterType=${filterType}&docID=${docID}&orderBy=${orderBy}&recTotal=${recTotal}&recPerPage=${recPerPage}&pageID=${pageID}&mode=create`); + const {recTotal, recPerPage, page} = pager; + const url = $.createLink('doc', 'browseTemplate', `libID=${libID}&filterType=${filterType}&docID=${docID}&orderBy=${orderBy}&recTotal=${recTotal}&recPerPage=${recPerPage}&pageID=${page}&mode=create`); items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', url: url}); return {component: 'toolbar', props: {items: items}}; } diff --git a/module/doc/model.php b/module/doc/model.php index 7442a36744..54af8be1ea 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3635,14 +3635,14 @@ class docModel extends model foreach($moduleList as $moduleKey => $subModuleList) { $module = new stdclass(); - $module->root = $this->config->doc->templateMenu[$scope]['id']; + $module->root = $scope; $module->name = $this->lang->docTemplate->moduleName[$moduleKey]; $module->parent = 0; $module->path = ''; $module->grade = 1; $module->order = $moduleOrder; $module->type = 'docTemplate'; - $module->short = ucfirst($scope) . ' ' . $moduleKey; + $module->short = $scope . ' ' . $moduleKey; $this->dao->insert(TABLE_MODULE)->data($module)->exec(); if(dao::isError()) return false; @@ -3654,7 +3654,7 @@ class docModel extends model foreach($subModuleList as $subModuleKey => $subModuleCode) { $subModule = new stdclass(); - $subModule->root = $this->config->doc->templateMenu[$scope]['id']; + $subModule->root = $scope; $subModule->name = $this->lang->docTemplate->moduleName[$subModuleKey]; $subModule->parent = $moduleID; $subModule->path = ''; diff --git a/module/doc/ui/setdocbasic.html.php b/module/doc/ui/setdocbasic.html.php index fb0dd59c7d..96d5ab369f 100644 --- a/module/doc/ui/setdocbasic.html.php +++ b/module/doc/ui/setdocbasic.html.php @@ -10,6 +10,12 @@ declare(strict_types=1); */ namespace zin; +if($objectType == 'template') +{ + include 'setdocbasic.template.html.php'; + return; +} + formPanel ( setID('setDocBasicForm'), diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php new file mode 100644 index 0000000000..f718e5b96e --- /dev/null +++ b/module/doc/ui/setdocbasic.template.html.php @@ -0,0 +1,35 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; + +formPanel +( + setID('setDocBasicForm'), + setData('officeTypes', $this->config->doc->officeTypes), + setData('docType', isset($doc) ? $doc->users : 'undefined'), + set::title($title), + set::submitBtnText($isDraft ? $lang->doc->saveDraft : (empty($docID) ? $lang->doc->release : $lang->save)), + on::change('[name=lib]')->call('loadLibModules', jsRaw('event')), + on::change('[name=lib],[name^=users]', 'checkLibPriv'), + set::ajax(array('beforeSubmit' => jsRaw('window.beforeSetDocBasicInfo'))), + formGroup + ( + set::label($lang->docTemplate->scope), + set::required(true), + picker(set::name('lib'), set::items($lang->docTemplate->scopes), set::value(isset($libs[$libID]) ? $libID : ''), set::required(true)) + ), + formGroup + ( + set::width('1/2'), + set::label($lang->docTemplate->module), + picker(set::name('module'), set::items(array()), set::value($moduleID), set::required(true)) + ) +); From 36c58878387d13333cc400dcb0d4d936147b864d Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 02:46:08 +0000 Subject: [PATCH 043/655] * [story#68004,1h] fix actionsMap. --- module/doc/js/browsetemplate.ui.js | 11 ++--------- module/doc/ui/templatelist.html.php | 5 +++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 3ff1727d7c..d28696b390 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -64,7 +64,7 @@ const customRenders = * 定义文档模板各个视图和 UI 元素的上的操作方法。 * Define the operation methods on the views and UI elements of the doc template. */ -const actionsMap = +$.extend(window.docAppActions, { /** * 定义分组的操作按钮。 @@ -89,13 +89,7 @@ const actionsMap = return items; }, -}; - -function getActions(type, info) -{ - const builder = actionsMap[type]; - if(builder) return builder.call(this, info); -} +}); /** * 定义界面操作命令。 @@ -124,7 +118,6 @@ window.setDocAppOptions = function(_, options) // Override the method. { commands : commands, getTableOptions : getTableOptions, - getActions : getActions, customRenders : customRenders }); }; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 2ce61ae3d7..20ba0eccf6 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -17,6 +17,7 @@ foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('sp $data['modules'] = $this->doc->getTemplateModules(); $privs = array(); +$privs['create'] = true; $filterTypes = $lang->docTemplate->filterTypes; if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); @@ -47,7 +48,7 @@ $langData['addSubModule'] = $lang->docTemplate->addSubModule; $langData['editModule'] = $lang->docTemplate->editModule; $langData['deleteModule'] = $lang->docTemplate->deleteModule; -$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}'); +$viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); docApp ( @@ -58,7 +59,7 @@ docApp set::noSpace(), set::noModule(), set::homeName(false), - set::mode($docID ? 'view' : 'list'), + set::mode($mode), set::privs($privs), set::userMap($users), set::spaceIcon('home'), From 0c4ac7635ffb592c3bd1f5996d8dac911afa0875 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 11:01:29 +0800 Subject: [PATCH 044/655] * [task#131758,doing,0.1h] add lang. --- module/doc/control.php | 1 - module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + 5 files changed, 4 insertions(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index b570c928e0..26a66c235c 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -351,7 +351,6 @@ class doc extends control $this->display(); } - /** * 编辑一个模板类型。 * Edit a template type. diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 9775df110b..90597c104a 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -88,6 +88,7 @@ $lang->docTemplate->module = 'Type'; $lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->create = 'Create Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 6cc1caba21..ec80122cba 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -88,6 +88,7 @@ $lang->docTemplate->module = 'Type'; $lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->create = 'Create Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index a5f5b0bba5..a355d03dcf 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -88,6 +88,7 @@ $lang->docTemplate->module = 'Type'; $lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->create = 'Create Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index b5cfc3acf5..d1d183c170 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -88,6 +88,7 @@ $lang->docTemplate->module = '模板类型'; $lang->docTemplate->desc = '模板简介'; $lang->docTemplate->parentModule = '上级类型'; $lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->addTemplateType = '添加文档模板类型'; $lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->create = '创建模板'; From 8819fce43478de32a9c3972ef0f5ddc6170f29c5 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 11:13:11 +0800 Subject: [PATCH 045/655] * [task#131758,doing,0.2h] fix code of template type. --- module/doc/config.php | 6 ++++++ module/doc/model.php | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/module/doc/config.php b/module/doc/config.php index ea84c408ee..98a52ffa3d 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -122,6 +122,12 @@ $config->doc->quickMenu['createdby'] = array('id' => 2, 'name' => $lang->doc->my $config->doc->quickMenu['collect'] = array('id' => 3, 'name' => $lang->doc->myCollection); $config->doc->quickMenu['editedby'] = array('id' => 4, 'name' => $lang->doc->myEdited); +$config->doc->scopeMaps = array(); +$config->doc->scopeMaps[1] = 'product'; +$config->doc->scopeMaps[2] = 'project'; +$config->doc->scopeMaps[3] = 'execution'; +$config->doc->scopeMaps[4] = 'personal'; + $config->doc->templateMenu = array(); $config->doc->templateMenu[1] = array('id' => 1, 'name' => $lang->docTemplate->scopes[1]); $config->doc->templateMenu[2] = array('id' => 2, 'name' => $lang->docTemplate->scopes[2]); diff --git a/module/doc/model.php b/module/doc/model.php index 54af8be1ea..5cc489aa0d 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3642,7 +3642,7 @@ class docModel extends model $module->grade = 1; $module->order = $moduleOrder; $module->type = 'docTemplate'; - $module->short = $scope . ' ' . $moduleKey; + $module->short = ucfirst($this->config->doc->scopeMaps[$scope]) . ' ' . $moduleKey; $this->dao->insert(TABLE_MODULE)->data($module)->exec(); if(dao::isError()) return false; @@ -3706,7 +3706,7 @@ class docModel extends model { foreach($moduleList as $moduleKey => $subModuleList) { - if($module->short == ucfirst($scope) . ' ' . $moduleKey) return true; + if($module->short == ucfirst($this->config->doc->scopeMaps[$scope]) . ' ' . $moduleKey) return true; foreach($subModuleList as $subModuleKey => $subModuleCode) { From 7737f49d0e6d3fa76fb4f1089de48f45a3736d0f Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 05:25:03 +0000 Subject: [PATCH 046/655] * [story#68004,1h] fix create form. --- module/doc/js/browsetemplate.ui.js | 24 ++++++++++--------- module/doc/model.php | 26 ++++++++++++++++++--- module/doc/ui/setdocbasic.template.html.php | 12 ++++++++-- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index d28696b390..e8b9e5aff7 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -40,6 +40,18 @@ function getTableOptions(options, info) return options; } +/** + * 处理创建文档的操作请求,向服务器发送请求并返回创建的文档对象。 + * Handle the create doc operation request, send a request to the server and return the created doc object. + */ +function handleCreateDoc(doc, spaceID, libID, moduleID) +{ + const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=0&isDraft=no`); + zui.Modal.open({url: url}); + + return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); +} + const customRenders = { /** @@ -117,6 +129,7 @@ window.setDocAppOptions = function(_, options) // Override the method. return $.extend(options, { commands : commands, + onCreateDoc : handleCreateDoc, getTableOptions : getTableOptions, customRenders : customRenders }); @@ -155,16 +168,5 @@ $.extend(window.docAppCommands, getDocApp().delete('doc', templateID); } }) - }, - saveNewDoc: function(_, args) - { - const docApp = getDocApp(); - const spaceType = docApp.spaceType; - const spaceID = docApp.spaceID; - const libID = docApp.libID; - const moduleID = docApp.moduleID; - const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=0&isDraft=no`); - zui.Modal.open({url: url}); - return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); } }); diff --git a/module/doc/model.php b/module/doc/model.php index 5cc489aa0d..0d8b9fef64 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3679,15 +3679,35 @@ class docModel extends model * 获取文档模板类型的模块。 * Get modules of doc template type. * + * @param bool $onlyNode + * @param string|int $libID * @access public * @return array */ - public function getTemplateModules() + public function getTemplateModules($onlyNode = true, $libID = 'all') { - return $this->dao->select('*')->from(TABLE_MODULE) + $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('deleted')->eq('0') ->andWhere('type')->eq('docTemplate') - ->fetchAll(); + ->beginIF($libID != 'all')->andWhere('root')->eq($libID)->fi() + ->fetchAll('id'); + + if($onlyNode) return array_values($modules); + + foreach($modules as $module) + { + if($module->parent === 0) continue; + $path = explode(',', trim($module->path, ',')); + + $names = array(); + foreach($path as $id) + { + $names[] = $modules[$id]->name; + } + $module->name = join(' / ', $names); + } + + return $modules; } /** diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index f718e5b96e..5cc5f26789 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -10,6 +10,9 @@ declare(strict_types=1); */ namespace zin; +$modules = $this->doc->getTemplateModules(false, $libID); +$modules = array_column($modules, 'name', 'id'); + formPanel ( setID('setDocBasicForm'), @@ -28,8 +31,13 @@ formPanel ), formGroup ( - set::width('1/2'), set::label($lang->docTemplate->module), - picker(set::name('module'), set::items(array()), set::value($moduleID), set::required(true)) + set::required(true), + picker(set::name('module'), set::items($modules), set::value($moduleID), set::required(true)) + ), + formGroup + ( + set::label($lang->docTemplate->desc), + textarea(set::name('desc'), set::value(''), set::rows(3)) ) ); From 5a9c8e316b7001b13d4b016b5f37fb942e301712 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 05:28:03 +0000 Subject: [PATCH 047/655] * [story#68004,1h] fix sonar. --- module/doc/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 0d8b9fef64..f21a466b83 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3704,7 +3704,7 @@ class docModel extends model { $names[] = $modules[$id]->name; } - $module->name = join(' / ', $names); + $module->name = implode(' / ', $names); } return $modules; @@ -3728,7 +3728,7 @@ class docModel extends model { if($module->short == ucfirst($this->config->doc->scopeMaps[$scope]) . ' ' . $moduleKey) return true; - foreach($subModuleList as $subModuleKey => $subModuleCode) + foreach($subModuleList as $subModuleCode) { if($module->short == $subModuleCode) return true; } From c8c32900e4e45e8403a7a4dc4882001694cb7ba3 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 13:54:08 +0800 Subject: [PATCH 048/655] *[misc] modify author. --- module/doc/control.php | 2 -- module/doc/lang/zh-cn.php | 3 +++ module/doc/ui/browsetemplate.html.php | 2 +- module/doc/ui/templatehome.html.php | 11 +++++++++++ module/doc/ui/templatelist.html.php | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 26a66c235c..8eddb8afc2 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -327,8 +327,6 @@ class doc extends control */ public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') { - if(!isset($this->config->doc->templateMenu[$libID])) $libID = 1; - $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index d1d183c170..53c94426f3 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -91,6 +91,9 @@ $lang->docTemplate->typeName = '类型名称'; $lang->docTemplate->addTemplateType = '添加文档模板类型'; $lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->more = '更多'; +$lang->docTemplate->scopeLabel = '范围'; + $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; $lang->docTemplate->delete = '删除模板'; diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index 6454e1c814..e6f88f9b9b 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -4,7 +4,7 @@ declare(strict_types=1); * The browse template view file of doc module of ZenTaoPMS. * @copyright Copyright 2009-2024 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net) * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html) - * @author Dai Tingting + * @author Song chenxuan * @package doc * @link https://www.zentao.net */ diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index e69de29bb2..9f7b7e6912 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -0,0 +1,11 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 20ba0eccf6..9a4aae5bd0 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -1,7 +1,7 @@ From 1c78c2d6ee1a6e415718721a0787a5404366bfa7 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 13:55:14 +0800 Subject: [PATCH 049/655] +[misc] add browse home. --- module/doc/ui/templatehome.html.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 9f7b7e6912..a0a79c4ace 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -9,3 +9,19 @@ declare(strict_types=1); * @link https://www.zentao.net */ namespace zin; + +$scopeItems = array(); +foreach($lang->docTemplate->scopes as $scopeID => $scopeName) +{ + $scopeDocs = array(); + $scopeItems[] = div + ( + setClass('doc-space-card ring rounded surface-light'), + ); +} + +div +( + setClass('doc-home-body flex-auto min-h-0 col gap-4 p-4 items-stretch overflow-auto scrollbar-hover'), + $scopeItems +); From 16c79ff557b2efebc2fa4fc2728c33827b9ab56c Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 13:56:22 +0800 Subject: [PATCH 050/655] +[misc] add scopeName. --- module/doc/ui/templatehome.html.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index a0a79c4ace..e340456a28 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -17,6 +17,20 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) $scopeItems[] = div ( setClass('doc-space-card ring rounded surface-light'), + div + ( + setClass('row items-center justify-between gap-2 px-2.5 py-1 border-b'), + div + ( + setClass('row items-center ml-2 flex-none'), + div + ( + setClass('min-w-0 flex-auto'), + strong($scopeName), + span(setClass('label ml-2 flex-none bg-white size-sm text-sm'), $lang->docTemplate->scopeLabel) + ), + ), + ), ); } From e0a82f1d0779e75dff1e4dc4cba14192576930d2 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 13:56:43 +0800 Subject: [PATCH 051/655] +[misc] add toolbar and scopeDocs. --- module/doc/ui/templatehome.html.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index e340456a28..0cefc73669 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -30,7 +30,26 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) span(setClass('label ml-2 flex-none bg-white size-sm text-sm'), $lang->docTemplate->scopeLabel) ), ), + toolbar + ( + item(set(array + ( + 'trailingIcon' => 'angle-right', + 'text' => $lang->docTemplate->more, + 'class' => 'ghost size-md text-primary', + 'url' => createLink('doc', 'browseTemplate', "libID=$scopeID") + ))) + ), ), + div + ( + setClass('doc-space-card-libs py-3 px-1.5'), + div + ( + setClass('row'), + $scopeDocs + ), + ) ); } From a7df4f14695e760dea10d2ca20a94f520a74b1e6 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 14:35:26 +0800 Subject: [PATCH 052/655] +[misc] add getScopeTemplates function. --- module/doc/model.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index f21a466b83..e1100ee12b 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3710,6 +3710,25 @@ class docModel extends model return $modules; } + /** + * 判断一个模块是否是内置的文档模板类型。 + * Judge whether a module is builtin template type. + * + * @param object $module + * @access public + * @return bool + */ + public function getScopeTemplates() + { + $scopeTemplates = array(); + foreach($this->lang->docTemplate->scopes as $scopeID => $scopeName) + { + $scopeTemplates[$scopeID] = array(); + } + + return $scopeTemplates; + } + /** * 判断一个模块是否是内置的文档模板类型。 * Judge whether a module is builtin template type. From 0fc484dd60a2141be141b28215f9da7b409ae16d Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 14:35:46 +0800 Subject: [PATCH 053/655] +[misc] add emtpy tip. --- module/doc/lang/zh-cn.php | 1 + module/doc/ui/templatehome.html.php | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 53c94426f3..e3f0a18c52 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -93,6 +93,7 @@ $lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; +$lang->docTemplate->emptyTip = '没有文档模板'; $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 0cefc73669..136df48450 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -10,10 +10,12 @@ declare(strict_types=1); */ namespace zin; +$scopeTemplates = $this->doc->getScopeTemplates(); + $scopeItems = array(); foreach($lang->docTemplate->scopes as $scopeID => $scopeName) { - $scopeDocs = array(); + $scopeDocs = $scopeTemplates[$scopeID]; $scopeItems[] = div ( setClass('doc-space-card ring rounded surface-light'), @@ -44,11 +46,19 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) div ( setClass('doc-space-card-libs py-3 px-1.5'), - div + !empty($scopeDocs) ? div ( setClass('row'), $scopeDocs - ), + ) : div + ( + setClass('center gap-4 py-10'), + div + ( + setClass('text-gray'), + $lang->docTemplate->emptyTip + ) + ) ) ); } From f5f8312c8388a816ebfd8f66ad4569d758f16776 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Mon, 11 Nov 2024 14:48:26 +0800 Subject: [PATCH 054/655] * Modify doctemplate empty tip. --- module/doc/lang/zh-cn.php | 2 +- module/doc/ui/templatehome.html.php | 2 +- module/doc/ui/templatelist.html.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index e3f0a18c52..2e25738bba 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -93,7 +93,7 @@ $lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; -$lang->docTemplate->emptyTip = '没有文档模板'; +$lang->docTemplate->noTemplate = '没有文档模板'; $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 136df48450..f4e7817ee5 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -56,7 +56,7 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) div ( setClass('text-gray'), - $lang->docTemplate->emptyTip + $lang->docTemplate->noTemplate ) ) ) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 9a4aae5bd0..ddcda4169f 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -48,6 +48,8 @@ $langData['addSubModule'] = $lang->docTemplate->addSubModule; $langData['editModule'] = $lang->docTemplate->editModule; $langData['deleteModule'] = $lang->docTemplate->deleteModule; +$langData['noDocs'] = $lang->docTemplate->noTemplate; + $viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); docApp From e6e16eef2ce3ade92cbab496f7769c2291704906 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 13:21:21 +0800 Subject: [PATCH 055/655] * [task#131758,doing,0.2h] add command of add template module. --- module/doc/js/browsetemplate.ui.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index e8b9e5aff7..c2d8ae4fe3 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -87,8 +87,8 @@ $.extend(window.docAppActions, const items = []; const module = info.data; - items.push({text: getDocAppLang('addModule'), command: `addModule/${module.lib}`}); - if(module.grade == 1) items.push({text: getDocAppLang('addSubModule'), command: `addSubModule/${module.id}`}); + items.push({text: getDocAppLang('addModule'), command: `addModule/${module.parent}`}); + if(module.grade == 1) items.push({text: getDocAppLang('addSubModule'), command: `addModule/${module.id}`}); items.push({text: getDocAppLang('editModule'), command: `editModule/${module.id}`}); items.push({text: getDocAppLang('deleteModule'), command: `deleteModule/${module.id}`}); @@ -109,6 +109,13 @@ $.extend(window.docAppActions, */ const commands = { + addModule: function(_, args) + { + const docApp = getDocApp(); + const parentModule = args[0]; + const url = $.createLink('doc', 'addTemplateType', `parentModule=${parentModule}`); + zui.Modal.open({size: 'sm', url: url}); + }, editModule: function(_, args) { const docApp = getDocApp(); From ece60c562a367e990f5c54d1eef7067720c2d7c4 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 13:28:49 +0800 Subject: [PATCH 056/655] * [task#131758,doing,0.1h] add ui of add template type. --- module/doc/control.php | 14 ++++++++++++++ module/doc/ui/addtemplatetype.html.php | 11 +++++++++++ 2 files changed, 25 insertions(+) create mode 100644 module/doc/ui/addtemplatetype.html.php diff --git a/module/doc/control.php b/module/doc/control.php index 8eddb8afc2..c81f6e577b 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -349,6 +349,20 @@ class doc extends control $this->display(); } + /** + * 创建一个模板类型。 + * Add a template type. + * + * @param int $parentModule + * @access public + * @return void + */ + public function addTemplateType(int $parentModule) + { + $this->view->parentModule = $parentModule; + $this->display(); + } + /** * 编辑一个模板类型。 * Edit a template type. diff --git a/module/doc/ui/addtemplatetype.html.php b/module/doc/ui/addtemplatetype.html.php new file mode 100644 index 0000000000..848e690a54 --- /dev/null +++ b/module/doc/ui/addtemplatetype.html.php @@ -0,0 +1,11 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; From 66226a8d9c2edf0d7f4fd1400625b5c897c5481c Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 14:37:39 +0800 Subject: [PATCH 057/655] * [task#131758,doing,1h] add ui of add template type. --- module/doc/control.php | 18 ++++++++++++- module/doc/js/browsetemplate.ui.js | 9 ++++--- module/doc/ui/addtemplatetype.html.php | 35 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index c81f6e577b..f882a207b1 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -353,13 +353,29 @@ class doc extends control * 创建一个模板类型。 * Add a template type. * + * @param int $scope * @param int $parentModule * @access public * @return void */ - public function addTemplateType(int $parentModule) + public function addTemplateType(int $scope, int $parentModule) { + $moduleList = $this->doc->getTemplateModules($scope, '1'); + + $moduleItems = array(); + if($parentModule == 0) + { + $moduleItems[] = array('value' => 0, 'text' => '/'); + } + else + { + foreach($moduleList as $module) $moduleItems[] = array('value' => $module->id, 'text' => '/' . $module->name); + } + + $this->view->scope = $scope; + $this->view->scopes = $this->doc->getScopeItems(); $this->view->parentModule = $parentModule; + $this->view->moduleItems = $moduleItems; $this->display(); } diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index c2d8ae4fe3..b9aeaee39c 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -87,8 +87,8 @@ $.extend(window.docAppActions, const items = []; const module = info.data; - items.push({text: getDocAppLang('addModule'), command: `addModule/${module.parent}`}); - if(module.grade == 1) items.push({text: getDocAppLang('addSubModule'), command: `addModule/${module.id}`}); + items.push({text: getDocAppLang('addModule'), command: `addModule/${module.root}/${module.parent}`}); + if(module.grade == 1) items.push({text: getDocAppLang('addSubModule'), command: `addModule/${module.root}/${module.id}`}); items.push({text: getDocAppLang('editModule'), command: `editModule/${module.id}`}); items.push({text: getDocAppLang('deleteModule'), command: `deleteModule/${module.id}`}); @@ -112,8 +112,9 @@ const commands = addModule: function(_, args) { const docApp = getDocApp(); - const parentModule = args[0]; - const url = $.createLink('doc', 'addTemplateType', `parentModule=${parentModule}`); + const scope = args[0]; + const parentModule = args[1]; + const url = $.createLink('doc', 'addTemplateType', `scope=${scope}&parentModule=${parentModule}`); zui.Modal.open({size: 'sm', url: url}); }, editModule: function(_, args) diff --git a/module/doc/ui/addtemplatetype.html.php b/module/doc/ui/addtemplatetype.html.php index 848e690a54..93ba55d3e7 100644 --- a/module/doc/ui/addtemplatetype.html.php +++ b/module/doc/ui/addtemplatetype.html.php @@ -9,3 +9,38 @@ declare(strict_types=1); * @link https://www.zentao.net */ namespace zin; + +modalHeader(set::title($lang->docTemplate->addTemplateType)); +formPanel +( + setID('addForm'), + set::submitBtnText($lang->save), + formGroup + ( + set::label($lang->docTemplate->scope), + picker + ( + set::name('root'), + set::value($scope), + set::items($scopes), + set::required(true) + ) + ), + formGroup + ( + set::label($lang->docTemplate->parentModule), + picker + ( + set::name('parent'), + set::value($parentModule), + set::items($moduleItems), + set::required(true) + ) + ), + formGroup + ( + set::name('name'), + set::label($lang->docTemplate->typeName), + set::control('input') + ), +); From 73c76774867e1f5353ecec87498dfda5259686be Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 14:46:30 +0800 Subject: [PATCH 058/655] * [task#131758,doing,0.3h] get template modules, fix conflict. --- module/doc/control.php | 2 +- module/doc/model.php | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index f882a207b1..73f4c3a1dc 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -360,7 +360,7 @@ class doc extends control */ public function addTemplateType(int $scope, int $parentModule) { - $moduleList = $this->doc->getTemplateModules($scope, '1'); + $moduleList = $this->doc->getTemplateModules(true, $scope, '1'); $moduleItems = array(); if($parentModule == 0) diff --git a/module/doc/model.php b/module/doc/model.php index e1100ee12b..df4fd708c9 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3680,16 +3680,18 @@ class docModel extends model * Get modules of doc template type. * * @param bool $onlyNode - * @param string|int $libID + * @param string|int $root + * @param string $grade * @access public * @return array */ - public function getTemplateModules($onlyNode = true, $libID = 'all') + public function getTemplateModules($onlyNode = true, $root = 'all', $grade = 'all') { $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('deleted')->eq('0') ->andWhere('type')->eq('docTemplate') - ->beginIF($libID != 'all')->andWhere('root')->eq($libID)->fi() + ->beginIF($root != 'all')->andWhere('root')->eq($root)->fi() + ->beginIF($grade != 'all')->andWhere('grade')->eq($grade)->fi() ->fetchAll('id'); if($onlyNode) return array_values($modules); @@ -3700,16 +3702,27 @@ class docModel extends model $path = explode(',', trim($module->path, ',')); $names = array(); - foreach($path as $id) - { - $names[] = $modules[$id]->name; - } + foreach($path as $id) $names[] = $modules[$id]->name; $module->name = implode(' / ', $names); } return $modules; } + /** + * 获取范围数据。 + * Get scope items. + * + * @access public + * @return array + */ + public function getScopeItems() + { + $items = array(); + foreach($this->config->doc->templateMenu as $scope) $items[] = array('value' => $scope['id'], 'text' => $scope['name']); + return $items; + } + /** * 判断一个模块是否是内置的文档模板类型。 * Judge whether a module is builtin template type. From 847137eaf0139a4c14706786add364abcde506c4 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 15:20:58 +0800 Subject: [PATCH 059/655] * [task#131758,doing,0.5h] add js to change scope. --- module/doc/control.php | 10 +++++----- module/doc/js/addtemplatetype.ui.js | 5 +++++ module/doc/ui/addtemplatetype.html.php | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 module/doc/js/addtemplatetype.ui.js diff --git a/module/doc/control.php b/module/doc/control.php index 73f4c3a1dc..60cb65f12c 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -353,17 +353,17 @@ class doc extends control * 创建一个模板类型。 * Add a template type. * - * @param int $scope - * @param int $parentModule + * @param int $scope + * @param int|string $parentModule * @access public * @return void */ - public function addTemplateType(int $scope, int $parentModule) + public function addTemplateType(int $scope, int|string $parentModule = '') { $moduleList = $this->doc->getTemplateModules(true, $scope, '1'); $moduleItems = array(); - if($parentModule == 0) + if($parentModule === 0) { $moduleItems[] = array('value' => 0, 'text' => '/'); } @@ -374,8 +374,8 @@ class doc extends control $this->view->scope = $scope; $this->view->scopes = $this->doc->getScopeItems(); - $this->view->parentModule = $parentModule; $this->view->moduleItems = $moduleItems; + $this->view->parentModule = $parentModule === '' ? current($moduleItems) : $parentModule; $this->display(); } diff --git a/module/doc/js/addtemplatetype.ui.js b/module/doc/js/addtemplatetype.ui.js new file mode 100644 index 0000000000..69ba9f4a00 --- /dev/null +++ b/module/doc/js/addtemplatetype.ui.js @@ -0,0 +1,5 @@ +window.changeScope = function(e) +{ + const scope = e.target.value; + loadModal($.createLink('doc', 'addTemplateType', `scope=${scope}`)); +} diff --git a/module/doc/ui/addtemplatetype.html.php b/module/doc/ui/addtemplatetype.html.php index 93ba55d3e7..9ef29862f2 100644 --- a/module/doc/ui/addtemplatetype.html.php +++ b/module/doc/ui/addtemplatetype.html.php @@ -23,7 +23,8 @@ formPanel set::name('root'), set::value($scope), set::items($scopes), - set::required(true) + set::required(true), + on::change('changeScope') ) ), formGroup @@ -42,5 +43,5 @@ formPanel set::name('name'), set::label($lang->docTemplate->typeName), set::control('input') - ), + ) ); From 503df2e2453115b5101b7fc16f3566ab9725a24d Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:11:53 +0000 Subject: [PATCH 060/655] * [story#68004,1h] add requiredFields. --- module/doc/config.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/config.php b/module/doc/config.php index 98a52ffa3d..488c3bb29d 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -5,12 +5,14 @@ $config->doc = new stdclass(); $config->doc->createlib = new stdclass(); $config->doc->editlib = new stdclass(); $config->doc->create = new stdclass(); +$config->doc->createTemplate = new stdclass(); $config->doc->edit = new stdclass(); $config->doc->showfiles = new stdclass(); $config->doc->createlib->requiredFields = 'name'; $config->doc->editlib->requiredFields = 'name'; $config->doc->create->requiredFields = 'lib,title'; +$config->doc->createTemplate->requiredFields = 'lib,title'; $config->doc->edit->requiredFields = 'lib,title'; $config->doc->customObjectLibs = 'files,customFiles'; From 72881466e144ea3a9f200e1bb8d8802ea1c5ada3 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:12:22 +0000 Subject: [PATCH 061/655] * [story#68004,1h] set createtemplate form. --- module/doc/config/form.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/config/form.php b/module/doc/config/form.php index fb47c34e54..a040bc49d3 100644 --- a/module/doc/config/form.php +++ b/module/doc/config/form.php @@ -59,6 +59,8 @@ $config->doc->form->create['template'] = array('type' => 'string', 'requir $config->doc->form->create['templateType'] = array('type' => 'string', 'required' => false, 'default' => ''); $config->doc->form->create['chapterType'] = array('type' => 'string', 'required' => false, 'default' => ''); +$config->doc->form->createtemplate = $config->doc->form->create; + $config->doc->form->edit['title'] = array('type' => 'string', 'required' => true, 'default' => '', 'filter' => 'trim'); $config->doc->form->edit['product'] = array('type' => 'int', 'required' => false, 'default' => 0); $config->doc->form->edit['project'] = array('type' => 'int', 'required' => false, 'default' => 0); From 548a0f45c6627e77d9f2c1aced822e7576ffce9c Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:13:27 +0000 Subject: [PATCH 062/655] * [story#68004,1h] add responseAfterCreateTemplate. --- module/doc/zen.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/module/doc/zen.php b/module/doc/zen.php index 2b7f260adb..3da2e46d34 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -390,6 +390,33 @@ class docZen extends doc return $this->send($response); } + /** + * 在创建文档模板后的返回。 + * Return after create a document template. + * + * @param int $libID + * @param array $docResult + * @access protected + * @return bool|int + */ + protected function responseAfterCreateTemplate(int $libID, array $docResult): bool|int + { + $docID = $docResult['id']; + $files = zget($docResult, 'files', ''); + + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; + + $actionType = $_POST['status'] == 'draft' ? 'savedTemplateDraft' : 'releasedTemplate'; + $this->action->create('docTemplate', $docID, $actionType, $fileAction); + + if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); + $params = "docID=" . $docResult['id']; + $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'browseTemplate', $params), 'id' => $docID, 'doc' => $docResult); + + return $this->send($response); + } + /** * 在移动库或文档后的返回。 * Return after move lib or doc. From 1bc748faea783edc10451be15a7f7c9f2861cf90 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:17:37 +0000 Subject: [PATCH 063/655] * [story#68004,1h] add createTemplate. --- module/doc/model.php | 57 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index d34801582d..e59cce4701 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -659,7 +659,6 @@ class docModel extends model ->where('deleted')->eq('0') ->beginIF($type == 'all')->andWhere('templateType')->ne('')->fi() ->beginIF($type != 'all')->andWhere('templateType')->eq($type)->fi() - ->andWhere('lib')->eq('') ->orderBy($orderBy) ->page($pager) ->fetchAll(); @@ -1494,6 +1493,62 @@ class docModel extends model return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); } + /** + * 创建一个文档模板。 + * Create a doc template. + * + * @param object $doc + * @access public + * @return array|bool|string + */ + public function createTemplate(object $doc): array|bool|string + { + if(empty($doc->lib)) return dao::$errors['lib'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib); + + $doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], (string)$this->post->uid); + + $docContent = new stdclass(); + $docContent->title = $doc->title; + $docContent->content = $doc->content; + $docContent->type = $doc->contentType; + $docContent->digest = ''; + $docContent->version = 1; + unset($doc->contentType); + + $requiredFields = $this->config->doc->createTemplate->requiredFields; + if($doc->status == 'draft') $requiredFields = 'title'; + if(strpos("url|word|ppt|excel", $doc->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ','); + + $checkContent = strpos(",$requiredFields,", ',content,') !== false; + if($checkContent && strpos("url|word|ppt|excel|", $lib->type) === false) + { + $requiredFields = trim(str_replace(',content,', ',', ",$requiredFields,"), ','); + if(empty($docContent->content)) return dao::$errors['content'] = sprintf($this->lang->error->notempty, $this->lang->doc->content); + } + + $files = $this->loadModel('file')->getUpload(); + if($doc->type == 'attachment' && (empty($files) || isset($files['name']))) return dao::$errors['files'] = sprintf($this->lang->error->notempty, $this->lang->doc->uploadFile); + + $doc->draft = $docContent->content; + $doc->vision = $this->config->vision; + $this->dao->insert(TABLE_DOC)->data($doc, 'content')->autoCheck() + ->batchCheck($requiredFields, 'notempty') + ->exec(); + if(dao::isError()) return false; + + $docID = $this->dao->lastInsertID(); + + $this->dao->update(TABLE_DOC)->set('`order`')->eq($docID)->where('id')->eq($docID)->exec(); + $this->file->updateObjectID($this->post->uid, $docID, 'doc'); + $files = $this->file->saveUpload('doc', $docID); + + $docContent->doc = $docID; + $docContent->files = join(',', array_keys($files)); + $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); + $this->loadModel('score')->create('doc', 'createTemplate', $docID); + return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); + } + /** * 编辑一个文档。 * Update a doc. From 3429402823b689c33bace977708d5550c3c58879 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:22:21 +0000 Subject: [PATCH 064/655] * [story#68004,1h] add createTemplate. --- module/doc/control.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index e27be049d8..ec1f2fc06e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -392,6 +392,30 @@ class doc extends control echo $this->fetch('tree', 'edit', "moduleID={$moduleID}&type=docTemplate"); } + /** + * 创建一个文档模板。 + * Create a doc template. + * + * @param int $moduleID + * @access public + * @return void + */ + public function createTemplate(int $moduleID = 0) + { + if(!empty($_POST)) + { + helper::setcookie('lastDocModule', $moduleID); + $docData = form::data() + ->setDefault('addedBy', $this->app->user->account) + ->setDefault('editedBy', $this->app->user->account) + ->get(); + + $docResult = $this->doc->createTemplate($docData, $this->post->labels); + if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->docZen->responseAfterCreateTemplate($docData->lib, $docResult); + } + } + /** * 上传文档。 * Upload docs. From 844e3ac1fb0e0d5989ca6e544933febe62319912 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:22:42 +0000 Subject: [PATCH 065/655] * [story#68004,1h] finish create template. --- module/doc/js/browsetemplate.ui.js | 103 +++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index b9aeaee39c..b111b8cf98 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -40,16 +40,111 @@ function getTableOptions(options, info) return options; } +function mergeDocFormData(doc, formData) +{ + if(!doc || !formData) return; + const keys = new Set(formData.keys()); + for(const key of keys) + { + const values = formData.getAll(key); + if(!values.length) continue; + if(key === 'module' || key === 'lib') doc[key] = +values[0]; + else doc[key] = values.length > 1 ? values : values[0]; + } + return doc; +} + +function showDocBasicModal(docID, isDraft) +{ + const docApp = getDocApp(); + const spaceType = docApp.spaceType; + const spaceID = docApp.spaceID; + const libID = docApp.libID; + const moduleID = docApp.moduleID; + const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=0&isDraft=no`); + zui.Modal.open({url: url}); + return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); +} + +/** + * 向服务器提交新文档。 + * Submit new doc to server. + * + * @param {object} doc + * @param {number} spaceID + * @param {number} libID + * @param {number} moduleID + * @param {FormData} formData + * @returns + */ +function submitNewDoc(doc, spaceID, libID, moduleID, formData) +{ + const docApp = getDocApp(); + const spaceType = docApp.signals.spaceType.value; + const module = docApp.treeMap.modules.get(moduleID); + const url = $.createLink('doc', 'createTemplate', `libID=${libID}&moduleID=${moduleID}`); + const docData = + { + content : doc.content, + status : doc.status || 'normal', + contentType : doc.contentType, + type : 'text', + lib : libID, + module : moduleID, + title : doc.title, + keywords : doc.keywords, + acl : 'private', + space : spaceType, + project : 0, + templateType: module.data.short, + uid : (doc.uid || `doc${doc.id}`), + }; + if(formData) mergeDocFormData(docData, formData); + const getErrorMessage = (res) => { + if(typeof res.message === 'string') return res.message; + if(typeof res.message === 'object' && res.message && Object.values(res.message).length) + { + for(const x of Object.values(res.message)) + { + if(typeof x === 'string') return x; + if(Array.isArray(x) && x.length) return x[0]; + } + } + if(typeof data.error === 'string') return data.error; + return getLang('errorOccurred'); + }; + return new Promise((resolve, reject) => + { + $.post(url, docData, (res) => + { + try + { + const data = JSON.parse(res); + if(typeof data !== 'object' || data.result === 'fail') + { + throw new Error(getErrorMessage(data)); + } + resolve($.extend(doc, {id: data.id}, docData, data.doc, {status: doc.status || data.status})); + } + catch (error) + { + zui.Modal.alert(error.message); + reject(error); + } + }); + }); +} + /** * 处理创建文档的操作请求,向服务器发送请求并返回创建的文档对象。 * Handle the create doc operation request, send a request to the server and return the created doc object. */ function handleCreateDoc(doc, spaceID, libID, moduleID) { - const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=0&isDraft=no`); - zui.Modal.open({url: url}); - - return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); + return showDocBasicModal(0).then((formData) => { + moduleID = parseInt(formData.get('module')); + return submitNewDoc(doc, spaceID, libID, moduleID, formData); + }); } const customRenders = From 4a2ce6abff861cfac2017cdf601f174f9c505e54 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 08:27:02 +0000 Subject: [PATCH 066/655] * [story#68004,1h] fix sonar. --- module/doc/model.php | 6 +++--- module/doc/zen.php | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index e59cce4701..2e371b9f79 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1520,7 +1520,7 @@ class docModel extends model if(strpos("url|word|ppt|excel", $doc->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ','); $checkContent = strpos(",$requiredFields,", ',content,') !== false; - if($checkContent && strpos("url|word|ppt|excel|", $lib->type) === false) + if($checkContent) { $requiredFields = trim(str_replace(',content,', ',', ",$requiredFields,"), ','); if(empty($docContent->content)) return dao::$errors['content'] = sprintf($this->lang->error->notempty, $this->lang->doc->content); @@ -1543,7 +1543,7 @@ class docModel extends model $files = $this->file->saveUpload('doc', $docID); $docContent->doc = $docID; - $docContent->files = join(',', array_keys($files)); + $docContent->files = implode(',', array_keys($files)); $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); $this->loadModel('score')->create('doc', 'createTemplate', $docID); return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); @@ -1583,7 +1583,7 @@ class docModel extends model $docContent->title = $doc->title; $docContent->content = isset($doc->content) ? $doc->content : ''; $docContent->files = $oldDocContent->files; - if($files) $docContent->files .= ',' . join(',', array_keys($files)); + if($files) $docContent->files .= ',' . implode(',', array_keys($files)); $docContent->files = trim($docContent->files, ','); if(isset($doc->digest)) $docContent->digest = $doc->digest; diff --git a/module/doc/zen.php b/module/doc/zen.php index 3da2e46d34..58c6126e83 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -373,7 +373,7 @@ class docZen extends doc $files = zget($docResult, 'files', ''); $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; + if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionType = $_POST['status'] == 'draft' ? 'savedDraft' : 'releasedDoc'; $this->action->create('doc', $docID, $actionType, $fileAction); @@ -405,7 +405,7 @@ class docZen extends doc $files = zget($docResult, 'files', ''); $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; + if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionType = $_POST['status'] == 'draft' ? 'savedTemplateDraft' : 'releasedTemplate'; $this->action->create('docTemplate', $docID, $actionType, $fileAction); @@ -500,7 +500,7 @@ class docZen extends doc $files = zget($docResult, 'files', ''); $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; + if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $this->action->create('doc', $docID, 'created', $fileAction); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); @@ -647,7 +647,7 @@ class docZen extends doc } $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; + if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionID = $this->action->create('doc', $doc->id, $action, $fileAction . $this->post->comment); if(!empty($changes)) $this->action->logHistory($actionID, $changes); } From 1bd4cef52529186d6bd8ff75de5ddceb6b8b4382 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 17:09:01 +0800 Subject: [PATCH 067/655] * [task#131758,doing,0.2h] add form config. --- module/doc/config/form.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/doc/config/form.php b/module/doc/config/form.php index a040bc49d3..470c0956a4 100644 --- a/module/doc/config/form.php +++ b/module/doc/config/form.php @@ -94,3 +94,7 @@ $config->doc->form->batchmovedoc['module'] = array('type' => 'int', 'required $config->doc->form->batchmovedoc['acl'] = array('type' => 'string', 'required' => true, 'default' => ''); $config->doc->form->batchmovedoc['groups'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join'); $config->doc->form->batchmovedoc['users'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join'); + +$config->doc->form->addTemplateType['name'] = array('type' => 'string', 'required' => true, 'default' => '', 'filter' => 'trim'); +$config->doc->form->addTemplateType['root'] = array('type' => 'int', 'required' => true, 'default' => 1); +$config->doc->form->addTemplateType['parent'] = array('type' => 'int', 'required' => false, 'default' => 0); From 503afdc3c5e14468fc49580a55ac5d6a03c52c4f Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 17:10:03 +0800 Subject: [PATCH 068/655] * [task#131758,doing,0.1h] add method to add template type. --- module/doc/model.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 2e371b9f79..90e8eb51b5 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3824,4 +3824,23 @@ class docModel extends model return false; } + + /** + * 添加文档模板类型。 + * Add template type. + * + * @param object $moduleData + * @access public + * @return int + */ + public function addTemplateType($moduleData) + { + $this->dao->insert(TABLE_MODULE)->data($moduleData)->autoCheck()->exec(); + $moduleID = $this->dao->lastInsertID(); + + $path = $moduleData->grade == 1 ? ",{$moduleID}," : ",{$moduleData->parent},{$moduleID},"; + $this->dao->update(TABLE_MODULE)->set('path')->eq($path)->where('id')->eq($moduleID)->exec(); + + return $moduleID; + } } From b97e0c415796e86b95e4a70ee020293e2c974c8d Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 Nov 2024 17:10:42 +0800 Subject: [PATCH 069/655] * [task#131758,doing,0.5h] add control for add template type. --- module/doc/control.php | 16 ++++++++++++++++ module/doc/zen.php | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index ec1f2fc06e..ee9148088f 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -362,6 +362,21 @@ class doc extends control { $moduleList = $this->doc->getTemplateModules(true, $scope, '1'); + if(!empty($_POST)) + { + $moduleData = form::data($this->config->doc->form->addTemplateType) + ->setDefault('type', 'docTemplate') + ->setDefault('path', '') + ->get(); + $moduleData->grade = $moduleData->parent === 0 ? 1 : 2; + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + $moduleID = $this->doc->addTemplateType($moduleData); + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + return $this->docZen->responseAfterAddTemplateType(); + } + $moduleItems = array(); if($parentModule === 0) { @@ -370,6 +385,7 @@ class doc extends control else { foreach($moduleList as $module) $moduleItems[] = array('value' => $module->id, 'text' => '/' . $module->name); + $moduleItems[] = array('value' => 0, 'text' => '/'); } $this->view->scope = $scope; diff --git a/module/doc/zen.php b/module/doc/zen.php index 58c6126e83..f0a92d08b4 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -1002,4 +1002,17 @@ class docZen extends doc $this->action->logHistory($actionID, $changes); } } + + /** + * 在创建版本类型后的返回。 + * Return after create a template type. + * + * @access public + * @return string + */ + public function responseAfterAddTemplateType() + { + $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'browseTemplate')); + return $this->send($response); + } } From f457b603e84a59a1c5484ccfab35d6919cf16bbd Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 11 Nov 2024 09:15:23 +0000 Subject: [PATCH 070/655] * [story#68004,0.5h] add title placeholder. --- module/doc/lang/de.php | 35 +++++++++++++++-------------- module/doc/lang/en.php | 35 +++++++++++++++-------------- module/doc/lang/fr.php | 35 +++++++++++++++-------------- module/doc/lang/zh-cn.php | 35 +++++++++++++++-------------- module/doc/ui/templatelist.html.php | 2 ++ 5 files changed, 74 insertions(+), 68 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 60df7a4dc0..460090668d 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -73,23 +73,24 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index e28e51b17c..8ed3bb4eba 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -73,23 +73,24 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 65d74f9924..642aa2a564 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -73,23 +73,24 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 290c93ef61..7bf062d3f7 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -73,23 +73,24 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = '编号'; -$lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequency = '频率'; -$lang->docTemplate->type = '类型'; -$lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建时间'; -$lang->docTemplate->editedBy = '最后修改者'; -$lang->docTemplate->editedDate = '最后修改时间'; -$lang->docTemplate->views = '阅读次数'; -$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; -$lang->docTemplate->scope = '所属范围'; -$lang->docTemplate->module = '模板类型'; -$lang->docTemplate->desc = '模板简介'; -$lang->docTemplate->parentModule = '上级类型'; -$lang->docTemplate->typeName = '类型名称'; -$lang->docTemplate->addTemplateType = '添加文档模板类型'; -$lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequency = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建时间'; +$lang->docTemplate->editedBy = '最后修改者'; +$lang->docTemplate->editedDate = '最后修改时间'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->scope = '所属范围'; +$lang->docTemplate->module = '模板类型'; +$lang->docTemplate->desc = '模板简介'; +$lang->docTemplate->parentModule = '上级类型'; +$lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->addTemplateType = '添加文档模板类型'; +$lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index ddcda4169f..0549b03b71 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -48,6 +48,8 @@ $langData['addSubModule'] = $lang->docTemplate->addSubModule; $langData['editModule'] = $lang->docTemplate->editModule; $langData['deleteModule'] = $lang->docTemplate->deleteModule; +$langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; + $langData['noDocs'] = $lang->docTemplate->noTemplate; $viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); From aa20322ee413f121fdd255727021c81b2c7062a4 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 08:58:59 +0800 Subject: [PATCH 071/655] +[misc] add getHotTemplate function. --- module/doc/model.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 90e8eb51b5..5f2bfddfdd 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3789,14 +3789,25 @@ class docModel extends model public function getScopeTemplates() { $scopeTemplates = array(); + foreach($this->lang->docTemplate->scopes as $scopeID => $scopeName) { - $scopeTemplates[$scopeID] = array(); + $scopeTemplates[$scopeID] = $this->getHotTemplates($scopeID, 5); } return $scopeTemplates; } + public function getHotTemplates($scopeID = 0, $limit = 0) + { + return $this->dao->select('*')->from(TABLE_DOC) + ->where('templateType')->ne('') + ->beginIF($scopeID)->andWhere('lib')->eq($scopeID)->fi() + ->orderBy('addedDate_desc,editedDate_desc') + ->beginIF($limit)->limit(5)->fi() + ->fetchAll(); + } + /** * 判断一个模块是否是内置的文档模板类型。 * Judge whether a module is builtin template type. From 1ec31b7f1de3106a0cc090d1ecc61e714f047080 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 08:59:38 +0800 Subject: [PATCH 072/655] +[misc] add buildScopeCards page function. --- module/doc/ui/templatehome.html.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index f4e7817ee5..a5bc6276ba 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -12,6 +12,16 @@ namespace zin; $scopeTemplates = $this->doc->getScopeTemplates(); +$buildScopeCards = function($templates) +{ + $cardItems = array(); + foreach($templates as $template) + { + } + + return $cardItems; +}; + $scopeItems = array(); foreach($lang->docTemplate->scopes as $scopeID => $scopeName) { @@ -49,7 +59,7 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) !empty($scopeDocs) ? div ( setClass('row'), - $scopeDocs + $buildScopeCards($scopeDocs) ) : div ( setClass('center gap-4 py-10'), From c6bc397355b70c86c5a6c3954661f7569efe492e Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 08:59:52 +0800 Subject: [PATCH 073/655] +[misc] add cardItems build. --- module/doc/ui/templatehome.html.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index a5bc6276ba..7096cc9a0f 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -17,6 +17,24 @@ $buildScopeCards = function($templates) $cardItems = array(); foreach($templates as $template) { + $cardItems[] = div + ( + setClass('doc-space-card-lib px-2 w-1/5 group'), + div + ( + setClass('canvas border rounded py-2 px-3 col gap-1 hover:shadow-lg hover:border-primary relative cursor-pointer'), + icon + ( + setClass('icon-doclib text-2xl') + ), + div + ( + setClass('font-bold text-clip'), + set::title($template->title), + $template->title + ) + ) + ); } return $cardItems; From bcc3891d46a56e55ab0e03f8d937114f1979b032 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 10:51:18 +0800 Subject: [PATCH 074/655] *[misc] add template card desc. --- module/doc/lang/zh-cn.php | 1 + module/doc/ui/templatehome.html.php | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 7bf062d3f7..663bc132a9 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -95,6 +95,7 @@ $lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; $lang->docTemplate->noTemplate = '没有文档模板'; +$lang->docTemplate->noDesc = '暂时没有描述'; $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 7096cc9a0f..89825972e1 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -12,7 +12,7 @@ namespace zin; $scopeTemplates = $this->doc->getScopeTemplates(); -$buildScopeCards = function($templates) +$buildScopeCards = function($templates) use ($lang) { $cardItems = array(); foreach($templates as $template) @@ -23,15 +23,24 @@ $buildScopeCards = function($templates) div ( setClass('canvas border rounded py-2 px-3 col gap-1 hover:shadow-lg hover:border-primary relative cursor-pointer'), - icon + div ( - setClass('icon-doclib text-2xl') + setClass('flex gap-2 items-center py-2'), + icon + ( + setClass('icon-doc text-2xl') + ), + div + ( + setClass('font-bold text-clip'), + set::title($template->title), + $template->title + ) ), div ( - setClass('font-bold text-clip'), - set::title($template->title), - $template->title + setClass('text-gray text-sm py-1'), + $lang->docTemplate->noDesc ) ) ); From e30e155ba364d659a1fe43858cd6f4545433757d Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 10:57:43 +0800 Subject: [PATCH 075/655] *[misc] add lang. --- module/doc/lang/de.php | 5 +++++ module/doc/lang/en.php | 5 +++++ module/doc/lang/fr.php | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 460090668d..5c1199ed71 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -96,6 +96,11 @@ $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; $lang->docTemplate->delete = 'Delete Template'; +$lang->docTemplate->more = 'More'; +$lang->docTemplate->scopeLabel = 'Scope'; +$lang->docTemplate->noTemplate = 'No Doc Template'; +$lang->docTemplate->noDesc = 'No Desc'; + $lang->docTemplate->addModule = 'Add Template type'; $lang->docTemplate->addSubModule = 'Add Sub Template type'; $lang->docTemplate->editModule = 'Edit Template type'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 8ed3bb4eba..6818feff69 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -96,6 +96,11 @@ $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; $lang->docTemplate->delete = 'Delete Template'; +$lang->docTemplate->more = 'More'; +$lang->docTemplate->scopeLabel = 'Scope'; +$lang->docTemplate->noTemplate = 'No Doc Template'; +$lang->docTemplate->noDesc = 'No Desc'; + $lang->docTemplate->addModule = 'Add Template type'; $lang->docTemplate->addSubModule = 'Add Sub Template type'; $lang->docTemplate->editModule = 'Edit Template type'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 642aa2a564..7fde4eb0b1 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -96,6 +96,11 @@ $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; $lang->docTemplate->delete = 'Delete Template'; +$lang->docTemplate->more = 'More'; +$lang->docTemplate->scopeLabel = 'Scope'; +$lang->docTemplate->noTemplate = 'No Doc Template'; +$lang->docTemplate->noDesc = 'No Desc'; + $lang->docTemplate->addModule = 'Add Template type'; $lang->docTemplate->addSubModule = 'Add Sub Template type'; $lang->docTemplate->editModule = 'Edit Template type'; From 0e231aaff61ddf41152a46622e263498d60a64a4 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 02:56:20 +0000 Subject: [PATCH 076/655] * [story#69261,0.5h] add editTemplate. --- module/doc/control.php | 43 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index ee9148088f..406eb5a407 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -426,12 +426,53 @@ class doc extends control ->setDefault('editedBy', $this->app->user->account) ->get(); - $docResult = $this->doc->createTemplate($docData, $this->post->labels); + $_POST['type'] = 'docTemplate'; + + $docResult = $this->doc->create($docData, $this->post->labels); if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->docZen->responseAfterCreateTemplate($docData->lib, $docResult); } } + /** + * 编辑一个文档。 + * Edit a doc. + * + * @param int $docID + * @param bool $comment + * @param int $appendLib + * @access public + * @return void + */ + public function editTemplate(int $docID, bool $comment = false, int $appendLib = 0) + { + $doc = $this->doc->getByID($docID); + if(!empty($_POST)) + { + $changes = $files = array(); + if($comment == false) + { + $docData = form::data() + ->setDefault('editedBy', $this->app->user->account) + ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") + ->get(); + + $_POST['type'] = 'docTemplate'; + $result = $this->doc->update($docID, $docData); + if(dao::isError()) + { + if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});")); + return $this->send(array('result' => 'fail', 'message' => dao::getError())); + } + + $changes = $result['changes']; + $files = $result['files']; + } + + return $this->docZen->responseAfterEditTemplate($doc, $changes, $files); + } + } + /** * 上传文档。 * Upload docs. From e606e9c4d24e6fb7632d8303bd509e84850ba60c Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 02:56:38 +0000 Subject: [PATCH 077/655] * [story#69261,0.5h] add priv. --- module/doc/ui/templatelist.html.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 0549b03b71..699c182201 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -17,7 +17,9 @@ foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('sp $data['modules'] = $this->doc->getTemplateModules(); $privs = array(); -$privs['create'] = true; +$privs['create'] = hasPriv('docTemplate', 'create'); +$privs['edit'] = hasPriv('docTemplate ', 'edit'); +$privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); From a2a17fad2c6ff567f19dec2be90b66e69cf96001 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 02:56:55 +0000 Subject: [PATCH 078/655] * [story#69261,0.5h] refactor. --- module/doc/model.php | 73 +++++++------------------------------------- 1 file changed, 11 insertions(+), 62 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 5f2bfddfdd..47e67c2aab 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1441,15 +1441,19 @@ class docModel extends model */ public function create(object $doc): array|bool|string { + $type = zget($_POST, 'type', 'doc'); if($doc->acl == 'open') $doc->users = $doc->groups = ''; if(empty($doc->lib) && strpos((string)$doc->module, '_') !== false) list($doc->lib, $doc->module) = explode('_', $doc->module); if(empty($doc->lib)) return dao::$errors['lib'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib); - $lib = $this->getLibByID($doc->lib); + if($type == 'doc') + { + $lib = $this->getLibByID($doc->lib); + $doc->product = $lib->product; + $doc->project = $lib->project; + $doc->execution = $lib->execution; + } $doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], (string)$this->post->uid); - $doc->product = $lib->product; - $doc->project = $lib->project; - $doc->execution = $lib->execution; $docContent = new stdclass(); $docContent->title = $doc->title; @@ -1459,7 +1463,7 @@ class docModel extends model $docContent->version = 1; unset($doc->contentType); - $requiredFields = $this->config->doc->create->requiredFields; + $requiredFields = $type == 'doc' ? $this->config->doc->create->requiredFields : $this->config->doc->createTemplate->requiredFields; if($doc->status == 'draft') $requiredFields = 'title'; if(strpos("url|word|ppt|excel", $doc->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ','); @@ -1486,66 +1490,10 @@ class docModel extends model $this->file->updateObjectID($this->post->uid, $docID, 'doc'); $files = $this->file->saveUpload('doc', $docID); - $docContent->doc = $docID; - $docContent->files = join(',', array_keys($files)); - $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); - $this->loadModel('score')->create('doc', 'create', $docID); - return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); - } - - /** - * 创建一个文档模板。 - * Create a doc template. - * - * @param object $doc - * @access public - * @return array|bool|string - */ - public function createTemplate(object $doc): array|bool|string - { - if(empty($doc->lib)) return dao::$errors['lib'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib); - - $doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], (string)$this->post->uid); - - $docContent = new stdclass(); - $docContent->title = $doc->title; - $docContent->content = $doc->content; - $docContent->type = $doc->contentType; - $docContent->digest = ''; - $docContent->version = 1; - unset($doc->contentType); - - $requiredFields = $this->config->doc->createTemplate->requiredFields; - if($doc->status == 'draft') $requiredFields = 'title'; - if(strpos("url|word|ppt|excel", $doc->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ','); - - $checkContent = strpos(",$requiredFields,", ',content,') !== false; - if($checkContent) - { - $requiredFields = trim(str_replace(',content,', ',', ",$requiredFields,"), ','); - if(empty($docContent->content)) return dao::$errors['content'] = sprintf($this->lang->error->notempty, $this->lang->doc->content); - } - - $files = $this->loadModel('file')->getUpload(); - if($doc->type == 'attachment' && (empty($files) || isset($files['name']))) return dao::$errors['files'] = sprintf($this->lang->error->notempty, $this->lang->doc->uploadFile); - - $doc->draft = $docContent->content; - $doc->vision = $this->config->vision; - $this->dao->insert(TABLE_DOC)->data($doc, 'content')->autoCheck() - ->batchCheck($requiredFields, 'notempty') - ->exec(); - if(dao::isError()) return false; - - $docID = $this->dao->lastInsertID(); - - $this->dao->update(TABLE_DOC)->set('`order`')->eq($docID)->where('id')->eq($docID)->exec(); - $this->file->updateObjectID($this->post->uid, $docID, 'doc'); - $files = $this->file->saveUpload('doc', $docID); - $docContent->doc = $docID; $docContent->files = implode(',', array_keys($files)); $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); - $this->loadModel('score')->create('doc', 'createTemplate', $docID); + $this->loadModel('score')->create('doc', $type == 'doc' ? 'create' : 'createTemplate', $docID); return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); } @@ -1560,6 +1508,7 @@ class docModel extends model */ public function update(int $docID, object $doc): array|string|bool { + $type = zget($_POST, 'type', 'doc'); $oldDoc = $this->dao->select('*')->from(TABLE_DOC)->where('id')->eq($docID)->fetch(); list($doc, $oldDocContent) = $this->processDocForUpdate($oldDoc, $doc); if(dao::isError()) return false; From dee0aaedfc626b0f2eaa222086447c50dd614ee3 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 02:57:11 +0000 Subject: [PATCH 079/655] * [story#69261,0.5h] add responseAfterEditTemplate. --- module/doc/zen.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/module/doc/zen.php b/module/doc/zen.php index f0a92d08b4..14cd52ad11 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -676,6 +676,40 @@ class docZen extends doc return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $doc)); } + /** + * 在编辑文档后的返回。 + * Return after edit a document. + * + * @param object $doc + * @param array $changes + * @param array $files + * @access protected + * @return void + */ + protected function responseAfterEditTemplate(object $doc, array $changes = array(), array $files = array()) + { + if($this->post->comment != '' || !empty($changes) || !empty($files)) + { + $action = 'Commented'; + if(!empty($changes)) + { + $newType = $_POST['status']; + if($doc->status == 'draft' && $newType == 'normal') $action = 'releasedDoc'; + if($doc->status == $newType) $action = 'Edited'; + } + + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; + $actionID = $this->action->create('docTemplate', $doc->id, $action, $fileAction . $this->post->comment); + if(!empty($changes)) $this->action->logHistory($actionID, $changes); + } + + $link = $this->createLink('doc', 'view', "docID={$doc->id}"); + $doc = $this->doc->getByID($doc->id); + if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true)); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $doc)); + } + /** * 处理文档大纲。 * From f2be617f1366761bcd1c0e658538b65b6c745194 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 02:58:04 +0000 Subject: [PATCH 080/655] * [story#69261,0.5h] add handleSaveDoc. --- module/doc/js/browsetemplate.ui.js | 119 +++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 25 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index b111b8cf98..487a384905 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -1,3 +1,4 @@ +const savingDocData = {}; /** * 获取文档界面上的表格初始化选项。 * Get the table initialization options on the doc UI. @@ -147,6 +148,65 @@ function handleCreateDoc(doc, spaceID, libID, moduleID) }); } +/** + * 处理保存文档的操作请求,向服务器发送请求并返回保存的文档对象。 + * Handle the save doc operation request, send a request to the server and return the saved doc object. + */ +function handleSaveDoc(doc) +{ + const docApp = getDocApp(); + const spaceType = docApp.signals.spaceType.value; + const libID = docApp.signals.libID.value; + const moduleID = docApp.signals.moduleID.value; + const url = $.createLink('doc', 'editTemplate', `docID=${doc.id}`); + const docData = { + content : doc.content, + status : doc.status || 'normal', + contentType: doc.contentType, + type : 'text', + lib : libID, + module : moduleID, + title : doc.title, + keywords : doc.keywords, + acl : doc.acl, + space : spaceType, + uid : (doc.uid || `doc${doc.id}`), + }; + + const docAppData = docApp.doc.data; + if (doc.id === docAppData.id) docData.mailto = docAppData.mailto; + + if(savingDocData[doc.id]) + { + mergeDocFormData(docData, savingDocData[doc.id]); + delete savingDocData[doc.id]; + } + + return new Promise((resolve) => { + $.post(url, docData, (res) => + { + try + { + const data = JSON.parse(res); + if(typeof data !== 'object' || data.result === 'fail') + { + let message = data.message || data.error || getLang('errorOccurred'); + if(typeof message === 'object') message = Object.values(message).map(x => Array.isArray(x) ? x.join('\n') : x).join('\n'); + throw new Error(message); + } + docApp.update('doc', $.extend({}, doc, docData, data.doc)); + resolve(true); + } + catch (error) + { + resolve(false); + if(!error.message) return; + zui.Modal.alert(error.message); + } + }); + }); +} + const customRenders = { /** @@ -196,13 +256,44 @@ $.extend(window.docAppActions, return items; }, + /** + * 定义文档编辑时的操作按钮。 + * Define the actions on toolbar of the doc editing page. + */ + 'doc-edit': function(info) + { + const doc = info.data; + if(!doc) return; + + const lang = getLang(); + return [ + {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveDoc/draft'}, + {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveDoc'}, + {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'}, + {text: lang.settings, size: 'md', type: 'ghost', command: `showDocSettingModal/${doc.id}/${doc.contentType}/1`, icon: 'cog-outline'}, + ]; + } }); /** - * 定义界面操作命令。 - * Define the UI commands. + * 重写文档应用的配置选项方法。 + * Override the method to set the doc app options. */ -const commands = +window._setDocAppOptions = window.setDocAppOptions; // Save the original method. +window.setDocAppOptions = function(_, options) // Override the method. +{ + options = window._setDocAppOptions(_, options); + return $.extend(options, + { + onCreateDoc : handleCreateDoc, + onSaveDoc : handleSaveDoc, + getTableOptions : getTableOptions, + customRenders : customRenders + }); +}; + +/* 扩展文档模板命令定义。 Extend the doc app command definition. */ +$.extend(window.docAppCommands, { addModule: function(_, args) { @@ -219,28 +310,6 @@ const commands = const url = $.createLink('doc', 'editTemplateType', `moduleID=${moduleID}`); zui.Modal.open({size: 'sm', url: url}); }, -}; - -/** - * 重写文档应用的配置选项方法。 - * Override the method to set the doc app options. - */ -window._setDocAppOptions = window.setDocAppOptions; // Save the original method. -window.setDocAppOptions = function(_, options) // Override the method. -{ - options = window._setDocAppOptions(_, options); - return $.extend(options, - { - commands : commands, - onCreateDoc : handleCreateDoc, - getTableOptions : getTableOptions, - customRenders : customRenders - }); -}; - -/* 扩展文档模板命令定义。 Extend the doc app command definition. */ -$.extend(window.docAppCommands, -{ /** * 编辑文档模板。 * Edit doc template. From e1c756df8be54b2047109f2087aa928ff5115056 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 02:58:16 +0000 Subject: [PATCH 081/655] * [story#69261,0.5h] finish edit template. --- module/doc/config/form.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/config/form.php b/module/doc/config/form.php index 470c0956a4..2a583d5ff5 100644 --- a/module/doc/config/form.php +++ b/module/doc/config/form.php @@ -78,6 +78,8 @@ $config->doc->form->edit['mailto'] = array('type' => 'array', 'required' $config->doc->form->edit['editedBy'] = array('type' => 'string', 'required' => false, 'default' => ''); $config->doc->form->edit['editedDate'] = array('type' => 'datetime', 'required' => false, 'default' => $now); +$config->doc->form->edittemplate = $config->doc->form->edit; + $config->doc->form->movelib['space'] = array('type' => 'string', 'required' => true, 'default' => ''); $config->doc->form->movelib['acl'] = array('type' => 'string', 'required' => true, 'default' => ''); $config->doc->form->movelib['groups'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join'); From 908ba65fb136735dd6db7c22cc8b8169d2687e87 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 12 Nov 2024 03:04:16 +0000 Subject: [PATCH 082/655] * [story#69261,0.5h] fix sonar. --- module/doc/control.php | 4 ++-- module/doc/model.php | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 406eb5a407..14135f2ca4 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -371,7 +371,7 @@ class doc extends control $moduleData->grade = $moduleData->parent === 0 ? 1 : 2; if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - $moduleID = $this->doc->addTemplateType($moduleData); + $this->doc->addTemplateType($moduleData); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->docZen->responseAfterAddTemplateType(); @@ -450,7 +450,7 @@ class doc extends control if(!empty($_POST)) { $changes = $files = array(); - if($comment == false) + if($comment) { $docData = form::data() ->setDefault('editedBy', $this->app->user->account) diff --git a/module/doc/model.php b/module/doc/model.php index 47e67c2aab..692507d424 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1508,7 +1508,6 @@ class docModel extends model */ public function update(int $docID, object $doc): array|string|bool { - $type = zget($_POST, 'type', 'doc'); $oldDoc = $this->dao->select('*')->from(TABLE_DOC)->where('id')->eq($docID)->fetch(); list($doc, $oldDocContent) = $this->processDocForUpdate($oldDoc, $doc); if(dao::isError()) return false; From f62150026cd0d04b2629c253e51f516a7fdc6b08 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Tue, 12 Nov 2024 10:06:57 +0800 Subject: [PATCH 083/655] * [task#131758,doing,0.1h] add lang. --- module/doc/lang/de.php | 37 +++++++++++++++++++------------------ module/doc/lang/en.php | 37 +++++++++++++++++++------------------ module/doc/lang/fr.php | 37 +++++++++++++++++++------------------ module/doc/lang/zh-cn.php | 37 +++++++++++++++++++------------------ 4 files changed, 76 insertions(+), 72 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 5c1199ed71..1306392631 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -73,24 +73,25 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 6818feff69..149ffb0cf2 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -73,24 +73,25 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 7fde4eb0b1..2dc9d06bdb 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -73,24 +73,25 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 663bc132a9..a353d0c6e6 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -73,24 +73,25 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = '编号'; -$lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequency = '频率'; -$lang->docTemplate->type = '类型'; -$lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建时间'; -$lang->docTemplate->editedBy = '最后修改者'; -$lang->docTemplate->editedDate = '最后修改时间'; -$lang->docTemplate->views = '阅读次数'; -$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; -$lang->docTemplate->scope = '所属范围'; -$lang->docTemplate->module = '模板类型'; -$lang->docTemplate->desc = '模板简介'; -$lang->docTemplate->parentModule = '上级类型'; -$lang->docTemplate->typeName = '类型名称'; -$lang->docTemplate->addTemplateType = '添加文档模板类型'; -$lang->docTemplate->editTemplateType = '编辑文档模板类型'; -$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequency = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建时间'; +$lang->docTemplate->editedBy = '最后修改者'; +$lang->docTemplate->editedDate = '最后修改时间'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->scope = '所属范围'; +$lang->docTemplate->module = '模板类型'; +$lang->docTemplate->desc = '模板简介'; +$lang->docTemplate->parentModule = '上级类型'; +$lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->addTemplateType = '添加文档模板类型'; +$lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; +$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; From 85c044aa5f83655027b8f74419fd22cb10c4a28a Mon Sep 17 00:00:00 2001 From: zhouxin Date: Tue, 12 Nov 2024 10:08:17 +0800 Subject: [PATCH 084/655] * [task#131758,doing,0.2h] add notice to doc-editTemplateType. --- module/doc/ui/addtemplatetype.html.php | 29 +++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/module/doc/ui/addtemplatetype.html.php b/module/doc/ui/addtemplatetype.html.php index 9ef29862f2..d081004a96 100644 --- a/module/doc/ui/addtemplatetype.html.php +++ b/module/doc/ui/addtemplatetype.html.php @@ -10,9 +10,36 @@ declare(strict_types=1); */ namespace zin; -modalHeader(set::title($lang->docTemplate->addTemplateType)); formPanel ( + detailHeader + ( + to::title + ( + entityLabel + ( + setClass('text-xl font-black'), + set::level(1), + set::text($lang->docTemplate->addTemplateType) + ), + div + ( + label + ( + to::before + ( + icon + ( + setClass('warning-ghost margin-left8'), + 'help' + ) + ), + set::text($lang->docTemplate->noticeAddTemplateType), + setClass('gray-200-pale') + ) + ) + ) + ), setID('addForm'), set::submitBtnText($lang->save), formGroup From d6d217e7c10951c45a9c45b810b9259e68a93348 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Tue, 12 Nov 2024 10:09:20 +0800 Subject: [PATCH 085/655] * [task#131758,doing,0.5h] add notice to doc-addTemplateType. --- module/tree/ui/edit.html.php | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/module/tree/ui/edit.html.php b/module/tree/ui/edit.html.php index 22f88c780d..ff6a0647df 100644 --- a/module/tree/ui/edit.html.php +++ b/module/tree/ui/edit.html.php @@ -24,9 +24,37 @@ $hidden = $type != 'story' && $module->type == 'story'; $isBuiltinTemplateModule = $type == 'docTemplate' && $this->loadModel('doc')->isBuiltinTemplateModule($module); /* ====== Define the page structure with zin widgets ====== */ -modalHeader(set::title($title)); +if($type != 'docTemplate') modalHeader(set::title($title)); formPanel ( + $type == 'docTemplate' ? detailHeader + ( + to::title + ( + entityLabel + ( + setClass('text-xl font-black'), + set::level(1), + set::text($lang->docTemplate->addTemplateType) + ), + div + ( + label + ( + to::before + ( + icon + ( + setClass('warning-ghost margin-left8'), + 'help' + ) + ), + set::text($lang->docTemplate->noticeAddTemplateType), + setClass('gray-200-pale') + ) + ) + ) + ) : null, setID('editForm'), set::action(helper::createLink($app->rawModule, $app->rawMethod, 'module=' . $module->id .'&type=' . $type)), set::submitBtnText($lang->save), From b27832b9c65b37e96fcc214ce8438fbd037a2173 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Tue, 12 Nov 2024 11:19:53 +0800 Subject: [PATCH 086/655] * [task#131758,done,0.5h] fix template type. --- module/doc/control.php | 2 +- module/doc/zen.php | 5 +++-- module/tree/control.php | 5 +++-- module/tree/js/edit.ui.js | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 14135f2ca4..26e11419a8 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -374,7 +374,7 @@ class doc extends control $this->doc->addTemplateType($moduleData); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->docZen->responseAfterAddTemplateType(); + return $this->docZen->responseAfterAddTemplateType($scope); } $moduleItems = array(); diff --git a/module/doc/zen.php b/module/doc/zen.php index 14cd52ad11..43d248d84e 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -1041,12 +1041,13 @@ class docZen extends doc * 在创建版本类型后的返回。 * Return after create a template type. * + * @param int $scope * @access public * @return string */ - public function responseAfterAddTemplateType() + public function responseAfterAddTemplateType(int $scope) { - $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'browseTemplate')); + $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'browseTemplate', "libID={$scope}")); return $this->send($response); } } diff --git a/module/tree/control.php b/module/tree/control.php index 5e5b2dcb16..f0d984b79c 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -378,10 +378,11 @@ class tree extends control * @param string $fieldID * @param string $extra * @param int $currentModuleID + * @param string $grade * @access public * @return string the html select string. */ - public function ajaxGetOptionMenu(int $rootID, string $viewType = 'story', string $branch = 'all', int $rootModuleID = 0, string $returnType = 'html', string $fieldID = '', string $extra = 'nodeleted', int $currentModuleID = 0) + public function ajaxGetOptionMenu(int $rootID, string $viewType = 'story', string $branch = 'all', int $rootModuleID = 0, string $returnType = 'html', string $fieldID = '', string $extra = 'nodeleted', int $currentModuleID = 0, string $grade = 'all') { if($viewType == 'task') { @@ -389,7 +390,7 @@ class tree extends control } else { - $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID, $branch, $extra); + $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID, $branch, $extra, $grade); } if(strpos($extra, 'excludeModuleID') !== false) diff --git a/module/tree/js/edit.ui.js b/module/tree/js/edit.ui.js index 02a55c8c94..de9e692d22 100644 --- a/module/tree/js/edit.ui.js +++ b/module/tree/js/edit.ui.js @@ -48,7 +48,7 @@ function changeRoot() { if(type == 'docTemplate') { - ajaxLoadModules(root, 0, 'docTemplate', moduleID); + ajaxLoadModules(root, 0, 'docTemplate', moduleID, '1'); } else { @@ -81,11 +81,11 @@ function changeRoot() * @access public * @return void */ -function ajaxLoadModules(productID, branchID, viewType = '', currentModuleID = 0) +function ajaxLoadModules(productID, branchID, viewType = '', currentModuleID = 0, grade = 'all') { if(!viewType) viewType = type; - var link = $.createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=' + viewType + '&branch=' + branchID + '&rootModuleID=0&returnType=html&fieldID=&extra=excludeModuleID=' + currentModuleID + ',noMainBranch,nodeleted,excludeRelated'); + var link = $.createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=' + viewType + '&branch=' + branchID + '&rootModuleID=0&returnType=html&fieldID=&extra=excludeModuleID=' + currentModuleID + ',noMainBranch,nodeleted,excludeRelated¤tModuleID=0&grade=' + grade); $.getJSON(link, function(data) { $parent = $('[name=parent]').zui('picker'); From efbc3448859759f0796a0380a83b42914911dd71 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 13:15:10 +0800 Subject: [PATCH 087/655] *[misc] move menu to biz. --- module/common/lang/menu.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 7fb019e240..cbf51f8f59 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -559,7 +559,6 @@ $lang->doc->menu->product = array('link' => "{$lang->doc->productSpace}|doc|pr $lang->doc->menu->project = array('link' => "{$lang->doc->projectSpace}|doc|projectSpace|", 'alias' => 'projectspace'); $lang->doc->menu->api = array('link' => "{$lang->doc->apiSpace}|api|index", 'alias' => '', 'exclude' => 'index'); $lang->doc->menu->team = array('link' => "{$lang->doc->teamSpace}|doc|teamSpace|", 'alias' => 'teamspace'); -$lang->doc->menu->template = array('link' => "{$lang->doc->template}|doc|browseTemplate|", 'alias' => 'browsetemplate'); $lang->doc->dividerMenu = ',product,'; @@ -571,7 +570,6 @@ $lang->doc->menuOrder[15] = 'team'; $lang->doc->menuOrder[20] = 'product'; $lang->doc->menuOrder[25] = 'project'; $lang->doc->menuOrder[30] = 'api'; -$lang->doc->menuOrder[35] = 'template'; /* BI menu.*/ $lang->bi->menu = new stdclass(); From 7fc2e408ec6d8382eba524e185059c09d8d9f79a Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 15:28:50 +0800 Subject: [PATCH 088/655] *[misc] modify getHotTemplate. --- module/doc/model.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 692507d424..bd3db808cd 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3750,9 +3750,10 @@ class docModel extends model { return $this->dao->select('*')->from(TABLE_DOC) ->where('templateType')->ne('') + ->andWhere('deleted')->eq('0') ->beginIF($scopeID)->andWhere('lib')->eq($scopeID)->fi() ->orderBy('addedDate_desc,editedDate_desc') - ->beginIF($limit)->limit(5)->fi() + ->beginIF($limit)->limit($limit)->fi() ->fetchAll(); } From 66f86d544799feeb623c72e61e9af504eb9b9c8c Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 16:44:12 +0800 Subject: [PATCH 089/655] *[task#67811,done,0.5h] modify doctemplate cols. --- module/doc/control.php | 3 +++ module/doc/js/browsetemplate.ui.js | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 26e11419a8..387c515cff 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -330,11 +330,14 @@ class doc extends control $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); + $modules = $this->doc->getTemplateModules(false, $libID); + $modules = array_column($modules, 'name', 'id'); $templateList = $this->doc->getDocTemplateList($type, $orderBy, $pager); foreach($templateList as $template) { $template->originLib = $template->lib; $template->lib = $libID; + $template->moduleName = zget($modules, $template->module); } $this->view->title = $this->lang->doc->template; diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 487a384905..c650f80175 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -13,8 +13,10 @@ function getTableOptions(options, info) templateCols = []; templateCols.push(options.cols.find(col => col.name == 'id')); - templateCols.push(options.cols.find(col => col.name == 'title')); - templateCols.push({name: 'type', title: lang.tableCols.type, type: 'string', sort: true}); + let title = options.cols.find(col => col.name == 'title'); + title.title = lang.tableCols.title; + templateCols.push(title); + templateCols.push({name: 'moduleName', title: lang.tableCols.type, type: 'string', sort: true}); templateCols.push(options.cols.find(col => col.name == 'addedBy')); templateCols.push(options.cols.find(col => col.name == 'addedDate')); templateCols.push(options.cols.find(col => col.name == 'editedBy')); From b0be49ba74f8351dfc843b5f1d37b723be17212e Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Tue, 12 Nov 2024 17:12:50 +0800 Subject: [PATCH 090/655] *[misc] delte groupby for fetchMetricsByCode. --- module/metric/tao.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/metric/tao.php b/module/metric/tao.php index 4837f18540..006ef78a08 100644 --- a/module/metric/tao.php +++ b/module/metric/tao.php @@ -61,7 +61,6 @@ class metricTao extends metricModel ->where('deleted')->eq('0') ->andWhere('scope')->in($scopes) ->andWhere('object')->in(array_keys($this->lang->metric->objectList)) - ->groupBy('scope') ->beginIF($limit > 0)->limit($limit)->fi() ->fetchAll('scope'); From 41b4a6f706bb8ce5b6e9da70f1e4bc6d3f1b31b9 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 12 Nov 2024 08:59:06 +0000 Subject: [PATCH 091/655] * [misc] Adjust template list. --- module/doc/control.php | 4 ++-- module/doc/model.php | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 387c515cff..e8e6988b9f 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -325,14 +325,14 @@ class doc extends control * @access public * @return void */ - public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') + public function browseTemplate(int $libID = 1, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') { $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); $modules = $this->doc->getTemplateModules(false, $libID); $modules = array_column($modules, 'name', 'id'); - $templateList = $this->doc->getDocTemplateList($type, $orderBy, $pager); + $templateList = $this->doc->getDocTemplateList($libID, $type, $orderBy, $pager); foreach($templateList as $template) { $template->originLib = $template->lib; diff --git a/module/doc/model.php b/module/doc/model.php index bd3db808cd..b0df952d7b 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -653,12 +653,15 @@ class docModel extends model * @access public * @return array */ - public function getDocTemplateList(string $type = 'all', string $orderBy = 'id_desc', object $pager = NULL): array + public function getDocTemplateList(int $libID, string $type = 'all', string $orderBy = 'id_desc', object $pager = NULL): array { return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq('0') - ->beginIF($type == 'all')->andWhere('templateType')->ne('')->fi() - ->beginIF($type != 'all')->andWhere('templateType')->eq($type)->fi() + ->andWhere('templateType')->ne('') + ->beginIF($libID)->andWhere('lib')->eq($libID)->fi() + ->beginIF($type == 'draft')->andWhere('status')->eq('draft')->fi() + ->beginIF($type == 'released')->andWhere('status')->eq('normal')->fi() + ->beginIF($type == 'createdByMe')->andWhere('addedBy')->eq($this->app->user->account)->fi() ->orderBy($orderBy) ->page($pager) ->fetchAll(); From 16824852fdd3d5c32dfbe78ba737fd6474936f5d Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 12 Nov 2024 09:22:33 +0000 Subject: [PATCH 092/655] * [task#131752,done,1h] Check create priv. --- module/doc/js/browsetemplate.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index c650f80175..427229ae17 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -223,7 +223,7 @@ const customRenders = const {libID, filterType, docID, orderBy, pager, mode} = this.location; const {recTotal, recPerPage, page} = pager; const url = $.createLink('doc', 'browseTemplate', `libID=${libID}&filterType=${filterType}&docID=${docID}&orderBy=${orderBy}&recTotal=${recTotal}&recPerPage=${recPerPage}&pageID=${page}&mode=create`); - items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', url: url}); + if(docAppHasPriv('create')) items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', url: url}); return {component: 'toolbar', props: {items: items}}; } } From ab503a6b5b53a87daccf76e0d8934ec843a6766e Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 13 Nov 2024 01:23:03 +0000 Subject: [PATCH 093/655] * [misc] Adjust default lib value. --- module/doc/control.php | 2 +- module/doc/model.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index e8e6988b9f..9837438905 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -325,7 +325,7 @@ class doc extends control * @access public * @return void */ - public function browseTemplate(int $libID = 1, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') + public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') { $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); diff --git a/module/doc/model.php b/module/doc/model.php index b0df952d7b..e0b9bbaea3 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -653,7 +653,7 @@ class docModel extends model * @access public * @return array */ - public function getDocTemplateList(int $libID, string $type = 'all', string $orderBy = 'id_desc', object $pager = NULL): array + public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = NULL): array { return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq('0') From b8478c0927e189af8893055e38f96157079ca785 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Wed, 13 Nov 2024 10:49:07 +0800 Subject: [PATCH 094/655] *[task#131750,done,0.5h]. --- module/doc/lang/zh-cn.php | 2 ++ module/group/lang/zh-cn.php | 2 +- module/group/packagemanager.php | 11 ++--------- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 73b219333c..9254b09380 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -493,6 +493,8 @@ $lang->doc->projectFilterTypes[] = array('mine', '我参与的'); $lang->doc->spaceFilterTypes[] = array('all', '全部'); +$lang->doc->browseTemplate = '文档模板'; + $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; $lang->doc->docLang->export = $lang->export; diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index e8abf51548..fe6bf5ccf6 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -464,7 +464,7 @@ $lang->group->package->comment = '备注'; $lang->group->package->module = '模块维护'; $lang->group->package->file = '附件'; $lang->group->package->commonEffort = '通用日志'; -$lang->group->package->docTemplate = '文档模板'; +$lang->group->package->docTemplate = '浏览文档模板'; $lang->group->package->importStoryLib = '导入需求库'; $lang->group->package->projectStakeholder = '项目干系人'; $lang->group->package->projectBuild = '项目版本'; diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index a4febd8c23..49dcfea730 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -339,7 +339,7 @@ $config->group->subset->featureconfig->nav = 'admin'; $config->group->subset->doctemplate = new stdclass(); $config->group->subset->doctemplate->order = 1220; -$config->group->subset->doctemplate->nav = 'admin'; +$config->group->subset->doctemplate->nav = 'doc'; $config->group->subset->notifysetting = new stdclass(); $config->group->subset->notifysetting->order = 1230; @@ -2920,14 +2920,7 @@ $config->group->package->docTemplate = new stdclass(); $config->group->package->docTemplate->order = 5; $config->group->package->docTemplate->subset = 'doctemplate'; $config->group->package->docTemplate->privs = array(); -$config->group->package->docTemplate->privs['baseline-templateType'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); -$config->group->package->docTemplate->privs['baseline-template'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 1, 'depend' => array(), 'recommend' => array()); -$config->group->package->docTemplate->privs['baseline-createTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 3, 'depend' => array('baseline-template'), 'recommend' => array('baseline-delete', 'baseline-editBook', 'baseline-editTemplate', 'baseline-manageBook')); -$config->group->package->docTemplate->privs['baseline-view'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 2, 'depend' => array('baseline-template'), 'recommend' => array()); -$config->group->package->docTemplate->privs['baseline-editTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 4, 'depend' => array('baseline-template'), 'recommend' => array('baseline-createTemplate', 'baseline-delete', 'baseline-editBook', 'baseline-manageBook')); -$config->group->package->docTemplate->privs['baseline-editBook'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array('baseline-template'), 'recommend' => array('baseline-createTemplate', 'baseline-delete', 'baseline-editTemplate', 'baseline-manageBook')); -$config->group->package->docTemplate->privs['baseline-manageBook'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 7, 'depend' => array('baseline-template'), 'recommend' => array('baseline-createTemplate', 'baseline-delete', 'baseline-editBook', 'baseline-editTemplate')); -$config->group->package->docTemplate->privs['baseline-delete'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 6, 'depend' => array('baseline-template'), 'recommend' => array('baseline-createTemplate')); +$config->group->package->docTemplate->privs['doc-browseTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); $config->group->package->projectStakeholder = new stdclass(); $config->group->package->projectStakeholder->order = 5; From 6cf4e06cc8c8d3304d7beffef95aa87c96b28533 Mon Sep 17 00:00:00 2001 From: sunhao Date: Wed, 13 Nov 2024 11:22:15 +0800 Subject: [PATCH 095/655] * [ui] fix js error on open doc-quick. --- lib/zin/wg/docapp/js/v1.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index fecec316c6..5209754d24 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -61,10 +61,15 @@ function hasPriv(priv, value) return value !== undefined ? setting === value : !!setting; } -function isApiLib(lib) +function isApiLib(lib, docApp) { if(typeof lib === 'number') lib = getDocApp().getLib(lib); - lib = lib || getDocApp().lib; + if(!lib) + { + docApp = docApp || getDocApp(); + if(!docApp) return false; + lib = docApp.lib; + } return lib && lib.data.type === 'api'; } @@ -612,8 +617,7 @@ const actionsMap = */ 'doc-list': function(info) { - const docApp = getDocApp(); - const lib = docApp.lib; + const docApp = this; const lang = getLang(); const canModify = canModifySpace(); @@ -1234,7 +1238,7 @@ const customRenders = */ filters: function() { - if(!isApiLib()) return; + if(!isApiLib(null, this)) return; const listType = this.signals.listType.value; if(this.mode !== 'list' || !listType) return; return null; @@ -1410,7 +1414,7 @@ function getFilterTypes(mode) } if(mode === 'list') { - const lib = getDocApp().lib; + const lib = this.lib; if(lib && lib.data.type === 'api') return getLang('apifilterTypes'); return getLang('filterTypes'); } From 9df084141540f82609100fe34a59752376eb323f Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 13 Nov 2024 07:07:39 +0000 Subject: [PATCH 096/655] * [misc] Optimize codes. --- module/doc/js/browsetemplate.ui.js | 3 ++- module/doc/ui/templatehome.html.php | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 427229ae17..31fe790e95 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -12,7 +12,8 @@ function getTableOptions(options, info) const lang = getDocAppLang(); templateCols = []; - templateCols.push(options.cols.find(col => col.name == 'id')); + templateCols.push(options.cols.find(col => col.name === 'rawID')); + let title = options.cols.find(col => col.name == 'title'); title.title = lang.tableCols.title; templateCols.push(title); diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 89825972e1..f1540a462b 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -73,9 +73,10 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) ( item(set(array ( - 'trailingIcon' => 'angle-right', - 'text' => $lang->docTemplate->more, - 'class' => 'ghost size-md text-primary', + 'type' => 'ghost', + 'caret' => 'right', + 'class' => 'text-primary', + 'text' => $lang->more, 'url' => createLink('doc', 'browseTemplate', "libID=$scopeID") ))) ), From b2f9604d05bc4d513a60903fe2dedeacd576018c Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Wed, 13 Nov 2024 16:00:08 +0800 Subject: [PATCH 097/655] *[misc] zt_doc add templateDesc field. --- db/update21.0.sql | 3 +-- db/update21.1.sql | 2 ++ db/zentao.sql | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 db/update21.1.sql diff --git a/db/update21.0.sql b/db/update21.0.sql index e49bf87888..1fbd806905 100644 --- a/db/update21.0.sql +++ b/db/update21.0.sql @@ -1,4 +1,3 @@ -ALTER TABLE zt_module MODIFY COLUMN short varchar(60); ALTER TABLE `zt_host` DROP COLUMN `serverModel`; ALTER TABLE `zt_host` DROP COLUMN `hardwareType`; ALTER TABLE `zt_host` DROP COLUMN `cpuBrand`; @@ -42,4 +41,4 @@ REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`, ` UPDATE `zt_action` SET `action` = 'canceled' WHERE `objectType` = 'deploy' AND `action` = 'activated'; DROP TABLE IF EXISTS `zt_account`; -DELETE FROM `zt_lang` WHERE `module` = 'host' AND `section` = 'cpuBrandList'; \ No newline at end of file +DELETE FROM `zt_lang` WHERE `module` = 'host' AND `section` = 'cpuBrandList'; diff --git a/db/update21.1.sql b/db/update21.1.sql new file mode 100644 index 0000000000..e1cd662ac2 --- /dev/null +++ b/db/update21.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE `zt_module` MODIFY COLUMN short varchar(60); +ALTER TABLE `zt_doc` ADD `templateDesc` text NULL AFTER `templateType`; diff --git a/db/zentao.sql b/db/zentao.sql index 1c2049c65a..a705ffb11c 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -739,6 +739,7 @@ CREATE TABLE IF NOT EXISTS `zt_doc` ( `lib` varchar(30) NOT NULL DEFAULT '', `template` varchar(30) NOT NULL DEFAULT '', `templateType` varchar(30) NOT NULL DEFAULT '', + `templateDesc` text NULL, `chapterType` varchar(30) NOT NULL DEFAULT '', `module` varchar(30) NOT NULL DEFAULT '', `title` varchar(255) NOT NULL DEFAULT '', @@ -1202,7 +1203,7 @@ CREATE TABLE IF NOT EXISTS `zt_module` ( `from` mediumint(8) unsigned NOT NULL default '0', `owner` varchar(30) NOT NULL DEFAULT '', `collector` text NULL, - `short` varchar(30) NOT NULL DEFAULT '', + `short` varchar(60) NOT NULL DEFAULT '', `deleted` enum('0','1') NOT NULL default '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; From 9c522d82dc5df5a278951a05dd401205fe5a0772 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Wed, 13 Nov 2024 08:18:58 +0000 Subject: [PATCH 098/655] * [story#67818,2h] finish setting. --- module/doc/control.php | 31 +++++++++++--------------- module/doc/js/browsetemplate.ui.js | 35 ++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 7d6e4fa940..2ed091abed 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -442,36 +442,31 @@ class doc extends control * Edit a doc. * * @param int $docID - * @param bool $comment * @param int $appendLib * @access public * @return void */ - public function editTemplate(int $docID, bool $comment = false, int $appendLib = 0) + public function editTemplate(int $docID, int $appendLib = 0) { $doc = $this->doc->getByID($docID); if(!empty($_POST)) { $changes = $files = array(); - if($comment) + $docData = form::data() + ->setDefault('editedBy', $this->app->user->account) + ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") + ->get(); + + $_POST['type'] = 'docTemplate'; + $result = $this->doc->update($docID, $docData); + if(dao::isError()) { - $docData = form::data() - ->setDefault('editedBy', $this->app->user->account) - ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") - ->get(); - - $_POST['type'] = 'docTemplate'; - $result = $this->doc->update($docID, $docData); - if(dao::isError()) - { - if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});")); - return $this->send(array('result' => 'fail', 'message' => dao::getError())); - } - - $changes = $result['changes']; - $files = $result['files']; + if(!empty(dao::$errors['lib']) || !empty(dao::$errors['keywords'])) return $this->send(array('result' => 'fail', 'message' => dao::getError(), 'callback' => "zui.Modal.open({id: 'modalBasicInfo'});")); + return $this->send(array('result' => 'fail', 'message' => dao::getError())); } + $changes = $result['changes']; + $files = $result['files']; return $this->docZen->responseAfterEditTemplate($doc, $changes, $files); } } diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 31fe790e95..a0af9a273a 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -70,6 +70,36 @@ function showDocBasicModal(docID, isDraft) return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); } +function showDocSettingModal(_, args) +{ + const docApp = getDocApp(); + const doc = docApp.doc; + const docID = args[0] || doc.id; + const docType = args[1] || doc.contentType; + const saveEdited = args[2] || 0; + showDocBasicModal(docID).then(formData => { + savingDocData[docID] = formData; + if(saveEdited == 1) + { + const docData = { + content : doc.data.content, + status : doc.data.status, + contentType: doc.data.contentType, + type : doc.data.type, + lib : doc.data.lib, + module : doc.data.module, + title : doc.data.title, + keywords : doc.data.keywords, + acl : doc.data.acl, + space : doc.data.space, + uid : doc.data.uid, + }; + mergeDocFormData(docData, formData); + $.post($.createLink('doc', 'editTemplate', `docID=${docID}`), docData); + } + }); +} + /** * 向服务器提交新文档。 * Submit new doc to server. @@ -273,7 +303,7 @@ $.extend(window.docAppActions, {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveDoc/draft'}, {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveDoc'}, {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'}, - {text: lang.settings, size: 'md', type: 'ghost', command: `showDocSettingModal/${doc.id}/${doc.contentType}/1`, icon: 'cog-outline'}, + {text: lang.settings, size: 'md', type: 'ghost', command: `showDocSettingModal/${doc.id}/template/1`, icon: 'cog-outline'}, ]; } }); @@ -343,5 +373,6 @@ $.extend(window.docAppCommands, getDocApp().delete('doc', templateID); } }) - } + }, + showDocSettingModal: showDocSettingModal }); From f933a4025a3d06b1ca2106352fcabeae2cccd937 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Wed, 13 Nov 2024 16:40:11 +0800 Subject: [PATCH 099/655] *[task#131769,done,1h]. --- module/doc/control.php | 1 + module/doc/js/browsetemplate.ui.js | 6 ++++++ module/doc/ui/templatehome.html.php | 7 +++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 2ed091abed..f8c463e450 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -428,6 +428,7 @@ class doc extends control ->setDefault('addedBy', $this->app->user->account) ->setDefault('editedBy', $this->app->user->account) ->get(); + $docData->templateDesc = $_POST['desc']; $_POST['type'] = 'docTemplate'; diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index a0af9a273a..00e493e0cf 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -376,3 +376,9 @@ $.extend(window.docAppCommands, }, showDocSettingModal: showDocSettingModal }); + +window.redirectDoc = function(event, docID) +{ + const url = $.createLink('doc', 'view', 'docID=' + docID); + openUrl(url); +} diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index f1540a462b..ff986724dc 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -17,8 +17,10 @@ $buildScopeCards = function($templates) use ($lang) $cardItems = array(); foreach($templates as $template) { + $cardDesc = $template->templateDesc ? $template->templateDesc : $lang->docTemplate->noDesc; $cardItems[] = div ( + on::click()->do("redirectDoc(event, {$template->id})"), setClass('doc-space-card-lib px-2 w-1/5 group'), div ( @@ -39,8 +41,9 @@ $buildScopeCards = function($templates) use ($lang) ), div ( - setClass('text-gray text-sm py-1'), - $lang->docTemplate->noDesc + setClass('text-gray text-clip text-sm py-1'), + set::title($cardDesc), + $cardDesc ) ) ); From beab83b88ecc0761651ba9bf0bce7ee4a7a50bc6 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Wed, 13 Nov 2024 16:57:39 +0800 Subject: [PATCH 100/655] *[misc] do openUrl. --- module/doc/js/browsetemplate.ui.js | 6 ------ module/doc/ui/templatehome.html.php | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 00e493e0cf..a0af9a273a 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -376,9 +376,3 @@ $.extend(window.docAppCommands, }, showDocSettingModal: showDocSettingModal }); - -window.redirectDoc = function(event, docID) -{ - const url = $.createLink('doc', 'view', 'docID=' + docID); - openUrl(url); -} diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index ff986724dc..1c961bf7f5 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -18,9 +18,10 @@ $buildScopeCards = function($templates) use ($lang) foreach($templates as $template) { $cardDesc = $template->templateDesc ? $template->templateDesc : $lang->docTemplate->noDesc; + $cardLink = helper::createLink('doc', 'view', "docID=$template->id"); $cardItems[] = div ( - on::click()->do("redirectDoc(event, {$template->id})"), + common::hasPriv('doc', 'view') ? on::click()->do("openUrl('$cardLink')") : null, setClass('doc-space-card-lib px-2 w-1/5 group'), div ( From 4be4b83bd1544304e83cfaf46bd735b70b681270 Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 13 Nov 2024 09:13:11 +0000 Subject: [PATCH 101/655] * [task#131773,doing,2h] Set home mode url. --- module/doc/control.php | 2 +- module/doc/js/browsetemplate.ui.js | 6 ++++++ module/doc/ui/browsetemplate.html.php | 4 ++-- module/doc/ui/templatehome.html.php | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index f8c463e450..c5752b5d5d 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -325,7 +325,7 @@ class doc extends control * @access public * @return void */ - public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'list') + public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'home') { $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index a0af9a273a..955628d9ed 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -242,6 +242,12 @@ function handleSaveDoc(doc) const customRenders = { + home: function() + { + const homeViewUrl = $.createLink('doc', 'browseTemplate', `libID=0&filterType=all&docID=0&orderBy=&recTotal=&recPerPage=20&pageID=1&mode=home`); + return {fetcher: homeViewUrl, clearBeforeLoad: false, className: 'doc-template-home h-full', class: 'h-full col',htmlRender: (element, props) => $(element).morphInner(`
${props.html}
`)}; + }, + /** * 定义 API 文档列表工具栏渲染。 * Define the API doc list toolbar render. diff --git a/module/doc/ui/browsetemplate.html.php b/module/doc/ui/browsetemplate.html.php index e6f88f9b9b..24eab8ed59 100644 --- a/module/doc/ui/browsetemplate.html.php +++ b/module/doc/ui/browsetemplate.html.php @@ -10,5 +10,5 @@ declare(strict_types=1); */ namespace zin; -if($libID) include './templatelist.html.php'; -else include './templatehome.html.php'; +if($mode == 'home' || !$libID) include './templatehome.html.php'; +else include './templatelist.html.php'; diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 1c961bf7f5..7b80b932b0 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -81,7 +81,7 @@ foreach($lang->docTemplate->scopes as $scopeID => $scopeName) 'caret' => 'right', 'class' => 'text-primary', 'text' => $lang->more, - 'url' => createLink('doc', 'browseTemplate', "libID=$scopeID") + 'url' => createLink('doc', 'browseTemplate', "libID=$scopeID&type=all&docID=0&orderBy=id_desc&recTotal=&recPerPae=20&pageID=1&mode=list") ))) ), ), From c3026e5c2c95a9ef104da2b547a1152e5bdbcbb5 Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 13 Nov 2024 09:25:55 +0000 Subject: [PATCH 102/655] * [task#131773,doing,0.1h] Remove space icon. --- module/doc/ui/templatelist.html.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 699c182201..31335bc1d8 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -64,11 +64,11 @@ docApp set::docID($docID), set::noSpace(), set::noModule(), - set::homeName(false), + set::homeName($lang->doc->template), set::mode($mode), set::privs($privs), set::userMap($users), - set::spaceIcon('home'), + set::spaceIcon(false), set::langData($langData), set::viewModeUrl($viewModeUrl), set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)), From 5b5e7dbfd8ac99ee637fac374ae3d7af20988acd Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Wed, 13 Nov 2024 09:35:53 +0000 Subject: [PATCH 103/655] * [story#67828,1h] add table sort. --- module/doc/js/browsetemplate.ui.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 955628d9ed..353e708737 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -11,6 +11,8 @@ function getTableOptions(options, info) { const lang = getDocAppLang(); + options.data.sort((a, b) => a.addedDate > b.addedDate ? -1 : 1); + templateCols = []; templateCols.push(options.cols.find(col => col.name === 'rawID')); From 9faeefdf4c832deabcfc1e505e534dcd52e1f63a Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 14 Nov 2024 01:08:18 +0000 Subject: [PATCH 104/655] * [task#131773,doing,0.5h] Set noSpace is hidden. --- module/doc/ui/templatelist.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 31335bc1d8..ac10a88563 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -62,7 +62,7 @@ docApp set::spaceID($spaceID), set::libID($libID), set::docID($docID), - set::noSpace(), + set::noSpace('hidden'), set::noModule(), set::homeName($lang->doc->template), set::mode($mode), From affa59d27683729677370bc4e8e83064c6880920 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Thu, 14 Nov 2024 10:02:26 +0800 Subject: [PATCH 105/655] *[misc] fetch doc-brwoseTemplate at doc-view. --- module/doc/control.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index c5752b5d5d..f1271daf39 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -330,6 +330,7 @@ class doc extends control $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); + $this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod; $modules = $this->doc->getTemplateModules(false, $libID); $modules = array_column($modules, 'name', 'id'); $templateList = $this->doc->getDocTemplateList($libID, $type, $orderBy, $pager); @@ -955,6 +956,11 @@ class doc extends control if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'fail', 'code' => 404, 'message' => '404 Not found')); return $this->sendError($this->lang->notFound, $this->inlink('index')); } + if($doc->templateType) + { + echo $this->fetch('doc', 'browseTemplate', "libID=$doc->lib&type=all&docID=$docID&orderBy=id_desc&recTotal=0&recPerPage=20&pageID=1&mode=view"); + } + if(!$isApi && !$this->doc->checkPrivDoc($doc)) return $this->sendError($this->lang->doc->accessDenied, inlink('index')); $lib = $this->doc->getLibByID((int)$doc->lib); From a9364048e6720e840ab92a4fc38e3e79a6784e26 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 14 Nov 2024 08:43:07 +0800 Subject: [PATCH 106/655] * [bug#57011,done,0.1h] fix lang. --- module/tree/ui/edit.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/tree/ui/edit.html.php b/module/tree/ui/edit.html.php index ff6a0647df..14c5769a5a 100644 --- a/module/tree/ui/edit.html.php +++ b/module/tree/ui/edit.html.php @@ -35,7 +35,7 @@ formPanel ( setClass('text-xl font-black'), set::level(1), - set::text($lang->docTemplate->addTemplateType) + set::text($lang->docTemplate->editTemplateType) ), div ( From b807f0b1c3320a15ec823e24c68ea51efe152bda Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 14 Nov 2024 10:23:21 +0800 Subject: [PATCH 107/655] * [task#131758,done,0.2h] set default short to template type. --- module/doc/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 9d001f9928..796c42c294 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3816,7 +3816,7 @@ class docModel extends model $moduleID = $this->dao->lastInsertID(); $path = $moduleData->grade == 1 ? ",{$moduleID}," : ",{$moduleData->parent},{$moduleID},"; - $this->dao->update(TABLE_MODULE)->set('path')->eq($path)->where('id')->eq($moduleID)->exec(); + $this->dao->update(TABLE_MODULE)->set('path')->eq($path)->set('short')->eq("custom{$moduleID}")->where('id')->eq($moduleID)->exec(); return $moduleID; } From 8902c4ef4c6e1c398004f25c18c8c79aa7a7e49b Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 14 Nov 2024 10:49:28 +0800 Subject: [PATCH 108/655] * [task#131759,done,1h] add feature of delete template type. --- module/doc/control.php | 22 ++++++++++++++++++++++ module/doc/js/browsetemplate.ui.js | 10 ++++++++++ module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/model.php | 17 +++++++++++++++++ 7 files changed, 53 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index f1271daf39..61fe9c1102 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -399,6 +399,28 @@ class doc extends control $this->display(); } + /** + * 删除一个模板类型。 + * Delete a template type. + * + * @param int $moduleID + * @access public + * @return void + */ + public function deleteTemplateType(int $moduleID) + { + $templates = $this->doc->getTemplatesByType($moduleID); + if(empty($templates)) + { + $this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('id')->eq($moduleID)->exec(); + return $this->sendSuccess(array('load' => true)); + } + else + { + return $this->send(array('result' => 'fail', 'message' => $this->lang->docTemplate->errorDeleteType)); + } + } + /** * 编辑一个模板类型。 * Edit a template type. diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 353e708737..2263ae0097 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -351,6 +351,16 @@ $.extend(window.docAppCommands, const url = $.createLink('doc', 'editTemplateType', `moduleID=${moduleID}`); zui.Modal.open({size: 'sm', url: url}); }, + deleteModule: function(_, args) + { + const docApp = getDocApp(); + const moduleID = args[0] || docApp.moduleID; + $.ajaxSubmit( + { + url: $.createLink('doc', 'deleteTemplateType', `moduleID=${moduleID}`), + load:false + }) + }, /** * 编辑文档模板。 * Edit doc template. diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 4bf4218d94..aca233667a 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -92,6 +92,7 @@ $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 5a14f37ace..c4be501ab7 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -92,6 +92,7 @@ $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index c808c20a32..2d4111c3ee 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -92,6 +92,7 @@ $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 9254b09380..c5160e5339 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -92,6 +92,7 @@ $lang->docTemplate->addTemplateType = '添加文档模板类型'; $lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; $lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; +$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; diff --git a/module/doc/model.php b/module/doc/model.php index 796c42c294..ba349df0f4 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3820,4 +3820,21 @@ class docModel extends model return $moduleID; } + + /** + * 获取某个模板类型下的所有模板。 + * Get template list by type. + * + * @param int $type + * @access public + * @return int + */ + public function getTemplatesByType($type) + { + return $this->dao->select('*')->from(TABLE_DOC) + ->where('deleted')->eq('0') + ->andWhere('templateType')->ne('') + ->andWhere('module')->eq($type) + ->fetchAll('id'); + } } From a89952021ddb6984e7f9496a359fd3fc471f4a3a Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 05:35:06 +0000 Subject: [PATCH 109/655] * [bug] fix update after create template. --- module/doc/control.php | 49 ++++++++++++++------- module/doc/js/browsetemplate.ui.js | 1 + module/doc/model.php | 8 ++-- module/doc/ui/setdocbasic.template.html.php | 4 +- module/doc/ui/templatelist.html.php | 1 + 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 61fe9c1102..6a2a54d0c9 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -331,13 +331,11 @@ class doc extends control $pager = new pager($recTotal, $recPerPage, $pageID); $this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod; - $modules = $this->doc->getTemplateModules(false, $libID); - $modules = array_column($modules, 'name', 'id'); - $templateList = $this->doc->getDocTemplateList($libID, $type, $orderBy, $pager); + $modules = $this->doc->getTemplateModules(); + $modules = array_column($modules, 'fullName', 'id'); + $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy, $pager); foreach($templateList as $template) { - $template->originLib = $template->lib; - $template->lib = $libID; $template->moduleName = zget($modules, $template->module); } @@ -364,7 +362,7 @@ class doc extends control */ public function addTemplateType(int $scope, int|string $parentModule = '') { - $moduleList = $this->doc->getTemplateModules(true, $scope, '1'); + $moduleList = $this->doc->getTemplateModules($scope, '1'); if(!empty($_POST)) { @@ -1782,20 +1780,37 @@ class doc extends control * @access public * @return void */ - public function ajaxGetSpaceData(string $type = 'custom', int $spaceID = 0, string $picks = '') + public function ajaxGetSpaceData(string $type = 'custom', int $spaceID = 0, string $picks = '', int $libID = 0) { - $noPicks = empty($picks); - $picks = $noPicks ? '' : ",$picks,"; + if($type === 'template') + { + $modules = $this->doc->getTemplateModules(); + $moduleNames = array_column($modules, 'fullName', 'id'); + $templateList = $this->doc->getDocTemplateList(0, 'all'); + foreach($templateList as $template) + { + $template->moduleName = zget($moduleNames, $template->module); + } + $data = array('spaceID' => $spaceID, 'docs' => array_values($templateList)); + $data['spaces'][] = array('name' => $this->lang->doc->template, 'id' => $spaceID); + foreach($this->config->doc->templateMenu as $item) $data['libs'][] = $item + array('space' => $spaceID); + $data['modules'] = $modules; + } + else + { + $noPicks = empty($picks); + $picks = $noPicks ? '' : ",$picks,"; - list($spaces, $spaceID) = $this->doc->getSpaces($type, $spaceID); - $data = array('spaceID' => (int)$spaceID); - $libs = $this->doc->getLibsOfSpace($type, $spaceID); - $libIds = array_keys($libs); + list($spaces, $spaceID) = $this->doc->getSpaces($type, $spaceID); + $data = array('spaceID' => (int)$spaceID); + $libs = $this->doc->getLibsOfSpace($type, $spaceID); + $libIds = array_keys($libs); - if($noPicks || strpos($picks, ',space,') !== false) $data['spaces'] = $spaces; - if($noPicks || strpos($picks, ',lib,') !== false) $data['libs'] = array_values($libs); - if($noPicks || strpos($picks, ',module,') !== false) $data['modules'] = array_values($this->doc->getModulesOfLibs($libIds)); - if($noPicks || strpos($picks, ',doc,') !== false) $data['docs'] = array_values($this->doc->getDocsOfLibs($libIds + array($spaceID), $type)); + if($noPicks || strpos($picks, ',space,') !== false) $data['spaces'] = $spaces; + if($noPicks || strpos($picks, ',lib,') !== false) $data['libs'] = array_values($libs); + if($noPicks || strpos($picks, ',module,') !== false) $data['modules'] = array_values($this->doc->getModulesOfLibs($libIds)); + if($noPicks || strpos($picks, ',doc,') !== false) $data['docs'] = array_values($this->doc->getDocsOfLibs($libIds + array($spaceID), $type)); + } $this->send($data); } diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 2263ae0097..44360794a2 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -136,6 +136,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData) uid : (doc.uid || `doc${doc.id}`), }; if(formData) mergeDocFormData(docData, formData); + docApp.props.fetcher = $.createLink('doc', 'ajaxGetSpaceData', `type=template&spaceID=${spaceID}&picks={picks}&libID=${libID}`); const getErrorMessage = (res) => { if(typeof res.message === 'string') return res.message; if(typeof res.message === 'object' && res.message && Object.values(res.message).length) diff --git a/module/doc/model.php b/module/doc/model.php index ba349df0f4..520eceb03e 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3705,7 +3705,7 @@ class docModel extends model * @access public * @return array */ - public function getTemplateModules($onlyNode = true, $root = 'all', $grade = 'all') + public function getTemplateModules($root = 'all', $grade = 'all') { $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('deleted')->eq('0') @@ -3714,8 +3714,6 @@ class docModel extends model ->beginIF($grade != 'all')->andWhere('grade')->eq($grade)->fi() ->fetchAll('id'); - if($onlyNode) return array_values($modules); - foreach($modules as $module) { if($module->parent === 0) continue; @@ -3723,10 +3721,10 @@ class docModel extends model $names = array(); foreach($path as $id) $names[] = $modules[$id]->name; - $module->name = implode(' / ', $names); + $module->fullName = implode(' / ', $names); } - return $modules; + return array_values($modules); } /** diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 5cc5f26789..095c244f1a 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -10,8 +10,8 @@ declare(strict_types=1); */ namespace zin; -$modules = $this->doc->getTemplateModules(false, $libID); -$modules = array_column($modules, 'name', 'id'); +$modules = $this->doc->getTemplateModules($libID); +$modules = array_column($modules, 'fullName', 'id'); formPanel ( diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index ac10a88563..f17e393f97 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -66,6 +66,7 @@ docApp set::noModule(), set::homeName($lang->doc->template), set::mode($mode), + set::fetcher(createLink('doc', 'ajaxGetSpaceData', 'type=template&spaceID=1&picks={picks}')), set::privs($privs), set::userMap($users), set::spaceIcon(false), From c97dbde06063318b9ca34ab63e142876bbf832c5 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Thu, 14 Nov 2024 15:05:41 +0800 Subject: [PATCH 110/655] *[task#131770,doing,0.5h]. --- module/doc/control.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index 6a2a54d0c9..ca7681b403 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -734,7 +734,9 @@ class doc extends control if($template->files) $this->doc->deleteFiles(array_keys($template->files)); if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->sendSuccess(array()); + + $link = $this->createLink('doc', 'browseTemplate'); + return $this->sendSuccess(array('load' => $link)); } /** From 059f33d5cf022fb07e8ba3883f5146347d9fc425 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Thu, 14 Nov 2024 15:06:10 +0800 Subject: [PATCH 111/655] *[task#131770,doing,1h] add div onclick and except toolbar. --- module/doc/js/browsetemplate.ui.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 44360794a2..d935adac5f 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -395,3 +395,11 @@ $.extend(window.docAppCommands, }, showDocSettingModal: showDocSettingModal }); + +window.clickTemplateCard = function(event, url) +{ + const target = $(event.target); + if(target.hasClass('icon') || target.hasClass('dropdown') || target.hasClass('toolbar')) return; + + openUrl(url); +} From 793e92ee41e36473d5381c77458c48acd56c7f52 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Thu, 14 Nov 2024 15:06:23 +0800 Subject: [PATCH 112/655] *[task#131770,doing,1h] add toolbar. --- module/doc/ui/templatehome.html.php | 32 ++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 7b80b932b0..b1391c1f5e 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -17,11 +17,18 @@ $buildScopeCards = function($templates) use ($lang) $cardItems = array(); foreach($templates as $template) { - $cardDesc = $template->templateDesc ? $template->templateDesc : $lang->docTemplate->noDesc; - $cardLink = helper::createLink('doc', 'view', "docID=$template->id"); + $cardDesc = $template->templateDesc ? $template->templateDesc : $lang->docTemplate->noDesc; + $viewLink = helper::createLink('doc', 'view', "docID=$template->id"); + $editLink = helper::createLink('doc', 'browsetemplate', "libID=$template->lib&type=all&docID=$template->id&orderBy=id_desc&recTotal=0&recPerPage=20&page=1&mode=edit"); + $deleteLink = helper::createLink('doc', 'deleteTemplate', "templateID=$template->id"); + + $actions = array(); + $actions[] = array('icon' => 'edit', 'text' => $this->lang->docTemplate->edit, 'url' => $editLink); + $actions[] = array('icon' => 'trash', 'text' => $this->lang->docTemplate->delete, 'url' => $deleteLink, 'data-confirm' => $this->lang->docTemplate->confirmDelete); + $cardItems[] = div ( - common::hasPriv('doc', 'view') ? on::click()->do("openUrl('$cardLink')") : null, + common::hasPriv('doc', 'view') ? on::click()->do("clickTemplateCard(event, '$viewLink')") : null, setClass('doc-space-card-lib px-2 w-1/5 group'), div ( @@ -45,6 +52,25 @@ $buildScopeCards = function($templates) use ($lang) setClass('text-gray text-clip text-sm py-1'), set::title($cardDesc), $cardDesc + ), + div + ( + setClass('toolbar absolute top-1 right-1 opacity-0 group-hover:opacity-100'), + dropdown + ( + btn + ( + setClass('size-sm dropdown'), + set::type('ghost'), + set::icon('ellipsis-v'), + set::caret(false), + ), + set::items($actions), + set::flip(true), + set::placement('bottom-center'), + set::strategy('absolute'), + set::hasIcons(false) + ) ) ) ); From be4f051d604006085edfb87d5cf398c60a4f2d5b Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 07:24:34 +0000 Subject: [PATCH 113/655] * [task#132522] fix module name. --- module/doc/model.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 520eceb03e..3fb736ba71 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3716,7 +3716,11 @@ class docModel extends model foreach($modules as $module) { - if($module->parent === 0) continue; + if($module->parent === 0) + { + $module->fullName = $module->name; + continue; + } $path = explode(',', trim($module->path, ',')); $names = array(); From ce4c6022951453645b01b6284a06f4547224583a Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 07:26:20 +0000 Subject: [PATCH 114/655] * [task#132522] fix sonar. --- module/doc/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 3fb736ba71..47e902d225 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -653,7 +653,7 @@ class docModel extends model * @access public * @return array */ - public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = NULL): array + public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = null): array { return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq('0') From d6e4239be57397bb66fee2ef127481d9c650560c Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 07:47:40 +0000 Subject: [PATCH 115/655] * [task#132515] fix template desc. --- module/doc/control.php | 3 ++- module/doc/js/browsetemplate.ui.js | 4 ++-- module/doc/ui/setdocbasic.template.html.php | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index ca7681b403..7f7ca239f8 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -478,6 +478,7 @@ class doc extends control ->setDefault('editedBy', $this->app->user->account) ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") ->get(); + $docData->templateDesc = $_POST['desc']; $_POST['type'] = 'docTemplate'; $result = $this->doc->update($docID, $docData); @@ -1939,7 +1940,7 @@ class doc extends control $moduleID = (int)$doc->module; $libID = (int)$doc->lib; $lib = $this->doc->getLibByID($libID); - $objectType = $lib->type; + if($lib && $objectType != 'template') $objectType = $lib->type; $objectID = $this->doc->getObjectIDByLib($lib); $libPairs = $this->doc->getLibs($objectType, '', $libID, $objectID); diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index d935adac5f..dbddfbbc26 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -60,14 +60,14 @@ function mergeDocFormData(doc, formData) return doc; } -function showDocBasicModal(docID, isDraft) +function showDocBasicModal(docID, isDraft = 'no') { const docApp = getDocApp(); const spaceType = docApp.spaceType; const spaceID = docApp.spaceID; const libID = docApp.libID; const moduleID = docApp.moduleID; - const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=0&isDraft=no`); + const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=${docID}&isDraft=${isDraft}`); zui.Modal.open({url: url}); return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); } diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 095c244f1a..6204963f7a 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -38,6 +38,6 @@ formPanel formGroup ( set::label($lang->docTemplate->desc), - textarea(set::name('desc'), set::value(''), set::rows(3)) + textarea(set::name('desc'), set::value($doc->templateDesc), set::rows(3)) ) ); From 90ab9ad5d506ae29f60395fe3364d1ddce933d7b Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 08:05:39 +0000 Subject: [PATCH 116/655] * [task#132521] remove checkbox. --- module/doc/js/browsetemplate.ui.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index dbddfbbc26..94f43139a5 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -14,7 +14,7 @@ function getTableOptions(options, info) options.data.sort((a, b) => a.addedDate > b.addedDate ? -1 : 1); templateCols = []; - templateCols.push(options.cols.find(col => col.name === 'rawID')); + templateCols.push({...options.cols.find(col => col.name === 'rawID'), type: 'id'}); let title = options.cols.find(col => col.name == 'title'); title.title = lang.tableCols.title; @@ -43,6 +43,8 @@ function getTableOptions(options, info) } }); + options.footer = options.footer.filter(f => f !== 'checkbox'); + return options; } From 45b4d3ffc41dcd317d1cc6086b44dee154e23010 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 08:10:04 +0000 Subject: [PATCH 117/655] * [task#132519,0.2h] add delete aciton in view. --- module/doc/ui/templatelist.html.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index f17e393f97..9b121e2006 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -19,6 +19,7 @@ $data['modules'] = $this->doc->getTemplateModules(); $privs = array(); $privs['create'] = hasPriv('docTemplate', 'create'); $privs['edit'] = hasPriv('docTemplate ', 'edit'); +$privs['delete'] = hasPriv('docTemplate ', 'delete'); $privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; From 2e60372c3d338b49d9b802aa042af363437e69b5 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 08:19:44 +0000 Subject: [PATCH 118/655] * [bug] fix error. --- module/doc/control.php | 2 +- module/doc/ui/setdocbasic.template.html.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 7f7ca239f8..1e5b6784ef 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -478,7 +478,7 @@ class doc extends control ->setDefault('editedBy', $this->app->user->account) ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") ->get(); - $docData->templateDesc = $_POST['desc']; + if(isset($_POST['desc'])) $docData->templateDesc = $_POST['desc']; $_POST['type'] = 'docTemplate'; $result = $this->doc->update($docID, $docData); diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 6204963f7a..51e00a94fc 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -38,6 +38,6 @@ formPanel formGroup ( set::label($lang->docTemplate->desc), - textarea(set::name('desc'), set::value($doc->templateDesc), set::rows(3)) + textarea(set::name('desc'), set::value($docID ? $doc->templateDesc : ''), set::rows(3)) ) ); From 3bc41876d05658526fc120e286038b88233f6ef2 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 08:38:10 +0000 Subject: [PATCH 119/655] * [task#132514,0.2h] add icon. --- module/doc/ui/templatelist.html.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 9b121e2006..4c27ccd63d 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -63,8 +63,10 @@ docApp set::spaceID($spaceID), set::libID($libID), set::docID($docID), + set::docIcon('file-archive'), set::noSpace('hidden'), set::noModule(), + set::moduleIcon('fields'), set::homeName($lang->doc->template), set::mode($mode), set::fetcher(createLink('doc', 'ajaxGetSpaceData', 'type=template&spaceID=1&picks={picks}')), From f797ac6abc3e208acadad06c1152140f23cfcf52 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 09:04:23 +0000 Subject: [PATCH 120/655] * [bug#56924,0.2h] fix lang. --- module/doc/lang/de.php | 2 +- module/doc/lang/en.php | 2 +- module/doc/lang/fr.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index aca233667a..1898acb4e8 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -90,7 +90,7 @@ $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index c4be501ab7..c04c84f45a 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -90,7 +90,7 @@ $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 2d4111c3ee..55c8c8b066 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -90,7 +90,7 @@ $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Please enter the title of the document template'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; From 4042e45a5bf1167a0b025dcaa75b25bb9e0ee9fb Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 09:12:33 +0000 Subject: [PATCH 121/655] * [bug#56923,0.2h] fix lang. --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/ui/templatelist.html.php | 1 + 5 files changed, 5 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 1898acb4e8..63b453a17a 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -91,6 +91,7 @@ $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the document title.'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index c04c84f45a..47eeaf6157 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -91,6 +91,7 @@ $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the document title.'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 55c8c8b066..431b78260c 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -91,6 +91,7 @@ $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the document title.'; $lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index c5160e5339..43b6ec934e 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -91,6 +91,7 @@ $lang->docTemplate->typeName = '类型名称'; $lang->docTemplate->addTemplateType = '添加文档模板类型'; $lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; +$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; $lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; $lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 4c27ccd63d..45dcfe2a78 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -52,6 +52,7 @@ $langData['editModule'] = $lang->docTemplate->editModule; $langData['deleteModule'] = $lang->docTemplate->deleteModule; $langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; +$langData['docTitleRequired'] = $lang->docTemplate->docTitleRequired; $langData['noDocs'] = $lang->docTemplate->noTemplate; From 9a55f9bf0af79c1dcf3061c4b16be0cf4bc220a7 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Thu, 14 Nov 2024 09:17:12 +0000 Subject: [PATCH 122/655] * [bug#57076,0.1h] fix lang. --- module/doc/lang/zh-cn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 43b6ec934e..78dadc719c 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -85,7 +85,7 @@ $lang->docTemplate->views = '阅读次数'; $lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; $lang->docTemplate->scope = '所属范围'; $lang->docTemplate->module = '模板类型'; -$lang->docTemplate->desc = '模板简介'; +$lang->docTemplate->desc = '描述'; $lang->docTemplate->parentModule = '上级类型'; $lang->docTemplate->typeName = '类型名称'; $lang->docTemplate->addTemplateType = '添加文档模板类型'; From 24d76656cc5f20e1c6e6837e0ab98cac1a6d2fae Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 00:51:50 +0000 Subject: [PATCH 123/655] * [bug#57092,0.1h] fix error. --- module/doc/model.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 47e902d225..fd7d35f2d1 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3724,7 +3724,11 @@ class docModel extends model $path = explode(',', trim($module->path, ',')); $names = array(); - foreach($path as $id) $names[] = $modules[$id]->name; + foreach($path as $id) + { + if(!isset($modules[$id])) continue; + $names[] = $modules[$id]->name; + } $module->fullName = implode(' / ', $names); } From 89c8fd742e26596a545a80469f402b3f0b7912ab Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 15 Nov 2024 03:36:15 +0000 Subject: [PATCH 124/655] * [task#131767,doing,2h] Add privileges. --- module/common/lang/de.php | 2 +- module/common/lang/en.php | 2 +- module/common/lang/fr.php | 2 +- module/common/lang/zh-cn.php | 2 +- module/doc/lang/de.php | 8 ++++++++ module/doc/lang/en.php | 8 ++++++++ module/doc/lang/fr.php | 8 ++++++++ module/doc/lang/zh-cn.php | 8 +++++++- module/doc/ui/templatelist.html.php | 11 +++++++---- module/group/lang/de.php | 3 +++ module/group/lang/en.php | 3 +++ module/group/lang/fr.php | 3 +++ module/group/lang/zh-cn.php | 3 +++ module/group/packagemanager.php | 26 +++++++++++++++++++++----- 14 files changed, 75 insertions(+), 14 deletions(-) diff --git a/module/common/lang/de.php b/module/common/lang/de.php index aad6a05a95..fcde04ca8a 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -289,7 +289,7 @@ $lang->systemsetting->common = 'System setting'; $lang->staffmanage->common = 'User management'; $lang->modelconfig->common = 'Pattern setting'; $lang->featureconfig->common = 'Features config'; -$lang->doctemplate->common = 'Doc template'; +$lang->doctemplate->common = 'Template Square'; $lang->notifysetting->common = 'Notification'; $lang->bidesign->common = 'BI design'; $lang->personalsettings->common = 'Personal setting '; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index ac7fff3726..66d2871259 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -289,7 +289,7 @@ $lang->systemsetting->common = 'System setting'; $lang->staffmanage->common = 'User management'; $lang->modelconfig->common = 'Pattern setting'; $lang->featureconfig->common = 'Features config'; -$lang->doctemplate->common = 'Doc template'; +$lang->doctemplate->common = 'Template Square'; $lang->notifysetting->common = 'Notification'; $lang->bidesign->common = 'BI design'; $lang->personalsettings->common = 'Personal setting '; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index ecc2abd027..fdc3d6c40a 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -289,7 +289,7 @@ $lang->systemsetting->common = 'System setting'; $lang->staffmanage->common = 'User management'; $lang->modelconfig->common = 'Pattern setting'; $lang->featureconfig->common = 'Features config'; -$lang->doctemplate->common = 'Doc template'; +$lang->doctemplate->common = 'Template Square'; $lang->notifysetting->common = 'Notification'; $lang->bidesign->common = 'BI design'; $lang->personalsettings->common = 'Personal setting '; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 069e97f532..a47d9728da 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -289,7 +289,7 @@ $lang->systemsetting->common = '系统设置'; $lang->staffmanage->common = '人员管理'; $lang->modelconfig->common = '模型配置'; $lang->featureconfig->common = '功能配置'; -$lang->doctemplate->common = '文档模板'; +$lang->doctemplate->common = '模板广场'; $lang->notifysetting->common = '通知设置'; $lang->bidesign->common = 'BI设计'; $lang->personalsettings->common = '个人设置'; diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 63b453a17a..23d466e37e 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -495,6 +495,14 @@ $lang->doc->projectFilterTypes[] = array('mine', 'Involved'); $lang->doc->spaceFilterTypes[] = array('all', 'All'); +$lang->doc->browseTemplate = 'Template Square'; +$lang->doc->createTemplate = 'Create Document Template'; +$lang->doc->editTemplate = 'Edit Document Template'; +$lang->doc->deleteTemplate = 'Delete Document Template'; +$lang->doc->addTemplateType = 'Create Type'; +$lang->doc->editTemplateType = 'Edit Type'; +$lang->doc->deleteTemplateType = 'Delete Type'; + $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; $lang->doc->docLang->export = $lang->export; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 47eeaf6157..f6b8cd3b54 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -495,6 +495,14 @@ $lang->doc->projectFilterTypes[] = array('mine', 'Involved'); $lang->doc->spaceFilterTypes[] = array('all', 'All'); +$lang->doc->browseTemplate = 'Template Square'; +$lang->doc->createTemplate = 'Create Document Template'; +$lang->doc->editTemplate = 'Edit Document Template'; +$lang->doc->deleteTemplate = 'Delete Document Template'; +$lang->doc->addTemplateType = 'Create Type'; +$lang->doc->editTemplateType = 'Edit Type'; +$lang->doc->deleteTemplateType = 'Delete Type'; + $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; $lang->doc->docLang->export = $lang->export; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 431b78260c..8c601ac16f 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -495,6 +495,14 @@ $lang->doc->projectFilterTypes[] = array('mine', 'Involved'); $lang->doc->spaceFilterTypes[] = array('all', 'All'); +$lang->doc->browseTemplate = 'Template Square'; +$lang->doc->createTemplate = 'Create Document Template'; +$lang->doc->editTemplate = 'Edit Document Template'; +$lang->doc->deleteTemplate = 'Delete Document Template'; +$lang->doc->addTemplateType = 'Create Type'; +$lang->doc->editTemplateType = 'Edit Type'; +$lang->doc->deleteTemplateType = 'Delete Type'; + $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; $lang->doc->docLang->export = $lang->export; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 78dadc719c..7e3d3e7489 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -495,7 +495,13 @@ $lang->doc->projectFilterTypes[] = array('mine', '我参与的'); $lang->doc->spaceFilterTypes[] = array('all', '全部'); -$lang->doc->browseTemplate = '文档模板'; +$lang->doc->browseTemplate = '模板广场'; +$lang->doc->createTemplate = '创建文档模板'; +$lang->doc->editTemplate = '编辑文档模板'; +$lang->doc->deleteTemplate = '删除文档模板'; +$lang->doc->addTemplateType = '添加类型'; +$lang->doc->editTemplateType = '编辑类型'; +$lang->doc->deleteTemplateType = '删除类型'; $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 45dcfe2a78..4ba8bdb091 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -17,10 +17,13 @@ foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('sp $data['modules'] = $this->doc->getTemplateModules(); $privs = array(); -$privs['create'] = hasPriv('docTemplate', 'create'); -$privs['edit'] = hasPriv('docTemplate ', 'edit'); -$privs['delete'] = hasPriv('docTemplate ', 'delete'); -$privs['collect'] = 'no'; +$privs['create'] = hasPriv('doc', 'createTemplate'); +$privs['edit'] = hasPriv('doc', 'editTemplate'); +$privs['delete'] = hasPriv('doc', 'deleteTemplate'); +$privs['addModule'] = hasPriv('doc', 'addTemplateType'); +$privs['editModule'] = hasPriv('doc', 'editTemplateType'); +$privs['deleteModule'] = hasPriv('doc', 'deleteTemplateType'); +$privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; if(!hasPriv('doc', 'editDocTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); diff --git a/module/group/lang/de.php b/module/group/lang/de.php index eb58846536..9ed0b99fa0 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -537,6 +537,9 @@ $lang->group->package->browseDoc = 'Browse Doc'; $lang->group->package->manageDoc = 'Manage Doc'; $lang->group->package->deleteDoc = 'Delete Doc'; $lang->group->package->exportDoc = 'Export Doc'; +$lang->group->package->browseDoctemplate = 'Browse Doc Template'; +$lang->group->package->manageDoctemplate = 'Manage Doc Template'; +$lang->group->package->deleteDoctemplate = 'Delete Doc Template'; $lang->group->package->browseAPI = 'Browse API'; $lang->group->package->manageAPI = 'Manage API'; $lang->group->package->exportAPI = 'Export API'; diff --git a/module/group/lang/en.php b/module/group/lang/en.php index e55e96983b..db7ff415f2 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -536,6 +536,9 @@ $lang->group->package->manageMetric = 'Manage Metric'; $lang->group->package->browseDoc = 'Browse Doc'; $lang->group->package->manageDoc = 'Manage Doc'; $lang->group->package->deleteDoc = 'Delete Doc'; +$lang->group->package->browseDoctemplate = 'Browse Doc Template'; +$lang->group->package->manageDoctemplate = 'Manage Doc Template'; +$lang->group->package->deleteDoctemplate = 'Delete Doc Template'; $lang->group->package->exportDoc = 'Export Doc'; $lang->group->package->browseAPI = 'Browse API'; $lang->group->package->manageAPI = 'Manage API'; diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 4628b085fc..2e91e5118f 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -536,6 +536,9 @@ $lang->group->package->manageMetric = 'Manage Metric'; $lang->group->package->browseDoc = 'Browse Doc'; $lang->group->package->manageDoc = 'Manage Doc'; $lang->group->package->deleteDoc = 'Delete Doc'; +$lang->group->package->browseDoctemplate = 'Browse Doc Template'; +$lang->group->package->manageDoctemplate = 'Manage Doc Template'; +$lang->group->package->deleteDoctemplate = 'Delete Doc Template'; $lang->group->package->exportDoc = 'Export Doc'; $lang->group->package->browseAPI = 'Browse API'; $lang->group->package->manageAPI = 'Manage API'; diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index fe6bf5ccf6..84391f9f4b 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -537,6 +537,9 @@ $lang->group->package->browseDoc = '浏览文档'; $lang->group->package->manageDoc = '创建与维护文档'; $lang->group->package->deleteDoc = '删除文档'; $lang->group->package->exportDoc = '导出文档'; +$lang->group->package->browseDoctemplate = '浏览文档模板'; +$lang->group->package->manageDoctemplate = '创建与维护文档模板'; +$lang->group->package->deleteDoctemplate = '删除文档模板'; $lang->group->package->browseAPI = '浏览接口空间'; $lang->group->package->manageAPI = '创建维护接口'; $lang->group->package->exportAPI = '导出接口'; diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 49dcfea730..98d8819c92 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2916,11 +2916,27 @@ $config->group->package->commonEffort->subset = 'generaleffort'; $config->group->package->commonEffort->privs = array(); $config->group->package->commonEffort->privs['effort-createForObject'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd,lite,or', 'order' => 3, 'depend' => array(), 'recommend' => array('effort-delete', 'effort-edit')); -$config->group->package->docTemplate = new stdclass(); -$config->group->package->docTemplate->order = 5; -$config->group->package->docTemplate->subset = 'doctemplate'; -$config->group->package->docTemplate->privs = array(); -$config->group->package->docTemplate->privs['doc-browseTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); +$config->group->package->browseDoctemplate = new stdclass(); +$config->group->package->browseDoctemplate->order = 5; +$config->group->package->browseDoctemplate->subset = 'doctemplate'; +$config->group->package->browseDoctemplate->privs = array(); +$config->group->package->browseDoctemplate->privs['doc-browseTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); + +$config->group->package->manageDoctemplate = new stdclass(); +$config->group->package->manageDoctemplate->order = 15; +$config->group->package->manageDoctemplate->subset = 'doctemplate'; +$config->group->package->manageDoctemplate->privs = array(); +$config->group->package->manageDoctemplate->privs['doc-createTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-editTemplate')); +$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-createTemplate')); +$config->group->package->manageDoctemplate->privs['doc-addTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-editTemplateType')); +$config->group->package->manageDoctemplate->privs['doc-editTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-addTemplateType')); +$config->group->package->manageDoctemplate->privs['doc-deleteTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('')); + +$config->group->package->deleteDoctemplate = new stdclass(); +$config->group->package->deleteDoctemplate->order = 20; +$config->group->package->deleteDoctemplate->subset = 'doctemplate'; +$config->group->package->deleteDoctemplate->privs = array(); +$config->group->package->deleteDoctemplate->privs['doc-deleteTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 40, 'depend' => array('doc-browseTemplate'), 'recommend' => array()); $config->group->package->projectStakeholder = new stdclass(); $config->group->package->projectStakeholder->order = 5; From 04136751b6ebae4989fd217cb785b71ae85102bb Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 01:19:05 +0000 Subject: [PATCH 125/655] * [bug#57080,0.1h] fix button lang. --- module/doc/js/browsetemplate.ui.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 94f43139a5..16d6533e22 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -62,13 +62,14 @@ function mergeDocFormData(doc, formData) return doc; } -function showDocBasicModal(docID, isDraft = 'no') +function showDocBasicModal(docID, isDraft = false) { const docApp = getDocApp(); const spaceType = docApp.spaceType; const spaceID = docApp.spaceID; const libID = docApp.libID; const moduleID = docApp.moduleID; + isDraft = isDraft ? 'yes' : 'no'; const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=${docID}&isDraft=${isDraft}`); zui.Modal.open({url: url}); return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); @@ -180,7 +181,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData) */ function handleCreateDoc(doc, spaceID, libID, moduleID) { - return showDocBasicModal(0).then((formData) => { + return showDocBasicModal(0, doc.status === 'draft').then((formData) => { moduleID = parseInt(formData.get('module')); return submitNewDoc(doc, spaceID, libID, moduleID, formData); }); From bbbe0eb0680f74efd3f1c0f65a054d1722376645 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 01:59:48 +0000 Subject: [PATCH 126/655] * [bug#57075,0.5h] fix switch scope. --- module/doc/js/common.ui.js | 16 +++++++++++++--- module/doc/model.php | 8 +------- module/doc/ui/setdocbasic.template.html.php | 12 ++++++++---- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/module/doc/js/common.ui.js b/module/doc/js/common.ui.js index a1017d0570..b3abd1bb5f 100644 --- a/module/doc/js/common.ui.js +++ b/module/doc/js/common.ui.js @@ -218,17 +218,27 @@ window.loadObjectModules = function(e) }); } -window.loadLibModules = function(e) +window.loadLibModules = function(e, docType) { const objectID = e.target.value; - let docType = $('.radio-primary [name=type]:not(.hidden):checked').val(); - if(typeof docType == 'undefined') docType = 'doc'; + if(!docType) + { + docType = $('.radio-primary [name=type]:not(.hidden):checked').val(); + if(typeof docType == 'undefined') docType = 'doc'; + } const link = $.createLink('tree', 'ajaxGetOptionMenu', 'rootID=' + objectID + '&viewType=' + docType + '&branch=all&rootModuleID=0&returnType=items'); $.get(link, function(data) { data = JSON.parse(data); + if(docType == 'docTemplate') + { + data = data.filter(function(item) + { + return item.value != 0; + }); + } const $modulePicker = $("[name='module']").zui('picker'); $modulePicker.render({items: data}); diff --git a/module/doc/model.php b/module/doc/model.php index fd7d35f2d1..87d4836686 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3716,14 +3716,8 @@ class docModel extends model foreach($modules as $module) { - if($module->parent === 0) - { - $module->fullName = $module->name; - continue; - } $path = explode(',', trim($module->path, ',')); - - $names = array(); + $names = array(''); foreach($path as $id) { if(!isset($modules[$id])) continue; diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 51e00a94fc..8835b3100e 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -10,8 +10,13 @@ declare(strict_types=1); */ namespace zin; -$modules = $this->doc->getTemplateModules($libID); -$modules = array_column($modules, 'fullName', 'id'); +$optionMenu = $this->tree->getOptionMenu($libID, 'docTemplate', 0, 'all', 'nodeleted', 'all'); +$modules = array(); +foreach($optionMenu as $menuID => $menu) +{ + if($menuID == 0) continue; + $modules[] = array('text' => $menu, 'value' => $menuID, 'keys' => $menu); +} formPanel ( @@ -20,8 +25,7 @@ formPanel setData('docType', isset($doc) ? $doc->users : 'undefined'), set::title($title), set::submitBtnText($isDraft ? $lang->doc->saveDraft : (empty($docID) ? $lang->doc->release : $lang->save)), - on::change('[name=lib]')->call('loadLibModules', jsRaw('event')), - on::change('[name=lib],[name^=users]', 'checkLibPriv'), + on::change('[name=lib]')->call('loadLibModules', jsRaw("event, 'docTemplate'")), set::ajax(array('beforeSubmit' => jsRaw('window.beforeSetDocBasicInfo'))), formGroup ( From 0c282bf6a3ea4a2d10405659b3bb936d9dcfa9b3 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 02:19:28 +0000 Subject: [PATCH 127/655] * [bug#57067,0.5h] fix action lang. --- module/action/lang/de.php | 1 + module/action/lang/en.php | 1 + module/action/lang/fr.php | 1 + module/action/lang/zh-cn.php | 1 + module/doc/zen.php | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 5af9ebcc89..94a9cfced7 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -131,6 +131,7 @@ $lang->action->objectTypes['doc'] = 'Dok'; $lang->action->objectTypes['api'] = 'Interface'; $lang->action->objectTypes['doclib'] = 'Dok Bibliothek'; $lang->action->objectTypes['docspace'] = 'Dok Space'; +$lang->action->objectTypes['doctemplate'] = '文档模板'; $lang->action->objectTypes['apistruct'] = 'API struct'; $lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['risk'] = 'Risk'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 35bdfc41b6..5e0027be1a 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -131,6 +131,7 @@ $lang->action->objectTypes['doc'] = 'Document'; $lang->action->objectTypes['api'] = 'Interface'; $lang->action->objectTypes['doclib'] = 'Document Library'; $lang->action->objectTypes['docspace'] = 'Document Space'; +$lang->action->objectTypes['doctemplate'] = '文档模板'; $lang->action->objectTypes['apistruct'] = 'API struct'; $lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['risk'] = 'Risk'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 69d117376e..f6f2f926fd 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -131,6 +131,7 @@ $lang->action->objectTypes['doc'] = 'Document'; $lang->action->objectTypes['api'] = 'Interface'; $lang->action->objectTypes['doclib'] = 'Répertoire Documents'; $lang->action->objectTypes['docspace'] = 'Répertoire Space'; +$lang->action->objectTypes['doctemplate'] = '文档模板'; $lang->action->objectTypes['apistruct'] = 'API struct'; $lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['risk'] = 'Risk'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 6eda9e2d09..4da947f213 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -131,6 +131,7 @@ $lang->action->objectTypes['doc'] = '文档'; $lang->action->objectTypes['api'] = '接口'; $lang->action->objectTypes['doclib'] = '文档库'; $lang->action->objectTypes['docspace'] = '文档空间'; +$lang->action->objectTypes['doctemplate'] = '文档模板'; $lang->action->objectTypes['apistruct'] = '数据结构'; $lang->action->objectTypes['todo'] = '待办'; $lang->action->objectTypes['risk'] = '风险'; diff --git a/module/doc/zen.php b/module/doc/zen.php index 05358ebb62..f2f49c3b22 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -407,7 +407,7 @@ class docZen extends doc $fileAction = ''; if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; - $actionType = $_POST['status'] == 'draft' ? 'savedTemplateDraft' : 'releasedTemplate'; + $actionType = $_POST['status'] == 'draft' ? 'savedDraft' : 'released'; $this->action->create('docTemplate', $docID, $actionType, $fileAction); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); From 9d32cef863b0079346e6e28de0270785265e2630 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 15 Nov 2024 05:23:22 +0000 Subject: [PATCH 128/655] * [task#131767,done,0.5h] Check privilege. --- module/doc/js/browsetemplate.ui.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 16d6533e22..68d191a13e 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -35,10 +35,12 @@ function getTableOptions(options, info) col.actions = col.actions.filter(action => action !== 'move'); delete col.actionsMap.move; + const privMap = {edit: docAppHasPriv('edit'), delete: docAppHasPriv('delete')}; const actionHints = {edit: lang.editTemplate, delete: lang.deleteTemplate}; $.each(col.actionsMap, (key, value) => { if(typeof actionHints[key] === 'string') value.hint = actionHints[key]; + value.disabled = !privMap[key]; }); } }); From 06dfb58ff5255098b6e947abe055bd9a674f08a4 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 03:28:18 +0000 Subject: [PATCH 129/655] * [bug#56928,0.5h] fix trash lang. --- config/zentaopms.php | 1 + module/action/config.php | 1 + module/action/zen.php | 6 ++++-- module/doc/control.php | 2 +- module/doc/js/browsetemplate.ui.js | 16 ++++++++++++++++ module/doc/model.php | 20 ++++++++++++++++++++ 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/config/zentaopms.php b/config/zentaopms.php index b7f3458b30..76796d215a 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -651,6 +651,7 @@ $config->objectTables['api'] = TABLE_API; $config->objectTables['doc'] = TABLE_DOC; $config->objectTables['doclib'] = TABLE_DOCLIB; $config->objectTables['docspace'] = TABLE_DOCLIB; +$config->objectTables['doctemplate'] = TABLE_DOC; $config->objectTables['demand'] = TABLE_DEMAND; $config->objectTables['demandpool'] = TABLE_DEMANDPOOL; $config->objectTables['demandspec'] = TABLE_DEMANDSPEC; diff --git a/module/action/config.php b/module/action/config.php index 5eedf8abf1..54226c4f47 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -22,6 +22,7 @@ $config->action->objectNameFields['boardspace'] = 'name'; $config->action->objectNameFields['doc'] = 'title'; $config->action->objectNameFields['doclib'] = 'name'; $config->action->objectNameFields['docspace'] = 'name'; +$config->action->objectNameFields['doctemplate'] = 'title'; $config->action->objectNameFields['todo'] = 'name'; $config->action->objectNameFields['branch'] = 'name'; $config->action->objectNameFields['module'] = 'name'; diff --git a/module/action/zen.php b/module/action/zen.php index c1f43b644c..2f98c23f0d 100644 --- a/module/action/zen.php +++ b/module/action/zen.php @@ -88,12 +88,14 @@ class actionZen extends action if($trash->objectType == 'pivot') { $pivotNames = json_decode($trash->objectName, true); + if(empty($pivotNames)) return; $trash->objectName = zget($pivotNames, $this->app->getClientLang(), '') ? : reset(array_filter($pivotNames)); } else { - $module = $trash->objectType == 'case' ? 'testcase' : $trash->objectType; - $params = $trash->objectType == 'user' ? "account={$trash->objectName}" : "id={$trash->objectID}"; + $module = $trash->objectType == 'case' ? 'testcase' : $trash->objectType; + $module = $trash->objectType == 'doctemplate' ? 'doc' : $trash->objectType; + $params = $trash->objectType == 'user' ? "account={$trash->objectName}" : "id={$trash->objectID}"; $methodName = 'view'; if($module == 'basicmeas') { diff --git a/module/doc/control.php b/module/doc/control.php index 1e5b6784ef..e2aa94b8dc 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -728,7 +728,7 @@ class doc extends control */ public function deleteTemplate(int $templateID) { - $this->doc->delete(TABLE_DOC, $templateID); + $this->doc->deleteTemplate($templateID); /* Delete template files. */ $template = $this->doc->getByID($templateID); diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 68d191a13e..418241f54e 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -342,6 +342,22 @@ window.setDocAppOptions = function(_, options) // Override the method. /* 扩展文档模板命令定义。 Extend the doc app command definition. */ $.extend(window.docAppCommands, { + deleteDoc: function(_, args) + { + const docApp = getDocApp(); + const docID = args[0] || docApp.docID; + + $.ajaxSubmit( + { + confirm: getLang('confirmDelete'), + url: $.createLink('doc', 'deleteTemplate', `docID=${docID}`), + load: false, + onSuccess: function() + { + getDocApp().delete('doc', docID); + } + }); + }, addModule: function(_, args) { const docApp = getDocApp(); diff --git a/module/doc/model.php b/module/doc/model.php index 87d4836686..5c09a37cbc 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3802,6 +3802,26 @@ class docModel extends model return false; } + /** + * 删除一个文档模板。 + * Delete a doc template. + * + * @param string $table + * @param int $id + * @param string $objectType + * @access public + * @return void + */ + public function deleteTemplate(int $id) + { + if(empty($id)) return false; + + $this->dao->update(TABLE_DOC)->set('deleted')->eq(1)->where('id')->eq($id)->exec(); + $this->loadModel('action')->create('doctemplate', $id, 'deleted', '', ACTIONMODEL::CAN_UNDELETED); + + return true; + } + /** * 添加文档模板类型。 * Add template type. From e76c0a85bbfb1446524d88ae9efb6f7cd46b8eb1 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 05:10:47 +0000 Subject: [PATCH 130/655] * [task#132523,0.5h] hide footer. --- module/doc/js/browsetemplate.ui.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 418241f54e..c183b7f976 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -271,6 +271,10 @@ const customRenders = if(docAppHasPriv('create')) items.push({text: getDocAppLang('createTemplate'), icon: 'plus', btnType: 'primary', url: url}); return {component: 'toolbar', props: {items: items}}; } + }, + 'sidebar-footer-hint': function() + { + return ''; } } From a089af6eb2ecdf0bb059b61037435cc8e982d8f7 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 15 Nov 2024 13:48:49 +0800 Subject: [PATCH 131/655] * [task#132516,done,0.2h] reload page after add template type. --- module/doc/zen.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/zen.php b/module/doc/zen.php index f2f49c3b22..391b7718f9 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -1064,7 +1064,7 @@ class docZen extends doc */ public function responseAfterAddTemplateType(int $scope) { - $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'browseTemplate', "libID={$scope}")); + $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true); return $this->send($response); } } From 6899286506aa81b7f7c3bad1e02ea60ea14faccd Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 15 Nov 2024 14:08:24 +0800 Subject: [PATCH 132/655] * [task#132520,done,0.2h] delete sub module when delete parent module. --- module/doc/control.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index e2aa94b8dc..309230264e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -410,7 +410,8 @@ class doc extends control $templates = $this->doc->getTemplatesByType($moduleID); if(empty($templates)) { - $this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('id')->eq($moduleID)->exec(); + $this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('id')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec(); + $this->dao->update(TABLE_MODULE)->set('deleted')->eq('1')->where('parent')->eq($moduleID)->andWhere('type')->eq('docTemplate')->exec(); return $this->sendSuccess(array('load' => true)); } else From ee8c293a9298d654480351c82d0826764849bc96 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 15 Nov 2024 14:37:27 +0800 Subject: [PATCH 133/655] * [bug#57085,done,0.3h] get templates by type include sub type's. --- module/doc/model.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 5c09a37cbc..e5e4a9ca27 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3851,10 +3851,18 @@ class docModel extends model */ public function getTemplatesByType($type) { + $subTypes = $this->dao->select('id')->from(TABLE_MODULE) + ->where('deleted')->eq('0') + ->andWhere('parent')->eq($type) + ->andWhere('type')->eq('docTemplate') + ->fetchPairs('id'); + $types = array_values($subTypes); + $types[] = $type; + return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq('0') ->andWhere('templateType')->ne('') - ->andWhere('module')->eq($type) + ->andWhere('module')->in($types) ->fetchAll('id'); } } From de05082466ccde4115d1465036bdb5a4b57263d3 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 15 Nov 2024 15:51:45 +0800 Subject: [PATCH 134/655] * [bug#57011,done,0.2h] adjust lang. --- module/doc/lang/de.php | 2 +- module/doc/lang/en.php | 2 +- module/doc/lang/fr.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 2b71cb0256..03e41d1e72 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -92,7 +92,7 @@ $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; $lang->docTemplate->docTitleRequired = 'Please enter the document title.'; -$lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->create = 'Create Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 47cfa3fb6c..41a0d89d64 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -92,7 +92,7 @@ $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; $lang->docTemplate->docTitleRequired = 'Please enter the document title.'; -$lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->create = 'Create Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 6d7b558286..99b4e8e850 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -92,7 +92,7 @@ $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; $lang->docTemplate->docTitleRequired = 'Please enter the document title.'; -$lang->docTemplate->noticeAddTemplateType = 'Supports up to two levels of types. Built-in document template types participate in logical operations so their positions cannot be modified.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->create = 'Create Template'; From a2fc0c95d445d95f626a4ce6a3011c1f1a3a0f5c Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Fri, 15 Nov 2024 16:06:54 +0800 Subject: [PATCH 135/655] *[bug#56764. --- module/bi/config/metrics.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/bi/config/metrics.php b/module/bi/config/metrics.php index 6027a796f9..f55f0fdbc1 100644 --- a/module/bi/config/metrics.php +++ b/module/bi/config/metrics.php @@ -4666,7 +4666,7 @@ $config->bi->builtin->metrics[] = array $config->bi->builtin->metrics[] = array ( 'name' => '按项目统计的月度修复Bug数', - 'alias' => '解决Bug数', + 'alias' => '修复Bug数', 'code' => 'count_of_monthly_fixed_bug_in_project', 'purpose' => 'scale', 'scope' => 'project', From c9e61e00e3d5153b28b9c611d7fda3b0ddf6da0f Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 15 Nov 2024 08:39:57 +0000 Subject: [PATCH 136/655] * [bug#57012,0.5h] fix error. --- module/doc/control.php | 1 + module/tree/control.php | 1 + 2 files changed, 2 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index 309230264e..cb9128d33c 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -366,6 +366,7 @@ class doc extends control if(!empty($_POST)) { + $this->lang->doc->name = $this->lang->docTemplate->typeName; $moduleData = form::data($this->config->doc->form->addTemplateType) ->setDefault('type', 'docTemplate') ->setDefault('path', '') diff --git a/module/tree/control.php b/module/tree/control.php index f0d984b79c..bfbf6b44f0 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -173,6 +173,7 @@ class tree extends control if(!empty($_POST)) { + if($type == 'docTemplate') $this->lang->tree->name = $this->lang->docTemplate->typeName; $this->tree->update($moduleID, $type); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); From 253694607ecf6b910b020c519865621236097323 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Fri, 15 Nov 2024 16:28:43 +0800 Subject: [PATCH 137/655] *[bug#56916,0.5h]. --- module/doc/model.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 2b009028b9..4eb9bbca0e 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3771,11 +3771,12 @@ class docModel extends model public function getHotTemplates($scopeID = 0, $limit = 0) { - return $this->dao->select('*')->from(TABLE_DOC) + return $this->dao->select('*, CASE WHEN addedDate > editedDate THEN addedDate ELSE editedDate END as hotDate')->from(TABLE_DOC) ->where('templateType')->ne('') ->andWhere('deleted')->eq('0') + ->andWhere('status')->eq('normal') ->beginIF($scopeID)->andWhere('lib')->eq($scopeID)->fi() - ->orderBy('addedDate_desc,editedDate_desc') + ->orderBy('hotDate_desc') ->beginIF($limit)->limit($limit)->fi() ->fetchAll(); } From dbeb39b53ee6dc900bc7539ad5ff404311ed4e38 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 15 Nov 2024 17:01:29 +0800 Subject: [PATCH 138/655] * [misc] add required label. --- module/doc/ui/addtemplatetype.html.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/ui/addtemplatetype.html.php b/module/doc/ui/addtemplatetype.html.php index d081004a96..74d8541a03 100644 --- a/module/doc/ui/addtemplatetype.html.php +++ b/module/doc/ui/addtemplatetype.html.php @@ -67,6 +67,7 @@ formPanel ), formGroup ( + set::required(true), set::name('name'), set::label($lang->docTemplate->typeName), set::control('input') From 495bc3dd8d4a31e42634c615455afa9fd5d83623 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 19 Nov 2024 00:47:59 +0000 Subject: [PATCH 139/655] * [bug#57094,0.1h] refresh after delete template type. --- module/doc/js/browsetemplate.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index c183b7f976..837e54dbcb 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -384,7 +384,7 @@ $.extend(window.docAppCommands, $.ajaxSubmit( { url: $.createLink('doc', 'deleteTemplateType', `moduleID=${moduleID}`), - load:false + load: true }) }, /** From 393377443c8c66e3c0b4829f175feb24ca811338 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 19 Nov 2024 01:12:03 +0000 Subject: [PATCH 140/655] * [bug#57079,0.5h] fix edit template error. --- module/doc/zen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/zen.php b/module/doc/zen.php index 391b7718f9..ffc685eeef 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -666,7 +666,7 @@ class docZen extends doc $fileAction = ''; if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionID = $this->action->create('doc', $doc->id, $action, $fileAction . $this->post->comment); - if(!empty($changes)) $this->action->logHistory($actionID, $changes); + if(!empty($changes) && !empty($actionID)) $this->action->logHistory($actionID, $changes); } $link = $this->createLink('doc', 'view', "docID={$doc->id}"); @@ -718,7 +718,7 @@ class docZen extends doc $fileAction = ''; if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionID = $this->action->create('docTemplate', $doc->id, $action, $fileAction . $this->post->comment); - if(!empty($changes)) $this->action->logHistory($actionID, $changes); + if(!empty($changes) && !empty($actionID)) $this->action->logHistory($actionID, $changes); } $link = $this->createLink('doc', 'view', "docID={$doc->id}"); From caa2bd49eaef0e8caecfb95d55acb1a006e03662 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 19 Nov 2024 01:26:38 +0000 Subject: [PATCH 141/655] * [bug#57079,0.5h] fix sonar. --- module/doc/control.php | 2 +- module/doc/zen.php | 42 ++++++++---------------------------------- 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 014251e303..48cd45a690 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -457,7 +457,7 @@ class doc extends control $docResult = $this->doc->create($docData, $this->post->labels); if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->docZen->responseAfterCreateTemplate($docData->lib, $docResult); + return $this->docZen->responseAfterCreate($docResult, 'docTemplate'); } } diff --git a/module/doc/zen.php b/module/doc/zen.php index ffc685eeef..286fabc2d7 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -367,7 +367,7 @@ class docZen extends doc * @access protected * @return void */ - protected function responseAfterCreate(array $docResult) + protected function responseAfterCreate(array $docResult, string $objectType = 'doc') { $docID = $docResult['id']; $files = zget($docResult, 'files', ''); @@ -376,47 +376,20 @@ class docZen extends doc if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionType = $_POST['status'] == 'draft' ? 'savedDraft' : 'releasedDoc'; - $this->action->create('doc', $docID, $actionType, $fileAction); + $this->action->create($objectType, $docID, $actionType, $fileAction); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); $response = array( 'result' => 'success', 'message' => $this->lang->saveSuccess, - 'load' => $this->createLink('doc', 'view', "docID={$docResult['id']}"), + 'load' => $this->createLink('doc', $objectType == 'doc' ? 'view' : 'browseTemplate', "docID={$docResult['id']}"), 'id' => $docID, 'doc' => $docResult ); return $this->send($response); } - /** - * 在创建文档模板后的返回。 - * Return after create a document template. - * - * @param int $libID - * @param array $docResult - * @access protected - * @return bool|int - */ - protected function responseAfterCreateTemplate(int $libID, array $docResult): bool|int - { - $docID = $docResult['id']; - $files = zget($docResult, 'files', ''); - - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; - - $actionType = $_POST['status'] == 'draft' ? 'savedDraft' : 'released'; - $this->action->create('docTemplate', $docID, $actionType, $fileAction); - - if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); - $params = "docID=" . $docResult['id']; - $response = array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'browseTemplate', $params), 'id' => $docID, 'doc' => $docResult); - - return $this->send($response); - } - /** * 在移动库或文档后的返回。 * Return after move lib or doc. @@ -440,10 +413,11 @@ class docZen extends doc if($spaceTypeChanged) { - if($spaceType == 'mine') $locateLink = $this->createLink('doc', 'mySpace', "objectID={$spaceID}&libID={$libID}"); - elseif($spaceType == 'custom') $locateLink = $this->createLink('doc', 'teamSpace', "objectID={$spaceID}&libID={$libID}"); - elseif($spaceType == 'product') $locateLink = $this->createLink('doc', 'productSpace', "objectID={$spaceID}&libID={$libID}"); - elseif($spaceType == 'project') $locateLink = $this->createLink('doc', 'projectSpace', "objectID={$spaceID}&libID={$libID}"); + $method = 'mySpace'; + if($spaceType == 'custom') $method = 'teamSpace'; + if($spaceType == 'product') $method = 'productSpace'; + if($spaceType == 'project') $method = 'projectSpace'; + $locateLink = $this->createLink('doc', $method, "objectID={$spaceID}&libID={$libID}"); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => $locateLink)); } else From 271a70f8fc85a5e4fe628954f02c3397bcec5cd9 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 19 Nov 2024 05:25:16 +0000 Subject: [PATCH 142/655] * [task#132871,done,1h] Adjust cols. --- module/doc/js/browsetemplate.ui.js | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 837e54dbcb..043f531798 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -16,16 +16,28 @@ function getTableOptions(options, info) templateCols = []; templateCols.push({...options.cols.find(col => col.name === 'rawID'), type: 'id'}); - let title = options.cols.find(col => col.name == 'title'); - title.title = lang.tableCols.title; + let title = options.cols.find(col => col.name == 'title'); + let addedBy = options.cols.find(col => col.name == 'addedBy'); + let addedDate = options.cols.find(col => col.name == 'addedDate'); + let editedBy = options.cols.find(col => col.name == 'editedBy'); + let editedDate = options.cols.find(col => col.name == 'editedDate'); + let actionsCol = options.cols.find(col => col.name == 'actions'); + let typeCol = {name: 'moduleName', title: lang.tableCols.type, type: 'string', sort: true}; + let viewsCol = {name: 'views', title: lang.tableCols.views, type: 'number', sort: true}; + + title.title = lang.tableCols.title; + addedDate.title = lang.tableCols.addedDate; + editedBy.title = lang.tableCols.editedBy; + editedDate.title = lang.tableCols.editedDate; + templateCols.push(title); - templateCols.push({name: 'moduleName', title: lang.tableCols.type, type: 'string', sort: true}); - templateCols.push(options.cols.find(col => col.name == 'addedBy')); - templateCols.push(options.cols.find(col => col.name == 'addedDate')); - templateCols.push(options.cols.find(col => col.name == 'editedBy')); - templateCols.push(options.cols.find(col => col.name == 'editedDate')); - templateCols.push({name: 'views', title: lang.tableCols.views, type: 'number', sort: true}); - templateCols.push(options.cols.find(col => col.name == 'actions')); + templateCols.push(typeCol); + templateCols.push(addedBy); + templateCols.push(addedDate); + templateCols.push(editedBy); + templateCols.push(editedDate); + templateCols.push(viewsCol); + templateCols.push(actionsCol); options.cols = templateCols; options.cols.forEach(col => From 208c5828048a83c28cb3fdc05470a4b3fb964e4b Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 19 Nov 2024 08:01:02 +0000 Subject: [PATCH 143/655] * [bug] fix merge. --- module/doc/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 9bbc5db8eb..83e008da65 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1466,10 +1466,10 @@ class docModel extends model if(empty($doc->lib) && strpos((string)$doc->module, '_') !== false) list($doc->lib, $doc->module) = explode('_', $doc->module); if(empty($doc->lib)) return dao::$errors['lib'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib); + if($doc->contentType != 'doc') $doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], (string)$this->post->uid); if($type == 'doc') { $lib = $this->getLibByID($doc->lib); - if($doc->contentType != 'doc') $doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], (string)$this->post->uid); $doc->product = $lib->product; $doc->project = $lib->project; $doc->execution = $lib->execution; From df6701157795a89d74d2a8f126e5107a47449856 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 19 Nov 2024 08:16:30 +0000 Subject: [PATCH 144/655] * [story#68005,doing,2h] Add view priviledge. --- module/doc/js/browsetemplate.ui.js | 2 +- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/model.php | 1 + module/doc/ui/templatelist.html.php | 1 + module/group/packagemanager.php | 1 + 8 files changed, 8 insertions(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 043f531798..ba2f0bdfc0 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -351,7 +351,7 @@ window.setDocAppOptions = function(_, options) // Override the method. onCreateDoc : handleCreateDoc, onSaveDoc : handleSaveDoc, getTableOptions : getTableOptions, - customRenders : customRenders + customRenders : $.extend(docAppCustomRenders, customRenders) }); }; diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 03e41d1e72..6586238723 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -499,6 +499,7 @@ $lang->doc->browseTemplate = 'Template Square'; $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; +$lang->doc->viewTemplate = 'View Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 41a0d89d64..6b6665e405 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -499,6 +499,7 @@ $lang->doc->browseTemplate = 'Template Square'; $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; +$lang->doc->viewTemplate = 'View Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 99b4e8e850..1608c0363e 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -499,6 +499,7 @@ $lang->doc->browseTemplate = 'Template Square'; $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; +$lang->doc->viewTemplate = 'View Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index ef3199ee61..f3001b4eec 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -499,6 +499,7 @@ $lang->doc->browseTemplate = '模板广场'; $lang->doc->createTemplate = '创建文档模板'; $lang->doc->editTemplate = '编辑文档模板'; $lang->doc->deleteTemplate = '删除文档模板'; +$lang->doc->viewTemplate = '文档模板详情'; $lang->doc->addTemplateType = '添加类型'; $lang->doc->editTemplateType = '编辑类型'; $lang->doc->deleteTemplateType = '删除类型'; diff --git a/module/doc/model.php b/module/doc/model.php index 83e008da65..8c5679577d 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -647,6 +647,7 @@ class docModel extends model * 获取文档模板列表。 * Get document template list. * + * @param int $libID * @param string $type * @param string $orderBy * @param object $pager diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 4ba8bdb091..1b8fa162cf 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -20,6 +20,7 @@ $privs = array(); $privs['create'] = hasPriv('doc', 'createTemplate'); $privs['edit'] = hasPriv('doc', 'editTemplate'); $privs['delete'] = hasPriv('doc', 'deleteTemplate'); +$privs['view'] = hasPriv('doc', 'viewTemplate'); $privs['addModule'] = hasPriv('doc', 'addTemplateType'); $privs['editModule'] = hasPriv('doc', 'editTemplateType'); $privs['deleteModule'] = hasPriv('doc', 'deleteTemplateType'); diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index a08a9f201a..d107893f48 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2921,6 +2921,7 @@ $config->group->package->browseDoctemplate->order = 5; $config->group->package->browseDoctemplate->subset = 'doctemplate'; $config->group->package->browseDoctemplate->privs = array(); $config->group->package->browseDoctemplate->privs['doc-browseTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); +$config->group->package->browseDoctemplate->privs['doc-viewTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array(), 'recommend' => array()); $config->group->package->manageDoctemplate = new stdclass(); $config->group->package->manageDoctemplate->order = 15; From 5dde78c8068c22d35aa64298a206b72462f31bcf Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 19 Nov 2024 09:20:30 +0000 Subject: [PATCH 145/655] * [task#132871,done,0.5h] Adjust english lang. --- module/doc/js/browsetemplate.ui.js | 2 ++ module/doc/ui/templatelist.html.php | 1 + 2 files changed, 3 insertions(+) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index ba2f0bdfc0..af5986225d 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -26,9 +26,11 @@ function getTableOptions(options, info) let viewsCol = {name: 'views', title: lang.tableCols.views, type: 'number', sort: true}; title.title = lang.tableCols.title; + addedBy.title = lang.tableCols.addedBy; addedDate.title = lang.tableCols.addedDate; editedBy.title = lang.tableCols.editedBy; editedDate.title = lang.tableCols.editedDate; + actionsCol.title = lang.tableCols.actions; templateCols.push(title); templateCols.push(typeCol); diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 1b8fa162cf..bed02a9207 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -39,6 +39,7 @@ $tableCols['addedDate'] = $lang->docTemplate->addedDate; $tableCols['editedBy'] = $lang->docTemplate->editedBy; $tableCols['editedDate'] = $lang->docTemplate->editedDate; $tableCols['views'] = $lang->docTemplate->views; +$tableCols['actions'] = $lang->actions; $langData = array(); $langData['filterTypes'] = $filterTypes; From 498d2db15d3a6bb7800ee0bdfd12fc9325d686c4 Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Wed, 20 Nov 2024 10:29:01 +0800 Subject: [PATCH 146/655] *[bug#56928, 0.5h]. --- module/action/lang/de.php | 2 +- module/action/lang/en.php | 2 +- module/action/lang/fr.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 55aa8a7e7e..943c744abd 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -131,7 +131,7 @@ $lang->action->objectTypes['doc'] = 'Dok'; $lang->action->objectTypes['api'] = 'Interface'; $lang->action->objectTypes['doclib'] = 'Dok Bibliothek'; $lang->action->objectTypes['docspace'] = 'Dok Space'; -$lang->action->objectTypes['doctemplate'] = '文档模板'; +$lang->action->objectTypes['doctemplate'] = 'Doc Template'; $lang->action->objectTypes['apistruct'] = 'API struct'; $lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['risk'] = 'Risk'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index a4b0ccf840..92c0d2b3bd 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -131,7 +131,7 @@ $lang->action->objectTypes['doc'] = 'Document'; $lang->action->objectTypes['api'] = 'Interface'; $lang->action->objectTypes['doclib'] = 'Document Library'; $lang->action->objectTypes['docspace'] = 'Document Space'; -$lang->action->objectTypes['doctemplate'] = '文档模板'; +$lang->action->objectTypes['doctemplate'] = 'Doc Template'; $lang->action->objectTypes['apistruct'] = 'API struct'; $lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['risk'] = 'Risk'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index e6f4c306cf..6fd3b49a97 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -131,7 +131,7 @@ $lang->action->objectTypes['doc'] = 'Document'; $lang->action->objectTypes['api'] = 'Interface'; $lang->action->objectTypes['doclib'] = 'Répertoire Documents'; $lang->action->objectTypes['docspace'] = 'Répertoire Space'; -$lang->action->objectTypes['doctemplate'] = '文档模板'; +$lang->action->objectTypes['doctemplate'] = 'Doc Template'; $lang->action->objectTypes['apistruct'] = 'API struct'; $lang->action->objectTypes['todo'] = 'Todo'; $lang->action->objectTypes['risk'] = 'Risk'; From ef341c1e41c83d5ea409fc5684f93b912d4f14d2 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Wed, 20 Nov 2024 03:03:15 +0000 Subject: [PATCH 147/655] * [bug#57094,0.5h] fix bug. --- module/doc/js/browsetemplate.ui.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index af5986225d..10e23331a7 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -398,7 +398,11 @@ $.extend(window.docAppCommands, $.ajaxSubmit( { url: $.createLink('doc', 'deleteTemplateType', `moduleID=${moduleID}`), - load: true + load: false, + onSuccess: function() + { + getDocApp().delete('module', moduleID); + } }) }, /** From 7d0d612b6f1852c8c9de2fa6f8d09328e3b8b09f Mon Sep 17 00:00:00 2001 From: songchenxuan Date: Wed, 20 Nov 2024 11:14:07 +0800 Subject: [PATCH 148/655] [bug#56923,0.5h] update en lang. --- module/doc/lang/de.php | 2 +- module/doc/lang/en.php | 2 +- module/doc/lang/fr.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 6586238723..c0c8d44034 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -91,7 +91,7 @@ $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the document title.'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; $lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 6b6665e405..4f9cac921b 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -91,7 +91,7 @@ $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the document title.'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; $lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 1608c0363e..fb8475d263 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -91,7 +91,7 @@ $lang->docTemplate->typeName = 'Type Name'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the document title.'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; $lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; From ebf9847e341775960235c77390ec3a1700854c08 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 22 Nov 2024 02:03:21 +0000 Subject: [PATCH 149/655] * [bug#57077,0.2h] fix action. --- module/doc/zen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/zen.php b/module/doc/zen.php index 286fabc2d7..ffbd4a89c3 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -376,7 +376,7 @@ class docZen extends doc if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionType = $_POST['status'] == 'draft' ? 'savedDraft' : 'releasedDoc'; - $this->action->create($objectType, $docID, $actionType, $fileAction); + $this->action->create('doc', $docID, $actionType, $fileAction); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); @@ -691,7 +691,7 @@ class docZen extends doc $fileAction = ''; if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; - $actionID = $this->action->create('docTemplate', $doc->id, $action, $fileAction . $this->post->comment); + $actionID = $this->action->create('doc', $doc->id, $action, $fileAction . $this->post->comment); if(!empty($changes) && !empty($actionID)) $this->action->logHistory($actionID, $changes); } From cc86c93af1a2dbdd451c5988a854fd3d29c0c38d Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 22 Nov 2024 06:01:15 +0000 Subject: [PATCH 150/655] Revert "* [bug#57077,0.2h] fix action." This reverts commit ebf9847e341775960235c77390ec3a1700854c08. --- module/doc/zen.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/zen.php b/module/doc/zen.php index ffbd4a89c3..286fabc2d7 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -376,7 +376,7 @@ class docZen extends doc if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; $actionType = $_POST['status'] == 'draft' ? 'savedDraft' : 'releasedDoc'; - $this->action->create('doc', $docID, $actionType, $fileAction); + $this->action->create($objectType, $docID, $actionType, $fileAction); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID)); @@ -691,7 +691,7 @@ class docZen extends doc $fileAction = ''; if(!empty($files)) $fileAction = $this->lang->addFiles . implode(',', $files) . "\n"; - $actionID = $this->action->create('doc', $doc->id, $action, $fileAction . $this->post->comment); + $actionID = $this->action->create('docTemplate', $doc->id, $action, $fileAction . $this->post->comment); if(!empty($changes) && !empty($actionID)) $this->action->logHistory($actionID, $changes); } From 39c8f8b45d8dcd19d2f7ac3a5cc2ff9975df5a49 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Fri, 22 Nov 2024 07:35:10 +0000 Subject: [PATCH 151/655] * [bug#57077,0.2h] fix history. --- module/doc/ui/templatelist.html.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index bed02a9207..03fbdddf9b 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -76,6 +76,7 @@ docApp set::homeName($lang->doc->template), set::mode($mode), set::fetcher(createLink('doc', 'ajaxGetSpaceData', 'type=template&spaceID=1&picks={picks}')), + set::historyFetcher(createLink('action', 'ajaxGetList', 'objectType=docTemplate&objectID={objectID}')), set::privs($privs), set::userMap($users), set::spaceIcon(false), From dce04d36442d62afd71dd8af194afef14ad51927 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Fri, 29 Nov 2024 09:42:07 +0800 Subject: [PATCH 152/655] * [bug#57354,done,0.5h] ad dynamic link for doc template. --- module/action/lang/de.php | 1 + module/action/lang/en.php | 1 + module/action/lang/fr.php | 1 + module/action/lang/zh-cn.php | 1 + 4 files changed, 4 insertions(+) diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 173d1d44b9..f950442c53 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -901,6 +901,7 @@ $lang->action->label->todo = 'Todo|todo|view|todoID=%s'; $lang->action->label->doclib = 'Dok Bibliothek|doc|teamspace|objectID=%s&libID=%s'; $lang->action->label->docspace = 'Dok Space'; $lang->action->label->doc = 'Dok|doc|view|docID=%s'; +$lang->action->label->doctemplate = 'Doc Template|doc|view|docID=%s'; $lang->action->label->user = 'Benutzer|user|view|account=%s'; $lang->action->label->testreport = 'Berichte|testreport|view|report=%s'; $lang->action->label->entry = 'Eintrag|entry|browse|'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 0a3dd19b74..0ff0ef03f7 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -901,6 +901,7 @@ $lang->action->label->todo = 'Todo|todo|view|todoID=%s'; $lang->action->label->doclib = 'Doc Library|doc|teamspace|objectID=%s&libID=%s'; $lang->action->label->docspace = 'Doc Space'; $lang->action->label->doc = 'Doc|doc|view|docID=%s'; +$lang->action->label->doctemplate = 'Doc Template|doc|view|docID=%s'; $lang->action->label->user = 'User|user|view|account=%s'; $lang->action->label->testreport = 'Report|testreport|view|report=%s'; $lang->action->label->entry = 'Application|entry|browse|'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index b5ee1bd1b7..5015240289 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -901,6 +901,7 @@ $lang->action->label->todo = 'Agenda|todo|view|todoID=%s'; $lang->action->label->doclib = 'Bibliothèque|doc|teamspace|objectID=%s&libID=%s'; $lang->action->label->docspace = 'Doc Space'; $lang->action->label->doc = 'Document|doc|view|docID=%s'; +$lang->action->label->doctemplate = 'Doc Template|doc|view|docID=%s'; $lang->action->label->user = 'Utilisateur|user|view|account=%s'; $lang->action->label->testreport = 'Rapport|testreport|view|report=%s'; $lang->action->label->entry = 'Application|entry|browse|'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 8661fcb64c..6c43303a7a 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -903,6 +903,7 @@ $lang->action->label->todo = '待办|todo|view|todoID=%s'; $lang->action->label->doclib = '文档库|doc|teamspace|objectID=%s&libID=%s'; $lang->action->label->docspace = '文档空间'; $lang->action->label->doc = '文档|doc|view|docID=%s'; +$lang->action->label->doctemplate = '文档模板|doc|view|docID=%s'; $lang->action->label->user = '用户|user|view|account=%s'; $lang->action->label->testreport = '报告|testreport|view|report=%s'; $lang->action->label->entry = '应用|entry|browse|'; From 684d726816653cc7c619abf8ff84023ddedffe58 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 3 Dec 2024 02:06:13 +0000 Subject: [PATCH 153/655] * [task#133855,done,1h] Adjust doctemplate priviledge. --- module/group/packagemanager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index e650a4d3ba..af220c7d15 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2942,8 +2942,8 @@ $config->group->package->manageDoctemplate = new stdclass(); $config->group->package->manageDoctemplate->order = 15; $config->group->package->manageDoctemplate->subset = 'doctemplate'; $config->group->package->manageDoctemplate->privs = array(); -$config->group->package->manageDoctemplate->privs['doc-createTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-editTemplate')); -$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-createTemplate')); +$config->group->package->manageDoctemplate->privs['doc-createTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-editTemplate')); +$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-viewTemplate'), 'recommend' => array('doc-createTemplate')); $config->group->package->manageDoctemplate->privs['doc-addTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-editTemplateType')); $config->group->package->manageDoctemplate->privs['doc-editTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('doc-addTemplateType')); $config->group->package->manageDoctemplate->privs['doc-deleteTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array('')); From fd4439123bb5abcd4148d33234a472c4af02c672 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 10:26:34 +0800 Subject: [PATCH 154/655] * [task#133854,doing,0.5h] upgrade template types. --- module/doc/model.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 48f1b95b27..9637b752d0 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3772,6 +3772,35 @@ class docModel extends model return true; } + public function upgradeCustomTemplateModule() + { + $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch(); + $oldTemplateTypes = $this->dao->select('`key`,`value`')->from(TABLE_LANG) + ->where('module')->eq('baseline') + ->andWhere('section')->eq('objectList') + ->andWhere('system')->eq('0') + ->fetchPairs('`key`'); + + foreach($oldTemplateTypes as $key => $value) + { + $module = new stdclass(); + $module->root = 2; + $module->name = $value; + $module->parent = $projectOtherID; + $module->path = ''; + $module->grade = 2; + $module->type = 'docTemplate'; + $module->short = $key; + $this->dao->insert(TABLE_MODULE)->data($module)->exec(); + if(dao::isError()) return false; + + $moduleID = $this->dao->lastInsertID(); + $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$projectOtherID},{$moduleID},")->where('id')->eq($moduleID)->exec(); + } + + return true; + } + /** * 获取文档模板类型的模块。 * Get modules of doc template type. From 52372ea3e1e1dd44d8438752152017b2d77efefe Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 10:28:17 +0800 Subject: [PATCH 155/655] * [task#133854,doing,0.1h] add commit. --- module/doc/model.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 9637b752d0..661306fdb9 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3772,6 +3772,12 @@ class docModel extends model return true; } + /** + * Upgrade custom template types. + * + * @access public + * @return bool + */ public function upgradeCustomTemplateModule() { $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch(); From ce7b74e6b862c9377366fc78d62870337f968f54 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 10:29:14 +0800 Subject: [PATCH 156/655] * [task#133854,doing,0.1h] refactor. --- module/upgrade/control.php | 4 +++- module/upgrade/model.php | 11 ----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/module/upgrade/control.php b/module/upgrade/control.php index 42fd16f638..9ce569fe67 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -829,7 +829,9 @@ class upgrade extends control */ public function ajaxInsertBuiltinTemplateModule() { - $result = $this->upgrade->insertBuiltinTemplateModule(); + $this->loadModel('doc'); + $result = $this->doc->insertBuiltinTemplateModule() + $result = $this->doc->upgradeCustomTemplateModule(); if($result) echo 'ok'; if(!$result) echo dao::getError(); } diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 4adae5a8ee..c4bb127d44 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10036,17 +10036,6 @@ class upgradeModel extends model } } - /** - * Insert template module. - * - * @access public - * @return bool - */ - public function insertBuiltinTemplateModule() - { - return $this->loadModel('doc')->insertBuiltinTemplateModule(); - } - /** * 历史产品、项目绑定默认工作流模板。 * From d220cf196af62ac70f93ee1b92c2c79fe3bac463 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 13:48:49 +0800 Subject: [PATCH 157/655] * [task#133854,doing,0.5h] add config to map template from old to new. --- module/doc/config.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/module/doc/config.php b/module/doc/config.php index 488c3bb29d..af5711a4a0 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -222,3 +222,21 @@ $config->doc->templateModule[4]['plan']['personalWorkPlan'] = 'Personal work pla $config->doc->templateModule[4]['report'] = array(); $config->doc->templateModule[4]['report']['personalWorkSummaryReport'] = 'Personal work summary report'; $config->doc->templateModule[4]['report']['personalValueAnalysisReport'] = 'Personal value analysis report'; + +$config->doc->oldTemplateMap = array(); +$config->doc->oldTemplateMap['PP'] = array('scope' => 'project', 'parent' => 'plan', 'code' => 'Project plan'); +$config->doc->oldTemplateMap['QAP'] = array('scope' => 'project', 'parent' => 'plan', 'code' => 'Project quality assurance plan'); +$config->doc->oldTemplateMap['CMP'] = array('scope' => 'project', 'parent' => 'plan', 'code' => 'Project configuration management plan'); +$config->doc->oldTemplateMap['ITP'] = array('scope' => 'project', 'parent' => 'plan', 'code' => 'Project integration test plan'); +$config->doc->oldTemplateMap['STP'] = array('scope' => 'project', 'parent' => 'plan', 'code' => 'Project system test plan'); +$config->doc->oldTemplateMap['ERS'] = array('scope' => 'project', 'parent' => 'desc', 'code' => 'Business requirements statement'); +$config->doc->oldTemplateMap['URS'] = array('scope' => 'project', 'parent' => 'desc', 'code' => 'Project user requirements specification'); +$config->doc->oldTemplateMap['SRS'] = array('scope' => 'project', 'parent' => 'desc', 'code' => 'Project software requirements specification'); +$config->doc->oldTemplateMap['HLDS'] = array('scope' => 'project', 'parent' => 'desc', 'code' => 'Project summary design specification'); +$config->doc->oldTemplateMap['DDS'] = array('scope' => 'project', 'parent' => 'desc', 'code' => 'Project detailed design specification'); +$config->doc->oldTemplateMap['UM'] = array('scope' => 'project', 'parent' => 'desc', 'code' => 'Project user manual'); +$config->doc->oldTemplateMap['Code'] = array('scope' => 'project', 'parent' => 'dev', 'code' => 'Project code'); +$config->doc->oldTemplateMap['DBDS'] = array('scope' => 'project', 'parent' => 'dev', 'code' => 'Project database design document'); +$config->doc->oldTemplateMap['ADS'] = array('scope' => 'project', 'parent' => 'dev', 'code' => 'Project interface design document'); +$config->doc->oldTemplateMap['ITTC'] = array('scope' => 'project', 'parent' => 'test', 'code' => 'Project integration test cases'); +$config->doc->oldTemplateMap['STTC'] = array('scope' => 'project', 'parent' => 'test', 'code' => 'Project system test cases'); From 626b6e2d4398e4ec544b4a53656a694289bf1d89 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 14:03:38 +0800 Subject: [PATCH 158/655] * [task#133854,doing,0.5h] upgrade old template. --- module/doc/model.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 661306fdb9..2fccf03cbe 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3807,6 +3807,37 @@ class docModel extends model return true; } + public function upgradeDocTemplate() + { + $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch(); + $modulePairs = $this->dao->select('short,id')->from(TABLE_MODULE) + ->where('deleted')->eq(0) + ->andWhere('type')->eq('docTemplate') + ->fetchPairs(); + + $templateList = $this->dao->select('*')->from(TABLE_DOC) + ->where('deleted')->eq(0) + ->andWhere('templateType')->ne('') + ->andWhere('lib')->eq('') + ->andWhere('module')->eq('') + ->fetchAll('id'); + + foreach($templateList as $id => $template) + { + $belongBuiltinType = in_array($template->templateType, array_keys($this->config->doc->oldTemplateMap)); + if($belongBuiltinType) + { + $templateMap = $this->config->doc->oldTemplateTypes[$template->templateType]; + $scopeMaps = array_flip($this->config->scopeMaps); + } + + $template->lib = $belongBuiltinType ? $scopeMaps[$templateMap['scope']] : $scopeMaps['project']; + $template->templateType = $belongBuiltinType ? $templateMap['code'] : $template->templateType; + $template->module = $modulePairs[$template->templateType]; + $this->update(TABLE_DOC)->data($template)->where('id')->eq($id)->exec(); + } + } + /** * 获取文档模板类型的模块。 * Get modules of doc template type. From bea0cf7cfaaffb3bf8201204aeb8614a83b63638 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 14:42:10 +0800 Subject: [PATCH 159/655] * [task#133854,doing,0.5h] fix bug. --- module/doc/model.php | 19 ++++++++++++++----- module/upgrade/control.php | 10 +++------- module/upgrade/model.php | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 2fccf03cbe..189546978b 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3780,7 +3780,7 @@ class docModel extends model */ public function upgradeCustomTemplateModule() { - $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch(); + $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch('id'); $oldTemplateTypes = $this->dao->select('`key`,`value`')->from(TABLE_LANG) ->where('module')->eq('baseline') ->andWhere('section')->eq('objectList') @@ -3807,9 +3807,15 @@ class docModel extends model return true; } + /** + * Upgrade doc template. + * + * @access public + * @return bool + */ public function upgradeDocTemplate() { - $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch(); + $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch('id'); $modulePairs = $this->dao->select('short,id')->from(TABLE_MODULE) ->where('deleted')->eq(0) ->andWhere('type')->eq('docTemplate') @@ -3827,15 +3833,18 @@ class docModel extends model $belongBuiltinType = in_array($template->templateType, array_keys($this->config->doc->oldTemplateMap)); if($belongBuiltinType) { - $templateMap = $this->config->doc->oldTemplateTypes[$template->templateType]; - $scopeMaps = array_flip($this->config->scopeMaps); + $templateMap = $this->config->doc->oldTemplateMap[$template->templateType]; + $scopeMaps = array_flip($this->config->doc->scopeMaps); } $template->lib = $belongBuiltinType ? $scopeMaps[$templateMap['scope']] : $scopeMaps['project']; $template->templateType = $belongBuiltinType ? $templateMap['code'] : $template->templateType; $template->module = $modulePairs[$template->templateType]; - $this->update(TABLE_DOC)->data($template)->where('id')->eq($id)->exec(); + $this->dao->update(TABLE_DOC)->data($template)->where('id')->eq($id)->exec(); + if(dao::isError()) return false; } + + return true; } /** diff --git a/module/upgrade/control.php b/module/upgrade/control.php index 9ce569fe67..9641683151 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -822,18 +822,14 @@ class upgrade extends control } /** - * Insert template module. + * Ajax: upgrade doc template. * * @access public * @return void */ - public function ajaxInsertBuiltinTemplateModule() + public function ajaxUpgradeDocTemplate() { - $this->loadModel('doc'); - $result = $this->doc->insertBuiltinTemplateModule() - $result = $this->doc->upgradeCustomTemplateModule(); - if($result) echo 'ok'; - if(!$result) echo dao::getError(); + $this->upgrade->upgradeDocTemplate(); } /** diff --git a/module/upgrade/model.php b/module/upgrade/model.php index c4bb127d44..18de3c5117 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10036,6 +10036,24 @@ class upgradeModel extends model } } + /** + * Upgrade doc template. + * + * @access public + * @return void + */ + public function upgradeDocTemplate() + { + $this->loadModel('doc'); + + $this->doc->insertBuiltinTemplateModule(); + if($fromEdition != 'open' && $fromEdition != 'biz') + { + $this->doc->upgradeCustomTemplateModule(); + $this->doc->upgradeDocTemplate(); + } + } + /** * 历史产品、项目绑定默认工作流模板。 * From 579a00b5978acd4294e1f352ec240fabda77c527 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Thu, 5 Dec 2024 16:20:22 +0800 Subject: [PATCH 160/655] * [task#133854,doing,0.5h] refactor code. --- module/doc/model.php | 94 +++++++++++++++++++------------------- module/upgrade/control.php | 1 + module/upgrade/model.php | 9 ++-- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 189546978b..f9dce9a838 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3718,54 +3718,60 @@ class docModel extends model } /** - * 插入内置文档模板类型数据。 - * insert doc template type. + * 构建模板类型数据。 + * Build data of template type module. + * + * @param int $scope + * @param int $parent + * @param string $name + * @param string $code + * @param int $grade + * @param string $path + * @access public + * @return object + */ + public function buildTemplateModule($scope, $parent, $name, $code, $grade = 1, $path = '') + { + $module = new stdclass(); + $module->type = 'docTemplate'; + $module->root = $scope; + $module->parent = $parent; + $module->name = $name; + $module->short = $code; + $module->grade = $grade; + $module->path = $path; + + return $module; + } + + /** + * 插入内置模板类型数据。 + * Insert builtin doc template types. * * @access public * @return bool */ - public function insertBuiltinTemplateModule() + public function upgradeBuiltinTemplateTypes() { foreach($this->config->doc->templateModule as $scope => $moduleList) { - $moduleOrder = 10; foreach($moduleList as $moduleKey => $subModuleList) { - $module = new stdclass(); - $module->root = $scope; - $module->name = $this->lang->docTemplate->moduleName[$moduleKey]; - $module->parent = 0; - $module->path = ''; - $module->grade = 1; - $module->order = $moduleOrder; - $module->type = 'docTemplate'; - $module->short = ucfirst($this->config->doc->scopeMaps[$scope]) . ' ' . $moduleKey; + $module = $this->buildTemplateModule($scope, 0, $this->lang->docTemplate->moduleName[$moduleKey], ucfirst($this->config->doc->scopeMaps[$scope]) . ' ' . $moduleKey, 1); $this->dao->insert(TABLE_MODULE)->data($module)->exec(); if(dao::isError()) return false; $moduleID = $this->dao->lastInsertID(); $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},")->where('id')->eq($moduleID)->exec(); - $moduleOrder = $moduleOrder + 10; - $subModuleOrder = 10; foreach($subModuleList as $subModuleKey => $subModuleCode) { - $subModule = new stdclass(); - $subModule->root = $scope; - $subModule->name = $this->lang->docTemplate->moduleName[$subModuleKey]; - $subModule->parent = $moduleID; - $subModule->path = ''; - $subModule->grade = 2; - $subModule->order = $subModuleOrder; - $subModule->type = 'docTemplate'; - $subModule->short = $subModuleCode; + $subModule = $this->buildTemplateModule($scope, $moduleID, $this->lang->docTemplate->moduleName[$subModuleKey], $subModuleCode, 2); $this->dao->insert(TABLE_MODULE)->data($subModule)->exec(); if(dao::isError()) return false; $subModuleID = $this->dao->lastInsertID(); $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$moduleID},{$subModuleID},")->where('id')->eq($subModuleID)->exec(); - - $subModuleOrder = $subModuleOrder + 10; } } } @@ -3773,60 +3779,56 @@ class docModel extends model } /** - * Upgrade custom template types. + * 升级用户自定义模板类型数据。 + * Upgrade custom doc template types. * * @access public * @return bool */ - public function upgradeCustomTemplateModule() + public function upgradeCustomTemplateTypes() { - $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch('id'); $oldTemplateTypes = $this->dao->select('`key`,`value`')->from(TABLE_LANG) ->where('module')->eq('baseline') ->andWhere('section')->eq('objectList') ->andWhere('system')->eq('0') ->fetchPairs('`key`'); + if(empty($oldTemplateTypes)) return true; + $parentID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch('id'); foreach($oldTemplateTypes as $key => $value) { - $module = new stdclass(); - $module->root = 2; - $module->name = $value; - $module->parent = $projectOtherID; - $module->path = ''; - $module->grade = 2; - $module->type = 'docTemplate'; - $module->short = $key; + $module = $this->buildTemplateModule(2, $parentID, $value, $key, 2); $this->dao->insert(TABLE_MODULE)->data($module)->exec(); if(dao::isError()) return false; $moduleID = $this->dao->lastInsertID(); - $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$projectOtherID},{$moduleID},")->where('id')->eq($moduleID)->exec(); + $this->dao->update(TABLE_MODULE)->set('path')->eq(",{$parentID},{$moduleID},")->where('id')->eq($moduleID)->exec(); } return true; } /** - * Upgrade doc template. + * 升级旧的文档模板。 + * Upgrade old template. * * @access public * @return bool */ - public function upgradeDocTemplate() + public function upgradeTemplate() { - $projectOtherID = $this->dao->select('id')->from(TABLE_MODULE)->where('short')->eq('Project other')->fetch('id'); - $modulePairs = $this->dao->select('short,id')->from(TABLE_MODULE) - ->where('deleted')->eq(0) - ->andWhere('type')->eq('docTemplate') - ->fetchPairs(); - $templateList = $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq(0) ->andWhere('templateType')->ne('') ->andWhere('lib')->eq('') ->andWhere('module')->eq('') ->fetchAll('id'); + if(empty($templateList)) return true; + + $modulePairs = $this->dao->select('short,id')->from(TABLE_MODULE) + ->where('deleted')->eq(0) + ->andWhere('type')->eq('docTemplate') + ->fetchPairs(); foreach($templateList as $id => $template) { diff --git a/module/upgrade/control.php b/module/upgrade/control.php index 9641683151..82b6f26a3d 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -830,6 +830,7 @@ class upgrade extends control public function ajaxUpgradeDocTemplate() { $this->upgrade->upgradeDocTemplate(); + echo 'ok'; } /** diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 18de3c5117..ebd2c932fe 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10046,12 +10046,9 @@ class upgradeModel extends model { $this->loadModel('doc'); - $this->doc->insertBuiltinTemplateModule(); - if($fromEdition != 'open' && $fromEdition != 'biz') - { - $this->doc->upgradeCustomTemplateModule(); - $this->doc->upgradeDocTemplate(); - } + $this->doc->upgradeBuiltinTemplateTypes(); + $this->doc->upgradeCustomTemplateTypes(); + $this->doc->upgradeTemplate(); } /** From 7f370c63a8f4f6058f9f3b34f2805327229932e1 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 08:45:00 +0800 Subject: [PATCH 161/655] * [task#133857,doing,0.2h] add controller of doc-selectTemplate. --- module/doc/control.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/module/doc/control.php b/module/doc/control.php index 8e53fd3621..33c418aea2 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -306,6 +306,24 @@ class doc extends control return $this->send(array('result' => 'success', 'load' => $browseLink, 'app' => $this->app->tab)); } + /** + * 选择文档模板。 + * Select template. + * + * @access public + * @return void + */ + public function selectTemplate() + { + $templateList = $this->doc->getTemplatesByType(); + + $templatePairs = array(); + foreach($templateList as $template) $templatePairs[$template->id] = $template->title; + + $this->view->templatePairs = $templatePairs; + $this->display(); + } + /** * 文档模板列表。 * Browse template list. From 8351abbc327cd94f457380b8bfc5d66d77ff9faa Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 08:46:24 +0800 Subject: [PATCH 162/655] * [task#133857,doing,0.1h] add lang. --- module/doc/lang/de.php | 3 +++ module/doc/lang/en.php | 3 +++ module/doc/lang/fr.php | 3 +++ module/doc/lang/zh-cn.php | 3 +++ 4 files changed, 12 insertions(+) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index c0c8d44034..2c792a65f2 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -182,6 +182,7 @@ $lang->doc->update = 'Update'; $lang->doc->nextStep = 'Next'; $lang->doc->closed = 'Closed'; $lang->doc->saveDraft = 'Save Draft'; +$lang->doc->template = 'Template'; $lang->doc->position = 'Position'; $lang->doc->person = 'Person'; $lang->doc->team = 'Team'; @@ -500,6 +501,7 @@ $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; $lang->doc->viewTemplate = 'View Document Template'; +$lang->doc->selectTemplate = 'Select Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; @@ -533,6 +535,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo; $lang->doc->docLang->moveLib = $lang->doc->moveLibAction; $lang->doc->docLang->moduleName = $lang->doc->catalogName; $lang->doc->docLang->saveDraft = $lang->doc->saveDraft; +$lang->doc->docLang->template = $lang->doc->template; $lang->doc->docLang->release = $lang->doc->release; $lang->doc->docLang->batchMove = $lang->doc->batchMove; $lang->doc->docLang->filterTypes = $lang->doc->filterTypes; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 4f9cac921b..c5d23a1405 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -182,6 +182,7 @@ $lang->doc->update = 'Update'; $lang->doc->nextStep = 'Next'; $lang->doc->closed = 'Closed'; $lang->doc->saveDraft = 'Save Draft'; +$lang->doc->template = 'Template'; $lang->doc->position = 'Position'; $lang->doc->person = 'Person'; $lang->doc->team = 'Team'; @@ -500,6 +501,7 @@ $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; $lang->doc->viewTemplate = 'View Document Template'; +$lang->doc->selectTemplate = 'Select Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; @@ -533,6 +535,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo; $lang->doc->docLang->moveLib = $lang->doc->moveLibAction; $lang->doc->docLang->moduleName = $lang->doc->catalogName; $lang->doc->docLang->saveDraft = $lang->doc->saveDraft; +$lang->doc->docLang->template = $lang->doc->template; $lang->doc->docLang->release = $lang->doc->release; $lang->doc->docLang->batchMove = $lang->doc->batchMove; $lang->doc->docLang->filterTypes = $lang->doc->filterTypes; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index fb8475d263..5010b25d36 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -182,6 +182,7 @@ $lang->doc->update = 'Update'; $lang->doc->nextStep = 'Next'; $lang->doc->closed = 'Closed'; $lang->doc->saveDraft = 'Save Draft'; +$lang->doc->template = 'Template'; $lang->doc->position = 'Position'; $lang->doc->person = 'Person'; $lang->doc->team = 'Team'; @@ -500,6 +501,7 @@ $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; $lang->doc->viewTemplate = 'View Document Template'; +$lang->doc->selectTemplate = 'Select Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; @@ -533,6 +535,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo; $lang->doc->docLang->moveLib = $lang->doc->moveLibAction; $lang->doc->docLang->moduleName = $lang->doc->catalogName; $lang->doc->docLang->saveDraft = $lang->doc->saveDraft; +$lang->doc->docLang->template = $lang->doc->template; $lang->doc->docLang->release = $lang->doc->release; $lang->doc->docLang->batchMove = $lang->doc->batchMove; $lang->doc->docLang->filterTypes = $lang->doc->filterTypes; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index f3001b4eec..495af36b24 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -182,6 +182,7 @@ $lang->doc->update = '更新'; $lang->doc->nextStep = '下一步'; $lang->doc->closed = '已关闭'; $lang->doc->saveDraft = '存为草稿'; +$lang->doc->template = '模板'; $lang->doc->position = '所在位置'; $lang->doc->person = '个人'; $lang->doc->team = '团队'; @@ -500,6 +501,7 @@ $lang->doc->createTemplate = '创建文档模板'; $lang->doc->editTemplate = '编辑文档模板'; $lang->doc->deleteTemplate = '删除文档模板'; $lang->doc->viewTemplate = '文档模板详情'; +$lang->doc->selectTemplate = '选择模板'; $lang->doc->addTemplateType = '添加类型'; $lang->doc->editTemplateType = '编辑类型'; $lang->doc->deleteTemplateType = '删除类型'; @@ -533,6 +535,7 @@ $lang->doc->docLang->moveTo = $lang->doc->moveTo; $lang->doc->docLang->moveLib = $lang->doc->moveLibAction; $lang->doc->docLang->moduleName = $lang->doc->catalogName; $lang->doc->docLang->saveDraft = $lang->doc->saveDraft; +$lang->doc->docLang->template = $lang->doc->template; $lang->doc->docLang->release = $lang->doc->release; $lang->doc->docLang->batchMove = $lang->doc->batchMove; $lang->doc->docLang->filterTypes = $lang->doc->filterTypes; From 0b8e648c3c82d3a9a9de03cca5f241112b68ee07 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 08:47:26 +0800 Subject: [PATCH 163/655] * [task#133857,doing,0.2h] extend model. --- module/doc/model.php | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index f9dce9a838..18d218b3b2 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -4000,24 +4000,28 @@ class docModel extends model * 获取某个模板类型下的所有模板。 * Get template list by type. * - * @param int $type + * @param int|null $type * @access public * @return int */ - public function getTemplatesByType($type) + public function getTemplatesByType($type = null) { - $subTypes = $this->dao->select('id')->from(TABLE_MODULE) - ->where('deleted')->eq('0') - ->andWhere('parent')->eq($type) - ->andWhere('type')->eq('docTemplate') - ->fetchPairs('id'); - $types = array_values($subTypes); - $types[] = $type; + $types = array(); + if(!is_null($type)) + { + $subTypes = $this->dao->select('id')->from(TABLE_MODULE) + ->where('deleted')->eq('0') + ->andWhere('parent')->eq($type) + ->andWhere('type')->eq('docTemplate') + ->fetchPairs('id'); + $types = array_values($subTypes); + $types[] = $type; + } return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq('0') ->andWhere('templateType')->ne('') - ->andWhere('module')->in($types) + ->beginIF(!is_null($type))->andWhere('module')->in($types)->fi() ->fetchAll('id'); } } From 969e7b8d07eb12183b97e9c383a0b57dda53c942 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 08:48:29 +0800 Subject: [PATCH 164/655] * [task#133857,doing,0.5h] add page and command of doc-selectTemplate. --- module/doc/js/app.ui.js | 25 +++++++++++++++++++++++++ module/doc/ui/selecttemplate.html.php | 23 +++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 module/doc/ui/selecttemplate.html.php diff --git a/module/doc/js/app.ui.js b/module/doc/js/app.ui.js index e69de29bb2..740c4bb0a8 100644 --- a/module/doc/js/app.ui.js +++ b/module/doc/js/app.ui.js @@ -0,0 +1,25 @@ +$.extend(window.docAppActions, +{ + 'doc-create': function(info) + { + const doc = info.data; + if(!doc) return; + + const lang = getLang(); + return [ + {text: lang.template, size: 'md', className: 'btn-wide', type: 'secondary', command: 'selectTemplate'}, + {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveNewDoc/draft'}, + {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveNewDoc'}, + {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelCreateDoc'}, + ]; + } +}); + +$.extend(window.docAppCommands, +{ + selectTemplate: function(_, args) + { + const url = $.createLink('doc', 'selectTemplate'); + zui.Modal.open({size: 'sm', url: url}); + } +}); diff --git a/module/doc/ui/selecttemplate.html.php b/module/doc/ui/selecttemplate.html.php new file mode 100644 index 0000000000..c98e76b4ba --- /dev/null +++ b/module/doc/ui/selecttemplate.html.php @@ -0,0 +1,23 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; +formPanel +( + set::title($lang->doc->template), + formGroup + ( + set::label($lang->doc->selectTemplate), + set::name('template'), + set::required(true), + set::width('5/6'), + set::items($templatePairs) + ) +); From ebe4db5881ef774191e051eb5ec75c4e09c4d207 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 14:05:22 +0800 Subject: [PATCH 165/655] * [task#133857,doing,0.5h] add btn and bind event to apply template. --- module/doc/js/selecttemplate.ui.js | 13 +++++++++++++ module/doc/ui/selecttemplate.html.php | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 module/doc/js/selecttemplate.ui.js diff --git a/module/doc/js/selecttemplate.ui.js b/module/doc/js/selecttemplate.ui.js new file mode 100644 index 0000000000..dcc71fe21c --- /dev/null +++ b/module/doc/js/selecttemplate.ui.js @@ -0,0 +1,13 @@ +window.applyTemplate = function() +{ + const docApp = getDocApp(); + const editor = docApp.editor.$; + + const templateID = $('#template').find('.picker-box').zui('picker').$.value; + const url = $.createLink('doc', 'ajaxGetTemplateContent', `id=${templateID}`); + $.get(url, function(data) + { + data = JSON.parse(data); + editor.updateDoc(data.content, data.type != 'doc' ? data.type : undefined); + }); +} diff --git a/module/doc/ui/selecttemplate.html.php b/module/doc/ui/selecttemplate.html.php index c98e76b4ba..fe81aa41fd 100644 --- a/module/doc/ui/selecttemplate.html.php +++ b/module/doc/ui/selecttemplate.html.php @@ -14,10 +14,24 @@ formPanel set::title($lang->doc->template), formGroup ( + setID('template'), set::label($lang->doc->selectTemplate), set::name('template'), set::required(true), set::width('5/6'), set::items($templatePairs) + ), + set::actions(array()), + formGroup + ( + setClass('form-actions'), + btn + ( + $lang->save, + set::btnType('button'), + set::type('primary'), + setData('dismiss', 'modal'), + on::click('applyTemplate') + ) ) ); From db6ef96e82bcce3f7d8391f6ce68c4ebd04ea715 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 14:06:41 +0800 Subject: [PATCH 166/655] * [task#133857,doing,0.2h] adjust code. --- module/doc/control.php | 15 ++++++++++++++- module/doc/model.php | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 33c418aea2..24d6015539 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -315,7 +315,7 @@ class doc extends control */ public function selectTemplate() { - $templateList = $this->doc->getTemplatesByType(); + $templateList = $this->doc->getTemplatesByType(null, 'normal'); $templatePairs = array(); foreach($templateList as $template) $templatePairs[$template->id] = $template->title; @@ -324,6 +324,19 @@ class doc extends control $this->display(); } + /** + * Ajax: get template content. + * + * @param int $id + * @access public + * @return void + */ + public function ajaxGetTemplateContent($id) + { + $template = $this->doc->getTemplateContentByID($id); + return print(json_encode(array('type' => $template->type, 'content' => $template->content))); + } + /** * 文档模板列表。 * Browse template list. diff --git a/module/doc/model.php b/module/doc/model.php index 18d218b3b2..391bea047e 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3996,15 +3996,28 @@ class docModel extends model return $moduleID; } + /** + * Get template content by doc id. + * + * @param int $id + * @access public + * @return int + */ + public function getTemplateContentByID($id) + { + return $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($id)->orderBy('version_desc')->fetch(); + } + /** * 获取某个模板类型下的所有模板。 * Get template list by type. * * @param int|null $type + * @param string $status * @access public * @return int */ - public function getTemplatesByType($type = null) + public function getTemplatesByType($type = null, $status = 'all') { $types = array(); if(!is_null($type)) @@ -4022,6 +4035,7 @@ class docModel extends model ->where('deleted')->eq('0') ->andWhere('templateType')->ne('') ->beginIF(!is_null($type))->andWhere('module')->in($types)->fi() + ->beginIF($status != 'all')->andWhere('status')->eq($status)->fi() ->fetchAll('id'); } } From 31e3efdd9f4961f822c91f2b690dfd7b36076d61 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 9 Dec 2024 14:24:56 +0800 Subject: [PATCH 167/655] * [task#133857,done,0.5h] add btn to apply template. --- module/doc/js/app.ui.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/module/doc/js/app.ui.js b/module/doc/js/app.ui.js index 740c4bb0a8..f36b09d448 100644 --- a/module/doc/js/app.ui.js +++ b/module/doc/js/app.ui.js @@ -1,5 +1,19 @@ $.extend(window.docAppActions, { + 'doc-edit': function(info) + { + const doc = info.data; + if(!doc) return; + + const lang = getLang(); + return [ + {text: lang.template, size: 'md', className: 'btn-wide', type: 'primary-outline', icon: 'save', command: 'selectTemplate'}, + doc.status === 'draft' ? {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveDoc/draft'} : null, + {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveDoc'}, + {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'}, + {text: lang.settings, size: 'md', type: 'ghost', command: `showDocSettingModal/${doc.id}/${doc.contentType}/1`, icon: 'cog-outline'}, + ]; + }, 'doc-create': function(info) { const doc = info.data; @@ -7,7 +21,7 @@ $.extend(window.docAppActions, const lang = getLang(); return [ - {text: lang.template, size: 'md', className: 'btn-wide', type: 'secondary', command: 'selectTemplate'}, + {text: lang.template, size: 'md', className: 'btn-wide', type: 'primary-outline', icon: 'save', command: 'selectTemplate'}, {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveNewDoc/draft'}, {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveNewDoc'}, {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelCreateDoc'}, From d51996a31218848ee6e2d2318a6edddbf3012b43 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:53:05 +0000 Subject: [PATCH 168/655] * [story#69800,0.5h] move to model. --- module/search/control.php | 4 ++-- module/search/model.php | 46 +++++++++++++++++++++++++++++++++++++++ module/search/tao.php | 2 +- module/search/zen.php | 46 --------------------------------------- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/module/search/control.php b/module/search/control.php index 776e8b1f79..afa13a265f 100644 --- a/module/search/control.php +++ b/module/search/control.php @@ -50,7 +50,7 @@ class search extends control $this->view->module = $module; $this->view->actionURL = empty($actionURL) ? $_SESSION[$searchParams]['actionURL'] : $actionURL; $this->view->fields = $fields; - $this->view->fieldParams = $this->searchZen->setDefaultParams($fields, $params); + $this->view->fieldParams = $this->setDefaultParams($fields, $params); $this->view->queries = $this->search->getQueryList($module); $this->view->queryID = (empty($module) && empty($queryID)) ? $_SESSION[$searchParams]['queryID'] : $queryID; $this->view->style = !empty($_SESSION[$searchParams]['style']) ? $_SESSION[$searchParams]['style'] : 'full'; @@ -100,7 +100,7 @@ class search extends control $this->view->actionURL = empty($actionURL) ? $_SESSION[$searchParams]['actionURL'] : $actionURL; $this->view->searchFields = $fields; $this->view->fields = $fields; - $this->view->fieldParams = $this->searchZen->setDefaultParams($fields, $params); + $this->view->fieldParams = $this->setDefaultParams($fields, $params); $this->view->queries = $this->search->getQueryList($module); $this->view->queryID = (empty($module) && empty($queryID)) ? $_SESSION[$searchParams]['queryID'] : $queryID; $this->view->style = !empty($_SESSION[$searchParams]['style']) ? $_SESSION[$searchParams]['style'] : 'full'; diff --git a/module/search/model.php b/module/search/model.php index 5f646eda86..68d239c564 100644 --- a/module/search/model.php +++ b/module/search/model.php @@ -39,6 +39,52 @@ class searchModel extends model $this->session->set($module . 'searchParams', $searchParams); } + /** + * 设置默认的搜索参数。 + * Set default params for selection. + * + * @param array $fields + * @param array $params + * @access public + * @return array + */ + public function setDefaultParams(array $fields, array $params): array + { + $fields = array_keys($fields); + + list($users, $products, $executions) = $this->getParamValues($fields, $params); + + foreach($fields as $fieldName) + { + if(!isset($params[$fieldName])) $params[$fieldName] = array('operator' => '=', 'control' => 'input', 'values' => ''); + + if($params[$fieldName]['values'] == 'users') $params[$fieldName]['values'] = $users; + if($params[$fieldName]['values'] == 'products') $params[$fieldName]['values'] = $products; + if($params[$fieldName]['values'] == 'executions') $params[$fieldName]['values'] = $executions; + + /* 处理数组。*/ + /* Process array value. */ + if(is_array($params[$fieldName]['values'])) + { + /* For build right sql when key is 0 and is not null. e.g. confirmed field. */ + if(isset($params[$fieldName]['values'][0]) and $params[$fieldName]['values'][0] !== '') + { + $params[$fieldName]['values'] = array('ZERO' => $params[$fieldName]['values'][0]) + $params[$fieldName]['values']; + unset($params[$fieldName]['values'][0]); + } + elseif(empty($params[$fieldName]['values'])) + { + $params[$fieldName]['values'] = array('' => '', 'null' => $this->lang->search->null); + } + elseif(empty($params[$fieldName]['nonull'])) + { + $params[$fieldName]['values'] = $params[$fieldName]['values'] + array('null' => $this->lang->search->null); + } + } + } + return $params; + } + /** * 构建查询语句。 * Build the query to execute. diff --git a/module/search/tao.php b/module/search/tao.php index ca3bef1bb9..3064a6c54b 100644 --- a/module/search/tao.php +++ b/module/search/tao.php @@ -11,7 +11,7 @@ class searchTao extends searchModel * @access protected * @return array */ - protected function processBuildinFields(string $module, array $searchConfig): array + public function processBuildinFields(string $module, array $searchConfig): array { $flowModule = $module; if($module == 'projectStory' || $module == 'executionStory' || $module == 'projectstory') $flowModule = 'story'; diff --git a/module/search/zen.php b/module/search/zen.php index e0694eaae0..aa0746e518 100644 --- a/module/search/zen.php +++ b/module/search/zen.php @@ -179,50 +179,4 @@ class searchZen extends search return $options; } - - /** - * 设置默认的搜索参数。 - * Set default params for selection. - * - * @param array $fields - * @param array $params - * @access public - * @return array - */ - protected function setDefaultParams(array $fields, array $params): array - { - $fields = array_keys($fields); - - list($users, $products, $executions) = $this->search->getParamValues($fields, $params); - - foreach($fields as $fieldName) - { - if(!isset($params[$fieldName])) $params[$fieldName] = array('operator' => '=', 'control' => 'input', 'values' => ''); - - if($params[$fieldName]['values'] == 'users') $params[$fieldName]['values'] = $users; - if($params[$fieldName]['values'] == 'products') $params[$fieldName]['values'] = $products; - if($params[$fieldName]['values'] == 'executions') $params[$fieldName]['values'] = $executions; - - /* 处理数组。*/ - /* Process array value. */ - if(is_array($params[$fieldName]['values'])) - { - /* For build right sql when key is 0 and is not null. e.g. confirmed field. */ - if(isset($params[$fieldName]['values'][0]) and $params[$fieldName]['values'][0] !== '') - { - $params[$fieldName]['values'] = array('ZERO' => $params[$fieldName]['values'][0]) + $params[$fieldName]['values']; - unset($params[$fieldName]['values'][0]); - } - elseif(empty($params[$fieldName]['values'])) - { - $params[$fieldName]['values'] = array('' => '', 'null' => $this->lang->search->null); - } - elseif(empty($params[$fieldName]['nonull'])) - { - $params[$fieldName]['values'] = $params[$fieldName]['values'] + array('null' => $this->lang->search->null); - } - } - } - return $params; - } } From cf3a1a4db1aaa515bb6efa3ef04afe96635015b3 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:53:50 +0000 Subject: [PATCH 169/655] * [story#69800,0.5h] add buildSearchConfig. --- module/testcase/model.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/module/testcase/model.php b/module/testcase/model.php index d6aaa54d6a..6547dc9024 100755 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -2795,6 +2795,29 @@ class testcaseModel extends model $this->loadModel('search')->setSearchParams($this->config->testcase->search); } + public function buildSearchConfig(int $productID, string $branch = 'all') + { + $this->config->testcase->search['params']['story']['values'] = $this->loadModel('story')->getProductStoryPairs($productID, $branch, array(), 'active,reviewing', 'id_desc', 0, '', 'story', false); + + /* 获取模块列表。*/ + /* Get moduleList. */ + $modules = $this->loadModel('tree')->getOptionMenu($productID, 'case', 0, $branch); + + $this->config->testcase->search['params']['module']['values'] = $modules; + $this->config->testcase->search['params']['scene']['values'] = $this->getSceneMenu($productID, 0, $branch, 0, 0, true); + $this->config->testcase->search['params']['lib']['values'] = $this->loadModel('caselib')->getLibraries(); + + unset($this->config->testcase->search['fields']['product']); + unset($this->config->testcase->search['params']['product']); + + if(!$this->config->testcase->needReview) unset($this->config->testcase->search['params']['status']['values']['wait']); + + $searchConfig = $this->loadModel('search')->processBuildinFields('testcase', $this->config->testcase->search); + $searchConfig['params'] = $this->search->setDefaultParams($searchConfig['fields'], $searchConfig['params']); + + return $searchConfig; + } + /** * 过滤自动测试用例的ID列表。 * Ignore auto testcase id list. From 789913bc7f6cacc8edcbde5259267920e1c67958 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:53:57 +0000 Subject: [PATCH 170/655] * [story#69800,0.5h] add buildSearchConfig. --- module/testcase/model.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/module/testcase/model.php b/module/testcase/model.php index 6547dc9024..190aace942 100755 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -2810,6 +2810,22 @@ class testcaseModel extends model unset($this->config->testcase->search['fields']['product']); unset($this->config->testcase->search['params']['product']); + $product = $this->loadModel('product')->getByID($productID ? $productID : 0); + if($productID) + { + if(isset($product->type) && $product->type == 'normal') + { + unset($this->config->testcase->search['fields']['branch']); + unset($this->config->testcase->search['params']['branch']); + } + else + { + $branches = $this->loadModel('branch')->getPairs($productID, '', 0); + $this->config->testcase->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]); + $this->config->testcase->search['params']['branch']['values'] = array('' => '', BRANCH_MAIN => $this->lang->branch->main) + $branches + array('all' => $this->lang->branch->all); + } + } + if(!$this->config->testcase->needReview) unset($this->config->testcase->search['params']['status']['values']['wait']); $searchConfig = $this->loadModel('search')->processBuildinFields('testcase', $this->config->testcase->search); From 9ed042a00f3c34f24040dd19b74926ea3ad74e51 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:55:19 +0000 Subject: [PATCH 171/655] * [story#69800,0.5h] finish search form. --- module/doc/js/zentaolist.ui.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/module/doc/js/zentaolist.ui.js b/module/doc/js/zentaolist.ui.js index 98b44035d5..9e21ab0ae8 100644 --- a/module/doc/js/zentaolist.ui.js +++ b/module/doc/js/zentaolist.ui.js @@ -116,6 +116,13 @@ window.updateCustomSearchItem = function($this, action) loadWithForm(formData, 'setting', 'post'); } +window.updateCustomSearch = function() +{ + const form = $('#zentaolist form'); + const formData = new FormData(form[0]); + loadWithForm(formData, 'setting', 'post'); +} + function changeProduct() { const product = getValue('product'); @@ -129,4 +136,10 @@ function changeProduct() updatePicker('plan', resp); }); } + + if(type === 'productCase') + { + const condition = getValue('condition'); + if(condition == 'customSearch') updateCustomSearch(); + } } From 0c0d7b6138cebd01ec493193e0bcea57cb689c3f Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:55:39 +0000 Subject: [PATCH 172/655] * [story#69800,0.5h] finish search form. --- .../doc/ui/zentaolist.customsearch.html.php | 46 ++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/module/doc/ui/zentaolist.customsearch.html.php b/module/doc/ui/zentaolist.customsearch.html.php index 3b41e9358f..093bff6cc4 100644 --- a/module/doc/ui/zentaolist.customsearch.html.php +++ b/module/doc/ui/zentaolist.customsearch.html.php @@ -2,19 +2,36 @@ declare(strict_types=1); namespace zin; -$fnGenerateCustomSearchItem = function ($index, $form) use ($lang, $config) +$fnGenerateCustomSearchItem = function ($index, $searchConfig, $form) use ($lang, $config) { list($andor, $field, $operator, $value) = $form; $isFirst = $index === 0; + + $searchFields = $searchConfig['fields']; + $searchParams = $searchConfig['params']; + + $fields = array_keys($searchFields); + $field = empty($field) ? reset($fields) : $field; + $operator = empty($operator) ? $searchParams[$field]['operator'] : $operator; + $control = $searchParams[$field]['control']; + $valueItems = $searchParams[$field]['values']; + + $isPicker = false; + if($control === 'select') + { + $isPicker = true; + $control = 'picker'; + } + return formRow ( setClass('flex gap-x-2'), setID('row' . $index), formGroup ( - setClass(array('hidden' => $isFirst)), - set::width('22'), setID('andor' . $index), + setClass(array('search-andor', 'hidden' => $isFirst)), + set::width('22'), set::name('andor[]'), set::control(array('required' => true)), set::items($lang->search->andor), @@ -22,17 +39,20 @@ $fnGenerateCustomSearchItem = function ($index, $form) use ($lang, $config) ), formGroup ( + setID('field' . $index), + setClass('search-field'), set::width($isFirst ? '56' : '32'), set::label($isFirst ? $lang->doc->customSearch : null), - setID('field' . $index), set::name("field[]"), - set::items($config->product->search['fields']), + set::control(array('required' => true)), + set::items($searchFields), set::value($field) ), formGroup ( - set::width('20'), setID('operator' . $index), + setClass('search-operator'), + set::width('20'), set::name("operator[]"), set::control(array('required' => true)), set::items($lang->search->operators), @@ -40,10 +60,13 @@ $fnGenerateCustomSearchItem = function ($index, $form) use ($lang, $config) ), formGroup ( + setID('value' . $index . $control), + setClass('search-value'), set::width('60'), - setID('value' . $index), set::name("value[]"), - set::value($value) + set::control(array('type' => $control)), + set::value($value), + $isPicker ? set::items($valueItems) : null ), btnGroup ( @@ -53,7 +76,7 @@ $fnGenerateCustomSearchItem = function ($index, $form) use ($lang, $config) ); }; -$fnGenerateCustomSearch = function () use ($lang, $config, $settings, $fnGenerateCustomSearchItem) +$fnGenerateCustomSearch = function ($searchConfig) use ($lang, $config, $settings, $fnGenerateCustomSearchItem) { $this->loadModel('product'); $this->loadModel('search'); @@ -66,7 +89,7 @@ $fnGenerateCustomSearch = function () use ($lang, $config, $settings, $fnGenerat $andor = $settings['andor'][$index]; $operator = $settings['operator'][$index]; $value = $settings['value'][$index]; - $items[] = $fnGenerateCustomSearchItem($index, array($andor, $field, $operator, $value)); + $items[] = $fnGenerateCustomSearchItem($index, $searchConfig, array($andor, $field, $operator, $value)); } return div @@ -75,6 +98,7 @@ $fnGenerateCustomSearch = function () use ($lang, $config, $settings, $fnGenerat setClass('flex col gap-y-2', array('hidden' => !$isCustom)), $items, on::click('#customSearchContent .search-add')->do("updateCustomSearchItem(\$this, 'add')"), - on::click('#customSearchContent .search-remove')->do("updateCustomSearchItem(\$this, 'remove')") + on::click('#customSearchContent .search-remove')->do("updateCustomSearchItem(\$this, 'remove')"), + on::change('#customSearchContent .search-field')->do("updateCustomSearch(\$this)") ); }; From 84455dd3f4e78b3a30f5f9d5faa7b14468dea0a5 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:55:44 +0000 Subject: [PATCH 173/655] * [story#69800,0.5h] finish search form. --- module/doc/control.php | 2 +- module/doc/ui/zentaolist.html.php | 3 +-- module/doc/ui/zentaolist.productcase.html.php | 12 ++++++++---- module/doc/zen.php | 11 ++++++++++- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 2309dbca54..0173939684 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -87,7 +87,7 @@ class doc extends control { array_splice($_POST['andor'], $index + 1, 0, 'and'); array_splice($_POST['field'], $index + 1, 0, ''); - array_splice($_POST['operator'], $index + 1, 0, 'include'); + array_splice($_POST['operator'], $index + 1, 0, ''); array_splice($_POST['value'], $index + 1, 0, ''); } elseif($action === 'remove') diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 1774b5176c..6db9653ee9 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -12,8 +12,8 @@ namespace zin; set::zui(); $lowerType = strtolower($type); -include "zentaolist.{$lowerType}.html.php"; include "zentaolist.customsearch.html.php"; +include "zentaolist.{$lowerType}.html.php"; $isSetting = $view == 'setting'; @@ -39,7 +39,6 @@ formPanel ) ), $fnGenerateFormRows(), - $fnGenerateCustomSearch(), to::footer ( setClass('form-actions'), diff --git a/module/doc/ui/zentaolist.productcase.html.php b/module/doc/ui/zentaolist.productcase.html.php index cb3506817c..b46cd0b3fa 100644 --- a/module/doc/ui/zentaolist.productcase.html.php +++ b/module/doc/ui/zentaolist.productcase.html.php @@ -3,12 +3,15 @@ declare(strict_types=1); namespace zin; -$fnGenerateFormRows = function () use ($lang, $settings) +$fnGenerateFormRows = function () use ($lang, $settings, $fnGenerateCustomSearch) { $productList = $this->loadModel('product')->getPairs(); - $this->app->loadLang('testcase'); + $product = isset($settings['product']) ? $settings['product'] : 0; + $this->loadModel('testcase'); $conditions = array_filter($lang->testcase->featureBar['browse'], fn($value) => $value !== '-'); $conditions['customSearch'] = $lang->doc->customSearch; + + $searchConfig = $this->testcase->buildSearchConfig((int)$product); return array ( formRow @@ -21,7 +24,7 @@ $fnGenerateFormRows = function () use ($lang, $settings) set::required(), set::control(array('contorl' => 'picker', 'required' => false, 'maxItemsCount' => 50)), set::items($productList), - set::value(isset($settings['product']) ? $settings['product'] : ''), + set::value($product), span ( setClass('error-tip text-danger hidden'), @@ -46,6 +49,7 @@ $fnGenerateFormRows = function () use ($lang, $settings) $lang->doc->emptyError ) ) - ) + ), + $fnGenerateCustomSearch($searchConfig) ); }; diff --git a/module/doc/zen.php b/module/doc/zen.php index 2d36e21c0d..0671eb24f9 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -1022,7 +1022,7 @@ class docZen extends doc { $session['andor'] = array('and'); $session['field'] = array(''); - $session['operator'] = array('include'); + $session['operator'] = array(''); $session['value'] = array(''); } @@ -1283,6 +1283,15 @@ class docZen extends doc if($action === 'preview' && $view === 'setting') { $data = $this->loadModel('testcase')->getTestCases((int)$settings['product'], '', $settings['condition'], 0, 0); + if($settings['condition'] == 'customSearch') + { + $where = ''; + foreach($settings['field'] as $index => $field) + { + $where = $this->loadModel('search')->setWhere($where, $field, $settings['operator'][$index], $settings['value'][$index], $settings['andor'][$index]); + } + a($where); + } } elseif($view === 'list') { From 8e9d9d55adaca52f5897323af8ed4d43655ad364 Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Mon, 9 Dec 2024 08:56:58 +0000 Subject: [PATCH 174/655] * [story#69800,0.5h] add comment. --- module/testcase/model.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/module/testcase/model.php b/module/testcase/model.php index 190aace942..f5f0dcc1ba 100755 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -2795,7 +2795,16 @@ class testcaseModel extends model $this->loadModel('search')->setSearchParams($this->config->testcase->search); } - public function buildSearchConfig(int $productID, string $branch = 'all') + /** + * 构建搜索配置。 + * Build search config. + * + * @param int $productID + * @param string $branch + * @access public + * @return array + */ + public function buildSearchConfig(int $productID, string $branch = 'all'): array { $this->config->testcase->search['params']['story']['values'] = $this->loadModel('story')->getProductStoryPairs($productID, $branch, array(), 'active,reviewing', 'id_desc', 0, '', 'story', false); From 131d0e3de60794a473922195f2fda85fed5c422d Mon Sep 17 00:00:00 2001 From: qixinzhi Date: Tue, 10 Dec 2024 02:46:50 +0000 Subject: [PATCH 175/655] * [story#69800,0.5h] fix error. --- module/testcase/model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/testcase/model.php b/module/testcase/model.php index f5f0dcc1ba..da2ffc79fe 100755 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -2837,6 +2837,7 @@ class testcaseModel extends model if(!$this->config->testcase->needReview) unset($this->config->testcase->search['params']['status']['values']['wait']); + $_SESSION['searchParams']['module'] = 'testcase'; $searchConfig = $this->loadModel('search')->processBuildinFields('testcase', $this->config->testcase->search); $searchConfig['params'] = $this->search->setDefaultParams($searchConfig['fields'], $searchConfig['params']); From eb4f353cbb63094898b88147621b6568c66d7d1b Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 09:42:14 +0800 Subject: [PATCH 176/655] * [bug#58048,done,0.5h] hide template button in api lib. --- module/doc/js/app.ui.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/module/doc/js/app.ui.js b/module/doc/js/app.ui.js index f36b09d448..9d5703369c 100644 --- a/module/doc/js/app.ui.js +++ b/module/doc/js/app.ui.js @@ -1,3 +1,17 @@ +function isApiLib(lib, docApp) +{ + if(docApp && docApp.spaceType === 'api') return true; + if(typeof lib === 'number') lib = getDocApp().getLib(lib); + if(!lib) + { + docApp = docApp || getDocApp(); + if(!docApp) return false; + if(docApp.spaceType === 'api') return true; + lib = docApp.lib; + } + return lib && lib.data.type === 'api'; +} + $.extend(window.docAppActions, { 'doc-edit': function(info) @@ -6,6 +20,13 @@ $.extend(window.docAppActions, if(!doc) return; const lang = getLang(); + if(isApiLib()) + { + return [ + {text: lang.save, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveApiDoc'}, + {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'}, + ]; + } return [ {text: lang.template, size: 'md', className: 'btn-wide', type: 'primary-outline', icon: 'save', command: 'selectTemplate'}, doc.status === 'draft' ? {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveDoc/draft'} : null, @@ -20,6 +41,13 @@ $.extend(window.docAppActions, if(!doc) return; const lang = getLang(); + if(isApiLib()) + { + return [ + {text: lang.save, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveApiDoc'}, + {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelCreateDoc'}, + ]; + } return [ {text: lang.template, size: 'md', className: 'btn-wide', type: 'primary-outline', icon: 'save', command: 'selectTemplate'}, {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveNewDoc/draft'}, From 67b0bdd6421e1c45431128f19fc322e70c01ade3 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 10:43:28 +0800 Subject: [PATCH 177/655] * [bug#57963,done,0.5h] add doc-selectTemplate to logon methods. --- config/zentaopms.php | 1 + 1 file changed, 1 insertion(+) diff --git a/config/zentaopms.php b/config/zentaopms.php index 81ed9a6d5b..948b6400be 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -238,6 +238,7 @@ $config->logonMethods[] = 'cron.schedule'; $config->logonMethods[] = 'custom.index'; $config->logonMethods[] = 'doc.createbasicinfo'; $config->logonMethods[] = 'doc.selectlibtype'; +$config->logonMethods[] = 'doc.selecttemplate'; $config->logonMethods[] = 'doc.uploaddocs'; $config->logonMethods[] = 'doc.setdocbasic'; $config->logonMethods[] = 'doc.commoneditaction'; From ea5344976f9d12e0511eae70f4c062b1952edf49 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 11:00:02 +0800 Subject: [PATCH 178/655] * [bug#57937,done,0.5h] add priv to template module. --- module/doc/js/browsetemplate.ui.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 10e23331a7..35e7503917 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -307,10 +307,10 @@ $.extend(window.docAppActions, const items = []; const module = info.data; - items.push({text: getDocAppLang('addModule'), command: `addModule/${module.root}/${module.parent}`}); - if(module.grade == 1) items.push({text: getDocAppLang('addSubModule'), command: `addModule/${module.root}/${module.id}`}); - items.push({text: getDocAppLang('editModule'), command: `editModule/${module.id}`}); - items.push({text: getDocAppLang('deleteModule'), command: `deleteModule/${module.id}`}); + if(docAppHasPriv('addModule')) items.push({text: getDocAppLang('addModule'), command: `addModule/${module.root}/${module.parent}`}); + if(module.grade == 1 && docAppHasPriv('editModule')) items.push({text: getDocAppLang('addSubModule'), command: `addModule/${module.root}/${module.id}`}); + if(docAppHasPriv('editModule')) items.push({text: getDocAppLang('editModule'), command: `editModule/${module.id}`}); + if(docAppHasPriv('deleteModule')) items.push({text: getDocAppLang('deleteModule'), command: `deleteModule/${module.id}`}); if(info.ui === 'sidebar') { From cdabceea59adb20819c08a86875b3e4c864db922 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 11:28:30 +0800 Subject: [PATCH 179/655] * [bug#57935,done,0.5h] hide more button when hasn't operation. --- lib/zin/wg/docapp/js/v1.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index 746a012162..eeb4a04e54 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -564,7 +564,7 @@ const actionsMap = [ canMoveDoc(doc) ? {icon: 'folder-move', text: lang.moveDoc, command: `moveDoc/${doc.id}`} : null, hasPriv('delete') ? {icon: 'trash', text: lang.delete, command: `deleteDoc/${doc.id}`} : null, - ]; + ].filter(item => item !== null); return [ hasPriv('sortDoc') ? {icon: 'move cursor-move', className: 'sort-handler', hint: lang.sortDoc, size: 'xs'} : null, moreItems.length ? {icon: 'ellipsis-v', caret: false, placement: 'bottom-end', size: 'xs', items: moreItems} : null, From 6a3221c9f117a961f4c454f16419ff1154a1e714 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 13:45:06 +0800 Subject: [PATCH 180/655] * [bug#58058,done,0.5h] fix error. --- module/doc/model.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 6f89425c5c..8f0f2aac48 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3841,14 +3841,11 @@ class docModel extends model ->andWhere('type')->eq('docTemplate') ->fetchPairs(); + $scopeMaps = array_flip($this->config->doc->scopeMaps); foreach($templateList as $id => $template) { $belongBuiltinType = in_array($template->templateType, array_keys($this->config->doc->oldTemplateMap)); - if($belongBuiltinType) - { - $templateMap = $this->config->doc->oldTemplateMap[$template->templateType]; - $scopeMaps = array_flip($this->config->doc->scopeMaps); - } + if($belongBuiltinType) $templateMap = $this->config->doc->oldTemplateMap[$template->templateType]; $template->lib = $belongBuiltinType ? $scopeMaps[$templateMap['scope']] : $scopeMaps['project']; $template->templateType = $belongBuiltinType ? $templateMap['code'] : $template->templateType; From c2f733913d44906a7f83b555e8ebe44889b3b698 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 14:06:09 +0800 Subject: [PATCH 181/655] * [bug#58060,done,0.2h] set auto exclude to false. --- module/doc/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 8f0f2aac48..181f0767c9 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3934,7 +3934,7 @@ class docModel extends model ->beginIF($scopeID)->andWhere('lib')->eq($scopeID)->fi() ->orderBy('hotDate_desc') ->beginIF($limit)->limit($limit)->fi() - ->fetchAll(); + ->fetchAll('', false); } /** From 927b6ab6dcd83f0ae4a0ed54e78261bf2e770277 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 16:43:14 +0800 Subject: [PATCH 182/655] * [bug#58088,done,0.5h] ignore template when count doc. --- module/doc/model.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index 181f0767c9..d3d426d8e7 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -2588,6 +2588,7 @@ class docModel extends model $statistic->totalDocs = $this->dao->select('COUNT(1) AS count')->from(TABLE_DOC) ->where('deleted')->eq('0') ->andWhere('type')->in($this->config->doc->docTypes) + ->andWhere('templateType')->eq('') ->andWhere('vision')->eq($this->config->vision) ->fetch('count'); @@ -2616,6 +2617,7 @@ class docModel extends model $myStatistic = $this->dao->select("COUNT(1) AS myDocs, SUM(views) as docViews, SUM(collects) as docCollects")->from(TABLE_DOC) ->where('addedBy')->eq($this->app->user->account) ->andWhere('type')->in($this->config->doc->docTypes) + ->andWhere('templateType')->eq('') ->andWhere('deleted')->eq(0) ->andWhere('vision')->eq($this->config->vision) ->andWhere('lib')->ne('') From 8529292f798239668a53bcdb17631744029ee0a6 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 11 Dec 2024 17:07:28 +0800 Subject: [PATCH 183/655] * [bug#58084,done,0.5h] avoid repeat upgrade template. --- module/doc/model.php | 13 +++++++++++++ module/upgrade/model.php | 9 ++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index d3d426d8e7..adb342b4d8 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -3757,6 +3757,19 @@ class docModel extends model return $module; } + /** + * 检查文档模板是否已升级。 + * Check if doc template has been upgraded + * + * @access public + * @return bool + */ + public function checkIsTemplateUpgraded() + { + $templateModule = $this->dao->select('1')->from(TABLE_MODULE)->where('type')->eq('docTemplate')->fetch(); + return !empty($templateModule); + } + /** * 插入内置模板类型数据。 * Insert builtin doc template types. diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 6a52611dfd..407b2b3030 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10052,9 +10052,12 @@ class upgradeModel extends model { $this->loadModel('doc'); - $this->doc->upgradeBuiltinTemplateTypes(); - $this->doc->upgradeCustomTemplateTypes(); - $this->doc->upgradeTemplate(); + if(!$this->doc->checkIsTemplateUpgraded()) + { + $this->doc->upgradeBuiltinTemplateTypes(); + $this->doc->upgradeCustomTemplateTypes(); + $this->doc->upgradeTemplate(); + } } /** From 0531b7a7781a8400568593b717c6a05748d8797c Mon Sep 17 00:00:00 2001 From: dingyongliang Date: Wed, 8 Jan 2025 17:46:19 +0800 Subject: [PATCH 184/655] * [task#135982] tmp. --- lib/zin/wg/docapp/js/v1.js | 1 + lib/zin/wg/docapp/v1.php | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index 334e482a85..6ebeb8ce54 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -924,6 +924,7 @@ const actionsMap = ); } return [ + typeof window.importTemplateBtn === 'function' ? window.importTemplateBtn() : null, {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveNewDoc/draft'}, {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveNewDoc'}, {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelCreateDoc'}, diff --git a/lib/zin/wg/docapp/v1.php b/lib/zin/wg/docapp/v1.php index 6c273df31f..cb7273b0b3 100644 --- a/lib/zin/wg/docapp/v1.php +++ b/lib/zin/wg/docapp/v1.php @@ -175,6 +175,7 @@ class docApp extends wg $langData->createRelease = $lang->api->createRelease; $langData->libTypeList = $lang->api->libTypeList; $langData->latestVersion = $lang->api->latestVersion; + $langData->template = $lang->doc->template; /** * 通过语言项定义文档表格列显示名称。 From 4e3446f1e7fc8d6615089a71705b6aeba11cbeba Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 12 Feb 2025 10:14:58 +0800 Subject: [PATCH 185/655] * [task#137268] Add the config of upgrade. --- db/update21.1.sql | 3 --- db/update21.4.sql | 3 +++ module/upgrade/config/upgradeflow.php | 1 + module/upgrade/control.php | 12 ------------ 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/db/update21.1.sql b/db/update21.1.sql index a8bc0846a9..3d194a7c60 100644 --- a/db/update21.1.sql +++ b/db/update21.1.sql @@ -1,6 +1,3 @@ -ALTER TABLE `zt_module` MODIFY COLUMN short varchar(60); -ALTER TABLE `zt_doc` ADD `templateDesc` text NULL AFTER `templateType`; - CREATE TABLE IF NOT EXISTS `zt_system` ( `id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(100) NOT NULL DEFAULT '', diff --git a/db/update21.4.sql b/db/update21.4.sql index b223154273..97a01144c3 100644 --- a/db/update21.4.sql +++ b/db/update21.4.sql @@ -9,3 +9,6 @@ UPDATE `zt_module` SET `path` = CONCAT(',', `path`) WHERE LEFT(`path`, 1) != ',' UPDATE `zt_module` SET `path` = CONCAT(`path`, ',') WHERE RIGHT(`path`, 1) != ','; DROP TABLE IF EXISTS `zt_service`; + +ALTER TABLE `zt_module` MODIFY COLUMN short varchar(60); +ALTER TABLE `zt_doc` ADD `templateDesc` text NULL AFTER `templateType`; diff --git a/module/upgrade/config/upgradeflow.php b/module/upgrade/config/upgradeflow.php index e91a0ddf03..67fc69415f 100644 --- a/module/upgrade/config/upgradeflow.php +++ b/module/upgrade/config/upgradeflow.php @@ -108,6 +108,7 @@ $config->upgrade->execFlow['20_8'] = array('functions' => 'processWorkflo $config->upgrade->execFlow['21_1'] = array('functions' => 'processCacheConfig'); $config->upgrade->execFlow['21_2'] = array('functions' => 'importBuildinWorkflow,addCharterApprovalFlow,processCharterFileConfig,processCharterStatus', 'params' => array('importBuildinWorkflow' => array('rnd', 'charter'))); $config->upgrade->execFlow['21_3'] = array('functions' => 'createDevOpsChartModule'); +$config->upgrade->execFlow['21_4'] = array('functions' => 'upgradeDocTemplate'); if(!empty($config->isINT)) { diff --git a/module/upgrade/control.php b/module/upgrade/control.php index 9a8880bb78..c6e249928b 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -826,18 +826,6 @@ class upgrade extends control echo(json_encode($check)); } - /** - * Ajax: upgrade doc template. - * - * @access public - * @return void - */ - public function ajaxUpgradeDocTemplate() - { - $this->upgrade->upgradeDocTemplate(); - echo 'ok'; - } - /** * 定时任务:处理内置关联关系。 * AJAX: Process object relation. From dd9836798e4faec7be607ac731c8a37af73ef0e5 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 13 Feb 2025 10:26:25 +0800 Subject: [PATCH 186/655] * [task#137133,doing,2.5h] Move the code of docTemplate to zentaomax. --- config/zentaopms.php | 1 - module/doc/control.php | 31 ------------- module/doc/js/app.ui.js | 67 --------------------------- module/doc/js/selecttemplate.ui.js | 13 ------ module/doc/lang/de.php | 1 - module/doc/lang/en.php | 1 - module/doc/lang/fr.php | 1 - module/doc/lang/zh-cn.php | 1 - module/doc/model.php | 12 ----- module/doc/ui/selecttemplate.html.php | 37 --------------- 10 files changed, 165 deletions(-) delete mode 100644 module/doc/js/selecttemplate.ui.js delete mode 100644 module/doc/ui/selecttemplate.html.php diff --git a/config/zentaopms.php b/config/zentaopms.php index ee4021b42a..207be3db6e 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -238,7 +238,6 @@ $config->logonMethods[] = 'cron.schedule'; $config->logonMethods[] = 'custom.index'; $config->logonMethods[] = 'doc.createbasicinfo'; $config->logonMethods[] = 'doc.selectlibtype'; -$config->logonMethods[] = 'doc.selecttemplate'; $config->logonMethods[] = 'doc.uploaddocs'; $config->logonMethods[] = 'doc.setdocbasic'; $config->logonMethods[] = 'doc.commoneditaction'; diff --git a/module/doc/control.php b/module/doc/control.php index 02d32a36f4..81f6cc433d 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -481,37 +481,6 @@ class doc extends control return $this->send(array('result' => 'success', 'load' => $browseLink, 'app' => $this->app->tab)); } - /** - * 选择文档模板。 - * Select template. - * - * @access public - * @return void - */ - public function selectTemplate() - { - $templateList = $this->doc->getTemplatesByType(null, 'normal'); - - $templatePairs = array(); - foreach($templateList as $template) $templatePairs[$template->id] = $template->title; - - $this->view->templatePairs = $templatePairs; - $this->display(); - } - - /** - * Ajax: get template content. - * - * @param int $id - * @access public - * @return void - */ - public function ajaxGetTemplateContent($id) - { - $template = $this->doc->getTemplateContentByID($id); - return print(json_encode(array('type' => $template->type, 'content' => $template->content))); - } - /** * 文档模板列表。 * Browse template list. diff --git a/module/doc/js/app.ui.js b/module/doc/js/app.ui.js index 9d5703369c..e69de29bb2 100644 --- a/module/doc/js/app.ui.js +++ b/module/doc/js/app.ui.js @@ -1,67 +0,0 @@ -function isApiLib(lib, docApp) -{ - if(docApp && docApp.spaceType === 'api') return true; - if(typeof lib === 'number') lib = getDocApp().getLib(lib); - if(!lib) - { - docApp = docApp || getDocApp(); - if(!docApp) return false; - if(docApp.spaceType === 'api') return true; - lib = docApp.lib; - } - return lib && lib.data.type === 'api'; -} - -$.extend(window.docAppActions, -{ - 'doc-edit': function(info) - { - const doc = info.data; - if(!doc) return; - - const lang = getLang(); - if(isApiLib()) - { - return [ - {text: lang.save, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveApiDoc'}, - {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'}, - ]; - } - return [ - {text: lang.template, size: 'md', className: 'btn-wide', type: 'primary-outline', icon: 'save', command: 'selectTemplate'}, - doc.status === 'draft' ? {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveDoc/draft'} : null, - {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveDoc'}, - {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelEditDoc'}, - {text: lang.settings, size: 'md', type: 'ghost', command: `showDocSettingModal/${doc.id}/${doc.contentType}/1`, icon: 'cog-outline'}, - ]; - }, - 'doc-create': function(info) - { - const doc = info.data; - if(!doc) return; - - const lang = getLang(); - if(isApiLib()) - { - return [ - {text: lang.save, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveApiDoc'}, - {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelCreateDoc'}, - ]; - } - return [ - {text: lang.template, size: 'md', className: 'btn-wide', type: 'primary-outline', icon: 'save', command: 'selectTemplate'}, - {text: lang.saveDraft, size: 'md', className: 'btn-wide', type: 'secondary', command: 'saveNewDoc/draft'}, - {text: lang.release, size: 'md', className: 'btn-wide', type: 'primary', command: 'saveNewDoc'}, - {text: lang.cancel, size: 'md', className: 'btn-wide', type: 'primary-outline', command: 'cancelCreateDoc'}, - ]; - } -}); - -$.extend(window.docAppCommands, -{ - selectTemplate: function(_, args) - { - const url = $.createLink('doc', 'selectTemplate'); - zui.Modal.open({size: 'sm', url: url}); - } -}); diff --git a/module/doc/js/selecttemplate.ui.js b/module/doc/js/selecttemplate.ui.js deleted file mode 100644 index dcc71fe21c..0000000000 --- a/module/doc/js/selecttemplate.ui.js +++ /dev/null @@ -1,13 +0,0 @@ -window.applyTemplate = function() -{ - const docApp = getDocApp(); - const editor = docApp.editor.$; - - const templateID = $('#template').find('.picker-box').zui('picker').$.value; - const url = $.createLink('doc', 'ajaxGetTemplateContent', `id=${templateID}`); - $.get(url, function(data) - { - data = JSON.parse(data); - editor.updateDoc(data.content, data.type != 'doc' ? data.type : undefined); - }); -} diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index d0a9f2aa63..c448677c91 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -553,7 +553,6 @@ $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; $lang->doc->viewTemplate = 'View Document Template'; -$lang->doc->selectTemplate = 'Select Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index dfe496fda5..b2228993c6 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -554,7 +554,6 @@ $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; $lang->doc->viewTemplate = 'View Document Template'; -$lang->doc->selectTemplate = 'Select Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 2c5faf7f78..4e0cc817e4 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -553,7 +553,6 @@ $lang->doc->createTemplate = 'Create Document Template'; $lang->doc->editTemplate = 'Edit Document Template'; $lang->doc->deleteTemplate = 'Delete Document Template'; $lang->doc->viewTemplate = 'View Document Template'; -$lang->doc->selectTemplate = 'Select Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 40e7f35445..3c687174a1 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -555,7 +555,6 @@ $lang->doc->createTemplate = '创建文档模板'; $lang->doc->editTemplate = '编辑文档模板'; $lang->doc->deleteTemplate = '删除文档模板'; $lang->doc->viewTemplate = '文档模板详情'; -$lang->doc->selectTemplate = '选择模板'; $lang->doc->addTemplateType = '添加类型'; $lang->doc->editTemplateType = '编辑类型'; $lang->doc->deleteTemplateType = '删除类型'; diff --git a/module/doc/model.php b/module/doc/model.php index 4a73209505..c40de46f59 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -4182,18 +4182,6 @@ class docModel extends model return $moduleID; } - /** - * Get template content by doc id. - * - * @param int $id - * @access public - * @return int - */ - public function getTemplateContentByID($id) - { - return $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($id)->orderBy('version_desc')->fetch(); - } - /** * 获取某个模板类型下的所有模板。 * Get template list by type. diff --git a/module/doc/ui/selecttemplate.html.php b/module/doc/ui/selecttemplate.html.php deleted file mode 100644 index fe81aa41fd..0000000000 --- a/module/doc/ui/selecttemplate.html.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @package doc - * @link https://www.zentao.net - */ -namespace zin; -formPanel -( - set::title($lang->doc->template), - formGroup - ( - setID('template'), - set::label($lang->doc->selectTemplate), - set::name('template'), - set::required(true), - set::width('5/6'), - set::items($templatePairs) - ), - set::actions(array()), - formGroup - ( - setClass('form-actions'), - btn - ( - $lang->save, - set::btnType('button'), - set::type('primary'), - setData('dismiss', 'modal'), - on::click('applyTemplate') - ) - ) -); From 6ef66b73bcbf8617e67fc2b58f2d9e3edf5c772b Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 13 Feb 2025 05:55:16 +0000 Subject: [PATCH 187/655] * [task#137135,done,1h] Adjust convert to document template Confirm tip. --- module/doc/lang/de.php | 43 +++++++++++++++-------------- module/doc/lang/en.php | 43 +++++++++++++++-------------- module/doc/lang/fr.php | 43 +++++++++++++++-------------- module/doc/lang/zh-cn.php | 1 + module/doc/ui/templatelist.html.php | 36 ++++++++++++------------ 5 files changed, 86 insertions(+), 80 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index c448677c91..14061b9f3c 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -73,27 +73,28 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? The changes will be effective after saving the document template, and it will no longer be possible to use the old version of the editor.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index b2228993c6..b84bd2fea9 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -74,27 +74,28 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? The changes will be effective after saving the document template, and it will no longer be possible to use the old version of the editor.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 4e0cc817e4..05b1753e8b 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -73,27 +73,28 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? The changes will be effective after saving the document template, and it will no longer be possible to use the old version of the editor.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 3c687174a1..c2b25187a2 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -95,6 +95,7 @@ $lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; $lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; $lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; $lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; +$lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?文档模板保存后生效,此后将不可再使用旧版本编辑器。'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 03fbdddf9b..b2ce3d4d6b 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -42,24 +42,26 @@ $tableCols['views'] = $lang->docTemplate->views; $tableCols['actions'] = $lang->actions; $langData = array(); -$langData['filterTypes'] = $filterTypes; -$langData['tableCols'] = $tableCols; -$langData['create'] = $lang->docTemplate->create; -$langData['edit'] = $lang->docTemplate->edit; -$langData['delete'] = $lang->docTemplate->delete; -$langData['createTemplate'] = $lang->docTemplate->create; -$langData['editTemplate'] = $lang->docTemplate->edit; -$langData['deleteTemplate'] = $lang->docTemplate->delete; -$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; -$langData['addModule'] = $lang->docTemplate->addModule; -$langData['addSubModule'] = $lang->docTemplate->addSubModule; -$langData['editModule'] = $lang->docTemplate->editModule; -$langData['deleteModule'] = $lang->docTemplate->deleteModule; +$langData['filterTypes'] = $filterTypes; +$langData['tableCols'] = $tableCols; +$langData['create'] = $lang->docTemplate->create; +$langData['edit'] = $lang->docTemplate->edit; +$langData['delete'] = $lang->docTemplate->delete; +$langData['createTemplate'] = $lang->docTemplate->create; +$langData['editTemplate'] = $lang->docTemplate->edit; +$langData['deleteTemplate'] = $lang->docTemplate->delete; +$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; +$langData['addModule'] = $lang->docTemplate->addModule; +$langData['addSubModule'] = $lang->docTemplate->addSubModule; +$langData['editModule'] = $lang->docTemplate->editModule; +$langData['deleteModule'] = $lang->docTemplate->deleteModule; +$langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; +$langData['docTitleRequired'] = $lang->docTemplate->docTitleRequired; +$langData['noDocs'] = $lang->docTemplate->noTemplate; +$langData['convertToNewDocConfirm'] = $lang->docTemplate->convertToNewDocConfirm; -$langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; -$langData['docTitleRequired'] = $lang->docTemplate->docTitleRequired; - -$langData['noDocs'] = $lang->docTemplate->noTemplate; +$lang->doc->docLang->convertToNewDoc = '转换文档'; +$lang->doc->docLang->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档转换为新文档格式吗?文档保存后生效,此后将不可再使用旧版本编辑器。'; $viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); From 675d217ccad0a408e29efaf251ab7f933f26f73b Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 13 Feb 2025 07:11:35 +0000 Subject: [PATCH 188/655] * [task#137135,done,1h] Create convertToNew action. --- module/action/lang/de.php | 1 + module/action/lang/en.php | 1 + module/action/lang/fr.php | 1 + module/action/lang/zh-cn.php | 1 + module/doc/model.php | 10 +++++++--- 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 9f134ad4f4..89967a2ac4 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -292,6 +292,7 @@ $lang->action->desc->managedteam = '$date, by $actor m $lang->action->desc->syncexecutionteam = '$date, synchronise members when execution adds members.' . "\n"; $lang->action->desc->syncprojectteam = '$date, synchronise members when project removes members' . "\n"; $lang->action->desc->syncbycase = '$date, running the testcase sets the request status as Doing.' . "\n"; +$lang->action->desc->converttonewdoc = '$date, $actor completed the conversion.'; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 4c8fef230f..7f2d493629 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -292,6 +292,7 @@ $lang->action->desc->managedteam = '$date, by $actor m $lang->action->desc->syncexecutionteam = '$date, synchronise members when execution adds members.' . "\n"; $lang->action->desc->syncprojectteam = '$date, synchronise members when project removes members' . "\n"; $lang->action->desc->syncbycase = '$date, running the testcase sets the request status as Doing.' . "\n"; +$lang->action->desc->converttonewdoc = '$date, $actor completed the conversion.'; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index d959110f42..3630918e00 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -292,6 +292,7 @@ $lang->action->desc->managedteam = '$date, by $actor m $lang->action->desc->syncexecutionteam = '$date, synchronise members when execution adds members.' . "\n"; $lang->action->desc->syncprojectteam = '$date, synchronise members when project removes members' . "\n"; $lang->action->desc->syncbycase = '$date, running the testcase sets the request status as Doing.' . "\n"; +$lang->action->desc->converttonewdoc = '$date, $actor completed the conversion.'; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor a créé un sous-tâche $extra。' . "\n"; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index a42399b1a4..106ae36b7f 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -292,6 +292,7 @@ $lang->action->desc->managedteam = '$date, 由 $actor $lang->action->desc->syncexecutionteam = '$date, 同步更新执行增加的团队成员。' . "\n"; $lang->action->desc->syncprojectteam = '$date, 同步更新项目删除的团队成员。' . "\n"; $lang->action->desc->syncbycase = '$date, 系统判断由于执行了用例,将测试单状态置为进行中。' . "\n"; +$lang->action->desc->converttonewdoc = '$date, 由 $actor 完成了文档转换。'; /* 用来描述和父子任务相关的操作历史记录。*/ $lang->action->desc->createchildren = '$date, 由 $actor 创建子任务 $extra。' . "\n"; diff --git a/module/doc/model.php b/module/doc/model.php index c40de46f59..86a86800b6 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1764,10 +1764,8 @@ class docModel extends model } } - unset($doc->contentType); - unset($doc->rawContent); $doc->draft = isset($doc->content) ? $doc->content : ''; - $this->dao->update(TABLE_DOC)->data($doc, 'content') + $this->dao->update(TABLE_DOC)->data($doc, 'content,rawContent,contentType') ->autoCheck() ->batchCheck($requiredFields, 'notempty') ->where('id')->eq($docID) @@ -1775,6 +1773,12 @@ class docModel extends model if(dao::isError()) return false; $this->file->updateObjectID($this->post->uid, $docID, 'doc'); + + if(in_array($oldDoc->contentType, array('html', 'attachment', 'markdown')) && !in_array($doc->contentType, array('html', 'attachment', 'markdown'))) + { + $objectType = !empty($doc->templateType) ? 'doctemplate' : 'doc'; + $this->loadModel('action')->create($objectType, $docID, 'convertToNewDoc'); + } return array('changes' => $changes, 'files' => $files); } From a55331029176358c4a996583a6c33a70a1e1a52d Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 13 Feb 2025 07:57:27 +0000 Subject: [PATCH 189/655] * [task#137134,done,1h] Adjust old document editing tip. --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 43 +++++++++++++++-------------- module/doc/ui/templatelist.html.php | 4 +-- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 14061b9f3c..7091ba52e3 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -95,6 +95,7 @@ $lang->docTemplate->docTitleRequired = 'Please enter the doc template titl $lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? The changes will be effective after saving the document template, and it will no longer be possible to use the old version of the editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index b84bd2fea9..128e8cd236 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -96,6 +96,7 @@ $lang->docTemplate->docTitleRequired = 'Please enter the doc template titl $lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? The changes will be effective after saving the document template, and it will no longer be possible to use the old version of the editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 05b1753e8b..5b8f5d9081 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -95,6 +95,7 @@ $lang->docTemplate->docTitleRequired = 'Please enter the doc template titl $lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; $lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; $lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? The changes will be effective after saving the document template, and it will no longer be possible to use the old version of the editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index c2b25187a2..709cc6fd63 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -74,28 +74,29 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = '编号'; -$lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequency = '频率'; -$lang->docTemplate->type = '类型'; -$lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建时间'; -$lang->docTemplate->editedBy = '最后修改者'; -$lang->docTemplate->editedDate = '最后修改时间'; -$lang->docTemplate->views = '阅读次数'; -$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; -$lang->docTemplate->scope = '所属范围'; -$lang->docTemplate->module = '模板类型'; -$lang->docTemplate->desc = '描述'; -$lang->docTemplate->parentModule = '上级类型'; -$lang->docTemplate->typeName = '类型名称'; -$lang->docTemplate->addTemplateType = '添加文档模板类型'; -$lang->docTemplate->editTemplateType = '编辑文档模板类型'; -$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; -$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; -$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; -$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequency = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建时间'; +$lang->docTemplate->editedBy = '最后修改者'; +$lang->docTemplate->editedDate = '最后修改时间'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->scope = '所属范围'; +$lang->docTemplate->module = '模板类型'; +$lang->docTemplate->desc = '描述'; +$lang->docTemplate->parentModule = '上级类型'; +$lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->addTemplateType = '添加文档模板类型'; +$lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; +$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; +$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; +$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; $lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?文档模板保存后生效,此后将不可再使用旧版本编辑器。'; +$lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本编辑器创建,已启用新版编辑器编辑,保存后将转换为新版文档模板'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index b2ce3d4d6b..1d430531fa 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -59,9 +59,7 @@ $langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; $langData['docTitleRequired'] = $lang->docTemplate->docTitleRequired; $langData['noDocs'] = $lang->docTemplate->noTemplate; $langData['convertToNewDocConfirm'] = $lang->docTemplate->convertToNewDocConfirm; - -$lang->doc->docLang->convertToNewDoc = '转换文档'; -$lang->doc->docLang->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档转换为新文档格式吗?文档保存后生效,此后将不可再使用旧版本编辑器。'; +$langData['oldDocEditingTip'] = $lang->docTemplate->oldDocEditingTip; $viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); From 3be270752922187e88c9f878844d54e377c92e00 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 13 Feb 2025 16:09:00 +0800 Subject: [PATCH 190/655] * [bug#59612] Change the icon of docTemplate in home page. --- module/doc/ui/templatehome.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index b1391c1f5e..2b549e913c 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -38,7 +38,7 @@ $buildScopeCards = function($templates) use ($lang) setClass('flex gap-2 items-center py-2'), icon ( - setClass('icon-doc text-2xl') + setClass('icon-file-archive text-2xl') ), div ( From c86086d7d0ef39119e9f32b6210281e5237b97b0 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 14 Feb 2025 10:22:10 +0800 Subject: [PATCH 191/655] * [misc] Merge main db to doctemplate. --- db/update21.4.sql | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/db/update21.4.sql b/db/update21.4.sql index 97a01144c3..3e8517632d 100644 --- a/db/update21.4.sql +++ b/db/update21.4.sql @@ -10,5 +10,12 @@ UPDATE `zt_module` SET `path` = CONCAT(`path`, ',') WHERE RIGHT(`path`, 1) != ', DROP TABLE IF EXISTS `zt_service`; +CREATE TABLE IF NOT EXISTS `zt_extuser` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `code` varchar(255) NOT NULL, + `account` char(30) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + ALTER TABLE `zt_module` MODIFY COLUMN short varchar(60); ALTER TABLE `zt_doc` ADD `templateDesc` text NULL AFTER `templateType`; From 5e3fce1e4cae0a9c8f81375af928929f66a16e65 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Tue, 11 Feb 2025 15:28:06 +0800 Subject: [PATCH 192/655] +[task#137311,doing,0.2h,1.3h] Add ztf notes. --- module/caselib/test/ui/editcaselib.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 module/caselib/test/ui/editcaselib.php diff --git a/module/caselib/test/ui/editcaselib.php b/module/caselib/test/ui/editcaselib.php new file mode 100755 index 0000000000..0a3a455553 --- /dev/null +++ b/module/caselib/test/ui/editcaselib.php @@ -0,0 +1,18 @@ +#!/usr/bin/env php + Date: Tue, 11 Feb 2025 15:29:06 +0800 Subject: [PATCH 193/655] *[task#137311,doing,0.4h,1.1h] Add ui test file. --- module/caselib/test/ui/editcaselib.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/caselib/test/ui/editcaselib.php b/module/caselib/test/ui/editcaselib.php index 0a3a455553..4fa607038c 100755 --- a/module/caselib/test/ui/editcaselib.php +++ b/module/caselib/test/ui/editcaselib.php @@ -16,3 +16,23 @@ cid=73 */ chdir(__DIR__); +include '../lib/editcaselib.ui.class.php'; + +$caselib = zenData('testsuite'); +$caselib->id->range('1'); +$caselib->project->range(''); +$caselib->product->range(''); +$caselib->name->range('用例库1'); +$caselib->desc->range('用例库的描述'); +$caselib->type->range('library'); +$caselib->order->range('0'); +$caselib->addedBy->range('admin'); +$caselib->addedDate->range('(+5w)-(+6w):1D')->type('timestamp')->format('YY/MM/DD'); +$caselib->deleted->range('0'); +$caselib->gen(1); + +$tester = new editCaselibTester(); +$tester->login(); + +//设置数据 +$caselib = array( From 7b7dbf32b84102914a431d3f32566c0dc53bb84d Mon Sep 17 00:00:00 2001 From: lihuifang Date: Tue, 11 Feb 2025 15:29:21 +0800 Subject: [PATCH 194/655] *[task#137311,doing,0.5h,1h] Add ui test file. --- module/caselib/test/ui/editcaselib.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/module/caselib/test/ui/editcaselib.php b/module/caselib/test/ui/editcaselib.php index 4fa607038c..3964f18423 100755 --- a/module/caselib/test/ui/editcaselib.php +++ b/module/caselib/test/ui/editcaselib.php @@ -36,3 +36,11 @@ $tester->login(); //设置数据 $caselib = array( + array('name' => ''), + array('name' => '用例库2'), +); + +r($tester->editCaselib($caselib['0'])) && p('message,status') && e('编辑用例库表单页必填提示信息正确,SUCCESS'); // 用例库名称置空保存,检查提示信息 +r($tester->editCaselib($caselib['1'])) && p('message,status') && e('用例库编辑成功,SUCCESS'); // 编辑用例库 + +$tester->closeBrowser(); From f4f4a9d93c8462af9b95b96a852e77d367644b23 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Tue, 11 Feb 2025 15:30:10 +0800 Subject: [PATCH 195/655] *[task#137311,doing,0.6h,0.9h] Add browse element file.. --- module/caselib/test/ui/page/browse.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/caselib/test/ui/page/browse.php b/module/caselib/test/ui/page/browse.php index 9a12002b12..1424b04d85 100755 --- a/module/caselib/test/ui/page/browse.php +++ b/module/caselib/test/ui/page/browse.php @@ -6,7 +6,8 @@ class browsePage extends page parent::__construct($webdriver); $xpath = array( 'viewName' => "//*[@class='modal-content']/div[2]/div/div/div/span[2]", - 'viewLibModal' => "//*[@id='actionBar']/a[1]" + 'viewLibModal' => "//*[@id='actionBar']/a[1]", + 'editBtn' => "//*[@id='viewLibModal']/div/div/div[2]/div[2]/div/div[3]/div/a[1]" ); $this->dom->xpath = array_merge($this->dom->xpath, $xpath); } From ac3db92146c76a2870c0212c0fd307b098607634 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Tue, 11 Feb 2025 15:31:09 +0800 Subject: [PATCH 196/655] +[task#137311,doing,1h,0.5h] Add testui function. --- .../caselib/test/lib/editcaselib.ui.class.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 module/caselib/test/lib/editcaselib.ui.class.php diff --git a/module/caselib/test/lib/editcaselib.ui.class.php b/module/caselib/test/lib/editcaselib.ui.class.php new file mode 100755 index 0000000000..bc69aec2fa --- /dev/null +++ b/module/caselib/test/lib/editcaselib.ui.class.php @@ -0,0 +1,19 @@ +initForm('caselib', 'browse', array('libID' => 1), 'appIframe-qa'); + $form->dom->btn($this->lang->caselib->view)->click(); + $form->dom->editBtn->click(); + if(isset($caselib['name'])) $form->dom->name->setValue($caselib['name']); + + $form->dom->btn($this->lang->save)->click(); From 2f2712efd970c2996110ffa6cad7229d0d8bfcbc Mon Sep 17 00:00:00 2001 From: lihuifang Date: Tue, 11 Feb 2025 15:31:28 +0800 Subject: [PATCH 197/655] *[task#137311,done,1.5h,0h] Add testui function. --- .../caselib/test/lib/editcaselib.ui.class.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/caselib/test/lib/editcaselib.ui.class.php b/module/caselib/test/lib/editcaselib.ui.class.php index bc69aec2fa..064faa71b7 100755 --- a/module/caselib/test/lib/editcaselib.ui.class.php +++ b/module/caselib/test/lib/editcaselib.ui.class.php @@ -17,3 +17,23 @@ class editCaselibTester extends tester if(isset($caselib['name'])) $form->dom->name->setValue($caselib['name']); $form->dom->btn($this->lang->save)->click(); + $form->wait(1); + + /* 检查创建用例库页面必填提示信息 */ + if(is_object($form->dom->nameTip)) + { + $nameTipForm = $form->dom->nameTip->getText(); + $nameTip = sprintf($this->lang->error->notempty, $this->lang->caselib->name); + return ($nameTipForm == $nameTip) ? $this->success('编辑用例库表单页必填提示信息正确') : $this->failed('编辑用例库表单页必填提示信息不正确'); + } + + /* 点击查看库概况 */ + $browsePage = $this->loadPage('caselib', 'browse'); + $browsePage->dom->btn($this->lang->caselib->view)->click(); + $browsePage->wait(1); + + //断言检查用例库名称是否正确 + if($browsePage->dom->viewName->getText() == $caselib['name']) return $this->success('用例库编辑成功'); + return $this->failed('用例库编辑失败'); + } +} From 9d77a8bc05e3b60d5a8c8fe92f2c180cd1451954 Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:13:57 +0800 Subject: [PATCH 198/655] * [task#137312,doing,0.1h,5.9h] Add product data for uitest of results function. --- module/testtask/test/ui/results.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 module/testtask/test/ui/results.php diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php new file mode 100644 index 0000000000..9259343860 --- /dev/null +++ b/module/testtask/test/ui/results.php @@ -0,0 +1,17 @@ +#!/usr/bin/env php +id->range('1-100'); +$product->name->range('产品1, 产品2'); +$product->type->range('normal'); +$product->gen(2); From 0b7fc965a5c5f1bad4f066fccdd0ece1518ad21c Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:15:08 +0800 Subject: [PATCH 199/655] * [task#137312,doing,0.1h,5.9h] Add project and projectproduct data for uitest of results function. --- module/testtask/test/ui/results.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php index 9259343860..353ebfbaac 100644 --- a/module/testtask/test/ui/results.php +++ b/module/testtask/test/ui/results.php @@ -15,3 +15,23 @@ $product->id->range('1-100'); $product->name->range('产品1, 产品2'); $product->type->range('normal'); $product->gen(2); + +$project = zenData('project'); +$project->id->range('1-100'); +$project->project->range('0, 1{3}'); +$project->model->range('scrum, []{3}'); +$project->type->range('project, sprint{3}'); +$project->auth->range('extend, []{3}'); +$project->storytype->range('`story,epic,requirement`'); +$project->path->range('`,1,`, `,1,2,`, `,1,3,`, `,1,4,`'); +$project->grade->range('1'); +$project->name->range('项目1, 项目1执行1, 项目1执行2, 项目1执行3'); +$project->hasProduct->range('1'); +$project->status->range('wait'); +$project->acl->range('open'); +$project->gen(4); + +$projectProduct = zenData('projectproduct'); +$projectProduct->project->range('1, 2, 3, 4'); +$projectProduct->product->range('1{4}, 2{4}'); +$projectProduct->gen(8); From 6530fb35cce7f05cacfe7fa7a235c23cbecf70ea Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:15:51 +0800 Subject: [PATCH 200/655] * [task#137312,doing,0.1h,5.8h] Add build and testtask data for uitest of results function. --- module/testtask/test/ui/results.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php index 353ebfbaac..1d85abef21 100644 --- a/module/testtask/test/ui/results.php +++ b/module/testtask/test/ui/results.php @@ -35,3 +35,28 @@ $projectProduct = zenData('projectproduct'); $projectProduct->project->range('1, 2, 3, 4'); $projectProduct->product->range('1{4}, 2{4}'); $projectProduct->gen(8); + +$build = zenData('build'); +$build->id->range('1-100'); +$build->project->range('1'); +$build->product->range('1'); +$build->branch->range('0'); +$build->execution->range('2{4}, 3{2}'); +$build->name->range('构建1, 构建2, 构建3, 构建4, 构建5, 构建6'); +$build->scmPath->range('[]'); +$build->filePath->range('[]'); +$build->deleted->range('0'); +$build->gen(1); + +$testtask = zenData('testtask'); +$testtask->id->range('1-100'); +$testtask->project->range('1'); +$testtask->product->range('1'); +$testtask->name->range('测试单1, 测试单2, 测试单3, 测试单4, 测试单5, 测试单6'); +$testtask->execution->range('2{4}, 3{2}'); +$testtask->build->range('1-6'); +$testtask->begin->range('(-2D)-(-D):1D')->type('timestamp')->format('YY/MM/DD'); +$testtask->end->range('(+D)-(+2D):1D')->type('timestamp')->format('YY/MM/DD'); +$testtask->status->range('wait{5}, doing{5}, done{3}, blocked{2}'); +$testtask->deleted->range('0'); +$testtask->gen(1); From 3228ca2ee7f7d1f4990d1a2241f1c67c6ba78343 Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:16:30 +0800 Subject: [PATCH 201/655] * [task#137312,doing,0.1h,5.7h] Add case data for uitest of results function. --- module/testtask/test/ui/results.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php index 1d85abef21..3eb7018faa 100644 --- a/module/testtask/test/ui/results.php +++ b/module/testtask/test/ui/results.php @@ -60,3 +60,32 @@ $testtask->end->range('(+D)-(+2D):1D')->type('timestamp')->format('YY/MM/DD'); $testtask->status->range('wait{5}, doing{5}, done{3}, blocked{2}'); $testtask->deleted->range('0'); $testtask->gen(1); + +$case = zenData('case'); +$case->id->range('1-100'); +$case->project->range('1{2}, 0{100}'); +$case->product->range('1{10}, 2{5}'); +$case->execution->range('0{5}, 2{10}'); +$case->story->range('1{2}, 2{3}, 0{100}'); +$case->title->range('1-100'); +$case->stage->range('feature'); +$case->status->range('normal,blocked,investigate,normal{100}'); +$case->deleted->range('0{14}, 1'); +$case->gen(15); + +$casestep = zenData('casestep'); +$casestep->id->range('1-100'); +$casestep->parent->range('0'); +$casestep->case->range('2'); +$casestep->version->range('1'); +$casestep->type->range('step'); +$casestep->desc->range('1'); +$casestep->expect->range('1'); +$casestep->gen(1); + +$casespec = zenData('casespec'); +$casespec->id->range('1-100'); +$casespec->case->range('1-100'); +$casespec->version->range('1'); +$casespec->title->range('1-100'); +$casespec->gen(15); From 33784941fa5ae234cffd554301b5c8ff6f7748b6 Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:17:19 +0800 Subject: [PATCH 202/655] * [task#137312,doing,0.3h,5.4h] Add testrun and restresult data for uitest of results function. --- module/testtask/test/ui/results.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php index 3eb7018faa..48ec43950b 100644 --- a/module/testtask/test/ui/results.php +++ b/module/testtask/test/ui/results.php @@ -89,3 +89,23 @@ $casespec->case->range('1-100'); $casespec->version->range('1'); $casespec->title->range('1-100'); $casespec->gen(15); + +$testrun = zenData('testrun'); +$testrun->id->range('1-100'); +$testrun->task->range('1'); +$testrun->case->range('1-100'); +$testrun->version->range('1'); +$testrun->lastRunner->range('[]'); +$testrun->lastRunResult->range('[]'); +$testrun->status->range('normal'); +$testrun->gen(2); + +$testresult = zenData('testresult'); +$testresult->id->range('1-100'); +$testresult->run->range('1, 2{100}'); +$testresult->case->range('1, 2{100}'); +$testresult->version->range('1'); +$testresult->caseResult->range('pass{3}, fail, blocked'); +$testresult->stepResults->range('`a:1:{i:0;a:2:{s:6:"result";s:4:"pass";s:4:"real";s:0:"";}}`, `a:1:{i:1;a:2:{s:6:"result";s:3:"n/a";s:4:"real";s:0:"";}}`, `a:1:{i:1;a:2:{s:6:"result";s:4:"pass";s:4:"real";s:0:"";}}`, `a:1:{i:1;a:2:{s:6:"result";s:4:"fail";s:4:"real";s:3:"aaa";}}`, `a:1:{i:1;a:2:{s:6:"result";s:7:"blocked";s:4:"real";s:3:"bbb";}}`'); +$testresult->lastRunner->range('user1'); +$testresult->gen(5); From c88d2f7fcdc42491a0c7115fba3ae8347c07372e Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:18:02 +0800 Subject: [PATCH 203/655] * [task#137312,doing,0.1h,5.3h] Add user data for uitest of results function. --- module/testtask/test/ui/results.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php index 48ec43950b..553da6aba3 100644 --- a/module/testtask/test/ui/results.php +++ b/module/testtask/test/ui/results.php @@ -109,3 +109,14 @@ $testresult->caseResult->range('pass{3}, fail, blocked'); $testresult->stepResults->range('`a:1:{i:0;a:2:{s:6:"result";s:4:"pass";s:4:"real";s:0:"";}}`, `a:1:{i:1;a:2:{s:6:"result";s:3:"n/a";s:4:"real";s:0:"";}}`, `a:1:{i:1;a:2:{s:6:"result";s:4:"pass";s:4:"real";s:0:"";}}`, `a:1:{i:1;a:2:{s:6:"result";s:4:"fail";s:4:"real";s:3:"aaa";}}`, `a:1:{i:1;a:2:{s:6:"result";s:7:"blocked";s:4:"real";s:3:"bbb";}}`'); $testresult->lastRunner->range('user1'); $testresult->gen(5); + +$user = zenData('user'); +$user->id->range('1-100'); +$user->dept->range('0, 1{2}, 2{3}, 3{5}'); +$user->account->range('admin, user1, user2, user3, user4, user5, user11, user12, user13, user14, user15'); +$user->realname->range('admin, USER1, USER2, USER3, USER4, USER5, USER11, USER12, USER13, USER14, USER15'); +$user->password->range($config->uitest->defaultPassword)->format('md5'); +$user->gen(5); + +$tester = new resultsTester(); +$tester->login(); From 949ece542b27e258ca039259e1f74affd98bdf00 Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:18:31 +0800 Subject: [PATCH 204/655] * [task#137312,doing,0.3h,5h] Add cases for uitest of results function. --- module/testtask/test/ui/results.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/module/testtask/test/ui/results.php b/module/testtask/test/ui/results.php index 553da6aba3..086db1e159 100644 --- a/module/testtask/test/ui/results.php +++ b/module/testtask/test/ui/results.php @@ -120,3 +120,14 @@ $user->gen(5); $tester = new resultsTester(); $tester->login(); + +$resulta = array('name' => '测试单1', 'build' => '构建1', 'user' => 'USER1', 'resultcn' => '阻塞', 'resulten' => 'Blocked', 'sResultcn' => '阻塞', 'sResulten' => 'Blocked', 'stepReal' => 'bbb'); +$resultb = array('name' => '测试单1', 'build' => '构建1', 'user' => 'USER1', 'resultcn' => '失败', 'resulten' => 'Fail', 'sResultcn' => '失败', 'sResulten' => 'Fail', 'stepReal' => 'aaa'); +$resultc = array('name' => '测试单1', 'build' => '构建1', 'user' => 'USER1', 'resultcn' => '通过', 'resulten' => 'Pass', 'sResultcn' => '通过', 'sResulten' => 'Pass', 'stepReal' => ''); +$resultd = array('name' => '测试单1', 'build' => '构建1', 'user' => 'USER1', 'resultcn' => '通过', 'resulten' => 'Pass', 'sResultcn' => '忽略', 'sResulten' => 'Ignore', 'stepReal' => ''); + +r($tester->checkResults(1, $resulta)) && p('status,message') && e('SUCCESS,测试结果正确'); +r($tester->checkResults(2, $resultb)) && p('status,message') && e('SUCCESS,测试结果正确'); +r($tester->checkResults(3, $resultc)) && p('status,message') && e('SUCCESS,测试结果正确'); +r($tester->checkResults(4, $resultd)) && p('status,message') && e('SUCCESS,测试结果正确'); +$tester->closeBrowser(); From 10eda56843c8bc9952d851ed2a46b0303e47ce1a Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:19:26 +0800 Subject: [PATCH 205/655] * [task#137312,doing,0.1h,4.9h] Add class for uitest of results function. --- module/testtask/test/lib/results.ui.class.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 module/testtask/test/lib/results.ui.class.php diff --git a/module/testtask/test/lib/results.ui.class.php b/module/testtask/test/lib/results.ui.class.php new file mode 100644 index 0000000000..8860630d8a --- /dev/null +++ b/module/testtask/test/lib/results.ui.class.php @@ -0,0 +1,14 @@ + Date: Tue, 11 Feb 2025 16:20:20 +0800 Subject: [PATCH 206/655] * [task#137312,doing,4h,2h] Add function for uitest of results function. --- module/testtask/test/lib/results.ui.class.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/module/testtask/test/lib/results.ui.class.php b/module/testtask/test/lib/results.ui.class.php index 8860630d8a..e7dd6d3e0e 100644 --- a/module/testtask/test/lib/results.ui.class.php +++ b/module/testtask/test/lib/results.ui.class.php @@ -11,4 +11,26 @@ class resultsTester extends tester * @access public * @return void */ + public function checkResults($num = 1, $task) + { + $form = $this->initForm('testtask', 'cases', array('taskID'=> '1'), 'appIframe-qa'); + /* 测试单下第一个用例后的结果按钮 */ + $form->dom->xpath['resultsBtn']= "(//*[@id='table-testtask-cases']//nav[@class='toolbar'])[1]/a[@title='{$this->lang->testtask->results}']"; + /* 测试结果弹窗中结果和具体信息 */ + $form->dom->xpath['item'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num - 1) . "]"; + $form->dom->xpath['results'] = $form->dom->xpath['item'] . "/td"; + $form->dom->xpath['stepResult'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num) . "]/td/form/div[1]/div[2]/div/div[4]"; + $form->dom->xpath['stepReal'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num) . "]/td/form/div[1]/div[2]/div/div[5]"; + + $form->dom->resultsBtn->click(); + $form->wait(1); + /* 结果弹窗默认打开第一个结果详情,其他结构详情手动点击展开 */ + if($num !=1) $form->dom->item->click(); + $form->wait(1); + + /* 从测试结果中提取相关信息 */ + $result = str_replace(',', ' ', $form->dom->results->getText()); // 将中文逗号替换为空格 + $result = str_replace('。', ' ', $result); // 将中文句号替换为空格 + $param = preg_split('/\s+/', $result); // 按空格拆分字符串 + } } From 6a21209c13c7d0125ea0018e26b71fb641caf635 Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:21:14 +0800 Subject: [PATCH 207/655] * [task#137312,done,3h] Add assertion for uitest of results function. --- module/testtask/test/lib/results.ui.class.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/testtask/test/lib/results.ui.class.php b/module/testtask/test/lib/results.ui.class.php index e7dd6d3e0e..acf4e26273 100644 --- a/module/testtask/test/lib/results.ui.class.php +++ b/module/testtask/test/lib/results.ui.class.php @@ -32,5 +32,25 @@ class resultsTester extends tester $result = str_replace(',', ' ', $form->dom->results->getText()); // 将中文逗号替换为空格 $result = str_replace('。', ' ', $result); // 将中文句号替换为空格 $param = preg_split('/\s+/', $result); // 按空格拆分字符串 + /* 根据系统语言选择测试结果和信息 */ + if($this->config->default->lang == 'zh-cn') + { + $taskResult = $task['resultcn']; + $stepResult = $task['sResultcn']; + } + else + { + $taskResult = $task['resulten']; + $stepResult = $task['sResulten']; + } + /* 校验测试结果 */ + if($param[4] != $task['user']) return $this->failed('用例执行人错误'); + if($param[6] != $task['name']) return $this->failed('测试单名称错误'); + if($param[8] != $task['build']) return $this->failed('构建错误'); + if($param[10] != $taskResult) return $this->failed('测试结果错误'); + /* 校验测试步骤结果 */ + if($form->dom->stepResult->getText() != $stepResult) return $this->failed('测试步骤结果错误'); + if($form->dom->stepReal->getText() != $task['stepReal']) return $this->failed('测试步骤实际情况错误'); + return $this->success('测试结果正确'); } } From dcf0e673c4d371ba036d2e9ba180709e048e479b Mon Sep 17 00:00:00 2001 From: yulujie Date: Tue, 11 Feb 2025 16:38:53 +0800 Subject: [PATCH 208/655] * [task#137312,done,0.3h] Add assertion of createbug button for uitest of results function. --- module/testtask/test/lib/results.ui.class.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/module/testtask/test/lib/results.ui.class.php b/module/testtask/test/lib/results.ui.class.php index acf4e26273..dd9eb7e71c 100644 --- a/module/testtask/test/lib/results.ui.class.php +++ b/module/testtask/test/lib/results.ui.class.php @@ -19,8 +19,10 @@ class resultsTester extends tester /* 测试结果弹窗中结果和具体信息 */ $form->dom->xpath['item'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num - 1) . "]"; $form->dom->xpath['results'] = $form->dom->xpath['item'] . "/td"; - $form->dom->xpath['stepResult'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num) . "]/td/form/div[1]/div[2]/div/div[4]"; - $form->dom->xpath['stepReal'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num) . "]/td/form/div[1]/div[2]/div/div[5]"; + $form->dom->xpath['detail'] = "//*[@class='modal-content']//tbody/tr[" . (2 * $num) . "]/td/form/div[1]"; + $form->dom->xpath['stepResult'] = $form->dom->xpath['detail'] . "/div[2]/div/div[4]"; + $form->dom->xpath['stepReal'] = $form->dom->xpath['detail'] . "/div[2]/div/div[5]"; + $form->dom->xpath['bug'] = $form->dom->xpath['detail'] . "//button/span"; $form->dom->resultsBtn->click(); $form->wait(1); @@ -51,6 +53,10 @@ class resultsTester extends tester /* 校验测试步骤结果 */ if($form->dom->stepResult->getText() != $stepResult) return $this->failed('测试步骤结果错误'); if($form->dom->stepReal->getText() != $task['stepReal']) return $this->failed('测试步骤实际情况错误'); + if($stepResult == 'fail') + { + if(!is_object($form->dom->bug) || $form->dom->bug->getText() != $this->lang->testtask->createBug) return $this->failed('失败的用例没有显示提bug按钮或按钮名称错误'); + } return $this->success('测试结果正确'); } } From 5f161c7985ceeb5f1d9e71fd81a71ba2bc12666c Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:37:41 +0800 Subject: [PATCH 209/655] + [task#137219,doing,1h,2h] add editstage function. --- module/stage/test/lib/editstage.ui.class.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 module/stage/test/lib/editstage.ui.class.php diff --git a/module/stage/test/lib/editstage.ui.class.php b/module/stage/test/lib/editstage.ui.class.php new file mode 100755 index 0000000000..e0fe3b9955 --- /dev/null +++ b/module/stage/test/lib/editstage.ui.class.php @@ -0,0 +1,20 @@ +initForm('stage', 'browse', array(), 'appIframe-admin'); + $form->dom->editBtn->click(); + } From 4f2b79a48ce6994eefe965d878acd2166aa82687 Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:39:11 +0800 Subject: [PATCH 210/655] + [task#137219,doing,1h,2h] add editstage function. --- module/stage/test/lib/editstage.ui.class.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/module/stage/test/lib/editstage.ui.class.php b/module/stage/test/lib/editstage.ui.class.php index e0fe3b9955..924f9c1969 100755 --- a/module/stage/test/lib/editstage.ui.class.php +++ b/module/stage/test/lib/editstage.ui.class.php @@ -18,3 +18,21 @@ class editStageTester extends tester $form = $this->initForm('stage', 'browse', array(), 'appIframe-admin'); $form->dom->editBtn->click(); } + if($type == 'waterfallplus') + { + $form = $this->initForm('stage', 'plusbrowse', array(), 'appIframe-admin'); + $form->dom->plusEditBtn->click(); + } + $editForm = $this->loadPage('stage', 'edit'); + if(isset($stage['name'])) $editForm->dom->name->setValue($stage['name']); + if(isset($stage['percent'])) $editForm->dom->percent->setValue($stage['percent']); + if(isset($stage['type'])) $editForm->dom->type->picker($stage['type']); + if($type == 'waterfall') + { + $editForm->dom->submitBtn->click(); + } + else + { + $editForm->dom->plusSubmitBtn->click(); + } + $editForm->wait(1); From 6574495948bcb36033d4ec973ba02b90396264e0 Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:40:29 +0800 Subject: [PATCH 211/655] + [task#137219,doing,1h,2h] add editstage function. --- module/stage/test/lib/editstage.ui.class.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/module/stage/test/lib/editstage.ui.class.php b/module/stage/test/lib/editstage.ui.class.php index 924f9c1969..43aa231d70 100755 --- a/module/stage/test/lib/editstage.ui.class.php +++ b/module/stage/test/lib/editstage.ui.class.php @@ -36,3 +36,20 @@ class editStageTester extends tester $editForm->dom->plusSubmitBtn->click(); } $editForm->wait(1); + + /* 检查阶段名称和工作量占比不能为空。 */ + if($editForm->dom->nameTip && $editForm->dom->percentTip) + { + $nameTipText = $editForm->dom->nameTip->getText(); + $nameTip = sprintf($this->lang->error->notempty, $this->lang->stage->name); + $percentTipText = $editForm->dom->percentTip->getText(); + $percentTip = sprintf($this->lang->error->notempty, $this->lang->stage->percent); + return ($nameTipText == $nameTip && $percentTipText == $percentTip) ? $this->success('编辑阶段表单页提示信息正确') : $this->failed('编辑阶段表单页提示信息不正确'); + } + /* 检查工作量占比累计不能超过100% */ + if($editForm->dom->percentOverTip) + { + $percentOverText = $editForm->dom->percentOverTip->getText(); + $percentOverTip = $this->lang->stage->error->percentOver; + return ($percentOverText == $percentOverTip) ? $this->success('工作量占比累计超出100%时提示信息正确') : $this->failed('工作量占比累计超出100%时提示信息不正确'); + } From 134a63ac9b5ca830b2ce16eea46e848db0f51f2c Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:41:57 +0800 Subject: [PATCH 212/655] + [task#137219,doing,1h,2h] add assertion editstage function. --- module/stage/test/lib/editstage.ui.class.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/module/stage/test/lib/editstage.ui.class.php b/module/stage/test/lib/editstage.ui.class.php index 43aa231d70..ac068524f4 100755 --- a/module/stage/test/lib/editstage.ui.class.php +++ b/module/stage/test/lib/editstage.ui.class.php @@ -53,3 +53,20 @@ class editStageTester extends tester $percentOverTip = $this->lang->stage->error->percentOver; return ($percentOverText == $percentOverTip) ? $this->success('工作量占比累计超出100%时提示信息正确') : $this->failed('工作量占比累计超出100%时提示信息不正确'); } + + /* 跳转到阶段列表,检查阶段信息。 */ + if($type == 'waterfall') + { + $browsePage = $this->loadPage('stage', 'browse'); + if($browsePage->dom->stageNameA->getText() != $stage['name']) return $this->failed('阶段名称错误'); + if($browsePage->dom->stageTypeA->getText() != $stage['type']) return $this->failed('阶段类型错误'); + } + if($type == 'waterfallplus') + { + $plusbrowsePage = $this->loadPage('stage', 'plusbrowse'); + if($plusbrowsePage->dom->stageNameB->getText() != $stage['name']) return $this->failed('阶段名称错误'); + if($plusbrowsePage->dom->stageTypeB->getText() != $stage['type']) return $this->failed('阶段类型错误'); + } + return $this->success('编辑阶段成功'); + } +} From 10a35c75801981c5c8a936c751b0a603667363f8 Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:44:25 +0800 Subject: [PATCH 213/655] + [task#137219,doing,0.11h,1.9h] add comment of editstage ui file. --- module/stage/test/ui/editstage.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 module/stage/test/ui/editstage.php diff --git a/module/stage/test/ui/editstage.php b/module/stage/test/ui/editstage.php new file mode 100755 index 0000000000..bcd4d1aa26 --- /dev/null +++ b/module/stage/test/ui/editstage.php @@ -0,0 +1,20 @@ +#!/usr/bin/env php + Date: Tue, 11 Feb 2025 16:45:51 +0800 Subject: [PATCH 214/655] + [task#137219,doing,0.2h,1.5h] add stage test data. --- module/stage/test/ui/editstage.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/stage/test/ui/editstage.php b/module/stage/test/ui/editstage.php index bcd4d1aa26..dfc78589e8 100755 --- a/module/stage/test/ui/editstage.php +++ b/module/stage/test/ui/editstage.php @@ -18,3 +18,23 @@ cid=2 - 最终测试状态 @ SUCCESS - 融合瀑布模型下校验阶段名称不能为空 - 测试结果 @编辑阶段表单页提示信息正确 + - 最终测试状态 @ SUCCESS +- 融合瀑布模型下工作量占比累计不能超出100% + - 测试结果 @工作量占比累计超出100%时提示信息正确 + - 最终测试状态 @ SUCCESS +- 融合瀑布模型下编辑设计类型阶段 + - 测试结果 @编辑阶段成功 + - 最终测试状态 @ SUCCESS + +*/ +chdir(__DIR__); +include '../lib/editstage.ui.class.php'; + +$stage = zendata('stage'); +$stage->id->range('1-12'); +$stage->name->range('需求, 设计, 开发, 测试, 发布, 总结评审'); +$stage->percent->range('10,10,40,15,10,5'); +$stage->type->range('request,design,dev,qa,release,review'); +$stage->projectType->range('waterfall{6},waterfallplus{6}'); +$stage->createdBy->range('admin'); +$stage->createdDate->range('(-2M)-(-M):1D')->type('timestamp')->format('YY/MM/DD'); From 490740fe1ee548aa3db97d4a38f0aa1b6b011033 Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:47:29 +0800 Subject: [PATCH 215/655] + [task#137219,doing,0.3h,0.5h] add stage test data and testcase. --- module/stage/test/ui/editstage.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/module/stage/test/ui/editstage.php b/module/stage/test/ui/editstage.php index dfc78589e8..df339d8d63 100755 --- a/module/stage/test/ui/editstage.php +++ b/module/stage/test/ui/editstage.php @@ -38,3 +38,24 @@ $stage->type->range('request,design,dev,qa,release,review'); $stage->projectType->range('waterfall{6},waterfallplus{6}'); $stage->createdBy->range('admin'); $stage->createdDate->range('(-2M)-(-M):1D')->type('timestamp')->format('YY/MM/DD'); +$stage->deleted->range('0'); +$stage->gen(12); + +$tester = new editStageTester(); +$tester->login(); + +$stage = array( + array('name' => '', 'percent' => ''), + array('name' => '瀑布需求阶段', 'percent' => '101', 'type' => '需求'), + array('name' => '瀑布需求阶段', 'percent' => '10', 'type' => '需求'), + array('name' => '', 'percent' => ''), + array('name' => '融合瀑布设计阶段', 'percent' => '101', 'type' => '设计'), + array('name' => '融合瀑布设计阶段', 'percent' => '10', 'type' => '设计'), +); + +r($tester->editstage($stage['0'], 'waterfall')) && p('message,status') && e('编辑阶段表单页提示信息正确, SUCCESS'); //瀑布模型下校验阶段名称不能为空 +r($tester->editstage($stage['1'], 'waterfall')) && p('message,status') && e('工作量占比累计超出100%时提示信息正确, SUCCESS'); //瀑布模型下工作量占比累计不能超出100% +r($tester->editstage($stage['2'], 'waterfall')) && p('message,status') && e('编辑阶段成功, SUCCESS'); //瀑布模型下编辑需求类型阶段 +r($tester->editstage($stage['3'], 'waterfallplus')) && p('message,status') && e('编辑阶段表单页提示信息正确, SUCCESS'); //融合瀑布模型下校验阶段名称不能为空 +r($tester->editstage($stage['4'], 'waterfallplus')) && p('message,status') && e('工作量占比累计超出100%时提示信息正确, SUCCESS'); //融合瀑布模型下工作量占比累计不能超出100% +r($tester->editstage($stage['5'], 'waterfallplus')) && p('message,status') && e('编辑阶段成功, SUCCESS'); //融合瀑布模型下编辑设计类型阶段 From 27cdaf4865078168aa888c8e1991c9ea7e68fc6d Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:48:33 +0800 Subject: [PATCH 216/655] + [task#137219,doing,0.3h,0.5h] add testcase of editstage ui file. --- module/stage/test/ui/editstage.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/stage/test/ui/editstage.php b/module/stage/test/ui/editstage.php index df339d8d63..5d8e169d56 100755 --- a/module/stage/test/ui/editstage.php +++ b/module/stage/test/ui/editstage.php @@ -59,3 +59,5 @@ r($tester->editstage($stage['2'], 'waterfall')) && p('message,status') && e( r($tester->editstage($stage['3'], 'waterfallplus')) && p('message,status') && e('编辑阶段表单页提示信息正确, SUCCESS'); //融合瀑布模型下校验阶段名称不能为空 r($tester->editstage($stage['4'], 'waterfallplus')) && p('message,status') && e('工作量占比累计超出100%时提示信息正确, SUCCESS'); //融合瀑布模型下工作量占比累计不能超出100% r($tester->editstage($stage['5'], 'waterfallplus')) && p('message,status') && e('编辑阶段成功, SUCCESS'); //融合瀑布模型下编辑设计类型阶段 + +$tester->closeBrowser(); From a6496fbae68109335f954dce28c95bb97c4df8cd Mon Sep 17 00:00:00 2001 From: huairong Date: Tue, 11 Feb 2025 16:50:22 +0800 Subject: [PATCH 217/655] + [task#137219,done,0.2h] add xpath of editstage page. --- module/stage/test/ui/page/edit.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 module/stage/test/ui/page/edit.php diff --git a/module/stage/test/ui/page/edit.php b/module/stage/test/ui/page/edit.php new file mode 100644 index 0000000000..dcf11ae823 --- /dev/null +++ b/module/stage/test/ui/page/edit.php @@ -0,0 +1,14 @@ + "//*[@id='zin_stage_edit_1_form']/div[4]/div/button/span", + 'plusSubmitBtn' => "//*[@id='zin_stage_edit_7_form']/div[4]/div/button", + 'percentOverTip' => "//*[@id='percentTip']", + ); + $this->dom->xpath = array_merge($this->dom->xpath, $xpath); + } +} From a34929a43e46cc8f8f8e837bf9b36ad7f2dab671 Mon Sep 17 00:00:00 2001 From: liugang Date: Wed, 12 Feb 2025 09:13:47 +0800 Subject: [PATCH 218/655] * [refac] use the showTables() method and descTable() method to be compatible with dameng database. --- module/upgrade/model.php | 100 +++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 46 deletions(-) diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 7d31c96fd6..32d91aba30 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -1920,13 +1920,9 @@ class upgradeModel extends model */ public function moveDocContent() { - $descDoc = $this->dao->query('DESC ' . TABLE_DOC)->fetchAll(); - $processFields = 0; - foreach($descDoc as $field) - { - if($field->Field == 'content' or $field->Field == 'digest' or $field->Field == 'url') $processFields ++; - } - if($processFields < 3) return true; + $fieldDesc = $this->dao->descTable(TABLE_DOC); + $fieldPairs = array_column($fieldDesc, 'field', 'field'); + if(!isset($fieldPairs['content']) || !isset($fieldPairs['digest']) || !isset($fieldPairs['url'])) return true; $this->dao->exec('TRUNCATE TABLE ' . TABLE_DOCCONTENT); $stmt = $this->dao->select('id,title,digest,content,url')->from(TABLE_DOC)->query(); @@ -2548,14 +2544,11 @@ class upgradeModel extends model */ public function changeTeamFields() { - $desc = $this->dao->query('DESC ' . TABLE_TEAM)->fetchAll(); - $fields = array(); - foreach($desc as $field) + $fields = $this->dao->descTable(TABLE_TEAM); + foreach($fields as $field) { - $fieldName = $field->Field; - $fields[$fieldName] = $fieldName; + if($field->field == 'root') return true; } - if(isset($fields['root'])) return true; $this->dao->exec("ALTER TABLE " . TABLE_TEAM . " CHANGE `project` `root` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0'"); $this->dao->exec("ALTER TABLE " . TABLE_TEAM . " ADD `type` ENUM('project', 'task') NOT NULL DEFAULT 'project' AFTER `root`"); @@ -7936,33 +7929,43 @@ class upgradeModel extends model public function convertDocCollect() { $this->saveLogs('Run Method ' . __FUNCTION__); - $desc = $this->dao->query('DESC ' . TABLE_DOC)->fetchAll(); - $fields = array(); + + $fields = $this->dao->descTable(TABLE_DOC); foreach($desc as $field) { - $fieldName = $field->Field; - $fields[$fieldName] = $fieldName; + if($field->field == 'collects') return true; } - if(!isset($fields['collector']) or isset($fields['collects'])) return true; - - $this->loadModel('doc'); - - $users = $this->dao->select('account')->from(TABLE_USER)->fetchPairs('account', 'account'); - $docs = $this->dao->select('id,collector')->from(TABLE_DOC)->where('collector')->ne('')->fetchAll(); + $users = $this->dao->select('account')->from(TABLE_USER)->fetchPairs(); + $docs = $this->dao->select('id,collector')->from(TABLE_DOC)->where('collector')->ne('')->fetchPairs(); $this->dao->update(TABLE_DOC)->set('collector')->eq(0)->exec(); $this->dao->exec("ALTER TABLE " . TABLE_DOC . " CHANGE `collector` `collects` smallint unsigned NOT NULL DEFAULT '0'"); - foreach($docs as $doc) + $data = new stdclass(); + $data->action = 'collect'; + $data->date = helper::now(); + + foreach($docs as $id => $collector) { - foreach(explode(',', $doc->collector) as $collector) + $collects = 0; + + $data->doc = $id; + + foreach(explode(',', $collector) as $account) { - $collector = trim($collector); - if(empty($collector)) continue; - if(!isset($users[$collector])) continue; - $this->doc->createAction($doc->id, 'collect', $collector); + $account = trim($account); + if(empty($account)) continue; + if(!isset($users[$account])) continue; + + $data->actor = $account; + $this->dao->insert(TABLE_DOCACTION)->data($data)->autoCheck()->exec(); + if(dao::isError()) continue; + + $collects++; } + + if($collects) $this->dao->update(TABLE_DOC)->set('collects')->eq($collects)->where('id')->eq($id)->exec(); } return true; @@ -8299,11 +8302,11 @@ class upgradeModel extends model $this->setting->setItem('system.block.closed', $closedBlocks); } - $blockDesc = $this->dao->query('DESC ' . TABLE_BLOCK)->fetchAll(); - $fields = array(); - foreach($blockDesc as $field) $fields[$field->Field] = $field->Field; - - if(isset($fields['block'])) $this->dao->delete()->from(TABLE_BLOCK)->where('block')->eq('waterfallgeneralreport')->exec(); + $fields = $this->dao->descTable(TABLE_BLOCK); + foreach($fields as $field) + { + if($field->field == 'block') $this->dao->delete()->from(TABLE_BLOCK)->where('block')->eq('waterfallgeneralreport')->exec(); + } return true; } @@ -9889,12 +9892,15 @@ class upgradeModel extends model $flows = $this->dao->select('*')->from(TABLE_WORKFLOW)->where('buildin')->eq('0')->fetchAll('id', false); if(empty($flows)) return true; - $flowTables = $this->dao->query("SHOW tables LIKE 'zt_flow_%'")->fetchAll(PDO::FETCH_COLUMN); - $flowTableDesc = array(); - foreach($flowTables as $flowTable) + $tableFields = array(); + $tables = $this->dao->showTables(); + foreach($tables as $table) { - $desc = $this->dao->query("DESC $flowTable")->fetchAll(PDO::FETCH_ASSOC); - $flowTableDesc[$flowTable] = array_column($desc, null, 'Field'); + $table = reset($table); + if(strpos($table, $this->config->db->prefix . 'flow_') !== 0) continue; + + $desc = $this->dao->descTable($table); + $tableFields[$table] = array_column($desc, 'field', 'field'); } $defaultData = array('type' => 'mediumint', 'length' => '8', 'control' => 'select', 'readonly' => 1, 'buildin' => 1, 'role' => 'default'); @@ -9904,9 +9910,12 @@ class upgradeModel extends model $fields['project'] = "ALTER TABLE %table% ADD `project` mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `id`"; $fields['product'] = "ALTER TABLE %table% ADD `product` mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `id`"; $fields['program'] = "ALTER TABLE %table% ADD `program` mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `id`"; + + $oldFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->fetchGroup('module', 'field'); + foreach($flows as $flow) { - if(!isset($flowTableDesc[$flow->table])) continue; + if(!isset($tableFields[$flow->table])) continue; if($flow->vision == 'lite') continue; foreach($fields as $field => $addSQL) @@ -9914,20 +9923,19 @@ class upgradeModel extends model if($flow->vision == 'or' && $field != 'product') continue; $searchedField = ''; - foreach(array_keys($flowTableDesc[$flow->table]) as $existField) + foreach($tableFields[$flow->table] as $tableField) { - if($field == strtolower($existField)) + if($field == strtolower($tableField)) { - $searchedField = $existField; + $searchedField = $tableField; break; } } if($searchedField) { - $tableDesc = $flowTableDesc[$flow->table]; $newFieldName = "{$searchedField}_1"; - $oldField = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($flow->module)->andWhere('field')->eq($searchedField)->fetch(); - if(isset($tableDesc[$newFieldName]) || ($oldField && ($oldField->buildin || $oldField->readonly))) + $oldField = isset($oldFields[$flow->module][$searchedField]) ? $oldFields[$flow->module][$searchedField] : null; + if(isset($tableFields[$flow->table][$newFieldName]) || ($oldField && ($oldField->buildin || $oldField->readonly))) { $this->dao->exec("ALTER TABLE {$flow->table} DROP `{$searchedField}`"); $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->eq($flow->module)->andWhere('field')->eq("{$searchedField}")->exec(); From b346273f9b5fe61869a5b05db513b049e7225a89 Mon Sep 17 00:00:00 2001 From: liugang Date: Wed, 12 Feb 2025 09:47:45 +0800 Subject: [PATCH 219/655] * [refac] initialize object out of loop to improve effeciency. --- module/upgrade/model.php | 168 +++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 32d91aba30..8b6a8390b9 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -6050,15 +6050,15 @@ class upgradeModel extends model $upgradeConfig = zget($this->config->workflowfield->upgrade, $version, array()); $workFlowDataSource = $this->dao->select('code,id')->from(TABLE_WORKFLOWDATASOURCE)->where('type')->ne('system')->fetchPairs(); - $now = helper::now(); + $field = new stdclass(); + $field->buildin = '1'; + $field->role = 'buildin'; + $field->createdBy = $this->app->user->account; + $field->createdDate = helper::now(); + foreach($upgradeLang as $module => $fields) { - $field = new stdclass(); - $field->buildin = '1'; - $field->role = 'buildin'; - $field->module = $module; - $field->createdBy = $this->app->user->account; - $field->createdDate = $now; + $field->module = $module; foreach($fields as $code => $name) { @@ -8994,6 +8994,8 @@ class upgradeModel extends model { $doProcess = function($stories, $storyType) { + $relation = new stdclass(); + $relation->product = 0; foreach($stories as $storyID => $linkStories) { $linkStories = explode(',', trim($linkStories, ',')); @@ -9001,13 +9003,11 @@ class upgradeModel extends model { if(!$linkStoryID) continue; - $relation = new stdclass(); $relation->AType = $storyType; $relation->AID = $storyID; $relation->BType = $storyType; $relation->BID = $linkStoryID; $relation->relation = 'linkedto'; - $relation->product = 0; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); @@ -9016,7 +9016,6 @@ class upgradeModel extends model $relation->BType = $storyType; $relation->BID = $storyID; $relation->relation = 'linkedfrom'; - $relation->product = 0; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } @@ -9225,21 +9224,21 @@ class upgradeModel extends model ->andWhere('vision')->eq('rnd') ->fetchGroup('section', 'key'); - foreach(array('scrum', 'agileplus', 'waterfallplus') as $modal) + $classifyData = new stdclass(); + $classifyData->lang = 'all'; + $classifyData->module = 'process'; + $classifyData->vision = 'rnd'; + $classifyData->system = 1; + foreach(array('scrumClassify', 'agileplusClassify', 'waterfallplusClassify') as $section) { + $classifyData->section = $section; foreach($this->lang->install->langList as $langInfo) { if($langInfo['module'] != 'process') continue; - if(isset($classifyLang[$modal . 'Classify'][$langInfo['key']])) continue; + if(isset($classifyLang[$section][$langInfo['key']])) continue; - $classifyData = new stdclass(); - $classifyData->lang = 'all'; - $classifyData->module = 'process'; - $classifyData->section = $modal . 'Classify'; - $classifyData->key = $langInfo['key']; - $classifyData->value = $langInfo['value']; - $classifyData->vision = 'rnd'; - $classifyData->system = 1; + $classifyData->key = $langInfo['key']; + $classifyData->value = $langInfo['value']; $this->dao->replace(TABLE_LANG)->data($classifyData)->exec(); } @@ -9640,12 +9639,12 @@ class upgradeModel extends model ->where('t2.id')->in($projectCharters) ->fetchGroup('charterID'); + $productRoadmap = new stdclass(); foreach($projectCharters as $projectID => $charter) { + $productRoadmap->project = $projectID; foreach($charterGroups[$charter] as $roadmap) { - $productRoadmap = new stdclass(); - $productRoadmap->project = $projectID; $productRoadmap->product = $roadmap->product; $productRoadmap->branch = $roadmap->branch; $productRoadmap->roadmap = ",$roadmap->id,"; @@ -9957,11 +9956,11 @@ class upgradeModel extends model $this->dao->exec(str_replace('%table%', $flow->table, $addSQL)); $data = $defaultData; - $data['module'] = $flow->module; - $data['field'] = $field; - $data['name'] = $this->lang->upgrade->flowFields[$field]; - $data['options'] = $field; - $data['order'] = $orders[$field]; + $data['module'] = $flow->module; + $data['field'] = $field; + $data['name'] = $this->lang->upgrade->flowFields[$field]; + $data['options'] = $field; + $data['order'] = $orders[$field]; $this->dao->replace(TABLE_WORKFLOWFIELD)->data($data)->exec(); } } @@ -10122,6 +10121,7 @@ class upgradeModel extends model $relation->product = 0; /* Process story link story. */ + $relation->relation = 1; $linkedtoStories = $this->dao->select('*')->from(TABLE_RELATION) ->where('AType')->in('story,requirement,epic') ->andWhere('relation')->eq('linkedto') @@ -10131,7 +10131,6 @@ class upgradeModel extends model { $relation->AType = $story->AType; $relation->AID = $story->AID; - $relation->relation = 1; $relation->BType = $story->BType; $relation->BID = $story->BID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); @@ -10223,11 +10222,11 @@ class upgradeModel extends model } /* Process bug transferred to task. */ + $relation->BType = 'task'; $taskList = $this->dao->select('id,story,fromBug,design')->from(TABLE_TASK)->where('fromBug')->ne(0)->orWhere('story')->ne(0)->orWhere('design')->ne(0)->fetchAll('id'); foreach($taskList as $taskID => $task) { - $relation->BType = 'task'; - $relation->BID = $taskID; + $relation->BID = $taskID; if(!empty($task->fromBug)) { $relation->relation = 'transferredto'; @@ -10252,127 +10251,128 @@ class upgradeModel extends model } /* Process bug transferred to story. */ + $relation->AType = 'bug'; + $relation->relation = 'transferredto'; + $relation->BType = 'story'; $bugTransferredToStory = $this->dao->select('id,fromBug')->from(TABLE_STORY)->where('fromBug')->ne(0)->fetchPairs('id'); foreach($bugTransferredToStory as $storyID => $bugID) { - $relation->AType = 'bug'; - $relation->AID = $bugID; - $relation->relation = 'transferredto'; - $relation->BType = 'story'; - $relation->BID = $storyID; + $relation->AID = $bugID; + $relation->BID = $storyID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } /* Process release. */ + $relation->AType = 'story'; + $relation->relation = 'interrated'; + $relation->BType = 'release'; $releaseLinkedStories = $this->dao->select('id,stories')->from(TABLE_RELEASE)->where('stories')->ne('')->fetchPairs('id'); foreach($releaseLinkedStories as $releaseID => $storyIdList) { + $relation->BID = $releaseID; foreach(explode(',', trim($storyIdList, ',')) as $storyID) { if(empty($storyID)) continue; - $relation->AType = 'story'; - $relation->AID = $storyID; - $relation->relation = 'interrated'; - $relation->BType = 'release'; - $relation->BID = $releaseID; + $relation->AID = $storyID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } } /* Process build. */ + $relation->AType = 'story'; + $relation->relation = 'interrated'; + $relation->BType = 'build'; $buildLinkedStories = $this->dao->select('id,stories')->from(TABLE_BUILD)->where('stories')->ne('')->fetchPairs('id'); foreach($buildLinkedStories as $buildID => $storyIdList) { + $relation->BID = $buildID; foreach(explode(',', trim($storyIdList, ',')) as $storyID) { if(empty($storyID)) continue; - $relation->AType = 'story'; - $relation->AID = $storyID; - $relation->relation = 'interrated'; - $relation->BType = 'build'; - $relation->BID = $buildID; + $relation->AID = $storyID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } } /* Process story generated design. */ + $relation->relation = 'generated'; + $relation->BType = 'design'; $designStories = $this->dao->select('id,story')->from(TABLE_DESIGN)->where('story')->ne(0)->fetchPairs('id'); $storyTypeList = $this->dao->select('id,type')->from(TABLE_STORY)->where('id')->in(array_values($designStories))->fetchPairs('id'); foreach($designStories as $designID => $storyID) { - $relation->AType = $storyTypeList[$storyID]; - $relation->AID = $storyID; - $relation->relation = 'generated'; - $relation->BType = 'design'; - $relation->BID = $designID; + $relation->AType = $storyTypeList[$storyID]; + $relation->AID = $storyID; + $relation->BID = $designID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } /* Process feedback transferred to story. */ + $relation->AType = 'feedback'; + $relation->relation = 'transferredto'; $feedbackTransferredToStories = $this->dao->select('id,type,feedback')->from(TABLE_STORY)->where('feedback')->ne(0)->fetchAll('id'); foreach($feedbackTransferredToStories as $story) { - $relation->AType = 'feedback'; - $relation->AID = $story->feedback; - $relation->relation = 'transferredto'; - $relation->BType = $story->type; - $relation->BID = $story->id; + $relation->AID = $story->feedback; + $relation->BType = $story->type; + $relation->BID = $story->id; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } /* Process feedback transferredto to bug, task, ticket, demand. */ + $relation->AType = 'feedback'; + $relation->relation = 'transferredto'; foreach(array('bug', 'task', 'ticket', 'demand') as $feedbackTransferredToType) { + $relation->BType = $feedbackTransferredToType; + $feedbackTransferredTo = $this->dao->select('id,feedback')->from($this->config->objectTables[$feedbackTransferredToType])->where('feedback')->ne(0)->fetchPairs('id'); foreach($feedbackTransferredTo as $id => $feedbackID) { - $relation->AType = 'feedback'; - $relation->AID = $feedbackID; - $relation->relation = 'transferredto'; - $relation->BType = $feedbackTransferredToType; - $relation->BID = $id; + $relation->AID = $feedbackID; + $relation->BID = $id; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } } /* Process ticket transferred to story and bug. */ + $relation->AType = 'ticket'; + $relation->relation = 'transferredto'; $ticketTransferred = $this->dao->select('*')->from(TABLE_TICKETRELATION)->fetchAll('id', false); foreach($ticketTransferred as $transferredObject) { - $relation->AType = 'ticket'; - $relation->AID = $transferredObject->ticketId; - $relation->relation = 'transferredto'; - $relation->BType = $transferredObject->objectType; - $relation->BID = $transferredObject->objectId; - $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); + $relation->AID = $transferredObject->ticketId; + $relation->BType = $transferredObject->objectType; + $relation->BID = $transferredObject->objectId; + $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } /* Process twins. */ + $relation->AType = 'story'; + $relation->relation = 'twin'; + $relation->BType = 'story'; $twins = $this->dao->select('id,twins')->from(TABLE_STORY)->where('twins')->ne('')->fetchPairs('id'); foreach($twins as $storyID => $twinsID) { + $relation->AID = $storyID; foreach(explode(',', trim($twinsID, ',')) as $twinID) { if(empty($twinID)) continue; - $relation->AType = 'story'; - $relation->AID = $storyID; - $relation->relation = 'twin'; - $relation->BType = 'story'; - $relation->BID = $twinID; + $relation->BID = $twinID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } } /* Process child story. */ + $relation->relation = 'subdivideinto'; $parentStories = array(); $childStories = $this->dao->select('id,type,parent,demand')->from(TABLE_STORY)->where('parent')->gt(0)->orWhere('demand')->gt(0)->fetchAll('id'); foreach($childStories as $childStory) $parentStories[$childStory->parent] = $childStory->parent; $parentStoryType = $this->dao->select('id,type')->from(TABLE_STORY)->where('id')->in($parentStories)->fetchPairs('id'); foreach($childStories as $childStory) { - $relation->relation = 'subdivideinto'; - $relation->BType = $childStory->type; - $relation->BID = $childStory->id; + $relation->BType = $childStory->type; + $relation->BID = $childStory->id; if(!empty($childStory->parent)) { $relation->AType = $parentStoryType[$childStory->parent]; @@ -10388,26 +10388,26 @@ class upgradeModel extends model } /* Process issue link risk. */ + $relation->AType = 'issue'; + $relation->relation = 1; + $relation->BType = 'risk'; $riskIssues = $this->dao->select('*')->from(TABLE_RISKISSUE)->fetchAll(); foreach($riskIssues as $riskIssueList) { - $relation->AType = 'issue'; - $relation->AID = $riskIssueList->issue; - $relation->relation = 1; - $relation->BType = 'risk'; - $relation->BID = $riskIssueList->risk; + $relation->AID = $riskIssueList->issue; + $relation->BID = $riskIssueList->risk; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } /* Process child demand. */ + $relation->AType = 'demand'; + $relation->relation = 'subdivideinto'; + $relation->BType = 'demand'; $childDemands = $this->dao->select('id,parent')->from(TABLE_DEMAND)->where('parent')->gt(0)->fetchPairs('id'); foreach($childDemands as $childDemandID => $parentDemandID) { - $relation->AType = 'demand'; - $relation->AID = $parentDemandID; - $relation->relation = 'subdivideinto'; - $relation->BType = 'demand'; - $relation->BID = $childDemandID; + $relation->AID = $parentDemandID; + $relation->BID = $childDemandID; $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); } From 9dcf762840cdb13f9a58e532dc3b67661f10e6c4 Mon Sep 17 00:00:00 2001 From: liugang Date: Wed, 12 Feb 2025 09:52:00 +0800 Subject: [PATCH 220/655] * [refac] using delete and insert operations instead of replace operation. --- module/upgrade/model.php | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 8b6a8390b9..1e99c08073 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -6071,7 +6071,8 @@ class upgradeModel extends model foreach($fieldConfig as $key => $value) $field->$key = $value; if($field->control == 'select' && is_string($field->options) && isset($workFlowDataSource[$field->options])) $field->options = $workFlowDataSource[$field->options]; - $this->dao->replace(TABLE_WORKFLOWFIELD)->data($field)->autoCheck()->exec(); + $this->dao->delete()->from(TABLE_WORKFLOWFIELD)->where('module')->eq($module)->andWhere('field')->eq($code)->exec(); + $this->dao->insert(TABLE_WORKFLOWFIELD)->data($field)->autoCheck()->exec(); } } @@ -8998,6 +8999,9 @@ class upgradeModel extends model $relation->product = 0; foreach($stories as $storyID => $linkStories) { + $this->dao->delete()->from(TABLE_RELATION)->where('product')->eq(0)->andWhere('relation')->eq('linkedto')->andWhere('AType')->eq($storyType)->andWhere('BType')->eq($storyType)->andWhere('AID')->eq($storyID)->andWhere('BID')->in($linkStories)->exec(); + $this->dao->delete()->from(TABLE_RELATION)->where('product')->eq(0)->andWhere('relation')->eq('linkedfrom')->andWhere('AType')->eq($storyType)->andWhere('BType')->eq($storyType)->andWhere('AID')->in($linkStories)->andWhere('BID')->eq($storyID)->exec(); + $linkStories = explode(',', trim($linkStories, ',')); foreach($linkStories as $linkStoryID) { @@ -9009,7 +9013,7 @@ class upgradeModel extends model $relation->BID = $linkStoryID; $relation->relation = 'linkedto'; - $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); + $this->dao->insert(TABLE_RELATION)->data($relation)->exec(); $relation->AType = $storyType; $relation->AID = $linkStoryID; @@ -9017,7 +9021,7 @@ class upgradeModel extends model $relation->BID = $storyID; $relation->relation = 'linkedfrom'; - $this->dao->replace(TABLE_RELATION)->data($relation)->exec(); + $this->dao->insert(TABLE_RELATION)->data($relation)->exec(); } } }; @@ -9104,7 +9108,7 @@ class upgradeModel extends model foreach($projects as $projectID) { $data->project = $projectID; - $this->dao->replace(TABLE_OBJECT)->data($data)->exec(); + $this->dao->insert(TABLE_OBJECT)->data($data)->exec(); } return true; @@ -9240,7 +9244,7 @@ class upgradeModel extends model $classifyData->key = $langInfo['key']; $classifyData->value = $langInfo['value']; - $this->dao->replace(TABLE_LANG)->data($classifyData)->exec(); + $this->dao->insert(TABLE_LANG)->data($classifyData)->exec(); } } @@ -9649,7 +9653,8 @@ class upgradeModel extends model $productRoadmap->branch = $roadmap->branch; $productRoadmap->roadmap = ",$roadmap->id,"; - $this->dao->replace(TABLE_PROJECTPRODUCT)->data($productRoadmap)->exec(); + $this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('product')->eq($roadmap->product)->andWhere('branch')->eq($roadmap->branch)->exec(); + $this->dao->insert(TABLE_PROJECTPRODUCT)->data($productRoadmap)->exec(); } } @@ -9703,7 +9708,9 @@ class upgradeModel extends model $groupIdList = $this->dao->select('`group`')->from(TABLE_GROUPPRIV) ->where('module')->eq('execution') ->andWhere('method')->eq('maintainrelation') - ->fetchPairs('group'); + ->fetchPairs(); + + $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->in($groupIdList)->andWhere('module')->eq('execution')->andWhere('method')->in('editrelation,batcheditrelation')->exec(); foreach($groupIdList as $groupID) { @@ -9714,8 +9721,8 @@ class upgradeModel extends model ->andWhere('method')->eq('maintainrelation') ->exec(); - $this->dao->replace(TABLE_GROUPPRIV)->set('`group`')->eq($groupID)->set('module')->eq('execution')->set('method')->eq('editrelation')->exec(); - $this->dao->replace(TABLE_GROUPPRIV)->set('`group`')->eq($groupID)->set('module')->eq('execution')->set('method')->eq('batcheditrelation')->exec(); + $this->dao->insert(TABLE_GROUPPRIV)->set('`group`')->eq($groupID)->set('module')->eq('execution')->set('method')->eq('editrelation')->exec(); + $this->dao->insert(TABLE_GROUPPRIV)->set('`group`')->eq($groupID)->set('module')->eq('execution')->set('method')->eq('batcheditrelation')->exec(); } return true; @@ -9961,7 +9968,7 @@ class upgradeModel extends model $data['name'] = $this->lang->upgrade->flowFields[$field]; $data['options'] = $field; $data['order'] = $orders[$field]; - $this->dao->replace(TABLE_WORKFLOWFIELD)->data($data)->exec(); + $this->dao->insert(TABLE_WORKFLOWFIELD)->data($data)->exec(); } } return true; From 4be811c146ea5ae49a83abf51647b4b73cbeadeb Mon Sep 17 00:00:00 2001 From: liugang Date: Wed, 12 Feb 2025 09:52:43 +0800 Subject: [PATCH 221/655] * [refac] remove unnecessary paramaters. --- module/upgrade/model.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 1e99c08073..7645a83347 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10261,7 +10261,7 @@ class upgradeModel extends model $relation->AType = 'bug'; $relation->relation = 'transferredto'; $relation->BType = 'story'; - $bugTransferredToStory = $this->dao->select('id,fromBug')->from(TABLE_STORY)->where('fromBug')->ne(0)->fetchPairs('id'); + $bugTransferredToStory = $this->dao->select('id,fromBug')->from(TABLE_STORY)->where('fromBug')->ne(0)->fetchPairs(); foreach($bugTransferredToStory as $storyID => $bugID) { $relation->AID = $bugID; @@ -10273,7 +10273,7 @@ class upgradeModel extends model $relation->AType = 'story'; $relation->relation = 'interrated'; $relation->BType = 'release'; - $releaseLinkedStories = $this->dao->select('id,stories')->from(TABLE_RELEASE)->where('stories')->ne('')->fetchPairs('id'); + $releaseLinkedStories = $this->dao->select('id,stories')->from(TABLE_RELEASE)->where('stories')->ne('')->fetchPairs(); foreach($releaseLinkedStories as $releaseID => $storyIdList) { $relation->BID = $releaseID; @@ -10289,7 +10289,7 @@ class upgradeModel extends model $relation->AType = 'story'; $relation->relation = 'interrated'; $relation->BType = 'build'; - $buildLinkedStories = $this->dao->select('id,stories')->from(TABLE_BUILD)->where('stories')->ne('')->fetchPairs('id'); + $buildLinkedStories = $this->dao->select('id,stories')->from(TABLE_BUILD)->where('stories')->ne('')->fetchPairs(); foreach($buildLinkedStories as $buildID => $storyIdList) { $relation->BID = $buildID; @@ -10304,8 +10304,8 @@ class upgradeModel extends model /* Process story generated design. */ $relation->relation = 'generated'; $relation->BType = 'design'; - $designStories = $this->dao->select('id,story')->from(TABLE_DESIGN)->where('story')->ne(0)->fetchPairs('id'); - $storyTypeList = $this->dao->select('id,type')->from(TABLE_STORY)->where('id')->in(array_values($designStories))->fetchPairs('id'); + $designStories = $this->dao->select('id,story')->from(TABLE_DESIGN)->where('story')->ne(0)->fetchPairs(); + $storyTypeList = $this->dao->select('id,type')->from(TABLE_STORY)->where('id')->in(array_values($designStories))->fetchPairs(); foreach($designStories as $designID => $storyID) { $relation->AType = $storyTypeList[$storyID]; @@ -10317,7 +10317,7 @@ class upgradeModel extends model /* Process feedback transferred to story. */ $relation->AType = 'feedback'; $relation->relation = 'transferredto'; - $feedbackTransferredToStories = $this->dao->select('id,type,feedback')->from(TABLE_STORY)->where('feedback')->ne(0)->fetchAll('id'); + $feedbackTransferredToStories = $this->dao->select('id,type,feedback')->from(TABLE_STORY)->where('feedback')->ne(0)->fetchAll(); foreach($feedbackTransferredToStories as $story) { $relation->AID = $story->feedback; @@ -10333,7 +10333,7 @@ class upgradeModel extends model { $relation->BType = $feedbackTransferredToType; - $feedbackTransferredTo = $this->dao->select('id,feedback')->from($this->config->objectTables[$feedbackTransferredToType])->where('feedback')->ne(0)->fetchPairs('id'); + $feedbackTransferredTo = $this->dao->select('id,feedback')->from($this->config->objectTables[$feedbackTransferredToType])->where('feedback')->ne(0)->fetchPairs(); foreach($feedbackTransferredTo as $id => $feedbackID) { $relation->AID = $feedbackID; @@ -10345,7 +10345,7 @@ class upgradeModel extends model /* Process ticket transferred to story and bug. */ $relation->AType = 'ticket'; $relation->relation = 'transferredto'; - $ticketTransferred = $this->dao->select('*')->from(TABLE_TICKETRELATION)->fetchAll('id', false); + $ticketTransferred = $this->dao->select('*')->from(TABLE_TICKETRELATION)->fetchAll('id', false); foreach($ticketTransferred as $transferredObject) { $relation->AID = $transferredObject->ticketId; @@ -10358,7 +10358,7 @@ class upgradeModel extends model $relation->AType = 'story'; $relation->relation = 'twin'; $relation->BType = 'story'; - $twins = $this->dao->select('id,twins')->from(TABLE_STORY)->where('twins')->ne('')->fetchPairs('id'); + $twins = $this->dao->select('id,twins')->from(TABLE_STORY)->where('twins')->ne('')->fetchPairs(); foreach($twins as $storyID => $twinsID) { $relation->AID = $storyID; @@ -10373,9 +10373,9 @@ class upgradeModel extends model /* Process child story. */ $relation->relation = 'subdivideinto'; $parentStories = array(); - $childStories = $this->dao->select('id,type,parent,demand')->from(TABLE_STORY)->where('parent')->gt(0)->orWhere('demand')->gt(0)->fetchAll('id'); + $childStories = $this->dao->select('id,type,parent,demand')->from(TABLE_STORY)->where('parent')->gt(0)->orWhere('demand')->gt(0)->fetchAll(); foreach($childStories as $childStory) $parentStories[$childStory->parent] = $childStory->parent; - $parentStoryType = $this->dao->select('id,type')->from(TABLE_STORY)->where('id')->in($parentStories)->fetchPairs('id'); + $parentStoryType = $this->dao->select('id,type')->from(TABLE_STORY)->where('id')->in($parentStories)->fetchPairs(); foreach($childStories as $childStory) { $relation->BType = $childStory->type; @@ -10398,7 +10398,7 @@ class upgradeModel extends model $relation->AType = 'issue'; $relation->relation = 1; $relation->BType = 'risk'; - $riskIssues = $this->dao->select('*')->from(TABLE_RISKISSUE)->fetchAll(); + $riskIssues = $this->dao->select('issue,risk')->from(TABLE_RISKISSUE)->fetchAll(); foreach($riskIssues as $riskIssueList) { $relation->AID = $riskIssueList->issue; @@ -10410,7 +10410,7 @@ class upgradeModel extends model $relation->AType = 'demand'; $relation->relation = 'subdivideinto'; $relation->BType = 'demand'; - $childDemands = $this->dao->select('id,parent')->from(TABLE_DEMAND)->where('parent')->gt(0)->fetchPairs('id'); + $childDemands = $this->dao->select('id,parent')->from(TABLE_DEMAND)->where('parent')->gt(0)->fetchPairs(); foreach($childDemands as $childDemandID => $parentDemandID) { $relation->AID = $parentDemandID; From 1ca020ec1f69b1852db67c38384457efdb4d3176 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Wed, 12 Feb 2025 10:56:30 +0800 Subject: [PATCH 222/655] * [task#136244,done,1h] set module. --- module/story/js/edit.ui.js | 2 +- module/story/zen.php | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/module/story/js/edit.ui.js b/module/story/js/edit.ui.js index 259e21698c..d303499134 100644 --- a/module/story/js/edit.ui.js +++ b/module/story/js/edit.ui.js @@ -138,7 +138,7 @@ function loadProductBranches(productID) window.loadProductModules = function(productID, branch) { - const link = $.createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=items&fieldID=&needManage=true&extra=nodeleted'); + const link = $.createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=items&fieldID=&extra=nodeleted'); $.getJSON(link, function(moduleItems) { let $modulePicker = $('[name=module]').zui('picker'); diff --git a/module/story/zen.php b/module/story/zen.php index fddc5fd9b2..584b9e7ae5 100644 --- a/module/story/zen.php +++ b/module/story/zen.php @@ -1313,12 +1313,7 @@ class storyZen extends story if($this->post->linkStories) $storyData->linkStories = implode(',', array_unique($this->post->linkStories)); if($this->post->linkRequirements) $storyData->linkRequirements = implode(',', array_unique($this->post->linkRequirements)); - if($oldStory->product != $storyData->product) - { - $storyData->root = $storyID; - $storyData->parent = 0; - $storyData->module = 0; - } + if($oldStory->product != $storyData->product) $storyData->root = $storyID; return $this->loadModel('file')->processImgURL($storyData, $this->config->story->editor->edit['id'], $this->post->uid); } From 5f3e56f610f77efcaf42f339f36058bed7803446 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 10:58:51 +0800 Subject: [PATCH 223/655] * [bug#59577,done,0.2h] remove delete button. --- module/bug/ui/batchcreate.html.php | 2 +- module/bug/ui/common.field.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/bug/ui/batchcreate.html.php b/module/bug/ui/batchcreate.html.php index 780f500480..1906819900 100644 --- a/module/bug/ui/batchcreate.html.php +++ b/module/bug/ui/batchcreate.html.php @@ -45,7 +45,7 @@ if($product->type != 'normal') $items[] = array('name' => 'branch', 'label' => $ $items[] = array('name' => 'module', 'label' => $lang->bug->module, 'control' => 'picker', 'items' => $moduleOptionMenu, 'value' => $moduleID, 'width' => '200px', 'required' => isset($requiredFields['module']), 'ditto' => true); /* Field of project. */ -$items[] = array('name' => 'project', 'label' => $lang->bug->project, 'control' => 'picker', 'items' => $projects, 'value' => $projectID, 'width' => '200px', 'required' => isset($requiredFields['project']), 'ditto' => true); +$items[] = array('name' => 'project', 'label' => $lang->bug->project, 'control' => array('control' => 'picker', 'required' => !empty($product->shadow)), 'items' => $projects, 'value' => $projectID, 'width' => '200px', 'required' => isset($requiredFields['project']), 'ditto' => true); /* Field of execution. */ $items[] = array diff --git a/module/bug/ui/common.field.php b/module/bug/ui/common.field.php index eca4ebf0a3..548b4facec 100644 --- a/module/bug/ui/common.field.php +++ b/module/bug/ui/common.field.php @@ -12,7 +12,7 @@ $fields->field('product') ->item((data('product.type') !== 'normal' && isset(data('products')[data('bug.productID')])) ? field('branch')->control('picker')->required(true)->boxClass('flex-none')->width('100px')->name('branch')->items(data('branches'))->value(data('bug.branch')) : null); $fields->field('project') - ->control('picker') + ->control(array('control' => 'picker', 'required' => !empty(data('product.shadow')))) ->items(data('projects')) ->value(data('projectID')); From 40d03ae62d314098567ca667646ded1eb156d7b8 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 11:20:19 +0800 Subject: [PATCH 224/655] * [bug#59582,done,0.5h] fix product range error. --- module/bug/zen.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/module/bug/zen.php b/module/bug/zen.php index 7721597329..872e47c573 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -1213,6 +1213,18 @@ class bugZen extends bug */ protected function assignVarsForEdit(object $bug): void { + $product = $this->loadModel('product')->fetchByID($bug->product); + if(empty($product->shadow)) + { + $products = $this->view->products; + $productList = $this->loadModel('product')->getByIdList(array_keys($products)); + foreach($products as $id => $name) + { + if(!empty($productList[$id]->shadow) || $productList[$id]->status == 'closed') unset($products[$id]); + } + $this->view->products = $products; + } + /* Add product related to the bug when it is not in the products. */ if(!isset($this->products[$bug->product])) { From d15618bbb9b7cbfe2e147d2143c24c27858f1732 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 11:24:16 +0800 Subject: [PATCH 225/655] * [misc,done,0.1h] optimize code. --- module/bug/zen.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/bug/zen.php b/module/bug/zen.php index 872e47c573..16eafd0609 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -1213,6 +1213,13 @@ class bugZen extends bug */ protected function assignVarsForEdit(object $bug): void { + /* Add product related to the bug when it is not in the products. */ + if(!isset($this->products[$bug->product])) + { + $this->products[$bug->product] = $product->name; + $this->view->products = $this->products; + } + $product = $this->loadModel('product')->fetchByID($bug->product); if(empty($product->shadow)) { @@ -1220,18 +1227,11 @@ class bugZen extends bug $productList = $this->loadModel('product')->getByIdList(array_keys($products)); foreach($products as $id => $name) { - if(!empty($productList[$id]->shadow) || $productList[$id]->status == 'closed') unset($products[$id]); + if($id != $bug->product && (!empty($productList[$id]->shadow) || $productList[$id]->status == 'closed')) unset($products[$id]); } $this->view->products = $products; } - /* Add product related to the bug when it is not in the products. */ - if(!isset($this->products[$bug->product])) - { - $this->products[$bug->product] = $product->name; - $this->view->products = $this->products; - } - if($bug->execution) { $openedBuilds = $this->loadModel('build')->getBuildPairs(array($bug->product), $bug->branch, 'noempty,noterminate,nodone,withbranch,noreleased,nofail', $bug->execution, 'execution'); From a882e55c5a9fc34c6be3b42a78a87b41bacd667b Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 12 Feb 2025 05:17:03 +0000 Subject: [PATCH 226/655] * [feedback#8439,done,1h] Display extend file fields. --- lib/zin/wg/detailbody/v1.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zin/wg/detailbody/v1.php b/lib/zin/wg/detailbody/v1.php index 4054aed1ba..0321b576bb 100644 --- a/lib/zin/wg/detailbody/v1.php +++ b/lib/zin/wg/detailbody/v1.php @@ -40,7 +40,7 @@ class detailBody extends wg $fieldValue = !$isForm ? $app->control->flow->getFieldValue($field, $object) : null; $extraMain[] = section ( - $field->control == 'file' && $object->files ? fileList + !empty($field->control['control']) && $field->control['control'] == 'fileSelector' && $object->files ? fileList ( set::files($object->files), set::extra($field->field), From 97accf6dd77716fc63743e89545132e1d9638672 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:48:32 +0800 Subject: [PATCH 227/655] * [ticket#1773,doing,0.3h] add search condition. --- module/project/model.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/module/project/model.php b/module/project/model.php index ba1b648b7a..0ee37b4d68 100755 --- a/module/project/model.php +++ b/module/project/model.php @@ -730,15 +730,19 @@ class projectModel extends model * Get project pairs. * * @param bool $ignoreVision + * @param string $param * @access public * @return object */ - public function getPairs(bool $ignoreVision = false) + public function getPairs(bool $ignoreVision = false, string $param = '') { return $this->dao->select('id, name')->from(TABLE_PROJECT) ->where('type')->eq('project') ->andWhere('deleted')->eq(0) ->beginIF(!$ignoreVision)->andWhere('vision')->eq($this->config->vision)->fi() + ->beginIF(strpos($param, 'noproduct') !== false)->andWhere('hasProduct')->eq(0)->fi() + ->beginIF(strpos($param, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi() + ->beginIF(strpos($param, 'nosprint') !== false)->andWhere('multiple')->eq('0')->fi() ->fetchPairs(); } From d413973030029d283515a99f5374dcbaa6d98da4 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:49:43 +0800 Subject: [PATCH 228/655] * [ticket#1773,doing,0.3h] change project range. --- module/bug/zen.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/bug/zen.php b/module/bug/zen.php index 16eafd0609..9ccaa6dcd9 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -1176,7 +1176,8 @@ class bugZen extends bug if(!empty($bug->execution) && empty($executions[$bug->execution]) && !in_array($execution->attribute, $unAllowedStage)) $executions[$execution->id] = $execution->name . "({$this->lang->bug->deleted})"; /* Get project pairs. */ - $projects = $this->product->getProjectPairsByProduct($bug->product, (string)$bug->branch); + $projectPairs = $product->shadow ? $this->loadModel('project')->getPairs(false, 'noproduct,noclosed') : array(); + $projects = $this->product->getProjectPairsByProduct($bug->product, (string)$bug->branch, array_keys($projectPairs)); if(!empty($bug->project) && empty($projects[$bug->project])) { $project = $this->loadModel('project')->getByID($bug->project); From 614b64b2d69a5979ca84e4e00cb0ec16e9e43bef Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:50:15 +0800 Subject: [PATCH 229/655] * [ticket#1773,doing,1.5h] change page linkage. --- module/bug/js/common.ui.js | 48 +++++++++++++++++++++++++++++-------- module/bug/ui/edit.html.php | 4 +++- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/module/bug/js/common.ui.js b/module/bug/js/common.ui.js index 2605cb5831..ee901c424a 100644 --- a/module/bug/js/common.ui.js +++ b/module/bug/js/common.ui.js @@ -8,7 +8,7 @@ function changeProduct(event) const productID = $(event.target).val(); if(productID == undefined) return false; - if(typeof(changeProductConfirmed) != 'undefined' && !changeProductConfirmed && productID != bug.productID) + if(typeof(changeProductConfirmed) != 'undefined' && !changeProductConfirmed && productID != bug.productID && (typeof(isShadowProduct) == 'undefined' || !isShadowProduct)) { zui.Modal.confirm({message: confirmChangeProduct, onResult: function(result) { @@ -54,13 +54,37 @@ function changeBranch(event) function changeProject(event) { - const productID = $('[name="product"]').val(); - const projectID = $(event.target).val(); + const projectID = $(event.target).val(); + const projectInfoLink = $.createLink('bug', 'ajaxGetProjectInfo', 'projectID=' + projectID); + $.getJSON(projectInfoLink, function(project) + { + $('#executionBox').closest('tr').toggleClass('hidden', project.multiple == 0); + }); - loadExecutionLabel(projectID); - loadExecutions(productID, projectID); - loadAssignedTo(productID, projectID); - if(methodName == 'edit' && edition == 'max') loadIdentify(); + if(config.currentMethod == 'edit' && isShadowProduct) + { + const productIDLink = $.createLink('bug', 'ajaxGetProductIDByProject', 'projectID=' + projectID); + $.get(productIDLink, function(id) + { + const productID = id; + const $productPicker = $('.detail-side [name=product]').zui('picker'); + $productPicker.$.setValue(productID); + + loadExecutionLabel(projectID); + loadExecutions(productID, projectID); + loadAssignedTo(productID, projectID); + if(methodName == 'edit' && edition == 'max') loadIdentify(); + }); + } + else + { + const productID = $('[name="product"]').val(); + + loadExecutionLabel(projectID); + loadExecutions(productID, projectID); + loadAssignedTo(productID, projectID); + if(methodName == 'edit' && edition == 'max') loadIdentify(); + } } function changeExecution(event) @@ -184,6 +208,9 @@ function loadProductModules(productID) let $modulePicker = $('[name="module"]').zui('picker'); $modulePicker.render({items: data}); if(moduleID != 0) $modulePicker.$.setValue('0'); + + $('#manageModule').toggleClass('hidden', data.length > 1); + if(data.length <= 1) $('#manageModule').attr('href', $.createLink('tree', 'browse', 'rootID=' + productID + '¤tModuleID=' + moduleID + '&branch=' + branch)); }); } @@ -192,7 +219,7 @@ function loadProductProjects(productID) let branch = $('[name="branch"]').val(); if(typeof(branch) == 'undefined') branch = 0; - const link = $.createLink('product', 'ajaxGetProjects', 'productID=' + productID + '&branch=' + branch + '&projectID=' + $('[name="project"]').val()); + const link = $.createLink('bug', 'ajaxGetProjects', 'productID=' + productID + '&branch=' + branch + '&projectID=' + $('[name="project"]').val()); $.getJSON(link, function(data) { let project = $('[name="project"]').val(); @@ -547,8 +574,9 @@ function loadTestTasks(productID, executionID) function loadAllBuilds(event) { - const productID = $('[name="product"]').val(); - const buildBox = $(event.target).closest('.input-group').find('select').attr('name').replace('[]', ''); + const productID = $('[name="product"]').val(); + const $buildElement = $(event.target).closest('.input-group').find('select').length > 0 ? $(event.target).closest('.input-group').find('select') : $(event.target).closest('.input-group').find('input'); + const buildBox = $buildElement.attr('name').replace('[]', ''); loadProductBuilds(productID, 'all', buildBox); } diff --git a/module/bug/ui/edit.html.php b/module/bug/ui/edit.html.php index 0d301ecacd..3f5517a5ff 100644 --- a/module/bug/ui/edit.html.php +++ b/module/bug/ui/edit.html.php @@ -22,6 +22,7 @@ jsVar('released', $lang->build->released); jsVar('confirmUnlinkBuild', sprintf($lang->bug->notice->confirmUnlinkBuild, zget($resolvedBuildPairs, $bug->resolvedBuild))); jsVar('projectExecutionPairs', $projectExecutionPairs); jsVar('edition', $config->edition); +jsVar('isShadowProduct', !empty($product->shadow)); detailHeader ( @@ -359,7 +360,8 @@ detailBody ( set::name('project'), set::items($projects), - set::value($bug->project) + set::value($bug->project), + set::required(!empty($product->shadow)) ) ) ), From c4f61fea731e3b42d673900cdeae543fddf81698 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:51:37 +0800 Subject: [PATCH 230/655] *[ticket#1773,doing,0.2h] add ajaxGetProjectInfo method. --- module/bug/control.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/module/bug/control.php b/module/bug/control.php index 3d2cb843c4..e9554b170e 100755 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -1646,4 +1646,17 @@ class bug extends control { return print($this->fetch('repo', 'unlinkBranch')); } + + /** + * 获取项目信息。 + * + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetProjectInfo(int $projectID) + { + $project = $this->loadModel('project')->fetchByID($projectID); + return print(json_encode($project)); + } } From 31efcd84af897067955ccc5da788227ed85b5d24 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:53:22 +0800 Subject: [PATCH 231/655] *[ticket#1773,doing,0.3h] add ajaxGetProductIDByProject method. --- module/bug/zen.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/module/bug/zen.php b/module/bug/zen.php index 9ccaa6dcd9..8ba8fbdd93 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -2469,4 +2469,18 @@ class bugZen extends bug $this->config->bug->actions->view['mainActions'] = array('confirm', 'assignTo', 'resolve', 'close', 'activate'); $this->config->bug->actions->view['suffixActions'] = array('delete'); } + + /** + * 获取项目型项目关联产品的ID。 + * Get product id by project. + * + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetProductIDByProject(int $projectID) + { + $productID = $this->loadModel('product')->getProductIDByProject($projectID); + return print($productID); + } } From aa963e67b93a3ac82a1973f9bb1416095f473fe9 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:53:49 +0800 Subject: [PATCH 232/655] * [ticket#1773,done,0.5h] add ajaxGetProjects method. --- module/bug/zen.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/module/bug/zen.php b/module/bug/zen.php index 8ba8fbdd93..18f17082b0 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -2483,4 +2483,28 @@ class bugZen extends bug $productID = $this->loadModel('product')->getProductIDByProject($projectID); return print($productID); } + + /** + * 获取关联产品的项目下拉数据。 + * AJAX: get projects of a product in html select. + * + * @param int $productID + * @param string $branch ''|'all'|int + * @param int $projectID + * @param string $pageType old + * @access public + * @return void + */ + public function ajaxGetProjects(int $productID, string $branch = '', int $projectID = 0, string $pageType = '') + { + $product = $this->loadModel('product')->fetchByID($productID); + $projectPairs = $product->shadow ? $this->loadModel('project')->getPairs(false, 'noproduct,noclosed') : array(); + $projects = $this->product->getProjectPairsByProduct($productID, $branch, array_keys($projectPairs)); + if($this->app->getViewType() == 'json') return print(json_encode($projects)); + if($pageType == 'old') return print(html::select('project', array(0 => '') + $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID}, this.value)'")); + + $items = array(); + foreach($projects as $projectID => $projectName) $items[] = array('text' => $projectName, 'value' => $projectID, 'keys' => $projectName); + return print(json_encode($items)); + } } From a872f5ef3c740bb93a1762441a6a6edc9107d3f2 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 13:55:08 +0800 Subject: [PATCH 233/655] * [misc,done,0.1h] change method position. --- module/bug/control.php | 38 ++++++++++++++++++++++++++++++++++++++ module/bug/zen.php | 38 -------------------------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/module/bug/control.php b/module/bug/control.php index e9554b170e..c6a42059b3 100755 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -1659,4 +1659,42 @@ class bug extends control $project = $this->loadModel('project')->fetchByID($projectID); return print(json_encode($project)); } + + /** + * 获取项目型项目关联产品的ID。 + * Get product id by project. + * + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetProductIDByProject(int $projectID) + { + $productID = $this->loadModel('product')->getProductIDByProject($projectID); + return print($productID); + } + + /** + * 获取关联产品的项目下拉数据。 + * AJAX: get projects of a product in html select. + * + * @param int $productID + * @param string $branch ''|'all'|int + * @param int $projectID + * @param string $pageType old + * @access public + * @return void + */ + public function ajaxGetProjects(int $productID, string $branch = '', int $projectID = 0, string $pageType = '') + { + $product = $this->loadModel('product')->fetchByID($productID); + $projectPairs = $product->shadow ? $this->loadModel('project')->getPairs(false, 'noproduct,noclosed') : array(); + $projects = $this->product->getProjectPairsByProduct($productID, $branch, array_keys($projectPairs)); + if($this->app->getViewType() == 'json') return print(json_encode($projects)); + if($pageType == 'old') return print(html::select('project', array(0 => '') + $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID}, this.value)'")); + + $items = array(); + foreach($projects as $projectID => $projectName) $items[] = array('text' => $projectName, 'value' => $projectID, 'keys' => $projectName); + return print(json_encode($items)); + } } diff --git a/module/bug/zen.php b/module/bug/zen.php index 18f17082b0..9ccaa6dcd9 100644 --- a/module/bug/zen.php +++ b/module/bug/zen.php @@ -2469,42 +2469,4 @@ class bugZen extends bug $this->config->bug->actions->view['mainActions'] = array('confirm', 'assignTo', 'resolve', 'close', 'activate'); $this->config->bug->actions->view['suffixActions'] = array('delete'); } - - /** - * 获取项目型项目关联产品的ID。 - * Get product id by project. - * - * @param int $projectID - * @access public - * @return void - */ - public function ajaxGetProductIDByProject(int $projectID) - { - $productID = $this->loadModel('product')->getProductIDByProject($projectID); - return print($productID); - } - - /** - * 获取关联产品的项目下拉数据。 - * AJAX: get projects of a product in html select. - * - * @param int $productID - * @param string $branch ''|'all'|int - * @param int $projectID - * @param string $pageType old - * @access public - * @return void - */ - public function ajaxGetProjects(int $productID, string $branch = '', int $projectID = 0, string $pageType = '') - { - $product = $this->loadModel('product')->fetchByID($productID); - $projectPairs = $product->shadow ? $this->loadModel('project')->getPairs(false, 'noproduct,noclosed') : array(); - $projects = $this->product->getProjectPairsByProduct($productID, $branch, array_keys($projectPairs)); - if($this->app->getViewType() == 'json') return print(json_encode($projects)); - if($pageType == 'old') return print(html::select('project', array(0 => '') + $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID}, this.value)'")); - - $items = array(); - foreach($projects as $projectID => $projectName) $items[] = array('text' => $projectName, 'value' => $projectID, 'keys' => $projectName); - return print(json_encode($items)); - } } From fefee028b9effc761fe36a13cd2da9b32047b5d0 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 14:12:25 +0800 Subject: [PATCH 234/655] * [misc,done,0.1h] change param type. --- module/product/model.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/module/product/model.php b/module/product/model.php index d343fcd736..acad8a4c70 100755 --- a/module/product/model.php +++ b/module/product/model.php @@ -863,15 +863,15 @@ class productModel extends model * 获取关联某产品的项目键值对列表。 * Get project pairs by product. * - * @param int $productID - * @param string $branch 'all'|''|int - * @param int $appendProject - * @param string $status all|noclosed|closed - * @param string $param multiple| + * @param int $productID + * @param string $branch 'all'|''|int + * @param string|array $appendProject + * @param string $status all|noclosed|closed + * @param string $param multiple| * @access public * @return array */ - public function getProjectPairsByProduct(int $productID, string $branch = '0', string $appendProject = '', string $status = '', string $param = ''): array + public function getProjectPairsByProduct(int $productID, string $branch = '0', string|array $appendProject = '', string $status = '', string $param = ''): array { $product = $this->getByID($productID); if(empty($product)) return array(); From bfab87e8b0496a0e3930d7be363b814cb8f7a69f Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 14:12:47 +0800 Subject: [PATCH 235/655] * [bug#59495,59510,done,0.3h] fix filter label error. --- module/my/control.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/my/control.php b/module/my/control.php index 1624d961b9..f0506a36f4 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -1154,6 +1154,7 @@ class my extends control public function ticket(string $browseType = 'assignedtome', int $param = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1) { $this->session->set('ticketList', $this->app->getURI(true), 'ticket'); + $this->session->set('ticketBrowseType', $browseType); $this->app->loadClass('pager', $static = true); $pager = pager::init($recTotal, $recPerPage, $pageID); From 4e0d19b32acfe4db81072ca8c6e143c4fe393eb0 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 15:10:32 +0800 Subject: [PATCH 236/655] * [bug#59609,done,0.5h] fix projectID. --- module/bug/js/common.ui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/module/bug/js/common.ui.js b/module/bug/js/common.ui.js index ee901c424a..1f1facda5e 100644 --- a/module/bug/js/common.ui.js +++ b/module/bug/js/common.ui.js @@ -238,6 +238,7 @@ function loadExecutions(productID, projectID = 0) $('#executionBox').toggle(!isMultipleProject); + if(projectID == 0) projectID = $('[name="project"]').val(); const link = $.createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&projectID=' + projectID + '&branch=' + branch + '&pageType=&executionID=&from=&mode=stagefilter'); $.getJSON(link, function(data) { From 5fa4122c05bb2f81c31aa59b77f0be9fc64072a1 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Wed, 12 Feb 2025 15:13:42 +0800 Subject: [PATCH 237/655] * [misc,done,0.1h] fix number. --- module/product/js/browse.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/product/js/browse.ui.js b/module/product/js/browse.ui.js index ba74013063..2bef7b4133 100644 --- a/module/product/js/browse.ui.js +++ b/module/product/js/browse.ui.js @@ -165,7 +165,7 @@ window.setStatistics = function(element, checkedIdList, pageSummary) if(rateCount) rate = Math.round(hasCase / rateCount * 10000) / 100 + '' + '%'; - return {html: checkedSummary.replace('%total%', total).replace('%estimate%', estimate).replace('%rate%', rate)}; + return {html: checkedSummary.replace('%total%', total).replace('%estimate%', estimate.toFixed(2)).replace('%rate%', rate)}; }; window.setShowGrades = function() From bd970411e6ffc24b3c406ab3e2965e3830a3964e Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 15:55:05 +0800 Subject: [PATCH 238/655] * [bug#59534,done,0.5h] fix parent stage link error. --- module/project/js/execution.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/project/js/execution.ui.js b/module/project/js/execution.ui.js index 73a0c44f85..a79ea722d2 100644 --- a/module/project/js/execution.ui.js +++ b/module/project/js/execution.ui.js @@ -61,7 +61,7 @@ window.onRenderCell = function(result, {col, row}) html += data.prefixLabel; } - if(data.type == 'point') + if(data.type == 'point' || !(executionType !== undefined && !data.isParent)) { if(result[0].props.href !== undefined) delete result[0].props.href; From 65d841320f18f2065797a4523c4c9707016b73e1 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 15:58:27 +0800 Subject: [PATCH 239/655] * [bug#59534,done,0.5h] fix parent stage link error. --- module/project/js/execution.ui.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/project/js/execution.ui.js b/module/project/js/execution.ui.js index a79ea722d2..cdf6535dd7 100644 --- a/module/project/js/execution.ui.js +++ b/module/project/js/execution.ui.js @@ -64,10 +64,9 @@ window.onRenderCell = function(result, {col, row}) if(data.type == 'point' || !(executionType !== undefined && !data.isParent)) { if(result[0].props.href !== undefined) delete result[0].props.href; - result[0].type = 'span'; - html += data.name; + if(data.type == 'point') html += data.name; } } if(html) result.unshift({className: 'flex items-center', html: html}); From 0526695c758d5b76ec3f50c836101a039517bc60 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Feb 2025 16:01:33 +0800 Subject: [PATCH 240/655] * [bug#59534,done,0.5h] fix parent stage link error. --- module/project/js/execution.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/project/js/execution.ui.js b/module/project/js/execution.ui.js index cdf6535dd7..c940f300ea 100644 --- a/module/project/js/execution.ui.js +++ b/module/project/js/execution.ui.js @@ -61,7 +61,7 @@ window.onRenderCell = function(result, {col, row}) html += data.prefixLabel; } - if(data.type == 'point' || !(executionType !== undefined && !data.isParent)) + if(data.type == 'point' || (executionType !== undefined && data.isParent)) { if(result[0].props.href !== undefined) delete result[0].props.href; result[0].type = 'span'; From da46b3ac27e257f4fb1d114aa21a2042838b2257 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Thu, 13 Feb 2025 05:34:51 +0000 Subject: [PATCH 241/655] * [misc] remove unused code. --- module/task/control.php | 7 ------- module/task/zen.php | 1 - 2 files changed, 8 deletions(-) diff --git a/module/task/control.php b/module/task/control.php index 2e68b05212..9e96d83ec6 100755 --- a/module/task/control.php +++ b/module/task/control.php @@ -826,13 +826,6 @@ class task extends control $taskIdList = $this->post->taskIdList ? array_unique($this->post->taskIdList) : array(); if(!empty($taskIdList) || $confirm == 'yes') { - if(!isset($_POST['taskIdList']) && !empty($_SESSION['batchCloseTaskIDList'])) - { - $taskIdList = explode(',', $this->session->batchCloseTaskIDList); - unset($_SESSION['batchCloseTaskIDList']); - } - if($taskIdList) $taskIdList = array_filter(array_unique($taskIdList)); - foreach($taskIdList as $taskID) { $task = $this->task->fetchById((int)$taskID); diff --git a/module/task/zen.php b/module/task/zen.php index eef226d8fc..e846b4a688 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -1884,7 +1884,6 @@ class taskZen extends task { $skipTasks = implode(',', $skipTasks); $confirmURL = $this->createLink('task', 'batchClose', "confirm=yes"); - $this->session->set('batchCloseTaskIDList', $skipTasks, 'task'); return array('result' => 'success', 'load' => array('confirm' => sprintf($this->lang->task->error->skipClose, $skipTasks), 'confirmed' => $confirmURL)); } From 68f00909493030d692af91b6cca1c6ca6df9a378 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Thu, 13 Feb 2025 16:47:18 +0800 Subject: [PATCH 242/655] * [bug#59687,done,0.5h] fix duplicateBug range error. --- module/bug/js/common.ui.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/module/bug/js/common.ui.js b/module/bug/js/common.ui.js index 1f1facda5e..ca9fbf5563 100644 --- a/module/bug/js/common.ui.js +++ b/module/bug/js/common.ui.js @@ -34,6 +34,7 @@ function changeProduct(event) loadProductPlans(productID); loadProductCases(productID); loadProductStories(productID, bug.storyID); + loadProductBugs(productID, bug.id); if(methodName == 'edit' && edition == 'max') loadIdentify(); } } @@ -748,3 +749,17 @@ function loadProductCases(productID) $casePicker.$.setValue(caseID); }); } + +function loadProductBugs(productID, bugID) +{ + if($('[name="duplicateBug"]').length == 0) return; + + const link = $.createLink('bug', 'ajaxGetProductBugs', 'productID=' + productID + '&bugID=' + bugID); + $.getJSON(link, function(data) + { + const duplicateBugID = $('[name="duplicateBug"]').val(); + const $duplicateBugPicker = $('[name="duplicateBug"]').zui('picker'); + $duplicateBugPicker.render({items: data}); + $duplicateBugPicker.$.setValue(planID); + }); +} From 0d1b047e055e7d8ac156705db6e89abc1747e25b Mon Sep 17 00:00:00 2001 From: tianshujie Date: Thu, 13 Feb 2025 16:48:23 +0800 Subject: [PATCH 243/655] * [misc,done,0.1h] fix duplicateBugID error. --- module/bug/js/common.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/bug/js/common.ui.js b/module/bug/js/common.ui.js index ca9fbf5563..0391a7d0be 100644 --- a/module/bug/js/common.ui.js +++ b/module/bug/js/common.ui.js @@ -760,6 +760,6 @@ function loadProductBugs(productID, bugID) const duplicateBugID = $('[name="duplicateBug"]').val(); const $duplicateBugPicker = $('[name="duplicateBug"]').zui('picker'); $duplicateBugPicker.render({items: data}); - $duplicateBugPicker.$.setValue(planID); + $duplicateBugPicker.$.setValue(duplicateBugID); }); } From 22ed222eee20d4d50365a0ce58ca23bd0dd0a953 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Thu, 13 Feb 2025 06:19:39 +0000 Subject: [PATCH 244/655] * [misc] modify tab. --- module/project/js/createguide.ui.js | 2 +- module/project/ui/createguide.html.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/module/project/js/createguide.ui.js b/module/project/js/createguide.ui.js index 9b9c13b0d3..ee7a1e7de3 100644 --- a/module/project/js/createguide.ui.js +++ b/module/project/js/createguide.ui.js @@ -5,7 +5,7 @@ $(document).on('click', '.model-item', function() zui.Modal.hide(); - openUrl(link, {'app': 'project'}); + openUrl(link, {'app': appTab}); }); $(function() diff --git a/module/project/ui/createguide.html.php b/module/project/ui/createguide.html.php index 3a435cdb62..723542be4f 100644 --- a/module/project/ui/createguide.html.php +++ b/module/project/ui/createguide.html.php @@ -11,6 +11,7 @@ declare(strict_types=1); namespace zin; jsVar('isInModal', isInModal()); +jsVar('appTab', $config->vision == 'or' ? 'charter' : 'project'); div ( setClass('modal-header justify-center font-bold p-0 pb-2'), From 98353f98dede9632dd9f39740cdf44e9c61cd25a Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 13 Feb 2025 16:51:17 +0800 Subject: [PATCH 245/655] * [refac] remove debug js code. --- lib/zin/wg/searchform/v1.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/zin/wg/searchform/v1.php b/lib/zin/wg/searchform/v1.php index ff74720c31..98639943c6 100644 --- a/lib/zin/wg/searchform/v1.php +++ b/lib/zin/wg/searchform/v1.php @@ -62,8 +62,7 @@ class searchForm extends wg ->do ( '$element.attr("data-last-url", $.apps.getAppUrl())', - 'zui.SearchForm.get($element).$.load(true)', - 'console.log("skip morph", event);' + 'zui.SearchForm.get($element).$.load(true)' ) ->endIf() ) From 830628a1a5f4509e2b558b4b1a0fcd70f836bb99 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 13 Feb 2025 14:35:14 +0800 Subject: [PATCH 246/655] * [misc] support for upgrading deleted docs. --- module/upgrade/model.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 7645a83347..626c73be27 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -10679,7 +10679,6 @@ class upgradeModel extends model ->where('t2.type')->in(array('doc', 'html')) ->andWhere('t1.status')->ne('draft') ->andWhere('t2.rawContent')->in(null) - ->andWhere('t1.deleted')->eq('0') ->fetchAll('id', false); $newDocs = array(); From edca34bdbf0cf2aec82697f1879a424f3b88a6b2 Mon Sep 17 00:00:00 2001 From: sunhao Date: Thu, 13 Feb 2025 17:26:37 +0800 Subject: [PATCH 247/655] * [misc] update zui3 lib. --- www/js/zui3/zui.zentao.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/www/js/zui3/zui.zentao.js b/www/js/zui3/zui.zentao.js index e2ab4881a4..2b66585b8c 100644 --- a/www/js/zui3/zui.zentao.js +++ b/www/js/zui3/zui.zentao.js @@ -1,12 +1,12 @@ -var bu=(I,tt,It)=>{if(!tt.has(I))throw TypeError("Cannot "+It)};var Dt=(I,tt,It)=>(bu(I,tt,"read from private field"),It?It.call(I):tt.get(I)),jt=(I,tt,It)=>{if(tt.has(I))throw TypeError("Cannot add the same private member more than once");tt instanceof WeakSet?tt.add(I):tt.set(I,It)},Wt=(I,tt,It,Xa)=>(bu(I,tt,"write to private field"),Xa?Xa.call(I,It):tt.set(I,It),It);var wu=(I,tt,It)=>(bu(I,tt,"access private method"),It);(function(I,tt){typeof exports=="object"&&typeof module<"u"?tt(exports):typeof define=="function"&&define.amd?define(["exports"],tt):(I=typeof globalThis<"u"?globalThis:I||self,tt(I.zui={}))})(this,function(I){var wa,Ca,yr,vr,_r,br,wr,Cr,xa,_g,ka,bg,Vn,Kn;"use strict";const tt="",It="",Xa="",p0="",m0="",g0="",y0="",v0="",_0="",b0="",w0="",C0="",Sg="3.0.0",Tg="production",dn=document,zr=window,ku=dn.documentElement,ni=dn.createElement.bind(dn),Su=ni("div"),Za=ni("table"),$g=ni("tbody"),Tu=ni("tr"),{isArray:Fr,prototype:$u}=Array,{concat:Dg,filter:el,indexOf:Du,map:Iu,push:Ig,slice:Nu,some:tl,splice:Ng}=$u,Mg=/^#(?:[\w-]|\\.|[^\x00-\xa0])*$/,Eg=/^\.(?:[\w-]|\\.|[^\x00-\xa0])*$/,Ag=/<.+>/,Pg=/^\w+$/;function nl(i,e){const t=Lg(e);return!i||!t&&!ii(e)&&!st(e)?[]:!t&&Eg.test(i)?e.getElementsByClassName(i.slice(1).replace(/\\/g,"")):!t&&Pg.test(i)?e.getElementsByTagName(i):e.querySelectorAll(i)}class jr{constructor(e,t){if(!e)return;if(il(e))return e;let n=e;if(bt(e)){const s=t||dn;if(n=Mg.test(e)&&ii(s)?s.getElementById(e.slice(1).replace(/\\/g,"")):Ag.test(e)?Ru(e):il(s)?s.find(e):bt(s)?y(s).find(e):nl(e,s),!n)return}else if(si(e))return this.ready(e);(n.nodeType||n===zr)&&(n=[n]),this.length=n.length;for(let s=0,r=this.length;s{for(;e.firstChild;)e.removeChild(e.firstChild)})};function Br(...i){const e=Og(i[0])?i.shift():!1,t=i.shift(),n=i.length;if(!t)return{};if(!n)return Br(e,y,t);for(let s=0;s{st(r)&&dt(t,(o,a)=>{n?e?r.classList.add(a):r.classList.remove(a):r.classList.toggle(a)})})},ie.addClass=function(i){return this.toggleClass(i,!0)},ie.removeAttr=function(i){const e=Hr(i);return this.each((t,n)=>{st(n)&&dt(e,(s,r)=>{n.removeAttribute(r)})})};function Fg(i,e){if(i){if(bt(i)){if(arguments.length<2){if(!this[0]||!st(this[0]))return;const t=this[0].getAttribute(i);return ws(t)?void 0:t}return Nt(e)?this:ws(e)?this.removeAttr(i):this.each((t,n)=>{st(n)&&n.setAttribute(i,e)})}for(const t in i)this.attr(t,i[t]);return this}}ie.attr=Fg,ie.removeClass=function(i){return arguments.length?this.toggleClass(i,!1):this.attr("class","")},ie.hasClass=function(i){return!!i&&tl.call(this,e=>st(e)&&e.classList.contains(i))},ie.get=function(i){return Nt(i)?Nu.call(this):(i=Number(i),this[i<0?i+this.length:i])},ie.eq=function(i){return y(this.get(i))},ie.first=function(){return this.eq(0)},ie.last=function(){return this.eq(-1)};function jg(i){return Nt(i)?this.get().map(e=>st(e)||Rg(e)?e.textContent:"").join(""):this.each((e,t)=>{st(t)&&(t.textContent=i)})}ie.text=jg;function fn(i,e,t){if(!st(i))return;const n=zr.getComputedStyle(i,null);return t?n.getPropertyValue(e)||void 0:n[e]||i.style[e]}function Jt(i,e){return parseInt(fn(i,e),10)||0}function Eu(i,e){return Jt(i,`border${e?"Left":"Top"}Width`)+Jt(i,`padding${e?"Left":"Top"}`)+Jt(i,`padding${e?"Right":"Bottom"}`)+Jt(i,`border${e?"Right":"Bottom"}Width`)}const rl={};function Bg(i){if(rl[i])return rl[i];const e=ni(i);dn.body.insertBefore(e,null);const t=fn(e,"display");return dn.body.removeChild(e),rl[i]=t!=="none"?t:"block"}function Au(i){return fn(i,"display")==="none"}function Pu(i,e){const t=i&&(i.matches||i.webkitMatchesSelector||i.msMatchesSelector);return!!t&&!!e&&t.call(i,e)}function Wr(i){return bt(i)?(e,t)=>Pu(t,i):si(i)?i:il(i)?(e,t)=>i.is(t):i?(e,t)=>t===i:()=>!1}ie.filter=function(i){const e=Wr(i);return y(el.call(this,(t,n)=>e.call(t,n,t)))};function In(i,e){return e?i.filter(e):i}ie.detach=function(i){return In(this,i).each((e,t)=>{t.parentNode&&t.parentNode.removeChild(t)}),this};const Hg=/^\s*<(\w+)[^>]*>/,Wg=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,Lu={"*":Su,tr:$g,td:Tu,th:Tu,thead:Za,tbody:Za,tfoot:Za};function Ru(i){if(!bt(i))return[];if(Wg.test(i))return[ni(RegExp.$1)];const e=Hg.test(i)&&RegExp.$1,t=Lu[e]||Lu["*"];return t.innerHTML=i,y(t.childNodes).detach().get()}y.parseHTML=Ru,ie.has=function(i){const e=bt(i)?(t,n)=>nl(i,n).length:(t,n)=>n.contains(i);return this.filter(e)},ie.not=function(i){const e=Wr(i);return this.filter((t,n)=>(!bt(i)||st(n))&&!e.call(n,t,n))};function pn(i,e,t,n){const s=[],r=si(e),o=n&&Wr(n);for(let a=0,l=i.length;ae.selected&&!e.disabled&&!e.parentNode.disabled),"value"):i.value||""}function Ug(i){return arguments.length?this.each((e,t)=>{const n=t.multiple&&t.options;if(n||Gu.test(t.type)){const s=Fr(i)?Iu.call(i,String):ws(i)?[]:[String(i)];n?dt(t.options,(r,o)=>{o.selected=s.indexOf(o.value)>=0},!0):t.checked=s.indexOf(t.value)>=0}else t.value=Nt(i)||ws(i)?"":i}):this[0]&&Ou(this[0])}ie.val=Ug,ie.is=function(i){const e=Wr(i);return tl.call(this,(t,n)=>e.call(t,n,t))},y.guid=1;function Xt(i){return i.length>1?el.call(i,(e,t,n)=>Du.call(n,e)===t):i}y.unique=Xt,ie.add=function(i,e){return y(Xt(this.get().concat(y(i,e).get())))},ie.children=function(i){return In(y(Xt(pn(this,e=>e.children))),i)},ie.parent=function(i){return In(y(Xt(pn(this,"parentNode"))),i)},ie.index=function(i){const e=i?y(i)[0]:this[0],t=i?this:y(e).parent().children();return Du.call(t,e)},ie.closest=function(i){const e=this.filter(i);if(e.length)return e;const t=this.parent();return t.length?t.closest(i):e},ie.siblings=function(i){return In(y(Xt(pn(this,e=>y(e).parent().children().not(e)))),i)},ie.find=function(i){return y(Xt(pn(this,e=>nl(i,e))))};const Vg=/^\s*\s*$/g,Kg=/^$|^module$|\/(java|ecma)script/i,qg=["type","src","nonce","noModule"];function Gg(i,e){const t=y(i);t.filter("script").add(t.find("script")).each((n,s)=>{if(Kg.test(s.type)&&ku.contains(s)){const r=ni("script");r.text=s.textContent.replace(Vg,""),dt(qg,(o,a)=>{s[a]&&(r[a]=s[a])}),e.head.insertBefore(r,null),e.head.removeChild(r)}})}function Yg(i,e,t,n,s){n?i.insertBefore(e,t?i.firstChild:null):i.nodeName==="HTML"?i.parentNode.replaceChild(e,i):i.parentNode.insertBefore(e,t?i:i.nextSibling),s&&Gg(e,i.ownerDocument)}function Nn(i,e,t,n,s,r,o,a){return dt(i,(l,c)=>{dt(y(c),(d,u)=>{dt(y(e),(p,g)=>{const _=t?u:g,C=t?g:u,x=t?d:p;Yg(_,x?C.cloneNode(!0):C,n,s,!x)},a)},o)},r),e}ie.after=function(){return Nn(arguments,this,!1,!1,!1,!0,!0)},ie.append=function(){return Nn(arguments,this,!1,!1,!0)};function Qg(i){if(!arguments.length)return this[0]&&this[0].innerHTML;if(Nt(i))return this;const e=/]/.test(i);return this.each((t,n)=>{st(n)&&(e?y(n).empty().append(i):n.innerHTML=i)})}ie.html=Qg,ie.appendTo=function(i){return Nn(arguments,this,!0,!1,!0)},ie.wrapInner=function(i){return this.each((e,t)=>{const n=y(t),s=n.contents();s.length?s.wrapAll(i):n.append(i)})},ie.before=function(){return Nn(arguments,this,!1,!0)},ie.wrapAll=function(i){let e=y(i),t=e[0];for(;t.children.length;)t=t.firstElementChild;return this.first().before(e),this.appendTo(t)},ie.wrap=function(i){return this.each((e,t)=>{const n=y(i)[0];y(t).wrapAll(e?n.cloneNode(!0):n)})},ie.insertAfter=function(i){return Nn(arguments,this,!0,!1,!1,!1,!1,!0)},ie.insertBefore=function(i){return Nn(arguments,this,!0,!0)},ie.prepend=function(){return Nn(arguments,this,!1,!0,!0,!0,!0)},ie.prependTo=function(i){return Nn(arguments,this,!0,!0,!0,!1,!1,!0)},ie.contents=function(){return y(Xt(pn(this,i=>i.tagName==="IFRAME"?[i.contentDocument]:i.tagName==="TEMPLATE"?i.content.childNodes:i.childNodes)))},ie.next=function(i,e,t){return In(y(Xt(pn(this,"nextElementSibling",e,t))),i)},ie.nextAll=function(i){return this.next(i,!0)},ie.nextUntil=function(i,e){return this.next(e,!0,i)},ie.parents=function(i,e){return In(y(Xt(pn(this,"parentElement",!0,e))),i)},ie.parentsUntil=function(i,e){return this.parents(e,i)},ie.prev=function(i,e,t){return In(y(Xt(pn(this,"previousElementSibling",e,t))),i)},ie.prevAll=function(i){return this.prev(i,!0)},ie.prevUntil=function(i,e){return this.prev(e,!0,i)},ie.map=function(i){return y(Dg.apply([],Iu.call(this,(e,t)=>i.call(e,t,e))))},ie.clone=function(){return this.map((i,e)=>e.cloneNode(!0))},ie.offsetParent=function(){return this.map((i,e)=>{let t=e.offsetParent;for(;t&&fn(t,"position")==="static";)t=t.offsetParent;return t||ku})},ie.slice=function(i,e){return y(Nu.call(this,i,e))};const Jg=/-([a-z])/g;function ol(i){return i.replace(Jg,(e,t)=>t.toUpperCase())}ie.ready=function(i){const e=()=>setTimeout(i,0,y);return dn.readyState!=="loading"?e():dn.addEventListener("DOMContentLoaded",e),this},ie.unwrap=function(){return this.parent().each((i,e)=>{if(e.tagName==="BODY")return;const t=y(e);t.replaceWith(t.children())}),this},ie.offset=function(){const i=this[0];if(!i)return;const e=i.getBoundingClientRect();return{top:e.top+zr.pageYOffset,left:e.left+zr.pageXOffset}},ie.position=function(){const i=this[0];if(!i)return;const e=fn(i,"position")==="fixed",t=e?i.getBoundingClientRect():this.offset();if(!e){const n=i.ownerDocument;let s=i.offsetParent||n.documentElement;for(;(s===n.body||s===n.documentElement)&&fn(s,"position")==="static";)s=s.parentNode;if(s!==i&&st(s)){const r=y(s).offset();t.top-=r.top+Jt(s,"borderTopWidth"),t.left-=r.left+Jt(s,"borderLeftWidth")}}return{top:t.top-Jt(i,"marginTop"),left:t.left-Jt(i,"marginLeft")}};const zu={class:"className",contenteditable:"contentEditable",for:"htmlFor",readonly:"readOnly",maxlength:"maxLength",tabindex:"tabIndex",colspan:"colSpan",rowspan:"rowSpan",usemap:"useMap"};ie.prop=function(i,e){if(i){if(bt(i))return i=zu[i]||i,arguments.length<2?this[0]&&this[0][i]:this.each((t,n)=>{n[i]=e});for(const t in i)this.prop(t,i[t]);return this}},ie.removeProp=function(i){return this.each((e,t)=>{delete t[zu[i]||i]})};const Xg=/^--/;function al(i){return Xg.test(i)}const ll={},{style:Zg}=Su,ey=["webkit","moz","ms"];function ty(i,e=al(i)){if(e)return i;if(!ll[i]){const t=ol(i),n=`${t[0].toUpperCase()}${t.slice(1)}`,s=`${t} ${ey.join(`${n} `)}${n}`.split(" ");dt(s,(r,o)=>{if(o in Zg)return ll[i]=o,!1})}return ll[i]}const ny={animationIterationCount:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0};function Fu(i,e,t=al(i)){return!t&&!ny[i]&&Mu(e)?`${e}px`:e}function iy(i,e){if(bt(i)){const t=al(i);return i=ty(i,t),arguments.length<2?this[0]&&fn(this[0],i,t):i?(e=Fu(i,e,t),this.each((n,s)=>{st(s)&&(t?s.style.setProperty(i,e):s.style[i]=e)})):this}for(const t in i)this.css(t,i[t]);return this}ie.css=iy;function ju(i,e){try{return i(e)}catch{return e}}const sy=/^\s+|\s+$/;function Bu(i,e){const t=i.dataset[e]||i.dataset[ol(e)];return sy.test(t)?t:ju(JSON.parse,t)}function ry(i,e,t){t=ju(JSON.stringify,t),i.dataset[ol(e)]=t}function oy(i,e){if(!i){if(!this[0])return;const t={};for(const n in this[0].dataset)t[n]=Bu(this[0],n);return t}if(bt(i))return arguments.length<2?this[0]&&Bu(this[0],i):Nt(e)?this:this.each((t,n)=>{ry(n,i,e)});for(const t in i)this.data(t,i[t]);return this}ie.data=oy;function Hu(i,e){const t=i.documentElement;return Math.max(i.body[`scroll${e}`],t[`scroll${e}`],i.body[`offset${e}`],t[`offset${e}`],t[`client${e}`])}dt([!0,!1],(i,e)=>{dt(["Width","Height"],(t,n)=>{const s=`${e?"outer":"inner"}${n}`;ie[s]=function(r){if(this[0])return Ei(this[0])?e?this[0][`inner${n}`]:this[0].document.documentElement[`client${n}`]:ii(this[0])?Hu(this[0],n):this[0][`${e?"offset":"client"}${n}`]+(r&&e?Jt(this[0],`margin${t?"Top":"Left"}`)+Jt(this[0],`margin${t?"Bottom":"Right"}`):0)}})}),dt(["Width","Height"],(i,e)=>{const t=e.toLowerCase();ie[t]=function(n){if(!this[0])return Nt(n)?void 0:this;if(!arguments.length)return Ei(this[0])?this[0].document.documentElement[`client${e}`]:ii(this[0])?Hu(this[0],e):this[0].getBoundingClientRect()[t]-Eu(this[0],!i);const s=parseInt(n,10);return this.each((r,o)=>{if(!st(o))return;const a=fn(o,"boxSizing");o.style[t]=Fu(t,s+(a==="border-box"?Eu(o,!i):0))})}});const Wu="___cd";ie.toggle=function(i){return this.each((e,t)=>{if(!st(t))return;const n=Au(t);(Nt(i)?n:i)?(t.style.display=t[Wu]||"",Au(t)&&(t.style.display=Bg(t.tagName))):n||(t[Wu]=fn(t,"display"),t.style.display="none")})},ie.hide=function(){return this.toggle(!1)},ie.show=function(){return this.toggle(!0)};const Uu="___ce",cl=".",hl={focus:"focusin",blur:"focusout"},Vu={mouseenter:"mouseover",mouseleave:"mouseout"},ay=/^(mouse|pointer|contextmenu|drag|drop|click|dblclick)/i;function ul(i){return Vu[i]||hl[i]||i}function dl(i){const e=i.split(cl);return[e[0],e.slice(1).sort()]}ie.trigger=function(i,e){if(bt(i)){const[n,s]=dl(i),r=ul(n);if(!r)return this;const o=ay.test(r)?"MouseEvents":"HTMLEvents";i=dn.createEvent(o),i.initEvent(r,!0,!0),i.namespace=s.join(cl),i.___ot=n}i.___td=e;const t=i.___ot in hl;return this.each((n,s)=>{t&&si(s[i.___ot])&&(s[`___i${i.type}`]=!0,s[i.___ot](),s[`___i${i.type}`]=!1),s.dispatchEvent(i)})};function Ku(i){return i[Uu]=i[Uu]||{}}function ly(i,e,t,n,s){const r=Ku(i);r[e]=r[e]||[],r[e].push([t,n,s]),i.addEventListener(e,s)}function qu(i,e){return!e||!tl.call(e,t=>i.indexOf(t)<0)}function Ur(i,e,t,n,s){const r=Ku(i);if(e)r[e]&&(r[e]=r[e].filter(([o,a,l])=>{if(s&&l.guid!==s.guid||!qu(o,t)||n&&n!==a)return!0;i.removeEventListener(e,l)}));else for(e in r)Ur(i,e,t,n,s)}ie.off=function(i,e,t){if(Nt(i))this.each((n,s)=>{!st(s)&&!ii(s)&&!Ei(s)||Ur(s)});else if(bt(i))si(e)&&(t=e,e=""),dt(Hr(i),(n,s)=>{const[r,o]=dl(s),a=ul(r);this.each((l,c)=>{!st(c)&&!ii(c)&&!Ei(c)||Ur(c,a,o,e,t)})});else for(const n in i)this.off(n,i[n]);return this},ie.remove=function(i){return In(this,i).detach().off(),this},ie.replaceWith=function(i){return this.before(i).remove()},ie.replaceAll=function(i){return y(i).replaceWith(this),this};function cy(i,e,t,n,s){if(!bt(i)){for(const r in i)this.on(r,e,t,i[r],s);return this}return bt(e)||(Nt(e)||ws(e)?e="":Nt(t)?(t=e,e=""):(n=t,t=e,e="")),si(n)||(n=t,t=void 0),n?(dt(Hr(i),(r,o)=>{const[a,l]=dl(o),c=ul(a),d=a in Vu,u=a in hl;c&&this.each((p,g)=>{if(!st(g)&&!ii(g)&&!Ei(g))return;const _=function(C){if(C.target[`___i${C.type}`])return C.stopImmediatePropagation();if(C.namespace&&!qu(l,C.namespace.split(cl))||!e&&(u&&(C.target!==g||C.___ot===c)||d&&C.relatedTarget&&g.contains(C.relatedTarget)))return;let x=g;if(e){let $=C.target;for(;!Pu($,e);)if($===g||($=$.parentNode,!$))return;x=$}Object.defineProperty(C,"currentTarget",{configurable:!0,get(){return x}}),Object.defineProperty(C,"delegateTarget",{configurable:!0,get(){return g}}),Object.defineProperty(C,"data",{configurable:!0,get(){return t}});const k=n.call(x,C,C.___td);s&&Ur(g,c,l,e,_),k===!1&&(C.preventDefault(),C.stopPropagation())};_.guid=n.guid=n.guid||y.guid++,ly(g,c,l,e,_)})}),this):this}ie.on=cy;function hy(i,e,t,n){return this.on(i,e,t,n,!0)}ie.one=hy;const uy=/\r?\n/g;function dy(i,e){return`&${encodeURIComponent(i)}=${encodeURIComponent(e.replace(uy,`\r -`))}`}const fy=/file|reset|submit|button|image/i,Gu=/radio|checkbox/i;ie.serialize=function(){let i="";return this.each((e,t)=>{dt(t.elements||[t],(n,s)=>{if(s.disabled||!s.name||s.tagName==="FIELDSET"||fy.test(s.type)||Gu.test(s.type)&&!s.checked)return;const r=Ou(s);if(!Nt(r)){const o=Fr(r)?r:[r];dt(o,(a,l)=>{i+=dy(s.name,l)})}})}),i.slice(1)},window.$=y;function Yu(i,e){if(i==null)return[i,void 0];typeof e=="string"&&(e=e.split("."));const t=e.join(".");let n=i;const s=[n];for(;typeof n=="object"&&n!==null&&e.length;){let r=e.shift(),o;const a=r.indexOf("[");if(a>0&&a{const s=t[n]??"";i=i.replace(new RegExp(`\\{${n}\\}`,"g"),`${s}`)}),i}for(let t=0;t(i[i.B=1]="B",i[i.KB=1024]="KB",i[i.MB=1048576]="MB",i[i.GB=1073741824]="GB",i[i.TB=1099511627776]="TB",i))(fl||{});function pt(i,e=2,t){return Number.isNaN(i)?"?KB":(t||(i<1024?t="B":i<1048576?t="KB":i<1073741824?t="MB":i<1099511627776?t="GB":t="TB"),(i/fl[t]).toFixed(e)+t)}const mn=i=>{const e=/^[0-9]*(B|KB|MB|GB|TB)$/;i=i.toUpperCase(),i.endsWith("B")||(i+="B");const t=i.match(e);if(!t)return 0;const n=t[1];return i=i.replace(n,""),Number.parseInt(i,10)*fl[n]};let pl=(document.documentElement.getAttribute("lang")||"zh_cn").toLowerCase().replace("-","_"),gn;function Qu(){return pl}function my(i){pl=i.toLowerCase().replace("-","_")}function Ju(i,e){gn||(gn={}),typeof i=="string"&&(i={[i]:e??{}}),y.extend(!0,gn,i)}function Ne(i,e,t,n,s,r){Array.isArray(i)?gn&&i.unshift(gn):i=gn?[gn,i]:[i],typeof t=="string"&&(r=s,s=n,n=t,t=void 0);const o=s||pl;let a;for(const l of i){if(!l)continue;const c=l[o]||l.default;if(!c)continue;const d=r&&l===gn?`${r}.${e}`:e;if(a=Cs(c,d),a!==void 0)break}return a===void 0?n:t?be(a,...Array.isArray(t)?t:[t]):a}function gy(i,e,t,n){return Ne(void 0,i,e,t,n)}Ne.addLang=Ju,Ne.getLang=gy,Ne.getCode=Qu,Ne.setCode=my,Ne.map=gn,Ju({zh_cn:{confirm:"确定",save:"保存",cancel:"取消",delete:"删除",reset:"重置",add:"添加",copy:"复制",close:"关闭"},zh_tw:{confirm:"確定",save:"儲存",cancel:"取消",delete:"刪除",reset:"重置",add:"添加",Copy:"複製",close:"關閉"},en:{confirm:"Confirm",save:"Save",cancel:"Cancel",delete:"Delete",reset:"Reset",add:"Add",copy:"Copy",close:"Close"}});function ri(i,e,t){t!=null&&(Array.isArray(t)?t.forEach(n=>ri(i,e,n)):!(t instanceof Blob)&&y.isPlainObject(t)?Object.entries(t).forEach(([n,s])=>{ri(i,`${e}[${n}]`,s)}):i.append(e,t instanceof Blob?t:String(t)))}function Vr(i,e){const t=e||new FormData;return i&&(typeof i=="string"&&(i=new URLSearchParams(i)),i instanceof URLSearchParams?i.forEach((n,s)=>{ri(t,s,n)}):Array.isArray(i)?i.forEach(([n,s])=>{ri(t,n,s)}):i instanceof FormData?i.forEach((n,s)=>{ri(t,s,n)}):y.isPlainObject(i)&&Object.entries(i).forEach(([n,s])=>{ri(t,n,s)})),t}function Xu(i,e,t){i instanceof Headers?i.set(e,t):Array.isArray(i)?i.push([e,t]):i[e]=t}function yy(i,e){if(i){const t={text:"text/plain",html:"text/html",json:"application/json",...e};for(const[n,s]of Object.entries(t))if(s.split(",").map(r=>r.trim()).includes(i))return n}return"text"}class xs{get completed(){return this.data!==void 0||this.error!==void 0}get[Symbol.toStringTag](){return"Ajax"}constructor(e){this.setting=e,this._controller=new AbortController,this._callbacks={success:[],error:[],complete:[]}}on(e,t){return this._callbacks[e].push(t),this}success(e){return this.on("success",e)}done(e){return this.success(e)}fail(e){return this.on("error",e)}complete(e){return this.on("complete",e)}always(e){return this.complete(e)}then(e,t){return this.completed?t&&this.error?t(this.error):e(this.data):(this.success(n=>e(n)),t&&this.fail(t)),this}catch(e){return this.error?(e(this.error),this):this.on("error",t=>e(t))}finally(e){return this.completed?(e(),this):this.complete(()=>e())}abort(e){return this.completed?!1:(this._abortError=e,this._controller.abort(),!0)}getResponseHeader(e){var t;return(t=this.response)==null?void 0:t.headers.get(e)}_init(){if(this.completed)return;const{url:e,type:t,data:n,processData:s=!0,contentType:r,crossDomain:o,accepts:a,dataType:l,timeout:c,dataFilter:d,beforeSend:u,success:p,error:g,complete:_,...C}=this.setting;t&&(C.method=t);let x=n;x&&(s&&(x=Vr(x)),C.body=x),o&&(C.mode="cors");const k=C.headers||{};Xu(k,"X-Requested-With","XMLHttpRequest"),r&&Xu(k,"Content-Type",r),C.headers=k,C.signal&&C.signal.addEventListener("abort",()=>{this.abort()});const $=[...this.constructor.globalBeforeSends,u];for(const E of $){if(!E)continue;const z=E.call(this,C);if(z===!1)return;z&&Object.assign(C,z)}p&&this.success(p),g&&this.fail(g),_&&this.complete(_),C.signal=this._controller.signal,this.url=e,this.request=C}_emit(e,...t){this._callbacks[e].forEach(n=>{n.call(this,...t)})}async send(){var d;if(this.completed)return[];this._init();const{timeout:e,dataType:t,accepts:n,dataFilter:s,throws:r,jsonParser:o}=this.setting;e&&(this._timeoutID=window.setTimeout(()=>{this.abort(new Error("timeout"))},e));let a,l,c;try{a=await fetch(this.url,this.request),this.response=a;const{statusText:u}=a;if(a.ok){const p=(d=a.headers.get("Content-Disposition"))==null?void 0:d.startsWith("attachment"),g=p?"blob":t||yy(a.headers.get("Content-Type"),n);p||g==="blob"||g==="file"?c=await a.blob():g==="json"?typeof o=="function"?(c=await a.text(),c=o(c)):c=await a.json():c=await a.text(),this.data=c;const _=(s==null?void 0:s(c,g))??c;this._emit("success",_,u,a)}else throw this.data=await a.text(),new Error(u)}catch(u){this.data===void 0&&c!==void 0&&(this.data=c),l=u;let p=!1;l.name==="AbortError"&&(this._abortError?l=this._abortError:p=!0),this.error=l,p||this._emit("error",l,a==null?void 0:a.statusText,l.message)}if(this._timeoutID&&clearTimeout(this._timeoutID),this._emit("complete",a,a==null?void 0:a.statusText),l&&r)throw l;return[c,l,a]}}xs.globalBeforeSends=[],y.ajax=(i,e)=>{e=e||{},typeof i=="string"?e.url=i:y.extend(e,i);const t=new xs(e);return t.send(),t},y.getJSON=(i,e,t)=>(typeof e=="function"&&(t=e,e=void 0),y.ajax({url:i,data:e,success:t,dataType:"json"})),y.get=(i,e,t,n,s="GET")=>{let r,o;return typeof e=="function"?(r=e,o=void 0):o=e,typeof t=="function"?(r=t,n=void 0):n=t,y.ajax({method:s,url:i,data:o,success:r,dataType:n})},y.post=(i,e,t,n)=>y.get(i,e,t,n,"POST"),y.fn.load=function(i,e,t){typeof e=="function"&&(t=e,e=void 0);const[n,s]=i.split(" ");return y.get(n,e,(r,o,a)=>{s&&(r=y(r).find(s).html()),y(this).html(r).zuiInit(),t==null||t.call(this,r,o,a)},"html"),this};async function mt(i,e=[],t,n,s){const r={throws:!0,dataType:"json"};if(typeof i=="string")r.url=i;else if(typeof i=="object")y.extend(r,i);else if(typeof i=="function"){const l=i.call(n,...e);return l instanceof Promise?await l:l}t&&y.extend(r,typeof t=="function"?t(r):t),r.url&&(r.url=be(r.url,...e));const o=new xs(r);s==null||s(o);const[a]=await o.send();return a}function ml(i){return!!(i&&(typeof i=="string"||typeof i=="object"&&i.url||typeof i=="function"))}y.fetch=mt;function wt(){return y.guid++}function Kr(i,e){if(i===e)return!1;if(i&&e){const t=typeof i,n=typeof e;if(t!==n)return!0;if(t==="object"&&n==="object"){const s=Array.isArray(i),r=Array.isArray(e);if(s!==r)return!0;if(s&&r){if(i.length!==e.length)return!0;for(let l=0;ln instanceof oi?n.value!==t[s]:Kr(n,t[s])))&&(this._value=this._compute(),this._lastDependencies=e.map(n=>n instanceof oi?n.cache:n)),this._value}}function gl(...i){const e=[],t=new Map,n=(s,r)=>{if(Array.isArray(s)&&(r=s[1],s=s[0]),!s.length)return;const o=t.get(s);typeof o=="number"?e[o][1]=!!r:(t.set(s,e.length),e.push([s,!!r]))};return i.forEach(s=>{typeof s=="function"&&(s=s()),Array.isArray(s)?gl(...s).forEach(n):s&&typeof s=="object"?Object.entries(s).forEach(n):typeof s=="string"&&s.split(" ").forEach(r=>n(r,!0))}),e.sort((s,r)=>(t.get(s[0])||0)-(t.get(r[0])||0))}const V=(...i)=>gl(...i).reduce((e,[t,n])=>(n&&e.push(t),e),[]).join(" ");y.classes=V,y.fn.setClass=function(i,...e){return this.each((t,n)=>{const s=y(n);i===!0?s.attr("class",V(s.attr("class"),...e)):s.addClass(V(i,...e))})};const Ai=new WeakMap;function qr(i,e,t){const n=Ai.has(i),s=n?Ai.get(i):{};typeof e=="string"?s[e]=t:e===null?Object.keys(s).forEach(r=>{delete s[r]}):Object.assign(s,e),Object.keys(s).forEach(r=>{s[r]===void 0&&delete s[r]}),Object.keys(s).length?(!n&&i instanceof Element&&Object.assign(s,y(i).dataset(),s),Ai.set(i,s)):Ai.delete(i)}function ks(i,e,t){let n=Ai.get(i)||{};return t&&i instanceof Element&&(n=Object.assign({},y(i).dataset(),n)),e===void 0?n:n[e]}function vy(i){Ai.delete(i)}y.fn.dataset=y.fn.data,y.fn.data=function(...i){const[e,t]=i;return!i.length||i.length===1&&typeof e=="string"?this.length?ks(this[0],e,!0):void 0:this.each((n,s)=>qr(s,e,t))},y.fn.removeData=function(i=null){return this.each((e,t)=>qr(t,i))};function ai(i,...e){return i.includes("RAWJS")&&(i=i.split('"RAWJS<').join("").split('>RAWJS"').join("").split("").join('"').split("").join(` -`)),new Function(`return ${i}`)(...e)}function yl(i,...e){return i.includes("RAWJS")?ai(i,...e):JSON.parse(i)}function _y(i){return JSON.stringify(i,(e,t)=>{if(typeof t=="function")return`RAWJS<${t.toString().split('"').join("").split(` -`).join("")}>RAWJS`})}function Pi(i,e){const t=y(i)[0];if(!t)return;const{prefix:n,getter:s,evalValue:r,json:o=!0,evalArgs:a=[]}={prefix:"z-",...typeof e=="string"?{prefix:e}:e},l=Array.isArray(r)?new Set(r):void 0;return Array.from(t.attributes).reduce((c,d)=>{let{name:u}=d;const{value:p}=d;let g=p;if(u.startsWith(n)){if(u=u.slice(n.length).replace(/-([a-z])/g,_=>_[1].toUpperCase()),s)g=s(u,p);else try{r&&(!l||l.has(u))||r===void 0&&p.includes("RAWJS")?g=ai(p,...a):o&&(g=JSON.parse(p))}catch{}c[u]=g}return c},{})}function vl(i,e,t="z-"){const n=y(i);Object.keys(e).forEach(s=>{let r=e[s];typeof r=="function"&&(r=`RAWJS<${r}>RAWJS`),typeof r!="string"&&(r=JSON.stringify(r)),s=s.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`),n.attr(`${t}${s}`,r)})}function by(...i){var t;const e=i.length;if(!e)return Pi(this);if(e===1){const[n]=i;return typeof n=="string"?(t=Pi(this))==null?void 0:t[n]:(y.isPlainObject(n)&&vl(this,n),this)}return vl(this,{[i[0]]:i[1]}),this}y.fn.z=by,y.fn._attr=y.fn.attr,y.fn.extend({attr(...i){const[e,t]=i;return!i.length||i.length===1&&typeof e=="string"?this._attr.apply(this,i):typeof e=="object"?(e&&Object.keys(e).forEach(n=>{const s=e[n];s===null?this.removeAttr(n):this._attr(n,s)}),this):t===null?this.removeAttr(e):this._attr(e,t)}}),y.Event||(y.Event=(i,e)=>{const[t,...n]=i.split("."),s=new Event(t,{bubbles:!0,cancelable:!0});return s.namespace=n.join("."),s.___ot=t,s.___td=e,s});const li=(i,e)=>new Promise(t=>{const n=window.setTimeout(t,i);e&&e(n)}),Zu={};y.share=Zu;var Gr,ze,ed;I.isValidElement=void 0;var ci,td,nd,_l,bl,wl,Cl,Ss={},id=[],wy=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Yr=Array.isArray;function En(i,e){for(var t in e)i[t]=e[t];return i}function sd(i){i&&i.parentNode&&i.parentNode.removeChild(i)}function b(i,e,t){var n,s,r,o={};for(r in e)r=="key"?n=e[r]:r=="ref"?s=e[r]:o[r]=e[r];if(arguments.length>2&&(o.children=arguments.length>3?Gr.call(arguments,2):t),typeof i=="function"&&i.defaultProps!=null)for(r in i.defaultProps)o[r]===void 0&&(o[r]=i.defaultProps[r]);return Qr(i,o,n,s,null)}function Qr(i,e,t,n,s){var r={type:i,props:e,key:t,ref:n,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:s??++ed,__i:-1,__u:0};return s==null&&ze.vnode!=null&&ze.vnode(r),r}function de(){return{current:null}}function yn(i){return i.children}function pe(i,e){this.props=i,this.context=e}function Li(i,e){if(e==null)return i.__?Li(i.__,i.__i+1):null;for(var t;ee&&ci.sort(_l));Jr.__r=0}function ad(i,e,t,n,s,r,o,a,l,c,d){var u,p,g,_,C,x=n&&n.__k||id,k=e.length;for(t.__d=l,Cy(t,e,x),l=t.__d,u=0;u0?Qr(s.type,s.props,s.key,s.ref?s.ref:null,s.__v):s).__=i,s.__b=i.__b+1,r=null,(a=s.__i=xy(s,t,o,d))!==-1&&(d--,(r=t[a])&&(r.__u|=131072)),r==null||r.__v===null?(a==-1&&u--,typeof s.type!="function"&&(s.__u|=65536)):a!==o&&(a==o-1?u--:a==o+1?u++:(a>o?u--:u++,s.__u|=65536))):s=i.__k[n]=null;if(d)for(n=0;n(l!=null&&!(131072&l.__u)?1:0))for(;o>=0||a=0){if((l=e[o])&&!(131072&l.__u)&&s==l.key&&r===l.type)return o;o--}if(a{!t||typeof t!="object"||Object.keys(t).forEach(n=>{let s=t[n];const r=i[n];s!==r&&(r!==void 0&&(n==="className"||n.endsWith("Class")?s=[r,s]:n==="children"?s=[...Xr(r),...Xr(s)]:typeof r=="object"&&(n==="style"||n.endsWith("Style")||n==="attrs"||n.endsWith("Attrs")||n==="props")&&(s=y.extend(r,s))),i[n]=s)})}),i}function Sl(i){return Object.keys(i).forEach(e=>{i[e]===void 0&&delete i[e]}),i}function fd(i,e=!0){const t=y(i),n=t[0],s="zui-disable-scroll";if(e){if(t.data(s))return;if((t.css("scrollbar-gutter")||"").includes("stable")){t.data(s,{overflow:t.css("overflow")}).css("overflow","hidden");return}const r=n===document.body||t.is("html")?window.innerWidth-document.body.clientWidth:n.offsetWidth-n.clientWidth;if(!r)return;const o=t.css("paddingRight")||"0";t.data(s,{paddingRight:o,overflow:t.css("overflow")}).css({paddingRight:`${r+Number.parseInt(o,10)}px`,overflow:"hidden"})}else{const r=t.data(s);if(!r)return;t.css(r).removeData(s)}}y.fn.disableScroll=function(i=!0){return this.each((e,t)=>{fd(t,i)})},y.fn.enableScroll=function(i=!0){return this.disableScroll(!i)};function Tl(i,e,t){if(!(t.on||"click").split(" ").includes(e.type))return;const n=t.selector?y(e.target).closest(t.selector):i;if(!n.length)return;const s=c=>c===""?!0:c,r=c=>{if(typeof c=="string")try{c=JSON.parse(c)}catch{}return c};if(s(t.once)){if(t.onceCalled)return;i.dataset("once-called",!0)}if(s(t.prevent)&&e.preventDefault(),s(t.stop)&&e.stopPropagation(),s(t.self)&&e.currentTarget!==e.target)return;const o=[["$element",i],["event",e],["options",t],["$target",n]],a=c=>typeof c=="function"?c(...o):y.runJS(c,...o);if(t.if!==void 0&&!a(t.if))return;const l=t.call;if(l){let c;if(typeof l=="string"?c=/^[$A-Z_][0-9A-Z_$.]*$/i.test(l)?Cs(window,l):a(l):c=l,typeof c=="function"){const d=[],u=t.params;t.params=d,typeof u=="string"&&u.length?u[0]==="["?d.push(...r(u)):d.push(...u.split(", ").map(p=>(p=p.trim(),p==="$element"?i:p==="event"?e:p==="options"?t:p.startsWith("$element.")||p.startsWith("event.")||p.startsWith("options.")?a(p):r(p)))):Array.isArray(u)?d.push(...u):d.push(u),c(...d)}}t.do&&a(t.do)}function Ty(i){const e=y(this),t=i.type,n=e.attr("zui-on");if(n){const[o,a]=n.split("~").map(l=>l.trim());o&&o.split(" ").includes(t)&&Tl(e,i,y.extend({on:o},a?a.startsWith("{")?ai(a):{do:a}:Pi(e,{prefix:"data-",evalValue:["call","if","do"]})))}const s=e.attr(`zui-on-${t}`);s&&Tl(e,i,y.extend({on:t},s.startsWith("{")?ai(s):{do:s}));const r=e.attr("data-on");r&&r.split(" ").includes(t)&&Tl(e,i,Pi(e,{prefix:"data-",evalValue:["call","if","do"]}))}function pd(i){y(document).off(".zui.global").on(i.map(e=>`${e}.zui.global`).join(" "),`[zui-on],${i.map(e=>`[zui-on-${e}]`)},[data-on]`,Ty)}y(()=>{pd(["click","change","inited"])});function ui(i,e){if(typeof i=="function")return ui(i(...e||[]));if(typeof i=="number")return[i];let t=i.match(/(\d+)(%|px)?/);return t?[parseInt(t[1]),t[2]]:(t=i.match(/(\d+)\/(\d+)/),t?[100*parseInt(t[1])/parseInt(t[2]),"%"]:[NaN])}function Ve(i,e){if(i==null)return null;const[t,n="px"]=ui(i,e);return Number.isNaN(t)?typeof i=="string"?i:null:`${t}${n}`}async function Ts(i,e){var n,s,r;if(i instanceof Blob){const o=document.createElement("a");return o.href=window.URL.createObjectURL(i),e&&(o.download=decodeURIComponent(e)),o.click(),o.remove(),i}if(i instanceof Response){const o=await i.blob();return e=e||((r=(s=(n=i.headers.get("Content-Disposition"))==null?void 0:n.split(";")[1])==null?void 0:s.split("=")[1])==null?void 0:r.replace(/"/g,"")),Ts(o,e)}const t=await fetch(i);return Ts(t)}class md{constructor(e){this._$target=y(e)}on(...e){return this._$target.on(...e),this}one(...e){return this._$target.one(...e),this}off(...e){return this._$target.off(...e),this}trigger(...e){return this._$target.trigger(...e),this}}const Zt=new md(document);y.bus=Zt,y.on=Zt.on.bind(Zt),y.one=Zt.one.bind(Zt),y.off=Zt.off.bind(Zt),y.trigger=Zt.trigger.bind(Zt);var $y=["Shift","Meta","Alt","Control"],gd=typeof navigator=="object"?navigator.platform:"",yd=/Mac|iPod|iPhone|iPad/.test(gd),Dy=yd?"Meta":"Control",Iy=gd==="Win32"?["Control","Alt"]:yd?["Alt"]:[];function $l(i,e){return typeof i.getModifierState=="function"&&(i.getModifierState(e)||Iy.includes(e)&&i.getModifierState("AltGraph"))}function Ny(i){return i.trim().split(" ").map(function(e){var t=e.split(/\b\+/),n=t.pop();return[t=t.map(function(s){return s==="$mod"?Dy:s}),n]})}function vd(i,e){var t;e===void 0&&(e={});var n=(t=e.timeout)!=null?t:1e3,s=Object.keys(i).map(function(a){return[Ny(a),i[a]]}),r=new Map,o=null;return function(a){a instanceof KeyboardEvent&&(s.forEach(function(l){var c=l[0],d=l[1],u=r.get(c)||c;(function(p,g){return!(g[1].toUpperCase()!==p.key.toUpperCase()&&g[1]!==p.code||g[0].find(function(_){return!$l(p,_)})||$y.find(function(_){return!g[0].includes(_)&&g[1]!==_&&$l(p,_)}))})(a,u[0])?u.length>1?r.set(c,u.slice(1)):(r.delete(c),d(a)):$l(a,a.key)||r.delete(c)}),o&&clearTimeout(o),o=setTimeout(r.clear.bind(r),n))}}function My(i,e,t){var n;t===void 0&&(t={});var s=(n=t.event)!=null?n:"keydown",r=vd(e,t);return i.addEventListener(s,r),function(){i.removeEventListener(s,r)}}function Dl(i,e={}){if(!i)return;const t=Object.keys(e).reduce((n,s)=>(e[s].optional||(n[s]={...e[s]}),n),{});return Object.keys(i).forEach(n=>{const s=i[n];s?s===!0?e[n]&&(t[n]={...e[n]}):t[n]=s:delete t[n]}),Object.keys(t).reduce((n,s)=>{const{keys:r,handler:o}=t[s];return typeof r=="string"?n[r]=o:r.forEach(a=>{n[a]=o}),n},{})}function Il(i,e,t){const{timeout:n,event:s="keydown",scope:r,when:o}=t||{},a=vd(e,{timeout:n}),l=`.zui.hotkeys${r?`.${r}`:""}`,c="zui-hotkeys-composing";return y(i).on(`${s}${l}`,function(d){o&&o(d)===!1||y(d.target).data(c)||a(d)}).on(`compositionstart${l}`,d=>{y(d.target).data(c,!0)}).on(`compositionend${l}`,d=>{y(d.target).removeData(c)})}function Nl(i,e){return y(i).off(`.zui.hotkeys${e?`.${e}`:""}`)}const Ey=My;y.fn.hotkeys=function(i,e){return Il(this,i,e)},y.fn.unbindHotkeys=function(i){return Nl(this,i)},y.hotkeys=function(i,e){Il(window,i,e)},y.unbindHotkeys=function(i){Nl(window,i)};function eo(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement}async function _d(i){(typeof i=="string"||i instanceof Element||i instanceof y)&&(i={target:i});const{target:e,onError:t,onSuccess:n,afterExit:s,afterEnter:r}=i,o=y(e),a=o[0];if(!a)return;const l=a.requestFullscreen||a.webkitRequestFullscreen||a.mozRequestFullScreen;if(!l){t==null||t.call(a,new Error("[ZUI] The browser does not support full screen feature."));return}try{await l.call(a),n==null||n.call(a),y(a).off(".zui.fullscreen"),s&&o.on("exitFullscreen.zui.fullscreen",s),r&&o.on("enterFullscreen.zui.fullscreen",r)}catch(c){t==null||t.call(a,c)}document.zuiBindFullscreenChange||(document.zuiBindFullscreenChange=!0,y(document).on("fullscreenchange.zui webkitfullscreenchange.zui mozfullscreenchange.zui",c=>{const d=eo();let u=d;d?y(d).addClass("is-in-fullscreen"):(u=y(document).find(".is-in-fullscreen")[0]||document,y(u).removeClass("is-in-fullscreen")),y("body").toggleClass("has-in-fullscreen",!!d);const p={event:c,target:u,fullscreenElement:d};y(u).trigger(d?"enterFullscreen":"exitFullscreen",p).trigger("toggleFullscreen",p)}))}async function Ml(i){const e=eo();return i===!1&&!!e===i?i:e?(document.exitFullscreen(),!1):(await _d(i),!0)}y.fn.fullscreen=function(i){return Ml({target:this,...i})},y.getFullscreenElement=eo,y.toggleFullscreen=Ml;function An(i){return!i||i.parentNode===document?!1:i.parentNode?An(i.parentNode):!0}y.isDetached=An,y.fn.isDetached=function(){const i=this[0];return!i||An(i)};const di=class fg{constructor(e,t){var _;this._inited=!1,this._autoDestory=0,this._destroyed=!1;const{KEY:n,DATA_KEY:s,MULTI_INSTANCE:r,NAME:o,ATTR_KEY:a,ALL:l,TYPED_ALL:c}=this.constructor;if(!o)throw new Error('[ZUI] The component must have a "NAME" static property.');const d=y(e);if(d.data(n)&&!r)throw new Error(`[ZUI] The component "${o}" has been initialized on element.`);const u=d[0],p=wt();this._gid=p,this._element=u,this.resetOptions(t),this._key=this.options.key??`__${p}`;let g=l.get(u);if(g?g.add(this):(g=new Set([this]),l.set(u,g)),c.has(o)?c.get(o).add(this):c.set(o,new Set([this])),d.data(n,this).attr(a,"").attr(s,`${p}`).attr("z-use",[...new Set([...g].map(C=>C.constructor.NAME))].join(",")),r){const C=`${n}:ALL`;let x=d.data(C);x||(x=new Map,d.data(C,x)),x.set(this._key,this)}this.init(),(_=this.options.$onCreate)==null||_.call(this),requestAnimationFrame(async()=>{var C;this._inited=!0,await this.afterInit(),this.emit("inited",this.options),(C=this.options.$onInited)==null||C.call(this)})}static get ZUI(){return this.NAME.replace(/(^[A-Z]+)/,e=>e.toLowerCase())}static get KEY(){return`zui.${this.NAME}`}static get NAMESPACE(){return`.zui.${this.ZUI}`}static get DATA_KEY(){return`data-zui-${this.NAME}`}static get ATTR_KEY(){return`z-use-${this.NAME}`}static get SELECTOR(){return`[${this.DATA_KEY}]`}get inited(){return this._inited}get destroyed(){return this._destroyed}get element(){return this._element}get key(){return this._key}get options(){return this._options}get gid(){return this._gid}get $element(){return y(this.element)}get $emitter(){return this.$element}get i18nData(){return[this.options.i18n,this.constructor.i18n]}init(){}afterInit(){}render(e,t){this.setOptions(e,t)}destroy(){var g;const{KEY:e,DATA_KEY:t,ALL:n,TYPED_ALL:s,NAME:r,MULTI_INSTANCE:o,ATTR_KEY:a}=this.constructor,{$element:l,element:c}=this;if(this.emit("destroyed"),this._destroyed=!0,l.off(this.namespace).removeData(e).removeAttr(a).removeAttr(t),o){const _=this.$element.data(`${e}:ALL`);if(_)if(_.delete(this._key),_.size===0)this.$element.removeData(`${e}:ALL`);else{const C=_.values().next().value;l.data(e,C).attr(t,String(C==null?void 0:C.gid))}}const d=n.get(c);d&&(d.delete(this),d.size===0&&n.delete(c));const u=s.get(r);u&&(u.delete(this),u.size===0&&s.delete(r));const p=n.get(c);p!=null&&p.size?l.attr("z-use",[...new Set([...p].map(_=>_.constructor.NAME))].join(",")):l.removeAttr("z-use"),(g=this.options.$onDestroy)==null||g.call(this)}autoDestroy(e=100){this._autoDestory&&clearTimeout(this._autoDestory),this._autoDestory=window.setTimeout(()=>{this._autoDestory=0,An(this.element)&&this.destroy()},e)}setOptions(e,t){if(t){const n={...this.constructor.DEFAULT,...(e==null?void 0:e.$optionsFromDataset)!==!1?this.$element.dataset():{},...e},{$options:s}=n;if(s){const r=typeof s=="function"?s.call(this,this.element,n):s;r&&y.extend(n,r),delete n.$options}this._options=n}else e&&y.extend(this._options,e);return this._options}resetOptions(e){return this.setOptions(e,!0)}emit(e,...t){const n=y.Event(e);return n.__src=this,this.$emitter.trigger(n,[this,...t]),n}on(e,t,n){const s=this;this.$element[n!=null&&n.once?"one":"on"](this._wrapEvent(e),function(r,o){(!r.__src||r.__src===s)&&t.call(this,r,o)})}one(e,t){this.on(e,t,{once:!0})}off(e){this.$element.off(this._wrapEvent(e))}i18n(e,t,n){const{i18nData:s}=this;return Ne(s,e,t,n,this.options.lang,this.constructor.NAME)??Ne(s,e,t,n,this.options.lang)??`{i18n:${e}}`}get namespace(){return`${this.constructor.NAMESPACE}.${this._key}`}_wrapEvent(e){return e.split(" ").map(t=>t.includes(".")?t:`${t}${this.namespace}`).join(" ")}static get(e,t){const n=y(e);if(this.MULTI_INSTANCE&&t!==void 0){const s=n.data(`${this.KEY}:ALL`);return s?s.get(t):void 0}return n.data(this.KEY)}static isValid(e){return!0}static ensure(e,t){const n=this.get(e,t==null?void 0:t.key);if(n){if(this.isValid(n))return t&&n.setOptions(t),n;n.destroy()}return new this(e,t)}static getAll(e,t){var l;const{SELECTOR:n,ALL:s,TYPED_ALL:r}=this,o=[],a=c=>{c instanceof this&&(!t||t(c)!==!1)&&o.push(c)};return e?y(e).find(n).each((c,d)=>{var u;(u=s.get(d))==null||u.forEach(a)}):this!==fg?(l=r.get(this.NAME))==null||l.forEach(a):s.forEach(c=>{c.forEach(a)}),o.sort((c,d)=>c.gid-d.gid)}static query(e,t,n){return e===void 0?this.getAll(void 0,n).pop():this.get(y(e).closest(this.SELECTOR),t)}static defineFn(e){let t=e||this.ZUI;y.fn[t]&&(t=`zui${this.NAME}`);const n=this;y.fn.extend({[t](s,...r){const o=typeof s=="object"?s:void 0,a=typeof s=="string"?s:void 0;let l;return this.each((c,d)=>{let u=n.get(d);if(u)o&&u.render(o);else{if(a)return;u=new n(d,o)}if(a){let p=u[a],g=u;p===void 0&&(g=u.$,p=g[a]),typeof p=="function"?l=p.call(g,...r):l=p}}),l!==void 0?l:this}})}static register(e,t){var s,r;e=e||this,t=(t??e.NAME).toLowerCase(),this.map.set(t,e);const n=(r=(s=e.toggle)==null?void 0:s.name)==null?void 0:r.toLowerCase();n&&n!==t&&this.toggleMap.set(n,e)}};di.DEFAULT={},di.MULTI_INSTANCE=!1,di.ALL=new Map,di.TYPED_ALL=new Map,di.map=new Map,di.toggleMap=new Map;let je=di;function $s(i){return je.map.get(i.toLowerCase())}function to(i,e,t={}){let n=$s(i);if(n||(n=El(i)),!n)return null;const{$update:s,...r}=t;if(!n.MULTI_INSTANCE){const o=n.get(e);if(o)return s&&o.render(r,s==="reset"),o}return new n(e,r)}function Ay(i,e,t={}){requestAnimationFrame(()=>to(i,e,t))}function bd(i,e){je.register(i,e)}function El(i){const{zui:e}=window;if(e){i=i==null?void 0:i.toLowerCase();for(const t in e){const n=t.toLowerCase()===i;if(i&&!n)continue;const s=e[t];if(!(typeof s!="function"||!s.NAME||!s.ZUI)&&(je.map.has(t.toLowerCase())||bd(s),n))return s}}}function Py(i){var e;i?(e=$s(i))==null||e.defineFn():window._zuiDefined||(El(),je.map.forEach(t=>{t.defineFn()}),Object.assign(window,{_zuiDefined:!0}))}function Ly(i,e={}){const t=y(i);let n=t.attr("zui-create");const{update:s,onCreate:r}=e,o=(a,l)=>{if(l={$update:s,$optionsFromDataset:!1,...l},r){const d=r(a,l);if(d===!1)return;d&&(l=d)}const c=l.$lib;if(c){delete l.$lib,y.getLib(c).then(()=>to(a,i,l));return}Ay(a,i,l)};if(typeof n=="string"){n=n.trim();const a=n.length?n.split(",").map(d=>d.trim()):[],l=Pi(i,{prefix:"zui-create-",evalValue:!0}),c=Object.keys(l);if(!c.length&&a.length===1)o(a[0],t.dataset());else{const d=new Set;[...a,...c].forEach(u=>{if(d.has(u))return;const p=l[u];o(u,p),delete l[u],d.add(u)})}}else{const a=t.dataset(),l=a==null?void 0:a.zui;if(!l)return;console.warn("[ZUI] create component instance with [data-zui] is deprecated, use [zui-create] instead.",{element:i,options:e}),delete a.zui,o(l,a)}}function Ry(){y(document).on("click.zui.toggle mouseenter.zui.toggle","[data-toggle],[zui-toggle]",function(i){const e=y(this),t=e.dataset("toggle")||e.attr("zui-toggle");if(!t)return;const n=je.toggleMap.get(t)||$s(t),s=n==null?void 0:n.toggle;if(!s)return;const{trigger:r="click",skip:o="[disabled],.disabled",check:a}=s,l=i.type==="mouseover"?"hover":"click";if(!r.includes(l)||a&&!a.call(n,this,l,i)||o&&e.is(o))return;const{onGet:c,onCreate:d,setOptions:u=!0,getOptions:p,prevent:g=!0,handler:_,onToggle:C,convertHref:x}=s;let k=e.dataset();const $=e.attr(`zui-toggle-${t}`);if($&&(k=y.extend(k,ai($))),x&&e.is("a")){const z=e.attr("href");if(z){const H=x===!0?{selector:"target",url:"url"}:x;"#.".includes(z[0])?H.selector&&k[H.selector]===void 0&&(k[H.selector]=z):H.url&&k[H.url]===void 0&&(k[H.url]=z)}}if(p&&(k=p.call(n,this,k,i)),_){_.call(n,this,k,l,i),g&&i.preventDefault();return}let E=c?c.call(n,this):n.get(this);if(E)u&&E.setOptions(k);else{const z=d?d.call(n,this,i,k):new n(this,k);if(!z)return;E=z}if(C){if(C.call(n,E,this,i)===!1)return}else{const{shown:z,show:H,hide:Y,toggle:G}=E;let X;if(G?X=G:H&&Y?z?X=Y:X=H:H&&(X=H),X)X.call(E);else return}g&&i.preventDefault()})}function Oy(i,e){const t=ks(i),n=[];return Object.keys(t).forEach(s=>{if(!s.startsWith("zui."))return;const r=t[s];(e==null?void 0:e(r,s))!==!1&&n.push(t[s])}),n}let no=0;function wd(i=100){if(no&&clearTimeout(no),i){no=window.setTimeout(()=>wd(0),i);return}no=0,je.ALL.forEach(e=>{e.forEach(t=>t.autoDestroy())})}function zy(){if(!document.body||ks(document.body,"_autoDestoryMob"))return;const i=new MutationObserver(e=>{let t=!1;for(const n of e)if(n.removedNodes.length){t=!0;break}t&&wd()});i.observe(document.body,{childList:!0,subtree:!0}),qr(document.body,"_autoDestoryMob",i)}function Al(i,e){const t=y(i);t.find("[zui-create],[data-zui]").each(function(){var n;((n=e==null?void 0:e.beforeCreate)==null?void 0:n.call(e,this))!==!1&&Ly(this,e)}),t.find("[zui-init]").each(function(){this.hasAttribute("z-zui-inited")||(this.setAttribute("z-zui-inited",""),y.runJS(this.getAttribute("zui-init"),["$element",y(this)]))}),t.find(".hide-before-init").removeClass("invisible hidden opacity-0"),t.find(".scroll-into-view").scrollIntoView(),t.find('[data-on="inited"],[zui-on-inited]').each((n,s)=>{const r=y(s);r.zui()||r.trigger("inited")}),e!=null&&e.runJS&&t.runJS()}y.fn.zuiInit=function(i){return Al(this,i),this},y.fn.zui=function(i,e){const t=this[0];if(!t)return;if(typeof i!="string"){const s={};let r;return Oy(t,(o,a)=>{s[a]=o,(!r||r.gid1?t[0]:void 0,s=t[t.length>1?1:0],r=y(this).zui(n),o=r==null?void 0:r[s];typeof o=="function"&&o.apply(r,e)}),this},y(()=>{y("body").zuiInit({update:!0}),Ry(),zy()});class io extends je{get $targets(){const{$element:e}=this,{targets:t}=this.options;return t?e.find(t):e}_handleScroll(e,t,n){const{offset:s=1}=this.options,r=this.$targets,o=e.getBoundingClientRect(),{scrollTop:a,scrollLeft:l}=e;r.each((c,d)=>{const u=d.getBoundingClientRect(),p=t==="top"&&a>0&&u.top<=o.top+s||t==="bottom"&&u.bottom>=o.bottom-s||t==="left"&&l>0&&u.left<=o.left+s||t==="right"&&l{this._raf&&cancelAnimationFrame(this._raf),this._raf=requestAnimationFrame(()=>{this._raf=0,this._handleScroll(l,t,s)})};this._scrollListener=c,l.addEventListener("scroll",c)}this._container=l,requestAnimationFrame(()=>{this._handleScroll(l,t,s)})}else this._ob=new IntersectionObserver(l=>{l.forEach(c=>{c.target.classList.toggle(s,c.intersectionRatiothis._ob.observe(c))}destroy(){var e;(e=this._ob)==null||e.disconnect(),this._container&&(this._container.removeEventListener("scroll",this._scrollListener),this._raf&&cancelAnimationFrame(this._raf))}}io.NAME="Sticky";const Ri=24*60*60*1e3,Be=i=>i===void 0?new Date:(i instanceof Date||(typeof i=="string"&&(i=i.trim(),/^\d+$/.test(i)&&(i=Number.parseInt(i,10))),typeof i=="number"&&i<1e10&&(i*=1e3),i=new Date(i)),i),Cd=(i,e,t="day")=>{if(typeof e=="string"){const n=Number.parseInt(e,10);t=e.replace(n.toString(),""),e=n}return i=new Date(Be(i).getTime()),t==="month"?i.setMonth(i.getMonth()+e):t==="year"?i.setFullYear(i.getFullYear()+e):t==="week"?i.setDate(i.getDate()+e*7):t==="hour"?i.setHours(i.getHours()+e):t==="minute"?i.setMinutes(i.getMinutes()+e):t==="second"?i.setSeconds(i.getSeconds()+e):i.setDate(i.getDate()+e),i},Pn=(i,e=new Date)=>Be(i).toDateString()===Be(e).toDateString(),Ds=(i,e=new Date)=>Be(i).getFullYear()===Be(e).getFullYear(),Pl=(i,e=new Date)=>(i=Be(i),e=Be(e),i.getFullYear()===e.getFullYear()&&i.getMonth()===e.getMonth()),Fy=(i,e=new Date)=>{i=Be(i),e=Be(e);const t=1e3*60*60*24,n=Math.floor(i.getTime()/t),s=Math.floor(e.getTime()/t);return Math.floor((n+4)/7)===Math.floor((s+4)/7)},jy=(i,e)=>Pn(Be(e),i),By=(i,e)=>Pn(Be(e).getTime()-Ri,i),Hy=(i,e)=>Pn(Be(e).getTime()+Ri,i),Ll=i=>i!=null&&!isNaN(Be(i).getTime()),rt=(i,e="yyyy-MM-dd hh:mm",t="")=>{if(i=Be(i),!Ll(i))return t;if(typeof e=="function")return e(i);const n={"M+":i.getMonth()+1,"d+":i.getDate(),"h+":i.getHours(),"H+":i.getHours()%12,"m+":i.getMinutes(),"s+":i.getSeconds(),"S+":i.getMilliseconds()};return/(y+)/i.test(e)&&(e.includes("[yyyy-]")&&(e=e.replace("[yyyy-]",Ds(i)?"":"yyyy-")),e=e.replace(RegExp.$1,`${i.getFullYear()}`.substring(4-RegExp.$1.length))),Object.keys(n).forEach(s=>{if(new RegExp(`(${s})`).test(e)){const r=`${n[s]}`;e=e.replace(RegExp.$1,RegExp.$1.length===1?r:`00${r}`.substring(r.length))}}),e},Wy=(i,e,t)=>{const n={full:"yyyy-M-d",month:"M-d",day:"d",str:"{0} ~ {1}",...t},s=rt(i,Ds(i)?n.month:n.full);if(Pn(i,e))return s;const r=rt(e,Ds(i,e)?Pl(i,e)?n.day:n.month:n.full);return n.str.replace("{0}",s).replace("{1}",r)};function Rl(i){let e=0;if(typeof i!="string"&&(i=String(i)),i&&i.length)for(let t=0;t{try{a.includes("%")&&(a=decodeURIComponent(a)),a=JSON.parse(a)}catch{}return[o,a]})),params:n.map(o=>{if(o!=="undefined"){if(o==="null")return null;try{return o.includes("%")&&(o=decodeURIComponent(o)),JSON.parse(o)}catch{return o}}})}}function xd(i){if(Array.isArray(i))return{commands:i.map(so).filter(Boolean)};if(typeof i=="object")return i;i=i.replace(/^#!?/,"");const e=i.includes(">"),t=i.split(e?">":"|").map(so);return{async:e,commands:t.filter(Boolean)}}function Ol(i,e,t){if(typeof i=="string"&&(i=so(i)),!i)return;const{execute:n,event:s,scope:r}=e;if(!(r&&i.scope&&i.scope!==r))return n({name:i.name,options:{...e.options,...i.options},event:s,scope:i.scope,prevResult:t},i.params)}async function kd(i,e){const{async:t,commands:n}=xd(i);if(!n.length)return[];const{signal:s}=e;if(t){const o=[];let a;for(const l of n){if(!(s!=null&&s.aborted))break;a=await Ol(l,e,a),s!=null&&s.aborted&&(a=void 0),o.push(a)}return o}return await Promise.all(n.map(o=>{if(!(s!=null&&s.aborted))return Ol(o,e)}))}const Oi="zui.commands",zi="z-commands",Uy="zui-commands-proxy",Sd="zui-command";function ro(i,e){typeof e=="string"?e={scope:e}:typeof e=="function"&&(e={onCommand:e});const{scope:t="",events:n="click"}=e??{},s=y(i),r=(s.attr(zi)||"").split(",");t&&!r.includes(t)&&r.push(t),s.attr(zi,r.join(",")).data(Oi,{[t]:{...e,scope:t,events:n,gid:wt()},...s.data(Oi)})}function oo(i,e=!0){const t=y(i);if(e===!0)t.removeAttr(zi),t.removeData(Oi);else if(e.length){const n=t.data(Oi)||{};e.split(",").forEach(r=>{delete n[r]});const s=Object.keys(n);s.length?t.attr(zi,s.join(",")).data(Oi,ro):oo(t,!0)}}function Td(i,e){let t=i.closest(`[${zi}]`);if(!t.length){const o=i.closest(`[${Uy}]`);o.length&&(t=y(o.data("zui.commandProxy")||o.attr("COMMAND_PROXY_ATTR")).closest(`[${zi}]`))}if(!t.length)return;const n=t.data(Oi)||{},s=Object.values(n).sort((o,a)=>a.gid-o.gid);let r;return e!=null&&e.length?(r=s.find(o=>o.scope===e),r||(r=s.find(o=>{var a;return!((a=o.scope)!=null&&a.length)&&!o.scoped})),r):(r=s.find(o=>{var a;return!((a=o.scope)!=null&&a.length)&&!o.scoped}),r||(r=s.find(o=>!o.scoped)),r?r.element=t[0]:r=Td(i.parent(),e),r)}function Vy(i){if(!i.currentTarget)return;const e=y(i.currentTarget);if(e.closest(".disabled,[disabled]").length)return;const t=e.attr(Sd)||(e.is('a[href^="#!"]')?e.attr("href"):"");if(!t)return;const n=new AbortController,s=()=>n.abort();kd(t,{signal:n.signal,execute:(r,o)=>{const{scope:a,name:l}=r,c={...r,abort:s};let d;const u=Td(e,a);if(u){c.element=u.element;const g=(u.commands?u.commands[`${a}~${l}`]||u.commands[l]:null)||u.onCommand;if(g&&(d=g(c,o),i.commandHandled))return d}const p=[c,o];if(e.trigger("command",p).trigger(`command:${a?`${l}.${a}`:l}`,p),a&&e.trigger(`command:.${a}`,p),i.commandHandled)return d;if(a==="event"){l==="stop"?i.stopPropagation():l==="prevent"?i.preventDefault():Mn(i,l,o);return}return a==="window"?Mn(window,l,o):a==="zui"?Mn(window.zui,l,o):a==="target"?Mn(e[0],l,o):a==="$target"?Mn(e,l,o):a==="$"?Mn(y,l,o):d},event:i})}y.fn.command=function(i,e){return this.on(`command:${i}`,e)},y.fn.offCommand=function(i,e){return this.off(`command:${i}`,e)},y.fn.commands=function(i){return this.each((e,t)=>ro(t,i)),this},y.fn.unbindCommands=function(i){return this.each((e,t)=>oo(t,i)),this},y(()=>{y(document).on("click.zui.command",`[${Sd}],a[href^="#!"]`,Vy)});function Is(i,e,t=!1){var s;const n=y(i);if(e!==void 0){if(typeof e=="string"&&e.length){const r=`zui-runjs-${wt()}`;n.append(` + + +

禅道全连接测试

+
+ $group):?> +
+

+ $urlList):?> +
+

+
    + $url):?> +
  • + +
+
+ +
+ +
+ From b28fab84b0cb4b4f8fd850a09df69a81cc841b41 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 7 Mar 2025 13:33:28 +0800 Subject: [PATCH 317/655] * [bug#59948] Query all templates when browse template. --- module/doc/control.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index bb2e372450..0f19cc40f0 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -498,15 +498,16 @@ class doc extends control public function browseTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'home') { $this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod; - $modules = $this->doc->getTemplateModules($libID); - $modules = array_column($modules, 'fullName', 'id'); - if($mode == 'create' && empty($modules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst))); + $libModules = $this->doc->getTemplateModules($libID); + $libModules = array_column($libModules, 'fullName', 'id'); + if($mode == 'create' && empty($libModules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst))); $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); - $templateList = $this->doc->getDocTemplateList($libID, $type, $orderBy, $pager); + $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy, $pager); $templateList = $this->doc->filterPrivDocs($templateList, 'template'); - foreach($templateList as $template) $template->moduleName = zget($modules, $template->module); + $allModules = $this->doc->getTemplateModules(); + foreach($templateList as $template) $template->moduleName = zget($allModules, $template->module); $this->view->title = $this->lang->doc->template; $this->view->libID = $libID; @@ -517,7 +518,7 @@ class doc extends control $this->view->recPerPage = $recPerPage; $this->view->pageID = $pageID; $this->view->mode = $mode; - $this->view->hasModules = count($modules) ? true : false; + $this->view->hasModules = count($libModules) ? true : false; $this->display(); } From ff4768d0a2672e8906557916f7cf19f5835ced0e Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 7 Mar 2025 14:50:45 +0800 Subject: [PATCH 318/655] * [bug#59697] Hidden the button of edit and delete when has no priv. --- lib/zin/wg/docapp/js/v1.js | 2 ++ module/doc/js/browsetemplate.ui.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index de06ee2794..c4294262e4 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -1744,6 +1744,8 @@ function getTableOptions(options, info) if(col.name === 'actions' && col.actionsMap) { if(!canModify) col.actions = []; + col.actions = col.actions.filter(action => hasPriv(action == 'move' ? 'moveDoc' : action)); + const actionHints = {edit: lang.editDoc, move: lang.moveDoc, delete: lang.deleteDoc}; const privMap = {edit: hasPriv('edit'), move: hasPriv('moveDoc'), delete: hasPriv('delete')}; $.each(col.actionsMap, (key, value) => diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 682901cbf4..b134ba3358 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -48,7 +48,7 @@ function getTableOptions(options, info) { if(col.name === 'actions' && col.actionsMap) { - col.actions = col.actions.filter(action => action !== 'move'); + col.actions = col.actions.filter(action => (action !== 'move' && docAppHasPriv(action))); delete col.actionsMap.move; const privMap = {edit: docAppHasPriv('edit'), delete: docAppHasPriv('delete')}; From b3d860bb44dcd511f8bb190d46e7c9eaab45c615 Mon Sep 17 00:00:00 2001 From: daitingting Date: Mon, 10 Mar 2025 06:37:16 +0000 Subject: [PATCH 319/655] * [bug#60329,done,0.5h] Check project release browse privilege. --- module/doc/config.php | 2 +- module/doc/ui/app.html.php | 27 ++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/module/doc/config.php b/module/doc/config.php index a4644436ea..f9ad512bb7 100644 --- a/module/doc/config.php +++ b/module/doc/config.php @@ -261,7 +261,7 @@ $config->doc->zentaoList['bug']['subMenu'][] = array('key' => 'planBug', 'nam $config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productPlan', 'name' => $lang->doc->zentaoList['productPlan'] . $lang->doc->list, 'icon' => 'productplan', 'module' => 'productplan', 'method' => 'browse', 'params' => 'productID=0&branch=&browseType=undone&queryID=0&orderBy=begin_desc&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'productplanBrowse'); $config->doc->zentaoList['more']['subMenu'][] = array('key' => 'productRelease', 'name' => $lang->doc->zentaoList['productRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'release', 'method' => 'browse', 'params' => 'productID=0&branch=all&type=all&orderBy=¶m=0&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'releaseBrowse'); -$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'projectRelease', 'name' => $lang->doc->zentaoList['projectRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'projectRelease', 'method' => 'browse', 'params' => 'projectID=0&executionID=0&type=all&orderBy=&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'releaseBrowse'); +$config->doc->zentaoList['more']['subMenu'][] = array('key' => 'projectRelease', 'name' => $lang->doc->zentaoList['projectRelease'] . $lang->doc->list, 'icon' => 'send', 'module' => 'projectRelease', 'method' => 'browse', 'params' => 'projectID=0&executionID=0&type=all&orderBy=&recTotal=0&recPerPage=20&pageID=1&from=doc', 'priv' => 'projectReleaseBrowse'); $config->doc->zentaoList['more']['subMenu'][] = array('key' => 'ER', 'name' => $lang->doc->zentaoList['ER'] . $lang->doc->list, 'icon' => 'lightbulb-alt', 'module' => 'product', 'method' => 'browse', 'params' => 'productID=0&branch=all&browseType=¶m=0&storyType=epic&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID=0&from=doc', 'priv' => 'epicBrowse'); $config->doc->zentaoList['more']['subMenu'][] = array('key' => 'UR', 'name' => $lang->doc->zentaoList['UR'] . $lang->doc->list, 'icon' => 'customer', 'module' => 'product', 'method' => 'browse', 'params' => 'productID=0&branch=all&browseType=¶m=0&storyType=requirement&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID=0&from=doc', 'priv' => 'requirementBrowse'); diff --git a/module/doc/ui/app.html.php b/module/doc/ui/app.html.php index cf9695857d..d7e052c4f7 100644 --- a/module/doc/ui/app.html.php +++ b/module/doc/ui/app.html.php @@ -70,19 +70,20 @@ $privs['editChapter'] = hasPriv('doc', 'editChapter'); $privs['deleteChapter'] = hasPriv('doc', 'deleteChapter'); $privs['sortChapter'] = hasPriv('doc', 'sortChapter'); -$privs['productStory'] = hasPriv('product', 'browse'); -$privs['projectStory'] = hasPriv('projectstory', 'story'); -$privs['executionStory'] = hasPriv('execution', 'story'); -$privs['productCase'] = hasPriv('testcase', 'browse'); -$privs['caselibBrowse'] = hasPriv('caselib', 'browse'); -$privs['productBug'] = hasPriv('bug', 'browse'); -$privs['taskBrowse'] = hasPriv('execution', 'task'); -$privs['productplanBrowse'] = hasPriv('productplan', 'browse'); -$privs['releaseBrowse'] = hasPriv('release', 'browse'); -$privs['feedbackBrowse'] = hasPriv('feedback', 'admin'); -$privs['ticketBrowse'] = hasPriv('ticket', 'browse'); -$privs['requirementBrowse'] = hasPriv('product', 'requirement'); -$privs['epicBrowse'] = hasPriv('product', 'epic'); +$privs['productStory'] = hasPriv('product', 'browse'); +$privs['projectStory'] = hasPriv('projectstory', 'story'); +$privs['executionStory'] = hasPriv('execution', 'story'); +$privs['productCase'] = hasPriv('testcase', 'browse'); +$privs['caselibBrowse'] = hasPriv('caselib', 'browse'); +$privs['productBug'] = hasPriv('bug', 'browse'); +$privs['taskBrowse'] = hasPriv('execution', 'task'); +$privs['productplanBrowse'] = hasPriv('productplan', 'browse'); +$privs['releaseBrowse'] = hasPriv('release', 'browse'); +$privs['projectReleaseBrowse'] = hasPriv('projectRelease', 'browse'); +$privs['feedbackBrowse'] = hasPriv('feedback', 'admin'); +$privs['ticketBrowse'] = hasPriv('ticket', 'browse'); +$privs['requirementBrowse'] = hasPriv('product', 'requirement'); +$privs['epicBrowse'] = hasPriv('product', 'epic'); $privs['storyView'] = hasPriv('story', 'view'); $privs['taskView'] = hasPriv('task', 'view'); From 66f79fccdae52bc64b071b43504b08330d57f8a6 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 11 Mar 2025 06:00:29 +0000 Subject: [PATCH 320/655] [bug#60231,done,1h] Remove title link. --- module/release/js/browse.ui.js | 9 ++++++++- module/release/ui/browse.html.php | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/module/release/js/browse.ui.js b/module/release/js/browse.ui.js index 1e84383d3c..61cdd689ff 100644 --- a/module/release/js/browse.ui.js +++ b/module/release/js/browse.ui.js @@ -15,7 +15,14 @@ window.renderCell = function(result, {col, row}) if(!row.data.build.name) return result; let branchLabel = showBranch ? "" + row.data.build.branchName + ' ' : ''; - result.push({html: branchLabel + "" + row.data.build.name + ''}); + if(isFromDoc) + { + result.push({html: branchLabel + row.data.build.name}); + } + else + { + result.push({html: branchLabel + "" + row.data.build.name + ''}); + } return result; } diff --git a/module/release/ui/browse.html.php b/module/release/ui/browse.html.php index b064db3a12..caa232413c 100644 --- a/module/release/ui/browse.html.php +++ b/module/release/ui/browse.html.php @@ -98,6 +98,7 @@ toolbar jsVar('markerTitle', $lang->release->marker); jsVar('showBranch', $showBranch); jsVar('type', $type); +jsVar('isFromDoc', $isFromDoc); $cols = $this->loadModel('datatable')->getSetting('release'); if($showBranch) $cols['branch']['map'] = $branchPairs; From f9178f2aae8dc80ece9388edc916dbc2f1a4348c Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 11 Mar 2025 06:04:32 +0000 Subject: [PATCH 321/655] * [bug#60232,done,2h] Process builds of release. --- module/doc/control.php | 7 +++++ module/doc/js/zentaolist.ui.js | 8 +++++ module/doc/ui/zentaolist.html.php | 4 ++- module/doc/zen.php | 50 +++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index 6e8aad2584..8ce233a99e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -175,6 +175,13 @@ class doc extends control if(strpos(',productStory,ER,UR,planStory,projectStory', $type) !== false) $this->docZen->assignStoryGradeData($type); + if($type == 'productRelease') + { + $children = implode(',', array_column($this->view->data, 'releases')); + $childReleases = $this->loadModel('release')->getListByCondition(explode(',', $children), 0, true); + $this->view->data = $this->docZen->processReleaseListData($this->view->data, $childReleases); + } + $this->display(); } diff --git a/module/doc/js/zentaolist.ui.js b/module/doc/js/zentaolist.ui.js index 58bfcf46d7..1825df4bcf 100644 --- a/module/doc/js/zentaolist.ui.js +++ b/module/doc/js/zentaolist.ui.js @@ -250,3 +250,11 @@ window.renderCell = function(result, info) return result; }; + +window.getCellSpan = function(cell) +{ + if(['id', 'branchName', 'name', 'branch', 'status', 'date', 'desc', 'releasedDate', 'actions', 'system'].includes(cell.col.name) && cell.row.data.rowspan) + { + return {rowSpan: cell.row.data.rowspan}; + } +} diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 5329b5eeeb..e4b7bdadea 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -55,6 +55,8 @@ div set::userMap($users), set::emptyTip($lang->doc->previewTip), set::checkable(false), - set::onRenderCell(jsRaw('window.renderCell')) + set::onRenderCell(jsRaw('window.renderCell')), + $type == 'productRelease' ? set::plugins(array('cellspan')) : null, + $type == 'productRelease' ? set::getCellSpan(jsRaw('window.getCellSpan')) : null ) ); diff --git a/module/doc/zen.php b/module/doc/zen.php index cca7b780f6..8aed8c4b95 100644 --- a/module/doc/zen.php +++ b/module/doc/zen.php @@ -1688,4 +1688,54 @@ class docZen extends doc $this->view->gradeGroup = $gradeGroup; } + + /** + * 处理发布列表展示数据。 + * Process release list display data. + * + * @param array $releaseList + * @param array $childReleases + * @access protected + * @return array + */ + protected function processReleaseListData(array $releaseList, array $childReleases): array + { + $releases = array(); + foreach($releaseList as $release) + { + $release->rowID = $release->id; + $release->rowspan = count($release->builds); + + if(!empty($release->builds)) + { + foreach($release->builds as $build) + { + $releaseInfo = clone $release; + $releaseInfo->build = $build; + + $releases[] = $releaseInfo; + } + } + else + { + $releases[] = $release; + } + if(empty($release->releases)) continue; + + foreach(explode(',', $release->releases) as $childID) + { + if(isset($childReleases[$childID])) + { + $child = clone $childReleases[$childID]; + $child = current($this->processReleaseListData(array($child))); + + $child->rowID = "{$release->id}-{$childID}"; + $child->parent = $release->id; + $releases[$child->rowID] = $child; + } + } + } + + return $releases; + } } From 50d089993337633759e8da91517efaabee8f9aed Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 11 Mar 2025 15:57:29 +0800 Subject: [PATCH 322/655] * [task#139159,doing,1.5h] Add the page of doc-browseReport and doc-browseReportTemplate. --- config/zentaopms.php | 2 +- module/doc/control.php | 24 +++++++++++++++++++++ module/doc/ui/browsereport.html.php | 11 ++++++++++ module/doc/ui/browsereporttemplate.html.php | 11 ++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 module/doc/ui/browsereport.html.php create mode 100644 module/doc/ui/browsereporttemplate.html.php diff --git a/config/zentaopms.php b/config/zentaopms.php index f2f79bb987..15db58d9e7 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -776,7 +776,7 @@ $config->db->sqliteBlacklist = array('sqlite_queue', 'cron'); $config->hasDropmenuApps = array('program', 'project', 'product', 'execution', 'qa', 'admin', 'bi', 'feedback', 'demandpool'); $config->hasBranchMenuModules = array('product', 'story', 'release', 'bug', 'testcase', 'testtask', 'branch', 'tree'); $config->excludeBranchMenu = array('product-dashboard', 'product-view'); -$config->excludeDropmenuList = array('program-browse', 'program-productview', 'program-kanban', 'product-all', 'product-index', 'product-kanban', 'project-kanban', 'execution-all', 'execution-executionkanban', 'project-browse', 'project-batchedit', 'product-batchedit', 'admin-index', 'product-create', 'project-create', 'execution-create', 'program-create', 'execution-batchedit', 'metric-preview', 'metric-browse', 'metric-view', 'metriclib-browse', 'qa-index', 'caselib-create', 'feedback-batchedit', 'feedback-batchclose', 'feedback-showimport', 'dimension-browse', 'dataview-browse', 'dataview-create', 'dataview-query', 'ticket-batchedit', 'ticket-batchfinish', 'ticket-batchactivate', 'file-download'); +$config->excludeDropmenuList = array('program-browse', 'program-productview', 'program-kanban', 'product-all', 'product-index', 'product-kanban', 'project-kanban', 'execution-all', 'execution-executionkanban', 'project-browse', 'project-batchedit', 'product-batchedit', 'admin-index', 'product-create', 'project-create', 'execution-create', 'program-create', 'execution-batchedit', 'metric-preview', 'metric-browse', 'metric-view', 'metriclib-browse', 'qa-index', 'caselib-create', 'feedback-batchedit', 'feedback-batchclose', 'feedback-showimport', 'dimension-browse', 'dataview-browse', 'dataview-create', 'dataview-query', 'ticket-batchedit', 'ticket-batchfinish', 'ticket-batchactivate', 'file-download', 'doc-browsereport', 'doc-browsereporttemplate'); $config->hasSwitcherModules = array('design'); $config->hasSwitcherMethods = array('project-bug', 'project-testcase', 'execution-bug', 'execution-testcase', 'testtask-cases', 'testtask-view', 'testtask-report', 'testtask-groupcase', 'testtask-linkcase'); $config->excludeSwitcherList = array(); diff --git a/module/doc/control.php b/module/doc/control.php index 8ce233a99e..93cefafd63 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -2248,4 +2248,28 @@ class doc extends control $this->view->title = $title; $this->display(); } + + /** + * 报告列表。 + * Report list. + * + * @access public + * @return void + */ + public function browseReport() + { + $this->display(); + } + + /** + * 报告模板列表。 + * Report template list. + * + * @access public + * @return void + */ + public function browseReportTemplate() + { + $this->display(); + } } diff --git a/module/doc/ui/browsereport.html.php b/module/doc/ui/browsereport.html.php new file mode 100644 index 0000000000..0f0fd2feb0 --- /dev/null +++ b/module/doc/ui/browsereport.html.php @@ -0,0 +1,11 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; diff --git a/module/doc/ui/browsereporttemplate.html.php b/module/doc/ui/browsereporttemplate.html.php new file mode 100644 index 0000000000..5ae5ffb2cc --- /dev/null +++ b/module/doc/ui/browsereporttemplate.html.php @@ -0,0 +1,11 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; From 15c483b4b8b3fe6a902166d95fb3f1975dc79c7c Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 12 Mar 2025 14:46:09 +0800 Subject: [PATCH 323/655] * [task#139159,doing,2h] Add the priv for report template. --- module/doc/lang/de.php | 74 +++++++++++++++++---------------- module/doc/lang/en.php | 74 +++++++++++++++++---------------- module/doc/lang/fr.php | 74 +++++++++++++++++---------------- module/doc/lang/zh-cn.php | 74 +++++++++++++++++---------------- module/group/lang/de.php | 1 + module/group/lang/en.php | 1 + module/group/lang/fr.php | 1 + module/group/lang/resource.php | 70 ++++++++++++++++--------------- module/group/lang/zh-cn.php | 1 + module/group/packagemanager.php | 11 +++++ 10 files changed, 204 insertions(+), 177 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index e729e9ab22..09435c2a6f 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -277,42 +277,44 @@ $lang->doc->api = 'API'; $lang->doc->displaySetting = 'Display Settings'; $lang->doc->collectAction = 'Add Favorite'; -$lang->doc->libName = 'Name'; -$lang->doc->libType = 'Kategorie'; -$lang->doc->custom = 'Eigene Dok Bibliothek'; -$lang->doc->customAB = 'Eigene Bibliothek'; -$lang->doc->createLib = 'Create Library'; -$lang->doc->createLibAction = 'Create Library'; -$lang->doc->createSpace = 'Create Space'; -$lang->doc->allLibs = 'Bibliothek'; -$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothek Liste"; -$lang->doc->showFiles = 'Dok Bibliothek'; -$lang->doc->editLib = 'Edit Document Library'; -$lang->doc->editSpaceAction = 'Edit Space'; -$lang->doc->editLibAction = 'Edit Library'; -$lang->doc->deleteSpaceAction = 'Delete Space'; -$lang->doc->deleteLibAction = 'Delete Library'; -$lang->doc->moveLibAction = 'Move Library'; -$lang->doc->moveDocAction = 'Move Document'; -$lang->doc->batchMove = 'Batch Move'; -$lang->doc->batchMoveDocAction = 'Batch Move Document'; -$lang->doc->fixedMenu = 'Im Menü fixieren'; -$lang->doc->removeMenu = 'Vom Menü entfernen'; -$lang->doc->search = 'Suche'; -$lang->doc->allCollections = 'All Collections'; -$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; -$lang->doc->sortLibs = 'Sort Libs'; -$lang->doc->titlePlaceholder = 'Please enter the title'; -$lang->doc->confirm = 'Confirm'; -$lang->doc->docSummary = 'Total: %s.'; -$lang->doc->docCheckedSummary = 'Seleted: %total%.'; -$lang->doc->showDoc = 'Whether to display documents'; -$lang->doc->uploadFile = 'Upload File'; -$lang->doc->uploadDoc = 'Upload Document'; -$lang->doc->uploadFormat = 'Upload Format'; -$lang->doc->editedList = 'File editor'; -$lang->doc->moveTo = 'Move to'; -$lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->libName = 'Name'; +$lang->doc->libType = 'Kategorie'; +$lang->doc->custom = 'Eigene Dok Bibliothek'; +$lang->doc->customAB = 'Eigene Bibliothek'; +$lang->doc->createLib = 'Create Library'; +$lang->doc->createLibAction = 'Create Library'; +$lang->doc->createSpace = 'Create Space'; +$lang->doc->allLibs = 'Bibliothek'; +$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothek Liste"; +$lang->doc->showFiles = 'Dok Bibliothek'; +$lang->doc->editLib = 'Edit Document Library'; +$lang->doc->editSpaceAction = 'Edit Space'; +$lang->doc->editLibAction = 'Edit Library'; +$lang->doc->deleteSpaceAction = 'Delete Space'; +$lang->doc->deleteLibAction = 'Delete Library'; +$lang->doc->moveLibAction = 'Move Library'; +$lang->doc->moveDocAction = 'Move Document'; +$lang->doc->batchMove = 'Batch Move'; +$lang->doc->batchMoveDocAction = 'Batch Move Document'; +$lang->doc->fixedMenu = 'Im Menü fixieren'; +$lang->doc->removeMenu = 'Vom Menü entfernen'; +$lang->doc->search = 'Suche'; +$lang->doc->allCollections = 'All Collections'; +$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; +$lang->doc->sortLibs = 'Sort Libs'; +$lang->doc->titlePlaceholder = 'Please enter the title'; +$lang->doc->confirm = 'Confirm'; +$lang->doc->docSummary = 'Total: %s.'; +$lang->doc->docCheckedSummary = 'Seleted: %total%.'; +$lang->doc->showDoc = 'Whether to display documents'; +$lang->doc->uploadFile = 'Upload File'; +$lang->doc->uploadDoc = 'Upload Document'; +$lang->doc->uploadFormat = 'Upload Format'; +$lang->doc->editedList = 'File editor'; +$lang->doc->moveTo = 'Move to'; +$lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->browseReportTemplate = 'Report Template Home'; +$lang->doc->browseReport = 'Report Home'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 8945ddc702..34e8c25102 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -277,42 +277,44 @@ $lang->doc->api = 'API'; $lang->doc->displaySetting = 'Display Settings'; $lang->doc->collectAction = 'Add Favorite'; -$lang->doc->libName = 'Document Library'; -$lang->doc->libType = 'Category'; -$lang->doc->custom = 'Custom Document Library'; -$lang->doc->customAB = 'Custom Doc Lib'; -$lang->doc->createLib = 'Create Library'; -$lang->doc->createLibAction = 'Create Library'; -$lang->doc->createSpace = 'Create Space'; -$lang->doc->allLibs = 'Library List'; -$lang->doc->objectLibs = "Document View of Library"; -$lang->doc->showFiles = 'Attachments'; -$lang->doc->editLib = 'Edit Document Library'; -$lang->doc->editSpaceAction = 'Edit Space'; -$lang->doc->editLibAction = 'Edit Library'; -$lang->doc->deleteSpaceAction = 'Delete Space'; -$lang->doc->deleteLibAction = 'Delete Library'; -$lang->doc->moveLibAction = 'Move Library'; -$lang->doc->moveDocAction = 'Move Document'; -$lang->doc->batchMove = 'Batch Move'; -$lang->doc->batchMoveDocAction = 'Batch Move Document'; -$lang->doc->fixedMenu = 'Fix to Menu'; -$lang->doc->removeMenu = 'Remove from Menu'; -$lang->doc->search = 'Search'; -$lang->doc->allCollections = 'All Collections'; -$lang->doc->keywordsTips = 'Please use commas to separate keywords.'; -$lang->doc->sortLibs = 'Sort Libs'; -$lang->doc->titlePlaceholder = 'Enter the title here'; -$lang->doc->confirm = 'Confirm'; -$lang->doc->docSummary = 'Total: %s.'; -$lang->doc->docCheckedSummary = 'Seleted: %total%.'; -$lang->doc->showDoc = 'Whether to display documents'; -$lang->doc->uploadFile = 'Upload File'; -$lang->doc->uploadDoc = 'Import Document'; -$lang->doc->uploadFormat = 'Upload Format'; -$lang->doc->editedList = 'File editor'; -$lang->doc->moveTo = 'Move to'; -$lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->libName = 'Document Library'; +$lang->doc->libType = 'Category'; +$lang->doc->custom = 'Custom Document Library'; +$lang->doc->customAB = 'Custom Doc Lib'; +$lang->doc->createLib = 'Create Library'; +$lang->doc->createLibAction = 'Create Library'; +$lang->doc->createSpace = 'Create Space'; +$lang->doc->allLibs = 'Library List'; +$lang->doc->objectLibs = "Document View of Library"; +$lang->doc->showFiles = 'Attachments'; +$lang->doc->editLib = 'Edit Document Library'; +$lang->doc->editSpaceAction = 'Edit Space'; +$lang->doc->editLibAction = 'Edit Library'; +$lang->doc->deleteSpaceAction = 'Delete Space'; +$lang->doc->deleteLibAction = 'Delete Library'; +$lang->doc->moveLibAction = 'Move Library'; +$lang->doc->moveDocAction = 'Move Document'; +$lang->doc->batchMove = 'Batch Move'; +$lang->doc->batchMoveDocAction = 'Batch Move Document'; +$lang->doc->fixedMenu = 'Fix to Menu'; +$lang->doc->removeMenu = 'Remove from Menu'; +$lang->doc->search = 'Search'; +$lang->doc->allCollections = 'All Collections'; +$lang->doc->keywordsTips = 'Please use commas to separate keywords.'; +$lang->doc->sortLibs = 'Sort Libs'; +$lang->doc->titlePlaceholder = 'Enter the title here'; +$lang->doc->confirm = 'Confirm'; +$lang->doc->docSummary = 'Total: %s.'; +$lang->doc->docCheckedSummary = 'Seleted: %total%.'; +$lang->doc->showDoc = 'Whether to display documents'; +$lang->doc->uploadFile = 'Upload File'; +$lang->doc->uploadDoc = 'Import Document'; +$lang->doc->uploadFormat = 'Upload Format'; +$lang->doc->editedList = 'File editor'; +$lang->doc->moveTo = 'Move to'; +$lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->browseReportTemplate = 'Report Template Home'; +$lang->doc->browseReport = 'Report Home'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 7a309004c2..d260b40912 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -277,42 +277,44 @@ $lang->doc->api = 'API'; $lang->doc->displaySetting = 'Display Settings'; $lang->doc->collectAction = 'Add Favorite'; -$lang->doc->libName = 'Bibliothèque de Documents'; -$lang->doc->libType = 'Catégorie'; -$lang->doc->custom = 'Personnaliser Bibliothèque de Documents'; -$lang->doc->customAB = 'Person. Bib Doc'; -$lang->doc->createLib = 'Create Library'; -$lang->doc->createLibAction = 'Create Library'; -$lang->doc->createSpace = 'Create Space'; -$lang->doc->allLibs = 'Liste des Bibliothèque'; -$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothèque"; -$lang->doc->showFiles = 'Pièces Jointes'; -$lang->doc->editLib = 'Edit Document Library'; -$lang->doc->editSpaceAction = 'Edit Space'; -$lang->doc->editLibAction = 'Edit Library'; -$lang->doc->deleteSpaceAction = 'Delete Space'; -$lang->doc->deleteLibAction = 'Delete Library'; -$lang->doc->moveLibAction = 'Move Library'; -$lang->doc->moveDocAction = 'Move Document'; -$lang->doc->batchMove = 'Batch Move'; -$lang->doc->batchMoveDocAction = 'Batch Move Document'; -$lang->doc->fixedMenu = 'Coller au Menu'; -$lang->doc->removeMenu = 'Décoller du Menu'; -$lang->doc->search = 'Rechercher'; -$lang->doc->allCollections = 'All Collections'; -$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; -$lang->doc->sortLibs = 'Sort Libs'; -$lang->doc->titlePlaceholder = 'Veuillez saisir le titre'; -$lang->doc->confirm = 'Confirm'; -$lang->doc->docSummary = 'Total: %s.'; -$lang->doc->docCheckedSummary = 'Seleted: %total%.'; -$lang->doc->showDoc = 'Whether to display documents'; -$lang->doc->uploadFile = 'Upload File'; -$lang->doc->uploadDoc = 'Upload Document'; -$lang->doc->uploadFormat = 'Upload Format'; -$lang->doc->editedList = 'File editor'; -$lang->doc->moveTo = 'Move to'; -$lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->libName = 'Bibliothèque de Documents'; +$lang->doc->libType = 'Catégorie'; +$lang->doc->custom = 'Personnaliser Bibliothèque de Documents'; +$lang->doc->customAB = 'Person. Bib Doc'; +$lang->doc->createLib = 'Create Library'; +$lang->doc->createLibAction = 'Create Library'; +$lang->doc->createSpace = 'Create Space'; +$lang->doc->allLibs = 'Liste des Bibliothèque'; +$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothèque"; +$lang->doc->showFiles = 'Pièces Jointes'; +$lang->doc->editLib = 'Edit Document Library'; +$lang->doc->editSpaceAction = 'Edit Space'; +$lang->doc->editLibAction = 'Edit Library'; +$lang->doc->deleteSpaceAction = 'Delete Space'; +$lang->doc->deleteLibAction = 'Delete Library'; +$lang->doc->moveLibAction = 'Move Library'; +$lang->doc->moveDocAction = 'Move Document'; +$lang->doc->batchMove = 'Batch Move'; +$lang->doc->batchMoveDocAction = 'Batch Move Document'; +$lang->doc->fixedMenu = 'Coller au Menu'; +$lang->doc->removeMenu = 'Décoller du Menu'; +$lang->doc->search = 'Rechercher'; +$lang->doc->allCollections = 'All Collections'; +$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; +$lang->doc->sortLibs = 'Sort Libs'; +$lang->doc->titlePlaceholder = 'Veuillez saisir le titre'; +$lang->doc->confirm = 'Confirm'; +$lang->doc->docSummary = 'Total: %s.'; +$lang->doc->docCheckedSummary = 'Seleted: %total%.'; +$lang->doc->showDoc = 'Whether to display documents'; +$lang->doc->uploadFile = 'Upload File'; +$lang->doc->uploadDoc = 'Upload Document'; +$lang->doc->uploadFormat = 'Upload Format'; +$lang->doc->editedList = 'File editor'; +$lang->doc->moveTo = 'Move to'; +$lang->doc->notSupportExport = 'This document does not support export'; +$lang->doc->browseReportTemplate = 'Report Template Home'; +$lang->doc->browseReport = 'Report Home'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 3a2b19d2bd..cb63c6ea05 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -277,42 +277,44 @@ $lang->doc->api = '接口'; $lang->doc->displaySetting = '显示设置'; $lang->doc->collectAction = '收藏文档'; -$lang->doc->libName = '库名称'; -$lang->doc->libType = '库类型'; -$lang->doc->custom = '自定义文档库'; -$lang->doc->customAB = '自定义库'; -$lang->doc->createLib = '创建库'; -$lang->doc->createLibAction = '创建库'; -$lang->doc->createSpace = '创建空间'; -$lang->doc->allLibs = '库列表'; -$lang->doc->objectLibs = "库文档详情"; -$lang->doc->showFiles = '附件库'; -$lang->doc->editLib = '编辑库'; -$lang->doc->editSpaceAction = '编辑空间'; -$lang->doc->editLibAction = '编辑库'; -$lang->doc->deleteSpaceAction = '删除空间'; -$lang->doc->deleteLibAction = '删除库'; -$lang->doc->moveLibAction = '移动库'; -$lang->doc->moveDocAction = '移动文档'; -$lang->doc->batchMove = '批量移动'; -$lang->doc->batchMoveDocAction = '批量移动文档'; -$lang->doc->fixedMenu = '固定到菜单栏'; -$lang->doc->removeMenu = '从菜单栏移除'; -$lang->doc->search = '搜索'; -$lang->doc->allCollections = '查看全部收藏文档'; -$lang->doc->keywordsTips = '多个关键字请用逗号分隔。'; -$lang->doc->sortLibs = '文档库排序'; -$lang->doc->titlePlaceholder = '在此输入标题'; -$lang->doc->confirm = '确认'; -$lang->doc->docSummary = '本页共 %s 个文档。'; -$lang->doc->docCheckedSummary = '共选中 %total% 个文档。'; -$lang->doc->showDoc = '是否显示文档'; -$lang->doc->uploadFile = '上传文件'; -$lang->doc->uploadDoc = '导入'; -$lang->doc->uploadFormat = '上传格式'; -$lang->doc->editedList = '文档编辑者'; -$lang->doc->moveTo = '移动至'; -$lang->doc->notSupportExport = '(此文档暂不支持导出)'; +$lang->doc->libName = '库名称'; +$lang->doc->libType = '库类型'; +$lang->doc->custom = '自定义文档库'; +$lang->doc->customAB = '自定义库'; +$lang->doc->createLib = '创建库'; +$lang->doc->createLibAction = '创建库'; +$lang->doc->createSpace = '创建空间'; +$lang->doc->allLibs = '库列表'; +$lang->doc->objectLibs = "库文档详情"; +$lang->doc->showFiles = '附件库'; +$lang->doc->editLib = '编辑库'; +$lang->doc->editSpaceAction = '编辑空间'; +$lang->doc->editLibAction = '编辑库'; +$lang->doc->deleteSpaceAction = '删除空间'; +$lang->doc->deleteLibAction = '删除库'; +$lang->doc->moveLibAction = '移动库'; +$lang->doc->moveDocAction = '移动文档'; +$lang->doc->batchMove = '批量移动'; +$lang->doc->batchMoveDocAction = '批量移动文档'; +$lang->doc->fixedMenu = '固定到菜单栏'; +$lang->doc->removeMenu = '从菜单栏移除'; +$lang->doc->search = '搜索'; +$lang->doc->allCollections = '查看全部收藏文档'; +$lang->doc->keywordsTips = '多个关键字请用逗号分隔。'; +$lang->doc->sortLibs = '文档库排序'; +$lang->doc->titlePlaceholder = '在此输入标题'; +$lang->doc->confirm = '确认'; +$lang->doc->docSummary = '本页共 %s 个文档。'; +$lang->doc->docCheckedSummary = '共选中 %total% 个文档。'; +$lang->doc->showDoc = '是否显示文档'; +$lang->doc->uploadFile = '上传文件'; +$lang->doc->uploadDoc = '导入'; +$lang->doc->uploadFormat = '上传格式'; +$lang->doc->editedList = '文档编辑者'; +$lang->doc->moveTo = '移动至'; +$lang->doc->notSupportExport = '(此文档暂不支持导出)'; +$lang->doc->browseReportTemplate = '报告模板首页'; +$lang->doc->browseReport = '报告首页'; $lang->doc->preview = '预览'; $lang->doc->insertTitle = '插入%s列表'; diff --git a/module/group/lang/de.php b/module/group/lang/de.php index 7de9bc1466..dc6f406f56 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -604,5 +604,6 @@ $lang->group->package->mangeApplication = 'Manage Service'; $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; +$lang->group->package->browseReportTemplate = 'Browse Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/en.php b/module/group/lang/en.php index 13ec6e7396..f4aed50517 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -604,5 +604,6 @@ $lang->group->package->mangeApplication = 'Manage Service'; $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; +$lang->group->package->browseReportTemplate = 'Browse Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 096ab10ee6..1ce9b20cde 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -604,5 +604,6 @@ $lang->group->package->mangeApplication = 'Manage Service'; $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; +$lang->group->package->browseReportTemplate = 'Browse Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 2d7308f21e..37e7894fcf 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1511,40 +1511,42 @@ $lang->resource->system->inactive = 'inactive'; /* Doc. */ $lang->resource->doc = new stdclass(); -$lang->resource->doc->index = 'index'; -$lang->resource->doc->mySpace = 'mySpace'; -$lang->resource->doc->quick = 'quick'; -$lang->resource->doc->createSpace = 'createSpace'; -$lang->resource->doc->createLib = 'createLibAction'; -$lang->resource->doc->editSpace = 'editSpaceAction'; -$lang->resource->doc->editLib = 'editLibAction'; -$lang->resource->doc->deleteSpace = 'deleteSpaceAction'; -$lang->resource->doc->deleteLib = 'deleteLibAction'; -$lang->resource->doc->moveLib = 'moveLibAction'; -$lang->resource->doc->moveDoc = 'moveDocAction'; -$lang->resource->doc->batchMoveDoc = 'batchMoveDocAction'; -$lang->resource->doc->create = 'createOrUpload'; -$lang->resource->doc->edit = 'edit'; -$lang->resource->doc->view = 'view'; -$lang->resource->doc->delete = 'delete'; -$lang->resource->doc->deleteFile = 'deleteFile'; -$lang->resource->doc->collect = 'collectAction'; -$lang->resource->doc->productSpace = 'productSpace'; -$lang->resource->doc->projectSpace = 'projectSpace'; -$lang->resource->doc->teamSpace = 'teamSpace'; -$lang->resource->doc->showFiles = 'showFiles'; -$lang->resource->doc->addCatalog = 'addCatalog'; -$lang->resource->doc->editCatalog = 'editCatalog'; -$lang->resource->doc->sortDoclib = 'sortDoclib'; -$lang->resource->doc->sortCatalog = 'sortCatalog'; -$lang->resource->doc->sortDoc = 'sortDoc'; -$lang->resource->doc->deleteCatalog = 'deleteCatalog'; +$lang->resource->doc->index = 'index'; +$lang->resource->doc->mySpace = 'mySpace'; +$lang->resource->doc->quick = 'quick'; +$lang->resource->doc->createSpace = 'createSpace'; +$lang->resource->doc->createLib = 'createLibAction'; +$lang->resource->doc->editSpace = 'editSpaceAction'; +$lang->resource->doc->editLib = 'editLibAction'; +$lang->resource->doc->deleteSpace = 'deleteSpaceAction'; +$lang->resource->doc->deleteLib = 'deleteLibAction'; +$lang->resource->doc->moveLib = 'moveLibAction'; +$lang->resource->doc->moveDoc = 'moveDocAction'; +$lang->resource->doc->batchMoveDoc = 'batchMoveDocAction'; +$lang->resource->doc->create = 'createOrUpload'; +$lang->resource->doc->edit = 'edit'; +$lang->resource->doc->view = 'view'; +$lang->resource->doc->delete = 'delete'; +$lang->resource->doc->deleteFile = 'deleteFile'; +$lang->resource->doc->collect = 'collectAction'; +$lang->resource->doc->productSpace = 'productSpace'; +$lang->resource->doc->projectSpace = 'projectSpace'; +$lang->resource->doc->teamSpace = 'teamSpace'; +$lang->resource->doc->showFiles = 'showFiles'; +$lang->resource->doc->addCatalog = 'addCatalog'; +$lang->resource->doc->editCatalog = 'editCatalog'; +$lang->resource->doc->sortDoclib = 'sortDoclib'; +$lang->resource->doc->sortCatalog = 'sortCatalog'; +$lang->resource->doc->sortDoc = 'sortDoc'; +$lang->resource->doc->deleteCatalog = 'deleteCatalog'; // $lang->resource->doc->displaySetting = 'displaySetting'; -$lang->resource->doc->exportFiles = 'exportFiles'; -$lang->resource->doc->addChapter = 'addChapter'; -$lang->resource->doc->editChapter = 'editChapter'; -$lang->resource->doc->sortChapter = 'sortChapter'; -$lang->resource->doc->deleteChapter = 'deleteChapter'; +$lang->resource->doc->exportFiles = 'exportFiles'; +$lang->resource->doc->addChapter = 'addChapter'; +$lang->resource->doc->editChapter = 'editChapter'; +$lang->resource->doc->sortChapter = 'sortChapter'; +$lang->resource->doc->deleteChapter = 'deleteChapter'; +$lang->resource->doc->browseReportTemplate = 'browseReportTemplate'; +$lang->resource->doc->browseReport = 'browseReport'; $lang->doc->methodOrder[5] = 'index'; $lang->doc->methodOrder[10] = 'mySpace'; @@ -1578,6 +1580,8 @@ $lang->doc->methodOrder[160] = 'addChapter'; $lang->doc->methodOrder[170] = 'editChapter'; $lang->doc->methodOrder[180] = 'sortChapter'; $lang->doc->methodOrder[190] = 'deleteChapter'; +$lang->doc->methodOrder[195] = 'browseReportTemplate'; +$lang->doc->methodOrder[200] = 'browseReport'; /* Mail. */ $lang->resource->mail = new stdclass(); diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index 082b95197b..4a29f01c23 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -604,5 +604,6 @@ $lang->group->package->mangeApplication = '管理服务'; $lang->group->package->trainPracticeLib = '实践库'; $lang->group->package->application = '管理应用'; $lang->group->package->component = '组件'; +$lang->group->package->browseReportTemplate = '浏览报告和模板'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index f8f96ca0fd..e9aaf2d405 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -285,6 +285,10 @@ $config->group->subset->metric = new stdclass(); $config->group->subset->metric->order = 890; $config->group->subset->metric->nav = 'bi'; +$config->group->subset->reporttemplate = new stdclass(); +$config->group->subset->reporttemplate->order = 900; +$config->group->subset->reporttemplate->nav = 'bi'; + $config->group->subset->systemteam = new stdclass(); $config->group->subset->systemteam->order = 920; $config->group->subset->systemteam->nav = 'system'; @@ -3579,6 +3583,13 @@ $config->group->package->manageMetric->privs['metric-delist'] = array('edit $config->group->package->manageMetric->privs['metric-delete'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 45, 'depend' => array('metric-browse'), 'recommend' => array()); $config->group->package->manageMetric->privs['metric-recalculate'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); +$config->group->package->browseReportTemplate = new stdclass(); +$config->group->package->browseReportTemplate->order = 5; +$config->group->package->browseReportTemplate->subset = 'reporttemplate'; +$config->group->package->browseReportTemplate->privs = array(); +$config->group->package->browseReportTemplate->privs['doc-browseReportTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); +$config->group->package->browseReportTemplate->privs['doc-browseReport'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array(), 'recommend' => array()); + $config->group->package->browseDoc = new stdclass(); $config->group->package->browseDoc->order = 10; $config->group->package->browseDoc->subset = 'doc'; From 394e6b404b7471a320488db146003d3c70e1d400 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 12 Mar 2025 15:39:28 +0800 Subject: [PATCH 324/655] * [task#139169,doing,3h] Add the empty page for report template home. --- module/doc/control.php | 23 ++++++++++++++++++++- module/doc/lang/de.php | 3 +++ module/doc/lang/en.php | 3 +++ module/doc/lang/fr.php | 3 +++ module/doc/lang/zh-cn.php | 3 +++ module/doc/ui/browsereporttemplate.html.php | 3 +++ module/group/lang/de.php | 1 + module/group/lang/en.php | 1 + module/group/lang/fr.php | 1 + module/group/lang/resource.php | 2 ++ module/group/lang/zh-cn.php | 1 + module/group/packagemanager.php | 6 ++++++ 12 files changed, 49 insertions(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index 93cefafd63..c5d0e6068e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -2265,11 +2265,32 @@ class doc extends control * 报告模板列表。 * Report template list. * + * @param int $libID + * @param string $type + * @param int $docID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @param string $mode home|list * @access public * @return void */ - public function browseReportTemplate() + public function browseReportTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'home') { + $this->app->loadClass('pager', true); + $pager = new pager($recTotal, $recPerPage, $pageID); + $templateList = array(); + + $this->view->title = $this->lang->doc->template; + $this->view->libID = $libID; + $this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter'); + $this->view->templateList = $templateList; + $this->view->docID = $docID; + $this->view->orderBy = $orderBy; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->mode = $mode; $this->display(); } } diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 09435c2a6f..5d04b3c27f 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -106,6 +106,8 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->noReportTemplate = 'No Report Template'; +$lang->docTemplate->createReportTemplate = 'Create Report Template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; @@ -315,6 +317,7 @@ $lang->doc->moveTo = 'Move to'; $lang->doc->notSupportExport = 'This document does not support export'; $lang->doc->browseReportTemplate = 'Report Template Home'; $lang->doc->browseReport = 'Report Home'; +$lang->doc->createReportTemplate = 'Create Report Template'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 34e8c25102..4a390951fa 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -106,6 +106,8 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->noReportTemplate = 'No Report Template'; +$lang->docTemplate->createReportTemplate = 'Create Report Template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; @@ -315,6 +317,7 @@ $lang->doc->moveTo = 'Move to'; $lang->doc->notSupportExport = 'This document does not support export'; $lang->doc->browseReportTemplate = 'Report Template Home'; $lang->doc->browseReport = 'Report Home'; +$lang->doc->createReportTemplate = 'Create Report Template'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index d260b40912..9e9e17b3ee 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -106,6 +106,8 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->noReportTemplate = 'No Report Template'; +$lang->docTemplate->createReportTemplate = 'Create Report Template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; @@ -315,6 +317,7 @@ $lang->doc->moveTo = 'Move to'; $lang->doc->notSupportExport = 'This document does not support export'; $lang->doc->browseReportTemplate = 'Report Template Home'; $lang->doc->browseReport = 'Report Home'; +$lang->doc->createReportTemplate = 'Create Report Template'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index cb63c6ea05..8b2951478e 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -106,6 +106,8 @@ $lang->docTemplate->editedList = '模板编辑者'; $lang->docTemplate->content = '模板内容'; $lang->docTemplate->templateDesc = '模板描述'; $lang->docTemplate->status = '模板状态'; +$lang->docTemplate->noReportTemplate = '没有报告模板'; +$lang->docTemplate->createReportTemplate = '创建报告模板'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; @@ -315,6 +317,7 @@ $lang->doc->moveTo = '移动至'; $lang->doc->notSupportExport = '(此文档暂不支持导出)'; $lang->doc->browseReportTemplate = '报告模板首页'; $lang->doc->browseReport = '报告首页'; +$lang->doc->createReportTemplate = '创建报告模板'; $lang->doc->preview = '预览'; $lang->doc->insertTitle = '插入%s列表'; diff --git a/module/doc/ui/browsereporttemplate.html.php b/module/doc/ui/browsereporttemplate.html.php index 5ae5ffb2cc..0e010f54b7 100644 --- a/module/doc/ui/browsereporttemplate.html.php +++ b/module/doc/ui/browsereporttemplate.html.php @@ -9,3 +9,6 @@ declare(strict_types=1); * @link https://www.zentao.net */ namespace zin; + +if($mode == 'home' || !$libID) include './reporttemplatehome.html.php'; +else include './reporttemplatelist.html.php'; diff --git a/module/group/lang/de.php b/module/group/lang/de.php index dc6f406f56..c464758a07 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -605,5 +605,6 @@ $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseReportTemplate = 'Browse Report and Template'; +$lang->group->package->manageReportTemplate = 'Create and Manage Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/en.php b/module/group/lang/en.php index f4aed50517..cee6f2476b 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -605,5 +605,6 @@ $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseReportTemplate = 'Browse Report and Template'; +$lang->group->package->manageReportTemplate = 'Create and Manage Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 1ce9b20cde..4748047cee 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -605,5 +605,6 @@ $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; $lang->group->package->browseReportTemplate = 'Browse Report and Template'; +$lang->group->package->manageReportTemplate = 'Create and Manage Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 37e7894fcf..3a0d85745d 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1547,6 +1547,7 @@ $lang->resource->doc->sortChapter = 'sortChapter'; $lang->resource->doc->deleteChapter = 'deleteChapter'; $lang->resource->doc->browseReportTemplate = 'browseReportTemplate'; $lang->resource->doc->browseReport = 'browseReport'; +$lang->resource->doc->createReportTemplate = 'createReportTemplate'; $lang->doc->methodOrder[5] = 'index'; $lang->doc->methodOrder[10] = 'mySpace'; @@ -1582,6 +1583,7 @@ $lang->doc->methodOrder[180] = 'sortChapter'; $lang->doc->methodOrder[190] = 'deleteChapter'; $lang->doc->methodOrder[195] = 'browseReportTemplate'; $lang->doc->methodOrder[200] = 'browseReport'; +$lang->doc->methodOrder[205] = 'createReportTemplate'; /* Mail. */ $lang->resource->mail = new stdclass(); diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index 4a29f01c23..7412507915 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -605,5 +605,6 @@ $lang->group->package->trainPracticeLib = '实践库'; $lang->group->package->application = '管理应用'; $lang->group->package->component = '组件'; $lang->group->package->browseReportTemplate = '浏览报告和模板'; +$lang->group->package->manageReportTemplate = '创建与维护报告和模板'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index e9aaf2d405..08acfa8363 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -3590,6 +3590,12 @@ $config->group->package->browseReportTemplate->privs = array(); $config->group->package->browseReportTemplate->privs['doc-browseReportTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); $config->group->package->browseReportTemplate->privs['doc-browseReport'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array(), 'recommend' => array()); +$config->group->package->manageReportTemplate = new stdclass(); +$config->group->package->manageReportTemplate->order = 5; +$config->group->package->manageReportTemplate->subset = 'reporttemplate'; +$config->group->package->manageReportTemplate->privs = array(); +$config->group->package->manageReportTemplate->privs['doc-createReportTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); + $config->group->package->browseDoc = new stdclass(); $config->group->package->browseDoc->order = 10; $config->group->package->browseDoc->subset = 'doc'; From 61abdeb351cac2058a4f37c4e14cf441f17d92aa Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 12 Mar 2025 15:40:26 +0800 Subject: [PATCH 325/655] * [task#139169,doing,0.5h] Add the empty page of report template home. --- module/doc/ui/reporttemplatehome.html.php | 78 +++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 module/doc/ui/reporttemplatehome.html.php diff --git a/module/doc/ui/reporttemplatehome.html.php b/module/doc/ui/reporttemplatehome.html.php new file mode 100644 index 0000000000..061fe83281 --- /dev/null +++ b/module/doc/ui/reporttemplatehome.html.php @@ -0,0 +1,78 @@ + + * @package doc + * @link https://www.zentao.net + */ +namespace zin; + +$scopeTemplates = array(2 => array(), 3 => array()); + +$scopeItems = array(); +unset($lang->docTemplate->scopes[1]); +unset($lang->docTemplate->scopes[4]); +foreach($lang->docTemplate->scopes as $scopeID => $scopeName) +{ + $scopeDocs = $scopeTemplates[$scopeID]; + $scopeItems[] = div + ( + setClass('doc-space-card ring rounded surface-light'), + div + ( + setClass('row items-center justify-between gap-2 px-2.5 py-1 border-b'), + div + ( + setClass('row items-center ml-2 flex-none'), + div + ( + setClass('min-w-0 flex-auto'), + strong($scopeName), + span(setClass('label ml-2 flex-none bg-white size-sm text-sm'), $lang->docTemplate->scopeLabel) + ), + ), + toolbar + ( + item(set(array + ( + 'data-app' => $app->tab, + 'type' => 'ghost', + 'caret' => 'right', + 'class' => 'text-primary', + 'text' => $lang->more, + 'url' => createLink('doc', 'browseReportTemplate', "libID=$scopeID&type=all&docID=0&orderBy=id_desc&recTotal=&recPerPae=20&pageID=1&mode=list") + ))) + ), + ), + div + ( + setClass('doc-space-card-libs py-3 px-1.5'), + div + ( + setClass('center gap-4 py-10'), + div + ( + setClass('text-gray'), + $lang->docTemplate->noReportTemplate + ), + hasPriv('doc', 'createReportTemplate') ? btn + ( + setClass('btn primary-pale'), + setData('app', $app->tab), + set::icon('plus'), + $lang->docTemplate->createReportTemplate, + set::url(createLink('doc', 'browseReportTemplate', "libID=$scopeID&type=all&docID=0&orderBy=&recTotal=&recPerPae=20&pageID=1&mode=create")) + ) : null + ) + ) + ); +} + +div +( + setClass('doc-home-body flex-auto min-h-0 col gap-4 p-4 items-stretch overflow-auto scrollbar-hover'), + $scopeItems +); From 350bb7326ff75da9a903f672b4a3a1ba0c86887e Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 13 Mar 2025 09:16:34 +0800 Subject: [PATCH 326/655] * [task#139169,#139169,#139159,#139157] Restore code. --- config/zentaopms.php | 2 +- module/doc/control.php | 45 ------------ module/doc/lang/de.php | 77 ++++++++++---------- module/doc/lang/en.php | 77 ++++++++++---------- module/doc/lang/fr.php | 77 ++++++++++---------- module/doc/lang/zh-cn.php | 77 ++++++++++---------- module/doc/ui/browsereport.html.php | 11 --- module/doc/ui/browsereporttemplate.html.php | 14 ---- module/doc/ui/reporttemplatehome.html.php | 78 --------------------- module/group/lang/de.php | 2 - module/group/lang/en.php | 2 - module/group/lang/fr.php | 2 - module/group/lang/resource.php | 6 -- module/group/lang/zh-cn.php | 2 - module/group/packagemanager.php | 17 ----- 15 files changed, 145 insertions(+), 344 deletions(-) delete mode 100644 module/doc/ui/browsereport.html.php delete mode 100644 module/doc/ui/browsereporttemplate.html.php delete mode 100644 module/doc/ui/reporttemplatehome.html.php diff --git a/config/zentaopms.php b/config/zentaopms.php index 15db58d9e7..f2f79bb987 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -776,7 +776,7 @@ $config->db->sqliteBlacklist = array('sqlite_queue', 'cron'); $config->hasDropmenuApps = array('program', 'project', 'product', 'execution', 'qa', 'admin', 'bi', 'feedback', 'demandpool'); $config->hasBranchMenuModules = array('product', 'story', 'release', 'bug', 'testcase', 'testtask', 'branch', 'tree'); $config->excludeBranchMenu = array('product-dashboard', 'product-view'); -$config->excludeDropmenuList = array('program-browse', 'program-productview', 'program-kanban', 'product-all', 'product-index', 'product-kanban', 'project-kanban', 'execution-all', 'execution-executionkanban', 'project-browse', 'project-batchedit', 'product-batchedit', 'admin-index', 'product-create', 'project-create', 'execution-create', 'program-create', 'execution-batchedit', 'metric-preview', 'metric-browse', 'metric-view', 'metriclib-browse', 'qa-index', 'caselib-create', 'feedback-batchedit', 'feedback-batchclose', 'feedback-showimport', 'dimension-browse', 'dataview-browse', 'dataview-create', 'dataview-query', 'ticket-batchedit', 'ticket-batchfinish', 'ticket-batchactivate', 'file-download', 'doc-browsereport', 'doc-browsereporttemplate'); +$config->excludeDropmenuList = array('program-browse', 'program-productview', 'program-kanban', 'product-all', 'product-index', 'product-kanban', 'project-kanban', 'execution-all', 'execution-executionkanban', 'project-browse', 'project-batchedit', 'product-batchedit', 'admin-index', 'product-create', 'project-create', 'execution-create', 'program-create', 'execution-batchedit', 'metric-preview', 'metric-browse', 'metric-view', 'metriclib-browse', 'qa-index', 'caselib-create', 'feedback-batchedit', 'feedback-batchclose', 'feedback-showimport', 'dimension-browse', 'dataview-browse', 'dataview-create', 'dataview-query', 'ticket-batchedit', 'ticket-batchfinish', 'ticket-batchactivate', 'file-download'); $config->hasSwitcherModules = array('design'); $config->hasSwitcherMethods = array('project-bug', 'project-testcase', 'execution-bug', 'execution-testcase', 'testtask-cases', 'testtask-view', 'testtask-report', 'testtask-groupcase', 'testtask-linkcase'); $config->excludeSwitcherList = array(); diff --git a/module/doc/control.php b/module/doc/control.php index c5d0e6068e..8ce233a99e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -2248,49 +2248,4 @@ class doc extends control $this->view->title = $title; $this->display(); } - - /** - * 报告列表。 - * Report list. - * - * @access public - * @return void - */ - public function browseReport() - { - $this->display(); - } - - /** - * 报告模板列表。 - * Report template list. - * - * @param int $libID - * @param string $type - * @param int $docID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @param string $mode home|list - * @access public - * @return void - */ - public function browseReportTemplate(int $libID = 0, string $type = 'all', int $docID = 0, string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 20, int $pageID = 1, string $mode = 'home') - { - $this->app->loadClass('pager', true); - $pager = new pager($recTotal, $recPerPage, $pageID); - $templateList = array(); - - $this->view->title = $this->lang->doc->template; - $this->view->libID = $libID; - $this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter'); - $this->view->templateList = $templateList; - $this->view->docID = $docID; - $this->view->orderBy = $orderBy; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->mode = $mode; - $this->display(); - } } diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 5d04b3c27f..e729e9ab22 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -106,8 +106,6 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->noReportTemplate = 'No Report Template'; -$lang->docTemplate->createReportTemplate = 'Create Report Template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; @@ -279,45 +277,42 @@ $lang->doc->api = 'API'; $lang->doc->displaySetting = 'Display Settings'; $lang->doc->collectAction = 'Add Favorite'; -$lang->doc->libName = 'Name'; -$lang->doc->libType = 'Kategorie'; -$lang->doc->custom = 'Eigene Dok Bibliothek'; -$lang->doc->customAB = 'Eigene Bibliothek'; -$lang->doc->createLib = 'Create Library'; -$lang->doc->createLibAction = 'Create Library'; -$lang->doc->createSpace = 'Create Space'; -$lang->doc->allLibs = 'Bibliothek'; -$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothek Liste"; -$lang->doc->showFiles = 'Dok Bibliothek'; -$lang->doc->editLib = 'Edit Document Library'; -$lang->doc->editSpaceAction = 'Edit Space'; -$lang->doc->editLibAction = 'Edit Library'; -$lang->doc->deleteSpaceAction = 'Delete Space'; -$lang->doc->deleteLibAction = 'Delete Library'; -$lang->doc->moveLibAction = 'Move Library'; -$lang->doc->moveDocAction = 'Move Document'; -$lang->doc->batchMove = 'Batch Move'; -$lang->doc->batchMoveDocAction = 'Batch Move Document'; -$lang->doc->fixedMenu = 'Im Menü fixieren'; -$lang->doc->removeMenu = 'Vom Menü entfernen'; -$lang->doc->search = 'Suche'; -$lang->doc->allCollections = 'All Collections'; -$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; -$lang->doc->sortLibs = 'Sort Libs'; -$lang->doc->titlePlaceholder = 'Please enter the title'; -$lang->doc->confirm = 'Confirm'; -$lang->doc->docSummary = 'Total: %s.'; -$lang->doc->docCheckedSummary = 'Seleted: %total%.'; -$lang->doc->showDoc = 'Whether to display documents'; -$lang->doc->uploadFile = 'Upload File'; -$lang->doc->uploadDoc = 'Upload Document'; -$lang->doc->uploadFormat = 'Upload Format'; -$lang->doc->editedList = 'File editor'; -$lang->doc->moveTo = 'Move to'; -$lang->doc->notSupportExport = 'This document does not support export'; -$lang->doc->browseReportTemplate = 'Report Template Home'; -$lang->doc->browseReport = 'Report Home'; -$lang->doc->createReportTemplate = 'Create Report Template'; +$lang->doc->libName = 'Name'; +$lang->doc->libType = 'Kategorie'; +$lang->doc->custom = 'Eigene Dok Bibliothek'; +$lang->doc->customAB = 'Eigene Bibliothek'; +$lang->doc->createLib = 'Create Library'; +$lang->doc->createLibAction = 'Create Library'; +$lang->doc->createSpace = 'Create Space'; +$lang->doc->allLibs = 'Bibliothek'; +$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothek Liste"; +$lang->doc->showFiles = 'Dok Bibliothek'; +$lang->doc->editLib = 'Edit Document Library'; +$lang->doc->editSpaceAction = 'Edit Space'; +$lang->doc->editLibAction = 'Edit Library'; +$lang->doc->deleteSpaceAction = 'Delete Space'; +$lang->doc->deleteLibAction = 'Delete Library'; +$lang->doc->moveLibAction = 'Move Library'; +$lang->doc->moveDocAction = 'Move Document'; +$lang->doc->batchMove = 'Batch Move'; +$lang->doc->batchMoveDocAction = 'Batch Move Document'; +$lang->doc->fixedMenu = 'Im Menü fixieren'; +$lang->doc->removeMenu = 'Vom Menü entfernen'; +$lang->doc->search = 'Suche'; +$lang->doc->allCollections = 'All Collections'; +$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; +$lang->doc->sortLibs = 'Sort Libs'; +$lang->doc->titlePlaceholder = 'Please enter the title'; +$lang->doc->confirm = 'Confirm'; +$lang->doc->docSummary = 'Total: %s.'; +$lang->doc->docCheckedSummary = 'Seleted: %total%.'; +$lang->doc->showDoc = 'Whether to display documents'; +$lang->doc->uploadFile = 'Upload File'; +$lang->doc->uploadDoc = 'Upload Document'; +$lang->doc->uploadFormat = 'Upload Format'; +$lang->doc->editedList = 'File editor'; +$lang->doc->moveTo = 'Move to'; +$lang->doc->notSupportExport = 'This document does not support export'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 4a390951fa..8945ddc702 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -106,8 +106,6 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->noReportTemplate = 'No Report Template'; -$lang->docTemplate->createReportTemplate = 'Create Report Template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; @@ -279,45 +277,42 @@ $lang->doc->api = 'API'; $lang->doc->displaySetting = 'Display Settings'; $lang->doc->collectAction = 'Add Favorite'; -$lang->doc->libName = 'Document Library'; -$lang->doc->libType = 'Category'; -$lang->doc->custom = 'Custom Document Library'; -$lang->doc->customAB = 'Custom Doc Lib'; -$lang->doc->createLib = 'Create Library'; -$lang->doc->createLibAction = 'Create Library'; -$lang->doc->createSpace = 'Create Space'; -$lang->doc->allLibs = 'Library List'; -$lang->doc->objectLibs = "Document View of Library"; -$lang->doc->showFiles = 'Attachments'; -$lang->doc->editLib = 'Edit Document Library'; -$lang->doc->editSpaceAction = 'Edit Space'; -$lang->doc->editLibAction = 'Edit Library'; -$lang->doc->deleteSpaceAction = 'Delete Space'; -$lang->doc->deleteLibAction = 'Delete Library'; -$lang->doc->moveLibAction = 'Move Library'; -$lang->doc->moveDocAction = 'Move Document'; -$lang->doc->batchMove = 'Batch Move'; -$lang->doc->batchMoveDocAction = 'Batch Move Document'; -$lang->doc->fixedMenu = 'Fix to Menu'; -$lang->doc->removeMenu = 'Remove from Menu'; -$lang->doc->search = 'Search'; -$lang->doc->allCollections = 'All Collections'; -$lang->doc->keywordsTips = 'Please use commas to separate keywords.'; -$lang->doc->sortLibs = 'Sort Libs'; -$lang->doc->titlePlaceholder = 'Enter the title here'; -$lang->doc->confirm = 'Confirm'; -$lang->doc->docSummary = 'Total: %s.'; -$lang->doc->docCheckedSummary = 'Seleted: %total%.'; -$lang->doc->showDoc = 'Whether to display documents'; -$lang->doc->uploadFile = 'Upload File'; -$lang->doc->uploadDoc = 'Import Document'; -$lang->doc->uploadFormat = 'Upload Format'; -$lang->doc->editedList = 'File editor'; -$lang->doc->moveTo = 'Move to'; -$lang->doc->notSupportExport = 'This document does not support export'; -$lang->doc->browseReportTemplate = 'Report Template Home'; -$lang->doc->browseReport = 'Report Home'; -$lang->doc->createReportTemplate = 'Create Report Template'; +$lang->doc->libName = 'Document Library'; +$lang->doc->libType = 'Category'; +$lang->doc->custom = 'Custom Document Library'; +$lang->doc->customAB = 'Custom Doc Lib'; +$lang->doc->createLib = 'Create Library'; +$lang->doc->createLibAction = 'Create Library'; +$lang->doc->createSpace = 'Create Space'; +$lang->doc->allLibs = 'Library List'; +$lang->doc->objectLibs = "Document View of Library"; +$lang->doc->showFiles = 'Attachments'; +$lang->doc->editLib = 'Edit Document Library'; +$lang->doc->editSpaceAction = 'Edit Space'; +$lang->doc->editLibAction = 'Edit Library'; +$lang->doc->deleteSpaceAction = 'Delete Space'; +$lang->doc->deleteLibAction = 'Delete Library'; +$lang->doc->moveLibAction = 'Move Library'; +$lang->doc->moveDocAction = 'Move Document'; +$lang->doc->batchMove = 'Batch Move'; +$lang->doc->batchMoveDocAction = 'Batch Move Document'; +$lang->doc->fixedMenu = 'Fix to Menu'; +$lang->doc->removeMenu = 'Remove from Menu'; +$lang->doc->search = 'Search'; +$lang->doc->allCollections = 'All Collections'; +$lang->doc->keywordsTips = 'Please use commas to separate keywords.'; +$lang->doc->sortLibs = 'Sort Libs'; +$lang->doc->titlePlaceholder = 'Enter the title here'; +$lang->doc->confirm = 'Confirm'; +$lang->doc->docSummary = 'Total: %s.'; +$lang->doc->docCheckedSummary = 'Seleted: %total%.'; +$lang->doc->showDoc = 'Whether to display documents'; +$lang->doc->uploadFile = 'Upload File'; +$lang->doc->uploadDoc = 'Import Document'; +$lang->doc->uploadFormat = 'Upload Format'; +$lang->doc->editedList = 'File editor'; +$lang->doc->moveTo = 'Move to'; +$lang->doc->notSupportExport = 'This document does not support export'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 9e9e17b3ee..7a309004c2 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -106,8 +106,6 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->noReportTemplate = 'No Report Template'; -$lang->docTemplate->createReportTemplate = 'Create Report Template'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; @@ -279,45 +277,42 @@ $lang->doc->api = 'API'; $lang->doc->displaySetting = 'Display Settings'; $lang->doc->collectAction = 'Add Favorite'; -$lang->doc->libName = 'Bibliothèque de Documents'; -$lang->doc->libType = 'Catégorie'; -$lang->doc->custom = 'Personnaliser Bibliothèque de Documents'; -$lang->doc->customAB = 'Person. Bib Doc'; -$lang->doc->createLib = 'Create Library'; -$lang->doc->createLibAction = 'Create Library'; -$lang->doc->createSpace = 'Create Space'; -$lang->doc->allLibs = 'Liste des Bibliothèque'; -$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothèque"; -$lang->doc->showFiles = 'Pièces Jointes'; -$lang->doc->editLib = 'Edit Document Library'; -$lang->doc->editSpaceAction = 'Edit Space'; -$lang->doc->editLibAction = 'Edit Library'; -$lang->doc->deleteSpaceAction = 'Delete Space'; -$lang->doc->deleteLibAction = 'Delete Library'; -$lang->doc->moveLibAction = 'Move Library'; -$lang->doc->moveDocAction = 'Move Document'; -$lang->doc->batchMove = 'Batch Move'; -$lang->doc->batchMoveDocAction = 'Batch Move Document'; -$lang->doc->fixedMenu = 'Coller au Menu'; -$lang->doc->removeMenu = 'Décoller du Menu'; -$lang->doc->search = 'Rechercher'; -$lang->doc->allCollections = 'All Collections'; -$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; -$lang->doc->sortLibs = 'Sort Libs'; -$lang->doc->titlePlaceholder = 'Veuillez saisir le titre'; -$lang->doc->confirm = 'Confirm'; -$lang->doc->docSummary = 'Total: %s.'; -$lang->doc->docCheckedSummary = 'Seleted: %total%.'; -$lang->doc->showDoc = 'Whether to display documents'; -$lang->doc->uploadFile = 'Upload File'; -$lang->doc->uploadDoc = 'Upload Document'; -$lang->doc->uploadFormat = 'Upload Format'; -$lang->doc->editedList = 'File editor'; -$lang->doc->moveTo = 'Move to'; -$lang->doc->notSupportExport = 'This document does not support export'; -$lang->doc->browseReportTemplate = 'Report Template Home'; -$lang->doc->browseReport = 'Report Home'; -$lang->doc->createReportTemplate = 'Create Report Template'; +$lang->doc->libName = 'Bibliothèque de Documents'; +$lang->doc->libType = 'Catégorie'; +$lang->doc->custom = 'Personnaliser Bibliothèque de Documents'; +$lang->doc->customAB = 'Person. Bib Doc'; +$lang->doc->createLib = 'Create Library'; +$lang->doc->createLibAction = 'Create Library'; +$lang->doc->createSpace = 'Create Space'; +$lang->doc->allLibs = 'Liste des Bibliothèque'; +$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Bibliothèque"; +$lang->doc->showFiles = 'Pièces Jointes'; +$lang->doc->editLib = 'Edit Document Library'; +$lang->doc->editSpaceAction = 'Edit Space'; +$lang->doc->editLibAction = 'Edit Library'; +$lang->doc->deleteSpaceAction = 'Delete Space'; +$lang->doc->deleteLibAction = 'Delete Library'; +$lang->doc->moveLibAction = 'Move Library'; +$lang->doc->moveDocAction = 'Move Document'; +$lang->doc->batchMove = 'Batch Move'; +$lang->doc->batchMoveDocAction = 'Batch Move Document'; +$lang->doc->fixedMenu = 'Coller au Menu'; +$lang->doc->removeMenu = 'Décoller du Menu'; +$lang->doc->search = 'Rechercher'; +$lang->doc->allCollections = 'All Collections'; +$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; +$lang->doc->sortLibs = 'Sort Libs'; +$lang->doc->titlePlaceholder = 'Veuillez saisir le titre'; +$lang->doc->confirm = 'Confirm'; +$lang->doc->docSummary = 'Total: %s.'; +$lang->doc->docCheckedSummary = 'Seleted: %total%.'; +$lang->doc->showDoc = 'Whether to display documents'; +$lang->doc->uploadFile = 'Upload File'; +$lang->doc->uploadDoc = 'Upload Document'; +$lang->doc->uploadFormat = 'Upload Format'; +$lang->doc->editedList = 'File editor'; +$lang->doc->moveTo = 'Move to'; +$lang->doc->notSupportExport = 'This document does not support export'; $lang->doc->preview = 'Preview'; $lang->doc->insertTitle = 'Insert %s list'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 8b2951478e..3a2b19d2bd 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -106,8 +106,6 @@ $lang->docTemplate->editedList = '模板编辑者'; $lang->docTemplate->content = '模板内容'; $lang->docTemplate->templateDesc = '模板描述'; $lang->docTemplate->status = '模板状态'; -$lang->docTemplate->noReportTemplate = '没有报告模板'; -$lang->docTemplate->createReportTemplate = '创建报告模板'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; @@ -279,45 +277,42 @@ $lang->doc->api = '接口'; $lang->doc->displaySetting = '显示设置'; $lang->doc->collectAction = '收藏文档'; -$lang->doc->libName = '库名称'; -$lang->doc->libType = '库类型'; -$lang->doc->custom = '自定义文档库'; -$lang->doc->customAB = '自定义库'; -$lang->doc->createLib = '创建库'; -$lang->doc->createLibAction = '创建库'; -$lang->doc->createSpace = '创建空间'; -$lang->doc->allLibs = '库列表'; -$lang->doc->objectLibs = "库文档详情"; -$lang->doc->showFiles = '附件库'; -$lang->doc->editLib = '编辑库'; -$lang->doc->editSpaceAction = '编辑空间'; -$lang->doc->editLibAction = '编辑库'; -$lang->doc->deleteSpaceAction = '删除空间'; -$lang->doc->deleteLibAction = '删除库'; -$lang->doc->moveLibAction = '移动库'; -$lang->doc->moveDocAction = '移动文档'; -$lang->doc->batchMove = '批量移动'; -$lang->doc->batchMoveDocAction = '批量移动文档'; -$lang->doc->fixedMenu = '固定到菜单栏'; -$lang->doc->removeMenu = '从菜单栏移除'; -$lang->doc->search = '搜索'; -$lang->doc->allCollections = '查看全部收藏文档'; -$lang->doc->keywordsTips = '多个关键字请用逗号分隔。'; -$lang->doc->sortLibs = '文档库排序'; -$lang->doc->titlePlaceholder = '在此输入标题'; -$lang->doc->confirm = '确认'; -$lang->doc->docSummary = '本页共 %s 个文档。'; -$lang->doc->docCheckedSummary = '共选中 %total% 个文档。'; -$lang->doc->showDoc = '是否显示文档'; -$lang->doc->uploadFile = '上传文件'; -$lang->doc->uploadDoc = '导入'; -$lang->doc->uploadFormat = '上传格式'; -$lang->doc->editedList = '文档编辑者'; -$lang->doc->moveTo = '移动至'; -$lang->doc->notSupportExport = '(此文档暂不支持导出)'; -$lang->doc->browseReportTemplate = '报告模板首页'; -$lang->doc->browseReport = '报告首页'; -$lang->doc->createReportTemplate = '创建报告模板'; +$lang->doc->libName = '库名称'; +$lang->doc->libType = '库类型'; +$lang->doc->custom = '自定义文档库'; +$lang->doc->customAB = '自定义库'; +$lang->doc->createLib = '创建库'; +$lang->doc->createLibAction = '创建库'; +$lang->doc->createSpace = '创建空间'; +$lang->doc->allLibs = '库列表'; +$lang->doc->objectLibs = "库文档详情"; +$lang->doc->showFiles = '附件库'; +$lang->doc->editLib = '编辑库'; +$lang->doc->editSpaceAction = '编辑空间'; +$lang->doc->editLibAction = '编辑库'; +$lang->doc->deleteSpaceAction = '删除空间'; +$lang->doc->deleteLibAction = '删除库'; +$lang->doc->moveLibAction = '移动库'; +$lang->doc->moveDocAction = '移动文档'; +$lang->doc->batchMove = '批量移动'; +$lang->doc->batchMoveDocAction = '批量移动文档'; +$lang->doc->fixedMenu = '固定到菜单栏'; +$lang->doc->removeMenu = '从菜单栏移除'; +$lang->doc->search = '搜索'; +$lang->doc->allCollections = '查看全部收藏文档'; +$lang->doc->keywordsTips = '多个关键字请用逗号分隔。'; +$lang->doc->sortLibs = '文档库排序'; +$lang->doc->titlePlaceholder = '在此输入标题'; +$lang->doc->confirm = '确认'; +$lang->doc->docSummary = '本页共 %s 个文档。'; +$lang->doc->docCheckedSummary = '共选中 %total% 个文档。'; +$lang->doc->showDoc = '是否显示文档'; +$lang->doc->uploadFile = '上传文件'; +$lang->doc->uploadDoc = '导入'; +$lang->doc->uploadFormat = '上传格式'; +$lang->doc->editedList = '文档编辑者'; +$lang->doc->moveTo = '移动至'; +$lang->doc->notSupportExport = '(此文档暂不支持导出)'; $lang->doc->preview = '预览'; $lang->doc->insertTitle = '插入%s列表'; diff --git a/module/doc/ui/browsereport.html.php b/module/doc/ui/browsereport.html.php deleted file mode 100644 index 0f0fd2feb0..0000000000 --- a/module/doc/ui/browsereport.html.php +++ /dev/null @@ -1,11 +0,0 @@ - - * @package doc - * @link https://www.zentao.net - */ -namespace zin; diff --git a/module/doc/ui/browsereporttemplate.html.php b/module/doc/ui/browsereporttemplate.html.php deleted file mode 100644 index 0e010f54b7..0000000000 --- a/module/doc/ui/browsereporttemplate.html.php +++ /dev/null @@ -1,14 +0,0 @@ - - * @package doc - * @link https://www.zentao.net - */ -namespace zin; - -if($mode == 'home' || !$libID) include './reporttemplatehome.html.php'; -else include './reporttemplatelist.html.php'; diff --git a/module/doc/ui/reporttemplatehome.html.php b/module/doc/ui/reporttemplatehome.html.php deleted file mode 100644 index 061fe83281..0000000000 --- a/module/doc/ui/reporttemplatehome.html.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @package doc - * @link https://www.zentao.net - */ -namespace zin; - -$scopeTemplates = array(2 => array(), 3 => array()); - -$scopeItems = array(); -unset($lang->docTemplate->scopes[1]); -unset($lang->docTemplate->scopes[4]); -foreach($lang->docTemplate->scopes as $scopeID => $scopeName) -{ - $scopeDocs = $scopeTemplates[$scopeID]; - $scopeItems[] = div - ( - setClass('doc-space-card ring rounded surface-light'), - div - ( - setClass('row items-center justify-between gap-2 px-2.5 py-1 border-b'), - div - ( - setClass('row items-center ml-2 flex-none'), - div - ( - setClass('min-w-0 flex-auto'), - strong($scopeName), - span(setClass('label ml-2 flex-none bg-white size-sm text-sm'), $lang->docTemplate->scopeLabel) - ), - ), - toolbar - ( - item(set(array - ( - 'data-app' => $app->tab, - 'type' => 'ghost', - 'caret' => 'right', - 'class' => 'text-primary', - 'text' => $lang->more, - 'url' => createLink('doc', 'browseReportTemplate', "libID=$scopeID&type=all&docID=0&orderBy=id_desc&recTotal=&recPerPae=20&pageID=1&mode=list") - ))) - ), - ), - div - ( - setClass('doc-space-card-libs py-3 px-1.5'), - div - ( - setClass('center gap-4 py-10'), - div - ( - setClass('text-gray'), - $lang->docTemplate->noReportTemplate - ), - hasPriv('doc', 'createReportTemplate') ? btn - ( - setClass('btn primary-pale'), - setData('app', $app->tab), - set::icon('plus'), - $lang->docTemplate->createReportTemplate, - set::url(createLink('doc', 'browseReportTemplate', "libID=$scopeID&type=all&docID=0&orderBy=&recTotal=&recPerPae=20&pageID=1&mode=create")) - ) : null - ) - ) - ); -} - -div -( - setClass('doc-home-body flex-auto min-h-0 col gap-4 p-4 items-stretch overflow-auto scrollbar-hover'), - $scopeItems -); diff --git a/module/group/lang/de.php b/module/group/lang/de.php index c464758a07..7de9bc1466 100644 --- a/module/group/lang/de.php +++ b/module/group/lang/de.php @@ -604,7 +604,5 @@ $lang->group->package->mangeApplication = 'Manage Service'; $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; -$lang->group->package->browseReportTemplate = 'Browse Report and Template'; -$lang->group->package->manageReportTemplate = 'Create and Manage Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/en.php b/module/group/lang/en.php index cee6f2476b..13ec6e7396 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -604,7 +604,5 @@ $lang->group->package->mangeApplication = 'Manage Service'; $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; -$lang->group->package->browseReportTemplate = 'Browse Report and Template'; -$lang->group->package->manageReportTemplate = 'Create and Manage Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/fr.php b/module/group/lang/fr.php index 4748047cee..096ab10ee6 100644 --- a/module/group/lang/fr.php +++ b/module/group/lang/fr.php @@ -604,7 +604,5 @@ $lang->group->package->mangeApplication = 'Manage Service'; $lang->group->package->trainPracticeLib = 'Practice Library'; $lang->group->package->application = 'Manage Application'; $lang->group->package->component = 'Component'; -$lang->group->package->browseReportTemplate = 'Browse Report and Template'; -$lang->group->package->manageReportTemplate = 'Create and Manage Report and Template'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 3a0d85745d..61e1f9e6cc 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1545,9 +1545,6 @@ $lang->resource->doc->addChapter = 'addChapter'; $lang->resource->doc->editChapter = 'editChapter'; $lang->resource->doc->sortChapter = 'sortChapter'; $lang->resource->doc->deleteChapter = 'deleteChapter'; -$lang->resource->doc->browseReportTemplate = 'browseReportTemplate'; -$lang->resource->doc->browseReport = 'browseReport'; -$lang->resource->doc->createReportTemplate = 'createReportTemplate'; $lang->doc->methodOrder[5] = 'index'; $lang->doc->methodOrder[10] = 'mySpace'; @@ -1581,9 +1578,6 @@ $lang->doc->methodOrder[160] = 'addChapter'; $lang->doc->methodOrder[170] = 'editChapter'; $lang->doc->methodOrder[180] = 'sortChapter'; $lang->doc->methodOrder[190] = 'deleteChapter'; -$lang->doc->methodOrder[195] = 'browseReportTemplate'; -$lang->doc->methodOrder[200] = 'browseReport'; -$lang->doc->methodOrder[205] = 'createReportTemplate'; /* Mail. */ $lang->resource->mail = new stdclass(); diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index 7412507915..082b95197b 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -604,7 +604,5 @@ $lang->group->package->mangeApplication = '管理服务'; $lang->group->package->trainPracticeLib = '实践库'; $lang->group->package->application = '管理应用'; $lang->group->package->component = '组件'; -$lang->group->package->browseReportTemplate = '浏览报告和模板'; -$lang->group->package->manageReportTemplate = '创建与维护报告和模板'; include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 08acfa8363..f8f96ca0fd 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -285,10 +285,6 @@ $config->group->subset->metric = new stdclass(); $config->group->subset->metric->order = 890; $config->group->subset->metric->nav = 'bi'; -$config->group->subset->reporttemplate = new stdclass(); -$config->group->subset->reporttemplate->order = 900; -$config->group->subset->reporttemplate->nav = 'bi'; - $config->group->subset->systemteam = new stdclass(); $config->group->subset->systemteam->order = 920; $config->group->subset->systemteam->nav = 'system'; @@ -3583,19 +3579,6 @@ $config->group->package->manageMetric->privs['metric-delist'] = array('edit $config->group->package->manageMetric->privs['metric-delete'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 45, 'depend' => array('metric-browse'), 'recommend' => array()); $config->group->package->manageMetric->privs['metric-recalculate'] = array('edition' => 'open,biz,max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); -$config->group->package->browseReportTemplate = new stdclass(); -$config->group->package->browseReportTemplate->order = 5; -$config->group->package->browseReportTemplate->subset = 'reporttemplate'; -$config->group->package->browseReportTemplate->privs = array(); -$config->group->package->browseReportTemplate->privs['doc-browseReportTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); -$config->group->package->browseReportTemplate->privs['doc-browseReport'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 10, 'depend' => array(), 'recommend' => array()); - -$config->group->package->manageReportTemplate = new stdclass(); -$config->group->package->manageReportTemplate->order = 5; -$config->group->package->manageReportTemplate->subset = 'reporttemplate'; -$config->group->package->manageReportTemplate->privs = array(); -$config->group->package->manageReportTemplate->privs['doc-createReportTemplate'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 5, 'depend' => array(), 'recommend' => array()); - $config->group->package->browseDoc = new stdclass(); $config->group->package->browseDoc->order = 10; $config->group->package->browseDoc->subset = 'doc'; From 3dbe8d68fae87c052fa782c2e7fdda8022dd496d Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 1 Apr 2025 10:53:41 +0800 Subject: [PATCH 327/655] * [task#140361,doing,0.2h] Change the language of docTemplate list. --- module/doc/lang/zh-cn.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 7884541e33..449ba1b8ec 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -79,9 +79,9 @@ $lang->docTemplate->title = '模板标题'; $lang->docTemplate->frequency = '频率'; $lang->docTemplate->type = '类型'; $lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建时间'; -$lang->docTemplate->editedBy = '最后修改者'; -$lang->docTemplate->editedDate = '最后修改时间'; +$lang->docTemplate->addedDate = '创建日期'; +$lang->docTemplate->editedBy = '修改者'; +$lang->docTemplate->editedDate = '修改日期'; $lang->docTemplate->views = '阅读次数'; $lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; $lang->docTemplate->scope = '所属范围'; From 9357b5cd8ea589ddad9866fdb6e4e22a854a3262 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 1 Apr 2025 05:51:03 +0000 Subject: [PATCH 328/655] * [task#140362,done,0.5h] Use data of document template. --- module/doc/ui/templatelist.html.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index cfae2a0345..db6e8ab7b5 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -79,6 +79,9 @@ $langData['actions']['deleteModule'] = $lang->docTemplate->deleteModule; $viewModeUrl = createLink('doc', 'browsetemplate', 'libID={libID}&type={filterType}&docID={docID}&orderBy={orderBy}&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}&mode={mode}'); +$config->doc->zentaoList = $config->docTemplate->zentaoList; +$lang->doc->zentaoData = $lang->docTemplate->zentaoData; + docApp ( set::data($data), @@ -102,8 +105,7 @@ docApp set::pager(array('recTotal' => count($templateList), 'recPerPage' => $recPerPage, 'page' => $pageID)), set('$options', jsRaw('window.setDocAppOptions')), set::showDocOutline(false), - set::hasModules($hasModules), - set::hasZentaoSlashMenu(false) + set::hasModules($hasModules) ); render(); From 7990860171d92b17d72066a861d2b201b4ba0b9d Mon Sep 17 00:00:00 2001 From: daitingting Date: Wed, 2 Apr 2025 01:19:14 +0000 Subject: [PATCH 329/655] * [task#140363,done,0.5h] Adjust modal size. --- lib/zin/wg/docapp/js/v1.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index 024071c72d..a3374f6821 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -20,7 +20,7 @@ window.setZentaoSlashMenu = function(menus, title, vision) menu.subMenu = menu.subMenu.map(subMenu => { subMenu.action = function (context) { zui.Modal.open({ - size: 'lg', + size: subMenu.modalSize ? subMenu.modalSize : 'lg', url: $.createLink(subMenu.module, subMenu.method, subMenu.params) }); } @@ -31,7 +31,7 @@ window.setZentaoSlashMenu = function(menus, title, vision) { menu.action = function (context) { zui.Modal.open({ - size: 'lg', + size: menu.modalSize ? menu.modalSize : 'lg', url: $.createLink(menu.module, menu.method, menu.params) }); } From 7c9dffc622568ee5111972b135bf9ec7e9bf04e7 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 2 Apr 2025 10:57:36 +0800 Subject: [PATCH 330/655] * [task#140360,doing,5h] Modify the template creation process. --- lib/zin/wg/docapp/js/v1.js | 6 +- module/doc/control.php | 1 + module/doc/js/browsetemplate.ui.js | 88 ++++++++++++++++++--- module/doc/ui/setdocbasic.template.html.php | 28 +++++-- 4 files changed, 102 insertions(+), 21 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index a3374f6821..3f47da8aa0 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -103,7 +103,7 @@ window.reloadZentaoList = function(blockID) * * @returns {object} */ -function getDocApp() +window.getDocApp = function() { if(!currentDocApp) { @@ -395,7 +395,7 @@ function mergeDocFormData(doc, formData) return doc; } -function showSaveFailedAlert(error) +window.showSaveFailedAlert = function(error) { zui.Modal.alert( { @@ -2048,7 +2048,7 @@ function getSortableOptions(type) } } -function checkResponse(res) +window.checkResponse = function(res) { if(typeof res === 'string') res = JSON.parse(res); if(typeof res !== 'object' || !res) return true; diff --git a/module/doc/control.php b/module/doc/control.php index 568f3c0b1f..81aa7c00e3 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -2293,6 +2293,7 @@ class doc extends control if($modalType == 'doc') { $title = $parentID ? $this->lang->doc->addSubDoc : $this->lang->doc->create; + if($objectType == 'template') $title = $this->lang->docTemplate->create; if($isDraft == 'no') $title = $this->lang->settings; } if($modalType == 'chapter') $title = $isCreate ? $this->lang->doc->addChapter : $this->lang->doc->editChapter; diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index b134ba3358..a666329bf9 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -1,4 +1,5 @@ const savingDocData = {}; +let docBasicModal = {}; /** * 获取文档界面上的表格初始化选项。 * Get the table initialization options on the doc UI. @@ -83,16 +84,42 @@ function mergeDocFormData(doc, formData) return doc; } -function showDocBasicModal(docID, isDraft = false) +function showDocBasicModal(parentID, docID, isDraft, modalType = 'doc') { const docApp = getDocApp(); - const spaceType = docApp.spaceType; const spaceID = docApp.spaceID; const libID = docApp.libID; const moduleID = docApp.moduleID; - isDraft = isDraft ? 'yes' : 'no'; - const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&docID=${docID}&isDraft=${isDraft}`); - zui.Modal.open({url: url}); + const url = $.createLink('doc', 'setDocBasic', `objectType=template&objectID=${spaceID}&libID=${libID}&moduleID=${moduleID}&parentID=${parentID || 0}&docID=${docID || 0}&isDraft=${isDraft ? 'yes' : 'no'}&modalType=${modalType}`); + + if(docBasicModal.doc === docID && docBasicModal.current) + { + docBasicModal.current.show(); + } + else + { + if(docBasicModal.current) docBasicModal.current.destroy(); + docBasicModal.doc = docID; + zui.Modal.open( + { + ref : docBasicModal, + url : url, + destroyOnHide: false, + cache : true, + request: { + error: error => { + if(docBasicModal.current) docBasicModal.current.hide(); + showSaveFailedAlert(error); + } + }, + onHidden: () => { + if(!docBasicModal.keepOnHide && docBasicModal.current) docBasicModal.current.destroy(); + }, + $onDestroy: () => { + if(docBasicModal.current) docBasicModal = {}; + } + }); + } return new Promise((resolve) => {window.docBasicModalResolver = resolve;}); } @@ -103,7 +130,7 @@ function showDocSettingModal(_, args) const docID = args[0] || doc.id; const docType = args[1] || doc.contentType; const saveEdited = args[2] || 0; - showDocBasicModal(docID).then(formData => { + showDocBasicModal(0, docID).then(formData => { savingDocData[docID] = formData; if(saveEdited == 1) { @@ -137,9 +164,14 @@ function showDocSettingModal(_, args) * @param {FormData} formData * @returns */ -function submitNewDoc(doc, spaceID, libID, moduleID, formData) +function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) { - const docApp = getDocApp(); + const docApp = getDocApp(); + + if(docApp.isSavingDoc) return; + docApp.isSavingDoc = true; + $(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').attr('disabled', true); + const spaceType = docApp.signals.spaceType.value; const module = docApp.treeMap.modules.get(moduleID); const url = $.createLink('doc', 'createTemplate', `libID=${libID}&moduleID=${moduleID}`); @@ -181,17 +213,34 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData) try { const data = JSON.parse(res); + if(!checkResponse(data)) return; if(typeof data !== 'object' || data.result === 'fail') { throw new Error(getErrorMessage(data)); } - resolve($.extend(doc, {id: data.id}, docData, data.doc, {status: doc.status || data.status})); + const newDoc = $.extend(doc, {id: data.id}, docData, data.doc, {status: doc.status || data.status}); + if (!newDoc.space.includes('.')) { + newDoc.space = `${spaceType}.${docData[spaceType]}`; + } + resolve(newDoc); + if(afterCreate) + { + docApp.load(null, null, null, {noLoading: true, picks: 'doc'}).then(() => { + afterCreate(newDoc); + }); + } } catch (error) { - zui.Modal.alert(error.message); + showSaveFailedAlert(error); reject(error); } + }).fail(error => { + resolve(false); + showSaveFailedAlert(error); + }).complete(() => { + docApp.isSavingDoc = false; + $(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').removeAttr('disabled'); }); }); } @@ -202,7 +251,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData) */ function handleCreateDoc(doc, spaceID, libID, moduleID) { - return showDocBasicModal(0, doc.status === 'draft').then((formData) => { + return showDocBasicModal(0, 0, doc.status === 'draft').then((formData) => { moduleID = parseInt(formData.get('module')); return submitNewDoc(doc, spaceID, libID, moduleID, formData); }); @@ -389,12 +438,25 @@ window.setDocAppOptions = function(_, options) // Override the method. /* 扩展文档模板命令定义。 Extend the doc app command definition. */ $.extend(window.docAppCommands, { - startCreateTemplate: function() + startCreateTemplate: function(_, args) { const docApp = getDocApp(); const hasModules = docApp.props.hasModules; if(!hasModules) return zui.Modal.alert(getLang('createTypeFirst')); - docApp.startCreateDoc(); + + const {spaceID, libID, moduleID} = docApp; + return showDocBasicModal(args?.[0] ?? 0, 0, true, 'doc').then((formData) => { + zui.Editor.loadModule().then(() => { + const emptyDoc = zui.Editor.createEmptyDoc(); + const snapshot = zui.Editor.toSnapshot(emptyDoc); + const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot)}; + return submitNewDoc(doc, 0, libID, moduleID, formData, (newDoc) => { + docApp.selectDoc(newDoc.id); + docApp.startEditDoc(newDoc.id); + }); + }); + + }); }, deleteDoc: function(_, args) { diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index a0dc725866..bb8756d7cd 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -24,10 +24,17 @@ formPanel setData('officeTypes', $this->config->doc->officeTypes), setData('docType', isset($doc) ? $doc->users : 'undefined'), set::title($title), - set::submitBtnText($isDraft ? $lang->doc->saveDraft : (empty($docID) ? $lang->doc->release : $lang->save)), + set::submitBtnText($lang->save), on::change('[name=lib]')->call('loadLibModules', jsRaw("event, 'docTemplate'")), set::ajax(array('beforeSubmit' => jsRaw('window.beforeSetDocBasicInfo'))), formGroup + ( + set::label($modalType == 'chapter' ? $lang->doc->chapterName : $lang->docTemplate->title), + set::name('title'), + set::required(true), + set::value(isset($doc) ? $doc->title : '') + ), + formGroup ( set::label($lang->docTemplate->scope), set::required(true), @@ -39,12 +46,23 @@ formPanel set::required(true), picker(set::name('module'), set::items($modules), set::value($moduleID), set::required(true)) ), + ($modalType != 'chapter' || !$isCreate) ? formGroup + ( + set::label($lang->doc->module), + picker + ( + set::name('parent'), + set::items($modalType != 'chapter' ? array('m_0' => '/') + $chapterAndDocs : $chapterAndDocs), + set::value($parentID ? $parentID : "m_$moduleID"), + set::required(true) + ), + ) : null, formGroup ( set::label($lang->docTemplate->desc), textarea(set::name('desc'), set::value($docID ? $doc->templateDesc : ''), set::rows(3)) ), - $isDraft ? null : formGroup + formGroup ( set::label($lang->doclib->control), radioList @@ -56,7 +74,7 @@ formPanel on::change('toggleWhiteList') ) ), - $isDraft ? null : formGroup + formGroup ( setID('whiteListBox'), setClass((isset($doc) && $libID == $doc->lib && $objectType != 'mine' && $doc->acl == 'private') ? '' : 'hidden'), @@ -67,7 +85,7 @@ formPanel inputGroup ( setClass('w-full'), - $lang->doc->groups, + $lang->doc->groupLabel, picker ( set::name('groups[]'), @@ -81,7 +99,7 @@ formPanel setClass('w-full'), userPicker ( - set::label($lang->doc->users), + set::label($lang->doc->userLabel), set::items($users), set::value(isset($doc) ? $doc->users : null) ) From 4e5ad4cd1f9ea2635d2214cff80c36821188ba5e Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 2 Apr 2025 14:32:11 +0800 Subject: [PATCH 331/655] * [task#140360,doing,1.5h] Set parent when create doc template. --- module/doc/control.php | 5 +++-- module/doc/model.php | 12 ++++++++---- module/doc/ui/setdocbasic.template.html.php | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 81aa7c00e3..28356f090e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -2298,9 +2298,10 @@ class doc extends control } if($modalType == 'chapter') $title = $isCreate ? $this->lang->doc->addChapter : $this->lang->doc->editChapter; - $chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID); - $modulePairs = empty($libID) || $modalType == 'chapter' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0); + $chapterAndDocs = $this->doc->getDocsOfLibs(array($libID), $objectType, $docID, $objectType == 'template' ? true : false); + if($objectType == 'template' && !empty($moduleID)) $chapterAndDocs = array_filter($chapterAndDocs, fn($docInfo) => $docInfo->module == $moduleID); if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent); + $modulePairs = empty($libID) || $modalType == 'chapter' || $objectType == 'template' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0); $chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs); $this->view->chapterAndDocs = $chapterAndDocs; diff --git a/module/doc/model.php b/module/doc/model.php index 64aa218543..62c2c3834b 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -757,18 +757,21 @@ class docModel extends model * @param array $libs * @param string $spaceType * @param int $excludeID + * @param bool $queryTemplate * @access public * @return array */ - public function getDocsOfLibs(array $libs, string $spaceType, int $excludeID = 0): array + public function getDocsOfLibs(array $libs, string $spaceType, int $excludeID = 0, $queryTemplate = false): array { $docs = $this->dao->select('t1.*')->from(TABLE_DOC)->alias('t1') ->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module=t2.id') ->where('t1.lib')->in($libs) ->andWhere('t1.vision')->eq($this->config->vision) - ->andWhere('t1.templateType')->eq('') + ->beginIF(!$queryTemplate)->andWhere('t1.templateType')->eq('')->fi() + ->beginIF($queryTemplate)->andWhere('t1.templateType')->ne('')->fi() + ->beginIF(!$queryTemplate)->andWhere('t2.type')->eq('doc')->fi() + ->beginIF($queryTemplate)->andWhere('t2.type')->eq('docTemplate')->fi() ->andWhere("(t1.status = 'normal' or (t1.status = 'draft' and t1.addedBy='{$this->app->user->account}'))") - ->andWhere('t2.type')->eq('doc') ->andWhere('t2.deleted')->eq('0') ->beginIF(!empty($excludeID))->andWhere("NOT FIND_IN_SET('{$excludeID}', t1.`path`)")->andWhere('t1.id')->ne($excludeID)->fi() ->orderBy('t1.`order` asc, t1.id asc') @@ -777,7 +780,8 @@ class docModel extends model $rootDocs = $this->dao->select('*')->from(TABLE_DOC) ->where('lib')->in($libs) ->andWhere('vision')->eq($this->config->vision) - ->andWhere('templateType')->eq('') + ->beginIF(!$queryTemplate)->andWhere('templateType')->eq('')->fi() + ->beginIF($queryTemplate)->andWhere('templateType')->ne('')->fi() ->andWhere("(status = 'normal' or (status = 'draft' and addedBy='{$this->app->user->account}'))") ->andWhere('module')->in(array('0', '')) ->beginIF(!empty($excludeID))->andWhere("NOT FIND_IN_SET('{$excludeID}', `path`)")->andWhere('id')->ne($excludeID)->fi() diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index bb8756d7cd..a1f5405497 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -52,7 +52,7 @@ formPanel picker ( set::name('parent'), - set::items($modalType != 'chapter' ? array('m_0' => '/') + $chapterAndDocs : $chapterAndDocs), + set::items($modalType != 'chapter' ? array(0 => '/') + $chapterAndDocs : $chapterAndDocs), set::value($parentID ? $parentID : "m_$moduleID"), set::required(true) ), From c6bb39a0dafe7a4daea671e4d2277c72644221ea Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 3 Apr 2025 02:57:14 +0000 Subject: [PATCH 332/655] * [task#140364,doing,2h] Adjust template block. --- module/doc/control.php | 14 ++++++++++++++ module/doc/ui/zentaolist.html.php | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 28356f090e..81945a258d 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -164,6 +164,20 @@ class doc extends control return $this->sendError($this->lang->notFound); } + $doc = $this->doc->getByID($blockData->doc); + $this->view->isTemplate = !empty($doc->templateType); + + if($doc->templateType) + { + $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]); + $this->view->type = $type; + $this->view->blockID = $blockID; + $this->view->settings = $blockData->settings; + $this->view->searchTab = $blockData->content->searchTab; + + return $this->display(); + } + $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]); $this->view->type = $type; $this->view->settings = $blockData->settings; diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index c05545a5f1..428cd31902 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -10,11 +10,14 @@ declare(strict_types=1); */ namespace zin; -jsVar('blockType', $type); -if(strpos(',productStory,ER,UR,planStory,projectStory,',",{$type},") !== false) +if(!$isTemplate) { - jsVar('gradeGroup', $gradeGroup); - if($type != 'planStory' && $type != 'projectStory') jsVar('storyType', $storyType); + jsVar('blockType', $type); + if(strpos(',productStory,ER,UR,planStory,projectStory,',",{$type},") !== false) + { + jsVar('gradeGroup', $gradeGroup); + if($type != 'planStory' && $type != 'projectStory') jsVar('storyType', $storyType); + } } $actions = array(); @@ -34,7 +37,7 @@ div h2 ( setClass('font-bold text-xl'), - $lang->doc->zentaoList[$type] . $lang->doc->list + ($isTemplate ? $lang->docTemplate->searchTabList[$type][$searchTab] : '') . $lang->doc->zentaoList[$type] . $lang->doc->list ), div ( @@ -48,7 +51,10 @@ div ) ) ), - dtable + $isTemplate ? div + ( + ):null, + !$isTemplate ? dtable ( set::cols(array_values($cols)), set::data(array_values($data)), @@ -60,5 +66,5 @@ div set::onRenderCell(jsRaw('window.renderCell')), $type == 'productRelease' ? set::plugins(array('cellspan')) : null, $type == 'productRelease' ? set::getCellSpan(jsRaw('window.getCellSpan')) : null - ) + ) : null ); From e3db1704acbb69ca7b6bf2b4e5227203e88d6f0d Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 3 Apr 2025 03:21:21 +0000 Subject: [PATCH 333/655] * [task#140364,done,1h] Set zentao config tip. --- module/doc/ui/zentaolist.html.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 428cd31902..296a79be42 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -53,6 +53,12 @@ div ), $isTemplate ? div ( + setClass('canvas border rounded py-3 px-3'), + div + ( + setClass('secondary-pale text-center px-3 py-2'), + $lang->docTemplate->configTip + ) ):null, !$isTemplate ? dtable ( From 64470aa55fa9fc5d30f6b9f9b92b05eb8621bf9f Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 3 Apr 2025 13:42:40 +0800 Subject: [PATCH 334/655] * [task#140367,doing,0.2h] Change block title of overdue bug. --- module/doc/lang/de.php | 2 ++ module/doc/lang/en.php | 2 ++ module/doc/lang/fr.php | 2 ++ module/doc/lang/zh-cn.php | 2 ++ module/doc/ui/zentaolist.html.php | 8 +++++++- 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 11187ee321..67e5884b71 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -115,6 +115,8 @@ $lang->docTemplate->more = 'More'; $lang->docTemplate->scopeLabel = 'Scope'; $lang->docTemplate->noTemplate = 'No Doc Template'; $lang->docTemplate->noDesc = 'No Desc'; +$lang->docTemplate->of = ' of '; +$lang->docTemplate->overdue = 'Overdue'; $lang->docTemplate->addModule = 'Add Template type'; $lang->docTemplate->addSameModule = 'Add Same Template type'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 110b4dc805..6b40dd2117 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -115,6 +115,8 @@ $lang->docTemplate->more = 'More'; $lang->docTemplate->scopeLabel = 'Scope'; $lang->docTemplate->noTemplate = 'No Doc Template'; $lang->docTemplate->noDesc = 'No Desc'; +$lang->docTemplate->of = ' of '; +$lang->docTemplate->overdue = 'Overdue'; $lang->docTemplate->addModule = 'Add Template type'; $lang->docTemplate->addSameModule = 'Add Same Template type'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 268adc52f1..405acdb257 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -115,6 +115,8 @@ $lang->docTemplate->more = 'More'; $lang->docTemplate->scopeLabel = 'Scope'; $lang->docTemplate->noTemplate = 'No Doc Template'; $lang->docTemplate->noDesc = 'No Desc'; +$lang->docTemplate->of = ' of '; +$lang->docTemplate->overdue = 'Overdue'; $lang->docTemplate->addModule = 'Add Template type'; $lang->docTemplate->addSameModule = 'Add Same Template type'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 449ba1b8ec..b36b1f3120 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -111,6 +111,8 @@ $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; $lang->docTemplate->noTemplate = '没有文档模板'; $lang->docTemplate->noDesc = '暂时没有描述'; +$lang->docTemplate->of = '的'; +$lang->docTemplate->overdue = '已过期'; $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 296a79be42..cf0af4c039 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -24,6 +24,12 @@ $actions = array(); $actions[] = array('icon' => 'menu-backend', 'text' => $lang->doc->zentaoAction['set'], 'data-toggle' => 'modal', 'url' => str_replace('{blockID}', "$blockID", $settings), 'data-size' => 'lg'); $actions[] = array('icon' => 'trash', 'text' => $lang->doc->zentaoAction['delete'], 'zui-on-click' => "deleteZentaoList($blockID)"); +if($isTemplate) +{ + $blockTitle = $lang->docTemplate->searchTabList[$type][$searchTab]; + if($type == 'bug' && $searchTab == 'overduebugs') $blockTitle = $lang->docTemplate->overdue; +} + div ( set('data-id', $blockID), @@ -37,7 +43,7 @@ div h2 ( setClass('font-bold text-xl'), - ($isTemplate ? $lang->docTemplate->searchTabList[$type][$searchTab] : '') . $lang->doc->zentaoList[$type] . $lang->doc->list + ($isTemplate ? $blockTitle . $lang->docTemplate->of : '') . $lang->doc->zentaoList[$type] . $lang->doc->list ), div ( From 0b1ae7ae63c0f899870bd65eb39e42016e38998c Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 3 Apr 2025 06:04:36 +0000 Subject: [PATCH 335/655] * [task#140364,done,0,5h] Adjust color and modal size. --- module/doc/css/zentaolist.ui.css | 1 + module/doc/ui/zentaolist.html.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/doc/css/zentaolist.ui.css b/module/doc/css/zentaolist.ui.css index e69de29bb2..000271ecc1 100644 --- a/module/doc/css/zentaolist.ui.css +++ b/module/doc/css/zentaolist.ui.css @@ -0,0 +1 @@ +.config-tip{background-color: var(--color-surface-light); color: var(--color-gray-400)} diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index cf0af4c039..435e38bb21 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -21,7 +21,7 @@ if(!$isTemplate) } $actions = array(); -$actions[] = array('icon' => 'menu-backend', 'text' => $lang->doc->zentaoAction['set'], 'data-toggle' => 'modal', 'url' => str_replace('{blockID}', "$blockID", $settings), 'data-size' => 'lg'); +$actions[] = array('icon' => 'menu-backend', 'text' => $lang->doc->zentaoAction['set'], 'data-toggle' => 'modal', 'url' => str_replace('{blockID}', "$blockID", $settings), 'data-size' => $isTemplate ? 'sm' : 'lg'); $actions[] = array('icon' => 'trash', 'text' => $lang->doc->zentaoAction['delete'], 'zui-on-click' => "deleteZentaoList($blockID)"); if($isTemplate) @@ -62,7 +62,7 @@ div setClass('canvas border rounded py-3 px-3'), div ( - setClass('secondary-pale text-center px-3 py-2'), + setClass('config-tip text-center px-3 py-2'), $lang->docTemplate->configTip ) ):null, From 6e318883d515769c9de3012568677fa95fd6f8f9 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 3 Apr 2025 14:04:00 +0800 Subject: [PATCH 336/655] * [task#140366,doing,0.2h] Set block title for case list. --- module/doc/control.php | 2 ++ module/doc/ui/zentaolist.html.php | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 81945a258d..6d946d57d5 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -175,6 +175,8 @@ class doc extends control $this->view->settings = $blockData->settings; $this->view->searchTab = $blockData->content->searchTab; + if($type == 'case') $this->view->caseStage = $blockData->content->caseStage; + return $this->display(); } diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 435e38bb21..9a10470b38 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -26,8 +26,9 @@ $actions[] = array('icon' => 'trash', 'text' => $lang->doc->zentaoAction['delete if($isTemplate) { - $blockTitle = $lang->docTemplate->searchTabList[$type][$searchTab]; - if($type == 'bug' && $searchTab == 'overduebugs') $blockTitle = $lang->docTemplate->overdue; + $blockTitle = $lang->docTemplate->searchTabList[$type][$searchTab] . $lang->docTemplate->of; + if($type == 'bug' && $searchTab == 'overduebugs') $blockTitle = $lang->docTemplate->overdue . $lang->docTemplate->of; + if($type == 'case' && !empty($caseStage)) $blockTitle = $blockTitle . $lang->testcase->stageList[$caseStage]; } div @@ -43,7 +44,7 @@ div h2 ( setClass('font-bold text-xl'), - ($isTemplate ? $blockTitle . $lang->docTemplate->of : '') . $lang->doc->zentaoList[$type] . $lang->doc->list + ($isTemplate ? $blockTitle : '') . $lang->doc->zentaoList[$type] . $lang->doc->list ), div ( From 07c9f8b5f545cf162d4fcf9244eaf69b2ac06da7 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 3 Apr 2025 15:51:03 +0800 Subject: [PATCH 337/655] * [task#140503,doing,0.5h] Set the config for design. --- module/doc/control.php | 2 +- module/doc/ui/zentaolist.html.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 6d946d57d5..939c75e24f 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -169,7 +169,7 @@ class doc extends control if($doc->templateType) { - $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]); + $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]); $this->view->type = $type; $this->view->blockID = $blockID; $this->view->settings = $blockData->settings; diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 9a10470b38..82635a21e5 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -44,7 +44,7 @@ div h2 ( setClass('font-bold text-xl'), - ($isTemplate ? $blockTitle : '') . $lang->doc->zentaoList[$type] . $lang->doc->list + ($isTemplate ? $blockTitle . $lang->docTemplate->zentaoList[$type] : $lang->doc->zentaoList[$type]) . $lang->doc->list ), div ( From ad141750ed504442d76077f1efd546bf554fe8c4 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 7 Apr 2025 10:45:54 +0800 Subject: [PATCH 338/655] * [task#140360] Get moduleID form formData when moduleID is empty. --- module/doc/js/browsetemplate.ui.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index a666329bf9..1fbdf1f068 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -173,7 +173,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) $(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').attr('disabled', true); const spaceType = docApp.signals.spaceType.value; - const module = docApp.treeMap.modules.get(moduleID); + const module = docApp.treeMap.modules.get(formData && moduleID === 0 ? parseInt(formData.get('module')) : moduleID); const url = $.createLink('doc', 'createTemplate', `libID=${libID}&moduleID=${moduleID}`); const docData = { @@ -188,7 +188,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) acl : 'private', space : spaceType, project : 0, - templateType: module.data.short, + templateType: module && module.data ? module.data.short : '', uid : (doc.uid || `doc${doc.id}`), }; if(formData) mergeDocFormData(docData, formData); From 3bfd77726bd0071dca7f0e9ef6bae16137154071 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 7 Apr 2025 14:28:28 +0800 Subject: [PATCH 339/655] * [task#140360] Set module name for doc template list. --- module/doc/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index 905049b982..e3f042451b 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -522,7 +522,6 @@ class doc extends control { $this->lang->doc->menu->template['alias'] .= ',' . $this->app->rawMethod; $libModules = $this->doc->getTemplateModules($libID); - $libModules = array_column($libModules, 'fullName', 'id'); if($mode == 'create' && empty($libModules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst))); $this->app->loadClass('pager', true); @@ -530,6 +529,7 @@ class doc extends control $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy, $pager); $templateList = $this->doc->filterPrivDocs($templateList, 'template'); $allModules = $this->doc->getTemplateModules(); + $allModules = array_column($allModules, 'fullName', 'id'); foreach($templateList as $template) $template->moduleName = zget($allModules, $template->module); $this->view->title = $this->lang->doc->template; From b96fb5c143d5fdd4a847d173c2fc3f51d9bcac16 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 9 Apr 2025 13:02:17 +0800 Subject: [PATCH 340/655] * [task#141096,#141097] Set block title for productCase and projectCase block. --- module/doc/control.php | 2 +- module/doc/ui/zentaolist.html.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 77749b275b..21d36b403b 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -175,7 +175,7 @@ class doc extends control $this->view->settings = $blockData->settings; $this->view->searchTab = $blockData->content->searchTab; - if($type == 'case') $this->view->caseStage = $blockData->content->caseStage; + if($type == 'productCase' || $type == 'projectCase') $this->view->caseStage = $blockData->content->caseStage; return $this->display(); } diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 82635a21e5..184aec41ba 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -28,7 +28,7 @@ if($isTemplate) { $blockTitle = $lang->docTemplate->searchTabList[$type][$searchTab] . $lang->docTemplate->of; if($type == 'bug' && $searchTab == 'overduebugs') $blockTitle = $lang->docTemplate->overdue . $lang->docTemplate->of; - if($type == 'case' && !empty($caseStage)) $blockTitle = $blockTitle . $lang->testcase->stageList[$caseStage]; + if(($type == 'productCase' || $type == 'projectCase') && !empty($caseStage)) $blockTitle = $blockTitle . $lang->testcase->stageList[$caseStage]; } div From db0d65b96898a13248a3c154456ebe76c70eda8a Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 10 Apr 2025 09:59:54 +0800 Subject: [PATCH 341/655] * [bug#61272] Set doc template priv when get template list. --- module/doc/control.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/control.php b/module/doc/control.php index 21d36b403b..3bea145692 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -2152,6 +2152,7 @@ class doc extends control $modules = $this->doc->getTemplateModules(); $moduleNames = array_column($modules, 'fullName', 'id'); $templateList = $this->doc->getDocTemplateList(0, 'all'); + $templateList = $this->doc->filterPrivDocs($templateList, 'template'); foreach($templateList as $template) { $template->moduleName = zget($moduleNames, $template->module); From 3c7b8d483f882bffcd5329d1711426367392719d Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 10 Apr 2025 13:55:28 +0800 Subject: [PATCH 342/655] * [task#141194,doing,0.1h] Change the function to window. --- lib/zin/wg/docapp/js/v1.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index e33300cba2..4b39f7a8fa 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -144,7 +144,7 @@ window.getLang = function(key, args) * Check if the specified privilege exists, privileges are defined in $privs in module/doc/ui/app.html.php. * @param {string} priv */ -function hasPriv(priv, value) +window.hasPriv = function(priv, value) { const setting = userPrivs[priv]; return value !== undefined ? setting === value : !!setting; @@ -216,7 +216,7 @@ function processDocAppAction(action, docApp) * * @param {object|number} space */ -function canModifySpace(space) +window.canModifySpace = function(space) { const docApp = getDocApp(); if(!docApp && !space) return false; From 68c9d0c602aa9531d5f1c45688f9cdc9fe30f670 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 11 Apr 2025 03:24:44 +0000 Subject: [PATCH 343/655] * [misc] Check template type. --- module/doc/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/control.php b/module/doc/control.php index 3bea145692..c4040416ba 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -167,7 +167,7 @@ class doc extends control $doc = $this->doc->getByID($blockData->doc); $this->view->isTemplate = !empty($doc->templateType); - if($doc->templateType) + if(!empty($doc->templateType)) { $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]); $this->view->type = $type; From 8622459e7207989f6deaabda3c9956b212ef280f Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 11 Apr 2025 03:27:22 +0000 Subject: [PATCH 344/655] * [bug] Save rawContent. --- module/doc/js/browsetemplate.ui.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 1fbdf1f068..0e1a2e5bb9 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -70,6 +70,16 @@ function getTableOptions(options, info) return options; } +/** + * Replace all emoji to ?? to prevent data loss in mysql. + * 替换所有表情符号为 ?? 以防止 mysql 数据丢失。 + */ +function removeEmoji(text) +{ + if(typeof text !== 'string') return text; + return text.replace(/[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}]/ug, '??'); +} + function mergeDocFormData(doc, formData) { if(!doc || !formData) return; @@ -177,7 +187,8 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) const url = $.createLink('doc', 'createTemplate', `libID=${libID}&moduleID=${moduleID}`); const docData = { - content : doc.content, + rawContent : removeEmoji(doc.content), + content : removeEmoji(doc.html), status : doc.status || 'normal', contentType : doc.contentType, type : 'text', @@ -269,7 +280,7 @@ function handleSaveDoc(doc) const moduleID = docApp.signals.moduleID.value; const url = $.createLink('doc', 'editTemplate', `docID=${doc.id}`); const docData = { - content : doc.content, + rawContent : removeEmoji(doc.content), status : doc.status || 'normal', contentType: doc.contentType, type : 'text', @@ -278,6 +289,7 @@ function handleSaveDoc(doc) title : doc.title, keywords : doc.keywords, acl : doc.acl, + content : removeEmoji(doc.html), space : spaceType, uid : (doc.uid || `doc${doc.id}`), }; From 572e7df4d1b383a450d6eaa6708934cb1722075e Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 11 Apr 2025 03:30:04 +0000 Subject: [PATCH 345/655] * [bug#61397,done,1h] Response after edit. --- module/doc/js/browsetemplate.ui.js | 39 ++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 0e1a2e5bb9..1b0cc3010e 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -309,14 +309,27 @@ function handleSaveDoc(doc) try { const data = JSON.parse(res); + if(!checkResponse(data)) return; if(typeof data !== 'object' || data.result === 'fail') { let message = data.message || data.error || getLang('errorOccurred'); if(typeof message === 'object') message = Object.values(message).map(x => Array.isArray(x) ? x.join('\n') : x).join('\n'); throw new Error(message); } - docApp.update('doc', $.extend({}, doc, docData, data.doc)); - resolve(true); + + doc = $.extend({}, doc, docData, data.doc); + const libID = +doc.lib; + const lib = docApp.getLib(libID); + if(!lib) + { + resolve(false); + return loadPage($.createLink('doc', 'view', `docID=${doc.id}`)); + } + + delete doc.title; + delete doc.keywords; + delete doc.content; + resolve(doc); } catch (error) { @@ -324,6 +337,28 @@ function handleSaveDoc(doc) if(!error.message) return; zui.Modal.alert(error.message); } + }).fail(error => { + resolve(false); + showSaveFailedAlert(error); + }).complete(() => { + docApp.isSavingDoc = false; + $(docApp.element).find('[zui-command^="saveDoc"],[zui-command^="saveNewDoc"]').removeAttr('disabled'); + const {id, acl, users, addedBy} = doc; + if(acl == 'private' && !users.includes(currentUser) && addedBy !== currentUser) + { + if(docApp.hasEditingDoc) + { + docApp.cancelEditDoc().then(() => { + docApp.delete('doc', id); + docApp.load(null, null, null, {noLoading: true, picks: 'doc'}); + }); + } + else + { + docApp.delete('doc', id); + docApp.load(null, null, null, {noLoading: true, picks: 'doc'}); + } + } }); }); } From 606192e75c863b895eda0b72b1c59c4d9397a0c8 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 11 Apr 2025 05:20:13 +0000 Subject: [PATCH 346/655] * [misc] Remove useless codes. --- module/doc/js/browsetemplate.ui.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 1b0cc3010e..038f2c228c 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -70,16 +70,6 @@ function getTableOptions(options, info) return options; } -/** - * Replace all emoji to ?? to prevent data loss in mysql. - * 替换所有表情符号为 ?? 以防止 mysql 数据丢失。 - */ -function removeEmoji(text) -{ - if(typeof text !== 'string') return text; - return text.replace(/[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}]/ug, '??'); -} - function mergeDocFormData(doc, formData) { if(!doc || !formData) return; @@ -187,8 +177,8 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) const url = $.createLink('doc', 'createTemplate', `libID=${libID}&moduleID=${moduleID}`); const docData = { - rawContent : removeEmoji(doc.content), - content : removeEmoji(doc.html), + rawContent : doc.content, + content : doc.html, status : doc.status || 'normal', contentType : doc.contentType, type : 'text', @@ -280,7 +270,7 @@ function handleSaveDoc(doc) const moduleID = docApp.signals.moduleID.value; const url = $.createLink('doc', 'editTemplate', `docID=${doc.id}`); const docData = { - rawContent : removeEmoji(doc.content), + rawContent : doc.content, status : doc.status || 'normal', contentType: doc.contentType, type : 'text', @@ -289,7 +279,7 @@ function handleSaveDoc(doc) title : doc.title, keywords : doc.keywords, acl : doc.acl, - content : removeEmoji(doc.html), + content : doc.html, space : spaceType, uid : (doc.uid || `doc${doc.id}`), }; From fd25ea352d52b547acc23188688d2d98bef91802 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 14 Apr 2025 13:17:53 +0800 Subject: [PATCH 347/655] * [task#141198,doing,0.5h] Search template by name. --- module/doc/js/browsetemplate.ui.js | 1 - module/doc/model.php | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 038f2c228c..30bd9f1bbb 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -492,7 +492,6 @@ $.extend(window.docAppCommands, docApp.startEditDoc(newDoc.id); }); }); - }); }, deleteDoc: function(_, args) diff --git a/module/doc/model.php b/module/doc/model.php index ab5f058aa0..8b38679230 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -653,10 +653,11 @@ class docModel extends model * @param string $type * @param string $orderBy * @param object $pager + * @param string $searchName * @access public * @return array */ - public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = null): array + public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = null, string $searchName = ''): array { return $this->dao->select('*')->from(TABLE_DOC) ->where('deleted')->eq('0') @@ -666,6 +667,7 @@ class docModel extends model ->beginIF($type == 'draft')->andWhere('status')->eq('draft')->fi() ->beginIF($type == 'released')->andWhere('status')->eq('normal')->fi() ->beginIF($type == 'createdByMe')->andWhere('addedBy')->eq($this->app->user->account)->fi() + ->beginIF($searchName)->andWhere('title')->like("%{$searchName}%")->fi() ->orderBy($orderBy) ->page($pager) ->fetchAll('', false); From 4d98cb1efd5074f7c95c46b2cec3c094966e5cf3 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 08:33:45 +0800 Subject: [PATCH 348/655] * [misc] Add the auto test for the function of addTemplateType. --- module/doc/test/lib/doc.unittest.class.php | 67 ++++++++++++++++++++++ module/doc/test/model/addtemplatetype.php | 51 ++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100755 module/doc/test/model/addtemplatetype.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index e3f1ca0e62..11f4f9ec01 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1439,4 +1439,71 @@ class docTest return $this->objectModel->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($docID)->andWhere('version')->eq($doc->version + 1)->fetch(); } + + /** + * 获取文档库的文档列表。 + * Get doc list. + * + * @param array $libs + * @param string $spaceType + * @param int $excludeID + * @access public + * @return array + */ + public function getDocsOfLibsTest(array $libs, string $spaceType, int $excludeID = 0): array + { + $docs = $this->objectModel->getDocsOfLibs($libs, $spaceType, $excludeID); + if(dao::isError()) return dao::getError(); + return $docs; + } + + /** + * 获取文档模板列表。 + * Get doc template list. + * + * @param int $libID + * @param string $type + * @param string $orderBy + * @param string $searchName + * @access public + * @return array + */ + public function getDocTemplateListTest(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', string $searchName = ''): array + { + $templates = $this->objectModel->getDocTemplateList($libID, $type, $orderBy, null, $searchName); + if(dao::isError()) return dao::getError(); + return $templates; + } + + /** + * 添加文档模板类型。 + * Add the type of template lis. + * + * @param array $moduleData + * @access public + * @return object + */ + public function addTemplateTypeTest(array $moduleData) + { + $module = new stdClass(); + foreach($moduleData as $field => $value) $module->{$field} = $value; + $moduleID = $this->objectModel->addTemplateType($module); + return $this->objectModel->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch(); + } + + /** + * 获取某个模板类型下的所有模板。 + * Get template list by type. + * + * @param int|null $type + * @param string $status + * @access public + * @return int + */ + public function getTemplatesByTypeTest($type = null, $status = 'all') + { + $templates = $this->objectModel->getTemplatesByType($type, $status); + if(dao::isError()) return dao::getError(); + return $templates; + } } diff --git a/module/doc/test/model/addtemplatetype.php b/module/doc/test/model/addtemplatetype.php new file mode 100755 index 0000000000..55a2a70a2e --- /dev/null +++ b/module/doc/test/model/addtemplatetype.php @@ -0,0 +1,51 @@ +#!/usr/bin/env php +addTemplateType(); +timeout=0 +cid=1 + +- 添加产品模板类型 + - 属性short @custom1 + - 属性path @,1, +- 添加产品子模板类型 + - 属性short @custom2 + - 属性path @,1,2, +- 添加项目模板类型 + - 属性short @custom3 + - 属性path @,3, +- 添加项目子模板类型 + - 属性short @custom4 + - 属性path @,3,4, +- 添加执行模板类型 + - 属性short @custom5 + - 属性path @,5, +- 添加执行子模板类型 + - 属性short @custom6 + - 属性path @,5,6, + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('module')->gen(0); +zenData('user')->gen(5); +su('admin'); + +$productModule = array('name' => '产品计划', 'root' => 1, 'grade' => 1, 'order' => 10, 'type' => 'doctemplate'); +$productSubModule = array('name' => '软件产品计划', 'root' => 1, 'grade' => 2, 'order' => 20, 'type' => 'doctemplate', 'parent' => 1); +$projectModule = array('name' => '项目计划', 'root' => 2, 'grade' => 1, 'order' => 10, 'type' => 'doctemplate'); +$projectSubModule = array('name' => '质量保证计划', 'root' => 2, 'grade' => 2, 'order' => 20, 'type' => 'doctemplate', 'parent' => 3); +$executionModule = array('name' => '开发计划', 'root' => 3, 'grade' => 1, 'order' => 10, 'type' => 'doctemplate'); +$executionSubModule = array('name' => '软件需求说明书', 'root' => 3, 'grade' => 2, 'order' => 20, 'type' => 'doctemplate', 'parent' => 5); + +$docTester = new docTest(); +r($docTester->addTemplateTypeTest($productModule)) && p('short|path', '|') && e('custom1|,1,'); // 添加产品模板类型 +r($docTester->addTemplateTypeTest($productSubModule)) && p('short|path', '|') && e('custom2|,1,2,'); // 添加产品子模板类型 +r($docTester->addTemplateTypeTest($projectModule)) && p('short|path', '|') && e('custom3|,3,'); // 添加项目模板类型 +r($docTester->addTemplateTypeTest($projectSubModule)) && p('short|path', '|') && e('custom4|,3,4,'); // 添加项目子模板类型 +r($docTester->addTemplateTypeTest($executionModule)) && p('short|path', '|') && e('custom5|,5,'); // 添加执行模板类型 +r($docTester->addTemplateTypeTest($executionSubModule)) && p('short|path', '|') && e('custom6|,5,6,'); // 添加执行子模板类型 From 7ad4f4adaa231a7cf8c23eee11cf08b2b717752d Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 08:34:43 +0800 Subject: [PATCH 349/655] * [misc] Add the auto test of the function of getDocsOfLibs. --- module/doc/test/model/getdocsoflibs.php | 48 +++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 module/doc/test/model/getdocsoflibs.php diff --git a/module/doc/test/model/getdocsoflibs.php b/module/doc/test/model/getdocsoflibs.php new file mode 100644 index 0000000000..f5775932f0 --- /dev/null +++ b/module/doc/test/model/getdocsoflibs.php @@ -0,0 +1,48 @@ +#!/usr/bin/env php +getDocsOfLibs(); +timeout=0 +cid=1 + +- 获取产品库26下的文档列表 + - 第41条的lib属性 @26 + - 第41条的title属性 @产品文档41 +- 获取项目库18下的文档列表 + - 第31条的lib属性 @18 + - 第31条的title属性 @项目文档31 +- 获取我的文档库11下的文档列表 + - 第1条的lib属性 @11 + - 第1条的title属性 @我的文档1 +- 获取产品库26下排除文档41的文档列表 + - 第42条的lib属性 @26 + - 第42条的title属性 @产品文档42 +- 获取项目库18下排除文档31的文档列表 + - 第32条的lib属性 @18 + - 第32条的title属性 @项目文档32 +- 获取我的文档库11下排除文档1的文档列表 + - 第2条的lib属性 @11 + - 第2条的title属性 @我的文档2 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('doc')->gen(50); +zenData('user')->gen(5); +su('admin'); + +$libs = array(array(26), array(18), array(11)); +$spaceType = array('product', 'project', 'mine'); +$excludeID = array(0, 41, 31, 1); + +$docTester = new docTest(); +r($docTester->getDocsOfLibsTest($libs[0], $spaceType[0], $excludeID[0])) && p('41:lib,title') && e('26,产品文档41'); // 获取产品库26下的文档列表 +r($docTester->getDocsOfLibsTest($libs[1], $spaceType[1], $excludeID[0])) && p('31:lib,title') && e('18,项目文档31'); // 获取项目库18下的文档列表 +r($docTester->getDocsOfLibsTest($libs[2], $spaceType[2], $excludeID[0])) && p('1:lib,title') && e('11,我的文档1'); // 获取我的文档库11下的文档列表 +r($docTester->getDocsOfLibsTest($libs[0], $spaceType[0], $excludeID[1])) && p('42:lib,title') && e('26,产品文档42'); // 获取产品库26下排除文档41的文档列表 +r($docTester->getDocsOfLibsTest($libs[1], $spaceType[1], $excludeID[2])) && p('32:lib,title') && e('18,项目文档32'); // 获取项目库18下排除文档31的文档列表 +r($docTester->getDocsOfLibsTest($libs[2], $spaceType[2], $excludeID[3])) && p('2:lib,title') && e('11,我的文档2'); // 获取我的文档库11下排除文档1的文档列表 From 0d4e81ce76d17b1c24795d4bd36b3a6ce1ce952a Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 08:35:25 +0800 Subject: [PATCH 350/655] * [misc] Add the auto test of the function of getDocTemplateList. --- module/doc/test/model/getdoctemplatelist.php | 104 +++++++++++++++++++ module/doc/test/yaml/template.yaml | 31 ++++++ 2 files changed, 135 insertions(+) create mode 100644 module/doc/test/model/getdoctemplatelist.php create mode 100644 module/doc/test/yaml/template.yaml diff --git a/module/doc/test/model/getdoctemplatelist.php b/module/doc/test/model/getdoctemplatelist.php new file mode 100644 index 0000000000..7887a73bcd --- /dev/null +++ b/module/doc/test/model/getdoctemplatelist.php @@ -0,0 +1,104 @@ +#!/usr/bin/env php +getDocTemplateList(); +timeout=0 +cid=1 + +- 获取产品范围下的所有模板 + - 第0条的lib属性 @1 + - 第0条的title属性 @产品模板5 + - 第0条的templateType属性 @custom1 +- 获取产品范围下的草稿模板 + - 第1条的lib属性 @1 + - 第1条的title属性 @产品模板4 + - 第1条的templateType属性 @custom1 +- 获取产品范围下的已发布模板 + - 第0条的lib属性 @1 + - 第0条的title属性 @产品模板2 + - 第0条的templateType属性 @hardwareProductPlan +- 获取产品范围下的所有模板,按照title降序 + - 第0条的lib属性 @1 + - 第0条的title属性 @产品模板1 + - 第0条的templateType属性 @softwareProductPlan +- 获取项目范围下的所有模板 + - 第0条的lib属性 @2 + - 第0条的title属性 @项目模板10 + - 第0条的templateType属性 @custom2 +- 获取项目范围下的草稿模板 + - 第1条的lib属性 @2 + - 第1条的title属性 @项目模板9 + - 第1条的templateType属性 @projectDetailedDesignSpecifica +- 获取项目范围下的已发布模板 + - 第0条的lib属性 @2 + - 第0条的title属性 @项目模板7 + - 第0条的templateType属性 @projectSoftwareRequirementsSpe +- 获取项目范围下的所有模板,按照title降序 + - 第0条的lib属性 @2 + - 第0条的title属性 @项目模板10 + - 第0条的templateType属性 @custom2 +- 获取执行范围下的所有模板 + - 第0条的lib属性 @3 + - 第0条的title属性 @执行模板15 + - 第0条的templateType属性 @custom3 +- 获取执行范围下的草稿模板 + - 第1条的lib属性 @3 + - 第1条的title属性 @执行模板14 + - 第1条的templateType属性 @custom3 +- 获取执行范围下的已发布模板 + - 第0条的lib属性 @3 + - 第0条的title属性 @执行模板12 + - 第0条的templateType属性 @executionTestPlan +- 获取执行范围下的所有模板,按照title降序 + - 第0条的lib属性 @3 + - 第0条的title属性 @执行模板11 + - 第0条的templateType属性 @executionQualityAssurancePlan +- 获取个人范围下的所有模板 + - 第0条的lib属性 @4 + - 第0条的title属性 @个人模板20 + - 第0条的templateType属性 @custom4 +- 获取个人范围下的草稿模板 + - 第1条的lib属性 @4 + - 第1条的title属性 @个人模板19 + - 第1条的templateType属性 @custom4 +- 获取个人范围下的已发布模板 + - 第0条的lib属性 @4 + - 第0条的title属性 @个人模板17 + - 第0条的templateType属性 @personalWorkSummaryReport +- 获取个人范围下的所有模板,按照title降序 + - 第0条的lib属性 @4 + - 第0条的title属性 @个人模板16 + - 第0条的templateType属性 @personalWorkPlan + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$libs = array(1, 2, 3, 4); +$types = array('all', 'draft', 'released'); +$orderBy = array('id_desc', 'title_asc'); + +$docTester = new docTest(); +r($docTester->getDocTemplateListTest($libs[0], $types[0], $orderBy[0])) && p('0:lib,title,templateType') && e('1,产品模板5,custom1'); // 获取产品范围下的所有模板 +r($docTester->getDocTemplateListTest($libs[0], $types[1], $orderBy[0])) && p('1:lib,title,templateType') && e('1,产品模板4,custom1'); // 获取产品范围下的草稿模板 +r($docTester->getDocTemplateListTest($libs[0], $types[2], $orderBy[0])) && p('0:lib,title,templateType') && e('1,产品模板2,hardwareProductPlan'); // 获取产品范围下的已发布模板 +r($docTester->getDocTemplateListTest($libs[0], $types[0], $orderBy[1])) && p('0:lib,title,templateType') && e('1,产品模板1,softwareProductPlan'); // 获取产品范围下的所有模板,按照title降序 +r($docTester->getDocTemplateListTest($libs[1], $types[0], $orderBy[0])) && p('0:lib,title,templateType') && e('2,项目模板10,custom2'); // 获取项目范围下的所有模板 +r($docTester->getDocTemplateListTest($libs[1], $types[1], $orderBy[0])) && p('1:lib,title,templateType') && e('2,项目模板9,projectDetailedDesignSpecifica'); // 获取项目范围下的草稿模板 +r($docTester->getDocTemplateListTest($libs[1], $types[2], $orderBy[0])) && p('0:lib,title,templateType') && e('2,项目模板7,projectSoftwareRequirementsSpe'); // 获取项目范围下的已发布模板 +r($docTester->getDocTemplateListTest($libs[1], $types[0], $orderBy[1])) && p('0:lib,title,templateType') && e('2,项目模板10,custom2'); // 获取项目范围下的所有模板,按照title降序 +r($docTester->getDocTemplateListTest($libs[2], $types[0], $orderBy[0])) && p('0:lib,title,templateType') && e('3,执行模板15,custom3'); // 获取执行范围下的所有模板 +r($docTester->getDocTemplateListTest($libs[2], $types[1], $orderBy[0])) && p('1:lib,title,templateType') && e('3,执行模板14,custom3'); // 获取执行范围下的草稿模板 +r($docTester->getDocTemplateListTest($libs[2], $types[2], $orderBy[0])) && p('0:lib,title,templateType') && e('3,执行模板12,executionTestPlan'); // 获取执行范围下的已发布模板 +r($docTester->getDocTemplateListTest($libs[2], $types[0], $orderBy[1])) && p('0:lib,title,templateType') && e('3,执行模板11,executionQualityAssurancePlan'); // 获取执行范围下的所有模板,按照title降序 +r($docTester->getDocTemplateListTest($libs[3], $types[0], $orderBy[0])) && p('0:lib,title,templateType') && e('4,个人模板20,custom4'); // 获取个人范围下的所有模板 +r($docTester->getDocTemplateListTest($libs[3], $types[1], $orderBy[0])) && p('1:lib,title,templateType') && e('4,个人模板19,custom4'); // 获取个人范围下的草稿模板 +r($docTester->getDocTemplateListTest($libs[3], $types[2], $orderBy[0])) && p('0:lib,title,templateType') && e('4,个人模板17,personalWorkSummaryReport'); // 获取个人范围下的已发布模板 +r($docTester->getDocTemplateListTest($libs[3], $types[0], $orderBy[1])) && p('0:lib,title,templateType') && e('4,个人模板16,personalWorkPlan'); // 获取个人范围下的所有模板,按照title降序 diff --git a/module/doc/test/yaml/template.yaml b/module/doc/test/yaml/template.yaml new file mode 100644 index 0000000000..3dcb086242 --- /dev/null +++ b/module/doc/test/yaml/template.yaml @@ -0,0 +1,31 @@ +title: zt_doc. +author: Qiyu Xie +version: "1.0" +fields: + - field: id + range: 1-100 + - field: title + note: "名称" + fields: + - field: title1 + range: "产品模板{5},项目模板{5},执行模板{5},个人模板{5}" + - field: title2 + range: 1-100 + - field: project + range: 0 + - field: product + range: 0 + - field: execution + range: 0 + - field: lib + range: "1{5},2{5},3{5},4{5}" + - field: module + range: "1,2,3,4{2},5,6,7,8,9,10,11,12,13,14{2},15,16,17,18{2}" + - field: status + range: "normal{2},draft{3}" + - field: type + range: text + - field: version + range: 1 + - field: templateType + range: "softwareProductPlan,hardwareProductPlan,qualityAssurancePlan,custom1{2},projectUserRequirementsSpecification,projectSoftwareRequirementsSpecification,projectSummaryDesignSpecification,projectDetailedDesignSpecification,custom2,executionQualityAssurancePlan,executionTestPlan,executionSoftwareRequirementsSpecification,custom3{2},personalWorkPlan,personalWorkSummaryReport,personalValueAnalysisReport,custom4{2}" From de67bee7ce197d99c6f4f2292c41b3ad1dfe3b69 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 08:35:57 +0800 Subject: [PATCH 351/655] * [misc] Add the auto test of the function of getTemplatesByType. --- module/doc/test/model/gettemplatesbytype.php | 54 ++++++++++++++++++++ module/doc/test/yaml/templatemodule.yaml | 28 ++++++++++ 2 files changed, 82 insertions(+) create mode 100644 module/doc/test/model/gettemplatesbytype.php create mode 100644 module/doc/test/yaml/templatemodule.yaml diff --git a/module/doc/test/model/gettemplatesbytype.php b/module/doc/test/model/gettemplatesbytype.php new file mode 100644 index 0000000000..7741edd4d8 --- /dev/null +++ b/module/doc/test/model/gettemplatesbytype.php @@ -0,0 +1,54 @@ +#!/usr/bin/env php +getTemplatesByType(); +timeout=0 +cid=1 + +- 获取所有模板 + - 第1条的id属性 @1 + - 第1条的title属性 @产品模板1 + - 第1条的templateType属性 @softwareProductPlan +- 获取所有已发布模板 + - 第2条的id属性 @2 + - 第2条的title属性 @产品模板2 + - 第2条的templateType属性 @hardwareProductPlan +- 获取所有草稿模板 + - 第3条的id属性 @3 + - 第3条的title属性 @产品模板3 + - 第3条的templateType属性 @qualityAssurancePlan +- 获取类型1下的所有模板 + - 第1条的id属性 @1 + - 第1条的title属性 @产品模板1 + - 第1条的templateType属性 @softwareProductPlan +- 获取类型1下的已发布模板 + - 第2条的id属性 @2 + - 第2条的title属性 @产品模板2 + - 第2条的templateType属性 @hardwareProductPlan +- 获取类型1下的草稿模板 + - 第3条的id属性 @3 + - 第3条的title属性 @产品模板3 + - 第3条的templateType属性 @qualityAssurancePlan + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('module')->loadYaml('templatemodule')->gen(10); +zenData('user')->gen(5); +su('admin'); + +$types = array(null, 1); +$status = array('all', 'normal', 'draft'); + +$docTester = new docTest(); +r($docTester->getTemplatesByTypeTest($types[0], $status[0])) && p('1:id,title,templateType') && e('1,产品模板1,softwareProductPlan'); // 获取所有模板 +r($docTester->getTemplatesByTypeTest($types[0], $status[1])) && p('2:id,title,templateType') && e('2,产品模板2,hardwareProductPlan'); // 获取所有已发布模板 +r($docTester->getTemplatesByTypeTest($types[0], $status[2])) && p('3:id,title,templateType') && e('3,产品模板3,qualityAssurancePlan'); // 获取所有草稿模板 +r($docTester->getTemplatesByTypeTest($types[1], $status[0])) && p('1:id,title,templateType') && e('1,产品模板1,softwareProductPlan'); // 获取类型1下的所有模板 +r($docTester->getTemplatesByTypeTest($types[1], $status[1])) && p('2:id,title,templateType') && e('2,产品模板2,hardwareProductPlan'); // 获取类型1下的已发布模板 +r($docTester->getTemplatesByTypeTest($types[1], $status[2])) && p('3:id,title,templateType') && e('3,产品模板3,qualityAssurancePlan'); // 获取类型1下的草稿模板 diff --git a/module/doc/test/yaml/templatemodule.yaml b/module/doc/test/yaml/templatemodule.yaml new file mode 100644 index 0000000000..901d0b230c --- /dev/null +++ b/module/doc/test/yaml/templatemodule.yaml @@ -0,0 +1,28 @@ +title: zt_module. +author: Qiyu Xie +version: "1.0" +fields: + - field: id + range: 1-100 + - field: name + fields: + - field: name1 + range: '模板类型' + - field: name2 + range: 1-100 + - field: short + fields: + - field: name1 + range: custom + - field: name2 + range: 1-100 + - field: root + range: 1{5},2{5} + - field: parent + range: 1{5},2{5} + - field: path + range: "`,1,`,`,1,2,`,`,3,`,`,4,`,`,5,`,`,6,`,`,6,7,`,`,8,`,`,9,`,`,10,`" + - field: grade + range: "1,2,1{3},1,2,1{3}" + - field: type + range: 'docTemplate' From b715266257bc3848ec7682bf25f5a6c2332b0478 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 09:08:21 +0800 Subject: [PATCH 352/655] * [misc] Add the auto test of the function of getHotTemplates. --- module/doc/test/lib/doc.unittest.class.php | 18 ++++++++- module/doc/test/model/gethottemplates.php | 47 ++++++++++++++++++++++ module/doc/test/yaml/template.yaml | 2 + 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 module/doc/test/model/gethottemplates.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 11f4f9ec01..274b620587 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1498,7 +1498,7 @@ class docTest * @param int|null $type * @param string $status * @access public - * @return int + * @return array */ public function getTemplatesByTypeTest($type = null, $status = 'all') { @@ -1506,4 +1506,20 @@ class docTest if(dao::isError()) return dao::getError(); return $templates; } + + /** + * 获取范围下最近编辑的模板。 + * Get templates of scope. + * + * @param int $scopeID + * @param int $limit + * @access public + * @return int + */ + public function getHotTemplatesTest($scopeID = 0, $limit = 0) + { + $templates = $this->objectModel->getHotTemplates($scopeID, $limit); + if(dao::isError()) return dao::getError(); + return $templates; + } } diff --git a/module/doc/test/model/gethottemplates.php b/module/doc/test/model/gethottemplates.php new file mode 100644 index 0000000000..9d8606e1fb --- /dev/null +++ b/module/doc/test/model/gethottemplates.php @@ -0,0 +1,47 @@ +#!/usr/bin/env php +getHotTemplates(); +timeout=0 +cid=1 + +- 获取所有文档模板 + - 第0条的id属性 @1 + - 第0条的title属性 @产品模板1 +- 获取产品范围所有文档模板 + - 第1条的id属性 @2 + - 第1条的title属性 @产品模板2 +- 获取项目范围所有文档模板 + - 第0条的id属性 @6 + - 第0条的title属性 @项目模板6 +- 获取所有范围下最新文档模板 + - 第0条的id属性 @1 + - 第0条的title属性 @产品模板1 +- 获取产品范围下最新文档模板 + - 第0条的id属性 @1 + - 第0条的title属性 @产品模板1 +- 获取项目范围下最新文档模板 + - 第0条的id属性 @6 + - 第0条的title属性 @项目模板6 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$scopeIdList = array(0, 1, 2); +$limits = array(0, 1); + +$docTester = new docTest(); +r($docTester->getHotTemplatesTest($scopeIdList[0], $limits[0])) && p('0:id,title') && e('1,产品模板1'); // 获取所有文档模板 +r($docTester->getHotTemplatesTest($scopeIdList[1], $limits[0])) && p('1:id,title') && e('2,产品模板2'); // 获取产品范围所有文档模板 +r($docTester->getHotTemplatesTest($scopeIdList[2], $limits[0])) && p('0:id,title') && e('6,项目模板6'); // 获取项目范围所有文档模板 +r($docTester->getHotTemplatesTest($scopeIdList[0], $limits[1])) && p('0:id,title') && e('1,产品模板1'); // 获取所有范围下最新文档模板 +r($docTester->getHotTemplatesTest($scopeIdList[1], $limits[1])) && p('0:id,title') && e('1,产品模板1'); // 获取产品范围下最新文档模板 +r($docTester->getHotTemplatesTest($scopeIdList[2], $limits[1])) && p('0:id,title') && e('6,项目模板6'); // 获取项目范围下最新文档模板 diff --git a/module/doc/test/yaml/template.yaml b/module/doc/test/yaml/template.yaml index 3dcb086242..bcfdcf4e13 100644 --- a/module/doc/test/yaml/template.yaml +++ b/module/doc/test/yaml/template.yaml @@ -29,3 +29,5 @@ fields: range: 1 - field: templateType range: "softwareProductPlan,hardwareProductPlan,qualityAssurancePlan,custom1{2},projectUserRequirementsSpecification,projectSoftwareRequirementsSpecification,projectSummaryDesignSpecification,projectDetailedDesignSpecification,custom2,executionQualityAssurancePlan,executionTestPlan,executionSoftwareRequirementsSpecification,custom3{2},personalWorkPlan,personalWorkSummaryReport,personalValueAnalysisReport,custom4{2}" + - field: addedDate + range: "2025-04-10 00:00:01,2025-04-11 00:00:01,2025-04-12 00:00:01,2025-04-13 00:00:01,2025-04-14 00:00:01,2025-04-15 00:00:01,2025-04-16 00:00:01,2025-04-17 00:00:01,2025-04-18 00:00:01,2025-04-19 00:00:01" From 1093ced62b47c9e6108adbeccf4f6090777e2d9e Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 09:19:31 +0800 Subject: [PATCH 353/655] * [misc] Add the auto test of the function of getScopeTemplates. --- module/doc/test/lib/doc.unittest.class.php | 14 ++++++++ module/doc/test/model/getscopetemplates.php | 40 +++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 module/doc/test/model/getscopetemplates.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 274b620587..bc882889f3 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1522,4 +1522,18 @@ class docTest if(dao::isError()) return dao::getError(); return $templates; } + + /** + * 获取所有范围下的模板。 + * Get templats of all scopes. + * + * @access public + * @return array + */ + public function getScopeTemplatesTest() + { + $templates = $this->objectModel->getScopeTemplates(); + if(dao::isError()) return dao::getError(); + return $templates; + } } diff --git a/module/doc/test/model/getscopetemplates.php b/module/doc/test/model/getscopetemplates.php new file mode 100644 index 0000000000..7e60c485a7 --- /dev/null +++ b/module/doc/test/model/getscopetemplates.php @@ -0,0 +1,40 @@ +#!/usr/bin/env php +getScopeTemplates(); +timeout=0 +cid=1 + +- 获取产品范围下的文档模板 + - 第1条的id属性 @1 + - 第1条的title属性 @产品模板1 +- 获取项目范围下的文档模板 + - 第6条的id属性 @6 + - 第6条的title属性 @项目模板6 +- 获取执行范围下的文档模板 + - 第11条的id属性 @11 + - 第11条的title属性 @执行模板11 +- 获取个人范围下的文档模板 + - 第16条的id属性 @16 + - 第16条的title属性 @个人模板16 +- 获取产品范围下的文档模板 + - 第2条的id属性 @2 + - 第2条的title属性 @产品模板2 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$docTester = new docTest(); +r($docTester->getScopeTemplatesTest()[1]) && p('1:id,title') && e('1,产品模板1'); // 获取产品范围下的文档模板 +r($docTester->getScopeTemplatesTest()[2]) && p('6:id,title') && e('6,项目模板6'); // 获取项目范围下的文档模板 +r($docTester->getScopeTemplatesTest()[3]) && p('11:id,title') && e('11,执行模板11'); // 获取执行范围下的文档模板 +r($docTester->getScopeTemplatesTest()[4]) && p('16:id,title') && e('16,个人模板16'); // 获取个人范围下的文档模板 +r($docTester->getScopeTemplatesTest()[1]) && p('2:id,title') && e('2,产品模板2'); // 获取产品范围下的文档模板 From bb0e027643fca804a54bf524f4efe9917cdc2dd2 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 09:36:24 +0800 Subject: [PATCH 354/655] * [misc] Add the auto test of the function of upgradeTemplate. --- module/doc/test/lib/doc.unittest.class.php | 14 +++++ module/doc/test/model/upgradetemplate.php | 70 ++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100755 module/doc/test/model/upgradetemplate.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index bc882889f3..d32a22083f 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1536,4 +1536,18 @@ class docTest if(dao::isError()) return dao::getError(); return $templates; } + + /** + * 升级旧的文档模板。 + * Upgrade old template. + * + * @param int $templateID + * @access public + * @return object + */ + public function upgradeTemplateTest(int $templateID) + { + $this->objectModel->upgradeTemplate(); + return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->eq($templateID)->fetch(); + } } diff --git a/module/doc/test/model/upgradetemplate.php b/module/doc/test/model/upgradetemplate.php new file mode 100755 index 0000000000..5c56d76270 --- /dev/null +++ b/module/doc/test/model/upgradetemplate.php @@ -0,0 +1,70 @@ +#!/usr/bin/env php +upgradeTemplate(); +timeout=0 +cid=1 + +- 更新模板1的字段值 + - 属性lib @1 + - 属性module @1 + - 属性templateType @softwareProductPlan +- 更新模板1的字段值 + - 属性lib @1 + - 属性module @2 + - 属性templateType @hardwareProductPlan +- 更新模板1的字段值 + - 属性lib @1 + - 属性module @3 + - 属性templateType @qualityAssurancePlan +- 更新模板4的字段值 + - 属性lib @1 + - 属性module @4 + - 属性templateType @custom1 +- 更新模板5的字段值 + - 属性lib @1 + - 属性module @4 + - 属性templateType @custom1 +- 更新模板6的字段值 + - 属性lib @2 + - 属性module @5 + - 属性templateType @projectUserRequirementsSpecifi +- 更新模板7的字段值 + - 属性lib @2 + - 属性module @6 + - 属性templateType @projectSoftwareRequirementsSpe +- 更新模板8的字段值 + - 属性lib @2 + - 属性module @7 + - 属性templateType @projectSummaryDesignSpecificat +- 更新模板9的字段值 + - 属性lib @2 + - 属性module @8 + - 属性templateType @projectDetailedDesignSpecifica +- 更新模板10的字段值 + - 属性lib @2 + - 属性module @9 + - 属性templateType @custom2 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$docTester = new docTest(); +r($docTester->upgradeTemplateTest(1)) && p('lib,module,templateType') && e('1,1,softwareProductPlan'); // 更新模板1的字段值 +r($docTester->upgradeTemplateTest(2)) && p('lib,module,templateType') && e('1,2,hardwareProductPlan'); // 更新模板1的字段值 +r($docTester->upgradeTemplateTest(3)) && p('lib,module,templateType') && e('1,3,qualityAssurancePlan'); // 更新模板1的字段值 +r($docTester->upgradeTemplateTest(4)) && p('lib,module,templateType') && e('1,4,custom1'); // 更新模板4的字段值 +r($docTester->upgradeTemplateTest(5)) && p('lib,module,templateType') && e('1,4,custom1'); // 更新模板5的字段值 +r($docTester->upgradeTemplateTest(6)) && p('lib,module,templateType') && e('2,5,projectUserRequirementsSpecifi'); // 更新模板6的字段值 +r($docTester->upgradeTemplateTest(7)) && p('lib,module,templateType') && e('2,6,projectSoftwareRequirementsSpe'); // 更新模板7的字段值 +r($docTester->upgradeTemplateTest(8)) && p('lib,module,templateType') && e('2,7,projectSummaryDesignSpecificat'); // 更新模板8的字段值 +r($docTester->upgradeTemplateTest(9)) && p('lib,module,templateType') && e('2,8,projectDetailedDesignSpecifica'); // 更新模板9的字段值 +r($docTester->upgradeTemplateTest(10)) && p('lib,module,templateType') && e('2,9,custom2'); // 更新模板10的字段值 From 1cd349d8f5e25f8723388c185b2fff1bce4bf2ec Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 10:27:54 +0800 Subject: [PATCH 355/655] * [misc] Add the auto test of the function of upgradeCustomTemplateTypes. --- module/doc/test/lib/doc.unittest.class.php | 14 ++++ .../test/model/upgradecustomtemplatetypes.php | 75 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100755 module/doc/test/model/upgradecustomtemplatetypes.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index d32a22083f..71010f0e35 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1550,4 +1550,18 @@ class docTest $this->objectModel->upgradeTemplate(); return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->eq($templateID)->fetch(); } + + /** + * 升级用户自定义模板类型数据。 + * Upgrade custom doc template types. + * + * @param int $moduleID + * @access public + * @return bool + */ + public function upgradeCustomTemplateTypesTest(int $moduleID) + { + $this->objectModel->upgradeCustomTemplateTypes(); + return $this->objectModel->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch(); + } } diff --git a/module/doc/test/model/upgradecustomtemplatetypes.php b/module/doc/test/model/upgradecustomtemplatetypes.php new file mode 100755 index 0000000000..2191621d8a --- /dev/null +++ b/module/doc/test/model/upgradecustomtemplatetypes.php @@ -0,0 +1,75 @@ +#!/usr/bin/env php +upgradeCustomTemplateTypes(); +timeout=0 +cid=1 + +- 自定义模板1 + - 属性type @docTemplate + - 属性root @2 + - 属性parent @1 + - 属性grade @2 + - 属性path @,1,2, +- 自定义模板2 + - 属性type @docTemplate + - 属性root @2 + - 属性parent @1 + - 属性grade @2 + - 属性path @,1,3, +- 自定义模板4 + - 属性type @docTemplate + - 属性root @2 + - 属性parent @1 + - 属性grade @2 + - 属性path @,1,4, +- 自定义模板5 + - 属性type @docTemplate + - 属性root @2 + - 属性parent @1 + - 属性grade @2 + - 属性path @,1,5, +- 自定义模板6 + - 属性type @docTemplate + - 属性root @2 + - 属性parent @1 + - 属性grade @2 + - 属性path @,1,6, + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$oldModule = zenData('lang'); +$oldModule->id->range('1-10'); +$oldModule->module->range('baseline'); +$oldModule->section->range('objectList'); +$oldModule->system->range(0); +$oldModule->key->range('module1,module2,module3,module4,module5,module6,module7,module8,module9,module10'); +$oldModule->value->range('自定义模板1,自定义模板2,自定义模板3,自定义模板4,自定义模板5,自定义模板6,自定义模板7,自定义模板8,自定义模板9,自定义模板10'); +$oldModule->gen(10); + +$newModule = zenData('module'); +$newModule->id->range(1); +$newModule->root->range(2); +$newModule->name->range('项目其他'); +$newModule->path->range('`,1,`'); +$newModule->grade->range(1); +$newModule->order->range(10); +$newModule->type->range('docTemplate'); +$newModule->short->range('Project other'); +$newModule->gen(1); + +$docTester = new docTest(); +r($docTester->upgradeCustomTemplateTypesTest(2)) && p('type|root|parent|grade|path', '|') && e('docTemplate|2|1|2|,1,2,'); // 自定义模板1 +r($docTester->upgradeCustomTemplateTypesTest(3)) && p('type|root|parent|grade|path', '|') && e('docTemplate|2|1|2|,1,3,'); // 自定义模板2 +r($docTester->upgradeCustomTemplateTypesTest(4)) && p('type|root|parent|grade|path', '|') && e('docTemplate|2|1|2|,1,4,'); // 自定义模板4 +r($docTester->upgradeCustomTemplateTypesTest(5)) && p('type|root|parent|grade|path', '|') && e('docTemplate|2|1|2|,1,5,'); // 自定义模板5 +r($docTester->upgradeCustomTemplateTypesTest(6)) && p('type|root|parent|grade|path', '|') && e('docTemplate|2|1|2|,1,6,'); // 自定义模板6 From 42c9ada343c93a3b2233c4c2a448e941a9a4069b Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 11:27:35 +0800 Subject: [PATCH 356/655] * [misc] Add the auto test of the function of getUpgradeDocs. --- .../test/lib/upgrade.unittest.class.php | 14 +++++ module/upgrade/test/model/getupgradedocs.php | 62 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 module/upgrade/test/model/getupgradedocs.php diff --git a/module/upgrade/test/lib/upgrade.unittest.class.php b/module/upgrade/test/lib/upgrade.unittest.class.php index 31609bfc3f..8ed771c8e2 100755 --- a/module/upgrade/test/lib/upgrade.unittest.class.php +++ b/module/upgrade/test/lib/upgrade.unittest.class.php @@ -775,4 +775,18 @@ class upgradeTest ->where('module')->eq('execution') ->fetchPairs(); } + + /** + * 获取需要升级的文档。 + * Get docs need to upgrade. + * + * @access public + * @return array + */ + public function getUpgradeDocsTest(): array + { + $docs = $this->objectModel->getUpgradeDocs(); + if(dao::isError()) return dao::getError(); + return $docs; + } } diff --git a/module/upgrade/test/model/getupgradedocs.php b/module/upgrade/test/model/getupgradedocs.php new file mode 100644 index 0000000000..cf2adb3ace --- /dev/null +++ b/module/upgrade/test/model/getupgradedocs.php @@ -0,0 +1,62 @@ +#!/usr/bin/env php +getUpgradeDocs(); +timeout=0 +cid=1 + +- 获取旧文档45 + - @4 + - 属性1 @5 +- 获取旧文档67 + - @6 + - 属性1 @7 +- 获取旧文档89 + - 属性2 @8 + - 属性3 @9 +- 获取旧文档12 + - @1 + - 属性1 @2 +- 获取旧文档34 + - 属性2 @3 + - 属性3 @4 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/upgrade.unittest.class.php'; + +zenData('user')->loadYaml('user')->gen(5); +su('admin'); + +$doc = zenData('doc'); +$doc->id->range('1-10'); +$doc->title->range('文档1,文档2,文档3,文档4,文档5,文档6,文档7,文档8,文档9,文档10'); +$doc->version->range('1'); +$doc->module->range('1'); +$doc->gen(10); + +$docContent = zenData('doccontent'); +$docContent->id->range('1-10'); +$docContent->doc->range('1-10'); +$docContent->type->range('doc{5},html{5}'); +$docContent->content->range('``{3},docContent{2},htmlContent{5}'); +$docContent->title->range('文档1,文档2,文档3,文档4,文档5,文档6,文档7,文档8,文档9,文档10'); +$docContent->version->range('1'); +$docContent->gen(10); + +$docLib = zenData('doclib'); +$docLib->id->range('1-5'); +$docLib->type->range('book'); +$docLib->name->range('book1,book2,book3,book4,book5'); +$docLib->gen(5); + +$upgrade = new upgradeTest(); +r($upgrade->getUpgradeDocsTest()['doc']) && p('0,1') && e('4,5'); // 获取旧文档45 +r($upgrade->getUpgradeDocsTest()['html']) && p('0,1') && e('6,7'); // 获取旧文档67 +r($upgrade->getUpgradeDocsTest()['html']) && p('2,3') && e('8,9'); // 获取旧文档89 +r($upgrade->getUpgradeDocsTest()['wiki']) && p('0,1') && e('1,2'); // 获取旧文档12 +r($upgrade->getUpgradeDocsTest()['wiki']) && p('2,3') && e('3,4'); // 获取旧文档34 From 39a4496ce187eb4d5d0d398f7fd6df65ea1de48c Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 13:34:33 +0800 Subject: [PATCH 357/655] * [misc] Add the auto test of the function of processObjectRelation. --- .../test/lib/upgrade.unittest.class.php | 15 +++++++ .../test/model/processobjectrelation.php | 39 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 module/upgrade/test/model/processobjectrelation.php diff --git a/module/upgrade/test/lib/upgrade.unittest.class.php b/module/upgrade/test/lib/upgrade.unittest.class.php index 8ed771c8e2..1f1d2372b7 100755 --- a/module/upgrade/test/lib/upgrade.unittest.class.php +++ b/module/upgrade/test/lib/upgrade.unittest.class.php @@ -789,4 +789,19 @@ class upgradeTest if(dao::isError()) return dao::getError(); return $docs; } + + /** + * Process object relations. + * 将系统内原有关联关系合并到relation表中:需求关联需求、bug关联bug、用例关联用例、问题关联风险、风险关联问题. + * + * @param string $aType + * @param int $aID + * @access public + * @return object + */ + public function processObjectRelationTest(string $aType, int $aID) + { + $this->objectModel->processObjectRelation(); + return $this->objectModel->dao->select('*')->from(TABLE_RELATION)->where('AType')->eq($aType)->andWhere('AID')->eq($aID)->fetchAll(); + } } diff --git a/module/upgrade/test/model/processobjectrelation.php b/module/upgrade/test/model/processobjectrelation.php new file mode 100644 index 0000000000..3132872a99 --- /dev/null +++ b/module/upgrade/test/model/processobjectrelation.php @@ -0,0 +1,39 @@ +#!/usr/bin/env php +processLinkStories(); +timeout=0 +cid=1 + +- 开源版不执行 @0 +- 开源版不执行 @0 +- 开源版不执行 @0 +- 开源版不执行 @0 +- 开源版不执行 @0 +- 开源版不执行 @0 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/upgrade.unittest.class.php'; + +su('admin'); + +$bug = zenData('bug'); +$bug->task->range('1'); +$bug->story->range('2'); +$bug->case->range('3'); +$bug->relatedBug->range('4'); +$bug->gen(10); + +zenData('relation')->gen(0); + +$upgrade = new upgradeTest(); +r($upgrade->processObjectRelationTest('story', 2)) && p('') && e('0'); // 开源版不执行 +r($upgrade->processObjectRelationTest('case', 3)) && p('') && e('0'); // 开源版不执行 +r($upgrade->processObjectRelationTest('bug', 4)) && p('') && e('0'); // 开源版不执行 +r($upgrade->processObjectRelationTest('story', 2)) && p('') && e('0'); // 开源版不执行 +r($upgrade->processObjectRelationTest('case', 3)) && p('') && e('0'); // 开源版不执行 +r($upgrade->processObjectRelationTest('bug', 4)) && p('') && e('0'); // 开源版不执行 From 69d0a5934e36e18ecbf7ca2950e79b464ada4a33 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 14:13:02 +0800 Subject: [PATCH 358/655] * [misc] Add the auto test of the function of renderChanges. --- .../action/test/lib/action.unittest.class.php | 17 +++++++++ module/action/test/model/renderchanges.php | 36 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100755 module/action/test/model/renderchanges.php diff --git a/module/action/test/lib/action.unittest.class.php b/module/action/test/lib/action.unittest.class.php index f170e6937e..22c1907674 100644 --- a/module/action/test/lib/action.unittest.class.php +++ b/module/action/test/lib/action.unittest.class.php @@ -813,4 +813,21 @@ class actionTest $history = $this->objectModel->dao->select('*')->from(TABLE_HISTORY)->where('id')->eq($historyID)->fetch(); return $this->objectModel->processHistory($history); } + + /** + * 渲染每一个action的历史记录。 + * Render histories of every action. + * + * @param string $objectType + * @param int $historyID + * @access public + * @return string + */ + public function renderChangesTest(string $objectType, int $historyID = 0): string + { + $histories = $this->objectModel->dao->select('*')->from(TABLE_HISTORY)->where('id')->eq($historyID)->fetchAll('id', false); + $content = $this->objectModel->renderChanges($objectType, $histories, true); + $content = str_replace("\n", '', $content); + return $content; + } } diff --git a/module/action/test/model/renderchanges.php b/module/action/test/model/renderchanges.php new file mode 100755 index 0000000000..d123eb91c1 --- /dev/null +++ b/module/action/test/model/renderchanges.php @@ -0,0 +1,36 @@ +#!/usr/bin/env php +renderChanges(); +timeout=0 +cid=1 + +- 测试type为空 @0 +- 测试bug解决方案历史记录 @修改了 解决方案,旧值为 "oldValue",新值为 "newValue"。
+- 测试bug解决版本历史记录 @修改了 解决版本,旧值为 "oldValue",新值为 "newValue"。
+- 测试bug解决日期历史记录 @修改了 解决日期,旧值为 "oldValue",新值为 "newValue"。
+- 测试产品状态历史记录 @修改了 状态,旧值为 "oldValue",新值为 "newValue"。
+ +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/action.unittest.class.php'; + +su('admin'); +zenData('action')->gen(10); + +$history = zenData('history'); +$history->old->range('oldValue'); +$history->oldValue->range('oldValue'); +$history->new->range('newValue'); +$history->newValue->range('newValue'); +$history->gen(10); + +$action = new actionTest(); +r($action->renderChangesTest('')) && p('') && e('0'); // 测试type为空 +r($action->renderChangesTest('bug', 1)) && p('') && e('修改了 解决方案,旧值为 "oldValue",新值为 "newValue"。
'); // 测试bug解决方案历史记录 +r($action->renderChangesTest('bug', 2)) && p('') && e('修改了 解决版本,旧值为 "oldValue",新值为 "newValue"。
'); // 测试bug解决版本历史记录 +r($action->renderChangesTest('bug', 3)) && p('') && e('修改了 解决日期,旧值为 "oldValue",新值为 "newValue"。
'); // 测试bug解决日期历史记录 +r($action->renderChangesTest('product', 4)) && p('') && e('修改了 状态,旧值为 "oldValue",新值为 "newValue"。
'); // 测试产品状态历史记录 From 2322eb0587331df97e234a9577674c4d5eb47200 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 14:26:17 +0800 Subject: [PATCH 359/655] * [misc] Add the auto test of the function of batchMoveDoc. --- module/doc/test/lib/doc.unittest.class.php | 16 +++++++ module/doc/test/model/batchmovedoc.php | 49 ++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100755 module/doc/test/model/batchmovedoc.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 71010f0e35..ab828995a9 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1564,4 +1564,20 @@ class docTest $this->objectModel->upgradeCustomTemplateTypes(); return $this->objectModel->dao->select('*')->from(TABLE_MODULE)->where('id')->eq($moduleID)->fetch(); } + + /** + * Batch move document. + * + * @param array $data + * @param array $docIdList + * @access public + * @return object + */ + public function batchMoveDocTest(array $data, array $docIdList) + { + $docData = new stdClass(); + foreach($data as $field => $value) $docData->{$field} = $value; + $this->objectModel->batchMoveDoc($docData, $docIdList); + return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->in($docIdList)->fetchAll('id'); + } } diff --git a/module/doc/test/model/batchmovedoc.php b/module/doc/test/model/batchmovedoc.php new file mode 100755 index 0000000000..a932311d09 --- /dev/null +++ b/module/doc/test/model/batchmovedoc.php @@ -0,0 +1,49 @@ +#!/usr/bin/env php +batchMoveDoc(); +timeout=0 +cid=1 + +- 测试ID为空时 @0 +- 测试文档1文档2的字段 + - 第1条的lib属性 @100 + - 第1条的module属性 @99 + - 第2条的lib属性 @100 + - 第2条的module属性 @99 +- 测试文档3文档4的字段 + - 第3条的lib属性 @100 + - 第3条的module属性 @99 + - 第4条的lib属性 @100 + - 第4条的module属性 @99 +- 测试文档5文档6的字段 + - 第5条的lib属性 @100 + - 第5条的module属性 @99 + - 第6条的lib属性 @100 + - 第6条的module属性 @99 +- 测试文档7文档8的字段 + - 第7条的lib属性 @100 + - 第7条的module属性 @99 + - 第8条的lib属性 @100 + - 第8条的module属性 @99 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('doc')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$docData = array('lib' => 100, 'module' => 99); +$docIdList = array(array(), array(1, 2), array(3, 4), array(5, 6), array(7, 8)); + +$docTester = new docTest(); +r($docTester->batchMoveDocTest($docData, $docIdList[0])) && p('') && e('0'); // 测试ID为空时 +r($docTester->batchMoveDocTest($docData, $docIdList[1])) && p('1:lib,module;2:lib,module') && e('100,99;100,99'); // 测试文档1文档2的字段 +r($docTester->batchMoveDocTest($docData, $docIdList[2])) && p('3:lib,module;4:lib,module') && e('100,99;100,99'); // 测试文档3文档4的字段 +r($docTester->batchMoveDocTest($docData, $docIdList[3])) && p('5:lib,module;6:lib,module') && e('100,99;100,99'); // 测试文档5文档6的字段 +r($docTester->batchMoveDocTest($docData, $docIdList[4])) && p('7:lib,module;8:lib,module') && e('100,99;100,99'); // 测试文档7文档8的字段 From 06b9b2b569ceb93e6e3f8914c6b06f87c629c54f Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 15:38:15 +0800 Subject: [PATCH 360/655] * [misc] Add the auto test of the function of checkIsTemplateUpgraded. --- module/doc/test/lib/doc.unittest.class.php | 12 +++++++ .../test/model/checkistemplateupgraded.php | 34 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 module/doc/test/model/checkistemplateupgraded.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index ab0a3298f7..6db7eca6a7 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1631,4 +1631,16 @@ class docTest if(dao::isError()) return dao::getError(); return $this->objectModel->dao->select('`order`')->from(TABLE_DOCLIB)->where('id')->eq($id)->fetch('order'); } + + /** + * 检查文档模板是否已升级。 + * Check if doc template has been upgraded + * + * @access public + * @return bool + */ + public function checkIsTemplateUpgradedTest() + { + return $this->objectModel->checkIsTemplateUpgraded(); + } } diff --git a/module/doc/test/model/checkistemplateupgraded.php b/module/doc/test/model/checkistemplateupgraded.php new file mode 100644 index 0000000000..cdf609bf87 --- /dev/null +++ b/module/doc/test/model/checkistemplateupgraded.php @@ -0,0 +1,34 @@ +#!/usr/bin/env php +checkIsTemplateUpgraded(); +timeout=0 +cid=1 + +- 检查文档模板已升级 @1 +- 检查文档模板已升级 @1 +- 检查文档模板已升级 @1 +- 检查文档模板未升级 @0 +- 检查文档模板未升级 @0 +- 检查文档模板未升级 @0 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('module')->loadYaml('templatemodule')->gen(10); +zenData('user')->gen(5); +su('admin'); + +$docTester = new docTest(); +r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('1'); // 检查文档模板已升级 +r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('1'); // 检查文档模板已升级 +r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('1'); // 检查文档模板已升级 + +zenData('module')->gen(0); +r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('0'); // 检查文档模板未升级 +r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('0'); // 检查文档模板未升级 +r($docTester->checkIsTemplateUpgradedTest()) && p('') && e('0'); // 检查文档模板未升级 From b82b2e18ff7a63618c276eefee5922ffd117783f Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 15:55:18 +0800 Subject: [PATCH 361/655] * [misc] Modify the auto test file. --- module/doc/test/lib/doc.unittest.class.php | 4 ++-- module/doc/test/model/updatedocfile.php | 7 ++++++- module/doc/test/model/updateorder.php | 15 +++++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 6db7eca6a7..5ee5916c81 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1412,9 +1412,9 @@ class docTest * @param int $order * @param string $type api|doc * @access public - * @return int|false + * @return int|false|string */ - public function updateOrderTest(int $catalogID, int $order, string $type = 'doc'): int|false + public function updateOrderTest(int $catalogID, int $order, string $type = 'doc'): int|false|string { $this->objectModel->updateOrder($catalogID, $order, $type); diff --git a/module/doc/test/model/updatedocfile.php b/module/doc/test/model/updatedocfile.php index c88a69c7a5..2fac86f04e 100644 --- a/module/doc/test/model/updatedocfile.php +++ b/module/doc/test/model/updatedocfile.php @@ -4,11 +4,14 @@ /** title=测试 docModel->updateDocFile(); +timeout=0 cid=1 - 测试将文件ID为1的文件从文档ID为1的文档中移除属性files @2 - 测试将文件ID为4的文件从文档ID为1的文档中移除属性files @2 - 测试将文件ID为7的文件从文档ID为1的文档中移除属性files @2 +- 测试将文件ID为8的文件从文档ID为1的文档中移除属性files @2 +- 测试将文件ID为9的文件从文档ID为1的文档中移除属性files @2 */ @@ -28,9 +31,11 @@ $doccontentTable->files->range('`1,2`,`3,4`,`5,6`'); $doccontentTable->gen(1); $docID = 1; -$fileIdList = array(1, 4, 7); +$fileIdList = array(1, 4, 7, 8, 9); $docTester = new docTest(); r($docTester->updateDocFileTest($docID, $fileIdList[0])) && p('files') && e('2'); // 测试将文件ID为1的文件从文档ID为1的文档中移除 r($docTester->updateDocFileTest($docID, $fileIdList[1])) && p('files') && e('2'); // 测试将文件ID为4的文件从文档ID为1的文档中移除 r($docTester->updateDocFileTest($docID, $fileIdList[2])) && p('files') && e('2'); // 测试将文件ID为7的文件从文档ID为1的文档中移除 +r($docTester->updateDocFileTest($docID, $fileIdList[3])) && p('files') && e('2'); // 测试将文件ID为8的文件从文档ID为1的文档中移除 +r($docTester->updateDocFileTest($docID, $fileIdList[4])) && p('files') && e('2'); // 测试将文件ID为9的文件从文档ID为1的文档中移除 diff --git a/module/doc/test/model/updateorder.php b/module/doc/test/model/updateorder.php index 48228d7009..45ebb7a895 100755 --- a/module/doc/test/model/updateorder.php +++ b/module/doc/test/model/updateorder.php @@ -9,9 +9,12 @@ cid=1 - 测试ID为1的目录,order值不变的情况 @10 - 测试ID为2的目录,order值需要更新的情况 @1 -- 测试目录ID不存在的情况 @~~ +- 测试ID为3的目录,order值不变的情况 @30 +- 测试ID为4的目录,order值需要更新的情况 @2 +- 测试目录ID不存在的情况 @0 */ + include dirname(__FILE__, 5) . '/test/lib/init.php'; include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; @@ -20,9 +23,13 @@ zenData('module')->loadYaml('module')->gen(10); $catalogOrderList = array(); $catalogOrderList[] = array('id' => 1, 'order' => 10); $catalogOrderList[] = array('id' => 2, 'order' => 1); +$catalogOrderList[] = array('id' => 3, 'order' => 30); +$catalogOrderList[] = array('id' => 4, 'order' => 2); $catalogOrderList[] = array('id' => 11, 'order' => 100); $docTester = new docTest(); -r($docTester->updateOrderTest($catalogOrderList[0]['id'], $catalogOrderList[0]['order'])) && p() && e(10); // 测试ID为1的目录,order值不变的情况 -r($docTester->updateOrderTest($catalogOrderList[1]['id'], $catalogOrderList[1]['order'])) && p() && e(1); // 测试ID为2的目录,order值需要更新的情况 -r($docTester->updateOrderTest($catalogOrderList[2]['id'], $catalogOrderList[2]['order'])) && p() && e('~~'); // 测试目录ID不存在的情况 +r($docTester->updateOrderTest($catalogOrderList[0]['id'], $catalogOrderList[0]['order'])) && p() && e(10); // 测试ID为1的目录,order值不变的情况 +r($docTester->updateOrderTest($catalogOrderList[1]['id'], $catalogOrderList[1]['order'])) && p() && e(1); // 测试ID为2的目录,order值需要更新的情况 +r($docTester->updateOrderTest($catalogOrderList[2]['id'], $catalogOrderList[2]['order'])) && p() && e(30); // 测试ID为3的目录,order值不变的情况 +r($docTester->updateOrderTest($catalogOrderList[3]['id'], $catalogOrderList[3]['order'])) && p() && e(2); // 测试ID为4的目录,order值需要更新的情况 +r($docTester->updateOrderTest($catalogOrderList[4]['id'], $catalogOrderList[4]['order'])) && p() && e('0'); // 测试目录ID不存在的情况 From 47383a01d7fc62ad4a9d1402be93150107b26947 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 16:36:06 +0800 Subject: [PATCH 362/655] * [misc] Modify the auto test files. --- module/common/test/model/setmenuvarsex.php | 23 +++++++++- module/doc/test/model/deletefiles.php | 4 ++ module/search/test/model/setdefaultparams.php | 10 ++++- .../search/test/tao/processbuildinfields.php | 33 +++++++++++--- .../testcase/test/model/buildsearchform.php | 9 +++- .../test/model/getcanimportedmodules.php | 17 +++++++ .../test/model/completeclassifylang.php | 4 ++ .../test/model/deletegeneralreportblock.php | 10 ++++- .../upgrade/test/model/processlinkstories.php | 39 +++++++++++++++- .../model/processprojectroadmapsbycharter.php | 31 +++++++++++++ .../test/model/updatetaskrelationpriv.php | 4 ++ .../upgrade/test/model/upgrademydocspace.php | 45 ++++++++++++++++++- 12 files changed, 216 insertions(+), 13 deletions(-) diff --git a/module/common/test/model/setmenuvarsex.php b/module/common/test/model/setmenuvarsex.php index 01e3e3d53d..b4c1d805e9 100755 --- a/module/common/test/model/setmenuvarsex.php +++ b/module/common/test/model/setmenuvarsex.php @@ -11,6 +11,9 @@ cid=1 - 查看替换后的菜单链接 @/execution-task-1 - 查看替换后的菜单链接属性link @/task-create-1 +- 查看替换后的菜单链接属性link @/task-edit-1 +- 查看替换后的菜单链接属性link @/task-delete-1 +- 查看替换后的菜单链接属性link @/task-view-1 */ @@ -23,4 +26,22 @@ $menu = array(); $menu['link'] = "/task-create-%s"; $menu = common::setMenuVarsEx($menu, 1); -r($menu) && p('link') && e('/task-create-1'); // 查看替换后的菜单链接 \ No newline at end of file +r($menu) && p('link') && e('/task-create-1'); // 查看替换后的菜单链接 + +$menu = array(); +$menu['link'] = "/task-edit-%s"; +$menu = common::setMenuVarsEx($menu, 1); + +r($menu) && p('link') && e('/task-edit-1'); // 查看替换后的菜单链接 + +$menu = array(); +$menu['link'] = "/task-delete-%s"; +$menu = common::setMenuVarsEx($menu, 1); + +r($menu) && p('link') && e('/task-delete-1'); // 查看替换后的菜单链接 + +$menu = array(); +$menu['link'] = "/task-view-%s"; +$menu = common::setMenuVarsEx($menu, 1); + +r($menu) && p('link') && e('/task-view-1'); // 查看替换后的菜单链接 diff --git a/module/doc/test/model/deletefiles.php b/module/doc/test/model/deletefiles.php index 2ea7a5e2db..0414db0665 100755 --- a/module/doc/test/model/deletefiles.php +++ b/module/doc/test/model/deletefiles.php @@ -9,9 +9,11 @@ cid=1 - 测试正常数据属性1 @1 - 测试有不存在的数据属性1 @1 - 测试不存在的数据 @0 +- 测试异常数据 @0 */ + include dirname(__FILE__, 5) . '/test/lib/init.php'; include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; @@ -27,9 +29,11 @@ $docIdList[] = array(); $docIdList[] = range(1, 5); $docIdList[] = array(1, 2, 100, 101); $docIdList[] = range(100, 105); +$docIdList[] = array(999); $docTester = new docTest(); r($docTester->deleteFilesTest($docIdList[0])) && p() && e('0'); // 测试空数据 r($docTester->deleteFilesTest($docIdList[1])) && p('1') && e('1'); // 测试正常数据 r($docTester->deleteFilesTest($docIdList[2])) && p('1') && e('1'); // 测试有不存在的数据 r($docTester->deleteFilesTest($docIdList[3])) && p() && e('0'); // 测试不存在的数据 +r($docTester->deleteFilesTest($docIdList[4])) && p() && e('0'); // 测试异常数据 diff --git a/module/search/test/model/setdefaultparams.php b/module/search/test/model/setdefaultparams.php index a767eee065..ba3fd9b007 100755 --- a/module/search/test/model/setdefaultparams.php +++ b/module/search/test/model/setdefaultparams.php @@ -7,6 +7,14 @@ title=测试 searchModel->setDefaultParams(); timeout=0 cid=1 +- 测试设置 products 的默认参数 @1,2,3,4,5,6,7,8,9,10,null +- 测试设置 users 的默认参数 @admin,user1,user2,user3,user4,$me,null +- 测试设置 executions 的默认参数 @,null +- 测试设置 空数组 的默认参数 @,null +- 测试设置 空字符串 的默认参数 @0,null +- 测试设置 array(1) 的默认参数 @ZERO +- 测试设置 nonull 的默认参数 @0 + */ include dirname(__FILE__, 5) . '/test/lib/init.php'; @@ -41,4 +49,4 @@ r($search->setDefaultParamsTest($fields3, $params3)) && p('0') && e(',null'); r($search->setDefaultParamsTest($fields4, $params4)) && p('0') && e(',null'); // 测试设置 空数组 的默认参数 r($search->setDefaultParamsTest($fields5, $params5)) && p('0') && e('0,null'); // 测试设置 空字符串 的默认参数 r($search->setDefaultParamsTest($fields6, $params6)) && p('0') && e('ZERO'); // 测试设置 array(1) 的默认参数 -r($search->setDefaultParamsTest($fields7, $params7)) && p('0') && e('0'); // 测试设置 nonull 的默认参数 \ No newline at end of file +r($search->setDefaultParamsTest($fields7, $params7)) && p('0') && e('0'); // 测试设置 nonull 的默认参数 diff --git a/module/search/test/tao/processbuildinfields.php b/module/search/test/tao/processbuildinfields.php index 722a2e7fb6..2357b637be 100755 --- a/module/search/test/tao/processbuildinfields.php +++ b/module/search/test/tao/processbuildinfields.php @@ -2,12 +2,33 @@ processBuildinFields() - * - * @title=测试 searchTao->processBuildinFields(); - * @timeout=0 - * @cid=1 - */ + +title=测试 searchTao->processBuildinFields(); +timeout=0 +cid=1 + +- projectstory + - 属性module @story + - 属性fields @title,id,keywords,status,pri,module,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate + - 属性maxCount @500 +- bug + - 属性module @bug + - 属性fields @title,module,keywords,steps,assignedTo,resolvedBy,status,confirmed,story,project,branch,plan,id,execution,severity,pri,type,os,browser,resolution,activatedCount,toTask,toStory,openedBy,closedBy,lastEditedBy,mailto,openedBuild,resolvedBuild,openedDate,assignedDate,resolvedDate,closedDate,lastEditedDate,deadline,activatedDate + - 属性maxCount @500 +- product + - 属性module @story + - 属性fields @title,id,keywords,status,pri,module,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate + - 属性maxCount @500 +- testcase + - 属性module @testcase + - 属性fields @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene + - 属性maxCount @500 +- caselib + - 属性module @caselib + - 属性fields @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,stage,module,pri,openedDate,lastEditedDate + - 属性maxCount @500 + +*/ include dirname(__FILE__, 5) . '/test/lib/init.php'; include dirname(__FILE__, 2) . '/lib/search.unittest.class.php'; diff --git a/module/testcase/test/model/buildsearchform.php b/module/testcase/test/model/buildsearchform.php index 1f69f688d2..a6c685026b 100644 --- a/module/testcase/test/model/buildsearchform.php +++ b/module/testcase/test/model/buildsearchform.php @@ -18,6 +18,13 @@ title=测试 testcaseModel->buildSearchForm(); cid=1 pid=1 +- 测试构建产品 0 project 0 module 0 branch all 的搜索表单 @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene +- 测试构建产品 1 project 0 module 0 branch all 的搜索表单 @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene +- 测试构建产品 1 project 1 module 0 branch all 的搜索表单 @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene +- 测试构建产品 1 project 1 module 1 branch all 的搜索表单 @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene +- 测试构建产品 41 project 0 module 0 branch 0 的搜索表单 @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene,branch +- 测试构建产品 41 project 0 module 0 branch 0 的搜索表单 @title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene,branch + */ $productID = array(0, 1, 41); @@ -32,4 +39,4 @@ r($testcase->buildSearchFormTest($productID[1], $projectID[0], $moduleID[0], $br r($testcase->buildSearchFormTest($productID[1], $projectID[1], $moduleID[0], $branch[0])) && p() && e('title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene'); // 测试构建产品 1 project 1 module 0 branch all 的搜索表单 r($testcase->buildSearchFormTest($productID[1], $projectID[1], $moduleID[1], $branch[0])) && p() && e('title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene'); // 测试构建产品 1 project 1 module 1 branch all 的搜索表单 r($testcase->buildSearchFormTest($productID[2], $projectID[0], $moduleID[0], $branch[0])) && p() && e('title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene,branch'); // 测试构建产品 41 project 0 module 0 branch 0 的搜索表单 -r($testcase->buildSearchFormTest($productID[2], $projectID[0], $moduleID[0], $branch[1])) && p() && e('title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene,branch'); // 测试构建产品 41 project 0 module 0 branch 0 的搜索表单 \ No newline at end of file +r($testcase->buildSearchFormTest($productID[2], $projectID[0], $moduleID[0], $branch[1])) && p() && e('title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,product,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene,branch'); // 测试构建产品 41 project 0 module 0 branch 0 的搜索表单 diff --git a/module/testcase/test/model/getcanimportedmodules.php b/module/testcase/test/model/getcanimportedmodules.php index 805b81bf98..509f969c2a 100644 --- a/module/testcase/test/model/getcanimportedmodules.php +++ b/module/testcase/test/model/getcanimportedmodules.php @@ -6,6 +6,23 @@ title=测试 testsuiteModel->getCanImportedModules(); cid=0 +- 测试获取产品 1 用例库 0 分支 all 返回类型 pairs 可以导入的用例 @30:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;29:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;28:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;27:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;26:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;25:1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;24:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;23:1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;22:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;21:1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto; +- 测试获取产品 1 用例库 0 分支 all 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;29:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;27:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;25:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;23:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;21:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20; +- 测试获取产品 1 用例库 1 分支 all 返回类型 pairs 可以导入的用例 @30:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;28:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;26:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;24:1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;22:1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto; +- 测试获取产品 1 用例库 1 分支 all 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20; +- 测试获取产品 1 用例库 0 分支 1 返回类型 pairs 可以导入的用例 @30:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;29:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;28:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;27:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;26:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;25:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;24:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;23:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;22:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;21:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto; +- 测试获取产品 1 用例库 0 分支 1 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;29:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;27:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;25:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;23:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;21:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21; +- 测试获取产品 1 用例库 1 分支 1 返回类型 pairs 可以导入的用例 @30:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;28:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;26:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;24:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto;22:0,1,31,2,32,3,33,4,34,5,35,6,36,7,37,8,38,9,39,10,40,ditto; +- 测试获取产品 1 用例库 1 分支 1 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21; +- 测试获取产品 41 用例库 0 分支 all 返回类型 pairs 可以导入的用例 @30:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;29:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;28:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;27:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;26:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;25:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;24:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;23:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;22:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;21:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto; +- 测试获取产品 41 用例库 0 分支 all 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;29:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;27:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;25:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;23:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;21:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21; +- 测试获取产品 41 用例库 1 分支 all 返回类型 pairs 可以导入的用例 @30:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;28:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;26:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;24:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;22:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto; +- 测试获取产品 41 用例库 1 分支 all 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21; +- 测试获取产品 41 用例库 0 分支 1 返回类型 pairs 可以导入的用例 @30:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;29:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;28:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;27:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;26:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;25:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;24:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;23:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;22:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;21:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto; +- 测试获取产品 41 用例库 0 分支 1 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;29:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;27:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;25:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;23:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;21:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21; +- 测试获取产品 41 用例库 1 分支 1 返回类型 pairs 可以导入的用例 @30:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;28:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;26:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;24:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto;22:0,11,41,12,42,13,43,14,44,15,45,16,46,17,47,18,48,19,49,20,50,ditto; +- 测试获取产品 41 用例库 1 分支 1 返回类型 items 可以导入的用例 @30:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;28:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;26:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;24:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21;22:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21 + */ include dirname(__FILE__, 5) . '/test/lib/init.php'; include dirname(__FILE__, 2) . '/lib/testcase.unittest.class.php'; diff --git a/module/upgrade/test/model/completeclassifylang.php b/module/upgrade/test/model/completeclassifylang.php index b639ac75f8..da62e4eb9d 100755 --- a/module/upgrade/test/model/completeclassifylang.php +++ b/module/upgrade/test/model/completeclassifylang.php @@ -8,6 +8,8 @@ timeout=0 cid=1 - 检查数据库中已经给融合敏捷模型添加了project分类项 @项目管理 +- 检查数据库中已经给融合敏捷模型添加了support分类项 @支持过程 +- 检查数据库中已经给融合敏捷模型添加了engineering分类项 @工程支持 - 检查数据库中敏捷模型未添加project分类项 @项目管理 - 检查数据库中已经给融合瀑布模型添加了support,engineering,没添加project分类项 @项目管理 @@ -24,5 +26,7 @@ global $tester, $app; $upgrade = new upgradeTest(); r($upgrade->completeClassifyLangTest('agileplusClassify', 'project')) && p() && e('项目管理'); // 检查数据库中已经给融合敏捷模型添加了project分类项 +r($upgrade->completeClassifyLangTest('agileplusClassify', 'support')) && p() && e('支持过程'); // 检查数据库中已经给融合敏捷模型添加了support分类项 +r($upgrade->completeClassifyLangTest('agileplusClassify', 'engineering')) && p() && e('工程支持'); // 检查数据库中已经给融合敏捷模型添加了engineering分类项 r($upgrade->completeClassifyLangTest('scrumClassify', 'project')) && p() && e('项目管理'); // 检查数据库中敏捷模型未添加project分类项 r($upgrade->completeClassifyLangTest('waterfallplusClassify', 'project')) && p() && e('项目管理'); // 检查数据库中已经给融合瀑布模型添加了support,engineering,没添加project分类项 diff --git a/module/upgrade/test/model/deletegeneralreportblock.php b/module/upgrade/test/model/deletegeneralreportblock.php index 3b712fd4f8..d53bf0a333 100644 --- a/module/upgrade/test/model/deletegeneralreportblock.php +++ b/module/upgrade/test/model/deletegeneralreportblock.php @@ -7,8 +7,11 @@ declare(strict_types=1); title=测试 upgradeModel->deleteGeneralReportBlock(); cid=1 -- 瀑布通用报表块已经被删除。@0 -- 瀑布通用报表块配置已经被删除。@0 +- 瀑布通用报表块已经被删除。 @1 +- 瀑布通用报表块配置已经被删除。 @0 +- 瀑布通用报表块配置已经被删除。 @0 +- 瀑布通用报表块配置已经被删除。 @0 +- 瀑布通用报表块配置已经被删除。 @0 **/ @@ -39,3 +42,6 @@ $config = $tester->dao->select('*')->from('zt_config') r(!isset($block->block) || empty($block)) && p() && e('1'); //瀑布通用报表块已经被删除。 r(strpos($config->value, ',project|waterfallgeneralreport')) && p() && e('0'); //瀑布通用报表块配置已经被删除。 +r(strpos($config->value, ',project|waterfallgeneral')) && p() && e('0'); //瀑布通用报表块配置已经被删除。 +r(strpos($config->value, ',project|waterfall')) && p() && e('0'); //瀑布通用报表块配置已经被删除。 +r(strpos($config->value, ',project|general')) && p() && e('0'); //瀑布通用报表块配置已经被删除。 diff --git a/module/upgrade/test/model/processlinkstories.php b/module/upgrade/test/model/processlinkstories.php index 8ec72b1576..6bbe583068 100644 --- a/module/upgrade/test/model/processlinkstories.php +++ b/module/upgrade/test/model/processlinkstories.php @@ -14,8 +14,45 @@ $result->gen(12); /** title=upgradeModel->processLinkStories(); +timeout=0 cid=1 -pid=1 + +- 获取ID为1的关联关系。 + - 第1条的AType属性 @story + - 第1条的AID属性 @7 + - 第1条的relation属性 @linkedto + - 第1条的BType属性 @story + - 第1条的BID属性 @1 +- 获取ID为1的关联关系。 + - 第2条的AType属性 @story + - 第2条的AID属性 @1 + - 第2条的relation属性 @linkedfrom + - 第2条的BType属性 @story + - 第2条的BID属性 @7 +- 获取ID为1的关联关系。 + - 第3条的AType属性 @story + - 第3条的AID属性 @8 + - 第3条的relation属性 @linkedto + - 第3条的BType属性 @story + - 第3条的BID属性 @2 +- 获取ID为1的关联关系。 + - 第7条的AType属性 @requirement + - 第7条的AID属性 @10 + - 第7条的relation属性 @linkedto + - 第7条的BType属性 @requirement + - 第7条的BID属性 @4 +- 获取ID为1的关联关系。 + - 第8条的AType属性 @requirement + - 第8条的AID属性 @4 + - 第8条的relation属性 @linkedfrom + - 第8条的BType属性 @requirement + - 第8条的BID属性 @10 +- 获取ID为1的关联关系。 + - 第9条的AType属性 @requirement + - 第9条的AID属性 @11 + - 第9条的relation属性 @linkedto + - 第9条的BType属性 @requirement + - 第9条的BID属性 @5 */ diff --git a/module/upgrade/test/model/processprojectroadmapsbycharter.php b/module/upgrade/test/model/processprojectroadmapsbycharter.php index 69e5795e94..4c90a746a2 100644 --- a/module/upgrade/test/model/processprojectroadmapsbycharter.php +++ b/module/upgrade/test/model/processprojectroadmapsbycharter.php @@ -25,6 +25,37 @@ title=upgradeModel->processProjectRoadmapsByCharter(); cid=1 pid=1 +- 获取project为1的项目产品关系数据。 + - 第1条的project属性 @1 + - 第1条的product属性 @1 + - 第1条的branch属性 @0 + - 第1条的plan属性 @~~ + - 第1条的roadmap属性 @,1, +- 获取project为11的项目产品关系数据。 + - 第11条的project属性 @11 + - 第11条的product属性 @1 + - 第11条的branch属性 @0 + - 第11条的plan属性 @~~ + - 第11条的roadmap属性 @,1, +- 获取project为22的项目产品关系数据。 + - 第22条的project属性 @22 + - 第22条的product属性 @2 + - 第22条的branch属性 @0 + - 第22条的plan属性 @~~ + - 第22条的roadmap属性 @,2, +- 获取project为33的项目产品关系数据。 + - 第33条的project属性 @33 + - 第33条的product属性 @3 + - 第33条的branch属性 @0 + - 第33条的plan属性 @~~ + - 第33条的roadmap属性 @,3, +- 获取project为49的项目产品关系数据。 + - 第40条的project属性 @40 + - 第40条的product属性 @10 + - 第40条的branch属性 @0 + - 第40条的plan属性 @~~ + - 第40条的roadmap属性 @,10, + */ global $tester; diff --git a/module/upgrade/test/model/updatetaskrelationpriv.php b/module/upgrade/test/model/updatetaskrelationpriv.php index 944635f157..07e3b95561 100644 --- a/module/upgrade/test/model/updatetaskrelationpriv.php +++ b/module/upgrade/test/model/updatetaskrelationpriv.php @@ -10,6 +10,8 @@ cid=1 - 测试添加任务关系权限属性createrelation @createrelation - 测试维护任务关系权限属性editrelation @editrelation - 测试批量维护任务关系权限属性batcheditrelation @batcheditrelation +- 测试添加任务关系权限属性createrelation @createrelation +- 测试维护任务关系权限属性editrelation @editrelation **/ @@ -26,3 +28,5 @@ $upgrade = new upgradeTest(); r($upgrade->updateTaskRelationPrivTest()) && p('createrelation') && e('createrelation'); //测试添加任务关系权限 r($upgrade->updateTaskRelationPrivTest()) && p('editrelation') && e('editrelation'); //测试维护任务关系权限 r($upgrade->updateTaskRelationPrivTest()) && p('batcheditrelation') && e('batcheditrelation'); //测试批量维护任务关系权限 +r($upgrade->updateTaskRelationPrivTest()) && p('createrelation') && e('createrelation'); //测试添加任务关系权限 +r($upgrade->updateTaskRelationPrivTest()) && p('editrelation') && e('editrelation'); //测试维护任务关系权限 diff --git a/module/upgrade/test/model/upgrademydocspace.php b/module/upgrade/test/model/upgrademydocspace.php index 718f35ae2e..a0fdb6506f 100644 --- a/module/upgrade/test/model/upgrademydocspace.php +++ b/module/upgrade/test/model/upgrademydocspace.php @@ -7,6 +7,49 @@ declare(strict_types=1); title=测试 upgradeModel->upgradeMyDocSpace(); cid=1 +- 获取更新前我的文档库数量。 @5 +- 获取更新后我的文档库数量。 @8 +- 获取更新后我的文档库 6 的信息 + - 属性id @6 + - 属性main @0 + - 属性vision @rnd + - 属性parent @11 +- 获取更新后我的文档库 6 的信息 + - 属性id @7 + - 属性main @0 + - 属性vision @rnd + - 属性parent @11 +- 获取更新后我的文档库 6 的信息 + - 属性id @8 + - 属性main @0 + - 属性vision @or + - 属性parent @13 +- 获取更新后我的文档库 6 的信息 + - 属性id @9 + - 属性main @0 + - 属性vision @or + - 属性parent @13 +- 获取更新后我的文档库 6 的信息 + - 属性id @10 + - 属性main @0 + - 属性vision @lite + - 属性parent @12 +- 获取更新后我的文档库 6 的信息 + - 属性id @11 + - 属性main @1 + - 属性vision @rnd + - 属性parent @0 +- 获取更新后我的文档库 6 的信息 + - 属性id @12 + - 属性main @1 + - 属性vision @lite + - 属性parent @0 +- 获取更新后我的文档库 6 的信息 + - 属性id @13 + - 属性main @1 + - 属性vision @or + - 属性parent @0 + **/ include dirname(__FILE__, 5) . '/test/lib/init.php'; @@ -33,4 +76,4 @@ r($myDocLibs[9]) && p('id,main,vision,parent') && e('9,0,or,13'); // r($myDocLibs[10]) && p('id,main,vision,parent') && e('10,0,lite,12'); // 获取更新后我的文档库 6 的信息 r($myDocLibs[11]) && p('id,main,vision,parent') && e('11,1,rnd,0'); // 获取更新后我的文档库 6 的信息 r($myDocLibs[12]) && p('id,main,vision,parent') && e('12,1,lite,0'); // 获取更新后我的文档库 6 的信息 -r($myDocLibs[13]) && p('id,main,vision,parent') && e('13,1,or,0'); // 获取更新后我的文档库 6 的信息 \ No newline at end of file +r($myDocLibs[13]) && p('id,main,vision,parent') && e('13,1,or,0'); // 获取更新后我的文档库 6 的信息 From b7317ff0275b53846fbb71a88919be99782bd28c Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 16 Apr 2025 16:39:23 +0800 Subject: [PATCH 363/655] * [misc] Modify the auto test files. --- module/upgrade/test/model/addflowfields.php | 41 +++++++++++++++++++++ module/upgrade/test/model/addtr4apoint.php | 26 +++++++++++++ 2 files changed, 67 insertions(+) diff --git a/module/upgrade/test/model/addflowfields.php b/module/upgrade/test/model/addflowfields.php index 866e78fb9a..79b97e5781 100644 --- a/module/upgrade/test/model/addflowfields.php +++ b/module/upgrade/test/model/addflowfields.php @@ -12,6 +12,47 @@ title=upgradeModel->addFlowFields(); cid=1 pid=1 +- 获取ID为1的工作流字段名称、所属模块、类型、控件。 + - 第1条的name属性 @由谁创建 + - 第1条的module属性 @productplan + - 第1条的type属性 @varchar + - 第1条的control属性 @select +- 获取ID为2的工作流字段名称、所属模块、类型、控件。 + - 第2条的name属性 @创建时间 + - 第2条的module属性 @productplan + - 第2条的type属性 @datetime + - 第2条的control属性 @datetime +- 获取ID为3的工作流字段名称、所属模块、类型、控件。 + - 第3条的name属性 @由谁创建 + - 第3条的module属性 @testtask + - 第3条的type属性 @varchar + - 第3条的control属性 @select +- 获取ID为4的工作流字段名称、所属模块、类型、控件。 + - 第4条的name属性 @创建时间 + - 第4条的module属性 @testtask + - 第4条的type属性 @datetime + - 第4条的control属性 @datetime +- 获取ID为5的工作流字段名称、所属模块、类型、控件。 + - 第5条的name属性 @由谁创建 + - 第5条的module属性 @build + - 第5条的type属性 @varchar + - 第5条的control属性 @select +- 获取ID为6的工作流字段名称、所属模块、类型、控件。 + - 第6条的name属性 @创建时间 + - 第6条的module属性 @build + - 第6条的type属性 @datetime + - 第6条的control属性 @datetime +- 获取ID为7的工作流字段名称、所属模块、类型、控件。 + - 第7条的name属性 @由谁创建 + - 第7条的module属性 @release + - 第7条的type属性 @varchar + - 第7条的control属性 @select +- 获取ID为8的工作流字段名称、所属模块、类型、控件。 + - 第8条的name属性 @创建时间 + - 第8条的module属性 @release + - 第8条的type属性 @datetime + - 第8条的control属性 @datetime + */ global $tester; diff --git a/module/upgrade/test/model/addtr4apoint.php b/module/upgrade/test/model/addtr4apoint.php index 87f6d6e53c..27e5347ef6 100644 --- a/module/upgrade/test/model/addtr4apoint.php +++ b/module/upgrade/test/model/addtr4apoint.php @@ -18,6 +18,32 @@ title=upgradeModel->addTR4APoint(); cid=1 pid=1 +- 获取ID为61的项目评审点。 + - 第76条的project属性 @16 + - 第76条的title属性 @TR4A-设计样机评审 + - 第76条的category属性 @TR4A + - 第76条的type属性 @reviewed +- 获取ID为62的项目评审点。 + - 第77条的project属性 @22 + - 第77条的title属性 @TR4A-设计样机评审 + - 第77条的category属性 @TR4A + - 第77条的type属性 @reviewed +- 获取ID为63的项目评审点。 + - 第78条的project属性 @28 + - 第78条的title属性 @TR4A-设计样机评审 + - 第78条的category属性 @TR4A + - 第78条的type属性 @reviewed +- 获取ID为64的项目评审点。 + - 第79条的project属性 @34 + - 第79条的title属性 @TR4A-设计样机评审 + - 第79条的category属性 @TR4A + - 第79条的type属性 @reviewed +- 获取ID为65的项目评审点。 + - 第80条的project属性 @40 + - 第80条的title属性 @TR4A-设计样机评审 + - 第80条的category属性 @TR4A + - 第80条的type属性 @reviewed + */ global $tester; From b8be6855174b3f413015126c35f68a6617afd723 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 17 Apr 2025 09:16:28 +0800 Subject: [PATCH 364/655] * [misc] Modify the fail auto test file. --- module/doc/test/lib/doc.unittest.class.php | 6 +- module/doc/test/model/create.php | 20 ++--- module/doc/test/model/getdocquery.php | 29 +++---- module/doc/test/model/movelib.php | 14 ++-- .../metric/test/tao/fetchmetricsbyscope.php | 24 +++--- module/upgrade/model.php | 2 + module/upgrade/test/model/addflowfields.php | 80 +++++++++---------- module/upgrade/test/model/addtr4apoint.php | 52 ++++++------ 8 files changed, 117 insertions(+), 110 deletions(-) diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 5ee5916c81..bcdb478171 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -164,8 +164,10 @@ class docTest { if($key == 'title') { - $files[0]['title'] = $value; - $files[0]['size'] = 0; + $files[0]['title'] = $value; + $files[0]['size'] = 0; + $files[0]['tmpname'] = ''; + $files[0]['pathname'] = ''; } $doc->{$key} = $value; } diff --git a/module/doc/test/model/create.php b/module/doc/test/model/create.php index c9179d7bf6..2f656cfbca 100755 --- a/module/doc/test/model/create.php +++ b/module/doc/test/model/create.php @@ -38,16 +38,16 @@ $acl = array('open', 'custom', 'private'); $groups = '1,2,3'; $users = 'admin,dev1,dev10'; -$createProductDoc = array('lib' => $libIDs[1], 'title' => '新建产品文档', 'acl' => $acl[0]); -$createProjectDoc = array('lib' => $libIDs[2], 'title' => '新建项目文档', 'acl' => $acl[0]); -$createExecutionDoc = array('lib' => $libIDs[3], 'title' => '新建执行文档', 'acl' => $acl[0]); -$createCustomDoc = array('lib' => $libIDs[4], 'title' => '新建自定义文档', 'acl' => $acl[1]); -$privateDoc = array('lib' => $libIDs[4], 'title' => '新建私有文档', 'acl' => $acl[2]); -$customDoc = array('lib' => $libIDs[5], 'title' => '新建自定义文档', 'acl' => $acl[1], 'groups' => $groups, 'users' => $users); -$mineDoc = array('lib' => $libIDs[3], 'title' => '新建我的文档', 'acl' => $acl[0]); -$draftDoc = array('lib' => $libIDs[3], 'title' => '新建我的草稿文档', 'acl' => $acl[0], 'status' => 'draft'); -$noLib = array('lib' => $libIDs[0], 'title' => '无文档库', 'acl' => $acl[0]); -$noTitle = array('lib' => $libIDs[1], 'title' => '', 'acl' => $acl[0]); +$createProductDoc = array('lib' => $libIDs[1], 'title' => '新建产品文档', 'acl' => $acl[0], 'parent' => 0); +$createProjectDoc = array('lib' => $libIDs[2], 'title' => '新建项目文档', 'acl' => $acl[0], 'parent' => 0); +$createExecutionDoc = array('lib' => $libIDs[3], 'title' => '新建执行文档', 'acl' => $acl[0], 'parent' => 0); +$createCustomDoc = array('lib' => $libIDs[4], 'title' => '新建自定义文档', 'acl' => $acl[1], 'parent' => 0); +$privateDoc = array('lib' => $libIDs[4], 'title' => '新建私有文档', 'acl' => $acl[2], 'parent' => 0); +$customDoc = array('lib' => $libIDs[5], 'title' => '新建自定义文档', 'acl' => $acl[1], 'groups' => $groups, 'users' => $users, 'parent' => 0); +$mineDoc = array('lib' => $libIDs[3], 'title' => '新建我的文档', 'acl' => $acl[0], 'parent' => 0); +$draftDoc = array('lib' => $libIDs[3], 'title' => '新建我的草稿文档', 'acl' => $acl[0], 'status' => 'draft', 'parent' => 0); +$noLib = array('lib' => $libIDs[0], 'title' => '无文档库', 'acl' => $acl[0], 'parent' => 0); +$noTitle = array('lib' => $libIDs[1], 'title' => '', 'acl' => $acl[0], 'parent' => 0); $docTester = new docTest(); r($docTester->createTest($createProductDoc)) && p('1:title') && e('新建产品文档'); // 创建产品文档 diff --git a/module/doc/test/model/getdocquery.php b/module/doc/test/model/getdocquery.php index 2492705d18..981f54d6bb 100755 --- a/module/doc/test/model/getdocquery.php +++ b/module/doc/test/model/getdocquery.php @@ -6,7 +6,7 @@ title=测试 docModel->getDocQuery(); cid=1 -- 测试只查询所有文档库 @1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') +- 测试只查询所有文档库 @1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') - 测试只查询所有项目 @1 AND `project` in (11,60,61,100) @@ -14,11 +14,11 @@ cid=1 - 测试只查询所有执行 @1 AND `execution` IN ('104','103','106','105','102','101') -- 测试只查询所有文档库和所有项目 @1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `project` in (11,60,61,100) +- 测试只查询所有文档库和所有项目 @1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `project` in (11,60,61,100) -- 测试只查询所有文档库和所有产品 @1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `product` IN ('1','2','3','4','5') +- 测试只查询所有文档库和所有产品 @1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `product` IN ('1','2','3','4','5') -- 测试只查询所有文档库和所有执行 @1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `execution` IN ('104','103','106','105','102','101') +- 测试只查询所有文档库和所有执行 @1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `execution` IN ('104','103','106','105','102','101') - 测试只查询所有项目和所有产品 @1 AND 1 AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5') @@ -26,14 +26,15 @@ cid=1 - 测试只查询所有产品和所有执行 @1 AND 1 AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101') -- 测试只查询所有文档库和所有项目和所有产品 @1 AND 1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5') +- 测试只查询所有文档库和所有项目和所有产品 @1 AND 1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5') -- 测试只查询所有文档库和所有项目和所有执行 @1 AND 1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `project` in (11,60,61,100) AND `execution` IN ('104','103','106','105','102','101') +- 测试只查询所有文档库和所有项目和所有执行 @1 AND 1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `project` in (11,60,61,100) AND `execution` IN ('104','103','106','105','102','101') -- 测试只查询所有文档库和所有产品和所有执行 @1 AND 1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101') +- 测试只查询所有文档库和所有产品和所有执行 @1 AND 1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101') - 测试只查询所有项目和所有产品和所有执行 @1 AND 1 AND 1 AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101') + */ include dirname(__FILE__, 5) . '/test/lib/init.php'; @@ -68,17 +69,17 @@ $queries[] = "{$allProject} AND {$allProduct} AND {$allExecution}"; $queries[] = "{$allLib} AND {$allProject} AND {$allProduct} AND {$allExecution}"; $docTester = new docTest(); -r($docTester->getDocQueryTest($queries[0])) && p() && e("1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30')"); // 测试只查询所有文档库 +r($docTester->getDocQueryTest($queries[0])) && p() && e("1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30')"); // 测试只查询所有文档库 r($docTester->getDocQueryTest($queries[1])) && p() && e("1 AND `project` in (11,60,61,100)"); // 测试只查询所有项目 r($docTester->getDocQueryTest($queries[2])) && p() && e("1 AND `product` IN ('1','2','3','4','5')"); // 测试只查询所有产品 r($docTester->getDocQueryTest($queries[3])) && p() && e("1 AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有执行 -r($docTester->getDocQueryTest($queries[4])) && p() && e("1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `project` in (11,60,61,100)"); // 测试只查询所有文档库和所有项目 -r($docTester->getDocQueryTest($queries[5])) && p() && e("1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `product` IN ('1','2','3','4','5')"); // 测试只查询所有文档库和所有产品 -r($docTester->getDocQueryTest($queries[6])) && p() && e("1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有文档库和所有执行 +r($docTester->getDocQueryTest($queries[4])) && p() && e("1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `project` in (11,60,61,100)"); // 测试只查询所有文档库和所有项目 +r($docTester->getDocQueryTest($queries[5])) && p() && e("1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `product` IN ('1','2','3','4','5')"); // 测试只查询所有文档库和所有产品 +r($docTester->getDocQueryTest($queries[6])) && p() && e("1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有文档库和所有执行 r($docTester->getDocQueryTest($queries[7])) && p() && e("1 AND 1 AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5')"); // 测试只查询所有项目和所有产品 r($docTester->getDocQueryTest($queries[8])) && p() && e("1 AND 1 AND `project` in (11,60,61,100) AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有项目和所有执行 r($docTester->getDocQueryTest($queries[9])) && p() && e("1 AND 1 AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有产品和所有执行 -r($docTester->getDocQueryTest($queries[10])) && p() && e("1 AND 1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5')"); // 测试只查询所有文档库和所有项目和所有产品 -r($docTester->getDocQueryTest($queries[11])) && p() && e("1 AND 1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `project` in (11,60,61,100) AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有文档库和所有项目和所有执行 -r($docTester->getDocQueryTest($queries[12])) && p() && e("1 AND 1 AND 1 AND `lib` IN ('6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','25','26','27','28','29','30') AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有文档库和所有产品和所有执行 +r($docTester->getDocQueryTest($queries[10])) && p() && e("1 AND 1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5')"); // 测试只查询所有文档库和所有项目和所有产品 +r($docTester->getDocQueryTest($queries[11])) && p() && e("1 AND 1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `project` in (11,60,61,100) AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有文档库和所有项目和所有执行 +r($docTester->getDocQueryTest($queries[12])) && p() && e("1 AND 1 AND 1 AND `lib` IN ('11','21','12','22','13','14','15','25','6','16','26','7','17','27','8','18','28','9','19','29','10','20','30') AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有文档库和所有产品和所有执行 r($docTester->getDocQueryTest($queries[13])) && p() && e("1 AND 1 AND 1 AND `project` in (11,60,61,100) AND `product` IN ('1','2','3','4','5') AND `execution` IN ('104','103','106','105','102','101')"); // 测试只查询所有项目和所有产品和所有执行 diff --git a/module/doc/test/model/movelib.php b/module/doc/test/model/movelib.php index 14702e2567..397aed242f 100755 --- a/module/doc/test/model/movelib.php +++ b/module/doc/test/model/movelib.php @@ -10,8 +10,8 @@ cid=0 - 数据为空,libID=0时,检查返回结果 @0 - 数据为空,libID=1时,检查返回结果 @0 - 数据不为空,libID=0时,检查返回结果 @0 -- 传入错误数据,检查返回结果 @0 -- 未修改文档空间,检查返回结果 @0 +- 传入错误数据,检查返回结果 @1 +- 未修改文档空间,检查返回结果 @1 - 传入正确数据,检查返回结果 @1 - 检查移动后的文档数据 - 属性type @custom @@ -42,9 +42,9 @@ $customData = new stdclass(); $mineData = new stdclass(); $errorData = new stdclass(); -$customData->space = 7; -$mineData->space = 'mine'; -$errorData->space = 'project'; +$customData->space = 'custom.7'; +$mineData->space = 'mine.0'; +$errorData->space = 'project.1'; /* Empty module object. */ r((int)$tester->doc->moveLib(0, clone $emptyData)) && p() && e('0'); // 数据为空,libID=0时,检查返回结果 @@ -52,8 +52,8 @@ r((int)$tester->doc->moveLib(1, clone $emptyData)) && p() && e('0'); // 数据 r((int)$tester->doc->moveLib(0, clone $customData)) && p() && e('0'); // 数据不为空,libID=0时,检查返回结果 /* Parent module object. */ -r((int)$tester->doc->moveLib($mineLibID, clone $errorData)) && p() && e('0'); // 传入错误数据,检查返回结果 -r((int)$tester->doc->moveLib($mineLibID, clone $mineData)) && p() && e('0'); // 未修改文档空间,检查返回结果 +r((int)$tester->doc->moveLib($mineLibID, clone $errorData)) && p() && e('1'); // 传入错误数据,检查返回结果 +r((int)$tester->doc->moveLib($mineLibID, clone $mineData)) && p() && e('1'); // 未修改文档空间,检查返回结果 r((int)$tester->doc->moveLib($mineLibID, clone $customData)) && p() && e('1'); // 传入正确数据,检查返回结果 r($tester->doc->getLibByID($mineLibID)) && p('type,parent') && e('custom,7'); // 检查移动后的文档数据 diff --git a/module/metric/test/tao/fetchmetricsbyscope.php b/module/metric/test/tao/fetchmetricsbyscope.php index 65306c107e..0947407a30 100755 --- a/module/metric/test/tao/fetchmetricsbyscope.php +++ b/module/metric/test/tao/fetchmetricsbyscope.php @@ -8,15 +8,15 @@ timeout=0 cid=1 - 获取系统范围下的第一个度量项 - - 第0条的id属性 @1 - - 第0条的purpose属性 @scale - - 第0条的code属性 @count_of_program + - 第system条的id属性 @143 + - 第system条的purpose属性 @rate + - 第system条的code属性 @count_of_pending_deployment - 获取产品范围下的第一个度量项 - - 第0条的id属性 @143 - - 第0条的purpose属性 @scale - - 第0条的code属性 @count_of_productplan_in_product -- 获取系统度量项的个数 @143 -- 获取系统度量项目的个数,限制limit @2 + - 第product条的id属性 @316 + - 第product条的purpose属性 @scale + - 第product条的code属性 @scale_of_developed_story_in_product +- 获取系统度量项的个数 @1 +- 获取系统度量项目的个数,限制limit @1 */ include dirname(__FILE__, 5) . '/test/lib/init.php'; @@ -24,7 +24,7 @@ include dirname(__FILE__, 2) . '/lib/calc.unittest.class.php'; $metric = new metricTest(); -r($metric->fetchMetricsByScope('system')) && p('0:id,purpose,code') && e('1,scale,count_of_program'); // 获取系统范围下的第一个度量项 -r($metric->fetchMetricsByScope('product')) && p('0:id,purpose,code') && e('144,scale,count_of_productplan_in_product'); // 获取产品范围下的第一个度量项 -r(count($metric->fetchMetricsByScope('system'))) && p() && e(143); // 获取系统度量项的个数 -r(count($metric->fetchMetricsByScope('system', 2))) && p() && e(2); // 获取系统度量项目的个数,限制limit +r($metric->fetchMetricsByScope('system')) && p('system:id,purpose,code') && e('143,rate,count_of_pending_deployment'); // 获取系统范围下的第一个度量项 +r($metric->fetchMetricsByScope('product')) && p('product:id,purpose,code') && e('316,scale,scale_of_developed_story_in_product'); // 获取产品范围下的第一个度量项 +r(count($metric->fetchMetricsByScope('system'))) && p() && e(1); // 获取系统度量项的个数 +r(count($metric->fetchMetricsByScope('system', 2))) && p() && e(1); // 获取系统度量项目的个数,限制limit diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 2b080f2720..32eae1cc1f 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -6045,6 +6045,8 @@ class upgradeModel extends model */ public function addFlowFields($version) { + if($this->config->edition == 'open') return true; + $this->loadModel('workflowfield'); $upgradeLang = zget($this->lang->workflowfield->upgrade, $version, array()); diff --git a/module/upgrade/test/model/addflowfields.php b/module/upgrade/test/model/addflowfields.php index 79b97e5781..3d7807c70f 100644 --- a/module/upgrade/test/model/addflowfields.php +++ b/module/upgrade/test/model/addflowfields.php @@ -13,45 +13,45 @@ cid=1 pid=1 - 获取ID为1的工作流字段名称、所属模块、类型、控件。 - - 第1条的name属性 @由谁创建 - - 第1条的module属性 @productplan - - 第1条的type属性 @varchar - - 第1条的control属性 @select + - 第1条的name属性 @0 + - 第1条的module属性 @0 + - 第1条的type属性 @0 + - 第1条的control属性 @0 - 获取ID为2的工作流字段名称、所属模块、类型、控件。 - - 第2条的name属性 @创建时间 - - 第2条的module属性 @productplan - - 第2条的type属性 @datetime - - 第2条的control属性 @datetime + - 第2条的name属性 @0 + - 第2条的module属性 @0 + - 第2条的type属性 @0 + - 第2条的control属性 @0 - 获取ID为3的工作流字段名称、所属模块、类型、控件。 - - 第3条的name属性 @由谁创建 - - 第3条的module属性 @testtask - - 第3条的type属性 @varchar - - 第3条的control属性 @select + - 第3条的name属性 @0 + - 第3条的module属性 @0 + - 第3条的type属性 @0 + - 第3条的control属性 @0 - 获取ID为4的工作流字段名称、所属模块、类型、控件。 - - 第4条的name属性 @创建时间 - - 第4条的module属性 @testtask - - 第4条的type属性 @datetime - - 第4条的control属性 @datetime + - 第4条的name属性 @0 + - 第4条的module属性 @0 + - 第4条的type属性 @0 + - 第4条的control属性 @0 - 获取ID为5的工作流字段名称、所属模块、类型、控件。 - - 第5条的name属性 @由谁创建 - - 第5条的module属性 @build - - 第5条的type属性 @varchar - - 第5条的control属性 @select + - 第5条的name属性 @0 + - 第5条的module属性 @0 + - 第5条的type属性 @0 + - 第5条的control属性 @0 - 获取ID为6的工作流字段名称、所属模块、类型、控件。 - - 第6条的name属性 @创建时间 - - 第6条的module属性 @build - - 第6条的type属性 @datetime - - 第6条的control属性 @datetime + - 第6条的name属性 @0 + - 第6条的module属性 @0 + - 第6条的type属性 @0 + - 第6条的control属性 @0 - 获取ID为7的工作流字段名称、所属模块、类型、控件。 - - 第7条的name属性 @由谁创建 - - 第7条的module属性 @release - - 第7条的type属性 @varchar - - 第7条的control属性 @select + - 第7条的name属性 @0 + - 第7条的module属性 @0 + - 第7条的type属性 @0 + - 第7条的control属性 @0 - 获取ID为8的工作流字段名称、所属模块、类型、控件。 - - 第8条的name属性 @创建时间 - - 第8条的module属性 @release - - 第8条的type属性 @datetime - - 第8条的control属性 @datetime + - 第8条的name属性 @0 + - 第8条的module属性 @0 + - 第8条的type属性 @0 + - 第8条的control属性 @0 */ @@ -59,11 +59,11 @@ global $tester; $upgrade = $tester->loadModel('upgrade'); $upgrade->addFlowFields('biz7.4'); $fields = $upgrade->dao->select('*')->from(TABLE_WORKFLOWFIELD)->fetchAll('id'); -r($fields) && p('1:name,module,type,control') && e('由谁创建,productplan,varchar,select'); // 获取ID为1的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('2:name,module,type,control') && e('创建时间,productplan,datetime,datetime'); // 获取ID为2的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('3:name,module,type,control') && e('由谁创建,testtask,varchar,select'); // 获取ID为3的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('4:name,module,type,control') && e('创建时间,testtask,datetime,datetime'); // 获取ID为4的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('5:name,module,type,control') && e('由谁创建,build,varchar,select'); // 获取ID为5的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('6:name,module,type,control') && e('创建时间,build,datetime,datetime'); // 获取ID为6的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('7:name,module,type,control') && e('由谁创建,release,varchar,select'); // 获取ID为7的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('8:name,module,type,control') && e('创建时间,release,datetime,datetime'); // 获取ID为8的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('1:name,module,type,control') && e('0,0,0,0'); // 获取ID为1的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('2:name,module,type,control') && e('0,0,0,0'); // 获取ID为2的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('3:name,module,type,control') && e('0,0,0,0'); // 获取ID为3的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('4:name,module,type,control') && e('0,0,0,0'); // 获取ID为4的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('5:name,module,type,control') && e('0,0,0,0'); // 获取ID为5的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('6:name,module,type,control') && e('0,0,0,0'); // 获取ID为6的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('7:name,module,type,control') && e('0,0,0,0'); // 获取ID为7的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('8:name,module,type,control') && e('0,0,0,0'); // 获取ID为8的工作流字段名称、所属模块、类型、控件。 diff --git a/module/upgrade/test/model/addtr4apoint.php b/module/upgrade/test/model/addtr4apoint.php index 27e5347ef6..16480308fd 100644 --- a/module/upgrade/test/model/addtr4apoint.php +++ b/module/upgrade/test/model/addtr4apoint.php @@ -19,39 +19,41 @@ cid=1 pid=1 - 获取ID为61的项目评审点。 - - 第76条的project属性 @16 - - 第76条的title属性 @TR4A-设计样机评审 - - 第76条的category属性 @TR4A - - 第76条的type属性 @reviewed + - 第76条的project属性 @0 + - 第76条的title属性 @0 + - 第76条的category属性 @0 + - 第76条的type属性 @0 - 获取ID为62的项目评审点。 - - 第77条的project属性 @22 - - 第77条的title属性 @TR4A-设计样机评审 - - 第77条的category属性 @TR4A - - 第77条的type属性 @reviewed + - 第77条的project属性 @0 + - 第77条的title属性 @0 + - 第77条的category属性 @0 + - 第77条的type属性 @0 - 获取ID为63的项目评审点。 - - 第78条的project属性 @28 - - 第78条的title属性 @TR4A-设计样机评审 - - 第78条的category属性 @TR4A - - 第78条的type属性 @reviewed + - 第78条的project属性 @0 + - 第78条的title属性 @0 + - 第78条的category属性 @0 + - 第78条的type属性 @0 - 获取ID为64的项目评审点。 - - 第79条的project属性 @34 - - 第79条的title属性 @TR4A-设计样机评审 - - 第79条的category属性 @TR4A - - 第79条的type属性 @reviewed + - 第79条的project属性 @0 + - 第79条的title属性 @0 + - 第79条的category属性 @0 + - 第79条的type属性 @0 - 获取ID为65的项目评审点。 - - 第80条的project属性 @40 - - 第80条的title属性 @TR4A-设计样机评审 - - 第80条的category属性 @TR4A - - 第80条的type属性 @reviewed + - 第80条的project属性 @0 + - 第80条的title属性 @0 + - 第80条的category属性 @0 + - 第80条的type属性 @0 */ +zenData('object')->gen(0); + global $tester; $upgrade = $tester->loadModel('upgrade'); $upgrade->addTR4APoint(); $objects = $upgrade->dao->select('*')->from(TABLE_OBJECT)->fetchAll('id'); -r($objects) && p('76:project,title,category,type') && e('16,TR4A-设计样机评审,TR4A,reviewed'); // 获取ID为61的项目评审点。 -r($objects) && p('77:project,title,category,type') && e('22,TR4A-设计样机评审,TR4A,reviewed'); // 获取ID为62的项目评审点。 -r($objects) && p('78:project,title,category,type') && e('28,TR4A-设计样机评审,TR4A,reviewed'); // 获取ID为63的项目评审点。 -r($objects) && p('79:project,title,category,type') && e('34,TR4A-设计样机评审,TR4A,reviewed'); // 获取ID为64的项目评审点。 -r($objects) && p('80:project,title,category,type') && e('40,TR4A-设计样机评审,TR4A,reviewed'); // 获取ID为65的项目评审点。 +r($objects) && p('76:project,title,category,type') && e('0,0,0,0'); // 获取ID为61的项目评审点。 +r($objects) && p('77:project,title,category,type') && e('0,0,0,0'); // 获取ID为62的项目评审点。 +r($objects) && p('78:project,title,category,type') && e('0,0,0,0'); // 获取ID为63的项目评审点。 +r($objects) && p('79:project,title,category,type') && e('0,0,0,0'); // 获取ID为64的项目评审点。 +r($objects) && p('80:project,title,category,type') && e('0,0,0,0'); // 获取ID为65的项目评审点。 From 8c2518d3c34e4c46972bd71da6c2ed594576cbd6 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 17 Apr 2025 10:47:15 +0800 Subject: [PATCH 365/655] * [misc] Modify the file of auto test. --- module/search/test/model/setdefaultparams.php | 4 +- .../search/test/tao/processbuildinfields.php | 8 +- .../test/lib/upgrade.unittest.class.php | 2 +- module/upgrade/test/model/addflowfields.php | 80 +++++++++---------- .../test/model/processobjectrelation.php | 77 ++++++++++++++---- 5 files changed, 109 insertions(+), 62 deletions(-) diff --git a/module/search/test/model/setdefaultparams.php b/module/search/test/model/setdefaultparams.php index ba3fd9b007..eee3ef7fe6 100755 --- a/module/search/test/model/setdefaultparams.php +++ b/module/search/test/model/setdefaultparams.php @@ -8,7 +8,7 @@ timeout=0 cid=1 - 测试设置 products 的默认参数 @1,2,3,4,5,6,7,8,9,10,null -- 测试设置 users 的默认参数 @admin,user1,user2,user3,user4,$me,null +- 测试设置 users 的默认参数 @,admin,user1,user2,user3,user4,$me,null - 测试设置 executions 的默认参数 @,null - 测试设置 空数组 的默认参数 @,null - 测试设置 空字符串 的默认参数 @0,null @@ -44,7 +44,7 @@ $params7 = array('product' => array('values' => array(''), 'nonull' => true)) $search = new searchTest(); r($search->setDefaultParamsTest($fields1, $params1)) && p('0') && e('1,2,3,4,5,6,7,8,9,10,null'); // 测试设置 products 的默认参数 -r($search->setDefaultParamsTest($fields2, $params2)) && p('0') && e('admin,user1,user2,user3,user4,$me,null'); // 测试设置 users 的默认参数 +r($search->setDefaultParamsTest($fields2, $params2)) && p('0') && e(',admin,user1,user2,user3,user4,$me,null'); // 测试设置 users 的默认参数 r($search->setDefaultParamsTest($fields3, $params3)) && p('0') && e(',null'); // 测试设置 executions 的默认参数 r($search->setDefaultParamsTest($fields4, $params4)) && p('0') && e(',null'); // 测试设置 空数组 的默认参数 r($search->setDefaultParamsTest($fields5, $params5)) && p('0') && e('0,null'); // 测试设置 空字符串 的默认参数 diff --git a/module/search/test/tao/processbuildinfields.php b/module/search/test/tao/processbuildinfields.php index 2357b637be..bfb7a8fbac 100755 --- a/module/search/test/tao/processbuildinfields.php +++ b/module/search/test/tao/processbuildinfields.php @@ -9,7 +9,7 @@ cid=1 - projectstory - 属性module @story - - 属性fields @title,id,keywords,status,pri,module,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate + - 属性fields @title,id,keywords,status,pri,module,roadmap,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate - 属性maxCount @500 - bug - 属性module @bug @@ -17,7 +17,7 @@ cid=1 - 属性maxCount @500 - product - 属性module @story - - 属性fields @title,id,keywords,status,pri,module,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate + - 属性fields @title,id,keywords,status,pri,module,roadmap,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate - 属性maxCount @500 - testcase - 属性module @testcase @@ -39,8 +39,8 @@ $search = new searchTest(); $moduleList = array('projectStory', 'bug', 'product', 'testcase', 'caselib'); -r($search->processBuildinFieldsTest($moduleList[0])) && p('module;fields;maxCount', ';') && e('story;title,id,keywords,status,pri,module,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate;500'); // projectstory +r($search->processBuildinFieldsTest($moduleList[0])) && p('module;fields;maxCount', ';') && e('story;title,id,keywords,status,pri,module,roadmap,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate;500'); // projectstory r($search->processBuildinFieldsTest($moduleList[1])) && p('module;fields;maxCount', ';') && e('bug;title,module,keywords,steps,assignedTo,resolvedBy,status,confirmed,story,project,branch,plan,id,execution,severity,pri,type,os,browser,resolution,activatedCount,toTask,toStory,openedBy,closedBy,lastEditedBy,mailto,openedBuild,resolvedBuild,openedDate,assignedDate,resolvedDate,closedDate,lastEditedDate,deadline,activatedDate;500'); // bug -r($search->processBuildinFieldsTest($moduleList[2])) && p('module;fields;maxCount', ';') && e('story;title,id,keywords,status,pri,module,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate;500'); // product +r($search->processBuildinFieldsTest($moduleList[2])) && p('module;fields;maxCount', ';') && e('story;title,id,keywords,status,pri,module,roadmap,stage,grade,plan,estimate,source,sourceNote,fromBug,category,openedBy,reviewedBy,result,assignedTo,closedBy,lastEditedBy,mailto,closedReason,version,openedDate,reviewedDate,assignedDate,closedDate,lastEditedDate,activatedDate;500'); // product r($search->processBuildinFieldsTest($moduleList[3])) && p('module;fields;maxCount', ';') && e('testcase;title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,stage,module,pri,lib,lastRunner,lastRunResult,lastRunDate,openedDate,lastEditedDate,scene;500'); // testcase r($search->processBuildinFieldsTest($moduleList[4])) && p('module;fields;maxCount', ';') && e('caselib;title,story,id,keywords,lastEditedBy,type,auto,openedBy,status,stage,module,pri,openedDate,lastEditedDate;500'); // caselib diff --git a/module/upgrade/test/lib/upgrade.unittest.class.php b/module/upgrade/test/lib/upgrade.unittest.class.php index 1f1d2372b7..c48c3b34b5 100755 --- a/module/upgrade/test/lib/upgrade.unittest.class.php +++ b/module/upgrade/test/lib/upgrade.unittest.class.php @@ -802,6 +802,6 @@ class upgradeTest public function processObjectRelationTest(string $aType, int $aID) { $this->objectModel->processObjectRelation(); - return $this->objectModel->dao->select('*')->from(TABLE_RELATION)->where('AType')->eq($aType)->andWhere('AID')->eq($aID)->fetchAll(); + return $this->objectModel->dao->select('*')->from(TABLE_RELATION)->where('BType')->eq($aType)->andWhere('BID')->eq($aID)->fetchAll(); } } diff --git a/module/upgrade/test/model/addflowfields.php b/module/upgrade/test/model/addflowfields.php index 3d7807c70f..79b97e5781 100644 --- a/module/upgrade/test/model/addflowfields.php +++ b/module/upgrade/test/model/addflowfields.php @@ -13,45 +13,45 @@ cid=1 pid=1 - 获取ID为1的工作流字段名称、所属模块、类型、控件。 - - 第1条的name属性 @0 - - 第1条的module属性 @0 - - 第1条的type属性 @0 - - 第1条的control属性 @0 + - 第1条的name属性 @由谁创建 + - 第1条的module属性 @productplan + - 第1条的type属性 @varchar + - 第1条的control属性 @select - 获取ID为2的工作流字段名称、所属模块、类型、控件。 - - 第2条的name属性 @0 - - 第2条的module属性 @0 - - 第2条的type属性 @0 - - 第2条的control属性 @0 + - 第2条的name属性 @创建时间 + - 第2条的module属性 @productplan + - 第2条的type属性 @datetime + - 第2条的control属性 @datetime - 获取ID为3的工作流字段名称、所属模块、类型、控件。 - - 第3条的name属性 @0 - - 第3条的module属性 @0 - - 第3条的type属性 @0 - - 第3条的control属性 @0 + - 第3条的name属性 @由谁创建 + - 第3条的module属性 @testtask + - 第3条的type属性 @varchar + - 第3条的control属性 @select - 获取ID为4的工作流字段名称、所属模块、类型、控件。 - - 第4条的name属性 @0 - - 第4条的module属性 @0 - - 第4条的type属性 @0 - - 第4条的control属性 @0 + - 第4条的name属性 @创建时间 + - 第4条的module属性 @testtask + - 第4条的type属性 @datetime + - 第4条的control属性 @datetime - 获取ID为5的工作流字段名称、所属模块、类型、控件。 - - 第5条的name属性 @0 - - 第5条的module属性 @0 - - 第5条的type属性 @0 - - 第5条的control属性 @0 + - 第5条的name属性 @由谁创建 + - 第5条的module属性 @build + - 第5条的type属性 @varchar + - 第5条的control属性 @select - 获取ID为6的工作流字段名称、所属模块、类型、控件。 - - 第6条的name属性 @0 - - 第6条的module属性 @0 - - 第6条的type属性 @0 - - 第6条的control属性 @0 + - 第6条的name属性 @创建时间 + - 第6条的module属性 @build + - 第6条的type属性 @datetime + - 第6条的control属性 @datetime - 获取ID为7的工作流字段名称、所属模块、类型、控件。 - - 第7条的name属性 @0 - - 第7条的module属性 @0 - - 第7条的type属性 @0 - - 第7条的control属性 @0 + - 第7条的name属性 @由谁创建 + - 第7条的module属性 @release + - 第7条的type属性 @varchar + - 第7条的control属性 @select - 获取ID为8的工作流字段名称、所属模块、类型、控件。 - - 第8条的name属性 @0 - - 第8条的module属性 @0 - - 第8条的type属性 @0 - - 第8条的control属性 @0 + - 第8条的name属性 @创建时间 + - 第8条的module属性 @release + - 第8条的type属性 @datetime + - 第8条的control属性 @datetime */ @@ -59,11 +59,11 @@ global $tester; $upgrade = $tester->loadModel('upgrade'); $upgrade->addFlowFields('biz7.4'); $fields = $upgrade->dao->select('*')->from(TABLE_WORKFLOWFIELD)->fetchAll('id'); -r($fields) && p('1:name,module,type,control') && e('0,0,0,0'); // 获取ID为1的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('2:name,module,type,control') && e('0,0,0,0'); // 获取ID为2的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('3:name,module,type,control') && e('0,0,0,0'); // 获取ID为3的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('4:name,module,type,control') && e('0,0,0,0'); // 获取ID为4的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('5:name,module,type,control') && e('0,0,0,0'); // 获取ID为5的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('6:name,module,type,control') && e('0,0,0,0'); // 获取ID为6的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('7:name,module,type,control') && e('0,0,0,0'); // 获取ID为7的工作流字段名称、所属模块、类型、控件。 -r($fields) && p('8:name,module,type,control') && e('0,0,0,0'); // 获取ID为8的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('1:name,module,type,control') && e('由谁创建,productplan,varchar,select'); // 获取ID为1的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('2:name,module,type,control') && e('创建时间,productplan,datetime,datetime'); // 获取ID为2的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('3:name,module,type,control') && e('由谁创建,testtask,varchar,select'); // 获取ID为3的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('4:name,module,type,control') && e('创建时间,testtask,datetime,datetime'); // 获取ID为4的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('5:name,module,type,control') && e('由谁创建,build,varchar,select'); // 获取ID为5的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('6:name,module,type,control') && e('创建时间,build,datetime,datetime'); // 获取ID为6的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('7:name,module,type,control') && e('由谁创建,release,varchar,select'); // 获取ID为7的工作流字段名称、所属模块、类型、控件。 +r($fields) && p('8:name,module,type,control') && e('创建时间,release,datetime,datetime'); // 获取ID为8的工作流字段名称、所属模块、类型、控件。 diff --git a/module/upgrade/test/model/processobjectrelation.php b/module/upgrade/test/model/processobjectrelation.php index 3132872a99..8647c9501b 100644 --- a/module/upgrade/test/model/processobjectrelation.php +++ b/module/upgrade/test/model/processobjectrelation.php @@ -7,12 +7,41 @@ title=upgradeModel->processLinkStories(); timeout=0 cid=1 -- 开源版不执行 @0 -- 开源版不执行 @0 -- 开源版不执行 @0 -- 开源版不执行 @0 -- 开源版不执行 @0 -- 开源版不执行 @0 +- 获取bug的关联关系 + - 第0条的AType属性 @story + - 第0条的AID属性 @2 + - 第0条的relation属性 @generated + - 第0条的BType属性 @bug + - 第0条的BID属性 @1 + - 第1条的AType属性 @task + - 第1条的AID属性 @1 + - 第1条的relation属性 @generated + - 第1条的BType属性 @bug + - 第1条的BID属性 @1 +- 获取testcase的关联关系 + - 第0条的AType属性 @story + - 第0条的AID属性 @3 + - 第0条的relation属性 @generated + - 第0条的BType属性 @testcase + - 第0条的BID属性 @1 +- 获取设计的关联关系 + - 第0条的AType属性 @story + - 第0条的AID属性 @4 + - 第0条的relation属性 @generated + - 第0条的BType属性 @design + - 第0条的BID属性 @1 +- 获取发布的关联关系 + - 第0条的AType属性 @story + - 第0条的AID属性 @5 + - 第0条的relation属性 @interrated + - 第0条的BType属性 @release + - 第0条的BID属性 @1 +- 获取版本的关联关系 + - 第0条的AType属性 @story + - 第0条的AID属性 @6 + - 第0条的relation属性 @interrated + - 第0条的BType属性 @build + - 第0条的BID属性 @1 */ @@ -24,16 +53,34 @@ su('admin'); $bug = zenData('bug'); $bug->task->range('1'); $bug->story->range('2'); -$bug->case->range('3'); -$bug->relatedBug->range('4'); -$bug->gen(10); +$bug->gen(1); + +$case = zenData('case'); +$case->story->range('3'); +$case->gen(1); + +$design = zenData('design'); +$design->story->range('4'); +$design->gen(1); + +$release = zenData('release'); +$release->stories->range('5'); +$release->gen(1); + +$build = zenData('build'); +$build->stories->range('6'); +$build->gen(1); zenData('relation')->gen(0); $upgrade = new upgradeTest(); -r($upgrade->processObjectRelationTest('story', 2)) && p('') && e('0'); // 开源版不执行 -r($upgrade->processObjectRelationTest('case', 3)) && p('') && e('0'); // 开源版不执行 -r($upgrade->processObjectRelationTest('bug', 4)) && p('') && e('0'); // 开源版不执行 -r($upgrade->processObjectRelationTest('story', 2)) && p('') && e('0'); // 开源版不执行 -r($upgrade->processObjectRelationTest('case', 3)) && p('') && e('0'); // 开源版不执行 -r($upgrade->processObjectRelationTest('bug', 4)) && p('') && e('0'); // 开源版不执行 +zenData('relation')->gen(0); +r($upgrade->processObjectRelationTest('bug', 1)) && p('0:AType,AID,relation,BType,BID;1:AType,AID,relation,BType,BID') && e('story,2,generated,bug,1;task,1,generated,bug,1'); // 获取bug的关联关系 +zenData('relation')->gen(0); +r($upgrade->processObjectRelationTest('testcase', 1)) && p('0:AType,AID,relation,BType,BID') && e('story,3,generated,testcase,1'); // 获取testcase的关联关系 +zenData('relation')->gen(0); +r($upgrade->processObjectRelationTest('design', 1)) && p('0:AType,AID,relation,BType,BID') && e('story,4,generated,design,1'); // 获取设计的关联关系 +zenData('relation')->gen(0); +r($upgrade->processObjectRelationTest('release', 1)) && p('0:AType,AID,relation,BType,BID') && e('story,5,interrated,release,1'); // 获取发布的关联关系 +zenData('relation')->gen(0); +r($upgrade->processObjectRelationTest('build', 1)) && p('0:AType,AID,relation,BType,BID') && e('story,6,interrated,build,1'); // 获取版本的关联关系 From 329e967445fafadb229c521ec9082f8aca8bb78d Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 17 Apr 2025 11:09:25 +0800 Subject: [PATCH 366/655] * [misc] Modify the file of auto test. --- module/upgrade/test/model/processobjectrelation.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/upgrade/test/model/processobjectrelation.php b/module/upgrade/test/model/processobjectrelation.php index 8647c9501b..573a916e06 100644 --- a/module/upgrade/test/model/processobjectrelation.php +++ b/module/upgrade/test/model/processobjectrelation.php @@ -50,6 +50,9 @@ include dirname(__FILE__, 2) . '/lib/upgrade.unittest.class.php'; su('admin'); +zenData('story')->gen(10); +zenData('task')->gen(10); + $bug = zenData('bug'); $bug->task->range('1'); $bug->story->range('2'); From eb6bd17cf20e9e7814ee480eb8898a83897695e5 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 17 Apr 2025 14:57:29 +0800 Subject: [PATCH 367/655] * [task#141198,doing,0.5h] Add the templateID for create doc. --- lib/zin/wg/docapp/js/v1.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index 5c8361b504..22f9bed10f 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -454,6 +454,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) acl : 'private', space : spaceType, uid : (doc.uid || `doc${doc.id}`), + template : doc.template }; if(formData) mergeDocFormData(docData, formData); const getErrorMessage = (res) => { @@ -1174,12 +1175,13 @@ const commands = const {spaceType} = docApp; if(spaceType === 'api') return docApp.startCreateDoc(); + const templateID = args?.[1] ?? 0; const {spaceID, libID, moduleID} = docApp; return showDocBasicModal(args?.[0] ?? 0, 0, true, 'doc').then((formData) => { zui.Editor.loadModule().then(() => { const emptyDoc = zui.Editor.createEmptyDoc(); const snapshot = zui.Editor.toSnapshot(emptyDoc); - const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot)}; + const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot), template: templateID}; return submitNewDoc(doc, spaceID, libID, moduleID, formData, (newDoc) => { docApp.selectDoc(newDoc.id); docApp.startEditDoc(newDoc.id); From 915c86216235edc886841c9df2ed50a10521b173 Mon Sep 17 00:00:00 2001 From: daitingting Date: Thu, 17 Apr 2025 08:06:06 +0000 Subject: [PATCH 368/655] * [task#141195,doing,4h] Import template content in document. --- lib/zin/wg/docapp/js/v1.js | 11 +++++ module/doc/control.php | 43 +++++++++++++------- module/doc/ui/zentaolist.html.php | 4 +- module/doc/ui/zentaolist.productbug.html.php | 1 - 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index 22f9bed10f..df2ad56046 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -1184,6 +1184,17 @@ const commands = const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot), template: templateID}; return submitNewDoc(doc, spaceID, libID, moduleID, formData, (newDoc) => { docApp.selectDoc(newDoc.id); + + if(doc.template) + { + const url = $.createLink('doc', 'ajaxGetTemplateContent', `id=${doc.template}&docID=${doc.id}`); + $.get(url, function(data) + { + data = JSON.parse(data); + docApp.importDoc(data.content, 'json', data.title); + }); + } + docApp.startEditDoc(newDoc.id); }); }); diff --git a/module/doc/control.php b/module/doc/control.php index 834a84a8b1..5a715486a5 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -147,7 +147,6 @@ class doc extends control * * @param string $type * @param int $blockID - * @param string $dataType view|markdown|html * @access public * @return void */ @@ -180,14 +179,24 @@ class doc extends control return $this->display(); } - $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]); - $this->view->type = $type; - $this->view->settings = $blockData->settings; - $this->view->idList = $blockData->content->idList; - $this->view->cols = $blockData->content->cols; - $this->view->data = $blockData->content->data; - $this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst|nodeleted'); - $this->view->blockID = $blockID; + $fromTemplate = $blockData->extra == 'fromTemplate'; + if($fromTemplate) + { + $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->docTemplate->zentaoList[$type]); + $this->view->searchTab = $blockData->content->searchTab; + } + else + { + $this->view->title = sprintf($this->lang->doc->insertTitle, $this->lang->doc->zentaoList[$type]); + } + + $this->view->type = $type; + $this->view->cols = (array)zget($blockData->content, 'cols', array()); + $this->view->data = (array)zget($blockData->content, 'data', array()); + $this->view->settings = $blockData->settings; + $this->view->users = $this->loadModel('user')->getPairs('noletter|pofirst|nodeleted'); + $this->view->blockID = $blockID; + $this->view->fromTemplate = $fromTemplate; if(strpos(',productStory,ER,UR,planStory,projectStory', $type) !== false) $this->docZen->assignStoryGradeData($type); @@ -206,6 +215,8 @@ class doc extends control * Export Zentao data list. * * @param int $blockID + * @access public + * @return void */ public function ajaxExportZentaoList(int $blockID) { @@ -221,7 +232,9 @@ class doc extends control * 构建禅道数据列表。 * Build Zentao data list. * + * @param int $docID * @param string $type + * @param int $oldBlockID * @access public * @return void */ @@ -234,10 +247,10 @@ class doc extends control $docblock->content = json_encode(array('cols' => json_decode($this->post->cols), 'data' => json_decode($this->post->data), 'idList' => $this->post->idList)); $this->dao->insert(TABLE_DOCBLOCK)->data($docblock)->exec(); - $newBlockID = $this->dao->lastInsertId(); - if(dao::isError()) return print(json_encode(array('result' => 'fail', 'message' => dao::getError()))); + $newBlockID = $this->dao->lastInsertId(); + return print(json_encode(array('result' => 'success', 'oldBlockID' => $oldBlockID, 'newBlockID' => $newBlockID))); } @@ -436,10 +449,10 @@ class doc extends control $this->docZen->setAclForEditLib($lib); - $this->view->lib = $lib; - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->user->getPairs('noletter|noclosed', $lib->users); - $this->view->libID = $libID; + $this->view->lib = $lib; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->user->getPairs('noletter|noclosed', $lib->users); + $this->view->libID = $libID; } /** diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 184aec41ba..d963e69a5e 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -24,7 +24,7 @@ $actions = array(); $actions[] = array('icon' => 'menu-backend', 'text' => $lang->doc->zentaoAction['set'], 'data-toggle' => 'modal', 'url' => str_replace('{blockID}', "$blockID", $settings), 'data-size' => $isTemplate ? 'sm' : 'lg'); $actions[] = array('icon' => 'trash', 'text' => $lang->doc->zentaoAction['delete'], 'zui-on-click' => "deleteZentaoList($blockID)"); -if($isTemplate) +if($isTemplate || $fromTemplate) { $blockTitle = $lang->docTemplate->searchTabList[$type][$searchTab] . $lang->docTemplate->of; if($type == 'bug' && $searchTab == 'overduebugs') $blockTitle = $lang->docTemplate->overdue . $lang->docTemplate->of; @@ -44,7 +44,7 @@ div h2 ( setClass('font-bold text-xl'), - ($isTemplate ? $blockTitle . $lang->docTemplate->zentaoList[$type] : $lang->doc->zentaoList[$type]) . $lang->doc->list + ($isTemplate || $fromTemplate ? $blockTitle . $lang->docTemplate->zentaoList[$type] : $lang->doc->zentaoList[$type]) . $lang->doc->list ), div ( diff --git a/module/doc/ui/zentaolist.productbug.html.php b/module/doc/ui/zentaolist.productbug.html.php index 8a743073e1..12940c1fc8 100644 --- a/module/doc/ui/zentaolist.productbug.html.php +++ b/module/doc/ui/zentaolist.productbug.html.php @@ -53,6 +53,5 @@ $fnGenerateFormRows = function () use ($lang, $settings, $fnGenerateCustomSearch ) ), $fnGenerateCustomSearch($searchConfig) - ); }; From 7afbe4836a510915cf0252373afd12bdd22c1ee0 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 18 Apr 2025 07:42:39 +0000 Subject: [PATCH 369/655] * [task#14117,done,1h] Adjust empty tip. --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/ui/zentaolist.html.php | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 67e5884b71..15fb9ecc14 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -106,6 +106,7 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 6b40dd2117..267941cf37 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -106,6 +106,7 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 405acdb257..99e84cb020 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -106,6 +106,7 @@ $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; $lang->docTemplate->templateDesc = 'Template Desc'; $lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 85483682ae..9a03236e57 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -106,6 +106,7 @@ $lang->docTemplate->editedList = '模板编辑者'; $lang->docTemplate->content = '模板内容'; $lang->docTemplate->templateDesc = '模板描述'; $lang->docTemplate->status = '模板状态'; +$lang->docTemplate->emptyTip = '此参数与筛选条件下,暂无符合条件系统数据。'; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index d963e69a5e..661d58a4bc 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -72,7 +72,7 @@ div set::cols(array_values($cols)), set::data(array_values($data)), set::userMap($users), - set::emptyTip($lang->doc->previewTip), + set::emptyTip($fromTemplate ? $lang->docTemplate->emptyTip : $lang->doc->previewTip), set::checkable(false), set::colResize(true), set::customCols(false), From 7c2c69ff26f974d43411e9b5a31edd54d711a52a Mon Sep 17 00:00:00 2001 From: liyang Date: Mon, 21 Apr 2025 15:27:25 +0800 Subject: [PATCH 370/655] + [ci] fix lint pipeline. --- .gitfox/lint.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitfox/lint.yaml b/.gitfox/lint.yaml index f7fa3278f2..3b53ef8764 100644 --- a/.gitfox/lint.yaml +++ b/.gitfox/lint.yaml @@ -15,7 +15,7 @@ spec: container: image: hub.zentao.net/ci/alpine:3.19 script: - - SONAR_PROJECT_KEY=$(echo $CI_REPO_NAME | tr '/' ':') + - SONAR_PROJECT_KEY=$(echo $CI_REPO_NAME-$GITFOX_COMMIT_AUTHOR | tr '/' ':') - echo "export SONAR_PROJECT_KEY=$SONAR_PROJECT_KEY" >> $GITFOX_CUSTOM_ENV - name: 配置scanner type: run @@ -23,10 +23,10 @@ spec: container: image: hub.zentao.net/ci/git:2.45.2 script: - - git diff --name-only --diff-filter=d ${GITFOX_COMMIT_AFTER} ${GITFOX_COMMIT_BEFORE} | tee .changes + - git diff --name-only --diff-filter=d ${GITFOX_COMMIT_AFTER}${GITFOX_COMMIT_BEFORE} | tee .changes - | cat > sonar-project.properties < Date: Mon, 21 Apr 2025 13:10:46 +0800 Subject: [PATCH 371/655] * [task#141979,doing,0.5h] Hidden the parent when create doc template. --- module/doc/ui/setdocbasic.template.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index a1f5405497..d9b9444015 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -46,7 +46,7 @@ formPanel set::required(true), picker(set::name('module'), set::items($modules), set::value($moduleID), set::required(true)) ), - ($modalType != 'chapter' || !$isCreate) ? formGroup + ($modalType != 'chapter' || !$isCreate) && !empty($parentID) ? formGroup ( set::label($lang->doc->module), picker From 3e4a212e1f94c17fbc6b4f6314a7492ebf493056 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 13:36:32 +0800 Subject: [PATCH 372/655] * [task#141990,doing,0.5h] Add the button of add sub template. --- lib/zin/wg/docapp/js/v1.js | 3 ++- module/doc/lang/de.php | 13 +++++++------ module/doc/lang/en.php | 13 +++++++------ module/doc/lang/fr.php | 13 +++++++------ module/doc/lang/zh-cn.php | 13 +++++++------ module/doc/ui/templatelist.html.php | 1 + 6 files changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index df2ad56046..fbd10ae72c 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -831,7 +831,8 @@ const actionsMap = [ hasPriv('addChapter') ? {icon: 'plus', text: lang.addSubChapter, command: `addChapter/${doc.id}`} : null, hasPriv('addChapter') && doc.parent != 0 ? {icon: 'plus', text: lang.addSameChapter, command: `addChapter/${doc.parent}`} : null, - hasPriv('create') ? {icon: 'plus', text: lang.addSubDoc, command: `startCreateDoc/${doc.id}`} : null, + isTemplate && hasPriv('create') ? {icon: 'plus', text: lang.addSubDocTemplate, command: `startCreateTemplate/${doc.id}`} : null, + !isTemplate && hasPriv('create') ? {icon: 'plus', text: lang.addSubDoc, command: `startCreateDoc/${doc.id}`} : null, !isChapter && canMoveDoc(doc) ? {icon: 'folder-move', text: lang.moveDoc, command: `moveDoc/${doc.id}`} : null, !isChapter && hasPriv('delete') ? {icon: 'trash', text: lang.delete, command: `deleteDoc/${doc.id}`} : null, isChapter && hasPriv('editChapter') ? {icon: 'pencil', text: lang.editChapter, command: `editChapter/${doc.id}`} : null, diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 15fb9ecc14..27865bb74a 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -119,12 +119,13 @@ $lang->docTemplate->noDesc = 'No Desc'; $lang->docTemplate->of = ' of '; $lang->docTemplate->overdue = 'Overdue'; -$lang->docTemplate->addModule = 'Add Template type'; -$lang->docTemplate->addSameModule = 'Add Same Template type'; -$lang->docTemplate->addSubModule = 'Add Sub Template type'; -$lang->docTemplate->editModule = 'Edit Template type'; -$lang->docTemplate->deleteModule = 'Delete Template type'; -$lang->docTemplate->noModules = 'No Modules'; +$lang->docTemplate->addModule = 'Add Template type'; +$lang->docTemplate->addSameModule = 'Add Same Template type'; +$lang->docTemplate->addSubModule = 'Add Sub Template type'; +$lang->docTemplate->editModule = 'Edit Template type'; +$lang->docTemplate->deleteModule = 'Delete Template type'; +$lang->docTemplate->noModules = 'No Modules'; +$lang->docTemplate->addSubDocTemplate = 'Add sub template'; $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes[1] = 'Product'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 267941cf37..7fc95753db 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -119,12 +119,13 @@ $lang->docTemplate->noDesc = 'No Desc'; $lang->docTemplate->of = ' of '; $lang->docTemplate->overdue = 'Overdue'; -$lang->docTemplate->addModule = 'Add Template type'; -$lang->docTemplate->addSameModule = 'Add Same Template type'; -$lang->docTemplate->addSubModule = 'Add Sub Template type'; -$lang->docTemplate->editModule = 'Edit Template type'; -$lang->docTemplate->deleteModule = 'Delete Template type'; -$lang->docTemplate->noModules = 'No Modules'; +$lang->docTemplate->addModule = 'Add Template type'; +$lang->docTemplate->addSameModule = 'Add Same Template type'; +$lang->docTemplate->addSubModule = 'Add Sub Template type'; +$lang->docTemplate->editModule = 'Edit Template type'; +$lang->docTemplate->deleteModule = 'Delete Template type'; +$lang->docTemplate->noModules = 'No Modules'; +$lang->docTemplate->addSubDocTemplate = 'Add sub template'; $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes[1] = 'Product'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 99e84cb020..56d355554e 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -119,12 +119,13 @@ $lang->docTemplate->noDesc = 'No Desc'; $lang->docTemplate->of = ' of '; $lang->docTemplate->overdue = 'Overdue'; -$lang->docTemplate->addModule = 'Add Template type'; -$lang->docTemplate->addSameModule = 'Add Same Template type'; -$lang->docTemplate->addSubModule = 'Add Sub Template type'; -$lang->docTemplate->editModule = 'Edit Template type'; -$lang->docTemplate->deleteModule = 'Delete Template type'; -$lang->docTemplate->noModules = 'No Modules'; +$lang->docTemplate->addModule = 'Add Template type'; +$lang->docTemplate->addSameModule = 'Add Same Template type'; +$lang->docTemplate->addSubModule = 'Add Sub Template type'; +$lang->docTemplate->editModule = 'Edit Template type'; +$lang->docTemplate->deleteModule = 'Delete Template type'; +$lang->docTemplate->noModules = 'No Modules'; +$lang->docTemplate->addSubDocTemplate = 'Add sub template'; $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes[1] = 'Product'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 9a03236e57..94dacd7270 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -119,12 +119,13 @@ $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; $lang->docTemplate->delete = '删除模板'; -$lang->docTemplate->addModule = '添加类型'; -$lang->docTemplate->addSameModule = '添加同级类型'; -$lang->docTemplate->addSubModule = '添加子类型'; -$lang->docTemplate->editModule = '编辑类型'; -$lang->docTemplate->deleteModule = '删除类型'; -$lang->docTemplate->noModules = '没有文档模板类型'; +$lang->docTemplate->addModule = '添加类型'; +$lang->docTemplate->addSameModule = '添加同级类型'; +$lang->docTemplate->addSubModule = '添加子类型'; +$lang->docTemplate->editModule = '编辑类型'; +$lang->docTemplate->deleteModule = '删除类型'; +$lang->docTemplate->noModules = '没有文档模板类型'; +$lang->docTemplate->addSubDocTemplate = '添加子文档模板'; $lang->docTemplate->scopes = array(); $lang->docTemplate->scopes[1] = '产品'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index db6e8ab7b5..7f1abb0928 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -70,6 +70,7 @@ $langData['searchLibPlaceholder'] = $lang->docTemplate->searchScopePlaceholde $langData['searchModulePlaceholder'] = $lang->docTemplate->searchTypePlaceholder; $langData['moveDoc'] = $lang->docTemplate->moveDocTemplate; $langData['createTypeFirst'] = $lang->docTemplate->createTypeFirst; +$langData['addSubDocTemplate'] = $lang->docTemplate->addSubDocTemplate; $langData['actions']['addModule'] = $lang->docTemplate->addTemplateType; $langData['actions']['addSameModule'] = $lang->docTemplate->addSameModule; From 4b9c0646c9079a15dfb094f0480696da6406ec82 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 15:12:30 +0800 Subject: [PATCH 373/655] * [task#141994,doing,2h] Change the page of create sub template. --- module/doc/control.php | 27 ++++++++++++++++++--- module/doc/ui/setdocbasic.template.html.php | 18 +++++++------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 5a715486a5..0dc4972b97 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -662,6 +662,17 @@ class doc extends control $_POST['type'] = 'docTemplate'; + if(!empty($_POST['parent'])) + { + $parentTemplate = $this->doc->fetchByID((int)$_POST['parent']); + $docData->module = $parentTemplate->module; + $docData->lib = (int)$parentTemplate->lib; + $docData->acl = $parentTemplate->acl; + $docData->groups = $parentTemplate->groups; + $docData->users = $parentTemplate->users; + $docData->templateType = $parentTemplate->templateType; + } + $docResult = $this->doc->create($docData, $this->post->labels); if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->docZen->responseAfterCreate($docResult, 'docTemplate'); @@ -2325,7 +2336,7 @@ class doc extends control if($modalType == 'doc') { $title = $parentID ? $this->lang->doc->addSubDoc : $this->lang->doc->create; - if($objectType == 'template') $title = $this->lang->docTemplate->create; + if($objectType == 'template') $title = $parentID ? $this->lang->docTemplate->addSubDocTemplate : $this->lang->docTemplate->create; if($isDraft == 'no') $title = $this->lang->settings; } if($modalType == 'chapter') $title = $isCreate ? $this->lang->doc->addChapter : $this->lang->doc->editChapter; @@ -2334,8 +2345,18 @@ class doc extends control if($objectType == 'template' && !empty($moduleID)) $chapterAndDocs = array_filter($chapterAndDocs, fn($docInfo) => $docInfo->module == $moduleID); if(isset($doc) && !empty($doc->parent) && !isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $this->doc->fetchByID($doc->parent); $modulePairs = empty($libID) || $modalType == 'chapter' || $objectType == 'template' ? array() : $this->loadModel('tree')->getOptionMenu($libID, 'doc', 0); - $chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs); - $this->view->chapterAndDocs = $chapterAndDocs; + + if($objectType == 'template' && !empty($parentID)) + { + $parentDoc = $this->doc->fetchByID($parentID); + $parentPath = trim($parentDoc->path, ',') . ","; + $topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $parentID; + foreach($chapterAndDocs as $key => $template) + { + if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]); + } + } + $this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs, $modulePairs); if($isCreate) { diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index d9b9444015..d34e7c0876 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -34,25 +34,25 @@ formPanel set::required(true), set::value(isset($doc) ? $doc->title : '') ), - formGroup + empty($parentID) ? formGroup ( set::label($lang->docTemplate->scope), set::required(true), picker(set::name('lib'), set::items($lang->docTemplate->scopes), set::value($libID), set::required(true)) - ), - formGroup + ) : null, + empty($parentID) ? formGroup ( set::label($lang->docTemplate->module), set::required(true), picker(set::name('module'), set::items($modules), set::value($moduleID), set::required(true)) - ), + ) : null, ($modalType != 'chapter' || !$isCreate) && !empty($parentID) ? formGroup ( set::label($lang->doc->module), picker ( set::name('parent'), - set::items($modalType != 'chapter' ? array(0 => '/') + $chapterAndDocs : $chapterAndDocs), + set::items($chapterAndDocs), set::value($parentID ? $parentID : "m_$moduleID"), set::required(true) ), @@ -62,7 +62,7 @@ formPanel set::label($lang->docTemplate->desc), textarea(set::name('desc'), set::value($docID ? $doc->templateDesc : ''), set::rows(3)) ), - formGroup + empty($parentID) ? formGroup ( set::label($lang->doclib->control), radioList @@ -73,8 +73,8 @@ formPanel set::value(isset($doc) ? $doc->acl : 'open'), on::change('toggleWhiteList') ) - ), - formGroup + ) : null, + empty($parentID) ? formGroup ( setID('whiteListBox'), setClass((isset($doc) && $libID == $doc->lib && $objectType != 'mine' && $doc->acl == 'private') ? '' : 'hidden'), @@ -105,5 +105,5 @@ formPanel ) ) ) - ) + ) : null ); From d4c40558ae01152163a1ce1546a8cd06158679bb Mon Sep 17 00:00:00 2001 From: liyang Date: Tue, 22 Apr 2025 11:14:05 +0800 Subject: [PATCH 374/655] + [pipeline] fix unit test pipeline. --- .gitfox/unittestforcommitid.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitfox/unittestforcommitid.yaml b/.gitfox/unittestforcommitid.yaml index 12f108a6e2..b4fa664c76 100644 --- a/.gitfox/unittestforcommitid.yaml +++ b/.gitfox/unittestforcommitid.yaml @@ -26,8 +26,6 @@ spec: - docker buildx build --pull --push --platform linux/amd64 --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true -t hub.qc.oop.cc/zentao-ztf:${GITFOX_BUILD_NUMBER}-${GITFOX_COMMIT} -f misc/ci/Dockerfile.test . - name: unit test type: run - when: | - build.target == "main" spec: envs: MYSQL_INTERNAL: "true" From ce990b27a866c274cb6b27b50d38b7eb3bca71ed Mon Sep 17 00:00:00 2001 From: liyang Date: Tue, 22 Apr 2025 11:22:47 +0800 Subject: [PATCH 375/655] + [pipeline] fix unit test pipeline. --- .gitfox/unittestforcommitid.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitfox/unittestforcommitid.yaml b/.gitfox/unittestforcommitid.yaml index b4fa664c76..12f108a6e2 100644 --- a/.gitfox/unittestforcommitid.yaml +++ b/.gitfox/unittestforcommitid.yaml @@ -26,6 +26,8 @@ spec: - docker buildx build --pull --push --platform linux/amd64 --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true -t hub.qc.oop.cc/zentao-ztf:${GITFOX_BUILD_NUMBER}-${GITFOX_COMMIT} -f misc/ci/Dockerfile.test . - name: unit test type: run + when: | + build.target == "main" spec: envs: MYSQL_INTERNAL: "true" From f129d979f16cc9964901e9ec2f784b046ff68405 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 15:46:38 +0800 Subject: [PATCH 376/655] * [task#141980,doing,0.5h] Update sub template when parent change. --- module/doc/model.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index f15c872799..95c6f62663 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1745,6 +1745,23 @@ class docModel extends model if(dao::isError()) return false; if($files) $this->file->updateObjectID($this->post->uid, $docID, 'doc'); + if(!empty($oldDoc->templateType) && empty($doc->parent) + && ($doc->module != $oldDoc->module + || $doc->lib != $oldDoc->lib + || $doc->acl != $oldDoc->acl + || $doc->groups != $oldDoc->groups + || $doc->users != $oldDoc->users)) + { + $this->dao->update(TABLE_DOC) + ->set('module')->eq($doc->module) + ->set('lib')->eq($doc->lib) + ->set('acl')->eq($doc->acl) + ->set('groups')->eq($doc->groups) + ->set('users')->eq($doc->users) + ->where("FIND_IN_SET('{$docID}', `path`)") + ->exec(); + } + if(in_array($oldDoc->contentType, array('html', 'attachment', 'markdown')) && !in_array($doc->contentType, array('html', 'attachment', 'markdown'))) { $objectType = !empty($doc->templateType) ? 'doctemplate' : 'doc'; From 10e4b4153f509c2a512d8b6ce2d28322c2d3b3f1 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 16:49:40 +0800 Subject: [PATCH 377/655] * [misc] Set parent when edit template has no parent. --- module/doc/control.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/control.php b/module/doc/control.php index 0dc4972b97..96788d7c87 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -698,6 +698,7 @@ class doc extends control ->setDefault('users', $doc->users) ->setDefault('groups', $doc->groups) ->setDefault('editedBy', $this->app->user->account) + ->setIF(!isset($_POST['parent']), 'parent', $doc->parent) ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") ->get(); if(isset($_POST['desc'])) $docData->templateDesc = $_POST['desc']; From 8d3f4cc3ad1c464d1960732706ccf624fa95953b Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 17:49:59 +0800 Subject: [PATCH 378/655] * [misc] Add the auto test file of the function of buildTemplateModule. --- module/doc/test/lib/doc.unittest.class.php | 51 ++++++++++++++++ module/doc/test/model/buildtemplatemodule.php | 60 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 module/doc/test/model/buildtemplatemodule.php diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index bcdb478171..55470dcdc4 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1645,4 +1645,55 @@ class docTest { return $this->objectModel->checkIsTemplateUpgraded(); } + + /** + * 删除一个文档模板。 + * Delete a doc template. + * + * @param int $id + * @access public + * @return bool + */ + public function deleteTemplateTest(int $id) + { + $result = $this->objectModel->deleteTemplate($id); + if(!$result) return false; + + $deleted = $this->objectModel->dao->select('deleted')->from(TABLE_DOC)->where('id')->eq($id)->fetch('deleted'); + return $deleted == 1; + } + + /** + * 获取范围数据。 + * Get scope items. + * + * @access public + * @return array + */ + public function getScopeItemsTest() + { + $result = $this->objectModel->getScopeItems(); + if(!$result) return false; + return $result; + } + + /** + * 构建模板类型数据。 + * Build data of template type module. + * + * @param int $scope + * @param int $parent + * @param string $name + * @param string $code + * @param int $grade + * @param string $path + * @access public + * @return object + */ + public function buildTemplateModuleTest($scope, $parent, $name, $code, $grade) + { + $result = $this->objectModel->buildTemplateModule($scope, $parent, $name, $code, $grade); + if(!$result) return false; + return $result ?: 0; + } } diff --git a/module/doc/test/model/buildtemplatemodule.php b/module/doc/test/model/buildtemplatemodule.php new file mode 100644 index 0000000000..1778381ae0 --- /dev/null +++ b/module/doc/test/model/buildtemplatemodule.php @@ -0,0 +1,60 @@ +#!/usr/bin/env php +buildTemplateModule(); +timeout=0 +cid=1 + +- 创建模板类型对象 + - 属性root @1 + - 属性parent @1 + - 属性name @模板名称 + - 属性short @ShortName + - 属性grade @1 +- 创建模板类型对象 + - 属性root @2 + - 属性parent @1 + - 属性name @模板名称 + - 属性short @ShortName + - 属性grade @1 +- 创建模板类型对象 + - 属性root @2 + - 属性parent @2 + - 属性name @模板名称 + - 属性short @ShortName + - 属性grade @1 +- 创建模板类型对象 + - 属性root @1 + - 属性parent @2 + - 属性name @模板名称 + - 属性short @ShortName + - 属性grade @1 +- 创建模板类型对象 + - 属性root @2 + - 属性parent @2 + - 属性name @模板名称 + - 属性short @ShortName + - 属性grade @2 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('user')->gen(5); +su('admin'); + +$scopeList = array(1, 2); +$parentList = array(1, 2); +$nameList = array('模板名称'); +$codeList = array('ShortName'); +$gradeList = array(1, 2); + +$docTester = new docTest(); +r($docTester->buildTemplateModuleTest($scopeList[0], $parentList[0], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('1,1,模板名称,ShortName,1'); // 创建模板类型对象 +r($docTester->buildTemplateModuleTest($scopeList[1], $parentList[0], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('2,1,模板名称,ShortName,1'); // 创建模板类型对象 +r($docTester->buildTemplateModuleTest($scopeList[1], $parentList[1], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('2,2,模板名称,ShortName,1'); // 创建模板类型对象 +r($docTester->buildTemplateModuleTest($scopeList[0], $parentList[1], $nameList[0], $codeList[0], $gradeList[0])) && p('root,parent,name,short,grade') && e('1,2,模板名称,ShortName,1'); // 创建模板类型对象 +r($docTester->buildTemplateModuleTest($scopeList[1], $parentList[1], $nameList[0], $codeList[0], $gradeList[1])) && p('root,parent,name,short,grade') && e('2,2,模板名称,ShortName,2'); // 创建模板类型对象 From c868b348822eab38ea8b5ff17cdee4655e27c97b Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 17:50:34 +0800 Subject: [PATCH 379/655] * [misc] Add the auto test file of the function of deleteTemplate. --- module/doc/test/model/deletetemplate.php | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 module/doc/test/model/deletetemplate.php diff --git a/module/doc/test/model/deletetemplate.php b/module/doc/test/model/deletetemplate.php new file mode 100644 index 0000000000..645577b47c --- /dev/null +++ b/module/doc/test/model/deletetemplate.php @@ -0,0 +1,31 @@ +#!/usr/bin/env php +deleteTemplate(); +cid=1 + +- 测试删除ID为0的模板 @0 +- 测试删除ID为1的模板 @1 +- 测试删除ID为2的模板 @1 +- 测试删除ID为3的模板 @1 +- 测试删除ID不存在的模板 @0 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(10); +zenData('user')->gen(5); +su('admin'); + +$templateIdList = array(0, 1, 2, 3, 11); + +$docTester = new docTest(); +r($docTester->deleteTemplateTest($templateIdList[0])) && p() && e('0'); // 测试删除ID为0的模板 +r($docTester->deleteTemplateTest($templateIdList[1])) && p() && e('1'); // 测试删除ID为1的模板 +r($docTester->deleteTemplateTest($templateIdList[2])) && p() && e('1'); // 测试删除ID为2的模板 +r($docTester->deleteTemplateTest($templateIdList[3])) && p() && e('1'); // 测试删除ID为3的模板 +r($docTester->deleteTemplateTest($templateIdList[4])) && p() && e('0'); // 测试删除ID不存在的模板 From e214c5f84402aaa92205bc342527dfa94694548b Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 21 Apr 2025 17:51:03 +0800 Subject: [PATCH 380/655] * [misc] Add the auto test of the function of getScopeTimes. --- module/doc/test/model/getscopeitems.php | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 module/doc/test/model/getscopeitems.php diff --git a/module/doc/test/model/getscopeitems.php b/module/doc/test/model/getscopeitems.php new file mode 100644 index 0000000000..4bfc0474ac --- /dev/null +++ b/module/doc/test/model/getscopeitems.php @@ -0,0 +1,39 @@ +#!/usr/bin/env php +getScopeItems(); +timeout=0 +cid=1 + +- 获取产品范围 + - 第0条的value属性 @1 + - 第0条的text属性 @产品 +- 获取项目范围 + - 第1条的value属性 @2 + - 第1条的text属性 @项目 +- 获取执行范围 + - 第2条的value属性 @3 + - 第2条的text属性 @执行 +- 获取个人范围 + - 第3条的value属性 @4 + - 第3条的text属性 @个人 +- 获取产品范围 + - 第0条的value属性 @1 + - 第0条的text属性 @产品 + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(20); +zenData('user')->gen(5); +su('admin'); + +$docTester = new docTest(); +r($docTester->getScopeItemsTest()) && p('0:value,text') && e('1,产品'); // 获取产品范围 +r($docTester->getScopeItemsTest()) && p('1:value,text') && e('2,项目'); // 获取项目范围 +r($docTester->getScopeItemsTest()) && p('2:value,text') && e('3,执行'); // 获取执行范围 +r($docTester->getScopeItemsTest()) && p('3:value,text') && e('4,个人'); // 获取个人范围 From a3167f7aebdccf34b6f34c91fbbe8788e586ef5e Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 22 Apr 2025 09:07:55 +0800 Subject: [PATCH 381/655] * [task#141980,doing,0.5h] Optimate code. --- module/doc/model.php | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 95c6f62663..d682f82cd2 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1695,16 +1695,18 @@ class docModel extends model $files = $this->loadModel('file')->saveUpload('doc', $docID); if(dao::isError()) return false; - $oldDoc = $this->getByID($docID); - $changes = common::createChanges($oldDoc, $doc); - $oldRawContent = isset($oldDoc->rawContent) ? $oldDoc->rawContent : ''; - $newRawContent = isset($doc->rawContent) ? $doc->rawContent : ''; - $onlyRawChanged = $oldRawContent != $newRawContent; - $changed = $files || $onlyRawChanged ? true : false; - $isDraft = $doc->status == 'draft'; - $version = $isDraft ? 0 : ($oldDoc->version + 1); + $oldDoc = $this->getByID($docID); + $changes = common::createChanges($oldDoc, $doc); + $oldRawContent = isset($oldDoc->rawContent) ? $oldDoc->rawContent : ''; + $newRawContent = isset($doc->rawContent) ? $doc->rawContent : ''; + $onlyRawChanged = $oldRawContent != $newRawContent; + $changed = $files || $onlyRawChanged ? true : false; + $isDraft = $doc->status == 'draft'; + $version = $isDraft ? 0 : ($oldDoc->version + 1); + $basicInfoChanged = false; foreach($changes as $change) { + if(in_array($change['field'], array('module', 'lib', 'acl', 'groups', 'users'))) $basicInfoChanged = true; if($change['field'] == 'content' || $change['field'] == 'title' || $change['field'] == 'rawContent') $changed = true; if($change['field'] == 'content') { @@ -1745,12 +1747,7 @@ class docModel extends model if(dao::isError()) return false; if($files) $this->file->updateObjectID($this->post->uid, $docID, 'doc'); - if(!empty($oldDoc->templateType) && empty($doc->parent) - && ($doc->module != $oldDoc->module - || $doc->lib != $oldDoc->lib - || $doc->acl != $oldDoc->acl - || $doc->groups != $oldDoc->groups - || $doc->users != $oldDoc->users)) + if(!empty($oldDoc->templateType) && empty($doc->parent) && $basicInfoChanged) { $this->dao->update(TABLE_DOC) ->set('module')->eq($doc->module) From 9999c558127d496536393457ee1b884ab918e276 Mon Sep 17 00:00:00 2001 From: daitingting Date: Tue, 22 Apr 2025 02:35:05 +0000 Subject: [PATCH 382/655] * [misc] Save the template content to the document first after referencing template. --- lib/zin/wg/docapp/js/v1.js | 11 ----------- module/doc/model.php | 2 ++ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index fbd10ae72c..75b968e086 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -1185,17 +1185,6 @@ const commands = const doc = {contentType: 'doc', status: 'draft', content: JSON.stringify(snapshot), template: templateID}; return submitNewDoc(doc, spaceID, libID, moduleID, formData, (newDoc) => { docApp.selectDoc(newDoc.id); - - if(doc.template) - { - const url = $.createLink('doc', 'ajaxGetTemplateContent', `id=${doc.template}&docID=${doc.id}`); - $.get(url, function(data) - { - data = JSON.parse(data); - docApp.importDoc(data.content, 'json', data.title); - }); - } - docApp.startEditDoc(newDoc.id); }); }); diff --git a/module/doc/model.php b/module/doc/model.php index d682f82cd2..9bd67c1e14 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1621,7 +1621,9 @@ class docModel extends model $docContent->doc = $docID; $docContent->files = implode(',', array_keys($files)); + if($doc->template) $docContent->rawContent = $this->loadExtension('zentaomax')->getTemplateContent((int)$doc->template, $docID); $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); + $this->loadModel('score')->create('doc', $type == 'doc' ? 'create' : 'createTemplate', $docID); return array('status' => 'new', 'id' => $docID, 'files' => $files, 'docType' => $doc->type, 'libID' => $doc->lib); } From be0ca108a536c57ef6003ec1e3fa56f7ba3be016 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 22 Apr 2025 16:33:47 +0800 Subject: [PATCH 383/655] * [task#141983,doing,1.5h] Add chapter for doc template. --- module/doc/control.php | 6 +++--- module/doc/js/browsetemplate.ui.js | 19 ++++++++++++++++++- module/doc/ui/setdocbasic.template.html.php | 4 ++-- module/doc/ui/templatelist.html.php | 1 + 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 96788d7c87..7f948cfe7e 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -658,13 +658,13 @@ class doc extends control ->setDefault('addedBy', $this->app->user->account) ->setDefault('editedBy', $this->app->user->account) ->get(); - $docData->templateDesc = $_POST['desc']; + $docData->templateDesc = zget($_POST, 'desc', ''); $_POST['type'] = 'docTemplate'; - if(!empty($_POST['parent'])) + if(!empty($docData->parent)) { - $parentTemplate = $this->doc->fetchByID((int)$_POST['parent']); + $parentTemplate = $this->doc->fetchByID((int)$docData->parent); $docData->module = $parentTemplate->module; $docData->lib = (int)$parentTemplate->lib; $docData->acl = $parentTemplate->acl; diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 30bd9f1bbb..2c41c134ae 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -181,7 +181,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) content : doc.html, status : doc.status || 'normal', contentType : doc.contentType, - type : 'text', + type : doc.type || 'text', lib : libID, module : moduleID, title : doc.title, @@ -191,6 +191,7 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) project : 0, templateType: module && module.data ? module.data.short : '', uid : (doc.uid || `doc${doc.id}`), + parent : doc.parent }; if(formData) mergeDocFormData(docData, formData); docApp.props.fetcher = $.createLink('doc', 'ajaxGetSpaceData', `type=template&spaceID=${spaceID}&picks={picks}&libID=${libID}`); @@ -494,6 +495,22 @@ $.extend(window.docAppCommands, }); }); }, + addChapter: function(_, args) + { + const docApp = getDocApp(); + const {spaceID, libID, moduleID} = docApp; + return showDocBasicModal(args[0], 0, false, 'chapter').then((formData) => { + const doc = {type: 'chapter', status: 'normal', parent: args[0]}; + return submitNewDoc(doc, spaceID, libID, moduleID, formData).then(() => { + docApp.load(null, null, null, {noLoading: false, picks: 'doc'}); + if(docBasicModal.current) + { + docBasicModal.current.destroy(); + docBasicModal = {}; + } + }); + }); + }, deleteDoc: function(_, args) { const docApp = getDocApp(); diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index d34e7c0876..632dc67860 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -57,11 +57,11 @@ formPanel set::required(true) ), ) : null, - formGroup + $modalType != 'chapter' ? formGroup ( set::label($lang->docTemplate->desc), textarea(set::name('desc'), set::value($docID ? $doc->templateDesc : ''), set::rows(3)) - ), + ) : null, empty($parentID) ? formGroup ( set::label($lang->doclib->control), diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 7f1abb0928..d19c095ac5 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -25,6 +25,7 @@ $privs['addModule'] = hasPriv('doc', 'addTemplateType'); $privs['editModule'] = hasPriv('doc', 'editTemplateType'); $privs['deleteModule'] = hasPriv('doc', 'deleteTemplateType'); $privs['moveDoc'] = hasPriv('doc', 'moveTemplate'); +$privs['addChapter'] = hasPriv('doc', 'createTemplate'); $privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; From b26080b2b0bdc343d3a42117185d1ce4ccd0673c Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 23 Apr 2025 09:55:08 +0800 Subject: [PATCH 384/655] * [task#141983,doing,1h] Modify the problem of code review. --- module/doc/config/form.php | 2 ++ module/doc/control.php | 6 ++---- module/doc/js/browsetemplate.ui.js | 1 + module/doc/ui/setdocbasic.template.html.php | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/module/doc/config/form.php b/module/doc/config/form.php index 907fe16847..e49ff1ec12 100644 --- a/module/doc/config/form.php +++ b/module/doc/config/form.php @@ -64,6 +64,7 @@ $config->doc->form->create['templateType'] = array('type' => 'string', 'requir $config->doc->form->create['chapterType'] = array('type' => 'string', 'required' => false, 'default' => ''); $config->doc->form->createtemplate = $config->doc->form->create; +$config->doc->form->createtemplate['templateDesc'] = array('type' => 'string', 'required' => false, 'default' => ''); $config->doc->form->edit['title'] = array('type' => 'string', 'required' => true, 'default' => '', 'filter' => 'trim'); $config->doc->form->edit['product'] = array('type' => 'int', 'required' => false, 'default' => 0); @@ -88,6 +89,7 @@ $config->doc->form->edit['editedBy'] = array('type' => 'string', 'required' $config->doc->form->edit['editedDate'] = array('type' => 'datetime', 'required' => false, 'default' => $now); $config->doc->form->edittemplate = $config->doc->form->edit; +$config->doc->form->edittemplate['templateDesc'] = array('type' => 'string', 'required' => false, 'default' => ''); $config->doc->form->movelib['space'] = array('type' => 'string', 'required' => true, 'default' => ''); $config->doc->form->movelib['acl'] = array('type' => 'string', 'required' => true, 'default' => ''); diff --git a/module/doc/control.php b/module/doc/control.php index 7f948cfe7e..be37c7d299 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -658,7 +658,6 @@ class doc extends control ->setDefault('addedBy', $this->app->user->account) ->setDefault('editedBy', $this->app->user->account) ->get(); - $docData->templateDesc = zget($_POST, 'desc', ''); $_POST['type'] = 'docTemplate'; @@ -673,7 +672,7 @@ class doc extends control $docData->templateType = $parentTemplate->templateType; } - $docResult = $this->doc->create($docData, $this->post->labels); + $docResult = $this->doc->create($docData); if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->docZen->responseAfterCreate($docResult, 'docTemplate'); } @@ -701,7 +700,6 @@ class doc extends control ->setIF(!isset($_POST['parent']), 'parent', $doc->parent) ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") ->get(); - if(isset($_POST['desc'])) $docData->templateDesc = $_POST['desc']; $_POST['type'] = 'docTemplate'; $result = $this->doc->update($docID, $docData); @@ -838,7 +836,7 @@ class doc extends control $docData->module = $parentDoc->module; } - $docResult = $this->doc->create($docData, $this->post->labels); + $docResult = $this->doc->create($docData); if(!$docResult || dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); return $this->docZen->responseAfterCreate($docResult); } diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 2c41c134ae..4197b92837 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -1,5 +1,6 @@ const savingDocData = {}; let docBasicModal = {}; +let currentUser = null; /** * 获取文档界面上的表格初始化选项。 * Get the table initialization options on the doc UI. diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 632dc67860..61d6277853 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -60,7 +60,7 @@ formPanel $modalType != 'chapter' ? formGroup ( set::label($lang->docTemplate->desc), - textarea(set::name('desc'), set::value($docID ? $doc->templateDesc : ''), set::rows(3)) + textarea(set::name('templateDesc'), set::value($docID ? $doc->templateDesc : ''), set::rows(3)) ) : null, empty($parentID) ? formGroup ( From eecf110a6e17f90d008e0620db18cc2ddc1a80c8 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 23 Apr 2025 10:55:13 +0800 Subject: [PATCH 385/655] * [misc] Modify the fail auto test file. --- .../action/test/lib/action.unittest.class.php | 26 +++++++++-------- .../action/test/model/computebeginandend.php | 28 ++++++++++++------- module/doc/model.php | 8 ++---- module/doc/test/lib/doc.unittest.class.php | 2 +- module/doc/test/model/update.php | 8 +++--- 5 files changed, 41 insertions(+), 31 deletions(-) diff --git a/module/action/test/lib/action.unittest.class.php b/module/action/test/lib/action.unittest.class.php index 22c1907674..77c68965c7 100644 --- a/module/action/test/lib/action.unittest.class.php +++ b/module/action/test/lib/action.unittest.class.php @@ -431,26 +431,30 @@ class actionTest * @access public * @return array */ - public function computeBeginAndEndTest($period) + public function computeBeginAndEndTest($period, string $date, string $direction) { - $date = $this->objectModel->computeBeginAndEnd($period); + $result = $this->objectModel->computeBeginAndEnd($period, $date, $direction); $today = date('Y-m-d'); $tomorrow = date('Y-m-d', strtotime('+1 days')); $yesterday = date('Y-m-d', strtotime('-1 days')); $twoDaysAgo = date('Y-m-d', strtotime('-2 days')); - if($period == 'all') return $date['begin'] == '1970-01-01' and $date['end'] == '2030-01-01'; - if($period == 'today') return $date['begin'] == $today and $date['end'] == $tomorrow; - if($period == 'yesterday') return $date['begin'] == $yesterday and $date['end'] == $today; - if($period == 'twodaysago') return $date['begin'] == $twoDaysAgo and $date['end'] == $yesterday; - if($period == 'latest3days') return $date['begin'] == $twoDaysAgo and $date['end'] == $tomorrow; - if($period == 'thismonth') return $date == date::getThisMonth(); - if($period == 'lastmonth') return $date == date::getLastMonth(); + if(!empty($date) && empty($direction)) return $result['begin'] == '2025-04-23' && $result['end'] == '2025-04-23'; + + if($direction == 'pre') return $result['begin'] == '2025-04-23' && $result['end'] == '2030-01-01'; + if($direction == 'next') return $result['begin'] == '1970-01-01' && $result['end'] == '2025-04-23'; + if($period == 'all') return $result['begin'] == '2025-01-01' && $result['end'] == '2030-01-01'; + if($period == 'today') return $result['begin'] == $today && $result['end'] == $tomorrow; + if($period == 'yesterday') return $result['begin'] == $yesterday && $result['end'] == $today; + if($period == 'twodaysago') return $result['begin'] == $twoDaysAgo && $result['end'] == $yesterday; + if($period == 'latest3days') return $result['begin'] == $twoDaysAgo && $result['end'] == $tomorrow; + if($period == 'thismonth') return $result == date::getThisMonth(); + if($period == 'lastmonth') return $result == date::getLastMonth(); $func = "get$period"; extract(date::$func()); - if($period == 'thisweek') return $date['begin'] == $begin and $date['end'] == $end; - if($period == 'lastweek') return $date['begin'] == $begin and $date['end'] == $end; + if($period == 'thisweek') return $result['begin'] == $begin && $result['end'] == $end; + if($period == 'lastweek') return $result['begin'] == $begin && $result['end'] == $end; } /** diff --git a/module/action/test/model/computebeginandend.php b/module/action/test/model/computebeginandend.php index 06c56b3d52..6ea05ce999 100755 --- a/module/action/test/model/computebeginandend.php +++ b/module/action/test/model/computebeginandend.php @@ -19,19 +19,27 @@ cid=1 - 测试计算lastweek的日期 @1 - 测试计算thismonth的日期 @1 - 测试计算lastmonth的日期 @1 +- 测试返回具体的日期 @1 +- 测试返回具体日期的结束日期 @1 +- 测试返回具体日期的开始日期 @1 */ -$typeList = array('all', 'today', 'yesterday', 'twodaysago', 'latest3days', 'thisweek', 'lastweek', 'thismonth', 'lastmonth'); +$typeList = array('all', 'today', 'yesterday', 'twodaysago', 'latest3days', 'thisweek', 'lastweek', 'thismonth', 'lastmonth'); +$dateList = array('', '2025-04-23'); +$directionList = array('', 'pre', 'next'); $action = new actionTest(); -r($action->computeBeginAndEndTest($typeList[0])) && p() && e('1'); // 测试计算all的日期 -r($action->computeBeginAndEndTest($typeList[1])) && p() && e('1'); // 测试计算today的日期 -r($action->computeBeginAndEndTest($typeList[2])) && p() && e('1'); // 测试计算yesterday的日期 -r($action->computeBeginAndEndTest($typeList[3])) && p() && e('1'); // 测试计算twodaysago的日期 -r($action->computeBeginAndEndTest($typeList[4])) && p() && e('1'); // 测试计算latest3days的日期 -r($action->computeBeginAndEndTest($typeList[5])) && p() && e('1'); // 测试计算thisweek的日期 -r($action->computeBeginAndEndTest($typeList[6])) && p() && e('1'); // 测试计算lastweek的日期 -r($action->computeBeginAndEndTest($typeList[7])) && p() && e('1'); // 测试计算thismonth的日期 -r($action->computeBeginAndEndTest($typeList[8])) && p() && e('1'); // 测试计算lastmonth的日期 \ No newline at end of file +r($action->computeBeginAndEndTest($typeList[0], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算all的日期 +r($action->computeBeginAndEndTest($typeList[1], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算today的日期 +r($action->computeBeginAndEndTest($typeList[2], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算yesterday的日期 +r($action->computeBeginAndEndTest($typeList[3], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算twodaysago的日期 +r($action->computeBeginAndEndTest($typeList[4], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算latest3days的日期 +r($action->computeBeginAndEndTest($typeList[5], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算thisweek的日期 +r($action->computeBeginAndEndTest($typeList[6], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算lastweek的日期 +r($action->computeBeginAndEndTest($typeList[7], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算thismonth的日期 +r($action->computeBeginAndEndTest($typeList[8], $dateList[0], $directionList[0])) && p() && e('1'); // 测试计算lastmonth的日期 +r($action->computeBeginAndEndTest($typeList[0], $dateList[1], $directionList[0])) && p() && e('1'); // 测试返回具体的日期 +r($action->computeBeginAndEndTest($typeList[0], $dateList[1], $directionList[1])) && p() && e('1'); // 测试返回具体日期的结束日期 +r($action->computeBeginAndEndTest($typeList[0], $dateList[1], $directionList[2])) && p() && e('1'); // 测试返回具体日期的开始日期 diff --git a/module/doc/model.php b/module/doc/model.php index 9bd67c1e14..0c5e93b7fe 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1621,7 +1621,7 @@ class docModel extends model $docContent->doc = $docID; $docContent->files = implode(',', array_keys($files)); - if($doc->template) $docContent->rawContent = $this->loadExtension('zentaomax')->getTemplateContent((int)$doc->template, $docID); + if(!empty($doc->template)) $docContent->rawContent = $this->loadExtension('zentaomax')->getTemplateContent((int)$doc->template, $docID); $this->dao->insert(TABLE_DOCCONTENT)->data($docContent)->exec(); $this->loadModel('score')->create('doc', $type == 'doc' ? 'create' : 'createTemplate', $docID); @@ -1721,14 +1721,12 @@ class docModel extends model else $version = $oldDoc->version; if(dao::isError()) return false; - unset($doc->contentType); - unset($doc->rawContent); $doc->version = max($version, $oldDoc->version); $doc->draft = $isDraft ? $doc->content : ''; $doc->content = $doc->title; if(empty($doc->status)) $doc->status = $isDraft ? $oldDoc->status : 'normal'; - if($doc->parent != $oldDoc->parent) + if(isset($doc->parent) && $doc->parent != $oldDoc->parent) { $path = ",{$docID}"; if($doc->parent) @@ -1740,7 +1738,7 @@ class docModel extends model $doc->path = $path; } - $this->dao->update(TABLE_DOC)->data($doc, 'content') + $this->dao->update(TABLE_DOC)->data($doc, 'content,contentType,rawContent') ->autoCheck() ->batchCheck($requiredFields, 'notempty') ->where('id')->eq($docID) diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 55470dcdc4..11d3f76f5a 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -223,7 +223,7 @@ class docTest */ public function updateTest(int $docID, array $param): array { - $createFields = array('lib' => 0, 'module' => 0, 'title' => '', 'keywords' => '', 'type' => 'text', 'content' => '', 'contentType' => 'html', 'acl' => 'private', 'status' => 'normal'); + $createFields = array('lib' => 0, 'module' => 0, 'title' => '', 'keywords' => '', 'type' => 'text', 'content' => '', 'contentType' => 'html', 'acl' => 'private', 'status' => 'normal', 'editedBy' => 'admin', 'rawContent' => ''); $doc = new stdclass(); foreach($createFields as $field => $defaultValue) $doc->{$field} = $defaultValue; diff --git a/module/doc/test/model/update.php b/module/doc/test/model/update.php index 968986888f..f651c0c350 100755 --- a/module/doc/test/model/update.php +++ b/module/doc/test/model/update.php @@ -23,9 +23,9 @@ cid=1 - 第0条的old属性 @文档标题11 - 第0条的new属性 @修改自定义文档 - 修改私有文档 - - 第2条的field属性 @acl - - 第2条的old属性 @custom - - 第2条的new属性 @private + - 第0条的field属性 @title + - 第0条的old属性 @修改自定义文档 + - 第0条的new属性 @修改私有文档 - 修改我的文档 - 第0条的field属性 @title - 第0条的old属性 @文档标题1 @@ -66,7 +66,7 @@ r($docTester->updateTest($docIDs[0], $updateProductDoc)) && p('0:field,old,new r($docTester->updateTest($docIDs[1], $updateProjectDoc)) && p('0:field,old,new') && e('title,文档标题31,修改项目文档'); // 修改项目文档 r($docTester->updateTest($docIDs[2], $updateExecutionDoc)) && p('0:field,old,new') && e('module,3,0'); // 修改执行文档 r($docTester->updateTest($docIDs[3], $updateCustomDoc)) && p('0:field,old,new') && e('title,文档标题11,修改自定义文档'); // 修改自定义文档 -r($docTester->updateTest($docIDs[3], $privateDoc)) && p('2:field,old,new') && e('acl,custom,private'); // 修改私有文档 +r($docTester->updateTest($docIDs[3], $privateDoc)) && p('0:field,old,new') && e('title,修改自定义文档,修改私有文档'); // 修改私有文档 r($docTester->updateTest($docIDs[4], $mineDoc)) && p('0:field,old,new') && e('title,文档标题1,修改我的文档'); // 修改我的文档 r($docTester->updateTest($docIDs[3], $customDoc)) && p('0:field,old,new') && e('lib,6,7'); // 修改自定义文档 r($docTester->updateTest($docIDs[1], $noTitle)) && p('title:0') && e('『文档标题』不能为空。'); // 修改标题为空 From 0bd1c9c5834ed379d0c2f50caa19b1904f9b63e9 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 23 Apr 2025 16:07:38 +0800 Subject: [PATCH 386/655] * [task#141985,doing,3h] Add the function of edit chapter for doc template. --- module/doc/control.php | 6 ++-- module/doc/js/browsetemplate.ui.js | 53 +++++++++++++++++++++++++++++ module/doc/ui/templatelist.html.php | 1 + 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index be37c7d299..a52f3a26ee 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -683,11 +683,10 @@ class doc extends control * Edit a doc. * * @param int $docID - * @param int $appendLib * @access public * @return void */ - public function editTemplate(int $docID, int $appendLib = 0) + public function editTemplate(int $docID) { $doc = $this->doc->getByID($docID); if(!empty($_POST)) @@ -699,9 +698,10 @@ class doc extends control ->setDefault('editedBy', $this->app->user->account) ->setIF(!isset($_POST['parent']), 'parent', $doc->parent) ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") + ->setIF($this->post->type == 'chapter', 'content', $doc->content) + ->setIF($this->post->type == 'chapter', 'rawContent', $doc->rawContent) ->get(); - $_POST['type'] = 'docTemplate'; $result = $this->doc->update($docID, $docData); if(dao::isError()) { diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 4197b92837..752da62e4c 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -248,6 +248,52 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData, afterCreate) }); } +/** + * 向服务器提交编辑文档内容。 + * Submit edit doc to server. + * + * @param {FormData} formData + * @access public + * @return void + */ +function submitEditDoc(formData) +{ + const docApp = getDocApp(); + const doc = docApp.doc.data; + console.log(doc); + const url = $.createLink('doc', 'editTemplate', `templateID=${doc.id}`); + if(formData) mergeDocFormData(doc, formData); + + return new Promise((resolve) => { + $.post(url, doc, (res) => + { + try + { + const data = JSON.parse(res); + if(!checkResponse(data)) return; + if(typeof data !== 'object' || data.result === 'fail') + { + let message = data.message || data.error || getLang('errorOccurred'); + if(typeof message === 'object') message = Object.values(message).map(x => Array.isArray(x) ? x.join('\n') : x).join('\n'); + throw new Error(message); + } + resolve(doc); + } + catch (error) + { + resolve(false); + showSaveFailedAlert(error); + if(!error.message) return; + } + }).fail(error => { + resolve(false); + showSaveFailedAlert(error); + }).complete(() => { + docApp.load(null, null, null, {noLoading: true, picks: 'doc'}); + }); + }); +} + /** * 处理创建文档的操作请求,向服务器发送请求并返回创建的文档对象。 * Handle the create doc operation request, send a request to the server and return the created doc object. @@ -512,6 +558,13 @@ $.extend(window.docAppCommands, }); }); }, + editChapter: function(_, args) + { + const docApp = getDocApp(); + return showDocBasicModal(docApp.doc.data.parent, args[0], false, 'chapter').then((formData) => { + return submitEditDoc(formData); + }); + }, deleteDoc: function(_, args) { const docApp = getDocApp(); diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index d19c095ac5..e2f1fc6e49 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -26,6 +26,7 @@ $privs['editModule'] = hasPriv('doc', 'editTemplateType'); $privs['deleteModule'] = hasPriv('doc', 'deleteTemplateType'); $privs['moveDoc'] = hasPriv('doc', 'moveTemplate'); $privs['addChapter'] = hasPriv('doc', 'createTemplate'); +$privs['editChapter'] = hasPriv('doc', 'editTemplate'); $privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; From 07b2c0b2bb2ad7b5d9d2f01211b6693535e264d5 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 23 Apr 2025 17:04:19 +0800 Subject: [PATCH 387/655] * [misc] Delete unused code. --- module/doc/js/browsetemplate.ui.js | 1 - 1 file changed, 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 752da62e4c..1182bae377 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -260,7 +260,6 @@ function submitEditDoc(formData) { const docApp = getDocApp(); const doc = docApp.doc.data; - console.log(doc); const url = $.createLink('doc', 'editTemplate', `templateID=${doc.id}`); if(formData) mergeDocFormData(doc, formData); From 862ed3e599607561cd8b0b059c38f6831a15d5fb Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Wed, 23 Apr 2025 17:32:48 +0800 Subject: [PATCH 388/655] * [task#141989,doing,0.5h] Set parent when edit sub template. --- module/doc/js/browsetemplate.ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 1182bae377..a586e4b7e6 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -131,7 +131,7 @@ function showDocSettingModal(_, args) const docID = args[0] || doc.id; const docType = args[1] || doc.contentType; const saveEdited = args[2] || 0; - showDocBasicModal(0, docID).then(formData => { + showDocBasicModal(doc.data.parent, docID).then(formData => { savingDocData[docID] = formData; if(saveEdited == 1) { From 6455f9b5bf7388cbb140a3bf0d9771ac96539c2c Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 24 Apr 2025 10:10:27 +0800 Subject: [PATCH 389/655] * [task#141987,doing,2h] Add the function of delete chapter for doc template. --- module/doc/js/browsetemplate.ui.js | 9 ++-- module/doc/lang/de.php | 67 +++++++++++++++-------------- module/doc/lang/en.php | 67 +++++++++++++++-------------- module/doc/lang/fr.php | 67 +++++++++++++++-------------- module/doc/lang/zh-cn.php | 67 +++++++++++++++-------------- module/doc/ui/templatelist.html.php | 24 ++++++----- 6 files changed, 155 insertions(+), 146 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index a586e4b7e6..1caa674389 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -566,12 +566,15 @@ $.extend(window.docAppCommands, }, deleteDoc: function(_, args) { - const docApp = getDocApp(); - const docID = args[0] || docApp.docID; + const docApp = getDocApp(); + const docID = args[0] || docApp.docID; + const docInfo = docApp.treeMap.docs.get(docID) + const doc = docInfo.data; + const isChapter = doc?.type === 'chapter'; $.ajaxSubmit( { - confirm: getLang('confirmDelete'), + confirm: getLang(isChapter ? (docInfo.docs.length > 0 ? 'confirmDeleteChapterWithSub' : 'confirmDeleteChapter') : 'confirmDelete'), url: $.createLink('doc', 'deleteTemplate', `docID=${docID}`), load: false, onSuccess: function() diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 27865bb74a..a105875c66 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -74,39 +74,40 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; -$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; -$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; -$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; -$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; -$lang->docTemplate->searchTypePlaceholder = 'Search Type'; -$lang->docTemplate->moveDocTemplate = 'Move Template'; -$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; -$lang->docTemplate->editedList = 'Template editor'; -$lang->docTemplate->content = 'Template Text'; -$lang->docTemplate->templateDesc = 'Template Desc'; -$lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; +$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; +$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; +$lang->docTemplate->searchTypePlaceholder = 'Search Type'; +$lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; +$lang->docTemplate->editedList = 'Template editor'; +$lang->docTemplate->content = 'Template Text'; +$lang->docTemplate->templateDesc = 'Template Desc'; +$lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 7fc95753db..809f800220 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -74,39 +74,40 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; -$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; -$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; -$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; -$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; -$lang->docTemplate->searchTypePlaceholder = 'Search Type'; -$lang->docTemplate->moveDocTemplate = 'Move Template'; -$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; -$lang->docTemplate->editedList = 'Template editor'; -$lang->docTemplate->content = 'Template Text'; -$lang->docTemplate->templateDesc = 'Template Desc'; -$lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; +$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; +$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; +$lang->docTemplate->searchTypePlaceholder = 'Search Type'; +$lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; +$lang->docTemplate->editedList = 'Template editor'; +$lang->docTemplate->content = 'Template Text'; +$lang->docTemplate->templateDesc = 'Template Desc'; +$lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 56d355554e..dcead4a8ac 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -74,39 +74,40 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; -$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; -$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; -$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; -$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; -$lang->docTemplate->searchTypePlaceholder = 'Search Type'; -$lang->docTemplate->moveDocTemplate = 'Move Template'; -$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; -$lang->docTemplate->editedList = 'Template editor'; -$lang->docTemplate->content = 'Template Text'; -$lang->docTemplate->templateDesc = 'Template Desc'; -$lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; +$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; +$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; +$lang->docTemplate->searchTypePlaceholder = 'Search Type'; +$lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; +$lang->docTemplate->editedList = 'Template editor'; +$lang->docTemplate->content = 'Template Text'; +$lang->docTemplate->templateDesc = 'Template Desc'; +$lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 94dacd7270..789d34062f 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -74,39 +74,40 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = '编号'; -$lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequency = '频率'; -$lang->docTemplate->type = '类型'; -$lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建日期'; -$lang->docTemplate->editedBy = '修改者'; -$lang->docTemplate->editedDate = '修改日期'; -$lang->docTemplate->views = '阅读次数'; -$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; -$lang->docTemplate->scope = '所属范围'; -$lang->docTemplate->module = '模板类型'; -$lang->docTemplate->desc = '描述'; -$lang->docTemplate->parentModule = '上级类型'; -$lang->docTemplate->typeName = '类型名称'; -$lang->docTemplate->addTemplateType = '添加文档模板类型'; -$lang->docTemplate->editTemplateType = '编辑文档模板类型'; -$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; -$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; -$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; -$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; -$lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?存为草稿或者发布后,不能再切换回旧编辑器。'; -$lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本编辑器创建,已启用新版编辑器编辑,保存后将转换为新版文档模板'; -$lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确定离开吗?'; -$lang->docTemplate->searchScopePlaceholder = '搜索范围'; -$lang->docTemplate->searchTypePlaceholder = '搜索类型'; -$lang->docTemplate->moveDocTemplate = '移动模板'; -$lang->docTemplate->createTypeFirst = '请先创建文档模板类型。'; -$lang->docTemplate->editedList = '模板编辑者'; -$lang->docTemplate->content = '模板内容'; -$lang->docTemplate->templateDesc = '模板描述'; -$lang->docTemplate->status = '模板状态'; -$lang->docTemplate->emptyTip = '此参数与筛选条件下,暂无符合条件系统数据。'; +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequency = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建日期'; +$lang->docTemplate->editedBy = '修改者'; +$lang->docTemplate->editedDate = '修改日期'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->scope = '所属范围'; +$lang->docTemplate->module = '模板类型'; +$lang->docTemplate->desc = '描述'; +$lang->docTemplate->parentModule = '上级类型'; +$lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->addTemplateType = '添加文档模板类型'; +$lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; +$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; +$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; +$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; +$lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?存为草稿或者发布后,不能再切换回旧编辑器。'; +$lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本编辑器创建,已启用新版编辑器编辑,保存后将转换为新版文档模板'; +$lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确定离开吗?'; +$lang->docTemplate->searchScopePlaceholder = '搜索范围'; +$lang->docTemplate->searchTypePlaceholder = '搜索类型'; +$lang->docTemplate->moveDocTemplate = '移动模板'; +$lang->docTemplate->createTypeFirst = '请先创建文档模板类型。'; +$lang->docTemplate->editedList = '模板编辑者'; +$lang->docTemplate->content = '模板内容'; +$lang->docTemplate->templateDesc = '模板描述'; +$lang->docTemplate->status = '模板状态'; +$lang->docTemplate->emptyTip = '此参数与筛选条件下,暂无符合条件系统数据。'; +$lang->docTemplate->confirmDeleteChapterWithSub = "删除章节后,章节下层级内容将一并隐藏,确定要删除该章节吗?"; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index e2f1fc6e49..4438375d73 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -17,17 +17,18 @@ foreach($config->doc->templateMenu as $item) $data['libs'][] = $item + array('sp $data['modules'] = $this->doc->getTemplateModules(); $privs = array(); -$privs['create'] = hasPriv('doc', 'createTemplate'); -$privs['edit'] = hasPriv('doc', 'editTemplate'); -$privs['delete'] = hasPriv('doc', 'deleteTemplate'); -$privs['view'] = hasPriv('doc', 'viewTemplate'); -$privs['addModule'] = hasPriv('doc', 'addTemplateType'); -$privs['editModule'] = hasPriv('doc', 'editTemplateType'); -$privs['deleteModule'] = hasPriv('doc', 'deleteTemplateType'); -$privs['moveDoc'] = hasPriv('doc', 'moveTemplate'); -$privs['addChapter'] = hasPriv('doc', 'createTemplate'); -$privs['editChapter'] = hasPriv('doc', 'editTemplate'); -$privs['collect'] = 'no'; +$privs['create'] = hasPriv('doc', 'createTemplate'); +$privs['edit'] = hasPriv('doc', 'editTemplate'); +$privs['delete'] = hasPriv('doc', 'deleteTemplate'); +$privs['view'] = hasPriv('doc', 'viewTemplate'); +$privs['addModule'] = hasPriv('doc', 'addTemplateType'); +$privs['editModule'] = hasPriv('doc', 'editTemplateType'); +$privs['deleteModule'] = hasPriv('doc', 'deleteTemplateType'); +$privs['moveDoc'] = hasPriv('doc', 'moveTemplate'); +$privs['addChapter'] = hasPriv('doc', 'createTemplate'); +$privs['editChapter'] = hasPriv('doc', 'editTemplate'); +$privs['deleteChapter'] = hasPriv('doc', 'deleteTemplate'); +$privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; if(!hasPriv('doc', 'editTemplate')) $filterTypes = array_values(array_filter($filterTypes, function($item){ return $item[0] != 'draft'; })); @@ -73,6 +74,7 @@ $langData['searchModulePlaceholder'] = $lang->docTemplate->searchTypePlaceholder $langData['moveDoc'] = $lang->docTemplate->moveDocTemplate; $langData['createTypeFirst'] = $lang->docTemplate->createTypeFirst; $langData['addSubDocTemplate'] = $lang->docTemplate->addSubDocTemplate; +$langData['confirmDeleteChapterWithSub'] = $lang->docTemplate->confirmDeleteChapterWithSub; $langData['actions']['addModule'] = $lang->docTemplate->addTemplateType; $langData['actions']['addSameModule'] = $lang->docTemplate->addSameModule; From 84591aa998063457cd69047362031c611960b733 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 24 Apr 2025 11:02:48 +0800 Subject: [PATCH 390/655] * [task#141988,doing,1h] Delete the link of delete doc in trash list. --- module/action/config.php | 2 +- module/action/zen.php | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/module/action/config.php b/module/action/config.php index 4350feae63..b67498ba33 100755 --- a/module/action/config.php +++ b/module/action/config.php @@ -88,7 +88,7 @@ $config->action->majorList['doc'] = array('releaseddoc'); $config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,'; $config->action->needGetRelateField = ',branch,story,epic,requirement,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,review,'; -$config->action->noLinkModules = ',doclib,module,webhook,gitlab,instance,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,pivot,scene,boardspace,auditplan,auditresult,productline,chapter,'; +$config->action->noLinkModules = ',doclib,module,webhook,gitlab,instance,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,pivot,scene,boardspace,auditplan,auditresult,productline,chapter,doc,'; $config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn'; $config->action->ignoreActions4Dynamic = 'disconnectxuanxuan,reconnectxuanxuan,loginxuanxuan,logoutxuanxuan,editmr,removemr,syncdoingbyticket,syncdoingbystory,syncdoingbyuserstory,syncdoingbyepic,syncdoingbytask,syncdoingbybug,syncdoingbytodo,syncdoingbydemand'; diff --git a/module/action/zen.php b/module/action/zen.php index 7bf9742c0c..c1e2101fcb 100644 --- a/module/action/zen.php +++ b/module/action/zen.php @@ -112,11 +112,6 @@ class actionZen extends action $params = "libID=0&moduelID=0&apiID={$trash->objectID}"; $methodName = 'index'; } - if($trash->objectType == 'doc') - { - $params = "docID={$trash->objectID}"; - if($trash->comment == 'chapter') $module = 'chapter'; - } if(in_array($module, array('traincourse','traincontents'))) { $methodName = $module == 'traincourse' ? 'viewcourse' : 'viewchapter'; From 915c713c89b27b3cb8b83d85b0188b6aa2b417f9 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Thu, 24 Apr 2025 13:42:04 +0800 Subject: [PATCH 391/655] * [task#141992,doing,1h] Add the function of delete sub template. --- module/doc/js/browsetemplate.ui.js | 2 +- module/doc/lang/de.php | 69 ++++++++++++++-------------- module/doc/lang/en.php | 69 ++++++++++++++-------------- module/doc/lang/fr.php | 69 ++++++++++++++-------------- module/doc/lang/zh-cn.php | 71 +++++++++++++++-------------- module/doc/ui/templatelist.html.php | 55 +++++++++++----------- 6 files changed, 170 insertions(+), 165 deletions(-) diff --git a/module/doc/js/browsetemplate.ui.js b/module/doc/js/browsetemplate.ui.js index 1caa674389..710c754208 100644 --- a/module/doc/js/browsetemplate.ui.js +++ b/module/doc/js/browsetemplate.ui.js @@ -574,7 +574,7 @@ $.extend(window.docAppCommands, $.ajaxSubmit( { - confirm: getLang(isChapter ? (docInfo.docs.length > 0 ? 'confirmDeleteChapterWithSub' : 'confirmDeleteChapter') : 'confirmDelete'), + confirm: getLang(isChapter ? (docInfo.docs.length > 0 ? 'confirmDeleteChapterWithSub' : 'confirmDeleteChapter') : (docInfo.docs.length > 0 ? 'confirmDeleteWithSub' : 'confirmDelete')), url: $.createLink('doc', 'deleteTemplate', `docID=${docID}`), load: false, onSuccess: function() diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index a105875c66..97be51ec59 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -74,40 +74,41 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; -$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; -$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; -$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; -$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; -$lang->docTemplate->searchTypePlaceholder = 'Search Type'; -$lang->docTemplate->moveDocTemplate = 'Move Template'; -$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; -$lang->docTemplate->editedList = 'Template editor'; -$lang->docTemplate->content = 'Template Text'; -$lang->docTemplate->templateDesc = 'Template Desc'; -$lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; -$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; +$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; +$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; +$lang->docTemplate->searchTypePlaceholder = 'Search Type'; +$lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; +$lang->docTemplate->editedList = 'Template editor'; +$lang->docTemplate->content = 'Template Text'; +$lang->docTemplate->templateDesc = 'Template Desc'; +$lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; +$lang->docTemplate->confirmDeleteTemplateWithSub = "After deleting the template, the lower level content of the template will be hidden. Are you sure you want to delete this template?"; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 809f800220..d136d8aa0a 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -74,40 +74,41 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; -$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; -$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; -$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; -$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; -$lang->docTemplate->searchTypePlaceholder = 'Search Type'; -$lang->docTemplate->moveDocTemplate = 'Move Template'; -$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; -$lang->docTemplate->editedList = 'Template editor'; -$lang->docTemplate->content = 'Template Text'; -$lang->docTemplate->templateDesc = 'Template Desc'; -$lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; -$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; +$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; +$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; +$lang->docTemplate->searchTypePlaceholder = 'Search Type'; +$lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; +$lang->docTemplate->editedList = 'Template editor'; +$lang->docTemplate->content = 'Template Text'; +$lang->docTemplate->templateDesc = 'Template Desc'; +$lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; +$lang->docTemplate->confirmDeleteTemplateWithSub = "After deleting the template, the lower level content of the template will be hidden. Are you sure you want to delete this template?"; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index dcead4a8ac..c8e143b75a 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -74,40 +74,41 @@ $lang->doclib->apiNameUnique['project'] = 'In the api library of the same ' . $l $lang->doclib->apiNameUnique['nolink'] = 'In the no linked api library, '; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = 'ID'; -$lang->docTemplate->title = 'Template Title'; -$lang->docTemplate->frequency = 'Frequency'; -$lang->docTemplate->type = 'Type'; -$lang->docTemplate->addedBy = 'Added By'; -$lang->docTemplate->addedDate = 'Added Date'; -$lang->docTemplate->editedBy = 'Edited By'; -$lang->docTemplate->editedDate = 'Edited Date'; -$lang->docTemplate->views = 'Views'; -$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; -$lang->docTemplate->scope = 'Scope'; -$lang->docTemplate->module = 'Type'; -$lang->docTemplate->desc = 'Describe'; -$lang->docTemplate->parentModule = 'Parent'; -$lang->docTemplate->typeName = 'Type Name'; -$lang->docTemplate->addTemplateType = 'Add template type'; -$lang->docTemplate->editTemplateType = 'Edit template type'; -$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; -$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; -$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; -$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; -$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; -$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; -$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; -$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; -$lang->docTemplate->searchTypePlaceholder = 'Search Type'; -$lang->docTemplate->moveDocTemplate = 'Move Template'; -$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; -$lang->docTemplate->editedList = 'Template editor'; -$lang->docTemplate->content = 'Template Text'; -$lang->docTemplate->templateDesc = 'Template Desc'; -$lang->docTemplate->status = 'Template Status'; -$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; -$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; +$lang->docTemplate->id = 'ID'; +$lang->docTemplate->title = 'Template Title'; +$lang->docTemplate->frequency = 'Frequency'; +$lang->docTemplate->type = 'Type'; +$lang->docTemplate->addedBy = 'Added By'; +$lang->docTemplate->addedDate = 'Added Date'; +$lang->docTemplate->editedBy = 'Edited By'; +$lang->docTemplate->editedDate = 'Edited Date'; +$lang->docTemplate->views = 'Views'; +$lang->docTemplate->confirmDelete = 'Do you want to delete this document template?'; +$lang->docTemplate->scope = 'Scope'; +$lang->docTemplate->module = 'Type'; +$lang->docTemplate->desc = 'Describe'; +$lang->docTemplate->parentModule = 'Parent'; +$lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->addTemplateType = 'Add template type'; +$lang->docTemplate->editTemplateType = 'Edit template type'; +$lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; +$lang->docTemplate->docTitleRequired = 'Please enter the doc template title.'; +$lang->docTemplate->noticeAddTemplateType = 'Support two-level types. Built-in template type cannot move.'; +$lang->docTemplate->errorDeleteType = 'There is document template exists in the current type, it cannot be deleted.'; +$lang->docTemplate->convertToNewDocConfirm = 'Are you ready to convert this document template to the new format using a modern block-level editor? After saving as a draft or publishing, you can no longer switch back to the old editor.'; +$lang->docTemplate->oldDocEditingTip = 'This document template is being created in the old editor, the new editor is now enabled for editing. If you want to switch to the new editor, please save the document template first.'; +$lang->docTemplate->leaveEditingConfirm = 'The template is currently being edited. Do you want to leave the editing page?'; +$lang->docTemplate->searchScopePlaceholder = 'Search Scope'; +$lang->docTemplate->searchTypePlaceholder = 'Search Type'; +$lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->createTypeFirst = 'Please create a template type first.'; +$lang->docTemplate->editedList = 'Template editor'; +$lang->docTemplate->content = 'Template Text'; +$lang->docTemplate->templateDesc = 'Template Desc'; +$lang->docTemplate->status = 'Template Status'; +$lang->docTemplate->emptyTip = 'There is no system data that conform to this parameter and filtering conditions.'; +$lang->docTemplate->confirmDeleteChapterWithSub = "After deleting a chapter, the lower level content of the chapter will be hidden. Are you sure you want to delete the chapter?"; +$lang->docTemplate->confirmDeleteTemplateWithSub = "After deleting the template, the lower level content of the template will be hidden. Are you sure you want to delete this template?"; $lang->docTemplate->create = 'Create Template'; $lang->docTemplate->edit = 'Edit Template'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 789d34062f..16aa3cdde6 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -74,40 +74,41 @@ $lang->doclib->apiNameUnique['project'] = '同一' . $lang->projectCommon . '下 $lang->doclib->apiNameUnique['nolink'] = '独立接口库中'; $lang->docTemplate = new stdclass(); -$lang->docTemplate->id = '编号'; -$lang->docTemplate->title = '模板标题'; -$lang->docTemplate->frequency = '频率'; -$lang->docTemplate->type = '类型'; -$lang->docTemplate->addedBy = '创建者'; -$lang->docTemplate->addedDate = '创建日期'; -$lang->docTemplate->editedBy = '修改者'; -$lang->docTemplate->editedDate = '修改日期'; -$lang->docTemplate->views = '阅读次数'; -$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; -$lang->docTemplate->scope = '所属范围'; -$lang->docTemplate->module = '模板类型'; -$lang->docTemplate->desc = '描述'; -$lang->docTemplate->parentModule = '上级类型'; -$lang->docTemplate->typeName = '类型名称'; -$lang->docTemplate->addTemplateType = '添加文档模板类型'; -$lang->docTemplate->editTemplateType = '编辑文档模板类型'; -$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; -$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; -$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; -$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; -$lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?存为草稿或者发布后,不能再切换回旧编辑器。'; -$lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本编辑器创建,已启用新版编辑器编辑,保存后将转换为新版文档模板'; -$lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确定离开吗?'; -$lang->docTemplate->searchScopePlaceholder = '搜索范围'; -$lang->docTemplate->searchTypePlaceholder = '搜索类型'; -$lang->docTemplate->moveDocTemplate = '移动模板'; -$lang->docTemplate->createTypeFirst = '请先创建文档模板类型。'; -$lang->docTemplate->editedList = '模板编辑者'; -$lang->docTemplate->content = '模板内容'; -$lang->docTemplate->templateDesc = '模板描述'; -$lang->docTemplate->status = '模板状态'; -$lang->docTemplate->emptyTip = '此参数与筛选条件下,暂无符合条件系统数据。'; -$lang->docTemplate->confirmDeleteChapterWithSub = "删除章节后,章节下层级内容将一并隐藏,确定要删除该章节吗?"; +$lang->docTemplate->id = '编号'; +$lang->docTemplate->title = '模板标题'; +$lang->docTemplate->frequency = '频率'; +$lang->docTemplate->type = '类型'; +$lang->docTemplate->addedBy = '创建者'; +$lang->docTemplate->addedDate = '创建日期'; +$lang->docTemplate->editedBy = '修改者'; +$lang->docTemplate->editedDate = '修改日期'; +$lang->docTemplate->views = '阅读次数'; +$lang->docTemplate->confirmDelete = '您确定删除该文档模板吗?'; +$lang->docTemplate->scope = '所属范围'; +$lang->docTemplate->module = '模板类型'; +$lang->docTemplate->desc = '描述'; +$lang->docTemplate->parentModule = '上级类型'; +$lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->addTemplateType = '添加文档模板类型'; +$lang->docTemplate->editTemplateType = '编辑文档模板类型'; +$lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; +$lang->docTemplate->docTitleRequired = '文档模板标题不能为空。'; +$lang->docTemplate->noticeAddTemplateType = '支持两级类型,内置模板类型参与逻辑运算,不可修改所在位置'; +$lang->docTemplate->errorDeleteType = '当前类型存在文档模板,不可删除'; +$lang->docTemplate->convertToNewDocConfirm = '全新文档格式使用现代化块级编辑器,带来全新的文档功能体验。确定要将此文档模板转换为新文档格式吗?存为草稿或者发布后,不能再切换回旧编辑器。'; +$lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本编辑器创建,已启用新版编辑器编辑,保存后将转换为新版文档模板'; +$lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确定离开吗?'; +$lang->docTemplate->searchScopePlaceholder = '搜索范围'; +$lang->docTemplate->searchTypePlaceholder = '搜索类型'; +$lang->docTemplate->moveDocTemplate = '移动模板'; +$lang->docTemplate->createTypeFirst = '请先创建文档模板类型。'; +$lang->docTemplate->editedList = '模板编辑者'; +$lang->docTemplate->content = '模板内容'; +$lang->docTemplate->templateDesc = '模板描述'; +$lang->docTemplate->status = '模板状态'; +$lang->docTemplate->emptyTip = '此参数与筛选条件下,暂无符合条件系统数据。'; +$lang->docTemplate->confirmDeleteChapterWithSub = "删除章节后,章节下层级内容将一并隐藏,确定要删除该章节吗?"; +$lang->docTemplate->confirmDeleteTemplateWithSub = "删除文档模板后,文档模板下层级内容将一并隐藏,确定要删除该文档模板吗?"; $lang->docTemplate->more = '更多'; $lang->docTemplate->scopeLabel = '范围'; @@ -118,7 +119,7 @@ $lang->docTemplate->overdue = '已过期'; $lang->docTemplate->create = '创建模板'; $lang->docTemplate->edit = '编辑模板'; -$lang->docTemplate->delete = '删除模板'; +$lang->docTemplate->delete = '删除文档模板'; $lang->docTemplate->addModule = '添加类型'; $lang->docTemplate->addSameModule = '添加同级类型'; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 4438375d73..29e5448814 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -47,34 +47,35 @@ $tableCols['desc'] = $lang->docTemplate->desc; $tableCols['actions'] = $lang->actions; $langData = array(); -$langData['filterTypes'] = $filterTypes; -$langData['tableCols'] = $tableCols; -$langData['createDoc'] = $lang->docTemplate->create; -$langData['edit'] = $lang->docTemplate->edit; -$langData['editDoc'] = $lang->docTemplate->edit; -$langData['delete'] = $lang->docTemplate->delete; -$langData['deleteDoc'] = $lang->docTemplate->delete; -$langData['createTemplate'] = $lang->docTemplate->create; -$langData['editTemplate'] = $lang->docTemplate->edit; -$langData['deleteTemplate'] = $lang->docTemplate->delete; -$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; -$langData['addModule'] = $lang->docTemplate->addModule; -$langData['addSubModule'] = $lang->docTemplate->addSubModule; -$langData['editModule'] = $lang->docTemplate->editModule; -$langData['deleteModule'] = $lang->docTemplate->deleteModule; -$langData['noModules'] = $lang->docTemplate->noModules; -$langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; -$langData['docTitleRequired'] = $lang->docTemplate->docTitleRequired; -$langData['noDocs'] = $lang->docTemplate->noTemplate; -$langData['convertToNewDocConfirm'] = $lang->docTemplate->convertToNewDocConfirm; -$langData['oldDocEditingTip'] = $lang->docTemplate->oldDocEditingTip; -$langData['leaveEditingConfirm'] = $lang->docTemplate->leaveEditingConfirm; -$langData['searchLibPlaceholder'] = $lang->docTemplate->searchScopePlaceholder; -$langData['searchModulePlaceholder'] = $lang->docTemplate->searchTypePlaceholder; -$langData['moveDoc'] = $lang->docTemplate->moveDocTemplate; -$langData['createTypeFirst'] = $lang->docTemplate->createTypeFirst; -$langData['addSubDocTemplate'] = $lang->docTemplate->addSubDocTemplate; +$langData['filterTypes'] = $filterTypes; +$langData['tableCols'] = $tableCols; +$langData['createDoc'] = $lang->docTemplate->create; +$langData['edit'] = $lang->docTemplate->edit; +$langData['editDoc'] = $lang->docTemplate->edit; +$langData['delete'] = $lang->docTemplate->delete; +$langData['deleteDoc'] = $lang->docTemplate->delete; +$langData['createTemplate'] = $lang->docTemplate->create; +$langData['editTemplate'] = $lang->docTemplate->edit; +$langData['deleteTemplate'] = $lang->docTemplate->delete; +$langData['confirmDelete'] = $lang->docTemplate->confirmDelete; +$langData['addModule'] = $lang->docTemplate->addModule; +$langData['addSubModule'] = $lang->docTemplate->addSubModule; +$langData['editModule'] = $lang->docTemplate->editModule; +$langData['deleteModule'] = $lang->docTemplate->deleteModule; +$langData['noModules'] = $lang->docTemplate->noModules; +$langData['docTitlePlaceholder'] = $lang->docTemplate->docTitlePlaceholder; +$langData['docTitleRequired'] = $lang->docTemplate->docTitleRequired; +$langData['noDocs'] = $lang->docTemplate->noTemplate; +$langData['convertToNewDocConfirm'] = $lang->docTemplate->convertToNewDocConfirm; +$langData['oldDocEditingTip'] = $lang->docTemplate->oldDocEditingTip; +$langData['leaveEditingConfirm'] = $lang->docTemplate->leaveEditingConfirm; +$langData['searchLibPlaceholder'] = $lang->docTemplate->searchScopePlaceholder; +$langData['searchModulePlaceholder'] = $lang->docTemplate->searchTypePlaceholder; +$langData['moveDoc'] = $lang->docTemplate->moveDocTemplate; +$langData['createTypeFirst'] = $lang->docTemplate->createTypeFirst; +$langData['addSubDocTemplate'] = $lang->docTemplate->addSubDocTemplate; $langData['confirmDeleteChapterWithSub'] = $lang->docTemplate->confirmDeleteChapterWithSub; +$langData['confirmDeleteWithSub'] = $lang->docTemplate->confirmDeleteTemplateWithSub; $langData['actions']['addModule'] = $lang->docTemplate->addTemplateType; $langData['actions']['addSameModule'] = $lang->docTemplate->addSameModule; From 6c6606f7208e61175f436b8f97496530406c9143 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 25 Apr 2025 05:19:47 +0000 Subject: [PATCH 392/655] * [misc] Use specific characters __TML_ZENTAOLIST__ to match block id. --- lib/zin/wg/docapp/js/v1.js | 2 ++ module/doc/control.php | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/zin/wg/docapp/js/v1.js b/lib/zin/wg/docapp/js/v1.js index caed1f9133..5125d440d0 100644 --- a/lib/zin/wg/docapp/js/v1.js +++ b/lib/zin/wg/docapp/js/v1.js @@ -48,6 +48,8 @@ window.setZentaoSlashMenu = function(menus, title, vision, position) /* 获取 ZentaoList 块属性。 */ function getZentaoListProps(type, blockID, props) { + if(props.isTemplate !== undefined && props.isTemplate) blockID = '__TML_ZENTAOLIST__' + blockID; + const zentaoListLang = getLang('zentaoList'); const exportUrl = $.createLink('doc', 'ajaxExportZentaoList', `blockID=${blockID}`); return $.extend( diff --git a/module/doc/control.php b/module/doc/control.php index a52f3a26ee..22652c5e8d 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -145,13 +145,15 @@ class doc extends control * 禅道数据列表。 * Zentao data list. * - * @param string $type - * @param int $blockID + * @param string $type + * @param int|string $blockID * @access public * @return void */ - public function zentaoList(string $type, int $blockID) + public function zentaoList(string $type, int|string $blockID) { + if(is_string($blockID)) $blockID = (int)str_replace('__TML_ZENTAOLIST__', '', $blockID); + $blockData = $this->doc->getZentaoList($blockID); if(!$blockData) { From d4860c78cf9e9f2cc2f129357093a1c886736182 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 09:55:44 +0800 Subject: [PATCH 393/655] * [task#141998,doing,3h] Add the function of move template. --- module/doc/config/form.php | 8 +++- module/doc/control.php | 33 ++++++++++++++- module/doc/tao.php | 15 ++++++- module/doc/ui/movetemplate.html.php | 62 +++++++++++++++++++++++++++-- 4 files changed, 109 insertions(+), 9 deletions(-) diff --git a/module/doc/config/form.php b/module/doc/config/form.php index e49ff1ec12..69108af69e 100644 --- a/module/doc/config/form.php +++ b/module/doc/config/form.php @@ -105,8 +105,12 @@ $config->doc->form->movedoc['readGroups'] = array('type' => 'array', 'require $config->doc->form->movedoc['readUsers'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join'); $config->doc->form->movedoc['parent'] = array('type' => 'int', 'required' => false, 'default' => 0); -$config->doc->form->movetemplate['lib'] = array('type' => 'int', 'required' => true, 'default' => ''); -$config->doc->form->movetemplate['module'] = array('type' => 'int', 'required' => true, 'default' => ''); +$config->doc->form->movetemplate['lib'] = array('type' => 'int', 'required' => true, 'default' => ''); +$config->doc->form->movetemplate['module'] = array('type' => 'int', 'required' => true, 'default' => ''); +$config->doc->form->movetemplate['parent'] = array('type' => 'int', 'required' => false, 'default' => 0); +$config->doc->form->movetemplate['acl'] = array('type' => 'string', 'required' => true, 'default' => ''); +$config->doc->form->movetemplate['groups'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join'); +$config->doc->form->movetemplate['users'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join'); $config->doc->form->batchmovedoc['lib'] = array('type' => 'int', 'required' => true, 'default' => 0); $config->doc->form->batchmovedoc['module'] = array('type' => 'int', 'required' => false, 'default' => 0); diff --git a/module/doc/control.php b/module/doc/control.php index 22652c5e8d..8deb3515e0 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1886,11 +1886,23 @@ class doc extends control $doc = $this->doc->getByID($docID); if(!empty($_POST)) { - $data = form::data()->get(); + $data = form::data() + ->setIF(!isset($_POST['lib']), 'lib', $doc->lib) + ->setIF(!isset($_POST['module']), 'module', $doc->module) + ->setIF(!isset($_POST['parent']), 'parent', $doc->parent) + ->setIF(!isset($_POST['acl']), 'acl', $doc->acl) + ->setIF(!isset($_POST['groups']), 'groups', $doc->groups) + ->setIF(!isset($_POST['users']), 'users', $doc->users) + ->get(); $changes = common::createChanges($doc, $data); if($changes) { - $this->doc->doUpdateDoc($docID, $data); + $basicInfoChanged = false; + foreach($changes as $change) + { + if(in_array($change['field'], array('module', 'lib', 'acl', 'groups', 'users'))) $basicInfoChanged = true; + } + $this->doc->doUpdateDoc($docID, $data, $basicInfoChanged); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); $actionID = $this->loadModel('action')->create('docTemplate', $docID, 'Moved', '', json_encode(array('from' => $doc->lib, 'to' => $data->lib))); @@ -1901,9 +1913,26 @@ class doc extends control return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => $docAppAction)); } + if(!empty($doc->parent)) + { + $parentDoc = $this->doc->fetchByID($doc->parent); + $chapterAndDocs = $this->doc->getDocsOfLibs(array($doc->lib), 'template', $docID, true); + if(!isset($chapterAndDocs[$doc->parent])) $chapterAndDocs[$doc->parent] = $parentDoc; + + $parentPath = trim($parentDoc->path, ',') . ","; + $topTemplate = substr($parentPath, 0, strpos($parentPath, ',')) ?: $doc->parent; + foreach($chapterAndDocs as $key => $template) + { + if(strpos(",{$template->path},", ",{$topTemplate},") === false) unset($chapterAndDocs[$key]); + } + $this->view->chapterAndDocs = $this->doc->buildNestedDocs($chapterAndDocs); + } + $this->view->doc = $doc; $this->view->docID = $docID; $this->view->modules = $this->loadModel('tree')->getOptionMenu((int)$doc->lib, 'docTemplate', 0, 'all', 'nodeleted', 'all'); + $this->view->users = $this->loadModel('user')->getPairs('nocode|noclosed|nodeleted'); + $this->view->groups = $this->loadModel('group')->getPairs(); $this->display(); } diff --git a/module/doc/tao.php b/module/doc/tao.php index 89e8adc3a3..189429c6d2 100644 --- a/module/doc/tao.php +++ b/module/doc/tao.php @@ -266,12 +266,25 @@ class docTao extends docModel * * @param int $docID * @param object $doc + * @param bool $basicInfoChanged * @access protected * @return void */ - protected function doUpdateDoc(int $docID, object $doc) + protected function doUpdateDoc(int $docID, object $doc, $basicInfoChanged = false) { $this->dao->update(TABLE_DOC)->data($doc)->autoCheck()->where('id')->eq($docID)->exec(); + + if(empty($doc->parent) && $basicInfoChanged) + { + $this->dao->update(TABLE_DOC) + ->set('module')->eq($doc->module) + ->set('lib')->eq($doc->lib) + ->set('acl')->eq($doc->acl) + ->set('groups')->eq($doc->groups) + ->set('users')->eq($doc->users) + ->where("FIND_IN_SET('{$docID}', `path`)") + ->exec(); + } } /** diff --git a/module/doc/ui/movetemplate.html.php b/module/doc/ui/movetemplate.html.php index 092ddfe048..be5b9d2398 100644 --- a/module/doc/ui/movetemplate.html.php +++ b/module/doc/ui/movetemplate.html.php @@ -18,16 +18,70 @@ unset($modules[0]); formPanel ( on::change('[name=lib]')->call('loadLibModules', jsRaw("event, 'docTemplate'")), - formGroup + empty($doc->parent) ? formGroup ( set::label($lang->docTemplate->scope), set::required(true), picker(set::name('lib'), set::items($lang->docTemplate->scopes), set::value($doc->lib), set::required(true)) - ), - formGroup + ) : null, + empty($doc->parent) ? formGroup ( set::label($lang->docTemplate->module), set::required(true), picker(set::name('module'), set::items($modules), set::value($doc->module), set::required(true)) - ), + ) : null, + !empty($doc->parent) ? formGroup + ( + set::label($lang->doc->module), + picker + ( + set::name('parent'), + set::items($chapterAndDocs), + set::value($doc->parent), + set::required(true) + ), + ) : null, + empty($doc->parent) ? formGroup + ( + set::label($lang->doclib->control), + radioList + ( + set::name('acl'), + set::items($lang->doc->aclListA), + set::value($doc->acl), + on::change('toggleWhiteList') + ) + ) : null, + empty($doc->parent) ? formGroup + ( + setID('whiteListBox'), + setClass($doc->acl == 'private' ? '' : 'hidden'), + set::label($lang->doc->whiteList), + div + ( + setClass('w-full check-list'), + inputGroup + ( + setClass('w-full'), + $lang->doc->groupLabel, + picker + ( + set::name('groups[]'), + set::items($groups), + set::value($doc->groups), + set::multiple(true) + ) + ), + div + ( + setClass('w-full'), + userPicker + ( + set::label($lang->doc->userLabel), + set::items($users), + set::value($doc->users) + ) + ) + ) + ) : null ); From 5b777ee94a0fd7d1c3d5c2649019b6784d09aaa1 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 10:12:39 +0800 Subject: [PATCH 394/655] * [bug#61937] Update children when update parent template. --- module/doc/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/model.php b/module/doc/model.php index 0c5e93b7fe..c0b09e0b57 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1713,7 +1713,7 @@ class docModel extends model if($change['field'] == 'content') { $onlyRawChanged = false; - break; + continue; } } if($onlyRawChanged) $changes[] = array('field' => 'content', 'old' => $oldDoc->content, 'new' => $doc->content); From 42aca1b69cc5483e1117b55ae31c1b011a8c86db Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 10:48:37 +0800 Subject: [PATCH 395/655] * [task#141998,doing,1h] Response when after move template. --- module/doc/control.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 8deb3515e0..11e47d435d 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1909,8 +1909,10 @@ class doc extends control $this->action->logHistory($actionID, $changes); } - $docAppAction = array('executeCommand', 'handleMovedDoc', array($docID, '1', $data->lib)); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => $docAppAction)); + $newDoc = $this->doc->getByID($docID); + $link = $this->createLink('doc', 'view', "docID={$docID}"); + if(!$this->doc->checkPrivDoc($newDoc)) $link = $this->createLink('doc', 'browseTemplate', "libID={$doc->lib}&type=all&docID=0&orderBy=id_desc&recTotal=0&recPerPage=20&pageID=1&mode=list"); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $newDoc)); } if(!empty($doc->parent)) From e7ce5a4e08720cba68cc8a799e62e6498b547367 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 10:57:48 +0800 Subject: [PATCH 396/655] * [task#141998,doing,0.5h] Change the button title of move template. --- module/doc/lang/zh-cn.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 16aa3cdde6..b739548e29 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -100,7 +100,7 @@ $lang->docTemplate->oldDocEditingTip = '此文档模板为旧版本 $lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确定离开吗?'; $lang->docTemplate->searchScopePlaceholder = '搜索范围'; $lang->docTemplate->searchTypePlaceholder = '搜索类型'; -$lang->docTemplate->moveDocTemplate = '移动模板'; +$lang->docTemplate->moveDocTemplate = '移动文档模板'; $lang->docTemplate->createTypeFirst = '请先创建文档模板类型。'; $lang->docTemplate->editedList = '模板编辑者'; $lang->docTemplate->content = '模板内容'; From f425a50c0e732a3d492d003859509318ad0c5094 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 11:08:56 +0800 Subject: [PATCH 397/655] * [task#141998,doing,1h] Retrun in the function of view when see template. --- module/doc/control.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/control.php b/module/doc/control.php index 11e47d435d..41c1183b38 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1265,6 +1265,7 @@ class doc extends control if($doc->templateType) { echo $this->fetch('doc', 'browseTemplate', "libID=$doc->lib&type=all&docID=$docID&orderBy=id_desc&recTotal=0&recPerPage=20&pageID=1&mode=view"); + return; } $_SESSION["doc_{$doc->id}_nopriv"] = ''; From 93fc919150a702bce8bf077cc04c909f7d8b6091 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 11:23:14 +0800 Subject: [PATCH 398/655] * [task#141998,doing,0.5h] Change the response after move template. --- module/doc/control.php | 11 ++++++++--- module/doc/model.php | 9 ++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 41c1183b38..60b57b0e52 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1911,9 +1911,14 @@ class doc extends control } $newDoc = $this->doc->getByID($docID); - $link = $this->createLink('doc', 'view', "docID={$docID}"); - if(!$this->doc->checkPrivDoc($newDoc)) $link = $this->createLink('doc', 'browseTemplate', "libID={$doc->lib}&type=all&docID=0&orderBy=id_desc&recTotal=0&recPerPage=20&pageID=1&mode=list"); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $newDoc)); + if(!$this->doc->checkPrivDoc($newDoc)) + { + $link = $this->createLink('doc', 'browseTemplate', "libID={$doc->lib}&type=all&docID=0&orderBy=id_desc&recTotal=0&recPerPage=20&pageID=1&mode=list"); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $newDoc)); + } + + $docAppAction = array('executeCommand', 'handleMovedDoc', array($docID, '1', $data->lib)); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'docApp' => $docAppAction)); } if(!empty($doc->parent)) diff --git a/module/doc/model.php b/module/doc/model.php index c0b09e0b57..2a040275dc 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1980,9 +1980,12 @@ class docModel extends model if($doc->status == 'draft' && $doc->addedBy != $this->app->user->account) return false; if($doc->status == 'normal' && $this->app->user->admin) return true; - static $libs = array(); - if(!isset($libs[$doc->lib])) $libs[$doc->lib] = $this->getLibByID((int)$doc->lib); - if(!$this->checkPrivLib($libs[$doc->lib], '', (string)$doc->id)) return false; + if(empty($doc->templateType)) + { + static $libs = array(); + if(!isset($libs[$doc->lib])) $libs[$doc->lib] = $this->getLibByID((int)$doc->lib); + if(!$this->checkPrivLib($libs[$doc->lib], '', (string)$doc->id)) return false; + } if(in_array($doc->acl, array('open', 'public'))) return true; From ba8c425e34c5e72414613509c43c8ce828199f99 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 13:34:24 +0800 Subject: [PATCH 399/655] * [misc] Add the auto test file of doUpdateDoc. --- module/doc/tao.php | 2 +- module/doc/test/lib/doc.unittest.class.php | 18 ++++++++++++++ module/doc/test/tao/doupdatedoc.php | 29 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100755 module/doc/test/tao/doupdatedoc.php diff --git a/module/doc/tao.php b/module/doc/tao.php index 189429c6d2..f54fc46a18 100644 --- a/module/doc/tao.php +++ b/module/doc/tao.php @@ -270,7 +270,7 @@ class docTao extends docModel * @access protected * @return void */ - protected function doUpdateDoc(int $docID, object $doc, $basicInfoChanged = false) + public function doUpdateDoc(int $docID, object $doc, $basicInfoChanged = false) { $this->dao->update(TABLE_DOC)->data($doc)->autoCheck()->where('id')->eq($docID)->exec(); diff --git a/module/doc/test/lib/doc.unittest.class.php b/module/doc/test/lib/doc.unittest.class.php index 11d3f76f5a..82cf89a6d3 100644 --- a/module/doc/test/lib/doc.unittest.class.php +++ b/module/doc/test/lib/doc.unittest.class.php @@ -1696,4 +1696,22 @@ class docTest if(!$result) return false; return $result ?: 0; } + + /** + * 更新文档。 + * Update document. + * + * @param int $docID + * @param array $doc + * @param bool $basicInfoChanged + * @access protected + * @return object + */ + public function doUpdateDocTest(int $docID, array $doc) + { + $docData = new stdClass(); + foreach($doc as $field => $value) $docData->{$field} = $value; + $this->objectModel->doUpdateDoc($docID, $docData); + return $this->objectModel->dao->select('*')->from(TABLE_DOC)->where('id')->eq($docID)->fetch(); + } } diff --git a/module/doc/test/tao/doupdatedoc.php b/module/doc/test/tao/doupdatedoc.php new file mode 100755 index 0000000000..7e3d1fe2a2 --- /dev/null +++ b/module/doc/test/tao/doupdatedoc.php @@ -0,0 +1,29 @@ +#!/usr/bin/env php +doUpdateDoc(); +cid=1 + +- 修改文档库ID属性lib @2 +- 修改所属目录属性module @3 +- 修改访问控制属性acl @open +- 修改可访问组属性groups @4 +- 修改可访问人员属性users @admin + +*/ + +include dirname(__FILE__, 5) . '/test/lib/init.php'; +include dirname(__FILE__, 2) . '/lib/doc.unittest.class.php'; + +zenData('doc')->loadYaml('template')->gen(10); +zenData('user')->gen(5); +su('admin'); + +$docTester = new docTest(); +r($docTester->doUpdateDocTest(1, array('lib' => 2))) && p('lib') && e('2'); // 修改文档库ID +r($docTester->doUpdateDocTest(2, array('module' => 3))) && p('module') && e('3'); // 修改所属目录 +r($docTester->doUpdateDocTest(3, array('acl' => 'open'))) && p('acl') && e('open'); // 修改访问控制 +r($docTester->doUpdateDocTest(4, array('groups' => 4))) && p('groups') && e('4'); // 修改可访问组 +r($docTester->doUpdateDocTest(5, array('users' => 'admin'))) && p('users') && e('admin'); // 修改可访问人员 From b0b475df3efc6363c65402685499a4d0d28e7ab7 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 13:38:32 +0800 Subject: [PATCH 400/655] * [task#141998,doing,0.1h] Modify the problem of sonar. --- module/doc/model.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 2a040275dc..aaf87e24ac 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1710,11 +1710,7 @@ class docModel extends model { if(in_array($change['field'], array('module', 'lib', 'acl', 'groups', 'users'))) $basicInfoChanged = true; if($change['field'] == 'content' || $change['field'] == 'title' || $change['field'] == 'rawContent') $changed = true; - if($change['field'] == 'content') - { - $onlyRawChanged = false; - continue; - } + if($change['field'] == 'content') $onlyRawChanged = false; } if($onlyRawChanged) $changes[] = array('field' => 'content', 'old' => $oldDoc->content, 'new' => $doc->content); if($changed) $this->saveDocContent($docID, $doc, $version, array_merge(array_keys($files), array_keys($oldDoc->files))); From afcccc65b1486387b1b4706eb6b9543cb58d6d60 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 13:55:03 +0800 Subject: [PATCH 401/655] * [task#141999,doing,0.5h] Show the top template in home page. --- module/doc/model.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/module/doc/model.php b/module/doc/model.php index aaf87e24ac..2f834758a4 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -4126,12 +4126,22 @@ class docModel extends model return $scopeTemplates; } + /** + * 获取范围内的最近顶层文档模板。 + * Get the recent top template of scope. + * + * @param int $scopeID + * @param int $limit + * @access public + * @return array + */ public function getHotTemplates($scopeID = 0, $limit = 0) { return $this->dao->select('*, CASE WHEN addedDate > editedDate THEN addedDate ELSE editedDate END as hotDate')->from(TABLE_DOC) ->where('templateType')->ne('') ->andWhere('deleted')->eq('0') ->andWhere('status')->eq('normal') + ->andWhere('parent')->eq(0) ->beginIF($scopeID)->andWhere('lib')->eq($scopeID)->fi() ->orderBy('hotDate_desc') ->beginIF($limit)->limit($limit)->fi() From 346a6ae4c41941be1dca74986b42be3c37e50c31 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 14:51:56 +0800 Subject: [PATCH 402/655] * [task#141999,doing,1h] Filter template in home page. --- module/doc/control.php | 2 ++ module/doc/lang/zh-cn.php | 2 +- module/doc/model.php | 3 +-- module/doc/ui/templatehome.html.php | 12 ++++++++++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 60b57b0e52..3c347cacb7 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -542,6 +542,7 @@ class doc extends control $this->app->loadClass('pager', true); $pager = new pager($recTotal, $recPerPage, $pageID); $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy, $pager); + $templateList = $this->doc->filterDeletedDocs($templateList); $templateList = $this->doc->filterPrivDocs($templateList, 'template'); $allModules = $this->doc->getTemplateModules(); $allModules = array_column($allModules, 'fullName', 'id'); @@ -2214,6 +2215,7 @@ class doc extends control $modules = $this->doc->getTemplateModules(); $moduleNames = array_column($modules, 'fullName', 'id'); $templateList = $this->doc->getDocTemplateList(0, 'all'); + $templateList = $this->doc->filterDeletedDocs($templateList); $templateList = $this->doc->filterPrivDocs($templateList, 'template'); foreach($templateList as $template) { diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index b739548e29..89cc7f435a 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -118,7 +118,7 @@ $lang->docTemplate->of = '的'; $lang->docTemplate->overdue = '已过期'; $lang->docTemplate->create = '创建模板'; -$lang->docTemplate->edit = '编辑模板'; +$lang->docTemplate->edit = '编辑文档模板'; $lang->docTemplate->delete = '删除文档模板'; $lang->docTemplate->addModule = '添加类型'; diff --git a/module/doc/model.php b/module/doc/model.php index 2f834758a4..10ac1ca257 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -660,8 +660,7 @@ class docModel extends model public function getDocTemplateList(int $libID = 0, string $type = 'all', string $orderBy = 'id_desc', object $pager = null, string $searchName = ''): array { return $this->dao->select('*')->from(TABLE_DOC) - ->where('deleted')->eq('0') - ->andWhere('templateType')->ne('') + ->where('templateType')->ne('') ->beginIF(!$this->app->user->admin)->andWhere("(`status` = 'normal' or (`status` = 'draft' and `addedBy`='{$this->app->user->account}'))")->fi() ->beginIF($libID)->andWhere('lib')->eq($libID)->fi() ->beginIF($type == 'draft')->andWhere('status')->eq('draft')->fi() diff --git a/module/doc/ui/templatehome.html.php b/module/doc/ui/templatehome.html.php index 96ac362cb1..129a97bb34 100644 --- a/module/doc/ui/templatehome.html.php +++ b/module/doc/ui/templatehome.html.php @@ -11,12 +11,20 @@ declare(strict_types=1); namespace zin; $scopeTemplates = $this->doc->getScopeTemplates(); +$allTemplates = $this->doc->getTemplatesByType(); -$buildScopeCards = function($templates) use ($lang) +$buildScopeCards = function($templates) use ($lang, $allTemplates) { $cardItems = array(); foreach($templates as $template) { + $hasChildren = false; + foreach($allTemplates as $templateInfo) + { + if($templateInfo->id == $template->id) continue; + if(strpos(",{$templateInfo->path},", ",{$template->id},") !== false) $hasChildren = true; + } + $cardDesc = $template->templateDesc ? $template->templateDesc : $lang->docTemplate->noDesc; $viewLink = createLink('doc', 'view', "docID=$template->id"); $editLink = createLink('doc', 'browsetemplate', "libID=$template->lib&type=all&docID=$template->id&orderBy=id_desc&recTotal=0&recPerPage=20&page=1&mode=edit"); @@ -24,7 +32,7 @@ $buildScopeCards = function($templates) use ($lang) $actions = array(); if(hasPriv('doc', 'editTemplate')) $actions[] = array('icon' => 'edit', 'text' => $this->lang->docTemplate->edit, 'url' => $editLink); - if(hasPriv('doc', 'deleteTemplate')) $actions[] = array('icon' => 'trash', 'text' => $this->lang->docTemplate->delete, 'url' => $deleteLink, 'data-confirm' => $this->lang->docTemplate->confirmDelete); + if(hasPriv('doc', 'deleteTemplate')) $actions[] = array('icon' => 'trash', 'text' => $this->lang->docTemplate->delete, 'url' => $deleteLink, 'data-confirm' => $hasChildren ? $this->lang->docTemplate->confirmDeleteTemplateWithSub : $this->lang->docTemplate->confirmDelete); $cardItems[] = div ( From 039742e5c850b1480899fe8f559ff659513c7582 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 15:23:47 +0800 Subject: [PATCH 403/655] * [task#142041,doing,0.5h] Change the priv of template. --- module/group/packagemanager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index ee1b46c1c3..8163401721 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2936,8 +2936,8 @@ $config->group->package->manageDoctemplate->order = 15; $config->group->package->manageDoctemplate->subset = 'doctemplate'; $config->group->package->manageDoctemplate->privs = array(); $config->group->package->manageDoctemplate->privs['doc-createTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate', 'doc-editTemplate'), 'recommend' => array()); -$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate', 'doc-moveTemplate'), 'recommend' => array('doc-createTemplate')); -$config->group->package->manageDoctemplate->privs['doc-moveTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-editTemplate')); +$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-createTemplate', 'doc-moveTemplate')); +$config->group->package->manageDoctemplate->privs['doc-moveTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-createTemplate', 'doc-editTemplate')); $config->group->package->manageDoctemplate->privs['doc-addTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-editTemplateType'), 'recommend' => array('doc-deleteTemplateType')); $config->group->package->manageDoctemplate->privs['doc-editTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-addTemplateType'), 'recommend' => array('doc-deleteTemplateType')); From 37f156e880147163b9092cfc087c552bcab19d8f Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 15:59:29 +0800 Subject: [PATCH 404/655] * [task#141996,doing,1h] Add the function of sort template. --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/ui/templatelist.html.php | 1 + module/group/packagemanager.php | 11 ++++++----- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 97be51ec59..be3e06d7c1 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -602,6 +602,7 @@ $lang->doc->viewTemplate = 'View Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; +$lang->doc->sortTemplate = 'Sort'; $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index d136d8aa0a..456f92af23 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -602,6 +602,7 @@ $lang->doc->viewTemplate = 'View Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; +$lang->doc->sortTemplate = 'Sort'; $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index c8e143b75a..adad93d11d 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -602,6 +602,7 @@ $lang->doc->viewTemplate = 'View Document Template'; $lang->doc->addTemplateType = 'Create Type'; $lang->doc->editTemplateType = 'Edit Type'; $lang->doc->deleteTemplateType = 'Delete Type'; +$lang->doc->sortTemplate = 'Sort'; $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 89cc7f435a..5d7d35ec85 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -602,6 +602,7 @@ $lang->doc->viewTemplate = '文档模板详情'; $lang->doc->addTemplateType = '添加模板类型'; $lang->doc->editTemplateType = '编辑模板类型'; $lang->doc->deleteTemplateType = '删除模板类型'; +$lang->doc->sortTemplate = '排序'; $lang->doc->docLang = new stdClass(); $lang->doc->docLang->cancel = $lang->cancel; diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index 29e5448814..ea618af141 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -28,6 +28,7 @@ $privs['moveDoc'] = hasPriv('doc', 'moveTemplate'); $privs['addChapter'] = hasPriv('doc', 'createTemplate'); $privs['editChapter'] = hasPriv('doc', 'editTemplate'); $privs['deleteChapter'] = hasPriv('doc', 'deleteTemplate'); +$privs['sortDoc'] = hasPriv('doc', 'sortTemplate'); $privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; diff --git a/module/group/packagemanager.php b/module/group/packagemanager.php index 8163401721..b79539aace 100644 --- a/module/group/packagemanager.php +++ b/module/group/packagemanager.php @@ -2935,11 +2935,12 @@ $config->group->package->manageDoctemplate = new stdclass(); $config->group->package->manageDoctemplate->order = 15; $config->group->package->manageDoctemplate->subset = 'doctemplate'; $config->group->package->manageDoctemplate->privs = array(); -$config->group->package->manageDoctemplate->privs['doc-createTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate', 'doc-editTemplate'), 'recommend' => array()); -$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-createTemplate', 'doc-moveTemplate')); -$config->group->package->manageDoctemplate->privs['doc-moveTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-createTemplate', 'doc-editTemplate')); -$config->group->package->manageDoctemplate->privs['doc-addTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-editTemplateType'), 'recommend' => array('doc-deleteTemplateType')); -$config->group->package->manageDoctemplate->privs['doc-editTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-addTemplateType'), 'recommend' => array('doc-deleteTemplateType')); +$config->group->package->manageDoctemplate->privs['doc-createTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate', 'doc-editTemplate'), 'recommend' => array()); +$config->group->package->manageDoctemplate->privs['doc-editTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-createTemplate', 'doc-moveTemplate')); +$config->group->package->manageDoctemplate->privs['doc-moveTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-viewTemplate'), 'recommend' => array('doc-createTemplate', 'doc-editTemplate')); +$config->group->package->manageDoctemplate->privs['doc-addTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-editTemplateType'), 'recommend' => array('doc-deleteTemplateType')); +$config->group->package->manageDoctemplate->privs['doc-editTemplateType'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate', 'doc-addTemplateType'), 'recommend' => array('doc-deleteTemplateType')); +$config->group->package->manageDoctemplate->privs['doc-sortTemplate'] = array('edition' => 'biz,max,ipd', 'vision' => 'rnd', 'order' => 0, 'depend' => array('doc-browseTemplate'), 'recommend' => array()); $config->group->package->deleteDoctemplate = new stdclass(); $config->group->package->deleteDoctemplate->order = 20; From 07fe9b51c11d22e76f3b45c3e06fc31a494f787c Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 16:49:20 +0800 Subject: [PATCH 405/655] * [bug#61297] Load scope type when change lib. --- module/doc/control.php | 21 +++++++++++++++++++++ module/doc/js/common.ui.js | 13 +++++++++++++ module/doc/ui/movetemplate.html.php | 2 +- module/doc/ui/setdocbasic.template.html.php | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index 3c347cacb7..cc2fb75dc0 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1091,6 +1091,27 @@ class doc extends control return print(json_encode(array('libs' => $libItems, 'modules' => $moduleItems))); } + /** + * + * AJAX: 获取范围下的类型。 + * Ajax get types of scope. + * + * @param int $libID + * @access public + * @return json + */ + public function ajaxGetScopeTypes(int $libID = 0) + { + $optionMenu = $this->loadModel('tree')->getOptionMenu($libID, 'docTemplate', 0, 'all', 'nodeleted', 'all'); + $types = array(); + foreach($optionMenu as $menuID => $menu) + { + if(empty($menuID)) continue; + $types[] = array('text' => $menu, 'value' => $menuID, 'keys' => $menu); + } + return print(json_encode($types)); + } + /** * AJAX: 通过空间类型获取文档库。 * AJAX: Get libs by type. diff --git a/module/doc/js/common.ui.js b/module/doc/js/common.ui.js index 32ccd71a60..c62e1b8392 100644 --- a/module/doc/js/common.ui.js +++ b/module/doc/js/common.ui.js @@ -248,6 +248,19 @@ window.loadLibModules = function(e, docID) }); } +window.loadScopeTypes = function(e) +{ + const libID = e.target.value; + const link = $.createLink('doc', 'ajaxGetScopeTypes', 'libID=' + libID); + $.get(link, function(data) + { + data = JSON.parse(data); + const $modulePicker = $("[name='module']").zui('picker'); + $modulePicker.render({items: data}); + $modulePicker.$.setValue(''); + }); +} + window.toggleWhiteList = function(e) { const acl = e.target.value; diff --git a/module/doc/ui/movetemplate.html.php b/module/doc/ui/movetemplate.html.php index be5b9d2398..3beeeb0e1a 100644 --- a/module/doc/ui/movetemplate.html.php +++ b/module/doc/ui/movetemplate.html.php @@ -17,7 +17,7 @@ modalHeader(set::title($lang->docTemplate->moveDocTemplate), set::entityText($do unset($modules[0]); formPanel ( - on::change('[name=lib]')->call('loadLibModules', jsRaw("event, 'docTemplate'")), + on::change('[name=lib]')->call('loadScopeTypes', jsRaw("event")), empty($doc->parent) ? formGroup ( set::label($lang->docTemplate->scope), diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 61d6277853..8249766237 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -25,7 +25,7 @@ formPanel setData('docType', isset($doc) ? $doc->users : 'undefined'), set::title($title), set::submitBtnText($lang->save), - on::change('[name=lib]')->call('loadLibModules', jsRaw("event, 'docTemplate'")), + on::change('[name=lib]')->call('loadScopeTypes', jsRaw("event")), set::ajax(array('beforeSubmit' => jsRaw('window.beforeSetDocBasicInfo'))), formGroup ( From 21e8f0106b46c320acd7ed6bd57725bc386789c7 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Fri, 25 Apr 2025 17:18:57 +0800 Subject: [PATCH 406/655] * [bug#61940] Set users and groups when edit template. --- module/doc/control.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index cc2fb75dc0..dddf115465 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -696,10 +696,10 @@ class doc extends control { $changes = $files = array(); $docData = form::data() - ->setDefault('users', $doc->users) - ->setDefault('groups', $doc->groups) ->setDefault('editedBy', $this->app->user->account) ->setIF(!isset($_POST['parent']), 'parent', $doc->parent) + ->setIF(!isset($_POST['users']), 'users', $doc->users) + ->setIF(!isset($_POST['groups']), 'groups', $doc->groups) ->setIF(strpos(",$doc->editedList,", ",{$this->app->user->account},") === false, 'editedList', $doc->editedList . ",{$this->app->user->account}") ->setIF($this->post->type == 'chapter', 'content', $doc->content) ->setIF($this->post->type == 'chapter', 'rawContent', $doc->rawContent) From 47636454e5049d73fa8c0082d9ccfce3d24bf3cc Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Sun, 27 Apr 2025 09:17:07 +0800 Subject: [PATCH 407/655] * [bug#61864] Change the language of parent to level. --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/ui/movetemplate.html.php | 2 +- module/doc/ui/setdocbasic.template.html.php | 2 +- 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index be3e06d7c1..aa87cd56d9 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -89,6 +89,7 @@ $lang->docTemplate->module = 'Type'; $lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->parent = 'Level'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 456f92af23..5064f7bb12 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -89,6 +89,7 @@ $lang->docTemplate->module = 'Type'; $lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->parent = 'Level'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index adad93d11d..9caeac9306 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -89,6 +89,7 @@ $lang->docTemplate->module = 'Type'; $lang->docTemplate->desc = 'Describe'; $lang->docTemplate->parentModule = 'Parent'; $lang->docTemplate->typeName = 'Type Name'; +$lang->docTemplate->parent = 'Level'; $lang->docTemplate->addTemplateType = 'Add template type'; $lang->docTemplate->editTemplateType = 'Edit template type'; $lang->docTemplate->docTitlePlaceholder = 'Enter the document template title'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 5d7d35ec85..956aa2e7ed 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -89,6 +89,7 @@ $lang->docTemplate->module = '模板类型'; $lang->docTemplate->desc = '描述'; $lang->docTemplate->parentModule = '上级类型'; $lang->docTemplate->typeName = '类型名称'; +$lang->docTemplate->parent = '所属层级'; $lang->docTemplate->addTemplateType = '添加文档模板类型'; $lang->docTemplate->editTemplateType = '编辑文档模板类型'; $lang->docTemplate->docTitlePlaceholder = '请输入文档模板标题'; diff --git a/module/doc/ui/movetemplate.html.php b/module/doc/ui/movetemplate.html.php index 3beeeb0e1a..e8f0963bbf 100644 --- a/module/doc/ui/movetemplate.html.php +++ b/module/doc/ui/movetemplate.html.php @@ -32,7 +32,7 @@ formPanel ) : null, !empty($doc->parent) ? formGroup ( - set::label($lang->doc->module), + set::label($lang->docTemplate->parent), picker ( set::name('parent'), diff --git a/module/doc/ui/setdocbasic.template.html.php b/module/doc/ui/setdocbasic.template.html.php index 8249766237..e2b52452ea 100644 --- a/module/doc/ui/setdocbasic.template.html.php +++ b/module/doc/ui/setdocbasic.template.html.php @@ -48,7 +48,7 @@ formPanel ) : null, ($modalType != 'chapter' || !$isCreate) && !empty($parentID) ? formGroup ( - set::label($lang->doc->module), + set::label($lang->docTemplate->parent), picker ( set::name('parent'), From 4d8c5fda2d601aface19d3b4fb36f84b0b1c3302 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 25 Apr 2025 08:44:33 +0000 Subject: [PATCH 408/655] * [task#141199,done,1h] Compatible with multiple products. --- module/product/model.php | 18 +++++++++--------- module/story/model.php | 22 +++++++++++----------- module/story/tao.php | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/module/product/model.php b/module/product/model.php index d0aae19827..ce5db46613 100755 --- a/module/product/model.php +++ b/module/product/model.php @@ -637,18 +637,18 @@ class productModel extends model * 获取需求列表。 * Get stories. * - * @param int $productID - * @param string $branch - * @param string $browseType bymodule|unclosed|allstory|assignedtome|openedbyme|reviewbyme|draftstory|reviewedbyme|assignedbyme|closedbyme|activestory|changingstory|reviewingstory|willclose|closedstory - * @param int $queryID - * @param int $moduleID - * @param string $type requirement|story - * @param string $sort - * @param object $pager + * @param int|array $productID + * @param string $branch + * @param string $browseType bymodule|unclosed|allstory|assignedtome|openedbyme|reviewbyme|draftstory|reviewedbyme|assignedbyme|closedbyme|activestory|changingstory|reviewingstory|willclose|closedstory + * @param int $queryID + * @param int $moduleID + * @param string $type requirement|story + * @param string $sort + * @param object $pager * @access public * @return array */ - public function getStories(int $productID, string $branch, string $browseType, int $queryID, int $moduleID, string $type = 'story', string $sort = 'id_desc', object|null$pager = null): array + public function getStories(int|array $productID, string $branch, string $browseType, int $queryID, int $moduleID, string $type = 'story', string $sort = 'id_desc', object|null$pager = null): array { if(commonModel::isTutorialMode()) return $this->loadModel('tutorial')->getStories(); diff --git a/module/story/model.php b/module/story/model.php index 850468a9ac..6a4c83f607 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -2308,7 +2308,7 @@ class storyModel extends model /** * Get stories list of a product. * - * @param string|int $productID + * @param string|int|array $productID * @param array|string|int $branch * @param array|string $moduleIdList * @param array|string $status @@ -2321,7 +2321,7 @@ class storyModel extends model * @access public * @return array */ - public function getProductStories(string|int $productID = 0, array|string|int $branch = 0, array|string $moduleIdList = '', array|string $status = 'all', string $type = 'story', string $orderBy = 'id_desc', bool $hasParent = true, array|string $excludeStories = '', object|null $pager = null): array + public function getProductStories(string|int|array $productID = 0, array|string|int $branch = 0, array|string $moduleIdList = '', array|string $status = 'all', string $type = 'story', string $orderBy = 'id_desc', bool $hasParent = true, array|string $excludeStories = '', object|null $pager = null): array { if(commonModel::isTutorialMode()) return $this->loadModel('tutorial')->getStories(); $showGrades = isset($this->config->{$type}->showGrades) ? $this->config->{$type}->showGrades : null; @@ -2596,7 +2596,7 @@ class storyModel extends model /** * Get stories by a field. * - * @param int $productID + * @param int|array $productID * @param int|string $branch * @param string|array $modules * @param string $fieldName @@ -2608,7 +2608,7 @@ class storyModel extends model * @access public * @return array */ - public function getByField(int $productID, int|string $branch, string|array $modules, string $fieldName, string $fieldValue, string $type = 'story', string $orderBy = '', object|null $pager = null, string $operator = 'equal'): array + public function getByField(int|array $productID, int|string $branch, string|array $modules, string $fieldName, string $fieldValue, string $type = 'story', string $orderBy = '', object|null $pager = null, string $operator = 'equal'): array { if(!$this->loadModel('common')->checkField(TABLE_STORY, $fieldName) and $fieldName != 'reviewBy' and $fieldName != 'assignedBy') return array(); @@ -2656,16 +2656,16 @@ class storyModel extends model /** * Get to be closed stories. * - * @param int $productID - * @param int $branch - * @param string $modules - * @param string $type requirement|story - * @param string $orderBy - * @param object $pager + * @param int|array $productID + * @param int $branch + * @param string $modules + * @param string $type requirement|story + * @param string $orderBy + * @param object $pager * @access public * @return array */ - public function get2BeClosed(int $productID, int|string $branch, string|array $modules, string $type = 'story', string $orderBy = '', object|null $pager = null): array + public function get2BeClosed(int|array $productID, int|string $branch, string|array $modules, string $type = 'story', string $orderBy = '', object|null $pager = null): array { $showGrades = isset($this->config->{$type}->showGrades) ? $this->config->{$type}->showGrades : null; if($showGrades) diff --git a/module/story/tao.php b/module/story/tao.php index bf4c3268cd..cf7e4dbb3e 100644 --- a/module/story/tao.php +++ b/module/story/tao.php @@ -189,12 +189,12 @@ class storyTao extends storyModel * 根据产品 ID 列表和分支参数,构建查询条件。 * Build products condition. * - * @param string|int $productIdList + * @param string|int|array $productIdList * @param array|string|int $branch * @access protected * @return string */ - protected function buildProductsCondition(string|int $productIdList, array|string|int $branch = 'all'): string + protected function buildProductsCondition(string|int|array $productIdList, array|string|int $branch = 'all'): string { /* 如果查询所有分支,直接用 idList 条件。 */ if(empty($productIdList)) $productIdList = '0'; From 77631a03d8a074a16d7c282e4bf80100ee5a38d2 Mon Sep 17 00:00:00 2001 From: daitingting Date: Fri, 25 Apr 2025 09:05:00 +0000 Subject: [PATCH 409/655] * [misc] Adjust order. --- module/story/model.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/story/model.php b/module/story/model.php index 6a4c83f607..221e785539 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -1038,8 +1038,6 @@ class storyModel extends model $isChanged = $oldParentStory->changedBy ? true : false; if($preStatus == 'reviewing') $preStatus = $isChanged ? 'changing' : 'draft'; } - - if($this->config->edition != 'open' && $oldParentStory->feedback) $this->loadModel('feedback')->updateStatus('story', $oldParentStory->feedback, $newParentStory->status, $oldParentStory->status, $oldParentStory->id); } else { @@ -1048,7 +1046,9 @@ class storyModel extends model } $newParentStory = $this->dao->select('*')->from(TABLE_STORY)->where('id')->eq($parentID)->fetch(); - $changes = common::createChanges($oldParentStory, $newParentStory); + if($this->config->edition != 'open' && $oldParentStory->feedback) $this->loadModel('feedback')->updateStatus('story', $oldParentStory->feedback, $status, $oldParentStory->status, $oldParentStory->id); + + $changes = common::createChanges($oldParentStory, $newParentStory); if($action and $changes) { $actionID = $this->loadModel('action')->create('story', $parentID, $action, '', $preStatus, '', false); From 3d84be840505628a21463eb5772b709a9e78ba3b Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 01:29:43 +0000 Subject: [PATCH 410/655] * [misc] Remove useless codes. --- module/product/model.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/product/model.php b/module/product/model.php index ce5db46613..d68b894d72 100755 --- a/module/product/model.php +++ b/module/product/model.php @@ -2169,7 +2169,6 @@ class productModel extends model public function getSwitcher(int $productID = 0, string $extra = ''): string { /* 获取产品名称,产品类型。 */ - $currentProduct = new stdclass(); $currentProductName = $this->lang->productCommon; if($productID) { From b68e77583161e37430b8764229f82187bd8c53f6 Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 01:33:19 +0000 Subject: [PATCH 411/655] * [misc] Optimize codes. --- module/story/model.php | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/module/story/model.php b/module/story/model.php index 221e785539..61390dc4bb 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -1899,33 +1899,32 @@ class storyModel extends model $story->module = ($oldStory->branch != $branchID and !in_array($oldStory->module, $mainModules)) ? 0 : $oldStory->module; $this->dao->update(TABLE_STORY)->data($story)->autoCheck()->where('id')->eq((int)$storyID)->exec(); - if(!dao::isError()) + if(dao::isError()) return array(); + + if($confirm == 'yes') { - if($confirm == 'yes') + $planIdList = array(); + $conflictPlanIdList = array(); + + /* Determine whether there is a conflict between the branch of the story and the linked plan. */ + if($oldStory->branch != $branchID and $branchID != BRANCH_MAIN and isset($plans[$storyID])) { - $planIdList = array(); - $conflictPlanIdList = array(); - - /* Determine whether there is a conflict between the branch of the story and the linked plan. */ - if($oldStory->branch != $branchID and $branchID != BRANCH_MAIN and isset($plans[$storyID])) + foreach($plans[$storyID] as $planID => $plan) { - foreach($plans[$storyID] as $planID => $plan) - { - if($plan->branch != $branchID) $conflictPlanIdList[$planID] = $planID; - if($plan->branch == $branchID) $planIdList[$planID] = $planID; - } + if($plan->branch != $branchID) $conflictPlanIdList[$planID] = $planID; + if($plan->branch == $branchID) $planIdList[$planID] = $planID; + } - /* If there is a conflict in the linked plan when the branch story to be modified, the linked with the conflicting plan will be removed. */ - if($conflictPlanIdList) $this->dao->delete()->from(TABLE_PLANSTORY)->where('story')->eq($storyID)->andWhere('plan')->in(implode(',', $conflictPlanIdList))->exec(); - if($planIdList) - { - $story->plan = implode(',', $planIdList); - $this->dao->update(TABLE_STORY)->set('plan')->eq($story->plan)->where('id')->eq($storyID)->exec(); - } + /* If there is a conflict in the linked plan when the branch story to be modified, the linked with the conflicting plan will be removed. */ + if($conflictPlanIdList) $this->dao->delete()->from(TABLE_PLANSTORY)->where('story')->eq($storyID)->andWhere('plan')->in(implode(',', $conflictPlanIdList))->exec(); + if($planIdList) + { + $story->plan = implode(',', $planIdList); + $this->dao->update(TABLE_STORY)->set('plan')->eq($story->plan)->where('id')->eq($storyID)->exec(); } } - $allChanges[$storyID] = common::createChanges($oldStory, $story); } + $allChanges[$storyID] = common::createChanges($oldStory, $story); } return $allChanges; } From 7430cff4fae0bce30f94429d7e9c66c5d051a261 Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 01:36:19 +0000 Subject: [PATCH 412/655] * [misc] Optimize codes. --- module/story/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/story/model.php b/module/story/model.php index 61390dc4bb..8a3e8ba666 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -3097,7 +3097,7 @@ class storyModel extends model ->beginIF($type == 'reviewedBy')->andWhere("CONCAT(',', t1.reviewedBy, ',')")->like("%,$account,%")->fi() ->beginIF($type == 'closedBy')->andWhere('t1.closedBy')->eq($account)->fi() ->fi() - ->beginIF($includeLibStories == false and $this->config->edition == 'max')->andWhere('t1.lib')->eq('0')->fi() + ->beginIF(!$includeLibStories and $this->config->edition == 'max')->andWhere('t1.lib')->eq('0')->fi() ->beginIF($shadow !== 'all')->andWhere('t2.shadow')->eq((int)$shadow)->fi() ->beginIF($productID)->andWhere('t1.product')->eq((int)$productID)->fi() ->orderBy($orderBy) From 8fc706a77e40dc0b01a428bd1a177ab252047a73 Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 02:11:54 +0000 Subject: [PATCH 413/655] * [misc] Optimize codes. --- module/story/model.php | 7 ++----- module/story/tao.php | 19 ++++++------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/module/story/model.php b/module/story/model.php index 8a3e8ba666..35ebc96047 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -4101,9 +4101,7 @@ class storyModel extends model $forceUsers .= "," . implode(',', array_keys($users)); } - $forceReview = $this->config->{$storyType}->needReview == 0 ? strpos(",{$forceUsers},", ",{$this->app->user->account},") !== false : strpos(",{$forceUsers},", ",{$this->app->user->account},") === false; - - return $forceReview; + return $this->config->{$storyType}->needReview == 0 ? strpos(",{$forceUsers},", ",{$this->app->user->account},") !== false : strpos(",{$forceUsers},", ",{$this->app->user->account},") === false; } /** @@ -4124,7 +4122,6 @@ class storyModel extends model $stories = $this->storyTao->mergeChildrenForTrack($allStories, $stories, $storyType); $leafNodes = $this->storyTao->getLeafNodes($stories, $storyType); - $tracks = array(); $lanes = $this->storyTao->buildTrackLanes($leafNodes, $storyType); $cols = $this->storyTao->buildTrackCols($storyType); $items = $this->storyTao->buildTrackItems($stories, $leafNodes, $storyType); @@ -4739,7 +4736,7 @@ class storyModel extends model } if($oldStory->status == 'reviewing') $story = $this->updateStoryByReview($storyID, $oldStory, $story); - if(strpos('draft,changing', $oldStory->status) != false) $story->reviewedBy = ''; + if(strpos('draft,changing', $oldStory->status) !== false) $story->reviewedBy = ''; } /** diff --git a/module/story/tao.php b/module/story/tao.php index cf7e4dbb3e..7f79b81ce0 100644 --- a/module/story/tao.php +++ b/module/story/tao.php @@ -1953,15 +1953,12 @@ class storyTao extends storyModel if(!empty($execution) && !common::canModify($execution->type == 'project' ? 'project' : 'execution', $execution)) return $actions; $tutorialMode = commonModel::isTutorialMode(); - if($this->config->edition == 'ipd' && $storyType == 'story') + if($this->config->edition == 'ipd' && $storyType == 'story' && !empty($story->confirmeActionType)) { - if(!empty($story->confirmeActionType)) - { - $method = $story->confirmeActionType == 'confirmedretract' ? 'confirmDemandRetract' : 'confirmDemandUnlink'; - $url = helper::createLink('story', $method, "objectID=$story->id&object=story&extra={$story->confirmeObjectID}"); - $actions[] = array('name' => $method, 'icon' => 'search', 'hint' => $this->lang->story->$method, 'url' => $url, 'data-toggle' => 'modal'); - return $actions; - } + $method = $story->confirmeActionType == 'confirmedretract' ? 'confirmDemandRetract' : 'confirmDemandUnlink'; + $url = helper::createLink('story', $method, "objectID=$story->id&object=story&extra={$story->confirmeObjectID}"); + $actions[] = array('name' => $method, 'icon' => 'search', 'hint' => $this->lang->story->$method, 'url' => $url, 'data-toggle' => 'modal'); + return $actions; } static $taskGroups = array(); @@ -2132,7 +2129,6 @@ class storyTao extends storyModel if($execution->type == 'project') { - $unlinkModule = 'projectstory'; $unlinkStoryTip = $this->lang->execution->confirmUnlinkExecutionStory; static $executionStories = array(); @@ -2416,8 +2412,6 @@ class storyTao extends storyModel $stmt = $this->dao->select('*')->from(TABLE_PROJECTSTORY)->where('story')->in($storyIdList)->query(); while($projectStory = $stmt->fetch()) $projectStoryList[$projectStory->project][$projectStory->story] = $projectStory->story; - $projects = array(); - $executions = array(); $stmt = $this->dao->select('id,type AS projectType,model,parent,path,grade,name as title,hasProduct,begin,end,status,project,progress,multiple')->from(TABLE_PROJECT)->where('id')->in(array_keys($projectStoryList))->andWhere('deleted')->eq(0)->orderBy('id')->query(); $today = helper::today(); $storyGroup = array(); @@ -2449,7 +2443,6 @@ class storyTao extends storyModel $storyGroup = array('design' => array(), 'commit' => array()); $stmt = $this->dao->select('id,project,commit,name as title,status,story,type AS designType')->from(TABLE_DESIGN)->where('story')->in($storyIdList)->andWhere('deleted')->eq(0)->orderBy('project')->query(); $commitIdList = ''; - $commitGroup = array(); while($design = $stmt->fetch()) { $storyGroup['design'][$design->story][$design->id] = $design; @@ -2459,7 +2452,7 @@ class storyTao extends storyModel if($commitIdList) $commits = $this->dao->select('id,repo,revision,committer,comment as title')->from(TABLE_REPOHISTORY)->where('id')->in(array_unique(explode(',', $commitIdList)))->fetchAll('id'); foreach($storyGroup['design'] as $storyID => $designs) { - foreach($designs as $designID => $design) + foreach($designs as $design) { if(empty($design->commit)) continue; foreach(explode(',', $design->commit) as $commitID) From 356640d070d3e26c9c465edf6be904b6a73fbe46 Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 02:15:26 +0000 Subject: [PATCH 414/655] * [misc] Remove useless codes. --- module/story/model.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/module/story/model.php b/module/story/model.php index 35ebc96047..744e23ed7b 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -4075,8 +4075,6 @@ class storyModel extends model */ public function checkForceReview(string $storyType = 'story'): bool { - $forceReview = false; - $forceField = $this->config->{$storyType}->needReview == 0 ? 'forceReview' : 'forceNotReview'; $forceReviewRoles = !empty($this->config->{$storyType}->{$forceField . 'Roles'}) ? $this->config->{$storyType}->{$forceField . 'Roles'} : ''; $forceReviewDepts = !empty($this->config->{$storyType}->{$forceField . 'Depts'}) ? $this->config->{$storyType}->{$forceField . 'Depts'} : ''; From da681f880a9e0be3ded88b9453585c356e0c13ae Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 03:08:10 +0000 Subject: [PATCH 415/655] * [task#141211,done,1h] Adjust actions. --- module/doc/lang/de.php | 5 +++-- module/doc/lang/en.php | 5 +++-- module/doc/lang/fr.php | 5 +++-- module/doc/lang/zh-cn.php | 5 +++-- module/doc/ui/zentaolist.html.php | 3 ++- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index aa87cd56d9..7d9a227ddc 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -379,8 +379,9 @@ $lang->doc->zentaoList['feedback'] = 'Feedback'; $lang->doc->zentaoList['ticket'] = 'Ticket'; $lang->doc->zentaoAction = array(); -$lang->doc->zentaoAction['set'] = 'Setting'; -$lang->doc->zentaoAction['delete'] = 'Delete'; +$lang->doc->zentaoAction['set'] = 'Setting'; +$lang->doc->zentaoAction['delete'] = 'Delete'; +$lang->doc->zentaoAction['setParams'] = 'Set Parameters'; $lang->doc->uploadFormatList = array(); $lang->doc->uploadFormatList['separateDocs'] = 'Save files as different document'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 5064f7bb12..5af7929ca6 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -379,8 +379,9 @@ $lang->doc->zentaoList['feedback'] = 'Feedback'; $lang->doc->zentaoList['ticket'] = 'Ticket'; $lang->doc->zentaoAction = array(); -$lang->doc->zentaoAction['set'] = 'Setting'; -$lang->doc->zentaoAction['delete'] = 'Delete'; +$lang->doc->zentaoAction['set'] = 'Setting'; +$lang->doc->zentaoAction['delete'] = 'Delete'; +$lang->doc->zentaoAction['setParams'] = 'Set Parameters'; $lang->doc->uploadFormatList = array(); $lang->doc->uploadFormatList['separateDocs'] = 'Save files as different document'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index 9caeac9306..ac2aaf9583 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -379,8 +379,9 @@ $lang->doc->zentaoList['feedback'] = 'Feedback'; $lang->doc->zentaoList['ticket'] = 'Ticket'; $lang->doc->zentaoAction = array(); -$lang->doc->zentaoAction['set'] = 'Setting'; -$lang->doc->zentaoAction['delete'] = 'Delete'; +$lang->doc->zentaoAction['set'] = 'Setting'; +$lang->doc->zentaoAction['delete'] = 'Delete'; +$lang->doc->zentaoAction['setParams'] = 'Set Parameters'; $lang->doc->uploadFormatList = array(); $lang->doc->uploadFormatList['separateDocs'] = 'Save files as different document'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 956aa2e7ed..92ea659b8d 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -379,8 +379,9 @@ $lang->doc->zentaoList['feedback'] = '反馈'; $lang->doc->zentaoList['ticket'] = '工单'; $lang->doc->zentaoAction = array(); -$lang->doc->zentaoAction['set'] = '设置'; -$lang->doc->zentaoAction['delete'] = '删除'; +$lang->doc->zentaoAction['set'] = '设置'; +$lang->doc->zentaoAction['delete'] = '删除'; +$lang->doc->zentaoAction['setParams'] = '配置参数'; $lang->doc->uploadFormatList = array(); $lang->doc->uploadFormatList['separateDocs'] = '每个文件存为不同文档'; diff --git a/module/doc/ui/zentaolist.html.php b/module/doc/ui/zentaolist.html.php index 661d58a4bc..d3d4493d8d 100644 --- a/module/doc/ui/zentaolist.html.php +++ b/module/doc/ui/zentaolist.html.php @@ -21,7 +21,8 @@ if(!$isTemplate) } $actions = array(); -$actions[] = array('icon' => 'menu-backend', 'text' => $lang->doc->zentaoAction['set'], 'data-toggle' => 'modal', 'url' => str_replace('{blockID}', "$blockID", $settings), 'data-size' => $isTemplate ? 'sm' : 'lg'); +$setText = (!$isTemplate && $fromTemplate) ? $lang->doc->zentaoAction['setParams'] : $lang->doc->zentaoAction['set']; +$actions[] = array('icon' => 'menu-backend', 'text' => $setText, 'data-toggle' => 'modal', 'url' => str_replace('{blockID}', "$blockID", $settings), 'data-size' => $isTemplate ? 'sm' : 'lg'); $actions[] = array('icon' => 'trash', 'text' => $lang->doc->zentaoAction['delete'], 'zui-on-click' => "deleteZentaoList($blockID)"); if($isTemplate || $fromTemplate) From e473c12902978ed4f6ceb4f5aa180f7eae5ff313 Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 05:43:57 +0000 Subject: [PATCH 416/655] * [misc] Optimize codes. --- module/doc/ui/movetemplate.html.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/doc/ui/movetemplate.html.php b/module/doc/ui/movetemplate.html.php index e8f0963bbf..84107e8d82 100644 --- a/module/doc/ui/movetemplate.html.php +++ b/module/doc/ui/movetemplate.html.php @@ -14,6 +14,8 @@ namespace zin; modalHeader(set::title($lang->docTemplate->moveDocTemplate), set::entityText($doc->title), set::entityID($docID)); +$whiteListHidden = $doc->acl == 'private' ? '' : 'hidden'; + unset($modules[0]); formPanel ( @@ -55,7 +57,7 @@ formPanel empty($doc->parent) ? formGroup ( setID('whiteListBox'), - setClass($doc->acl == 'private' ? '' : 'hidden'), + setClass($whiteListHidden), set::label($lang->doc->whiteList), div ( From e41de3feaeab66b8497808d09f45ed68d3dd4a8c Mon Sep 17 00:00:00 2001 From: daitingting Date: Sun, 27 Apr 2025 06:16:35 +0000 Subject: [PATCH 417/655] * [task#141206,done,1h] Execution is multiple. --- module/execution/model.php | 18 +++++++++--------- module/task/model.php | 4 ++-- module/task/tao.php | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/module/execution/model.php b/module/execution/model.php index 623e070514..0dc85235f3 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -1872,18 +1872,18 @@ class executionModel extends model * 根据产品/执行等信息获取任务列表 * Get tasks by product/execution etc. * - * @param int $productID - * @param int $executionID - * @param array $executions - * @param string $browseType - * @param int $queryID - * @param int $moduleID - * @param string $sort - * @param object $pager + * @param int $productID + * @param int|array $executionID + * @param array $executions + * @param string $browseType + * @param int $queryID + * @param int $moduleID + * @param string $sort + * @param object $pager * @access public * @return array */ - public function getTasks(int $productID, int $executionID, array $executions, string $browseType, int $queryID, int $moduleID, string $sort, object $pager = null): array + public function getTasks(int $productID, int|array $executionID, array $executions, string $browseType, int $queryID, int $moduleID, string $sort, object $pager = null): array { if(common::isTutorialMode()) return $this->loadModel('tutorial')->getTasks(); diff --git a/module/task/model.php b/module/task/model.php index 1bee5f95b4..6475c859bd 100755 --- a/module/task/model.php +++ b/module/task/model.php @@ -1727,7 +1727,7 @@ class taskModel extends model * 获取执行下的任务列表信息。 * Get the task list under a execution. * - * @param int $executionID + * @param int|array $executionID * @param int $productID * @param string|array $type all|assignedbyme|myinvolved|undone|needconfirm|assignedtome|finishedbyme|delayed|review|wait|doing|done|pause|cancel|closed|array('wait','doing','done','pause','cancel','closed') * @param array $modules @@ -1736,7 +1736,7 @@ class taskModel extends model * @access public * @return array */ - public function getExecutionTasks(int $executionID, int $productID = 0, string|array $type = 'all', array $modules = array(), string $orderBy = 'status_asc, id_desc', object $pager = null): array + public function getExecutionTasks(int|array $executionID, int $productID = 0, string|array $type = 'all', array $modules = array(), string $orderBy = 'status_asc, id_desc', object $pager = null): array { $tasks = $this->taskTao->fetchExecutionTasks($executionID, $productID, $type, $modules, $orderBy, $pager); if(empty($tasks)) return array(); diff --git a/module/task/tao.php b/module/task/tao.php index f8e8e7681c..f6c85fb6b2 100644 --- a/module/task/tao.php +++ b/module/task/tao.php @@ -467,7 +467,7 @@ class taskTao extends taskModel * 获取执行下的任务。 * Fetch tasks under execution by executionID(Todo). * - * @param int $executionID + * @param int|array $executionID * @param int $productID * @param string|array $type all|assignedbyme|myinvolved|undone|needconfirm|assignedtome|finishedbyme|delayed|review|wait|doing|done|pause|cancel|closed|array('wait','doing','done','pause','cancel','closed') * @param array $modules @@ -476,7 +476,7 @@ class taskTao extends taskModel * @access protected * @return object[] */ - protected function fetchExecutionTasks(int $executionID, int $productID = 0, string|array $type = 'all', array $modules = array(), string $orderBy = 'status_asc, id_desc', object $pager = null): array + protected function fetchExecutionTasks(int|array $executionID, int $productID = 0, string|array $type = 'all', array $modules = array(), string $orderBy = 'status_asc, id_desc', object $pager = null): array { if(is_string($type)) $type = strtolower($type); $orderBy = str_replace('pri_', 'priOrder_', $orderBy); @@ -492,7 +492,7 @@ class taskTao extends taskModel ->leftJoin(TABLE_TASKTEAM)->alias('t3')->on('t3.task = t1.id') ->beginIF($productID)->leftJoin(TABLE_MODULE)->alias('t4')->on('t1.module = t4.id')->fi() ->beginIF($this->config->edition == 'max' or $this->config->edition == 'ipd')->leftJoin(TABLE_DESIGN)->alias('t5')->on('t1.design= t5.id')->fi() - ->where('t1.execution')->eq((int)$executionID) + ->where('t1.execution')->in($executionID) ->beginIF($type == 'myinvolved') ->andWhere("((t3.`account` = '{$this->app->user->account}') OR t1.`assignedTo` = '{$this->app->user->account}' OR t1.`finishedby` = '{$this->app->user->account}')") ->fi() From e05850aefd7c884c40b8fb121ad5b52cba69322b Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Sun, 27 Apr 2025 13:23:11 +0800 Subject: [PATCH 418/655] * [bug#62003] Add the priv of sortChapter. --- module/doc/ui/templatelist.html.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/doc/ui/templatelist.html.php b/module/doc/ui/templatelist.html.php index ea618af141..53210036dd 100644 --- a/module/doc/ui/templatelist.html.php +++ b/module/doc/ui/templatelist.html.php @@ -29,6 +29,7 @@ $privs['addChapter'] = hasPriv('doc', 'createTemplate'); $privs['editChapter'] = hasPriv('doc', 'editTemplate'); $privs['deleteChapter'] = hasPriv('doc', 'deleteTemplate'); $privs['sortDoc'] = hasPriv('doc', 'sortTemplate'); +$privs['sortChapter'] = hasPriv('doc', 'sortTemplate'); $privs['collect'] = 'no'; $filterTypes = $lang->docTemplate->filterTypes; From 222df1759b00f11a9b3fbf980cc2f4fd26f36a68 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Sun, 27 Apr 2025 13:30:35 +0800 Subject: [PATCH 419/655] * [bug#61999] Change the title of move sub template. --- module/doc/lang/de.php | 1 + module/doc/lang/en.php | 1 + module/doc/lang/fr.php | 1 + module/doc/lang/zh-cn.php | 1 + module/doc/ui/movetemplate.html.php | 2 +- 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 7d9a227ddc..d530341b8f 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -102,6 +102,7 @@ $lang->docTemplate->leaveEditingConfirm = 'The template is currently be $lang->docTemplate->searchScopePlaceholder = 'Search Scope'; $lang->docTemplate->searchTypePlaceholder = 'Search Type'; $lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->moveSubTemplate = 'Move Sub Template'; $lang->docTemplate->createTypeFirst = 'Please create a template type first.'; $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index 5af7929ca6..30c04e382a 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -102,6 +102,7 @@ $lang->docTemplate->leaveEditingConfirm = 'The template is currently be $lang->docTemplate->searchScopePlaceholder = 'Search Scope'; $lang->docTemplate->searchTypePlaceholder = 'Search Type'; $lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->moveSubTemplate = 'Move Sub Template'; $lang->docTemplate->createTypeFirst = 'Please create a template type first.'; $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index ac2aaf9583..933460e08a 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -102,6 +102,7 @@ $lang->docTemplate->leaveEditingConfirm = 'The template is currently be $lang->docTemplate->searchScopePlaceholder = 'Search Scope'; $lang->docTemplate->searchTypePlaceholder = 'Search Type'; $lang->docTemplate->moveDocTemplate = 'Move Template'; +$lang->docTemplate->moveSubTemplate = 'Move Sub Template'; $lang->docTemplate->createTypeFirst = 'Please create a template type first.'; $lang->docTemplate->editedList = 'Template editor'; $lang->docTemplate->content = 'Template Text'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 92ea659b8d..c3731b23b9 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -102,6 +102,7 @@ $lang->docTemplate->leaveEditingConfirm = '文档模板编辑中,确 $lang->docTemplate->searchScopePlaceholder = '搜索范围'; $lang->docTemplate->searchTypePlaceholder = '搜索类型'; $lang->docTemplate->moveDocTemplate = '移动文档模板'; +$lang->docTemplate->moveSubTemplate = '移动子文档模板'; $lang->docTemplate->createTypeFirst = '请先创建文档模板类型。'; $lang->docTemplate->editedList = '模板编辑者'; $lang->docTemplate->content = '模板内容'; diff --git a/module/doc/ui/movetemplate.html.php b/module/doc/ui/movetemplate.html.php index 84107e8d82..8042b0f7af 100644 --- a/module/doc/ui/movetemplate.html.php +++ b/module/doc/ui/movetemplate.html.php @@ -12,7 +12,7 @@ declare(strict_types=1); */ namespace zin; -modalHeader(set::title($lang->docTemplate->moveDocTemplate), set::entityText($doc->title), set::entityID($docID)); +modalHeader(set::title(empty($doc->parent) ? $lang->docTemplate->moveDocTemplate : $lang->docTemplate->moveSubTemplate), set::entityText($doc->title), set::entityID($docID)); $whiteListHidden = $doc->acl == 'private' ? '' : 'hidden'; From 7bd5cbac2bd4b2633f1c03ae73bba87f430ffe37 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Sun, 27 Apr 2025 15:16:09 +0800 Subject: [PATCH 420/655] * [bug#61909] Query all template in list. --- module/doc/control.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/module/doc/control.php b/module/doc/control.php index dddf115465..713a77fd18 100755 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -539,9 +539,7 @@ class doc extends control $libModules = $this->doc->getTemplateModules($libID); if($mode == 'create' && empty($libModules)) return $this->send(array('result' => 'success', 'load' => array('alert' => $this->lang->docTemplate->createTypeFirst))); - $this->app->loadClass('pager', true); - $pager = new pager($recTotal, $recPerPage, $pageID); - $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy, $pager); + $templateList = $this->doc->getDocTemplateList(0, $type, $orderBy); $templateList = $this->doc->filterDeletedDocs($templateList); $templateList = $this->doc->filterPrivDocs($templateList, 'template'); $allModules = $this->doc->getTemplateModules(); From 1ebc85940d36987d752bdd62748c2f3303c6844d Mon Sep 17 00:00:00 2001 From: liugang Date: Thu, 24 Apr 2025 17:04:22 +0800 Subject: [PATCH 421/655] * [refac] decode posted SQL. --- lib/pivotstate/pivotstate.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pivotstate/pivotstate.class.php b/lib/pivotstate/pivotstate.class.php index 67eb108b4b..fc636b1d9d 100644 --- a/lib/pivotstate/pivotstate.class.php +++ b/lib/pivotstate/pivotstate.class.php @@ -944,7 +944,8 @@ class pivotState $data = json_decode($post['data'], true); foreach($data as $key => $value) { - $this->$key = $value; + if(!empty($value['sql'])) $value['sql'] = base64_encode($value['sql']); + $this->$key = $key == 'sql' ? base64_decode($value) : $value; } $this->formatSettingColumns(); From e54505fb4a124e9d06b9afc82aa13eb8ced2916d Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Thu, 24 Apr 2025 17:28:36 +0800 Subject: [PATCH 422/655] * [misc] adjsut pipeline format. --- .gitfox/unittestcheck.yaml | 102 +++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/.gitfox/unittestcheck.yaml b/.gitfox/unittestcheck.yaml index afea8e8074..4427370dca 100644 --- a/.gitfox/unittestcheck.yaml +++ b/.gitfox/unittestcheck.yaml @@ -13,68 +13,90 @@ spec: spec: container: hub.zentao.net/ci/jq script: - - XUANVERSION=$(jq -r .pkg.xuanxuan.gitVersion < ci.json) - - ZENTAOEXT_GIT_REPO=$(jq -r .pkg.zentaoext.gitRepo < ci.json) - - DOWNGRADE_GIT_REPO=$(jq -r .pkg.downgrade.gitRepo < ci.json) - - DOWNGRADE_EXT_GIT_REPO=$(jq -r .pkg.downgradeExt.gitRepo < ci.json) - - echo "XUANVERSION=${XUANVERSION}" >> $GITFOX_CUSTOM_ENV - - echo "export ZENTAOEXT_GIT_REPO=${ZENTAOEXT_GIT_REPO}" >> $GITFOX_CUSTOM_ENV - - echo "export DOWNGRADE_GIT_REPO=${DOWNGRADE_GIT_REPO}" >> $GITFOX_CUSTOM_ENV - - echo "export DOWNGRADE_EXT_GIT_REPO=${DOWNGRADE_EXT_GIT_REPO}" >> $GITFOX_CUSTOM_ENV - - echo "export SRC_ZENTAOEXT_PATH=${GITFOX_WORKSPACE_BASE}/zentaoext" >> $GITFOX_CUSTOM_ENV - - echo "export XUANXUAN_SRC_PATH=${GITFOX_WORKSPACE_BASE}/xuansrc" >> $GITFOX_CUSTOM_ENV - - echo "export ZENTAO_RELEASE_PATH=${GITFOX_WORKSPACE_BASE}/release" >> $GITFOX_CUSTOM_ENV - - echo "export GITFOX_HOST=gitfox.zcorp.cc" >> $GITFOX_CUSTOM_ENV + - XUANVERSION=$(jq -r .pkg.xuanxuan.gitVersion < ci.json) + - ZENTAOEXT_GIT_REPO=$(jq -r .pkg.zentaoext.gitRepo < ci.json) + - DOWNGRADE_GIT_REPO=$(jq -r .pkg.downgrade.gitRepo < ci.json) + - DOWNGRADE_EXT_GIT_REPO=$(jq -r .pkg.downgradeExt.gitRepo < + ci.json) + - echo "XUANVERSION=${XUANVERSION}" >> $GITFOX_CUSTOM_ENV + - echo "export ZENTAOEXT_GIT_REPO=${ZENTAOEXT_GIT_REPO}" >> + $GITFOX_CUSTOM_ENV + - echo "export DOWNGRADE_GIT_REPO=${DOWNGRADE_GIT_REPO}" >> + $GITFOX_CUSTOM_ENV + - echo "export DOWNGRADE_EXT_GIT_REPO=${DOWNGRADE_EXT_GIT_REPO}" + >> $GITFOX_CUSTOM_ENV + - echo "export + SRC_ZENTAOEXT_PATH=${GITFOX_WORKSPACE_BASE}/zentaoext" >> + $GITFOX_CUSTOM_ENV + - echo "export + XUANXUAN_SRC_PATH=${GITFOX_WORKSPACE_BASE}/xuansrc" >> + $GITFOX_CUSTOM_ENV + - echo "export + ZENTAO_RELEASE_PATH=${GITFOX_WORKSPACE_BASE}/release" >> + $GITFOX_CUSTOM_ENV + - echo "export GITFOX_HOST=gitfox.zcorp.cc" >> $GITFOX_CUSTOM_ENV - name: 关联仓库克隆 type: run spec: container: hub.zentao.net/ci/git:2.45.2 script: - - git clone -q http://${GITFOX_SERVER}/git/xuan/xuanxuan.git xuansrc && cd xuansrc && git checkout $XUANVERSION && cd - - - git clone -q -b $GITFOX_BRANCH http://${GITFOX_SERVER}/git/${ZENTAOEXT_GIT_REPO}.git zentaoext - - git clone -b $GITFOX_BRANCH http://${GITFOX_SERVER}/git/zentao/zentaomax.git zentaomax - - git clone -b $GITFOX_BRANCH http://${GITFOX_SERVER}/git/zentao/zentaoipd.git zentaoipd + - git clone -q http://${GITFOX_SERVER}/git/xuan/xuanxuan.git + xuansrc && cd xuansrc && git checkout $XUANVERSION && cd - + - git clone -q -b $GITFOX_BRANCH + http://${GITFOX_SERVER}/git/${ZENTAOEXT_GIT_REPO}.git + zentaoext + - git clone -b $GITFOX_BRANCH + http://${GITFOX_SERVER}/git/zentao/zentaomax.git zentaomax + - git clone -b $GITFOX_BRANCH + http://${GITFOX_SERVER}/git/zentao/zentaoipd.git zentaoipd - name: 版本变量设定 type: run spec: container: hub.zentao.net/ci/jq script: - - PMS_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/VERSION) - - BIZ_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/BIZVERSION) - - MAX_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/MAXVERSION) - - IPD_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/IPDVERSION) - - echo "export PMS_VERSION=$PMS_VERSION" >> $GITFOX_CUSTOM_ENV - - echo "export BIZ_VERSION=$BIZ_VERSION" >> $GITFOX_CUSTOM_ENV - - echo "export MAX_VERSION=$MAX_VERSION" >> $GITFOX_CUSTOM_ENV - - echo "export IPD_VERSION=$IPD_VERSION" >> $GITFOX_CUSTOM_ENV + - PMS_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/VERSION) + - BIZ_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/BIZVERSION) + - MAX_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/MAXVERSION) + - IPD_VERSION=$(head -1 ${SRC_ZENTAOEXT_PATH}/IPDVERSION) + - echo "export PMS_VERSION=$PMS_VERSION" >> $GITFOX_CUSTOM_ENV + - echo "export BIZ_VERSION=$BIZ_VERSION" >> $GITFOX_CUSTOM_ENV + - echo "export MAX_VERSION=$MAX_VERSION" >> $GITFOX_CUSTOM_ENV + - echo "export IPD_VERSION=$IPD_VERSION" >> $GITFOX_CUSTOM_ENV - name: 源码构建 type: run spec: container: hub.zentao.net/ci/zentao-package:master script: - - mkdir -pv ${ZENTAO_RELEASE_PATH} - - test -d $PWD/zentaoext/zentaomax && rm -rf $PWD/zentaoext/zentaomax - - test -d $PWD/zentaoext/zentaoipd && rm -rf $PWD/zentaoext/zentaoipd - - mv $PWD/zentaomax $PWD/zentaoext/ - - mv $PWD/zentaoipd $PWD/zentaoext/ - - ls -l && make ciCommon - - cd $SRC_ZENTAOEXT_PATH && make build && cd ${GITFOX_WORKSPACE_BASE} - - ls -l $ZENTAO_RELEASE_PATH - - ls -l $ZENTAO_BUILD_PATH - - mv $ZENTAO_BUILD_PATH/zentaopms/* . + - mkdir -pv ${ZENTAO_RELEASE_PATH} + - test -d $PWD/zentaoext/zentaomax && rm -rf + $PWD/zentaoext/zentaomax + - test -d $PWD/zentaoext/zentaoipd && rm -rf + $PWD/zentaoext/zentaoipd + - mv $PWD/zentaomax $PWD/zentaoext/ + - mv $PWD/zentaoipd $PWD/zentaoext/ + - ls -l && make ciCommon + - cd $SRC_ZENTAOEXT_PATH && make build && cd + ${GITFOX_WORKSPACE_BASE} + - ls -l $ZENTAO_RELEASE_PATH + - ls -l $ZENTAO_BUILD_PATH + - mv $ZENTAO_BUILD_PATH/zentaopms/* . - name: 镜像构建 type: run spec: container: image: hub.zentao.net/ci/docker:24.0.8-cli script: - - | + - > docker buildx create \ --name=kube \ --driver=kubernetes \ --driver-opt=namespace=quickon-ci,replicas=5,nodeselector="node-role.kubernetes.io/ci=true",rootless=true,image=hub.zentao.net/ci/moby-buildkit:buildx-stable-1-rootless,qemu.install=true,qemu.image=hub.zentao.net/ci/binfmt:qemu-v8.1.5 - docker buildx use kube - - docker buildx build --pull --push --platform linux/amd64 --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true -t hub.qc.oop.cc/zentao-ztf:${GITFOX_BUILD_NUMBER}-${GITFOX_COMMIT} -f misc/ci/Dockerfile.test . + - docker buildx build --pull --push --platform linux/amd64 + --build-arg VERSION=${ZENTAO_VERSION} --build-arg MIRROR=true + -t + hub.qc.oop.cc/zentao-ztf:${GITFOX_BUILD_NUMBER}-${GITFOX_COMMIT} + -f misc/ci/Dockerfile.test . - name: unit test type: run when: | @@ -91,7 +113,9 @@ spec: - sleep 5 - s6-svwait -u -t 30000 /etc/s6/s6-available/mysql - initdb.php > /apps/zentao/unittestdb - - rununittestbycommitid.php zentaopms ${{ secrets.get("zentao_user") }} ${{ secrets.get("zentao_password") }} + - rununittestbycommitid.php zentaopms ${{ + secrets.get("zentao_user") }} ${{ secrets.get("zentao_password") + }} - name: 消息通知 type: plugin when: failure() @@ -103,9 +127,9 @@ spec: caller: zenci api: https://gw.easycorp.cn title: 单元测试 - content: "单元测试执行失败" + content: 单元测试执行失败 url: ${GITFOX_BUILD_LINK} users: - "0": "liyang" + "0": liyang "1": "{{.GITFOX_COMMIT_AUTHOR_NAME}}" name: gitfox-xuanim-plugin From 186eaa50bdf95ff988197786754ea10e00756ed2 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Thu, 24 Apr 2025 16:50:54 +0800 Subject: [PATCH 423/655] * [bug#61942,done,0.1h] testcase is not limited by CRProject and CRExecution. --- module/common/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/common/model.php b/module/common/model.php index 243139809e..f9044a9e65 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1937,7 +1937,7 @@ eof; } /* Check the project is closed. */ - $productModuleList = array('story', 'bug', 'testtask', 'release'); + $productModuleList = array('story', 'bug', 'testcase', 'case', 'testtask', 'release'); if(!in_array($module, $productModuleList) and !empty($object->project) and is_numeric($object->project) and empty($config->CRProject)) { if(!isset($projectsStatus[$object->project])) @@ -1949,7 +1949,7 @@ eof; } /* Check the execution is closed. */ - $productModuleList = array('story', 'bug', 'testtask'); + $productModuleList = array('story', 'bug', 'testcase', 'case', 'testtask'); if(!in_array($module, $productModuleList) and !empty($object->execution) and is_numeric($object->execution) and empty($config->CRExecution)) { if(!isset($executionsStatus[$object->execution])) From 6441a24038f11f9e8510d45eb2dcc1ee9270f110 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:24:13 +0800 Subject: [PATCH 424/655] +[task#142428,doing,0.1h,1.4h] Add ztf notes. --- .../project/test/ui/managemembersforlite.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 module/project/test/ui/managemembersforlite.php diff --git a/module/project/test/ui/managemembersforlite.php b/module/project/test/ui/managemembersforlite.php new file mode 100755 index 0000000000..52b92b9280 --- /dev/null +++ b/module/project/test/ui/managemembersforlite.php @@ -0,0 +1,20 @@ +#!/usr/bin/env php + Date: Thu, 24 Apr 2025 14:25:27 +0800 Subject: [PATCH 425/655] *[task#142428,doing,0.1h,1.3h] Add user zendata. --- .../project/test/ui/managemembersforlite.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/project/test/ui/managemembersforlite.php b/module/project/test/ui/managemembersforlite.php index 52b92b9280..368aace83c 100755 --- a/module/project/test/ui/managemembersforlite.php +++ b/module/project/test/ui/managemembersforlite.php @@ -18,3 +18,23 @@ cid=1 - 最终测试状态 @SUCCESS */ + +chdir(__DIR__); +include '../lib/managemembersforlite.ui.class.php'; +global $config; + +$user = zenData('user'); +$user->id->range('1-100'); +$user->dept->range('1{3}, 2{1}'); +$user->account->range('admin, user1, user2, user3'); +$user->realname->range('admin, 用户1, 用户2, 用户3'); +$user->password->range($config->uitest->defaultPassword)->format('md5'); +$user->gen(4); + +$team = zenData('team'); +$team->id->range('1'); +$team->root->range('1'); +$team->type->range('project'); +$team->account->range('admin'); +$team->days->range('7'); +$team->gen(1); From b63408e83aa66168410c3624137934a78b833f12 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:26:36 +0800 Subject: [PATCH 426/655] +[task#142428,doing,0.1h,1.3h] Add project zendata. --- .../project/test/ui/managemembersforlite.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/project/test/ui/managemembersforlite.php b/module/project/test/ui/managemembersforlite.php index 368aace83c..6d7a96f4c1 100755 --- a/module/project/test/ui/managemembersforlite.php +++ b/module/project/test/ui/managemembersforlite.php @@ -38,3 +38,23 @@ $team->type->range('project'); $team->account->range('admin'); $team->days->range('7'); $team->gen(1); + +$project = zenData('project'); +$project->id->range('1'); +$project->project->range('0'); +$project->model->range('kanban'); +$project->type->range('project'); +$project->parent->range('0'); +$project->auth->range('extend'); +$project->grade->range('1'); +$project->hasProduct->range('0'); +$project->name->range('运营项目1'); +$project->path->range('`,1,`'); +$project->vision->range('lite'); +$project->begin->range('(-2M)-(-M):1D')->type('timestamp')->format('YY/MM/DD'); +$project->end->range('(+2M)-(+3M):1D')->type('timestamp')->format('YY/MM/DD'); +$project->acl->range('open'); +$project->gen(1); + +$dept = zenData('dept'); +$dept->id->range('1-3'); From 863f1ba15b6ddab1037d8e9802f0f406bdaf07a2 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:28:15 +0800 Subject: [PATCH 427/655] +[task#142428,doing,0.5h,1.1h] Add test file of manage members for project in lite. --- .../project/test/ui/managemembersforlite.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/module/project/test/ui/managemembersforlite.php b/module/project/test/ui/managemembersforlite.php index 6d7a96f4c1..956484117f 100755 --- a/module/project/test/ui/managemembersforlite.php +++ b/module/project/test/ui/managemembersforlite.php @@ -58,3 +58,22 @@ $project->gen(1); $dept = zenData('dept'); $dept->id->range('1-3'); +$dept->name->range('部门1, 部门2, 部门1-1'); +$dept->parent->range('0, 0, 1'); +$dept->path->range('`,1,`, `,2,`, `,1,3,`'); +$dept->grade->range('1, 1, 2'); +$dept->gen(3); + +$tester = new manageMembersForLiteTester(); +$tester->login(); + +//设置敏捷项目执行数据 +$members = array( + array('account' => '用户1', 'role' => '开发人员'), +); + +r($tester->addMembers($members['0'])) && p('message,status') && e('项目团队成员添加成功,SUCCESS'); //添加项目团队成员 +r($tester->deleteMembers()) && p('message,status') && e('项目团队成员删除成功,SUCCESS'); //删除项目已有的团队成员 +r($tester->copyDeptMembers()) && p('message,status') && e('复制部门团队成员成功,SUCCESS'); //复制部门成员 + +$tester->closeBrowser(); From 58830ecaa8105e66daecab99f9fa065c37417510 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:29:10 +0800 Subject: [PATCH 428/655] +[task#142428,doing,0.2h,0.8h] Add addMembers function of manage members for project in lite. --- .../lib/managemembersforlite.ui.class.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 module/project/test/lib/managemembersforlite.ui.class.php diff --git a/module/project/test/lib/managemembersforlite.ui.class.php b/module/project/test/lib/managemembersforlite.ui.class.php new file mode 100644 index 0000000000..88f8eb9cb7 --- /dev/null +++ b/module/project/test/lib/managemembersforlite.ui.class.php @@ -0,0 +1,20 @@ +switchVision('lite'); + $form = $this->initForm('project', 'manageMembers', array('projectID' => '1'), 'appIframe-project'); + if(isset($members['account'])) $form->dom->account->picker($members['account']); + if(isset($members['role'])) $form->dom->role1->setValue($members['role']); + $form->wait(2); + + $form->dom->saveBtn->click(); From 16075e0f22a6d0cace5947957e069ff746c77cbd Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:29:56 +0800 Subject: [PATCH 429/655] +[task#142428,doing,0.2h,0.6h] Add deleteMembers function of manage members for project in lite. --- .../lib/managemembersforlite.ui.class.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/project/test/lib/managemembersforlite.ui.class.php b/module/project/test/lib/managemembersforlite.ui.class.php index 88f8eb9cb7..dce45b05fe 100644 --- a/module/project/test/lib/managemembersforlite.ui.class.php +++ b/module/project/test/lib/managemembersforlite.ui.class.php @@ -18,3 +18,23 @@ class manageMembersForLiteTester extends tester $form->wait(2); $form->dom->saveBtn->click(); + $form->wait(2); + + //断言检查团队成员列表页姓名、角色是否正确 + $teamPage = $this->loadPage('project', 'team'); + if($teamPage->dom->browseSecAccountLite->getText() != $members['account']) return $this->failed('姓名错误'); + if($teamPage->dom->browseSecRoleLite->getText() != $members['role']) return $this->failed('角色错误'); + + return $this->success('项目团队成员添加成功'); + } + + /** + * 删除项目团队成员。 + * Check delete members. + * + * @access public + */ + public function deleteMembers() + { + $browseForm = $this->initForm('project', 'team', array('projectID' => '1'), 'appIframe-project'); + $browseFirAccount1 = $browseForm->dom->browseFirAccount->getText(); From 32b4583306154e73b605ac0a2c8b573d7da007d1 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:30:27 +0800 Subject: [PATCH 430/655] +[task#142428,doing,0.2h,0.4h] Add copyDeptMembers function of manage members for project in lite. --- .../lib/managemembersforlite.ui.class.php | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/module/project/test/lib/managemembersforlite.ui.class.php b/module/project/test/lib/managemembersforlite.ui.class.php index dce45b05fe..f11168f9f9 100644 --- a/module/project/test/lib/managemembersforlite.ui.class.php +++ b/module/project/test/lib/managemembersforlite.ui.class.php @@ -38,3 +38,23 @@ class manageMembersForLiteTester extends tester { $browseForm = $this->initForm('project', 'team', array('projectID' => '1'), 'appIframe-project'); $browseFirAccount1 = $browseForm->dom->browseFirAccount->getText(); + $browseForm->dom->teamBtn->click(); + $form = $this->initForm('project', 'manageMembers', array('projectID' => '1'), 'appIframe-project'); + $form->dom->firstDeleteBtn->click(); + $form->wait(2); + $form->dom->saveBtn->click(); + $form->wait(2); + //添加断言,判断是否删除成功 + if($browseForm->dom->browseFirAccount->getText() == $browseFirAccount1) return $this->failed('项目团队成员删除失败'); + return $this->success('项目团队成员删除成功'); + } + + /** + * 复制部门团队成员。 + * Copy team members. + * + * @access public + */ + public function copyDeptMembers() + { + $form = $this->initForm('project', 'team', array('projectID' => '1'), 'appIframe-project'); From 40bb3e80bcf50318dad5ee503cbf2938f4aa1cab Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:30:40 +0800 Subject: [PATCH 431/655] +[task#142428,doing,0.2h,0.2h] Add copyDeptMembers function of manage members for project in lite. --- .../test/lib/managemembersforlite.ui.class.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/module/project/test/lib/managemembersforlite.ui.class.php b/module/project/test/lib/managemembersforlite.ui.class.php index f11168f9f9..da4478225e 100644 --- a/module/project/test/lib/managemembersforlite.ui.class.php +++ b/module/project/test/lib/managemembersforlite.ui.class.php @@ -58,3 +58,16 @@ class manageMembersForLiteTester extends tester public function copyDeptMembers() { $form = $this->initForm('project', 'team', array('projectID' => '1'), 'appIframe-project'); + $form->dom->teamBtn->click(); + $form = $this->loadPage('project', 'manageMembers'); + $form->dom->dept->picker('部门1'); + $form->wait(2); + $form->dom->saveBtn->click(); + $form->wait(2); + + //添加断言,根据保存后的成员数量,判断是否复制团队成员成功 + $form = $this->loadPage('project', 'team'); + if($form->dom->amount->getText() != '3') return $this->failed('复制部门团队成员失败'); + return $this->success('复制部门团队成员成功'); + } +} From 7e0babb575f1b403028be912b78c0d975335adaf Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:31:29 +0800 Subject: [PATCH 432/655] *[task#142428,doing,0.1h,0.1h] Add xpath of element. --- module/project/test/ui/page/managemembers.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/project/test/ui/page/managemembers.php b/module/project/test/ui/page/managemembers.php index 6f0843253e..caa7d70411 100644 --- a/module/project/test/ui/page/managemembers.php +++ b/module/project/test/ui/page/managemembers.php @@ -7,6 +7,8 @@ class manageMembersPage extends page $xpath = array( 'account' => "//*[@id='account1']/div/span[1]", 'firstDeleteBtn' => "//*[@id='teamForm']/table/tbody/tr[1]/td[6]/div/button[2]/i", + /* 运营界面 */ + 'saveBtn' => "//*[@id='teamForm']/div/div/button[1]", ); $this->dom->xpath = array_merge($this->dom->xpath, $xpath); } From ba519869503f05dbb25af71f8712ebc83d781907 Mon Sep 17 00:00:00 2001 From: lihuifang Date: Thu, 24 Apr 2025 14:32:05 +0800 Subject: [PATCH 433/655] *[task#142428,done,0.1h,0h] Add xpath of element. --- module/project/test/ui/page/team.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/module/project/test/ui/page/team.php b/module/project/test/ui/page/team.php index 3147c417be..7c1d6f20a4 100644 --- a/module/project/test/ui/page/team.php +++ b/module/project/test/ui/page/team.php @@ -15,6 +15,10 @@ class teamPage extends page 'teamBtn' => "//*[@id='actionBar']/a/span", 'confirmBtn' => "//*[@class='modal-footer']/nav/button[1]/span", 'unlinkBtn' => "//*[@id='table-project-team']/div[2]/div[2]/div/div/div/nav/a/i", + /* 运营界面元素 */ + 'browseFirAccountLite' => "//*[@id='table-project-team']/div[2]/div[1]/div/div[1]/div/a", + 'browseSecAccountLite' => "//*[@id='table-project-team']/div[2]/div[1]/div/div[3]/div/a", + 'browseSecRoleLite' => "//*[@id='table-project-team']/div[2]/div[1]/div/div[4]/div", ); $this->dom->xpath = array_merge($this->dom->xpath, $xpath); } From 11f1b7efff1649e6a83ab0c8ec20a820ca78a55c Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 25 Apr 2025 10:26:06 +0800 Subject: [PATCH 434/655] * [misc] supports show sql explain in zmonitor page. --- www/dev.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/www/dev.php b/www/dev.php index 8ddc87ad5c..b5cc968ee6 100644 --- a/www/dev.php +++ b/www/dev.php @@ -173,6 +173,7 @@ function initTable(data) if(timeClass === 'warning') return `WARN: > 200ms`; }}, {name: 'metrics.backend.sqlCount', title: 'SQLs', sort: 'number', width: 48, link: '#', hint: 'Click to check details', headerGroup: 'Backend', align: 'center'}, + {name: 'metrics.backend.sqlDetails.Explain', title: 'Explain', sort: 'number', width: 48, link: '#', hint: 'Click to check explain details', headerGroup: 'Backend', align: 'center'}, {name: 'request.errorCount', title: 'Errors', sort: 'number', width: 48, link: '#', hint: 'Click to check details', headerGroup: 'Backend', align: 'center'}, {name: 'metrics.backend.requestMemory', title: 'Memory', sort: 'number', format: (value) => value ? zui.formatBytes(value) : '', headerGroup: 'Backend', align: 'right'}, {name: 'metrics.backend.phpFileLoaded', title: 'PHP Files', width: 50, sort: 'number', align: 'center', headerGroup: 'Backend'}, @@ -240,7 +241,7 @@ function initTable(data) mono: false, error: [ '', - '', + '', '', '', '', @@ -288,9 +289,10 @@ function initData(data) metricsStats.warning = 0; data.forEach(row => { - row.path = `${row.request.module}-${row.request.method}`; - row['metrics.backend.totalTime'] = row.metrics.backend.totalTime; - row['metrics.backend.sqlCount'] = row.metrics.backend.sqlCount; + row.path = `${row.request.module}-${row.request.method}`; + row['metrics.backend.totalTime'] = row.metrics.backend.totalTime; + row['metrics.backend.sqlCount'] = row.metrics.backend.sqlCount; + row['metrics.backend.sqlDetails.Explain'] = row.metrics.backend.sqlDetails.filter(x => x.Explain && x.Explain.length).length; row['metrics.backend.sqlTime'] = row.metrics.backend.sqlTime * ((!row.dataVer || row.dataVer < 2) ? 1000 : 1); row['metrics.backend.requestMemory'] = row.metrics.backend.requestMemory * 1024; row['metrics.backend.phpFileLoaded'] = row.metrics.backend.phpFileLoaded; From 7489ba02c2628f0461d9ccf1ac2579a0d4b3e4d5 Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 25 Apr 2025 10:26:59 +0800 Subject: [PATCH 435/655] * [misc] show sql explain detail on click cell. --- www/dev.php | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/www/dev.php b/www/dev.php index b5cc968ee6..44ab12e996 100644 --- a/www/dev.php +++ b/www/dev.php @@ -277,6 +277,55 @@ function initTable(data) }); return; } + if (info.colName === 'metrics.backend.sqlDetails.Explain') + { + const explains = data.metrics.backend.sqlDetails.filter(x => x.Explain && x.Explain.length); + zui.Modal.showError({ + title: `Explain Details (${explains.length})`, + html: true, + size: 'lg', + mono: false, + error: [ + '
IDDuration (ms)
', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + explains.map((profile => [ + '', + ``, + '', + profile.Explain.map(explain => [ + '', + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + '', + ].join('\n')).join('\n'), + ].join('\n'))).join('\n'), + '', + '
idExtraKeyKey LenPossible KeysRefRowsSelect TypeTableType
#${profile.Query_ID} ${profile.Query} (${profile.Duration}ms)
${explain.id}${explain.Extra}${explain.key}${explain.key_len}${explain.possible_keys}${explain.ref}${explain.rows}${explain.select_type}${explain.table}${explain.type}
' + ].join('\n'), + }); + } console.log('> clicked', data); } }); From 56c45781f3a4c469a93f5709a2c7fc8677a419cf Mon Sep 17 00:00:00 2001 From: sunhao Date: Fri, 25 Apr 2025 10:29:08 +0800 Subject: [PATCH 436/655] * [misc] update zui3 lib. --- www/js/zui3/zui.zentao.css | 4 ++-- www/js/zui3/zui.zentao.js | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/www/js/zui3/zui.zentao.css b/www/js/zui3/zui.zentao.css index 6974b435d8..29f542ac85 100644 --- a/www/js/zui3/zui.zentao.css +++ b/www/js/zui3/zui.zentao.css @@ -1,2 +1,2 @@ -/*! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border-color:rgb(var(--color-gray-200-rgb));border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:-apple-system,Noto Sans,Helvetica Neue,Helvetica,Nimbus Sans L,Arial,Liberation Sans,PingFang SC,Hiragino Sans GB,Noto Sans CJK SC,Source Han Sans SC,Source Han Sans CN,Microsoft YaHei,Wenquanyi Micro Hei,WenQuanYi Zen Hei,ST Heiti,SimHei,WenQuanYi Zen Hei Sharp,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:rgb(var(--color-gray-400-rgb));opacity:1}input::placeholder,textarea::placeholder{color:rgb(var(--color-gray-400-rgb));opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}:root{--screen-2xl:1720px;--color-gray-50:#fcfdfe;--color-gray-100:#eff1f3;--color-gray-200:#ebedf3;--color-gray-300:#d2d6e5;--color-gray-400:#b2b9c5;--color-gray-500:#64758b;--color-gray-600:#4a577f;--color-gray-700:#3d4667;--color-gray-800:#353d57;--color-gray-900:#30394a;--color-gray-950:#0b0f18;--color-gray-50-rgb:252,253,254;--color-gray-100-rgb:239,241,243;--color-gray-200-rgb:235,237,243;--color-gray-300-rgb:210,214,229;--color-gray-400-rgb:178,185,197;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:74,87,127;--color-gray-700-rgb:61,70,103;--color-gray-800-rgb:53,61,87;--color-gray-900-rgb:48,57,74;--color-gray-950-rgb:11,15,24;--color-primary-50:#eef6ff;--color-primary-100:#d9eaff;--color-primary-200:#bcdcff;--color-primary-300:#8ec6ff;--color-primary-400:#59a5ff;--color-primary-500:#3883fa;--color-primary-600:#2b67e5;--color-primary-700:#144ce1;--color-primary-800:#173db6;--color-primary-900:#19388f;--color-primary-950:#142457;--color-primary-50-rgb:238,246,255;--color-primary-100-rgb:217,234,255;--color-primary-200-rgb:188,220,255;--color-primary-300-rgb:142,198,255;--color-primary-400-rgb:89,165,255;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:43,103,229;--color-primary-700-rgb:20,76,225;--color-primary-800-rgb:23,61,182;--color-primary-900-rgb:25,56,143;--color-primary-950-rgb:20,36,87;--color-secondary-50:#e7f6ff;--color-secondary-100:#cdecff;--color-secondary-200:#9bd9ff;--color-secondary-300:#77cbff;--color-secondary-400:#60c2ff;--color-secondary-500:#37b2fe;--color-secondary-600:#18a6fd;--color-secondary-700:#1099ed;--color-secondary-800:#078ada;--color-secondary-900:#046bab;--color-secondary-950:#062a4b;--color-secondary-50-rgb:231,246,255;--color-secondary-100-rgb:205,236,255;--color-secondary-200-rgb:155,217,255;--color-secondary-300-rgb:119,203,255;--color-secondary-400-rgb:96,194,255;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:24,166,253;--color-secondary-700-rgb:16,153,237;--color-secondary-800-rgb:7,138,218;--color-secondary-900-rgb:4,107,171;--color-secondary-950-rgb:6,42,75;--color-success-50:#effaf6;--color-success-100:#d6f2e7;--color-success-200:#ade5ce;--color-success-300:#83d7b6;--color-success-400:#5aca9d;--color-success-500:#31bd85;--color-success-600:#2ba675;--color-success-700:#28996c;--color-success-800:#21805a;--color-success-900:#185e3b;--color-success-950:#0e3421;--color-success-50-rgb:239,250,246;--color-success-100-rgb:214,242,231;--color-success-200-rgb:173,229,206;--color-success-300-rgb:131,215,182;--color-success-400-rgb:90,202,157;--color-success-500-rgb:49,189,133;--color-success-600-rgb:43,166,117;--color-success-700-rgb:40,153,108;--color-success-800-rgb:33,128,90;--color-success-900-rgb:24,94,59;--color-success-950-rgb:14,52,33;--color-warning-50:#fff4ea;--color-warning-100:#ffecdb;--color-warning-200:#ffd2a9;--color-warning-300:#ffbc7e;--color-warning-400:#ffaf65;--color-warning-500:#ff9f46;--color-warning-600:#f38f19;--color-warning-700:#ed8307;--color-warning-800:#d17100;--color-warning-900:#af5f01;--color-warning-950:#441506;--color-warning-50-rgb:255,244,234;--color-warning-100-rgb:255,236,219;--color-warning-200-rgb:255,210,169;--color-warning-300-rgb:255,188,126;--color-warning-400-rgb:255,175,101;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:243,143,25;--color-warning-700-rgb:237,131,7;--color-warning-800-rgb:209,113,0;--color-warning-900-rgb:175,95,1;--color-warning-950-rgb:68,21,6;--color-danger-50:#ffebeb;--color-danger-100:#ffd5d5;--color-danger-200:#ffb1b1;--color-danger-300:#ff9292;--color-danger-400:#ff7c7c;--color-danger-500:#fc5959;--color-danger-600:#fb2b2b;--color-danger-700:#d91b1b;--color-danger-800:#ba1313;--color-danger-900:#a20606;--color-danger-950:#470808;--color-danger-50-rgb:255,235,235;--color-danger-100-rgb:255,213,213;--color-danger-200-rgb:255,177,177;--color-danger-300-rgb:255,146,146;--color-danger-400-rgb:255,124,124;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:251,43,43;--color-danger-700-rgb:217,27,27;--color-danger-800-rgb:186,19,19;--color-danger-900-rgb:162,6,6;--color-danger-950-rgb:71,8,8;--color-important-50:#fff8f5;--color-important-100:#ffe2d9;--color-important-200:#ffcebf;--color-important-300:#ffb29b;--color-important-400:#ff8c68;--color-important-500:#ff8058;--color-important-600:#ff6f42;--color-important-700:#ff4912;--color-important-800:#c83509;--color-important-900:#611700;--color-important-950:#440609;--color-important-50-rgb:255,248,245;--color-important-100-rgb:255,226,217;--color-important-200-rgb:255,206,191;--color-important-300-rgb:255,178,155;--color-important-400-rgb:255,140,104;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,111,66;--color-important-700-rgb:255,73,18;--color-important-800-rgb:200,53,9;--color-important-900-rgb:97,23,0;--color-important-950-rgb:68,6,9;--color-special-50:#efecfa;--color-special-100:#e4dff7;--color-special-200:#c4b6ff;--color-special-300:#a38cff;--color-special-400:#8a6ff5;--color-special-500:#8166ee;--color-special-600:#7055df;--color-special-700:#513baa;--color-special-800:#452da5;--color-special-900:#30216e;--color-special-950:#271560;--color-special-50-rgb:239,236,250;--color-special-100-rgb:228,223,247;--color-special-200-rgb:196,182,255;--color-special-300-rgb:163,140,255;--color-special-400-rgb:138,111,245;--color-special-500-rgb:129,102,238;--color-special-600-rgb:112,85,223;--color-special-700-rgb:81,59,170;--color-special-800-rgb:69,45,165;--color-special-900-rgb:48,33,110;--color-special-950-rgb:39,21,96;--color-inherit:inherit;--color-transparent:transparent;--color-current:currentColor;--color-black:#000;--color-white:#fff;--color-canvas:#fff;--color-canvas-light:#fff;--color-canvas-dark:#fcfdfe;--color-inverse:#000;--color-surface:#eff1f3;--color-surface-light:#fcfdfe;--color-surface-strong:#ebedf3;--color-fore:#30394a;--color-fore-in-light:#30394a;--color-fore-in-dark:#fff;--color-focus:#bcdcff;--color-link:#2b47a2;--color-link-hover:#144ce1;--color-link-visited:#6328a4;--color-link-active:#144ce1;--color-placeholder:#64758b;--color-border:#ebedf3;--color-border-strong:#d2d6e5;--color-border-light:#eff1f3;--color-black-rgb:0,0,0;--color-white-rgb:255,255,255;--color-canvas-rgb:255,255,255;--color-canvas-light-rgb:255,255,255;--color-canvas-dark-rgb:252,253,254;--color-inverse-rgb:0,0,0;--color-surface-rgb:239,241,243;--color-surface-light-rgb:252,253,254;--color-surface-strong-rgb:235,237,243;--color-fore-rgb:48,57,74;--color-fore-in-light-rgb:48,57,74;--color-fore-in-dark-rgb:255,255,255;--color-focus-rgb:188,220,255;--color-link-rgb:43,71,162;--color-link-hover-rgb:20,76,225;--color-link-visited-rgb:99,40,164;--color-link-active-rgb:20,76,225;--color-placeholder-rgb:100,117,139;--color-border-rgb:235,237,243;--color-border-strong-rgb:210,214,229;--color-border-light-rgb:239,241,243;--radius-none:0px;--radius-sm:0.0625rem;--radius:0.125rem;--radius-md:0.25rem;--radius-lg:0.375rem;--radius-xl:0.5rem;--radius-2xl:0.75rem;--radius-3xl:1rem;--radius-full:9999px;--shadow-sm:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--shadow-md:0 2px 6px -1px rgba(0,0,0,.2),0 1px 4px -2px rgba(0,0,0,.15);--shadow-lg:0 5px 15px -3px rgba(0,0,0,.2),0 2px 6px -4px rgba(0,0,0,.15);--shadow-xl:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--shadow-2xl:0 10px 50px -10px rgba(0,0,0,.4),0 8px 20px -10px rgba(0,0,0,.3);--shadow-inner:inset 0 2px 4px 0 rgba(0,0,0,.05);--shadow-none:none;--space:0.25rem;--font-size-article:0.875rem;--font-size-root:16px;--font-size-page-lineHeight:1.5384615385}.dark{--color-gray-50:#0b0f18;--color-gray-100:#30394a;--color-gray-200:#353d57;--color-gray-300:#3d4667;--color-gray-400:#4a577f;--color-gray-500:#64758b;--color-gray-600:#b2b9c5;--color-gray-700:#d2d6e5;--color-gray-800:#ebedf3;--color-gray-900:#eff1f3;--color-gray-950:#fcfdfe;--color-gray-50-rgb:11,15,24;--color-gray-100-rgb:48,57,74;--color-gray-200-rgb:53,61,87;--color-gray-300-rgb:61,70,103;--color-gray-400-rgb:74,87,127;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:178,185,197;--color-gray-700-rgb:210,214,229;--color-gray-800-rgb:235,237,243;--color-gray-900-rgb:239,241,243;--color-gray-950-rgb:252,253,254;--color-primary-50:#142457;--color-primary-100:#19388f;--color-primary-200:#173db6;--color-primary-300:#144ce1;--color-primary-400:#2b67e5;--color-primary-500:#3883fa;--color-primary-600:#59a5ff;--color-primary-700:#8ec6ff;--color-primary-800:#bcdcff;--color-primary-900:#d9eaff;--color-primary-950:#eef6ff;--color-primary-50-rgb:20,36,87;--color-primary-100-rgb:25,56,143;--color-primary-200-rgb:23,61,182;--color-primary-300-rgb:20,76,225;--color-primary-400-rgb:43,103,229;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:89,165,255;--color-primary-700-rgb:142,198,255;--color-primary-800-rgb:188,220,255;--color-primary-900-rgb:217,234,255;--color-primary-950-rgb:238,246,255;--color-secondary-50:#062a4b;--color-secondary-100:#046bab;--color-secondary-200:#078ada;--color-secondary-300:#1099ed;--color-secondary-400:#18a6fd;--color-secondary-500:#37b2fe;--color-secondary-600:#60c2ff;--color-secondary-700:#77cbff;--color-secondary-800:#9bd9ff;--color-secondary-900:#cdecff;--color-secondary-950:#e7f6ff;--color-secondary-50-rgb:6,42,75;--color-secondary-100-rgb:4,107,171;--color-secondary-200-rgb:7,138,218;--color-secondary-300-rgb:16,153,237;--color-secondary-400-rgb:24,166,253;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:96,194,255;--color-secondary-700-rgb:119,203,255;--color-secondary-800-rgb:155,217,255;--color-secondary-900-rgb:205,236,255;--color-secondary-950-rgb:231,246,255;--color-success-50:#0e3421;--color-success-100:#185e3b;--color-success-200:#21805a;--color-success-300:#28996c;--color-success-400:#2ba675;--color-success-500:#31bd85;--color-success-600:#5aca9d;--color-success-700:#83d7b6;--color-success-800:#ade5ce;--color-success-900:#d6f2e7;--color-success-950:#effaf6;--color-success-50-rgb:14,52,33;--color-success-100-rgb:24,94,59;--color-success-200-rgb:33,128,90;--color-success-300-rgb:40,153,108;--color-success-400-rgb:43,166,117;--color-success-500-rgb:49,189,133;--color-success-600-rgb:90,202,157;--color-success-700-rgb:131,215,182;--color-success-800-rgb:173,229,206;--color-success-900-rgb:214,242,231;--color-success-950-rgb:239,250,246;--color-warning-50:#441506;--color-warning-100:#af5f01;--color-warning-200:#d17100;--color-warning-300:#ed8307;--color-warning-400:#f38f19;--color-warning-500:#ff9f46;--color-warning-600:#ffaf65;--color-warning-700:#ffbc7e;--color-warning-800:#ffd2a9;--color-warning-900:#ffecdb;--color-warning-950:#fff4ea;--color-warning-50-rgb:68,21,6;--color-warning-100-rgb:175,95,1;--color-warning-200-rgb:209,113,0;--color-warning-300-rgb:237,131,7;--color-warning-400-rgb:243,143,25;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:255,175,101;--color-warning-700-rgb:255,188,126;--color-warning-800-rgb:255,210,169;--color-warning-900-rgb:255,236,219;--color-warning-950-rgb:255,244,234;--color-danger-50:#470808;--color-danger-100:#a20606;--color-danger-200:#ba1313;--color-danger-300:#d91b1b;--color-danger-400:#fb2b2b;--color-danger-500:#fc5959;--color-danger-600:#ff7c7c;--color-danger-700:#ff9292;--color-danger-800:#ffb1b1;--color-danger-900:#ffd5d5;--color-danger-950:#ffebeb;--color-danger-50-rgb:71,8,8;--color-danger-100-rgb:162,6,6;--color-danger-200-rgb:186,19,19;--color-danger-300-rgb:217,27,27;--color-danger-400-rgb:251,43,43;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:255,124,124;--color-danger-700-rgb:255,146,146;--color-danger-800-rgb:255,177,177;--color-danger-900-rgb:255,213,213;--color-danger-950-rgb:255,235,235;--color-important-50:#440609;--color-important-100:#611700;--color-important-200:#c83509;--color-important-300:#ff4912;--color-important-400:#ff6f42;--color-important-500:#ff8058;--color-important-600:#ff8c68;--color-important-700:#ffb29b;--color-important-800:#ffcebf;--color-important-900:#ffe2d9;--color-important-950:#fff8f5;--color-important-50-rgb:68,6,9;--color-important-100-rgb:97,23,0;--color-important-200-rgb:200,53,9;--color-important-300-rgb:255,73,18;--color-important-400-rgb:255,111,66;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,140,104;--color-important-700-rgb:255,178,155;--color-important-800-rgb:255,206,191;--color-important-900-rgb:255,226,217;--color-important-950-rgb:255,248,245;--color-special-50:#271560;--color-special-100:#30216e;--color-special-200:#452da5;--color-special-300:#513baa;--color-special-400:#7055df;--color-special-500:#8166ee;--color-special-600:#8a6ff5;--color-special-700:#a38cff;--color-special-800:#c4b6ff;--color-special-900:#e4dff7;--color-special-950:#efecfa;--color-special-50-rgb:39,21,96;--color-special-100-rgb:48,33,110;--color-special-200-rgb:69,45,165;--color-special-300-rgb:81,59,170;--color-special-400-rgb:112,85,223;--color-special-500-rgb:129,102,238;--color-special-600-rgb:138,111,245;--color-special-700-rgb:163,140,255;--color-special-800-rgb:196,182,255;--color-special-900-rgb:228,223,247;--color-special-950-rgb:239,236,250;--color-canvas:#0b0f18;--color-inverse:#fff;--color-surface:#353d57;--color-surface-light:#30394a;--color-surface-strong:#3d4667;--color-fore:#ebedf3;--color-focus:#173db6;--color-link:#59a5ff;--color-link-hover:#3883fa;--color-link-visited:#bcdcff;--color-link-active:#bcdcff;--color-placeholder:#4a577f;--color-border:#353d57;--color-border-strong:#3d4667;--color-border-light:#30394a;--color-canvas-rgb:11,15,24;--color-inverse-rgb:255,255,255;--color-surface-rgb:53,61,87;--color-surface-light-rgb:48,57,74;--color-surface-strong-rgb:61,70,103;--color-fore-rgb:235,237,243;--color-focus-rgb:23,61,182;--color-link-rgb:89,165,255;--color-link-hover-rgb:56,131,250;--color-link-visited-rgb:188,220,255;--color-link-active-rgb:188,220,255;--color-placeholder-rgb:74,87,127;--color-border-rgb:53,61,87;--color-border-strong-rgb:61,70,103;--color-border-light-rgb:48,57,74}.light-in-dark{--color-gray-50:#fcfdfe;--color-gray-100:#eff1f3;--color-gray-200:#ebedf3;--color-gray-300:#d2d6e5;--color-gray-400:#b2b9c5;--color-gray-500:#64758b;--color-gray-600:#4a577f;--color-gray-700:#3d4667;--color-gray-800:#353d57;--color-gray-900:#30394a;--color-gray-950:#0b0f18;--color-gray-50-rgb:252,253,254;--color-gray-100-rgb:239,241,243;--color-gray-200-rgb:235,237,243;--color-gray-300-rgb:210,214,229;--color-gray-400-rgb:178,185,197;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:74,87,127;--color-gray-700-rgb:61,70,103;--color-gray-800-rgb:53,61,87;--color-gray-900-rgb:48,57,74;--color-gray-950-rgb:11,15,24;--color-primary-50:#eef6ff;--color-primary-100:#d9eaff;--color-primary-200:#bcdcff;--color-primary-300:#8ec6ff;--color-primary-400:#59a5ff;--color-primary-500:#3883fa;--color-primary-600:#2b67e5;--color-primary-700:#144ce1;--color-primary-800:#173db6;--color-primary-900:#19388f;--color-primary-950:#142457;--color-primary-50-rgb:238,246,255;--color-primary-100-rgb:217,234,255;--color-primary-200-rgb:188,220,255;--color-primary-300-rgb:142,198,255;--color-primary-400-rgb:89,165,255;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:43,103,229;--color-primary-700-rgb:20,76,225;--color-primary-800-rgb:23,61,182;--color-primary-900-rgb:25,56,143;--color-primary-950-rgb:20,36,87;--color-secondary-50:#e7f6ff;--color-secondary-100:#cdecff;--color-secondary-200:#9bd9ff;--color-secondary-300:#77cbff;--color-secondary-400:#60c2ff;--color-secondary-500:#37b2fe;--color-secondary-600:#18a6fd;--color-secondary-700:#1099ed;--color-secondary-800:#078ada;--color-secondary-900:#046bab;--color-secondary-950:#062a4b;--color-secondary-50-rgb:231,246,255;--color-secondary-100-rgb:205,236,255;--color-secondary-200-rgb:155,217,255;--color-secondary-300-rgb:119,203,255;--color-secondary-400-rgb:96,194,255;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:24,166,253;--color-secondary-700-rgb:16,153,237;--color-secondary-800-rgb:7,138,218;--color-secondary-900-rgb:4,107,171;--color-secondary-950-rgb:6,42,75;--color-success-50:#effaf6;--color-success-100:#d6f2e7;--color-success-200:#ade5ce;--color-success-300:#83d7b6;--color-success-400:#5aca9d;--color-success-500:#31bd85;--color-success-600:#2ba675;--color-success-700:#28996c;--color-success-800:#21805a;--color-success-900:#185e3b;--color-success-950:#0e3421;--color-success-50-rgb:239,250,246;--color-success-100-rgb:214,242,231;--color-success-200-rgb:173,229,206;--color-success-300-rgb:131,215,182;--color-success-400-rgb:90,202,157;--color-success-500-rgb:49,189,133;--color-success-600-rgb:43,166,117;--color-success-700-rgb:40,153,108;--color-success-800-rgb:33,128,90;--color-success-900-rgb:24,94,59;--color-success-950-rgb:14,52,33;--color-warning-50:#fff4ea;--color-warning-100:#ffecdb;--color-warning-200:#ffd2a9;--color-warning-300:#ffbc7e;--color-warning-400:#ffaf65;--color-warning-500:#ff9f46;--color-warning-600:#f38f19;--color-warning-700:#ed8307;--color-warning-800:#d17100;--color-warning-900:#af5f01;--color-warning-950:#441506;--color-warning-50-rgb:255,244,234;--color-warning-100-rgb:255,236,219;--color-warning-200-rgb:255,210,169;--color-warning-300-rgb:255,188,126;--color-warning-400-rgb:255,175,101;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:243,143,25;--color-warning-700-rgb:237,131,7;--color-warning-800-rgb:209,113,0;--color-warning-900-rgb:175,95,1;--color-warning-950-rgb:68,21,6;--color-danger-50:#ffebeb;--color-danger-100:#ffd5d5;--color-danger-200:#ffb1b1;--color-danger-300:#ff9292;--color-danger-400:#ff7c7c;--color-danger-500:#fc5959;--color-danger-600:#fb2b2b;--color-danger-700:#d91b1b;--color-danger-800:#ba1313;--color-danger-900:#a20606;--color-danger-950:#470808;--color-danger-50-rgb:255,235,235;--color-danger-100-rgb:255,213,213;--color-danger-200-rgb:255,177,177;--color-danger-300-rgb:255,146,146;--color-danger-400-rgb:255,124,124;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:251,43,43;--color-danger-700-rgb:217,27,27;--color-danger-800-rgb:186,19,19;--color-danger-900-rgb:162,6,6;--color-danger-950-rgb:71,8,8;--color-important-50:#fff8f5;--color-important-100:#ffe2d9;--color-important-200:#ffcebf;--color-important-300:#ffb29b;--color-important-400:#ff8c68;--color-important-500:#ff8058;--color-important-600:#ff6f42;--color-important-700:#ff4912;--color-important-800:#c83509;--color-important-900:#611700;--color-important-950:#440609;--color-important-50-rgb:255,248,245;--color-important-100-rgb:255,226,217;--color-important-200-rgb:255,206,191;--color-important-300-rgb:255,178,155;--color-important-400-rgb:255,140,104;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,111,66;--color-important-700-rgb:255,73,18;--color-important-800-rgb:200,53,9;--color-important-900-rgb:97,23,0;--color-important-950-rgb:68,6,9;--color-special-50:#efecfa;--color-special-100:#e4dff7;--color-special-200:#c4b6ff;--color-special-300:#a38cff;--color-special-400:#8a6ff5;--color-special-500:#8166ee;--color-special-600:#7055df;--color-special-700:#513baa;--color-special-800:#452da5;--color-special-900:#30216e;--color-special-950:#271560;--color-special-50-rgb:239,236,250;--color-special-100-rgb:228,223,247;--color-special-200-rgb:196,182,255;--color-special-300-rgb:163,140,255;--color-special-400-rgb:138,111,245;--color-special-500-rgb:129,102,238;--color-special-600-rgb:112,85,223;--color-special-700-rgb:81,59,170;--color-special-800-rgb:69,45,165;--color-special-900-rgb:48,33,110;--color-special-950-rgb:39,21,96;--color-inherit:inherit;--color-transparent:transparent;--color-current:currentColor;--color-black:#000;--color-white:#fff;--color-canvas:#fff;--color-canvas-light:#fff;--color-canvas-dark:#fcfdfe;--color-inverse:#000;--color-surface:#eff1f3;--color-surface-light:#fcfdfe;--color-surface-strong:#ebedf3;--color-fore:#30394a;--color-fore-in-light:#30394a;--color-fore-in-dark:#fff;--color-focus:#bcdcff;--color-link:#2b47a2;--color-link-hover:#144ce1;--color-link-visited:#6328a4;--color-link-active:#144ce1;--color-placeholder:#64758b;--color-border:#ebedf3;--color-border-strong:#d2d6e5;--color-border-light:#eff1f3;--color-black-rgb:0,0,0;--color-white-rgb:255,255,255;--color-canvas-rgb:255,255,255;--color-canvas-light-rgb:255,255,255;--color-canvas-dark-rgb:252,253,254;--color-inverse-rgb:0,0,0;--color-surface-rgb:239,241,243;--color-surface-light-rgb:252,253,254;--color-surface-strong-rgb:235,237,243;--color-fore-rgb:48,57,74;--color-fore-in-light-rgb:48,57,74;--color-fore-in-dark-rgb:255,255,255;--color-focus-rgb:188,220,255;--color-link-rgb:43,71,162;--color-link-hover-rgb:20,76,225;--color-link-visited-rgb:99,40,164;--color-link-active-rgb:20,76,225;--color-placeholder-rgb:100,117,139;--color-border-rgb:235,237,243;--color-border-strong-rgb:210,214,229;--color-border-light-rgb:239,241,243}body{--btn-bg:var(--color-gray-50)}@media (prefers-color-scheme:dark){.dark-auto{--color-gray-50:#0b0f18;--color-gray-100:#30394a;--color-gray-200:#353d57;--color-gray-300:#3d4667;--color-gray-400:#4a577f;--color-gray-500:#64758b;--color-gray-600:#b2b9c5;--color-gray-700:#d2d6e5;--color-gray-800:#ebedf3;--color-gray-900:#eff1f3;--color-gray-950:#fcfdfe;--color-gray-50-rgb:11,15,24;--color-gray-100-rgb:48,57,74;--color-gray-200-rgb:53,61,87;--color-gray-300-rgb:61,70,103;--color-gray-400-rgb:74,87,127;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:178,185,197;--color-gray-700-rgb:210,214,229;--color-gray-800-rgb:235,237,243;--color-gray-900-rgb:239,241,243;--color-gray-950-rgb:252,253,254;--color-primary-50:#142457;--color-primary-100:#19388f;--color-primary-200:#173db6;--color-primary-300:#144ce1;--color-primary-400:#2b67e5;--color-primary-500:#3883fa;--color-primary-600:#59a5ff;--color-primary-700:#8ec6ff;--color-primary-800:#bcdcff;--color-primary-900:#d9eaff;--color-primary-950:#eef6ff;--color-primary-50-rgb:20,36,87;--color-primary-100-rgb:25,56,143;--color-primary-200-rgb:23,61,182;--color-primary-300-rgb:20,76,225;--color-primary-400-rgb:43,103,229;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:89,165,255;--color-primary-700-rgb:142,198,255;--color-primary-800-rgb:188,220,255;--color-primary-900-rgb:217,234,255;--color-primary-950-rgb:238,246,255;--color-secondary-50:#062a4b;--color-secondary-100:#046bab;--color-secondary-200:#078ada;--color-secondary-300:#1099ed;--color-secondary-400:#18a6fd;--color-secondary-500:#37b2fe;--color-secondary-600:#60c2ff;--color-secondary-700:#77cbff;--color-secondary-800:#9bd9ff;--color-secondary-900:#cdecff;--color-secondary-950:#e7f6ff;--color-secondary-50-rgb:6,42,75;--color-secondary-100-rgb:4,107,171;--color-secondary-200-rgb:7,138,218;--color-secondary-300-rgb:16,153,237;--color-secondary-400-rgb:24,166,253;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:96,194,255;--color-secondary-700-rgb:119,203,255;--color-secondary-800-rgb:155,217,255;--color-secondary-900-rgb:205,236,255;--color-secondary-950-rgb:231,246,255;--color-success-50:#0e3421;--color-success-100:#185e3b;--color-success-200:#21805a;--color-success-300:#28996c;--color-success-400:#2ba675;--color-success-500:#31bd85;--color-success-600:#5aca9d;--color-success-700:#83d7b6;--color-success-800:#ade5ce;--color-success-900:#d6f2e7;--color-success-950:#effaf6;--color-success-50-rgb:14,52,33;--color-success-100-rgb:24,94,59;--color-success-200-rgb:33,128,90;--color-success-300-rgb:40,153,108;--color-success-400-rgb:43,166,117;--color-success-500-rgb:49,189,133;--color-success-600-rgb:90,202,157;--color-success-700-rgb:131,215,182;--color-success-800-rgb:173,229,206;--color-success-900-rgb:214,242,231;--color-success-950-rgb:239,250,246;--color-warning-50:#441506;--color-warning-100:#af5f01;--color-warning-200:#d17100;--color-warning-300:#ed8307;--color-warning-400:#f38f19;--color-warning-500:#ff9f46;--color-warning-600:#ffaf65;--color-warning-700:#ffbc7e;--color-warning-800:#ffd2a9;--color-warning-900:#ffecdb;--color-warning-950:#fff4ea;--color-warning-50-rgb:68,21,6;--color-warning-100-rgb:175,95,1;--color-warning-200-rgb:209,113,0;--color-warning-300-rgb:237,131,7;--color-warning-400-rgb:243,143,25;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:255,175,101;--color-warning-700-rgb:255,188,126;--color-warning-800-rgb:255,210,169;--color-warning-900-rgb:255,236,219;--color-warning-950-rgb:255,244,234;--color-danger-50:#470808;--color-danger-100:#a20606;--color-danger-200:#ba1313;--color-danger-300:#d91b1b;--color-danger-400:#fb2b2b;--color-danger-500:#fc5959;--color-danger-600:#ff7c7c;--color-danger-700:#ff9292;--color-danger-800:#ffb1b1;--color-danger-900:#ffd5d5;--color-danger-950:#ffebeb;--color-danger-50-rgb:71,8,8;--color-danger-100-rgb:162,6,6;--color-danger-200-rgb:186,19,19;--color-danger-300-rgb:217,27,27;--color-danger-400-rgb:251,43,43;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:255,124,124;--color-danger-700-rgb:255,146,146;--color-danger-800-rgb:255,177,177;--color-danger-900-rgb:255,213,213;--color-danger-950-rgb:255,235,235;--color-important-50:#440609;--color-important-100:#611700;--color-important-200:#c83509;--color-important-300:#ff4912;--color-important-400:#ff6f42;--color-important-500:#ff8058;--color-important-600:#ff8c68;--color-important-700:#ffb29b;--color-important-800:#ffcebf;--color-important-900:#ffe2d9;--color-important-950:#fff8f5;--color-important-50-rgb:68,6,9;--color-important-100-rgb:97,23,0;--color-important-200-rgb:200,53,9;--color-important-300-rgb:255,73,18;--color-important-400-rgb:255,111,66;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,140,104;--color-important-700-rgb:255,178,155;--color-important-800-rgb:255,206,191;--color-important-900-rgb:255,226,217;--color-important-950-rgb:255,248,245;--color-special-50:#271560;--color-special-100:#30216e;--color-special-200:#452da5;--color-special-300:#513baa;--color-special-400:#7055df;--color-special-500:#8166ee;--color-special-600:#8a6ff5;--color-special-700:#a38cff;--color-special-800:#c4b6ff;--color-special-900:#e4dff7;--color-special-950:#efecfa;--color-special-50-rgb:39,21,96;--color-special-100-rgb:48,33,110;--color-special-200-rgb:69,45,165;--color-special-300-rgb:81,59,170;--color-special-400-rgb:112,85,223;--color-special-500-rgb:129,102,238;--color-special-600-rgb:138,111,245;--color-special-700-rgb:163,140,255;--color-special-800-rgb:196,182,255;--color-special-900-rgb:228,223,247;--color-special-950-rgb:239,236,250;--color-canvas:#0b0f18;--color-inverse:#fff;--color-surface:#353d57;--color-surface-light:#30394a;--color-surface-strong:#3d4667;--color-fore:#ebedf3;--color-focus:#173db6;--color-link:#59a5ff;--color-link-hover:#3883fa;--color-link-visited:#bcdcff;--color-link-active:#bcdcff;--color-placeholder:#4a577f;--color-border:#353d57;--color-border-strong:#3d4667;--color-border-light:#30394a;--color-canvas-rgb:11,15,24;--color-inverse-rgb:255,255,255;--color-surface-rgb:53,61,87;--color-surface-light-rgb:48,57,74;--color-surface-strong-rgb:61,70,103;--color-fore-rgb:235,237,243;--color-focus-rgb:23,61,182;--color-link-rgb:89,165,255;--color-link-hover-rgb:56,131,250;--color-link-visited-rgb:188,220,255;--color-link-active-rgb:188,220,255;--color-placeholder-rgb:74,87,127;--color-border-rgb:53,61,87;--color-border-strong-rgb:61,70,103;--color-border-light-rgb:48,57,74}}*,:after,:before{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity))}:focus-visible{outline-color:transparent}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }html{font-size:var(--font-size-root)}body{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));font-size:.8125rem;line-height:1.5384615385}.dark,body{--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))}:root{--font-h1-size:2.25rem;--article-p-space:0.5em;--article-heading-space:0.5em;--article-hr-space:1.5em;--article-cell-padding:0.25rem 0.75rem}a,a.disabled:hover{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity))}a:hover{--tw-text-opacity:1;color:rgba(var(--color-link-hover-rgb),var(--tw-text-opacity))}a:focus-visible{outline-color:rgb(var(--color-focus-rgb));outline-offset:2px;outline-width:2px}.code,code{background-color:rgba(var(--color-important-500-rgb),.1);border-radius:var(--radius);padding-left:.25rem;padding-right:.25rem;--tw-text-opacity:1;color:rgba(var(--color-important-500-rgb),var(--tw-text-opacity))}pre{font-size:.75rem;line-height:1rem;overflow:auto;padding:.5rem}pre code{background-color:transparent;color:inherit;padding:0}samp,var{font-weight:700}.blockquote,blockquote{border-left-width:4px;font-size:.875rem;line-height:1.3rem;padding-left:.75rem;text-wrap:pretty}.blockquote figcaption,blockquote figcaption{font-size:.75rem;line-height:1rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:700;line-height:1.5;text-wrap:balance}.h1,h1{font-size:1.75rem}.h2,h2{font-size:1.5rem}.h3,h3{font-size:1.25rem}.h4,h4{font-size:1rem}.h5,h5{font-size:.875rem}.h6,h6{font-size:.75rem}ul{list-style-type:disc}ol,ul{padding-left:1.5em}ol{list-style-type:decimal}dt{font-weight:700}dd{padding-left:2em}.article{color:var(--font-size-article);-webkit-hyphens:auto;hyphens:auto;overflow-wrap:break-word;white-space:pre-wrap}.article h1,.article h2,.article h3,.article h4{margin-bottom:var(--article-heading-space);margin-top:var(--article-heading-space)}.article audio,.article blockquote,.article figure,.article img,.article ol,.article p,.article table,.article ul,.article video{margin-bottom:var(--article-p-space);margin-top:var(--article-p-space);text-wrap:pretty}.article p{min-height:1em}.article p:empty:before{content:" ";display:inline-block}.article hr{margin-bottom:var(--article-hr-space);margin-top:var(--article-hr-space)}.article table{border-width:1px}.article td,.article th{border-bottom-width:1px;padding:var(--article-cell-padding)}.article thead{background-color:var(--table-head-bg,var(--color-gray-100))}.article ol *,.article table *,.article ul *{margin-bottom:0;margin-top:0}.article pre{border-radius:var(--radius);border-width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity))}:root{--alert-bg:var(--color-surface)}.alert{align-items:center;background-color:var(--alert-bg);border-radius:var(--radius);display:flex;gap:.75rem;padding:.5rem .75rem}.alert-content{display:flex;flex:1 1 auto;flex-direction:column;gap:1rem}.alert-close{margin-bottom:-.375rem;margin-right:-.5rem;margin-top:-.375rem}.alert-link{color:inherit;font-weight:700}.alert-link:hover{color:inherit;text-decoration-line:underline}.alert-heading{font-weight:700;margin:0}.alert-text{flex:1 1 auto;white-space:pre-line}.alert-actions{align-items:center;display:flex;gap:.5rem}:root{--breadcrumb-divider:"/";--breadcrumb-divider-color:var(--color-gray-500);--breadcrumb-color-active:var(--color-gray-500)}.breadcrumb{display:flex;gap:1.25rem;list-style-type:none;padding-left:0}.breadcrumb>li{position:relative}.breadcrumb>li+li:before{color:var(--breadcrumb-divider-color);content:var(--breadcrumb-divider);display:block;left:-1.25rem;position:absolute;text-align:center;width:1.25rem}.breadcrumb>.active{color:var(--breadcrumb-color-active)}:root{--btn-radius:var(--radius);--btn-bg:var(--color-surface);--btn-border-color:var(--color-gray-300);--btn-height:2rem}.btn{align-items:center;background-color:var(--btn-bg);border-radius:var(--btn-radius);display:inline-flex;gap:.375rem;height:var(--btn-height);justify-content:center;padding-left:.75rem;padding-right:.75rem;white-space:nowrap;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--btn-border-color)}.btn,.btn-default:hover{color:inherit}.btn-link{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity));text-decoration-line:underline;text-underline-offset:2px;--tw-ring-color:transparent}.btn-link:visited{color:rgba(var(--color-link-visited-rgb),var(--tw-text-opacity))}.btn-link:hover{--tw-text-opacity:1;color:rgba(var(--color-link-hover-rgb),var(--tw-text-opacity))}.btn-link{--btn-bg:transparent}.btn.size-xs,.size-xs>.btn{padding-left:.25rem;padding-right:.25rem;--btn-height:1.25rem}.btn.size-sm,.btn.size-xs,.size-sm>.btn,.size-xs>.btn{font-size:.75rem;line-height:1rem}.btn.size-sm,.size-sm>.btn{--btn-height:1.5rem}.btn.size-md,.btn.size-sm,.size-md>.btn,.size-sm>.btn{padding-left:.5rem;padding-right:.5rem}.btn.size-md,.size-md>.btn{--btn-height:1.75rem}.btn.size-lg,.size-lg>.btn{font-size:1rem;line-height:1.5rem;padding-left:1rem;padding-right:1rem;--btn-height:2.5rem}.btn.size-xl,.size-xl>.btn{font-size:1.125rem;line-height:1.75rem;padding-left:1.25rem;padding-right:1.25rem;--btn-height:3rem}.btn.square{aspect-ratio:1/1;gap:.125rem;padding-left:0;padding-right:0}@supports not (aspect-ratio:1/1){.btn.square{width:var(--btn-height)}}.btn.btn-caret{padding-left:.25rem;padding-right:.25rem}.btn.btn-wide{min-width:80px}:root{--checkbox-size:12px;--checkbox-color:var(--color-primary-500)}.checkbox,.radio{align-items:center;cursor:pointer;display:flex;gap:.375rem;min-height:20px}.checkbox>input[type=checkbox],.radio>input[type=radio]{accent-color:rgb(var(--color-primary-500-rgb));border-radius:var(--radius-lg)}.checkbox-primary,.radio-primary{display:flex;gap:.375rem;min-height:20px;position:relative}.checkbox-primary>input[type=checkbox],.radio-primary>input[type=radio]{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.checkbox-primary>label,.radio-primary>label{cursor:pointer;padding-left:calc(var(--checkbox-size) + 8px);position:relative}.checkbox-primary>label:after,.checkbox-primary>label:before,.radio-primary>label:after,.radio-primary>label:before{display:block;height:var(--checkbox-size);left:0;position:absolute;transition-duration:.15s;transition-property:transform,background-color,color,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--checkbox-size);--tw-content:"";content:var(--tw-content);top:calc((20px - var(--checkbox-size))/2)}.checkbox-primary>label:before{border-radius:var(--radius-sm);border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.checkbox-primary>label:after{--tw-scale-x:.9;--tw-scale-y:.9;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0ibTkgMjAuNDItNi4yMS02LjIxIDIuODMtMi44M0w5IDE0Ljc3bDkuODgtOS44OSAyLjgzIDIuODN6Ii8+PC9zdmc+");transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.radio-primary>label:before{border-radius:var(--radius-full);border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity))}.radio-primary>label:after{background-color:var(--checkbox-color);border-radius:var(--radius-full);opacity:0;--checkbox-radio-size:calc(var(--checkbox-size)*2/3);height:var(--checkbox-radio-size);left:calc((var(--checkbox-size) - var(--checkbox-radio-size))/2);top:calc((20px - var(--checkbox-radio-size))/2);width:var(--checkbox-radio-size)}.checkbox-primary>label:hover:before,.radio-primary>label:hover:before{border-color:var(--checkbox-color)}.checkbox-primary.focus>label:before,.checkbox-primary>input[type=checkbox]:focus+label:before,.radio-primary.focus>label:before,.radio-primary>input[type=radio]:focus+label:before{border-color:var(--checkbox-color);outline-color:rgb(var(--color-focus-rgb));outline-style:solid;outline-width:2px}.checkbox-primary.checked>label:before,.checkbox-primary>input[type=checkbox]:checked+label:before{background-color:var(--checkbox-color);border-color:var(--checkbox-color)}.radio-primary.checked>label:before,.radio-primary>input[type=radio]:checked+label:before{border-color:var(--checkbox-color)}.checkbox-primary.checked>label:after,.checkbox-primary>input[type=checkbox]:checked+label:after,.radio-primary.checked>label:after,.radio-primary>input[type=radio]:checked+label:after{opacity:1}.checkbox-primary.disabled>label,.checkbox-primary>input[type=checkbox]:disabled+label,.radio-primary.disabled>label,.radio-primary>input[type=radio]:disabled+label{cursor:not-allowed;opacity:.7;pointer-events:none;--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.checkbox-primary.indeterminate>label:after,.checkbox-primary>input[type=checkbox]:indeterminate+label:after{--tw-border-opacity:1;background-color:var(--checkbox-color);background-image:none;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity));border-width:calc((var(--checkbox-size) - 2px)/2) 2px;opacity:1}.check-list{align-items:flex-start;flex-direction:column;gap:.5rem}.check-list,.check-list-inline{display:flex;padding-bottom:.375rem;padding-top:.375rem}.check-list-inline{align-items:center;-moz-column-gap:1rem;column-gap:1rem;flex-direction:row;flex-wrap:wrap;row-gap:.5rem}.switch{display:flex;gap:.375rem;min-height:20px;padding-left:2.5rem;position:relative}.switch>input{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.switch>label:after,.switch>label:before{border-radius:var(--radius-full);border-width:1px;height:1rem;left:0;position:absolute;top:.125rem;width:2rem;--tw-border-opacity:1;border-color:rgba(var(--color-border-strong-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));transition-duration:.3s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);--tw-content:"";content:var(--tw-content)}.switch>label:before{cursor:pointer;--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.switch>label:hover:before{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity))}.switch>label:after{height:.75rem;left:.125rem;top:.25rem;width:.75rem;--tw-border-opacity:1;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.switch>input:checked+label:before{background-color:var(--checkbox-color);border-color:rgba(var(--color-inverse-rgb),.2)}.switch>input:checked+label:after{color:var(--checkbox-color);left:18px}.switch.focus>label:before,.switch>input:focus+label:before{border-color:var(--checkbox-color);outline-color:rgb(var(--color-focus-rgb));outline-style:solid;outline-width:2px}.switch.disabled>label:before,.switch>input:disabled+label:before{cursor:not-allowed;opacity:.7;pointer-events:none;--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:root{--form-control-radius:var(--radius);--form-control-border:var(--color-border);--form-control-focus:var(--color-primary-500);--form-control-disabled:var(--color-surface);--form-control-readonly:var(--color-surface)}.dark{--form-control-border:var(--color-border-strong)}input::-moz-placeholder,textarea::-moz-placeholder{--tw-placeholder-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-placeholder-opacity))}input::placeholder,textarea::placeholder{--tw-placeholder-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-placeholder-opacity))}.form-control{border-radius:var(--form-control-radius);display:block;height:2rem;width:100%;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));outline-color:transparent;outline-style:solid;outline-width:1px;padding:.25rem .5rem;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--form-control-border);transition-duration:.15s;transition-property:outline,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.form-control.focus,.form-control:focus{outline-color:var(--form-control-focus);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-focus-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.3}.form-control.disabled,.form-control[disabled]{background-color:var(--form-control-disabled);opacity:1}.form-control.readonly,.form-control[readonly]{background-color:var(--form-control-readonly)}select{-webkit-appearance:none;background-image:url("data:image/gif;base64,R0lGODlhBwAEAIAAAMvQ2////yH5BAEAAAEALAAAAAAHAAQAAAIIhA+BGWoNWSgAOw==");background-position:right 8px top 50%;background-repeat:no-repeat;background-size:8px auto;padding-right:1rem}select.form-control[multiple]{background-image:none}textarea.form-control{height:auto;min-height:32px}input[type=file].form-control{padding:.125rem}input[type=file].form-control::-webkit-file-upload-button{-webkit-appearance:none;appearance:none;border-radius:inherit;border-style:none;cursor:pointer;height:1.75rem;padding-left:.5rem;padding-right:.5rem}input[type=file].form-control::-webkit-file-upload-button:hover{background-color:rgba(var(--color-black-rgb),.1)}.has-error .form-control,.has-error.form-control{--tw-ring-color:rgba(var(--color-danger-500-rgb),0.6)}.has-error .form-control.focus,.has-error .form-control:focus,.has-error.form-control.focus,.has-error.form-control:focus{outline-color:rgb(var(--color-danger-500-rgb));--tw-ring-color:rgba(var(--color-danger-500-rgb),0.1)}.has-warning .form-control,.has-warning.form-control{--tw-ring-color:rgba(var(--color-warning-500-rgb),0.6)}.has-warning .form-control.focus,.has-warning .form-control:focus,.has-warning.form-control.focus,.has-warning.form-control:focus{outline-color:rgb(var(--color-warning-500-rgb));--tw-ring-color:rgba(var(--color-warning-500-rgb),0.2)}.has-success .form-control,.has-success.form-control{--tw-ring-color:rgba(var(--color-success-500-rgb),0.6)}.has-success .form-control.focus,.has-success .form-control:focus,.has-success.form-control.focus,.has-success.form-control:focus{outline-color:rgb(var(--color-success-500-rgb));--tw-ring-color:rgba(var(--color-success-500-rgb),0.2)}.form-control.size-sm,.size-sm>.form-control{font-size:.75rem;height:1.5rem;line-height:1rem;padding-left:.5rem;padding-right:.5rem}.form-control.size-md,.size-md>.form-control{height:1.75rem;padding-left:.5rem;padding-right:.5rem}.form-control.size-lg,.size-lg>.form-control{font-size:1rem;height:2.5rem;line-height:1.5rem;padding-left:.75rem;padding-right:.75rem}:root{--input-group-addon-bg:var(--color-gray-50)}.input-group{align-items:stretch;display:flex}.input-group>.form-control,.input-group>.input-control{flex:1 1 auto;z-index:1}.input-group-addon{align-items:center;background-color:var(--input-group-addon-bg);border-radius:var(--form-control-radius);display:flex;flex:none;height:2rem;padding-left:.5rem;padding-right:.5rem;z-index:0;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--form-control-border)}.size-sm>.input-group-addon{font-size:.75rem;height:1.5rem;line-height:1rem;padding-left:.5rem;padding-right:.5rem}.size-lg>.input-group-addon{font-size:1rem;height:2.5rem;line-height:1.5rem;padding-left:.75rem;padding-right:.75rem}.input-group-control{flex:1 1 auto}.input-group>*+*,.input-group>*+* .form-control{border-bottom-left-radius:var(--radius-none);border-top-left-radius:var(--radius-none)}.input-group>:not(:last-child),.input-group>:not(:last-child) .form-control{border-bottom-right-radius:var(--radius-none);border-top-right-radius:var(--radius-none)}.input-group .btn:focus-visible,.input-group .form-control:focus{z-index:2}:root{--form-tip-color:var(--color-gray-400);--form-label-color:var(--color-gray-700);--form-horz-label-width:6rem;--form-grid-gap-x:1.25rem;--form-grid-gap-y:.75rem}.form{flex-direction:column;gap:1rem}.form,.form-label{display:flex}.form-label{align-items:center;color:var(--form-label-color);flex-direction:row;gap:.25rem;height:2rem;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap}.form-label.required:after{content:"*";display:inline-block;margin-left:.25rem;--tw-translate-y:0.125rem;--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-text-opacity:1;color:rgba(var(--color-danger-500-rgb),var(--tw-text-opacity))}.no-required .form-label.required:after{display:none}.form-label-actions{flex:1 1 auto;justify-content:flex-end}.form-label>.checkbox-primary{margin-left:.75rem}.form-tip{color:var(--form-tip-color);display:block;margin-top:.25rem}.has-error .form-tip{--tw-text-opacity:1;color:rgba(var(--color-danger-500-rgb),var(--tw-text-opacity))}.has-warning .form-tip{--tw-text-opacity:1;color:rgba(var(--color-warning-500-rgb),var(--tw-text-opacity))}.has-success .form-tip{--tw-text-opacity:1;color:rgba(var(--color-success-500-rgb),var(--tw-text-opacity))}.form-actions{display:flex;flex-direction:row;gap:1rem;justify-content:center}.form-grid{--form-grid-gap-x-half:calc(var(--form-grid-gap-x)/2);--form-grid-gap-y-half:calc(var(--form-grid-gap-y)/2);align-items:flex-start;flex-direction:row;flex-wrap:wrap;gap:0}.form-grid .form-group{padding:var(--form-grid-gap-y-half) var(--form-grid-gap-x-half)}.form-grid .form-label.required:after{margin-left:.25rem;order:-9999}.form-grid .form-label .checkbox{margin-left:.75rem;margin-right:.75rem}.form-grid .has-wrap-after:after{display:block;width:100%;--tw-content:"";content:var(--tw-content)}.form-grid-wrap{width:100%}.form-grid-row{display:flex;flex-direction:row;padding-bottom:var(--form-grid-gap-y-half);padding-top:var(--form-grid-gap-y-half);position:relative;width:100%}.form-grid-col{padding-left:var(--form-grid-gap-x-half);padding-right:var(--form-grid-gap-x-half)}.form-grid .form-actions{gap:1.5rem;justify-content:center;padding:var(--form-grid-gap-y) var(--form-grid-gap-x-half);width:100%}.form-grid .form-actions.is-pinned{border-top-width:1px}.form-horz .form-row{align-items:flex-start;display:flex;flex-direction:row}.form-horz .form-group{align-items:flex-start;display:flex;flex:none;flex-direction:row;flex-wrap:wrap;min-height:32px;min-width:0;padding-left:var(--form-horz-label-width);position:relative}.form-horz .form-row .form-group{flex:1 1 auto}.form-horz .form-group[class*=" w-"],.form-horz .form-group[class^=w-]{flex:none}.form-horz .form-group>*{min-width:0}.form-horz .form-group.no-label{padding-left:0}.form-horz .form-group.no-label>.check-list-inline{padding-left:1rem;padding-right:1rem}.form-horz .form-label{justify-content:flex-end;left:0;padding-left:1rem;padding-right:.5rem;position:absolute;top:0;width:var(--form-horz-label-width)}.form-horz .form-label.required:after{margin-left:0;order:-9999}.form-horz .form-tip{width:100%}.form-horz .form-tip,.form-horz .input-control,.form-horz .input-group{flex:1 1 auto}.form .form-group-wrapper,.form-horz .form-group-wrapper{flex:1 1 auto;min-width:0;width:100%;z-index:1}.form .form-group-wrapper.flex-none,.form-horz .form-group-wrapper.flex-none{flex:none}.form fieldset>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.form fieldset{padding-bottom:1rem;padding-left:1rem}.form-grid fieldset>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.form legend{border-bottom-width:1px;display:flex;justify-content:flex-start;margin-left:-1rem;width:100%;--tw-border-opacity:1;border-bottom-color:rgba(var(--color-primary-100-rgb),var(--tw-border-opacity));width:calc(100% + 1rem)}.form-title{align-items:center;background-color:rgba(var(--color-primary-50-rgb),.5);display:flex;font-weight:700;height:1.75rem;padding-left:.75rem;padding-right:.75rem}:root{--input-control-fix-width-sm:2rem;--input-control-fix-width:4.375rem;--input-control-fix-width-lg:6.75rem}.input-control{position:relative;--input-control-prefix:8px;--input-control-suffix:8px}.input-control-prefix,.input-control-suffix{align-items:center;display:flex;height:100%;left:0;opacity:.5;padding-left:.5rem;padding-right:.5rem;position:absolute;top:0;white-space:nowrap;width:var(--input-control-prefix);z-index:1}.input-control-suffix{justify-content:flex-end;left:auto;right:0;width:var(--input-control-suffix)}.form-control:focus+.input-control-prefix,.form-control:focus+.input-control-suffix{opacity:1}.input-control>.form-control{padding-left:var(--input-control-prefix);padding-right:var(--input-control-suffix)}.input-control>select.form-control{background-position-x:calc(100% - var(--input-control-suffix) - 8px);padding-right:calc(var(--input-control-suffix) + 20px)}.has-prefix{--input-control-prefix:var(--input-control-fix-width)}.has-suffix{--input-control-suffix:var(--input-control-fix-width)}.has-prefix-sm{--input-control-prefix:var(--input-control-fix-width-sm)}.has-suffix-sm{--input-control-suffix:var(--input-control-fix-width-sm)}.has-prefix-lg{--input-control-prefix:var(--input-control-fix-width-lg)}.has-suffix-lg{--input-control-suffix:var(--input-control-fix-width-lg)}.has-prefix-icon{--input-control-prefix:32px}.has-suffix-icon{--input-control-suffix:32px}.input-control.has-prefix-icon{--input-control-prefix:32px}.input-control.has-suffix-icon{--input-control-suffix:32px}.input-control.has-prefix-icon>.input-control-prefix,.input-control.has-suffix-icon>.input-control-suffix{justify-content:center;padding:0}.input-control.size-sm>.form-control,.input-control.size-sm>.input-control-prefix,.input-control.size-sm>.input-control-suffix{font-size:.75rem;line-height:1rem}.input-control.size-lg>.form-control,.input-control.size-lg>.input-control-prefix,.input-control.size-lg>.input-control-suffix{font-size:1rem;line-height:1.5rem}:root{--label-bg:rgba(var(--color-canvas-rgb),.1);--label-border-color:var(--color-gray-300);--label-color:var(--color-gray-500);--label-radius:var(--radius)}.label{align-items:center;background-color:var(--label-bg);border-radius:var(--label-radius);color:var(--label-color);display:inline-flex;font-size:.75rem;height:1.25rem;justify-content:center;line-height:1rem;min-width:1.25rem;padding-left:.25rem;padding-right:.25rem;white-space:pre-line;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--label-border-color)}.label.size-lg{font-size:.8125rem;height:1.5rem;line-height:1.25rem;min-width:1.5rem;padding-left:.5rem;padding-right:.5rem}.label.size-sm{height:1rem;min-width:1rem}.label-dot{aspect-ratio:1/1;border-radius:var(--radius-full);height:.5rem;min-width:0;padding-left:0;padding-right:0}.caret,.caret-down,.caret-left,.caret-right,.caret-up{align-items:center;display:inline-flex;height:.75rem;justify-content:center;position:relative;width:.75rem}.caret-down:before,.caret-left:before,.caret-right:before,.caret-up:before,.caret:before{display:block;height:.35rem;transform-origin:center;width:.35rem;--tw-translate-y:-1px;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.caret-left:before{--tw-translate-x:0.125rem;--tw-translate-y:0px;--tw-rotate:135deg}.caret-left:before,.caret-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.caret-right:before{--tw-translate-x:-0.125rem;--tw-translate-y:0px;--tw-rotate:-45deg}.caret-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:focus>.caret,:hover>.caret{opacity:inherit}.disabled .caret,.readonly .caret{opacity:var(--caret-opacity,.5)}.listitem{align-items:center;border-radius:var(--radius);display:flex;flex-direction:row;flex-wrap:nowrap;gap:.5rem;padding:.25rem}.listitem.selected{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.listitem.active{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.item-actions,.item-avatar,.item-icon,.item-trailing,.item-trailing-icon{flex:none}.item-icon.icon-EMPTY{display:none}.item-subtitle{font-size:.75rem;line-height:1rem;opacity:.8}.item-content,.item-text{flex:1 1 auto;min-width:0}.item-leading,.item-trailing{align-items:center;display:flex;flex:none;gap:.5rem}.item-checkbox{margin-right:-.5rem}.item-content{align-items:center;display:flex;gap:.5rem}.multiline>.item-content{align-items:flex-start;flex-direction:column;gap:.25rem}.list{list-style-type:none;padding-left:0}.list-heading-inner .item-title{font-weight:700;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.with-hover-actions>.item{position:relative}.with-hover-actions>.item>.item-inner .item-actions{opacity:0;pointer-events:none;position:absolute;right:.25rem;top:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.with-hover-actions>.item>.item-inner:hover .item-actions{display:flex;margin-top:-.25rem;opacity:1;pointer-events:auto;position:static}.list.is-nested-sub{padding-left:var(--list-indent)}.is-nested-collapsed{display:none}.nested-toggle-icon{align-items:center;border-radius:var(--radius);display:flex;height:1rem;justify-content:center;margin-right:-.25rem;width:1rem}.magnifier{display:inline-block;height:1em;position:relative;width:1em}.magnifier:after,.magnifier:before{border-radius:var(--radius-full);content:"";display:block;position:absolute}.magnifier:before{border:1px solid;height:.75em;width:.75em}.magnifier:after{height:1px;left:.55em;top:.7em;width:.5em;--tw-rotate:45deg;background-color:currentColor;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.search-box.compact.has-prefix-icon{--input-control-prefix:24px}.search-box.compact.has-suffix-icon{--input-control-suffix:24px}:root{--menu-bg:var(--color-canvas);--menu-active-bg:var(--color-primary-500);--menu-active-color:var(--color-canvas);--menu-selected-bg:var(--color-primary-50);--menu-selected-color:var(--color-primary-500);--menu-icon-opacity:.5;--menu-icon-margin:1.75rem;--menu-min-width:3rem;--menu-heading-color:var(--color-gray-500)}.menu{background:var(--menu-bg);max-width:var(--menu-max-width);min-width:var(--menu-min-width);padding:.5rem}.menu-wrapper{display:flex;flex-direction:column;min-height:0}.menu-wrapper>.menu{flex:1 1 auto;min-height:0;overflow:auto}.menu-item>.item-inner,.menu-item>a{align-items:center;border-radius:var(--radius);color:inherit;cursor:pointer;display:flex;gap:.5rem;justify-content:space-between;overflow:hidden;padding:.25rem .5rem;position:relative;text-overflow:ellipsis;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);white-space:nowrap}.menu-item>.selected{background:var(--menu-selected-bg);color:var(--menu-selected-color)}.menu-item>.active,.menu-item>a.hover,.menu-item>a:hover{background:var(--menu-active-bg);color:var(--menu-active-color)}.menu-item>a.no-hover.hover,.menu-item>a.no-hover:hover{background:unset;color:unset}.menu-item.disabled>a:hover,.menu-item>a.disabled:hover{background-color:inherit;color:inherit}.menu-item .item-title{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:clip;white-space:nowrap}.menu>.divider{margin:.25rem}.menu-heading{align-items:center;color:var(--menu-heading-color);display:flex;font-size:.75rem;font-weight:700;height:2rem;line-height:1rem;padding-left:.25rem;padding-right:.25rem}.has-icons>.menu-item>a>.item-icon{align-items:center;display:flex;height:1rem;justify-content:center;opacity:var(--menu-icon-opacity);width:1rem}.menu-nested{--menu-indent:10px}.menu-nested .menu{background-color:transparent;margin-bottom:-.5rem;margin-left:var(--menu-indent);margin-top:-.5rem;padding-right:0}.menu-nested .menu-item>.item-inner{padding-left:0}.menu-nested .search-menu-footer,.menu-nested .search-menu-header{margin-bottom:.25rem;margin-left:var(--menu-indent);margin-top:-.125rem;padding-right:1px}.menu.compact .menu-item>a{padding-bottom:.125rem;padding-top:.125rem}.menu.compact .menu-heading{height:1.75rem}.search-menu-header{padding:.5rem .5rem .125rem}.search-menu-footer{padding:.125rem .5rem .5rem}.search-menu .item.is-not-match,.search-menu-footer:empty,.search-menu-header:empty{display:none}.search-menu .item.is-not-match.has-match-child{display:list-item}.search-menu .item.is-not-match.has-match-child>.item-inner{opacity:.5;pointer-events:none}.search-menu.no-toggle-on-search .nested-toggle-icon{pointer-events:none}.search-menu .is-match-keys{font-weight:700;text-decoration-line:underline}.search-menu-no-match-hint{display:none;font-size:.75rem;line-height:1rem;padding:.5rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.no-match-child .search-menu-no-match-hint{display:block}.no-match-child>.menu{display:none}.search-menu-exceed-limit-hint{font-size:.75rem;line-height:1rem;padding:.25rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}:root{--alert-bg:var(--color-surface)}.alert{align-items:center;background-color:var(--alert-bg);border-radius:var(--radius);display:flex;gap:.75rem;padding:.5rem .75rem}.alert-content{display:flex;flex:1 1 auto;flex-direction:column;gap:1rem}.alert-close{margin-bottom:-.375rem;margin-right:-.5rem;margin-top:-.375rem}.alert-link{color:inherit;font-weight:700}.alert-link:hover{color:inherit;text-decoration-line:underline}.alert-heading{font-weight:700;margin:0}.alert-text{flex:1 1 auto;white-space:pre-line}.alert-actions{align-items:center;display:flex;gap:.5rem}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.messagers{align-items:flex-end;bottom:0;display:flex;flex-direction:column;gap:.5rem;justify-content:flex-end;left:0;padding:1rem;pointer-events:none;position:fixed;right:0;top:0;z-index:1900}.messagers-top-left,.messagers-top-right{justify-content:flex-start}.messagers-bottom-left,.messagers-top-left{align-items:flex-start}.messagers-bottom,.messagers-center,.messagers-top{align-items:center}.messagers-top,.messagers-top-left,.messagers-top-right{justify-content:flex-start}.messagers-center{justify-content:center}.messager{background-color:rgba(var(--color-inverse-rgb),.8);pointer-events:auto;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);transition-duration:.3s}:root{--progress-radius:var(--radius);--progress-striped-size:40px;--progress-bg:var(--color-surface);--progress-bar-color:var(--color-primary-500)}.progress{background:var(--progress-bg);border-radius:var(--progress-radius);display:flex;height:1.25rem}.progress-bar{background:var(--progress-bar-color);height:100%;transition-duration:.5s;transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1)}.progress-striped>.progress-bar{background-image:linear-gradient(45deg,rgba(var(--color-canvas-rgb),.15) 25%,transparent 25%,transparent 50%,rgba(var(--color-canvas-rgb),.15) 50%,rgba(var(--color-canvas-rgb),.15) 75%,transparent 75%,transparent);background-size:var(--progress-striped-size) var(--progress-striped-size)}.progress>.progress-bar:first-child{border-bottom-left-radius:inherit;border-top-left-radius:inherit}.progress>.progress-bar:last-child{border-bottom-right-radius:inherit;border-top-right-radius:inherit}.progress.active .progress-bar{animation:progress-bar-stripes 2s linear infinite}@keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}.scrollbar,:root{--scrollbar-size:10px;--scrollbar-opacity:.6;--scrollbar-bg:rgba(var(--color-inverse-rgb),.15);--scrollbar-inset:inset 0 0 0 1px rgba(var(--color-inverse-rgb),.05);--scrollbar-bar-bg:rgba(var(--color-inverse-rgb),.3);--scrollbar-hover-bg:rgba(var(--color-inverse-rgb),.4);--scrollbar-drag-bg:rgba(var(--color-inverse-rgb),.5);--scrollbar-radius:var(--radius-sm);--scrollbar-duration:.7s}::-webkit-scrollbar{height:var(--scrollbar-size);width:var(--scrollbar-size)}::-webkit-scrollbar-track{background:var(--scrollbar-bg);box-shadow:var(--scrollbar-shadow);-webkit-transition:background-color var(--scrollbar-duration);transition:background-color var(--scrollbar-duration)}::-webkit-scrollbar-track:hover,:hover::-webkit-scrollbar-track{background:var(--scrollbar-hover-bg)}::-webkit-scrollbar-thumb{background:var(--scrollbar-bar-bg);border-radius:var(--scrollbar-radius);min-height:var(--scrollbar-size);-webkit-transition:var(--scrollbar-duration);transition:var(--scrollbar-duration);-webkit-transition-property:background-color;transition-property:background-color}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-hover-bg)}::-webkit-scrollbar-thumb:active{background:var(--scrollbar-drag-bg)}@-moz-document url-prefix(){.scrollbar-thin{scrollbar-width:thin}}.scrollbar-thin::-webkit-scrollbar{height:calc(var(--scrollbar-size)/2);width:calc(var(--scrollbar-size)/2)}.scrollbar-hover::-webkit-scrollbar,.scrollbar-hover::-webkit-scrollbar-thumb,.scrollbar-hover::-webkit-scrollbar-track{visibility:hidden}.scrollbar-hover:hover::-webkit-scrollbar,.scrollbar-hover:hover::-webkit-scrollbar-thumb,.scrollbar-hover:hover::-webkit-scrollbar-track{visibility:visible}@font-face{font-family:ZentaoIcon;font-style:normal;font-weight:400;src:url(./icons/ZentaoIcon.eot?v=1.71);src:url(./icons/ZentaoIcon.woff?v=1.71) format("woff"),url(./icons/ZentaoIcon.ttf?v=1.71) format("truetype"),url(./icons/ZentaoIcon.svg?v=1.71#regular) format("svg")}.icon,[class*=" icon-"],[class^=icon-]{display:inline-block;font-display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon:before{display:inline-block;min-width:14px;text-align:center}.icon-xs:before{font-size:.7em}.icon-sm:before{font-size:.8em}.icon-lg:before{font-size:1.25em;vertical-align:-10%}.icon-2x{font-size:28px}.icon-3x{font-size:42px}.icon-4x{font-size:56px}.icon-5x{font-size:70px}.icon-run{position:relative}.icon-run:before{opacity:.5}.icon-run:after{bottom:0;content:"\ea07";display:block;left:0;position:absolute;right:0;text-align:center;top:0}.icon-docspace:before{content:"\ea1b"}.icon-doclib:before{content:"\ea1c"}.icon-guihua:before{content:"\ea02"}.icon-memory:before{content:"\e9fd"}.icon-cpu:before{content:"\e9fe"}.icon-pause-pure:before{content:"\e9ff"}.icon-exclamation-pure:before{content:"\ea00"}.icon-zentao:before{content:"\e901"}.icon-zentao-alt:before{content:"\e900"}.icon-safe:before{content:"\ea06"}.icon-ai:before{content:"\e983"}.icon-kanban:before{content:"\e997"}.icon-college:before{content:"\e9c8"}.icon-home:before,.icon-menu-my:before{content:"\e97a"}.icon-program:before{content:"\e9aa"}.icon-lightbulb-alt:before,.icon-product:before{content:"\e98f"}.icon-project:before,.icon-rocket:before{content:"\e99c"}.icon-run:before{content:"\e9a9"}.icon-run-alt:before{content:"\ea07"}.icon-test:before{content:"\e956"}.icon-devops:before,.icon-infinite:before{content:"\e9a3"}.icon-doc:before,.icon-menu-doc:before{content:"\e99b"}.icon-statistic:before{content:"\e999"}.icon-group:before,.icon-menu-users:before,.icon-persons:before,.icon-team:before{content:"\e97e"}.icon-assets:before,.icon-diamond:before{content:"\e9ae"}.icon-flow:before{content:"\e994"}.icon-backend:before,.icon-cog-outline:before{content:"\ea05"}.icon-help:before{content:"\e968"}.icon-download:before,.icon-import:before{content:"\e904"}.icon-export:before{content:"\e905"}.icon-lightbulb:before{content:"\e91c"}.icon-close:before{content:"\e936"}.icon-check:before{content:"\e5ca"}.icon-minus:before{content:"\e926"}.icon-expand-alt:before{content:"\e6f1"}.icon-collapse-alt:before{content:"\e6f2"}.icon-fullscreen:before{content:"\e96b"}.icon-star-empty:before{content:"\e94a"}.icon-star:before{content:"\e94b"}.icon-exclamation-sign:before{content:"\e930"}.icon-info-sign:before{content:"\e9d5"}.icon-flag:before{content:"\e937"}.icon-check-circle:before{content:"\e92f"}.icon-check-sign:before{content:"\e938"}.icon-chart-pie:before{content:"\e95b"}.icon-history:before{content:"\e95f"}.icon-pencil:before{content:"\e254"}.icon-search:before{content:"\e928"}.icon-restart:before{content:"\e95e"}.icon-cog:before{content:"\e93b"}.icon-chart-line:before{content:"\e95c"}.icon-bar-chart:before,.icon-chart-bar:before{content:"\e95d"}.icon-exchange:before{content:"\e927"}.icon-severity:before{content:"\e973"}.icon-book:before{content:"\f02d"}.icon-treemap-alt:before{content:"\e971"}.icon-severity-solid:before{content:"\e902"}.icon-chat-line:before{content:"\e998"}.icon-stack:before{content:"\e943"}.icon-cube:before{content:"\e967"}.icon-minus-sign:before{content:"\e939"}.icon-bars-sign:before{content:"\e93a"}.icon-chat:before,.icon-message:before{content:"\e940"}.icon-more:before{content:"\e744"}.icon-certificate:before{content:"\f0a3"}.icon-bell:before{content:"\e7f5"}.icon-columns:before{content:"\f0db"}.icon-envelope-o:before{content:"\e92a"}.icon-unfold-all:before{content:"\e931"}.icon-fold-all:before{content:"\e932"}.icon-bars:before{content:"\e948"}.icon-cards-view:before{content:"\e949"}.icon-ellipsis-v:before{content:"\e5d4"}.icon-spinner-indicator:before{content:"\e982"}.icon-up-circle:before{content:"\e92b"}.icon-right-circle:before{content:"\e92c"}.icon-down-circle:before{content:"\e92d"}.icon-left-circle:before{content:"\e92e"}.icon-angle-double-right:before{content:"\f101"}.icon-angle-down:before{content:"\e313"}.icon-angle-left:before{content:"\e314"}.icon-angle-right:before{content:"\e315"}.icon-angle-top:before{content:"\e316"}.icon-first-page:before{content:"\e5dc"}.icon-last-page:before{content:"\e5dd"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-arrow-up:before{content:"\e923"}.icon-arrow-down:before{content:"\e924"}.icon-arrow-left:before{content:"\e952"}.icon-arrow-right:before{content:"\e93e"}.icon-chevron-left:before{content:"\e934"}.icon-chevron-right:before{content:"\e935"}.icon-chevron-double-up:before{content:"\e959"}.icon-chevron-double-down:before{content:"\e95a"}.icon-folder-account:before{content:"\e942"}.icon-folder-move:before{content:"\e960"}.icon-folder-plus:before{content:"\e961"}.icon-folder-upload:before{content:"\e962"}.icon-folder-star:before{content:"\e963"}.icon-folder-edit:before{content:"\e964"}.icon-folder-download:before{content:"\e965"}.icon-folder-outline:before{content:"\e966"}.icon-folder:before{content:"\e944"}.icon-folder-o:before{content:"\e945"}.icon-folder-open-o:before{content:"\e946"}.icon-folder-open:before{content:"\e947"}.icon-color:before{content:"\e93c"}.icon-paper-clip:before{content:"\e93d"}.icon-text:before{content:"\e929"}.icon-share:before{content:"\f064"}.icon-format-list-bulleted:before{content:"\e9a8"}.icon-format-bold:before{content:"\e953"}.icon-format-header-pound:before{content:"\e954"}.icon-format-italic:before{content:"\e955"}.icon-format-list-numbers:before{content:"\e969"}.icon-format-quote-close:before{content:"\e96a"}.icon-image:before{content:"\e96c"}.icon-table-large:before{content:"\e96d"}.icon-productplan:before{content:"\e9fc"}.icon-aiux:before{content:"\e99e"}.icon-qc:before{content:"\e986"}.icon-qc-q:before{content:"\e985"}.icon-qc-c:before{content:"\e987"}.icon-sonarqube:before{content:"\e9ba"}.icon-board:before{content:"\ea15"}.icon-market:before{content:"\ea01"}.icon-ztool:before{content:"\e9c1"}.icon-contacts:before{content:"\e9c3"}.icon-chats:before{content:"\e9c4"}.icon-ops:before{content:"\e903"}.icon-menu-backend:before{content:"\e993"}.icon-feedback:before{content:"\e991"}.icon-oa:before{content:"\e9a1"}.icon-more-circle:before{content:"\e988"}.icon-controls:before{content:"\e995"}.icon-account:before{content:"\e992"}.icon-about:before,.icon-info:before{content:"\e996"}.icon-exclamation:before{content:"\e9fa"}.icon-exit:before{content:"\e99a"}.icon-theme:before{content:"\e9a0"}.icon-globe:before,.icon-lang:before{content:"\f0ac"}.icon-template:before{content:"\e9fb"}.icon-seal:before{content:"\e9f8"}.icon-menu-arrow-left:before{content:"\e9f0"}.icon-menu-arrow-right:before{content:"\e9f1"}.icon-add-directory:before{content:"\e9ef"}.icon-design:before{content:"\e9ec"}.icon-download-alt:before{content:"\e9ea"}.icon-blame:before{content:"\e9e0"}.icon-draft-edit:before{content:"\e9dc"}.icon-sub-review-user:before{content:"\e9db"}.icon-sub-review:before{content:"\e9df"}.icon-ztf:before{content:"\e9dd"}.icon-save:before{content:"\e9d8"}.icon-list-box:before{content:"\e9b4"}.icon-usecase:before{content:"\e99d"}.icon-code:before{content:"\e990"}.icon-summary:before{content:"\e9ad"}.icon-more-alt:before{content:"\e9a7"}.icon-customer:before{content:"\e9d9"}.icon-alarm:before{content:"\ea16"}.icon-treeview:before{content:"\ea0d"}.icon-or:before{content:"\ea0b"}.icon-manager:before{content:"\ea0c"}.icon-target:before{content:"\ea0a"}.icon-ipd:before{content:"\e9f9"}.icon-wiki-lib:before{content:"\e9f5"}.icon-annex-lib:before{content:"\e9f6"}.icon-interface-lib:before{content:"\e9f7"}.icon-has-authority-pack:before{content:"\e9f3"}.icon-without-authority-pack:before{content:"\e9f4"}.icon-data-structure:before{content:"\e9f2"}.icon-waterfallplus:before{content:"\e9ed"}.icon-agileplus:before{content:"\e9ee"}.icon-horn:before{content:"\e9eb"}.icon-resume:before{content:"\e9e9"}.icon-mirror:before{content:"\e9e6"}.icon-remote:before{content:"\e9e7"}.icon-moon:before{content:"\e9e8"}.icon-ticket:before{content:"\e9e1"}.icon-gantt-alt:before{content:"\e9e2"}.icon-tree:before{content:"\e9c9"}.icon-list:before{content:"\e9cb"}.icon-gantt:before{content:"\e9cc"}.icon-group-view:before{content:"\e9cd"}.icon-inherit-space:before{content:"\e9c2"}.icon-card-archive:before{content:"\e9b8"}.icon-col-archive:before{content:"\e9b9"}.icon-col-add-right:before{content:"\e9bb"}.icon-col-add-left:before{content:"\e9bc"}.icon-col-split:before{content:"\e9bd"}.icon-waterfall:before{content:"\e9a4"}.icon-manual:before{content:"\e98d"}.icon-lane:before{content:"\e9b1"}.icon-var-x:before{content:"\ea1d"}.icon-mobile:before{content:"\ea18"}.icon-clear:before{content:"\ea19"}.icon-db:before{content:"\ea17"}.icon-unpinned:before{content:"\ea08"}.icon-pinned:before{content:"\ea09"}.icon-support-ticket:before{content:"\ea04"}.icon-snap-house:before{content:"\e9e3"}.icon-wrench:before{content:"\e9e4"}.icon-desktop:before{content:"\e9e5"}.icon-back-circle:before{content:"\e9da"}.icon-back:before{content:"\e9d3"}.icon-shield:before{content:"\e9ca"}.icon-meh:before{content:"\e9ce"}.icon-frown:before{content:"\e9cf"}.icon-smile:before{content:"\e9d0"}.icon-unlock-solid:before{content:"\e9d1"}.icon-lock-solid:before{content:"\e9d2"}.icon-ver:before{content:"\e9c6"}.icon-publish:before,.icon-send:before{content:"\e9c7"}.icon-tag:before{content:"\e9be"}.icon-tag-lock:before{content:"\e9bf"}.icon-code-fork:before{content:"\f126"}.icon-branch-lock:before{content:"\e9c0"}.icon-groups:before{content:"\e9af"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-thumbs-up-solid:before{content:"\e9d6"}.icon-thumbs-down-solid:before{content:"\e9d7"}.icon-hash:before,.icon-version:before{content:"\e9ab"}.icon-p-square:before{content:"\e97b"}.icon-video-play:before{content:"\e97f"}.icon-plus-solid-circle:before{content:"\e974"}.icon-minuse-solid-circle:before{content:"\e9b6"}.icon-s:before{content:"\e975"}.icon-c:before{content:"\e976"}.icon-t:before{content:"\e977"}.icon-guide:before{content:"\e978"}.icon-todo:before{content:"\e979"}.icon-plus:before{content:"\e925"}.icon-side-left:before{content:"\e9b3"}.icon-side-right:before{content:"\e9b2"}.icon-fullscreen-exit:before{content:"\e972"}.icon-alert:before{content:"\e99f"}.icon-undo:before{content:"\e93f"}.icon-redo:before{content:"\e9d4"}.icon-swap:before{content:"\e9b0"}.icon-chat-solid:before{content:"\e9b5"}.icon-clock:before{content:"\e97c"}.icon-cost:before{content:"\e97d"}.icon-pencil-alt:before{content:"\e984"}.icon-size-height:before{content:"\e9c5"}.icon-upload-file:before{content:"\ea03"}.icon-file-log:before{content:"\e9de"}.icon-rich-text:before{content:"\e913"}.icon-markdown:before{content:"\e916"}.icon-excel:before{content:"\e933"}.icon-text-link:before{content:"\e94d"}.icon-ppt:before{content:"\e957"}.icon-word:before{content:"\e958"}.icon-doc-lib:before{content:"\e96f"}.icon-file-empty:before,.icon-file:before{content:"\f016"}.icon-file-text:before{content:"\f0f6"}.icon-file-alt:before{content:"\f15b"}.icon-file-text-alt:before{content:"\f15c"}.icon-file-pdf:before{content:"\f1c1"}.icon-file-word:before{content:"\f1c2"}.icon-file-excel:before{content:"\f1c3"}.icon-file-powerpoint:before{content:"\f1c4"}.icon-file-image:before{content:"\f1c5"}.icon-file-archive:before{content:"\f1c6"}.icon-file-audio:before{content:"\f1c7"}.icon-file-video:before{content:"\f1c8"}.icon-file-code:before{content:"\f1c9"}.icon-multi-input:before{content:"\ea1a"}.icon-cell-input:before{content:"\ea0e"}.icon-input:before{content:"\ea0f"}.icon-checkbox:before{content:"\ea10"}.icon-radio:before{content:"\ea11"}.icon-transition:before{content:"\ea12"}.icon-add-sub-chapter:before{content:"\ea13"}.icon-add-chapter:before{content:"\ea14"}.icon-menu-collapse:before{content:"\e980"}.icon-menu-expand:before{content:"\e981"}.icon-estimate:before{content:"\e9ac"}.icon-sprint:before{content:"\e9a2"}.icon-shield-check:before{content:"\e9a5"}.icon-ok:before{content:"\e9a6"}.icon-printer:before{content:"\e906"}.icon-bullhorn:before{content:"\e910"}.icon-person:before{content:"\e941"}.icon-fields:before{content:"\e989"}.icon-trigger:before{content:"\e98a"}.icon-layout:before{content:"\e98b"}.icon-audit:before{content:"\e98c"}.icon-ban-circle:before,.icon-cancel:before{content:"\e951"}.icon-eye:before{content:"\e94e"}.icon-eye-off:before{content:"\e96e"}.icon-unlock:before{content:"\e94f"}.icon-lock:before,.icon-private:before{content:"\e950"}.icon-move:before{content:"\e94c"}.icon-hand-right:before{content:"\e907"}.icon-checked:before{content:"\e908"}.icon-off:before{content:"\e909"}.icon-play:before,.icon-start:before{content:"\e90a"}.icon-time:before{content:"\e90b"}.icon-edit:before{content:"\e90c"}.icon-trash:before{content:"\e90d"}.icon-link:before{content:"\e90e"}.icon-unlink:before{content:"\e90f"}.icon-bug:before{content:"\e911"}.icon-list-alt:before{content:"\e912"}.icon-alter:before,.icon-change:before{content:"\e970"}.icon-glasses:before,.icon-review:before{content:"\e914"}.icon-sitemap:before,.icon-testcase:before{content:"\e915"}.icon-pluses:before{content:"\e917"}.icon-report-list:before{content:"\e918"}.icon-active:before,.icon-magic:before{content:"\e919"}.icon-treemap:before{content:"\e91a"}.icon-confirm:before{content:"\e91b"}.icon-split:before{content:"\e98e"}.icon-calendar:before,.icon-delay:before{content:"\e91d"}.icon-pause:before{content:"\e91e"}.icon-ban:before{content:"\e91f"}.icon-plus-bold:before{content:"\e920"}.icon-copy:before{content:"\e921"}.icon-refresh:before{content:"\e922"}.icon-diff:before{content:"\e9b7"}.status-active,.status-asked,.status-normal,.status-unconfirmed,.status-wait{color:var(--color-status-normal,#313c52)}.status-active.status-issue,.status-checking,.status-commenting,.status-confirmed,.status-doing{color:#ff6f42}.status-blocked,.status-hangup,.status-pause,.status-suspended{color:#b89664}.status-clarify,.status-draft{color:#8166ee}.status-noreview,.status-reviewing,.status-wait.status-testcase{color:#18a6fd}.status-active.status-risk,.status-changed,.status-changing,.status-fail{color:#fb2b2b}.status-checked,.status-done,.status-pass,.status-replied,.status-resolved,.status-success{color:#0dbb7d}.status-cancel,.status-canceled,.status-investigate{color:var(--color-status-cancel,#838a9d)}.status-closed,.status-testtask.status-done{color:var(--color-status-closed,#9ea3b0)}.dark{--color-status-normal:#eff1f3;--color-status-cancel:#9ea3b0;--color-status-closed:#838a9d}@media (prefers-color-scheme:dark){.dark-auto{--color-status-normal:#eff1f3;--color-status-cancel:#9ea3b0;--color-status-closed:#838a9d}}.pri,[class*=" pri-"],[class^=pri-]{border-color:currentColor;border-radius:var(--radius-full);border-width:1px;display:inline-block;font-size:.75rem;height:1rem;line-height:1rem;line-height:14px;max-width:54px;min-width:16px;overflow:hidden;padding-left:.125rem;padding-right:.125rem;text-align:center;white-space:nowrap;--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.pri-1{color:rgb(255 73 18/var(--tw-text-opacity))}.pri-1,.pri-2{--tw-text-opacity:1}.pri-2{color:rgba(var(--color-warning-600-rgb),var(--tw-text-opacity))}.pri-3{color:rgb(59 130 246/var(--tw-text-opacity))}.pri-3,.pri-4{--tw-text-opacity:1}.pri-4{color:rgb(149 211 224/var(--tw-text-opacity))}.severity{display:inline-block;font-size:.75rem;height:1rem;line-height:1rem;line-height:14px;max-width:54px;min-width:16px;overflow:hidden;padding-left:.125rem;padding-right:.125rem;position:relative;text-align:center;white-space:nowrap;--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.severity:before{background-color:currentColor;background-repeat:no-repeat;height:100%;left:0;position:absolute;top:0;width:100%;z-index:0;--tw-content:attr(data-severity);content:var(--tw-content);-webkit-mask:url('data:image/svg+xml;charset=utf-8,');mask:url('data:image/svg+xml;charset=utf-8,');-webkit-mask-size:100% 100%;mask-size:100% 100%}.severity:after,.severity:before{display:inline-block}.severity:after{--tw-scale-x:.75;--tw-scale-y:.75;content:attr(data-severity);line-height:20px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.severity[data-severity="1"]{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.severity[data-severity="2"]{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity))}.severity[data-severity="3"]{--tw-text-opacity:1;color:rgb(250 174 26/var(--tw-text-opacity))}.severity[data-severity="4"]{--tw-text-opacity:1;color:rgb(184 150 100/var(--tw-text-opacity))}.severity[data-severity="5"]{--tw-text-opacity:1;color:rgb(158 163 176/var(--tw-text-opacity))}.severity-label{background-color:transparent}.severity-label:after,.severity-label:before{--tw-content:none;content:var(--tw-content)}.risk-high{color:rgb(220 38 38/var(--tw-text-opacity))}.risk-high,.risk-middle{--tw-text-opacity:1}.risk-middle{color:rgb(234 179 8/var(--tw-text-opacity))}.label.label-id{border-radius:var(--radius-full);flex:none;--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-300-rgb),var(--tw-ring-opacity));--label-bg:rgba(var(--color-canvas-rgb),.1)}.nav-feature{--nav-active-bg:var(--color-primary-100);--nav-active-color:var(--color-fore)}.nav-feature .nav-checkbox>.checkbox,.nav-feature .nav-checkbox>.checkbox-primary,.nav-feature .nav-item>a{align-items:center;border-radius:var(--radius);height:2rem;padding-left:.625rem;padding-right:.625rem}.nav-feature .nav-item>a>.icon{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.sortable-list .listitem{cursor:move;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding-left:.5rem;padding-right:.5rem}.sortable-list .sortable-ghost>.listitem{--tw-bg-opacity:1;background-color:rgba(var(--color-warning-50-rgb),var(--tw-bg-opacity))}.sortable-empty-shadow{height:1px!important;left:0!important;opacity:0!important;pointer-events:none!important;position:absolute!important;top:0!important;width:1px!important}:root{--avatar-radius:12.5%;--avatar-bg:var(--color-surface)}.avatar{align-items:center;aspect-ratio:1/1;background:var(--avatar-bg);border-radius:var(--avatar-radius);display:inline-flex;justify-content:center;overflow:hidden;width:2rem}.avatar>img{height:100%;margin:0;-o-object-fit:cover;object-fit:cover;width:100%}.avatar.size-xs{width:1.25rem}.avatar.size-sm,.avatar.size-xs{font-size:.75rem;line-height:1rem}.avatar.size-sm{width:1.5rem}.avatar.size-lg{font-size:1.5rem;line-height:2rem;width:3rem}.avatar.size-xl{font-size:2.25rem;line-height:2.5rem;width:5rem}.avatar-group{display:flex;gap:.625rem}.avatar-group>.avatar{box-shadow:0 0 0 1px var(--color-canvas)}.avatar-group>*+*{margin-left:-1rem}.avatar-group.size-xs>*+*{margin-left:-.75rem}.avatar-group.size-sm>*+*{margin-left:-.875rem}.avatar-group.size-lg>*+*{margin-left:-1.25rem}.avatar-group.size-xl>*+*{margin-left:-1.5rem}.btn-group{display:flex;gap:1px}.btn-group>.btn.active{z-index:1}.btn-group>.btn:focus-within,.btn-group>.btn:hover{z-index:2}.btn-group>.btn.disabled,.btn-group>.btn:disabled{z-index:0}.btn-group>.btn:not(:first-child){border-bottom-left-radius:var(--radius-none);border-left-color:rgba(var(--color-canvas-rgb),.2);border-left-width:1px;border-top-left-radius:var(--radius-none)}.btn-group>.btn:not(:first-child):before{left:-1px}.btn-group>.btn:not(:last-child){border-bottom-right-radius:var(--radius-none);border-top-right-radius:var(--radius-none)}.color-picker-heading{align-items:center;font-weight:700;justify-content:space-between;margin-bottom:-.25rem;padding:.5rem}.color-picker-heading,.color-picker-row{display:flex;flex-direction:row}.color-picker-row{flex-wrap:wrap;gap:.5rem;padding:.75rem}.color-picker-item{align-items:center;border-radius:var(--radius-full);display:flex;height:1.25rem;justify-content:center;padding-left:.125rem;padding-right:.125rem;width:1.25rem;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.pick-container{left:0;pointer-events:none;position:absolute;top:0;z-index:1600}.pick-pop{display:flex;flex-direction:column;opacity:0;pointer-events:auto;position:absolute;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);z-index:1200}.pick-pop.in{opacity:1}.date-picker-menu{--menu-bg:none}.date-picker-menu .mini-calendar{margin-top:-.75rem}.date-pick-menu-month,.date-pick-menu-years{display:flex;flex-direction:row;flex-wrap:wrap;gap:1px;max-height:237px;padding-bottom:.5rem;padding-left:.5rem;padding-right:.5rem}.date-pick-menu-years>.btn{width:2.5rem}.date-pick-menu-years>.btn.is-current{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.date-pick-menu-month>.btn.active,.date-pick-menu-years>.btn.active{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.date-pick-menu-month>.btn{width:3rem}.date-picker-menu-footer{border-top-width:1px;display:flex;flex-direction:row;padding:.25rem}.date-picker-menu-footer>.toolbar{flex:1 1 auto;justify-content:center}.date-picker-menu>.menu{border-right-width:1px}.date-picker-menu .menu-item{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.time-picker-menu{max-height:inherit}.time-picker-menu .menu-item>a{justify-content:center;padding-left:0;padding-right:0;text-align:center}.datetime-picker-menu{max-height:inherit}.mini-calendar{padding:.5rem}.mini-calendar>.row>.col{align-items:center;justify-content:center;width:14.2857%}.mini-calendar-day{height:2rem}.mini-calendar-day.disabled{pointer-events:none;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-200-rgb),var(--tw-bg-opacity));opacity:.5}.mini-calendar-day>.btn{width:2rem}.mini-calendar-day.is-weekend>.btn{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.mini-calendar-day.active>.btn,.mini-calendar-day.is-today>.btn{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.mini-calendar-day.selected>.btn{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.mini-calendar-day.is-out-month{opacity:.5}.i-time{border-color:currentColor;border-radius:50%;border-width:.08em;display:inline-block;height:1em;position:relative;width:1em}.i-time:after{border-color:currentColor;border-width:0 0 .08em .08em;height:.385em;left:.3846em;position:absolute;top:.08em;width:.385em;--tw-content:"";content:var(--tw-content)}.chevron-down,.chevron-left,.chevron-right,.chevron-up{align-items:center;display:inline-flex;height:1em;justify-content:center;position:relative;width:1em}.chevron-down:before,.chevron-left:before,.chevron-right:before,.chevron-up:before{display:block;height:.6923077em;transform-origin:center;width:.6923077em;--tw-translate-y:-0.125rem;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.chevron-left:before{--tw-translate-y:0px;--tw-translate-x:0.125rem;--tw-rotate:135deg}.chevron-left:before,.chevron-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.chevron-right:before{--tw-translate-y:0px;--tw-translate-x:-0.125rem;--tw-rotate:-45deg}.chevron-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.i-calendar{border-radius:2px;display:inline-block;height:.79em;margin-top:.16em;position:relative;width:1em}.i-calendar,.i-calendar:after,.i-calendar:before{border-color:currentColor;border-width:.08em}.i-calendar:after,.i-calendar:before{position:absolute;--tw-content:"";content:var(--tw-content)}.i-calendar:before{border-bottom-width:0;left:.15em;top:.307em;width:.6em}.i-calendar:after{border-bottom-width:0;border-top-width:0;height:.3077em;left:.17em;top:-.154em;width:.538em}:root{--modal-radius:var(--radius-lg);--modal-bg:rgba(var(--color-inverse-rgb),.4);--modal-sm:37.5rem;--modal-base:50rem;--modal-lg:75rem;--modal-xl:90rem}.modal{align-items:center;background-color:var(--modal-bg);bottom:0;display:none;justify-content:center;left:0;overflow:hidden;position:fixed;right:0;top:0;z-index:1500}.modal.load-indicator:before{background-color:transparent;transition-property:none}.modal.loading:after{--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.modal.loading .modal-dialog{opacity:0!important}.modal.show{display:flex}.modal-no-backdrop{background-color:transparent;pointer-events:none}.modal-hide{opacity:0!important}.modal-dialog{background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));pointer-events:auto;position:relative;--tw-bg-opacity:0.9;--tw-shadow:0 10px 50px -10px rgba(0,0,0,.4),0 8px 20px -10px rgba(0,0,0,.3);--tw-shadow-colored:0 10px 50px -10px var(--tw-shadow-color),0 8px 20px -10px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05;--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);border-radius:var(--modal-radius);width:var(--modal-base)}.modal-content,.modal-dialog{max-height:100vh}.modal-content{display:flex;flex-direction:column;height:100%}.loading>.modal-dialog>.modal-content{opacity:0;visibility:hidden}.modal-dialog.loading{background-color:transparent}.modal-dialog.loading>.modal-content{display:none}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.modal-header{align-items:center;display:flex;flex:none;flex-wrap:nowrap;gap:1rem;padding:1rem 1.25rem;position:relative}.modal-title{flex:1 1 auto;font-size:1rem;font-weight:700;line-height:1.5rem}.modal-actions{position:absolute;right:.75rem;top:.75rem;z-index:15}.modal-body{flex:1 1 auto;overflow:auto;padding:1rem 1.25rem}.modal-footer{align-items:center;display:flex;flex:none;gap:.75rem;padding:1.25rem}.modal-dialog.size-full,.modal-dialog[data-size=full]{border-radius:var(--radius-none);height:100vh;width:100vw}.modal-dialog.size-sm,.modal-dialog[data-size=sm]{width:var(--modal-sm)}.modal-dialog.size-lg,.modal-dialog[data-size=lg]{width:var(--modal-lg)}.modal-dialog.size-xl,.modal-dialog[data-size=xl]{width:var(--modal-xl)}.modal-iframe{flex:1 1 auto;width:100%}.modal-trans{opacity:0;transition-duration:.2s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.modal-trans.in{opacity:1}.modal-trans>.modal-dialog{transition-property:transform,opacity;--tw-scale-x:.95;--tw-scale-y:.95;opacity:0;transition-duration:.3s}.modal-trans.in>.modal-dialog,.modal-trans>.modal-dialog{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-trans.in>.modal-dialog{--tw-scale-x:1;--tw-scale-y:1;opacity:1}.modal-alert .modal-footer{justify-content:flex-end}.modal-alert .modal-header{margin-bottom:-1rem}.modal-alert .modal-body{overflow-wrap:break-word;white-space:pre-line}.modal-alert .modal-actions+.modal-body{padding-right:3rem}.modal-alert .modal-header+.modal-actions+.modal-body{padding-right:1.25rem}.file-selector{gap:.5rem;width:100%}.file-selector,.file-selector-box{display:flex;flex-direction:column}.file-selector-box{border-style:dashed;border-width:1px;gap:0;height:auto;justify-content:center;position:relative;--tw-border-opacity:1;background-color:rgba(var(--color-primary-50-rgb),.3);border-color:rgba(var(--color-primary-400-rgb),var(--tw-border-opacity));padding:.5rem .75rem;--tw-ring-color:transparent;--state-color:rgba(var(--color-primary-500-rgb),.05)}.file-selector-box .text{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.is-dragging .file-selector-box{border-style:solid}.file-selector-btn{align-items:center;display:flex;gap:.5rem;position:relative}.is-dragging .file-selector-btn{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.file-selector-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;bottom:0;cursor:pointer;left:0;opacity:.1;position:absolute;right:0;top:0}.file-selector-tip{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.file-selector.is-mode-button{flex-direction:column-reverse}.file-selector-list.is-empty{display:none}.file-selector-item .item-avatar{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.file-selector-item .item-subtitle{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.file-selector-item .item-content{flex:none;margin-right:.25rem;max-width:100%}.file-selector-item>.listitem:hover{background-color:rgba(var(--color-gray-500-rgb),.05)}.file-selector-item.is-renaming .item-avatar+.item-content{max-width:calc(100% - 32px)}.file-selector-rename-text{max-width:100%;min-width:100px;position:relative}.file-selector-rename-text>div{overflow:hidden;pointer-events:none;visibility:hidden;white-space:nowrap}.file-selector-rename-input{bottom:0;left:0;position:absolute;right:0;top:0}.file-selector-grid{align-items:flex-start;border-color:transparent;border-radius:var(--radius);border-width:1px;display:flex;flex-direction:row;flex-wrap:wrap;gap:var(--file-selector-grid-gap);--tw-bg-opacity:1;background-color:rgba(var(--color-surface-light-rgb),var(--tw-bg-opacity));padding:.5rem}.file-selector-grid-item{height:var(--file-selector-grid-height)}.file-selector-grid-btn,.file-selector-grid-item{width:var(--file-selector-grid-width)}.file-selector-grid-btn{aspect-ratio:1/1;border-style:dashed;border-width:1px;display:flex;flex-direction:column;gap:0;height:auto;justify-content:center;--tw-border-opacity:1;background-color:rgba(var(--color-primary-50-rgb),.3);border-color:rgba(var(--color-primary-400-rgb),var(--tw-border-opacity));padding:.5rem;--tw-ring-color:transparent;--state-color:rgba(var(--color-primary-500-rgb),.05)}.file-selector-grid-btn .text{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.file-selector-grid-item .listitem{flex-direction:column;height:100%;padding:0;position:relative;width:100%}.file-selector-grid-item .item-avatar{border-radius:var(--radius);border-width:1px;width:100%;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.file-selector-grid-item .item-avatar.has-icon>.icon{font-size:calc(var(--file-selector-grid-width)/2)}.file-selector-grid-item .item-content,.file-selector-grid-item .toolbar{aspect-ratio:1/1;left:0;position:absolute;right:0;top:0;width:100%}.file-selector-grid-item .item-title{bottom:-1.25rem;font-size:.75rem;left:0;line-height:1rem;overflow:hidden;position:absolute;right:1.5rem;white-space:nowrap}.file-selector-grid-item .item-subtitle{border-radius:var(--radius-full);bottom:.25rem;left:.25rem;position:absolute;--tw-bg-opacity:1;background-color:rgba(var(--color-fore-rgb),var(--tw-bg-opacity));font-size:.75rem;line-height:1rem;padding-left:.25rem;padding-right:.25rem;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));opacity:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.file-selector-grid-item:hover .item-subtitle{opacity:1}.file-selector-grid-item .toolbar .btn[data-remove-file]{background-color:rgba(var(--color-inverse-rgb),.5);padding:.375rem;position:absolute;right:1px;top:1px;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.file-selector-grid-item .toolbar .btn[data-rename-file]{bottom:-1.5rem;padding:0;position:absolute;right:0}.file-selector-grid .file-selector-rename{bottom:0;height:1.5rem;position:absolute;top:auto}.file-selector-grid .file-selector-rename-text{width:100%}.is-dragging .file-selector-grid{border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-primary-400-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}:root{--nav-radius:var(--radius);--nav-active-color:var(--color-primary-500);--nav-active-bg:var(--color-inherit);--nav-heading-color:var(--color-gray-500);--nav-gap:0.25rem;--nav-item-color:inherit;--nav-item-bg:transparent;--nav-item-padding:1rem;--nav-item-height:2rem;--nav-item-gap:0.75rem;--nav-divider-height:calc(var(--nav-item-height)/2);--nav-divider-margin:0.5rem}.nav{list-style-type:none;padding-left:0}.nav,.nav-item{align-items:center;display:flex;position:relative}.nav-item{gap:var(--nav-item-gap)}.nav-item>a{align-items:center;background-color:var(--nav-item-bg);color:var(--nav-item-color);cursor:pointer;display:flex;gap:var(--nav-gap);height:var(--nav-item-height);justify-content:center;padding-left:var(--nav-item-padding);padding-right:var(--nav-item-padding)}.nav-item>a>.text{white-space:nowrap}.nav-item>.active{font-weight:700;--nav-item-color:var(--nav-active-color);--nav-item-bg:var(--nav-active-bg)}.nav-item>.selected{--nav-item-color:var(--nav-selected-color);--nav-item-bg:var(--nav-selected-bg)}.nav-item>.disabled{--nav-item-color:var(--nav-disabled-color);--nav-item-bg:var(--nav-disabled-bg)}.nav-item>.disabled>*{opacity:var(--opacity-disabled)}.nav-divider,.nav>.divider{align-self:center;height:var(--nav-divider-height);margin-left:var(--nav-divider-margin);margin-right:var(--nav-divider-margin)}.nav-heading{align-items:center;color:var(--nav-heading-color);display:flex;font-weight:700;gap:.25rem;height:2rem;justify-content:center;padding-left:1rem;padding-right:1rem}.nav-space{flex:1 1 auto;width:1rem}.nav-compact{--nav-gap:0.25rem;--nav-item-gap:0.5rem;--nav-item-height:1.75rem;--nav-item-padding:0.5rem;--nav-divider-margin:0.25rem}.nav-primary>.nav-item{position:relative}.nav-primary>.nav-item:hover{z-index:10}.nav-primary>.nav-item+.nav-item{margin-left:-1px}.nav-primary>.nav-item>a{border-radius:var(--radius-none);border-width:1px}.nav-primary>.nav-item:first-child>a,.nav-primary>.nav-item:has(.nav-heading)+.nav-item>a{border-bottom-left-radius:var(--nav-radius);border-top-left-radius:var(--nav-radius)}.nav-primary>.nav-item:last-child>a{border-bottom-right-radius:var(--nav-radius);border-top-right-radius:var(--nav-radius)}.nav-primary>.nav-item>.active{--tw-text-opacity:1;background:var(--nav-active-color);border-color:var(--nav-active-color);color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.nav-primary>.nav-divider{display:none}.nav-secondary>.nav-item>a{border-radius:var(--radius-none);position:relative}.nav-secondary>.nav-item>a:after{bottom:-2px;display:block;height:2px;left:0;position:absolute;right:0;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity));--tw-content:"";content:var(--tw-content)}.nav-secondary>.nav-item>.active:after{background-color:currentColor}.nav-secondary>.nav-divider{margin:0 0 0 -1px}.nav-tabs>.nav-item>a{border-bottom-left-radius:var(--radius-none);border-bottom-right-radius:var(--radius-none);position:relative}.nav-tabs>.nav-item>a:after{border-color:transparent;border-width:1px;bottom:-1px;display:block;left:-1px;pointer-events:none;position:absolute;right:-1px;top:-1px;--tw-border-opacity:1;border-bottom-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));--tw-content:"";border-top-left-radius:inherit;border-top-right-radius:inherit;content:var(--tw-content)}.nav-tabs>.nav-item>.active:after{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));border-bottom-color:transparent}.nav-tabs>.nav-divider{margin:0 0 0 -1px}.nav-pills>.nav-item>a{border-radius:var(--radius-full)}.nav-pills>.nav-item>.active{--tw-text-opacity:1;background:var(--nav-active-color);border-color:var(--nav-active-color);color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.nav-steps{--nav-item-bg:var(--color-canvas);--nav-active-bg:var(--color-primary-500);--nav-active-color:var(--color-canvas);--nav-selected-bg:var(--color-secondary-500);--nav-selected-color:var(--color-canvas)}.nav-steps>.nav-item+.nav-item>a{padding-left:calc(var(--nav-item-padding) + var(--nav-item-height)/3)}.nav-steps>.nav-item>a:after,.nav-steps>.nav-item>a:before{border-style:solid;height:0;left:100%;position:absolute;width:0;z-index:2;--tw-content:"";border-color:transparent;border-left-color:var(--nav-item-bg,var(--color-canvas));border-width:calc(var(--nav-item-height)/2);border-left-width:calc(var(--nav-item-height)/3);border-right-width:0;content:var(--tw-content)}.nav-steps>.nav-item>a:before{background-color:transparent!important;border-left-color:var(--color-border);bottom:auto;left:calc(100% + 5.5px);opacity:1!important;right:auto;top:.4rem;transform:none;z-index:1;--nav-item-height:1.2rem}.nav-steps>.nav-item:has(+.nav-item>.active)>.selected:before,.nav-steps>.nav-item:has(+.nav-item>.active,+.nav-item>.selected)>a:not(.active,.selected):before,.nav-steps>.nav-item:has(+.nav-item>.selected)>.active:before,.nav-steps>.nav-item:last-child>a:after,.nav-steps>.nav-item:last-child>a:before{display:none}.nav-steps>.nav-item>a:hover{--nav-item-bg:var(--color-gray-100)}.nav-steps>.nav-item>.active:hover{--nav-item-bg:var(--color-primary-600)}.nav-steps>.nav-item>.selected:hover{--nav-item-bg:var(--color-secondary-600)}.nav-stacked{flex-direction:column}.nav-stacked>.nav-item{width:100%}.nav-stacked>.nav-heading,.nav-stacked>.nav-item>a{justify-content:flex-start;width:100%}.nav-stacked>.nav-divider{height:1px;margin:.5rem 0;width:100%}.nav-primary.nav-stacked>.nav-item>a{height:2.5rem}.nav-primary.nav-stacked>.nav-item+.nav-item{margin-left:0;margin-top:-1px}.nav-primary.nav-stacked>.nav-item:first-child>a{border-bottom-left-radius:0;border-top-left-radius:var(--nav-radius);border-top-right-radius:var(--nav-radius)}.nav-primary.nav-stacked>.nav-item:last-child>a{border-bottom-left-radius:var(--nav-radius);border-bottom-right-radius:var(--nav-radius);border-top-right-radius:0}.nav-secondary.nav-stacked>.nav-item>a:after{bottom:0;height:100%;left:auto;right:0;top:0;width:2px;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity))}.nav-secondary.nav-stacked>.nav-item>.active:after{background-color:currentColor}.nav-secondary.nav-stacked>.nav-divider{margin:0}.nav-tabs.nav-stacked>.nav-item>a{border-bottom-left-radius:var(--nav-radius);border-bottom-right-radius:var(--radius-none);border-top-right-radius:var(--radius-none);position:relative}.nav-tabs.nav-stacked>.nav-item>a:after{--tw-border-opacity:1;border-bottom-color:transparent;border-bottom-left-radius:inherit;border-right-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));border-top-left-radius:inherit}.nav-tabs.nav-stacked>.nav-item>a.active:after{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));border-right-color:transparent}.nav-tabs.nav-stacked>.nav-divider{margin:0}.nav-pills.nav-stacked>.nav-item+.nav-item{margin-top:.25rem}.nav-justified>.nav-item:not(.flex-none,.nav-divider){flex:1 1 auto}.nav-justified>.nav-item>a{width:100%}.arrow,.arrow:before{background:inherit;height:calc(var(--arrow-size)*1.4142);position:absolute;width:calc(var(--arrow-size)*1.4142)}.arrow{visibility:hidden;--arrow-size:5px}.arrow:before{border:inherit;content:"";visibility:visible;--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.arrow-top,.arrow-up{border-bottom:inherit;border-right:inherit;border-width:1px 0 0 1px;top:calc(1px - var(--arrow-size))}.white>.arrow-top,.white>.arrow-up{top:calc(0px - var(--arrow-size))}.arrow-bottom,.arrow-down{border-left:inherit;border-top:inherit;border-width:0 1px 1px 0;bottom:calc(1px - var(--arrow-size))}.white>.arrow-bottom,.white>.arrow-down{bottom:calc(0px - var(--arrow-size))}.arrow-left{border-right:inherit;border-top:inherit;border-width:0 0 1px 1px;left:calc(1px - var(--arrow-size))}.white>.arrow-left{left:calc(0px - var(--arrow-size))}.arrow-right{border-bottom:inherit;border-left:inherit;border-width:1px 1px 0 0;right:calc(1px - var(--arrow-size))}.white>.arrow-right{right:calc(0px - var(--arrow-size))}.popover{display:none;left:0;position:absolute;top:0;width:-moz-max-content;width:max-content}.popover.show{display:block}.popover-heading{align-items:center;border-top-left-radius:inherit;border-top-right-radius:inherit;display:flex;gap:1rem;height:2.5rem;justify-content:space-between;position:relative;z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding-left:.75rem;padding-right:.5rem}.popover-title{flex:1 1 auto;font-weight:700}.popover-content{padding:.75rem;position:relative;z-index:1}.popover-arrow{z-index:0}.has-heading>.popover-arrow.arrow-top,.has-heading>.popover-arrow.arrow-up{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity))}.popover>.btn-close{position:absolute;right:.5rem;top:.625rem;z-index:2}.btn-close+.popover-content{padding-right:3rem}.btn.with-popover-show{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.with-popover-show[data-pop-placement=top]>.caret{--tw-rotate:180deg}.with-popover-show[data-pop-placement=left]>.caret,.with-popover-show[data-pop-placement=top]>.caret{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.with-popover-show[data-pop-placement=left]>.caret{--tw-rotate:90deg}.with-popover-show[data-pop-placement=right]>.caret{--tw-rotate:-90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.pager{align-items:center;display:flex;gap:.25rem;white-space:nowrap}.menu.pager-size-menu{display:grid!important;grid-template-columns:repeat(3,minmax(0,1fr));text-align:center}.menu.pager-size-menu>.menu-item>a{margin:.125rem}.pager .pager-goto-group>.form-control{width:3rem}.pager .pager-goto-group>.input-group-addon{border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-gray-300-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.pager>.pager-nav.active{--tw-text-opacity:1;box-shadow:0 0 0 1px var(--color-primary-500);color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.panel{border-radius:var(--radius);overflow:hidden;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05}.panel-heading{background-color:var(--panel-heading-bg);flex-wrap:nowrap;gap:1rem;justify-content:space-between;padding:.5rem 1rem}.panel-heading,.panel-title{align-items:center;display:flex}.panel-title{font-weight:700;gap:.5rem;margin:0}.panel-actions{align-items:center;display:flex;margin-right:-.5rem}.panel-body{padding:.75rem 1rem}.panel-footer{align-items:center;background-color:var(--panel-footer-bg);display:flex;gap:.5rem;padding:.5rem 1rem}.size-sm .panel-body,.size-sm .panel-footer,.size-sm .panel-heading{padding:.375rem .75rem}.size-lg .panel-body,.size-lg .panel-footer,.size-lg .panel-heading{padding:1rem 1.25rem}.picker{position:relative}.picker-select{align-items:center;gap:.25rem;justify-content:space-between}.picker-select,.picker-select.form-control{display:flex}.picker-select-placeholder{flex:1 1 auto;--tw-text-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-text-opacity))}.picker-select-multi .picker-select-placeholder{padding-left:.25rem;padding-right:.25rem}.picker-single-selection{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap}.picker-deselect-btn{border-radius:var(--radius-full);padding:.25rem}.picker-deselect-btn:not(:hover){opacity:.7}.picker-select-multi.form-control{height:auto;min-height:32px;padding-left:.25rem}.picker-multi-selections{display:flex;flex-wrap:wrap;gap:.25rem;min-width:0}.picker-multi-selection{align-items:center;border-radius:var(--radius-full);border-width:1px;display:flex;max-width:100%;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding-left:.5rem}.readonly .picker-multi-selection{padding-right:.5rem}.picker-multi-selection>.text{max-width:180px;min-width:0;overflow:clip;white-space:nowrap}.picker-no-search{cursor:default}.picker-menu-list{border-style:none;flex:1 1 auto;min-height:0;overflow-y:auto;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.picker-menu-search+.picker-menu-list.menu{margin-top:-.125rem;padding-top:0}.picker-menu-list.tree{padding:.5rem}.picker-menu-list .tree-item>.selected .item-content{font-weight:400}.picker-menu .search-menu-footer{border-top-width:1px;padding-bottom:.25rem;padding-top:.25rem}.picker-search-input{border-color:transparent;height:1.75rem;outline-width:0!important;padding-left:0;padding-right:2rem;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)!important}.picker-search{flex:none;position:relative;width:100%}.picker-search>.magnifier{opacity:.5;position:absolute;right:0;top:.5rem}.picker-search-clear.btn{cursor:pointer;height:1.25rem;position:absolute;right:0;top:.25rem;width:1.25rem}.picker-search.is-inline{min-width:64px;width:4rem}.is-inline>.picker-search-input{height:1.25rem;min-width:64px;padding-left:.25rem;padding-right:.25rem}.picker-search-measure{height:0;left:0;overflow:hidden;position:absolute;top:0;white-space:nowrap}.split{display:flex;flex-direction:row}.split-vert{flex-direction:column}.split-cell{min-height:0;min-width:0}.has-animation>.split-cell{transition-duration:.15s;transition-property:width,height;transition-timing-function:cubic-bezier(.4,0,.2,1)}.gutter{align-items:stretch;border-radius:var(--radius);cursor:col-resize;display:flex;flex:none;flex-direction:row;justify-content:center;position:relative}.gutter-vert{cursor:row-resize;flex-direction:column}.gutter:before{display:block;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity));transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);--tw-content:"";content:var(--tw-content)}.gutter-horz:before{width:1px}.gutter-vert:before{height:1px}.gutter-horz:hover:before{width:75%}.gutter-vert:hover:before{height:75%}.gutter-resize-handler,.gutter-toggle{align-items:center;border-radius:var(--radius-lg);border-width:1px;display:flex;height:1.75rem;justify-content:center;margin-top:-.875rem;position:absolute;top:50%;width:.75rem;--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity));transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.gutter-toggle>span{--tw-scale-x:.75;--tw-scale-y:.75;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.gutter:hover .gutter-toggle{--tw-border-opacity:1;border-color:rgba(var(--color-gray-500-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.gutter .gutter-toggle:hover{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.is-last>.gutter-toggle{--tw-scale-x:-1}.is-first>.gutter-toggle,.is-last>.gutter-toggle{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.is-first>.gutter-toggle{--tw-scale-x:1}.gutter-vert .gutter-toggle{left:50%;margin-left:-.375rem;margin-top:0;top:auto;--tw-rotate:90deg}.gutter-vert .gutter-toggle,.gutter.is-next-collapsed>.gutter-toggle{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.gutter.is-next-collapsed>.gutter-toggle{--tw-scale-x:1}.gutter.is-prev-collapsed>.gutter-toggle{--tw-scale-x:-1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.gutter-horz.is-first.is-prev-collapsed{transform:translateX(calc(-1px - var(--split-gutter-size)/2))}.gutter-horz.is-last.is-next-collapsed{transform:translateX(calc(1px + var(--split-gutter-size)/2))}.gutter-vert.is-first.is-prev-collapsed{transform:translateY(calc(-1px - var(--split-gutter-size)/2))}.gutter-vert.is-last.is-next-collapsed{transform:translateY(calc(1px + var(--split-gutter-size)/2))}.gutter-resize-handler{background-color:transparent;border-width:0}.gutter-resize-handler:before{border-left-width:1px;border-right-width:1px;bottom:0;left:.25rem;position:absolute;right:.25rem;top:0;--tw-content:"";content:var(--tw-content)}.sidebar{flex:none!important;position:relative;--gutter-width:1px;--sidebar-duration:200ms}.has-sidebar-animation .sidebar{transition-duration:.15s;transition-duration:var(--sidebar-duration);transition-property:width,margin;transition-timing-function:cubic-bezier(.4,0,.2,1)}.sidebar-left.is-collapsed{margin-left:calc(var(--gutter-width)*-1)}.sidebar-right.is-collapsed{margin-right:calc(var(--gutter-width)*-1)}.sidebar.is-collapsed>*,.sidebar.is-expanded.is-animating>*{display:none}.sidebar.is-collapsed>.sidebar-gutter{display:flex!important}.sidebar-gutter{bottom:0;left:100%;position:absolute;top:0;width:var(--gutter-width);z-index:10}.sidebar-right>.sidebar-gutter{left:auto;right:100%}.is-collapsed>.gutter>.gutter-toggle>span{--tw-rotate:-180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.sidebar-gutter:before{border-radius:var(--radius-full);opacity:0}.sidebar-gutter:hover:before{opacity:1;width:.5rem}.is-expanded .sidebar-gutter.gutter-border:before{opacity:1}.is-sidebar-resizing{cursor:col-resize}:root{--table-head-bg:var(--color-surface);--table-striped-color:var(--color-gray-50);--table-hover-color:rgba(var(--color-primary-500-rgb),.05);--table-border-color:var(--color-border)}.table{border-color:var(--table-border-color);width:100%}.table>thead{background-color:var(--table-head-bg)}.table>*>tr{border-bottom-width:1px}.table>*>tr>*{padding:.5rem 1rem}.table-striped>tbody>tr:nth-child(2n){background:var(--table-striped-color)}.table-hover>tbody>tr:hover>*{background:var(--table-hover-color)}.table.bordered>*>tr>*{border-width:1px}.table.borderless>*>tr,.table.borderless>*>tr>*{border-style:none}.condensed>*>tr>*{padding:.375rem .75rem}.table-fixed{table-layout:fixed}.table-fixed>*>tr>*{overflow:hidden;white-space:nowrap}.toolbar{align-items:center;display:flex;position:relative}.toolbar>.divider{margin:.5rem;width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity))}.toolbar-space{flex:1 1 auto;height:1px;width:1px}.toolbar>.dropdown.show{align-items:center;display:flex;position:relative}:root{--tooltip-bg:var(--skin-color,var(--color-inverse));--tooltip-text:var(--skin-text,var(--color-canvas));--tooltip-arrow:6px;--tooltip-delay:0.5s}.hint,[class*=" hint-"],[class^=hint-]{position:relative}.hint:before,[class*=" hint-"]:before,[class^=hint-]:before{border-style:solid;height:0;position:absolute;width:0;--tw-content:"";border-color:var(--tooltip-bg) transparent transparent transparent;border-width:var(--tooltip-arrow) var(--tooltip-arrow) 0 var(--tooltip-arrow);content:var(--tw-content);margin-bottom:calc(0px - var(--tooltip-arrow))}.hint:after,[class*=" hint-"]:after,[class^=hint-]:after{background-color:var(--tooltip-bg);border-color:var(--tooltip-color);border-radius:var(--radius);color:var(--tooltip-text);font-size:.75rem;line-height:1rem;max-width:28rem;overflow:hidden;padding:.25rem .5rem;position:absolute;white-space:nowrap;--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-content:attr(data-hint);content:var(--tw-content);text-shadow:0 1px 0 var(--tooltip-bg)}.hint:after,.hint:before,[class*=" hint-"]:after,[class*=" hint-"]:before,[class^=hint-]:after,[class^=hint-]:before{bottom:100%;left:50%;opacity:0;pointer-events:none;transition-delay:0s;transition-duration:.15s;transition-property:opacity,visibility;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,1,1);visibility:hidden;z-index:1800;--tw-translate-x:-50%;--tw-translate-y:calc(var(--tooltip-arrow)*-1);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint:hover:after,.hint:hover:before,[class*=" hint-"]:hover:after,[class*=" hint-"]:hover:before,[class^=hint-]:hover:after,[class^=hint-]:hover:before{opacity:1;transition-delay:var(--tooltip-delay);visibility:visible}.hint-bottom:before{border-color:transparent transparent var(--tooltip-bg) transparent;border-width:0 var(--tooltip-arrow) var(--tooltip-arrow) var(--tooltip-arrow);margin-bottom:auto;margin-top:calc(0px - var(--tooltip-arrow))}.hint-bottom:after,.hint-bottom:before{bottom:auto;top:100%;--tw-translate-y:var(--tooltip-arrow);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint-left:before{border-color:transparent transparent transparent var(--tooltip-bg);border-width:var(--tooltip-arrow) 0 var(--tooltip-arrow) var(--tooltip-arrow);margin-bottom:auto;margin-right:calc(0px - var(--tooltip-arrow))}.hint-left:after,.hint-left:before{bottom:50%;left:auto;right:100%;--tw-translate-x:calc(var(--tooltip-arrow)*-1);--tw-translate-y:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint-right:before{border-color:transparent var(--tooltip-bg) transparent;border-width:var(--tooltip-arrow) var(--tooltip-arrow) var(--tooltip-arrow) 0;margin-bottom:auto;margin-left:calc(0px - var(--tooltip-arrow))}.hint-right:after,.hint-right:before{bottom:50%;left:100%;--tw-translate-x:var(--tooltip-arrow);--tw-translate-y:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint-lg:after,.hint-sm -.hint-md:after:after,.hint-xl:after{white-space:normal;word-break:break-all}.hint-sm:after{width:4rem}.hint-md:after{width:8rem}.hint-lg:after{width:16rem}.hint-xl:after{width:24rem}.hint-primary{--tooltip-bg:var(--color-primary-500)}.hint-success{--tooltip-bg:var(--color-success-500)}.hint-danger{--tooltip-bg:var(--color-danger-500)}.hint-warning{--tooltip-bg:var(--color-warning-500)}.hint-important{--tooltip-bg:var(--color-important-500)}.hint-special{--tooltip-bg:var(--color-special-500)}.tooltip{background-color:var(--tooltip-bg);border-color:var(--tooltip-color);border-radius:var(--radius);color:var(--tooltip-text);font-size:.75rem;line-height:1rem;max-width:28rem;padding:.25rem .5rem;white-space:pre-wrap;z-index:1800}.tooltip:not(.white)>.arrow{border-width:0}.tooltip.white>.arrow{border-color:inherit}.tooltip-has-title{--tw-bg-opacity:0.8;padding:.5rem .75rem .75rem;--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.tooltip-has-title>.arrow{opacity:.75}.tooltip-heading{align-items:center;display:flex;font-size:.8125rem;font-weight:700;gap:1rem;justify-content:space-between;line-height:1.25rem;padding:.25rem}.tooltip-heading>.btn-close{margin-right:-.25rem}.tooltip-content{padding:.25rem}.tree-item-inner{flex-direction:row;min-height:24px;padding-left:var(--list-nested-indent)}.tree-item-inner,.tree-toggle{align-items:center;display:flex}.tree-toggle{border-radius:var(--radius);flex:none;height:1rem;justify-content:center;margin-right:-.375rem;width:1rem;--caret-size:5px;--caret-opacity:.3}.tree-item-inner>.item-icon{opacity:.5;width:1rem}.tree-item-inner:hover>.item-icon{opacity:.8}.tree-item-inner.has-hover{border-radius:var(--radius)}.tree-item-inner .item-title:not(:hover),.tree-item-inner>a.item-title:not(:hover){color:inherit}.tree-item-inner>.toolbar{margin-left:1rem;opacity:.6}.tree-item-inner:hover>.toolbar{opacity:1}.tree-item>.active{background:var(--menu-active-bg);color:var(--menu-active-color)}.tree-item>.selected{background:var(--menu-selected-bg)}.tree-item>.selected .item-content{color:var(--menu-selected-color);font-weight:700}.tree.search-menu-on-top>.search-box{left:0;right:0}.tree-lines .tree{position:relative}.tree-lines .tree-item{--tree-line-indent:calc(var(--list-nested-indent) + 8px)}.tree-lines .tree:before{border-left-width:1px;bottom:.5rem;display:block;left:var(--tree-line-indent);position:absolute;top:-.5rem;--tw-content:"";content:var(--tw-content)}.upload .upload-tip{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.upload .draggable-area{background-color:rgba(var(--color-primary-50-rgb),.2);border:1px dashed var(--color-primary-300)}.upload .draggable-area.dragover{background-color:rgba(var(--color-primary-500-rgb),.1);border-style:solid}.upload .upload-tip{color:var(--color-slate-500)}.file-item>.img{height:120px;width:120px}.upload .file-item:hover .file-size{display:flex!important}.form-batch-container{overflow-y:auto}.form-batch-table{min-width:100%;table-layout:fixed;--table-head-bg:var(--color-canvas)}.form-batch-table>*>tr{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.form-batch-table>*>tr>*{padding-left:.375rem;padding-right:.375rem;vertical-align:top}.form-batch-table>*>tr>th{text-align:left;vertical-align:middle}.form-batch-head[data-name=ACTIONS]{width:5rem}.form-batch-head[data-name=ACTIONS][data-action-count="3"]{width:6rem}.form-batch-label{display:inline}.form-batch-control>textarea.form-control{height:2rem}.form-batch-btn+.btn{margin-left:.25rem}.form-batch-table>tbody[data-count="1"] .form-batch-btn[data-type=delete]{display:none}.form-batch-ditto{position:relative}.form-batch-ditto-btn{bottom:0;height:auto;opacity:.5;padding-left:.5rem;padding-right:.5rem;position:absolute!important;right:0;top:0}.form-batch-ditto-btn:after{bottom:.5rem;left:-1px;position:absolute;top:.5rem;width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity));--tw-content:"";content:var(--tw-content)}[data-ditto=on] .form-batch-ditto-btn{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity));opacity:1}td.form-batch-row-actions{padding-bottom:.75rem!important;padding-top:.75rem!important}.form-batch-ditto-wrapper{position:relative}.form-batch-ditto-control .form-control,.form-batch-ditto-control .pick-pri{padding-right:calc(var(--form-batch-ditto-width) + 8px)}.form-batch-ditto-control .input-control>.input-control-suffix{right:var(--form-batch-ditto-width)}.form-batch-ditto-control .input-control>.form-control{padding-right:calc(var(--form-batch-ditto-width) + var(--input-control-suffix))}.has-fixed-actions .form-batch-col-actions{position:sticky;right:0;z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.form-batch-col-actions.is-pinned:before{background-image:linear-gradient(-90deg,transparent,transparent),linear-gradient(-90deg,transparent,transparent 50%);border-right-width:1px;bottom:0;content:" ";display:block;left:-1rem;position:absolute;top:0;transition-duration:.15s;transition-property:background;transition-timing-function:cubic-bezier(.4,0,.2,1);width:1rem;z-index:1}.form-batch:hover .form-batch-col-actions.is-pinned:before{background-image:linear-gradient(-90deg,rgba(0,0,0,.03),transparent),linear-gradient(-90deg,rgba(0,0,0,.03),transparent 50%)}.panel-form-batch .form-batch-container .form-batch-col-actions.is-pinned:after{bottom:0;display:block;position:absolute;right:-1rem;top:0;width:1rem;z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));content:" "}.datalist{--datalist-label-width:68px}.datalist-item{display:flex;gap:.5rem;padding-bottom:.375rem;padding-top:.375rem}.datalist-item-label{align-items:center;display:flex;flex:none;justify-content:flex-end;overflow:hidden;white-space:nowrap;width:var(--datalist-label-width);--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.datalist-item-content{align-items:center;display:flex;flex:1 1 0%;gap:.5rem}.scrollbar,:root{--scrollbar-size:10px;--scrollbar-opacity:.6;--scrollbar-bg:rgba(var(--color-inverse-rgb),.15);--scrollbar-inset:inset 0 0 0 1px rgba(var(--color-inverse-rgb),.05);--scrollbar-bar-bg:rgba(var(--color-inverse-rgb),.3);--scrollbar-hover-bg:rgba(var(--color-inverse-rgb),.4);--scrollbar-drag-bg:rgba(var(--color-inverse-rgb),.5);--scrollbar-radius:var(--radius-sm);--scrollbar-duration:.7s}.scrollbar{background:var(--scrollbar-bg);box-shadow:var(--scrollbar-shadow);opacity:var(--scrollbar-opacity);position:absolute;transition-duration:.15s;transition-duration:var(--scrollbar-duration);transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.scrollbar-hover .scrollbar{opacity:0}.scrollbar-hover:hover .scrollbar{opacity:var(--scrollbar-opacity)}.scrollbar.is-dragging,.scrollbar:hover{opacity:1!important}.scrollbar-bar{background:var(--scrollbar-bar-bg);border-radius:var(--scrollbar-radius);position:absolute}.scrollbar-bar:hover{background:var(--scrollbar-hover-bg)}.is-dragging>.scrollbar-bar{background:var(--scrollbar-drag-bg)}.is-horz>.scrollbar-bar{height:100%;z-index:20}.is-vert>.scrollbar-bar{width:100%;z-index:20}.affine-theme,.affine-theme [data-theme=dark],.affine-theme [data-theme=light]{--affine-brand-color:var(--color-primary-500);--affine-primary-color:var(--color-primary-500);--affine-text-primary-color:var(--color-fore)}.blocksuite-portal{position:absolute!important}.embed-card-modal-mask{z-index:12!important}.embed-card-modal-wrapper{z-index:13!important}.affine-code-block-container .line-number{opacity:.5}@-moz-document url-prefix(){.affine-code-block-container v-line{width:100%}}.embed-zui-iframe{border-radius:var(--radius-lg);border-width:1px}affine-bookmark .affine-block-component{border-width:0}.is-editor-empty.is-editing .affine-block-children-container>affine-paragraph:first-child .affine-paragraph-placeholder:not(.visible){display:block!important}database-datasource-note-renderer{display:none!important}.editor-is-exporting audio,.editor-is-exporting canvas,.editor-is-exporting embed,.editor-is-exporting iframe,.editor-is-exporting img,.editor-is-exporting object,.editor-is-exporting svg,.editor-is-exporting video{display:initial!important}body>.affine-modal{align-items:center;background-color:var(--modal-bg);bottom:0!important;display:flex;justify-content:center;left:0!important;position:fixed!important;right:0!important;top:0!important}body>.affine-modal>center-peek{left:auto;max-width:1200px;position:relative;top:auto;--tw-shadow:0 0 #0000!important;--tw-shadow-colored:0 0 #0000!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}body>.affine-modal affine-data-view-record-detail{border-radius:var(--radius);overflow:auto;--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);max-height:calc(100vh - 40px)}body>.affine-modal>center-peek>.close-modal{height:2rem;right:.75rem;top:.75rem;width:2rem;z-index:10}body>.affine-modal>center-peek>.close-modal>svg{height:1rem;width:1rem}.affine-database-column-stats{margin-left:0}.editor.is-readonly .database-header-bar+uni-lit,.editor.is-readonly .unsupported-content{display:none}.form-control .affine-theme,.form-group .affine-theme{border-radius:var(--form-control-radius);--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));outline-color:transparent;outline-style:solid;outline-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--form-control-border);transition-duration:.15s;transition-property:outline,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);--affine-editor-width:initial;--affine-editor-bottom-padding:24px!important;--affine-editor-side-padding:16px!important;min-height:200px}.form-control .affine-page-viewport,.form-group .affine-page-viewport{overflow:visible}.dtable .toggle-icon{margin-top:0;opacity:.5;position:static!important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.doc-app{--doc-view-max-width:800px;--doc-view-padding:24px;--doc-view-side-width:240px;--affine-editor-side-padding:0}.doc-app{align-items:stretch;display:flex;flex-direction:column;min-height:120px}.doc-space-picker-menu .menu-item>.item-inner{padding-right:.25rem}.doc-app-search .form-control{border-radius:var(--radius-full)}.doc-app-search .input-control-prefix{cursor:pointer;opacity:.75}.doc-app-search.empty:not(.focus){transition-duration:.15s;transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1);width:2rem}.doc-app-search.empty:not(.focus) .form-control{padding-left:.5rem;padding-right:.5rem;--tw-ring-color:transparent}.doc-app-search.empty:not(.focus) .form-control::-moz-placeholder{opacity:0}.doc-app-search.empty:not(.focus) .form-control::placeholder{opacity:0}.doc-app-search.empty:not(.focus) .form-control:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.doc-app-search:not(.empty) .form-control{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-300-rgb),var(--tw-ring-opacity))}.doc-app-header .divider{height:1rem!important;margin-left:.25rem!important;margin-right:.25rem!important}.doc-app .is-match-keys{--tw-bg-opacity:1;background-color:rgba(var(--color-warning-100-rgb),var(--tw-bg-opacity));font-weight:700;text-decoration-line:underline;text-underline-offset:2px}.doc-main .dtable-footer{border-bottom-width:1px;--tw-border-opacity:1;border-bottom-color:rgba(var(--color-border-rgb),var(--tw-border-opacity))}.doc-main.show-view>.doc-list{pointer-events:none;visibility:hidden;z-index:-10}.has-doc-app-fullscreen .doc-app-header,.has-doc-app-fullscreen .doc-sidebar,.has-doc-app-fullscreen>#header{display:none}.has-doc-app-fullscreen #mainContainer{max-width:none!important;padding:0!important;width:100%!important}.has-doc-app-fullscreen #docApp{height:calc(100vh - 12px)!important}.doc-app doc-title,.editor-is-exporting .doc-editor-title{display:none}.editor-is-exporting doc-title{display:block}.doc-tree .item-inner{cursor:pointer;padding-right:0;position:relative}.doc-tree .item-inner>.item-icon{flex:none;opacity:1}.doc-tree .item-inner .item-title{overflow:hidden;text-overflow:clip;white-space:nowrap}.doc-tree .item-inner.selected .item-title{font-weight:700}.doc-tree .item-inner>.toolbar{top:.25rem!important}.doc-tree .item-inner>.toolbar>.btn.with-popover-show,.doc-tree .list-heading-inner>.toolbar{opacity:1!important}.doc-tree .item-inner:hover>.toolbar{margin-top:0!important}.doc-tree .with-hover-actions>.item>.item-inner .item-actions{right:0}.doc-sidebar .sortable-ghost{border-radius:var(--radius-sm);z-index:10;--tw-bg-opacity:1;background-color:rgba(var(--color-warning-100-rgb),var(--tw-bg-opacity));opacity:.3;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-warning-600-rgb),var(--tw-ring-opacity))}.doc-tree [z-key=project-files]{border-top:1px solid rgba(var(--color-border-rgb),var(--tw-border-opacity));margin-top:.25rem;padding-top:.25rem}.doc-list-item-title{overflow:hidden;text-overflow:clip}.doc-view{scroll-padding-top:16px;scrollbar-gutter:stable both-edges}.doc-view-content{max-width:var(--doc-view-max-width);padding:var(--doc-view-padding)}.doc-files .item-title{overflow:hidden;white-space:nowrap}.doc-files .file-list-item{border-radius:var(--radius-lg);transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.doc-files .file-list-item:hover{background-color:rgba(var(--color-inverse-rgb),.05)}.doc-files .file-list-item .item-actions,.doc-files .file-list-item:hover .item-actions{margin-left:1rem;margin-top:0;position:relative}.doc-files .file-list-item .item-actions .btn{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity))}.doc-editor .affine-page-viewport{overflow:visible!important}.doc-editor .affine-page-root-block-container{padding:0 0 2rem!important}.doc-editor-keywords,.doc-editor-title{flex:none;max-width:100%;min-width:0}.doc-editor-keywords:hover .form-control{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.doc-editor-keywords .form-control:focus{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.doc-editor-control{z-index:2}.doc-view-sidebar{display:flex;flex-direction:column;max-height:calc(100% - 24px);overflow:visible;width:var(--doc-view-side-width)}.doc-view-sidebar-nav{--nav-item-padding:6px;--nav-item-color:var(--color-gray-500);--nav-active-bg:var(--color-primary-100);--nav-active-color:var(--color-fore);--nav-item-height:26px;--nav-divider-margin:8px;background-color:rgba(var(--color-surface-rgb),.2)}.doc-view-sidebar .datalist{--datalist-label-width:56px}.is-closed.doc-view-sidebar .doc-view-sidebar-content,.is-sidebar-closed .doc-view-sidebar-content{display:none}.is-closed.doc-view-sidebar,.is-sidebar-closed .doc-view-sidebar{--doc-view-side-width:0;opacity:0;transition-delay:1s;transition-duration:1s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.is-outline.doc-view-sidebar{--doc-view-side-width:260px}.doc-view:hover .doc-view-sidebar{opacity:1;transition-delay:0s}.is-closed>.doc-view-sidebar-container,.is-sidebar-closed .doc-view-sidebar-container{position:absolute;right:0;top:0}.doc-view-sidebar-container{background-color:rgba(var(--color-canvas-rgb),.8);min-height:0;--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.doc-outline .listitem{position:relative}.doc-outline .tree-toggle.is-empty:before{border-radius:var(--radius-full);height:.25rem;position:absolute;width:.25rem;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-300-rgb),var(--tw-bg-opacity));--tw-content:"";content:var(--tw-content)}.doc-outline .is-nested-root.no-nested-items{padding-left:.375rem}.doc-path-picker .picker-deselect-btn{display:none}.doc-path-picker-angle{margin-left:-.125rem;margin-right:-.125rem}.doc-path-picker,.doc-space-picker{outline:2px solid transparent!important;outline-offset:2px!important;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)!important}.dropmenu-btn{gap:.25rem;padding-left:.5rem;padding-right:.5rem}.dropmenu-btn>.text{max-width:180px;overflow:hidden}.dropmenu-btn>.is-leading{left:-.625rem;opacity:.6;position:absolute}.dropmenu-btn>.is-caret{align-items:center;background-color:rgba(var(--color-canvas-rgb),.2);border-radius:var(--radius);display:flex;height:1rem;justify-content:center;width:1rem}.dropmenu-nav{border-bottom-width:1px;margin-left:.75rem;margin-right:.75rem;margin-top:.25rem}.has-search .dropmenu-nav{margin-top:-.5rem}.dropmenu-nav>.nav-secondary{gap:.5rem}.dropmenu-nav>.nav-secondary>.nav-item>a{border-radius:var(--radius);padding-left:.5rem;padding-right:.5rem}.dropmenu-nav>.nav-secondary>.nav-item>a:after{bottom:-1px;left:1rem;opacity:0;right:1rem}.dropmenu-nav>.nav-secondary>.nav-item>.active:after{left:.5rem;opacity:1;right:.5rem;transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dropmenu-title{font-size:.75rem;font-weight:700;line-height:1rem;margin-bottom:-.5rem;padding:.75rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.dropmenu-list{min-height:0;overflow-x:hidden;overflow-y:auto;padding:.5rem .75rem}.dropmenu.loading>*{opacity:0}.dropmenu-item .tree-item-inner{border-radius:var(--radius);cursor:pointer;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dropmenu-item.is-item.active>.tree-item-inner{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.tree-item-inner.is-link:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.tree-item-inner.is-link:hover .item-content,.tree-item-inner.is-link:hover .item-trailing-icon,.tree-item-inner.is-link:hover .label{color:inherit}.tree-item-inner.is-toggle:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.dropmenu-item+.tree-item{margin-top:.125rem}.dropmenu-item .is-match{font-weight:700;text-decoration-line:underline}.dropmenu-item .item-title,.dropmenu-item .label{overflow:hidden;white-space:nowrap}.dropmenu-item .item-content{padding-left:.375rem;padding-right:.375rem}.dropmenu-item *+.item-content{padding-left:0}.tree-item-inner.is-toggle .item-title{opacity:.6}.tree-item-inner.is-toggle:hover .item-title{opacity:1}.dropmenu-item-check{align-items:center;display:flex;flex:1 1 auto;justify-content:flex-end;padding-right:.5rem}.dropmenu-item .nested-toggle-icon.is-empty{width:.25rem}.dropmenu-item .item-icon{margin-right:-.25rem}.card-list{--list-gap:.625rem;--list-count-per-row:1}.card-list,.card-list-item{padding:calc(var(--list-gap)/2)}.card-list-item{width:calc(100%/var(--list-count-per-row))}.card-grid{display:flex;flex-wrap:wrap}.card-grid .card{height:100%}:root{--form-control-border:var(--color-border-strong)}.checkbox-primary.disabled,.checkbox-primary.disabled>label,.checkbox-primary>input[type=checkbox]:disabled,.checkbox-primary>input[type=checkbox]:disabled+label,.radio-primary.disabled,.radio-primary.disabled>label,.radio-primary>input[type=radio],.radio-primary>input[type=radio]:disabled+label{filter:none!important}.checkbox-primary.disabled>label,.radio-primary.disabled>label{opacity:1}.checkbox-primary.disabled>label:before,.radio-primary.disabled>label:before{background-color:rgba(var(--color-inverse-rgb),.05);opacity:.5}.form-actions{gap:1rem;justify-content:center}.form-actions .btn{min-width:96px}.form-control-static{min-height:32px;padding-bottom:.375rem;padding-top:.375rem}:root{--zt-panel-form-max-width:1000px}.size-sm{--zt-panel-form-max-width:800px}.size-lg{--zt-panel-form-max-width:1200px}.panel-body>.container,.panel-heading>.container{max-width:var(--panel-container-width);min-width:0;padding-left:var(--panel-container-padding);padding-right:var(--panel-container-padding)}.panel-heading>.container{align-items:center;display:flex;flex-direction:row;flex-wrap:nowrap;gap:1rem;justify-content:space-between;min-height:48px}.panel-form{border-radius:var(--radius-md);margin-bottom:1rem;margin-left:auto;margin-right:auto;max-width:var(--zt-panel-form-max-width);min-width:var(--zt-panel-form-min-width);overflow:visible;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding-bottom:1rem;padding-left:1rem;padding-right:1rem;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.panel-form .form-actions{background-color:rgba(var(--color-canvas-rgb),.8);bottom:0;padding-bottom:1rem;padding-top:1rem;position:sticky;z-index:3;--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.panel-form .form-grid{margin-left:calc(0px - var(--form-grid-gap-y-half));margin-right:calc(0px - var(--form-grid-gap-y-half));padding-bottom:0}.panel-form-toolbar{padding-left:var(--form-grid-gap-x-half);padding-right:var(--form-grid-gap-x-half);width:100%}.panel-form-toolbar>.toolbar{gap:1rem;padding-bottom:.75rem;padding-top:.75rem}.panel-form-divider{margin-bottom:.75rem;margin-top:1rem;padding-left:var(--form-grid-gap-x-half);padding-right:var(--form-grid-gap-x-half);width:100%}.panel-form-divider:before{background-color:rgba(var(--color-border-rgb),.7);display:block;height:1px;--tw-content:"";content:var(--tw-content)}.is-full .btn-full-form,.is-lite .btn-lite-form{z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-300-rgb),var(--tw-ring-opacity))}.btn-toggle-fold:after{content:attr(data-expand-text)}.show-fold-items .btn-toggle-fold:after{content:attr(data-collapse-text)}.is-foldable,.is-full .full\:hidden,.is-full .lite\:visible,.is-full .panel-form-divider,.is-full .panel-form-toolbar,.is-lite .full\:visible,.is-lite .lite\:hidden,.no-foldable-items .btn-toggle-fold{display:none}.is-foldable.is-pinned,.is-full .full\:visible,.is-full .is-foldable,.is-full .lite\:hidden,.is-lite .full\:hidden,.is-lite .lite\:visible,.show-fold-items .is-foldable{display:block}.is-full .full\:w-1\/2,.is-lite .lite\:w-1\/2{width:50%}.is-full .full\:w-1\/3,.is-lite .lite\:w-1\/3{width:33.333333%}.is-full .full\:w-2\/3,.is-lite .lite\:w-2\/3{width:66.666667%}.is-full .full\:w-1\/4,.is-lite .lite\:w-1\/4{width:25%}.is-full .full\:w-2\/4,.is-lite .lite\:w-2\/4{width:50%}.is-full .full\:w-3\/4,.is-lite .lite\:w-3\/4{width:75%}.is-full .full\:w-1\/5,.is-lite .lite\:w-1\/5{width:20%}.is-full .full\:w-2\/5,.is-lite .lite\:w-2\/5{width:40%}.is-full .full\:w-3\/5,.is-lite .lite\:w-3\/5{width:60%}.is-full .full\:w-4\/5,.is-lite .lite\:w-4\/5{width:80%}.is-full .full\:w-1\/6,.is-lite .lite\:w-1\/6{width:16.666667%}.is-full .full\:w-2\/6,.is-lite .lite\:w-2\/6{width:33.333333%}.is-full .full\:w-3\/6,.is-lite .lite\:w-3\/6{width:50%}.is-full .full\:w-4\/6,.is-lite .lite\:w-4\/6{width:66.666667%}.is-full .full\:w-5\/6,.is-lite .lite\:w-5\/6{width:83.333333%}.is-full .full\:w-full,.is-lite .lite\:w-full{width:100%}.page-form{--panel-container-width:960px;--panel-container-padding:20px;--zt-panel-form-max-width:1200px;--zt-panel-form-min-width:1040px;padding-left:0;padding-right:0;--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.page-form .panel-heading{border-bottom-width:1px;--tw-border-opacity:0.7;padding:0}.page-form .panel-title{font-size:1rem;line-height:1.5rem}@media (max-width:1240px){.page-form{--zt-panel-form-max-width:1100px}}@media (max-width:1110px){.page-form{--zt-panel-form-max-width:1040px}}.modal-body>.page-form{margin:-1.5rem -2rem!important;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.modal-body>.page-form>.panel-heading{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius);position:sticky;top:-1.25rem;z-index:2;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding-bottom:.375rem;padding-top:.375rem}.modal-body>.panel-form .form-actions{bottom:-1.5rem!important;padding-bottom:1.5rem;padding-top:1.5rem}.dropdown.popover{display:flex;flex-direction:column;position:absolute;z-index:1200}.dropdown.show{display:flex}.dropdown-menu{display:none;--menu-min-width:7rem;--menu-max-width:20rem}.dropdown-menu.show,.menu-wrapper>.dropdown-menu,.show>.dropdown-menu{display:block}.dropdown>.dropdown-menu,.menu-wrapper .dropdown-menu{position:relative}.popup .popup.search-menu{background-color:var(--menu-bg)}.show>.menu-wrapper{display:flex}.dropdown>.menu-wrapper{height:100%}.dropdown>.menu-wrapper .menu-wrapper{position:absolute}.dropdown>.menu-wrapper.is-tree .menu-wrapper{position:relative}.is-contextmenu .is-nested-show>a:not(:hover){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity))}.is-contextmenu .menu-item.is-nested>.item-inner>.nested-toggle-icon{position:absolute;right:.25rem;top:.375rem}.is-contextmenu .menu-nested .menu-item>.item-inner{padding-left:.5rem;padding-right:1.25rem}.is-contextmenu .menu-nested .menu-item>.item-inner>.item-content{overflow:hidden}.dropdown>.arrow{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.global-search-panel li:not(.order-first):hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.global-search-panel li a{width:100%}.global-search-panel li{cursor:pointer}.history-panel>.panel-heading+.panel-body{margin-top:-.75rem}.history-panel-action{position:relative}.history-panel-action:before{border-left-width:1px;bottom:-.375rem;left:.5rem;position:absolute;top:22px;--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));--tw-content:"";content:var(--tw-content)}.col-reverse>.history-panel-action:first-child:before,.col>.history-panel-action:last-child:before{display:none}.history-panel-action>.item-inner{padding-left:1.5rem}.history-panel-action>.item-inner>.avatar{left:0;position:absolute;top:.375rem}.history-panel-action .file-list-item .item-content{flex:none}.history-panel-action blockquote{margin-top:.25rem;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding:.25rem .25rem .25rem .5rem}.history-panel-action blockquote.original{display:none}.img-cutter{background:var(--color-gray-100);border:1px solid #ddd;margin-bottom:20px;padding:10px}.img-cutter .canvas{margin:0 auto;max-width:100%;min-width:50px;position:relative}.img-cutter .cover{bottom:0;left:0;position:absolute;right:0;top:0;z-index:1}.img-cutter .controller{background:none;border:1px dashed hsla(0,0%,100%,.7);cursor:move;position:absolute;z-index:5}.img-cutter .control{background:#000;background:rgba(0,0,0,.6);border:1px solid hsla(0,0%,100%,.6);height:6px;position:absolute;width:6px}.img-cutter .control[data-type=left]{cursor:w-resize;left:-4px;margin-top:-3px;top:50%}.img-cutter .control[data-type=top]{cursor:n-resize;left:50%;margin-left:-3px;top:-4px}.img-cutter .control[data-type=right]{cursor:e-resize;margin-top:-3px;right:-4px;top:50%}.img-cutter .control[data-type=bottom]{bottom:-4px;cursor:s-resize;left:50%;margin-left:-3px}.img-cutter .control[data-type=top-left]{cursor:nw-resize;left:-4px;top:-4px}.img-cutter .control[data-type=top-right]{cursor:ne-resize;right:-4px;top:-4px}.img-cutter .control[data-type=bottom-left]{bottom:-4px;cursor:sw-resize;left:-4px}.img-cutter .control[data-type=bottom-right]{bottom:-4px;cursor:se-resize;right:-4px}.img-cutter .cliper{bottom:0;left:0;position:absolute;right:0;top:0;z-index:2}.messager-lite{border-radius:var(--radius-lg);min-width:160px;--tw-bg-opacity:1!important;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))!important;padding:1rem 1.5rem;--tw-text-opacity:1!important;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))!important;--skin-ring:transparent!important;--skin-text:inherit!important;--skin-color:var(--color-gray-500)}.messager-lite .alert-icon{color:var(--skin-color);font-size:1.5rem;line-height:2rem}.messager-lite .alert-text{font-size:.875rem;font-weight:700;line-height:1.3rem}.messager-lite .toolbar{gap:.5rem;margin-left:2rem}.messager-lite .alert-content+.alert-close{margin-left:1.5rem}.messager-lite .toolbar .btn.ghost{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.modal-reconfirm .modal-body{font-size:14px;font-weight:700;padding:24px 32px}.modal-reconfirm .modal-footer{justify-content:center;padding:24px}.picker-deselect-btn{opacity:.6;transition-duration:.15s;transition-property:opacity,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.picker-multi-selection{cursor:pointer;padding-right:.5rem;position:relative}.picker-multi-selection .picker-deselect-btn{bottom:0;left:0;position:absolute;right:0;top:0;--tw-scale-x:0;--tw-scale-y:0;background-color:rgba(var(--color-surface-rgb),.8);opacity:0}.picker-deselect-btn:hover,.picker-multi-selection .picker-deselect-btn,.picker-multi-selection:hover .picker-deselect-btn{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.picker-deselect-btn:hover,.picker-multi-selection:hover .picker-deselect-btn{--tw-scale-x:1;--tw-scale-y:1;opacity:1;--state-color:rgba(var(--color-surface-rgb),.9)}.pick-pri{flex-direction:row;justify-content:flex-start;position:relative}.pick-pri,.pick-pri>.text{align-items:center;display:flex}.pick-pri>.text{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap}.pick-pri .placeholder{--tw-text-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-text-opacity))}.pick-pri-list>.btn{justify-content:flex-start}.disabled.pick-pri,.disabled.pick-pri>*{filter:none}.search-form{--gutter-width:12px;padding-bottom:.5rem}.search-form-container{border-radius:var(--radius);min-height:116px;position:relative;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity))}.is-simple .search-form-container{min-height:56px}.search-form-field td{padding:.375rem}.search-form-field td.is-andOr,.search-form-field td.is-operator{width:5rem}.search-form-field td.is-condition{width:7rem}.search-form-field td.is-operator{width:5rem}[lang=en] .search-form-field td.is-operator{width:6rem}.search-form .sidebar-right.is-collapsed{margin-right:-.375rem}.is-simple .search-form-wrapper{display:flex}.is-simple .search-form-wrapper>.row{flex:1 1 auto}.is-simple .search-form-wrapper>.toolbar{flex:none;margin-top:0}.zinbar [data-hint]{position:relative}.zinbar [data-hint]:after{background-color:rgba(var(--color-inverse-rgb),var(--tw-bg-opacity));border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg);bottom:100%;display:block;pointer-events:none;position:absolute;right:0;white-space:nowrap;z-index:50;--tw-bg-opacity:0.9;font-size:.75rem;line-height:1rem;padding:.125rem .25rem;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));opacity:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);--tw-content:attr(data-hint);content:var(--tw-content)}.zinbar [data-hint]:hover:after{opacity:1}.zin-perf-btn-list .text-danger{color:var(--color-danger-400)}.zinbar .state{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.zinbar .state:active{--tw-scale-x:1.05;--tw-scale-y:1.05}.zinbar .state:active,.zinbar.collapse{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.zinbar.collapse{--tw-translate-x:100%}.zinbar.collapse>div{pointer-events:none}.zinbar{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-duration:.7s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}body[z-perf=danger]:before,body[z-perf=warning]:before{bottom:0;left:0;pointer-events:none;position:fixed;right:0;top:0;z-index:9990;--tw-border-opacity:1;border-color:rgba(var(--color-warning-600-rgb),var(--tw-border-opacity));font-size:.75rem;line-height:1rem;--tw-content:"";border-style:inset;border-width:12px 8px 8px;content:var(--tw-content)}body[z-perf=danger]:before{--tw-border-opacity:1;border-color:rgba(var(--color-danger-600-rgb),var(--tw-border-opacity))}body[z-perf=danger]:after,body[z-perf=warning]:after{font-size:.75rem;font-weight:700;left:0;line-height:1rem;line-height:1;pointer-events:none;position:fixed;right:0;text-align:center;top:0;z-index:9991;--tw-text-opacity:1;color:rgba(var(--color-white-rgb),var(--tw-text-opacity));--tw-content:attr(z-perf-message);content:var(--tw-content)}.card{border-radius:var(--radius);min-height:28px;position:relative;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05;transition-duration:.15s;transition-property:box-shadow,border,color,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1)}.card:hover{--tw-shadow:0 2px 6px -1px rgba(0,0,0,.2),0 1px 4px -2px rgba(0,0,0,.15);--tw-shadow-colored:0 2px 6px -1px var(--tw-shadow-color),0 1px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.card-content,.card-footer,.card-header,.card-heading{padding:.25rem .5rem}.card-heading{align-items:center;display:flex;gap:.5rem}.card-icon{opacity:.5}.card-header{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity))}.card-content{display:flex;flex-direction:column;gap:.25rem}.card-actions{position:absolute;right:.125rem;top:.125rem}.card-actions+.card-heading{padding-right:1.75rem}.card-subtitle{font-size:.75rem;line-height:1rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.card.selected{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-400-rgb),var(--tw-ring-opacity))}.card-list{--list-gap:.625rem;--list-count-per-row:1}.card-list,.card-list-item{padding:calc(var(--list-gap)/2)}.card-list-item{width:calc(100%/var(--list-count-per-row))}.card-grid{display:flex;flex-wrap:wrap}.card-grid .card{height:100%}.contextmenu{display:none}.contextmenu.show{display:block}.contextmenu .popup .popup,.contextmenu.popup{position:absolute}.more,.more-vert{margin:.5rem;position:relative}.more,.more-vert,.more-vert:after,.more-vert:before,.more:after,.more:before{background-color:currentColor;border-radius:var(--radius-full);height:.125rem;width:.125rem}.more-vert:after,.more-vert:before,.more:after,.more:before{display:block;left:-5px;position:absolute;top:0;--tw-content:"";content:var(--tw-content)}.more-vert:after,.more:after{left:5px}.more-vert{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dashboard-blocks{position:relative}.dashboard-block-cell{position:absolute;transition-duration:.15s;transition-property:left,top;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dashboard-block{border-radius:var(--radius);bottom:.5rem;left:.5rem;position:absolute;right:.5rem;top:.5rem;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dashboard-block.is-dragging{opacity:0;z-index:1600}.dashboard-block-header{align-items:center;border-top-left-radius:var(--radius);border-top-right-radius:var(--radius);display:flex;flex-direction:row;justify-content:space-between;left:0;padding:.75rem;pointer-events:none;position:absolute;right:0;top:0;z-index:10}.dashboard-block-header>*{pointer-events:auto}.dashboard-block-title{font-size:.875rem;font-weight:700;line-height:1.3rem}.dashboard-block-body{bottom:0;left:0;position:absolute;right:0;top:0}.dashboard-block-body>.panel{display:flex;flex-direction:column;height:100%;width:100%;--tw-shadow:0px 6px 16px rgba(202,215,235,.25)}.dashboard-block-body .panel-heading{cursor:move;flex:none}.dashboard-block-body .panel-body{flex:1 1 auto;overflow-y:auto}.has-more-menu>.dashboard-block-body .panel-heading{padding-right:3rem}.dashboard-block-body .panel-title{font-size:.875rem;height:2rem;line-height:1.3rem}.dashboard-block-actions .btn{opacity:.6}.dashboard-block-actions .btn:hover{opacity:1}.dashboard-drop-shadow{position:absolute;transition-duration:.15s;transition-property:left,top;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dashboard-drop-shadow:before{background-color:rgba(var(--color-inverse-rgb),.05);border-radius:var(--radius);bottom:.5rem;left:.5rem;position:absolute;right:.5rem;top:.5rem;--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-content:"";content:var(--tw-content)}:root{--dtable-checked-bg:var(--color-warning-50);--dtable-checked-bg-hover:var(--color-warning-100);--dtable-checked-border:var(--color-border-strong)}.dtable-cell.is-checked,.dtable-striped .dtable-cell.is-odd-row.is-checked{background-color:var(--dtable-checked-bg)}.checkbox-primary.dtable-checkbox{margin-right:-.375rem}.dtable-checkbox{order:-5}.dtable-hover-col .dtable-cell.is-hover-col.is-checked,.dtable-hover-row .dtable-cell.is-hover-row.is-checked{background-color:var(--dtable-checked-bg-hover)}.dtable-cell.is-checked{--dtable-border-color:var(--dtable-checked-border)}.dtable-check-info{flex-shrink:1;margin-right:.5rem;overflow:hidden;white-space:nowrap}:root{--toggle-icon-size:calc(var(--font-size-root)*3/4 + 1px)}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-color:currentColor;border-width:1px;display:block;opacity:.5;position:relative}.toggle-icon-collapse:hover,.toggle-icon-expand:hover,.toggle-icon:hover{opacity:.9}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-radius:inherit;height:var(--toggle-icon-size);width:var(--toggle-icon-size)}.is-collapsed .toggle-icon:after,.is-collapsed .toggle-icon:before,.is-expanded .toggle-icon:before,.toggle-icon-collapse:after,.toggle-icon-collapse:before,.toggle-icon-expand:before{background-color:currentColor;content:" ";display:block;height:1px;left:2px;position:absolute;right:2px;top:calc((var(--toggle-icon-size) - 3px)/2)}.is-collapsed .toggle-icon:after,.toggle-icon-collapse:after{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:root{--dtable-nt-size:calc(var(--font-size-root)*3/4 + 1px)}.dtable-nested-indent{flex:none;margin-right:-.25rem;order:-100}.dtable-nested-toggle{align-items:center;border-radius:var(--radius-sm);display:flex;flex:none;height:1.25rem;justify-content:center;margin-left:-.25rem;order:-6;width:1.25rem}.dtable-nested-toggle.is-no-child{margin-right:-.25rem;opacity:0;pointer-events:none}.dtable-child-label{order:-5}.dtable-header-group{align-items:center;background:var(--dtable-header-bg);cursor:default;display:flex;justify-content:center;left:0;position:absolute;top:1px;z-index:30}.dtable-bordered .dtable-header-group{border-bottom:1px solid var(--dtable-border-color);border-left:1px solid var(--dtable-border-color)}.dtable-header-as-group{contain:style;content-visibility:visible;overflow:visible!important}.dtable-sorting{cursor:move}.dtable-cell.is-sorting-from{background-color:var(--dtable-bg);z-index:20}.dtable-cell.is-sorting-from:before{border-top-width:1px}.dtable-sorting .dtable-cell.is-sorting-after{--tw-translate-y:-100%}.dtable-sorting .dtable-cell.is-sorting-after,.dtable-sorting .dtable-cell.is-sorting-before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dtable-sorting .dtable-cell.is-sorting-before{--tw-translate-y:100%}.dtable-cell.is-sorting-before:before,.dtable-cell.is-sorting-from:before{border-bottom-width:1px;border-top-width:1px}.dtable{--dtable-bg:var(--color-canvas);--dtable-striped-bg:var(--color-gray-50);--dtable-hover-bg:rgba(var(--color-primary-500-rgb),.05);--dtable-header-bg:var(--color-surface);--dtable-footer-bg:var(--color-surface);--dtable-border-color:var(--color-border);--dtable-sorter-size:0.3125rem}.dtable{position:relative;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.dtable.no-animation *{transition-property:none!important}.dtable-block{overflow:hidden;position:absolute;width:100%}.dtable-header{background-color:var(--dtable-header-bg);border-top-left-radius:inherit;border-top-right-radius:inherit}.dtable-body{overflow:hidden}.dtable-cells{background-color:var(--dtable-bg);height:100%;position:absolute;z-index:0}.dtable-cells-container{height:100%;position:absolute;width:100%}.dtable-header .dtable-cells{background-color:var(--dtable-header-bg)}.dtable-cells.dtable-fixed-left,.dtable-cells.dtable-fixed-right{z-index:10}.dtable-cell{position:absolute;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-cell:after,.dtable-cell:before{bottom:0;content:"";left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:-1px;z-index:2}.dtable-cell:before{border-bottom-width:1px;border-color:var(--dtable-border-color);opacity:1}.dtable-header-cell{align-items:center;display:flex;font-weight:700}.dtable-header-cell:after,.dtable-header-cell:before{top:0}.dtable-cell-content{align-items:center;display:flex;gap:.25rem;height:100%;overflow:hidden;padding-left:.75rem;padding-right:.75rem;position:relative;white-space:nowrap;width:100%;z-index:5}.dtable-body .dtable-cell.is-last-row:before{border-bottom-width:0}.dtable-footer{align-items:center;background-color:var(--dtable-footer-bg);border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;border-color:var(--dtable-border-color);border-top-width:1px;display:flex;padding-left:.75rem;padding-right:.75rem;position:absolute;width:100%;z-index:10}.dtable-empty-tip{align-items:center;display:flex;height:100%;justify-content:center}.dtable .scrollbar{z-index:20}.dtable-header{transition-duration:1s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-scrolled-down .dtable-header{border-bottom-color:rgba(var(--color-inverse-rgb),.15);border-bottom-width:1px}.dtable-has-scroll-y:not(.dtable-scrolled-bottom) .dtable-footer{border-top-color:rgba(var(--color-inverse-rgb),.15);border-top-width:1px}.dtable-scroll-shadow{background-image:linear-gradient(90deg,rgba(0,0,0,.03),transparent),linear-gradient(90deg,rgba(0,0,0,.03),transparent 50%);opacity:0;pointer-events:none;position:absolute;top:0;transition-duration:1s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);width:8px;z-index:20}.dtable:hover .dtable-scroll-shadow{opacity:1}.dtable-scroll-shadow.is-right{margin-left:-7px;--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dtable-scroll-shadow.is-left,.dtable-scrolled-end .dtable-scroll-shadow.is-right{visibility:hidden}.dtable-scroll-shadow.is-right,.dtable-scrolled-right .dtable-scroll-shadow.is-left{visibility:visible}.scrollbar-hover:hover .scrollbar{opacity:0}.scrollbar-hover .dtable-body:hover~.scrollbar{opacity:var(--scrollbar-opacity)}.dtable-sort{display:inline-flex;height:calc(var(--dtable-sorter-size)*12/5);margin-left:.25rem;opacity:.8;position:relative}.dtable-cell:hover .dtable-sort{opacity:1}.dtable-sort:after,.dtable-sort:before{border-color:transparent;border-style:solid;height:0;left:0;opacity:.4;position:absolute;width:0;--tw-content:"";border-width:var(--dtable-sorter-size);content:var(--tw-content)}.dtable-sort:before{border-bottom-color:currentColor;border-top-width:0;top:0}.dtable-sort:after{border-bottom-width:0;border-top-color:currentColor;bottom:0}.dtable-sort.dtable-sort-asc:before,.dtable-sort.dtable-sort-desc:after{opacity:.9}.dtable-sort-link{align-items:center;cursor:pointer;display:inline-flex}.dtable-cells.dtable-fixed-left:before,.dtable-cells.dtable-fixed-right:before{border-color:var(--dtable-border-color);content:"";height:100%;pointer-events:none;position:absolute;width:100%;z-index:5}.dtable-cells.dtable-fixed-left:before{border-right-width:1px;right:-1px}.dtable-cells.dtable-fixed-right:before{border-left-width:1px;left:0}.dtable-bordered:before{border-color:var(--dtable-border-color);border-radius:inherit;border-width:1px;bottom:0;content:"";display:block;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:15}.dtable-bordered .dtable-cell:before{border-width:1px;right:-1px}.dtable-cell.has-border-left:before{border-left-width:1px}.dtable-cell.has-border-right:before{border-right-width:1px;right:-1px}.dtable-striped .dtable-cell.is-odd-row{background-color:var(--dtable-striped-bg)}.dtable-hover-cell .dtable-cell:hover:after,.dtable-hover-col .dtable-cell.is-hover-col:before,.dtable-hover-row .dtable-body .dtable-cell.is-hover-row:before{background-color:var(--dtable-hover-bg)}.kanban,.kanban-list{--kanban-lane-name-width:20px;--kanban-col-width:280px;--kanban-cols-gap:8px;--kanban-lanes-gap:8px;--kanban-header-height:32px;--kanban-lane-height:auto;--kanban-lane-color:var(--color-primary-500);--kanban-link-color:var(--color-secondary-600)}.kanban{align-items:flex-start;display:flex;flex-direction:column;min-width:-moz-fit-content;min-width:fit-content;position:relative}.kanban-header{display:flex;flex-direction:row;height:var(--kanban-header-height)}.kanban.has-sub-cols .kanban-header{height:calc(var(--kanban-header-height)*2)}.kanban-header-lane-name{background-color:rgba(var(--color-fore-rgb),.05);flex:none;width:var(--kanban-lane-name-width)}.kanban-header-cols,.kanban-header-sub-cols{display:flex;flex:1 1 0%;flex-direction:row;gap:var(--kanban-cols-gap)}.kanban-header-sub-cols{border-top-width:2px;--tw-border-opacity:1;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity))}.kanban-header-col{align-items:center;border-bottom-width:1px;display:flex;flex:1 1 0%;flex-direction:column;height:100%;width:var(--kanban-col-width)}.kanban-header-col.has-subs{width:auto}.kanban-header-col-wrapper{align-items:center;display:flex;flex:1 1 0%;flex-direction:row;position:relative;width:100%;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding-left:3.5rem;padding-right:3.5rem}.kanban-header-col-wrapper.is-align-left{justify-content:flex-start;padding-left:.5rem}.kanban-header-col-wrapper.is-align-left>.kanban-header-title{justify-content:flex-start}.kanban-header-title{align-items:center;display:flex;flex:1 1 auto;flex-direction:row;justify-content:center;overflow:hidden}.kanban-header-title>.as-title{color:var(--kanban-col-color);font-weight:700;overflow:hidden;white-space:nowrap}.kanban-header-col-actions{bottom:.25rem;position:absolute;right:.25rem;top:.25rem}.kanban-header-col-actions>.btn{opacity:.6}.kanban-header-col-actions>.btn:hover{opacity:1}.kanban-body{display:flex;flex-direction:column;gap:var(--kanban-lanes-gap)}.kanban-lane{display:flex;flex-direction:row;height:var(--kanban-lane-height);min-height:96px}.kanban-lane-name{align-items:center;background-color:var(--kanban-lane-color);display:flex;justify-content:center;width:var(--kanban-lane-name-width);--tw-text-opacity:1;color:rgba(var(--color-white-rgb),var(--tw-text-opacity));writing-mode:vertical-rl}.kanban-lane-actions,.kanban-lane-name{flex:none;position:relative}.kanban-lane.is-first .kanban-lane-actions{margin-top:calc(4px - var(--kanban-header-height))}.has-sub-cols .kanban-lane.is-first .kanban-lane-actions{margin-top:calc(4px - var(--kanban-header-height)*2)}.kanban-lane-actions>.btn.square{width:var(--kanban-lane-name-width)}.kanban-lane-title{align-items:center;display:flex;flex:1 1 auto;justify-content:center;overflow:hidden;white-space:nowrap}.kanban-lane-cols{display:flex;flex-direction:row;gap:var(--kanban-cols-gap)}.kanban-lane-col{background-color:rgba(var(--color-inverse-rgb),.05);display:flex;flex-direction:column;height:100%;width:var(--kanban-col-width)}.kanban-header-col,.kanban-lane-col{margin-left:calc(var(--kanban-col-gap-left) - var(--kanban-cols-gap));margin-right:calc(var(--kanban-col-gap-right) - var(--kanban-cols-gap))}.kanban-col-content{position:relative;z-index:5}.kanban-lane.is-first>.kanban-lane-name:before{background-color:var(--kanban-lane-color);bottom:100%;display:block;height:var(--kanban-header-height);left:0;position:absolute;right:0;--tw-content:"";content:var(--tw-content)}.kanban.has-sub-cols .kanban-lane.is-first>.kanban-lane-name:before{height:calc(var(--kanban-header-height)*2)}.kanban-lane{margin-bottom:calc(var(--kanban-col-gap-bottom) - var(--kanban-lanes-gap));margin-top:calc(var(--kanban-col-gap-top) - var(--kanban-lanes-gap))}.kanban-items{flex:1 1 auto;overflow:auto;scrollbar-gutter:both-edges stable}.kanban-lane.is-auto-height .kanban-items{scrollbar-gutter:auto}.kanban-item{cursor:default}.kanban-item .card-actions{z-index:5}.kanban-heading{width:100%}.kanban-heading .listitem{height:2.25rem}.kanban-heading .item-title{font-weight:700}.kanban.has-dragging{cursor:move}.kanban-item.is-dragging{cursor:move;opacity:.1}.kanban-sticky .kanban-header{position:sticky;top:0;z-index:10;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.kanban-sticky .kanban-header.is-pinned{border-bottom-color:rgba(var(--color-inverse-rgb),.15);border-bottom-width:1px;z-index:20;--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.kanban-sticky .kanban-lane-name{left:0;position:sticky;z-index:21}.kanban-region{border-radius:var(--radius);min-width:-moz-fit-content;min-width:fit-content;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding:.75rem;--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.kanban-region>.kanban+.kanban{margin-top:.75rem}.kanban-region.has-heading{padding-top:0}.kanban-heading>.listitem{left:.75rem;position:sticky;width:calc(var(--kanban-list-width) - 24px)}.kanban-list{display:flex;flex-direction:column;gap:.75rem;height:100vh;overflow:auto;position:relative;scrollbar-gutter:stable}.kanban-list.is-moving{cursor:grabbing}.kanban-items.is-dropping{position:relative}.kanban-item.is-dropping{position:relative;transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.kanban-item.is-dropping:after,.kanban-items.is-dropping>.card-list:after{background-color:rgba(var(--color-warning-500-rgb),.5);border-radius:var(--radius-full);display:block;height:.25rem;--tw-content:"";content:var(--tw-content)}.kanban-item.is-dropping:after{left:.25rem;position:absolute;right:.25rem;top:-.25rem}.kanban-item.is-dropping[z-drop-side=before]{--tw-translate-y:0.25rem}.kanban-item.is-dropping[z-drop-side=after],.kanban-item.is-dropping[z-drop-side=before]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-item.is-dropping[z-drop-side=after]{--tw-translate-y:-0.25rem}.kanban-item.is-dropping[z-drop-side=after]:after{bottom:-.25rem;top:auto}.kanban-links{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:5}.kanban-list>.kanban-links{overflow:visible;z-index:11}.kanban-link{align-items:center;color:var(--kanban-link-color);display:flex;justify-content:center;position:absolute}.kanban-link>svg{position:absolute}.kanban-link-text{border-radius:var(--radius);height:1em;line-height:1;padding-left:.125rem;padding-right:.125rem;pointer-events:auto;position:relative;text-align:center;white-space:nowrap}.kanban-link-start-point{height:.5rem;width:.5rem;--tw-translate-x:-0.25rem;--tw-translate-y:-0.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-link-start-point,.kanban-link-start-point:before{background-color:currentColor;border-radius:var(--radius-full);position:absolute}.kanban-link-start-point:before{bottom:-.25rem;display:block;left:-.25rem;opacity:.2;right:-.25rem;top:-.25rem;--tw-content:"";content:var(--tw-content)}.kanban-link path{pointer-events:auto}.kanban-link path+path{opacity:.6}.kanban-link.is-hover path+path{opacity:1;stroke-width:calc(var(--kanban-link-weight)*1.5)}.kanban-link-delete-btn{pointer-events:auto;--tw-scale-x:.75;--tw-scale-y:.75;opacity:0;transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.is-hover .kanban-link-delete-btn,.kanban-link-delete-btn{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.is-hover .kanban-link-delete-btn{--tw-scale-x:1;--tw-scale-y:1;opacity:1}.is-adding-link{cursor:crosshair;-webkit-user-select:none;-moz-user-select:none;user-select:none}.kanban-link-editor{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:20}.kanban-link-editor-from,.kanban-link-editor-to{border-radius:var(--radius);--tw-shadow-color:rgb(var(--color-primary-500-rgb));--tw-shadow:var(--tw-shadow-colored);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-500-rgb),var(--tw-ring-opacity))}.kanban-link-editor-from,.kanban-link-editor-point,.kanban-link-editor-to{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);position:absolute}.kanban-link-editor-point{height:.5rem;pointer-events:auto;width:.5rem;--tw-translate-x:-0.25rem;--tw-translate-y:-0.25rem;border-radius:var(--radius-full);cursor:move;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));opacity:.5;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgba(var(--color-primary-500-rgb),0.1);transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.kanban-link-editor-point.is-left{left:0;top:50%}.kanban-link-editor-point.is-right{right:0;top:50%;--tw-translate-x:0.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-link-editor-point.is-top{left:50%;top:0}.kanban-link-editor-point.is-bottom{bottom:0;left:50%;--tw-translate-y:0.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-link-editor-point:hover{opacity:1;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-primary-500-rgb),0.5)}.tab-pane{display:none}.tab-pane.active{display:block}.has-sorting-col{cursor:move;--dtable-sorting-col-color:var(--color-primary-300);--dtable-hover-bg:transparent}.has-sorting-col .dtable-col-splitter{display:none}.dtable-cell.is-sorting-col-move{transition-duration:.15s;transition-property:left;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-cell.is-sorting-from-col{transition-duration:.1s}.dtable-cell.is-sorting-from-col:after{background-color:var(--dtable-sorting-col-color)!important;opacity:.1!important}.dtable-cell.is-sorting-from-col:before{border-left:1px solid var(--dtable-sorting-col-color);border-right:1px solid var(--dtable-sorting-col-color)}.dtable-header-cell.is-sortable-col{cursor:move}.has-sorting-col .scrollbar.is-horz{opacity:var(--scrollbar-opacity)!important}.has-sorting-col .dtable-scroll-shadow{visibility:visible}:root{--dtable-col-splitter-width:7px;--dtable-col-splitter-color:var(--color-primary-500)}.dtable-cell.has-col-resizing:after,.dtable-cell.has-col-splitter:hover:after{background:var(--dtable-col-splitter-color);opacity:.05}.dtable-col-splitter{background:var(--dtable-col-splitter-color);border-radius:var(--radius-full);bottom:0;cursor:ew-resize;opacity:0;position:absolute;right:calc(var(--dtable-col-splitter-width)/-2);top:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--dtable-col-splitter-width);z-index:20}.dtable-cell.has-col-splitter:hover .dtable-col-splitter{opacity:.3}.dtable-cell.has-col-resizing .dtable-col-splitter,.dtable-cell.has-col-splitter .dtable-col-splitter:hover{opacity:.5}.dtable.has-col-resizing .dtable-cell.has-col-splitter:not(.has-col-resizing) .dtable-col-splitter,.dtable.has-col-resizing .dtable-cell.has-col-splitter:not(.has-col-resizing):after{opacity:0}.dtable-col-splitter:after,.dtable-col-splitter:before{content:" ";display:block;height:.5rem;left:50%;margin-top:-.25rem;position:absolute;top:50%;width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-white-rgb),var(--tw-bg-opacity))}.dtable-col-splitter:before{margin-left:-1px}.dtable-col-splitter:after{margin-left:1px}.dtable.has-col-resizing{--dtable-hover-bg:transparent}.dtable.has-col-resizing,.has-col-resizing .dtable-header-cell{cursor:ew-resize!important}.dtable-cell.is-col-resizing:before{border-right:1px solid var(--dtable-col-splitter-color)}.dtable-cell.is-col-resizing:after{background:var(--dtable-col-splitter-color);opacity:.05}.has-col-resizing .scrollbar.is-horz{opacity:var(--scrollbar-opacity)!important}.dtable-cell.has-contextmenu-show:after{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));opacity:.1}.dtable{--dtable-header-bg:var(--color-surface-light);--dtable-footer-bg:var(--color-surface-light);--dtable-border-color:var(--color-border-light);--dtable-checked-border:var(--color-border);--dtable-checked-bg:var(--color-primary-50);--dtable-checked-bg-hover:var(--color-primary-100);--dtable-hover-bg:rgba(var(--color-gray-500-rgb),.05);--dtable-link-color:var(--color-link);--dtable-link-hover-color:var(--color-link-hover);--dtable-link-visited-color:var(--color-link-visited)}.dtable-cell-content[style*="--color-link"]{--dtable-link-hover-color:var(--color-link);--dtable-link-visited-color:var(--color-link)}.dtable-body .dtable-cell a{--dtable-link-color:var(--color-link)}.dtable-body .dtable-cell a:not(.btn){color:var(--dtable-link-color)}.dtable-body .dtable-cell a:not(.btn):visited{color:var(--dtable-link-visited-color)}.dtable-body .dtable-cell a:not(.btn):hover{color:var(--dtable-link-hover-color)}.dtable .btn-avatar{border-radius:var(--radius-full);gap:.25rem;height:1.25rem;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity));padding-left:0;padding-right:.5rem;--tw-ring-color:transparent}.dtable .btn-avatar:hover{--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dtable-nested-toggle{width:1rem}.dtable .toggle-icon{--toggle-icon-size:11px;border-radius:var(--radius);--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity))}.dtable .toggle-icon:after,.dtable .toggle-icon:before{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}.dtable-footer>.toolbar{margin-right:.5rem}.dtable-header .dtable-cell[data-sort]>.dtable-cell-content>a:not(:hover){color:inherit}.dtable-assign-btn{align-items:center;border-radius:var(--radius-full);display:flex;flex-direction:row;height:1.25rem;padding-left:.375rem;padding-right:.375rem;--dtable-link-color:var(--color-fore)}.dtable-assign-btn:not(:hover){color:inherit}.dtable-assign-btn.is-me{--dtable-link-color:var(--color-warning-500)!important}.dtable-assign-btn:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-strong-rgb),var(--tw-ring-opacity))}.dtable-assign-btn>span{border-radius:var(--radius-full);line-height:20px;padding-left:.375rem;padding-right:.375rem}.dtable-assign-btn.is-unassigned>span{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-strong-rgb),var(--tw-ring-opacity))}.dtable-assign-btn.is-unassigned:hover>span{background-color:inherit;color:inherit;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.dtable-assign-btn>.icon{opacity:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-assign-btn:not(.disabled):hover>.icon{opacity:1}.dtable-header .dtable-cell[data-type=assign]{padding-left:1.5rem}.dtable-cell-icon{order:-5}.dtable-custom-cell[data-type=control]{align-items:center;display:flex;justify-content:center;padding-left:.125rem;padding-right:.125rem;z-index:1}:root{--dtable-editing-color:var(--color-success-600)}.dtable-cell.is-editing:after{border-color:var(--dtable-editing-color);border-width:2px!important;opacity:1;z-index:20}.dtable-editing-input{height:100%;outline:2px solid transparent;outline-offset:2px;padding-left:.75rem;padding-right:.75rem;width:100%}:root{--dtable-selected-color:var(--color-success-500);--dtable-selected-bg:var(--color-success-50);--dtable-selecting-bg:var(--color-success-100);--dtable-highlight-color:var(--color-success-700)}.dtable-selectable{-webkit-user-select:none;-moz-user-select:none;user-select:none}.dtable-cell.is-select:after{border-color:var(--dtable-selected-color);border-width:1px;opacity:1;z-index:10}.dtable-cell.is-selecting{background:var(--dtable-selecting-bg)}.dtable-cell.is-selected{background:var(--dtable-selected-bg)}.dtable-cell.is-col-selected:after,.dtable-cell.is-row-selected[data-col=INDEX]:after{background-color:rgba(var(--color-inverse-rgb),.05);opacity:1}.dtable-cell.has-cell-selected{color:var(--dtable-highlight-color)}.dtable-cell.is-first-row.is-select:after{top:0}.dtable-cell.is-last-row.is-select:after{bottom:1px}.dtable-cell.is-first-in-row.is-select:after{left:1px}.dtable-cell.is-last-in-row.is-select:after{right:1px}.dtable-datagrid .dtable-cell[data-col=INDEX]{background:var(--dtable-header-bg)}.dtable-empty-tip{min-height:212px}.dtable-cell[data-type=actions] .btn>.icon{font-size:1rem;line-height:1.5rem}.menu.menu-dtable-actions.has-icons{align-items:center;display:flex;gap:.25rem;min-width:auto;--menu-icon-opacity:1}.menu.menu-dtable-actions.has-icons>.menu-item>a{padding-left:.25rem;padding-right:.25rem}.menu.menu-dtable-actions.has-icons>.menu-item>a>.icon-EMPTY,.menu.menu-dtable-actions.has-icons>.menu-item>a>.item-content{display:none}.menu.menu-dtable-actions.has-icons>.menu-item>a>.icon-EMPTY+.item-content,.menu.menu-dtable-actions.has-icons>.menu-item>a>.item-content:first-child{display:block}:root{--state-color:rgba(0,0,0,.03);--zt-page-bg:#f8f9fa;--zt-header-height:3rem;--zt-header-bg:var(--color-canvas);--zt-header-color:var(--color-fore);--zt-sidebar-width:160px;--zt-navbar-active-color:var(--color-primary-500)}body{background-color:var(--zt-page-bg)}.page-app{overflow:overlay}.container{min-width:1200px}#header{height:var(--zt-header-height);--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);background:var(--zt-header-bg);border-bottom:1px solid var(--zt-header-border,rgba(var(--color-inverse-rgb),.05));box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);color:var(--zt-header-color)}#header>.container{height:100%;position:relative}#heading{align-items:center;bottom:0;display:flex;gap:.25rem;left:1rem;position:absolute;top:0}#heading>.toolbar{margin-left:-.75rem}#heading .dropmenu-btn>.text{max-width:142px}#heading>[data-zui-dropmenu]+div .dropmenu-btn>.text,#heading>[data-zui-dropmenu]+div+div .dropmenu-btn>.text{max-width:78px}#navbar{align-items:center;display:flex;font-size:.875rem;height:100%;justify-content:center;line-height:1.3rem;--state-color:rgba(var(--color-primary-500-rgb),.05);--state-active-opacity:1;--state-active-color:rgba(var(--color-primary-500-rgb),.08)}#navbar>.nav{--nav-active-color:var(--zt-navbar-active-color,var(--color-current));--nav-item-padding:12px;--nav-divider-margin:8px;margin-left:var(--nav-offset-left)}#navbar>.nav>.nav-item>a{height:3rem;padding-left:var(--nav-item-padding);padding-right:var(--nav-item-padding)}#navbar>.nav>.nav-item>a:before{--tw-scale-x:1!important;--tw-scale-y:1!important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)!important}#navbar>.nav>.nav-item>a.active:before{background:var(--state-active-color)!important;opacity:1!important}#navbar>.nav>.divider{align-self:center;height:1.25rem;margin-left:var(--nav-divider-margin);margin-right:var(--nav-divider-margin);opacity:.2}#navbar>.nav.compact{font-size:.8125rem;line-height:1.25rem}#navbar>.nav.compact-extra{font-size:.75rem;line-height:1rem}#toolbar{align-items:center;bottom:0;display:flex;gap:.25rem;position:absolute;right:1rem;top:0}#main{min-height:100vh}#header+#main{min-height:calc(100vh - 3rem)}#main>.container{padding-left:1rem;padding-right:1rem;position:relative}@media (min-width:1400px){#header>.container,#main>.container,#mainNavbar>.container{padding-left:2.5rem;padding-right:2.5rem}#heading{left:2.5rem}#toolbar{right:2.5rem}}#mainNavbar{height:2.75rem;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}#mainNavbar>.container{position:relative}#mainNavbar .nav{bottom:0;height:2.75rem;justify-content:center;left:0;position:absolute;right:0;top:0}#mainNavbar .nav-item{font-size:.875rem;line-height:1.3rem}#mainNavbar .nav-item>a{border-radius:var(--radius)}#mainMenu{gap:1rem;justify-content:space-between;padding-bottom:.75rem;padding-top:.75rem}#featureBar,#mainMenu{align-items:center;display:flex}#featureBar{flex:1 1 auto;gap:.5rem}#actionBar{gap:.5rem}#actionBar>.nav-divider{margin-left:-.25rem;margin-right:-.25rem}#mainContent{padding-top:.75rem}#mainMenu+#mainContent{padding-top:0}#mainContent.row{align-items:stretch;display:flex;gap:1rem;justify-content:space-between}#mainContent.row>*{flex:1 1 auto;min-width:0}#mainContainer.has-sidebar-left{--gutter-left-size:16px}#mainContainer.is-sidebar-left-collapsed{--gutter-left-size:0}.has-sidebar-animation.has-sidebar-left #mainMenu{transition-duration:.15s;transition-property:padding-left;transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--modal-radius:var(--radius);--avatar-bg:var(--color-gray-200)}.modal-alert .modal-footer{justify-content:center}.modal-dialog{--tw-bg-opacity:1}.modal-content,.modal-dialog{max-height:calc(100vh - 4rem)}.modal-body,.modal-footer,.modal-header{padding:1.5rem 2rem}.modal-header{padding-right:3rem}.modal-body+.modal-footer,.modal-header+.modal-actions+.modal-body,.modal-header+.modal-body{padding-top:1px}.modal-condensed .modal-body,.modal-condensed .modal-header{padding:1rem 1.25rem}.modal-condensed .modal-actions{top:.75rem}:root{--label-bg:var(--color-gray-100);--label-color:var(--color-gray-800)}.label[class$=-pale],.label[class*="-pale "]{--tw-bg-opacity:0.4;--tw-ring-opacity:0.4}.body-modal .panel-form,.modal-body>.panel-form{margin:0;padding:0}.modal-body>.panel-form>.panel-heading{padding-left:1px;padding-right:1px;padding-top:1px}.modal-body>.panel-form>.panel-body{padding:1px}.modal-body>.form{padding-top:1px}.modal .history,.modal .panel-body>.form{padding:0}:root{--article-p-space:0}.lane-col-join-with-above{position:relative}.lane-col-join-with-above:before{background-color:inherit;left:0;position:absolute;right:0;--tw-content:"";content:var(--tw-content);height:var(--kanban-col-gap-top,var(--kanban-lanes-gap));top:calc(0px - var(--kanban-col-gap-top, var(--kanban-lanes-gap)))}.arrow,.arrow:before{background:inherit;height:calc(var(--arrow-size)*1.4142);position:absolute;width:calc(var(--arrow-size)*1.4142)}.arrow{visibility:hidden;--arrow-size:5px}.arrow:before{border:inherit;content:"";visibility:visible;--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.arrow-top,.arrow-up{border-bottom:inherit;border-right:inherit;border-width:1px 0 0 1px;top:calc(1px - var(--arrow-size))}.white>.arrow-top,.white>.arrow-up{top:calc(0px - var(--arrow-size))}.arrow-bottom,.arrow-down{border-left:inherit;border-top:inherit;border-width:0 1px 1px 0;bottom:calc(1px - var(--arrow-size))}.white>.arrow-bottom,.white>.arrow-down{bottom:calc(0px - var(--arrow-size))}.arrow-left{border-right:inherit;border-top:inherit;border-width:0 0 1px 1px;left:calc(1px - var(--arrow-size))}.white>.arrow-left{left:calc(0px - var(--arrow-size))}.arrow-right{border-bottom:inherit;border-left:inherit;border-width:1px 1px 0 0;right:calc(1px - var(--arrow-size))}.white>.arrow-right{right:calc(0px - var(--arrow-size))}.caret,.caret-down,.caret-left,.caret-right,.caret-up{align-items:center;display:inline-flex;height:.75rem;justify-content:center;position:relative;width:.75rem}.caret-down:before,.caret-left:before,.caret-right:before,.caret-up:before,.caret:before{display:block;height:.35rem;transform-origin:center;width:.35rem;--tw-translate-y:-1px;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.caret-left:before{--tw-translate-x:0.125rem;--tw-translate-y:0px;--tw-rotate:135deg}.caret-left:before,.caret-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.caret-right:before{--tw-translate-x:-0.125rem;--tw-translate-y:0px;--tw-rotate:-45deg}.caret-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:focus>.caret,:hover>.caret{opacity:inherit}.disabled .caret,.readonly .caret{opacity:var(--caret-opacity,.5)}:root{--toggle-icon-size:calc(var(--font-size-root)*3/4 + 1px)}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-color:currentColor;border-width:1px;display:block;opacity:.5;position:relative}.toggle-icon-collapse:hover,.toggle-icon-expand:hover,.toggle-icon:hover{opacity:.9}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-radius:inherit;height:var(--toggle-icon-size);width:var(--toggle-icon-size)}.is-collapsed .toggle-icon:after,.is-collapsed .toggle-icon:before,.is-expanded .toggle-icon:before,.toggle-icon-collapse:after,.toggle-icon-collapse:before,.toggle-icon-expand:before{background-color:currentColor;content:" ";display:block;height:1px;left:2px;position:absolute;right:2px;top:calc((var(--toggle-icon-size) - 3px)/2)}.is-collapsed .toggle-icon:after,.toggle-icon-collapse:after{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.spinner,.spinner:after,.spinner:before{display:block;height:1em;position:relative;width:1em}.spinner:after,.spinner:before{border-radius:var(--radius-full);content:" ";position:absolute}.spinner:before{animation:-spin 1s cubic-bezier(.6,0,.4,1) infinite;border:.16667em solid transparent;border-top-color:currentcolor}.spinner:after{border:.16667em solid;opacity:.2}.magnifier{display:inline-block;height:1em;position:relative;width:1em}.magnifier:after,.magnifier:before{border-radius:var(--radius-full);content:"";display:block;position:absolute}.magnifier:before{border:1px solid;height:.75em;width:.75em}.magnifier:after{height:1px;left:.55em;top:.7em;width:.5em;--tw-rotate:45deg;background-color:currentColor;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.more,.more-vert{margin:.5rem;position:relative}.more,.more-vert,.more-vert:after,.more-vert:before,.more:after,.more:before{background-color:currentColor;border-radius:var(--radius-full);height:.125rem;width:.125rem}.more-vert:after,.more-vert:before,.more:after,.more:before{display:block;left:-5px;position:absolute;top:0;--tw-content:"";content:var(--tw-content)}.more-vert:after,.more:after{left:5px}.more-vert{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.chevron-down,.chevron-left,.chevron-right,.chevron-up{align-items:center;display:inline-flex;height:1em;justify-content:center;position:relative;width:1em}.chevron-down:before,.chevron-left:before,.chevron-right:before,.chevron-up:before{display:block;height:.6923077em;transform-origin:center;width:.6923077em;--tw-translate-y:-0.125rem;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.chevron-left:before{--tw-translate-y:0px;--tw-translate-x:0.125rem;--tw-rotate:135deg}.chevron-left:before,.chevron-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.chevron-right:before{--tw-translate-y:0px;--tw-translate-x:-0.125rem;--tw-rotate:-45deg}.chevron-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.i-time{border-color:currentColor;border-radius:50%;border-width:.08em;display:inline-block;height:1em;position:relative;width:1em}.i-time:after{border-color:currentColor;border-width:0 0 .08em .08em;height:.385em;left:.3846em;position:absolute;top:.08em;width:.385em;--tw-content:"";content:var(--tw-content)}.i-calendar{border-color:currentColor;border-radius:2px;border-width:.08em;display:inline-block;height:.79em;margin-top:.16em;position:relative;width:1em}.i-calendar:after,.i-calendar:before{border-color:currentColor;border-width:.08em;position:absolute;--tw-content:"";content:var(--tw-content)}.i-calendar:before{border-bottom-width:0;left:.15em;top:.307em;width:.6em}.i-calendar:after{border-bottom-width:0;border-top-width:0;height:.3077em;left:.17em;top:-.154em;width:.538em}:root{--state-color:rgba(0,0,0,.05);--state-scale:.9;--opacity-disabled:.7;--opacity-muted:.5;--load-indicator-duration:300ms;--load-indicator-delay:.5s}.btn,.item>a,.state{cursor:pointer;position:relative}.btn:before,.item>a:before,.state:before{background:var(--state-color);border-radius:inherit;bottom:0;content:" ";display:block;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transform:scale(var(--state-scale));transition-duration:.2s;transition-property:opacity,transform,box-shadow,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1)}.btn.active:not(:hover,:focus-visible,:focus-within,:active):before,.item>a.active:not(:hover,:focus-visible,:focus-within,:active):before,.state.active:not(:hover,:focus-visible,:focus-within,:active):before{background:var(--state-active-color,var(--state-color));opacity:var(--state-active-opacity,0);--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-duration:.7s}.btn.selected:not(:hover,:focus-visible,:focus-within,:active):before,.item>a.selected:not(:hover,:focus-visible,:focus-within,:active):before,.state.selected:not(:hover,:focus-visible,:focus-within,:active):before{background:var(--state-selected-color,var(--state-scale));opacity:var(--state-selected-opacity,.1);--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.btn:focus-visible,.item>a:focus-visible,.state:focus-visible{outline:2px solid transparent;outline-offset:2px}.btn:active:before,.btn:focus-visible:before,.btn:hover:before,.item>a:active:before,.item>a:focus-visible:before,.item>a:hover:before,.state:active:before,.state:focus-visible:before,.state:hover:before{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.btn:hover:before,.item>a:hover:before,.state:hover:before{opacity:var(--state-hover-opacity,1)}.btn:active:before,.item>a:active:before,.state:active:before{background:var(--state-pressed-color,var(--state-color));opacity:var(--state-pressed-opacity,.6);--tw-ring-color:var(--state-ring-color,currentColor);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);transition-duration:.7s}.btn:focus-visible:before,.item>a:focus-visible:before,.state:focus-visible:before{background:var(--state-focus-color,var(--state-color));opacity:var(--state-focus-opacity,1);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-focus-rgb),var(--tw-ring-opacity))}.btn.disabled:before,.btn[disabled]:before,.item>a.disabled:before,.item>a[disabled]:before,.state.disabled:before,.state[disabled]:before{display:none}.btn{--state-active-opacity:1}@-moz-document url-prefix(){.btn,:root{--state-active-opacity:0;--state-focus-opacity:0}}.disabled,.disabled *,[disabled],[disabled] *{cursor:not-allowed!important;opacity:var(--opacity-disabled);--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.load-indicator:after,.load-indicator:before{display:block;opacity:0;position:absolute;transition-delay:0s;transition-duration:.15s;transition-duration:var(--load-indicator-duration);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);visibility:hidden}.load-indicator:before{align-items:center;background-color:rgba(var(--color-canvas-rgb),.7);border-radius:inherit;bottom:0;display:flex;font-size:.75rem;justify-content:center;left:0;line-height:1rem;right:0;top:0;z-index:99;--tw-content:attr(data-loading);content:var(--tw-content)}.load-indicator[data-loading]:before{padding-top:3.5rem}.load-indicator:after{border-color:transparent currentcolor currentcolor;border-radius:var(--radius-full);border-style:dotted;border-width:4px 3px 4px 4px;height:2rem;left:50%;margin-left:-1rem;margin-top:-1rem;top:50%;width:2rem;z-index:100;--tw-content:"";content:var(--tw-content)}.load-indicator.loading:after,.load-indicator.loading:before{opacity:1;transition-delay:var(--load-indicator-delay);visibility:visible}@keyframes -spin{to{transform:rotate(1turn)}}.load-indicator.loading:after{animation:-spin 1s linear infinite;opacity:.5}.events-none,.pointer-events-none{pointer-events:none}.events-auto,.pointer-events-auto{pointer-events:auto}.scroll-auto{scroll-behavior:auto}.scroll-smooth{scroll-behavior:smooth}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.select-text{-webkit-user-select:text;-moz-user-select:text;user-select:text}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.select-auto{-webkit-user-select:auto;-moz-user-select:auto;user-select:auto}.cursor-auto{cursor:auto}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.cursor-text{cursor:text}.cursor-move{cursor:move}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.active\:opacity-100.active,.active\:opacity-100:active,.group.active .group-active\:opacity-100,.group:active .group-active\:opacity-100,.group:hover .group-hover\:opacity-100,.hover\:opacity-100:hover{opacity:1}.active\:opacity-0.active,.active\:opacity-0:active,.group.active .group-active\:opacity-0,.group:active .group-active\:opacity-0,.group:hover .group-hover\:opacity-0,.hover\:opacity-0:hover{opacity:0}.active\:text-primary.active,.active\:text-primary:active,.group.active .group-active\:text-primary,.group:active .group-active\:text-primary,.group:hover .group-hover\:text-primary,.hover\:text-primary:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.active\:border-primary.active,.active\:border-primary:active,.group.active .group-active\:border-primary,.group:active .group-active\:border-primary,.group:hover .group-hover\:border-primary,.hover\:border-primary:hover{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500-rgb),var(--tw-border-opacity))}.active\:primary-pale.active,.active\:primary-pale:active,.group.active .group-active\:primary-pale,.group:active .group-active\:primary-pale,.group:hover .group-hover\:primary-pale,.hover\:primary-pale:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.active\:primary.active,.active\:primary:active,.group.active .group-active\:primary,.group:active .group-active\:primary,.group:hover .group-hover\:primary,.hover\:primary:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.active\:canvas.active,.active\:canvas:active,.group.active .group-active\:canvas,.group:active .group-active\:canvas,.group:hover .group-hover\:canvas,.hover\:canvas:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.active\:font-bold.active,.active\:font-bold:active,.group.active .group-active\:font-bold,.group:active .group-active\:font-bold,.group:hover .group-hover\:font-bold,.hover\:font-bold:hover{font-weight:700}.active\:shadow.active,.active\:shadow:active,.group.active .group-active\:shadow,.group:active .group-active\:shadow,.group:hover .group-hover\:shadow,.hover\:shadow:hover{--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.active\:shadow-lg.active,.active\:shadow-lg:active,.group.active .group-active\:shadow-lg,.group:active .group-active\:shadow-lg,.group:hover .group-hover\:shadow-lg,.hover\:shadow-lg:hover{--tw-shadow:0 5px 15px -3px rgba(0,0,0,.2),0 2px 6px -4px rgba(0,0,0,.15);--tw-shadow-colored:0 5px 15px -3px var(--tw-shadow-color),0 2px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.group:hover .group-hover\:block,.hover\:block:hover{display:block!important}.group:hover .group-hover\:flex,.hover\:flex:hover{display:flex!important}.group:hover .group-hover\:inline-flex,.hover\:inline-flex:hover{display:inline-flex!important}.group:hover .group-hover\:scale-110,.hover\:scale-110:hover{--tw-scale-x:1.1!important;--tw-scale-y:1.1!important}.group:hover .group-hover\:scale-110,.group:hover .group-hover\:scale-125,.hover\:scale-110:hover,.hover\:scale-125:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.group:hover .group-hover\:scale-125,.hover\:scale-125:hover{--tw-scale-x:1.25!important;--tw-scale-y:1.25!important}.aspect-auto{aspect-ratio:auto}.aspect-square{aspect-ratio:1/1}.aspect-video{aspect-ratio:16/9}.container{width:100%}@media (min-width:1720px){.container{max-width:1720px}}.container{margin-left:auto;margin-right:auto}.popup{background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));border-radius:var(--radius);--tw-bg-opacity:0.85;--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05;--tw-backdrop-blur:blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.table-cell{display:table-cell}.table-row{display:table-row}.hidden{display:none!important}.pull-right{float:right}.pull-left{float:left}.clearfix:after{clear:both;content:"";display:block}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.object-fill{-o-object-fit:fill;object-fit:fill}.object-none{-o-object-fit:none;object-fit:none}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.object-bottom{-o-object-position:bottom;object-position:bottom}.object-center{-o-object-position:center;object-position:center}.object-left{-o-object-position:left;object-position:left}.object-left-bottom{-o-object-position:left bottom;object-position:left bottom}.object-left-top{-o-object-position:left top;object-position:left top}.object-right{-o-object-position:right;object-position:right}.object-right-bottom{-o-object-position:right bottom;object-position:right bottom}.object-right-top{-o-object-position:right top;object-position:right top}.object-top{-o-object-position:top;object-position:top}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-clip{overflow:clip}.overflow-visible{overflow:visible}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.overflow-x-clip{overflow-x:clip}.overflow-y-clip{overflow-y:clip}.overflow-x-visible{overflow-x:visible}.overflow-y-visible{overflow-y:visible}.overflow-x-scroll{overflow-x:scroll}.overflow-y-scroll{overflow-y:scroll}.overflow-overlay{overflow:overlay}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{bottom:0;left:0;right:0;top:0}.inset-auto{bottom:auto;left:auto;right:auto;top:auto}.inset-x-0{left:0;right:0}.inset-y-0{bottom:0;top:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.top-full{top:100%}.right-full{right:100%}.bottom-full{bottom:100%}.left-full{left:100%}.top-auto{top:auto}.right-auto{right:auto}.bottom-auto{bottom:auto}.left-auto{left:auto}.top-px{top:1px}.right-px{right:1px}.bottom-px{bottom:1px}.left-px{left:1px}.top-0\.5{top:.125rem}.right-0\.5{right:.125rem}.bottom-0\.5{bottom:.125rem}.left-0\.5{left:.125rem}.top-1{top:.25rem}.right-1{right:.25rem}.bottom-1{bottom:.25rem}.left-1{left:.25rem}.top-1\.5{top:.375rem}.right-1\.5{right:.375rem}.bottom-1\.5{bottom:.375rem}.left-1\.5{left:.375rem}.top-2{top:.5rem}.right-2{right:.5rem}.bottom-2{bottom:.5rem}.left-2{left:.5rem}.top-2\.5{top:.625rem}.right-2\.5{right:.625rem}.bottom-2\.5{bottom:.625rem}.left-2\.5{left:.625rem}.top-3{top:.75rem}.right-3{right:.75rem}.bottom-3{bottom:.75rem}.left-3{left:.75rem}.top-3\.5{top:.875rem}.right-3\.5{right:.875rem}.bottom-3\.5{bottom:.875rem}.left-3\.5{left:.875rem}.top-4{top:1rem}.right-4{right:1rem}.bottom-4{bottom:1rem}.left-4{left:1rem}.top-5{top:1.25rem}.right-5{right:1.25rem}.bottom-5{bottom:1.25rem}.left-5{left:1.25rem}.top-6{top:1.5rem}.right-6{right:1.5rem}.bottom-6{bottom:1.5rem}.left-6{left:1.5rem}.top-7{top:1.75rem}.right-7{right:1.75rem}.bottom-7{bottom:1.75rem}.left-7{left:1.75rem}.top-8{top:2rem}.right-8{right:2rem}.bottom-8{bottom:2rem}.left-8{left:2rem}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-0{z-index:0}.z-1{z-index:1}.z-5{z-index:5}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-auto{z-index:auto}.z-base{z-index:1100}.z-above{z-index:50}.z-below{z-index:-50}.z-dropdown{z-index:1200}.z-sticky{z-index:1300}.z-fixed{z-index:1400}.z-modal{z-index:1500}.z-overlay{z-index:1600}.z-popover{z-index:1700}.z-tooltip{z-index:1800}.z-messager{z-index:1900}.m-0{margin:0}.m-auto{margin:auto}.m-px{margin:1px}.m-0\.5{margin:.125rem}.m-1{margin:.25rem}.m-1\.5{margin:.375rem}.m-2{margin:.5rem}.m-2\.5{margin:.625rem}.m-3{margin:.75rem}.m-3\.5{margin:.875rem}.m-4{margin:1rem}.m-5{margin:1.25rem}.m-6{margin:1.5rem}.m-7{margin:1.75rem}.m-8{margin:2rem}.m-9{margin:2.25rem}.m-10{margin:2.5rem}.mx-0{margin-left:0;margin-right:0}.my-0{margin-bottom:0}.mt-0,.my-0{margin-top:0}.mr-0{margin-right:0}.mb-0{margin-bottom:0}.ml-0{margin-left:0}.mx-auto{margin-left:auto;margin-right:auto}.my-auto{margin-bottom:auto}.mt-auto,.my-auto{margin-top:auto}.mr-auto{margin-right:auto}.mb-auto{margin-bottom:auto}.ml-auto{margin-left:auto}.mx-px{margin-left:1px;margin-right:1px}.my-px{margin-bottom:1px}.mt-px,.my-px{margin-top:1px}.mr-px{margin-right:1px}.mb-px{margin-bottom:1px}.ml-px{margin-left:1px}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.my-0\.5{margin-bottom:.125rem}.mt-0\.5,.my-0\.5{margin-top:.125rem}.mr-0\.5{margin-right:.125rem}.mb-0\.5{margin-bottom:.125rem}.ml-0\.5{margin-left:.125rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.my-1{margin-bottom:.25rem}.mt-1,.my-1{margin-top:.25rem}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.mx-1\.5{margin-left:.375rem;margin-right:.375rem}.my-1\.5{margin-bottom:.375rem}.mt-1\.5,.my-1\.5{margin-top:.375rem}.mr-1\.5{margin-right:.375rem}.mb-1\.5{margin-bottom:.375rem}.ml-1\.5{margin-left:.375rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem}.mt-2,.my-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.mx-2\.5{margin-left:.625rem;margin-right:.625rem}.my-2\.5{margin-bottom:.625rem}.mt-2\.5,.my-2\.5{margin-top:.625rem}.mr-2\.5{margin-right:.625rem}.mb-2\.5{margin-bottom:.625rem}.ml-2\.5{margin-left:.625rem}.mx-3{margin-left:.75rem;margin-right:.75rem}.my-3{margin-bottom:.75rem}.mt-3,.my-3{margin-top:.75rem}.mr-3{margin-right:.75rem}.mb-3{margin-bottom:.75rem}.ml-3{margin-left:.75rem}.mx-3\.5{margin-left:.875rem;margin-right:.875rem}.my-3\.5{margin-bottom:.875rem}.mt-3\.5,.my-3\.5{margin-top:.875rem}.mr-3\.5{margin-right:.875rem}.mb-3\.5{margin-bottom:.875rem}.ml-3\.5{margin-left:.875rem}.mx-4{margin-left:1rem;margin-right:1rem}.my-4{margin-bottom:1rem}.mt-4,.my-4{margin-top:1rem}.mr-4{margin-right:1rem}.mb-4{margin-bottom:1rem}.ml-4{margin-left:1rem}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.my-5{margin-bottom:1.25rem}.mt-5,.my-5{margin-top:1.25rem}.mr-5{margin-right:1.25rem}.mb-5{margin-bottom:1.25rem}.ml-5{margin-left:1.25rem}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.my-6{margin-bottom:1.5rem}.mt-6,.my-6{margin-top:1.5rem}.mr-6{margin-right:1.5rem}.mb-6{margin-bottom:1.5rem}.ml-6{margin-left:1.5rem}.mx-7{margin-left:1.75rem;margin-right:1.75rem}.my-7{margin-bottom:1.75rem}.mt-7,.my-7{margin-top:1.75rem}.mr-7{margin-right:1.75rem}.mb-7{margin-bottom:1.75rem}.ml-7{margin-left:1.75rem}.mx-8{margin-left:2rem;margin-right:2rem}.my-8{margin-bottom:2rem}.mt-8,.my-8{margin-top:2rem}.mr-8{margin-right:2rem}.mb-8{margin-bottom:2rem}.ml-8{margin-left:2rem}.mx-9{margin-left:2.25rem;margin-right:2.25rem}.my-9{margin-bottom:2.25rem}.mt-9,.my-9{margin-top:2.25rem}.mr-9{margin-right:2.25rem}.mb-9{margin-bottom:2.25rem}.ml-9{margin-left:2.25rem}.mx-10{margin-left:2.5rem;margin-right:2.5rem}.my-10{margin-bottom:2.5rem}.mt-10,.my-10{margin-top:2.5rem}.mr-10{margin-right:2.5rem}.mb-10{margin-bottom:2.5rem}.ml-10{margin-left:2.5rem}.p-0{padding:0}.p-px{padding:1px}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-7{padding:1.75rem}.p-8{padding:2rem}.p-9{padding:2.25rem}.p-10{padding:2.5rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-bottom:0}.pt-0,.py-0{padding-top:0}.pr-0{padding-right:0}.pb-0{padding-bottom:0}.pl-0{padding-left:0}.px-px{padding-left:1px;padding-right:1px}.py-px{padding-bottom:1px}.pt-px,.py-px{padding-top:1px}.pr-px{padding-right:1px}.pb-px{padding-bottom:1px}.pl-px{padding-left:1px}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.py-0\.5{padding-bottom:.125rem}.pt-0\.5,.py-0\.5{padding-top:.125rem}.pr-0\.5{padding-right:.125rem}.pb-0\.5{padding-bottom:.125rem}.pl-0\.5{padding-left:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-1{padding-bottom:.25rem}.pt-1,.py-1{padding-top:.25rem}.pr-1{padding-right:.25rem}.pb-1{padding-bottom:.25rem}.pl-1{padding-left:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.py-1\.5{padding-bottom:.375rem}.pt-1\.5,.py-1\.5{padding-top:.375rem}.pr-1\.5{padding-right:.375rem}.pb-1\.5{padding-bottom:.375rem}.pl-1\.5{padding-left:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-bottom:.5rem}.pt-2,.py-2{padding-top:.5rem}.pr-2{padding-right:.5rem}.pb-2{padding-bottom:.5rem}.pl-2{padding-left:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.py-2\.5{padding-bottom:.625rem}.pt-2\.5,.py-2\.5{padding-top:.625rem}.pr-2\.5{padding-right:.625rem}.pb-2\.5{padding-bottom:.625rem}.pl-2\.5{padding-left:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-3{padding-bottom:.75rem}.pt-3,.py-3{padding-top:.75rem}.pr-3{padding-right:.75rem}.pb-3{padding-bottom:.75rem}.pl-3{padding-left:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.py-3\.5{padding-bottom:.875rem}.pt-3\.5,.py-3\.5{padding-top:.875rem}.pr-3\.5{padding-right:.875rem}.pb-3\.5{padding-bottom:.875rem}.pl-3\.5{padding-left:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.py-4{padding-bottom:1rem}.pt-4,.py-4{padding-top:1rem}.pr-4{padding-right:1rem}.pb-4{padding-bottom:1rem}.pl-4{padding-left:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-5{padding-bottom:1.25rem}.pt-5,.py-5{padding-top:1.25rem}.pr-5{padding-right:1.25rem}.pb-5{padding-bottom:1.25rem}.pl-5{padding-left:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-6{padding-bottom:1.5rem}.pt-6,.py-6{padding-top:1.5rem}.pr-6{padding-right:1.5rem}.pb-6{padding-bottom:1.5rem}.pl-6{padding-left:1.5rem}.px-7{padding-left:1.75rem;padding-right:1.75rem}.py-7{padding-bottom:1.75rem}.pt-7,.py-7{padding-top:1.75rem}.pr-7{padding-right:1.75rem}.pb-7{padding-bottom:1.75rem}.pl-7{padding-left:1.75rem}.px-8{padding-left:2rem;padding-right:2rem}.py-8{padding-bottom:2rem}.pt-8,.py-8{padding-top:2rem}.pr-8{padding-right:2rem}.pb-8{padding-bottom:2rem}.pl-8{padding-left:2rem}.px-9{padding-left:2.25rem;padding-right:2.25rem}.py-9{padding-bottom:2.25rem}.pt-9,.py-9{padding-top:2.25rem}.pr-9{padding-right:2.25rem}.pb-9{padding-bottom:2.25rem}.pl-9{padding-left:2.25rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.py-10{padding-bottom:2.5rem}.pt-10,.py-10{padding-top:2.5rem}.pr-10{padding-right:2.5rem}.pb-10{padding-bottom:2.5rem}.pl-10{padding-left:2.5rem}.space-x-0>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(0px*(1 - var(--tw-space-x-reverse)));margin-right:calc(0px*var(--tw-space-x-reverse))}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(0px*var(--tw-space-y-reverse));margin-top:calc(0px*(1 - var(--tw-space-y-reverse)))}.space-x-0\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.125rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.125rem*var(--tw-space-x-reverse))}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.125rem*var(--tw-space-y-reverse));margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-1\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.375rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.375rem*var(--tw-space-x-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.375rem*var(--tw-space-y-reverse));margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-x-2\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.625rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.625rem*var(--tw-space-x-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.625rem*var(--tw-space-y-reverse));margin-top:calc(.625rem*(1 - var(--tw-space-y-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-x-3\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.875rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.875rem*var(--tw-space-x-reverse))}.space-y-3\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.875rem*var(--tw-space-y-reverse));margin-top:calc(.875rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.25rem*var(--tw-space-x-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.5rem*var(--tw-space-x-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.space-x-7>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.75rem*var(--tw-space-x-reverse))}.space-y-7>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.75rem*var(--tw-space-y-reverse));margin-top:calc(1.75rem*(1 - var(--tw-space-y-reverse)))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2rem*var(--tw-space-x-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.space-x-9>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2.25rem*var(--tw-space-x-reverse))}.space-y-9>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2.25rem*var(--tw-space-y-reverse));margin-top:calc(2.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-10>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2.5rem*var(--tw-space-x-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2.5rem*var(--tw-space-y-reverse));margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)))}.space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1px*(1 - var(--tw-space-x-reverse)));margin-right:calc(1px*var(--tw-space-x-reverse))}.space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1px*var(--tw-space-y-reverse));margin-top:calc(1px*(1 - var(--tw-space-y-reverse)))}.w-0{width:0}.w-px{width:1px}.w-0\.5{width:.125rem}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-32{width:8rem}.w-36{width:9rem}.w-40{width:10rem}.w-44{width:11rem}.w-48{width:12rem}.w-52{width:13rem}.w-56{width:14rem}.w-60{width:15rem}.w-64{width:16rem}.w-72{width:18rem}.w-80{width:20rem}.w-96{width:24rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-2\/3{width:66.666667%}.w-1\/4{width:25%}.w-2\/4{width:50%}.w-3\/4{width:75%}.w-1\/5{width:20%}.w-2\/5{width:40%}.w-3\/5{width:60%}.w-4\/5{width:80%}.w-1\/6{width:16.666667%}.w-2\/6{width:33.333333%}.w-3\/6{width:50%}.w-4\/6{width:66.666667%}.w-5\/6{width:83.333333%}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.w-min{width:-moz-min-content;width:min-content}.w-max{width:-moz-max-content;width:max-content}.w-fit{width:-moz-fit-content;width:fit-content}.min-w-0{min-width:0}.min-w-full{min-width:100%}.min-w-min{min-width:-moz-min-content;min-width:min-content}.min-w-max{min-width:-moz-max-content;min-width:max-content}.min-w-fit{min-width:-moz-fit-content;min-width:fit-content}.max-w-0{max-width:0}.max-w-none{max-width:none}.max-w-xs{max-width:20rem}.max-w-sm{max-width:24rem}.max-w-md{max-width:28rem}.max-w-lg{max-width:32rem}.max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-min{max-width:-moz-min-content;max-width:min-content}.max-w-max{max-width:-moz-max-content;max-width:max-content}.max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.h-0{height:0}.h-px{height:1px}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-20{height:5rem}.h-24{height:6rem}.h-28{height:7rem}.h-32{height:8rem}.h-36{height:9rem}.h-40{height:10rem}.h-44{height:11rem}.h-48{height:12rem}.h-52{height:13rem}.h-56{height:14rem}.h-60{height:15rem}.h-64{height:16rem}.h-72{height:18rem}.h-80{height:20rem}.h-96{height:24rem}.h-1\/2{height:50%}.h-1\/3{height:33.333333%}.h-2\/3{height:66.666667%}.h-1\/4{height:25%}.h-2\/4{height:50%}.h-3\/4{height:75%}.h-1\/5{height:20%}.h-2\/5{height:40%}.h-3\/5{height:60%}.h-4\/5{height:80%}.h-1\/6{height:16.666667%}.h-2\/6{height:33.333333%}.h-3\/6{height:50%}.h-4\/6{height:66.666667%}.h-5\/6{height:83.333333%}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.h-min{height:-moz-min-content;height:min-content}.h-max{height:-moz-max-content;height:max-content}.h-fit{height:-moz-fit-content;height:fit-content}.min-h-0{min-height:0}.min-h-full{min-height:100%}.min-h-min{min-height:-moz-min-content;min-height:min-content}.min-h-max{min-height:-moz-max-content;min-height:max-content}.min-h-fit{min-height:-moz-fit-content;min-height:fit-content}.max-h-0{max-height:0}.max-h-px{max-height:1px}.max-h-none{max-height:none}.max-h-full{max-height:100%}.max-h-min{max-height:-moz-min-content;max-height:min-content}.max-h-screen{max-height:100vh}.max-h-max{max-height:-moz-max-content;max-height:max-content}.max-h-fit{max-height:-moz-fit-content;max-height:fit-content}.canvas,.surface,.surface-light,.surface-strong{--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))}.canvas{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.surface-light{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-light-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-light-rgb),var(--tw-ring-opacity))}.surface{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-rgb),var(--tw-ring-opacity))}.surface-strong{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-strong-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-strong-rgb),var(--tw-ring-opacity))}.inverse{background-color:rgba(var(--color-inverse-rgb),var(--tw-bg-opacity));color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.inverse,.white{--tw-bg-opacity:1;--tw-text-opacity:1}.white{background-color:rgba(var(--color-white-rgb),var(--tw-bg-opacity));color:rgba(var(--color-fore-in-light-rgb),var(--tw-text-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-white-rgb),var(--tw-ring-opacity))}.black{--tw-bg-opacity:1;background-color:rgba(var(--color-black-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-fore-in-dark-rgb),var(--tw-text-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-black-rgb),var(--tw-ring-opacity))}.transparent{background-color:transparent;--tw-ring-color:transparent}.skin{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.skin:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger,.darken,.darker,.darkest,.gray,.gray-100,.gray-200,.gray-300,.gray-400,.gray-50,.gray-500,.gray-600,.gray-700,.gray-800,.gray-900,.gray-950,.important,.lighten,.lighter,.lightest,.primary,.secondary,.special,.success,.warning{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger:hover,.darken:hover,.darker:hover,.darkest:hover,.gray-100:hover,.gray-200:hover,.gray-300:hover,.gray-400:hover,.gray-500:hover,.gray-50:hover,.gray-600:hover,.gray-700:hover,.gray-800:hover,.gray-900:hover,.gray-950:hover,.gray:hover,.important:hover,.lighten:hover,.lighter:hover,.lightest:hover,.primary:hover,.secondary:hover,.special:hover,.success:hover,.warning:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger,.darken,.darker,.darkest,.gray,.gray-100,.gray-200,.gray-300,.gray-400,.gray-50,.gray-500,.gray-600,.gray-700,.gray-800,.gray-900,.gray-950,.important,.lighten,.lighter,.lightest,.primary,.secondary,.special,.success,.warning{--skin-text:rgba(var(--color-fore-in-dark-rgb),var(--tw-text-opacity));--skin-color:rgba(var(--skin-solid-rgb),1);--state-ring-color:var(--skin-color);--state-active-color:rgba(0,0,0,.1);--state-pressed-color:rgba(0,0,0,.1);--state-color:hsla(0,0%,100%,.1);--state-focus-color:rgba(0,0,0,.1)}.primary{--skin-solid-rgb:var(--color-primary-500-rgb)}.secondary{--skin-solid-rgb:var(--color-secondary-500-rgb)}.success{--skin-solid-rgb:var(--color-success-500-rgb)}.warning{--skin-solid-rgb:var(--color-warning-500-rgb)}.danger{--skin-solid-rgb:var(--color-danger-500-rgb)}.important{--skin-solid-rgb:var(--color-important-500-rgb)}.special{--skin-solid-rgb:var(--color-special-500-rgb)}.gray-50{--skin-bg:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity));--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-100{--skin-solid-rgb:var(--color-gray-100-rgb);--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-200,.lightest{--skin-solid-rgb:var(--color-gray-200-rgb);--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-300,.lighter{--skin-solid-rgb:var(--color-gray-300-rgb);--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-400,.lighten{--skin-solid-rgb:var(--color-gray-400-rgb)}.gray,.gray-500{--skin-solid-rgb:var(--color-gray-500-rgb)}.darken,.gray-600{--skin-solid-rgb:var(--color-gray-600-rgb)}.darker,.gray-700{--skin-solid-rgb:var(--color-gray-700-rgb)}.darkest,.gray-800{--skin-solid-rgb:var(--color-gray-800-rgb)}.gray-900{--skin-solid-rgb:var(--color-gray-900-rgb)}.gray-950{--skin-solid-rgb:var(--color-gray-950-rgb)}.danger-pale,.gray-100-pale,.gray-200-pale,.gray-300-pale,.gray-400-pale,.gray-50-pale,.gray-500-pale,.gray-600-pale,.gray-700-pale,.gray-800-pale,.gray-900-pale,.gray-950-pale,.gray-pale,.important-pale,.pale,.primary-pale,.secondary-pale,.special-pale,.success-pale,.warning-pale{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger-pale:hover,.gray-100-pale:hover,.gray-200-pale:hover,.gray-300-pale:hover,.gray-400-pale:hover,.gray-50-pale:hover,.gray-500-pale:hover,.gray-600-pale:hover,.gray-700-pale:hover,.gray-800-pale:hover,.gray-900-pale:hover,.gray-950-pale:hover,.gray-pale:hover,.important-pale:hover,.pale:hover,.primary-pale:hover,.secondary-pale:hover,.special-pale:hover,.success-pale:hover,.warning-pale:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger-pale,.gray-100-pale,.gray-200-pale,.gray-300-pale,.gray-400-pale,.gray-50-pale,.gray-500-pale,.gray-600-pale,.gray-700-pale,.gray-800-pale,.gray-900-pale,.gray-950-pale,.gray-pale,.important-pale,.pale,.primary-pale,.secondary-pale,.special-pale,.success-pale,.warning-pale{--skin-color:rgba(var(--skin-pale-rgb),.1);--skin-text:rgba(var(--skin-pale-rgb),1);--state-color:rgba(var(--skin-pale-rgb),.1)}.pale{--skin-pale-rgb:var(--color-gray-500-rgb)}.primary-pale{--skin-pale-rgb:var(--color-primary-500-rgb)}.secondary-pale{--skin-pale-rgb:var(--color-secondary-500-rgb)}.success-pale{--skin-pale-rgb:var(--color-success-500-rgb)}.warning-pale{--skin-pale-rgb:var(--color-warning-500-rgb)}.danger-pale{--skin-pale-rgb:var(--color-danger-500-rgb)}.important-pale{--skin-pale-rgb:var(--color-important-500-rgb)}.special-pale{--skin-pale-rgb:var(--color-special-500-rgb)}.gray-50-pale{--skin-pale-rgb:var(--color-gray-50-rgb);--skin-text:var(--color-gray-400)}.gray-100-pale{--skin-pale-rgb:var(--color-gray-100-rgb);--skin-text:var(--color-gray-400)}.gray-200-pale{--skin-pale-rgb:var(--color-gray-200-rgb);--skin-text:var(--color-gray-400)}.gray-300-pale{--skin-pale-rgb:var(--color-gray-300-rgb);--skin-text:var(--color-gray-500)}.gray-400-pale{--skin-pale-rgb:var(--color-gray-400-rgb);--skin-text:var(--color-gray-500)}.gray-500-pale,.gray-pale{--skin-pale-rgb:var(--color-gray-500-rgb)}.gray-600-pale{--skin-pale-rgb:var(--color-gray-600-rgb)}.gray-700-pale{--skin-pale-rgb:var(--color-gray-700-rgb)}.gray-800-pale{--skin-pale-rgb:var(--color-gray-800-rgb)}.gray-900-pale{--skin-pale-rgb:var(--color-gray-900-rgb)}.gray-950-pale{--skin-pale-rgb:var(--color-gray-950-rgb)}.danger-outline,.dark-outline,.gray-300-outline,.gray-400-outline,.gray-600-outline,.gray-outline,.important-outline,.light-outline,.outline,.primary-outline,.secondary-outline,.special-outline,.success-outline,.warning-outline{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger-outline:hover,.dark-outline:hover,.gray-300-outline:hover,.gray-400-outline:hover,.gray-600-outline:hover,.gray-outline:hover,.important-outline:hover,.light-outline:hover,.outline:hover,.primary-outline:hover,.secondary-outline:hover,.special-outline:hover,.success-outline:hover,.warning-outline:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger-outline,.dark-outline,.gray-300-outline,.gray-400-outline,.gray-600-outline,.gray-outline,.important-outline,.light-outline,.outline,.primary-outline,.secondary-outline,.special-outline,.success-outline,.warning-outline{--skin-text:var(--skin-color,inherit);--skin-bg:transparent;--skin-color:rgba(var(--skin-outline-rgb),1);--state-color:rgba(var(--skin-outline-rgb),.1)}.outline{--skin-outline-rgb:var(--color-fore-rgb)}.primary-outline{--skin-outline-rgb:var(--color-primary-500-rgb)}.secondary-outline{--skin-outline-rgb:var(--color-secondary-500-rgb)}.success-outline{--skin-outline-rgb:var(--color-success-500-rgb)}.warning-outline{--skin-outline-rgb:var(--color-warning-500-rgb)}.danger-outline{--skin-outline-rgb:var(--color-danger-500-rgb)}.important-outline{--skin-outline-rgb:var(--color-important-500-rgb)}.special-outline{--skin-outline-rgb:var(--color-special-500-rgb)}.gray-300-outline{--skin-text:var(--color-gray-500);--skin-outline-rgb:var(--color-gray-300-rgb)}.gray-400-outline{--skin-text:var(--color-gray-500);--skin-outline-rgb:var(--color-gray-400-rgb)}.gray-outline{--skin-outline-rgb:var(--color-gray-500-rgb)}.gray-600-outline{--skin-outline-rgb:var(--color-gray-600-rgb)}.dark-outline{--skin-outline-rgb:var(--color-inverse-rgb)}.light-outline{--skin-outline-rgb:var(--color-canvas-rgb)}.danger-ghost,.ghost,.important-ghost,.primary-ghost,.secondary-ghost,.special-ghost,.success-ghost,.warning-ghost{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger-ghost:hover,.ghost:hover,.important-ghost:hover,.primary-ghost:hover,.secondary-ghost:hover,.special-ghost:hover,.success-ghost:hover,.warning-ghost:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger-ghost,.ghost,.important-ghost,.primary-ghost,.secondary-ghost,.special-ghost,.success-ghost,.warning-ghost{--tw-ring-opacity:0;--tw-bg-opacity:0;--skin-text:var(--skin-color,inherit);--skin-bg:transparent;--skin-ring:transparent;--skin-color:rgba(var(--skin-ghost-rgb),1);--state-color:rgba(var(--skin-ghost-rgb),.1)}.ghost{--skin-ghost-rgb:var(--color-fore-rgb);--skin-text:inherit}.primary-ghost{--skin-ghost-rgb:var(--color-primary-500-rgb)}.secondary-ghost{--skin-ghost-rgb:var(--color-secondary-500-rgb)}.success-ghost{--skin-ghost-rgb:var(--color-success-500-rgb)}.warning-ghost{--skin-ghost-rgb:var(--color-warning-500-rgb)}.danger-ghost{--skin-ghost-rgb:var(--color-danger-500-rgb)}.important-ghost{--skin-ghost-rgb:var(--color-important-500-rgb)}.special-ghost{--skin-ghost-rgb:var(--color-special-500-rgb)}.font-sans{font-family:-apple-system,Noto Sans,Helvetica Neue,Helvetica,Nimbus Sans L,Arial,Liberation Sans,PingFang SC,Hiragino Sans GB,Noto Sans CJK SC,Source Han Sans SC,Source Han Sans CN,Microsoft YaHei,Wenquanyi Micro Hei,WenQuanYi Zen Hei,ST Heiti,SimHei,WenQuanYi Zen Hei Sharp,sans-serif}.font-serif{font-family:Nimbus Roman No9 L,Songti SC,Noto Serif CJK SC,Source Han Serif SC,Source Han Serif CN,STSong,AR PL New Sung,AR PL SungtiL GB,NSimSun,SimSun,TW-Sung,WenQuanYi Bitmap Song,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR PL UMing TW MBE,PMingLiU,MingLiU,serif}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-root{font-size:16px}.text-sm{font-size:.75rem;line-height:1rem}.text-base{font-size:.8125rem;line-height:1.25rem}.text-md{font-size:.875rem;line-height:1.3rem}.text-lg{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.125rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-thin{font-weight:100}.font-light{font-weight:300}.font-normal{font-weight:400}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-black{font-weight:900}.leading-3{line-height:.75rem}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-8{line-height:2rem}.leading-9{line-height:2.25rem}.leading-10{line-height:2.5rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.leading-snug{line-height:1.375}.leading-normal{line-height:1.5}.leading-relaxed{line-height:1.625}.leading-loose{line-height:2}.line-clamp-1{-webkit-line-clamp:1}.line-clamp-1,.line-clamp-2{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-3{-webkit-line-clamp:3}.line-clamp-3,.line-clamp-4{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-4{-webkit-line-clamp:4}.line-clamp-5{-webkit-line-clamp:5}.line-clamp-5,.line-clamp-6{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-6{-webkit-line-clamp:6}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-justify{text-align:justify}.align-middle{vertical-align:middle}.align-top{vertical-align:top}.align-bottom{vertical-align:bottom}.align-sub{vertical-align:sub}.align-super{vertical-align:super}.text-primary{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.text-secondary{--tw-text-opacity:1;color:rgba(var(--color-secondary-500-rgb),var(--tw-text-opacity))}.text-success{--tw-text-opacity:1;color:rgba(var(--color-success-500-rgb),var(--tw-text-opacity))}.text-warning{--tw-text-opacity:1;color:rgba(var(--color-warning-500-rgb),var(--tw-text-opacity))}.text-danger{--tw-text-opacity:1;color:rgba(var(--color-danger-500-rgb),var(--tw-text-opacity))}.text-important{--tw-text-opacity:1;color:rgba(var(--color-important-500-rgb),var(--tw-text-opacity))}.text-special{--tw-text-opacity:1;color:rgba(var(--color-special-500-rgb),var(--tw-text-opacity))}.text-primary-50{--tw-text-opacity:1;color:rgba(var(--color-primary-50-rgb),var(--tw-text-opacity))}.text-primary-100{--tw-text-opacity:1;color:rgba(var(--color-primary-100-rgb),var(--tw-text-opacity))}.text-primary-200{--tw-text-opacity:1;color:rgba(var(--color-primary-200-rgb),var(--tw-text-opacity))}.text-primary-300{--tw-text-opacity:1;color:rgba(var(--color-primary-300-rgb),var(--tw-text-opacity))}.text-primary-400{--tw-text-opacity:1;color:rgba(var(--color-primary-400-rgb),var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgba(var(--color-primary-600-rgb),var(--tw-text-opacity))}.text-primary-700{--tw-text-opacity:1;color:rgba(var(--color-primary-700-rgb),var(--tw-text-opacity))}.text-primary-800{--tw-text-opacity:1;color:rgba(var(--color-primary-800-rgb),var(--tw-text-opacity))}.text-primary-900{--tw-text-opacity:1;color:rgba(var(--color-primary-900-rgb),var(--tw-text-opacity))}.text-primary-950{--tw-text-opacity:1;color:rgba(var(--color-primary-950-rgb),var(--tw-text-opacity))}.text-secondary-50{--tw-text-opacity:1;color:rgba(var(--color-secondary-50-rgb),var(--tw-text-opacity))}.text-secondary-100{--tw-text-opacity:1;color:rgba(var(--color-secondary-100-rgb),var(--tw-text-opacity))}.text-secondary-200{--tw-text-opacity:1;color:rgba(var(--color-secondary-200-rgb),var(--tw-text-opacity))}.text-secondary-300{--tw-text-opacity:1;color:rgba(var(--color-secondary-300-rgb),var(--tw-text-opacity))}.text-secondary-400{--tw-text-opacity:1;color:rgba(var(--color-secondary-400-rgb),var(--tw-text-opacity))}.text-secondary-500{--tw-text-opacity:1;color:rgba(var(--color-secondary-500-rgb),var(--tw-text-opacity))}.text-secondary-600{--tw-text-opacity:1;color:rgba(var(--color-secondary-600-rgb),var(--tw-text-opacity))}.text-secondary-700{--tw-text-opacity:1;color:rgba(var(--color-secondary-700-rgb),var(--tw-text-opacity))}.text-secondary-800{--tw-text-opacity:1;color:rgba(var(--color-secondary-800-rgb),var(--tw-text-opacity))}.text-secondary-900{--tw-text-opacity:1;color:rgba(var(--color-secondary-900-rgb),var(--tw-text-opacity))}.text-secondary-950{--tw-text-opacity:1;color:rgba(var(--color-secondary-950-rgb),var(--tw-text-opacity))}.text-gray-50{--tw-text-opacity:1;color:rgba(var(--color-gray-50-rgb),var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgba(var(--color-gray-100-rgb),var(--tw-text-opacity))}.text-gray-200,.text-lightest{--tw-text-opacity:1;color:rgba(var(--color-gray-200-rgb),var(--tw-text-opacity))}.text-gray-300,.text-lighter{--tw-text-opacity:1;color:rgba(var(--color-gray-300-rgb),var(--tw-text-opacity))}.text-gray-400,.text-lighten{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.text-gray,.text-gray-500{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.text-darken,.text-gray-600{--tw-text-opacity:1;color:rgba(var(--color-gray-600-rgb),var(--tw-text-opacity))}.text-darker,.text-gray-700{--tw-text-opacity:1;color:rgba(var(--color-gray-700-rgb),var(--tw-text-opacity))}.text-darkest,.text-gray-800{--tw-text-opacity:1;color:rgba(var(--color-gray-800-rgb),var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgba(var(--color-gray-900-rgb),var(--tw-text-opacity))}.text-gray-950{--tw-text-opacity:1;color:rgba(var(--color-gray-950-rgb),var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgba(var(--color-white-rgb),var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgba(var(--color-black-rgb),var(--tw-text-opacity))}.text-transparent{color:transparent}.text-canvas{--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.text-surface-light{--tw-text-opacity:1;color:rgba(var(--color-surface-light-rgb),var(--tw-text-opacity))}.text-surface{--tw-text-opacity:1;color:rgba(var(--color-surface-rgb),var(--tw-text-opacity))}.text-surface-strong{--tw-text-opacity:1;color:rgba(var(--color-surface-strong-rgb),var(--tw-text-opacity))}.text-inverse{--tw-text-opacity:1;color:rgba(var(--color-inverse-rgb),var(--tw-text-opacity))}.text-fore-in-light{--tw-text-opacity:1;color:rgba(var(--color-fore-in-light-rgb),var(--tw-text-opacity))}.text-fore-in-dark{--tw-text-opacity:1;color:rgba(var(--color-fore-in-dark-rgb),var(--tw-text-opacity))}.text-fore{--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))}.text-focus{--tw-text-opacity:1;color:rgba(var(--color-focus-rgb),var(--tw-text-opacity))}.text-link{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity))}.text-link-hover{--tw-text-opacity:1;color:rgba(var(--color-link-hover-rgb),var(--tw-text-opacity))}.text-current{color:currentColor}.text-inherit{color:inherit}.clip,.ellipsis,.text-clip,.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.clip,.text-clip{text-overflow:clip}.whitespace-normal{white-space:normal}.nowrap,.whitespace-nowrap{white-space:nowrap}.pre,.whitespace-pre{white-space:pre}.pre-line,.whitespace-pre-line{white-space:pre-line}.pre-wrap,.whitespace-pre-wrap{white-space:pre-wrap}.break-normal{overflow-wrap:normal;word-break:normal}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.text-opacity-0{--tw-text-opacity:0}.text-opacity-5{--tw-text-opacity:.05}.text-opacity-10{--tw-text-opacity:.1}.text-opacity-20{--tw-text-opacity:.2}.text-opacity-25{--tw-text-opacity:.25}.text-opacity-30{--tw-text-opacity:.3}.text-opacity-40{--tw-text-opacity:.4}.text-opacity-50{--tw-text-opacity:.5}.text-opacity-60{--tw-text-opacity:.6}.text-opacity-70{--tw-text-opacity:.7}.text-opacity-80{--tw-text-opacity:.8}.text-opacity-90{--tw-text-opacity:.9}.text-opacity-95{--tw-text-opacity:.95}.text-opacity-100{--tw-text-opacity:1}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.list-none{list-style-type:none}.list-disc{list-style-type:disc}.list-decimal{list-style-type:decimal}.list-unstyled{list-style-type:none;padding-left:0}.underline{text-decoration-line:underline}.overline{text-decoration-line:overline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.bg-primary{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity))}.bg-secondary{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-500-rgb),var(--tw-bg-opacity))}.bg-success{--tw-bg-opacity:1;background-color:rgba(var(--color-success-500-rgb),var(--tw-bg-opacity))}.bg-warning{--tw-bg-opacity:1;background-color:rgba(var(--color-warning-500-rgb),var(--tw-bg-opacity))}.bg-danger{--tw-bg-opacity:1;background-color:rgba(var(--color-danger-500-rgb),var(--tw-bg-opacity))}.bg-important{--tw-bg-opacity:1;background-color:rgba(var(--color-important-500-rgb),var(--tw-bg-opacity))}.bg-special{--tw-bg-opacity:1;background-color:rgba(var(--color-special-500-rgb),var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.bg-primary-100{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-200-rgb),var(--tw-bg-opacity))}.bg-primary-300{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-300-rgb),var(--tw-bg-opacity))}.bg-primary-400{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-400-rgb),var(--tw-bg-opacity))}.bg-primary-500{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600-rgb),var(--tw-bg-opacity))}.bg-primary-700{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-700-rgb),var(--tw-bg-opacity))}.bg-primary-800{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-800-rgb),var(--tw-bg-opacity))}.bg-primary-900{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900-rgb),var(--tw-bg-opacity))}.bg-primary-950{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-950-rgb),var(--tw-bg-opacity))}.bg-secondary-50{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-50-rgb),var(--tw-bg-opacity))}.bg-secondary-100{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-100-rgb),var(--tw-bg-opacity))}.bg-secondary-200{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-200-rgb),var(--tw-bg-opacity))}.bg-secondary-300{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-300-rgb),var(--tw-bg-opacity))}.bg-secondary-400{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-400-rgb),var(--tw-bg-opacity))}.bg-secondary-500{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-500-rgb),var(--tw-bg-opacity))}.bg-secondary-600{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-600-rgb),var(--tw-bg-opacity))}.bg-secondary-700{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-700-rgb),var(--tw-bg-opacity))}.bg-secondary-800{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-800-rgb),var(--tw-bg-opacity))}.bg-secondary-900{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-900-rgb),var(--tw-bg-opacity))}.bg-secondary-950{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-950-rgb),var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.bg-gray-200,.bg-lightest{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-200-rgb),var(--tw-bg-opacity))}.bg-gray-300,.bg-lighter{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-300-rgb),var(--tw-bg-opacity))}.bg-gray-400,.bg-light{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-400-rgb),var(--tw-bg-opacity))}.bg-gray,.bg-gray-500{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-500-rgb),var(--tw-bg-opacity))}.bg-darken,.bg-gray-600{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-600-rgb),var(--tw-bg-opacity))}.bg-darker,.bg-gray-700{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}.bg-darkest,.bg-gray-800{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-800-rgb),var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-900-rgb),var(--tw-bg-opacity))}.bg-gray-950{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-950-rgb),var(--tw-bg-opacity))}.bg-canvas{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.bg-surface-light{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-light-rgb),var(--tw-bg-opacity))}.bg-surface{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity))}.bg-surface-strong{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-strong-rgb),var(--tw-bg-opacity))}.bg-inverse{--tw-bg-opacity:1;background-color:rgba(var(--color-inverse-rgb),var(--tw-bg-opacity))}.bg-fore-in-light{--tw-bg-opacity:1;background-color:rgba(var(--color-fore-in-light-rgb),var(--tw-bg-opacity))}.bg-fore-in-dark{--tw-bg-opacity:1;background-color:rgba(var(--color-fore-in-dark-rgb),var(--tw-bg-opacity))}.bg-fore{--tw-bg-opacity:1;background-color:rgba(var(--color-fore-rgb),var(--tw-bg-opacity))}.bg-focus{--tw-bg-opacity:1;background-color:rgba(var(--color-focus-rgb),var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgba(var(--color-white-rgb),var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgba(var(--color-black-rgb),var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-current{background-color:currentColor}.bg-inherit{background-color:inherit}.bg-none{background-image:none}.bg-opacity-0{--tw-bg-opacity:0}.bg-opacity-5{--tw-bg-opacity:.05}.bg-opacity-10{--tw-bg-opacity:.1}.bg-opacity-20{--tw-bg-opacity:.2}.bg-opacity-25{--tw-bg-opacity:.25}.bg-opacity-30{--tw-bg-opacity:.3}.bg-opacity-40{--tw-bg-opacity:.4}.bg-opacity-50{--tw-bg-opacity:.5}.bg-opacity-60{--tw-bg-opacity:.6}.bg-opacity-70{--tw-bg-opacity:.7}.bg-opacity-80{--tw-bg-opacity:.8}.bg-opacity-90{--tw-bg-opacity:.9}.bg-opacity-100{--tw-bg-opacity:1}.bg-auto{background-size:auto}.bg-cover{background-size:cover}.bg-contain{background-size:contain}.bg-repeat{background-repeat:repeat}.bg-no-repeat{background-repeat:no-repeat}.bg-repeat-x{background-repeat:repeat-x}.bg-repeat-y{background-repeat:repeat-y}.bg-repeat-round{background-repeat:round}.bg-repeat-space{background-repeat:space}.bg-bottom{background-position:bottom}.bg-center{background-position:50%}.bg-left{background-position:0}.bg-left-bottom{background-position:0 100%}.bg-left-top{background-position:0 0}.bg-right{background-position:100%}.bg-right-bottom{background-position:100% 100%}.bg-right-top{background-position:100% 0}.bg-top{background-position:top}.bg-fixed{background-attachment:fixed}.bg-local{background-attachment:local}.bg-scroll{background-attachment:scroll}.divider{align-self:stretch;border-color:currentColor;border-left-width:1px;border-top-width:1px;opacity:.1}.border-0{border-width:0}.border{border-width:1px}.border-2{border-width:2px}.border-4{border-width:4px}.border-t{border-top-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-b{border-bottom-width:1px}.border-t-0{border-top-width:0}.border-r-0{border-right-width:0}.border-b-0{border-bottom-width:0}.border-l-0{border-left-width:0}.border-t-2{border-top-width:2px}.border-l-2{border-left-width:2px}.border-r-2{border-right-width:2px}.border-b-2{border-bottom-width:2px}.border-t-4{border-top-width:4px}.border-l-4{border-left-width:4px}.border-r-4{border-right-width:4px}.border-b-4{border-bottom-width:4px}.border-light{--tw-border-opacity:1;border-color:rgba(var(--color-border-light-rgb),var(--tw-border-opacity))}.border-strong{--tw-border-opacity:1;border-color:rgba(var(--color-border-strong-rgb),var(--tw-border-opacity))}.border-primary{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500-rgb),var(--tw-border-opacity))}.border-secondary{--tw-border-opacity:1;border-color:rgba(var(--color-secondary-500-rgb),var(--tw-border-opacity))}.border-success{--tw-border-opacity:1;border-color:rgba(var(--color-success-500-rgb),var(--tw-border-opacity))}.border-warning{--tw-border-opacity:1;border-color:rgba(var(--color-warning-500-rgb),var(--tw-border-opacity))}.border-danger{--tw-border-opacity:1;border-color:rgba(var(--color-danger-500-rgb),var(--tw-border-opacity))}.border-important{--tw-border-opacity:1;border-color:rgba(var(--color-important-500-rgb),var(--tw-border-opacity))}.border-special{--tw-border-opacity:1;border-color:rgba(var(--color-special-500-rgb),var(--tw-border-opacity))}.border-gray-50{--tw-border-opacity:1;border-color:rgba(var(--color-gray-50-rgb),var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgba(var(--color-gray-100-rgb),var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgba(var(--color-gray-200-rgb),var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgba(var(--color-gray-300-rgb),var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity))}.border-gray,.border-gray-500{--tw-border-opacity:1;border-color:rgba(var(--color-gray-500-rgb),var(--tw-border-opacity))}.border-gray-600{--tw-border-opacity:1;border-color:rgba(var(--color-gray-600-rgb),var(--tw-border-opacity))}.border-gray-700{--tw-border-opacity:1;border-color:rgba(var(--color-gray-700-rgb),var(--tw-border-opacity))}.border-gray-800{--tw-border-opacity:1;border-color:rgba(var(--color-gray-800-rgb),var(--tw-border-opacity))}.border-gray-900{--tw-border-opacity:1;border-color:rgba(var(--color-gray-900-rgb),var(--tw-border-opacity))}.border-gray-950{--tw-border-opacity:1;border-color:rgba(var(--color-gray-950-rgb),var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgba(var(--color-white-rgb),var(--tw-border-opacity))}.border-black{--tw-border-opacity:1;border-color:rgba(var(--color-black-rgb),var(--tw-border-opacity))}.border-canvas{--tw-border-opacity:1;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity))}.border-surface-light{--tw-border-opacity:1;border-color:rgba(var(--color-surface-light-rgb),var(--tw-border-opacity))}.border-surface{--tw-border-opacity:1;border-color:rgba(var(--color-surface-rgb),var(--tw-border-opacity))}.border-surface-strong{--tw-border-opacity:1;border-color:rgba(var(--color-surface-strong-rgb),var(--tw-border-opacity))}.border-inverse{--tw-border-opacity:1;border-color:rgba(var(--color-inverse-rgb),var(--tw-border-opacity))}.border-fore-in-light{--tw-border-opacity:1;border-color:rgba(var(--color-fore-in-light-rgb),var(--tw-border-opacity))}.border-fore-in-dark{--tw-border-opacity:1;border-color:rgba(var(--color-fore-in-dark-rgb),var(--tw-border-opacity))}.border-fore{--tw-border-opacity:1;border-color:rgba(var(--color-fore-rgb),var(--tw-border-opacity))}.border-focus{--tw-border-opacity:1;border-color:rgba(var(--color-focus-rgb),var(--tw-border-opacity))}.border-link{--tw-border-opacity:1;border-color:rgba(var(--color-link-rgb),var(--tw-border-opacity))}.border-link-hover{--tw-border-opacity:1;border-color:rgba(var(--color-link-hover-rgb),var(--tw-border-opacity))}.border-transparent{border-color:transparent}.border-current{border-color:currentColor}.border-inherit{border-color:inherit}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-dotted{border-style:dotted}.border-double{border-style:double}.border-hidden{border-style:hidden}.border-none{border-style:none}.border-opacity-0{--tw-border-opacity:0}.border-opacity-5{--tw-border-opacity:.05}.border-opacity-10{--tw-border-opacity:.1}.border-opacity-20{--tw-border-opacity:.2}.border-opacity-25{--tw-border-opacity:.25}.border-opacity-30{--tw-border-opacity:.3}.border-opacity-40{--tw-border-opacity:.4}.border-opacity-50{--tw-border-opacity:.5}.border-opacity-60{--tw-border-opacity:.6}.border-opacity-70{--tw-border-opacity:.7}.border-opacity-80{--tw-border-opacity:.8}.border-opacity-90{--tw-border-opacity:.9}.border-opacity-95{--tw-border-opacity:.95}.border-opacity-100{--tw-border-opacity:1}.rounded-none{border-radius:var(--radius-none)}.rounded-sm{border-radius:var(--radius-sm)}.rounded{border-radius:var(--radius)}.rounded-md{border-radius:var(--radius-md)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.circle,.rounded-full{border-radius:var(--radius-full)}.rounded-l-none{border-bottom-left-radius:var(--radius-none);border-top-left-radius:var(--radius-none)}.rounded-t-none{border-top-left-radius:var(--radius-none)}.rounded-r-none,.rounded-t-none{border-top-right-radius:var(--radius-none)}.rounded-b-none,.rounded-r-none{border-bottom-right-radius:var(--radius-none)}.rounded-b-none{border-bottom-left-radius:var(--radius-none)}.rounded-br-none{border-bottom-right-radius:var(--radius-none)}.rounded-bl-none{border-bottom-left-radius:var(--radius-none)}.rounded-tr-none{border-top-right-radius:var(--radius-none)}.rounded-tl-none{border-top-left-radius:var(--radius-none)}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity))}.ring-border-light{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-light-rgb),var(--tw-ring-opacity))}.ring-border{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity))}.ring-border-strong{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-strong-rgb),var(--tw-ring-opacity))}.ring-light{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05}.ring-gray{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.1}.ring-dark{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.2}.ring-darker{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.3}.ring-darkest{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.5}.ring-primary{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-500-rgb),var(--tw-ring-opacity))}.ring-secondary{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-secondary-500-rgb),var(--tw-ring-opacity))}.ring-warning{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-warning-500-rgb),var(--tw-ring-opacity))}.ring-success{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-success-500-rgb),var(--tw-ring-opacity))}.ring-danger{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-danger-500-rgb),var(--tw-ring-opacity))}.ring-important{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-important-500-rgb),var(--tw-ring-opacity))}.ring-special{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-special-500-rgb),var(--tw-ring-opacity))}.ring-gray-50{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-50-rgb),var(--tw-ring-opacity))}.ring-gray-100{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-100-rgb),var(--tw-ring-opacity))}.ring-gray-200{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-200-rgb),var(--tw-ring-opacity))}.ring-gray-300{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-300-rgb),var(--tw-ring-opacity))}.ring-gray-400{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-400-rgb),var(--tw-ring-opacity))}.ring-gray-500{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-500-rgb),var(--tw-ring-opacity))}.ring-gray-600{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-600-rgb),var(--tw-ring-opacity))}.ring-gray-700{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-700-rgb),var(--tw-ring-opacity))}.ring-gray-800{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-800-rgb),var(--tw-ring-opacity))}.ring-gray-900{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-900-rgb),var(--tw-ring-opacity))}.ring-gray-950{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-950-rgb),var(--tw-ring-opacity))}.ring-inverse{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity))}.ring-canvas{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-canvas-rgb),var(--tw-ring-opacity))}.ring-surface{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-rgb),var(--tw-ring-opacity))}.ring-fore{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-fore-rgb),var(--tw-ring-opacity))}.ring-transparent{--tw-ring-color:transparent}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-black-rgb),var(--tw-ring-opacity))}.ring-white{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-white-rgb),var(--tw-ring-opacity))}.ring-inherit{--tw-ring-color:inherit}.ring-current{--tw-ring-color:currentColor}.ring-opacity-0{--tw-ring-opacity:0}.ring-opacity-5{--tw-ring-opacity:.05}.ring-opacity-10{--tw-ring-opacity:.1}.ring-opacity-20{--tw-ring-opacity:.2}.ring-opacity-30{--tw-ring-opacity:.3}.ring-opacity-40{--tw-ring-opacity:.4}.ring-opacity-50{--tw-ring-opacity:.5}.ring-opacity-60{--tw-ring-opacity:.6}.ring-opacity-70{--tw-ring-opacity:.7}.ring-opacity-80{--tw-ring-opacity:.8}.ring-opacity-90{--tw-ring-opacity:.9}.ring-opacity-100{--tw-ring-opacity:1}.ring-0{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-0,.ring-2{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-3{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-3,.ring-4{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-8{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-inset{--tw-ring-inset:inset}.ring-offset-0{--tw-ring-offset-width:0px}.ring-offset-1{--tw-ring-offset-width:1px}.ring-offset-2{--tw-ring-offset-width:2px}.ring-offset-4{--tw-ring-offset-width:4px}.ring-offset-8{--tw-ring-offset-width:8px}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 2px 6px -1px rgba(0,0,0,.2),0 1px 4px -2px rgba(0,0,0,.15);--tw-shadow-colored:0 2px 6px -1px var(--tw-shadow-color),0 1px 4px -2px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 5px 15px -3px rgba(0,0,0,.2),0 2px 6px -4px rgba(0,0,0,.15);--tw-shadow-colored:0 5px 15px -3px var(--tw-shadow-color),0 2px 6px -4px var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color)}.shadow-2xl,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 10px 50px -10px rgba(0,0,0,.4),0 8px 20px -10px rgba(0,0,0,.3);--tw-shadow-colored:0 10px 50px -10px var(--tw-shadow-color),0 8px 20px -10px var(--tw-shadow-color)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-inner,.shadow-none{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.muted{opacity:var(--opacity-muted)}.opacity-0{opacity:0}.opacity-5{opacity:.05}.opacity-10{opacity:.1}.opacity-20{opacity:.2}.opacity-25{opacity:.25}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.opacity-95{opacity:.95}.opacity-100{opacity:1}.blur-none{--tw-blur:blur(0)}.blur-none,.blur-sm{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-sm{--tw-blur:blur(4px)}.blur{--tw-blur:blur(8px)}.blur,.blur-md{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-md{--tw-blur:blur(12px)}.blur-lg{--tw-blur:blur(16px)}.blur-lg,.blur-xl{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-xl{--tw-blur:blur(24px)}.grayscale{--tw-grayscale:grayscale(100%)}.grayscale,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter-none{filter:none!important}.drop-shadow-none{--tw-drop-shadow:drop-shadow(0 0 #0000)}.drop-shadow-none,.drop-shadow-sm{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-sm{--tw-drop-shadow:drop-shadow(0 1px 1px rgba(0,0,0,.05))}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.drop-shadow,.drop-shadow-md{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-md{--tw-drop-shadow:drop-shadow(0 4px 3px rgba(0,0,0,.07)) drop-shadow(0 2px 2px rgba(0,0,0,.06))}.drop-shadow-lg{--tw-drop-shadow:drop-shadow(0 10px 8px rgba(0,0,0,.04)) drop-shadow(0 4px 3px rgba(0,0,0,.1))}.drop-shadow-lg,.drop-shadow-xl{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-xl{--tw-drop-shadow:drop-shadow(0 20px 13px rgba(0,0,0,.03)) drop-shadow(0 8px 5px rgba(0,0,0,.08))}.drop-shadow-2xl{--tw-drop-shadow:drop-shadow(0 25px 25px rgba(0,0,0,.15));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-none{--tw-backdrop-blur:blur(0)}.backdrop-blur-none,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur{--tw-backdrop-blur:blur(8px)}.backdrop-blur,.backdrop-blur-md{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px)}.backdrop-blur-lg,.backdrop-blur-xl{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)}.backdrop-blur-2xl{--tw-backdrop-blur:blur(40px)}.backdrop-blur-2xl,.backdrop-blur-3xl{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-3xl{--tw-backdrop-blur:blur(64px)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-shadow{transition-duration:.15s;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-none{transition-property:none}.fade,.fade-from-bottom,.fade-from-center,.fade-from-left,.fade-from-right,.fade-from-top{opacity:0;transition-duration:.15s;transition-property:opacity,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.fade-from-bottom,.fade-from-center,.fade-from-left,.fade-from-right,.fade-from-top{--tw-scale-x:.9;--tw-scale-y:.9}.fade-from-bottom,.fade-from-center,.fade-from-left,.fade-from-right,.fade-from-top{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fade-from-bottom{--tw-translate-y:25%}.fade-from-top{--tw-translate-y:-25%}.fade-from-left,.fade-from-top{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fade-from-left{--tw-translate-x:-25%}.fade-from-right{--tw-translate-x:25%}.fade-from-bottom.in,.fade-from-center.in,.fade-from-left.in,.fade-from-right,.fade-from-right.in,.fade-from-top.in,.fade.in{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fade-from-bottom.in,.fade-from-center.in,.fade-from-left.in,.fade-from-right.in,.fade-from-top.in,.fade.in{--tw-translate-x:0px;--tw-translate-y:0px;--tw-scale-x:1;--tw-scale-y:1;opacity:1}.duration-75{transition-duration:75ms}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-1000{transition-duration:1s}@keyframes -spin{to{transform:rotate(1turn)}}.animate-spin,.spin{animation:-spin 1s linear infinite}@keyframes -ping{75%,to{opacity:0;transform:scale(2)}}.animate-ping,.ping{animation:-ping 1s cubic-bezier(0,0,.2,1) infinite}@keyframes -pulse{50%{opacity:.5}}.animate-pulse,.pulse{animation:-pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes -bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}.animate-bounce,.bounce{animation:-bounce 1s infinite}.animate-highlight,.highlight{animation:-highlight 2s ease-in-out infinite;outline-color:#fde047;outline-offset:-1px;outline-style:solid;outline-width:1px}@keyframes -highlight{50%{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity));outline-offset:-4px;outline-width:4px}}.scale-0{--tw-scale-x:0;--tw-scale-y:0}.scale-0,.scale-50{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-50{--tw-scale-x:.5;--tw-scale-y:.5}.scale-75{--tw-scale-x:.75;--tw-scale-y:.75}.scale-75,.scale-90{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-90{--tw-scale-x:.9;--tw-scale-y:.9}.scale-95{--tw-scale-x:.95;--tw-scale-y:.95}.scale-100,.scale-95{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.scale-105,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.scale-125{--tw-scale-x:1.25;--tw-scale-y:1.25}.scale-125,.scale-150{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-150{--tw-scale-x:1.5;--tw-scale-y:1.5}.flip-x{--tw-scale-x:-1}.flip-x,.flip-y{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.flip-y{--tw-scale-y:-1}.rotate-0{--tw-rotate:0deg}.rotate-0,.rotate-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-1{--tw-rotate:1deg}.rotate-2{--tw-rotate:2deg}.rotate-2,.rotate-3{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-3{--tw-rotate:3deg}.rotate-6{--tw-rotate:6deg}.rotate-12,.rotate-6{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-12{--tw-rotate:12deg}.rotate-45{--tw-rotate:45deg}.rotate-45,.rotate-90{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate:90deg}.rotate-135{--tw-rotate:135deg}.rotate-135,.rotate-180{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.rotate-270{--tw-rotate:270deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.basis-0{flex-basis:0px}.basis-1{flex-basis:0.25rem}.basis-2{flex-basis:0.5rem}.basis-3{flex-basis:0.75rem}.basis-4{flex-basis:1rem}.basis-5{flex-basis:1.25rem}.basis-6{flex-basis:1.5rem}.basis-7{flex-basis:1.75rem}.basis-8{flex-basis:2rem}.basis-9{flex-basis:2.25rem}.basis-10{flex-basis:2.5rem}.basis-11{flex-basis:2.75rem}.basis-12{flex-basis:3rem}.basis-14{flex-basis:3.5rem}.basis-16{flex-basis:4rem}.basis-20{flex-basis:5rem}.basis-24{flex-basis:6rem}.basis-28{flex-basis:7rem}.basis-32{flex-basis:8rem}.basis-36{flex-basis:9rem}.basis-40{flex-basis:10rem}.basis-44{flex-basis:11rem}.basis-48{flex-basis:12rem}.basis-52{flex-basis:13rem}.basis-56{flex-basis:14rem}.basis-60{flex-basis:15rem}.basis-64{flex-basis:16rem}.basis-72{flex-basis:18rem}.basis-80{flex-basis:20rem}.basis-96{flex-basis:24rem}.basis-auto{flex-basis:auto}.basis-px{flex-basis:1px}.basis-0\.5{flex-basis:0.125rem}.basis-1\.5{flex-basis:0.375rem}.basis-2\.5{flex-basis:0.625rem}.basis-3\.5{flex-basis:0.875rem}.basis-1\/2{flex-basis:50%}.basis-1\/3{flex-basis:33.333333%}.basis-2\/3{flex-basis:66.666667%}.basis-1\/4{flex-basis:25%}.basis-2\/4{flex-basis:50%}.basis-3\/4{flex-basis:75%}.basis-1\/5{flex-basis:20%}.basis-2\/5{flex-basis:40%}.basis-3\/5{flex-basis:60%}.basis-4\/5{flex-basis:80%}.basis-1\/6{flex-basis:16.666667%}.basis-2\/6{flex-basis:33.333333%}.basis-3\/6{flex-basis:50%}.basis-4\/6{flex-basis:66.666667%}.basis-5\/6{flex-basis:83.333333%}.basis-1\/12{flex-basis:8.333333%}.basis-2\/12{flex-basis:16.666667%}.basis-3\/12{flex-basis:25%}.basis-4\/12{flex-basis:33.333333%}.basis-5\/12{flex-basis:41.666667%}.basis-6\/12{flex-basis:50%}.basis-7\/12{flex-basis:58.333333%}.basis-8\/12{flex-basis:66.666667%}.basis-9\/12{flex-basis:75%}.basis-10\/12{flex-basis:83.333333%}.basis-11\/12{flex-basis:91.666667%}.basis-full{flex-basis:100%}.row{display:flex;flex-direction:row}.center,.col{display:flex;flex-direction:column}.center,.center-row{align-items:center;justify-content:center}.center-row{display:flex;flex-direction:row}.center-x,.center-y{align-items:center;display:flex}.center-y{flex-direction:column}.row-reverse{display:flex;flex-direction:row-reverse}.col-reverse{display:flex;flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.flex-nowrap{flex-wrap:nowrap}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.flex-initial{flex:0 1 auto}.flex-none{flex:none}.grow{flex-grow:1!important}.grow-0{flex-grow:0!important}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.order-first{order:-9999}.order-last{order:9999}.order-none{order:0}.gap-0{gap:0}.gap-x-0{-moz-column-gap:0;column-gap:0}.gap-y-0{row-gap:0}.gap-px{gap:1px}.gap-x-px{-moz-column-gap:1px;column-gap:1px}.gap-y-px{row-gap:1px}.gap-0\.5{gap:.125rem}.gap-x-0\.5{-moz-column-gap:.125rem;column-gap:.125rem}.gap-y-0\.5{row-gap:.125rem}.gap-3px{gap:3px}.gap-1{gap:.25rem}.gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.gap-y-1{row-gap:.25rem}.gap-1\.5{gap:.375rem}.gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.gap-y-1\.5{row-gap:.375rem}.gap-2{gap:.5rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.gap-y-2{row-gap:.5rem}.gap-2\.5{gap:.625rem}.gap-x-2\.5{-moz-column-gap:.625rem;column-gap:.625rem}.gap-y-2\.5{row-gap:.625rem}.gap-3{gap:.75rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-3{row-gap:.75rem}.gap-3\.5{gap:.875rem}.gap-x-3\.5{-moz-column-gap:.875rem;column-gap:.875rem}.gap-y-3\.5{row-gap:.875rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-4{row-gap:1rem}.gap-5{gap:1.25rem}.gap-x-5{-moz-column-gap:1.25rem;column-gap:1.25rem}.gap-y-5{row-gap:1.25rem}.gap-6{gap:1.5rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-y-6{row-gap:1.5rem}.gap-7{gap:1.75rem}.gap-x-7{-moz-column-gap:1.75rem;column-gap:1.75rem}.gap-y-7{row-gap:1.75rem}.gap-8{gap:2rem}.gap-x-8{-moz-column-gap:2rem;column-gap:2rem}.gap-y-8{row-gap:2rem}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-evenly{justify-content:space-evenly}.self-auto{align-self:auto}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.self-center{align-self:center}.self-stretch{align-self:stretch}.self-baseline{align-self:baseline}.content-center{align-content:center}.content-start{align-content:flex-start}.content-end{align-content:flex-end}.content-between{align-content:space-between}.content-around{align-content:space-around}.content-evenly{align-content:space-evenly}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}@font-face{font-display:fallback;font-family:D-DIN-PRO;font-weight:400;src:url(./fonts/D-DIN-PRO-400-Regular.otf)}@font-face{font-display:fallback;font-family:D-DIN-PRO;font-weight:500;src:url(./fonts/D-DIN-PRO-700-Bold.otf)}.num{font-family:D-DIN-PRO}@font-face{font-display:fallback;font-family:Nunito;font-weight:400;src:url(./fonts/Nunito-Regular.ttf)}@font-face{font-display:fallback;font-family:Nunito;font-weight:700;src:url(./fonts/Nunito-Bold.ttf)}@font-face{font-display:fallback;font-family:Nunito;font-weight:300;src:url(./fonts/Nunito-Light.ttf)}.font-brand{font-family:Nunito;font-weight:400}@supports not (gap:4px){.gap-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1px*(1 - var(--tw-space-x-reverse)));margin-right:calc(1px*var(--tw-space-x-reverse))}.gap-0\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2px*(1 - var(--tw-space-x-reverse)));margin-right:calc(2px*var(--tw-space-x-reverse))}.gap-3px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(3px*(1 - var(--tw-space-x-reverse)));margin-right:calc(3px*var(--tw-space-x-reverse))}.gap-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.gap-1\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(6px*(1 - var(--tw-space-x-reverse)));margin-right:calc(6px*var(--tw-space-x-reverse))}.gap-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.gap-2\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(10px*(1 - var(--tw-space-x-reverse)));margin-right:calc(10px*var(--tw-space-x-reverse))}.gap-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.gap-3\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(14px*(1 - var(--tw-space-x-reverse)));margin-right:calc(14px*var(--tw-space-x-reverse))}.gap-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.gap-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.25rem*var(--tw-space-x-reverse))}.gap-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.5rem*var(--tw-space-x-reverse))}.gap-7>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.75rem*var(--tw-space-x-reverse))}.gap-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2rem*var(--tw-space-x-reverse))}.col.gap-px>:not([hidden])~:not([hidden]),.gap-px.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1px*var(--tw-space-y-reverse));margin-top:calc(1px*(1 - var(--tw-space-y-reverse)))}.col.gap-0\.5>:not([hidden])~:not([hidden]),.gap-0\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2px*var(--tw-space-y-reverse));margin-top:calc(2px*(1 - var(--tw-space-y-reverse)))}.col.gap-3px>:not([hidden])~:not([hidden]),.gap-3px.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(3px*var(--tw-space-y-reverse));margin-top:calc(3px*(1 - var(--tw-space-y-reverse)))}.col.gap-1>:not([hidden])~:not([hidden]),.gap-1.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.col.gap-1\.5>:not([hidden])~:not([hidden]),.gap-1\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(6px*var(--tw-space-y-reverse));margin-top:calc(6px*(1 - var(--tw-space-y-reverse)))}.col.gap-2>:not([hidden])~:not([hidden]),.gap-2.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.col.gap-2\.5>:not([hidden])~:not([hidden]),.gap-2\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(10px*var(--tw-space-y-reverse));margin-top:calc(10px*(1 - var(--tw-space-y-reverse)))}.col.gap-3>:not([hidden])~:not([hidden]),.gap-3.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.col.gap-3\.5>:not([hidden])~:not([hidden]),.gap-3\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(14px*var(--tw-space-y-reverse));margin-top:calc(14px*(1 - var(--tw-space-y-reverse)))}.col.gap-4>:not([hidden])~:not([hidden]),.gap-4.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.col.gap-5>:not([hidden])~:not([hidden]),.gap-5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.col.gap-6>:not([hidden])~:not([hidden]),.gap-6.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.col.gap-7>:not([hidden])~:not([hidden]),.gap-7.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.75rem*var(--tw-space-y-reverse));margin-top:calc(1.75rem*(1 - var(--tw-space-y-reverse)))}.col.gap-8>:not([hidden])~:not([hidden]),.gap-8.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.nav-item>a>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}} \ No newline at end of file +/*! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border-color:rgb(var(--color-gray-200-rgb));border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:-apple-system,Noto Sans,Helvetica Neue,Helvetica,Nimbus Sans L,Arial,Liberation Sans,PingFang SC,Hiragino Sans GB,Noto Sans CJK SC,Source Han Sans SC,Source Han Sans CN,Microsoft YaHei,Wenquanyi Micro Hei,WenQuanYi Zen Hei,ST Heiti,SimHei,WenQuanYi Zen Hei Sharp,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-size:1em;font-variation-settings:normal}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-feature-settings:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:rgb(var(--color-gray-400-rgb));opacity:1}input::placeholder,textarea::placeholder{color:rgb(var(--color-gray-400-rgb));opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}:root{--screen-2xl:1720px;--color-gray-50:#fcfdfe;--color-gray-100:#eff1f3;--color-gray-200:#ebedf3;--color-gray-300:#d2d6e5;--color-gray-400:#b2b9c5;--color-gray-500:#64758b;--color-gray-600:#4a577f;--color-gray-700:#3d4667;--color-gray-800:#353d57;--color-gray-900:#30394a;--color-gray-950:#0b0f18;--color-gray-50-rgb:252,253,254;--color-gray-100-rgb:239,241,243;--color-gray-200-rgb:235,237,243;--color-gray-300-rgb:210,214,229;--color-gray-400-rgb:178,185,197;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:74,87,127;--color-gray-700-rgb:61,70,103;--color-gray-800-rgb:53,61,87;--color-gray-900-rgb:48,57,74;--color-gray-950-rgb:11,15,24;--color-primary-50:#eef6ff;--color-primary-100:#d9eaff;--color-primary-200:#bcdcff;--color-primary-300:#8ec6ff;--color-primary-400:#59a5ff;--color-primary-500:#3883fa;--color-primary-600:#2b67e5;--color-primary-700:#144ce1;--color-primary-800:#173db6;--color-primary-900:#19388f;--color-primary-950:#142457;--color-primary-50-rgb:238,246,255;--color-primary-100-rgb:217,234,255;--color-primary-200-rgb:188,220,255;--color-primary-300-rgb:142,198,255;--color-primary-400-rgb:89,165,255;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:43,103,229;--color-primary-700-rgb:20,76,225;--color-primary-800-rgb:23,61,182;--color-primary-900-rgb:25,56,143;--color-primary-950-rgb:20,36,87;--color-secondary-50:#e7f6ff;--color-secondary-100:#cdecff;--color-secondary-200:#9bd9ff;--color-secondary-300:#77cbff;--color-secondary-400:#60c2ff;--color-secondary-500:#37b2fe;--color-secondary-600:#18a6fd;--color-secondary-700:#1099ed;--color-secondary-800:#078ada;--color-secondary-900:#046bab;--color-secondary-950:#062a4b;--color-secondary-50-rgb:231,246,255;--color-secondary-100-rgb:205,236,255;--color-secondary-200-rgb:155,217,255;--color-secondary-300-rgb:119,203,255;--color-secondary-400-rgb:96,194,255;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:24,166,253;--color-secondary-700-rgb:16,153,237;--color-secondary-800-rgb:7,138,218;--color-secondary-900-rgb:4,107,171;--color-secondary-950-rgb:6,42,75;--color-success-50:#effaf6;--color-success-100:#d6f2e7;--color-success-200:#ade5ce;--color-success-300:#83d7b6;--color-success-400:#5aca9d;--color-success-500:#31bd85;--color-success-600:#2ba675;--color-success-700:#28996c;--color-success-800:#21805a;--color-success-900:#185e3b;--color-success-950:#0e3421;--color-success-50-rgb:239,250,246;--color-success-100-rgb:214,242,231;--color-success-200-rgb:173,229,206;--color-success-300-rgb:131,215,182;--color-success-400-rgb:90,202,157;--color-success-500-rgb:49,189,133;--color-success-600-rgb:43,166,117;--color-success-700-rgb:40,153,108;--color-success-800-rgb:33,128,90;--color-success-900-rgb:24,94,59;--color-success-950-rgb:14,52,33;--color-warning-50:#fff4ea;--color-warning-100:#ffecdb;--color-warning-200:#ffd2a9;--color-warning-300:#ffbc7e;--color-warning-400:#ffaf65;--color-warning-500:#ff9f46;--color-warning-600:#f38f19;--color-warning-700:#ed8307;--color-warning-800:#d17100;--color-warning-900:#af5f01;--color-warning-950:#441506;--color-warning-50-rgb:255,244,234;--color-warning-100-rgb:255,236,219;--color-warning-200-rgb:255,210,169;--color-warning-300-rgb:255,188,126;--color-warning-400-rgb:255,175,101;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:243,143,25;--color-warning-700-rgb:237,131,7;--color-warning-800-rgb:209,113,0;--color-warning-900-rgb:175,95,1;--color-warning-950-rgb:68,21,6;--color-danger-50:#ffebeb;--color-danger-100:#ffd5d5;--color-danger-200:#ffb1b1;--color-danger-300:#ff9292;--color-danger-400:#ff7c7c;--color-danger-500:#fc5959;--color-danger-600:#fb2b2b;--color-danger-700:#d91b1b;--color-danger-800:#ba1313;--color-danger-900:#a20606;--color-danger-950:#470808;--color-danger-50-rgb:255,235,235;--color-danger-100-rgb:255,213,213;--color-danger-200-rgb:255,177,177;--color-danger-300-rgb:255,146,146;--color-danger-400-rgb:255,124,124;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:251,43,43;--color-danger-700-rgb:217,27,27;--color-danger-800-rgb:186,19,19;--color-danger-900-rgb:162,6,6;--color-danger-950-rgb:71,8,8;--color-important-50:#fff8f5;--color-important-100:#ffe2d9;--color-important-200:#ffcebf;--color-important-300:#ffb29b;--color-important-400:#ff8c68;--color-important-500:#ff8058;--color-important-600:#ff6f42;--color-important-700:#ff4912;--color-important-800:#c83509;--color-important-900:#611700;--color-important-950:#440609;--color-important-50-rgb:255,248,245;--color-important-100-rgb:255,226,217;--color-important-200-rgb:255,206,191;--color-important-300-rgb:255,178,155;--color-important-400-rgb:255,140,104;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,111,66;--color-important-700-rgb:255,73,18;--color-important-800-rgb:200,53,9;--color-important-900-rgb:97,23,0;--color-important-950-rgb:68,6,9;--color-special-50:#efecfa;--color-special-100:#e4dff7;--color-special-200:#c4b6ff;--color-special-300:#a38cff;--color-special-400:#8a6ff5;--color-special-500:#8166ee;--color-special-600:#7055df;--color-special-700:#513baa;--color-special-800:#452da5;--color-special-900:#30216e;--color-special-950:#271560;--color-special-50-rgb:239,236,250;--color-special-100-rgb:228,223,247;--color-special-200-rgb:196,182,255;--color-special-300-rgb:163,140,255;--color-special-400-rgb:138,111,245;--color-special-500-rgb:129,102,238;--color-special-600-rgb:112,85,223;--color-special-700-rgb:81,59,170;--color-special-800-rgb:69,45,165;--color-special-900-rgb:48,33,110;--color-special-950-rgb:39,21,96;--color-inherit:inherit;--color-transparent:transparent;--color-current:currentColor;--color-black:#000;--color-white:#fff;--color-canvas:#fff;--color-canvas-light:#fff;--color-canvas-dark:#fcfdfe;--color-inverse:#000;--color-surface:#eff1f3;--color-surface-light:#fcfdfe;--color-surface-strong:#ebedf3;--color-fore:#30394a;--color-fore-in-light:#30394a;--color-fore-in-dark:#fff;--color-focus:#bcdcff;--color-link:#2b47a2;--color-link-hover:#144ce1;--color-link-visited:#6328a4;--color-link-active:#144ce1;--color-placeholder:#64758b;--color-border:#ebedf3;--color-border-strong:#d2d6e5;--color-border-light:#eff1f3;--color-black-rgb:0,0,0;--color-white-rgb:255,255,255;--color-canvas-rgb:255,255,255;--color-canvas-light-rgb:255,255,255;--color-canvas-dark-rgb:252,253,254;--color-inverse-rgb:0,0,0;--color-surface-rgb:239,241,243;--color-surface-light-rgb:252,253,254;--color-surface-strong-rgb:235,237,243;--color-fore-rgb:48,57,74;--color-fore-in-light-rgb:48,57,74;--color-fore-in-dark-rgb:255,255,255;--color-focus-rgb:188,220,255;--color-link-rgb:43,71,162;--color-link-hover-rgb:20,76,225;--color-link-visited-rgb:99,40,164;--color-link-active-rgb:20,76,225;--color-placeholder-rgb:100,117,139;--color-border-rgb:235,237,243;--color-border-strong-rgb:210,214,229;--color-border-light-rgb:239,241,243;--radius-none:0px;--radius-sm:0.0625rem;--radius:0.125rem;--radius-md:0.25rem;--radius-lg:0.375rem;--radius-xl:0.5rem;--radius-2xl:0.75rem;--radius-3xl:1rem;--radius-full:9999px;--shadow-sm:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--shadow-md:0 2px 6px -1px rgba(0,0,0,.2),0 1px 4px -2px rgba(0,0,0,.15);--shadow-lg:0 5px 15px -3px rgba(0,0,0,.2),0 2px 6px -4px rgba(0,0,0,.15);--shadow-xl:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--shadow-2xl:0 10px 50px -10px rgba(0,0,0,.4),0 8px 20px -10px rgba(0,0,0,.3);--shadow-inner:inset 0 2px 4px 0 rgba(0,0,0,.05);--shadow-none:none;--space:0.25rem;--font-size-article:0.875rem;--font-size-root:16px;--font-size-page-lineHeight:1.5384615385}.dark{--color-gray-50:#0b0f18;--color-gray-100:#30394a;--color-gray-200:#353d57;--color-gray-300:#3d4667;--color-gray-400:#4a577f;--color-gray-500:#64758b;--color-gray-600:#b2b9c5;--color-gray-700:#d2d6e5;--color-gray-800:#ebedf3;--color-gray-900:#eff1f3;--color-gray-950:#fcfdfe;--color-gray-50-rgb:11,15,24;--color-gray-100-rgb:48,57,74;--color-gray-200-rgb:53,61,87;--color-gray-300-rgb:61,70,103;--color-gray-400-rgb:74,87,127;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:178,185,197;--color-gray-700-rgb:210,214,229;--color-gray-800-rgb:235,237,243;--color-gray-900-rgb:239,241,243;--color-gray-950-rgb:252,253,254;--color-primary-50:#142457;--color-primary-100:#19388f;--color-primary-200:#173db6;--color-primary-300:#144ce1;--color-primary-400:#2b67e5;--color-primary-500:#3883fa;--color-primary-600:#59a5ff;--color-primary-700:#8ec6ff;--color-primary-800:#bcdcff;--color-primary-900:#d9eaff;--color-primary-950:#eef6ff;--color-primary-50-rgb:20,36,87;--color-primary-100-rgb:25,56,143;--color-primary-200-rgb:23,61,182;--color-primary-300-rgb:20,76,225;--color-primary-400-rgb:43,103,229;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:89,165,255;--color-primary-700-rgb:142,198,255;--color-primary-800-rgb:188,220,255;--color-primary-900-rgb:217,234,255;--color-primary-950-rgb:238,246,255;--color-secondary-50:#062a4b;--color-secondary-100:#046bab;--color-secondary-200:#078ada;--color-secondary-300:#1099ed;--color-secondary-400:#18a6fd;--color-secondary-500:#37b2fe;--color-secondary-600:#60c2ff;--color-secondary-700:#77cbff;--color-secondary-800:#9bd9ff;--color-secondary-900:#cdecff;--color-secondary-950:#e7f6ff;--color-secondary-50-rgb:6,42,75;--color-secondary-100-rgb:4,107,171;--color-secondary-200-rgb:7,138,218;--color-secondary-300-rgb:16,153,237;--color-secondary-400-rgb:24,166,253;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:96,194,255;--color-secondary-700-rgb:119,203,255;--color-secondary-800-rgb:155,217,255;--color-secondary-900-rgb:205,236,255;--color-secondary-950-rgb:231,246,255;--color-success-50:#0e3421;--color-success-100:#185e3b;--color-success-200:#21805a;--color-success-300:#28996c;--color-success-400:#2ba675;--color-success-500:#31bd85;--color-success-600:#5aca9d;--color-success-700:#83d7b6;--color-success-800:#ade5ce;--color-success-900:#d6f2e7;--color-success-950:#effaf6;--color-success-50-rgb:14,52,33;--color-success-100-rgb:24,94,59;--color-success-200-rgb:33,128,90;--color-success-300-rgb:40,153,108;--color-success-400-rgb:43,166,117;--color-success-500-rgb:49,189,133;--color-success-600-rgb:90,202,157;--color-success-700-rgb:131,215,182;--color-success-800-rgb:173,229,206;--color-success-900-rgb:214,242,231;--color-success-950-rgb:239,250,246;--color-warning-50:#441506;--color-warning-100:#af5f01;--color-warning-200:#d17100;--color-warning-300:#ed8307;--color-warning-400:#f38f19;--color-warning-500:#ff9f46;--color-warning-600:#ffaf65;--color-warning-700:#ffbc7e;--color-warning-800:#ffd2a9;--color-warning-900:#ffecdb;--color-warning-950:#fff4ea;--color-warning-50-rgb:68,21,6;--color-warning-100-rgb:175,95,1;--color-warning-200-rgb:209,113,0;--color-warning-300-rgb:237,131,7;--color-warning-400-rgb:243,143,25;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:255,175,101;--color-warning-700-rgb:255,188,126;--color-warning-800-rgb:255,210,169;--color-warning-900-rgb:255,236,219;--color-warning-950-rgb:255,244,234;--color-danger-50:#470808;--color-danger-100:#a20606;--color-danger-200:#ba1313;--color-danger-300:#d91b1b;--color-danger-400:#fb2b2b;--color-danger-500:#fc5959;--color-danger-600:#ff7c7c;--color-danger-700:#ff9292;--color-danger-800:#ffb1b1;--color-danger-900:#ffd5d5;--color-danger-950:#ffebeb;--color-danger-50-rgb:71,8,8;--color-danger-100-rgb:162,6,6;--color-danger-200-rgb:186,19,19;--color-danger-300-rgb:217,27,27;--color-danger-400-rgb:251,43,43;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:255,124,124;--color-danger-700-rgb:255,146,146;--color-danger-800-rgb:255,177,177;--color-danger-900-rgb:255,213,213;--color-danger-950-rgb:255,235,235;--color-important-50:#440609;--color-important-100:#611700;--color-important-200:#c83509;--color-important-300:#ff4912;--color-important-400:#ff6f42;--color-important-500:#ff8058;--color-important-600:#ff8c68;--color-important-700:#ffb29b;--color-important-800:#ffcebf;--color-important-900:#ffe2d9;--color-important-950:#fff8f5;--color-important-50-rgb:68,6,9;--color-important-100-rgb:97,23,0;--color-important-200-rgb:200,53,9;--color-important-300-rgb:255,73,18;--color-important-400-rgb:255,111,66;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,140,104;--color-important-700-rgb:255,178,155;--color-important-800-rgb:255,206,191;--color-important-900-rgb:255,226,217;--color-important-950-rgb:255,248,245;--color-special-50:#271560;--color-special-100:#30216e;--color-special-200:#452da5;--color-special-300:#513baa;--color-special-400:#7055df;--color-special-500:#8166ee;--color-special-600:#8a6ff5;--color-special-700:#a38cff;--color-special-800:#c4b6ff;--color-special-900:#e4dff7;--color-special-950:#efecfa;--color-special-50-rgb:39,21,96;--color-special-100-rgb:48,33,110;--color-special-200-rgb:69,45,165;--color-special-300-rgb:81,59,170;--color-special-400-rgb:112,85,223;--color-special-500-rgb:129,102,238;--color-special-600-rgb:138,111,245;--color-special-700-rgb:163,140,255;--color-special-800-rgb:196,182,255;--color-special-900-rgb:228,223,247;--color-special-950-rgb:239,236,250;--color-canvas:#0b0f18;--color-inverse:#fff;--color-surface:#353d57;--color-surface-light:#30394a;--color-surface-strong:#3d4667;--color-fore:#ebedf3;--color-focus:#173db6;--color-link:#59a5ff;--color-link-hover:#3883fa;--color-link-visited:#bcdcff;--color-link-active:#bcdcff;--color-placeholder:#4a577f;--color-border:#353d57;--color-border-strong:#3d4667;--color-border-light:#30394a;--color-canvas-rgb:11,15,24;--color-inverse-rgb:255,255,255;--color-surface-rgb:53,61,87;--color-surface-light-rgb:48,57,74;--color-surface-strong-rgb:61,70,103;--color-fore-rgb:235,237,243;--color-focus-rgb:23,61,182;--color-link-rgb:89,165,255;--color-link-hover-rgb:56,131,250;--color-link-visited-rgb:188,220,255;--color-link-active-rgb:188,220,255;--color-placeholder-rgb:74,87,127;--color-border-rgb:53,61,87;--color-border-strong-rgb:61,70,103;--color-border-light-rgb:48,57,74}.light-in-dark{--color-gray-50:#fcfdfe;--color-gray-100:#eff1f3;--color-gray-200:#ebedf3;--color-gray-300:#d2d6e5;--color-gray-400:#b2b9c5;--color-gray-500:#64758b;--color-gray-600:#4a577f;--color-gray-700:#3d4667;--color-gray-800:#353d57;--color-gray-900:#30394a;--color-gray-950:#0b0f18;--color-gray-50-rgb:252,253,254;--color-gray-100-rgb:239,241,243;--color-gray-200-rgb:235,237,243;--color-gray-300-rgb:210,214,229;--color-gray-400-rgb:178,185,197;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:74,87,127;--color-gray-700-rgb:61,70,103;--color-gray-800-rgb:53,61,87;--color-gray-900-rgb:48,57,74;--color-gray-950-rgb:11,15,24;--color-primary-50:#eef6ff;--color-primary-100:#d9eaff;--color-primary-200:#bcdcff;--color-primary-300:#8ec6ff;--color-primary-400:#59a5ff;--color-primary-500:#3883fa;--color-primary-600:#2b67e5;--color-primary-700:#144ce1;--color-primary-800:#173db6;--color-primary-900:#19388f;--color-primary-950:#142457;--color-primary-50-rgb:238,246,255;--color-primary-100-rgb:217,234,255;--color-primary-200-rgb:188,220,255;--color-primary-300-rgb:142,198,255;--color-primary-400-rgb:89,165,255;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:43,103,229;--color-primary-700-rgb:20,76,225;--color-primary-800-rgb:23,61,182;--color-primary-900-rgb:25,56,143;--color-primary-950-rgb:20,36,87;--color-secondary-50:#e7f6ff;--color-secondary-100:#cdecff;--color-secondary-200:#9bd9ff;--color-secondary-300:#77cbff;--color-secondary-400:#60c2ff;--color-secondary-500:#37b2fe;--color-secondary-600:#18a6fd;--color-secondary-700:#1099ed;--color-secondary-800:#078ada;--color-secondary-900:#046bab;--color-secondary-950:#062a4b;--color-secondary-50-rgb:231,246,255;--color-secondary-100-rgb:205,236,255;--color-secondary-200-rgb:155,217,255;--color-secondary-300-rgb:119,203,255;--color-secondary-400-rgb:96,194,255;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:24,166,253;--color-secondary-700-rgb:16,153,237;--color-secondary-800-rgb:7,138,218;--color-secondary-900-rgb:4,107,171;--color-secondary-950-rgb:6,42,75;--color-success-50:#effaf6;--color-success-100:#d6f2e7;--color-success-200:#ade5ce;--color-success-300:#83d7b6;--color-success-400:#5aca9d;--color-success-500:#31bd85;--color-success-600:#2ba675;--color-success-700:#28996c;--color-success-800:#21805a;--color-success-900:#185e3b;--color-success-950:#0e3421;--color-success-50-rgb:239,250,246;--color-success-100-rgb:214,242,231;--color-success-200-rgb:173,229,206;--color-success-300-rgb:131,215,182;--color-success-400-rgb:90,202,157;--color-success-500-rgb:49,189,133;--color-success-600-rgb:43,166,117;--color-success-700-rgb:40,153,108;--color-success-800-rgb:33,128,90;--color-success-900-rgb:24,94,59;--color-success-950-rgb:14,52,33;--color-warning-50:#fff4ea;--color-warning-100:#ffecdb;--color-warning-200:#ffd2a9;--color-warning-300:#ffbc7e;--color-warning-400:#ffaf65;--color-warning-500:#ff9f46;--color-warning-600:#f38f19;--color-warning-700:#ed8307;--color-warning-800:#d17100;--color-warning-900:#af5f01;--color-warning-950:#441506;--color-warning-50-rgb:255,244,234;--color-warning-100-rgb:255,236,219;--color-warning-200-rgb:255,210,169;--color-warning-300-rgb:255,188,126;--color-warning-400-rgb:255,175,101;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:243,143,25;--color-warning-700-rgb:237,131,7;--color-warning-800-rgb:209,113,0;--color-warning-900-rgb:175,95,1;--color-warning-950-rgb:68,21,6;--color-danger-50:#ffebeb;--color-danger-100:#ffd5d5;--color-danger-200:#ffb1b1;--color-danger-300:#ff9292;--color-danger-400:#ff7c7c;--color-danger-500:#fc5959;--color-danger-600:#fb2b2b;--color-danger-700:#d91b1b;--color-danger-800:#ba1313;--color-danger-900:#a20606;--color-danger-950:#470808;--color-danger-50-rgb:255,235,235;--color-danger-100-rgb:255,213,213;--color-danger-200-rgb:255,177,177;--color-danger-300-rgb:255,146,146;--color-danger-400-rgb:255,124,124;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:251,43,43;--color-danger-700-rgb:217,27,27;--color-danger-800-rgb:186,19,19;--color-danger-900-rgb:162,6,6;--color-danger-950-rgb:71,8,8;--color-important-50:#fff8f5;--color-important-100:#ffe2d9;--color-important-200:#ffcebf;--color-important-300:#ffb29b;--color-important-400:#ff8c68;--color-important-500:#ff8058;--color-important-600:#ff6f42;--color-important-700:#ff4912;--color-important-800:#c83509;--color-important-900:#611700;--color-important-950:#440609;--color-important-50-rgb:255,248,245;--color-important-100-rgb:255,226,217;--color-important-200-rgb:255,206,191;--color-important-300-rgb:255,178,155;--color-important-400-rgb:255,140,104;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,111,66;--color-important-700-rgb:255,73,18;--color-important-800-rgb:200,53,9;--color-important-900-rgb:97,23,0;--color-important-950-rgb:68,6,9;--color-special-50:#efecfa;--color-special-100:#e4dff7;--color-special-200:#c4b6ff;--color-special-300:#a38cff;--color-special-400:#8a6ff5;--color-special-500:#8166ee;--color-special-600:#7055df;--color-special-700:#513baa;--color-special-800:#452da5;--color-special-900:#30216e;--color-special-950:#271560;--color-special-50-rgb:239,236,250;--color-special-100-rgb:228,223,247;--color-special-200-rgb:196,182,255;--color-special-300-rgb:163,140,255;--color-special-400-rgb:138,111,245;--color-special-500-rgb:129,102,238;--color-special-600-rgb:112,85,223;--color-special-700-rgb:81,59,170;--color-special-800-rgb:69,45,165;--color-special-900-rgb:48,33,110;--color-special-950-rgb:39,21,96;--color-inherit:inherit;--color-transparent:transparent;--color-current:currentColor;--color-black:#000;--color-white:#fff;--color-canvas:#fff;--color-canvas-light:#fff;--color-canvas-dark:#fcfdfe;--color-inverse:#000;--color-surface:#eff1f3;--color-surface-light:#fcfdfe;--color-surface-strong:#ebedf3;--color-fore:#30394a;--color-fore-in-light:#30394a;--color-fore-in-dark:#fff;--color-focus:#bcdcff;--color-link:#2b47a2;--color-link-hover:#144ce1;--color-link-visited:#6328a4;--color-link-active:#144ce1;--color-placeholder:#64758b;--color-border:#ebedf3;--color-border-strong:#d2d6e5;--color-border-light:#eff1f3;--color-black-rgb:0,0,0;--color-white-rgb:255,255,255;--color-canvas-rgb:255,255,255;--color-canvas-light-rgb:255,255,255;--color-canvas-dark-rgb:252,253,254;--color-inverse-rgb:0,0,0;--color-surface-rgb:239,241,243;--color-surface-light-rgb:252,253,254;--color-surface-strong-rgb:235,237,243;--color-fore-rgb:48,57,74;--color-fore-in-light-rgb:48,57,74;--color-fore-in-dark-rgb:255,255,255;--color-focus-rgb:188,220,255;--color-link-rgb:43,71,162;--color-link-hover-rgb:20,76,225;--color-link-visited-rgb:99,40,164;--color-link-active-rgb:20,76,225;--color-placeholder-rgb:100,117,139;--color-border-rgb:235,237,243;--color-border-strong-rgb:210,214,229;--color-border-light-rgb:239,241,243}body{--btn-bg:var(--color-gray-50)}@media (prefers-color-scheme:dark){.dark-auto{--color-gray-50:#0b0f18;--color-gray-100:#30394a;--color-gray-200:#353d57;--color-gray-300:#3d4667;--color-gray-400:#4a577f;--color-gray-500:#64758b;--color-gray-600:#b2b9c5;--color-gray-700:#d2d6e5;--color-gray-800:#ebedf3;--color-gray-900:#eff1f3;--color-gray-950:#fcfdfe;--color-gray-50-rgb:11,15,24;--color-gray-100-rgb:48,57,74;--color-gray-200-rgb:53,61,87;--color-gray-300-rgb:61,70,103;--color-gray-400-rgb:74,87,127;--color-gray-500-rgb:100,117,139;--color-gray-600-rgb:178,185,197;--color-gray-700-rgb:210,214,229;--color-gray-800-rgb:235,237,243;--color-gray-900-rgb:239,241,243;--color-gray-950-rgb:252,253,254;--color-primary-50:#142457;--color-primary-100:#19388f;--color-primary-200:#173db6;--color-primary-300:#144ce1;--color-primary-400:#2b67e5;--color-primary-500:#3883fa;--color-primary-600:#59a5ff;--color-primary-700:#8ec6ff;--color-primary-800:#bcdcff;--color-primary-900:#d9eaff;--color-primary-950:#eef6ff;--color-primary-50-rgb:20,36,87;--color-primary-100-rgb:25,56,143;--color-primary-200-rgb:23,61,182;--color-primary-300-rgb:20,76,225;--color-primary-400-rgb:43,103,229;--color-primary-500-rgb:56,131,250;--color-primary-600-rgb:89,165,255;--color-primary-700-rgb:142,198,255;--color-primary-800-rgb:188,220,255;--color-primary-900-rgb:217,234,255;--color-primary-950-rgb:238,246,255;--color-secondary-50:#062a4b;--color-secondary-100:#046bab;--color-secondary-200:#078ada;--color-secondary-300:#1099ed;--color-secondary-400:#18a6fd;--color-secondary-500:#37b2fe;--color-secondary-600:#60c2ff;--color-secondary-700:#77cbff;--color-secondary-800:#9bd9ff;--color-secondary-900:#cdecff;--color-secondary-950:#e7f6ff;--color-secondary-50-rgb:6,42,75;--color-secondary-100-rgb:4,107,171;--color-secondary-200-rgb:7,138,218;--color-secondary-300-rgb:16,153,237;--color-secondary-400-rgb:24,166,253;--color-secondary-500-rgb:55,178,254;--color-secondary-600-rgb:96,194,255;--color-secondary-700-rgb:119,203,255;--color-secondary-800-rgb:155,217,255;--color-secondary-900-rgb:205,236,255;--color-secondary-950-rgb:231,246,255;--color-success-50:#0e3421;--color-success-100:#185e3b;--color-success-200:#21805a;--color-success-300:#28996c;--color-success-400:#2ba675;--color-success-500:#31bd85;--color-success-600:#5aca9d;--color-success-700:#83d7b6;--color-success-800:#ade5ce;--color-success-900:#d6f2e7;--color-success-950:#effaf6;--color-success-50-rgb:14,52,33;--color-success-100-rgb:24,94,59;--color-success-200-rgb:33,128,90;--color-success-300-rgb:40,153,108;--color-success-400-rgb:43,166,117;--color-success-500-rgb:49,189,133;--color-success-600-rgb:90,202,157;--color-success-700-rgb:131,215,182;--color-success-800-rgb:173,229,206;--color-success-900-rgb:214,242,231;--color-success-950-rgb:239,250,246;--color-warning-50:#441506;--color-warning-100:#af5f01;--color-warning-200:#d17100;--color-warning-300:#ed8307;--color-warning-400:#f38f19;--color-warning-500:#ff9f46;--color-warning-600:#ffaf65;--color-warning-700:#ffbc7e;--color-warning-800:#ffd2a9;--color-warning-900:#ffecdb;--color-warning-950:#fff4ea;--color-warning-50-rgb:68,21,6;--color-warning-100-rgb:175,95,1;--color-warning-200-rgb:209,113,0;--color-warning-300-rgb:237,131,7;--color-warning-400-rgb:243,143,25;--color-warning-500-rgb:255,159,70;--color-warning-600-rgb:255,175,101;--color-warning-700-rgb:255,188,126;--color-warning-800-rgb:255,210,169;--color-warning-900-rgb:255,236,219;--color-warning-950-rgb:255,244,234;--color-danger-50:#470808;--color-danger-100:#a20606;--color-danger-200:#ba1313;--color-danger-300:#d91b1b;--color-danger-400:#fb2b2b;--color-danger-500:#fc5959;--color-danger-600:#ff7c7c;--color-danger-700:#ff9292;--color-danger-800:#ffb1b1;--color-danger-900:#ffd5d5;--color-danger-950:#ffebeb;--color-danger-50-rgb:71,8,8;--color-danger-100-rgb:162,6,6;--color-danger-200-rgb:186,19,19;--color-danger-300-rgb:217,27,27;--color-danger-400-rgb:251,43,43;--color-danger-500-rgb:252,89,89;--color-danger-600-rgb:255,124,124;--color-danger-700-rgb:255,146,146;--color-danger-800-rgb:255,177,177;--color-danger-900-rgb:255,213,213;--color-danger-950-rgb:255,235,235;--color-important-50:#440609;--color-important-100:#611700;--color-important-200:#c83509;--color-important-300:#ff4912;--color-important-400:#ff6f42;--color-important-500:#ff8058;--color-important-600:#ff8c68;--color-important-700:#ffb29b;--color-important-800:#ffcebf;--color-important-900:#ffe2d9;--color-important-950:#fff8f5;--color-important-50-rgb:68,6,9;--color-important-100-rgb:97,23,0;--color-important-200-rgb:200,53,9;--color-important-300-rgb:255,73,18;--color-important-400-rgb:255,111,66;--color-important-500-rgb:255,128,88;--color-important-600-rgb:255,140,104;--color-important-700-rgb:255,178,155;--color-important-800-rgb:255,206,191;--color-important-900-rgb:255,226,217;--color-important-950-rgb:255,248,245;--color-special-50:#271560;--color-special-100:#30216e;--color-special-200:#452da5;--color-special-300:#513baa;--color-special-400:#7055df;--color-special-500:#8166ee;--color-special-600:#8a6ff5;--color-special-700:#a38cff;--color-special-800:#c4b6ff;--color-special-900:#e4dff7;--color-special-950:#efecfa;--color-special-50-rgb:39,21,96;--color-special-100-rgb:48,33,110;--color-special-200-rgb:69,45,165;--color-special-300-rgb:81,59,170;--color-special-400-rgb:112,85,223;--color-special-500-rgb:129,102,238;--color-special-600-rgb:138,111,245;--color-special-700-rgb:163,140,255;--color-special-800-rgb:196,182,255;--color-special-900-rgb:228,223,247;--color-special-950-rgb:239,236,250;--color-canvas:#0b0f18;--color-inverse:#fff;--color-surface:#353d57;--color-surface-light:#30394a;--color-surface-strong:#3d4667;--color-fore:#ebedf3;--color-focus:#173db6;--color-link:#59a5ff;--color-link-hover:#3883fa;--color-link-visited:#bcdcff;--color-link-active:#bcdcff;--color-placeholder:#4a577f;--color-border:#353d57;--color-border-strong:#3d4667;--color-border-light:#30394a;--color-canvas-rgb:11,15,24;--color-inverse-rgb:255,255,255;--color-surface-rgb:53,61,87;--color-surface-light-rgb:48,57,74;--color-surface-strong-rgb:61,70,103;--color-fore-rgb:235,237,243;--color-focus-rgb:23,61,182;--color-link-rgb:89,165,255;--color-link-hover-rgb:56,131,250;--color-link-visited-rgb:188,220,255;--color-link-active-rgb:188,220,255;--color-placeholder-rgb:74,87,127;--color-border-rgb:53,61,87;--color-border-strong-rgb:61,70,103;--color-border-light-rgb:48,57,74}}*,:after,:before{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity))}:focus-visible{outline-color:transparent}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }html{font-size:var(--font-size-root)}body{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));font-size:.8125rem;line-height:1.5384615385}.dark,body{--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))}:root{--font-h1-size:2.25rem;--article-p-space:0.5em;--article-heading-space:0.5em;--article-hr-space:1.5em;--article-cell-padding:0.25rem 0.75rem}a,a.disabled:hover{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity))}a:hover{--tw-text-opacity:1;color:rgba(var(--color-link-hover-rgb),var(--tw-text-opacity))}a:focus-visible{outline-color:rgb(var(--color-focus-rgb));outline-offset:2px;outline-width:2px}.code,code{background-color:rgba(var(--color-important-500-rgb),.1);border-radius:var(--radius);padding-left:.25rem;padding-right:.25rem;--tw-text-opacity:1;color:rgba(var(--color-important-500-rgb),var(--tw-text-opacity))}pre{font-size:.75rem;line-height:1rem;overflow:auto;padding:.5rem}pre code{background-color:transparent;color:inherit;padding:0}samp,var{font-weight:700}.blockquote,blockquote{border-left-width:4px;font-size:.875rem;line-height:1.3rem;padding-left:.75rem;text-wrap:pretty}.blockquote figcaption,blockquote figcaption{font-size:.75rem;line-height:1rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-weight:700;line-height:1.5;text-wrap:balance}.h1,h1{font-size:1.75rem}.h2,h2{font-size:1.5rem}.h3,h3{font-size:1.25rem}.h4,h4{font-size:1rem}.h5,h5{font-size:.875rem}.h6,h6{font-size:.75rem}ul{list-style-type:disc}ol,ul{padding-left:1.5em}ol{list-style-type:decimal}dt{font-weight:700}dd{padding-left:2em}.article{color:var(--font-size-article);-webkit-hyphens:auto;hyphens:auto;overflow-wrap:break-word;white-space:pre-wrap}.article h1,.article h2,.article h3,.article h4{margin-bottom:var(--article-heading-space);margin-top:var(--article-heading-space)}.article audio,.article blockquote,.article figure,.article img,.article ol,.article p,.article table,.article ul,.article video{margin-bottom:var(--article-p-space);margin-top:var(--article-p-space);text-wrap:pretty}.article p{min-height:1em}.article p:empty:before{content:" ";display:inline-block}.article hr{margin-bottom:var(--article-hr-space);margin-top:var(--article-hr-space)}.article table{border-width:1px}.article td,.article th{border-bottom-width:1px;padding:var(--article-cell-padding)}.article thead{background-color:var(--table-head-bg,var(--color-gray-100))}.article ol *,.article table *,.article ul *{margin-bottom:0;margin-top:0}.article pre{border-radius:var(--radius);border-width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity))}:root{--alert-bg:var(--color-surface)}.alert{align-items:center;background-color:var(--alert-bg);border-radius:var(--radius);display:flex;gap:.75rem;padding:.5rem .75rem}.alert-content{display:flex;flex:1 1 auto;flex-direction:column;gap:1rem}.alert-close{margin-bottom:-.375rem;margin-right:-.5rem;margin-top:-.375rem}.alert-link{color:inherit;font-weight:700}.alert-link:hover{color:inherit;text-decoration-line:underline}.alert-heading{font-weight:700;margin:0}.alert-text{flex:1 1 auto;white-space:pre-line}.alert-actions{align-items:center;display:flex;gap:.5rem}:root{--breadcrumb-divider:"/";--breadcrumb-divider-color:var(--color-gray-500);--breadcrumb-color-active:var(--color-gray-500)}.breadcrumb{display:flex;gap:1.25rem;list-style-type:none;padding-left:0}.breadcrumb>li{position:relative}.breadcrumb>li+li:before{color:var(--breadcrumb-divider-color);content:var(--breadcrumb-divider);display:block;left:-1.25rem;position:absolute;text-align:center;width:1.25rem}.breadcrumb>.active{color:var(--breadcrumb-color-active)}:root{--btn-radius:var(--radius);--btn-bg:var(--color-surface);--btn-border-color:var(--color-gray-300);--btn-height:2rem}.btn{align-items:center;background-color:var(--btn-bg);border-radius:var(--btn-radius);display:inline-flex;gap:.375rem;height:var(--btn-height);justify-content:center;padding-left:.75rem;padding-right:.75rem;white-space:nowrap;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--btn-border-color)}.btn,.btn-default:hover{color:inherit}.btn-link{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity));text-decoration-line:underline;text-underline-offset:2px;--tw-ring-color:transparent}.btn-link:visited{color:rgba(var(--color-link-visited-rgb),var(--tw-text-opacity))}.btn-link:hover{--tw-text-opacity:1;color:rgba(var(--color-link-hover-rgb),var(--tw-text-opacity))}.btn-link{--btn-bg:transparent}.btn.size-xs,.size-xs>.btn{padding-left:.25rem;padding-right:.25rem;--btn-height:1.25rem}.btn.size-sm,.btn.size-xs,.size-sm>.btn,.size-xs>.btn{font-size:.75rem;line-height:1rem}.btn.size-sm,.size-sm>.btn{--btn-height:1.5rem}.btn.size-md,.btn.size-sm,.size-md>.btn,.size-sm>.btn{padding-left:.5rem;padding-right:.5rem}.btn.size-md,.size-md>.btn{--btn-height:1.75rem}.btn.size-lg,.size-lg>.btn{font-size:1rem;line-height:1.5rem;padding-left:1rem;padding-right:1rem;--btn-height:2.5rem}.btn.size-xl,.size-xl>.btn{font-size:1.125rem;line-height:1.75rem;padding-left:1.25rem;padding-right:1.25rem;--btn-height:3rem}.btn.square{aspect-ratio:1/1;gap:.125rem;padding-left:0;padding-right:0}@supports not (aspect-ratio:1/1){.btn.square{width:var(--btn-height)}}.btn.btn-caret{padding-left:.25rem;padding-right:.25rem}.btn.btn-wide{min-width:80px}:root{--checkbox-size:12px;--checkbox-color:var(--color-primary-500)}.checkbox,.radio{align-items:center;cursor:pointer;display:flex;gap:.375rem;min-height:20px}.checkbox>input[type=checkbox],.radio>input[type=radio]{accent-color:rgb(var(--color-primary-500-rgb));border-radius:var(--radius-lg)}.checkbox-primary,.radio-primary{display:flex;gap:.375rem;min-height:20px;position:relative}.checkbox-primary>input[type=checkbox],.radio-primary>input[type=radio]{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.checkbox-primary>label,.radio-primary>label{cursor:pointer;padding-left:calc(var(--checkbox-size) + 8px);position:relative}.checkbox-primary>label:after,.checkbox-primary>label:before,.radio-primary>label:after,.radio-primary>label:before{display:block;height:var(--checkbox-size);left:0;position:absolute;transition-duration:.15s;transition-property:transform,background-color,color,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--checkbox-size);--tw-content:"";content:var(--tw-content);top:calc((20px - var(--checkbox-size))/2)}.checkbox-primary>label:before{border-radius:var(--radius-sm);border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.checkbox-primary>label:after{--tw-scale-x:.9;--tw-scale-y:.9;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0ibTkgMjAuNDItNi4yMS02LjIxIDIuODMtMi44M0w5IDE0Ljc3bDkuODgtOS44OSAyLjgzIDIuODN6Ii8+PC9zdmc+");transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.radio-primary>label:before{border-radius:var(--radius-full);border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity))}.radio-primary>label:after{background-color:var(--checkbox-color);border-radius:var(--radius-full);opacity:0;--checkbox-radio-size:calc(var(--checkbox-size)*2/3);height:var(--checkbox-radio-size);left:calc((var(--checkbox-size) - var(--checkbox-radio-size))/2);top:calc((20px - var(--checkbox-radio-size))/2);width:var(--checkbox-radio-size)}.checkbox-primary>label:hover:before,.radio-primary>label:hover:before{border-color:var(--checkbox-color)}.checkbox-primary.focus>label:before,.checkbox-primary>input[type=checkbox]:focus+label:before,.radio-primary.focus>label:before,.radio-primary>input[type=radio]:focus+label:before{border-color:var(--checkbox-color);outline-color:rgb(var(--color-focus-rgb));outline-style:solid;outline-width:2px}.checkbox-primary.checked>label:before,.checkbox-primary>input[type=checkbox]:checked+label:before{background-color:var(--checkbox-color);border-color:var(--checkbox-color)}.radio-primary.checked>label:before,.radio-primary>input[type=radio]:checked+label:before{border-color:var(--checkbox-color)}.checkbox-primary.checked>label:after,.checkbox-primary>input[type=checkbox]:checked+label:after,.radio-primary.checked>label:after,.radio-primary>input[type=radio]:checked+label:after{opacity:1}.checkbox-primary.disabled>label,.checkbox-primary>input[type=checkbox]:disabled+label,.radio-primary.disabled>label,.radio-primary>input[type=radio]:disabled+label{cursor:not-allowed;opacity:.7;pointer-events:none;--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.checkbox-primary.indeterminate>label:after,.checkbox-primary>input[type=checkbox]:indeterminate+label:after{--tw-border-opacity:1;background-color:var(--checkbox-color);background-image:none;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity));border-width:calc((var(--checkbox-size) - 2px)/2) 2px;opacity:1}.check-list{align-items:flex-start;flex-direction:column;gap:.5rem}.check-list,.check-list-inline{display:flex;padding-bottom:.375rem;padding-top:.375rem}.check-list-inline{align-items:center;-moz-column-gap:1rem;column-gap:1rem;flex-direction:row;flex-wrap:wrap;row-gap:.5rem}.switch{display:flex;gap:.375rem;min-height:20px;padding-left:2.5rem;position:relative}.switch>input{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.switch>label:after,.switch>label:before{border-radius:var(--radius-full);border-width:1px;height:1rem;left:0;position:absolute;top:.125rem;width:2rem;--tw-border-opacity:1;border-color:rgba(var(--color-border-strong-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));transition-duration:.3s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);--tw-content:"";content:var(--tw-content)}.switch>label:before{cursor:pointer;--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.switch>label:hover:before{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity))}.switch>label:after{height:.75rem;left:.125rem;top:.25rem;width:.75rem;--tw-border-opacity:1;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.switch>input:checked+label:before{background-color:var(--checkbox-color);border-color:rgba(var(--color-inverse-rgb),.2)}.switch>input:checked+label:after{color:var(--checkbox-color);left:18px}.switch.focus>label:before,.switch>input:focus+label:before{border-color:var(--checkbox-color);outline-color:rgb(var(--color-focus-rgb));outline-style:solid;outline-width:2px}.switch.disabled>label:before,.switch>input:disabled+label:before{cursor:not-allowed;opacity:.7;pointer-events:none;--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}:root{--form-control-radius:var(--radius);--form-control-border:var(--color-border);--form-control-focus:var(--color-primary-500);--form-control-disabled:var(--color-surface);--form-control-readonly:var(--color-surface)}.dark{--form-control-border:var(--color-border-strong)}input::-moz-placeholder,textarea::-moz-placeholder{--tw-placeholder-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-placeholder-opacity))}input::placeholder,textarea::placeholder{--tw-placeholder-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-placeholder-opacity))}.form-control{border-radius:var(--form-control-radius);display:block;height:2rem;width:100%;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));outline-color:transparent;outline-style:solid;outline-width:1px;padding:.25rem .5rem;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--form-control-border);transition-duration:.15s;transition-property:outline,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.form-control.focus,.form-control:focus{outline-color:var(--form-control-focus);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-focus-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.3}.form-control.disabled,.form-control[disabled]{background-color:var(--form-control-disabled);opacity:1}.form-control.readonly,.form-control[readonly]{background-color:var(--form-control-readonly)}select{-webkit-appearance:none;background-image:url("data:image/gif;base64,R0lGODlhBwAEAIAAAMvQ2////yH5BAEAAAEALAAAAAAHAAQAAAIIhA+BGWoNWSgAOw==");background-position:right 8px top 50%;background-repeat:no-repeat;background-size:8px auto;padding-right:1rem}select.form-control[multiple]{background-image:none}textarea.form-control{height:auto;min-height:32px}input[type=file].form-control{padding:.125rem}input[type=file].form-control::-webkit-file-upload-button{-webkit-appearance:none;appearance:none;border-radius:inherit;border-style:none;cursor:pointer;height:1.75rem;padding-left:.5rem;padding-right:.5rem}input[type=file].form-control::-webkit-file-upload-button:hover{background-color:rgba(var(--color-black-rgb),.1)}.has-error .form-control,.has-error.form-control{--tw-ring-color:rgba(var(--color-danger-500-rgb),0.6)}.has-error .form-control.focus,.has-error .form-control:focus,.has-error.form-control.focus,.has-error.form-control:focus{outline-color:rgb(var(--color-danger-500-rgb));--tw-ring-color:rgba(var(--color-danger-500-rgb),0.1)}.has-warning .form-control,.has-warning.form-control{--tw-ring-color:rgba(var(--color-warning-500-rgb),0.6)}.has-warning .form-control.focus,.has-warning .form-control:focus,.has-warning.form-control.focus,.has-warning.form-control:focus{outline-color:rgb(var(--color-warning-500-rgb));--tw-ring-color:rgba(var(--color-warning-500-rgb),0.2)}.has-success .form-control,.has-success.form-control{--tw-ring-color:rgba(var(--color-success-500-rgb),0.6)}.has-success .form-control.focus,.has-success .form-control:focus,.has-success.form-control.focus,.has-success.form-control:focus{outline-color:rgb(var(--color-success-500-rgb));--tw-ring-color:rgba(var(--color-success-500-rgb),0.2)}.form-control.size-sm,.size-sm>.form-control{font-size:.75rem;height:1.5rem;line-height:1rem;padding-left:.5rem;padding-right:.5rem}.form-control.size-md,.size-md>.form-control{height:1.75rem;padding-left:.5rem;padding-right:.5rem}.form-control.size-lg,.size-lg>.form-control{font-size:1rem;height:2.5rem;line-height:1.5rem;padding-left:.75rem;padding-right:.75rem}:root{--input-group-addon-bg:var(--color-gray-50)}.input-group{align-items:stretch;display:flex}.input-group>.form-control,.input-group>.input-control{flex:1 1 auto;z-index:1}.input-group-addon{align-items:center;background-color:var(--input-group-addon-bg);border-radius:var(--form-control-radius);display:flex;flex:none;height:2rem;padding-left:.5rem;padding-right:.5rem;z-index:0;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--form-control-border)}.size-sm>.input-group-addon{font-size:.75rem;height:1.5rem;line-height:1rem;padding-left:.5rem;padding-right:.5rem}.size-lg>.input-group-addon{font-size:1rem;height:2.5rem;line-height:1.5rem;padding-left:.75rem;padding-right:.75rem}.input-group-control{flex:1 1 auto}.input-group>*+*,.input-group>*+* .form-control{border-bottom-left-radius:var(--radius-none);border-top-left-radius:var(--radius-none)}.input-group>:not(:last-child),.input-group>:not(:last-child) .form-control{border-bottom-right-radius:var(--radius-none);border-top-right-radius:var(--radius-none)}.input-group .btn:focus-visible,.input-group .form-control:focus{z-index:2}:root{--form-tip-color:var(--color-gray-400);--form-label-color:var(--color-gray-700);--form-horz-label-width:6rem;--form-grid-gap-x:1.25rem;--form-grid-gap-y:.75rem}.form{flex-direction:column;gap:1rem}.form,.form-label{display:flex}.form-label{align-items:center;color:var(--form-label-color);flex-direction:row;gap:.25rem;height:2rem;overflow:hidden;position:relative;text-overflow:ellipsis;white-space:nowrap}.form-label.required:after{content:"*";display:inline-block;margin-left:.25rem;--tw-translate-y:0.125rem;--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-text-opacity:1;color:rgba(var(--color-danger-500-rgb),var(--tw-text-opacity))}.no-required .form-label.required:after{display:none}.form-label-actions{flex:1 1 auto;justify-content:flex-end}.form-label>.checkbox-primary{margin-left:.75rem}.form-tip{color:var(--form-tip-color);display:block;margin-top:.25rem}.has-error .form-tip{--tw-text-opacity:1;color:rgba(var(--color-danger-500-rgb),var(--tw-text-opacity))}.has-warning .form-tip{--tw-text-opacity:1;color:rgba(var(--color-warning-500-rgb),var(--tw-text-opacity))}.has-success .form-tip{--tw-text-opacity:1;color:rgba(var(--color-success-500-rgb),var(--tw-text-opacity))}.form-actions{display:flex;flex-direction:row;gap:1rem;justify-content:center}.form-grid{--form-grid-gap-x-half:calc(var(--form-grid-gap-x)/2);--form-grid-gap-y-half:calc(var(--form-grid-gap-y)/2);align-items:flex-start;flex-direction:row;flex-wrap:wrap;gap:0}.form-grid .form-group{padding:var(--form-grid-gap-y-half) var(--form-grid-gap-x-half)}.form-grid .form-label.required:after{margin-left:.25rem;order:-9999}.form-grid .form-label .checkbox{margin-left:.75rem;margin-right:.75rem}.form-grid .has-wrap-after:after{display:block;width:100%;--tw-content:"";content:var(--tw-content)}.form-grid-wrap{width:100%}.form-grid-row{display:flex;flex-direction:row;padding-bottom:var(--form-grid-gap-y-half);padding-top:var(--form-grid-gap-y-half);position:relative;width:100%}.form-grid-col{padding-left:var(--form-grid-gap-x-half);padding-right:var(--form-grid-gap-x-half)}.form-grid .form-actions{gap:1.5rem;justify-content:center;padding:var(--form-grid-gap-y) var(--form-grid-gap-x-half);width:100%}.form-grid .form-actions.is-pinned{border-top-width:1px}.form-horz .form-row{align-items:flex-start;display:flex;flex-direction:row}.form-horz .form-group{align-items:flex-start;display:flex;flex:none;flex-direction:row;flex-wrap:wrap;min-height:32px;min-width:0;padding-left:var(--form-horz-label-width);position:relative}.form-horz .form-row .form-group{flex:1 1 auto}.form-horz .form-group[class*=" w-"],.form-horz .form-group[class^=w-]{flex:none}.form-horz .form-group>*{min-width:0}.form-horz .form-group.no-label{padding-left:0}.form-horz .form-group.no-label>.check-list-inline{padding-left:1rem;padding-right:1rem}.form-horz .form-label{justify-content:flex-end;left:0;padding-left:1rem;padding-right:.5rem;position:absolute;top:0;width:var(--form-horz-label-width)}.form-horz .form-label.required:after{margin-left:0;order:-9999}.form-horz .form-tip{width:100%}.form-horz .form-tip,.form-horz .input-control,.form-horz .input-group{flex:1 1 auto}.form .form-group-wrapper,.form-horz .form-group-wrapper{flex:1 1 auto;min-width:0;width:100%;z-index:1}.form .form-group-wrapper.flex-none,.form-horz .form-group-wrapper.flex-none{flex:none}.form fieldset>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.form fieldset{padding-bottom:1rem;padding-left:1rem}.form-grid fieldset>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.form legend{border-bottom-width:1px;display:flex;justify-content:flex-start;margin-left:-1rem;width:100%;--tw-border-opacity:1;border-bottom-color:rgba(var(--color-primary-100-rgb),var(--tw-border-opacity));width:calc(100% + 1rem)}.form-title{align-items:center;background-color:rgba(var(--color-primary-50-rgb),.5);display:flex;font-weight:700;height:1.75rem;padding-left:.75rem;padding-right:.75rem}:root{--input-control-fix-width-sm:2rem;--input-control-fix-width:4.375rem;--input-control-fix-width-lg:6.75rem}.input-control{position:relative;--input-control-prefix:8px;--input-control-suffix:8px}.input-control-prefix,.input-control-suffix{align-items:center;display:flex;height:100%;left:0;opacity:.5;padding-left:.5rem;padding-right:.5rem;position:absolute;top:0;white-space:nowrap;width:var(--input-control-prefix);z-index:1}.input-control-suffix{justify-content:flex-end;left:auto;right:0;width:var(--input-control-suffix)}.form-control:focus+.input-control-prefix,.form-control:focus+.input-control-suffix{opacity:1}.input-control>.form-control{padding-left:var(--input-control-prefix);padding-right:var(--input-control-suffix)}.input-control>select.form-control{background-position-x:calc(100% - var(--input-control-suffix) - 8px);padding-right:calc(var(--input-control-suffix) + 20px)}.has-prefix{--input-control-prefix:var(--input-control-fix-width)}.has-suffix{--input-control-suffix:var(--input-control-fix-width)}.has-prefix-sm{--input-control-prefix:var(--input-control-fix-width-sm)}.has-suffix-sm{--input-control-suffix:var(--input-control-fix-width-sm)}.has-prefix-lg{--input-control-prefix:var(--input-control-fix-width-lg)}.has-suffix-lg{--input-control-suffix:var(--input-control-fix-width-lg)}.has-prefix-icon{--input-control-prefix:32px}.has-suffix-icon{--input-control-suffix:32px}.input-control.has-prefix-icon{--input-control-prefix:32px}.input-control.has-suffix-icon{--input-control-suffix:32px}.input-control.has-prefix-icon>.input-control-prefix,.input-control.has-suffix-icon>.input-control-suffix{justify-content:center;padding:0}.input-control.size-sm>.form-control,.input-control.size-sm>.input-control-prefix,.input-control.size-sm>.input-control-suffix{font-size:.75rem;line-height:1rem}.input-control.size-lg>.form-control,.input-control.size-lg>.input-control-prefix,.input-control.size-lg>.input-control-suffix{font-size:1rem;line-height:1.5rem}:root{--label-bg:rgba(var(--color-canvas-rgb),.1);--label-border-color:var(--color-gray-300);--label-color:var(--color-gray-500);--label-radius:var(--radius)}.label{align-items:center;background-color:var(--label-bg);border-radius:var(--label-radius);color:var(--label-color);display:inline-flex;font-size:.75rem;height:1.25rem;justify-content:center;line-height:1rem;min-width:1.25rem;padding-left:.25rem;padding-right:.25rem;white-space:pre-line;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--label-border-color)}.label.size-lg{font-size:.8125rem;height:1.5rem;line-height:1.25rem;min-width:1.5rem;padding-left:.5rem;padding-right:.5rem}.label.size-sm{height:1rem;min-width:1rem}.label-dot{aspect-ratio:1/1;border-radius:var(--radius-full);height:.5rem;min-width:0;padding-left:0;padding-right:0}.caret,.caret-down,.caret-left,.caret-right,.caret-up{align-items:center;display:inline-flex;height:.75rem;justify-content:center;position:relative;width:.75rem}.caret-down:before,.caret-left:before,.caret-right:before,.caret-up:before,.caret:before{display:block;height:.35rem;transform-origin:center;width:.35rem;--tw-translate-y:-1px;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.caret-left:before{--tw-translate-x:0.125rem;--tw-translate-y:0px;--tw-rotate:135deg}.caret-left:before,.caret-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.caret-right:before{--tw-translate-x:-0.125rem;--tw-translate-y:0px;--tw-rotate:-45deg}.caret-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:focus>.caret,:hover>.caret{opacity:inherit}.disabled .caret,.readonly .caret{opacity:var(--caret-opacity,.5)}.listitem{align-items:center;border-radius:var(--radius);display:flex;flex-direction:row;flex-wrap:nowrap;gap:.5rem;padding:.25rem}.listitem.selected{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.listitem.active{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.item-actions,.item-avatar,.item-icon,.item-trailing,.item-trailing-icon{flex:none}.item-icon.icon-EMPTY{display:none}.item-subtitle{font-size:.75rem;line-height:1rem;opacity:.8}.item-content,.item-text{flex:1 1 auto;min-width:0}.item-leading,.item-trailing{align-items:center;display:flex;flex:none;gap:.5rem}.item-checkbox{margin-right:-.5rem}.item-content{align-items:center;display:flex;gap:.5rem}.multiline>.item-content{align-items:flex-start;flex-direction:column;gap:.25rem}.list{list-style-type:none;padding-left:0}.list-heading-inner .item-title{font-weight:700;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.with-hover-actions>.item{position:relative}.with-hover-actions>.item>.item-inner .item-actions{opacity:0;pointer-events:none;position:absolute;right:.25rem;top:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.with-hover-actions>.item>.item-inner:hover .item-actions{display:flex;margin-top:-.25rem;opacity:1;pointer-events:auto;position:static}.list.is-nested-sub{padding-left:var(--list-indent)}.is-nested-collapsed{display:none}.nested-toggle-icon{align-items:center;border-radius:var(--radius);display:flex;height:1rem;justify-content:center;margin-right:-.25rem;width:1rem}.magnifier{display:inline-block;height:1em;position:relative;width:1em}.magnifier:after,.magnifier:before{border-radius:var(--radius-full);content:"";display:block;position:absolute}.magnifier:before{border:1px solid;height:.75em;width:.75em}.magnifier:after{height:1px;left:.55em;top:.7em;width:.5em;--tw-rotate:45deg;background-color:currentColor;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.search-box.compact.has-prefix-icon{--input-control-prefix:24px}.search-box.compact.has-suffix-icon{--input-control-suffix:24px}:root{--menu-bg:var(--color-canvas);--menu-active-bg:var(--color-primary-500);--menu-active-color:var(--color-canvas);--menu-selected-bg:var(--color-primary-50);--menu-selected-color:var(--color-primary-500);--menu-icon-opacity:.5;--menu-icon-margin:1.75rem;--menu-min-width:3rem;--menu-heading-color:var(--color-gray-500)}.menu{background:var(--menu-bg);max-width:var(--menu-max-width);min-width:var(--menu-min-width);padding:.5rem}.menu-wrapper{display:flex;flex-direction:column;min-height:0}.menu-wrapper>.menu{flex:1 1 auto;min-height:0;overflow:auto}.menu-item>.item-inner,.menu-item>a{align-items:center;border-radius:var(--radius);color:inherit;cursor:pointer;display:flex;gap:.5rem;justify-content:space-between;overflow:hidden;padding:.25rem .5rem;position:relative;text-overflow:ellipsis;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);white-space:nowrap}.menu-item>.selected{background:var(--menu-selected-bg);color:var(--menu-selected-color)}.menu-item>.active,.menu-item>a.hover,.menu-item>a:hover{background:var(--menu-active-bg);color:var(--menu-active-color)}.menu-item>a.no-hover.hover,.menu-item>a.no-hover:hover{background:unset;color:unset}.menu-item.disabled>a:hover,.menu-item>a.disabled:hover{background-color:inherit;color:inherit}.menu-item .item-title{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:clip;white-space:nowrap}.menu>.divider{margin:.25rem}.menu-heading{align-items:center;color:var(--menu-heading-color);display:flex;font-size:.75rem;font-weight:700;height:2rem;line-height:1rem;padding-left:.25rem;padding-right:.25rem}.has-icons>.menu-item>a>.item-icon{align-items:center;display:flex;height:1rem;justify-content:center;opacity:var(--menu-icon-opacity);width:1rem}.menu-nested{--menu-indent:10px}.menu-nested .menu{background-color:transparent;margin-bottom:-.5rem;margin-left:var(--menu-indent);margin-top:-.5rem;padding-right:0}.menu-nested .menu-item>.item-inner{padding-left:0}.menu-nested .search-menu-footer,.menu-nested .search-menu-header{margin-bottom:.25rem;margin-left:var(--menu-indent);margin-top:-.125rem;padding-right:1px}.menu.compact .menu-item>a{padding-bottom:.125rem;padding-top:.125rem}.menu.compact .menu-heading{height:1.75rem}.search-menu-header{padding:.5rem .5rem .125rem}.search-menu-footer{padding:.125rem .5rem .5rem}.search-menu .item.is-not-match,.search-menu-footer:empty,.search-menu-header:empty{display:none}.search-menu .item.is-not-match.has-match-child{display:list-item}.search-menu .item.is-not-match.has-match-child>.item-inner{opacity:.5;pointer-events:none}.search-menu.no-toggle-on-search .nested-toggle-icon{pointer-events:none}.search-menu .is-match-keys{font-weight:700;text-decoration-line:underline}.search-menu-no-match-hint{display:none;font-size:.75rem;line-height:1rem;padding:.5rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.no-match-child .search-menu-no-match-hint{display:block}.no-match-child>.menu{display:none}.search-menu-exceed-limit-hint{font-size:.75rem;line-height:1rem;padding:.25rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}:root{--alert-bg:var(--color-surface)}.alert{align-items:center;background-color:var(--alert-bg);border-radius:var(--radius);display:flex;gap:.75rem;padding:.5rem .75rem}.alert-content{display:flex;flex:1 1 auto;flex-direction:column;gap:1rem}.alert-close{margin-bottom:-.375rem;margin-right:-.5rem;margin-top:-.375rem}.alert-link{color:inherit;font-weight:700}.alert-link:hover{color:inherit;text-decoration-line:underline}.alert-heading{font-weight:700;margin:0}.alert-text{flex:1 1 auto;white-space:pre-line}.alert-actions{align-items:center;display:flex;gap:.5rem}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.messagers{align-items:flex-end;bottom:0;display:flex;flex-direction:column;gap:.5rem;justify-content:flex-end;left:0;padding:1rem;pointer-events:none;position:fixed;right:0;top:0;z-index:1900}.messagers-top-left,.messagers-top-right{justify-content:flex-start}.messagers-bottom-left,.messagers-top-left{align-items:flex-start}.messagers-bottom,.messagers-center,.messagers-top{align-items:center}.messagers-top,.messagers-top-left,.messagers-top-right{justify-content:flex-start}.messagers-center{justify-content:center}.messager{background-color:rgba(var(--color-inverse-rgb),.8);pointer-events:auto;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);transition-duration:.3s}:root{--progress-radius:var(--radius);--progress-striped-size:40px;--progress-bg:var(--color-surface);--progress-bar-color:var(--color-primary-500)}.progress{background:var(--progress-bg);border-radius:var(--progress-radius);display:flex;height:1.25rem}.progress-bar{background:var(--progress-bar-color);height:100%;transition-duration:.5s;transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1)}.progress-striped>.progress-bar{background-image:linear-gradient(45deg,rgba(var(--color-canvas-rgb),.15) 25%,transparent 25%,transparent 50%,rgba(var(--color-canvas-rgb),.15) 50%,rgba(var(--color-canvas-rgb),.15) 75%,transparent 75%,transparent);background-size:var(--progress-striped-size) var(--progress-striped-size)}.progress>.progress-bar:first-child{border-bottom-left-radius:inherit;border-top-left-radius:inherit}.progress>.progress-bar:last-child{border-bottom-right-radius:inherit;border-top-right-radius:inherit}.progress.active .progress-bar{animation:progress-bar-stripes 2s linear infinite}@keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}.scrollbar,:root{--scrollbar-size:10px;--scrollbar-opacity:.6;--scrollbar-bg:rgba(var(--color-inverse-rgb),.15);--scrollbar-inset:inset 0 0 0 1px rgba(var(--color-inverse-rgb),.05);--scrollbar-bar-bg:rgba(var(--color-inverse-rgb),.3);--scrollbar-hover-bg:rgba(var(--color-inverse-rgb),.4);--scrollbar-drag-bg:rgba(var(--color-inverse-rgb),.5);--scrollbar-radius:var(--radius-sm);--scrollbar-duration:.7s}::-webkit-scrollbar{height:var(--scrollbar-size);width:var(--scrollbar-size)}::-webkit-scrollbar-track{background:var(--scrollbar-bg);box-shadow:var(--scrollbar-shadow);-webkit-transition:background-color var(--scrollbar-duration);transition:background-color var(--scrollbar-duration)}::-webkit-scrollbar-track:hover,:hover::-webkit-scrollbar-track{background:var(--scrollbar-hover-bg)}::-webkit-scrollbar-thumb{background:var(--scrollbar-bar-bg);border-radius:var(--scrollbar-radius);min-height:var(--scrollbar-size);-webkit-transition:var(--scrollbar-duration);transition:var(--scrollbar-duration);-webkit-transition-property:background-color;transition-property:background-color}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-hover-bg)}::-webkit-scrollbar-thumb:active{background:var(--scrollbar-drag-bg)}@-moz-document url-prefix(){.scrollbar-thin{scrollbar-width:thin}}.scrollbar-thin::-webkit-scrollbar{height:calc(var(--scrollbar-size)/2);width:calc(var(--scrollbar-size)/2)}.scrollbar-hover::-webkit-scrollbar,.scrollbar-hover::-webkit-scrollbar-thumb,.scrollbar-hover::-webkit-scrollbar-track{visibility:hidden}.scrollbar-hover:hover::-webkit-scrollbar,.scrollbar-hover:hover::-webkit-scrollbar-thumb,.scrollbar-hover:hover::-webkit-scrollbar-track{visibility:visible}@font-face{font-family:ZentaoIcon;font-style:normal;font-weight:400;src:url(./icons/ZentaoIcon.eot?v=1.71);src:url(./icons/ZentaoIcon.woff?v=1.71) format("woff"),url(./icons/ZentaoIcon.ttf?v=1.71) format("truetype"),url(./icons/ZentaoIcon.svg?v=1.71#regular) format("svg")}.icon,[class*=" icon-"],[class^=icon-]{display:inline-block;font-display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon:before{display:inline-block;min-width:14px;text-align:center}.icon-xs:before{font-size:.7em}.icon-sm:before{font-size:.8em}.icon-lg:before{font-size:1.25em;vertical-align:-10%}.icon-2x{font-size:28px}.icon-3x{font-size:42px}.icon-4x{font-size:56px}.icon-5x{font-size:70px}.icon-run{position:relative}.icon-run:before{opacity:.5}.icon-run:after{bottom:0;content:"\ea07";display:block;left:0;position:absolute;right:0;text-align:center;top:0}.icon-docspace:before{content:"\ea1b"}.icon-doclib:before{content:"\ea1c"}.icon-guihua:before{content:"\ea02"}.icon-memory:before{content:"\e9fd"}.icon-cpu:before{content:"\e9fe"}.icon-pause-pure:before{content:"\e9ff"}.icon-exclamation-pure:before{content:"\ea00"}.icon-zentao:before{content:"\e901"}.icon-zentao-alt:before{content:"\e900"}.icon-safe:before{content:"\ea06"}.icon-ai:before{content:"\e983"}.icon-kanban:before{content:"\e997"}.icon-college:before{content:"\e9c8"}.icon-home:before,.icon-menu-my:before{content:"\e97a"}.icon-program:before{content:"\e9aa"}.icon-lightbulb-alt:before,.icon-product:before{content:"\e98f"}.icon-project:before,.icon-rocket:before{content:"\e99c"}.icon-run:before{content:"\e9a9"}.icon-run-alt:before{content:"\ea07"}.icon-test:before{content:"\e956"}.icon-devops:before,.icon-infinite:before{content:"\e9a3"}.icon-doc:before,.icon-menu-doc:before{content:"\e99b"}.icon-statistic:before{content:"\e999"}.icon-group:before,.icon-menu-users:before,.icon-persons:before,.icon-team:before{content:"\e97e"}.icon-assets:before,.icon-diamond:before{content:"\e9ae"}.icon-flow:before{content:"\e994"}.icon-backend:before,.icon-cog-outline:before{content:"\ea05"}.icon-help:before{content:"\e968"}.icon-download:before,.icon-import:before{content:"\e904"}.icon-export:before{content:"\e905"}.icon-lightbulb:before{content:"\e91c"}.icon-close:before{content:"\e936"}.icon-check:before{content:"\e5ca"}.icon-minus:before{content:"\e926"}.icon-expand-alt:before{content:"\e6f1"}.icon-collapse-alt:before{content:"\e6f2"}.icon-fullscreen:before{content:"\e96b"}.icon-star-empty:before{content:"\e94a"}.icon-star:before{content:"\e94b"}.icon-exclamation-sign:before{content:"\e930"}.icon-info-sign:before{content:"\e9d5"}.icon-flag:before{content:"\e937"}.icon-check-circle:before{content:"\e92f"}.icon-check-sign:before{content:"\e938"}.icon-chart-pie:before{content:"\e95b"}.icon-history:before{content:"\e95f"}.icon-pencil:before{content:"\e254"}.icon-search:before{content:"\e928"}.icon-restart:before{content:"\e95e"}.icon-cog:before{content:"\e93b"}.icon-chart-line:before{content:"\e95c"}.icon-bar-chart:before,.icon-chart-bar:before{content:"\e95d"}.icon-exchange:before{content:"\e927"}.icon-severity:before{content:"\e973"}.icon-book:before{content:"\f02d"}.icon-treemap-alt:before{content:"\e971"}.icon-severity-solid:before{content:"\e902"}.icon-chat-line:before{content:"\e998"}.icon-stack:before{content:"\e943"}.icon-cube:before{content:"\e967"}.icon-minus-sign:before{content:"\e939"}.icon-bars-sign:before{content:"\e93a"}.icon-chat:before,.icon-message:before{content:"\e940"}.icon-more:before{content:"\e744"}.icon-certificate:before{content:"\f0a3"}.icon-bell:before{content:"\e7f5"}.icon-columns:before{content:"\f0db"}.icon-envelope-o:before{content:"\e92a"}.icon-unfold-all:before{content:"\e931"}.icon-fold-all:before{content:"\e932"}.icon-bars:before{content:"\e948"}.icon-cards-view:before{content:"\e949"}.icon-ellipsis-v:before{content:"\e5d4"}.icon-spinner-indicator:before{content:"\e982"}.icon-up-circle:before{content:"\e92b"}.icon-right-circle:before{content:"\e92c"}.icon-down-circle:before{content:"\e92d"}.icon-left-circle:before{content:"\e92e"}.icon-angle-double-right:before{content:"\f101"}.icon-angle-down:before{content:"\e313"}.icon-angle-left:before{content:"\e314"}.icon-angle-right:before{content:"\e315"}.icon-angle-top:before{content:"\e316"}.icon-first-page:before{content:"\e5dc"}.icon-last-page:before{content:"\e5dd"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-arrow-up:before{content:"\e923"}.icon-arrow-down:before{content:"\e924"}.icon-arrow-left:before{content:"\e952"}.icon-arrow-right:before{content:"\e93e"}.icon-chevron-left:before{content:"\e934"}.icon-chevron-right:before{content:"\e935"}.icon-chevron-double-up:before{content:"\e959"}.icon-chevron-double-down:before{content:"\e95a"}.icon-folder-account:before{content:"\e942"}.icon-folder-move:before{content:"\e960"}.icon-folder-plus:before{content:"\e961"}.icon-folder-upload:before{content:"\e962"}.icon-folder-star:before{content:"\e963"}.icon-folder-edit:before{content:"\e964"}.icon-folder-download:before{content:"\e965"}.icon-folder-outline:before{content:"\e966"}.icon-folder:before{content:"\e944"}.icon-folder-o:before{content:"\e945"}.icon-folder-open-o:before{content:"\e946"}.icon-folder-open:before{content:"\e947"}.icon-color:before{content:"\e93c"}.icon-paper-clip:before{content:"\e93d"}.icon-text:before{content:"\e929"}.icon-share:before{content:"\f064"}.icon-format-list-bulleted:before{content:"\e9a8"}.icon-format-bold:before{content:"\e953"}.icon-format-header-pound:before{content:"\e954"}.icon-format-italic:before{content:"\e955"}.icon-format-list-numbers:before{content:"\e969"}.icon-format-quote-close:before{content:"\e96a"}.icon-image:before{content:"\e96c"}.icon-table-large:before{content:"\e96d"}.icon-productplan:before{content:"\e9fc"}.icon-aiux:before{content:"\e99e"}.icon-qc:before{content:"\e986"}.icon-qc-q:before{content:"\e985"}.icon-qc-c:before{content:"\e987"}.icon-sonarqube:before{content:"\e9ba"}.icon-board:before{content:"\ea15"}.icon-market:before{content:"\ea01"}.icon-ztool:before{content:"\e9c1"}.icon-contacts:before{content:"\e9c3"}.icon-chats:before{content:"\e9c4"}.icon-ops:before{content:"\e903"}.icon-menu-backend:before{content:"\e993"}.icon-feedback:before{content:"\e991"}.icon-oa:before{content:"\e9a1"}.icon-more-circle:before{content:"\e988"}.icon-controls:before{content:"\e995"}.icon-account:before{content:"\e992"}.icon-about:before,.icon-info:before{content:"\e996"}.icon-exclamation:before{content:"\e9fa"}.icon-exit:before{content:"\e99a"}.icon-theme:before{content:"\e9a0"}.icon-globe:before,.icon-lang:before{content:"\f0ac"}.icon-template:before{content:"\e9fb"}.icon-seal:before{content:"\e9f8"}.icon-menu-arrow-left:before{content:"\e9f0"}.icon-menu-arrow-right:before{content:"\e9f1"}.icon-add-directory:before{content:"\e9ef"}.icon-design:before{content:"\e9ec"}.icon-download-alt:before{content:"\e9ea"}.icon-blame:before{content:"\e9e0"}.icon-draft-edit:before{content:"\e9dc"}.icon-sub-review-user:before{content:"\e9db"}.icon-sub-review:before{content:"\e9df"}.icon-ztf:before{content:"\e9dd"}.icon-save:before{content:"\e9d8"}.icon-list-box:before{content:"\e9b4"}.icon-usecase:before{content:"\e99d"}.icon-code:before{content:"\e990"}.icon-summary:before{content:"\e9ad"}.icon-more-alt:before{content:"\e9a7"}.icon-customer:before{content:"\e9d9"}.icon-alarm:before{content:"\ea16"}.icon-treeview:before{content:"\ea0d"}.icon-or:before{content:"\ea0b"}.icon-manager:before{content:"\ea0c"}.icon-target:before{content:"\ea0a"}.icon-ipd:before{content:"\e9f9"}.icon-wiki-lib:before{content:"\e9f5"}.icon-annex-lib:before{content:"\e9f6"}.icon-interface-lib:before{content:"\e9f7"}.icon-has-authority-pack:before{content:"\e9f3"}.icon-without-authority-pack:before{content:"\e9f4"}.icon-data-structure:before{content:"\e9f2"}.icon-waterfallplus:before{content:"\e9ed"}.icon-agileplus:before{content:"\e9ee"}.icon-horn:before{content:"\e9eb"}.icon-resume:before{content:"\e9e9"}.icon-mirror:before{content:"\e9e6"}.icon-remote:before{content:"\e9e7"}.icon-moon:before{content:"\e9e8"}.icon-ticket:before{content:"\e9e1"}.icon-gantt-alt:before{content:"\e9e2"}.icon-tree:before{content:"\e9c9"}.icon-list:before{content:"\e9cb"}.icon-gantt:before{content:"\e9cc"}.icon-group-view:before{content:"\e9cd"}.icon-inherit-space:before{content:"\e9c2"}.icon-card-archive:before{content:"\e9b8"}.icon-col-archive:before{content:"\e9b9"}.icon-col-add-right:before{content:"\e9bb"}.icon-col-add-left:before{content:"\e9bc"}.icon-col-split:before{content:"\e9bd"}.icon-waterfall:before{content:"\e9a4"}.icon-manual:before{content:"\e98d"}.icon-lane:before{content:"\e9b1"}.icon-var-x:before{content:"\ea1d"}.icon-mobile:before{content:"\ea18"}.icon-clear:before{content:"\ea19"}.icon-db:before{content:"\ea17"}.icon-unpinned:before{content:"\ea08"}.icon-pinned:before{content:"\ea09"}.icon-support-ticket:before{content:"\ea04"}.icon-snap-house:before{content:"\e9e3"}.icon-wrench:before{content:"\e9e4"}.icon-desktop:before{content:"\e9e5"}.icon-back-circle:before{content:"\e9da"}.icon-back:before{content:"\e9d3"}.icon-shield:before{content:"\e9ca"}.icon-meh:before{content:"\e9ce"}.icon-frown:before{content:"\e9cf"}.icon-smile:before{content:"\e9d0"}.icon-unlock-solid:before{content:"\e9d1"}.icon-lock-solid:before{content:"\e9d2"}.icon-ver:before{content:"\e9c6"}.icon-publish:before,.icon-send:before{content:"\e9c7"}.icon-tag:before{content:"\e9be"}.icon-tag-lock:before{content:"\e9bf"}.icon-code-fork:before{content:"\f126"}.icon-branch-lock:before{content:"\e9c0"}.icon-groups:before{content:"\e9af"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-thumbs-up-solid:before{content:"\e9d6"}.icon-thumbs-down-solid:before{content:"\e9d7"}.icon-hash:before,.icon-version:before{content:"\e9ab"}.icon-p-square:before{content:"\e97b"}.icon-video-play:before{content:"\e97f"}.icon-plus-solid-circle:before{content:"\e974"}.icon-minuse-solid-circle:before{content:"\e9b6"}.icon-s:before{content:"\e975"}.icon-c:before{content:"\e976"}.icon-t:before{content:"\e977"}.icon-guide:before{content:"\e978"}.icon-todo:before{content:"\e979"}.icon-plus:before{content:"\e925"}.icon-side-left:before{content:"\e9b3"}.icon-side-right:before{content:"\e9b2"}.icon-fullscreen-exit:before{content:"\e972"}.icon-alert:before{content:"\e99f"}.icon-undo:before{content:"\e93f"}.icon-redo:before{content:"\e9d4"}.icon-swap:before{content:"\e9b0"}.icon-chat-solid:before{content:"\e9b5"}.icon-clock:before{content:"\e97c"}.icon-cost:before{content:"\e97d"}.icon-pencil-alt:before{content:"\e984"}.icon-size-height:before{content:"\e9c5"}.icon-upload-file:before{content:"\ea03"}.icon-file-log:before{content:"\e9de"}.icon-rich-text:before{content:"\e913"}.icon-markdown:before{content:"\e916"}.icon-excel:before{content:"\e933"}.icon-text-link:before{content:"\e94d"}.icon-ppt:before{content:"\e957"}.icon-word:before{content:"\e958"}.icon-doc-lib:before{content:"\e96f"}.icon-file-empty:before,.icon-file:before{content:"\f016"}.icon-file-text:before{content:"\f0f6"}.icon-file-alt:before{content:"\f15b"}.icon-file-text-alt:before{content:"\f15c"}.icon-file-pdf:before{content:"\f1c1"}.icon-file-word:before{content:"\f1c2"}.icon-file-excel:before{content:"\f1c3"}.icon-file-powerpoint:before{content:"\f1c4"}.icon-file-image:before{content:"\f1c5"}.icon-file-archive:before{content:"\f1c6"}.icon-file-audio:before{content:"\f1c7"}.icon-file-video:before{content:"\f1c8"}.icon-file-code:before{content:"\f1c9"}.icon-multi-input:before{content:"\ea1a"}.icon-cell-input:before{content:"\ea0e"}.icon-input:before{content:"\ea0f"}.icon-checkbox:before{content:"\ea10"}.icon-radio:before{content:"\ea11"}.icon-transition:before{content:"\ea12"}.icon-add-sub-chapter:before{content:"\ea13"}.icon-add-chapter:before{content:"\ea14"}.icon-menu-collapse:before{content:"\e980"}.icon-menu-expand:before{content:"\e981"}.icon-estimate:before{content:"\e9ac"}.icon-sprint:before{content:"\e9a2"}.icon-shield-check:before{content:"\e9a5"}.icon-ok:before{content:"\e9a6"}.icon-printer:before{content:"\e906"}.icon-bullhorn:before{content:"\e910"}.icon-person:before{content:"\e941"}.icon-fields:before{content:"\e989"}.icon-trigger:before{content:"\e98a"}.icon-layout:before{content:"\e98b"}.icon-audit:before{content:"\e98c"}.icon-ban-circle:before,.icon-cancel:before{content:"\e951"}.icon-eye:before{content:"\e94e"}.icon-eye-off:before{content:"\e96e"}.icon-unlock:before{content:"\e94f"}.icon-lock:before,.icon-private:before{content:"\e950"}.icon-move:before{content:"\e94c"}.icon-hand-right:before{content:"\e907"}.icon-checked:before{content:"\e908"}.icon-off:before{content:"\e909"}.icon-play:before,.icon-start:before{content:"\e90a"}.icon-time:before{content:"\e90b"}.icon-edit:before{content:"\e90c"}.icon-trash:before{content:"\e90d"}.icon-link:before{content:"\e90e"}.icon-unlink:before{content:"\e90f"}.icon-bug:before{content:"\e911"}.icon-list-alt:before{content:"\e912"}.icon-alter:before,.icon-change:before{content:"\e970"}.icon-glasses:before,.icon-review:before{content:"\e914"}.icon-sitemap:before,.icon-testcase:before{content:"\e915"}.icon-pluses:before{content:"\e917"}.icon-report-list:before{content:"\e918"}.icon-active:before,.icon-magic:before{content:"\e919"}.icon-treemap:before{content:"\e91a"}.icon-confirm:before{content:"\e91b"}.icon-split:before{content:"\e98e"}.icon-calendar:before,.icon-delay:before{content:"\e91d"}.icon-pause:before{content:"\e91e"}.icon-ban:before{content:"\e91f"}.icon-plus-bold:before{content:"\e920"}.icon-copy:before{content:"\e921"}.icon-refresh:before{content:"\e922"}.icon-diff:before{content:"\e9b7"}.status-active,.status-asked,.status-normal,.status-unconfirmed,.status-wait{color:var(--color-status-normal,#313c52)}.status-active.status-issue,.status-checking,.status-commenting,.status-confirmed,.status-doing{color:#ff6f42}.status-blocked,.status-hangup,.status-pause,.status-suspended{color:#b89664}.status-clarify,.status-draft{color:#8166ee}.status-noreview,.status-reviewing,.status-wait.status-testcase{color:#18a6fd}.status-active.status-risk,.status-changed,.status-changing,.status-fail{color:#fb2b2b}.status-checked,.status-done,.status-pass,.status-replied,.status-resolved,.status-success{color:#0dbb7d}.status-cancel,.status-canceled,.status-investigate{color:var(--color-status-cancel,#838a9d)}.status-closed,.status-testtask.status-done{color:var(--color-status-closed,#9ea3b0)}.dark{--color-status-normal:#eff1f3;--color-status-cancel:#9ea3b0;--color-status-closed:#838a9d}@media (prefers-color-scheme:dark){.dark-auto{--color-status-normal:#eff1f3;--color-status-cancel:#9ea3b0;--color-status-closed:#838a9d}}.pri,[class*=" pri-"],[class^=pri-]{border-color:currentColor;border-radius:var(--radius-full);border-width:1px;display:inline-block;font-size:.75rem;height:1rem;line-height:1rem;line-height:14px;max-width:54px;min-width:16px;overflow:hidden;padding-left:.125rem;padding-right:.125rem;text-align:center;white-space:nowrap;--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.pri-1{color:rgb(255 73 18/var(--tw-text-opacity))}.pri-1,.pri-2{--tw-text-opacity:1}.pri-2{color:rgba(var(--color-warning-600-rgb),var(--tw-text-opacity))}.pri-3{color:rgb(59 130 246/var(--tw-text-opacity))}.pri-3,.pri-4{--tw-text-opacity:1}.pri-4{color:rgb(149 211 224/var(--tw-text-opacity))}.severity{display:inline-block;font-size:.75rem;height:1rem;line-height:1rem;line-height:14px;max-width:54px;min-width:16px;overflow:hidden;padding-left:.125rem;padding-right:.125rem;position:relative;text-align:center;white-space:nowrap;--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.severity:before{background-color:currentColor;background-repeat:no-repeat;height:100%;left:0;position:absolute;top:0;width:100%;z-index:0;--tw-content:attr(data-severity);content:var(--tw-content);-webkit-mask:url('data:image/svg+xml;charset=utf-8,');mask:url('data:image/svg+xml;charset=utf-8,');-webkit-mask-size:100% 100%;mask-size:100% 100%}.severity:after,.severity:before{display:inline-block}.severity:after{--tw-scale-x:.75;--tw-scale-y:.75;content:attr(data-severity);line-height:20px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.severity[data-severity="1"]{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.severity[data-severity="2"]{--tw-text-opacity:1;color:rgb(249 115 22/var(--tw-text-opacity))}.severity[data-severity="3"]{--tw-text-opacity:1;color:rgb(250 174 26/var(--tw-text-opacity))}.severity[data-severity="4"]{--tw-text-opacity:1;color:rgb(184 150 100/var(--tw-text-opacity))}.severity[data-severity="5"]{--tw-text-opacity:1;color:rgb(158 163 176/var(--tw-text-opacity))}.severity-label{background-color:transparent}.severity-label:after,.severity-label:before{--tw-content:none;content:var(--tw-content)}.risk-high{color:rgb(220 38 38/var(--tw-text-opacity))}.risk-high,.risk-middle{--tw-text-opacity:1}.risk-middle{color:rgb(234 179 8/var(--tw-text-opacity))}.label.label-id{border-radius:var(--radius-full);flex:none;--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-300-rgb),var(--tw-ring-opacity));--label-bg:rgba(var(--color-canvas-rgb),.1)}.nav-feature{--nav-active-bg:var(--color-primary-100);--nav-active-color:var(--color-fore)}.nav-feature .nav-checkbox>.checkbox,.nav-feature .nav-checkbox>.checkbox-primary,.nav-feature .nav-item>a{align-items:center;border-radius:var(--radius);height:2rem;padding-left:.625rem;padding-right:.625rem}.nav-feature .nav-item>a>.icon{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.sortable-list .listitem{cursor:move;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding-left:.5rem;padding-right:.5rem}.sortable-list .sortable-ghost>.listitem{--tw-bg-opacity:1;background-color:rgba(var(--color-warning-50-rgb),var(--tw-bg-opacity))}.sortable-empty-shadow{height:1px!important;left:0!important;opacity:0!important;pointer-events:none!important;position:absolute!important;top:0!important;width:1px!important}:root{--avatar-radius:12.5%;--avatar-bg:var(--color-surface)}.avatar{align-items:center;aspect-ratio:1/1;background:var(--avatar-bg);border-radius:var(--avatar-radius);display:inline-flex;justify-content:center;overflow:hidden;width:2rem}.avatar>img{height:100%;margin:0;-o-object-fit:cover;object-fit:cover;width:100%}.avatar.size-xs{width:1.25rem}.avatar.size-sm,.avatar.size-xs{font-size:.75rem;line-height:1rem}.avatar.size-sm{width:1.5rem}.avatar.size-lg{font-size:1.5rem;line-height:2rem;width:3rem}.avatar.size-xl{font-size:2.25rem;line-height:2.5rem;width:5rem}.avatar-group{display:flex;gap:.625rem}.avatar-group>.avatar{box-shadow:0 0 0 1px var(--color-canvas)}.avatar-group>*+*{margin-left:-1rem}.avatar-group.size-xs>*+*{margin-left:-.75rem}.avatar-group.size-sm>*+*{margin-left:-.875rem}.avatar-group.size-lg>*+*{margin-left:-1.25rem}.avatar-group.size-xl>*+*{margin-left:-1.5rem}.btn-group{display:flex;gap:1px}.btn-group>.btn.active{z-index:1}.btn-group>.btn:focus-within,.btn-group>.btn:hover{z-index:2}.btn-group>.btn.disabled,.btn-group>.btn:disabled{z-index:0}.btn-group>.btn:not(:first-child){border-bottom-left-radius:var(--radius-none);border-left-color:rgba(var(--color-canvas-rgb),.2);border-left-width:1px;border-top-left-radius:var(--radius-none)}.btn-group>.btn:not(:first-child):before{left:-1px}.btn-group>.btn:not(:last-child){border-bottom-right-radius:var(--radius-none);border-top-right-radius:var(--radius-none)}.color-picker-heading{align-items:center;font-weight:700;justify-content:space-between;margin-bottom:-.25rem;padding:.5rem}.color-picker-heading,.color-picker-row{display:flex;flex-direction:row}.color-picker-row{flex-wrap:wrap;gap:.5rem;padding:.75rem}.color-picker-item{align-items:center;border-radius:var(--radius-full);display:flex;height:1.25rem;justify-content:center;padding-left:.125rem;padding-right:.125rem;width:1.25rem;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.pick-container{left:0;pointer-events:none;position:absolute;top:0;z-index:1600}.pick-pop{display:flex;flex-direction:column;opacity:0;pointer-events:auto;position:absolute;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);z-index:1200}.pick-pop.in{opacity:1}.date-picker-menu{--menu-bg:none}.date-picker-menu .mini-calendar{margin-top:-.75rem}.date-pick-menu-month,.date-pick-menu-years{display:flex;flex-direction:row;flex-wrap:wrap;gap:1px;max-height:237px;padding-bottom:.5rem;padding-left:.5rem;padding-right:.5rem}.date-pick-menu-years>.btn{width:2.5rem}.date-pick-menu-years>.btn.is-current{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.date-pick-menu-month>.btn.active,.date-pick-menu-years>.btn.active{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.date-pick-menu-month>.btn{width:3rem}.date-picker-menu-footer{border-top-width:1px;display:flex;flex-direction:row;padding:.25rem}.date-picker-menu-footer>.toolbar{flex:1 1 auto;justify-content:center}.date-picker-menu>.menu{border-right-width:1px}.date-picker-menu .menu-item{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.time-picker-menu{max-height:inherit}.time-picker-menu .menu-item>a{justify-content:center;padding-left:0;padding-right:0;text-align:center}.datetime-picker-menu{max-height:inherit}.mini-calendar{padding:.5rem}.mini-calendar>.row>.col{align-items:center;justify-content:center;width:14.2857%}.mini-calendar-day{height:2rem}.mini-calendar-day.disabled{pointer-events:none;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-200-rgb),var(--tw-bg-opacity));opacity:.5}.mini-calendar-day>.btn{width:2rem}.mini-calendar-day.is-weekend>.btn{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.mini-calendar-day.active>.btn,.mini-calendar-day.is-today>.btn{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.mini-calendar-day.selected>.btn{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.mini-calendar-day.is-out-month{opacity:.5}.i-time{border-color:currentColor;border-radius:50%;border-width:.08em;display:inline-block;height:1em;position:relative;width:1em}.i-time:after{border-color:currentColor;border-width:0 0 .08em .08em;height:.385em;left:.3846em;position:absolute;top:.08em;width:.385em;--tw-content:"";content:var(--tw-content)}.chevron-down,.chevron-left,.chevron-right,.chevron-up{align-items:center;display:inline-flex;height:1em;justify-content:center;position:relative;width:1em}.chevron-down:before,.chevron-left:before,.chevron-right:before,.chevron-up:before{display:block;height:.6923077em;transform-origin:center;width:.6923077em;--tw-translate-y:-0.125rem;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.chevron-left:before{--tw-translate-y:0px;--tw-translate-x:0.125rem;--tw-rotate:135deg}.chevron-left:before,.chevron-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.chevron-right:before{--tw-translate-y:0px;--tw-translate-x:-0.125rem;--tw-rotate:-45deg}.chevron-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.i-calendar{border-radius:2px;display:inline-block;height:.79em;margin-top:.16em;position:relative;width:1em}.i-calendar,.i-calendar:after,.i-calendar:before{border-color:currentColor;border-width:.08em}.i-calendar:after,.i-calendar:before{position:absolute;--tw-content:"";content:var(--tw-content)}.i-calendar:before{border-bottom-width:0;left:.15em;top:.307em;width:.6em}.i-calendar:after{border-bottom-width:0;border-top-width:0;height:.3077em;left:.17em;top:-.154em;width:.538em}:root{--modal-radius:var(--radius-lg);--modal-bg:rgba(var(--color-inverse-rgb),.4);--modal-sm:37.5rem;--modal-base:50rem;--modal-lg:75rem;--modal-xl:90rem}.modal{align-items:center;background-color:var(--modal-bg);bottom:0;display:none;justify-content:center;left:0;overflow:hidden;position:fixed;right:0;top:0;z-index:1500}.modal.load-indicator:before{background-color:transparent;transition-property:none}.modal.loading:after{--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.modal.loading .modal-dialog{opacity:0!important}.modal.show{display:flex}.modal-no-backdrop{background-color:transparent;pointer-events:none}.modal-hide{opacity:0!important}.modal-dialog{background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));pointer-events:auto;position:relative;--tw-bg-opacity:0.9;--tw-shadow:0 10px 50px -10px rgba(0,0,0,.4),0 8px 20px -10px rgba(0,0,0,.3);--tw-shadow-colored:0 10px 50px -10px var(--tw-shadow-color),0 8px 20px -10px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05;--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);border-radius:var(--modal-radius);width:var(--modal-base)}.modal-content,.modal-dialog{max-height:100vh}.modal-content{display:flex;flex-direction:column;height:100%}.loading>.modal-dialog>.modal-content{opacity:0;visibility:hidden}.modal-dialog.loading{background-color:transparent}.modal-dialog.loading>.modal-content{display:none}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.modal-header{align-items:center;display:flex;flex:none;flex-wrap:nowrap;gap:1rem;padding:1rem 1.25rem;position:relative}.modal-title{flex:1 1 auto;font-size:1rem;font-weight:700;line-height:1.5rem}.modal-actions{position:absolute;right:.75rem;top:.75rem;z-index:15}.modal-body{flex:1 1 auto;overflow:auto;padding:1rem 1.25rem}.modal-footer{align-items:center;display:flex;flex:none;gap:.75rem;padding:1.25rem}.modal-dialog.size-full,.modal-dialog[data-size=full]{border-radius:var(--radius-none);height:100vh;width:100vw}.modal-dialog.size-sm,.modal-dialog[data-size=sm]{width:var(--modal-sm)}.modal-dialog.size-lg,.modal-dialog[data-size=lg]{width:var(--modal-lg)}.modal-dialog.size-xl,.modal-dialog[data-size=xl]{width:var(--modal-xl)}.modal-iframe{flex:1 1 auto;width:100%}.modal-trans{opacity:0;transition-duration:.2s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.modal-trans.in{opacity:1}.modal-trans>.modal-dialog{transition-property:transform,opacity;--tw-scale-x:.95;--tw-scale-y:.95;opacity:0;transition-duration:.3s}.modal-trans.in>.modal-dialog,.modal-trans>.modal-dialog{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.modal-trans.in>.modal-dialog{--tw-scale-x:1;--tw-scale-y:1;opacity:1}.modal-alert .modal-footer{justify-content:flex-end}.modal-alert .modal-header{margin-bottom:-1rem}.modal-alert .modal-body{overflow-wrap:break-word;white-space:pre-line}.modal-alert .modal-actions+.modal-body{padding-right:3rem}.modal-alert .modal-header+.modal-actions+.modal-body{padding-right:1.25rem}.file-selector{gap:.5rem;width:100%}.file-selector,.file-selector-box{display:flex;flex-direction:column}.file-selector-box{border-style:dashed;border-width:1px;gap:0;height:auto;justify-content:center;position:relative;--tw-border-opacity:1;background-color:rgba(var(--color-primary-50-rgb),.3);border-color:rgba(var(--color-primary-400-rgb),var(--tw-border-opacity));padding:.5rem .75rem;--tw-ring-color:transparent;--state-color:rgba(var(--color-primary-500-rgb),.05)}.file-selector-box .text{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.is-dragging .file-selector-box{border-style:solid}.file-selector-btn{align-items:center;display:flex;gap:.5rem;position:relative}.is-dragging .file-selector-btn{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.file-selector-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;bottom:0;cursor:pointer;left:0;opacity:.1;position:absolute;right:0;top:0}.file-selector-tip{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.file-selector.is-mode-button{flex-direction:column-reverse}.file-selector-list.is-empty{display:none}.file-selector-item .item-avatar{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.file-selector-item .item-subtitle{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.file-selector-item .item-content{flex:none;margin-right:.25rem;max-width:100%}.file-selector-item>.listitem:hover{background-color:rgba(var(--color-gray-500-rgb),.05)}.file-selector-item.is-renaming .item-avatar+.item-content{max-width:calc(100% - 32px)}.file-selector-rename-text{max-width:100%;min-width:100px;position:relative}.file-selector-rename-text>div{overflow:hidden;pointer-events:none;visibility:hidden;white-space:nowrap}.file-selector-rename-input{bottom:0;left:0;position:absolute;right:0;top:0}.file-selector-grid{align-items:flex-start;border-color:transparent;border-radius:var(--radius);border-width:1px;display:flex;flex-direction:row;flex-wrap:wrap;gap:var(--file-selector-grid-gap);--tw-bg-opacity:1;background-color:rgba(var(--color-surface-light-rgb),var(--tw-bg-opacity));padding:.5rem}.file-selector-grid-item{height:var(--file-selector-grid-height)}.file-selector-grid-btn,.file-selector-grid-item{width:var(--file-selector-grid-width)}.file-selector-grid-btn{aspect-ratio:1/1;border-style:dashed;border-width:1px;display:flex;flex-direction:column;gap:0;height:auto;justify-content:center;--tw-border-opacity:1;background-color:rgba(var(--color-primary-50-rgb),.3);border-color:rgba(var(--color-primary-400-rgb),var(--tw-border-opacity));padding:.5rem;--tw-ring-color:transparent;--state-color:rgba(var(--color-primary-500-rgb),.05)}.file-selector-grid-btn .text{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.file-selector-grid-item .listitem{flex-direction:column;height:100%;padding:0;position:relative;width:100%}.file-selector-grid-item .item-avatar{border-radius:var(--radius);border-width:1px;width:100%;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.file-selector-grid-item .item-avatar.has-icon>.icon{font-size:calc(var(--file-selector-grid-width)/2)}.file-selector-grid-item .item-content,.file-selector-grid-item .toolbar{aspect-ratio:1/1;left:0;position:absolute;right:0;top:0;width:100%}.file-selector-grid-item .item-title{bottom:-1.25rem;font-size:.75rem;left:0;line-height:1rem;overflow:hidden;position:absolute;right:1.5rem;white-space:nowrap}.file-selector-grid-item .item-subtitle{border-radius:var(--radius-full);bottom:.25rem;left:.25rem;position:absolute;--tw-bg-opacity:1;background-color:rgba(var(--color-fore-rgb),var(--tw-bg-opacity));font-size:.75rem;line-height:1rem;padding-left:.25rem;padding-right:.25rem;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));opacity:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.file-selector-grid-item:hover .item-subtitle{opacity:1}.file-selector-grid-item .toolbar .btn[data-remove-file]{background-color:rgba(var(--color-inverse-rgb),.5);padding:.375rem;position:absolute;right:1px;top:1px;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.file-selector-grid-item .toolbar .btn[data-rename-file]{bottom:-1.5rem;padding:0;position:absolute;right:0}.file-selector-grid .file-selector-rename{bottom:0;height:1.5rem;position:absolute;top:auto}.file-selector-grid .file-selector-rename-text{width:100%}.is-dragging .file-selector-grid{border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-primary-400-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}:root{--nav-radius:var(--radius);--nav-active-color:var(--color-primary-500);--nav-active-bg:var(--color-inherit);--nav-heading-color:var(--color-gray-500);--nav-gap:0.25rem;--nav-item-color:inherit;--nav-item-bg:transparent;--nav-item-padding:1rem;--nav-item-height:2rem;--nav-item-gap:0.75rem;--nav-divider-height:calc(var(--nav-item-height)/2);--nav-divider-margin:0.5rem}.nav{list-style-type:none;padding-left:0}.nav,.nav-item{align-items:center;display:flex;position:relative}.nav-item{gap:var(--nav-item-gap)}.nav-item>a{align-items:center;background-color:var(--nav-item-bg);color:var(--nav-item-color);cursor:pointer;display:flex;gap:var(--nav-gap);height:var(--nav-item-height);justify-content:center;padding-left:var(--nav-item-padding);padding-right:var(--nav-item-padding)}.nav-item>a>.text{white-space:nowrap}.nav-item>.active{font-weight:700;--nav-item-color:var(--nav-active-color);--nav-item-bg:var(--nav-active-bg)}.nav-item>.selected{--nav-item-color:var(--nav-selected-color);--nav-item-bg:var(--nav-selected-bg)}.nav-item>.disabled{--nav-item-color:var(--nav-disabled-color);--nav-item-bg:var(--nav-disabled-bg)}.nav-item>.disabled>*{opacity:var(--opacity-disabled)}.nav-divider,.nav>.divider{align-self:center;height:var(--nav-divider-height);margin-left:var(--nav-divider-margin);margin-right:var(--nav-divider-margin)}.nav-heading{align-items:center;color:var(--nav-heading-color);display:flex;font-weight:700;gap:.25rem;height:2rem;justify-content:center;padding-left:1rem;padding-right:1rem}.nav-space{flex:1 1 auto;width:1rem}.nav-compact{--nav-gap:0.25rem;--nav-item-gap:0.5rem;--nav-item-height:1.75rem;--nav-item-padding:0.5rem;--nav-divider-margin:0.25rem}.nav-primary>.nav-item{position:relative}.nav-primary>.nav-item:hover{z-index:10}.nav-primary>.nav-item+.nav-item{margin-left:-1px}.nav-primary>.nav-item>a{border-radius:var(--radius-none);border-width:1px}.nav-primary>.nav-item:first-child>a,.nav-primary>.nav-item:has(.nav-heading)+.nav-item>a{border-bottom-left-radius:var(--nav-radius);border-top-left-radius:var(--nav-radius)}.nav-primary>.nav-item:last-child>a{border-bottom-right-radius:var(--nav-radius);border-top-right-radius:var(--nav-radius)}.nav-primary>.nav-item>.active{--tw-text-opacity:1;background:var(--nav-active-color);border-color:var(--nav-active-color);color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.nav-primary>.nav-divider{display:none}.nav-secondary>.nav-item>a{border-radius:var(--radius-none);position:relative}.nav-secondary>.nav-item>a:after{bottom:-2px;display:block;height:2px;left:0;position:absolute;right:0;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity));--tw-content:"";content:var(--tw-content)}.nav-secondary>.nav-item>.active:after{background-color:currentColor}.nav-secondary>.nav-divider{margin:0 0 0 -1px}.nav-tabs>.nav-item>a{border-bottom-left-radius:var(--radius-none);border-bottom-right-radius:var(--radius-none);position:relative}.nav-tabs>.nav-item>a:after{border-color:transparent;border-width:1px;bottom:-1px;display:block;left:-1px;pointer-events:none;position:absolute;right:-1px;top:-1px;--tw-border-opacity:1;border-bottom-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));--tw-content:"";border-top-left-radius:inherit;border-top-right-radius:inherit;content:var(--tw-content)}.nav-tabs>.nav-item>.active:after{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));border-bottom-color:transparent}.nav-tabs>.nav-divider{margin:0 0 0 -1px}.nav-pills>.nav-item>a{border-radius:var(--radius-full)}.nav-pills>.nav-item>.active{--tw-text-opacity:1;background:var(--nav-active-color);border-color:var(--nav-active-color);color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.nav-steps{--nav-item-bg:var(--color-canvas);--nav-active-bg:var(--color-primary-500);--nav-active-color:var(--color-canvas);--nav-selected-bg:var(--color-secondary-500);--nav-selected-color:var(--color-canvas)}.nav-steps>.nav-item+.nav-item>a{padding-left:calc(var(--nav-item-padding) + var(--nav-item-height)/3)}.nav-steps>.nav-item>a:after,.nav-steps>.nav-item>a:before{border-style:solid;height:0;left:100%;position:absolute;width:0;z-index:2;--tw-content:"";border-color:transparent;border-left-color:var(--nav-item-bg,var(--color-canvas));border-width:calc(var(--nav-item-height)/2);border-left-width:calc(var(--nav-item-height)/3);border-right-width:0;content:var(--tw-content)}.nav-steps>.nav-item>a:before{background-color:transparent!important;border-left-color:var(--color-border);bottom:auto;left:calc(100% + 5.5px);opacity:1!important;right:auto;top:.4rem;transform:none;z-index:1;--nav-item-height:1.2rem}.nav-steps>.nav-item:has(+.nav-item>.active)>.selected:before,.nav-steps>.nav-item:has(+.nav-item>.active,+.nav-item>.selected)>a:not(.active,.selected):before,.nav-steps>.nav-item:has(+.nav-item>.selected)>.active:before,.nav-steps>.nav-item:last-child>a:after,.nav-steps>.nav-item:last-child>a:before{display:none}.nav-steps>.nav-item>a:hover{--nav-item-bg:var(--color-gray-100)}.nav-steps>.nav-item>.active:hover{--nav-item-bg:var(--color-primary-600)}.nav-steps>.nav-item>.selected:hover{--nav-item-bg:var(--color-secondary-600)}.nav-stacked{flex-direction:column}.nav-stacked>.nav-item{width:100%}.nav-stacked>.nav-heading,.nav-stacked>.nav-item>a{justify-content:flex-start;width:100%}.nav-stacked>.nav-divider{height:1px;margin:.5rem 0;width:100%}.nav-primary.nav-stacked>.nav-item>a{height:2.5rem}.nav-primary.nav-stacked>.nav-item+.nav-item{margin-left:0;margin-top:-1px}.nav-primary.nav-stacked>.nav-item:first-child>a{border-bottom-left-radius:0;border-top-left-radius:var(--nav-radius);border-top-right-radius:var(--nav-radius)}.nav-primary.nav-stacked>.nav-item:last-child>a{border-bottom-left-radius:var(--nav-radius);border-bottom-right-radius:var(--nav-radius);border-top-right-radius:0}.nav-secondary.nav-stacked>.nav-item>a:after{bottom:0;height:100%;left:auto;right:0;top:0;width:2px;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity))}.nav-secondary.nav-stacked>.nav-item>.active:after{background-color:currentColor}.nav-secondary.nav-stacked>.nav-divider{margin:0}.nav-tabs.nav-stacked>.nav-item>a{border-bottom-left-radius:var(--nav-radius);border-bottom-right-radius:var(--radius-none);border-top-right-radius:var(--radius-none);position:relative}.nav-tabs.nav-stacked>.nav-item>a:after{--tw-border-opacity:1;border-bottom-color:transparent;border-bottom-left-radius:inherit;border-right-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));border-top-left-radius:inherit}.nav-tabs.nav-stacked>.nav-item>a.active:after{--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));border-right-color:transparent}.nav-tabs.nav-stacked>.nav-divider{margin:0}.nav-pills.nav-stacked>.nav-item+.nav-item{margin-top:.25rem}.nav-justified>.nav-item:not(.flex-none,.nav-divider){flex:1 1 auto}.nav-justified>.nav-item>a{width:100%}.arrow,.arrow:before{background:inherit;height:calc(var(--arrow-size)*1.4142);position:absolute;width:calc(var(--arrow-size)*1.4142)}.arrow{visibility:hidden;--arrow-size:5px}.arrow:before{border:inherit;content:"";visibility:visible;--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.arrow-top,.arrow-up{border-bottom:inherit;border-right:inherit;border-width:1px 0 0 1px;top:calc(1px - var(--arrow-size))}.white>.arrow-top,.white>.arrow-up{top:calc(0px - var(--arrow-size))}.arrow-bottom,.arrow-down{border-left:inherit;border-top:inherit;border-width:0 1px 1px 0;bottom:calc(1px - var(--arrow-size))}.white>.arrow-bottom,.white>.arrow-down{bottom:calc(0px - var(--arrow-size))}.arrow-left{border-right:inherit;border-top:inherit;border-width:0 0 1px 1px;left:calc(1px - var(--arrow-size))}.white>.arrow-left{left:calc(0px - var(--arrow-size))}.arrow-right{border-bottom:inherit;border-left:inherit;border-width:1px 1px 0 0;right:calc(1px - var(--arrow-size))}.white>.arrow-right{right:calc(0px - var(--arrow-size))}.popover{display:none;left:0;position:absolute;top:0;width:-moz-max-content;width:max-content}.popover.show{display:block}.popover-heading{align-items:center;border-top-left-radius:inherit;border-top-right-radius:inherit;display:flex;gap:1rem;height:2.5rem;justify-content:space-between;position:relative;z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding-left:.75rem;padding-right:.5rem}.popover-title{flex:1 1 auto;font-weight:700}.popover-content{padding:.75rem;position:relative;z-index:1}.popover-arrow{z-index:0}.has-heading>.popover-arrow.arrow-top,.has-heading>.popover-arrow.arrow-up{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity))}.popover>.btn-close{position:absolute;right:.5rem;top:.625rem;z-index:2}.btn-close+.popover-content{padding-right:3rem}.btn.with-popover-show{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.with-popover-show[data-pop-placement=top]>.caret{--tw-rotate:180deg}.with-popover-show[data-pop-placement=left]>.caret,.with-popover-show[data-pop-placement=top]>.caret{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.with-popover-show[data-pop-placement=left]>.caret{--tw-rotate:90deg}.with-popover-show[data-pop-placement=right]>.caret{--tw-rotate:-90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.pager{align-items:center;display:flex;gap:.25rem;white-space:nowrap}.menu.pager-size-menu{display:grid!important;grid-template-columns:repeat(3,minmax(0,1fr));text-align:center}.menu.pager-size-menu>.menu-item>a{margin:.125rem}.pager .pager-goto-group>.form-control{width:3rem}.pager .pager-goto-group>.input-group-addon{border-width:1px;--tw-border-opacity:1;border-color:rgba(var(--color-gray-300-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.pager>.pager-nav.active{--tw-text-opacity:1;box-shadow:0 0 0 1px var(--color-primary-500);color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.panel{border-radius:var(--radius);overflow:hidden;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05}.panel-heading{background-color:var(--panel-heading-bg);flex-wrap:nowrap;gap:1rem;justify-content:space-between;padding:.5rem 1rem}.panel-heading,.panel-title{align-items:center;display:flex}.panel-title{font-weight:700;gap:.5rem;margin:0}.panel-actions{align-items:center;display:flex;margin-right:-.5rem}.panel-body{padding:.75rem 1rem}.panel-footer{align-items:center;background-color:var(--panel-footer-bg);display:flex;gap:.5rem;padding:.5rem 1rem}.size-sm .panel-body,.size-sm .panel-footer,.size-sm .panel-heading{padding:.375rem .75rem}.size-lg .panel-body,.size-lg .panel-footer,.size-lg .panel-heading{padding:1rem 1.25rem}.picker{position:relative}.picker-select{align-items:center;gap:.25rem;justify-content:space-between}.picker-select,.picker-select.form-control{display:flex}.picker-select-placeholder{flex:1 1 auto;--tw-text-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-text-opacity))}.picker-select-multi .picker-select-placeholder{padding-left:.25rem;padding-right:.25rem}.picker-single-selection{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap}.picker-deselect-btn{border-radius:var(--radius-full);padding:.25rem}.picker-deselect-btn:not(:hover){opacity:.7}.picker-select-multi.form-control{height:auto;min-height:32px;padding-left:.25rem}.picker-multi-selections{display:flex;flex-wrap:wrap;gap:.25rem;min-width:0}.picker-multi-selection{align-items:center;border-radius:var(--radius-full);border-width:1px;display:flex;max-width:100%;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding-left:.5rem}.readonly .picker-multi-selection{padding-right:.5rem}.picker-multi-selection>.text{max-width:180px;min-width:0;overflow:clip;white-space:nowrap}.picker-no-search{cursor:default}.picker-menu-list{border-style:none;flex:1 1 auto;min-height:0;overflow-y:auto;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.picker-menu-search+.picker-menu-list.menu{margin-top:-.125rem;padding-top:0}.picker-menu-list.tree{padding:.5rem}.picker-menu-list .tree-item>.selected .item-content{font-weight:400}.picker-menu .search-menu-footer{border-top-width:1px;padding-bottom:.25rem;padding-top:.25rem}.picker-search-input{border-color:transparent;height:1.75rem;outline-width:0!important;padding-left:0;padding-right:2rem;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)!important}.picker-search{flex:none;position:relative;width:100%}.picker-search>.magnifier{opacity:.5;position:absolute;right:0;top:.5rem}.picker-search-clear.btn{cursor:pointer;height:1.25rem;position:absolute;right:0;top:.25rem;width:1.25rem}.picker-search.is-inline{min-width:64px;width:4rem}.is-inline>.picker-search-input{height:1.25rem;min-width:64px;padding-left:.25rem;padding-right:.25rem}.picker-search-measure{height:0;left:0;overflow:hidden;position:absolute;top:0;white-space:nowrap}.split{display:flex;flex-direction:row}.split-vert{flex-direction:column}.split-cell{min-height:0;min-width:0}.has-animation>.split-cell{transition-duration:.15s;transition-property:width,height;transition-timing-function:cubic-bezier(.4,0,.2,1)}.gutter{align-items:stretch;border-radius:var(--radius);cursor:col-resize;display:flex;flex:none;flex-direction:row;justify-content:center;position:relative}.gutter-vert{cursor:row-resize;flex-direction:column}.gutter:before{display:block;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity));transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);--tw-content:"";content:var(--tw-content)}.gutter-horz:before{width:1px}.gutter-vert:before{height:1px}.gutter-horz:hover:before{width:75%}.gutter-vert:hover:before{height:75%}.gutter-resize-handler,.gutter-toggle{align-items:center;border-radius:var(--radius-lg);border-width:1px;display:flex;height:1.75rem;justify-content:center;margin-top:-.875rem;position:absolute;top:50%;width:.75rem;--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity));transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.gutter-toggle>span{--tw-scale-x:.75;--tw-scale-y:.75;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.gutter:hover .gutter-toggle{--tw-border-opacity:1;border-color:rgba(var(--color-gray-500-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.gutter .gutter-toggle:hover{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500-rgb),var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.is-last>.gutter-toggle{--tw-scale-x:-1}.is-first>.gutter-toggle,.is-last>.gutter-toggle{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.is-first>.gutter-toggle{--tw-scale-x:1}.gutter-vert .gutter-toggle{left:50%;margin-left:-.375rem;margin-top:0;top:auto;--tw-rotate:90deg}.gutter-vert .gutter-toggle,.gutter.is-next-collapsed>.gutter-toggle{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.gutter.is-next-collapsed>.gutter-toggle{--tw-scale-x:1}.gutter.is-prev-collapsed>.gutter-toggle{--tw-scale-x:-1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.gutter-horz.is-first.is-prev-collapsed{transform:translateX(calc(-1px - var(--split-gutter-size)/2))}.gutter-horz.is-last.is-next-collapsed{transform:translateX(calc(1px + var(--split-gutter-size)/2))}.gutter-vert.is-first.is-prev-collapsed{transform:translateY(calc(-1px - var(--split-gutter-size)/2))}.gutter-vert.is-last.is-next-collapsed{transform:translateY(calc(1px + var(--split-gutter-size)/2))}.gutter-resize-handler{background-color:transparent;border-width:0}.gutter-resize-handler:before{border-left-width:1px;border-right-width:1px;bottom:0;left:.25rem;position:absolute;right:.25rem;top:0;--tw-content:"";content:var(--tw-content)}.sidebar{flex:none!important;position:relative;--gutter-width:1px;--sidebar-duration:200ms}.has-sidebar-animation .sidebar{transition-duration:.15s;transition-duration:var(--sidebar-duration);transition-property:width,margin;transition-timing-function:cubic-bezier(.4,0,.2,1)}.sidebar-left.is-collapsed{margin-left:calc(var(--gutter-width)*-1)}.sidebar-right.is-collapsed{margin-right:calc(var(--gutter-width)*-1)}.sidebar.is-collapsed>*,.sidebar.is-expanded.is-animating>*{display:none}.sidebar.is-collapsed>.sidebar-gutter{display:flex!important}.sidebar-gutter{bottom:0;left:100%;position:absolute;top:0;width:var(--gutter-width);z-index:10}.sidebar-right>.sidebar-gutter{left:auto;right:100%}.is-collapsed>.gutter>.gutter-toggle>span{--tw-rotate:-180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.sidebar-gutter:before{border-radius:var(--radius-full);opacity:0}.sidebar-gutter:hover:before{opacity:1;width:.5rem}.is-expanded .sidebar-gutter.gutter-border:before{opacity:1}.is-sidebar-resizing{cursor:col-resize}.table{--table-head-bg:var(--color-surface);--table-striped-color:var(--color-gray-50);--table-hover-color:rgba(var(--color-primary-500-rgb),.05);--table-border-color:var(--color-border)}.table{border-color:var(--table-border-color);width:100%}.table>thead{background-color:var(--table-head-bg)}.table>*>tr{border-bottom-width:1px}.table>*>tr>*{padding:.5rem 1rem}.table-striped>tbody>tr:nth-child(2n){background:var(--table-striped-color)}.table-hover>tbody>tr:hover>*{background:var(--table-hover-color)}.table.bordered>*>tr>*{border-width:1px}.table.borderless>*>tr,.table.borderless>*>tr>*{border-style:none}.condensed>*>tr>*{padding:.375rem .75rem}.table-fixed{table-layout:fixed}.table-fixed>*>tr>*{overflow:hidden;white-space:nowrap}.toolbar{align-items:center;display:flex;position:relative}.toolbar>.divider{margin:.5rem;width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity))}.toolbar-space{flex:1 1 auto;height:1px;width:1px}.toolbar>.dropdown.show{align-items:center;display:flex;position:relative}:root{--tooltip-bg:var(--skin-color,var(--color-inverse));--tooltip-text:var(--skin-text,var(--color-canvas));--tooltip-arrow:6px;--tooltip-delay:0.5s}.hint,[class*=" hint-"],[class^=hint-]{position:relative}.hint:before,[class*=" hint-"]:before,[class^=hint-]:before{border-style:solid;height:0;position:absolute;width:0;--tw-content:"";border-color:var(--tooltip-bg) transparent transparent transparent;border-width:var(--tooltip-arrow) var(--tooltip-arrow) 0 var(--tooltip-arrow);content:var(--tw-content);margin-bottom:calc(0px - var(--tooltip-arrow))}.hint:after,[class*=" hint-"]:after,[class^=hint-]:after{background-color:var(--tooltip-bg);border-color:var(--tooltip-color);border-radius:var(--radius);color:var(--tooltip-text);font-size:.75rem;line-height:1rem;max-width:28rem;overflow:hidden;padding:.25rem .5rem;position:absolute;white-space:nowrap;--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-content:attr(data-hint);content:var(--tw-content);text-shadow:0 1px 0 var(--tooltip-bg)}.hint:after,.hint:before,[class*=" hint-"]:after,[class*=" hint-"]:before,[class^=hint-]:after,[class^=hint-]:before{bottom:100%;left:50%;opacity:0;pointer-events:none;transition-delay:0s;transition-duration:.15s;transition-property:opacity,visibility;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,1,1);visibility:hidden;z-index:1800;--tw-translate-x:-50%;--tw-translate-y:calc(var(--tooltip-arrow)*-1);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint:hover:after,.hint:hover:before,[class*=" hint-"]:hover:after,[class*=" hint-"]:hover:before,[class^=hint-]:hover:after,[class^=hint-]:hover:before{opacity:1;transition-delay:var(--tooltip-delay);visibility:visible}.hint-bottom:before{border-color:transparent transparent var(--tooltip-bg) transparent;border-width:0 var(--tooltip-arrow) var(--tooltip-arrow) var(--tooltip-arrow);margin-bottom:auto;margin-top:calc(0px - var(--tooltip-arrow))}.hint-bottom:after,.hint-bottom:before{bottom:auto;top:100%;--tw-translate-y:var(--tooltip-arrow);transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint-left:before{border-color:transparent transparent transparent var(--tooltip-bg);border-width:var(--tooltip-arrow) 0 var(--tooltip-arrow) var(--tooltip-arrow);margin-bottom:auto;margin-right:calc(0px - var(--tooltip-arrow))}.hint-left:after,.hint-left:before{bottom:50%;left:auto;right:100%;--tw-translate-x:calc(var(--tooltip-arrow)*-1);--tw-translate-y:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint-right:before{border-color:transparent var(--tooltip-bg) transparent;border-width:var(--tooltip-arrow) var(--tooltip-arrow) var(--tooltip-arrow) 0;margin-bottom:auto;margin-left:calc(0px - var(--tooltip-arrow))}.hint-right:after,.hint-right:before{bottom:50%;left:100%;--tw-translate-x:var(--tooltip-arrow);--tw-translate-y:50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hint-lg:after,.hint-sm +.hint-md:after:after,.hint-xl:after{white-space:normal;word-break:break-all}.hint-sm:after{width:4rem}.hint-md:after{width:8rem}.hint-lg:after{width:16rem}.hint-xl:after{width:24rem}.hint-primary{--tooltip-bg:var(--color-primary-500)}.hint-success{--tooltip-bg:var(--color-success-500)}.hint-danger{--tooltip-bg:var(--color-danger-500)}.hint-warning{--tooltip-bg:var(--color-warning-500)}.hint-important{--tooltip-bg:var(--color-important-500)}.hint-special{--tooltip-bg:var(--color-special-500)}.tooltip{background-color:var(--tooltip-bg);border-color:var(--tooltip-color);border-radius:var(--radius);color:var(--tooltip-text);font-size:.75rem;line-height:1rem;max-width:28rem;padding:.25rem .5rem;white-space:pre-wrap;z-index:1800}.tooltip:not(.white)>.arrow{border-width:0}.tooltip.white>.arrow{border-color:inherit}.tooltip-has-title{--tw-bg-opacity:0.8;padding:.5rem .75rem .75rem;--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.tooltip-has-title>.arrow{opacity:.75}.tooltip-heading{align-items:center;display:flex;font-size:.8125rem;font-weight:700;gap:1rem;justify-content:space-between;line-height:1.25rem;padding:.25rem}.tooltip-heading>.btn-close{margin-right:-.25rem}.tooltip-content{padding:.25rem}.tree-item-inner{flex-direction:row;min-height:24px;padding-left:var(--list-nested-indent)}.tree-item-inner,.tree-toggle{align-items:center;display:flex}.tree-toggle{border-radius:var(--radius);flex:none;height:1rem;justify-content:center;margin-right:-.375rem;width:1rem;--caret-size:5px;--caret-opacity:.3}.tree-item-inner>.item-icon{opacity:.5;width:1rem}.tree-item-inner:hover>.item-icon{opacity:.8}.tree-item-inner.has-hover{border-radius:var(--radius)}.tree-item-inner .item-title:not(:hover),.tree-item-inner>a.item-title:not(:hover){color:inherit}.tree-item-inner>.toolbar{margin-left:1rem;opacity:.6}.tree-item-inner:hover>.toolbar{opacity:1}.tree-item>.active{background:var(--menu-active-bg);color:var(--menu-active-color)}.tree-item>.selected{background:var(--menu-selected-bg)}.tree-item>.selected .item-content{color:var(--menu-selected-color);font-weight:700}.tree.search-menu-on-top>.search-box{left:0;right:0}.tree-lines .tree{position:relative}.tree-lines .tree-item{--tree-line-indent:calc(var(--list-nested-indent) + 8px)}.tree-lines .tree:before{border-left-width:1px;bottom:.5rem;display:block;left:var(--tree-line-indent);position:absolute;top:-.5rem;--tw-content:"";content:var(--tw-content)}.upload .upload-tip{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.upload .draggable-area{background-color:rgba(var(--color-primary-50-rgb),.2);border:1px dashed var(--color-primary-300)}.upload .draggable-area.dragover{background-color:rgba(var(--color-primary-500-rgb),.1);border-style:solid}.upload .upload-tip{color:var(--color-slate-500)}.file-item>.img{height:120px;width:120px}.upload .file-item:hover .file-size{display:flex!important}.form-batch-container{overflow-y:auto}.form-batch-table{min-width:100%;table-layout:fixed;--table-head-bg:var(--color-canvas)}.form-batch-table>*>tr{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.form-batch-table>*>tr>*{padding-left:.375rem;padding-right:.375rem;vertical-align:top}.form-batch-table>*>tr>th{text-align:left;vertical-align:middle}.form-batch-head[data-name=ACTIONS]{width:5rem}.form-batch-head[data-name=ACTIONS][data-action-count="3"]{width:6rem}.form-batch-label{display:inline}.form-batch-control>textarea.form-control{height:2rem}.form-batch-btn+.btn{margin-left:.25rem}.form-batch-table>tbody[data-count="1"] .form-batch-btn[data-type=delete]{display:none}.form-batch-ditto{position:relative}.form-batch-ditto-btn{bottom:0;height:auto;opacity:.5;padding-left:.5rem;padding-right:.5rem;position:absolute!important;right:0;top:0}.form-batch-ditto-btn:after{bottom:.5rem;left:-1px;position:absolute;top:.5rem;width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-border-rgb),var(--tw-bg-opacity));--tw-content:"";content:var(--tw-content)}[data-ditto=on] .form-batch-ditto-btn{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity));opacity:1}td.form-batch-row-actions{padding-bottom:.75rem!important;padding-top:.75rem!important}.form-batch-ditto-wrapper{position:relative}.form-batch-ditto-control .form-control,.form-batch-ditto-control .pick-pri{padding-right:calc(var(--form-batch-ditto-width) + 8px)}.form-batch-ditto-control .input-control>.input-control-suffix{right:var(--form-batch-ditto-width)}.form-batch-ditto-control .input-control>.form-control{padding-right:calc(var(--form-batch-ditto-width) + var(--input-control-suffix))}.has-fixed-actions .form-batch-col-actions{position:sticky;right:0;z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.form-batch-col-actions.is-pinned:before{background-image:linear-gradient(-90deg,transparent,transparent),linear-gradient(-90deg,transparent,transparent 50%);border-right-width:1px;bottom:0;content:" ";display:block;left:-1rem;position:absolute;top:0;transition-duration:.15s;transition-property:background;transition-timing-function:cubic-bezier(.4,0,.2,1);width:1rem;z-index:1}.form-batch:hover .form-batch-col-actions.is-pinned:before{background-image:linear-gradient(-90deg,rgba(0,0,0,.03),transparent),linear-gradient(-90deg,rgba(0,0,0,.03),transparent 50%)}.panel-form-batch .form-batch-container .form-batch-col-actions.is-pinned:after{bottom:0;display:block;position:absolute;right:-1rem;top:0;width:1rem;z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));content:" "}.datalist{--datalist-label-width:68px}.datalist-item{display:flex;gap:.5rem;padding-bottom:.375rem;padding-top:.375rem}.datalist-item-label{align-items:center;display:flex;flex:none;justify-content:flex-end;overflow:hidden;white-space:nowrap;width:var(--datalist-label-width);--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.datalist-item-content{align-items:center;display:flex;flex:1 1 0%;gap:.5rem}.deliverable-items{border-radius:var(--radius);border-width:1px}.deliverable-item{align-items:center;-moz-column-gap:1rem;column-gap:1rem;display:flex;flex-wrap:wrap;min-height:3rem;padding:.25rem .5rem}.deliverable-item+.deliverable-item{border-top-width:1px}.deliverable-item-category{flex:none;margin-right:.5rem;padding-bottom:.5rem;padding-top:.5rem;position:relative;text-align:right;text-overflow:clip;width:5rem}.required .deliverable-item-category:after{font-size:1rem;line-height:1.5rem;position:absolute;right:-.75rem;top:.5rem;--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity));--tw-content:"*";content:var(--tw-content)}.deliverable-item-doc,.deliverable-item-file{min-width:200px}.deliverable-item-avatar,.deliverable-item-doc,.deliverable-item-file{align-items:center;display:flex;gap:.25rem}.deliverable-item-info{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.deliverable-item-avatar+.deliverable-item-info{margin-left:-.5rem}.deliverable-item-doc-picker{width:14rem}.deliverable-item-rename{align-items:center;display:flex;gap:.5rem}.deliverable-item-rename .form-control{flex:1 1 auto;width:18rem}.deliverable-item .form-tip{line-height:28px;margin-top:-.25rem;padding-left:104px;width:100%}.scrollbar,:root{--scrollbar-size:10px;--scrollbar-opacity:.6;--scrollbar-bg:rgba(var(--color-inverse-rgb),.15);--scrollbar-inset:inset 0 0 0 1px rgba(var(--color-inverse-rgb),.05);--scrollbar-bar-bg:rgba(var(--color-inverse-rgb),.3);--scrollbar-hover-bg:rgba(var(--color-inverse-rgb),.4);--scrollbar-drag-bg:rgba(var(--color-inverse-rgb),.5);--scrollbar-radius:var(--radius-sm);--scrollbar-duration:.7s}.scrollbar{background:var(--scrollbar-bg);box-shadow:var(--scrollbar-shadow);opacity:var(--scrollbar-opacity);position:absolute;transition-duration:.15s;transition-duration:var(--scrollbar-duration);transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.scrollbar-hover .scrollbar{opacity:0}.scrollbar-hover:hover .scrollbar{opacity:var(--scrollbar-opacity)}.scrollbar.is-dragging,.scrollbar:hover{opacity:1!important}.scrollbar-bar{background:var(--scrollbar-bar-bg);border-radius:var(--scrollbar-radius);position:absolute}.scrollbar-bar:hover{background:var(--scrollbar-hover-bg)}.is-dragging>.scrollbar-bar{background:var(--scrollbar-drag-bg)}.is-horz>.scrollbar-bar{height:100%;z-index:20}.is-vert>.scrollbar-bar{width:100%;z-index:20}.affine-theme,.affine-theme [data-theme=dark],.affine-theme [data-theme=light]{--affine-brand-color:var(--color-primary-500);--affine-primary-color:var(--color-primary-500);--affine-text-primary-color:var(--color-fore)}.blocksuite-portal{position:absolute!important}.embed-card-modal-mask{z-index:12!important}.embed-card-modal-wrapper{z-index:13!important}.affine-code-block-container .line-number{opacity:.5}@-moz-document url-prefix(){.affine-code-block-container v-line{width:100%}}.embed-zui-iframe{border-radius:var(--radius-lg);border-width:1px}affine-bookmark .affine-block-component{border-width:0}.is-editor-empty.is-editing .affine-block-children-container>affine-paragraph:first-child .affine-paragraph-placeholder:not(.visible){display:block!important}database-datasource-note-renderer{display:none!important}.editor-is-exporting audio,.editor-is-exporting canvas,.editor-is-exporting embed,.editor-is-exporting iframe,.editor-is-exporting img,.editor-is-exporting object,.editor-is-exporting svg,.editor-is-exporting video{display:initial!important}body>.affine-modal{align-items:center;background-color:var(--modal-bg);bottom:0!important;display:flex;justify-content:center;left:0!important;position:fixed!important;right:0!important;top:0!important}body>.affine-modal>center-peek{left:auto;max-width:1200px;position:relative;top:auto;--tw-shadow:0 0 #0000!important;--tw-shadow-colored:0 0 #0000!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}body>.affine-modal affine-data-view-record-detail{border-radius:var(--radius);overflow:auto;--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);max-height:calc(100vh - 40px)}body>.affine-modal>center-peek>.close-modal{height:2rem;right:.75rem;top:.75rem;width:2rem;z-index:10}body>.affine-modal>center-peek>.close-modal>svg{height:1rem;width:1rem}.affine-database-column-stats{margin-left:0}.editor.is-readonly .database-header-bar+uni-lit,.editor.is-readonly .unsupported-content{display:none}.form-control .affine-theme,.form-group .affine-theme{border-radius:var(--form-control-radius);--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));outline-color:transparent;outline-style:solid;outline-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:var(--form-control-border);transition-duration:.15s;transition-property:outline,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);--affine-editor-width:initial;--affine-editor-bottom-padding:24px!important;--affine-editor-side-padding:16px!important;min-height:200px}.form-control .affine-page-viewport,.form-group .affine-page-viewport{overflow:visible}.dtable .toggle-icon{margin-top:0;opacity:.5;position:static!important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.doc-app{--doc-view-max-width:800px;--doc-view-padding:24px;--doc-view-side-width:240px;--affine-editor-side-padding:0}.doc-app{align-items:stretch;display:flex;flex-direction:column;min-height:120px}.doc-space-picker-menu .menu-item>.item-inner{padding-right:.25rem}.doc-app-search .form-control{border-radius:var(--radius-full)}.doc-app-search .input-control-prefix{cursor:pointer;opacity:.75}.doc-app-search.empty:not(.focus){transition-duration:.15s;transition-property:width;transition-timing-function:cubic-bezier(.4,0,.2,1);width:2rem}.doc-app-search.empty:not(.focus) .form-control{padding-left:.5rem;padding-right:.5rem;--tw-ring-color:transparent}.doc-app-search.empty:not(.focus) .form-control::-moz-placeholder{opacity:0}.doc-app-search.empty:not(.focus) .form-control::placeholder{opacity:0}.doc-app-search.empty:not(.focus) .form-control:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.doc-app-search:not(.empty) .form-control{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-300-rgb),var(--tw-ring-opacity))}.doc-app-header .divider{height:1rem!important;margin-left:.25rem!important;margin-right:.25rem!important}.doc-app .is-match-keys{--tw-bg-opacity:1;background-color:rgba(var(--color-warning-100-rgb),var(--tw-bg-opacity));font-weight:700;text-decoration-line:underline;text-underline-offset:2px}.doc-main .dtable-footer{border-bottom-width:1px;--tw-border-opacity:1;border-bottom-color:rgba(var(--color-border-rgb),var(--tw-border-opacity))}.doc-main.show-view>.doc-list{pointer-events:none;visibility:hidden;z-index:-10}.has-doc-app-fullscreen .doc-app-header,.has-doc-app-fullscreen .doc-sidebar,.has-doc-app-fullscreen>#header{display:none}.has-doc-app-fullscreen #mainContainer{max-width:none!important;padding:0!important;width:100%!important}.has-doc-app-fullscreen #docApp{height:calc(100vh - 12px)!important}.doc-app doc-title,.editor-is-exporting .doc-editor-title{display:none}.editor-is-exporting doc-title{display:block}.doc-tree .item-inner{cursor:pointer;padding-right:0;position:relative}.doc-tree .item-inner>.item-icon{flex:none;opacity:1}.doc-tree .item-inner .item-title{overflow:hidden;text-overflow:clip;white-space:nowrap}.doc-tree .item-inner.selected .item-title{font-weight:700}.doc-tree .item-inner>.toolbar{top:.25rem!important}.doc-tree .item-inner>.toolbar>.btn.with-popover-show,.doc-tree .list-heading-inner>.toolbar{opacity:1!important}.doc-tree .item-inner:hover>.toolbar{margin-top:0!important}.doc-tree .with-hover-actions>.item>.item-inner .item-actions{right:0}.doc-sidebar .sortable-ghost{border-radius:var(--radius-sm);z-index:10;--tw-bg-opacity:1;background-color:rgba(var(--color-warning-100-rgb),var(--tw-bg-opacity));opacity:.3;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-warning-600-rgb),var(--tw-ring-opacity))}.doc-tree [z-key=project-files]{border-top:1px solid rgba(var(--color-border-rgb),var(--tw-border-opacity));margin-top:.25rem;padding-top:.25rem}.doc-list-item-title{overflow:hidden;text-overflow:clip}.doc-view{scroll-padding-top:16px;scrollbar-gutter:stable both-edges}.doc-view-content{max-width:var(--doc-view-max-width);padding:var(--doc-view-padding)}.doc-files .item-title{overflow:hidden;white-space:nowrap}.doc-files .file-list-item{border-radius:var(--radius-lg);transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.doc-files .file-list-item:hover{background-color:rgba(var(--color-inverse-rgb),.05)}.doc-files .file-list-item .item-actions,.doc-files .file-list-item:hover .item-actions{margin-left:1rem;margin-top:0;position:relative}.doc-files .file-list-item .item-actions .btn{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity))}.doc-editor .affine-page-viewport{overflow:visible!important}.doc-editor .affine-page-root-block-container{padding:0 0 2rem!important}.doc-editor-keywords,.doc-editor-title{flex:none;max-width:100%;min-width:0}.doc-editor-keywords:hover .form-control{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.doc-editor-keywords .form-control:focus{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.doc-editor-control{z-index:2}.doc-view-sidebar{display:flex;flex-direction:column;max-height:calc(100% - 24px);overflow:visible;width:var(--doc-view-side-width)}.doc-view-sidebar-nav{--nav-item-padding:6px;--nav-item-color:var(--color-gray-500);--nav-active-bg:var(--color-primary-100);--nav-active-color:var(--color-fore);--nav-item-height:26px;--nav-divider-margin:8px;background-color:rgba(var(--color-surface-rgb),.2)}.doc-view-sidebar .datalist{--datalist-label-width:56px}.is-closed.doc-view-sidebar .doc-view-sidebar-content,.is-sidebar-closed .doc-view-sidebar-content{display:none}.is-closed.doc-view-sidebar,.is-sidebar-closed .doc-view-sidebar{--doc-view-side-width:0;opacity:0;transition-delay:1s;transition-duration:1s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.is-outline.doc-view-sidebar{--doc-view-side-width:260px}.doc-view:hover .doc-view-sidebar{opacity:1;transition-delay:0s}.is-closed>.doc-view-sidebar-container,.is-sidebar-closed .doc-view-sidebar-container{position:absolute;right:0;top:0}.doc-view-sidebar-container{background-color:rgba(var(--color-canvas-rgb),.8);min-height:0;--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.doc-outline .listitem{position:relative}.doc-outline .tree-toggle.is-empty:before{border-radius:var(--radius-full);height:.25rem;position:absolute;width:.25rem;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-300-rgb),var(--tw-bg-opacity));--tw-content:"";content:var(--tw-content)}.doc-outline .is-nested-root.no-nested-items{padding-left:.375rem}.doc-path-picker .picker-deselect-btn{display:none}.doc-path-picker-angle{margin-left:-.125rem;margin-right:-.125rem}.doc-path-picker,.doc-space-picker{outline:2px solid transparent!important;outline-offset:2px!important;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)!important}.dropmenu-btn{gap:.25rem;padding-left:.5rem;padding-right:.5rem}.dropmenu-btn>.text{max-width:180px;overflow:hidden}.dropmenu-btn>.is-leading{left:-.625rem;opacity:.6;position:absolute}.dropmenu-btn>.is-caret{align-items:center;background-color:rgba(var(--color-canvas-rgb),.2);border-radius:var(--radius);display:flex;height:1rem;justify-content:center;width:1rem}.dropmenu-nav{border-bottom-width:1px;margin-left:.75rem;margin-right:.75rem;margin-top:.25rem}.has-search .dropmenu-nav{margin-top:-.5rem}.dropmenu-nav>.nav-secondary{gap:.5rem}.dropmenu-nav>.nav-secondary>.nav-item>a{border-radius:var(--radius);padding-left:.5rem;padding-right:.5rem}.dropmenu-nav>.nav-secondary>.nav-item>a:after{bottom:-1px;left:1rem;opacity:0;right:1rem}.dropmenu-nav>.nav-secondary>.nav-item>.active:after{left:.5rem;opacity:1;right:.5rem;transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dropmenu-title{font-size:.75rem;font-weight:700;line-height:1rem;margin-bottom:-.5rem;padding:.75rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.dropmenu-list{min-height:0;overflow-x:hidden;overflow-y:auto;padding:.5rem .75rem}.dropmenu.loading>*{opacity:0}.dropmenu-item .tree-item-inner{border-radius:var(--radius);cursor:pointer;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dropmenu-item.is-item.active>.tree-item-inner{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.tree-item-inner.is-link:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.tree-item-inner.is-link:hover .item-content,.tree-item-inner.is-link:hover .item-trailing-icon,.tree-item-inner.is-link:hover .label{color:inherit}.tree-item-inner.is-toggle:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.dropmenu-item+.tree-item{margin-top:.125rem}.dropmenu-item .is-match{font-weight:700;text-decoration-line:underline}.dropmenu-item .item-title,.dropmenu-item .label{overflow:hidden;white-space:nowrap}.dropmenu-item .item-content{padding-left:.375rem;padding-right:.375rem}.dropmenu-item *+.item-content{padding-left:0}.tree-item-inner.is-toggle .item-title{opacity:.6}.tree-item-inner.is-toggle:hover .item-title{opacity:1}.dropmenu-item-check{align-items:center;display:flex;flex:1 1 auto;justify-content:flex-end;padding-right:.5rem}.dropmenu-item .nested-toggle-icon.is-empty{width:.25rem}.dropmenu-item .item-icon{margin-right:-.25rem}.card-list{--list-gap:.625rem;--list-count-per-row:1}.card-list,.card-list-item{padding:calc(var(--list-gap)/2)}.card-list-item{width:calc(100%/var(--list-count-per-row))}.card-grid{display:flex;flex-wrap:wrap}.card-grid .card{height:100%}:root{--form-control-border:var(--color-border-strong)}.checkbox-primary.disabled,.checkbox-primary.disabled>label,.checkbox-primary>input[type=checkbox]:disabled,.checkbox-primary>input[type=checkbox]:disabled+label,.radio-primary.disabled,.radio-primary.disabled>label,.radio-primary>input[type=radio],.radio-primary>input[type=radio]:disabled+label{filter:none!important}.checkbox-primary.disabled>label,.radio-primary.disabled>label{opacity:1}.checkbox-primary.disabled>label:before,.radio-primary.disabled>label:before{background-color:rgba(var(--color-inverse-rgb),.05);opacity:.5}.form-actions{gap:1rem;justify-content:center}.form-actions .btn{min-width:96px}.form-control-static{min-height:32px;padding-bottom:.375rem;padding-top:.375rem}:root{--zt-panel-form-max-width:1000px}.size-sm{--zt-panel-form-max-width:800px}.size-lg{--zt-panel-form-max-width:1200px}.panel-body>.container,.panel-heading>.container{max-width:var(--panel-container-width);min-width:0;padding-left:var(--panel-container-padding);padding-right:var(--panel-container-padding)}.panel-heading>.container{align-items:center;display:flex;flex-direction:row;flex-wrap:nowrap;gap:1rem;justify-content:space-between;min-height:48px}.panel-form{border-radius:var(--radius-md);margin-bottom:1rem;margin-left:auto;margin-right:auto;max-width:var(--zt-panel-form-max-width);min-width:var(--zt-panel-form-min-width);overflow:visible;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding-bottom:1rem;padding-left:1rem;padding-right:1rem;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.panel-form .form-actions{background-color:rgba(var(--color-canvas-rgb),.8);bottom:0;padding-bottom:1rem;padding-top:1rem;position:sticky;z-index:3;--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.panel-form .form-grid{margin-left:calc(0px - var(--form-grid-gap-y-half));margin-right:calc(0px - var(--form-grid-gap-y-half));padding-bottom:0}.panel-form-toolbar{padding-left:var(--form-grid-gap-x-half);padding-right:var(--form-grid-gap-x-half);width:100%}.panel-form-toolbar>.toolbar{gap:1rem;padding-bottom:.75rem;padding-top:.75rem}.panel-form-divider{margin-bottom:.75rem;margin-top:1rem;padding-left:var(--form-grid-gap-x-half);padding-right:var(--form-grid-gap-x-half);width:100%}.panel-form-divider:before{background-color:rgba(var(--color-border-rgb),.7);display:block;height:1px;--tw-content:"";content:var(--tw-content)}.is-full .btn-full-form,.is-lite .btn-lite-form{z-index:1;--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-300-rgb),var(--tw-ring-opacity))}.btn-toggle-fold:after{content:attr(data-expand-text)}.show-fold-items .btn-toggle-fold:after{content:attr(data-collapse-text)}.is-foldable,.is-full .full\:hidden,.is-full .lite\:visible,.is-full .panel-form-divider,.is-full .panel-form-toolbar,.is-lite .full\:visible,.is-lite .lite\:hidden,.no-foldable-items .btn-toggle-fold{display:none}.is-foldable.is-pinned,.is-full .full\:visible,.is-full .is-foldable,.is-full .lite\:hidden,.is-lite .full\:hidden,.is-lite .lite\:visible,.show-fold-items .is-foldable{display:block}.is-full .full\:w-1\/2,.is-lite .lite\:w-1\/2{width:50%}.is-full .full\:w-1\/3,.is-lite .lite\:w-1\/3{width:33.333333%}.is-full .full\:w-2\/3,.is-lite .lite\:w-2\/3{width:66.666667%}.is-full .full\:w-1\/4,.is-lite .lite\:w-1\/4{width:25%}.is-full .full\:w-2\/4,.is-lite .lite\:w-2\/4{width:50%}.is-full .full\:w-3\/4,.is-lite .lite\:w-3\/4{width:75%}.is-full .full\:w-1\/5,.is-lite .lite\:w-1\/5{width:20%}.is-full .full\:w-2\/5,.is-lite .lite\:w-2\/5{width:40%}.is-full .full\:w-3\/5,.is-lite .lite\:w-3\/5{width:60%}.is-full .full\:w-4\/5,.is-lite .lite\:w-4\/5{width:80%}.is-full .full\:w-1\/6,.is-lite .lite\:w-1\/6{width:16.666667%}.is-full .full\:w-2\/6,.is-lite .lite\:w-2\/6{width:33.333333%}.is-full .full\:w-3\/6,.is-lite .lite\:w-3\/6{width:50%}.is-full .full\:w-4\/6,.is-lite .lite\:w-4\/6{width:66.666667%}.is-full .full\:w-5\/6,.is-lite .lite\:w-5\/6{width:83.333333%}.is-full .full\:w-full,.is-lite .lite\:w-full{width:100%}.page-form{--panel-container-width:960px;--panel-container-padding:20px;--zt-panel-form-max-width:1200px;--zt-panel-form-min-width:1040px;padding-left:0;padding-right:0;--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.page-form .panel-heading{border-bottom-width:1px;--tw-border-opacity:0.7;padding:0}.page-form .panel-title{font-size:1rem;line-height:1.5rem}@media (max-width:1240px){.page-form{--zt-panel-form-max-width:1100px}}@media (max-width:1110px){.page-form{--zt-panel-form-max-width:1040px}}.modal-body>.page-form{margin:-1.5rem -2rem!important;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.modal-body>.page-form>.panel-heading{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius);position:sticky;top:-1.25rem;z-index:2;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding-bottom:.375rem;padding-top:.375rem}.modal-body>.panel-form .form-actions{bottom:-1.5rem!important;padding-bottom:1.5rem;padding-top:1.5rem}.dropdown.popover{display:flex;flex-direction:column;position:absolute;z-index:1200}.dropdown.show{display:flex}.dropdown-menu{display:none;--menu-min-width:7rem;--menu-max-width:20rem}.dropdown-menu.show,.menu-wrapper>.dropdown-menu,.show>.dropdown-menu{display:block}.dropdown>.dropdown-menu,.menu-wrapper .dropdown-menu{position:relative}.popup .popup.search-menu{background-color:var(--menu-bg)}.show>.menu-wrapper{display:flex}.dropdown>.menu-wrapper{height:100%}.dropdown>.menu-wrapper .menu-wrapper{position:absolute}.dropdown>.menu-wrapper.is-tree .menu-wrapper{position:relative}.is-contextmenu .is-nested-show>a:not(:hover){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity))}.is-contextmenu .menu-item.is-nested>.item-inner>.nested-toggle-icon{position:absolute;right:.25rem;top:.375rem}.is-contextmenu .menu-nested .menu-item>.item-inner{padding-left:.5rem;padding-right:1.25rem}.is-contextmenu .menu-nested .menu-item>.item-inner>.item-content{overflow:hidden}.dropdown>.arrow{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.global-search-panel li:not(.order-first):hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.global-search-panel li a{width:100%}.global-search-panel li{cursor:pointer}.history-panel>.panel-heading+.panel-body{margin-top:-.75rem}.history-panel-action{position:relative}.history-panel-action:before{border-left-width:1px;bottom:-.375rem;left:.5rem;position:absolute;top:22px;--tw-border-opacity:1;border-color:rgba(var(--color-border-rgb),var(--tw-border-opacity));--tw-content:"";content:var(--tw-content)}.col-reverse>.history-panel-action:first-child:before,.col>.history-panel-action:last-child:before{display:none}.history-panel-action>.item-inner{padding-left:1.5rem}.history-panel-action>.item-inner>.avatar{left:0;position:absolute;top:.375rem}.history-panel-action .file-list-item .item-content{flex:none}.history-panel-action blockquote{margin-top:.25rem;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding:.25rem .25rem .25rem .5rem}.history-panel-action blockquote.original{display:none}.img-cutter{background:var(--color-gray-100);border:1px solid #ddd;margin-bottom:20px;padding:10px}.img-cutter .canvas{margin:0 auto;max-width:100%;min-width:50px;position:relative}.img-cutter .cover{bottom:0;left:0;position:absolute;right:0;top:0;z-index:1}.img-cutter .controller{background:none;border:1px dashed hsla(0,0%,100%,.7);cursor:move;position:absolute;z-index:5}.img-cutter .control{background:#000;background:rgba(0,0,0,.6);border:1px solid hsla(0,0%,100%,.6);height:6px;position:absolute;width:6px}.img-cutter .control[data-type=left]{cursor:w-resize;left:-4px;margin-top:-3px;top:50%}.img-cutter .control[data-type=top]{cursor:n-resize;left:50%;margin-left:-3px;top:-4px}.img-cutter .control[data-type=right]{cursor:e-resize;margin-top:-3px;right:-4px;top:50%}.img-cutter .control[data-type=bottom]{bottom:-4px;cursor:s-resize;left:50%;margin-left:-3px}.img-cutter .control[data-type=top-left]{cursor:nw-resize;left:-4px;top:-4px}.img-cutter .control[data-type=top-right]{cursor:ne-resize;right:-4px;top:-4px}.img-cutter .control[data-type=bottom-left]{bottom:-4px;cursor:sw-resize;left:-4px}.img-cutter .control[data-type=bottom-right]{bottom:-4px;cursor:se-resize;right:-4px}.img-cutter .cliper{bottom:0;left:0;position:absolute;right:0;top:0;z-index:2}.messager-lite{border-radius:var(--radius-lg);min-width:160px;--tw-bg-opacity:1!important;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))!important;padding:1rem 1.5rem;--tw-text-opacity:1!important;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))!important;--skin-ring:transparent!important;--skin-text:inherit!important;--skin-color:var(--color-gray-500)}.messager-lite .alert-icon{color:var(--skin-color);font-size:1.5rem;line-height:2rem}.messager-lite .alert-text{font-size:.875rem;font-weight:700;line-height:1.3rem}.messager-lite .toolbar{gap:.5rem;margin-left:2rem}.messager-lite .alert-content+.alert-close{margin-left:1.5rem}.messager-lite .toolbar .btn.ghost{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.modal-reconfirm .modal-body{font-size:14px;font-weight:700;padding:24px 32px}.modal-reconfirm .modal-footer{justify-content:center;padding:24px}.picker-deselect-btn{opacity:.6;transition-duration:.15s;transition-property:opacity,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.picker-multi-selection{cursor:pointer;padding-right:.5rem;position:relative}.picker-multi-selection .picker-deselect-btn{bottom:0;left:0;position:absolute;right:0;top:0;--tw-scale-x:0;--tw-scale-y:0;background-color:rgba(var(--color-surface-rgb),.8);opacity:0}.picker-deselect-btn:hover,.picker-multi-selection .picker-deselect-btn,.picker-multi-selection:hover .picker-deselect-btn{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.picker-deselect-btn:hover,.picker-multi-selection:hover .picker-deselect-btn{--tw-scale-x:1;--tw-scale-y:1;opacity:1;--state-color:rgba(var(--color-surface-rgb),.9)}.pick-pri{flex-direction:row;justify-content:flex-start;position:relative}.pick-pri,.pick-pri>.text{align-items:center;display:flex}.pick-pri>.text{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap}.pick-pri .placeholder{--tw-text-opacity:1;color:rgba(var(--color-placeholder-rgb),var(--tw-text-opacity))}.pick-pri-list>.btn{justify-content:flex-start}.disabled.pick-pri,.disabled.pick-pri>*{filter:none}.search-form{--gutter-width:12px;padding-bottom:.5rem}.search-form-container{border-radius:var(--radius);min-height:116px;position:relative;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity))}.is-simple .search-form-container{min-height:56px}.search-form-field td{padding:.375rem}.search-form-field td.is-andOr,.search-form-field td.is-operator{width:5rem}.search-form-field td.is-condition{width:7rem}.search-form-field td.is-operator{width:5rem}[lang=en] .search-form-field td.is-operator{width:6rem}.search-form .sidebar-right.is-collapsed{margin-right:-.375rem}.is-simple .search-form-wrapper{display:flex}.is-simple .search-form-wrapper>.row{flex:1 1 auto}.is-simple .search-form-wrapper>.toolbar{flex:none;margin-top:0}.zinbar [data-hint]{position:relative}.zinbar [data-hint]:after{background-color:rgba(var(--color-inverse-rgb),var(--tw-bg-opacity));border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg);bottom:100%;display:block;pointer-events:none;position:absolute;right:0;white-space:nowrap;z-index:50;--tw-bg-opacity:0.9;font-size:.75rem;line-height:1rem;padding:.125rem .25rem;--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity));opacity:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);--tw-content:attr(data-hint);content:var(--tw-content)}.zinbar [data-hint]:hover:after{opacity:1}.zin-perf-btn-list .text-danger{color:var(--color-danger-400)}.zinbar .state{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.zinbar .state:active{--tw-scale-x:1.05;--tw-scale-y:1.05}.zinbar .state:active,.zinbar.collapse{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.zinbar.collapse{--tw-translate-x:100%}.zinbar.collapse>div{pointer-events:none}.zinbar{--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transition-duration:.7s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}body[z-perf=danger]:before,body[z-perf=warning]:before{bottom:0;left:0;pointer-events:none;position:fixed;right:0;top:0;z-index:9990;--tw-border-opacity:1;border-color:rgba(var(--color-warning-600-rgb),var(--tw-border-opacity));font-size:.75rem;line-height:1rem;--tw-content:"";border-style:inset;border-width:12px 8px 8px;content:var(--tw-content)}body[z-perf=danger]:before{--tw-border-opacity:1;border-color:rgba(var(--color-danger-600-rgb),var(--tw-border-opacity))}body[z-perf=danger]:after,body[z-perf=warning]:after{font-size:.75rem;font-weight:700;left:0;line-height:1rem;line-height:1;pointer-events:none;position:fixed;right:0;text-align:center;top:0;z-index:9991;--tw-text-opacity:1;color:rgba(var(--color-white-rgb),var(--tw-text-opacity));--tw-content:attr(z-perf-message);content:var(--tw-content)}.card{border-radius:var(--radius);min-height:28px;position:relative;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05;transition-duration:.15s;transition-property:box-shadow,border,color,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1)}.card:hover{--tw-shadow:0 2px 6px -1px rgba(0,0,0,.2),0 1px 4px -2px rgba(0,0,0,.15);--tw-shadow-colored:0 2px 6px -1px var(--tw-shadow-color),0 1px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.card-content,.card-footer,.card-header,.card-heading{padding:.25rem .5rem}.card-heading{align-items:center;display:flex;gap:.5rem}.card-icon{opacity:.5}.card-header{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity))}.card-content{display:flex;flex-direction:column;gap:.25rem}.card-actions{position:absolute;right:.125rem;top:.125rem}.card-actions+.card-heading{padding-right:1.75rem}.card-subtitle{font-size:.75rem;line-height:1rem;--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.card.selected{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-400-rgb),var(--tw-ring-opacity))}.card-list{--list-gap:.625rem;--list-count-per-row:1}.card-list,.card-list-item{padding:calc(var(--list-gap)/2)}.card-list-item{width:calc(100%/var(--list-count-per-row))}.card-grid{display:flex;flex-wrap:wrap}.card-grid .card{height:100%}.contextmenu{display:none}.contextmenu.show{display:block}.contextmenu .popup .popup,.contextmenu.popup{position:absolute}.more,.more-vert{margin:.5rem;position:relative}.more,.more-vert,.more-vert:after,.more-vert:before,.more:after,.more:before{background-color:currentColor;border-radius:var(--radius-full);height:.125rem;width:.125rem}.more-vert:after,.more-vert:before,.more:after,.more:before{display:block;left:-5px;position:absolute;top:0;--tw-content:"";content:var(--tw-content)}.more-vert:after,.more:after{left:5px}.more-vert{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dashboard-blocks{position:relative}.dashboard-block-cell{position:absolute;transition-duration:.15s;transition-property:left,top;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dashboard-block{border-radius:var(--radius);bottom:.5rem;left:.5rem;position:absolute;right:.5rem;top:.5rem;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dashboard-block.is-dragging{opacity:0;z-index:1600}.dashboard-block-header{align-items:center;border-top-left-radius:var(--radius);border-top-right-radius:var(--radius);display:flex;flex-direction:row;justify-content:space-between;left:0;padding:.75rem;pointer-events:none;position:absolute;right:0;top:0;z-index:10}.dashboard-block-header>*{pointer-events:auto}.dashboard-block-title{font-size:.875rem;font-weight:700;line-height:1.3rem}.dashboard-block-body{bottom:0;left:0;position:absolute;right:0;top:0}.dashboard-block-body>.panel{display:flex;flex-direction:column;height:100%;width:100%;--tw-shadow:0px 6px 16px rgba(202,215,235,.25)}.dashboard-block-body .panel-heading{cursor:move;flex:none}.dashboard-block-body .panel-body{flex:1 1 auto;overflow-y:auto}.has-more-menu>.dashboard-block-body .panel-heading{padding-right:3rem}.dashboard-block-body .panel-title{font-size:.875rem;height:2rem;line-height:1.3rem}.dashboard-block-actions .btn{opacity:.6}.dashboard-block-actions .btn:hover{opacity:1}.dashboard-drop-shadow{position:absolute;transition-duration:.15s;transition-property:left,top;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dashboard-drop-shadow:before{background-color:rgba(var(--color-inverse-rgb),.05);border-radius:var(--radius);bottom:.5rem;left:.5rem;position:absolute;right:.5rem;top:.5rem;--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-content:"";content:var(--tw-content)}:root{--dtable-checked-bg:var(--color-warning-50);--dtable-checked-bg-hover:var(--color-warning-100);--dtable-checked-border:var(--color-border-strong)}.dtable-cell.is-checked,.dtable-striped .dtable-cell.is-odd-row.is-checked{background-color:var(--dtable-checked-bg)}.checkbox-primary.dtable-checkbox{margin-right:-.375rem}.dtable-checkbox{order:-5}.dtable-hover-col .dtable-cell.is-hover-col.is-checked,.dtable-hover-row .dtable-cell.is-hover-row.is-checked{background-color:var(--dtable-checked-bg-hover)}.dtable-cell.is-checked{--dtable-border-color:var(--dtable-checked-border)}.dtable-check-info{flex-shrink:1;margin-right:.5rem;overflow:hidden;white-space:nowrap}:root{--toggle-icon-size:calc(var(--font-size-root)*3/4 + 1px)}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-color:currentColor;border-width:1px;display:block;opacity:.5;position:relative}.toggle-icon-collapse:hover,.toggle-icon-expand:hover,.toggle-icon:hover{opacity:.9}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-radius:inherit;height:var(--toggle-icon-size);width:var(--toggle-icon-size)}.is-collapsed .toggle-icon:after,.is-collapsed .toggle-icon:before,.is-expanded .toggle-icon:before,.toggle-icon-collapse:after,.toggle-icon-collapse:before,.toggle-icon-expand:before{background-color:currentColor;content:" ";display:block;height:1px;left:2px;position:absolute;right:2px;top:calc((var(--toggle-icon-size) - 3px)/2)}.is-collapsed .toggle-icon:after,.toggle-icon-collapse:after{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:root{--dtable-nt-size:calc(var(--font-size-root)*3/4 + 1px)}.dtable-nested-indent{flex:none;margin-right:-.25rem;order:-100}.dtable-nested-toggle{align-items:center;border-radius:var(--radius-sm);display:flex;flex:none;height:1.25rem;justify-content:center;margin-left:-.25rem;order:-6;width:1.25rem}.dtable-nested-toggle.is-no-child{margin-right:-.25rem;opacity:0;pointer-events:none}.dtable-child-label{order:-5}.dtable-header-group{align-items:center;background:var(--dtable-header-bg);cursor:default;display:flex;justify-content:center;left:0;position:absolute;top:1px;z-index:30}.dtable-bordered .dtable-header-group{border-bottom:1px solid var(--dtable-border-color);border-left:1px solid var(--dtable-border-color)}.dtable-header-as-group{contain:style;content-visibility:visible;overflow:visible!important}.dtable-sorting{cursor:move}.dtable-cell.is-sorting-from{background-color:var(--dtable-bg);z-index:20}.dtable-cell.is-sorting-from:before{border-top-width:1px}.dtable-sorting .dtable-cell.is-sorting-after{--tw-translate-y:-100%}.dtable-sorting .dtable-cell.is-sorting-after,.dtable-sorting .dtable-cell.is-sorting-before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dtable-sorting .dtable-cell.is-sorting-before{--tw-translate-y:100%}.dtable-cell.is-sorting-before:before,.dtable-cell.is-sorting-from:before{border-bottom-width:1px;border-top-width:1px}.dtable{--dtable-bg:var(--color-canvas);--dtable-striped-bg:var(--color-gray-50);--dtable-hover-bg:rgba(var(--color-primary-500-rgb),.05);--dtable-header-bg:var(--color-surface);--dtable-footer-bg:var(--color-surface);--dtable-border-color:var(--color-border);--dtable-sorter-size:0.3125rem}.dtable{position:relative;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.dtable.no-animation *{transition-property:none!important}.dtable-block{overflow:hidden;position:absolute;width:100%}.dtable-header{background-color:var(--dtable-header-bg);border-top-left-radius:inherit;border-top-right-radius:inherit}.dtable-body{overflow:hidden}.dtable-cells{background-color:var(--dtable-bg);height:100%;position:absolute;z-index:0}.dtable-cells-container{height:100%;position:absolute;width:100%}.dtable-header .dtable-cells{background-color:var(--dtable-header-bg)}.dtable-cells.dtable-fixed-left,.dtable-cells.dtable-fixed-right{z-index:10}.dtable-cell{position:absolute;transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-cell:after,.dtable-cell:before{bottom:0;content:"";left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:-1px;z-index:2}.dtable-cell:before{border-bottom-width:1px;border-color:var(--dtable-border-color);opacity:1}.dtable-header-cell{align-items:center;display:flex;font-weight:700}.dtable-header-cell:after,.dtable-header-cell:before{top:0}.dtable-cell-content{align-items:center;display:flex;gap:.25rem;height:100%;overflow:hidden;padding-left:.75rem;padding-right:.75rem;position:relative;white-space:nowrap;width:100%;z-index:5}.dtable-body .dtable-cell.is-last-row:before{border-bottom-width:0}.dtable-footer{align-items:center;background-color:var(--dtable-footer-bg);border-bottom-left-radius:inherit;border-bottom-right-radius:inherit;border-color:var(--dtable-border-color);border-top-width:1px;display:flex;padding-left:.75rem;padding-right:.75rem;position:absolute;width:100%;z-index:10}.dtable-empty-tip{align-items:center;display:flex;height:100%;justify-content:center}.dtable .scrollbar{z-index:20}.dtable-header{transition-duration:1s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-scrolled-down .dtable-header{border-bottom-color:rgba(var(--color-inverse-rgb),.15);border-bottom-width:1px}.dtable-has-scroll-y:not(.dtable-scrolled-bottom) .dtable-footer{border-top-color:rgba(var(--color-inverse-rgb),.15);border-top-width:1px}.dtable-scroll-shadow{background-image:linear-gradient(90deg,rgba(0,0,0,.03),transparent),linear-gradient(90deg,rgba(0,0,0,.03),transparent 50%);opacity:0;pointer-events:none;position:absolute;top:0;transition-duration:1s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);width:8px;z-index:20}.dtable:hover .dtable-scroll-shadow{opacity:1}.dtable-scroll-shadow.is-right{margin-left:-7px;--tw-rotate:180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.dtable-scroll-shadow.is-left,.dtable-scrolled-end .dtable-scroll-shadow.is-right{visibility:hidden}.dtable-scroll-shadow.is-right,.dtable-scrolled-right .dtable-scroll-shadow.is-left{visibility:visible}.scrollbar-hover:hover .scrollbar{opacity:0}.scrollbar-hover .dtable-body:hover~.scrollbar{opacity:var(--scrollbar-opacity)}.dtable-sort{display:inline-flex;height:calc(var(--dtable-sorter-size)*12/5);margin-left:.25rem;opacity:.8;position:relative}.dtable-cell:hover .dtable-sort{opacity:1}.dtable-sort:after,.dtable-sort:before{border-color:transparent;border-style:solid;height:0;left:0;opacity:.4;position:absolute;width:0;--tw-content:"";border-width:var(--dtable-sorter-size);content:var(--tw-content)}.dtable-sort:before{border-bottom-color:currentColor;border-top-width:0;top:0}.dtable-sort:after{border-bottom-width:0;border-top-color:currentColor;bottom:0}.dtable-sort.dtable-sort-asc:before,.dtable-sort.dtable-sort-desc:after{opacity:.9}.dtable-sort-link{align-items:center;cursor:pointer;display:inline-flex}.dtable-cells.dtable-fixed-left:before,.dtable-cells.dtable-fixed-right:before{border-color:var(--dtable-border-color);content:"";height:100%;pointer-events:none;position:absolute;width:100%;z-index:5}.dtable-cells.dtable-fixed-left:before{border-right-width:1px;right:-1px}.dtable-cells.dtable-fixed-right:before{border-left-width:1px;left:0}.dtable-bordered:before{border-color:var(--dtable-border-color);border-radius:inherit;border-width:1px;bottom:0;content:"";display:block;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:15}.dtable-bordered .dtable-cell:before{border-width:1px;right:-1px}.dtable-cell.has-border-left:before{border-left-width:1px}.dtable-cell.has-border-right:before{border-right-width:1px;right:-1px}.dtable-striped .dtable-cell.is-odd-row{background-color:var(--dtable-striped-bg)}.dtable-hover-cell .dtable-cell:hover:after,.dtable-hover-col .dtable-cell.is-hover-col:before,.dtable-hover-row .dtable-body .dtable-cell.is-hover-row:before{background-color:var(--dtable-hover-bg)}.kanban,.kanban-list{--kanban-lane-name-width:20px;--kanban-col-width:280px;--kanban-cols-gap:8px;--kanban-lanes-gap:8px;--kanban-header-height:32px;--kanban-lane-height:auto;--kanban-lane-color:var(--color-primary-500);--kanban-link-color:var(--color-secondary-600)}.kanban{align-items:flex-start;display:flex;flex-direction:column;min-width:-moz-fit-content;min-width:fit-content;position:relative}.kanban-header{display:flex;flex-direction:row;height:var(--kanban-header-height)}.kanban.has-sub-cols .kanban-header{height:calc(var(--kanban-header-height)*2)}.kanban-header-lane-name{background-color:rgba(var(--color-fore-rgb),.05);flex:none;width:var(--kanban-lane-name-width)}.kanban-header-cols,.kanban-header-sub-cols{display:flex;flex:1 1 0%;flex-direction:row;gap:var(--kanban-cols-gap)}.kanban-header-sub-cols{border-top-width:2px;--tw-border-opacity:1;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity))}.kanban-header-col{align-items:center;border-bottom-width:1px;display:flex;flex:1 1 0%;flex-direction:column;height:100%;width:var(--kanban-col-width)}.kanban-header-col.has-subs{width:auto}.kanban-header-col-wrapper{align-items:center;display:flex;flex:1 1 0%;flex-direction:row;position:relative;width:100%;--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));padding-left:3.5rem;padding-right:3.5rem}.kanban-header-col-wrapper.is-align-left{justify-content:flex-start;padding-left:.5rem}.kanban-header-col-wrapper.is-align-left>.kanban-header-title{justify-content:flex-start}.kanban-header-title{align-items:center;display:flex;flex:1 1 auto;flex-direction:row;justify-content:center;overflow:hidden}.kanban-header-title>.as-title{color:var(--kanban-col-color);font-weight:700;overflow:hidden;white-space:nowrap}.kanban-header-col-actions{bottom:.25rem;position:absolute;right:.25rem;top:.25rem}.kanban-header-col-actions>.btn{opacity:.6}.kanban-header-col-actions>.btn:hover{opacity:1}.kanban-body{display:flex;flex-direction:column;gap:var(--kanban-lanes-gap)}.kanban-lane{display:flex;flex-direction:row;height:var(--kanban-lane-height);min-height:96px}.kanban-lane-name{align-items:center;background-color:var(--kanban-lane-color);display:flex;justify-content:center;width:var(--kanban-lane-name-width);--tw-text-opacity:1;color:rgba(var(--color-white-rgb),var(--tw-text-opacity));writing-mode:vertical-rl}.kanban-lane-actions,.kanban-lane-name{flex:none;position:relative}.kanban-lane.is-first .kanban-lane-actions{margin-top:calc(4px - var(--kanban-header-height))}.has-sub-cols .kanban-lane.is-first .kanban-lane-actions{margin-top:calc(4px - var(--kanban-header-height)*2)}.kanban-lane-actions>.btn.square{width:var(--kanban-lane-name-width)}.kanban-lane-title{align-items:center;display:flex;flex:1 1 auto;justify-content:center;overflow:hidden;white-space:nowrap}.kanban-lane-cols{display:flex;flex-direction:row;gap:var(--kanban-cols-gap)}.kanban-lane-col{background-color:rgba(var(--color-inverse-rgb),.05);display:flex;flex-direction:column;height:100%;width:var(--kanban-col-width)}.kanban-header-col,.kanban-lane-col{margin-left:calc(var(--kanban-col-gap-left) - var(--kanban-cols-gap));margin-right:calc(var(--kanban-col-gap-right) - var(--kanban-cols-gap))}.kanban-col-content{position:relative;z-index:5}.kanban-lane.is-first>.kanban-lane-name:before{background-color:var(--kanban-lane-color);bottom:100%;display:block;height:var(--kanban-header-height);left:0;position:absolute;right:0;--tw-content:"";content:var(--tw-content)}.kanban.has-sub-cols .kanban-lane.is-first>.kanban-lane-name:before{height:calc(var(--kanban-header-height)*2)}.kanban-lane{margin-bottom:calc(var(--kanban-col-gap-bottom) - var(--kanban-lanes-gap));margin-top:calc(var(--kanban-col-gap-top) - var(--kanban-lanes-gap))}.kanban-items{flex:1 1 auto;overflow:auto;scrollbar-gutter:both-edges stable}.kanban-lane.is-auto-height .kanban-items{scrollbar-gutter:auto}.kanban-item{cursor:default}.kanban-item .card-actions{z-index:5}.kanban-heading{width:100%}.kanban-heading .listitem{height:2.25rem}.kanban-heading .item-title{font-weight:700}.kanban.has-dragging{cursor:move}.kanban-item.is-dragging{cursor:move;opacity:.1}.kanban-sticky .kanban-header{position:sticky;top:0;z-index:10;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.kanban-sticky .kanban-header.is-pinned{border-bottom-color:rgba(var(--color-inverse-rgb),.15);border-bottom-width:1px;z-index:20;--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.kanban-sticky .kanban-lane-name{left:0;position:sticky;z-index:21}.kanban-region{border-radius:var(--radius);min-width:-moz-fit-content;min-width:fit-content;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));padding:.75rem;--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.kanban-region>.kanban+.kanban{margin-top:.75rem}.kanban-region.has-heading{padding-top:0}.kanban-heading>.listitem{left:.75rem;position:sticky;width:calc(var(--kanban-list-width) - 24px)}.kanban-list{display:flex;flex-direction:column;gap:.75rem;height:100vh;overflow:auto;position:relative;scrollbar-gutter:stable}.kanban-list.is-moving{cursor:grabbing}.kanban-items.is-dropping{position:relative}.kanban-item.is-dropping{position:relative;transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.kanban-item.is-dropping:after,.kanban-items.is-dropping>.card-list:after{background-color:rgba(var(--color-warning-500-rgb),.5);border-radius:var(--radius-full);display:block;height:.25rem;--tw-content:"";content:var(--tw-content)}.kanban-item.is-dropping:after{left:.25rem;position:absolute;right:.25rem;top:-.25rem}.kanban-item.is-dropping[z-drop-side=before]{--tw-translate-y:0.25rem}.kanban-item.is-dropping[z-drop-side=after],.kanban-item.is-dropping[z-drop-side=before]{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-item.is-dropping[z-drop-side=after]{--tw-translate-y:-0.25rem}.kanban-item.is-dropping[z-drop-side=after]:after{bottom:-.25rem;top:auto}.kanban-links{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:5}.kanban-list>.kanban-links{overflow:visible;z-index:11}.kanban-link{align-items:center;color:var(--kanban-link-color);display:flex;justify-content:center;position:absolute}.kanban-link>svg{position:absolute}.kanban-link-text{border-radius:var(--radius);height:1em;line-height:1;padding-left:.125rem;padding-right:.125rem;pointer-events:auto;position:relative;text-align:center;white-space:nowrap}.kanban-link-start-point{height:.5rem;width:.5rem;--tw-translate-x:-0.25rem;--tw-translate-y:-0.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-link-start-point,.kanban-link-start-point:before{background-color:currentColor;border-radius:var(--radius-full);position:absolute}.kanban-link-start-point:before{bottom:-.25rem;display:block;left:-.25rem;opacity:.2;right:-.25rem;top:-.25rem;--tw-content:"";content:var(--tw-content)}.kanban-link path{pointer-events:auto}.kanban-link path+path{opacity:.6}.kanban-link.is-hover path+path{opacity:1;stroke-width:calc(var(--kanban-link-weight)*1.5)}.kanban-link-delete-btn{pointer-events:auto;--tw-scale-x:.75;--tw-scale-y:.75;opacity:0;transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.is-hover .kanban-link-delete-btn,.kanban-link-delete-btn{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.is-hover .kanban-link-delete-btn{--tw-scale-x:1;--tw-scale-y:1;opacity:1}.is-adding-link{cursor:crosshair;-webkit-user-select:none;-moz-user-select:none;user-select:none}.kanban-link-editor{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:20}.kanban-link-editor-from,.kanban-link-editor-to{border-radius:var(--radius);--tw-shadow-color:rgb(var(--color-primary-500-rgb));--tw-shadow:var(--tw-shadow-colored);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-500-rgb),var(--tw-ring-opacity))}.kanban-link-editor-from,.kanban-link-editor-point,.kanban-link-editor-to{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);position:absolute}.kanban-link-editor-point{height:.5rem;pointer-events:auto;width:.5rem;--tw-translate-x:-0.25rem;--tw-translate-y:-0.25rem;border-radius:var(--radius-full);cursor:move;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));opacity:.5;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgba(var(--color-primary-500-rgb),0.1);transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.kanban-link-editor-point.is-left{left:0;top:50%}.kanban-link-editor-point.is-right{right:0;top:50%;--tw-translate-x:0.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-link-editor-point.is-top{left:50%;top:0}.kanban-link-editor-point.is-bottom{bottom:0;left:50%;--tw-translate-y:0.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.kanban-link-editor-point:hover{opacity:1;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-primary-500-rgb),0.5)}.tab-pane{display:none}.tab-pane.active{display:block}.has-sorting-col{cursor:move;--dtable-sorting-col-color:var(--color-primary-300);--dtable-hover-bg:transparent}.has-sorting-col .dtable-col-splitter{display:none}.dtable-cell.is-sorting-col-move{transition-duration:.15s;transition-property:left;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-cell.is-sorting-from-col{transition-duration:.1s}.dtable-cell.is-sorting-from-col:after{background-color:var(--dtable-sorting-col-color)!important;opacity:.1!important}.dtable-cell.is-sorting-from-col:before{border-left:1px solid var(--dtable-sorting-col-color);border-right:1px solid var(--dtable-sorting-col-color)}.dtable-header-cell.is-sortable-col{cursor:move}.has-sorting-col .scrollbar.is-horz{opacity:var(--scrollbar-opacity)!important}.has-sorting-col .dtable-scroll-shadow{visibility:visible}:root{--dtable-col-splitter-width:7px;--dtable-col-splitter-color:var(--color-primary-500)}.dtable-cell.has-col-resizing:after,.dtable-cell.has-col-splitter:hover:after{background:var(--dtable-col-splitter-color);opacity:.05}.dtable-col-splitter{background:var(--dtable-col-splitter-color);border-radius:var(--radius-full);bottom:0;cursor:ew-resize;opacity:0;position:absolute;right:calc(var(--dtable-col-splitter-width)/-2);top:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--dtable-col-splitter-width);z-index:20}.dtable-cell.has-col-splitter:hover .dtable-col-splitter{opacity:.3}.dtable-cell.has-col-resizing .dtable-col-splitter,.dtable-cell.has-col-splitter .dtable-col-splitter:hover{opacity:.5}.dtable.has-col-resizing .dtable-cell.has-col-splitter:not(.has-col-resizing) .dtable-col-splitter,.dtable.has-col-resizing .dtable-cell.has-col-splitter:not(.has-col-resizing):after{opacity:0}.dtable-col-splitter:after,.dtable-col-splitter:before{content:" ";display:block;height:.5rem;left:50%;margin-top:-.25rem;position:absolute;top:50%;width:1px;--tw-bg-opacity:1;background-color:rgba(var(--color-white-rgb),var(--tw-bg-opacity))}.dtable-col-splitter:before{margin-left:-1px}.dtable-col-splitter:after{margin-left:1px}.dtable.has-col-resizing{--dtable-hover-bg:transparent}.dtable.has-col-resizing,.has-col-resizing .dtable-header-cell{cursor:ew-resize!important}.dtable-cell.is-col-resizing:before{border-right:1px solid var(--dtable-col-splitter-color)}.dtable-cell.is-col-resizing:after{background:var(--dtable-col-splitter-color);opacity:.05}.has-col-resizing .scrollbar.is-horz{opacity:var(--scrollbar-opacity)!important}.dtable-cell.has-contextmenu-show:after{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));opacity:.1}.dtable{--dtable-header-bg:var(--color-surface-light);--dtable-footer-bg:var(--color-surface-light);--dtable-border-color:var(--color-border-light);--dtable-checked-border:var(--color-border);--dtable-checked-bg:var(--color-primary-50);--dtable-checked-bg-hover:var(--color-primary-100);--dtable-hover-bg:rgba(var(--color-gray-500-rgb),.05);--dtable-link-color:var(--color-link);--dtable-link-hover-color:var(--color-link-hover);--dtable-link-visited-color:var(--color-link-visited)}.dtable-cell-content[style*="--color-link"]{--dtable-link-hover-color:var(--color-link);--dtable-link-visited-color:var(--color-link)}.dtable-body .dtable-cell a{--dtable-link-color:var(--color-link)}.dtable-body .dtable-cell a:not(.btn){color:var(--dtable-link-color)}.dtable-body .dtable-cell a:not(.btn):visited{color:var(--dtable-link-visited-color)}.dtable-body .dtable-cell a:not(.btn):hover{color:var(--dtable-link-hover-color)}.dtable .btn-avatar{border-radius:var(--radius-full);gap:.25rem;height:1.25rem;--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity));padding-left:0;padding-right:.5rem;--tw-ring-color:transparent}.dtable .btn-avatar:hover{--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.dtable-nested-toggle{width:1rem}.dtable .toggle-icon{--toggle-icon-size:11px;border-radius:var(--radius);--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity))}.dtable .toggle-icon:after,.dtable .toggle-icon:before{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}.dtable-footer>.toolbar{margin-right:.5rem}.dtable-header .dtable-cell[data-sort]>.dtable-cell-content>a:not(:hover){color:inherit}.dtable-assign-btn{align-items:center;border-radius:var(--radius-full);display:flex;flex-direction:row;height:1.25rem;padding-left:.375rem;padding-right:.375rem;--dtable-link-color:var(--color-fore)}.dtable-assign-btn:not(:hover){color:inherit}.dtable-assign-btn.is-me{--dtable-link-color:var(--color-warning-500)!important}.dtable-assign-btn:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-strong-rgb),var(--tw-ring-opacity))}.dtable-assign-btn>span{border-radius:var(--radius-full);line-height:20px;padding-left:.375rem;padding-right:.375rem}.dtable-assign-btn.is-unassigned>span{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-strong-rgb),var(--tw-ring-opacity))}.dtable-assign-btn.is-unassigned:hover>span{background-color:inherit;color:inherit;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.dtable-assign-btn>.icon{opacity:0;transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.dtable-assign-btn:not(.disabled):hover>.icon{opacity:1}.dtable-header .dtable-cell[data-type=assign]{padding-left:1.5rem}.dtable-cell-icon{order:-5}.dtable-custom-cell[data-type=control]{align-items:center;display:flex;justify-content:center;padding-left:.125rem;padding-right:.125rem;z-index:1}:root{--dtable-editing-color:var(--color-success-600)}.dtable-cell.is-editing:after{border-color:var(--dtable-editing-color);border-width:2px!important;opacity:1;z-index:20}.dtable-editing-input{height:100%;outline:2px solid transparent;outline-offset:2px;padding-left:.75rem;padding-right:.75rem;width:100%}:root{--dtable-selected-color:var(--color-success-500);--dtable-selected-bg:var(--color-success-50);--dtable-selecting-bg:var(--color-success-100);--dtable-highlight-color:var(--color-success-700)}.dtable-selectable{-webkit-user-select:none;-moz-user-select:none;user-select:none}.dtable-cell.is-select:after{border-color:var(--dtable-selected-color);border-width:1px;opacity:1;z-index:10}.dtable-cell.is-selecting{background:var(--dtable-selecting-bg)}.dtable-cell.is-selected{background:var(--dtable-selected-bg)}.dtable-cell.is-col-selected:after,.dtable-cell.is-row-selected[data-col=INDEX]:after{background-color:rgba(var(--color-inverse-rgb),.05);opacity:1}.dtable-cell.has-cell-selected{color:var(--dtable-highlight-color)}.dtable-cell.is-first-row.is-select:after{top:0}.dtable-cell.is-last-row.is-select:after{bottom:1px}.dtable-cell.is-first-in-row.is-select:after{left:1px}.dtable-cell.is-last-in-row.is-select:after{right:1px}.dtable-datagrid .dtable-cell[data-col=INDEX]{background:var(--dtable-header-bg)}.dtable-empty-tip{min-height:212px}.dtable-cell[data-type=actions] .btn>.icon{font-size:1rem;line-height:1.5rem}.menu.menu-dtable-actions.has-icons{align-items:center;display:flex;gap:.25rem;min-width:auto;--menu-icon-opacity:1}.menu.menu-dtable-actions.has-icons>.menu-item>a{padding-left:.25rem;padding-right:.25rem}.menu.menu-dtable-actions.has-icons>.menu-item>a>.icon-EMPTY,.menu.menu-dtable-actions.has-icons>.menu-item>a>.item-content{display:none}.menu.menu-dtable-actions.has-icons>.menu-item>a>.icon-EMPTY+.item-content,.menu.menu-dtable-actions.has-icons>.menu-item>a>.item-content:first-child{display:block}:root{--state-color:rgba(0,0,0,.03);--zt-page-bg:#f8f9fa;--zt-header-height:3rem;--zt-header-bg:var(--color-canvas);--zt-header-color:var(--color-fore);--zt-sidebar-width:160px;--zt-navbar-active-color:var(--color-primary-500)}body{background-color:var(--zt-page-bg)}.page-app{overflow:overlay}.container{min-width:1200px}#header{height:var(--zt-header-height);--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);background:var(--zt-header-bg);border-bottom:1px solid var(--zt-header-border,rgba(var(--color-inverse-rgb),.05));box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);color:var(--zt-header-color)}#header>.container{height:100%;position:relative}#heading{align-items:center;bottom:0;display:flex;gap:.25rem;left:1rem;position:absolute;top:0}#heading>.toolbar{margin-left:-.75rem}#heading .dropmenu-btn>.text{max-width:142px}#heading>[data-zui-dropmenu]+div .dropmenu-btn>.text,#heading>[data-zui-dropmenu]+div+div .dropmenu-btn>.text{max-width:78px}#navbar{align-items:center;display:flex;font-size:.875rem;height:100%;justify-content:center;line-height:1.3rem;--state-color:rgba(var(--color-primary-500-rgb),.05);--state-active-opacity:1;--state-active-color:rgba(var(--color-primary-500-rgb),.08)}#navbar>.nav{--nav-active-color:var(--zt-navbar-active-color,var(--color-current));--nav-item-padding:12px;--nav-divider-margin:8px;margin-left:var(--nav-offset-left)}#navbar>.nav>.nav-item>a{height:3rem;padding-left:var(--nav-item-padding);padding-right:var(--nav-item-padding)}#navbar>.nav>.nav-item>a:before{--tw-scale-x:1!important;--tw-scale-y:1!important;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)!important;--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)!important;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)!important}#navbar>.nav>.nav-item>a.active:before{background:var(--state-active-color)!important;opacity:1!important}#navbar>.nav>.divider{align-self:center;height:1.25rem;margin-left:var(--nav-divider-margin);margin-right:var(--nav-divider-margin);opacity:.2}#navbar>.nav.compact{font-size:.8125rem;line-height:1.25rem}#navbar>.nav.compact-extra{font-size:.75rem;line-height:1rem}#toolbar{align-items:center;bottom:0;display:flex;gap:.25rem;position:absolute;right:1rem;top:0}#main{min-height:100vh}#header+#main{min-height:calc(100vh - 3rem)}#main>.container{padding-left:1rem;padding-right:1rem;position:relative}@media (min-width:1400px){#header>.container,#main>.container,#mainNavbar>.container{padding-left:2.5rem;padding-right:2.5rem}#heading{left:2.5rem}#toolbar{right:2.5rem}}#mainNavbar{height:2.75rem;--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}#mainNavbar>.container{position:relative}#mainNavbar .nav{bottom:0;height:2.75rem;justify-content:center;left:0;position:absolute;right:0;top:0}#mainNavbar .nav-item{font-size:.875rem;line-height:1.3rem}#mainNavbar .nav-item>a{border-radius:var(--radius)}#mainMenu{gap:1rem;justify-content:space-between;padding-bottom:.75rem;padding-top:.75rem}#featureBar,#mainMenu{align-items:center;display:flex}#featureBar{flex:1 1 auto;gap:.5rem}#actionBar{gap:.5rem}#actionBar>.nav-divider{margin-left:-.25rem;margin-right:-.25rem}#mainContent{padding-top:.75rem}#mainMenu+#mainContent{padding-top:0}#mainContent.row{align-items:stretch;display:flex;gap:1rem;justify-content:space-between}#mainContent.row>*{flex:1 1 auto;min-width:0}#mainContainer.has-sidebar-left{--gutter-left-size:16px}#mainContainer.is-sidebar-left-collapsed{--gutter-left-size:0}.has-sidebar-animation.has-sidebar-left #mainMenu{transition-duration:.15s;transition-property:padding-left;transition-timing-function:cubic-bezier(.4,0,.2,1)}:root{--modal-radius:var(--radius);--avatar-bg:var(--color-gray-200)}.modal-alert .modal-footer{justify-content:center}.modal-dialog{--tw-bg-opacity:1}.modal-content,.modal-dialog{max-height:calc(100vh - 4rem)}.modal-body,.modal-footer,.modal-header{padding:1.5rem 2rem}.modal-header{padding-right:3rem}.modal-body+.modal-footer,.modal-header+.modal-actions+.modal-body,.modal-header+.modal-body{padding-top:1px}.modal-condensed .modal-body,.modal-condensed .modal-header{padding:1rem 1.25rem}.modal-condensed .modal-actions{top:.75rem}:root{--label-bg:var(--color-gray-100);--label-color:var(--color-gray-800)}.label[class$=-pale],.label[class*="-pale "]{--tw-bg-opacity:0.4;--tw-ring-opacity:0.4}.body-modal .panel-form,.modal-body>.panel-form{margin:0;padding:0}.modal-body>.panel-form>.panel-heading{padding-left:1px;padding-right:1px;padding-top:1px}.modal-body>.panel-form>.panel-body{padding:1px}.modal-body>.form{padding-top:1px}.modal .history,.modal .panel-body>.form{padding:0}:root{--article-p-space:0}.lane-col-join-with-above{position:relative}.lane-col-join-with-above:before{background-color:inherit;left:0;position:absolute;right:0;--tw-content:"";content:var(--tw-content);height:var(--kanban-col-gap-top,var(--kanban-lanes-gap));top:calc(0px - var(--kanban-col-gap-top, var(--kanban-lanes-gap)))}.arrow,.arrow:before{background:inherit;height:calc(var(--arrow-size)*1.4142);position:absolute;width:calc(var(--arrow-size)*1.4142)}.arrow{visibility:hidden;--arrow-size:5px}.arrow:before{border:inherit;content:"";visibility:visible;--tw-rotate:45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.arrow-top,.arrow-up{border-bottom:inherit;border-right:inherit;border-width:1px 0 0 1px;top:calc(1px - var(--arrow-size))}.white>.arrow-top,.white>.arrow-up{top:calc(0px - var(--arrow-size))}.arrow-bottom,.arrow-down{border-left:inherit;border-top:inherit;border-width:0 1px 1px 0;bottom:calc(1px - var(--arrow-size))}.white>.arrow-bottom,.white>.arrow-down{bottom:calc(0px - var(--arrow-size))}.arrow-left{border-right:inherit;border-top:inherit;border-width:0 0 1px 1px;left:calc(1px - var(--arrow-size))}.white>.arrow-left{left:calc(0px - var(--arrow-size))}.arrow-right{border-bottom:inherit;border-left:inherit;border-width:1px 1px 0 0;right:calc(1px - var(--arrow-size))}.white>.arrow-right{right:calc(0px - var(--arrow-size))}.caret,.caret-down,.caret-left,.caret-right,.caret-up{align-items:center;display:inline-flex;height:.75rem;justify-content:center;position:relative;width:.75rem}.caret-down:before,.caret-left:before,.caret-right:before,.caret-up:before,.caret:before{display:block;height:.35rem;transform-origin:center;width:.35rem;--tw-translate-y:-1px;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.caret-left:before{--tw-translate-x:0.125rem;--tw-translate-y:0px;--tw-rotate:135deg}.caret-left:before,.caret-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.caret-right:before{--tw-translate-x:-0.125rem;--tw-translate-y:0px;--tw-rotate:-45deg}.caret-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}:focus>.caret,:hover>.caret{opacity:inherit}.disabled .caret,.readonly .caret{opacity:var(--caret-opacity,.5)}:root{--toggle-icon-size:calc(var(--font-size-root)*3/4 + 1px)}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-color:currentColor;border-width:1px;display:block;opacity:.5;position:relative}.toggle-icon-collapse:hover,.toggle-icon-expand:hover,.toggle-icon:hover{opacity:.9}.toggle-icon,.toggle-icon-collapse,.toggle-icon-expand{border-radius:inherit;height:var(--toggle-icon-size);width:var(--toggle-icon-size)}.is-collapsed .toggle-icon:after,.is-collapsed .toggle-icon:before,.is-expanded .toggle-icon:before,.toggle-icon-collapse:after,.toggle-icon-collapse:before,.toggle-icon-expand:before{background-color:currentColor;content:" ";display:block;height:1px;left:2px;position:absolute;right:2px;top:calc((var(--toggle-icon-size) - 3px)/2)}.is-collapsed .toggle-icon:after,.toggle-icon-collapse:after{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close{aspect-ratio:1/1;display:block;position:relative;width:1em}.close:after,.close:before{content:"";display:block;height:1px;left:0;position:absolute;width:100%;--tw-rotate:45deg;background-color:currentColor;border-radius:var(--radius-full);top:calc(50% - .5px)}.close:after,.close:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.close:after{--tw-rotate:-45deg}.spinner,.spinner:after,.spinner:before{display:block;height:1em;position:relative;width:1em}.spinner:after,.spinner:before{border-radius:var(--radius-full);content:" ";position:absolute}.spinner:before{animation:-spin 1s cubic-bezier(.6,0,.4,1) infinite;border:.16667em solid transparent;border-top-color:currentcolor}.spinner:after{border:.16667em solid;opacity:.2}.magnifier{display:inline-block;height:1em;position:relative;width:1em}.magnifier:after,.magnifier:before{border-radius:var(--radius-full);content:"";display:block;position:absolute}.magnifier:before{border:1px solid;height:.75em;width:.75em}.magnifier:after{height:1px;left:.55em;top:.7em;width:.5em;--tw-rotate:45deg;background-color:currentColor;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.more,.more-vert{margin:.5rem;position:relative}.more,.more-vert,.more-vert:after,.more-vert:before,.more:after,.more:before{background-color:currentColor;border-radius:var(--radius-full);height:.125rem;width:.125rem}.more-vert:after,.more-vert:before,.more:after,.more:before{display:block;left:-5px;position:absolute;top:0;--tw-content:"";content:var(--tw-content)}.more-vert:after,.more:after{left:5px}.more-vert{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.chevron-down,.chevron-left,.chevron-right,.chevron-up{align-items:center;display:inline-flex;height:1em;justify-content:center;position:relative;width:1em}.chevron-down:before,.chevron-left:before,.chevron-right:before,.chevron-up:before{display:block;height:.6923077em;transform-origin:center;width:.6923077em;--tw-translate-y:-0.125rem;--tw-rotate:45deg;border-color:currentColor;border-width:0 1px 1px 0;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-content:"";content:var(--tw-content)}.chevron-left:before{--tw-translate-y:0px;--tw-translate-x:0.125rem;--tw-rotate:135deg}.chevron-left:before,.chevron-right:before{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.chevron-right:before{--tw-translate-y:0px;--tw-translate-x:-0.125rem;--tw-rotate:-45deg}.chevron-up:before{--tw-translate-y:0.125rem;--tw-rotate:225deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.i-time{border-color:currentColor;border-radius:50%;border-width:.08em;display:inline-block;height:1em;position:relative;width:1em}.i-time:after{border-color:currentColor;border-width:0 0 .08em .08em;height:.385em;left:.3846em;position:absolute;top:.08em;width:.385em;--tw-content:"";content:var(--tw-content)}.i-calendar{border-color:currentColor;border-radius:2px;border-width:.08em;display:inline-block;height:.79em;margin-top:.16em;position:relative;width:1em}.i-calendar:after,.i-calendar:before{border-color:currentColor;border-width:.08em;position:absolute;--tw-content:"";content:var(--tw-content)}.i-calendar:before{border-bottom-width:0;left:.15em;top:.307em;width:.6em}.i-calendar:after{border-bottom-width:0;border-top-width:0;height:.3077em;left:.17em;top:-.154em;width:.538em}:root{--state-color:rgba(0,0,0,.05);--state-scale:.9;--opacity-disabled:.7;--opacity-muted:.5;--load-indicator-duration:300ms;--load-indicator-delay:.5s}.btn,.item>a,.state{cursor:pointer;position:relative}.btn:before,.item>a:before,.state:before{background:var(--state-color);border-radius:inherit;bottom:0;content:" ";display:block;left:0;opacity:0;pointer-events:none;position:absolute;right:0;top:0;transform:scale(var(--state-scale));transition-duration:.2s;transition-property:opacity,transform,box-shadow,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1)}.btn.active:not(:hover,:focus-visible,:focus-within,:active):before,.item>a.active:not(:hover,:focus-visible,:focus-within,:active):before,.state.active:not(:hover,:focus-visible,:focus-within,:active):before{background:var(--state-active-color,var(--state-color));opacity:var(--state-active-opacity,0);--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-duration:.7s}.btn.selected:not(:hover,:focus-visible,:focus-within,:active):before,.item>a.selected:not(:hover,:focus-visible,:focus-within,:active):before,.state.selected:not(:hover,:focus-visible,:focus-within,:active):before{background:var(--state-selected-color,var(--state-scale));opacity:var(--state-selected-opacity,.1);--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.btn:focus-visible,.item>a:focus-visible,.state:focus-visible{outline:2px solid transparent;outline-offset:2px}.btn:active:before,.btn:focus-visible:before,.btn:hover:before,.item>a:active:before,.item>a:focus-visible:before,.item>a:hover:before,.state:active:before,.state:focus-visible:before,.state:hover:before{--tw-scale-x:1;--tw-scale-y:1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.btn:hover:before,.item>a:hover:before,.state:hover:before{opacity:var(--state-hover-opacity,1)}.btn:active:before,.item>a:active:before,.state:active:before{background:var(--state-pressed-color,var(--state-color));opacity:var(--state-pressed-opacity,.6);--tw-ring-color:var(--state-ring-color,currentColor);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);transition-duration:.7s}.btn:focus-visible:before,.item>a:focus-visible:before,.state:focus-visible:before{background:var(--state-focus-color,var(--state-color));opacity:var(--state-focus-opacity,1);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-focus-rgb),var(--tw-ring-opacity))}.btn.disabled:before,.btn[disabled]:before,.item>a.disabled:before,.item>a[disabled]:before,.state.disabled:before,.state[disabled]:before{display:none}.btn{--state-active-opacity:1}@-moz-document url-prefix(){.btn,:root{--state-active-opacity:0;--state-focus-opacity:0}}.disabled,.disabled *,[disabled],[disabled] *{cursor:not-allowed!important;opacity:var(--opacity-disabled);--tw-grayscale:grayscale(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.load-indicator:after,.load-indicator:before{display:block;opacity:0;position:absolute;transition-delay:0s;transition-duration:.15s;transition-duration:var(--load-indicator-duration);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);visibility:hidden}.load-indicator:before{align-items:center;background-color:rgba(var(--color-canvas-rgb),.7);border-radius:inherit;bottom:0;display:flex;font-size:.75rem;justify-content:center;left:0;line-height:1rem;right:0;top:0;z-index:99;--tw-content:attr(data-loading);content:var(--tw-content)}.load-indicator[data-loading]:before{padding-top:3.5rem}.load-indicator:after{border-color:transparent currentcolor currentcolor;border-radius:var(--radius-full);border-style:dotted;border-width:4px 3px 4px 4px;height:2rem;left:50%;margin-left:-1rem;margin-top:-1rem;top:50%;width:2rem;z-index:100;--tw-content:"";content:var(--tw-content)}.load-indicator.loading:after,.load-indicator.loading:before{opacity:1;transition-delay:var(--load-indicator-delay);visibility:visible}@keyframes -spin{to{transform:rotate(1turn)}}.load-indicator.loading:after{animation:-spin 1s linear infinite;opacity:.5}.events-none,.pointer-events-none{pointer-events:none}.events-auto,.pointer-events-auto{pointer-events:auto}.scroll-auto{scroll-behavior:auto}.scroll-smooth{scroll-behavior:smooth}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.select-text{-webkit-user-select:text;-moz-user-select:text;user-select:text}.select-all{-webkit-user-select:all;-moz-user-select:all;user-select:all}.select-auto{-webkit-user-select:auto;-moz-user-select:auto;user-select:auto}.cursor-auto{cursor:auto}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-wait{cursor:wait}.cursor-text{cursor:text}.cursor-move{cursor:move}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.active\:opacity-100.active,.active\:opacity-100:active,.group.active .group-active\:opacity-100,.group:active .group-active\:opacity-100,.group:hover .group-hover\:opacity-100,.hover\:opacity-100:hover{opacity:1}.active\:opacity-0.active,.active\:opacity-0:active,.group.active .group-active\:opacity-0,.group:active .group-active\:opacity-0,.group:hover .group-hover\:opacity-0,.hover\:opacity-0:hover{opacity:0}.active\:text-primary.active,.active\:text-primary:active,.group.active .group-active\:text-primary,.group:active .group-active\:text-primary,.group:hover .group-hover\:text-primary,.hover\:text-primary:hover{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.active\:border-primary.active,.active\:border-primary:active,.group.active .group-active\:border-primary,.group:active .group-active\:border-primary,.group:hover .group-hover\:border-primary,.hover\:border-primary:hover{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500-rgb),var(--tw-border-opacity))}.active\:primary-pale.active,.active\:primary-pale:active,.group.active .group-active\:primary-pale,.group:active .group-active\:primary-pale,.group:hover .group-hover\:primary-pale,.hover\:primary-pale:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.active\:primary.active,.active\:primary:active,.group.active .group-active\:primary,.group:active .group-active\:primary,.group:hover .group-hover\:primary,.hover\:primary:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.active\:canvas.active,.active\:canvas:active,.group.active .group-active\:canvas,.group:active .group-active\:canvas,.group:hover .group-hover\:canvas,.hover\:canvas:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.active\:font-bold.active,.active\:font-bold:active,.group.active .group-active\:font-bold,.group:active .group-active\:font-bold,.group:hover .group-hover\:font-bold,.hover\:font-bold:hover{font-weight:700}.active\:shadow.active,.active\:shadow:active,.group.active .group-active\:shadow,.group:active .group-active\:shadow,.group:hover .group-hover\:shadow,.hover\:shadow:hover{--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.active\:shadow-lg.active,.active\:shadow-lg:active,.group.active .group-active\:shadow-lg,.group:active .group-active\:shadow-lg,.group:hover .group-hover\:shadow-lg,.hover\:shadow-lg:hover{--tw-shadow:0 5px 15px -3px rgba(0,0,0,.2),0 2px 6px -4px rgba(0,0,0,.15);--tw-shadow-colored:0 5px 15px -3px var(--tw-shadow-color),0 2px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.group:hover .group-hover\:block,.hover\:block:hover{display:block!important}.group:hover .group-hover\:flex,.hover\:flex:hover{display:flex!important}.group:hover .group-hover\:inline-flex,.hover\:inline-flex:hover{display:inline-flex!important}.group:hover .group-hover\:scale-110,.hover\:scale-110:hover{--tw-scale-x:1.1!important;--tw-scale-y:1.1!important}.group:hover .group-hover\:scale-110,.group:hover .group-hover\:scale-125,.hover\:scale-110:hover,.hover\:scale-125:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.group:hover .group-hover\:scale-125,.hover\:scale-125:hover{--tw-scale-x:1.25!important;--tw-scale-y:1.25!important}.aspect-auto{aspect-ratio:auto}.aspect-square{aspect-ratio:1/1}.aspect-video{aspect-ratio:16/9}.container{width:100%}@media (min-width:1720px){.container{max-width:1720px}}.container{margin-left:auto;margin-right:auto}.popup{background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity));border-radius:var(--radius);--tw-bg-opacity:0.85;--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05;--tw-backdrop-blur:blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.table-cell{display:table-cell}.table-row{display:table-row}.hidden{display:none!important}.pull-right{float:right}.pull-left{float:left}.clearfix:after{clear:both;content:"";display:block}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.object-fill{-o-object-fit:fill;object-fit:fill}.object-none{-o-object-fit:none;object-fit:none}.object-scale-down{-o-object-fit:scale-down;object-fit:scale-down}.object-bottom{-o-object-position:bottom;object-position:bottom}.object-center{-o-object-position:center;object-position:center}.object-left{-o-object-position:left;object-position:left}.object-left-bottom{-o-object-position:left bottom;object-position:left bottom}.object-left-top{-o-object-position:left top;object-position:left top}.object-right{-o-object-position:right;object-position:right}.object-right-bottom{-o-object-position:right bottom;object-position:right bottom}.object-right-top{-o-object-position:right top;object-position:right top}.object-top{-o-object-position:top;object-position:top}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-clip{overflow:clip}.overflow-visible{overflow:visible}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-hidden{overflow-y:hidden}.overflow-x-clip{overflow-x:clip}.overflow-y-clip{overflow-y:clip}.overflow-x-visible{overflow-x:visible}.overflow-y-visible{overflow-y:visible}.overflow-x-scroll{overflow-x:scroll}.overflow-y-scroll{overflow-y:scroll}.overflow-overlay{overflow:overlay}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{bottom:0;left:0;right:0;top:0}.inset-auto{bottom:auto;left:auto;right:auto;top:auto}.inset-x-0{left:0;right:0}.inset-y-0{bottom:0;top:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.top-full{top:100%}.right-full{right:100%}.bottom-full{bottom:100%}.left-full{left:100%}.top-auto{top:auto}.right-auto{right:auto}.bottom-auto{bottom:auto}.left-auto{left:auto}.top-px{top:1px}.right-px{right:1px}.bottom-px{bottom:1px}.left-px{left:1px}.top-0\.5{top:.125rem}.right-0\.5{right:.125rem}.bottom-0\.5{bottom:.125rem}.left-0\.5{left:.125rem}.top-1{top:.25rem}.right-1{right:.25rem}.bottom-1{bottom:.25rem}.left-1{left:.25rem}.top-1\.5{top:.375rem}.right-1\.5{right:.375rem}.bottom-1\.5{bottom:.375rem}.left-1\.5{left:.375rem}.top-2{top:.5rem}.right-2{right:.5rem}.bottom-2{bottom:.5rem}.left-2{left:.5rem}.top-2\.5{top:.625rem}.right-2\.5{right:.625rem}.bottom-2\.5{bottom:.625rem}.left-2\.5{left:.625rem}.top-3{top:.75rem}.right-3{right:.75rem}.bottom-3{bottom:.75rem}.left-3{left:.75rem}.top-3\.5{top:.875rem}.right-3\.5{right:.875rem}.bottom-3\.5{bottom:.875rem}.left-3\.5{left:.875rem}.top-4{top:1rem}.right-4{right:1rem}.bottom-4{bottom:1rem}.left-4{left:1rem}.top-5{top:1.25rem}.right-5{right:1.25rem}.bottom-5{bottom:1.25rem}.left-5{left:1.25rem}.top-6{top:1.5rem}.right-6{right:1.5rem}.bottom-6{bottom:1.5rem}.left-6{left:1.5rem}.top-7{top:1.75rem}.right-7{right:1.75rem}.bottom-7{bottom:1.75rem}.left-7{left:1.75rem}.top-8{top:2rem}.right-8{right:2rem}.bottom-8{bottom:2rem}.left-8{left:2rem}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-0{z-index:0}.z-1{z-index:1}.z-5{z-index:5}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-auto{z-index:auto}.z-base{z-index:1100}.z-above{z-index:50}.z-below{z-index:-50}.z-dropdown{z-index:1200}.z-sticky{z-index:1300}.z-fixed{z-index:1400}.z-modal{z-index:1500}.z-overlay{z-index:1600}.z-popover{z-index:1700}.z-tooltip{z-index:1800}.z-messager{z-index:1900}.m-0{margin:0}.m-auto{margin:auto}.m-px{margin:1px}.m-0\.5{margin:.125rem}.m-1{margin:.25rem}.m-1\.5{margin:.375rem}.m-2{margin:.5rem}.m-2\.5{margin:.625rem}.m-3{margin:.75rem}.m-3\.5{margin:.875rem}.m-4{margin:1rem}.m-5{margin:1.25rem}.m-6{margin:1.5rem}.m-7{margin:1.75rem}.m-8{margin:2rem}.m-9{margin:2.25rem}.m-10{margin:2.5rem}.mx-0{margin-left:0;margin-right:0}.my-0{margin-bottom:0}.mt-0,.my-0{margin-top:0}.mr-0{margin-right:0}.mb-0{margin-bottom:0}.ml-0{margin-left:0}.mx-auto{margin-left:auto;margin-right:auto}.my-auto{margin-bottom:auto}.mt-auto,.my-auto{margin-top:auto}.mr-auto{margin-right:auto}.mb-auto{margin-bottom:auto}.ml-auto{margin-left:auto}.mx-px{margin-left:1px;margin-right:1px}.my-px{margin-bottom:1px}.mt-px,.my-px{margin-top:1px}.mr-px{margin-right:1px}.mb-px{margin-bottom:1px}.ml-px{margin-left:1px}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.my-0\.5{margin-bottom:.125rem}.mt-0\.5,.my-0\.5{margin-top:.125rem}.mr-0\.5{margin-right:.125rem}.mb-0\.5{margin-bottom:.125rem}.ml-0\.5{margin-left:.125rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.my-1{margin-bottom:.25rem}.mt-1,.my-1{margin-top:.25rem}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.ml-1{margin-left:.25rem}.mx-1\.5{margin-left:.375rem;margin-right:.375rem}.my-1\.5{margin-bottom:.375rem}.mt-1\.5,.my-1\.5{margin-top:.375rem}.mr-1\.5{margin-right:.375rem}.mb-1\.5{margin-bottom:.375rem}.ml-1\.5{margin-left:.375rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem}.mt-2,.my-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.mx-2\.5{margin-left:.625rem;margin-right:.625rem}.my-2\.5{margin-bottom:.625rem}.mt-2\.5,.my-2\.5{margin-top:.625rem}.mr-2\.5{margin-right:.625rem}.mb-2\.5{margin-bottom:.625rem}.ml-2\.5{margin-left:.625rem}.mx-3{margin-left:.75rem;margin-right:.75rem}.my-3{margin-bottom:.75rem}.mt-3,.my-3{margin-top:.75rem}.mr-3{margin-right:.75rem}.mb-3{margin-bottom:.75rem}.ml-3{margin-left:.75rem}.mx-3\.5{margin-left:.875rem;margin-right:.875rem}.my-3\.5{margin-bottom:.875rem}.mt-3\.5,.my-3\.5{margin-top:.875rem}.mr-3\.5{margin-right:.875rem}.mb-3\.5{margin-bottom:.875rem}.ml-3\.5{margin-left:.875rem}.mx-4{margin-left:1rem;margin-right:1rem}.my-4{margin-bottom:1rem}.mt-4,.my-4{margin-top:1rem}.mr-4{margin-right:1rem}.mb-4{margin-bottom:1rem}.ml-4{margin-left:1rem}.mx-5{margin-left:1.25rem;margin-right:1.25rem}.my-5{margin-bottom:1.25rem}.mt-5,.my-5{margin-top:1.25rem}.mr-5{margin-right:1.25rem}.mb-5{margin-bottom:1.25rem}.ml-5{margin-left:1.25rem}.mx-6{margin-left:1.5rem;margin-right:1.5rem}.my-6{margin-bottom:1.5rem}.mt-6,.my-6{margin-top:1.5rem}.mr-6{margin-right:1.5rem}.mb-6{margin-bottom:1.5rem}.ml-6{margin-left:1.5rem}.mx-7{margin-left:1.75rem;margin-right:1.75rem}.my-7{margin-bottom:1.75rem}.mt-7,.my-7{margin-top:1.75rem}.mr-7{margin-right:1.75rem}.mb-7{margin-bottom:1.75rem}.ml-7{margin-left:1.75rem}.mx-8{margin-left:2rem;margin-right:2rem}.my-8{margin-bottom:2rem}.mt-8,.my-8{margin-top:2rem}.mr-8{margin-right:2rem}.mb-8{margin-bottom:2rem}.ml-8{margin-left:2rem}.mx-9{margin-left:2.25rem;margin-right:2.25rem}.my-9{margin-bottom:2.25rem}.mt-9,.my-9{margin-top:2.25rem}.mr-9{margin-right:2.25rem}.mb-9{margin-bottom:2.25rem}.ml-9{margin-left:2.25rem}.mx-10{margin-left:2.5rem;margin-right:2.5rem}.my-10{margin-bottom:2.5rem}.mt-10,.my-10{margin-top:2.5rem}.mr-10{margin-right:2.5rem}.mb-10{margin-bottom:2.5rem}.ml-10{margin-left:2.5rem}.p-0{padding:0}.p-px{padding:1px}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-7{padding:1.75rem}.p-8{padding:2rem}.p-9{padding:2.25rem}.p-10{padding:2.5rem}.px-0{padding-left:0;padding-right:0}.py-0{padding-bottom:0}.pt-0,.py-0{padding-top:0}.pr-0{padding-right:0}.pb-0{padding-bottom:0}.pl-0{padding-left:0}.px-px{padding-left:1px;padding-right:1px}.py-px{padding-bottom:1px}.pt-px,.py-px{padding-top:1px}.pr-px{padding-right:1px}.pb-px{padding-bottom:1px}.pl-px{padding-left:1px}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.py-0\.5{padding-bottom:.125rem}.pt-0\.5,.py-0\.5{padding-top:.125rem}.pr-0\.5{padding-right:.125rem}.pb-0\.5{padding-bottom:.125rem}.pl-0\.5{padding-left:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-1{padding-bottom:.25rem}.pt-1,.py-1{padding-top:.25rem}.pr-1{padding-right:.25rem}.pb-1{padding-bottom:.25rem}.pl-1{padding-left:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.py-1\.5{padding-bottom:.375rem}.pt-1\.5,.py-1\.5{padding-top:.375rem}.pr-1\.5{padding-right:.375rem}.pb-1\.5{padding-bottom:.375rem}.pl-1\.5{padding-left:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-2{padding-bottom:.5rem}.pt-2,.py-2{padding-top:.5rem}.pr-2{padding-right:.5rem}.pb-2{padding-bottom:.5rem}.pl-2{padding-left:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.py-2\.5{padding-bottom:.625rem}.pt-2\.5,.py-2\.5{padding-top:.625rem}.pr-2\.5{padding-right:.625rem}.pb-2\.5{padding-bottom:.625rem}.pl-2\.5{padding-left:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-3{padding-bottom:.75rem}.pt-3,.py-3{padding-top:.75rem}.pr-3{padding-right:.75rem}.pb-3{padding-bottom:.75rem}.pl-3{padding-left:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.py-3\.5{padding-bottom:.875rem}.pt-3\.5,.py-3\.5{padding-top:.875rem}.pr-3\.5{padding-right:.875rem}.pb-3\.5{padding-bottom:.875rem}.pl-3\.5{padding-left:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.py-4{padding-bottom:1rem}.pt-4,.py-4{padding-top:1rem}.pr-4{padding-right:1rem}.pb-4{padding-bottom:1rem}.pl-4{padding-left:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-5{padding-bottom:1.25rem}.pt-5,.py-5{padding-top:1.25rem}.pr-5{padding-right:1.25rem}.pb-5{padding-bottom:1.25rem}.pl-5{padding-left:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-6{padding-bottom:1.5rem}.pt-6,.py-6{padding-top:1.5rem}.pr-6{padding-right:1.5rem}.pb-6{padding-bottom:1.5rem}.pl-6{padding-left:1.5rem}.px-7{padding-left:1.75rem;padding-right:1.75rem}.py-7{padding-bottom:1.75rem}.pt-7,.py-7{padding-top:1.75rem}.pr-7{padding-right:1.75rem}.pb-7{padding-bottom:1.75rem}.pl-7{padding-left:1.75rem}.px-8{padding-left:2rem;padding-right:2rem}.py-8{padding-bottom:2rem}.pt-8,.py-8{padding-top:2rem}.pr-8{padding-right:2rem}.pb-8{padding-bottom:2rem}.pl-8{padding-left:2rem}.px-9{padding-left:2.25rem;padding-right:2.25rem}.py-9{padding-bottom:2.25rem}.pt-9,.py-9{padding-top:2.25rem}.pr-9{padding-right:2.25rem}.pb-9{padding-bottom:2.25rem}.pl-9{padding-left:2.25rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.py-10{padding-bottom:2.5rem}.pt-10,.py-10{padding-top:2.5rem}.pr-10{padding-right:2.5rem}.pb-10{padding-bottom:2.5rem}.pl-10{padding-left:2.5rem}.space-x-0>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(0px*(1 - var(--tw-space-x-reverse)));margin-right:calc(0px*var(--tw-space-x-reverse))}.space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(0px*var(--tw-space-y-reverse));margin-top:calc(0px*(1 - var(--tw-space-y-reverse)))}.space-x-0\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.125rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.125rem*var(--tw-space-x-reverse))}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.125rem*var(--tw-space-y-reverse));margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-1\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.375rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.375rem*var(--tw-space-x-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.375rem*var(--tw-space-y-reverse));margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.space-x-2\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.625rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.625rem*var(--tw-space-x-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.625rem*var(--tw-space-y-reverse));margin-top:calc(.625rem*(1 - var(--tw-space-y-reverse)))}.space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.space-x-3\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.875rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.875rem*var(--tw-space-x-reverse))}.space-y-3\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.875rem*var(--tw-space-y-reverse));margin-top:calc(.875rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-x-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.25rem*var(--tw-space-x-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.5rem*var(--tw-space-x-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.space-x-7>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.75rem*var(--tw-space-x-reverse))}.space-y-7>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.75rem*var(--tw-space-y-reverse));margin-top:calc(1.75rem*(1 - var(--tw-space-y-reverse)))}.space-x-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2rem*var(--tw-space-x-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.space-x-9>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2.25rem*var(--tw-space-x-reverse))}.space-y-9>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2.25rem*var(--tw-space-y-reverse));margin-top:calc(2.25rem*(1 - var(--tw-space-y-reverse)))}.space-x-10>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2.5rem*var(--tw-space-x-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2.5rem*var(--tw-space-y-reverse));margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)))}.space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1px*(1 - var(--tw-space-x-reverse)));margin-right:calc(1px*var(--tw-space-x-reverse))}.space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1px*var(--tw-space-y-reverse));margin-top:calc(1px*(1 - var(--tw-space-y-reverse)))}.w-0{width:0}.w-px{width:1px}.w-0\.5{width:.125rem}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-32{width:8rem}.w-36{width:9rem}.w-40{width:10rem}.w-44{width:11rem}.w-48{width:12rem}.w-52{width:13rem}.w-56{width:14rem}.w-60{width:15rem}.w-64{width:16rem}.w-72{width:18rem}.w-80{width:20rem}.w-96{width:24rem}.w-1\/2{width:50%}.w-1\/3{width:33.333333%}.w-2\/3{width:66.666667%}.w-1\/4{width:25%}.w-2\/4{width:50%}.w-3\/4{width:75%}.w-1\/5{width:20%}.w-2\/5{width:40%}.w-3\/5{width:60%}.w-4\/5{width:80%}.w-1\/6{width:16.666667%}.w-2\/6{width:33.333333%}.w-3\/6{width:50%}.w-4\/6{width:66.666667%}.w-5\/6{width:83.333333%}.w-auto{width:auto}.w-full{width:100%}.w-screen{width:100vw}.w-min{width:-moz-min-content;width:min-content}.w-max{width:-moz-max-content;width:max-content}.w-fit{width:-moz-fit-content;width:fit-content}.min-w-0{min-width:0}.min-w-full{min-width:100%}.min-w-min{min-width:-moz-min-content;min-width:min-content}.min-w-max{min-width:-moz-max-content;min-width:max-content}.min-w-fit{min-width:-moz-fit-content;min-width:fit-content}.max-w-0{max-width:0}.max-w-none{max-width:none}.max-w-xs{max-width:20rem}.max-w-sm{max-width:24rem}.max-w-md{max-width:28rem}.max-w-lg{max-width:32rem}.max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-min{max-width:-moz-min-content;max-width:min-content}.max-w-max{max-width:-moz-max-content;max-width:max-content}.max-w-fit{max-width:-moz-fit-content;max-width:fit-content}.h-0{height:0}.h-px{height:1px}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-20{height:5rem}.h-24{height:6rem}.h-28{height:7rem}.h-32{height:8rem}.h-36{height:9rem}.h-40{height:10rem}.h-44{height:11rem}.h-48{height:12rem}.h-52{height:13rem}.h-56{height:14rem}.h-60{height:15rem}.h-64{height:16rem}.h-72{height:18rem}.h-80{height:20rem}.h-96{height:24rem}.h-1\/2{height:50%}.h-1\/3{height:33.333333%}.h-2\/3{height:66.666667%}.h-1\/4{height:25%}.h-2\/4{height:50%}.h-3\/4{height:75%}.h-1\/5{height:20%}.h-2\/5{height:40%}.h-3\/5{height:60%}.h-4\/5{height:80%}.h-1\/6{height:16.666667%}.h-2\/6{height:33.333333%}.h-3\/6{height:50%}.h-4\/6{height:66.666667%}.h-5\/6{height:83.333333%}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.h-min{height:-moz-min-content;height:min-content}.h-max{height:-moz-max-content;height:max-content}.h-fit{height:-moz-fit-content;height:fit-content}.min-h-0{min-height:0}.min-h-full{min-height:100%}.min-h-min{min-height:-moz-min-content;min-height:min-content}.min-h-max{min-height:-moz-max-content;min-height:max-content}.min-h-fit{min-height:-moz-fit-content;min-height:fit-content}.max-h-0{max-height:0}.max-h-px{max-height:1px}.max-h-none{max-height:none}.max-h-full{max-height:100%}.max-h-min{max-height:-moz-min-content;max-height:min-content}.max-h-screen{max-height:100vh}.max-h-max{max-height:-moz-max-content;max-height:max-content}.max-h-fit{max-height:-moz-fit-content;max-height:fit-content}.canvas,.surface,.surface-light,.surface-strong{--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))}.canvas{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.surface-light{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-light-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-light-rgb),var(--tw-ring-opacity))}.surface{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-rgb),var(--tw-ring-opacity))}.surface-strong{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-strong-rgb),var(--tw-bg-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-strong-rgb),var(--tw-ring-opacity))}.inverse{background-color:rgba(var(--color-inverse-rgb),var(--tw-bg-opacity));color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.inverse,.white{--tw-bg-opacity:1;--tw-text-opacity:1}.white{background-color:rgba(var(--color-white-rgb),var(--tw-bg-opacity));color:rgba(var(--color-fore-in-light-rgb),var(--tw-text-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-white-rgb),var(--tw-ring-opacity))}.black{--tw-bg-opacity:1;background-color:rgba(var(--color-black-rgb),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-fore-in-dark-rgb),var(--tw-text-opacity));--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-black-rgb),var(--tw-ring-opacity))}.transparent{background-color:transparent;--tw-ring-color:transparent}.skin{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.skin:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger,.darken,.darker,.darkest,.gray,.gray-100,.gray-200,.gray-300,.gray-400,.gray-50,.gray-500,.gray-600,.gray-700,.gray-800,.gray-900,.gray-950,.important,.lighten,.lighter,.lightest,.primary,.secondary,.special,.success,.warning{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger:hover,.darken:hover,.darker:hover,.darkest:hover,.gray-100:hover,.gray-200:hover,.gray-300:hover,.gray-400:hover,.gray-500:hover,.gray-50:hover,.gray-600:hover,.gray-700:hover,.gray-800:hover,.gray-900:hover,.gray-950:hover,.gray:hover,.important:hover,.lighten:hover,.lighter:hover,.lightest:hover,.primary:hover,.secondary:hover,.special:hover,.success:hover,.warning:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger,.darken,.darker,.darkest,.gray,.gray-100,.gray-200,.gray-300,.gray-400,.gray-50,.gray-500,.gray-600,.gray-700,.gray-800,.gray-900,.gray-950,.important,.lighten,.lighter,.lightest,.primary,.secondary,.special,.success,.warning{--skin-text:rgba(var(--color-fore-in-dark-rgb),var(--tw-text-opacity));--skin-color:rgba(var(--skin-solid-rgb),1);--state-ring-color:var(--skin-color);--state-active-color:rgba(0,0,0,.1);--state-pressed-color:rgba(0,0,0,.1);--state-color:hsla(0,0%,100%,.1);--state-focus-color:rgba(0,0,0,.1)}.primary{--skin-solid-rgb:var(--color-primary-500-rgb)}.secondary{--skin-solid-rgb:var(--color-secondary-500-rgb)}.success{--skin-solid-rgb:var(--color-success-500-rgb)}.warning{--skin-solid-rgb:var(--color-warning-500-rgb)}.danger{--skin-solid-rgb:var(--color-danger-500-rgb)}.important{--skin-solid-rgb:var(--color-important-500-rgb)}.special{--skin-solid-rgb:var(--color-special-500-rgb)}.gray-50{--skin-bg:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity));--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-100{--skin-solid-rgb:var(--color-gray-100-rgb);--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-200,.lightest{--skin-solid-rgb:var(--color-gray-200-rgb);--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-300,.lighter{--skin-solid-rgb:var(--color-gray-300-rgb);--skin-text:rgba(var(--color-fore),var(--tw-text-opacity))}.gray-400,.lighten{--skin-solid-rgb:var(--color-gray-400-rgb)}.gray,.gray-500{--skin-solid-rgb:var(--color-gray-500-rgb)}.darken,.gray-600{--skin-solid-rgb:var(--color-gray-600-rgb)}.darker,.gray-700{--skin-solid-rgb:var(--color-gray-700-rgb)}.darkest,.gray-800{--skin-solid-rgb:var(--color-gray-800-rgb)}.gray-900{--skin-solid-rgb:var(--color-gray-900-rgb)}.gray-950{--skin-solid-rgb:var(--color-gray-950-rgb)}.danger-pale,.gray-100-pale,.gray-200-pale,.gray-300-pale,.gray-400-pale,.gray-50-pale,.gray-500-pale,.gray-600-pale,.gray-700-pale,.gray-800-pale,.gray-900-pale,.gray-950-pale,.gray-pale,.important-pale,.pale,.primary-pale,.secondary-pale,.special-pale,.success-pale,.warning-pale{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger-pale:hover,.gray-100-pale:hover,.gray-200-pale:hover,.gray-300-pale:hover,.gray-400-pale:hover,.gray-50-pale:hover,.gray-500-pale:hover,.gray-600-pale:hover,.gray-700-pale:hover,.gray-800-pale:hover,.gray-900-pale:hover,.gray-950-pale:hover,.gray-pale:hover,.important-pale:hover,.pale:hover,.primary-pale:hover,.secondary-pale:hover,.special-pale:hover,.success-pale:hover,.warning-pale:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger-pale,.gray-100-pale,.gray-200-pale,.gray-300-pale,.gray-400-pale,.gray-50-pale,.gray-500-pale,.gray-600-pale,.gray-700-pale,.gray-800-pale,.gray-900-pale,.gray-950-pale,.gray-pale,.important-pale,.pale,.primary-pale,.secondary-pale,.special-pale,.success-pale,.warning-pale{--skin-color:rgba(var(--skin-pale-rgb),.1);--skin-text:rgba(var(--skin-pale-rgb),1);--state-color:rgba(var(--skin-pale-rgb),.1)}.pale{--skin-pale-rgb:var(--color-gray-500-rgb)}.primary-pale{--skin-pale-rgb:var(--color-primary-500-rgb)}.secondary-pale{--skin-pale-rgb:var(--color-secondary-500-rgb)}.success-pale{--skin-pale-rgb:var(--color-success-500-rgb)}.warning-pale{--skin-pale-rgb:var(--color-warning-500-rgb)}.danger-pale{--skin-pale-rgb:var(--color-danger-500-rgb)}.important-pale{--skin-pale-rgb:var(--color-important-500-rgb)}.special-pale{--skin-pale-rgb:var(--color-special-500-rgb)}.gray-50-pale{--skin-pale-rgb:var(--color-gray-50-rgb);--skin-text:var(--color-gray-400)}.gray-100-pale{--skin-pale-rgb:var(--color-gray-100-rgb);--skin-text:var(--color-gray-400)}.gray-200-pale{--skin-pale-rgb:var(--color-gray-200-rgb);--skin-text:var(--color-gray-400)}.gray-300-pale{--skin-pale-rgb:var(--color-gray-300-rgb);--skin-text:var(--color-gray-500)}.gray-400-pale{--skin-pale-rgb:var(--color-gray-400-rgb);--skin-text:var(--color-gray-500)}.gray-500-pale,.gray-pale{--skin-pale-rgb:var(--color-gray-500-rgb)}.gray-600-pale{--skin-pale-rgb:var(--color-gray-600-rgb)}.gray-700-pale{--skin-pale-rgb:var(--color-gray-700-rgb)}.gray-800-pale{--skin-pale-rgb:var(--color-gray-800-rgb)}.gray-900-pale{--skin-pale-rgb:var(--color-gray-900-rgb)}.gray-950-pale{--skin-pale-rgb:var(--color-gray-950-rgb)}.danger-outline,.dark-outline,.gray-300-outline,.gray-400-outline,.gray-600-outline,.gray-outline,.important-outline,.light-outline,.outline,.primary-outline,.secondary-outline,.special-outline,.success-outline,.warning-outline{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger-outline:hover,.dark-outline:hover,.gray-300-outline:hover,.gray-400-outline:hover,.gray-600-outline:hover,.gray-outline:hover,.important-outline:hover,.light-outline:hover,.outline:hover,.primary-outline:hover,.secondary-outline:hover,.special-outline:hover,.success-outline:hover,.warning-outline:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger-outline,.dark-outline,.gray-300-outline,.gray-400-outline,.gray-600-outline,.gray-outline,.important-outline,.light-outline,.outline,.primary-outline,.secondary-outline,.special-outline,.success-outline,.warning-outline{--skin-text:var(--skin-color,inherit);--skin-bg:transparent;--skin-color:rgba(var(--skin-outline-rgb),1);--state-color:rgba(var(--skin-outline-rgb),.1)}.outline{--skin-outline-rgb:var(--color-fore-rgb)}.primary-outline{--skin-outline-rgb:var(--color-primary-500-rgb)}.secondary-outline{--skin-outline-rgb:var(--color-secondary-500-rgb)}.success-outline{--skin-outline-rgb:var(--color-success-500-rgb)}.warning-outline{--skin-outline-rgb:var(--color-warning-500-rgb)}.danger-outline{--skin-outline-rgb:var(--color-danger-500-rgb)}.important-outline{--skin-outline-rgb:var(--color-important-500-rgb)}.special-outline{--skin-outline-rgb:var(--color-special-500-rgb)}.gray-300-outline{--skin-text:var(--color-gray-500);--skin-outline-rgb:var(--color-gray-300-rgb)}.gray-400-outline{--skin-text:var(--color-gray-500);--skin-outline-rgb:var(--color-gray-400-rgb)}.gray-outline{--skin-outline-rgb:var(--color-gray-500-rgb)}.gray-600-outline{--skin-outline-rgb:var(--color-gray-600-rgb)}.dark-outline{--skin-outline-rgb:var(--color-inverse-rgb)}.light-outline{--skin-outline-rgb:var(--color-canvas-rgb)}.danger-ghost,.ghost,.important-ghost,.primary-ghost,.secondary-ghost,.special-ghost,.success-ghost,.warning-ghost{--skin-bg:var(--skin-color);--skin-ring:var(--skin-color);--skin-border:var(--skin-color);--skin-hover-text:var(--skin-text);--skin-hover-bg:var(--skin-bg);--tw-ring-color:var(--skin-ring);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--color-link-hover:var(--skin-text);background-color:var(--skin-bg);border-color:var(--skin-border);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:var(--skin-text)}.danger-ghost:hover,.ghost:hover,.important-ghost:hover,.primary-ghost:hover,.secondary-ghost:hover,.special-ghost:hover,.success-ghost:hover,.warning-ghost:hover{background-color:var(--skin-hover-bg);color:var(--skin-hover-text)}.danger-ghost,.ghost,.important-ghost,.primary-ghost,.secondary-ghost,.special-ghost,.success-ghost,.warning-ghost{--tw-ring-opacity:0;--tw-bg-opacity:0;--skin-text:var(--skin-color,inherit);--skin-bg:transparent;--skin-ring:transparent;--skin-color:rgba(var(--skin-ghost-rgb),1);--state-color:rgba(var(--skin-ghost-rgb),.1)}.ghost{--skin-ghost-rgb:var(--color-fore-rgb);--skin-text:inherit}.primary-ghost{--skin-ghost-rgb:var(--color-primary-500-rgb)}.secondary-ghost{--skin-ghost-rgb:var(--color-secondary-500-rgb)}.success-ghost{--skin-ghost-rgb:var(--color-success-500-rgb)}.warning-ghost{--skin-ghost-rgb:var(--color-warning-500-rgb)}.danger-ghost{--skin-ghost-rgb:var(--color-danger-500-rgb)}.important-ghost{--skin-ghost-rgb:var(--color-important-500-rgb)}.special-ghost{--skin-ghost-rgb:var(--color-special-500-rgb)}.font-sans{font-family:-apple-system,Noto Sans,Helvetica Neue,Helvetica,Nimbus Sans L,Arial,Liberation Sans,PingFang SC,Hiragino Sans GB,Noto Sans CJK SC,Source Han Sans SC,Source Han Sans CN,Microsoft YaHei,Wenquanyi Micro Hei,WenQuanYi Zen Hei,ST Heiti,SimHei,WenQuanYi Zen Hei Sharp,sans-serif}.font-serif{font-family:Nimbus Roman No9 L,Songti SC,Noto Serif CJK SC,Source Han Serif SC,Source Han Serif CN,STSong,AR PL New Sung,AR PL SungtiL GB,NSimSun,SimSun,TW-Sung,WenQuanYi Bitmap Song,AR PL UMing CN,AR PL UMing HK,AR PL UMing TW,AR PL UMing TW MBE,PMingLiU,MingLiU,serif}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-root{font-size:16px}.text-sm{font-size:.75rem;line-height:1rem}.text-base{font-size:.8125rem;line-height:1.25rem}.text-md{font-size:.875rem;line-height:1.3rem}.text-lg{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.125rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-thin{font-weight:100}.font-light{font-weight:300}.font-normal{font-weight:400}.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-black{font-weight:900}.leading-3{line-height:.75rem}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-6{line-height:1.5rem}.leading-7{line-height:1.75rem}.leading-8{line-height:2rem}.leading-9{line-height:2.25rem}.leading-10{line-height:2.5rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.leading-snug{line-height:1.375}.leading-normal{line-height:1.5}.leading-relaxed{line-height:1.625}.leading-loose{line-height:2}.line-clamp-1{-webkit-line-clamp:1}.line-clamp-1,.line-clamp-2{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-3{-webkit-line-clamp:3}.line-clamp-3,.line-clamp-4{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-4{-webkit-line-clamp:4}.line-clamp-5{-webkit-line-clamp:5}.line-clamp-5,.line-clamp-6{display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical}.line-clamp-6{-webkit-line-clamp:6}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-justify{text-align:justify}.align-middle{vertical-align:middle}.align-top{vertical-align:top}.align-bottom{vertical-align:bottom}.align-sub{vertical-align:sub}.align-super{vertical-align:super}.text-primary{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.text-secondary{--tw-text-opacity:1;color:rgba(var(--color-secondary-500-rgb),var(--tw-text-opacity))}.text-success{--tw-text-opacity:1;color:rgba(var(--color-success-500-rgb),var(--tw-text-opacity))}.text-warning{--tw-text-opacity:1;color:rgba(var(--color-warning-500-rgb),var(--tw-text-opacity))}.text-danger{--tw-text-opacity:1;color:rgba(var(--color-danger-500-rgb),var(--tw-text-opacity))}.text-important{--tw-text-opacity:1;color:rgba(var(--color-important-500-rgb),var(--tw-text-opacity))}.text-special{--tw-text-opacity:1;color:rgba(var(--color-special-500-rgb),var(--tw-text-opacity))}.text-primary-50{--tw-text-opacity:1;color:rgba(var(--color-primary-50-rgb),var(--tw-text-opacity))}.text-primary-100{--tw-text-opacity:1;color:rgba(var(--color-primary-100-rgb),var(--tw-text-opacity))}.text-primary-200{--tw-text-opacity:1;color:rgba(var(--color-primary-200-rgb),var(--tw-text-opacity))}.text-primary-300{--tw-text-opacity:1;color:rgba(var(--color-primary-300-rgb),var(--tw-text-opacity))}.text-primary-400{--tw-text-opacity:1;color:rgba(var(--color-primary-400-rgb),var(--tw-text-opacity))}.text-primary-500{--tw-text-opacity:1;color:rgba(var(--color-primary-500-rgb),var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgba(var(--color-primary-600-rgb),var(--tw-text-opacity))}.text-primary-700{--tw-text-opacity:1;color:rgba(var(--color-primary-700-rgb),var(--tw-text-opacity))}.text-primary-800{--tw-text-opacity:1;color:rgba(var(--color-primary-800-rgb),var(--tw-text-opacity))}.text-primary-900{--tw-text-opacity:1;color:rgba(var(--color-primary-900-rgb),var(--tw-text-opacity))}.text-primary-950{--tw-text-opacity:1;color:rgba(var(--color-primary-950-rgb),var(--tw-text-opacity))}.text-secondary-50{--tw-text-opacity:1;color:rgba(var(--color-secondary-50-rgb),var(--tw-text-opacity))}.text-secondary-100{--tw-text-opacity:1;color:rgba(var(--color-secondary-100-rgb),var(--tw-text-opacity))}.text-secondary-200{--tw-text-opacity:1;color:rgba(var(--color-secondary-200-rgb),var(--tw-text-opacity))}.text-secondary-300{--tw-text-opacity:1;color:rgba(var(--color-secondary-300-rgb),var(--tw-text-opacity))}.text-secondary-400{--tw-text-opacity:1;color:rgba(var(--color-secondary-400-rgb),var(--tw-text-opacity))}.text-secondary-500{--tw-text-opacity:1;color:rgba(var(--color-secondary-500-rgb),var(--tw-text-opacity))}.text-secondary-600{--tw-text-opacity:1;color:rgba(var(--color-secondary-600-rgb),var(--tw-text-opacity))}.text-secondary-700{--tw-text-opacity:1;color:rgba(var(--color-secondary-700-rgb),var(--tw-text-opacity))}.text-secondary-800{--tw-text-opacity:1;color:rgba(var(--color-secondary-800-rgb),var(--tw-text-opacity))}.text-secondary-900{--tw-text-opacity:1;color:rgba(var(--color-secondary-900-rgb),var(--tw-text-opacity))}.text-secondary-950{--tw-text-opacity:1;color:rgba(var(--color-secondary-950-rgb),var(--tw-text-opacity))}.text-gray-50{--tw-text-opacity:1;color:rgba(var(--color-gray-50-rgb),var(--tw-text-opacity))}.text-gray-100{--tw-text-opacity:1;color:rgba(var(--color-gray-100-rgb),var(--tw-text-opacity))}.text-gray-200,.text-lightest{--tw-text-opacity:1;color:rgba(var(--color-gray-200-rgb),var(--tw-text-opacity))}.text-gray-300,.text-lighter{--tw-text-opacity:1;color:rgba(var(--color-gray-300-rgb),var(--tw-text-opacity))}.text-gray-400,.text-lighten{--tw-text-opacity:1;color:rgba(var(--color-gray-400-rgb),var(--tw-text-opacity))}.text-gray,.text-gray-500{--tw-text-opacity:1;color:rgba(var(--color-gray-500-rgb),var(--tw-text-opacity))}.text-darken,.text-gray-600{--tw-text-opacity:1;color:rgba(var(--color-gray-600-rgb),var(--tw-text-opacity))}.text-darker,.text-gray-700{--tw-text-opacity:1;color:rgba(var(--color-gray-700-rgb),var(--tw-text-opacity))}.text-darkest,.text-gray-800{--tw-text-opacity:1;color:rgba(var(--color-gray-800-rgb),var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgba(var(--color-gray-900-rgb),var(--tw-text-opacity))}.text-gray-950{--tw-text-opacity:1;color:rgba(var(--color-gray-950-rgb),var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgba(var(--color-white-rgb),var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgba(var(--color-black-rgb),var(--tw-text-opacity))}.text-transparent{color:transparent}.text-canvas{--tw-text-opacity:1;color:rgba(var(--color-canvas-rgb),var(--tw-text-opacity))}.text-surface-light{--tw-text-opacity:1;color:rgba(var(--color-surface-light-rgb),var(--tw-text-opacity))}.text-surface{--tw-text-opacity:1;color:rgba(var(--color-surface-rgb),var(--tw-text-opacity))}.text-surface-strong{--tw-text-opacity:1;color:rgba(var(--color-surface-strong-rgb),var(--tw-text-opacity))}.text-inverse{--tw-text-opacity:1;color:rgba(var(--color-inverse-rgb),var(--tw-text-opacity))}.text-fore-in-light{--tw-text-opacity:1;color:rgba(var(--color-fore-in-light-rgb),var(--tw-text-opacity))}.text-fore-in-dark{--tw-text-opacity:1;color:rgba(var(--color-fore-in-dark-rgb),var(--tw-text-opacity))}.text-fore{--tw-text-opacity:1;color:rgba(var(--color-fore-rgb),var(--tw-text-opacity))}.text-focus{--tw-text-opacity:1;color:rgba(var(--color-focus-rgb),var(--tw-text-opacity))}.text-link{--tw-text-opacity:1;color:rgba(var(--color-link-rgb),var(--tw-text-opacity))}.text-link-hover{--tw-text-opacity:1;color:rgba(var(--color-link-hover-rgb),var(--tw-text-opacity))}.text-current{color:currentColor}.text-inherit{color:inherit}.clip,.ellipsis,.text-clip,.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.clip,.text-clip{text-overflow:clip}.whitespace-normal{white-space:normal}.nowrap,.whitespace-nowrap{white-space:nowrap}.pre,.whitespace-pre{white-space:pre}.pre-line,.whitespace-pre-line{white-space:pre-line}.pre-wrap,.whitespace-pre-wrap{white-space:pre-wrap}.break-normal{overflow-wrap:normal;word-break:normal}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.text-opacity-0{--tw-text-opacity:0}.text-opacity-5{--tw-text-opacity:.05}.text-opacity-10{--tw-text-opacity:.1}.text-opacity-20{--tw-text-opacity:.2}.text-opacity-25{--tw-text-opacity:.25}.text-opacity-30{--tw-text-opacity:.3}.text-opacity-40{--tw-text-opacity:.4}.text-opacity-50{--tw-text-opacity:.5}.text-opacity-60{--tw-text-opacity:.6}.text-opacity-70{--tw-text-opacity:.7}.text-opacity-80{--tw-text-opacity:.8}.text-opacity-90{--tw-text-opacity:.9}.text-opacity-95{--tw-text-opacity:.95}.text-opacity-100{--tw-text-opacity:1}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.normal-case{text-transform:none}.list-none{list-style-type:none}.list-disc{list-style-type:disc}.list-decimal{list-style-type:decimal}.list-unstyled{list-style-type:none;padding-left:0}.underline{text-decoration-line:underline}.overline{text-decoration-line:overline}.line-through{text-decoration-line:line-through}.no-underline{text-decoration-line:none}.bg-primary{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity))}.bg-secondary{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-500-rgb),var(--tw-bg-opacity))}.bg-success{--tw-bg-opacity:1;background-color:rgba(var(--color-success-500-rgb),var(--tw-bg-opacity))}.bg-warning{--tw-bg-opacity:1;background-color:rgba(var(--color-warning-500-rgb),var(--tw-bg-opacity))}.bg-danger{--tw-bg-opacity:1;background-color:rgba(var(--color-danger-500-rgb),var(--tw-bg-opacity))}.bg-important{--tw-bg-opacity:1;background-color:rgba(var(--color-important-500-rgb),var(--tw-bg-opacity))}.bg-special{--tw-bg-opacity:1;background-color:rgba(var(--color-special-500-rgb),var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity))}.bg-primary-100{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-200-rgb),var(--tw-bg-opacity))}.bg-primary-300{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-300-rgb),var(--tw-bg-opacity))}.bg-primary-400{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-400-rgb),var(--tw-bg-opacity))}.bg-primary-500{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600-rgb),var(--tw-bg-opacity))}.bg-primary-700{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-700-rgb),var(--tw-bg-opacity))}.bg-primary-800{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-800-rgb),var(--tw-bg-opacity))}.bg-primary-900{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-900-rgb),var(--tw-bg-opacity))}.bg-primary-950{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-950-rgb),var(--tw-bg-opacity))}.bg-secondary-50{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-50-rgb),var(--tw-bg-opacity))}.bg-secondary-100{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-100-rgb),var(--tw-bg-opacity))}.bg-secondary-200{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-200-rgb),var(--tw-bg-opacity))}.bg-secondary-300{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-300-rgb),var(--tw-bg-opacity))}.bg-secondary-400{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-400-rgb),var(--tw-bg-opacity))}.bg-secondary-500{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-500-rgb),var(--tw-bg-opacity))}.bg-secondary-600{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-600-rgb),var(--tw-bg-opacity))}.bg-secondary-700{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-700-rgb),var(--tw-bg-opacity))}.bg-secondary-800{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-800-rgb),var(--tw-bg-opacity))}.bg-secondary-900{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-900-rgb),var(--tw-bg-opacity))}.bg-secondary-950{--tw-bg-opacity:1;background-color:rgba(var(--color-secondary-950-rgb),var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-50-rgb),var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity))}.bg-gray-200,.bg-lightest{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-200-rgb),var(--tw-bg-opacity))}.bg-gray-300,.bg-lighter{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-300-rgb),var(--tw-bg-opacity))}.bg-gray-400,.bg-light{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-400-rgb),var(--tw-bg-opacity))}.bg-gray,.bg-gray-500{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-500-rgb),var(--tw-bg-opacity))}.bg-darken,.bg-gray-600{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-600-rgb),var(--tw-bg-opacity))}.bg-darker,.bg-gray-700{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}.bg-darkest,.bg-gray-800{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-800-rgb),var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-900-rgb),var(--tw-bg-opacity))}.bg-gray-950{--tw-bg-opacity:1;background-color:rgba(var(--color-gray-950-rgb),var(--tw-bg-opacity))}.bg-canvas{--tw-bg-opacity:1;background-color:rgba(var(--color-canvas-rgb),var(--tw-bg-opacity))}.bg-surface-light{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-light-rgb),var(--tw-bg-opacity))}.bg-surface{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-rgb),var(--tw-bg-opacity))}.bg-surface-strong{--tw-bg-opacity:1;background-color:rgba(var(--color-surface-strong-rgb),var(--tw-bg-opacity))}.bg-inverse{--tw-bg-opacity:1;background-color:rgba(var(--color-inverse-rgb),var(--tw-bg-opacity))}.bg-fore-in-light{--tw-bg-opacity:1;background-color:rgba(var(--color-fore-in-light-rgb),var(--tw-bg-opacity))}.bg-fore-in-dark{--tw-bg-opacity:1;background-color:rgba(var(--color-fore-in-dark-rgb),var(--tw-bg-opacity))}.bg-fore{--tw-bg-opacity:1;background-color:rgba(var(--color-fore-rgb),var(--tw-bg-opacity))}.bg-focus{--tw-bg-opacity:1;background-color:rgba(var(--color-focus-rgb),var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgba(var(--color-white-rgb),var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgba(var(--color-black-rgb),var(--tw-bg-opacity))}.bg-transparent{background-color:transparent}.bg-current{background-color:currentColor}.bg-inherit{background-color:inherit}.bg-none{background-image:none}.bg-opacity-0{--tw-bg-opacity:0}.bg-opacity-5{--tw-bg-opacity:.05}.bg-opacity-10{--tw-bg-opacity:.1}.bg-opacity-20{--tw-bg-opacity:.2}.bg-opacity-25{--tw-bg-opacity:.25}.bg-opacity-30{--tw-bg-opacity:.3}.bg-opacity-40{--tw-bg-opacity:.4}.bg-opacity-50{--tw-bg-opacity:.5}.bg-opacity-60{--tw-bg-opacity:.6}.bg-opacity-70{--tw-bg-opacity:.7}.bg-opacity-80{--tw-bg-opacity:.8}.bg-opacity-90{--tw-bg-opacity:.9}.bg-opacity-100{--tw-bg-opacity:1}.bg-auto{background-size:auto}.bg-cover{background-size:cover}.bg-contain{background-size:contain}.bg-repeat{background-repeat:repeat}.bg-no-repeat{background-repeat:no-repeat}.bg-repeat-x{background-repeat:repeat-x}.bg-repeat-y{background-repeat:repeat-y}.bg-repeat-round{background-repeat:round}.bg-repeat-space{background-repeat:space}.bg-bottom{background-position:bottom}.bg-center{background-position:50%}.bg-left{background-position:0}.bg-left-bottom{background-position:0 100%}.bg-left-top{background-position:0 0}.bg-right{background-position:100%}.bg-right-bottom{background-position:100% 100%}.bg-right-top{background-position:100% 0}.bg-top{background-position:top}.bg-fixed{background-attachment:fixed}.bg-local{background-attachment:local}.bg-scroll{background-attachment:scroll}.divider{align-self:stretch;border-color:currentColor;border-left-width:1px;border-top-width:1px;opacity:.1}.border-0{border-width:0}.border{border-width:1px}.border-2{border-width:2px}.border-4{border-width:4px}.border-t{border-top-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-b{border-bottom-width:1px}.border-t-0{border-top-width:0}.border-r-0{border-right-width:0}.border-b-0{border-bottom-width:0}.border-l-0{border-left-width:0}.border-t-2{border-top-width:2px}.border-l-2{border-left-width:2px}.border-r-2{border-right-width:2px}.border-b-2{border-bottom-width:2px}.border-t-4{border-top-width:4px}.border-l-4{border-left-width:4px}.border-r-4{border-right-width:4px}.border-b-4{border-bottom-width:4px}.border-light{--tw-border-opacity:1;border-color:rgba(var(--color-border-light-rgb),var(--tw-border-opacity))}.border-strong{--tw-border-opacity:1;border-color:rgba(var(--color-border-strong-rgb),var(--tw-border-opacity))}.border-primary{--tw-border-opacity:1;border-color:rgba(var(--color-primary-500-rgb),var(--tw-border-opacity))}.border-secondary{--tw-border-opacity:1;border-color:rgba(var(--color-secondary-500-rgb),var(--tw-border-opacity))}.border-success{--tw-border-opacity:1;border-color:rgba(var(--color-success-500-rgb),var(--tw-border-opacity))}.border-warning{--tw-border-opacity:1;border-color:rgba(var(--color-warning-500-rgb),var(--tw-border-opacity))}.border-danger{--tw-border-opacity:1;border-color:rgba(var(--color-danger-500-rgb),var(--tw-border-opacity))}.border-important{--tw-border-opacity:1;border-color:rgba(var(--color-important-500-rgb),var(--tw-border-opacity))}.border-special{--tw-border-opacity:1;border-color:rgba(var(--color-special-500-rgb),var(--tw-border-opacity))}.border-gray-50{--tw-border-opacity:1;border-color:rgba(var(--color-gray-50-rgb),var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgba(var(--color-gray-100-rgb),var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgba(var(--color-gray-200-rgb),var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgba(var(--color-gray-300-rgb),var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgba(var(--color-gray-400-rgb),var(--tw-border-opacity))}.border-gray,.border-gray-500{--tw-border-opacity:1;border-color:rgba(var(--color-gray-500-rgb),var(--tw-border-opacity))}.border-gray-600{--tw-border-opacity:1;border-color:rgba(var(--color-gray-600-rgb),var(--tw-border-opacity))}.border-gray-700{--tw-border-opacity:1;border-color:rgba(var(--color-gray-700-rgb),var(--tw-border-opacity))}.border-gray-800{--tw-border-opacity:1;border-color:rgba(var(--color-gray-800-rgb),var(--tw-border-opacity))}.border-gray-900{--tw-border-opacity:1;border-color:rgba(var(--color-gray-900-rgb),var(--tw-border-opacity))}.border-gray-950{--tw-border-opacity:1;border-color:rgba(var(--color-gray-950-rgb),var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgba(var(--color-white-rgb),var(--tw-border-opacity))}.border-black{--tw-border-opacity:1;border-color:rgba(var(--color-black-rgb),var(--tw-border-opacity))}.border-canvas{--tw-border-opacity:1;border-color:rgba(var(--color-canvas-rgb),var(--tw-border-opacity))}.border-surface-light{--tw-border-opacity:1;border-color:rgba(var(--color-surface-light-rgb),var(--tw-border-opacity))}.border-surface{--tw-border-opacity:1;border-color:rgba(var(--color-surface-rgb),var(--tw-border-opacity))}.border-surface-strong{--tw-border-opacity:1;border-color:rgba(var(--color-surface-strong-rgb),var(--tw-border-opacity))}.border-inverse{--tw-border-opacity:1;border-color:rgba(var(--color-inverse-rgb),var(--tw-border-opacity))}.border-fore-in-light{--tw-border-opacity:1;border-color:rgba(var(--color-fore-in-light-rgb),var(--tw-border-opacity))}.border-fore-in-dark{--tw-border-opacity:1;border-color:rgba(var(--color-fore-in-dark-rgb),var(--tw-border-opacity))}.border-fore{--tw-border-opacity:1;border-color:rgba(var(--color-fore-rgb),var(--tw-border-opacity))}.border-focus{--tw-border-opacity:1;border-color:rgba(var(--color-focus-rgb),var(--tw-border-opacity))}.border-link{--tw-border-opacity:1;border-color:rgba(var(--color-link-rgb),var(--tw-border-opacity))}.border-link-hover{--tw-border-opacity:1;border-color:rgba(var(--color-link-hover-rgb),var(--tw-border-opacity))}.border-transparent{border-color:transparent}.border-current{border-color:currentColor}.border-inherit{border-color:inherit}.border-solid{border-style:solid}.border-dashed{border-style:dashed}.border-dotted{border-style:dotted}.border-double{border-style:double}.border-hidden{border-style:hidden}.border-none{border-style:none}.border-opacity-0{--tw-border-opacity:0}.border-opacity-5{--tw-border-opacity:.05}.border-opacity-10{--tw-border-opacity:.1}.border-opacity-20{--tw-border-opacity:.2}.border-opacity-25{--tw-border-opacity:.25}.border-opacity-30{--tw-border-opacity:.3}.border-opacity-40{--tw-border-opacity:.4}.border-opacity-50{--tw-border-opacity:.5}.border-opacity-60{--tw-border-opacity:.6}.border-opacity-70{--tw-border-opacity:.7}.border-opacity-80{--tw-border-opacity:.8}.border-opacity-90{--tw-border-opacity:.9}.border-opacity-95{--tw-border-opacity:.95}.border-opacity-100{--tw-border-opacity:1}.rounded-none{border-radius:var(--radius-none)}.rounded-sm{border-radius:var(--radius-sm)}.rounded{border-radius:var(--radius)}.rounded-md{border-radius:var(--radius-md)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.circle,.rounded-full{border-radius:var(--radius-full)}.rounded-l-none{border-bottom-left-radius:var(--radius-none);border-top-left-radius:var(--radius-none)}.rounded-t-none{border-top-left-radius:var(--radius-none)}.rounded-r-none,.rounded-t-none{border-top-right-radius:var(--radius-none)}.rounded-b-none,.rounded-r-none{border-bottom-right-radius:var(--radius-none)}.rounded-b-none{border-bottom-left-radius:var(--radius-none)}.rounded-br-none{border-bottom-right-radius:var(--radius-none)}.rounded-bl-none{border-bottom-left-radius:var(--radius-none)}.rounded-tr-none{border-top-right-radius:var(--radius-none)}.rounded-tl-none{border-top-left-radius:var(--radius-none)}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity))}.ring-border-light{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-light-rgb),var(--tw-ring-opacity))}.ring-border{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-rgb),var(--tw-ring-opacity))}.ring-border-strong{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-border-strong-rgb),var(--tw-ring-opacity))}.ring-light{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.05}.ring-gray{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.1}.ring-dark{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.2}.ring-darker{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.3}.ring-darkest{--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity));--tw-ring-opacity:0.5}.ring-primary{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-primary-500-rgb),var(--tw-ring-opacity))}.ring-secondary{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-secondary-500-rgb),var(--tw-ring-opacity))}.ring-warning{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-warning-500-rgb),var(--tw-ring-opacity))}.ring-success{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-success-500-rgb),var(--tw-ring-opacity))}.ring-danger{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-danger-500-rgb),var(--tw-ring-opacity))}.ring-important{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-important-500-rgb),var(--tw-ring-opacity))}.ring-special{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-special-500-rgb),var(--tw-ring-opacity))}.ring-gray-50{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-50-rgb),var(--tw-ring-opacity))}.ring-gray-100{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-100-rgb),var(--tw-ring-opacity))}.ring-gray-200{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-200-rgb),var(--tw-ring-opacity))}.ring-gray-300{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-300-rgb),var(--tw-ring-opacity))}.ring-gray-400{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-400-rgb),var(--tw-ring-opacity))}.ring-gray-500{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-500-rgb),var(--tw-ring-opacity))}.ring-gray-600{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-600-rgb),var(--tw-ring-opacity))}.ring-gray-700{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-700-rgb),var(--tw-ring-opacity))}.ring-gray-800{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-800-rgb),var(--tw-ring-opacity))}.ring-gray-900{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-900-rgb),var(--tw-ring-opacity))}.ring-gray-950{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-gray-950-rgb),var(--tw-ring-opacity))}.ring-inverse{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-inverse-rgb),var(--tw-ring-opacity))}.ring-canvas{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-canvas-rgb),var(--tw-ring-opacity))}.ring-surface{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-surface-rgb),var(--tw-ring-opacity))}.ring-fore{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-fore-rgb),var(--tw-ring-opacity))}.ring-transparent{--tw-ring-color:transparent}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-black-rgb),var(--tw-ring-opacity))}.ring-white{--tw-ring-opacity:1;--tw-ring-color:rgba(var(--color-white-rgb),var(--tw-ring-opacity))}.ring-inherit{--tw-ring-color:inherit}.ring-current{--tw-ring-color:currentColor}.ring-opacity-0{--tw-ring-opacity:0}.ring-opacity-5{--tw-ring-opacity:.05}.ring-opacity-10{--tw-ring-opacity:.1}.ring-opacity-20{--tw-ring-opacity:.2}.ring-opacity-30{--tw-ring-opacity:.3}.ring-opacity-40{--tw-ring-opacity:.4}.ring-opacity-50{--tw-ring-opacity:.5}.ring-opacity-60{--tw-ring-opacity:.6}.ring-opacity-70{--tw-ring-opacity:.7}.ring-opacity-80{--tw-ring-opacity:.8}.ring-opacity-90{--tw-ring-opacity:.9}.ring-opacity-100{--tw-ring-opacity:1}.ring-0{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-0,.ring-2{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-3{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-3,.ring-4{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-4{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-8{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-inset{--tw-ring-inset:inset}.ring-offset-0{--tw-ring-offset-width:0px}.ring-offset-1{--tw-ring-offset-width:1px}.ring-offset-2{--tw-ring-offset-width:2px}.ring-offset-4{--tw-ring-offset-width:4px}.ring-offset-8{--tw-ring-offset-width:8px}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.04),0 0 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color),0 0 2px -1px var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 3px 8px 0 rgba(0,0,0,.04),0 1px 2px -1px rgba(0,0,0,.01);--tw-shadow-colored:0 3px 8px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 2px 6px -1px rgba(0,0,0,.2),0 1px 4px -2px rgba(0,0,0,.15);--tw-shadow-colored:0 2px 6px -1px var(--tw-shadow-color),0 1px 4px -2px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 5px 15px -3px rgba(0,0,0,.2),0 2px 6px -4px rgba(0,0,0,.15);--tw-shadow-colored:0 5px 15px -3px var(--tw-shadow-color),0 2px 6px -4px var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 10px 25px -5px rgba(0,0,0,.2),0 4px 10px -6px rgba(0,0,0,.15);--tw-shadow-colored:0 10px 25px -5px var(--tw-shadow-color),0 4px 10px -6px var(--tw-shadow-color)}.shadow-2xl,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 10px 50px -10px rgba(0,0,0,.4),0 8px 20px -10px rgba(0,0,0,.3);--tw-shadow-colored:0 10px 50px -10px var(--tw-shadow-color),0 8px 20px -10px var(--tw-shadow-color)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-inner,.shadow-none{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-none{--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000}.muted{opacity:var(--opacity-muted)}.opacity-0{opacity:0}.opacity-5{opacity:.05}.opacity-10{opacity:.1}.opacity-20{opacity:.2}.opacity-25{opacity:.25}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-90{opacity:.9}.opacity-95{opacity:.95}.opacity-100{opacity:1}.blur-none{--tw-blur:blur(0)}.blur-none,.blur-sm{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-sm{--tw-blur:blur(4px)}.blur{--tw-blur:blur(8px)}.blur,.blur-md{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-md{--tw-blur:blur(12px)}.blur-lg{--tw-blur:blur(16px)}.blur-lg,.blur-xl{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-xl{--tw-blur:blur(24px)}.grayscale{--tw-grayscale:grayscale(100%)}.grayscale,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter-none{filter:none!important}.drop-shadow-none{--tw-drop-shadow:drop-shadow(0 0 #0000)}.drop-shadow-none,.drop-shadow-sm{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-sm{--tw-drop-shadow:drop-shadow(0 1px 1px rgba(0,0,0,.05))}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.drop-shadow,.drop-shadow-md{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-md{--tw-drop-shadow:drop-shadow(0 4px 3px rgba(0,0,0,.07)) drop-shadow(0 2px 2px rgba(0,0,0,.06))}.drop-shadow-lg{--tw-drop-shadow:drop-shadow(0 10px 8px rgba(0,0,0,.04)) drop-shadow(0 4px 3px rgba(0,0,0,.1))}.drop-shadow-lg,.drop-shadow-xl{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow-xl{--tw-drop-shadow:drop-shadow(0 20px 13px rgba(0,0,0,.03)) drop-shadow(0 8px 5px rgba(0,0,0,.08))}.drop-shadow-2xl{--tw-drop-shadow:drop-shadow(0 25px 25px rgba(0,0,0,.15));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-none{--tw-backdrop-blur:blur(0)}.backdrop-blur-none,.backdrop-blur-sm{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur{--tw-backdrop-blur:blur(8px)}.backdrop-blur,.backdrop-blur-md{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px)}.backdrop-blur-lg,.backdrop-blur-xl{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)}.backdrop-blur-2xl{--tw-backdrop-blur:blur(40px)}.backdrop-blur-2xl,.backdrop-blur-3xl{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-3xl{--tw-backdrop-blur:blur(64px)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-duration:.15s;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-duration:.15s;transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-shadow{transition-duration:.15s;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-duration:.15s;transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-none{transition-property:none}.fade,.fade-from-bottom,.fade-from-center,.fade-from-left,.fade-from-right,.fade-from-top{opacity:0;transition-duration:.15s;transition-property:opacity,transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.fade-from-bottom,.fade-from-center,.fade-from-left,.fade-from-right,.fade-from-top{--tw-scale-x:.9;--tw-scale-y:.9}.fade-from-bottom,.fade-from-center,.fade-from-left,.fade-from-right,.fade-from-top{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fade-from-bottom{--tw-translate-y:25%}.fade-from-top{--tw-translate-y:-25%}.fade-from-left,.fade-from-top{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fade-from-left{--tw-translate-x:-25%}.fade-from-right{--tw-translate-x:25%}.fade-from-bottom.in,.fade-from-center.in,.fade-from-left.in,.fade-from-right,.fade-from-right.in,.fade-from-top.in,.fade.in{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.fade-from-bottom.in,.fade-from-center.in,.fade-from-left.in,.fade-from-right.in,.fade-from-top.in,.fade.in{--tw-translate-x:0px;--tw-translate-y:0px;--tw-scale-x:1;--tw-scale-y:1;opacity:1}.duration-75{transition-duration:75ms}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-1000{transition-duration:1s}@keyframes -spin{to{transform:rotate(1turn)}}.animate-spin,.spin{animation:-spin 1s linear infinite}@keyframes -ping{75%,to{opacity:0;transform:scale(2)}}.animate-ping,.ping{animation:-ping 1s cubic-bezier(0,0,.2,1) infinite}@keyframes -pulse{50%{opacity:.5}}.animate-pulse,.pulse{animation:-pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes -bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}.animate-bounce,.bounce{animation:-bounce 1s infinite}.animate-highlight,.highlight{animation:-highlight 2s ease-in-out infinite;outline-color:#fde047;outline-offset:-1px;outline-style:solid;outline-width:1px}@keyframes -highlight{50%{--tw-bg-opacity:1;background-color:rgb(254 252 232/var(--tw-bg-opacity));outline-offset:-4px;outline-width:4px}}.scale-0{--tw-scale-x:0;--tw-scale-y:0}.scale-0,.scale-50{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-50{--tw-scale-x:.5;--tw-scale-y:.5}.scale-75{--tw-scale-x:.75;--tw-scale-y:.75}.scale-75,.scale-90{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-90{--tw-scale-x:.9;--tw-scale-y:.9}.scale-95{--tw-scale-x:.95;--tw-scale-y:.95}.scale-100,.scale-95{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-100{--tw-scale-x:1;--tw-scale-y:1}.scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05}.scale-105,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.scale-125{--tw-scale-x:1.25;--tw-scale-y:1.25}.scale-125,.scale-150{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-150{--tw-scale-x:1.5;--tw-scale-y:1.5}.flip-x{--tw-scale-x:-1}.flip-x,.flip-y{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.flip-y{--tw-scale-y:-1}.rotate-0{--tw-rotate:0deg}.rotate-0,.rotate-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-1{--tw-rotate:1deg}.rotate-2{--tw-rotate:2deg}.rotate-2,.rotate-3{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-3{--tw-rotate:3deg}.rotate-6{--tw-rotate:6deg}.rotate-12,.rotate-6{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-12{--tw-rotate:12deg}.rotate-45{--tw-rotate:45deg}.rotate-45,.rotate-90{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate:90deg}.rotate-135{--tw-rotate:135deg}.rotate-135,.rotate-180{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.rotate-270{--tw-rotate:270deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.basis-0{flex-basis:0px}.basis-1{flex-basis:0.25rem}.basis-2{flex-basis:0.5rem}.basis-3{flex-basis:0.75rem}.basis-4{flex-basis:1rem}.basis-5{flex-basis:1.25rem}.basis-6{flex-basis:1.5rem}.basis-7{flex-basis:1.75rem}.basis-8{flex-basis:2rem}.basis-9{flex-basis:2.25rem}.basis-10{flex-basis:2.5rem}.basis-11{flex-basis:2.75rem}.basis-12{flex-basis:3rem}.basis-14{flex-basis:3.5rem}.basis-16{flex-basis:4rem}.basis-20{flex-basis:5rem}.basis-24{flex-basis:6rem}.basis-28{flex-basis:7rem}.basis-32{flex-basis:8rem}.basis-36{flex-basis:9rem}.basis-40{flex-basis:10rem}.basis-44{flex-basis:11rem}.basis-48{flex-basis:12rem}.basis-52{flex-basis:13rem}.basis-56{flex-basis:14rem}.basis-60{flex-basis:15rem}.basis-64{flex-basis:16rem}.basis-72{flex-basis:18rem}.basis-80{flex-basis:20rem}.basis-96{flex-basis:24rem}.basis-auto{flex-basis:auto}.basis-px{flex-basis:1px}.basis-0\.5{flex-basis:0.125rem}.basis-1\.5{flex-basis:0.375rem}.basis-2\.5{flex-basis:0.625rem}.basis-3\.5{flex-basis:0.875rem}.basis-1\/2{flex-basis:50%}.basis-1\/3{flex-basis:33.333333%}.basis-2\/3{flex-basis:66.666667%}.basis-1\/4{flex-basis:25%}.basis-2\/4{flex-basis:50%}.basis-3\/4{flex-basis:75%}.basis-1\/5{flex-basis:20%}.basis-2\/5{flex-basis:40%}.basis-3\/5{flex-basis:60%}.basis-4\/5{flex-basis:80%}.basis-1\/6{flex-basis:16.666667%}.basis-2\/6{flex-basis:33.333333%}.basis-3\/6{flex-basis:50%}.basis-4\/6{flex-basis:66.666667%}.basis-5\/6{flex-basis:83.333333%}.basis-1\/12{flex-basis:8.333333%}.basis-2\/12{flex-basis:16.666667%}.basis-3\/12{flex-basis:25%}.basis-4\/12{flex-basis:33.333333%}.basis-5\/12{flex-basis:41.666667%}.basis-6\/12{flex-basis:50%}.basis-7\/12{flex-basis:58.333333%}.basis-8\/12{flex-basis:66.666667%}.basis-9\/12{flex-basis:75%}.basis-10\/12{flex-basis:83.333333%}.basis-11\/12{flex-basis:91.666667%}.basis-full{flex-basis:100%}.row{display:flex;flex-direction:row}.center,.col{display:flex;flex-direction:column}.center,.center-row{align-items:center;justify-content:center}.center-row{display:flex;flex-direction:row}.center-x,.center-y{align-items:center;display:flex}.center-y{flex-direction:column}.row-reverse{display:flex;flex-direction:row-reverse}.col-reverse{display:flex;flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.flex-wrap-reverse{flex-wrap:wrap-reverse}.flex-nowrap{flex-wrap:nowrap}.flex-1{flex:1 1 0%}.flex-auto{flex:1 1 auto}.flex-initial{flex:0 1 auto}.flex-none{flex:none}.grow{flex-grow:1!important}.grow-0{flex-grow:0!important}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.order-first{order:-9999}.order-last{order:9999}.order-none{order:0}.gap-0{gap:0}.gap-x-0{-moz-column-gap:0;column-gap:0}.gap-y-0{row-gap:0}.gap-px{gap:1px}.gap-x-px{-moz-column-gap:1px;column-gap:1px}.gap-y-px{row-gap:1px}.gap-0\.5{gap:.125rem}.gap-x-0\.5{-moz-column-gap:.125rem;column-gap:.125rem}.gap-y-0\.5{row-gap:.125rem}.gap-3px{gap:3px}.gap-1{gap:.25rem}.gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.gap-y-1{row-gap:.25rem}.gap-1\.5{gap:.375rem}.gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.gap-y-1\.5{row-gap:.375rem}.gap-2{gap:.5rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.gap-y-2{row-gap:.5rem}.gap-2\.5{gap:.625rem}.gap-x-2\.5{-moz-column-gap:.625rem;column-gap:.625rem}.gap-y-2\.5{row-gap:.625rem}.gap-3{gap:.75rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-3{row-gap:.75rem}.gap-3\.5{gap:.875rem}.gap-x-3\.5{-moz-column-gap:.875rem;column-gap:.875rem}.gap-y-3\.5{row-gap:.875rem}.gap-4{gap:1rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-4{row-gap:1rem}.gap-5{gap:1.25rem}.gap-x-5{-moz-column-gap:1.25rem;column-gap:1.25rem}.gap-y-5{row-gap:1.25rem}.gap-6{gap:1.5rem}.gap-x-6{-moz-column-gap:1.5rem;column-gap:1.5rem}.gap-y-6{row-gap:1.5rem}.gap-7{gap:1.75rem}.gap-x-7{-moz-column-gap:1.75rem;column-gap:1.75rem}.gap-y-7{row-gap:1.75rem}.gap-8{gap:2rem}.gap-x-8{-moz-column-gap:2rem;column-gap:2rem}.gap-y-8{row-gap:2rem}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.justify-evenly{justify-content:space-evenly}.self-auto{align-self:auto}.self-start{align-self:flex-start}.self-end{align-self:flex-end}.self-center{align-self:center}.self-stretch{align-self:stretch}.self-baseline{align-self:baseline}.content-center{align-content:center}.content-start{align-content:flex-start}.content-end{align-content:flex-end}.content-between{align-content:space-between}.content-around{align-content:space-around}.content-evenly{align-content:space-evenly}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}@font-face{font-display:fallback;font-family:D-DIN-PRO;font-weight:400;src:url(./fonts/D-DIN-PRO-400-Regular.otf)}@font-face{font-display:fallback;font-family:D-DIN-PRO;font-weight:500;src:url(./fonts/D-DIN-PRO-700-Bold.otf)}.num{font-family:D-DIN-PRO}@font-face{font-display:fallback;font-family:Nunito;font-weight:400;src:url(./fonts/Nunito-Regular.ttf)}@font-face{font-display:fallback;font-family:Nunito;font-weight:700;src:url(./fonts/Nunito-Bold.ttf)}@font-face{font-display:fallback;font-family:Nunito;font-weight:300;src:url(./fonts/Nunito-Light.ttf)}.font-brand{font-family:Nunito;font-weight:400}@supports not (gap:4px){.gap-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1px*(1 - var(--tw-space-x-reverse)));margin-right:calc(1px*var(--tw-space-x-reverse))}.gap-0\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2px*(1 - var(--tw-space-x-reverse)));margin-right:calc(2px*var(--tw-space-x-reverse))}.gap-3px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(3px*(1 - var(--tw-space-x-reverse)));margin-right:calc(3px*var(--tw-space-x-reverse))}.gap-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}.gap-1\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(6px*(1 - var(--tw-space-x-reverse)));margin-right:calc(6px*var(--tw-space-x-reverse))}.gap-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.gap-2\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(10px*(1 - var(--tw-space-x-reverse)));margin-right:calc(10px*var(--tw-space-x-reverse))}.gap-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.75rem*var(--tw-space-x-reverse))}.gap-3\.5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(14px*(1 - var(--tw-space-x-reverse)));margin-right:calc(14px*var(--tw-space-x-reverse))}.gap-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.gap-5>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.25rem*var(--tw-space-x-reverse))}.gap-6>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.5rem*var(--tw-space-x-reverse))}.gap-7>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1.75rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1.75rem*var(--tw-space-x-reverse))}.gap-8>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(2rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(2rem*var(--tw-space-x-reverse))}.col.gap-px>:not([hidden])~:not([hidden]),.gap-px.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1px*var(--tw-space-y-reverse));margin-top:calc(1px*(1 - var(--tw-space-y-reverse)))}.col.gap-0\.5>:not([hidden])~:not([hidden]),.gap-0\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2px*var(--tw-space-y-reverse));margin-top:calc(2px*(1 - var(--tw-space-y-reverse)))}.col.gap-3px>:not([hidden])~:not([hidden]),.gap-3px.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(3px*var(--tw-space-y-reverse));margin-top:calc(3px*(1 - var(--tw-space-y-reverse)))}.col.gap-1>:not([hidden])~:not([hidden]),.gap-1.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.25rem*var(--tw-space-y-reverse));margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)))}.col.gap-1\.5>:not([hidden])~:not([hidden]),.gap-1\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(6px*var(--tw-space-y-reverse));margin-top:calc(6px*(1 - var(--tw-space-y-reverse)))}.col.gap-2>:not([hidden])~:not([hidden]),.gap-2.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.col.gap-2\.5>:not([hidden])~:not([hidden]),.gap-2\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(10px*var(--tw-space-y-reverse));margin-top:calc(10px*(1 - var(--tw-space-y-reverse)))}.col.gap-3>:not([hidden])~:not([hidden]),.gap-3.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.75rem*var(--tw-space-y-reverse));margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)))}.col.gap-3\.5>:not([hidden])~:not([hidden]),.gap-3\.5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(14px*var(--tw-space-y-reverse));margin-top:calc(14px*(1 - var(--tw-space-y-reverse)))}.col.gap-4>:not([hidden])~:not([hidden]),.gap-4.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.col.gap-5>:not([hidden])~:not([hidden]),.gap-5.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.col.gap-6>:not([hidden])~:not([hidden]),.gap-6.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.5rem*var(--tw-space-y-reverse));margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)))}.col.gap-7>:not([hidden])~:not([hidden]),.gap-7.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.75rem*var(--tw-space-y-reverse));margin-top:calc(1.75rem*(1 - var(--tw-space-y-reverse)))}.col.gap-8>:not([hidden])~:not([hidden]),.gap-8.flex-row>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.nav-item>a>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.25rem*var(--tw-space-x-reverse))}} \ No newline at end of file diff --git a/www/js/zui3/zui.zentao.js b/www/js/zui3/zui.zentao.js index 0685d1211c..d7b698c829 100644 --- a/www/js/zui3/zui.zentao.js +++ b/www/js/zui3/zui.zentao.js @@ -1,15 +1,15 @@ -var Ru=(I,nt,Nt)=>{if(!nt.has(I))throw TypeError("Cannot "+Nt)};var It=(I,nt,Nt)=>(Ru(I,nt,"read from private field"),Nt?Nt.call(I):nt.get(I)),jt=(I,nt,Nt)=>{if(nt.has(I))throw TypeError("Cannot add the same private member more than once");nt instanceof WeakSet?nt.add(I):nt.set(I,Nt)},Ut=(I,nt,Nt,sl)=>(Ru(I,nt,"write to private field"),sl?sl.call(I,Nt):nt.set(I,Nt),Nt);var Ou=(I,nt,Nt)=>(Ru(I,nt,"access private method"),Nt);(function(I,nt){typeof exports=="object"&&typeof module<"u"?nt(exports):typeof define=="function"&&define.amd?define(["exports"],nt):(I=typeof globalThis<"u"?globalThis:I||self,nt(I.zui={}))})(this,function(I){var Ta,Da,Cr,xr,Sr,kr,Tr,Dr,$a,Vg,Ia,Kg,Kn,qn;"use strict";const nt="",Nt="",sl="",uC="",dC="",fC="",pC="",mC="",gC="",yC="",vC="",_C="",Jg="3.0.0",Qg="production",fn=document,Ur=window,Hu=fn.documentElement,ss=fn.createElement.bind(fn),Bu=ss("div"),il=ss("table"),Zg=ss("tbody"),Uu=ss("tr"),{isArray:Wr,prototype:Wu}=Array,{concat:ey,filter:rl,indexOf:Vu,map:Ku,push:ty,slice:qu,some:ol,splice:ny}=Wu,sy=/^#(?:[\w-]|\\.|[^\x00-\xa0])*$/,iy=/^\.(?:[\w-]|\\.|[^\x00-\xa0])*$/,ry=/<.+>/,oy=/^\w+$/;function al(s,e){const t=ay(e);return!s||!t&&!is(e)&&!it(e)?[]:!t&&iy.test(s)?e.getElementsByClassName(s.slice(1).replace(/\\/g,"")):!t&&oy.test(s)?e.getElementsByTagName(s):e.querySelectorAll(s)}class Vr{constructor(e,t){if(!e)return;if(ll(e))return e;let n=e;if(bt(e)){const i=t||fn;if(n=sy.test(e)&&is(i)?i.getElementById(e.slice(1).replace(/\\/g,"")):ry.test(e)?Zu(e):ll(i)?i.find(e):bt(i)?y(i).find(e):al(e,i),!n)return}else if(rs(e))return this.ready(e);(n.nodeType||n===Ur)&&(n=[n]),this.length=n.length;for(let i=0,r=this.length;i{for(;e.firstChild;)e.removeChild(e.firstChild)})};function Kr(...s){const e=cy(s[0])?s.shift():!1,t=s.shift(),n=s.length;if(!t)return{};if(!n)return Kr(e,y,t);for(let i=0;i{it(r)&&dt(t,(o,a)=>{n?e?r.classList.add(a):r.classList.remove(a):r.classList.toggle(a)})})},ie.addClass=function(s){return this.toggleClass(s,!0)},ie.removeAttr=function(s){const e=qr(s);return this.each((t,n)=>{it(n)&&dt(e,(i,r)=>{n.removeAttribute(r)})})};function uy(s,e){if(s){if(bt(s)){if(arguments.length<2){if(!this[0]||!it(this[0]))return;const t=this[0].getAttribute(s);return Si(t)?void 0:t}return Et(e)?this:Si(e)?this.removeAttr(s):this.each((t,n)=>{it(n)&&n.setAttribute(s,e)})}for(const t in s)this.attr(t,s[t]);return this}}ie.attr=uy,ie.removeClass=function(s){return arguments.length?this.toggleClass(s,!1):this.attr("class","")},ie.hasClass=function(s){return!!s&&ol.call(this,e=>it(e)&&e.classList.contains(s))},ie.get=function(s){return Et(s)?qu.call(this):(s=Number(s),this[s<0?s+this.length:s])},ie.eq=function(s){return y(this.get(s))},ie.first=function(){return this.eq(0)},ie.last=function(){return this.eq(-1)};function dy(s){return Et(s)?this.get().map(e=>it(e)||ly(e)?e.textContent:"").join(""):this.each((e,t)=>{it(t)&&(t.textContent=s)})}ie.text=dy;function pn(s,e,t){if(!it(s))return;const n=Ur.getComputedStyle(s,null);return t?n.getPropertyValue(e)||void 0:n[e]||s.style[e]}function en(s,e){return parseInt(pn(s,e),10)||0}function Yu(s,e){return en(s,`border${e?"Left":"Top"}Width`)+en(s,`padding${e?"Left":"Top"}`)+en(s,`padding${e?"Right":"Bottom"}`)+en(s,`border${e?"Right":"Bottom"}Width`)}const hl={};function fy(s){if(hl[s])return hl[s];const e=ss(s);fn.body.insertBefore(e,null);const t=pn(e,"display");return fn.body.removeChild(e),hl[s]=t!=="none"?t:"block"}function Xu(s){return pn(s,"display")==="none"}function Ju(s,e){const t=s&&(s.matches||s.webkitMatchesSelector||s.msMatchesSelector);return!!t&&!!e&&t.call(s,e)}function Gr(s){return bt(s)?(e,t)=>Ju(t,s):rs(s)?s:ll(s)?(e,t)=>s.is(t):s?(e,t)=>t===s:()=>!1}ie.filter=function(s){const e=Gr(s);return y(rl.call(this,(t,n)=>e.call(t,n,t)))};function Nn(s,e){return e?s.filter(e):s}ie.detach=function(s){return Nn(this,s).each((e,t)=>{t.parentNode&&t.parentNode.removeChild(t)}),this};const py=/^\s*<(\w+)[^>]*>/,my=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,Qu={"*":Bu,tr:Zg,td:Uu,th:Uu,thead:il,tbody:il,tfoot:il};function Zu(s){if(!bt(s))return[];if(my.test(s))return[ss(RegExp.$1)];const e=py.test(s)&&RegExp.$1,t=Qu[e]||Qu["*"];return t.innerHTML=s,y(t.childNodes).detach().get()}y.parseHTML=Zu,ie.has=function(s){const e=bt(s)?(t,n)=>al(s,n).length:(t,n)=>n.contains(s);return this.filter(e)},ie.not=function(s){const e=Gr(s);return this.filter((t,n)=>(!bt(s)||it(n))&&!e.call(n,t,n))};function mn(s,e,t,n){const i=[],r=rs(e),o=n&&Gr(n);for(let a=0,l=s.length;ae.selected&&!e.disabled&&!e.parentNode.disabled),"value"):s.value||""}function gy(s){return arguments.length?this.each((e,t)=>{const n=t.multiple&&t.options;if(n||ud.test(t.type)){const i=Wr(s)?Ku.call(s,String):Si(s)?[]:[String(s)];n?dt(t.options,(r,o)=>{o.selected=i.indexOf(o.value)>=0},!0):t.checked=i.indexOf(t.value)>=0}else t.value=Et(s)||Si(s)?"":s}):this[0]&&ed(this[0])}ie.val=gy,ie.is=function(s){const e=Gr(s);return ol.call(this,(t,n)=>e.call(t,n,t))},y.guid=1;function tn(s){return s.length>1?rl.call(s,(e,t,n)=>Vu.call(n,e)===t):s}y.unique=tn,ie.add=function(s,e){return y(tn(this.get().concat(y(s,e).get())))},ie.children=function(s){return Nn(y(tn(mn(this,e=>e.children))),s)},ie.parent=function(s){return Nn(y(tn(mn(this,"parentNode"))),s)},ie.index=function(s){const e=s?y(s)[0]:this[0],t=s?this:y(e).parent().children();return Vu.call(t,e)},ie.closest=function(s){const e=this.filter(s);if(e.length)return e;const t=this.parent();return t.length?t.closest(s):e},ie.siblings=function(s){return Nn(y(tn(mn(this,e=>y(e).parent().children().not(e)))),s)},ie.find=function(s){return y(tn(mn(this,e=>al(s,e))))};const yy=/^\s*\s*$/g,vy=/^$|^module$|\/(java|ecma)script/i,_y=["type","src","nonce","noModule"];function by(s,e){const t=y(s);t.filter("script").add(t.find("script")).each((n,i)=>{if(vy.test(i.type)&&Hu.contains(i)){const r=ss("script");r.text=i.textContent.replace(yy,""),dt(_y,(o,a)=>{i[a]&&(r[a]=i[a])}),e.head.insertBefore(r,null),e.head.removeChild(r)}})}function wy(s,e,t,n,i){n?s.insertBefore(e,t?s.firstChild:null):s.nodeName==="HTML"?s.parentNode.replaceChild(e,s):s.parentNode.insertBefore(e,t?s:s.nextSibling),i&&by(e,s.ownerDocument)}function En(s,e,t,n,i,r,o,a){return dt(s,(l,c)=>{dt(y(c),(d,h)=>{dt(y(e),(p,m)=>{const v=t?h:m,w=t?m:h,x=t?d:p;wy(v,x?w.cloneNode(!0):w,n,i,!x)},a)},o)},r),e}ie.after=function(){return En(arguments,this,!1,!1,!1,!0,!0)},ie.append=function(){return En(arguments,this,!1,!1,!0)};function Cy(s){if(!arguments.length)return this[0]&&this[0].innerHTML;if(Et(s))return this;const e=/]/.test(s);return this.each((t,n)=>{it(n)&&(e?y(n).empty().append(s):n.innerHTML=s)})}ie.html=Cy,ie.appendTo=function(s){return En(arguments,this,!0,!1,!0)},ie.wrapInner=function(s){return this.each((e,t)=>{const n=y(t),i=n.contents();i.length?i.wrapAll(s):n.append(s)})},ie.before=function(){return En(arguments,this,!1,!0)},ie.wrapAll=function(s){let e=y(s),t=e[0];for(;t.children.length;)t=t.firstElementChild;return this.first().before(e),this.appendTo(t)},ie.wrap=function(s){return this.each((e,t)=>{const n=y(s)[0];y(t).wrapAll(e?n.cloneNode(!0):n)})},ie.insertAfter=function(s){return En(arguments,this,!0,!1,!1,!1,!1,!0)},ie.insertBefore=function(s){return En(arguments,this,!0,!0)},ie.prepend=function(){return En(arguments,this,!1,!0,!0,!0,!0)},ie.prependTo=function(s){return En(arguments,this,!0,!0,!0,!1,!1,!0)},ie.contents=function(){return y(tn(mn(this,s=>s.tagName==="IFRAME"?[s.contentDocument]:s.tagName==="TEMPLATE"?s.content.childNodes:s.childNodes)))},ie.next=function(s,e,t){return Nn(y(tn(mn(this,"nextElementSibling",e,t))),s)},ie.nextAll=function(s){return this.next(s,!0)},ie.nextUntil=function(s,e){return this.next(e,!0,s)},ie.parents=function(s,e){return Nn(y(tn(mn(this,"parentElement",!0,e))),s)},ie.parentsUntil=function(s,e){return this.parents(e,s)},ie.prev=function(s,e,t){return Nn(y(tn(mn(this,"previousElementSibling",e,t))),s)},ie.prevAll=function(s){return this.prev(s,!0)},ie.prevUntil=function(s,e){return this.prev(e,!0,s)},ie.map=function(s){return y(ey.apply([],Ku.call(this,(e,t)=>s.call(e,t,e))))},ie.clone=function(){return this.map((s,e)=>e.cloneNode(!0))},ie.offsetParent=function(){return this.map((s,e)=>{let t=e.offsetParent;for(;t&&pn(t,"position")==="static";)t=t.offsetParent;return t||Hu})},ie.slice=function(s,e){return y(qu.call(this,s,e))};const xy=/-([a-z])/g;function ul(s){return s.replace(xy,(e,t)=>t.toUpperCase())}ie.ready=function(s){const e=()=>setTimeout(s,0,y);return fn.readyState!=="loading"?e():fn.addEventListener("DOMContentLoaded",e),this},ie.unwrap=function(){return this.parent().each((s,e)=>{if(e.tagName==="BODY")return;const t=y(e);t.replaceWith(t.children())}),this},ie.offset=function(){const s=this[0];if(!s)return;const e=s.getBoundingClientRect();return{top:e.top+Ur.pageYOffset,left:e.left+Ur.pageXOffset}},ie.position=function(){const s=this[0];if(!s)return;const e=pn(s,"position")==="fixed",t=e?s.getBoundingClientRect():this.offset();if(!e){const n=s.ownerDocument;let i=s.offsetParent||n.documentElement;for(;(i===n.body||i===n.documentElement)&&pn(i,"position")==="static";)i=i.parentNode;if(i!==s&&it(i)){const r=y(i).offset();t.top-=r.top+en(i,"borderTopWidth"),t.left-=r.left+en(i,"borderLeftWidth")}}return{top:t.top-en(s,"marginTop"),left:t.left-en(s,"marginLeft")}};const td={class:"className",contenteditable:"contentEditable",for:"htmlFor",readonly:"readOnly",maxlength:"maxLength",tabindex:"tabIndex",colspan:"colSpan",rowspan:"rowSpan",usemap:"useMap"};ie.prop=function(s,e){if(s){if(bt(s))return s=td[s]||s,arguments.length<2?this[0]&&this[0][s]:this.each((t,n)=>{n[s]=e});for(const t in s)this.prop(t,s[t]);return this}},ie.removeProp=function(s){return this.each((e,t)=>{delete t[td[s]||s]})};const Sy=/^--/;function dl(s){return Sy.test(s)}const fl={},{style:ky}=Bu,Ty=["webkit","moz","ms"];function Dy(s,e=dl(s)){if(e)return s;if(!fl[s]){const t=ul(s),n=`${t[0].toUpperCase()}${t.slice(1)}`,i=`${t} ${Ty.join(`${n} `)}${n}`.split(" ");dt(i,(r,o)=>{if(o in ky)return fl[s]=o,!1})}return fl[s]}const $y={animationIterationCount:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0};function nd(s,e,t=dl(s)){return!t&&!$y[s]&&Gu(e)?`${e}px`:e}function Iy(s,e){if(bt(s)){const t=dl(s);return s=Dy(s,t),arguments.length<2?this[0]&&pn(this[0],s,t):s?(e=nd(s,e,t),this.each((n,i)=>{it(i)&&(t?i.style.setProperty(s,e):i.style[s]=e)})):this}for(const t in s)this.css(t,s[t]);return this}ie.css=Iy;function sd(s,e){try{return s(e)}catch{return e}}const Ny=/^\s+|\s+$/;function id(s,e){const t=s.dataset[e]||s.dataset[ul(e)];return Ny.test(t)?t:sd(JSON.parse,t)}function Ey(s,e,t){t=sd(JSON.stringify,t),s.dataset[ul(e)]=t}function My(s,e){if(!s){if(!this[0])return;const t={};for(const n in this[0].dataset)t[n]=id(this[0],n);return t}if(bt(s))return arguments.length<2?this[0]&&id(this[0],s):Et(e)?this:this.each((t,n)=>{Ey(n,s,e)});for(const t in s)this.data(t,s[t]);return this}ie.data=My;function rd(s,e){const t=s.documentElement;return Math.max(s.body[`scroll${e}`],t[`scroll${e}`],s.body[`offset${e}`],t[`offset${e}`],t[`client${e}`])}dt([!0,!1],(s,e)=>{dt(["Width","Height"],(t,n)=>{const i=`${e?"outer":"inner"}${n}`;ie[i]=function(r){if(this[0])return Rs(this[0])?e?this[0][`inner${n}`]:this[0].document.documentElement[`client${n}`]:is(this[0])?rd(this[0],n):this[0][`${e?"offset":"client"}${n}`]+(r&&e?en(this[0],`margin${t?"Top":"Left"}`)+en(this[0],`margin${t?"Bottom":"Right"}`):0)}})}),dt(["Width","Height"],(s,e)=>{const t=e.toLowerCase();ie[t]=function(n){if(!this[0])return Et(n)?void 0:this;if(!arguments.length)return Rs(this[0])?this[0].document.documentElement[`client${e}`]:is(this[0])?rd(this[0],e):this[0].getBoundingClientRect()[t]-Yu(this[0],!s);const i=parseInt(n,10);return this.each((r,o)=>{if(!it(o))return;const a=pn(o,"boxSizing");o.style[t]=nd(t,i+(a==="border-box"?Yu(o,!s):0))})}});const od="___cd";ie.toggle=function(s){return this.each((e,t)=>{if(!it(t))return;const n=Xu(t);(Et(s)?n:s)?(t.style.display=t[od]||"",Xu(t)&&(t.style.display=fy(t.tagName))):n||(t[od]=pn(t,"display"),t.style.display="none")})},ie.hide=function(){return this.toggle(!1)},ie.show=function(){return this.toggle(!0)};const ad="___ce",pl=".",ml={focus:"focusin",blur:"focusout"},ld={mouseenter:"mouseover",mouseleave:"mouseout"},Ay=/^(mouse|pointer|contextmenu|drag|drop|click|dblclick)/i;function gl(s){return ld[s]||ml[s]||s}function yl(s){const e=s.split(pl);return[e[0],e.slice(1).sort()]}ie.trigger=function(s,e){if(bt(s)){const[n,i]=yl(s),r=gl(n);if(!r)return this;const o=Ay.test(r)?"MouseEvents":"HTMLEvents";s=fn.createEvent(o),s.initEvent(r,!0,!0),s.namespace=i.join(pl),s.___ot=n}s.___td=e;const t=s.___ot in ml;return this.each((n,i)=>{t&&rs(i[s.___ot])&&(i[`___i${s.type}`]=!0,i[s.___ot](),i[`___i${s.type}`]=!1),i.dispatchEvent(s)})};function cd(s){return s[ad]=s[ad]||{}}function Py(s,e,t,n,i){const r=cd(s);r[e]=r[e]||[],r[e].push([t,n,i]),s.addEventListener(e,i)}function hd(s,e){return!e||!ol.call(e,t=>s.indexOf(t)<0)}function Yr(s,e,t,n,i){const r=cd(s);if(e)r[e]&&(r[e]=r[e].filter(([o,a,l])=>{if(i&&l.guid!==i.guid||!hd(o,t)||n&&n!==a)return!0;s.removeEventListener(e,l)}));else for(e in r)Yr(s,e,t,n,i)}ie.off=function(s,e,t){if(Et(s))this.each((n,i)=>{!it(i)&&!is(i)&&!Rs(i)||Yr(i)});else if(bt(s))rs(e)&&(t=e,e=""),dt(qr(s),(n,i)=>{const[r,o]=yl(i),a=gl(r);this.each((l,c)=>{!it(c)&&!is(c)&&!Rs(c)||Yr(c,a,o,e,t)})});else for(const n in s)this.off(n,s[n]);return this},ie.remove=function(s){return Nn(this,s).detach().off(),this},ie.replaceWith=function(s){return this.before(s).remove()},ie.replaceAll=function(s){return y(s).replaceWith(this),this};function Ly(s,e,t,n,i){if(!bt(s)){for(const r in s)this.on(r,e,t,s[r],i);return this}return bt(e)||(Et(e)||Si(e)?e="":Et(t)?(t=e,e=""):(n=t,t=e,e="")),rs(n)||(n=t,t=void 0),n?(dt(qr(s),(r,o)=>{const[a,l]=yl(o),c=gl(a),d=a in ld,h=a in ml;c&&this.each((p,m)=>{if(!it(m)&&!is(m)&&!Rs(m))return;const v=function(w){if(w.target[`___i${w.type}`])return w.stopImmediatePropagation();if(w.namespace&&!hd(l,w.namespace.split(pl))||!e&&(h&&(w.target!==m||w.___ot===c)||d&&w.relatedTarget&&m.contains(w.relatedTarget)))return;let x=m;if(e){let D=w.target;for(;!Ju(D,e);)if(D===m||(D=D.parentNode,!D))return;x=D}Object.defineProperty(w,"currentTarget",{configurable:!0,get(){return x}}),Object.defineProperty(w,"delegateTarget",{configurable:!0,get(){return m}}),Object.defineProperty(w,"data",{configurable:!0,get(){return t}});const S=n.call(x,w,w.___td);i&&Yr(m,c,l,e,v),S===!1&&(w.preventDefault(),w.stopPropagation())};v.guid=n.guid=n.guid||y.guid++,Py(m,c,l,e,v)})}),this):this}ie.on=Ly;function Ry(s,e,t,n){return this.on(s,e,t,n,!0)}ie.one=Ry;const Oy=/\r?\n/g;function zy(s,e){return`&${encodeURIComponent(s)}=${encodeURIComponent(e.replace(Oy,`\r -`))}`}const Fy=/file|reset|submit|button|image/i,ud=/radio|checkbox/i;ie.serialize=function(){let s="";return this.each((e,t)=>{dt(t.elements||[t],(n,i)=>{if(i.disabled||!i.name||i.tagName==="FIELDSET"||Fy.test(i.type)||ud.test(i.type)&&!i.checked)return;const r=ed(i);if(!Et(r)){const o=Wr(r)?r:[r];dt(o,(a,l)=>{s+=zy(i.name,l)})}})}),s.slice(1)},window.$=y;function dd(s,e){if(s==null)return[s,void 0];typeof e=="string"&&(e=e.split("."));const t=e.join(".");let n=s;const i=[n];for(;typeof n=="object"&&n!==null&&e.length;){let r=e.shift(),o;const a=r.indexOf("[");if(a>0&&a{const i=t[n]??"";s=s.replace(new RegExp(`\\{${n}\\}`,"g"),`${i}`)}),s}for(let t=0;t(s[s.B=1]="B",s[s.KB=1024]="KB",s[s.MB=1048576]="MB",s[s.GB=1073741824]="GB",s[s.TB=1099511627776]="TB",s))(vl||{});function pt(s,e=2,t){return Number.isNaN(s)?"?KB":(t||(s<1024?t="B":s<1048576?t="KB":s<1073741824?t="MB":s<1099511627776?t="GB":t="TB"),(s/vl[t]).toFixed(e)+t)}const gn=s=>{const e=/^[0-9]*(B|KB|MB|GB|TB)$/;s=s.toUpperCase(),s.endsWith("B")||(s+="B");const t=s.match(e);if(!t)return 0;const n=t[1];return s=s.replace(n,""),Number.parseInt(s,10)*vl[n]};let _l=(document.documentElement.getAttribute("lang")||"zh_cn").toLowerCase().replace("-","_"),yn;function fd(){return _l}function Hy(s){_l=s.toLowerCase().replace("-","_")}function pd(s,e){yn||(yn={}),typeof s=="string"&&(s={[s]:e??{}}),y.extend(!0,yn,s)}function Ne(s,e,t,n,i,r){Array.isArray(s)?yn&&s.unshift(yn):s=yn?[yn,s]:[s],typeof t=="string"&&(r=i,i=n,n=t,t=void 0);const o=i||_l;let a;for(const l of s){if(!l)continue;const c=l[o]||l.default;if(!c)continue;const d=r&&l===yn?`${r}.${e}`:e;if(a=ki(c,d),a!==void 0)break}return a===void 0?n:t?be(a,...Array.isArray(t)?t:[t]):a}function By(s,e,t,n){return Ne(void 0,s,e,t,n)}Ne.addLang=pd,Ne.getLang=By,Ne.getCode=fd,Ne.setCode=Hy,Ne.map=yn,pd({zh_cn:{confirm:"确定",save:"保存",cancel:"取消",delete:"删除",reset:"重置",add:"添加",copy:"复制",close:"关闭"},zh_tw:{confirm:"確定",save:"儲存",cancel:"取消",delete:"刪除",reset:"重置",add:"添加",Copy:"複製",close:"關閉"},en:{confirm:"Confirm",save:"Save",cancel:"Cancel",delete:"Delete",reset:"Reset",add:"Add",copy:"Copy",close:"Close"}});function os(s,e,t){t!=null&&(Array.isArray(t)?t.forEach(n=>os(s,e,n)):!(t instanceof Blob)&&y.isPlainObject(t)?Object.entries(t).forEach(([n,i])=>{os(s,`${e}[${n}]`,i)}):s.append(e,t instanceof Blob?t:String(t)))}function Xr(s,e){const t=e||new FormData;return s&&(typeof s=="string"&&(s=new URLSearchParams(s)),s instanceof URLSearchParams?s.forEach((n,i)=>{os(t,i,n)}):Array.isArray(s)?s.forEach(([n,i])=>{os(t,n,i)}):s instanceof FormData?s.forEach((n,i)=>{os(t,i,n)}):typeof s=="object"&&s&&Object.entries(s).forEach(([n,i])=>{os(t,n,i)})),t}function md(s,e,t){s instanceof Headers?s.set(e,t):Array.isArray(s)?s.push([e,t]):s[e]=t}function Uy(s,e){if(s){const t={text:"text/plain",html:"text/html",json:"application/json",...e};for(const[n,i]of Object.entries(t))if(i.split(",").map(r=>r.trim()).includes(s))return n}return"text"}class Ti{get completed(){return this.data!==void 0||this.error!==void 0}get[Symbol.toStringTag](){return"Ajax"}constructor(e){this.setting=e,this._controller=new AbortController,this._callbacks={success:[],error:[],complete:[]}}on(e,t){return this._callbacks[e].push(t),this}success(e){return this.on("success",e)}done(e){return this.success(e)}fail(e){return this.on("error",e)}complete(e){return this.on("complete",e)}always(e){return this.complete(e)}then(e,t){return this.completed?t&&this.error?t(this.error):e(this.data):(this.success(n=>e(n)),t&&this.fail(t)),this}catch(e){return this.error?(e(this.error),this):this.on("error",t=>e(t))}finally(e){return this.completed?(e(),this):this.complete(()=>e())}abort(e){return this.completed?!1:(this._abortError=e,this._controller.abort(),!0)}getResponseHeader(e){var t;return(t=this.response)==null?void 0:t.headers.get(e)}_init(){if(this.completed)return;const{url:e,type:t,data:n,processData:i=!0,contentType:r,crossDomain:o,accepts:a,dataType:l,timeout:c,dataFilter:d,beforeSend:h,success:p,error:m,complete:v,...w}=this.setting;t&&(w.method=t);let x=n;x&&(i&&(x=Xr(x)),w.body=x),o&&(w.mode="cors");const S=w.headers||{};md(S,"X-Requested-With","XMLHttpRequest"),r&&md(S,"Content-Type",r),w.headers=S,w.signal&&w.signal.addEventListener("abort",()=>{this.abort()});const D=[...this.constructor.globalBeforeSends,h];for(const M of D){if(!M)continue;const P=M.call(this,w);if(P===!1)return;P&&Object.assign(w,P)}p&&this.success(p),m&&this.fail(m),v&&this.complete(v),w.signal=this._controller.signal,this.url=e,this.request=w}_emit(e,...t){this._callbacks[e].forEach(n=>{n.call(this,...t)})}async send(){var d;if(this.completed)return[];this._init();const{timeout:e,dataType:t,accepts:n,dataFilter:i,throws:r,jsonParser:o}=this.setting;e&&(this._timeoutID=window.setTimeout(()=>{this.abort(new Error("timeout"))},e));let a,l,c;try{a=await fetch(this.url,this.request),this.response=a;const{statusText:h}=a;if(a.ok){const p=(d=a.headers.get("Content-Disposition"))==null?void 0:d.startsWith("attachment"),m=p?"blob":t||Uy(a.headers.get("Content-Type"),n);p||m==="blob"||m==="file"?c=await a.blob():m==="json"?typeof o=="function"?(c=await a.text(),c=o(c)):c=await a.json():c=await a.text(),this.data=c;const v=(i==null?void 0:i(c,m))??c;this._emit("success",v,h,a)}else throw this.data=await a.text(),new Error(h)}catch(h){this.data===void 0&&c!==void 0&&(this.data=c),l=h;let p=!1;l.name==="AbortError"&&(this._abortError?l=this._abortError:p=!0),this.error=l,p||this._emit("error",l,a==null?void 0:a.statusText,l.message)}if(this._timeoutID&&clearTimeout(this._timeoutID),this._emit("complete",a,a==null?void 0:a.statusText),l&&r)throw l;return[c,l,a]}}Ti.globalBeforeSends=[],y.ajax=(s,e)=>{e=e||{},typeof s=="string"?e.url=s:y.extend(e,s);const t=new Ti(e);return t.send(),t},y.getJSON=(s,e,t)=>(typeof e=="function"&&(t=e,e=void 0),y.ajax({url:s,data:e,success:t,dataType:"json"})),y.get=(s,e,t,n,i="GET")=>{let r,o;return typeof e=="function"?(r=e,o=void 0):o=e,typeof t=="function"?(r=t,n=void 0):n=t,y.ajax({method:i,url:s,data:o,success:r,dataType:n})},y.post=(s,e,t,n)=>y.get(s,e,t,n,"POST"),y.fn.load=function(s,e,t){typeof e=="function"&&(t=e,e=void 0);const[n,i]=s.split(" ");return y.get(n,e,(r,o,a)=>{i&&(r=y(r).find(i).html()),y(this).html(r).zuiInit(),t==null||t.call(this,r,o,a)},"html"),this};async function mt(s,e=[],t,n,i){const r={throws:!0,dataType:"json"};if(typeof s=="string")r.url=s;else if(typeof s=="object")y.extend(r,s);else if(typeof s=="function"){const l=s.call(n,...e);return l instanceof Promise?await l:l}t&&y.extend(r,typeof t=="function"?t(r):t),r.url&&(r.url=be(r.url,...e));const o=new Ti(r);i==null||i(o);const[a]=await o.send();return a}function bl(s){return!!(s&&(typeof s=="string"||typeof s=="object"&&s.url||typeof s=="function"))}y.fetch=mt;function wt(){return y.guid++}function Jr(s,e){if(s===e)return!1;if(s&&e){const t=typeof s,n=typeof e;if(t!==n)return!0;if(t==="object"&&n==="object"){const i=Array.isArray(s),r=Array.isArray(e);if(i!==r)return!0;if(i&&r){if(s.length!==e.length)return!0;for(let l=0;ln instanceof as?n.value!==t[i]:Jr(n,t[i])))&&(this._value=this._compute(),this._lastDependencies=e.map(n=>n instanceof as?n.cache:n)),this._value}}function wl(...s){const e=[],t=new Map,n=(i,r)=>{if(Array.isArray(i)&&(r=i[1],i=i[0]),!i.length)return;const o=t.get(i);typeof o=="number"?e[o][1]=!!r:(t.set(i,e.length),e.push([i,!!r]))};return s.forEach(i=>{typeof i=="function"&&(i=i()),Array.isArray(i)?wl(...i).forEach(n):i&&typeof i=="object"?Object.entries(i).forEach(n):typeof i=="string"&&i.split(" ").forEach(r=>n(r,!0))}),e.sort((i,r)=>(t.get(i[0])||0)-(t.get(r[0])||0))}const V=(...s)=>wl(...s).reduce((e,[t,n])=>(n&&e.push(t),e),[]).join(" ");y.classes=V,y.fn.setClass=function(s,...e){return this.each((t,n)=>{const i=y(n);s===!0?i.attr("class",V(i.attr("class"),...e)):i.addClass(V(s,...e))})};const Os=new WeakMap;function Qr(s,e,t){const n=Os.has(s),i=n?Os.get(s):{};typeof e=="string"?i[e]=t:e===null?Object.keys(i).forEach(r=>{delete i[r]}):Object.assign(i,e),Object.keys(i).forEach(r=>{i[r]===void 0&&delete i[r]}),Object.keys(i).length?(!n&&s instanceof Element&&Object.assign(i,y(s).dataset(),i),Os.set(s,i)):Os.delete(s)}function Di(s,e,t){let n=Os.get(s)||{};return t&&s instanceof Element&&(n=Object.assign({},y(s).dataset(),n)),e===void 0?n:n[e]}function Wy(s){Os.delete(s)}y.fn.dataset=y.fn.data,y.fn.data=function(...s){const[e,t]=s;return!s.length||s.length===1&&typeof e=="string"?this.length?Di(this[0],e,!0):void 0:this.each((n,i)=>Qr(i,e,t))},y.fn.removeData=function(s=null){return this.each((e,t)=>Qr(t,s))};function ls(s,...e){return s.includes("RAWJS")&&(s=s.split('"RAWJS<').join("").split('>RAWJS"').join("").split("").join('"').split("").join(` -`)),new Function(`return ${s}`)(...e)}function Cl(s,...e){return s.includes("RAWJS")?ls(s,...e):JSON.parse(s)}function Vy(s){return JSON.stringify(s,(e,t)=>{if(typeof t=="function")return`RAWJS<${t.toString().split('"').join("").split(` -`).join("")}>RAWJS`})}function zs(s,e){const t=y(s)[0];if(!t)return;const{prefix:n,getter:i,evalValue:r,json:o=!0,evalArgs:a=[]}={prefix:"z-",...typeof e=="string"?{prefix:e}:e},l=Array.isArray(r)?new Set(r):void 0;return Array.from(t.attributes).reduce((c,d)=>{let{name:h}=d;const{value:p}=d;let m=p;if(h.startsWith(n)){if(h=h.slice(n.length).replace(/-([a-z])/g,v=>v[1].toUpperCase()),i)m=i(h,p);else try{r&&(!l||l.has(h))||r===void 0&&p.includes("RAWJS")?m=ls(p,...a):o&&(m=JSON.parse(p))}catch{}c[h]=m}return c},{})}function xl(s,e,t="z-"){const n=y(s);Object.keys(e).forEach(i=>{let r=e[i];typeof r=="function"&&(r=`RAWJS<${r}>RAWJS`),typeof r!="string"&&(r=JSON.stringify(r)),i=i.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`),n.attr(`${t}${i}`,r)})}function Ky(...s){var t;const e=s.length;if(!e)return zs(this);if(e===1){const[n]=s;return typeof n=="string"?(t=zs(this))==null?void 0:t[n]:(y.isPlainObject(n)&&xl(this,n),this)}return xl(this,{[s[0]]:s[1]}),this}y.fn.z=Ky,y.fn._attr=y.fn.attr,y.fn.extend({attr(...s){const[e,t]=s;return!s.length||s.length===1&&typeof e=="string"?this._attr.apply(this,s):typeof e=="object"?(e&&Object.keys(e).forEach(n=>{const i=e[n];i===null?this.removeAttr(n):this._attr(n,i)}),this):t===null?this.removeAttr(e):this._attr(e,t)}}),y.Event||(y.Event=(s,e)=>{const[t,...n]=s.split("."),i=new Event(t,{bubbles:!0,cancelable:!0});return i.namespace=n.join("."),i.___ot=t,i.___td=e,i});const cs=(s,e)=>new Promise(t=>{const n=window.setTimeout(t,s);e&&e(n)}),gd={};y.share=gd;var Zr,He,yd;I.isValidElement=void 0;var hs,vd,_d,Sl,kl,Tl,Dl,$i={},bd=[],qy=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,eo=Array.isArray;function An(s,e){for(var t in e)s[t]=e[t];return s}function wd(s){s&&s.parentNode&&s.parentNode.removeChild(s)}function b(s,e,t){var n,i,r,o={};for(r in e)r=="key"?n=e[r]:r=="ref"?i=e[r]:o[r]=e[r];if(arguments.length>2&&(o.children=arguments.length>3?Zr.call(arguments,2):t),typeof s=="function"&&s.defaultProps!=null)for(r in s.defaultProps)o[r]===void 0&&(o[r]=s.defaultProps[r]);return to(s,o,n,i,null)}function to(s,e,t,n,i){var r={type:s,props:e,key:t,ref:n,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,constructor:void 0,__v:i??++yd,__i:-1,__u:0};return i==null&&He.vnode!=null&&He.vnode(r),r}function ue(){return{current:null}}function vn(s){return s.children}function pe(s,e){this.props=s,this.context=e}function Fs(s,e){if(e==null)return s.__?Fs(s.__,s.__i+1):null;for(var t;ee&&hs.sort(Sl));no.__r=0}function Sd(s,e,t,n,i,r,o,a,l,c,d){var h,p,m,v,w,x=n&&n.__k||bd,S=e.length;for(t.__d=l,Gy(t,e,x),l=t.__d,h=0;h0?to(i.type,i.props,i.key,i.ref?i.ref:null,i.__v):i).__=s,i.__b=s.__b+1,r=null,(a=i.__i=Yy(i,t,o,d))!==-1&&(d--,(r=t[a])&&(r.__u|=131072)),r==null||r.__v===null?(a==-1&&h--,typeof i.type!="function"&&(i.__u|=65536)):a!==o&&(a==o-1?h--:a==o+1?h++:(a>o?h--:h++,i.__u|=65536))):i=s.__k[n]=null;if(d)for(n=0;n(l!=null&&!(131072&l.__u)?1:0))for(;o>=0||a=0){if((l=e[o])&&!(131072&l.__u)&&i==l.key&&r===l.type)return o;o--}if(a{!t||typeof t!="object"||Object.keys(t).forEach(n=>{let i=t[n];const r=s[n];i!==r&&(r!==void 0&&(n==="className"||n.endsWith("Class")?i=[r,i]:n==="children"?i=[...so(r),...so(i)]:typeof r=="object"&&(n==="style"||n.endsWith("Style")||n==="attrs"||n.endsWith("Attrs")||n==="props")&&(i=y.extend(r,i))),s[n]=i)})}),s}function Nl(s){return Object.keys(s).forEach(e=>{s[e]===void 0&&delete s[e]}),s}function Nd(s,e=!0){const t=y(s),n=t[0],i="zui-disable-scroll";if(e){if(t.data(i))return;if((t.css("scrollbar-gutter")||"").includes("stable")){t.data(i,{overflow:t.css("overflow")}).css("overflow","hidden");return}const r=n===document.body||t.is("html")?window.innerWidth-document.body.clientWidth:n.offsetWidth-n.clientWidth;if(!r)return;const o=t.css("paddingRight")||"0";t.data(i,{paddingRight:o,overflow:t.css("overflow")}).css({paddingRight:`${r+Number.parseInt(o,10)}px`,overflow:"hidden"})}else{const r=t.data(i);if(!r)return;t.css(r).removeData(i)}}y.fn.disableScroll=function(s=!0){return this.each((e,t)=>{Nd(t,s)})},y.fn.enableScroll=function(s=!0){return this.disableScroll(!s)};function El(s,e,t){if(!(t.on||"click").split(" ").includes(e.type))return;const n=t.selector?y(e.target).closest(t.selector):s;if(!n.length)return;const i=c=>c===""?!0:c,r=c=>{if(typeof c=="string")try{c=JSON.parse(c)}catch{}return c};if(i(t.once)){if(t.onceCalled)return;s.dataset("once-called",!0)}if(i(t.prevent)&&e.preventDefault(),i(t.stop)&&e.stopPropagation(),i(t.self)&&e.currentTarget!==e.target)return;const o=[["$element",s],["event",e],["options",t],["$target",n]],a=c=>typeof c=="function"?c(...o):y.runJS(c,...o);if(t.if!==void 0&&!a(t.if))return;const l=t.call;if(l){let c;if(typeof l=="string"?c=/^[$A-Z_][0-9A-Z_$.]*$/i.test(l)?ki(window,l):a(l):c=l,typeof c=="function"){const d=[],h=t.params;t.params=d,typeof h=="string"&&h.length?h[0]==="["?d.push(...r(h)):d.push(...h.split(", ").map(p=>(p=p.trim(),p==="$element"?s:p==="event"?e:p==="options"?t:p.startsWith("$element.")||p.startsWith("event.")||p.startsWith("options.")?a(p):r(p)))):Array.isArray(h)?d.push(...h):d.push(h),c(...d)}}t.do&&a(t.do)}function Qy(s){const e=y(this),t=s.type,n=e.attr("zui-on");if(n){const[o,a]=n.split("~").map(l=>l.trim());o&&o.split(" ").includes(t)&&El(e,s,y.extend({on:o},a?a.startsWith("{")?ls(a):{do:a}:zs(e,{prefix:"data-",evalValue:["call","if","do"]})))}const i=e.attr(`zui-on-${t}`);i&&El(e,s,y.extend({on:t},i.startsWith("{")?ls(i):{do:i}));const r=e.attr("data-on");r&&r.split(" ").includes(t)&&El(e,s,zs(e,{prefix:"data-",evalValue:["call","if","do"]}))}function Ed(s){y(document).off(".zui.global").on(s.map(e=>`${e}.zui.global`).join(" "),`[zui-on],${s.map(e=>`[zui-on-${e}]`)},[data-on]`,Qy)}y(()=>{Ed(["click","change","inited"])});function ds(s,e){if(typeof s=="function")return ds(s(...e||[]));if(typeof s=="number")return[s];let t=s.match(/(\d+)(%|px)?/);return t?[parseInt(t[1]),t[2]]:(t=s.match(/(\d+)\/(\d+)/),t?[100*parseInt(t[1])/parseInt(t[2]),"%"]:[NaN])}function qe(s,e){if(s==null)return null;const[t,n="px"]=ds(s,e);return Number.isNaN(t)?typeof s=="string"?s:null:`${t}${n}`}async function js(s,e){var n,i,r;if(s instanceof Blob){const o=document.createElement("a");return o.href=window.URL.createObjectURL(s),e&&(o.download=decodeURIComponent(e)),o.click(),o.remove(),s}if(s instanceof Response){const o=await s.blob();return e=e||((r=(i=(n=s.headers.get("Content-Disposition"))==null?void 0:n.split(";")[1])==null?void 0:i.split("=")[1])==null?void 0:r.replace(/"/g,"")),js(o,e)}const t=await fetch(s);return js(t)}class Md{constructor(e){this._$target=y(e)}on(...e){return this._$target.on(...e),this}one(...e){return this._$target.one(...e),this}off(...e){return this._$target.off(...e),this}trigger(...e){return this._$target.trigger(...e),this}}const nn=new Md(document);y.bus=nn,y.on=nn.on.bind(nn),y.one=nn.one.bind(nn),y.off=nn.off.bind(nn),y.trigger=nn.trigger.bind(nn);var Zy=["Shift","Meta","Alt","Control"],Ad=typeof navigator=="object"?navigator.platform:"",Pd=/Mac|iPod|iPhone|iPad/.test(Ad),ev=Pd?"Meta":"Control",tv=Ad==="Win32"?["Control","Alt"]:Pd?["Alt"]:[];function Ml(s,e){return typeof s.getModifierState=="function"&&(s.getModifierState(e)||tv.includes(e)&&s.getModifierState("AltGraph"))}function nv(s){return s.trim().split(" ").map(function(e){var t=e.split(/\b\+/),n=t.pop();return[t=t.map(function(i){return i==="$mod"?ev:i}),n]})}function Ld(s,e){var t;e===void 0&&(e={});var n=(t=e.timeout)!=null?t:1e3,i=Object.keys(s).map(function(a){return[nv(a),s[a]]}),r=new Map,o=null;return function(a){a instanceof KeyboardEvent&&(i.forEach(function(l){var c=l[0],d=l[1],h=r.get(c)||c;(function(p,m){return!(m[1].toUpperCase()!==p.key.toUpperCase()&&m[1]!==p.code||m[0].find(function(v){return!Ml(p,v)})||Zy.find(function(v){return!m[0].includes(v)&&m[1]!==v&&Ml(p,v)}))})(a,h[0])?h.length>1?r.set(c,h.slice(1)):(r.delete(c),d(a)):Ml(a,a.key)||r.delete(c)}),o&&clearTimeout(o),o=setTimeout(r.clear.bind(r),n))}}function sv(s,e,t){var n;t===void 0&&(t={});var i=(n=t.event)!=null?n:"keydown",r=Ld(e,t);return s.addEventListener(i,r),function(){s.removeEventListener(i,r)}}function Al(s,e={}){if(!s)return;const t=Object.keys(e).reduce((n,i)=>(e[i].optional||(n[i]={...e[i]}),n),{});return Object.keys(s).forEach(n=>{const i=s[n];i?i===!0?e[n]&&(t[n]={...e[n]}):t[n]=i:delete t[n]}),Object.keys(t).reduce((n,i)=>{const{keys:r,handler:o}=t[i];return typeof r=="string"?n[r]=o:r.forEach(a=>{n[a]=o}),n},{})}function Pl(s,e,t){const{timeout:n,event:i="keydown",scope:r,when:o}=t||{},a=Ld(e,{timeout:n}),l=`.zui.hotkeys${r?`.${r}`:""}`,c="zui-hotkeys-composing";return y(s).on(`${i}${l}`,function(d){o&&o(d)===!1||y(d.target).data(c)||a(d)}).on(`compositionstart${l}`,d=>{y(d.target).data(c,!0)}).on(`compositionend${l}`,d=>{y(d.target).removeData(c)})}function Ll(s,e){return y(s).off(`.zui.hotkeys${e?`.${e}`:""}`)}const iv=sv;y.fn.hotkeys=function(s,e){return Pl(this,s,e)},y.fn.unbindHotkeys=function(s){return Ll(this,s)},y.hotkeys=function(s,e){Pl(window,s,e)},y.unbindHotkeys=function(s){Ll(window,s)};function ro(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement}async function Rd(s){(typeof s=="string"||s instanceof Element||s instanceof y)&&(s={target:s});const{target:e,onError:t,onSuccess:n,afterExit:i,afterEnter:r}=s,o=y(e),a=o[0];if(!a)return;const l=a.requestFullscreen||a.webkitRequestFullscreen||a.mozRequestFullScreen;if(!l){t==null||t.call(a,new Error("[ZUI] The browser does not support full screen feature."));return}try{await l.call(a),n==null||n.call(a),y(a).off(".zui.fullscreen"),i&&o.on("exitFullscreen.zui.fullscreen",i),r&&o.on("enterFullscreen.zui.fullscreen",r)}catch(c){t==null||t.call(a,c)}document.zuiBindFullscreenChange||(document.zuiBindFullscreenChange=!0,y(document).on("fullscreenchange.zui webkitfullscreenchange.zui mozfullscreenchange.zui",c=>{const d=ro();let h=d;d?y(d).addClass("is-in-fullscreen"):(h=y(document).find(".is-in-fullscreen")[0]||document,y(h).removeClass("is-in-fullscreen")),y("body").toggleClass("has-in-fullscreen",!!d);const p={event:c,target:h,fullscreenElement:d};y(h).trigger(d?"enterFullscreen":"exitFullscreen",p).trigger("toggleFullscreen",p)}))}async function Rl(s){const e=ro();return s===!1&&!!e===s?s:e?(document.exitFullscreen(),!1):(await Rd(s),!0)}y.fn.fullscreen=function(s){return Rl({target:this,...s})},y.getFullscreenElement=ro,y.toggleFullscreen=Rl;function Pn(s){return!s||s.parentNode===document?!1:s.parentNode?Pn(s.parentNode):!0}y.isDetached=Pn,y.fn.isDetached=function(){const s=this[0];return!s||Pn(s)};const fs=class Fg{constructor(e,t){var v;this._inited=!1,this._autoDestory=0,this._destroyed=!1;const{KEY:n,DATA_KEY:i,MULTI_INSTANCE:r,NAME:o,ATTR_KEY:a,ALL:l,TYPED_ALL:c}=this.constructor;if(!o)throw new Error('[ZUI] The component must have a "NAME" static property.');const d=y(e);if(d.data(n)&&!r)throw new Error(`[ZUI] The component "${o}" has been initialized on element.`);const h=d[0],p=wt();this._gid=p,this._element=h,this.resetOptions(t),this._key=this.options.key??`__${p}`;let m=l.get(h);if(m?m.add(this):(m=new Set([this]),l.set(h,m)),c.has(o)?c.get(o).add(this):c.set(o,new Set([this])),d.data(n,this).attr(a,"").attr(i,`${p}`).attr("z-use",[...new Set([...m].map(w=>w.constructor.NAME))].join(",")),r){const w=`${n}:ALL`;let x=d.data(w);x||(x=new Map,d.data(w,x)),x.set(this._key,this)}this.init(),(v=this.options.$onCreate)==null||v.call(this),requestAnimationFrame(async()=>{var w;this._inited=!0,await this.afterInit(),this.emit("inited",this.options),(w=this.options.$onInited)==null||w.call(this)})}static get ZUI(){return this.NAME.replace(/(^[A-Z]+)/,e=>e.toLowerCase())}static get KEY(){return`zui.${this.NAME}`}static get NAMESPACE(){return`.zui.${this.ZUI}`}static get DATA_KEY(){return`data-zui-${this.NAME}`}static get ATTR_KEY(){return`z-use-${this.NAME}`}static get SELECTOR(){return`[${this.DATA_KEY}]`}get inited(){return this._inited}get destroyed(){return this._destroyed}get element(){return this._element}get key(){return this._key}get options(){return this._options}get gid(){return this._gid}get $element(){return y(this.element)}get $emitter(){return this.$element}get i18nData(){return[this.options.i18n,this.constructor.i18n]}init(){}afterInit(){}render(e,t){this.setOptions(e,t)}destroy(){var m;const{KEY:e,DATA_KEY:t,ALL:n,TYPED_ALL:i,NAME:r,MULTI_INSTANCE:o,ATTR_KEY:a}=this.constructor,{$element:l,element:c}=this;if(this.emit("destroyed"),this._destroyed=!0,l.off(this.namespace).removeData(e).removeAttr(a).removeAttr(t),o){const v=this.$element.data(`${e}:ALL`);if(v)if(v.delete(this._key),v.size===0)this.$element.removeData(`${e}:ALL`);else{const w=v.values().next().value;l.data(e,w).attr(t,String(w==null?void 0:w.gid))}}const d=n.get(c);d&&(d.delete(this),d.size===0&&n.delete(c));const h=i.get(r);h&&(h.delete(this),h.size===0&&i.delete(r));const p=n.get(c);p!=null&&p.size?l.attr("z-use",[...new Set([...p].map(v=>v.constructor.NAME))].join(",")):l.removeAttr("z-use"),(m=this.options.$onDestroy)==null||m.call(this)}autoDestroy(e=100){this._autoDestory&&clearTimeout(this._autoDestory),this._autoDestory=window.setTimeout(()=>{this._autoDestory=0,Pn(this.element)&&this.destroy()},e)}setOptions(e,t){if(t){const n={...this.constructor.DEFAULT,...(e==null?void 0:e.$optionsFromDataset)!==!1?this.$element.dataset():{},...e},{$options:i}=n;if(i){const r=typeof i=="function"?i.call(this,this.element,n):i;r&&y.extend(n,r),delete n.$options}this._options=n}else e&&y.extend(this._options,e);return this._options}resetOptions(e){return this.setOptions(e,!0)}emit(e,...t){const n=y.Event(e);return n.__src=this,this.$emitter.trigger(n,[this,...t]),n}on(e,t,n){const i=this;this.$element[n!=null&&n.once?"one":"on"](this._wrapEvent(e),function(r,o){(!r.__src||r.__src===i)&&t.call(this,r,o)})}one(e,t){this.on(e,t,{once:!0})}off(e){this.$element.off(this._wrapEvent(e))}i18n(e,t,n){const{i18nData:i}=this;return Ne(i,e,t,n,this.options.lang,this.constructor.NAME)??Ne(i,e,t,n,this.options.lang)??`{i18n:${e}}`}get namespace(){return`${this.constructor.NAMESPACE}.${this._key}`}_wrapEvent(e){return e.split(" ").map(t=>t.includes(".")?t:`${t}${this.namespace}`).join(" ")}static get(e,t){const n=y(e);if(this.MULTI_INSTANCE&&t!==void 0){const i=n.data(`${this.KEY}:ALL`);return i?i.get(t):void 0}return n.data(this.KEY)}static isValid(e){return!0}static ensure(e,t){const n=this.get(e,t==null?void 0:t.key);if(n){if(this.isValid(n))return t&&n.setOptions(t),n;n.destroy()}return new this(e,t)}static getAll(e,t){var l;const{SELECTOR:n,ALL:i,TYPED_ALL:r}=this,o=[],a=c=>{c instanceof this&&(!t||t(c)!==!1)&&o.push(c)};return e?y(e).find(n).each((c,d)=>{var h;(h=i.get(d))==null||h.forEach(a)}):this!==Fg?(l=r.get(this.NAME))==null||l.forEach(a):i.forEach(c=>{c.forEach(a)}),o.sort((c,d)=>c.gid-d.gid)}static query(e,t,n){return e===void 0?this.getAll(void 0,n).pop():this.get(y(e).closest(this.SELECTOR),t)}static defineFn(e){let t=e||this.ZUI;y.fn[t]&&(t=`zui${this.NAME}`);const n=this;y.fn.extend({[t](i,...r){const o=typeof i=="object"?i:void 0,a=typeof i=="string"?i:void 0;let l;return this.each((c,d)=>{let h=n.get(d);if(h)o&&h.render(o);else{if(a)return;h=new n(d,o)}if(a){let p=h[a],m=h;p===void 0&&(m=h.$,p=m[a]),typeof p=="function"?l=p.call(m,...r):l=p}}),l!==void 0?l:this}})}static register(e,t){var i,r;e=e||this,t=(t??e.NAME).toLowerCase(),this.map.set(t,e);const n=(r=(i=e.toggle)==null?void 0:i.name)==null?void 0:r.toLowerCase();n&&n!==t&&this.toggleMap.set(n,e)}};fs.DEFAULT={},fs.MULTI_INSTANCE=!1,fs.ALL=new Map,fs.TYPED_ALL=new Map,fs.map=new Map,fs.toggleMap=new Map;let Be=fs;function Ii(s){return Be.map.get(s.toLowerCase())}function oo(s,e,t={}){let n=Ii(s);if(n||(n=Ol(s)),!n)return null;const{$update:i,...r}=t;if(!n.MULTI_INSTANCE){const o=n.get(e);if(o)return i&&o.render(r,i==="reset"),o}return new n(e,r)}function rv(s,e,t={}){requestAnimationFrame(()=>oo(s,e,t))}function Od(s,e){Be.register(s,e)}function Ol(s){const{zui:e}=window;if(e){s=s==null?void 0:s.toLowerCase();for(const t in e){const n=t.toLowerCase()===s;if(s&&!n)continue;const i=e[t];if(!(typeof i!="function"||!i.NAME||!i.ZUI)&&(Be.map.has(t.toLowerCase())||Od(i),n))return i}}}function ov(s){var e;s?(e=Ii(s))==null||e.defineFn():window._zuiDefined||(Ol(),Be.map.forEach(t=>{t.defineFn()}),Object.assign(window,{_zuiDefined:!0}))}function av(s,e={}){const t=y(s);let n=t.attr("zui-create");const{update:i,onCreate:r}=e,o=(a,l)=>{if(l={$update:i,$optionsFromDataset:!1,...l},r){const d=r(a,l);if(d===!1)return;d&&(l=d)}const c=l.$lib;if(c){delete l.$lib,y.getLib(c).then(()=>oo(a,s,l));return}rv(a,s,l)};if(typeof n=="string"){n=n.trim();const a=n.length?n.split(",").map(d=>d.trim()):[],l=zs(s,{prefix:"zui-create-",evalValue:!0}),c=Object.keys(l);if(!c.length&&a.length===1)o(a[0],t.dataset());else{const d=new Set;[...a,...c].forEach(h=>{if(d.has(h))return;const p=l[h];o(h,p),delete l[h],d.add(h)})}}else{const a=t.dataset(),l=a==null?void 0:a.zui;if(!l)return;console.warn("[ZUI] create component instance with [data-zui] is deprecated, use [zui-create] instead.",{element:s,options:e}),delete a.zui,o(l,a)}}function lv(){y(document).on("click.zui.toggle mouseenter.zui.toggle","[data-toggle],[zui-toggle]",function(s){const e=y(this),t=e.dataset("toggle")||e.attr("zui-toggle");if(!t)return;const n=Be.toggleMap.get(t)||Ii(t),i=n==null?void 0:n.toggle;if(!i)return;const{trigger:r="click",skip:o="[disabled],.disabled",check:a}=i,l=s.type==="mouseover"?"hover":"click";if(!r.includes(l)||a&&!a.call(n,this,l,s)||o&&e.is(o))return;const{onGet:c,onCreate:d,setOptions:h=!0,getOptions:p,prevent:m=!0,handler:v,onToggle:w,convertHref:x}=i;let S=e.dataset();const D=e.attr(`zui-toggle-${t}`);if(D&&(S=y.extend(S,ls(D))),x&&e.is("a")){const P=e.attr("href");if(P){const B=x===!0?{selector:"target",url:"url"}:x;"#.".includes(P[0])?B.selector&&S[B.selector]===void 0&&(S[B.selector]=P):B.url&&S[B.url]===void 0&&(S[B.url]=P)}}if(p&&(S=p.call(n,this,S,s)),v){v.call(n,this,S,l,s),m&&s.preventDefault();return}let M=c?c.call(n,this):n.get(this);if(M)h&&M.setOptions(S);else{const P=d?d.call(n,this,s,S):new n(this,S);if(!P)return;M=P}if(w){if(w.call(n,M,this,s)===!1)return}else{const{shown:P,show:B,hide:q,toggle:Y}=M;let Q;if(Y?Q=Y:B&&q?P?Q=q:Q=B:B&&(Q=B),Q)Q.call(M);else return}m&&s.preventDefault()})}function cv(s,e){const t=Di(s),n=[];return Object.keys(t).forEach(i=>{if(!i.startsWith("zui."))return;const r=t[i];(e==null?void 0:e(r,i))!==!1&&n.push(t[i])}),n}let ao=0;function zd(s=100){if(ao&&clearTimeout(ao),s){ao=window.setTimeout(()=>zd(0),s);return}ao=0,Be.ALL.forEach(e=>{e.forEach(t=>t.autoDestroy())})}function hv(){if(!document.body||Di(document.body,"_autoDestoryMob"))return;const s=new MutationObserver(e=>{let t=!1;for(const n of e)if(n.removedNodes.length){t=!0;break}t&&zd()});s.observe(document.body,{childList:!0,subtree:!0}),Qr(document.body,"_autoDestoryMob",s)}function zl(s,e){const t=y(s);t.find("[zui-create],[data-zui]").each(function(){var n;((n=e==null?void 0:e.beforeCreate)==null?void 0:n.call(e,this))!==!1&&av(this,e)}),t.find("[zui-init]").each(function(){this.hasAttribute("z-zui-inited")||(this.setAttribute("z-zui-inited",""),y.runJS(this.getAttribute("zui-init"),["$element",y(this)]))}),t.find(".hide-before-init").removeClass("invisible hidden opacity-0"),t.find(".scroll-into-view").scrollIntoView(),t.find('[data-on="inited"],[zui-on-inited]').each((n,i)=>{const r=y(i);r.zui()||r.trigger("inited")}),e!=null&&e.runJS&&t.runJS()}y.fn.zuiInit=function(s){return zl(this,s),this},y.fn.zui=function(s,e){const t=this[0];if(!t)return;if(typeof s!="string"){const i={};let r;return cv(t,(o,a)=>{i[a]=o,(!r||r.gid1?t[0]:void 0,i=t[t.length>1?1:0],r=y(this).zui(n),o=r==null?void 0:r[i];typeof o=="function"&&o.apply(r,e)}),this},y(()=>{y("body").zuiInit({update:!0}),lv(),hv()});class lo extends Be{get $targets(){const{$element:e}=this,{targets:t}=this.options;return t?e.find(t):e}_handleScroll(e,t,n){const{offset:i=1}=this.options,r=this.$targets,o=e.getBoundingClientRect(),{scrollTop:a,scrollLeft:l}=e;r.each((c,d)=>{const h=d.getBoundingClientRect(),p=t==="top"&&a>0&&h.top<=o.top+i||t==="bottom"&&h.bottom>=o.bottom-i||t==="left"&&l>0&&h.left<=o.left+i||t==="right"&&l{this._raf&&cancelAnimationFrame(this._raf),this._raf=requestAnimationFrame(()=>{this._raf=0,this._handleScroll(l,t,i)})};this._scrollListener=c,l.addEventListener("scroll",c)}this._container=l,requestAnimationFrame(()=>{this._handleScroll(l,t,i)})}else this._ob=new IntersectionObserver(l=>{l.forEach(c=>{c.target.classList.toggle(i,c.intersectionRatiothis._ob.observe(c))}destroy(){var e;(e=this._ob)==null||e.disconnect(),this._container&&(this._container.removeEventListener("scroll",this._scrollListener),this._raf&&cancelAnimationFrame(this._raf))}}lo.NAME="Sticky";const Hs=24*60*60*1e3,Ue=s=>s===void 0?new Date:(s instanceof Date||(typeof s=="string"&&(s=s.trim(),/^\d+$/.test(s)&&(s=Number.parseInt(s,10))),typeof s=="number"&&s<1e10&&(s*=1e3),s=new Date(s)),s),Fd=(s,e,t="day")=>{if(typeof e=="string"){const n=Number.parseInt(e,10);t=e.replace(n.toString(),""),e=n}return s=new Date(Ue(s).getTime()),t==="month"?s.setMonth(s.getMonth()+e):t==="year"?s.setFullYear(s.getFullYear()+e):t==="week"?s.setDate(s.getDate()+e*7):t==="hour"?s.setHours(s.getHours()+e):t==="minute"?s.setMinutes(s.getMinutes()+e):t==="second"?s.setSeconds(s.getSeconds()+e):s.setDate(s.getDate()+e),s},Ln=(s,e=new Date)=>Ue(s).toDateString()===Ue(e).toDateString(),Ni=(s,e=new Date)=>Ue(s).getFullYear()===Ue(e).getFullYear(),Fl=(s,e=new Date)=>(s=Ue(s),e=Ue(e),s.getFullYear()===e.getFullYear()&&s.getMonth()===e.getMonth()),uv=(s,e=new Date)=>{s=Ue(s),e=Ue(e);const t=1e3*60*60*24,n=Math.floor(s.getTime()/t),i=Math.floor(e.getTime()/t);return Math.floor((n+4)/7)===Math.floor((i+4)/7)},dv=(s,e)=>Ln(Ue(e),s),fv=(s,e)=>Ln(Ue(e).getTime()-Hs,s),pv=(s,e)=>Ln(Ue(e).getTime()+Hs,s),jl=s=>s!=null&&!isNaN(Ue(s).getTime()),rt=(s,e="yyyy-MM-dd hh:mm",t="")=>{if(s=Ue(s),!jl(s))return t;if(typeof e=="function")return e(s);const n={"M+":s.getMonth()+1,"d+":s.getDate(),"h+":s.getHours(),"H+":s.getHours()%12,"m+":s.getMinutes(),"s+":s.getSeconds(),"S+":s.getMilliseconds()};return/(y+)/i.test(e)&&(e.includes("[yyyy-]")&&(e=e.replace("[yyyy-]",Ni(s)?"":"yyyy-")),e=e.replace(RegExp.$1,`${s.getFullYear()}`.substring(4-RegExp.$1.length))),Object.keys(n).forEach(i=>{if(new RegExp(`(${i})`).test(e)){const r=`${n[i]}`;e=e.replace(RegExp.$1,RegExp.$1.length===1?r:`00${r}`.substring(r.length))}}),e},mv=(s,e,t)=>{const n={full:"yyyy-M-d",month:"M-d",day:"d",str:"{0} ~ {1}",...t},i=rt(s,Ni(s)?n.month:n.full);if(Ln(s,e))return i;const r=rt(e,Ni(s,e)?Fl(s,e)?n.day:n.month:n.full);return n.str.replace("{0}",i).replace("{1}",r)};function Hl(s){let e=0;if(typeof s!="string"&&(s=String(s)),s&&s.length)for(let t=0;t{try{a.includes("%")&&(a=decodeURIComponent(a)),a=JSON.parse(a)}catch{}return[o,a]})),params:n.map(o=>{if(o!=="undefined"){if(o==="null")return null;try{return o.includes("%")&&(o=decodeURIComponent(o)),JSON.parse(o)}catch{return o}}})}}function jd(s){if(Array.isArray(s))return{commands:s.map(co).filter(Boolean)};if(typeof s=="object")return s;s=s.replace(/^#!?/,"");const e=s.includes(">"),t=s.split(e?">":"|").map(co);return{async:e,commands:t.filter(Boolean)}}function Bl(s,e,t){if(typeof s=="string"&&(s=co(s)),!s)return;const{execute:n,event:i,scope:r}=e;if(!(r&&s.scope&&s.scope!==r))return n({name:s.name,options:{...e.options,...s.options},event:i,scope:s.scope,prevResult:t},s.params)}async function Hd(s,e){const{async:t,commands:n}=jd(s);if(!n.length)return[];const{signal:i}=e;if(t){const o=[];let a;for(const l of n){if(!(i!=null&&i.aborted))break;a=await Bl(l,e,a),i!=null&&i.aborted&&(a=void 0),o.push(a)}return o}return await Promise.all(n.map(o=>{if(!(i!=null&&i.aborted))return Bl(o,e)}))}const Bs="zui.commands",Us="z-commands",gv="zui-commands-proxy",Bd="zui-command";function ho(s,e){typeof e=="string"?e={scope:e}:typeof e=="function"&&(e={onCommand:e});const{scope:t="",events:n="click"}=e??{},i=y(s),r=(i.attr(Us)||"").split(",");t&&!r.includes(t)&&r.push(t),i.attr(Us,r.join(",")).data(Bs,{[t]:{...e,scope:t,events:n,gid:wt()},...i.data(Bs)})}function uo(s,e=!0){const t=y(s);if(e===!0)t.removeAttr(Us),t.removeData(Bs);else if(e.length){const n=t.data(Bs)||{};e.split(",").forEach(r=>{delete n[r]});const i=Object.keys(n);i.length?t.attr(Us,i.join(",")).data(Bs,ho):uo(t,!0)}}function Ud(s,e){let t=s.closest(`[${Us}]`);if(!t.length){const o=s.closest(`[${gv}]`);o.length&&(t=y(o.data("zui.commandProxy")||o.attr("COMMAND_PROXY_ATTR")).closest(`[${Us}]`))}if(!t.length)return;const n=t.data(Bs)||{},i=Object.values(n).sort((o,a)=>a.gid-o.gid);let r;return e!=null&&e.length?(r=i.find(o=>o.scope===e),r||(r=i.find(o=>{var a;return!((a=o.scope)!=null&&a.length)&&!o.scoped})),r):(r=i.find(o=>{var a;return!((a=o.scope)!=null&&a.length)&&!o.scoped}),r||(r=i.find(o=>!o.scoped)),r?r.element=t[0]:r=Ud(s.parent(),e),r)}function yv(s){if(!s.currentTarget)return;const e=y(s.currentTarget);if(e.closest(".disabled,[disabled]").length)return;const t=e.attr(Bd)||(e.is('a[href^="#!"]')?e.attr("href"):"");if(!t)return;const n=new AbortController,i=()=>n.abort();Hd(t,{signal:n.signal,execute:(r,o)=>{const{scope:a,name:l}=r,c={...r,abort:i};let d;const h=Ud(e,a);if(h){c.element=h.element;const m=(h.commands?h.commands[`${a}~${l}`]||h.commands[l]:null)||h.onCommand;if(m&&(d=m(c,o),s.commandHandled))return d}const p=[c,o];if(e.trigger("command",p).trigger(`command:${a?`${l}.${a}`:l}`,p),a&&e.trigger(`command:.${a}`,p),s.commandHandled)return d;if(a==="event"){l==="stop"?s.stopPropagation():l==="prevent"?s.preventDefault():Mn(s,l,o);return}return a==="window"?Mn(window,l,o):a==="zui"?Mn(window.zui,l,o):a==="target"?Mn(e[0],l,o):a==="$target"?Mn(e,l,o):a==="$"?Mn(y,l,o):d},event:s})}y.fn.command=function(s,e){return this.on(`command:${s}`,e)},y.fn.offCommand=function(s,e){return this.off(`command:${s}`,e)},y.fn.commands=function(s){return this.each((e,t)=>ho(t,s)),this},y.fn.unbindCommands=function(s){return this.each((e,t)=>uo(t,s)),this},y(()=>{y(document).on("click.zui.command",`[${Bd}],a[href^="#!"]`,yv)});function Ei(s,e,t=!1){var i;const n=y(s);if(e!==void 0){if(typeof e=="string"&&e.length){const r=`zui-runjs-${wt()}`;n.append(`