Merge branch 'main' into feature/doctemplate
This commit is contained in:
@@ -29,8 +29,6 @@ clean:
|
||||
rm -f *.sh
|
||||
rm -f *.deb *.rpm
|
||||
common:
|
||||
curl https://$(GITFOX_HOST)/_artifacts/zentao/raw/zui3/static/blocksuite/$(SUITEVERSION)/blocksuite-$(SUITEVERSION).tar.gz | tar zxf - -C www/js/zui3/editor/
|
||||
|
||||
mkdir zentaopms
|
||||
cp -fr api zentaopms/
|
||||
cp -fr bin zentaopms/
|
||||
@@ -44,6 +42,8 @@ common:
|
||||
cp -fr sdk zentaopms/
|
||||
cp -fr roadrunner zentaopms/
|
||||
cp -fr www zentaopms && rm -fr zentaopms/www/data/ && mkdir -p zentaopms/www/data/upload && mkdir zentaopms/www/data/course
|
||||
if [ ! -d "zentaopms/www/js/zui3/editor" ]; then mkdir -p zentaopms/www/js/zui3/editor; fi
|
||||
curl https://$(GITFOX_HOST)/_artifacts/zentao/raw/zui3/static/blocksuite/$(SUITEVERSION)/blocksuite-$(SUITEVERSION).tar.gz | tar zxf - -C zentaopms/www/js/zui3/editor/
|
||||
mkdir zentaopms/tmp
|
||||
mkdir zentaopms/tmp/cache/
|
||||
mkdir zentaopms/tmp/duckdb/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"pkg": {
|
||||
"xuanxuan": {
|
||||
"gitVersion": "ca19e71757be425f4cd3b29b00d29a49ce99d221",
|
||||
"version": "9.2"
|
||||
"gitVersion": "78d92ad400d384dae664112fca03b6c599ce0e5e",
|
||||
"version": "9.2.1"
|
||||
},
|
||||
"zentaoext": {
|
||||
"gitRepo": "zentao/zentaoext"
|
||||
@@ -17,7 +17,7 @@
|
||||
"gitRepo": "ci/zentaoext-downgrade"
|
||||
},
|
||||
"blocksuite": {
|
||||
"version": "0.17.32"
|
||||
"version": "0.17.33"
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
@@ -42,7 +42,8 @@
|
||||
"bucket": "download",
|
||||
"nexus": {
|
||||
"release": "easycorp",
|
||||
"snapshot": "easycorp-snapshot"
|
||||
"snapshot": "easycorp-snapshot",
|
||||
"source": "easycorp-source"
|
||||
}
|
||||
},
|
||||
"push_version": "true",
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ REPLACE INTO `zt_bug` (`id`, `project`, `product`, `injection`, `identify`, `bra
|
||||
(3, 2, 1, 0, 0, 0, 4, 3, 0, 4, 1, 7, 0, 0, '成果展示页面问题', '', 3, 1, 'codeerror', '', '', '', '', '<p><span style=\"font-size:13px;font-family:\'Source Han Sans CN\', PingFangSC, \'Microsoft YaHei\', HiraginoSansGB, Roboto, Helvetica, Tahoma, sans-serif;\">[步骤] 进入首页</span></p><p><span style=\"font-size:13px;font-family:\'Source Han Sans CN\', PingFangSC, \'Microsoft YaHei\', HiraginoSansGB, Roboto, Helvetica, Tahoma, sans-serif;\">[结果] 出现乱码</span></p><p><span style=\"font-size:13px;font-family:\'Source Han Sans CN\', PingFangSC, \'Microsoft YaHei\', HiraginoSansGB, Roboto, Helvetica, Tahoma, sans-serif;\">[期望] 正常显示</span></p>', 'active', '', '', 0, 0, NULL, '', '', '', 'admin', '2024-04-02 16:14:38', 'trunk', '', NULL, NULL, '', '', '', NULL, '', NULL, 0, '', 0, 0, 0, 0, 0, 0, NULL, '', '', '', '', '', 0, '', NULL, '0'),
|
||||
(4, 2, 1, 0, 0, 0, 4, 3, 0, 4, 1, 8, 0, 0, '售后服务页面问题', '', 3, 1, 'codeerror', '', '', '', '', '<p><span style=\"font-size:13px;font-family:\'Source Han Sans CN\', PingFangSC, \'Microsoft YaHei\', HiraginoSansGB, Roboto, Helvetica, Tahoma, sans-serif;\">[步骤] 进入售后服务</span></p><p><span style=\"font-size:13px;font-family:\'Source Han Sans CN\', PingFangSC, \'Microsoft YaHei\', HiraginoSansGB, Roboto, Helvetica, Tahoma, sans-serif;\">[结果]乱码</span></p><p><span style=\"font-size:13px;font-family:\'Source Han Sans CN\', PingFangSC, \'Microsoft YaHei\', HiraginoSansGB, Roboto, Helvetica, Tahoma, sans-serif;\">[期望]正常显示</span></p>', 'resolved', '', '', 1, 0, NULL, '', '', '', 'admin', '2024-04-02 16:15:52', 'trunk', 'admin', '2024-04-02 16:17:48', NULL, 'admin', 'fixed', 'trunk', '2024-04-02 00:00:00', '', NULL, 0, '', 0, 0, 0, 0, 0, 0, NULL, '', '', '', '', '', 0, 'admin', '2024-04-02 16:17:48', '0');
|
||||
REPLACE INTO `zt_build` (`id`, `project`, `product`, `branch`, `execution`, `builds`, `name`, `system`, `scmPath`, `filePath`, `date`, `stories`, `bugs`, `artifactRepoID`, `builder`, `desc`, `createdBy`, `createdDate`, `deleted`) VALUES
|
||||
(1, 2, 1, '0', 3, '', '第一期版本', 1, '', '', '2024-04-02', ',4', '', 0, 'admin', '', 'admin', '2024-04-02 16:07:17', '0');
|
||||
(1, 2, 1, '0', 3, '', '第一期构建', 1, '', '', '2024-04-02', ',4', '', 0, 'admin', '', 'admin', '2024-04-02 16:07:17', '0');
|
||||
REPLACE INTO `zt_burn` (`execution`, `product`, `task`, `date`, `estimate`, `left`, `consumed`, `storyPoint`) VALUES
|
||||
(3, 0, 0, '2024-04-02', 35, 35, 19, 2);
|
||||
REPLACE INTO `zt_case` (`id`, `project`, `product`, `execution`, `branch`, `lib`, `module`, `path`, `story`, `storyVersion`, `title`, `precondition`, `keywords`, `pri`, `type`, `auto`, `frame`, `stage`, `howRun`, `script`, `scriptedBy`, `scriptedDate`, `scriptStatus`, `scriptLocation`, `status`, `subStatus`, `color`, `frequency`, `order`, `openedBy`, `openedDate`, `reviewedBy`, `reviewedDate`, `lastEditedBy`, `lastEditedDate`, `version`, `linkCase`, `fromBug`, `fromCaseID`, `fromCaseVersion`, `deleted`, `lastRunner`, `lastRunDate`, `lastRunResult`, `scene`, `sort`) VALUES
|
||||
|
||||
@@ -1158,6 +1158,7 @@ CREATE TABLE `zt_dataview` (
|
||||
`name` varchar(155) NOT NULL DEFAULT '',
|
||||
`code` varchar(50) NOT NULL DEFAULT '',
|
||||
`mode` enum('text','builder') NOT NULL DEFAULT 'builder',
|
||||
`driver` enum('mysql','duckdb') NOT NULL DEFAULT 'mysql',
|
||||
`view` varchar(57) NOT NULL DEFAULT '',
|
||||
`sql` text DEFAULT NULL,
|
||||
`fields` mediumtext DEFAULT NULL,
|
||||
@@ -1413,7 +1414,7 @@ CREATE TABLE `zt_doccontent` (
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`digest` varchar(255) NOT NULL DEFAULT '',
|
||||
`content` longtext DEFAULT NULL,
|
||||
`html` longtext DEFAULT NULL,
|
||||
`rawContent` longtext DEFAULT NULL,
|
||||
`files` text DEFAULT NULL,
|
||||
`type` varchar(10) NOT NULL DEFAULT '',
|
||||
`version` smallint(6) unsigned NOT NULL DEFAULT 0,
|
||||
@@ -3618,7 +3619,7 @@ CREATE TABLE `zt_system` (
|
||||
`product` mediumint(8) unsigned NOT NULL DEFAULT 0,
|
||||
`integrated` enum('0','1') NOT NULL DEFAULT '0',
|
||||
`latestRelease` mediumint(8) unsigned NOT NULL DEFAULT 0,
|
||||
`latestDate` date DEFAULT NULL,
|
||||
`latestDate` datetime DEFAULT NULL,
|
||||
`children` varchar(255) NOT NULL DEFAULT '',
|
||||
`status` enum('active','inactive') NOT NULL DEFAULT 'active',
|
||||
`desc` mediumtext DEFAULT NULL,
|
||||
|
||||
+6
-2
@@ -84,8 +84,8 @@ CREATE INDEX `idx_object` ON `zt_mark`(`objectType`,`objectID`);
|
||||
CREATE INDEX `idx_account` ON `zt_mark`(`account`);
|
||||
|
||||
UPDATE `zt_grouppriv` SET `module` = 'cache', `method` = 'setting' WHERE `module` = 'admin' AND `method` = 'cache';
|
||||
REPLACE INTO `zt_grouppriv` SELECT `group`, 'cache', 'clear' FROM `zt_grouppriv` WHERE `module` = 'cache' AND `method` = 'setting';
|
||||
REPLACE INTO `zt_grouppriv` SELECT `group`, 'system', 'create' FROM `zt_grouppriv` WHERE `module` IN ('release', 'projectrelease', 'build', 'projectbuild') AND `method` = 'create';
|
||||
INSERT INTO `zt_grouppriv` SELECT `group`, 'cache', 'clear' FROM `zt_grouppriv` WHERE `module` = 'cache' AND `method` = 'setting';
|
||||
INSERT INTO `zt_grouppriv` SELECT DISTINCT `group`, 'system', 'create' FROM `zt_grouppriv` WHERE `module` IN ('release', 'projectrelease', 'build', 'projectbuild') AND `method` = 'create';
|
||||
|
||||
UPDATE `zt_pivot` SET `version` = '1';
|
||||
UPDATE `zt_pivot` SET `builtin` = '1', `createdDate` = '2009-03-14' WHERE `id` >= 1000 AND `id` <= 1028;
|
||||
@@ -95,3 +95,7 @@ UPDATE `zt_pivotdrill` SET `version` = '1';
|
||||
DELETE FROM `zt_cron` WHERE `command` = 'moduleName=misc&methodName=cleanCache';
|
||||
|
||||
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`) VALUES ('0', '2', '*', '*', '*', 'moduleName=system&methodName=initSystem', '初始化产品下应用数据', 'zentao', 1, 'normal');
|
||||
|
||||
DELETE FROM `zt_object` WHERE `type` = 'taged' AND `deleted` = '1';
|
||||
|
||||
ALTER TABLE `zt_doccontent` ADD `rawContent` longtext DEFAULT NULL AFTER `content`;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE `zt_doccontent` ADD `html` longtext DEFAULT NULL AFTER `content`;
|
||||
+1
-1
@@ -802,7 +802,7 @@ CREATE TABLE IF NOT EXISTS `zt_doccontent` (
|
||||
`title` varchar(255) NOT NULL DEFAULT '',
|
||||
`digest` varchar(255) NOT NULL DEFAULT '',
|
||||
`content` longtext NULL,
|
||||
`html` longtext DEFAULT NULL,
|
||||
`rawContent` longtext DEFAULT NULL,
|
||||
`files` text NULL,
|
||||
`type` varchar(10) NOT NULL DEFAULT '',
|
||||
`version` smallint(6) unsigned NOT NULL DEFAULT '0',
|
||||
|
||||
@@ -41,7 +41,7 @@ formPanel
|
||||
set::url('#copyProjectModal'),
|
||||
set('data-destroyOnHide', true),
|
||||
set('data-toggle', 'modal'),
|
||||
set('data-size', 'sm'),
|
||||
set('data-size', 'md'),
|
||||
$lang->project->copy
|
||||
)
|
||||
),
|
||||
|
||||
@@ -17,6 +17,7 @@ class xuanxuanMessage extends messageModel
|
||||
if($objectType == 'story') $field = 'obj.*,product.name as productName';
|
||||
if($objectType == 'bug') $field = 'obj.*,project.name as projectName,product.name as productName,execu.name as execuName';
|
||||
if($objectType == 'feedback') $field = 'obj.*,product.name as productName';
|
||||
if($objectType == 'demand') $field = 'obj.*,pool.name as poolName';
|
||||
|
||||
$object = $this->dao->select($field)->from($this->config->objectTables[$objectType])->alias('obj')
|
||||
->beginIF($objectType == 'task')
|
||||
@@ -34,6 +35,9 @@ class xuanxuanMessage extends messageModel
|
||||
->beginIF($objectType == 'feedback')
|
||||
->leftJoin($this->config->objectTables['product'])->alias('product')->on('product.id = obj.product')
|
||||
->fi()
|
||||
->beginIF($objectType == 'demand')
|
||||
->leftJoin($this->config->objectTables['demandpool'])->alias('pool')->on('pool.id = obj.pool')
|
||||
->fi()
|
||||
->where('obj.id')->eq($objectID)
|
||||
->fetch();
|
||||
$field = $this->config->action->objectNameFields[$objectType];
|
||||
@@ -70,6 +74,21 @@ class xuanxuanMessage extends messageModel
|
||||
foreach($senderUser as $user) $target .= ',' . $user;
|
||||
}
|
||||
}
|
||||
elseif($objectType == 'demandpool')
|
||||
{
|
||||
if(!empty($object->owner)) $target .= trim($object->owner, ',');
|
||||
if(!empty($object->reviewer)) $target .= ',' . trim($object->reviewer, ',');
|
||||
}
|
||||
elseif($objectType == 'demand')
|
||||
{
|
||||
$target .= $object->createdBy;
|
||||
if(!empty($object->assignedTo)) $target .= $object->assignedTo == 'closed' ? '' : $object->assignedTo;
|
||||
if(!empty($object->mailto)) $target .= ",{$object->mailto}";
|
||||
$reviewers = $this->loadModel('demand')->getReviewerPairs($object->id, $object->version);
|
||||
$reviewers = array_keys($reviewers);
|
||||
if($reviewers) $target .= ',' . implode(',', $reviewers);
|
||||
$target = trim($target, ',');
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!empty($object->assignedTo)) $target .= $object->assignedTo == 'closed' ? $object->openedBy : $object->assignedTo;
|
||||
@@ -126,18 +145,19 @@ class xuanxuanMessage extends messageModel
|
||||
}
|
||||
elseif($objectType == 'demandpool')
|
||||
{
|
||||
if(!empty($object->owner)) $target .= trim($object->owner, ',');
|
||||
if(!empty($object->reviewer)) $target .= ',' . trim($object->reviewer, ',');
|
||||
$subcontent->headTitle = $object->name;
|
||||
$subcontent->parentType = '';
|
||||
$subcontent->parent = 0;
|
||||
$subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('demandpool', 'browse', '', 'html'));
|
||||
$subcontent->cardURL = $url;
|
||||
}
|
||||
elseif($objectType == 'demand')
|
||||
{
|
||||
$target .= $object->createdBy;
|
||||
if(!empty($object->assignedTo)) $target .= $object->assignedTo == 'closed' ? '' : $object->assignedTo;
|
||||
if(!empty($object->mailto)) $target .= ",{$object->mailto}";
|
||||
$reviewers = $this->loadModel('demand')->getReviewerPairs($object->id, $object->version);
|
||||
$reviewers = array_keys($reviewers);
|
||||
if($reviewers) $target .= ',' . implode(',', $reviewers);
|
||||
$target = trim($target, ',');
|
||||
$subcontent->headTitle = $object->poolName;
|
||||
$subcontent->parentType = 'demandpool';
|
||||
$subcontent->parent = $object->pool;
|
||||
$subcontent->parentURL = "xxc:openInApp/zentao-integrated/" . urlencode($server . helper::createLink('demand', 'browse', "id=$object->pool", 'html'));
|
||||
$subcontent->cardURL = $url;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -179,7 +199,7 @@ class xuanxuanMessage extends messageModel
|
||||
|
||||
$content = json_encode($contentData);
|
||||
$avatarUrl = $server . $this->app->getWebRoot() . 'favicon.ico';
|
||||
if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story' || $objectType == 'feedback')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl));
|
||||
if($target && ($objectType == 'bug' || $objectType == 'task' || $objectType == 'story' || $objectType == 'feedback' || $objectType == 'demand' || $objectType == 'demandpool')) $this->loadModel('im')->messageCreateNotify($target, $title, $subtitle = '', $content, $contentType = 'object', $url, $actions = array(), $sender = array('id' => 'zentao', 'realname' => $this->lang->message->sender, 'name' => $this->lang->message->sender, 'avatar' => $avatarUrl));
|
||||
|
||||
if($objectType == 'mr' and is_array($this->lang->message->mr->$actionType) and !empty($object->assignee))
|
||||
{
|
||||
|
||||
@@ -565,7 +565,7 @@ class baseMao
|
||||
if(is_string($value)) $value = explode(',', str_replace(' ', '', $value));
|
||||
if(is_array($value))
|
||||
{
|
||||
$rawResult = $this->cache->fetchAll($this->table, $value);
|
||||
$rawResult = $this->cache->fetchAll($this->table, array_filter($value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+5
-1
@@ -653,7 +653,11 @@ class cache
|
||||
if(empty($objectIdList)) $objectIdList = $allObjectIdList;
|
||||
|
||||
$keys = [];
|
||||
foreach($objectIdList as $objectID) $keys[$objectID] = $this->getRawCacheKey($code, $objectID);
|
||||
foreach($objectIdList as $objectID)
|
||||
{
|
||||
if(!$objectID) continue;
|
||||
$keys[$objectID] = $this->getRawCacheKey($code, $objectID);
|
||||
}
|
||||
|
||||
$objects = $this->cache->getMultiple(array_values($keys));
|
||||
|
||||
|
||||
@@ -63,11 +63,13 @@ function hasPriv(priv, value)
|
||||
|
||||
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';
|
||||
@@ -76,6 +78,7 @@ function isApiLib(lib, docApp)
|
||||
function isApiDoc(doc)
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
if(docApp && docApp.spaceType === 'api') return true;
|
||||
if(typeof doc !== 'object' && docApp) doc = docApp.getDoc(doc);
|
||||
if(doc && doc.api !== undefined) return doc.api;
|
||||
const id = typeof doc === 'object' ? doc.id : doc;
|
||||
@@ -243,8 +246,8 @@ function submitNewDoc(doc, spaceID, libID, moduleID, formData)
|
||||
const url = $.createLink('doc', 'create', `objectType=${spaceType}&objectID=${Math.max(spaceID, 0)}&libID=${libID}&moduleID=${moduleID}`);
|
||||
const docData =
|
||||
{
|
||||
content : doc.content,
|
||||
html : doc.html,
|
||||
rawContent : doc.content,
|
||||
content : doc.html,
|
||||
status : doc.status || 'normal',
|
||||
contentType: doc.contentType,
|
||||
type : 'text',
|
||||
@@ -319,7 +322,7 @@ function handleSaveDoc(doc)
|
||||
const moduleID = docApp.signals.moduleID.value;
|
||||
const url = $.createLink('doc', 'edit', `docID=${doc.id}`);
|
||||
const docData = {
|
||||
content : doc.content,
|
||||
rawContent : doc.content,
|
||||
status : doc.status || 'normal',
|
||||
contentType: doc.contentType,
|
||||
type : 'text',
|
||||
@@ -328,7 +331,7 @@ function handleSaveDoc(doc)
|
||||
title : doc.title,
|
||||
keywords : doc.keywords,
|
||||
acl : doc.acl,
|
||||
html : doc.html,
|
||||
content : doc.html,
|
||||
space : spaceType,
|
||||
uid : (doc.uid || `doc${doc.id}`),
|
||||
};
|
||||
@@ -370,6 +373,19 @@ function handleSaveDoc(doc)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移文档。
|
||||
* Migrate doc.
|
||||
*/
|
||||
function handleMigrateDoc(doc)
|
||||
{
|
||||
const url = $.createLink('doc', 'ajaxMigrateDoc', `docID=${doc.id}`);
|
||||
const docData = {html : doc.html};
|
||||
return new Promise((resolve) => {
|
||||
$.post(url, docData, (res) => resolve(!!res));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查给定的文档是否可以进行移动操作。
|
||||
* Check if the given doc can be moved.
|
||||
@@ -547,8 +563,9 @@ const actionsMap =
|
||||
const canAddModule = canModify && hasPriv('addModule');
|
||||
|
||||
/* 获取侧边栏没有模块时的操作按钮。 Get actions when sidebar no module. */
|
||||
if(canAddModule && info.ui === 'sidebar-no-module')
|
||||
if(info.ui === 'sidebar-no-module')
|
||||
{
|
||||
if(!canAddModule) return;
|
||||
return [{text: lang.actions.addModule, command: `addModule/${lib.id}/0/${lib.id}/child`, icon: 'plus', type: 'primary-pale'}];
|
||||
}
|
||||
|
||||
@@ -857,7 +874,7 @@ const commands =
|
||||
{
|
||||
const docApp = getDocApp();
|
||||
const libID = args[0] || docApp.libID;
|
||||
const url = $.createLink('doc', 'editLib', `libID=${libID}`);
|
||||
const url = $.createLink(isApiLib(libID) ? 'api' : 'doc', 'editLib', `libID=${libID}`);
|
||||
zui.Modal.open({size: 'sm', url: url});
|
||||
},
|
||||
deleteLib: function(_, args)
|
||||
@@ -1660,6 +1677,7 @@ window.setDocAppOptions = function(_, options)
|
||||
customRenders : customRenders,
|
||||
onCreateDoc : userPrivs.create ? handleCreateDoc : null,
|
||||
onSaveDoc : userPrivs.edit ? handleSaveDoc : null,
|
||||
onMigrateDoc : userPrivs.edit ? handleMigrateDoc : null,
|
||||
canMoveDoc : canMoveDoc,
|
||||
onSwitchView : handleSwitchView,
|
||||
getActions : getActions,
|
||||
|
||||
@@ -104,7 +104,7 @@ class featureBar extends wg
|
||||
|
||||
$subItems[] = $subItem;
|
||||
|
||||
if($key === $current || ($current == 'bysearch' && $key == $param))
|
||||
if($key === $current || ($current == 'bysearch' && $key === $param))
|
||||
{
|
||||
$isActive = true;
|
||||
$activeText = $text;
|
||||
|
||||
@@ -38,6 +38,7 @@ class filter extends wg
|
||||
set::items($items),
|
||||
set::menu($menu),
|
||||
set::multiple($multiple),
|
||||
set::toolbar($multiple),
|
||||
on::change()->do(<<<JS
|
||||
const hasUrl = () => \$this.zui().\$.props.items.hasOwnProperty('url');
|
||||
if(hasUrl()) \$this.zui().\$.props.items.data.values = \$this.zui().\$.value;
|
||||
|
||||
@@ -9,14 +9,17 @@ class graph extends wg
|
||||
'responsive?: bool=false',
|
||||
'width?: number|string="100%"',
|
||||
'height?: number|string="500"',
|
||||
'graphID?: number=0',
|
||||
);
|
||||
|
||||
protected function build(): zui
|
||||
{
|
||||
list($type, $width, $height, $responsive) = $this->prop(array('type', 'width', 'height', 'responsive'));
|
||||
list($type, $width, $height, $responsive, $graphID) = $this->prop(array('type', 'width', 'height', 'responsive', 'graphID'));
|
||||
if(empty($graphID)) $graphID = uniqid();
|
||||
|
||||
|
||||
return zui::graph(
|
||||
set::_id('zin_graph_' . uniqid()),
|
||||
set::_id('zin_graph_' . $graphID),
|
||||
set::type($type),
|
||||
set::responsive($responsive),
|
||||
set::_style(array('width' => is_int($width) ? "{$width}px" : $width, 'height' => is_int($height) ? "{$height}px" : $height)),
|
||||
|
||||
@@ -33,7 +33,7 @@ class thinkAppeals extends thinkModel
|
||||
return echarts
|
||||
(
|
||||
set::animationDuration(0),
|
||||
set::width('1000px'),
|
||||
set::width('1600px'),
|
||||
set::height('1000px'),
|
||||
set::color(array('#29AA93', '#FF9F46')),
|
||||
set::legend(array(array(
|
||||
@@ -42,17 +42,30 @@ class thinkAppeals extends thinkModel
|
||||
'itemGap' => 90,
|
||||
'itemWidth' => 14,
|
||||
'itemHeight' => 14,
|
||||
'bottom' => 40,
|
||||
'textStyle' => array('color' => '#64758B', 'padding' => array(0, 0, 0, 16))
|
||||
'bottom' => 20,
|
||||
'textStyle' => array('color' => '#64758B', 'fontSize' => 20, 'padding' => array(0, 0, 0, 16))
|
||||
))),
|
||||
set::radar(array('nameGap' => 32, 'indicator' => $this->getIndicator())),
|
||||
set::radar(array(
|
||||
'nameGap' => 32,
|
||||
'splitArea' => array('areaStyle' => array('color' => array('#EAF5FF'))),
|
||||
'splitLine' => array('lineStyle' => array('color' => '#CFE7FE', 'width' => 3)),
|
||||
'axisLine' => array('lineStyle' => array('color' => '#CFE7FE', 'width' => 3)),
|
||||
'axisLabel' => array('color' => '#9EA3B0', 'textStyle' => array('fontSize' => 24)),
|
||||
'name' => array('textStyle' => array('fontSize' => 24)),
|
||||
'indicator' => $this->getIndicator()
|
||||
)),
|
||||
set::series
|
||||
(
|
||||
array(
|
||||
array(
|
||||
'type' => 'radar',
|
||||
'data' => $blocks['seriesData'],
|
||||
'label' => array('normal' => array('show' => true, 'formatter' => jsRaw('formatSeriesLabel')))
|
||||
'symbolSize' => 10,
|
||||
'type' => 'radar',
|
||||
'data' => $blocks['seriesData'],
|
||||
'label' => array('normal' => array(
|
||||
'show' => true,
|
||||
'formatter' => jsRaw('formatSeriesLabel'),
|
||||
'textStyle' => array('fontSize' => 24)
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
.think-form-batch .form-batch-container::-webkit-scrollbar-track {background: var(--color-gray-200);}
|
||||
.think-form-batch .form-batch-head .form-label {text-overflow: unset; white-space: unset; font-weight: 400; position: static; padding: 0;}
|
||||
.think-form-batch .form-batch-table>*>tr>* {padding-top: calc(var(--space)); padding-bottom: calc(var(--space));}
|
||||
.think-form-batch .form-batch-col-actions {padding: 0.5rem 0 !important;}
|
||||
.think-form-batch .form-batch-head[data-name="ACTIONS"], .think-form-batch .form-batch-row-actions {width: 3.325rem; position: sticky; right: 0; background: var(--color-canvas);}
|
||||
.think-form-batch td[data-name="ACTIONS"] {padding: 0.5rem 0 !important;}
|
||||
.think-form-batch .form-batch-head[data-name="ACTIONS"], .think-form-batch td[data-name="ACTIONS"] {width: 3.325rem; position: sticky; right: 0; background: var(--color-canvas);}
|
||||
.think-form-batch .form-batch-head[data-name="ACTIONS"] .form-label {display: none;}
|
||||
.think-form-batch .form-batch-col-actions .btn {color: var(--color-primary-500);}
|
||||
.think-form-batch td[data-name="ACTIONS"] .btn {color: var(--color-primary-500);}
|
||||
.think-form-batch .form-control[disabled] {background-color: rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity)); --tw-bg-opacity: .4; color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}
|
||||
|
||||
@@ -15,16 +15,20 @@ window.changeRows = function()
|
||||
|
||||
window.renderRowData = function()
|
||||
{
|
||||
$(modeClass + ' .think-form-batch .form-batch-col-actions .btn[data-type="add"]').prop({
|
||||
disabled: ($(modeClass + ' .think-form-batch tbody tr').length >= canAddRowsOfMulticol || disabled),
|
||||
title: $(modeClass + ' .think-form-batch tbody tr').length >= canAddRowsOfMulticol ? addRowsTips.replace('%s', canAddRowsOfMulticol) : addLang,
|
||||
});
|
||||
$(modeClass + ' .think-form-batch .form-batch-col-actions .btn[data-type="delete"]').prop({
|
||||
disabled: disabled,
|
||||
})
|
||||
const modeClass = $('.think-form-batch').data('modeClass');
|
||||
if(modeClass != undefined)
|
||||
{
|
||||
$(modeClass + ' .think-form-batch td[data-name="ACTIONS"] .btn[data-type="add"]').prop({
|
||||
disabled: ($(modeClass + ' .think-form-batch tbody tr').length >= canAddRowsOfMulticol || disabled),
|
||||
title: $(modeClass + ' .think-form-batch tbody tr').length >= canAddRowsOfMulticol ? addRowsTips.replace('%s', canAddRowsOfMulticol) : addLang,
|
||||
});
|
||||
$(modeClass + ' .think-form-batch td[data-name="ACTIONS"] .btn[data-type="delete"]').prop({
|
||||
disabled: disabled,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('click', '.form-batch-col-actions .btn', function()
|
||||
$(document).on('click', 'td[data-name="ACTIONS"] .btn', function()
|
||||
{
|
||||
renderRowData();
|
||||
if($(this).data('type') == 'add') $(this).closest('tr').next().find('td:first-child .form-control')[0].focus();
|
||||
@@ -161,4 +165,4 @@ window.changeMulticolumnSetOption = function(target)
|
||||
$('.text-danger').remove();
|
||||
$('.has-error').removeClass('has-error');
|
||||
$('.required-tip button').toggleClass('hidden', target.value == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,6 @@ class thinkMulticolumn extends thinkQuestion
|
||||
jsVar('addRowsTips', $lang->thinkrun->tips->addRow);
|
||||
jsVar('addLang', $lang->thinkrun->add);
|
||||
jsVar('disabled', $runDisabled || $preViewDisabled);
|
||||
jsVar('modeClass', !empty($modeClass) ? '.' . $modeClass : '');
|
||||
|
||||
$fields = array_values((array)$fields);
|
||||
$batchItems = array();
|
||||
@@ -113,6 +112,7 @@ class thinkMulticolumn extends thinkQuestion
|
||||
set::onRenderRow(jsRaw('renderRowData')),
|
||||
$isRun ? formHidden('status', '') : null,
|
||||
set::data($result),
|
||||
setData('modeClass', !empty($modeClass) ? '.' . $modeClass : ''),
|
||||
$batchItems
|
||||
);
|
||||
return $detailWg;
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
.score-content .check-items .item-control{border-color:rgba(var(--color-primary-100-rgb),var(--tw-border-opacity));}
|
||||
.score-content .check-items .item-control:hover{background: rgba(var(--color-primary-100-rgb),var(--tw-bg-opacity));}
|
||||
.score-content .check-items .item-control .radio-primary{display: none;}
|
||||
.score-content .check-items .item-control.is-checked{background: rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity)); color: rgba(var(--color-white-rgb),var(--tw-text-opacity));}
|
||||
.score-content .check-items .item-control.is-checked{background: rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity)); color: rgba(var(--color-white-rgb),var(--tw-text-opacity)); border-color: rgba(var(--color-primary-500-rgb),var(--tw-bg-opacity));}
|
||||
|
||||
@@ -122,6 +122,12 @@ class thinkStepBase extends wg
|
||||
$sourceQuestion = array();
|
||||
$sourceItems = array();
|
||||
|
||||
$wizard->config = !empty($wizard->config) ? $wizard->config : array();
|
||||
$wizard->config = is_string($wizard->config) ? json_decode($wizard->config, true) : $wizard->config;
|
||||
$configureObjects = !empty($wizard->config['configureObjects']) ? json_decode($wizard->config['configureObjects'], true) : array();
|
||||
$isAssignedObject = !empty($configureObjects['isAssignedObject']) ? $configureObjects['isAssignedObject'] : 0;
|
||||
$showBuiltTip = isset($step->options->canConfigureRatio) && $step->options->canConfigureRatio == 0;
|
||||
|
||||
if(!empty($quotedQuestions))
|
||||
{
|
||||
foreach($quotedQuestions as $item)
|
||||
@@ -161,12 +167,13 @@ class thinkStepBase extends wg
|
||||
);
|
||||
}
|
||||
}
|
||||
$runSourceTip = !empty($sourceQuestion) && !$preViewModel;
|
||||
|
||||
if($isRun && (!empty($quotedQuestions) || !empty($sourceQuestion)))
|
||||
if($isRun && (!empty($quotedQuestions) || $runSourceTip))
|
||||
{
|
||||
$tipType = $lang->thinkstep->label->option;
|
||||
$sourceQuestionTip = array();
|
||||
if(!empty($sourceQuestion))
|
||||
if($runSourceTip)
|
||||
{
|
||||
foreach ($sourceQuestion as $sourceQuestionItem)
|
||||
{
|
||||
@@ -180,11 +187,11 @@ class thinkStepBase extends wg
|
||||
);
|
||||
}
|
||||
}
|
||||
$showRunTips = (!empty($quotedQuestions) || !empty($sourceQuestion)) && !$preViewModel;
|
||||
$showRunTips = ((!empty($quotedQuestions) && empty($isAssignedObject)) || !empty($sourceQuestion));
|
||||
$detailTip[] = $showRunTips ? div
|
||||
(
|
||||
setClass('bg-primary-50 text-gray p-2 mt-3 leading-normal'),
|
||||
!empty($quotedQuestions) ? div
|
||||
(!empty($quotedQuestions) && empty($isAssignedObject)) ? div
|
||||
(
|
||||
setClass('flex items-center'),
|
||||
icon(setClass('font text-warning mr-1'), 'about'),
|
||||
@@ -220,11 +227,7 @@ class thinkStepBase extends wg
|
||||
}
|
||||
if($preViewModel)
|
||||
{
|
||||
$wizard->config = !empty($wizard->config) ? $wizard->config : array();
|
||||
$wizard->config = is_string($wizard->config) ? json_decode($wizard->config, true) : $wizard->config;
|
||||
$configureObjects = !empty($wizard->config['configureObjects']) ? json_decode($wizard->config['configureObjects'], true) : array();
|
||||
$isAssignedObject = !empty($configureObjects['isAssignedObject']) ? $configureObjects['isAssignedObject'] : 0;
|
||||
$detailTip[] = (!empty($quotedQuestions) && !empty($isAssignedObject)) ? div
|
||||
$detailTip[] = ((!empty($quotedQuestions) && !empty($isAssignedObject)) || $showBuiltTip)? div
|
||||
(
|
||||
setClass('flex text-gray-400 mt-2 items-center text-sm ml-2'),
|
||||
icon(setClass('text-important mr-2'), 'about'),
|
||||
|
||||
@@ -53,6 +53,7 @@ class thinkStepMenu extends wg
|
||||
|
||||
private function buildMenuTree(array $items, int $parentID = 0): array
|
||||
{
|
||||
global $config;
|
||||
if(empty($items)) $items = $this->modules;
|
||||
if(empty($items)) return array();
|
||||
|
||||
@@ -60,7 +61,13 @@ class thinkStepMenu extends wg
|
||||
$toggleNonNodeShow = $this->prop('toggleNonNodeShow');
|
||||
$hidden = $this->prop('hidden');
|
||||
$sortTree = $this->prop('sortable') || $this->prop('onSort');
|
||||
$wizard = $this->prop('wizard');
|
||||
$hiddenModelType = in_array($wizard->model, $config->thinkwizard->hiddenMenuModel);
|
||||
$parentItems = array();
|
||||
$questionItems = array();
|
||||
|
||||
if($hiddenModelType) $questionItems = array_values($items);
|
||||
|
||||
foreach($items as $setting)
|
||||
{
|
||||
if(!is_object($setting)) continue;
|
||||
@@ -73,8 +80,18 @@ class thinkStepMenu extends wg
|
||||
$quotedText = $this->getQuotedText($this->modules, $quotedTitle);
|
||||
}
|
||||
|
||||
$itemQuestionIndex = 0;
|
||||
|
||||
foreach ($questionItems as $index => $questionItem)
|
||||
{
|
||||
if($questionItem->id == $setting->id) $itemQuestionIndex = $index;
|
||||
}
|
||||
|
||||
if(!empty($itemQuestionIndex) && $hiddenModelType) $preStep = $questionItems[$itemQuestionIndex - 1];
|
||||
|
||||
$canView = common::hasPriv('thinkstep', 'view');
|
||||
$unClickable = $toggleNonNodeShow && $setting->id != $activeKey && $setting->type != 'node' && json_decode($setting->answer) == null;
|
||||
$hiddenStep = $unClickable || (!empty($preStep) && empty($preStep->answer));
|
||||
$item = array(
|
||||
'key' => $setting->id,
|
||||
'text' => (isset($setting->index) ? ($setting->index . '. ') : '') . $setting->title,
|
||||
@@ -90,7 +107,7 @@ class thinkStepMenu extends wg
|
||||
'disabled' => $unClickable,
|
||||
'actions' => $this->prop('showAction') ? $this->getActions($setting) : null,
|
||||
'data-wizard' => $setting->wizard,
|
||||
'class' => $unClickable && $hidden ? 'hidden': ''
|
||||
'class' => $hiddenStep && $hidden ? 'hidden' : ''
|
||||
);
|
||||
|
||||
if($sortTree) $item['trailingIcon'] = 'move muted cursor-move';
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
.form-horz .form-group {align-items: center;}
|
||||
.result-width {width: calc(100% - 148px);}
|
||||
.form-control[disabled] {background-color: rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity)); --tw-bg-opacity: .4; color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}
|
||||
.form-control[readonly] {cursor: not-allowed; background-color: rgba(var(--color-gray-100-rgb),var(--tw-bg-opacity)); --tw-bg-opacity: .4; color:rgba(var(--color-gray-700-rgb),var(--tw-bg-opacity))}
|
||||
@@ -57,56 +57,58 @@ class thinkTableInput extends thinkQuestion
|
||||
foreach($fields as $item)
|
||||
{
|
||||
$value = !empty($result) && isset($result[$index]) ? $result[$index] : '';
|
||||
$tableInputItems[] = formGroup
|
||||
(
|
||||
setClass('flex items-center'),
|
||||
div
|
||||
$tableInputItems[] = array(
|
||||
formGroup
|
||||
(
|
||||
setClass('flex items-center'),
|
||||
div
|
||||
(
|
||||
setClass('text-right mr-2 w-24 line-clamp-2'),
|
||||
$item,
|
||||
set::title($item)
|
||||
),
|
||||
div
|
||||
(
|
||||
set::title($value),
|
||||
setClass(empty($inputType) ? 'result-width' : '', $index == 0 ? '' : 'mt-2'),
|
||||
empty($inputType) ? textarea
|
||||
(
|
||||
set::rows('2'),
|
||||
set::name('result[' . $index . ']'),
|
||||
set::value($value),
|
||||
set::placeholder($lang->thinkrun->pleaseInput)
|
||||
) : inputControl
|
||||
(
|
||||
input(set(array(
|
||||
'class' => 'w-72 h-10 dimension-weight',
|
||||
'name' => 'result[' . $index . ']',
|
||||
'type' => 'number',
|
||||
'min' => 1,
|
||||
'max' => 100,
|
||||
'value' => $value,
|
||||
'disabled' => ($value && !$canConfigureRatio ),
|
||||
'placeholder' => $lang->thinkrun->pleaseInput
|
||||
)),
|
||||
on::input('changePercentInput')
|
||||
),
|
||||
to::suffix($lang->thinkwizard->dimension->percentageSign),
|
||||
set::suffixWidth(32)
|
||||
),
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('flex'),
|
||||
setStyle(array('min-width' => '40px')),
|
||||
($index == count($fields) - 1 && $supportAdd) ? icon
|
||||
div
|
||||
(
|
||||
'plus',
|
||||
setClass('mr-1 btn-add ml-2 text-sm text-primary add-rows cursor-pointer', $disabledAdd ? 'disabled' : ''),
|
||||
setData('canAddRows', $canAddRows),
|
||||
setData('fieldsCount', count($fields)),
|
||||
set::title(sprintf($lang->thinkrun->tips->add, $canAddRows)),
|
||||
) : null,
|
||||
)
|
||||
set::title($value),
|
||||
setClass(empty($inputType) ? 'result-width' : '', $index == 0 ? '' : 'mt-2'),
|
||||
empty($inputType) ? textarea
|
||||
(
|
||||
set::rows('2'),
|
||||
set::name('result[' . $index . ']'),
|
||||
set::value($value),
|
||||
set::placeholder($lang->thinkrun->pleaseInput)
|
||||
) : inputControl
|
||||
(
|
||||
input(set(array(
|
||||
'class' => 'w-72 h-10 dimension-weight',
|
||||
'name' => 'result[' . $index . ']',
|
||||
'type' => 'number',
|
||||
'min' => 1,
|
||||
'max' => 100,
|
||||
'value' => $value,
|
||||
'readonly' => ($value && !$canConfigureRatio),
|
||||
'placeholder' => $lang->thinkrun->pleaseInput
|
||||
)),
|
||||
on::input('changePercentInput')
|
||||
),
|
||||
to::suffix($lang->thinkwizard->dimension->percentageSign),
|
||||
set::suffixWidth(32)
|
||||
),
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('flex'),
|
||||
setStyle(array('min-width' => '40px')),
|
||||
($index == count($fields) - 1 && $supportAdd) ? icon
|
||||
(
|
||||
'plus',
|
||||
setClass('mr-1 btn-add ml-2 text-sm text-primary add-rows cursor-pointer', $disabledAdd ? 'disabled' : ''),
|
||||
setData('canAddRows', $canAddRows),
|
||||
setData('fieldsCount', count($fields)),
|
||||
set::title(sprintf($lang->thinkrun->tips->add, $canAddRows)),
|
||||
) : null,
|
||||
)
|
||||
),
|
||||
);
|
||||
$index ++;
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -1,5 +1,5 @@
|
||||
library 'z-common@main'
|
||||
library 'z-zentaopms@feat-241030'
|
||||
library 'z-common@feat-241129'
|
||||
library 'z-zentaopms@feat-241129'
|
||||
|
||||
pipeline {
|
||||
agent {
|
||||
|
||||
@@ -129,3 +129,5 @@ $config->action->multipleObjectFields['testtask']['type'] = 'typeList';
|
||||
|
||||
$config->action->approvalFields['reviewStatus'] = 'reviewStatusList';
|
||||
$config->action->approvalFields['reviewResult'] = 'reviewResultList';
|
||||
|
||||
$config->action->hiddenTrashObjects = 'object,cm';
|
||||
|
||||
@@ -189,6 +189,7 @@ $lang->action->objectTypes['projectbuild'] = 'Build';
|
||||
$lang->action->objectTypes['board'] = 'Board';
|
||||
$lang->action->objectTypes['boardspace'] = 'Board Space';
|
||||
$lang->action->objectTypes['productline'] = 'Product Line';
|
||||
$lang->action->objectTypes['system'] = $lang->product->system;
|
||||
|
||||
/* Used to describe operation history. */
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -562,7 +563,7 @@ $lang->action->label->createbackup = 'Created system backup';
|
||||
$lang->action->label->deletebackup = 'Deleted system backup';
|
||||
$lang->action->label->restorebackup = 'Restored system backup';
|
||||
$lang->action->label->upgradesystem = 'Executed system upgrade';
|
||||
$lang->action->label->system = 'Application';
|
||||
$lang->action->label->system = $lang->product->system;
|
||||
$lang->action->label->manualbackup = 'Manual backup';
|
||||
$lang->action->label->autobackup = 'Automatic backup';
|
||||
$lang->action->label->openautobackup = 'Enable automatic backup';
|
||||
|
||||
@@ -189,6 +189,7 @@ $lang->action->objectTypes['projectbuild'] = 'Build';
|
||||
$lang->action->objectTypes['board'] = 'Board';
|
||||
$lang->action->objectTypes['boardspace'] = 'Board Space';
|
||||
$lang->action->objectTypes['productline'] = 'Product Line';
|
||||
$lang->action->objectTypes['system'] = $lang->product->system;
|
||||
|
||||
/* Used to describe operation history. */
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -562,7 +563,7 @@ $lang->action->label->createbackup = 'Created system backup';
|
||||
$lang->action->label->deletebackup = 'Deleted system backup';
|
||||
$lang->action->label->restorebackup = 'Restored system backup';
|
||||
$lang->action->label->upgradesystem = 'Executed system upgrade';
|
||||
$lang->action->label->system = 'Application';
|
||||
$lang->action->label->system = $lang->product->system;
|
||||
$lang->action->label->manualbackup = 'Manual backup';
|
||||
$lang->action->label->autobackup = 'Automatic backup';
|
||||
$lang->action->label->openautobackup = 'Enable automatic backup';
|
||||
|
||||
@@ -189,6 +189,7 @@ $lang->action->objectTypes['projectbuild'] = 'Build';
|
||||
$lang->action->objectTypes['board'] = 'Board';
|
||||
$lang->action->objectTypes['boardspace'] = 'Board Space';
|
||||
$lang->action->objectTypes['productline'] = 'Product Line';
|
||||
$lang->action->objectTypes['system'] = $lang->product->system;
|
||||
|
||||
/* Used to describe operation history. */
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -562,7 +563,7 @@ $lang->action->label->createbackup = 'Created system backup';
|
||||
$lang->action->label->deletebackup = 'Deleted system backup';
|
||||
$lang->action->label->restorebackup = 'Restored system backup';
|
||||
$lang->action->label->upgradesystem = 'Executed system upgrade';
|
||||
$lang->action->label->system = 'Application';
|
||||
$lang->action->label->system = $lang->product->system;
|
||||
$lang->action->label->manualbackup = 'Manual backup';
|
||||
$lang->action->label->autobackup = 'Automatic backup';
|
||||
$lang->action->label->openautobackup = 'Enable automatic backup';
|
||||
|
||||
@@ -189,7 +189,7 @@ $lang->action->objectTypes['projectbuild'] = '构建';
|
||||
$lang->action->objectTypes['board'] = '白板';
|
||||
$lang->action->objectTypes['boardspace'] = '白板空间';
|
||||
$lang->action->objectTypes['productline'] = '产品线';
|
||||
$lang->action->objectTypes['system'] = '应用';
|
||||
$lang->action->objectTypes['system'] = $lang->product->system;
|
||||
|
||||
/* 用来描述操作历史记录。*/
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -563,7 +563,7 @@ $lang->action->label->createbackup = '创建了系统备份';
|
||||
$lang->action->label->deletebackup = '删除了系统备份';
|
||||
$lang->action->label->restorebackup = '还原了系统备份';
|
||||
$lang->action->label->upgradesystem = '执行了系统升级';
|
||||
$lang->action->label->system = '应用';
|
||||
$lang->action->label->system = $lang->product->system;
|
||||
$lang->action->label->manualbackup = '手动备份了';
|
||||
$lang->action->label->autobackup = '自动备份了';
|
||||
$lang->action->label->openautobackup = '开启自动备份';
|
||||
|
||||
@@ -404,6 +404,7 @@ class actionModel extends model
|
||||
->orWhere('(objectType')->eq('execution')->andWhere('objectID')->notIn($noMultipleExecutions)
|
||||
->markRight(2)
|
||||
->fi()
|
||||
->andWhere('objectType')->notIn($this->config->action->hiddenTrashObjects)
|
||||
->andWhere('extra')->eq($extra)
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->orderBy($orderBy)
|
||||
@@ -511,6 +512,7 @@ class actionModel extends model
|
||||
->andWhere($trashQuery)
|
||||
->andWhere('t1.extra')->eq($extra)
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('objectType')->notIn($this->config->action->hiddenTrashObjects)
|
||||
->beginIF($objectType != 'pipeline' && $objectType != 'all')->andWhere('t1.objectType')->eq($objectType)->fi()
|
||||
|
||||
->beginIF($objectType == 'pipeline')
|
||||
@@ -1103,7 +1105,7 @@ class actionModel extends model
|
||||
$shadowProducts = $this->dao->select('id')->from(TABLE_PRODUCT)->where('shadow')->eq(1)->fetchPairs();
|
||||
$projectMultiples = $this->dao->select('id,type,multiple')->from(TABLE_PROJECT)->where('id')->in($projectIdList)->fetchAll('id');
|
||||
$docList = $this->loadModel('doc')->getPrivDocs(array(), 0, 'all');
|
||||
$apiList = $this->loadModel('api')->getPrivApis();
|
||||
$apiList = $this->loadModel('api')->getPrivApis('all');
|
||||
$docLibList = $this->doc->getLibs('hasApi');
|
||||
foreach($actions as $i => $action)
|
||||
{
|
||||
@@ -1501,6 +1503,11 @@ class actionModel extends model
|
||||
}
|
||||
if($action->objectType == 'demand' && !empty($object->parent)) $this->loadModel('demand')->updateParentDemandStage($object->parent);
|
||||
if($action->objectType == 'release') $this->loadModel('system')->setSystemRelease((int)$object->system, $action->objectID);
|
||||
if(in_array($action->objectType, array('release', 'build')) && !empty($object->system))
|
||||
{
|
||||
$systemActionID = $this->dao->select('id')->from(TABLE_ACTION)->where('objectType')->eq('system')->andWhere('objectID')->eq($object->system)->andWhere('action')->eq('deleted')->orderBy('id_desc')->fetch('id');
|
||||
if($systemActionID) $this->undelete($systemActionID);
|
||||
}
|
||||
|
||||
/* 在action表中更新action记录。 */
|
||||
/* Update action record in action table. */
|
||||
|
||||
@@ -86,7 +86,7 @@ $lang->admin->menuList->model['menuOrder']['15'] = 'waterfall';
|
||||
$lang->admin->menuList->model['menuOrder']['20'] = 'agileplus';
|
||||
$lang->admin->menuList->model['menuOrder']['25'] = 'waterfallplus';
|
||||
|
||||
$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'links' => array('custom|set|module=project&field=unitList'));
|
||||
$lang->admin->menuList->model['tabMenu']['common']['project'] = array('link' => "{$lang->project->common}|custom|required|module=project", 'alias' => 'set,project', 'exclude' => 'custom-required', 'links' => array('custom|set|module=project&field=unitList'));
|
||||
if(helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus')) $lang->admin->menuList->model['tabMenu']['common']['stage'] = array('link' => "{$lang->stage->type}|stage|settype|", 'subModule' => 'stage');
|
||||
$lang->admin->menuList->model['tabMenu']['common']['build'] = array('link' => "{$lang->build->common}|custom|required|module=build", 'alias' => 'set', 'exclude' => 'custom');
|
||||
$lang->admin->menuList->model['tabMenu']['common']['flow'] = array('link' => "{$lang->custom->flow}|custom|flow|", 'divider' => true);
|
||||
|
||||
@@ -75,6 +75,8 @@ $config->api->dtable->release->fieldList['addedDate']['type'] = 'date';
|
||||
|
||||
$config->api->dtable->release->fieldList['actions']['name'] = 'actions';
|
||||
$config->api->dtable->release->fieldList['actions']['title'] = $lang->actions;
|
||||
$config->api->dtable->release->fieldList['actions']['width'] = '70px';
|
||||
$config->api->dtable->release->fieldList['actions']['align'] = 'center';
|
||||
$config->api->dtable->release->fieldList['actions']['type'] = 'actions';
|
||||
$config->api->dtable->release->fieldList['actions']['menu'] = array('deleteRelease');
|
||||
$config->api->dtable->release->fieldList['actions']['list']['deleteRelease']['icon'] = 'trash';
|
||||
|
||||
@@ -159,8 +159,9 @@ class api extends control
|
||||
{
|
||||
if(!isset($programs[$product->program])) continue;
|
||||
$program = $programs[$product->program];
|
||||
$program->products[] = $product;
|
||||
$product->apiCount = isset($productsCount[$product->id]) ? $productsCount[$product->id] : 0;
|
||||
if($notempty && $product->apiCount == 0) continue;
|
||||
$program->products[] = $product;
|
||||
$program->apiCount = isset($program->apiCount) ? $program->apiCount + $product->apiCount : $product->apiCount;
|
||||
}
|
||||
}
|
||||
@@ -172,9 +173,10 @@ class api extends control
|
||||
$topParent = $project->parent ? explode(',', trim($project->path, ','))[0] : 0;
|
||||
if(!isset($programs[$topParent])) continue;
|
||||
$program = $programs[$topParent];
|
||||
$program->projects[] = $project;
|
||||
$project->apiCount = isset($projectsCount[$project->id]) ? $projectsCount[$project->id] : 0;
|
||||
if($notempty && $project->apiCount == 0) continue;
|
||||
$program->apiCount = isset($program->apiCount) ? $program->apiCount + $project->apiCount : $project->apiCount;
|
||||
$program->projects[] = $project;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
.table-empty-tip {padding: 80px 10px; text-align: center; background: #fff;}
|
||||
.table-empty-tip .btn-group .btn {background-color: rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity)); color: var(--nav-active-color); --tw-ring-color: rgba(var(--color-primary-50-rgb),var(--tw-bg-opacity));}
|
||||
|
||||
.picker-menu .menu-item.is-nested > .item-inner .item-content .item-title {flex-grow: 0!important; opacity: .6;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner .item-content .item-subtitle {--skin-pale-rgb: var(--color-gray-500-rgb); height: 1rem; min-width: 1rem; border-radius: var(--radius-full); --skin-color: rgba(var(--skin-pale-rgb), .1); --skin-text: rgba(var(--skin-pale-rgb), 1); --state-color: rgba(var(--skin-pale-rgb), .1); --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); display: inline-flex; font-size: .75rem; align-items: center; justify-content: center; line-height: 1rem; padding-left: .25rem; padding-right: .25rem;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner {background-color: inherit!important; color: inherit!important; cursor: default;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner::before {display: none;}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.dropmenu-nav .nav-item {white-space: nowrap;}
|
||||
@@ -228,8 +228,10 @@ function getSpaceMenuText(text, state)
|
||||
function getSpaceMenuOptions(spaceType, spaceID)
|
||||
{
|
||||
const libID = this.libID;
|
||||
const lang = $('html').attr('lang');
|
||||
|
||||
return {
|
||||
popWidth : 350,
|
||||
popWidth : ['zh-cn', 'zh-tw'].includes(lang) ? 350 : 400,
|
||||
onClickItem : handleClickSpaceMenu,
|
||||
defaultValue: spaceID === 'nolink' ? `lib.${libID}`: spaceID,
|
||||
display : getSpaceMenuText.bind(this)
|
||||
|
||||
@@ -188,9 +188,9 @@ $lang->api->requestTypeOptions['application/x-www-form-urlencoded'] = 'applicati
|
||||
$lang->api->requestTypeOptions['multipart/form-data'] = 'multipart/form-data';
|
||||
|
||||
$lang->api->libTypeList = array();
|
||||
$lang->api->libTypeList['product'] = $lang->productCommon . ' Api Library';
|
||||
$lang->api->libTypeList['project'] = $lang->projectCommon . ' Api Library';
|
||||
$lang->api->libTypeList['nolink'] = 'Independent Api Library';
|
||||
$lang->api->libTypeList['product'] = $lang->productCommon . ' API';
|
||||
$lang->api->libTypeList['project'] = $lang->projectCommon . ' API';
|
||||
$lang->api->libTypeList['nolink'] = 'Independent API';
|
||||
|
||||
$lang->api->statusOptions = array(
|
||||
'done' => 'Done',
|
||||
|
||||
@@ -188,9 +188,9 @@ $lang->api->requestTypeOptions['application/x-www-form-urlencoded'] = 'applicati
|
||||
$lang->api->requestTypeOptions['multipart/form-data'] = 'multipart/form-data';
|
||||
|
||||
$lang->api->libTypeList = array();
|
||||
$lang->api->libTypeList['product'] = $lang->productCommon . ' Api Library';
|
||||
$lang->api->libTypeList['project'] = $lang->projectCommon . ' Api Library';
|
||||
$lang->api->libTypeList['nolink'] = 'Independent Api Library';
|
||||
$lang->api->libTypeList['product'] = $lang->productCommon . ' API';
|
||||
$lang->api->libTypeList['project'] = $lang->projectCommon . ' API';
|
||||
$lang->api->libTypeList['nolink'] = 'Independent API';
|
||||
|
||||
$lang->api->statusOptions = array(
|
||||
'done' => 'Done',
|
||||
|
||||
@@ -137,7 +137,7 @@ if($config->inQuickon)
|
||||
|
||||
if($this->config->inQuickon)
|
||||
{
|
||||
$data = null;
|
||||
$data = array();
|
||||
if(!empty($backups)) $data = initTableData($backups, $config->system->dtable->backup->fieldList, $this->system);
|
||||
|
||||
foreach($data as &$backup)
|
||||
|
||||
+1
-1
@@ -901,7 +901,7 @@ class biModel extends model
|
||||
/* 如果是升级模式,那么需要采用当前时间,确保用户可以看到“新”标签。*/
|
||||
$pivotSpec->createdDate = $isInstall ? $createdDate : helper::now();
|
||||
$pivotSpecStmt = $this->dao->insert(TABLE_PIVOTSPEC)->data($pivotSpec);
|
||||
$pivotSpecSQLs[] = $pivotSpecStmt->get();
|
||||
$pivotSQLs[] = $pivotSpecStmt->get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -770,6 +770,7 @@ class bugZen extends bug
|
||||
/* Get story and task id list. */
|
||||
$storyIdList = $taskIdList = array();
|
||||
if($this->config->edition == 'max') $identifyList = $this->loadModel('review')->getPairs(0, 0, true);
|
||||
if($this->config->edition != 'open') $bugRelatedObjectList = $this->custom->getRelatedObjectList(array_keys($bugs), 'bug', 'byRelation', true);
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
if($bug->story) $storyIdList[$bug->story] = $bug->story;
|
||||
@@ -781,8 +782,7 @@ class bugZen extends bug
|
||||
$bug->injection = zget($identifyList, $bug->injection, '');
|
||||
$bug->identify = zget($identifyList, $bug->identify, '');
|
||||
}
|
||||
|
||||
if($this->config->edition != 'open') $bug->relatedObject = $this->custom->getRelatedObjectList($bug->id, 'bug', 'byRelation', true);
|
||||
if($this->config->edition != 'open') $bug->relatedObject = zget($bugRelatedObjectList, $bug->id, 0);
|
||||
}
|
||||
|
||||
$showModule = !empty($this->config->bug->browse->showModule) ? $this->config->bug->browse->showModule : '';
|
||||
|
||||
@@ -12,6 +12,7 @@ $config->build->editor->edit = array('id' => 'desc', 'tools' => 'simpleTools')
|
||||
global $lang, $app;
|
||||
$config->build->search['module'] = 'build';
|
||||
$config->build->search['fields']['name'] = $lang->build->nameAB;
|
||||
$config->build->search['fields']['system'] = $lang->build->system;
|
||||
$config->build->search['fields']['id'] = $lang->build->id;
|
||||
$config->build->search['fields']['product'] = $lang->build->product;
|
||||
$config->build->search['fields']['scmPath'] = $lang->build->scmPath;
|
||||
@@ -21,6 +22,7 @@ $config->build->search['fields']['builder'] = $lang->build->builder;
|
||||
$config->build->search['fields']['desc'] = $lang->build->desc;
|
||||
|
||||
$config->build->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
$config->build->search['params']['system'] = array('operator' => '=', 'control' => 'select', 'values' => array());
|
||||
$config->build->search['params']['product'] = array('operator' => '=', 'control' => 'select', 'values' => 'products');
|
||||
$config->build->search['params']['scmPath'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
$config->build->search['params']['filePath'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
|
||||
|
||||
@@ -35,7 +35,6 @@ window.loadSystem = function(productID)
|
||||
{
|
||||
productID = parseInt(productID);
|
||||
if(!productID) productID = $('input[name=product]').val();
|
||||
if(typeof(productID) == "undefined") return;
|
||||
|
||||
$.get($.createLink('build', 'ajaxGetSystemList', 'productID=' + productID), function(data)
|
||||
{
|
||||
|
||||
@@ -10,8 +10,8 @@ $().ready(function()
|
||||
$(document).off('change', '[name=product], [name^=branch]').on('change', '[name=product], [name^=branch]', function()
|
||||
{
|
||||
let projectID = $('input[name=project]').val();
|
||||
let productID = $('input[name=product]').val();
|
||||
let systemID = $('input[name=system]').val();
|
||||
let productID = $('#createBuildForm input[name=product]').val();
|
||||
let systemID = $('input[name=system]').val();
|
||||
$.get($.createLink('build', 'ajaxGetProjectBuilds', 'projectID=' + projectID + '&productID=' + productID + '&varName=builds&build=&branch=all&&needCreate=&type=noempty,notrunk,separate,singled&systemID=' + systemID), function(data)
|
||||
{
|
||||
if(data)
|
||||
@@ -30,7 +30,10 @@ $().ready(function()
|
||||
{
|
||||
$('#branch').prev('.form-label').html(data.branchName);
|
||||
}, 'json');
|
||||
|
||||
loadSystem(productID);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$(document).on('change', 'input[name=isIntegrated]', function()
|
||||
@@ -67,7 +70,6 @@ $().ready(function()
|
||||
}
|
||||
});
|
||||
loadBranches();
|
||||
loadSystem();
|
||||
if(multipleProject)
|
||||
{
|
||||
window.waitDom('[name=execution]', function()
|
||||
@@ -75,6 +77,10 @@ $().ready(function()
|
||||
loadProducts();
|
||||
})
|
||||
}
|
||||
if(hidden == 'hide')
|
||||
{
|
||||
loadSystem(currentProduct);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -115,7 +121,6 @@ function loadProducts(executionID)
|
||||
});
|
||||
|
||||
loadLastBuild();
|
||||
loadSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,8 +22,8 @@ $lang->build->batchUnlinkStory = "Batch {$lang->SRCommon} Unlink";
|
||||
$lang->build->batchUnlinkBug = 'Batch Bug Unlink';
|
||||
$lang->build->viewBug = 'Bugs';
|
||||
$lang->build->bugList = 'Bug List';
|
||||
$lang->build->system = 'Application';
|
||||
$lang->build->addSystem = 'Add Application';
|
||||
$lang->build->system = $lang->product->system;
|
||||
$lang->build->addSystem = 'Add ' . $lang->product->system;
|
||||
|
||||
$lang->build->confirmDelete = "Möchten Sie dieses Build löschen?";
|
||||
$lang->build->confirmUnlinkStory = "Möchten Sie diese {$lang->SRCommon} löschen?";
|
||||
|
||||
@@ -22,8 +22,8 @@ $lang->build->batchUnlinkStory = "Batch Unlink {$lang->SRCommon}";
|
||||
$lang->build->batchUnlinkBug = 'Batch Unlink Bugs';
|
||||
$lang->build->viewBug = 'Bugs';
|
||||
$lang->build->bugList = 'Bug List';
|
||||
$lang->build->system = 'Application';
|
||||
$lang->build->addSystem = 'Add Application';
|
||||
$lang->build->system = $lang->product->system;
|
||||
$lang->build->addSystem = 'Add ' . $lang->product->system;
|
||||
|
||||
$lang->build->confirmDelete = "Do you want to delete this build?";
|
||||
$lang->build->confirmUnlinkStory = "Do you want to unlink this {$lang->SRCommon}?";
|
||||
|
||||
@@ -22,8 +22,8 @@ $lang->build->batchUnlinkStory = "Retirer {$lang->SRCommon} par Lot";
|
||||
$lang->build->batchUnlinkBug = 'Retirer Bugs par Lot';
|
||||
$lang->build->viewBug = 'Bugs';
|
||||
$lang->build->bugList = 'Bug List';
|
||||
$lang->build->system = 'Application';
|
||||
$lang->build->addSystem = 'Ajouter Application';
|
||||
$lang->build->system = $lang->product->system;
|
||||
$lang->build->addSystem = 'Add ' . $lang->product->system;
|
||||
|
||||
$lang->build->confirmDelete = "Voulez-vous supprimer ce build ?";
|
||||
$lang->build->confirmUnlinkStory = "Voulez-vous retirer cette {$lang->SRCommon} du Build ?";
|
||||
|
||||
@@ -22,8 +22,8 @@ $lang->build->batchUnlinkStory = "批量移除{$lang->SRCommon}";
|
||||
$lang->build->batchUnlinkBug = '批量移除Bug';
|
||||
$lang->build->viewBug = '查看Bug';
|
||||
$lang->build->bugList = 'Bug列表';
|
||||
$lang->build->system = '所属应用';
|
||||
$lang->build->addSystem = '新建应用';
|
||||
$lang->build->system = '所属' . $lang->product->system;
|
||||
$lang->build->addSystem = '新建' . $lang->product->system;
|
||||
|
||||
$lang->build->confirmDelete = "您确认删除该构建吗?";
|
||||
$lang->build->confirmUnlinkStory = "您确认移除该{$lang->SRCommon}吗?";
|
||||
|
||||
@@ -18,6 +18,8 @@ jsVar('projectID', $projectID);
|
||||
jsVar('executionID', $executionID);
|
||||
jsVar('today', helper::today());
|
||||
jsVar('projectModel', isset($project->model) ? $project->model : '');
|
||||
jsVar('currentProduct', $productID);
|
||||
jsVar('hidden', $hidden);
|
||||
|
||||
$integratedRow = '';
|
||||
if($app->tab == 'project' && !empty($multipleProject))
|
||||
@@ -108,6 +110,7 @@ $productBranches = zget($product, 'branches', array());
|
||||
formPanel
|
||||
(
|
||||
set::title($lang->build->create),
|
||||
set::formID('createBuildForm'),
|
||||
on::change('[name=newSystem]', 'setSystemBox'),
|
||||
on::change('[name=system]', 'loadBuilds'),
|
||||
$integratedRow,
|
||||
|
||||
@@ -59,6 +59,7 @@ class buildZen extends build
|
||||
$this->view->executions = $executions;
|
||||
$this->view->lastBuild = $this->build->getLast($executionID, $projectID);
|
||||
$this->view->project = $this->project->getByID($projectID);
|
||||
$this->view->productID = $productID;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,7 @@ $lang->store->common = 'Store';
|
||||
$lang->instance->common = 'Instance';
|
||||
$lang->ai->common = 'AI';
|
||||
$lang->aiapp->common = 'AI';
|
||||
$lang->product->system = 'Application';
|
||||
|
||||
$lang->programstakeholder->common = 'Stakeholder';
|
||||
$lang->featureswitch->common = 'Features On/Off';
|
||||
|
||||
@@ -282,6 +282,7 @@ $lang->store->common = 'Store';
|
||||
$lang->instance->common = 'Instance';
|
||||
$lang->ai->common = 'AI';
|
||||
$lang->aiapp->common = 'AI';
|
||||
$lang->product->system = 'Application';
|
||||
|
||||
$lang->programstakeholder->common = 'Stakeholder';
|
||||
$lang->featureswitch->common = 'Features On/Off';
|
||||
|
||||
@@ -282,6 +282,7 @@ $lang->store->common = 'Store';
|
||||
$lang->instance->common = 'Instance';
|
||||
$lang->ai->common = 'AI';
|
||||
$lang->aiapp->common = 'AI';
|
||||
$lang->product->system = 'Application';
|
||||
|
||||
$lang->programstakeholder->common = 'Stakeholder';
|
||||
$lang->featureswitch->common = 'Features On/Off';
|
||||
|
||||
@@ -282,6 +282,7 @@ $lang->store->common = '应用市场';
|
||||
$lang->instance->common = '服务';
|
||||
$lang->ai->common = 'AI';
|
||||
$lang->aiapp->common = 'AI';
|
||||
$lang->product->system = '应用';
|
||||
|
||||
$lang->programstakeholder->common = '干系人';
|
||||
$lang->featureswitch->common = '功能开关';
|
||||
|
||||
@@ -1321,7 +1321,7 @@ eof;
|
||||
* The following pages can be allowed to open in non-iframe, so ignore these pages.
|
||||
*/
|
||||
$module = $this->app->getModuleName();
|
||||
$whitelist = is_string($whitelist) ? $whitelist : '|index|tutorial|install|upgrade|sso|cron|misc|user-login|user-deny|user-logout|user-reset|user-forgetpassword|user-resetpassword|my-changepassword|my-preference|file-read|file-download|file-preview|file-uploadimages|file-ajaxwopifiles|report-annualdata|misc-captcha|execution-printkanban|traincourse-ajaxuploadlargefile|traincourse-playvideo|screen-view|zanode-create|screen-ajaxgetchart|ai-chat|integration-wopi|instance-terminal|conference-getconferencepermissions|';
|
||||
$whitelist = is_string($whitelist) ? $whitelist : '|index|tutorial|install|upgrade|sso|cron|misc|user-login|user-deny|user-logout|user-reset|user-forgetpassword|user-resetpassword|my-changepassword|my-preference|file-read|file-download|file-preview|file-uploadimages|file-ajaxwopifiles|report-annualdata|misc-captcha|execution-printkanban|traincourse-ajaxuploadlargefile|traincourse-playvideo|screen-view|zanode-create|screen-ajaxgetchart|ai-chat|integration-wopi|instance-terminal|conference-getconferencepermissions|instance-logs|';
|
||||
$iframeList = '|cron-index|zanode-create|';
|
||||
|
||||
if(strpos($iframeList, "|{$module}-{$method}|") === false && (strpos($whitelist, "|{$module}|") !== false || strpos($whitelist, "|{$module}-{$method}|") !== false)) return true;
|
||||
|
||||
@@ -8,9 +8,11 @@ title=测试 commonModel::checkIframe();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 查看任务一和任务二的描述差异长度 @77
|
||||
- 查看返回的差异中<ins>标签的位置 @44
|
||||
- 查看返回的差异中<del>标签的位置 @5
|
||||
- 查看任务一和任务二的描述差异长度 @1
|
||||
- 查看返回的差异中<ins>标签的位置 查看返回的差异中<del>标签的位置 @1
|
||||
- 查看实例的终端页面instance-terminal会跳出iframe打开 @1
|
||||
- 实例的日志页面instance-logs也会跳出iframe打开 @1
|
||||
- 查看实例的事件页面instance-events会在iframe中打开 @1
|
||||
|
||||
*/
|
||||
|
||||
@@ -24,3 +26,15 @@ r($tester->common->checkIframe()) && p() && e('1'); // 查看该页面是否要
|
||||
$app->moduleName = 'execution';
|
||||
$app->methodName = 'task';
|
||||
r($tester->common->checkIframe()) && p() && e('1'); // 查看该页面是否要在iframe中打开
|
||||
|
||||
$app->moduleName = 'instance';
|
||||
$app->methodName = 'terminal';
|
||||
r($tester->common->checkIframe()) && p(0) && e('1');
|
||||
|
||||
$app->moduleName = 'instance';
|
||||
$app->methodName = 'logs';
|
||||
r($tester->common->checkIframe()) && p('0') && e('1');
|
||||
|
||||
$app->moduleName = 'instance';
|
||||
$app->methodName = 'events';
|
||||
r($tester->common->checkIframe()) && p(0) && e('1');
|
||||
|
||||
@@ -111,7 +111,7 @@ $config->custom->customFields['todo'] = array('custom' => array('batchCre
|
||||
$config->custom->customFields['user'] = array('custom' => array('batchCreateFields', 'batchEditFields'));
|
||||
|
||||
global $lang;
|
||||
$config->custom->commonLang = array('$URCOMMON' => $lang->URCommon, '$SRCOMMON' => $lang->SRCommon, '$PRODUCTCOMMON' => $lang->productCommon, '$PROJECTCOMMON' => $lang->projectCommon, '$EXECUTIONCOMMON' => $lang->executionCommon);
|
||||
$config->custom->commonLang = array('$ERCOMMON' => $lang->ERCommon, '$URCOMMON' => $lang->URCommon, '$SRCOMMON' => $lang->SRCommon, '$PRODUCTCOMMON' => $lang->productCommon, '$PROJECTCOMMON' => $lang->projectCommon, '$EXECUTIONCOMMON' => $lang->executionCommon);
|
||||
|
||||
$config->custom->browseStoryConcept = new stdclass();
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ class customModel extends model
|
||||
}
|
||||
else
|
||||
{
|
||||
if($customLang->module == 'productMenu' && $customLang->key == 'system') $this->lang->product->system = $customLang->value;
|
||||
$processedLang[$customLang->module][$customLang->section][$customLang->key] = $customLang->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,8 +115,8 @@ class design extends control
|
||||
$designs = $this->design->getList($projectID, $productID, $type, $queryID, $orderBy, $pager);
|
||||
if($this->config->edition != 'open')
|
||||
{
|
||||
$this->loadModel('custom');
|
||||
foreach($designs as $design) $design->relatedObject = $this->custom->getRelatedObjectList($design->id, 'design', 'byRelation', true);
|
||||
$designRelatedObjectList = $this->loadModel('custom')->getRelatedObjectList(array_keys($designs), 'design', 'byRelation', true);
|
||||
foreach($designs as $design) $design->relatedObject = zget($designRelatedObjectList, $design->id, 0);
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->design->common . $this->lang->hyphen . $this->lang->design->browse;
|
||||
|
||||
@@ -121,6 +121,8 @@ class dev extends control
|
||||
$method = 'work';
|
||||
}
|
||||
$moduleName = $module . 'SubMenu';
|
||||
|
||||
if($moduleName == 'qa' && $method = 'automation') $this->loadModel('zanode')->setMenu();
|
||||
}
|
||||
|
||||
if($type == 'tag')
|
||||
|
||||
@@ -318,6 +318,12 @@ class devModel extends model
|
||||
|
||||
if(isset($defaultLang->$module->menu))
|
||||
{
|
||||
if($module == 'product')
|
||||
{
|
||||
$defaultLang->product->menu->system = $defaultLang->product->system;
|
||||
$defaultLang->product->menuOrder[41] = 'system';
|
||||
}
|
||||
|
||||
$menuList = $defaultLang->$module->menu;
|
||||
if(isset($defaultLang->$module->menuOrder)) $menuList->menuOrder = $defaultLang->$module->menuOrder;
|
||||
$menuList = $this->sortMenus($menuList);
|
||||
|
||||
@@ -55,7 +55,7 @@ $config->doc->form->create['users'] = array('type' => 'array', 'requir
|
||||
$config->doc->form->create['mailto'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
$config->doc->form->create['contentType'] = array('type' => 'string', 'required' => false, 'default' => 'doc');
|
||||
$config->doc->form->create['content'] = array('type' => 'string', 'required' => false, 'default' => '', 'control' => 'editor', 'skipRequired' => true);
|
||||
$config->doc->form->create['html'] = array('type' => 'string', 'required' => false, 'default' => '', 'skipRequired' => true);
|
||||
$config->doc->form->create['rawContent'] = array('type' => 'string', 'required' => false, 'default' => '', 'control' => 'editor', 'skipRequired' => true);
|
||||
$config->doc->form->create['template'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->doc->form->create['templateType'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->doc->form->create['chapterType'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
@@ -72,9 +72,9 @@ $config->doc->form->edit['status'] = array('type' => 'string', 'required'
|
||||
$config->doc->form->edit['type'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->doc->form->edit['keywords'] = array('type' => 'string', 'required' => false, 'default' => '', 'skipRequired' => true);
|
||||
$config->doc->form->edit['acl'] = array('type' => 'string', 'required' => false, 'default' => '');
|
||||
$config->doc->form->edit['contentType']= array('type' => 'string', 'required' => false, 'default' => 'html');
|
||||
$config->doc->form->edit['contentType']= array('type' => 'string', 'required' => false, 'default' => 'doc');
|
||||
$config->doc->form->edit['content'] = array('type' => 'string', 'required' => false, 'default' => '', 'control' => 'editor', 'skipRequired' => true);
|
||||
$config->doc->form->edit['html'] = array('type' => 'string', 'required' => false, 'default' => '', 'control' => 'editor', 'skipRequired' => true);
|
||||
$config->doc->form->edit['rawContent'] = array('type' => 'string', 'required' => false, 'default' => '', 'control' => 'editor', 'skipRequired' => true);
|
||||
$config->doc->form->edit['groups'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
$config->doc->form->edit['users'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
$config->doc->form->edit['mailto'] = array('type' => 'array', 'required' => false, 'default' => '', 'filter' => 'join');
|
||||
|
||||
+59
-10
@@ -1825,6 +1825,46 @@ class doc extends control
|
||||
$this->send($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax: Get migrate docs id list.
|
||||
* Ajax: 获取迁移文档ID列表。
|
||||
*
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetMigrateDocs(string $type)
|
||||
{
|
||||
$docs = $this->doc->getMigrateDocs($type);
|
||||
echo json_encode($docs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax: Migrate doc.
|
||||
* Ajax: 迁移文档。
|
||||
*
|
||||
* @param int $docID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxMigrateDoc(int $docID)
|
||||
{
|
||||
if(!common::hasPriv('doc', 'edit')) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorPrivilege));
|
||||
|
||||
if(empty($_POST)) return $this->send(array('result' => 'fail', 'message' => $this->lang->error->unsupportedReq));
|
||||
|
||||
$doc = $this->doc->getByID($docID);
|
||||
if(empty($doc)) return $this->send(array('result' => 'fail', 'message' => $this->lang->notFound));
|
||||
|
||||
if(!$this->doc->checkPrivDoc($doc)) return $this->send(array('result' => 'fail', 'message' => $this->lang->doc->errorPrivilege));
|
||||
|
||||
$html = $this->post->html;
|
||||
$result = $this->doc->migrateDoc($docID, $doc->version, $html);
|
||||
if(!$result) return $this->send(array('result' => 'fail', 'message' => $this->lang->saveFailed));
|
||||
|
||||
$this->send(array('result' => 'success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax: Get doc data.
|
||||
* Ajax: 获取文档数据。
|
||||
@@ -1869,10 +1909,12 @@ class doc extends control
|
||||
$doc->object = $object;
|
||||
}
|
||||
|
||||
if(!empty($doc->rawContent)) $doc->content = $doc->rawContent;
|
||||
if($doc->contentType === 'doc' && is_string($doc->content)) $doc->content = htmlspecialchars_decode($doc->content);
|
||||
if(is_string($doc->title)) $doc->title = htmlspecialchars_decode($doc->title);
|
||||
if(!empty($doc->keywords) && is_string($doc->keywords)) $doc->keywords = htmlspecialchars_decode($doc->keywords);
|
||||
|
||||
unset($doc->rawContent);
|
||||
if($docID) $this->doc->createAction($docID, 'view');
|
||||
|
||||
$this->send($doc);
|
||||
@@ -1894,18 +1936,25 @@ class doc extends control
|
||||
*/
|
||||
public function ajaxGetFiles(string $type, int $objectID, string $browseType = '', string $orderBy = 'id_desc', int $recTotal = 0, int $recPerPage = 9999, int $pageID = 1)
|
||||
{
|
||||
/* Load pager. */
|
||||
$rawMethod = $this->app->rawMethod;
|
||||
$this->app->rawMethod = 'showFiles';
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$this->app->rawMethod = $rawMethod;
|
||||
if(common::hasPriv('doc', 'showFiles'))
|
||||
{
|
||||
/* Load pager. */
|
||||
$rawMethod = $this->app->rawMethod;
|
||||
$this->app->rawMethod = 'showFiles';
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
$this->app->rawMethod = $rawMethod;
|
||||
|
||||
$files = $this->doc->getLibFiles($type, $objectID, $browseType, 0, $orderBy, $pager);
|
||||
$sourcePairs = $this->doc->getFileSourcePairs($files);
|
||||
$files = $this->docZen->processFiles($files, array(), $sourcePairs, true);
|
||||
$files = $this->doc->getLibFiles($type, $objectID, $browseType, 0, $orderBy, $pager);
|
||||
$sourcePairs = $this->doc->getFileSourcePairs($files);
|
||||
$files = $this->docZen->processFiles($files, array(), $sourcePairs, true);
|
||||
|
||||
echo json_encode(array_values($files)); // $this->send($files); not work.
|
||||
echo json_encode(array_values($files)); // $this->send($files); not work.
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '[]';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
.files-grid .img-holder > img {width: 33%; margin: 0 auto; max-height: 64px;}
|
||||
.files-grid .img-holder > img.not-exist {opacity: 0;}
|
||||
|
||||
.menu-item.is-nested > .item-inner .item-content .item-title {flex-grow: 0!important; opacity: .6;}
|
||||
.menu-item.is-nested > .item-inner .item-content .item-subtitle {--skin-pale-rgb: var(--color-gray-500-rgb); height: 1rem; min-width: 1rem; border-radius: var(--radius-full); --skin-color: rgba(var(--skin-pale-rgb), .1); --skin-text: rgba(var(--skin-pale-rgb), 1); --state-color: rgba(var(--skin-pale-rgb), .1); --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); display: inline-flex; font-size: .75rem; align-items: center; justify-content: center; line-height: 1rem; padding-left: .25rem; padding-right: .25rem;}
|
||||
.menu-item.is-nested > .item-inner {background-color: inherit!important; color: inherit!important; cursor: default;}
|
||||
.menu-item.is-nested > .item-inner::before {display: none;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner .item-content .item-title {flex-grow: 0!important; opacity: .6;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner .item-content .item-subtitle {--skin-pale-rgb: var(--color-gray-500-rgb); height: 1rem; min-width: 1rem; border-radius: var(--radius-full); --skin-color: rgba(var(--skin-pale-rgb), .1); --skin-text: rgba(var(--skin-pale-rgb), 1); --state-color: rgba(var(--skin-pale-rgb), .1); --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); display: inline-flex; font-size: .75rem; align-items: center; justify-content: center; line-height: 1rem; padding-left: .25rem; padding-right: .25rem;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner {background-color: inherit!important; color: inherit!important; cursor: default;}
|
||||
.picker-menu .menu-item.is-nested > .item-inner::before {display: none;}
|
||||
|
||||
@@ -20,6 +20,7 @@ window.changeDoclibAcl = function(e)
|
||||
{
|
||||
$('.apilib').removeClass('hidden');
|
||||
$('#orderBox').addClass('hidden');
|
||||
$('#orderBox #orderByid_asc').trigger('click');
|
||||
$('#aclBox .check-list').html($('#aclAPIBox .check-list').html());
|
||||
$("#aclBox input[id='aclopen']").prop('checked', true);
|
||||
|
||||
@@ -28,6 +29,7 @@ window.changeDoclibAcl = function(e)
|
||||
else
|
||||
{
|
||||
$('.apilib').addClass('hidden');
|
||||
$('#orderBox').removeClass('hidden');
|
||||
$('#aclBox .check-list').html($('#aclOtherBox .check-list').html());
|
||||
$("#aclBox input[id='acldefault']").prop('checked', true);
|
||||
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
window.loadExecutions = function(e)
|
||||
window.loadExecutions = function()
|
||||
{
|
||||
const officeTypes = $('#setDocBasicForm').data('officeTypes');
|
||||
const docType = $('#setDocBasicForm').data('docType');
|
||||
const isOfficeType = officeTypes.includes(docType);
|
||||
const projectElement = isOfficeType ? '.projectBox input[name="project"]': '#setDocBasicForm input[name="project"]';
|
||||
const executionElement = isOfficeType ? '.executionBox input[name="execution"]': '#setDocBasicForm input[name="execution"]';
|
||||
const projectID = $(projectElement).val();
|
||||
if($(executionElement))
|
||||
const $project = $('#setDocBasicForm input[name="project"]');
|
||||
const $execution = $('#setDocBasicForm input[name="execution"]');
|
||||
const projectID = $project.val();
|
||||
|
||||
if($execution.length)
|
||||
{
|
||||
const executionID = $(executionElement).val();
|
||||
const link = $.createLink('project', 'ajaxGetExecutions', "projectID=" + projectID + "&mode=multiple,leaf,noprefix");
|
||||
const executionID = $execution.val();
|
||||
const link = $.createLink('project', 'ajaxGetExecutions', `projectID=${projectID}&mode=multiple,leaf,noprefix`);
|
||||
$.getJSON(link, function(data)
|
||||
{
|
||||
let $picker = $(executionElement).zui('picker');
|
||||
$picker.render({items: data.items, disabled: !data.multiple});
|
||||
$picker.$.setValue(executionID);
|
||||
const picker = $(executionElement).zui('picker');
|
||||
picker.render({items: data.items, disabled: !data.multiple});
|
||||
picker.$.setValue(executionID);
|
||||
});
|
||||
}
|
||||
|
||||
const link = $.createLink('doc', 'ajaxGetModules', 'objectType=project&objectID=' + projectID + '&type=doc');
|
||||
const link = $.createLink('doc', 'ajaxGetModules', `objectType=project&objectID=${projectID}&type=doc`);
|
||||
$.getJSON(link, function(data)
|
||||
{
|
||||
const $libPicker = $(`${isOfficeType ? '' : '#setDocBasicForm'} [name='lib']`).zui('picker');
|
||||
$libPicker.render({items: data.libs});
|
||||
$libPicker.$.setValue('');
|
||||
const libPicker = $(`#setDocBasicForm [name="lib"]`).zui('picker');
|
||||
libPicker.render({items: data.libs});
|
||||
libPicker.$.setValue('');
|
||||
|
||||
const $modulePicker = $(`${isOfficeType ? '' : '#setDocBasicForm'} [name='module']`).zui('picker');
|
||||
$modulePicker.render({items: data.modules});
|
||||
$modulePicker.$.setValue('');
|
||||
const modulePicker = $(`#setDocBasicForm [name="module"]`).zui('picker');
|
||||
modulePicker.render({items: data.modules});
|
||||
modulePicker.$.setValue('');
|
||||
});
|
||||
}
|
||||
|
||||
+74
-19
@@ -775,8 +775,9 @@ class docModel extends model
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('templateType')->eq('')
|
||||
->andWhere("(status = 'normal' or (status = 'draft' and addedBy='{$this->app->user->account}'))")
|
||||
->andWhere('module')->eq(0)
|
||||
->andWhere('module')->in(array('0', ''))
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('type')->ne('chapter')
|
||||
->orderBy('`order` asc, id_asc')
|
||||
->fetchAll('id');
|
||||
|
||||
@@ -813,6 +814,58 @@ class docModel extends model
|
||||
return $docs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取需要迁移的文档ID列表。
|
||||
* Get docs need to migrate.
|
||||
*
|
||||
* @param string $spaceType
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrateDocs(string $spaceType)
|
||||
{
|
||||
$docs = $this->dao->select('t1.*,t2.title,t2.content,t2.type as contentType,t2.html')->from(TABLE_DOC)->alias('t1')
|
||||
->leftJoin(TABLE_DOCCONTENT)->alias('t2')->on('t1.id=t2.doc && t1.version=t2.version')
|
||||
->where('t2.type')->eq('doc')
|
||||
->andWhere('t1.status')->ne('draft')
|
||||
->andWhere('t2.html')->in(null)
|
||||
->andWhere('t1.deleted')->eq('0')
|
||||
->fetchAll('id');
|
||||
|
||||
$docs = $this->filterPrivDocs($docs, $spaceType);
|
||||
$ids = array();
|
||||
|
||||
foreach($docs as $doc)
|
||||
{
|
||||
if(empty($doc->rawContent) && !empty($doc->content)) $ids[] = $doc->id;
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移文档,设置新编辑器文档的 html。
|
||||
* Migrate doc, set doc html generated by new editor.
|
||||
*
|
||||
* @param int $docID
|
||||
* @param int $version
|
||||
* @param string $html
|
||||
*/
|
||||
public function migrateDoc(int $docID, int $version, string $html): bool
|
||||
{
|
||||
$docContent = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($docID)->andWhere('version')->eq($version)->fetch();
|
||||
if(empty($docContent)) return false;
|
||||
|
||||
$rawContent = empty($docContent->rawContent) ? $docContent->content : $docContent->rawContent;
|
||||
$this->dao->update(TABLE_DOCCONTENT)
|
||||
->set('rawContent')->eq($rawContent)
|
||||
->set('content')->eq($html)
|
||||
->where('id')->eq($docContent->id)
|
||||
->exec();
|
||||
|
||||
if(dao::isError()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤出有权限的文档列表。
|
||||
* Filter docs which has privilege.
|
||||
@@ -1094,6 +1147,7 @@ class docModel extends model
|
||||
$doc->title = isset($docContent->title) ? $docContent->title : $doc->title;
|
||||
$doc->digest = isset($docContent->digest) ? $docContent->digest : '';
|
||||
$doc->content = isset($docContent->content) ? $docContent->content : '';
|
||||
$doc->rawContent = isset($docContent->rawContent) ? $docContent->rawContent : '';
|
||||
$doc->contentType = isset($docContent->type) ? $docContent->type : '';
|
||||
$doc->contentVersion = isset($docContent->version) ? $docContent->version : $version;
|
||||
if($doc->type != 'url' && $doc->contentType != 'markdown' && $doc->contentType != 'doc') $doc = $this->loadModel('file')->replaceImgURL($doc, 'content,draft');
|
||||
@@ -1395,6 +1449,7 @@ class docModel extends model
|
||||
$docContent->digest = '';
|
||||
$docContent->version = 1;
|
||||
unset($doc->contentType);
|
||||
unset($doc->rawContent);
|
||||
|
||||
return $this->insertSeperateDocs($doc, $docContent, $files);
|
||||
}
|
||||
@@ -1477,15 +1532,15 @@ class docModel extends model
|
||||
$doc->execution = $lib->execution;
|
||||
}
|
||||
|
||||
$docContent = new stdclass();
|
||||
$docContent->title = $doc->title;
|
||||
$docContent->content = $doc->content;
|
||||
$docContent->type = $doc->contentType;
|
||||
$docContent->html = isset($doc->html) ? $doc->html : '';
|
||||
$docContent->digest = '';
|
||||
$docContent->version = 1;
|
||||
$docContent = new stdclass();
|
||||
$docContent->title = $doc->title;
|
||||
$docContent->content = $doc->content;
|
||||
$docContent->type = $doc->contentType;
|
||||
$docContent->rawContent = isset($doc->rawContent) ? $doc->rawContent : '';
|
||||
$docContent->digest = '';
|
||||
$docContent->version = 1;
|
||||
unset($doc->contentType);
|
||||
unset($doc->html);
|
||||
unset($doc->rawContent);
|
||||
|
||||
$requiredFields = $type == 'doc' ? $this->config->doc->create->requiredFields : $this->config->doc->createTemplate->requiredFields;
|
||||
if($doc->status == 'draft') $requiredFields = 'title';
|
||||
@@ -1550,15 +1605,15 @@ class docModel extends model
|
||||
|
||||
if($changed)
|
||||
{
|
||||
$docContent = new stdclass();
|
||||
$docContent->doc = $oldDoc->id;
|
||||
$docContent->title = $doc->title;
|
||||
$docContent->content = isset($doc->content) ? $doc->content : '';
|
||||
$docContent->files = $oldDocContent->files;
|
||||
$docContent->type = isset($doc->contentType) ? $doc->contentType : $oldDocContent->type;
|
||||
$docContent = new stdclass();
|
||||
$docContent->doc = $oldDoc->id;
|
||||
$docContent->title = $doc->title;
|
||||
$docContent->content = isset($doc->content) ? $doc->content : '';
|
||||
$docContent->files = $oldDocContent->files;
|
||||
$docContent->type = isset($doc->contentType) ? $doc->contentType : $oldDocContent->type;
|
||||
if($files) $docContent->files .= ',' . join(',', array_keys($files));
|
||||
$docContent->html = isset($doc->html) ? $doc->html : '';
|
||||
$docContent->files = trim($docContent->files, ',');
|
||||
$docContent->rawContent = isset($doc->rawContent) ? $doc->rawContent : '';
|
||||
$docContent->files = trim($docContent->files, ',');
|
||||
if(isset($doc->digest)) $docContent->digest = $doc->digest;
|
||||
|
||||
if($oldDoc->status == 'draft') $this->dao->update(TABLE_DOCCONTENT)->data($docContent)->where('id')->eq($oldDocContent->id)->exec();
|
||||
@@ -1571,7 +1626,7 @@ class docModel extends model
|
||||
}
|
||||
|
||||
unset($doc->contentType);
|
||||
unset($doc->html);
|
||||
unset($doc->rawContent);
|
||||
$doc->draft = isset($doc->content) ? $doc->content : '';
|
||||
$this->dao->update(TABLE_DOC)->data($doc, 'content')
|
||||
->autoCheck()
|
||||
@@ -3304,7 +3359,7 @@ class docModel extends model
|
||||
{
|
||||
$allLibs = $this->getLibs('hasApi');
|
||||
$hasPrivDocIdList = $this->getPrivDocs(array(), 0, 'all');
|
||||
$apiList = $this->loadModel('api')->getPrivApis();
|
||||
$apiList = $this->loadModel('api')->getPrivApis('all');
|
||||
$actionCondition = $this->loadModel('action')->getActionCondition('doc');
|
||||
|
||||
$actions = $this->dao->select('*')->from(TABLE_ACTION)
|
||||
|
||||
@@ -53,6 +53,7 @@ $privs['sortModule'] = hasPriv('doc', 'sortCatalog');
|
||||
$privs['sortDoclib'] = hasPriv('doc', 'sortDoclib');
|
||||
$privs['sortDoc'] = hasPriv('doc', 'sortDoc');
|
||||
$privs['batchMoveDoc'] = hasPriv('doc', 'batchMoveDoc');
|
||||
$privs['showFiles'] = hasPriv('doc', 'showFiles');
|
||||
$privs['createApi'] = hasPriv('api', 'create');
|
||||
$privs['editApi'] = hasPriv('api', 'edit');
|
||||
$privs['viewApi'] = hasPriv('api', 'view');
|
||||
@@ -74,5 +75,7 @@ docApp
|
||||
set::homeName($homeName),
|
||||
set::pager(array('recTotal' => $recTotal, 'recPerPage' => $recPerPage, 'page' => $pageID)),
|
||||
set::privs($privs),
|
||||
set::showLibFiles($privs['showFiles'] ? array('product', 'project', 'execution') : false),
|
||||
set::migrateUrl(createLink('doc', 'ajaxGetMigrateDocs', "type=$type")),
|
||||
set('$options', jsRaw('window.setDocAppOptions'))
|
||||
);
|
||||
|
||||
@@ -17,28 +17,25 @@ $apiType = isset($params['apiType']) ? $params['apiType'] : 'product';
|
||||
$products = $this->loadModel('product')->getPairs();
|
||||
$projects = $this->loadModel('project')->getPairsByProgram(0, 'all', false, 'order_asc');
|
||||
|
||||
$libs = array();
|
||||
if($apiType == 'product')
|
||||
{
|
||||
$useType = $apiType;
|
||||
$objectID = isset($params['objectID']) ? (int)$params['objectID'] : key($products);
|
||||
$libPairs = $this->doc->getLibs($useType, '', '', (int)$objectID);
|
||||
$libs = $this->doc->getApiLibs(0, $useType, (int)$objectID);
|
||||
}
|
||||
elseif($apiType == 'project')
|
||||
{
|
||||
$objectID = isset($params['objectID']) ? (int)$params['objectID'] : key($projects);
|
||||
$executions = $this->loadModel('execution')->getPairs($objectID, 'all', 'multiple,leaf,noprefix');
|
||||
$executionID = (isset($params['executionID']) && isset($executions[$params['executionID']])) ? $params['executionID'] : '';
|
||||
|
||||
$useType = $executionID ? 'execution' : 'project';
|
||||
$useID = $executionID ? $executionID : $objectID;
|
||||
$libPairs = $this->doc->getLibs($useType, '', '', (int)$useID);
|
||||
$useType = $apiType;
|
||||
$objectID = isset($params['objectID']) ? (int)$params['objectID'] : key($projects);
|
||||
$libs = $this->doc->getApiLibs(0, $useType, (int)$objectID);
|
||||
}
|
||||
elseif($apiType == 'nolink')
|
||||
{
|
||||
$libs = $this->doc->getApiLibs(0, 'nolink');
|
||||
$libPairs = array();
|
||||
foreach($libs as $libID => $lib) $libPairs[$libID] = $lib->name;
|
||||
$libs = $this->doc->getApiLibs(0, 'nolink');
|
||||
}
|
||||
$libPairs = array();
|
||||
foreach($libs as $libID => $lib) $libPairs[$libID] = $lib->name;
|
||||
|
||||
$libID = isset($params['libID']) && isset($libPairs[$params['libID']]) ? $params['libID'] : key($libPairs);
|
||||
|
||||
@@ -74,32 +71,11 @@ form
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->doc->project),
|
||||
set::width('2/5'),
|
||||
set::width('4/5'),
|
||||
set::name('project'),
|
||||
set::items(createLink('project', 'ajaxGetDropMenu', "objectID=$objectID&module=&method=&extra=selectmode&useLink=0")),
|
||||
set::value($objectID),
|
||||
set::required(true)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
set::width('2/5'),
|
||||
set::label($lang->doc->execution),
|
||||
set::labelClass('executionTH'),
|
||||
set::control(array('control' => 'picker', 'name' => 'execution', 'items' => $executions, 'value' => $executionID))
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
setClass('executionHelp'),
|
||||
icon
|
||||
(
|
||||
'help',
|
||||
set('data-toggle', 'tooltip'),
|
||||
set('data-title', $lang->doc->placeholder->execution),
|
||||
set('data-placement', 'right'),
|
||||
set('data-type', 'white'),
|
||||
set('data-class-name', 'text-gray border border-light'),
|
||||
setClass('ml-2 mt-2 text-gray')
|
||||
)
|
||||
)
|
||||
) : null,
|
||||
$apiType == 'product' ? formRow
|
||||
|
||||
@@ -64,7 +64,7 @@ form
|
||||
formGroup
|
||||
(
|
||||
set::label($lang->doc->project),
|
||||
set::width('2/5'),
|
||||
set::width($docType == 'doc' ? '2/5' : '4/5'),
|
||||
set::name('project'),
|
||||
set::items(createLink('project', 'ajaxGetDropMenu', "objectID=$objectID&module=&method=&extra=selectmode&useLink=0")),
|
||||
set::value($objectID),
|
||||
|
||||
@@ -664,6 +664,12 @@ class docZen extends doc
|
||||
}
|
||||
|
||||
if(isInModal()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => true));
|
||||
|
||||
if(!empty($doc->rawContent)) $doc->content = $doc->rawContent;
|
||||
if($doc->contentType === 'doc' && is_string($doc->content)) $doc->content = htmlspecialchars_decode($doc->content);
|
||||
if(is_string($doc->title)) $doc->title = htmlspecialchars_decode($doc->title);
|
||||
if(!empty($doc->keywords) && is_string($doc->keywords)) $doc->keywords = htmlspecialchars_decode($doc->keywords);
|
||||
unset($doc->rawContent);
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link, 'doc' => $doc));
|
||||
}
|
||||
|
||||
|
||||
@@ -161,9 +161,10 @@ class execution extends control
|
||||
foreach($this->view->teamMembers as $key => $member) $memberPairs[$key] = $member->realname;
|
||||
$memberPairs = $this->loadModel('user')->setCurrentUserFirst($memberPairs);
|
||||
|
||||
if($this->config->edition != 'open') $taskRelatedObject = $this->loadModel('custom')->getRelatedObjectList(array_keys($tasks), 'task', 'byRelation', true);
|
||||
|
||||
/* Append branches to task. */
|
||||
$this->loadModel('task');
|
||||
$this->loadModel('custom');
|
||||
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($this->view->products));
|
||||
foreach($tasks as $task)
|
||||
{
|
||||
@@ -183,7 +184,7 @@ class execution extends control
|
||||
}
|
||||
if(isset($branchGroups[$task->product][$task->branch])) $task->branch = $branchGroups[$task->product][$task->branch];
|
||||
if($task->needConfirm) $task->status = 'changed';
|
||||
if($this->config->edition != 'open') $task->relatedObject = $this->custom->getRelatedObjectList($task->id, 'task', 'byRelation', true);
|
||||
if($this->config->edition != 'open') $task->relatedObject = zget($taskRelatedObject, $task->id, 0);
|
||||
}
|
||||
|
||||
$showAllModule = empty($this->config->execution->task->allModule) ? '' : 'allModule';
|
||||
@@ -1599,6 +1600,7 @@ class execution extends control
|
||||
|
||||
$this->view->title = $this->view->execution->name . $this->lang->hyphen .$this->lang->execution->close;
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noletter');
|
||||
$this->view->from = $from;
|
||||
$this->view->actions = $this->loadModel('action')->getList($this->objectType, $executionID);
|
||||
$this->view->unclosedTasks = $this->loadModel('task')->getUnclosedTasksByExecution($executionID);
|
||||
$this->display();
|
||||
|
||||
@@ -1051,7 +1051,7 @@ class executionModel extends model
|
||||
$project = $this->loadModel('project')->getByID($projectID);
|
||||
if(empty($project)) return;
|
||||
|
||||
if(($project->model == 'waterfall' || $project->model == 'waterfallplus') && $parentID != $projectID)
|
||||
if(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd')) && $parentID != $projectID)
|
||||
{
|
||||
$this->app->loadLang('programplan');
|
||||
$parent = $this->getByID($parentID);
|
||||
@@ -4507,27 +4507,30 @@ class executionModel extends model
|
||||
$this->app->loadLang('story');
|
||||
$gradePairs = zget($gradeGroup, $tree->type, array());
|
||||
$grade = zget($gradePairs, $tree->grade, $tree->grade);
|
||||
$gradeName = ($grade && isset($grade->name)) ? "<span class='label gray-pale rounded-full'>{$grade->name}</span>" : '';
|
||||
$treeData[$index]['url'] = $canViewStory ? helper::createLink('execution', 'treeStory', "taskID={$tree->storyId}") : '';
|
||||
$treeData[$index]['content'] = array(
|
||||
'html' => "<div class='tree-link'><span class='label gray-pale rounded-full'>{$grade->name}</span><span class='ml-4'>{$tree->storyId}</span><span class='title " . ($canViewStory ? 'text-primary' : '') . " ml-4' title='{$tree->title}'>{$tree->title}</span>" . $assigedToHtml . '</div>',
|
||||
'html' => "<div class='tree-link'>{$gradeName}<span class='ml-4'>{$tree->storyId}</span><span class='title " . ($canViewStory ? 'text-primary' : '') . " ml-4' title='{$tree->title}'>{$tree->title}</span>" . $assigedToHtml . '</div>',
|
||||
);
|
||||
break;
|
||||
case 'requirement':
|
||||
$this->app->loadLang('requirement');
|
||||
$gradePairs = zget($gradeGroup, $tree->type, array());
|
||||
$grade = zget($gradePairs, $tree->grade, $tree->grade);
|
||||
$gradeName = ($grade && isset($grade->name)) ? "<span class='label gray-pale rounded-full'>{$grade->name}</span>" : '';
|
||||
$treeData[$index]['url'] = helper::createLink('execution', 'treeStory', "taskID={$tree->storyId}");
|
||||
$treeData[$index]['content'] = array(
|
||||
'html' => "<div class='tree-link'><span class='label gray-pale rounded-full'>{$grade->name}</span><span class='ml-4'>{$tree->storyId}</span><span class='title text-primary ml-4' title='{$tree->title}'>{$tree->title}</span>" . $assigedToHtml . '</div>',
|
||||
'html' => "<div class='tree-link'>{$gradeName}<span class='ml-4'>{$tree->storyId}</span><span class='title text-primary ml-4' title='{$tree->title}'>{$tree->title}</span>" . $assigedToHtml . '</div>',
|
||||
);
|
||||
break;
|
||||
case 'epic':
|
||||
$this->app->loadLang('epic');
|
||||
$gradePairs = zget($gradeGroup, $tree->type, array());
|
||||
$grade = zget($gradePairs, $tree->grade, $tree->grade);
|
||||
$gradeName = ($grade && isset($grade->name)) ? "<span class='label gray-pale rounded-full'>{$grade->name}</span>" : '';
|
||||
$treeData[$index]['url'] = helper::createLink('execution', 'treeStory', "taskID={$tree->storyId}");
|
||||
$treeData[$index]['content'] = array(
|
||||
'html' => "<div class='tree-link'><span class='label gray-pale rounded-full'>{$grade->name}</span><span class='ml-4'>{$tree->storyId}</span><span class='title text-primary ml-4' title='{$tree->title}'>{$tree->title}</span>" . $assigedToHtml . '</div>',
|
||||
'html' => "<div class='tree-link'>{$gradeName}<span class='ml-4'>{$tree->storyId}</span><span class='title text-primary ml-4' title='{$tree->title}'>{$tree->title}</span>" . $assigedToHtml . '</div>',
|
||||
);
|
||||
break;
|
||||
case 'branch':
|
||||
|
||||
@@ -27,6 +27,7 @@ jsVar('hourPointNotError', sprintf($lang->story->float, $lang->story->convertRe
|
||||
|
||||
/* Show feature bar. */
|
||||
$queryMenuLink = createLink($app->rawModule, $app->rawMethod, "&executionID=$execution->id&storyType=$storyType&orderBy=$orderBy&type=bySearch¶m={queryID}");
|
||||
if(empty($param) && $this->cookie->storyModuleParam) $param = $this->cookie->storyModuleParam;
|
||||
featureBar
|
||||
(
|
||||
to::leading
|
||||
|
||||
@@ -1578,7 +1578,7 @@ class executionZen extends execution
|
||||
if($this->config->edition != 'open')
|
||||
{
|
||||
$flow = $this->loadModel('workflow')->getByModule($module);
|
||||
if(in_array($flow->app, array('scrum', 'waterfall'))) $flow->app = 'project';
|
||||
if(!empty($flow) && in_array($flow->app, array('scrum', 'waterfall'))) $flow->app = 'project';
|
||||
if(!empty($flow) && $flow->buildin == '0') return helper::createLink('flow', 'ajaxSwitchBelong', "objectID=%s&moduleName=$module") . "#app=$flow->app";
|
||||
}
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ class fileModel extends model
|
||||
$contentType = isset($mimes[$fileType]) ? $mimes[$fileType] : $mimes['default'];
|
||||
|
||||
/* Safari浏览器下载文件名乱码问题。 */
|
||||
if($_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded' && preg_match("/Safari/", $_SERVER["HTTP_USER_AGENT"]))
|
||||
if(isset($_SERVER['CONTENT_TYPE']) && isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded' && preg_match("/Safari/", $_SERVER["HTTP_USER_AGENT"]))
|
||||
{
|
||||
$fileName = rawurlencode($fileName);
|
||||
$attachment = 'attachment; filename*=utf-8\'\'' . $fileName;
|
||||
|
||||
@@ -21,19 +21,17 @@ $config->instance->enableAutoRestore = in_array('auto-rollback', $features);
|
||||
global $lang, $app;
|
||||
$app->loadLang('space');
|
||||
|
||||
$config->instance->actionList['showLogs']['icon'] = 'time';
|
||||
$config->instance->actionList['showLogs']['hint'] = $lang->instance->log->viewButton;
|
||||
$config->instance->actionList['showLogs']['text'] = $lang->instance->log->viewButton;
|
||||
$config->instance->actionList['showLogs']['url'] = array('module' => 'instance', 'method' => 'logs', 'params' => 'id={id}&zin=1');
|
||||
$config->instance->actionList['showLogs']['data-toggle'] = 'modal';
|
||||
$config->instance->actionList['showLogs']['class'] = 'task-record-btn';
|
||||
$config->instance->actionList['showLogs']['icon'] = 'time';
|
||||
$config->instance->actionList['showLogs']['hint'] = $lang->instance->log->viewButton;
|
||||
$config->instance->actionList['showLogs']['text'] = $lang->instance->log->viewButton;
|
||||
$config->instance->actionList['showLogs']['url'] = array('module' => 'instance', 'method' => 'logs', 'params' => 'id={id}');
|
||||
$config->instance->actionList['showLogs']['target'] = '_blank';
|
||||
|
||||
$config->instance->actionList['showEvents']['icon'] = 'magic';
|
||||
$config->instance->actionList['showEvents']['icon'] = 'summary';
|
||||
$config->instance->actionList['showEvents']['hint'] = $lang->instance->event->viewButton;
|
||||
$config->instance->actionList['showEvents']['text'] = $lang->instance->event->viewButton;
|
||||
$config->instance->actionList['showEvents']['url'] = array('module' => 'instance', 'method' => 'events', 'params' => 'id={id}');
|
||||
$config->instance->actionList['showEvents']['data-toggle'] = 'modal';
|
||||
$config->instance->actionList['showEvents']['class'] = 'task-record-btn';
|
||||
|
||||
$config->instance->actionList['ajaxStart']['icon'] = 'play';
|
||||
$config->instance->actionList['ajaxStart']['className'] = 'ajax-submit';
|
||||
|
||||
@@ -726,6 +726,7 @@ class instance extends control
|
||||
$instance = $this->instance->getByID($id);
|
||||
|
||||
$this->view->instance = $instance;
|
||||
$this->view->title = $this->lang->instance->log->viewButton;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,22 +8,29 @@ window.initComponent = function (instanceID)
|
||||
{
|
||||
toggleLoading('#events-panel', false);
|
||||
$picker.render({items: items});
|
||||
if (typeof (items) !== 'undefined')
|
||||
{
|
||||
$picker.$.setValue(items.component);
|
||||
}
|
||||
if (typeof (items) !== 'undefined') $picker.$.setValue(items.component);
|
||||
if (items.length === 1) $('#component-events').addClass('hidden');
|
||||
showEvents(instanceID);
|
||||
});
|
||||
};
|
||||
|
||||
window.showEvents = function (instanceID)
|
||||
|
||||
window.showEvents = function (instanceID, noEventTip)
|
||||
{
|
||||
const instanceComponent = $('[name=component]').val();
|
||||
const target = $.createLink('instance', 'showEvents', 'id=' + instanceID + "&component=" + instanceComponent);
|
||||
toggleLoading('#events-panel', true);
|
||||
$.getJSON(target, function (data)
|
||||
$.getJSON(target, function (resp)
|
||||
{
|
||||
toggleLoading('#events-panel', false);
|
||||
$('#events-content').html(data.data.map(item => item.lastSeen + ' ' + item.type + ' ' + item.reason + ' ' + item.object + ' ' + item.message).join('\n'));
|
||||
$('#events-content').removeClass('dtable-empty-tip flex');
|
||||
if (resp.code !== 200 || resp.data.length === 0)
|
||||
{
|
||||
$('#events-content').html(noEventTip);
|
||||
$('#events-content').addClass('dtable-empty-tip flex');
|
||||
return;
|
||||
}
|
||||
$('#events-content').html(resp.data.map(item => item.lastSeen + ' ' + item.type + ' ' + item.reason + ' ' + item.object + ' ' + item.message).join('\n'));
|
||||
$('#events-content')[0].scrollTop = $('#events-content')[0].scrollHeight;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ window.initComponent = function (instanceID)
|
||||
});
|
||||
};
|
||||
|
||||
window.changeComponent = function (instanceID)
|
||||
window.changeComponent = function (instanceID, noLogsTip)
|
||||
{
|
||||
toggleLoading('#logs-panel', true);
|
||||
const $picker = $('[name=pod]').zui('picker');
|
||||
@@ -29,20 +29,50 @@ window.changeComponent = function (instanceID)
|
||||
$picker.$.setValue(items.pod);
|
||||
}
|
||||
toggleLoading('#logs-panel', false);
|
||||
showLogs(instanceID);
|
||||
showLogs(instanceID, noLogsTip);
|
||||
startAutoRefreshLogs(instanceID, noLogsTip);
|
||||
});
|
||||
};
|
||||
|
||||
window.showLogs = function (instanceID)
|
||||
window.showLogs = function (instanceID, noLogsTip)
|
||||
{
|
||||
const headerHeight = document.getElementById('logs-header').offsetHeight;
|
||||
document.getElementById('logs-content').style.height = `calc(100vh - ${headerHeight}px - 16px)`;
|
||||
const instanceComponent = $('[name=component]').val();
|
||||
const instancePod = $('[name=pod]').val();
|
||||
const previous = $('[name=previous]').val();
|
||||
const previous = $('[name=previous]:checked').val();
|
||||
const target = $.createLink('instance', 'showlogs', 'id=' + instanceID + "&component=" + instanceComponent + "&pod=" + instancePod + "&previous=" + previous);
|
||||
toggleLoading('#logs-panel', true);
|
||||
$.getJSON(target, function (data)
|
||||
$.getJSON(target, function (resp)
|
||||
{
|
||||
toggleLoading('#logs-panel', false);
|
||||
$('#logs-content').html(data.data.map(item => item.timestamp + ' ' + item.content).join('\n'));
|
||||
$('#logs-content').removeClass('dtable-empty-tip flex');
|
||||
if (resp.code !== 200 || resp.data.length === 0)
|
||||
{
|
||||
$('#logs-content').html(noLogsTip);
|
||||
$('#logs-content').addClass('dtable-empty-tip flex');
|
||||
return;
|
||||
}
|
||||
$('#logs-content').html(resp.data.map(item => item.timestamp + ' ' + item.content).join('\n'));
|
||||
$('#logs-content')[0].scrollTop = $('#logs-content')[0].scrollHeight;
|
||||
});
|
||||
};
|
||||
|
||||
let logsTimer = null;
|
||||
|
||||
window.startAutoRefreshLogs = function (instanceID, noLogsTip) {
|
||||
if(logsTimer) clearInterval(logsTimer);
|
||||
logsTimer = setInterval(function() {
|
||||
showLogs(instanceID, noLogsTip);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
window.toggleAutoRefresh = function(instanceID, noLogsTip) {
|
||||
const $toggleBtn = $('#autoRefreshBtn');
|
||||
if(logsTimer) {
|
||||
clearInterval(logsTimer);
|
||||
logsTimer = null;
|
||||
$toggleBtn.html('<i class="icon icon-play"></i>');
|
||||
} else {
|
||||
startAutoRefreshLogs(instanceID, noLogsTip);
|
||||
$toggleBtn.html('<i class="icon icon-pause"></i>');
|
||||
}
|
||||
}
|
||||
@@ -187,20 +187,24 @@ $lang->instance->log = new stdclass;
|
||||
$lang->instance->log->date = 'date';
|
||||
$lang->instance->log->message = 'Content';
|
||||
|
||||
$lang->instance->log->viewButton = 'Logs';
|
||||
$lang->instance->log->title = 'Watch Logs';
|
||||
$lang->instance->log->button = 'View Now';
|
||||
$lang->instance->log->viewButton = 'Logs';
|
||||
$lang->instance->log->title = 'Watch Logs';
|
||||
$lang->instance->log->button = 'View Now';
|
||||
$lang->instance->log->autoRefresh = 'Switch refresh status';
|
||||
$lang->instance->log->tips = 'The logs are refreshed automatically by default, and you can switch the button to switch';
|
||||
$lang->instance->log->noLog = 'No logs yet';
|
||||
|
||||
|
||||
$lang->instance->component = 'Component';
|
||||
$lang->instance->pod = 'Pod';
|
||||
$lang->instance->isPrevious = 'Is Previous container';
|
||||
$lang->instance->isPreviousList[0] = 'No';
|
||||
$lang->instance->isPreviousList[1] = 'Yes';
|
||||
$lang->instance->isPreviousList[0] = 'Current container';
|
||||
$lang->instance->isPreviousList[1] = 'Previous container';
|
||||
|
||||
$lang->instance->event = new stdClass;
|
||||
$lang->instance->event->viewButton = 'Events';
|
||||
$lang->instance->event->title = 'Watch Events';
|
||||
$lang->instance->event->button = 'View Now';
|
||||
$lang->instance->event->noEvents = 'No events yet';
|
||||
|
||||
$lang->instance->actionList = array();
|
||||
$lang->instance->actionList['install'] = '%s installed';
|
||||
|
||||
@@ -187,20 +187,24 @@ $lang->instance->log = new stdclass;
|
||||
$lang->instance->log->date = 'date';
|
||||
$lang->instance->log->message = 'Content';
|
||||
|
||||
$lang->instance->log->viewButton = 'Logs';
|
||||
$lang->instance->log->title = 'Watch Logs';
|
||||
$lang->instance->log->button = 'View Now';
|
||||
$lang->instance->log->viewButton = 'Logs';
|
||||
$lang->instance->log->title = 'Watch Logs';
|
||||
$lang->instance->log->button = 'View Now';
|
||||
$lang->instance->log->autoRefresh = 'Switch refresh status';
|
||||
$lang->instance->log->tips = 'The logs are refreshed automatically by default, and you can switch the button to switch';
|
||||
$lang->instance->log->noLog = 'No logs yet';
|
||||
|
||||
|
||||
$lang->instance->component = 'Component';
|
||||
$lang->instance->pod = 'Pod';
|
||||
$lang->instance->isPrevious = 'Is Previous container';
|
||||
$lang->instance->isPreviousList[0] = 'No';
|
||||
$lang->instance->isPreviousList[1] = 'Yes';
|
||||
$lang->instance->isPreviousList[0] = 'Current container';
|
||||
$lang->instance->isPreviousList[1] = 'Previous container';
|
||||
|
||||
$lang->instance->event = new stdClass;
|
||||
$lang->instance->event->viewButton = 'Events';
|
||||
$lang->instance->event->title = 'Watch Events';
|
||||
$lang->instance->event->button = 'View Now';
|
||||
$lang->instance->event->noEvents = 'No events yet';
|
||||
|
||||
$lang->instance->actionList = array();
|
||||
$lang->instance->actionList['install'] = '%s installed';
|
||||
|
||||
@@ -187,20 +187,24 @@ $lang->instance->log = new stdclass;
|
||||
$lang->instance->log->date = 'date';
|
||||
$lang->instance->log->message = 'Content';
|
||||
|
||||
$lang->instance->log->viewButton = 'Logs';
|
||||
$lang->instance->log->title = 'Watch Logs';
|
||||
$lang->instance->log->button = 'View Now';
|
||||
$lang->instance->log->viewButton = 'Logs';
|
||||
$lang->instance->log->title = 'Watch Logs';
|
||||
$lang->instance->log->button = 'View Now';
|
||||
$lang->instance->log->autoRefresh = 'Switch refresh status';
|
||||
$lang->instance->log->tips = 'The logs are refreshed automatically by default, and you can switch the button to switch';
|
||||
$lang->instance->log->noLog = 'No logs yet';
|
||||
|
||||
|
||||
$lang->instance->component = 'Component';
|
||||
$lang->instance->pod = 'Pod';
|
||||
$lang->instance->isPrevious = 'Is Previous container';
|
||||
$lang->instance->isPreviousList[0] = 'No';
|
||||
$lang->instance->isPreviousList[1] = 'Yes';
|
||||
$lang->instance->isPreviousList[0] = 'Current container';
|
||||
$lang->instance->isPreviousList[1] = 'Previous container';
|
||||
|
||||
$lang->instance->event = new stdClass;
|
||||
$lang->instance->event->viewButton = 'Events';
|
||||
$lang->instance->event->title = 'Watch Events';
|
||||
$lang->instance->event->button = 'View Now';
|
||||
$lang->instance->event->noEvents = 'No events yet';
|
||||
|
||||
$lang->instance->actionList = array();
|
||||
$lang->instance->actionList['install'] = '%s installed';
|
||||
|
||||
@@ -187,24 +187,28 @@ $lang->instance->management = '管理';
|
||||
$lang->instance->dbReady = '正常';
|
||||
$lang->instance->dbWaiting = '等待就绪';
|
||||
|
||||
$lang->instance->log = new stdclass;
|
||||
$lang->instance->log = new stdClass;
|
||||
$lang->instance->log->date = '日期';
|
||||
$lang->instance->log->message = '内容';
|
||||
|
||||
$lang->instance->log->viewButton = '日志';
|
||||
$lang->instance->log->title = '查看日志';
|
||||
$lang->instance->log->button = '立即查看';
|
||||
$lang->instance->log->viewButton = '日志';
|
||||
$lang->instance->log->title = '查看日志';
|
||||
$lang->instance->log->button = '立即查看';
|
||||
$lang->instance->log->autoRefresh = '切换刷新状态';
|
||||
$lang->instance->log->tips = '日志默认自动刷新,可点切换按钮切换';
|
||||
$lang->instance->log->noLog = '暂无日志';
|
||||
|
||||
|
||||
$lang->instance->component = '组件';
|
||||
$lang->instance->pod = 'Pod';
|
||||
$lang->instance->isPrevious = '是否上个退出容器';
|
||||
$lang->instance->isPreviousList[0] = '否';
|
||||
$lang->instance->isPreviousList[1] = '是';
|
||||
$lang->instance->isPreviousList[0] = '当前容器';
|
||||
$lang->instance->isPreviousList[1] = '上个容器';
|
||||
|
||||
$lang->instance->event = new stdClass;
|
||||
$lang->instance->event->viewButton = '事件';
|
||||
$lang->instance->event->title = '查看事件';
|
||||
$lang->instance->event->button = '立即查看';
|
||||
$lang->instance->event->noEvents = '暂无事件';
|
||||
|
||||
$lang->instance->actionList = array();
|
||||
$lang->instance->actionList['install'] = '安装了%s';
|
||||
|
||||
@@ -15,52 +15,40 @@ namespace zin;
|
||||
formPanel
|
||||
(
|
||||
set::title($lang->instance->event->title),
|
||||
set::actions(array(
|
||||
array(
|
||||
'text' => $lang->instance->event->button,
|
||||
'type' => 'primary',
|
||||
'onclick' => 'window.showEvents('.$instance->id.')',
|
||||
)
|
||||
)),
|
||||
set::actions(false),
|
||||
setID('events-panel'),
|
||||
setClass('w-full'),
|
||||
formRow
|
||||
inputGroup
|
||||
(
|
||||
formGroup
|
||||
input
|
||||
(
|
||||
setClass('hidden'),
|
||||
set::name('name'),
|
||||
set::labelWidth('160px'),
|
||||
set::required(true),
|
||||
set::label($lang->instance->name),
|
||||
set::value($instance->name),
|
||||
set::disabled(true),
|
||||
)
|
||||
),
|
||||
formRow
|
||||
(
|
||||
formGroup
|
||||
set::inline(true),
|
||||
),
|
||||
inputGroup
|
||||
(
|
||||
setID('component-events'),
|
||||
set::name('component'),
|
||||
set::labelWidth('160px'),
|
||||
set::control('picker'),
|
||||
set::required(true),
|
||||
set::label($lang->instance->component),
|
||||
on::inited()->call('initComponent', $instance->id),
|
||||
on::change()->call('showEvents', $instance->id)
|
||||
$lang->instance->component,
|
||||
picker
|
||||
(
|
||||
set::name('component'),
|
||||
set::control('picker'),
|
||||
set::required(true),
|
||||
set::label($lang->instance->component),
|
||||
set::inline(true),
|
||||
on::inited()->call('initComponent', $instance->id),
|
||||
on::change()->call('showEvents', $instance->id, $lang->instance->event->noEvents)
|
||||
)
|
||||
)
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('px-1 mt-2 w-full'),
|
||||
panel
|
||||
(
|
||||
setClass('py-2'),
|
||||
form
|
||||
(
|
||||
h::pre(setID('events-content'), setClass('bg-gray-800 text-white progress block h-96')),
|
||||
set::actions(false)
|
||||
)
|
||||
)
|
||||
setClass('w-full'),
|
||||
h::pre(setID('events-content'), setClass('bg-gray-800 text-white block h-96 scrollbar-thin')),
|
||||
set::actions(false)
|
||||
)
|
||||
);
|
||||
@@ -11,83 +11,85 @@ declare(strict_types=1);
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
set::zui(true);
|
||||
|
||||
formPanel
|
||||
div
|
||||
(
|
||||
set::title($lang->instance->log->title),
|
||||
set::actions(array(
|
||||
array(
|
||||
'text' => $lang->instance->log->button,
|
||||
'type' => 'primary',
|
||||
'onclick' => 'window.showLogs('.$instance->id.')',
|
||||
)
|
||||
)),
|
||||
setID('logs-panel'),
|
||||
setClass('w-full'),
|
||||
formRow
|
||||
(
|
||||
formGroup
|
||||
(
|
||||
set::name('name'),
|
||||
set::labelWidth('160px'),
|
||||
set::required(true),
|
||||
set::label($lang->instance->name),
|
||||
set::value($instance->name),
|
||||
set::disabled(true)
|
||||
)
|
||||
),
|
||||
formRow
|
||||
(
|
||||
formGroup
|
||||
(
|
||||
setID('component-logs'),
|
||||
set::name('component'),
|
||||
set::labelWidth('160px'),
|
||||
set::control('picker'),
|
||||
set::required(true),
|
||||
set::label($lang->instance->component),
|
||||
on::change()->call('changeComponent', $instance->id)
|
||||
)
|
||||
),
|
||||
formRow
|
||||
(
|
||||
formGroup
|
||||
(
|
||||
setID('pod-logs'),
|
||||
set::name('pod'),
|
||||
set::labelWidth('160px'),
|
||||
set::control('picker'),
|
||||
set::required(true),
|
||||
set::label($lang->instance->pod),
|
||||
set::items(array())
|
||||
)
|
||||
),
|
||||
setClass('px-1 mt-2 w-full'),
|
||||
formRow
|
||||
(
|
||||
setID('logs-header'),
|
||||
setClass('flex px-1 top-0 bg-white'),
|
||||
formGroup(
|
||||
inputGroup
|
||||
(
|
||||
h::button
|
||||
(
|
||||
setClass('btn primary'),
|
||||
$lang->instance->log->autoRefresh,
|
||||
span(
|
||||
setID('autoRefreshBtn'),
|
||||
icon(setClass('icon icon-pause'))
|
||||
),
|
||||
on::click()->call('toggleAutoRefresh', $instance->id, $lang->instance->log->noLog)
|
||||
),
|
||||
$lang->instance->name,
|
||||
input
|
||||
(
|
||||
set::class('input-group-addon'),
|
||||
set::name('name'),
|
||||
set::required(true),
|
||||
set::value($instance->name),
|
||||
set::disabled(true)
|
||||
),
|
||||
$lang->instance->component,
|
||||
picker
|
||||
(
|
||||
setClass('input-group-addon w-48'),
|
||||
setID('component-logs'),
|
||||
set::name('component'),
|
||||
set::control('picker'),
|
||||
set::required(true),
|
||||
on::change()->call('changeComponent', $instance->id, $lang->instance->log->noLog)
|
||||
),
|
||||
$lang->instance->pod,
|
||||
picker
|
||||
(
|
||||
setClass('input-group-addon w-72'),
|
||||
setID('pod-logs'),
|
||||
set::name('pod'),
|
||||
set::required(true),
|
||||
set::items(array()),
|
||||
set::inline(true),
|
||||
on::inited()->call('initComponent', $instance->id, $lang->instance->log->noLog)
|
||||
)
|
||||
)
|
||||
),
|
||||
formGroup
|
||||
(
|
||||
setClass('flex mx-2'),
|
||||
setID('is-previous'),
|
||||
set::name('previous'),
|
||||
set::labelWidth('160px'),
|
||||
set::control('picker'),
|
||||
set::label($lang->instance->isPrevious),
|
||||
set::control('radioListInline'),
|
||||
set::items($lang->instance->isPreviousList),
|
||||
set::value(0),
|
||||
on::change()->call('showLogs', $instance->id),
|
||||
on::inited()->call('initComponent', $instance->id)
|
||||
set::inline(true),
|
||||
on::change()->call('showLogs', $instance->id, $lang->instance->log->noLog)
|
||||
),
|
||||
formGroup(
|
||||
setClass('flex mx-2 text-sm text-gray-500'),
|
||||
set::label( setClass('text-danger'), $lang->instance->log->tips)
|
||||
)
|
||||
),
|
||||
div
|
||||
(
|
||||
setClass('px-1 mt-2 w-full'),
|
||||
panel
|
||||
(
|
||||
setClass('py-2'),
|
||||
form
|
||||
(
|
||||
h::pre(setID('logs-content'), setClass('bg-gray-800 text-white progress block h-96')),
|
||||
set::actions(false)
|
||||
)
|
||||
)
|
||||
setClass('px-1 mt-2 w-full h-full'),
|
||||
h::pre(
|
||||
setID('logs-content'),
|
||||
setClass('bg-gray-800 text-white block h-screen scrollbar-thin')
|
||||
),
|
||||
set::actions(false)
|
||||
)
|
||||
);
|
||||
);
|
||||
render('pagebase');
|
||||
@@ -1504,7 +1504,8 @@ class kanbanModel extends model
|
||||
if(in_array($laneType, array('epic', 'requirement')) && strpos($project->storyType, $laneType) === false) continue;
|
||||
list($laneData, $columnData, $cardsData) = $this->buildExecutionGroup($lane, $columns, $objectGroup, $searchValue, $menus);
|
||||
|
||||
if($lane->type == 'risk') $cardsData = $this->appendRiskField($cardsData, $objectGroup['risk']);
|
||||
if($lane->type == 'risk' && in_array($this->config->edition, array('max', 'ipd'))) $cardsData = $this->appendRiskField($cardsData, $objectGroup['risk']);
|
||||
|
||||
$kanbanID = 'group' . $lane->id;
|
||||
|
||||
$kanbanGroup[$laneType]['id'] = $lane->id;
|
||||
@@ -2885,7 +2886,8 @@ class kanbanModel extends model
|
||||
if($laneType == 'story') $cardPairs = $this->kanbanTao->refreshStoryCards($cardPairs, $executionID, $otherCardList);
|
||||
if($laneType == 'bug') $cardPairs = $this->kanbanTao->refreshBugCards($cardPairs, $executionID, $otherCardList);
|
||||
if($laneType == 'task') $cardPairs = $this->kanbanTao->refreshTaskCards($cardPairs, $executionID, $otherCardList);
|
||||
if($laneType == 'risk') $cardPairs = $this->refreshRiskCards($cardPairs, $executionID, $otherCardList);
|
||||
|
||||
if($laneType == 'risk' && in_array($this->config->edition, array('max', 'ipd'))) $cardPairs = $this->refreshRiskCards($cardPairs, $executionID, $otherCardList);
|
||||
|
||||
$colPairs = $this->dao->select('t2.type, t2.id')->from(TABLE_KANBANCELL)->alias('t1')
|
||||
->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.`column` = t2.id')
|
||||
|
||||
+16
-13
@@ -517,20 +517,23 @@ class kanbanTao extends kanbanModel
|
||||
$strLength = strlen($realname);
|
||||
|
||||
$displayText = '';
|
||||
if($strLength === $mbLength)
|
||||
if($realname)
|
||||
{
|
||||
/* Pure alphabet or numbers 纯英文情况 */
|
||||
$displayText = strtoupper($realname[0]);
|
||||
}
|
||||
else if($strLength % $mbLength == 0 && $strLength % 3 == 0)
|
||||
{
|
||||
/* Pure chinese characters 纯中文的情况 */
|
||||
$displayText = $mbLength <= $maxTextLen ? $realname : mb_substr($realname, $mbLength - $maxTextLen, $mbLength, 'utf-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mix of Chinese and English 中英文混合的情况 */
|
||||
$displayText = $mbLength <= $maxTextLen ? $realname : mb_substr($realname, 0, $maxTextLen, 'utf-8');
|
||||
if(isset($realname[0]) && $strLength === $mbLength)
|
||||
{
|
||||
/* Pure alphabet or numbers 纯英文情况 */
|
||||
$displayText = strtoupper($realname[0]);
|
||||
}
|
||||
else if($strLength % $mbLength == 0 && $strLength % 3 == 0)
|
||||
{
|
||||
/* Pure chinese characters 纯中文的情况 */
|
||||
$displayText = $mbLength <= $maxTextLen ? $realname : mb_substr($realname, $mbLength - $maxTextLen, $mbLength, 'utf-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mix of Chinese and English 中英文混合的情况 */
|
||||
$displayText = $mbLength <= $maxTextLen ? $realname : mb_substr($realname, 0, $maxTextLen, 'utf-8');
|
||||
}
|
||||
}
|
||||
|
||||
$userAvatar = zget($avatarPairs, $account, '');
|
||||
|
||||
@@ -934,7 +934,7 @@ class my extends control
|
||||
$this->view->mode = 'audit';
|
||||
$this->view->flows = $flows;
|
||||
$this->view->products = $this->loadModel('product')->getPairs('', 0, '', 'all');;
|
||||
$this->view->projects = $this->loadModel('project')->getPairsByProgram();;
|
||||
$this->view->projects = $this->loadModel('project')->getPairs();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
|
||||
@@ -1422,6 +1422,9 @@ class myModel extends model
|
||||
$review->status = $objectType == 'attend' ? $object->reviewStatus : (isset($object->status) && !isset($flows[$objectType]) ? $object->status : 'done');
|
||||
if(strpos($review->result, ',') !== false) list($review->result) = explode(',', $review->result);
|
||||
|
||||
$review->product = isset($object->product) ? $object->product : 0;
|
||||
$review->project = isset($object->project) ? $object->project : 0;
|
||||
|
||||
if($objectType == 'story') $review->storyType = $object->type;
|
||||
if($review->type == 'review') $review->type = 'projectreview';
|
||||
if($review->type == 'case') $review->type = 'testcase';
|
||||
|
||||
@@ -95,11 +95,16 @@ class pivot extends control
|
||||
|
||||
$this->pivotZen->show($groupID, $pivotID, '', $version);
|
||||
|
||||
$this->loadModel('mark')->setMark(array($pivotID), 'pivot', $version, 'version');
|
||||
$marks = $this->loadModel('mark')->getNeededMarks(array($pivotID), 'pivot', 'all', 'version');
|
||||
$marks = array();
|
||||
if($pivot->builtin == 1)
|
||||
{
|
||||
$this->loadModel('mark')->setMark(array($pivotID), 'pivot', $version, 'version');
|
||||
$marks = $this->loadModel('mark')->getNeededMarks(array($pivotID), 'pivot', 'all', 'version');
|
||||
}
|
||||
|
||||
$this->view->versionSpecs = $versionSpecs;
|
||||
$this->view->markedVersions = array_column($marks, 'version');
|
||||
$this->view->builtin = $pivot->builtin;
|
||||
$this->view->version = $version;
|
||||
$this->view->groupID = $groupID;
|
||||
$this->view->pivotID = $groupID;
|
||||
|
||||
@@ -1863,7 +1863,7 @@ class pivotModel extends model
|
||||
$data->array = array();
|
||||
$data->drills = array();
|
||||
|
||||
if(!isset($settings['columns'])) return array(data, array());
|
||||
if(!isset($settings['columns'])) return array($data, array());
|
||||
|
||||
$filters = $this->processQueryFilterDefaults($filters);
|
||||
/* Replace the variable with the default value. */
|
||||
@@ -2947,14 +2947,8 @@ class pivotModel extends model
|
||||
|
||||
foreach($pivots as $index => $pivot)
|
||||
{
|
||||
if(isset($pivotMaxVersion[$pivot->id]) && $pivotMaxVersion[$pivot->id] != $pivot->version)
|
||||
{
|
||||
$pivots[$index]->versionChange = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$pivots[$index]->versionChange = false;
|
||||
}
|
||||
$maxVersion = zget($pivotMaxVersion, $pivot->id, '');
|
||||
$pivots[$index]->versionChange = $maxVersion != $pivot->version && $pivot->builtin == 1;
|
||||
}
|
||||
|
||||
return $isObject ? current($pivots) : $pivots;
|
||||
|
||||
@@ -18,22 +18,30 @@ include_once 'show.html.php';
|
||||
$versionsTableBody = array();
|
||||
foreach($versionSpecs as $versionSpec)
|
||||
{
|
||||
$isMarked = in_array($versionSpec->version, $markedVersions);
|
||||
$isBuiltIn = $builtin == 1;
|
||||
$isFirstVersion = $versionSpec->version == 1;
|
||||
$isMainVersion = filter_var($versionSpec->version, FILTER_VALIDATE_INT) !== false;
|
||||
$versionsTableBody[] = h::tr
|
||||
(
|
||||
$version == $versionSpec->version ? setClass('bg-secondary-50') : null,
|
||||
on::click("previewVersion"),
|
||||
h::td
|
||||
(
|
||||
on::click("previewVersion"),
|
||||
setData(array('pivot' => $pivot->id, 'version' => $versionSpec->version, 'group' => $groupID)),
|
||||
'#' . $versionSpec->version,
|
||||
!in_array($versionSpec->version, $markedVersions) ? span
|
||||
span
|
||||
(
|
||||
setData(array('pivot' => $pivot->id, 'version' => $versionSpec->version, 'group' => $groupID)),
|
||||
setClass("label ghost size-sm bg-secondary-50 text-secondary-500 rounded-full"),
|
||||
setClass("label ghost size-sm bg-secondary-50 text-secondary-500 rounded-full", array('hidden' => $isMarked || $isFirstVersion || !$isBuiltIn || ($isBuiltIn && !$isMainVersion))),
|
||||
$lang->pivot->newVersion
|
||||
) : null
|
||||
)
|
||||
),
|
||||
h::td(empty($versionSpec->desc) ? $lang->pivot->noDesc : $versionSpec->desc)
|
||||
h::td
|
||||
(
|
||||
setData(array('pivot' => $pivot->id, 'version' => $versionSpec->version, 'group' => $groupID)),
|
||||
empty($versionSpec->desc) ? $lang->pivot->noDesc : $versionSpec->desc
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,12 +125,17 @@ class pivotZen extends pivot
|
||||
*/
|
||||
protected function setNewMark(object $pivot, object $firstAction, array $builtins): void
|
||||
{
|
||||
// 版本没有改变,此时讨论是不是新透视表
|
||||
/* 如果不是内置透视表,则不需要展示“新”标签。*/
|
||||
/* If the pivot is not built-in, no need to display the "new" tag. */
|
||||
if($pivot->builtin == 0) return;
|
||||
/* 版本没有改变,此时讨论是不是新透视表。*/
|
||||
/* The version has not changed, so it is judged whether it is a new pivot. */
|
||||
if(!$pivot->versionChange)
|
||||
{
|
||||
if(!isset($builtins[$pivot->id])) return;
|
||||
if(!$pivot->mark && $pivot->createdDate < $firstAction->date) $pivot->mark = true;
|
||||
if(!$pivot->mark) $pivot->name = array('text' => $pivot->name, 'html' => $pivot->name . ' <span class="label ghost size-sm bg-secondary-50 text-secondary-500 rounded-full">' . $this->lang->pivot->new . '</span>');
|
||||
$isMainVersion = filter_var($pivot->version, FILTER_VALIDATE_INT) !== false;
|
||||
if(!$pivot->mark && $isMainVersion) $pivot->name = array('text' => $pivot->name, 'html' => $pivot->name . ' <span class="label ghost size-sm bg-secondary-50 text-secondary-500 rounded-full">' . $this->lang->pivot->new . '</span>');
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -202,7 +207,7 @@ class pivotZen extends pivot
|
||||
$driver = $pivot->driver;
|
||||
|
||||
$this->pivot->isVersionChange($pivot);
|
||||
if($mark)
|
||||
if($mark && $pivot->builtin == 1)
|
||||
{
|
||||
$markVersion = $pivot->versionChange ? $this->pivot->getMaxVersion($pivot->id) : $pivot->version;
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ if($app->rawModule == 'programplan')
|
||||
if($project->stageBy == 'product')
|
||||
{
|
||||
$viewName = $productID != 0 ? zget($productList, $productID) : $lang->product->allProduct;
|
||||
$items = array(array('text' => $lang->product->allProduct, 'url' => $this->createLink('programplan', 'browse', "projectID=$projectID&productID=all&type=gantt")));
|
||||
$items = array(array('text' => $lang->product->allProduct, 'url' => $this->createLink('programplan', 'browse', "projectID=$projectID&productID=0&type=gantt")));
|
||||
foreach($productList as $key => $productName) $items[] = array('text' => $productName, 'url' => $this->createLink('programplan', 'browse', "projectID=$projectID&productID=$key&type=gantt"));
|
||||
$productDropdown = dropdown
|
||||
(
|
||||
|
||||
@@ -292,7 +292,7 @@ $config->project->linkMap->reviewissue = array();
|
||||
$config->project->linkMap->reviewissue[''] = array('reviewissue', 'issue', 'projectID=%s', '');
|
||||
|
||||
$config->project->linkMap->cm = array();
|
||||
$config->project->linkMap->cm['report'] = array('cm', 'report', 'projectID=%s', '');
|
||||
$config->project->linkMap->cm['report'] = array('project', 'index', 'projectID=%s', '');
|
||||
|
||||
$config->project->linkMap->weekly = array();
|
||||
$config->project->linkMap->weekly['index'] = array('weekly', 'index', 'projectID=%s', '');
|
||||
|
||||
@@ -122,6 +122,7 @@ class project extends control
|
||||
$this->view->method = $method;
|
||||
$this->view->programs = $programs;
|
||||
$this->view->extra = $extra;
|
||||
$this->view->useLink = $useLink;
|
||||
|
||||
$this->view->projects = $orderedProjects;
|
||||
$this->view->involvedProjects = $involvedProjects;
|
||||
|
||||
@@ -976,6 +976,7 @@ class projectModel extends model
|
||||
$this->config->build->search['actionURL'] = helper::createLink($this->app->rawModule, $this->app->rawMethod, "projectID=$projectID&type=bysearch&queryID=myQueryID");
|
||||
$this->config->build->search['queryID'] = $queryID;
|
||||
$this->config->build->search['params']['product']['values'] = $products;
|
||||
$this->config->build->search['params']['system']['values'] = $this->loadModel('system')->getPairs((int)$productID, '0');
|
||||
|
||||
$this->loadModel('search')->setSearchParams($this->config->build->search);
|
||||
return true;
|
||||
|
||||
@@ -110,10 +110,17 @@ else
|
||||
$item['text'] = $project->name;
|
||||
$item['icon'] = $project->model == 'scrum' ? 'sprint' : $project->model;
|
||||
$item['keys'] = zget(common::convert2Pinyin(array($project->name)), $project->name, '');
|
||||
$item['url'] = sprintf($link, $project->id);
|
||||
$item['involved'] = isset($involvedProjects[$project->id]);
|
||||
|
||||
if((empty($project->multiple) || $project->type == 'kanban' || $project->model == 'kanban') && strpos($link, 'ajaxSwitchBelong') === false) $item['url'] = helper::createLink('project', 'index', "projectID={$project->id}");
|
||||
if($useLink == 1)
|
||||
{
|
||||
$item['url'] = sprintf($link, $project->id);
|
||||
if((empty($project->multiple) || $project->type == 'kanban' || $project->model == 'kanban') && strpos($link, 'ajaxSwitchBelong') === false) $item['url'] = helper::createLink('project', 'index', "projectID={$project->id}");
|
||||
}
|
||||
else
|
||||
{
|
||||
$item['url'] = '#';
|
||||
}
|
||||
|
||||
if(empty($activeGroup) && $projectID == $project->id) $activeGroup = $group;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user