Merge branch '15.0.beta3' of https://gitlab.zcorp.cc/easycorp/zentaopms into 15.0.beta3

This commit is contained in:
Guanxiying
2021-04-27 19:15:16 +08:00
98 changed files with 713 additions and 417 deletions
+3 -2
View File
@@ -138,8 +138,9 @@ $config->features->checkClient = true;
/* 文件上传设置。 Upload settings. */
$config->file = new stdclass();
$config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,aspx,ashx,asa,cer,cdx,aspl,shtm,shtml,html,htm';
$config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql';
$config->file->dangers = 'php,php3,php4,phtml,php5,jsp,py,rb,asp,aspx,ashx,asa,cer,cdx,aspl,shtm,shtml,html,htm';
$config->file->allowed = 'txt,doc,docx,dot,wps,wri,pdf,ppt,pptx,xls,xlsx,ett,xlt,xlsm,csv,jpg,jpeg,png,psd,gif,ico,bmp,swf,avi,rmvb,rm,mp3,mp4,3gp,flv,mov,movie,rar,zip,bz,bz2,tar,gz,mpp,rp,pdm,vsdx,vsd,sql';
$config->file->storageType = 'fs'; // fs or s3
/* Upload settings. */
$config->allowedTags = '<p><span><h1><h2><h3><h4><h5><em><u><strong><br><ol><ul><li><img><a><b><font><hr><pre><div><table><td><th><tr><tbody><embed><style>';
+1 -1
View File
@@ -34,7 +34,7 @@ ALTER TABLE `zt_doclib` CHANGE `project` `execution` mediumint(8) unsigned NOT N
ALTER TABLE `zt_task` CHANGE `project` `execution` mediumint(8) unsigned NOT NULL;
ALTER TABLE `zt_testreport` CHANGE `project` `execution` mediumint(8) unsigned NOT NULL;
ALTER TABLE `zt_testtask` CHANGE `project` `execution` mediumint(8) unsigned NOT NULL;
ALTER TABLE `zt_webhook` CHANGE `projects` `executions` mediumint(8) unsigned NOT NULL;
ALTER TABLE `zt_webhook` CHANGE `projects` `executions` text NOT NULL;
ALTER TABLE `zt_action` ADD `project` mediumint(8) unsigned NOT NULL AFTER `product`;
ALTER TABLE `zt_task` ADD `project` mediumint(8) unsigned NOT NULL AFTER `id`;
+4
View File
@@ -0,0 +1,4 @@
ALTER TABLE `zt_webhook` CHANGE `projects` `executions` text NOT NULL;
ALTER TABLE `zt_webhook` CHANGE `executions` `executions` text NOT NULL;
ALTER TABLE `zt_repo` ADD `extra` char(30) COLLATE 'utf8_general_ci' NOT NULL AFTER `desc`;
+2 -1
View File
@@ -751,6 +751,7 @@ CREATE TABLE IF NOT EXISTS `zt_repo` (
`synced` tinyint(1) NOT NULL DEFAULT '0',
`lastSync` datetime NOT NULL,
`desc` text NOT NULL,
`extra` char(30) NOT NULL,
`deleted` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@@ -1228,7 +1229,7 @@ CREATE TABLE IF NOT EXISTS `zt_webhook` (
`contentType` varchar(30) NOT NULL DEFAULT 'application/json',
`sendType` enum('sync','async') NOT NULL DEFAULT 'sync',
`products` text NOT NULL,
`projects` text NOT NULL,
`executions` text NOT NULL,
`params` varchar(100) NOT NULL,
`actions` text NOT NULL,
`desc` text NOT NULL,
-24
View File
@@ -228,30 +228,6 @@ class helper extends baseHelper
$version
);
}
/**
* Save file to storage: fs(www/data/upload) or s3(s3, oss, minio)
*
* @param string $tmpFile
* @param string $fileName
* @access public
* @return bool
*/
public static function saveFile($tmpFile, $filePath)
{
global $config;
if(!isset($config->storageType) or $config->storageType == 'fs')
{
return move_uploaded_file($tmpFile, $filePath);
}
else if(isset($config->storageType) and $config->storageType == 's3')
{
return move_uploaded_file($tmpFile, $filePath); // TODO
}
return false;
}
}
/**
+16 -6
View File
@@ -885,16 +885,18 @@ class baseJS
* 显示一个确认框,点击确定跳转到$okURL,点击取消跳转到$cancelURL。
* show a confirm box, press ok go to okURL, else go to cancleURL.
*
* @param string $message 显示的内容。 the text to be showed.
* @param string $okURL 点击确定后跳转的地址。 the url to go to when press 'ok'.
* @param string $cancleURL 点击取消后跳转的地址。 the url to go to when press 'cancle'.
* @param string $okTarget 点击确定后跳转的target。 the target to go to when press 'ok'.
* @param string $cancleTarget 点击取消后跳转的target。 the target to go to when press 'cancle'.
* @param string $message 显示的内容。 the text to be showed.
* @param string $okURL 点击确定后跳转的地址。 the url to go to when press 'ok'.
* @param string $cancleURL 点击取消后跳转的地址。 the url to go to when press 'cancle'.
* @param string $okTarget 点击确定后跳转的target。 the target to go to when press 'ok'.
* @param string $cancleTarget 点击取消后跳转的target。 the target to go to when press 'cancle'.
* @param string $okOpenApp 点击确定后跳转的应用。 the app to go to when press 'ok'.
* @param string $cancleOpenApp 点击取消后跳转的应用。 the app to go to when press 'cancle'.
* @static
* @access public
* @return string
*/
static public function confirm($message = '', $okURL = '', $cancleURL = '', $okTarget = "self", $cancleTarget = "self")
static public function confirm($message = '', $okURL = '', $cancleURL = '', $okTarget = "self", $cancleTarget = "self", $okOpenApp = '', $cancleOpenApp = '')
{
global $app;
if($app->viewType == 'json')
@@ -921,6 +923,10 @@ class baseJS
{
$confirmAction = "history.back(-1);";
}
elseif(strpos($okTarget, '$.apps.open') !== false)
{
$confirmAction = "$okTarget('$okURL', '$okOpenApp');";
}
elseif(!empty($okURL))
{
$confirmAction = "$okTarget.location = '$okURL';";
@@ -931,6 +937,10 @@ class baseJS
{
$cancleAction = "history.back(-1);";
}
elseif(strpos($cancleTarget, '$.apps.open') !== false)
{
$cancleAction = "$cancleTarget('$cancleURL', '$cancleOpenApp');";
}
elseif(!empty($cancleURL))
{
$cancleAction = "$cancleTarget.location = '$cancleURL';";
+210 -209
View File
@@ -5,13 +5,13 @@ class gitlab
public $projectID;
/**
* Construct
*
* Construct
*
* @param string $client gitlab api url.
* @param string $root id of gitlab project.
* @param string $username null
* @param string $password token of gitlab api.
* @param string $encoding
* @param string $encoding
* @access public
* @return void
*/
@@ -25,9 +25,9 @@ class gitlab
/**
* List files.
*
* @param string $path
* @param string $revision
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
@@ -41,124 +41,124 @@ class gitlab
$param->ref = $revision;
$param->recursive = 0;
$list = $this->fetch($api, $param);
$list = $this->fetch($api, $param);
if(empty($list)) return array();
$infos = array();
foreach($list as $file)
{
$info = new stdClass();
if($file->type == 'blob')
{
$info = new stdClass();
if($file->type == 'blob')
{
$path = $file->path;
$file = $this->files($file->path);
$info->name = $file->file_name;
$info->kind = 'file';
$info->account = $file->committer;
$info->date = $file->date;
$info->size = $file->size;
$info->comment = $file->comment;
$info->revision = $file->revision;
}
else
{
$commits = $this->getCommitsByPath($file->path);
if(empty($commits)) continue;
$commit = $commits[0];
$file = $this->files($file->path);
$info->name = $file->path;
$info->kind = 'dir';
$info->revision = $commit->id;
$info->account = $commit->committer_name;
$info->date = date('Y-m-d H:i:s', strtotime($commit->committed_date));
$info->size = 0;
$info->comment = $commit->message;
}
$info->name = $file->file_name;
$info->kind = 'file';
$info->account = $file->committer;
$info->date = $file->date;
$info->size = $file->size;
$info->comment = $file->comment;
$info->revision = $file->revision;
}
else
{
$commits = $this->getCommitsByPath($file->path);
if(empty($commits)) continue;
$commit = $commits[0];
$infos[] = $info;
unset($info);
}
$info->name = $file->path;
$info->kind = 'dir';
$info->revision = $commit->id;
$info->account = $commit->committer_name;
$info->date = date('Y-m-d H:i:s', strtotime($commit->committed_date));
$info->size = 0;
$info->comment = $commit->message;
}
/* Sort by kind */
foreach($infos as $key => $info) $kinds[$key] = $info->kind;
if($infos) array_multisort($kinds, SORT_ASC, $infos);
return $infos;
}
$infos[] = $info;
unset($info);
}
/**
* Get files info.
*
* @param string $path
* @param string $ref
* @access public
* @return array
*/
public function files($path, $ref = 'master')
{
$path = urlencode($path);
$api = "files/$path";
$param = new stdclass();
$param->ref = $ref;
$file = $this->fetch($api, $param);
/* Sort by kind */
foreach($infos as $key => $info) $kinds[$key] = $info->kind;
if($infos) array_multisort($kinds, SORT_ASC, $infos);
return $infos;
}
$commits = $this->getCommitsByPath($path);
$file->revision = $file->commit_id;
$file->size = $this->formatBytes($file->size);
/**
* Get files info.
*
* @param string $path
* @param string $ref
* @access public
* @return array
*/
public function files($path, $ref = 'master')
{
$path = urlencode($path);
$api = "files/$path";
$param = new stdclass();
$param->ref = $ref;
$file = $this->fetch($api, $param);
if(!empty($commits))
{
$commit = $commits[0];
$file->committer = $commit->committer_name;
$file->comment = $commit->message;
$file->date = date('Y-m-d H:i:s', strtotime($commit->committed_date));
}
$commits = $this->getCommitsByPath($path);
$file->revision = $file->commit_id;
$file->size = $this->formatBytes($file->size);
return $file;
}
if(!empty($commits))
{
$commit = $commits[0];
$file->committer = $commit->committer_name;
$file->comment = $commit->message;
$file->date = date('Y-m-d H:i:s', strtotime($commit->committed_date));
}
/**
* Get tags
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function tags($path, $revision = 'HEAD')
{
$api = "tags";
return $file;
}
/**
* Get tags
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function tags($path, $revision = 'HEAD')
{
$api = "tags";
$list = $this->fetch($api);
$tags = array();
foreach($list as $tag) $tags[] = $tag->name;
return $tags;
}
return $tags;
}
/**
* Get branch
*
* @access public
* @return array
*/
public function branch()
{
$api = "branches";
$list = $this->fetch($api);
/**
* Get branch
*
* @access public
* @return array
*/
public function branch()
{
$api = "branches";
$list = $this->fetch($api);
$branches = array();
foreach($list as $branch) $branches[$branch->name] = $branch->name;
asort($branches);
$branches = array();
foreach($list as $branch) $branches[$branch->name] = $branch->name;
asort($branches);
return $branches;
}
return $branches;
}
/**
* Get last log.
*
* @param string $path
* @param int $count
/**
* Get last log.
*
* @param string $path
* @param int $count
* @access public
* @return array
*/
@@ -169,11 +169,11 @@ class gitlab
/**
* Get logs.
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
* @param int $count
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
* @param int $count
* @access public
* @return array
*/
@@ -193,9 +193,9 @@ class gitlab
/**
* Blame file
*
* @param string $path
* @param string $revision
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
@@ -204,47 +204,47 @@ class gitlab
if(!scm::checkRevision($revision)) return array();
$path = ltrim($path, DIRECTORY_SEPARATOR);
$path = urlencode($path);
$api = "files/$path/blame";
$param = new stdclass;
$param->ref = $this->branch;
$path = urlencode($path);
$api = "files/$path/blame";
$param = new stdclass;
$param->ref = $this->branch;
$results = $this->fetch($api, $param);
$blames = array();
$revLine = 0;
$revision = '';
$lineNumber = 1;
foreach($results as $blame)
{
$line = array();
$line['revision'] = $blame->commit->id;
$line['committer'] = $blame->commit->committer_name;
$line['time'] = $blame->commit->committer_name;
$line['line'] = $lineNumber;
$line['lines'] = count($blame->lines);
$line['content'] = array_shift($blame->lines);
$lineNumber = 1;
foreach($results as $blame)
{
$line = array();
$line['revision'] = $blame->commit->id;
$line['committer'] = $blame->commit->committer_name;
$line['time'] = $blame->commit->committer_name;
$line['line'] = $lineNumber;
$line['lines'] = count($blame->lines);
$line['content'] = array_shift($blame->lines);
$blames[] = $line;
$blames[] = $line;
$lineNumber ++;
$lineNumber ++;
foreach($blame->lines as $line)
{
$blames[] = array('line' => $lineNumber, 'content' => $line);
$lineNumber ++;
}
}
foreach($blame->lines as $line)
{
$blames[] = array('line' => $lineNumber, 'content' => $line);
$lineNumber ++;
}
}
return $blames;
}
/**
* Diff file.
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
* @access public
* @return array
*/
@@ -252,7 +252,7 @@ class gitlab
{
if(!scm::checkRevision($fromRevision)) return array();
if(!scm::checkRevision($toRevision)) return array();
$api = "compare";
$params = array('from' => $fromRevision, 'to' => $toRevision, 'straight' => 1);
$results = $this->fetch($api, $params);
@@ -277,9 +277,9 @@ class gitlab
/**
* Cat file.
*
* @param string $entry
* @param string $revision
*
* @param string $entry
* @param string $revision
* @access public
* @return string
*/
@@ -292,9 +292,9 @@ class gitlab
/**
* Get info.
*
* @param string $entry
* @param string $revision
*
* @param string $entry
* @param string $revision
* @access public
* @return object
*/
@@ -303,9 +303,10 @@ class gitlab
if(!scm::checkRevision($revision)) return false;
$info = new stdclass();
$info->kind = 'dir';
$info->path = $entry;
$info->root = '';
$info->kind = 'dir';
$info->path = $entry;
$info->revision = $revision;
$info->root = '';
if($entry)
{
@@ -327,15 +328,14 @@ class gitlab
/**
* Exec git cmd.
*
* @param string $cmd
*
* @param string $cmd
* @access public
* @todo Exec commads by gitlab api.
* @return array
*/
public function exec($cmd)
{
chdir($this->root);
return execCmd(escapeCmd("$this->client $cmd"), 'array');
}
@@ -436,9 +436,9 @@ class gitlab
/**
* Get commit count.
*
* @param int $commits
* @param string $lastVersion
*
* @param int $commits
* @param string $lastVersion
* @access public
* @return int
*/
@@ -453,7 +453,7 @@ class gitlab
/**
* Get first revision.
*
*
* @access public
* @return string
*/
@@ -465,8 +465,8 @@ class gitlab
}
/**
* Get latest revision
*
* Get latest revision
*
* @access public
* @return string
*/
@@ -480,10 +480,10 @@ class gitlab
/**
* Get commits.
*
* @param string $version
* @param int $count
* @param string $branch
*
* @param string $version
* @param int $count
* @param string $branch
* @access public
* @return array
*/
@@ -491,18 +491,19 @@ class gitlab
{
if(!scm::checkRevision($version)) return array();
$api = "commits";
$count = 500;
$params = array();
$params['ref_name'] = $branch;
$params['per_page'] = $count;
$params['all'] = 1;
if($version)
{
$lastCommit = $this->getSingleCommit($version);
$params['until'] = $lastCommit->committed_date;
}
if($version)
{
$lastCommit = $this->getSingleCommit($version);
if(empty($lastCommit)) return array();
$params['until'] = $lastCommit->committed_date;
}
$list = $this->fetch($api, $params);
@@ -514,42 +515,42 @@ class gitlab
$log->revision = $commit->id;
$log->comment = $commit->message;
$log->time = date('Y-m-d H:i:s', strtotime($commit->created_at));
$commits[$commit->id] = $log;
$files[$commit->id] = $this->getFilesByCommit($log->revision);
$files[$commit->id] = $this->getFilesByCommit($log->revision);
}
return array('commits' => $commits, 'files' => $files);
}
/**
* getCommit
*
* @param int $sha
* @access public
* @return void
*/
public function getSingleCommit($sha)
{
/**
* getCommit
*
* @param int $sha
* @access public
* @return void
*/
public function getSingleCommit($sha)
{
if(!scm::checkRevision($sha)) return null;
$api = "commits/$sha";
return $this->fetch($api);
}
return $this->fetch($api);
}
/**
* Get commits by path.
*
* @param string $path
* @access public
* @return array
*/
public function getCommitsByPath($path, $fromRevision = '', $toRevision = '')
{
/**
* Get commits by path.
*
* @param string $path
* @access public
* @return array
*/
public function getCommitsByPath($path, $fromRevision = '', $toRevision = '')
{
$path = ltrim($path, DIRECTORY_SEPARATOR);
$api = "commits";
$api = "commits";
$param = new stdclass();
$param->path = urldecode($path);
$param = new stdclass();
$param->path = urldecode($path);
$param->ref_name = $this->branch;
if($fromRevision) $fromRevision = $this->getSingleCommit($fromRevision);
@@ -566,13 +567,13 @@ class gitlab
$param->since = $since;
$param->until = $until;
return $this->fetch($api, $param);
}
return $this->fetch($api, $param);
}
/**
* Get files by commit.
*
* @param string $commit
*
* @param string $commit
* @access public
* @return void
*/
@@ -598,7 +599,7 @@ class gitlab
$file->revision = $revision;
$file->path = '/' . $row->new_path;
$file->type = 'file';
$file->action = 'M';
if($row->new_file) $file->action = 'A';
if($row->renamed_file) $file->action = 'R';
@@ -611,9 +612,9 @@ class gitlab
/**
* Repository/tree api.
*
* @param string $path
* @param bool $recursive
*
* @param string $path
* @param bool $recursive
* @access public
* @return void
*/
@@ -630,8 +631,8 @@ class gitlab
/**
* Fetch data from gitlab api.
*
* @param string $api
*
* @param string $api
* @access public
* @return void
*/
@@ -640,7 +641,7 @@ class gitlab
$params = (array) $params;
$params['private_token'] = $this->token;
$api = ltrim($api, '/');
$api = ltrim($api, '/');
$api = $this->root . $api . '?' . http_build_query($params);
$response = file_get_contents($api);
@@ -649,24 +650,24 @@ class gitlab
/**
* Format bytes shown.
*
* @param int $size
*
* @param int $size
* @static
* @access public
* @return string
*/
public static function formatBytes($size)
{
if($size < 1024) return $size . 'Bytes';
{
if($size < 1024) return $size . 'Bytes';
if(round($size / (1024 * 1024), 2) > 1) return round($size / (1024 * 1024), 2) . 'G';
if(round($size / 1024, 2) > 1) return round($size / 1024, 2) . 'M';
return round($size, 2) . 'KB';
}
if(round($size / 1024, 2) > 1) return round($size / 1024, 2) . 'M';
return round($size, 2) . 'KB';
}
/**
* Parse log.
*
* @param array $logs
*
* @param array $logs
* @access public
* @return array
*/
+15
View File
@@ -868,6 +868,7 @@ class actionModel extends model
public function transformActions($actions)
{
$this->app->loadLang('todo');
$requirements = array();
/* Get commiters. */
$commiters = $this->loadModel('user')->getCommiters();
@@ -901,6 +902,16 @@ class actionModel extends model
$objectProject[$object->id] = $object->project > 0 ? $object->project : $object->id;
}
}
elseif($objectType == 'story')
{
$objectInfo = $this->dao->select('id,title,type')->from($table)->where('id')->in($objectIds)->fetchAll();
foreach($objectInfo as $object)
{
$objectName[$object->id] = $object->title;
if($object->type == 'requirement') $requirements[$object->id] = $object->id;
}
$objectProject = array();
}
else
{
$objectName = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs();
@@ -946,6 +957,10 @@ class actionModel extends model
if(isset($this->lang->action->label->$objectType))
{
$objectLabel = $this->lang->action->label->$objectType;
/* Replace story to requirement. */
if(in_array($action->objectID, $requirements)) $objectLabel = str_replace($this->lang->SRCommon, $this->lang->URCommon, $objectLabel);
if(!is_array($objectLabel)) $action->objectLabel = $objectLabel;
if(is_array($objectLabel) and isset($objectLabel[$actionType])) $action->objectLabel = $objectLabel[$actionType];
}
+2 -2
View File
@@ -54,8 +54,8 @@
$methodName = 'view';
if($module == 'caselib')
{
$methodName = 'libview';
$module = 'testsuite';
$methodName = 'view';
$module = 'caselib';
}
if(isset($config->action->customFlows[$action->objectType]))
{
+1 -1
View File
@@ -63,7 +63,7 @@
<?php if($i == 0):?>
<td <?php if($rowspan > 1) echo "rowspan='$rowspan'"?>><?php echo date(DT_DATETIME1, $backupFile->time);?></td>
<?php endif;?>
<td class='text-left' style='padding-left:5px;'><?php echo $file;?></td>
<td title=<?php echo $file;?> class='text-left' style='padding-left:5px;'><?php echo $file;?></td>
<td><?php echo zget($summary, 'allCount', '');?></td>
<td><?php echo zget($summary, 'count', '');?></td>
<td>
+5
View File
@@ -26,3 +26,8 @@ body {padding-bottom: 20px;}
#dashboard .block-sm .hide-in-sm {display: none;}
#dashboard .block-dynamic .panel-body {overflow-x: hidden;}
.modal-body {padding: 10px 20px 20px 20px;}
#dashboard .block-scrumoverview .table {margin-bottom: 12px;}
#dashboard .block-scrumoverview .table thead tr th {padding-left: 0; text-align: right; border-bottom: unset;}
#dashboard .block-scrumoverview .table tbody tr td {padding-left: 0;}
#dashboard .block-scrumoverview .table tbody tr th {text-align: right;}
+2 -1
View File
@@ -15,7 +15,8 @@ $(function()
}
else
{
var lang = config.clientLang;
var lang = config.clientLang;
blockTitle = $blockParams.find('#title').val();
if(lang.indexOf('zh') >= 0)
{
if(blockTitle.indexOf(preValue) >= 0)
+1 -1
View File
@@ -53,7 +53,7 @@
?>
<tr>
<td class='c-id-xs'><?php echo sprintf('%03d', $bug->id);?></td>
<td class='c-name' style='color: <?php echo $bug->color?>' title='<?php echo $bug->title?>'><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id", '', '', $bug->project), $bug->title)?></td>
<td class='c-name' title='<?php echo $bug->title?>'><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title, '', "style='color: $bug->color'")?></td>
<?php if($longBlock):?>
<td class='c-severity'>
<?php if($hasCustomSeverity):?>
@@ -13,12 +13,6 @@
<?php if(empty($totalData)): ?>
<div class='empty-tip'><?php common::printLink('project', 'create', '', "<i class='icon-plus'></i> " . $lang->project->create, '', "class='btn btn-primary'")?></div>
<?php else:?>
<style>
.table {margin-bottom: 12px;}
.table thead tr th {padding-left: 0; text-align: right; border-bottom: unset;}
.table tbody tr td {padding-left: 0;}
.table tbody tr th {text-align: right;}
</style>
<table class="table table-data">
<thead>
<tr>
+3 -3
View File
@@ -61,7 +61,7 @@ class bug extends control
}
else
{
$products = $this->product->getPairs();
$products = $this->product->getPairs('', 0, 'program_asc');
}
$this->view->products = $this->products = $products;
@@ -401,7 +401,7 @@ class bug extends control
else
{
setcookie('bugModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$location = $this->createLink('bug', 'browse', "productID={$this->post->product}&branch=$branch&browseType=unclosed&param=0&orderBy=id_desc");
$location = $this->createLink('bug', 'browse', "productID={$this->post->product}&branch=$branch&browseType=byModule&param={$this->post->module}&orderBy=id_desc");
}
if($this->app->getViewType() == 'xhtml') $location = $this->createLink('bug', 'view', "bugID=$bugID");
$response['locate'] = $location;
@@ -514,7 +514,7 @@ class bug extends control
if(empty($moduleOptionMenu)) die(js::locate(helper::createLink('tree', 'browse', "productID=$productID&view=story")));
/* Get products and projects. */
$products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed');
$products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed', 0, 'program_asc');
$projects = array(0 => '');
if($projectID)
{
+4 -2
View File
@@ -544,7 +544,7 @@ function notice()
if($('#openedBuild').find('option').length <= 1)
{
var html = '';
if($('#execution').length == 0 || $('#execution').val() == '')
if($('#execution').length == 0 || $('#execution').val() == 0)
{
var branch = $('#branch').val();
if(typeof(branch) == 'undefined') branch = 0;
@@ -556,7 +556,9 @@ function notice()
else
{
executionID = $('#execution').val();
link = createLink('build', 'create','executionID=' + executionID + '&productID=' + $('#product').val());
productID = $('#product').val();
projectID = $('#project').val();
link = createLink('build', 'create','executionID=' + executionID + '&productID=' + productID + '&projectID=' + projectID);
link += config.requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes';
html += '<a href="' + link + '" data-toggle="modal" data-type="iframe" style="padding-right:5px">' + createBuild + '</a> ';
html += '<a href="javascript:loadExecutionBuilds(' + executionID + ')">' + refresh + '</a>';
+1 -1
View File
@@ -19,7 +19,7 @@ $lang->bug->module = '所属模块';
$lang->bug->moduleAB = '模块';
$lang->bug->project = '所属项目';
$lang->bug->execution = '所属' . $lang->executionCommon;
$lang->bug->story = "相关{$lang->SRCommon}";
$lang->bug->story = "相关需求";
$lang->bug->storyVersion = "{$lang->SRCommon}版本";
$lang->bug->color = '标题颜色';
$lang->bug->task = '相关任务';
+1 -1
View File
@@ -325,7 +325,7 @@ js::set('blockID', $blockID);
<tr>
<td colspan="3" class="text-center form-actions">
<?php echo html::submitButton();?>
<?php if($caseID == 0) echo html::backButton();?>
<?php echo html::backButton();?>
<?php echo html::hidden('case', (int)$caseID) . html::hidden('caseVersion', (int)$version);?>
<?php echo html::hidden('result', (int)$runID) . html::hidden('testtask', empty($testtask) ? 0 : $testtask->id);?>
</td>
+2 -2
View File
@@ -117,7 +117,7 @@
</tr>
<?php if($product->type != 'normal'):?>
<tr>
<th><?php echo sprintf($lang->product->branch, $lang->product->branchName[$product->name]);?></th>
<th><?php echo sprintf($lang->product->branch, $lang->product->branchName[$product->type]);?></th>
<td><?php if(!common::printLink('bug', 'browse', "productID=$bug->product&branch=$bug->branch", $branchName)) echo $branchName;?></td>
</tr>
<?php endif;?>
@@ -240,7 +240,7 @@
<table class='table table-data'>
<tbody>
<tr>
<th class='w-60px'><?php echo $lang->bug->execution;?></th>
<th class='w-70px'><?php echo $lang->bug->execution;?></th>
<td><?php if($bug->execution) echo html::a($this->createLink('execution', 'browse', "executionid=$bug->execution"), $bug->executionName);?></td>
</tr>
<tr class='nofixed'>
+1 -1
View File
@@ -505,7 +505,7 @@ class caselib extends control
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
helper::saveFile($file['tmpname'], $fileName);
move_uploaded_file($file['tmpname'], $fileName);
$rows = $this->file->parseCSV($fileName);
$fields = $this->testcase->getImportFields($productID);
+3 -1
View File
@@ -29,7 +29,9 @@ class caselibModel extends model
if($libraries)
{
$currentLibName = zget($libraries, $libID, '');
$libName = '';
if(!isset($libraries[$libID])) $libName = $this->dao->select('name')->from(TABLE_TESTSUITE)->where('id')->eq($libID)->fetch('name');
$currentLibName = zget($libraries, $libID, $libName);
setCookie("lastCaseLib", $libID, $this->config->cookieLife, $this->config->webRoot, '', false, true);
$dropMenuLink = helper::createLink('caselib', 'ajaxGetDropMenu', "objectID=$libID&module=caselib&method=browse");
+1 -1
View File
@@ -183,7 +183,7 @@ $lang->project->homeMenu->browse = array('link' => ($config->systemMode == 'new'
$lang->scrum->menu = new stdclass();
$lang->scrum->menu->index = array('link' => "{$lang->dashboard}|project|index|project=%s");
$lang->scrum->menu->execution = array('link' => "$lang->executionCommon|project|execution|status=all&projectID=%s");
$lang->scrum->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory', 'alias' => 'story,track');
$lang->scrum->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree', 'alias' => 'story,track');
$lang->scrum->menu->doc = array('link' => "{$lang->doc->common}|doc|objectLibs|type=project&objectID=%s", 'subModule' => 'doc');
$lang->scrum->menu->qa = array('link' => "{$lang->qa->common}|project|bug|projectID=%s", 'subModule' => 'testcase,testtask,bug,testreport', 'alias' => 'bug,testtask,testcase,testreport');
$lang->scrum->menu->devops = array('link' => "{$lang->repo->common}|repo|browse|repoID=0&branchID=&objectID=%s", 'subModule' => 'repo');
+1 -1
View File
@@ -43,7 +43,7 @@
</tr>
<tr>
<th><?php echo $lang->doclib->control;?></th>
<?php if($lib->type == 'product' or $lib->type == 'execution' or ($config->systemMode == 'classic' and $lib->type != 'custom')):?>
<?php if($lib->type == 'product' or $lib->type == 'execution'):?>
<td>
<?php echo html::radio('acl', $lang->doclib->aclListA, $lib->acl, "onchange='toggleAcl(this.value, \"lib\")'")?>
<span class='text-info' id='noticeAcl'><?php echo $lang->doc->noticeAcl['lib'][$lib->type][$lib->acl];?></span>
+28
View File
@@ -1361,6 +1361,13 @@ class execution extends control
if(!empty($_POST))
{
$oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->fetchPairs('plan');
$oldPlanStories = $this->dao->select('t1.story')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.project=t2.project')
->where('t1.project')->eq($executionID)
->andWhere('t2.plan')->in(array_keys($oldPlans))
->fetchAll('story');
$oldProducts = $this->execution->getProducts($executionID);
$changes = $this->execution->update($executionID);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -1386,6 +1393,16 @@ class execution extends control
$actionID = $this->loadModel('action')->create($this->objectType, $executionID, 'edited', '', $products);
$this->action->logHistory($actionID, $changes);
}
/* Link the plan stories. */
$diffResult = array_diff($oldPlans, $_POST['plans']);
if(!empty($_POST['plans']) and !empty($diffResult))
{
$projectID = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('project');
$this->loadModel('productplan')->linkProject($executionID, $_POST['plans'], $oldPlanStories);
$this->loadModel('productplan')->linkProject($projectID, $_POST['plans']);
}
$this->executeHooks($executionID);
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "executionID=$executionID")));
}
@@ -2044,6 +2061,13 @@ class execution extends control
if($unresolvedBugs->count) $tips .= sprintf($this->lang->execution->unresolvedBug, $unresolvedBugs->count);
if($tips) $tips = $this->lang->execution->unfinishedExecution . $tips;
$type = $this->dao->select('type')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('type');
if($type == 'stage')
{
if($tips) $tips = str_replace($this->lang->executionCommon, $this->lang->project->stage, $tips);
$this->lang->execution->confirmDelete = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->execution->confirmDelete);
}
echo js::confirm($tips . sprintf($this->lang->execution->confirmDelete, $this->executions[$executionID]), $this->createLink('execution', 'delete', "executionID=$executionID&confirm=yes"));
exit;
}
@@ -2817,6 +2841,10 @@ class execution extends control
$this->fetch('file', 'export2' . $this->post->fileType, $_POST);
}
$this->loadModel('project');
$project = $this->project->getByID($this->session->project);
if($project->model == 'waterfall') $this->lang->executionCommon = $this->lang->project->stage;
$this->view->fileName = (in_array($status, array('all', 'undone')) ? $this->lang->execution->$status : $this->lang->execution->statusList[$status]) . $this->lang->executionCommon;
$this->display();
+5 -4
View File
@@ -277,7 +277,7 @@ $lang->execution->howToUpdateBurn = "<a href='http://api.zentao.net/goto.php
$lang->execution->whyNoStories = "Keine Story kann verknüpft werden. Bitte prüfen Sie ob ein Story mit {$lang->executionCommon} verknüpft ist {$lang->productCommon} und stellen Sie sicher das diese geprüft ist.";
$lang->execution->productStories = "{$lang->executionCommon} verknüpfte Story ist ein Subset von {$lang->productCommon}, welche nur nach überprüfung verknüpft werden kann. Bitte <a href='%s'> Story verknüpfen</a>。";
$lang->execution->haveDraft = "There are %s draft stories can't be linked.";
$lang->execution->doneExecutions = 'Erledigt';
$lang->execution->doneExecutions = 'Erledigt';
$lang->execution->selectDept = 'Abteilung wählen';
$lang->execution->selectDeptTitle = 'Abteilung wählen';
$lang->execution->copyTeam = 'Team kopieren';
@@ -285,12 +285,13 @@ $lang->execution->copyFromTeam = "Kopieren von {$lang->executionCommon} T
$lang->execution->noMatched = "$lang->executionCommon mit '%s' konnte nicht gefunden werden.";
$lang->execution->copyTitle = "Wählen Sie ein {$lang->executionCommon} zum Kopieren.";
$lang->execution->copyTeamTitle = "Wählen Sie ein {$lang->executionCommon} Team zum Kopieren.";
$lang->execution->copyNoExecution = "{$lang->executionCommon} kann nicht kopiert werden.";
$lang->execution->copyFromExecution = "Kopie von {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->copyNoExecution = "{$lang->executionCommon} kann nicht kopiert werden.";
$lang->execution->copyFromExecution = "Kopie von {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->cancelCopy = 'Kopieren abbrechen';
$lang->execution->byPeriod = 'Nach Zeit';
$lang->execution->byUser = 'Nach Benutzer';
$lang->execution->noExecution = 'Keine Projekte. ';
$lang->execution->noExecution = 'Keine Projekte. ';
$lang->execution->noExecutions = "No {$lang->execution->common}.";
$lang->execution->noMembers = 'Keine Mitglieder. ';
$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s";
$lang->execution->linkPRJStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the project)";
+1
View File
@@ -291,6 +291,7 @@ $lang->execution->cancelCopy = 'Cancel Copy';
$lang->execution->byPeriod = 'By Time';
$lang->execution->byUser = 'By User';
$lang->execution->noExecution = "No {$lang->executionCommon}. ";
$lang->execution->noExecutions = "No {$lang->execution->common}.";
$lang->execution->noMembers = 'No team members yet. ';
$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s";
// $lang->execution->linkProjectStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the execution)";
+5 -4
View File
@@ -277,7 +277,7 @@ $lang->execution->howToUpdateBurn = "<a href='https://api.zentao.pm/goto.php
$lang->execution->whyNoStories = "Aucune story ne peut être associée. Vérifiez s'il existe des stories dans {$lang->executionCommon} qui sont associées à {$lang->productCommon} et vérifiez qu'elles ont bien été validées.";
$lang->execution->productStories = "Les stories associées au {$lang->executionCommon} sont une portion des stories associées au {$lang->productCommon}. Les stories ne peuvent être associées à un {$lang->executionCommon} qu'après avoir été validées. <a href='%s'> Associer Stories</a> maintenant.";
$lang->execution->haveDraft = "%s stories sont encore en conception, elles ne peuvent pas être associées au {$lang->executionCommon} actuellement.";
$lang->execution->doneExecutions = 'Terminé';
$lang->execution->doneExecutions = 'Terminé';
$lang->execution->selectDept = 'Sélection Compartiment';
$lang->execution->selectDeptTitle = 'Sélection Utilisateur';
$lang->execution->copyTeam = 'Copier Equipe';
@@ -285,12 +285,13 @@ $lang->execution->copyFromTeam = "Copié de l'Equipe {$lang->executionCom
$lang->execution->noMatched = "Aucun $lang->executionCommon inclus '%s' ne peut être trouvé.";
$lang->execution->copyTitle = "Choisissez un {$lang->executionCommon} à copier.";
$lang->execution->copyTeamTitle = "Choisissez une Equipe {$lang->executionCommon} à copier.";
$lang->execution->copyNoExecution = "Aucun {$lang->executionCommon} ne peut être copié.";
$lang->execution->copyFromExecution = "Copié du {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->copyNoExecution = "Aucun {$lang->executionCommon} ne peut être copié.";
$lang->execution->copyFromExecution = "Copié du {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->cancelCopy = 'Annuler la copie';
$lang->execution->byPeriod = 'Par Temps';
$lang->execution->byUser = 'Par Utilisateur';
$lang->execution->noExecution = "Aucun {$lang->executionCommon}. ";
$lang->execution->noExecution = "Aucun {$lang->executionCommon}. ";
$lang->execution->noExecutions = "Aucun {$lang->execution->common}.";
$lang->execution->noMembers = "Actuellement il n'y a aucun membre dans l'équipe. On ne va pas aller loin... ";
$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s";
$lang->execution->linkPRJStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the project)";
+5 -4
View File
@@ -277,7 +277,7 @@ $lang->execution->howToUpdateBurn = "<a href='https://api.zentao.pm/goto.php
$lang->execution->whyNoStories = "Không có câu chuyện có thể liên kết. Vui lòng kiểm tra có câu chuyện trong {$lang->executionCommon} cái liên kết tới {$lang->productCommon} và chắc chắn nó đã được duyệt.";
$lang->execution->productStories = "Câu chuyện liên kết tới {$lang->executionCommon} là tập hợp con của câu chuyện liên kết tới {$lang->productCommon}. Các câu chuyện chỉ có thể liên kết sau khi chúng đã được duyệt. <a href='%s'> Liên kết câu chuyện</a> now.";
$lang->execution->haveDraft = "%s câu chuyện đang nháp, bởi vậy chúng không thể liên kết.";
$lang->execution->doneExecutions = 'Kết thúc';
$lang->execution->doneExecutions = 'Kết thúc';
$lang->execution->selectDept = 'Chọn phòng/ban';
$lang->execution->selectDeptTitle = 'Chọn người dùng';
$lang->execution->copyTeam = 'Copy đội nhóm';
@@ -285,12 +285,13 @@ $lang->execution->copyFromTeam = "Sao chép từ {$lang->executionCommon}
$lang->execution->noMatched = "Không có $lang->executionCommon bao gồm '%s' có thể được tìm thấy.";
$lang->execution->copyTitle = "Chọn một {$lang->executionCommon} để sao chép.";
$lang->execution->copyTeamTitle = "Chọn một {$lang->executionCommon} đội nhóm để sao chép.";
$lang->execution->copyNoExecution = "Không có {$lang->executionCommon} có thể sao chép.";
$lang->execution->copyFromExecution = "Sao chép từ {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->copyNoExecution = "Không có {$lang->executionCommon} có thể sao chép.";
$lang->execution->copyFromExecution = "Sao chép từ {$lang->executionCommon} <strong>%s</strong>";
$lang->execution->cancelCopy = 'Hủy sao chép';
$lang->execution->byPeriod = 'Theo thời gian';
$lang->execution->byUser = 'Theo người dùng';
$lang->execution->noExecution = "Không có {$lang->executionCommon} nào";
$lang->execution->noExecution = "Không có {$lang->executionCommon} nào";
$lang->execution->noExecutions = "Không có {$lang->execution->common} nào";
$lang->execution->noMembers = 'Không có thành viên đội nhóm nào';
$lang->execution->workloadTotal = "The cumulative workload ratio should not exceed 100, and the total workload under the current product is: %s";
$lang->execution->linkPRJStoryTip = "(Link {$lang->SRCommon} comes from {$lang->SRCommon} linked under the project)";
+1
View File
@@ -291,6 +291,7 @@ $lang->execution->cancelCopy = '取消复制';
$lang->execution->byPeriod = '按时间段';
$lang->execution->byUser = '按用户';
$lang->execution->noExecution = "暂时没有{$lang->executionCommon}。";
$lang->execution->noExecutions = "暂时没有{$lang->execution->common}。";
$lang->execution->noMembers = '暂时没有团队成员。';
$lang->execution->workloadTotal = "工作量占比累计不应当超过100, 当前产品下的工作量之和为%s";
// $lang->execution->linkProjectStoryTip = "(关联{$lang->SRCommon}来源于项目下所关联的{$lang->SRCommon})";
+1
View File
@@ -291,6 +291,7 @@ $lang->execution->cancelCopy = '取消複製';
$lang->execution->byPeriod = '按時間段';
$lang->execution->byUser = '按用戶';
$lang->execution->noExecution = "暫時沒有{$lang->executionCommon}。";
$lang->execution->noExecutions = "暫時沒有{$lang->execution->common}。";
$lang->execution->noMembers = '暫時沒有團隊成員。';
$lang->execution->workloadTotal = "工作量占比累計不應當超過100, 當前產品下的工作量之和為%s";
// $lang->execution->linkProjectStoryTip = "(關聯{$lang->SRCommon}來源於項目下所關聯的{$lang->SRCommon})";
+20 -6
View File
@@ -69,6 +69,15 @@ class executionModel extends model
/* Unset story, bug, build and testtask if type is ops. */
$execution = $this->getByID($executionID);
if($execution->type == 'stage')
{
global $lang;
$this->loadModel('execution');
$this->app->loadLang('project');
$lang->executionCommon = $lang->project->stage;
include $this->app->getModulePath('execution') . 'lang/' . $this->app->getClientLang() . '.php';
}
if($execution and $execution->lifetime == 'ops')
{
unset($this->lang->execution->menu->story);
@@ -387,10 +396,10 @@ class executionModel extends model
$this->app->loadLang('doc');
$lib = new stdclass();
$lib->execution = $executionID;
$lib->name = $this->lang->doclib->main['execution'];
$lib->type = 'execution';
$lib->main = '1';
$lib->acl = 'default';
$lib->name = $type == 'stage' ? str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->doclib->main['execution']) : $this->lang->doclib->main['execution'];
$lib->type = 'execution';
$lib->main = '1';
$lib->acl = 'default';
$this->dao->insert(TABLE_DOCLIB)->data($lib)->exec();
$whitelist = explode(',', $sprint->whitelist);
@@ -840,7 +849,7 @@ class executionModel extends model
*/
public function getSwitcher($executionID, $currentModule, $currentMethod)
{
if(in_array($currentMethod, array('index', 'all', 'batchedit', 'create'))) return;
if($currentModule == 'execution' and in_array($currentMethod, array('index', 'all', 'batchedit', 'create'))) return;
$currentExecutionName = $this->lang->execution->common;
if($executionID)
@@ -1151,6 +1160,11 @@ class executionModel extends model
$module = 'execution';
$method = 'story';
}
if($module == 'product' and $method == 'showerrornone')
{
$module = 'execution';
$method = 'task';
}
if($module == 'execution' and $method == 'create') return;
if($extra != '')
@@ -2114,7 +2128,7 @@ class executionModel extends model
$this->loadModel('story')->setStage($storyID);
$this->unlinkCases($executionID, $storyID);
$objectType = $executionID == $this->session->project ? unlinkedfromproject : unlinkedfromexecution;
$objectType = $executionID == $this->session->project ? 'unlinkedfromproject' : 'unlinkedfromexecution';
$this->loadModel('action')->create('story', $storyID, $objectType, '', $executionID);
$tasks = $this->dao->select('id')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('execution')->eq($executionID)->andWhere('status')->in('wait,doing')->fetchPairs('id');
+11
View File
@@ -38,6 +38,16 @@ td.hours {text-align: right; overflow: hidden; text-overflow: ellipsis; white-sp
</div>
</div>
<div id='mainContent' class="main-row fade">
<?php if(empty($executionStats)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $from == 'execution' ? $lang->execution->noExecutions : $lang->execution->noExecution;?></span>
<?php if(common::hasPriv('execution', 'create')):?>
<?php echo html::a($this->createLink('execution', 'create', "projectID=$projectID"), "<i class='icon icon-plus'></i> " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-info' data-app='$from'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<?php $canBatchEdit = common::hasPriv('execution', 'batchEdit'); ?>
<form class='main-table' id='executionsForm' method='post' action='<?php echo inLink('batchEdit');?>' data-ride='table'>
<table class='table has-sort-head table-fixed' id='executionList'>
@@ -154,6 +164,7 @@ td.hours {text-align: right; overflow: hidden; text-overflow: ellipsis; white-sp
</div>
<?php endif;?>
</form>
<?php endif;?>
</div>
<script>
$("#<?php echo $status;?>Tab").addClass('btn-active-text');
+2 -1
View File
@@ -431,7 +431,7 @@ class extension extends control
$tmpName = $_FILES['file']['tmp_name'];
$fileName = $_FILES['file']['name'];
$dest = $this->app->getTmpRoot() . "/extension/$fileName";
helper::saveFile($tmpName, $dest);
move_uploaded_file($tmpName, $dest);
$extension = basename($fileName, '.zip');
$return = $this->extension->extractPackage($extension);
@@ -455,6 +455,7 @@ class extension extends control
$link = $type == 'install' ? inlink('install', "extension=$extension") : inlink('upgrade', "extension=$extension");
die(js::locate($link, 'parent'));
}
$this->display();
}
+2 -2
View File
@@ -97,7 +97,7 @@ class fileModel extends model
foreach($files as $id => $file)
{
if($file['size'] == 0) continue;
if(!helper::saveFile($file['tmpname'], $this->savePath . $this->getSaveName($file['pathname']))) return false;
if(!move_uploaded_file($file['tmpname'], $this->savePath . $this->getSaveName($file['pathname']))) return false;
$file = $this->compressImage($file);
@@ -470,7 +470,7 @@ class fileModel extends model
$filePath = $this->dao->select('pathname')->from(TABLE_FILE)->where('id')->eq($fileID)->fetch();
$pathName = $filePath->pathname;
$realPathName = $this->savePath . $this->getRealPathName($pathName);
if(!is_dir(dirname($realPathName)))mkdir(dirname($realPathName));
if(!is_dir(dirname($realPathName))) mkdir(dirname($realPathName));
helper::saveFile($file['tmpname'], $realPathName);
$file['pathname'] = $pathName;
+2 -1
View File
@@ -17,8 +17,9 @@ $sessionString .= session_name() . '=' . session_id();
function deleteFile(fileID)
{
if(!fileID) return;
hiddenwin.location.href =createLink('file', 'delete', 'fileID=' + fileID);
hiddenwin.location.href = createLink('file', 'delete', 'fileID=' + fileID);
}
/* Download a file, append the mouse to the link. Thus we call decide to open the file in browser no download it. */
function downloadFile(fileID, extension, imageWidth, fileTitle)
{
+1 -1
View File
@@ -25,7 +25,7 @@ body.menu-hide {padding-left: 0;}
.menu-hide #menu .nav > li.has-avatar > a {padding: 2px 0;}
#menuMoreNav {display: none;}
.show-more-nav #menuMoreNav {display: block;}
#menuMoreList {left: 100%; margin-left: -2px; top: -5px; background-color: #3c495c;}
#menuMoreList {left: 100%; margin-left: -2px; top: 0; background-color: #3c495c;}
#menuMoreList > li {padding: 2px 6px;}
#menuMoreList > li > a {color: #fff; padding: 4px 6px 4px 12px; border-radius: 2px; margin: 0;}
#menuMoreList > li > a > .icon {opacity: 1; font-size: 16px;}
+23 -3
View File
@@ -429,7 +429,7 @@
var maxHeight = $menuNav.height();
var showMoreMenu = false;
var currentHeight = 40;
var moreMenuHeight = 13;
var moreMenuHeight = 12;
$menuItems.each(function()
{
@@ -450,7 +450,7 @@
if(isDivider) return;
}
moreMenuHeight += isDivider ? 13 : 31;
moreMenuHeight += isDivider ? 13 : 30;
$list.append($item.clone().removeClass('hidden'));
}
else
@@ -461,7 +461,26 @@
/* The magic number "111" is the space between dropdown trigger
btn and the bottom of screen */
$list.css('top', moreMenuHeight > 111 ? 111 - moreMenuHeight : '');
var listStyle = {maxHeight: 'initial', top: moreMenuHeight > 111 ? 111 - moreMenuHeight : ''};
if($list[0].getBoundingClientRect)
{
var btnBounding = $list.prev('a')[0].getBoundingClientRect();
if(btnBounding.height)
{
var winHeight = $(window).height();
if(winHeight < moreMenuHeight)
{
listStyle.maxHeight = winHeight;
listStyle.overflow = 'auto';
listStyle.top = 5 - btnBounding.top;
}
else if(moreMenuHeight > (winHeight - btnBounding.top))
{
listStyle.top = winHeight - btnBounding.top - moreMenuHeight + 5;
}
}
}
$list.css(listStyle);
$menuNav.toggleClass('show-more-nav', showMoreMenu);
if(showMoreMenu && !$list.data('listened-click'))
@@ -554,6 +573,7 @@
/* Refresh more menu on window resize */
$(window).on('resize', refreshMoreMenu);
refreshMoreMenu();
setTimeout(refreshMoreMenu, 500);
});
}());
-1
View File
@@ -56,7 +56,6 @@ js::set('defaultOpen', $open);
<li id='menuToggleMenu'>
<a type='button' class='menu-toggle'>
<i class='icon icon-sm icon-menu-collapse'></i>
<i class='icon icon-sm icon-menu-unfold'></i>
</a>
</li>
</ul>
+1 -8
View File
@@ -26,13 +26,6 @@
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->project->empty;?></span>
<?php if(isset($this->config->maxVersion) and common::hasPriv('project', 'createGuide')):?>
<?php echo html::a($this->createLink('project', 'createGuide'), "<i class='icon icon-plus'></i> " . $lang->my->createProgram, '', "class='btn btn-info' data-toggle=modal");?>
<?php elseif($this->config->systemMode == 'new' and common::hasPriv('project', 'create')):?>
<?php echo html::a($this->createLink('project', 'create', 'mode=scrum'), '<i class="icon icon-plus"></i>' . $lang->project->create, '', 'class="btn btn-info"');?>
<?php elseif($this->config->systemMode == 'classic' and common::hasPriv('execution', 'create')):?>
<?php echo html::a($this->createLink('execution', 'create'), '<i class="icon icon-plus"></i>' . $lang->execution->create, '', 'class="btn btn-info"');?>
<?php endif;?>
</p>
</div>
<?php else:?>
@@ -98,7 +91,7 @@
<div class='btn-group'>
<button type='button' class='btn dropdown-toggle' data-toggle='dropdown' title="<?php echo $this->lang->more;?>"><i class='icon-more-alt'></i></button>
<ul class='dropdown-menu pull-right text-center' role='menu'>
<?php common::printIcon('project', 'manageProducts', "projectID=$project->id&projectID=$project->parent", $project, 'list', 'link', '', '', false, "data-group='project'", '', $project->id);?>
<?php common::printIcon('project', 'manageProducts', "projectID=$project->id", $project, 'list', 'link', '', '', false, "data-group='project'", '', $project->id);?>
<?php common::printIcon('project', 'whitelist', "projectID=$project->id&projectID=$project->parent&module=project", $project, 'list', 'shield-check', '', '', false, "data-group='project'", '', $project->id);?>
<?php if(common::hasPriv('project','delete')) echo html::a($this->createLink("project", "delete", "projectID=$project->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn' title='{$this->lang->project->delete}' data-group='my'");?>
</ul>
+1 -2
View File
@@ -60,7 +60,7 @@
<th class='c-hours'> <?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
<th class='c-status'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
<th class='c-stage'> <?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
<th class='c-actions-5'> <?php echo $lang->actions;?></th>
<th class='c-actions-4'> <?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
@@ -98,7 +98,6 @@
common::printIcon('story', 'review', $vars, $story, 'list', 'search', '', 'iframe', true);
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars, $story, 'list', '', '', 'iframe', true, "data-width='95%'");
common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap');
}
?>
</td>
+3 -3
View File
@@ -54,7 +54,7 @@
<th class='w-50px'> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
<th> <?php common::printOrderLink('title', $orderBy, $vars, $lang->testcase->title);?></th>
<?php if($type == 'assigntome'):?>
<th class='w-100px'> <?php common::printOrderLink('task', $orderBy, $vars, $lang->testtask->common);?></th>
<th class='w-100px'> <?php common::printOrderLink('task', $orderBy, $vars, $lang->testtask->common);?></th>
<?php endif;?>
<th class='w-type'> <?php common::printOrderLink('type', $orderBy, $vars, $lang->typeAB);?></th>
<th class='c-user'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
@@ -87,7 +87,7 @@
<?php if($type == 'assigntome') $params .= "&from=testtask&taskID=$case->task";?>
<td class='text-left'><?php echo html::a($this->createLink('testcase', 'view', $params), $case->title, null, "style='color: $case->color'");?></td>
<?php if($type == 'assigntome'):?>
<td class='c-name'><?php echo $case->taskName;?></td>
<td class='c-name' title='<?php echo $case->taskName;?>'><?php echo $case->taskName;?></td>
<?php endif;?>
<td><?php echo zget($lang->testcase->typeList, $case->type);?></td>
<td><?php echo zget($users, $case->openedBy);?></td>
@@ -99,7 +99,7 @@
<?php
if($canBeChanged)
{
common::printIcon('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=caseID=$caseID,version=$case->version,runID=$runID", $case, 'list', 'bug', '', '', '', "data-app='qa'");
common::printIcon('testcase', 'createBug', "product=$case->product&branch=$case->branch&extra=caseID=$caseID,version=$case->version,runID=$runID", $case, 'list', 'bug', '', 'iframe', 'true', "data-app='qa' data-toggle=''");
common::printIcon('testcase', 'create', "productID=$case->product&branch=$case->branch&moduleID=$case->module&from={$app->rawMethod}&param=$caseID", $case, 'list', 'copy', '', 'iframe', true, "data-width='95%'");
common::printIcon('testtask', 'runCase', "runID=$runID&caseID=$caseID&version=$case->version", '', 'list', 'play', '', 'iframe', true, "data-width='95%'", '', $case->project);
common::printIcon('testtask', 'results', "runID=$runID&caseID=$caseID", '', 'list', 'list-alt', '', 'iframe', true, "data-width='95%'", '', $case->project);
+1 -1
View File
@@ -848,7 +848,7 @@ class product extends control
$projects += $this->product->getProjectPairsByProduct($productID, $branch ? "0,$branch" : $branch);
if($this->app->getViewType() == 'json') die(json_encode($projects));
die(html::select('project', $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID})'"));
die(html::select('project', $projects, $projectID, "class='form-control' onchange='loadProductExecutions({$productID}, this.value)'"));
}
/**
+2 -1
View File
@@ -40,7 +40,8 @@ $lang->product->plans = 'Plan';
$lang->product->releases = 'Release';
$lang->product->docs = 'Dok';
$lang->product->bugs = 'Verknüpfte Bugs';
$lang->product->projects = "Verknüpfte {$lang->executionCommon}";
$lang->product->projects = "Linked Project";
$lang->product->executions = "Verknüpfte {$lang->execution->common}";
$lang->product->cases = 'Fälle';
$lang->product->builds = 'Builds';
$lang->product->roadmap = 'Roadmap';
+2 -1
View File
@@ -44,7 +44,8 @@ $lang->product->plans = 'Plans';
$lang->product->releases = 'Releases';
$lang->product->docs = 'Doc';
$lang->product->bugs = 'Linked Bug';
$lang->product->projects = "Linked {$lang->executionCommon}";
$lang->product->projects = "Linked Project";
$lang->product->executions = "Linked {$lang->execution->common}";
$lang->product->cases = 'Case';
$lang->product->builds = 'Build';
$lang->product->roadmap = "{$lang->productCommon} Roadmap";
+2 -1
View File
@@ -40,7 +40,8 @@ $lang->product->plans = 'Plans';
$lang->product->releases = 'Releases';
$lang->product->docs = 'Doc';
$lang->product->bugs = 'Bug Liés';
$lang->product->projects = "{$lang->executionCommon}s Liés";
$lang->product->projects = "Linked Project";
$lang->product->executions = "{$lang->execution->common}s Liés";
$lang->product->cases = 'CasTests';
$lang->product->builds = 'Build';
$lang->product->roadmap = "Roadmap {$lang->productCommon}";
+2 -1
View File
@@ -40,7 +40,8 @@ $lang->product->plans = 'Kế hoạch';
$lang->product->releases = 'Phát hành';
$lang->product->docs = 'Tài liệu';
$lang->product->bugs = 'Bug liên kết';
$lang->product->projects = "{$lang->executionCommon} liên kết";
$lang->product->projects = "Linked Project";
$lang->product->executions = "{$lang->execution->common} liên kết";
$lang->product->cases = 'Tình huống';
$lang->product->builds = 'Bản dựng';
$lang->product->roadmap = "Lộ trình {$lang->productCommon}";
+2 -1
View File
@@ -44,7 +44,8 @@ $lang->product->plans = "计划数";
$lang->product->releases = '发布数';
$lang->product->docs = '文档数';
$lang->product->bugs = '相关Bug';
$lang->product->projects = "关联{$lang->executionCommon}数";
$lang->product->projects = "关联项目数";
$lang->product->executions = "关联{$lang->execution->common}数";
$lang->product->cases = '用例数';
$lang->product->builds = '版本数';
$lang->product->roadmap = "{$lang->productCommon}路线图";
+49 -21
View File
@@ -74,7 +74,7 @@ class productModel extends model
*/
public function select($products, $productID, $currentModule, $currentMethod, $extra = '', $branch = 0, $module = 0, $moduleType = '', $withBranch = true)
{
$isBrowseBug = (strpos(',project,execution,', ",{$this->app->openApp},") !== false and strpos(',bug,testcase,testtask,', ",{$this->app->rawMethod},") !== false and isset($products[0])) ? true : false;
$isBrowseBug = (strpos(',project,execution,', ",{$this->app->openApp},") !== false and strpos(',bug,testcase,testtask,ajaxselectstory,', ",{$this->app->rawMethod},") !== false and isset($products[0])) ? true : false;
$this->app->loadLang('product');
if(!$isBrowseBug and !$productID)
@@ -261,21 +261,36 @@ class productModel extends model
*
* @param string $mode
* @param string $programID
* @param string $orderBy program_asc
* @return array
*/
public function getPairs($mode = '', $programID = 0)
public function getPairs($mode = '', $programID = 0, $orderBy = '')
{
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProductPairs();
$orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'isClosed';
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->beginIF($programID)->andWhere('program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->products)->fi()
->orderBy($orderBy)
->fetchPairs('id', 'name');
if($orderBy == 'program_asc')
{
$products = $this->dao->select('t1.id as id, t1.name as name, t1.*, IF(INSTR(" closed", t1.status) < 2, 0, 1) AS isClosed')->from(TABLE_PRODUCT)->alias('t1')
->leftJoin(TABLE_PROGRAM)->alias('t2')->on('t1.program = t2.id')
->where('t1.deleted')->eq(0)
->beginIF($programID)->andWhere('t1.program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t1.status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->products)->fi()
->orderBy('t2.order_asc, t1.line_desc, t1.order_desc')
->fetchPairs('id', 'name');
}
else
{
$orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'isClosed';
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
->from(TABLE_PRODUCT)
->where('deleted')->eq(0)
->beginIF($programID)->andWhere('program')->eq($programID)->fi()
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->products)->fi()
->orderBy($orderBy)
->fetchPairs('id', 'name');
}
return $products;
}
@@ -1257,16 +1272,25 @@ class productModel extends model
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t2.deleted')->eq(0)
->andWhere('t1.product')->eq($productID)
->andWhere('t2.type')->eq('project')
->fetch();
$product->stories = $stories;
$product->plans = $plans ? $plans->count : 0;
$product->releases = $releases ? $releases->count : 0;
$product->builds = $builds ? $builds->count : 0;
$product->cases = $cases ? $cases->count : 0;
$product->projects = $projects ? $projects->count : 0;
$product->bugs = $bugs ? $bugs->count : 0;
$product->docs = $docs ? $docs->count : 0;
$executions = $this->dao->select('count("t1.*") AS count')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t2.deleted')->eq(0)
->andWhere('t1.product')->eq($productID)
->andWhere('t2.type')->in('sprint,stage')
->fetch();
$product->stories = $stories;
$product->plans = $plans ? $plans->count : 0;
$product->releases = $releases ? $releases->count : 0;
$product->builds = $builds ? $builds->count : 0;
$product->cases = $cases ? $cases->count : 0;
$product->projects = $projects ? $projects->count : 0;
$product->executions = $executions ? $executions->count : 0;
$product->bugs = $bugs ? $bugs->count : 0;
$product->docs = $docs ? $docs->count : 0;
return $product;
}
@@ -1540,7 +1564,7 @@ class productModel extends model
public function getProductLink($module, $method, $extra, $branch = false)
{
$link = '';
if(strpos('programplan,product,roadmap,bug,testcase,testtask,story,qa,testsuite,testreport,build,projectrelease,projectstory', ',' . $module . ',') !== false)
if(strpos(',programplan,product,roadmap,bug,testcase,testtask,story,qa,testsuite,testreport,build,projectrelease,projectstory,', ',' . $module . ',') !== false)
{
if($module == 'product' && $method == 'project')
{
@@ -1569,12 +1593,16 @@ class productModel extends model
elseif($module == 'programplan')
{
$extra = $extra ? $extra : 'gantt';
$link = helper::createLink($module, 'browse', "projectID=%s&productID=%s&type=$extra" . ($branch ? "&branch=%s" : ''));
$link = helper::createLink($module, 'browse', "projectID=%s&productID=%s&type=$extra");
}
elseif($module == 'story' && $method == 'report')
{
$link = helper::createLink($module, 'report', "productID=%s" . ($branch ? "&branch=%s" : '&branch=0') . "&extra=$extra");
}
elseif($module == 'testtask')
{
$link = helper::createLink($module, 'browse', "productID=%s" . ($branch ? "&branch=%s" : '&branch=0') . "&extra=$extra");
}
elseif($module == 'bug' && $method == 'view')
{
$link = helper::createLink('bug', 'browse', "productID=%s" . ($branch ? "&branch=%s" : '&branch=0') . "&extra=$extra");
+2 -3
View File
@@ -81,9 +81,7 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
</div>
<?php endif;?>
<?php
$this->moduleName = $this->app->rawModule;
$this->methodName = $this->app->rawMethod;
foreach(customModel::getFeatureMenu($this->moduleName, $this->methodName) as $menuItem)
foreach(customModel::getFeatureMenu($this->app->rawModule, $this->app->rawMethod) as $menuItem)
{
if(isset($menuItem->hidden)) continue;
if($menuItem->name == 'emptysr' && $storyType == 'story') continue;
@@ -341,6 +339,7 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
<ul class='dropdown-menu'>
<?php
$class = $canBatchClose ? '' : "class='disabled'";
$productID = $this->app->openApp == 'project' ? 0 : $productID;
$actionLink = $this->createLink('story', 'batchClose', "productID=$productID&projectID=0&storyType=$storyType");
$misc = $canBatchClose ? "onclick=\"setFormAction('$actionLink')\"" : '';
echo "<li $class>" . html::a('#', $lang->close, '', $misc) . "</li>";
+1 -1
View File
@@ -75,7 +75,7 @@
<th><?php echo $lang->product->acl;?></th>
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->product->aclList, 'private', "onclick='setWhite(this.value);'", 'block'));?></td>
</tr>
<tr class="hidden" id="whitelistBox">
<tr id="whitelistBox">
<th><?php echo $lang->whitelist;?></th>
<td><?php echo html::select('whitelist[]', $users, '', 'class="form-control chosen" multiple');?></td>
<td></td>
+3 -2
View File
@@ -40,7 +40,7 @@
<th class='w-80px'><?php echo $lang->project->begin;?></th>
<th class='w-80px'><?php echo $lang->project->end;?></th>
<th class='w-70px'><?php echo $lang->project->status;?></th>
<th class="w-70px"><?php echo $lang->project->budget;?></th>
<th class="w-80px text-center"><?php echo $lang->project->budget;?></th>
<th class="w-60px text-center"><?php echo $lang->project->estimate;?></th>
<th class="w-60px text-center"><?php echo $lang->project->consume;?></th>
<th class='w-50px'><?php echo $lang->project->progress;?></th>
@@ -78,7 +78,8 @@
</td>
<?php $projectBudget = in_array($this->app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?>
<?php $budgetTitle = $project->budget != 0 ? zget($this->lang->project->currencySymbol, $project->budgetUnit) . ' ' . $projectBudget : $this->lang->project->future;?>
<td title='<?php echo $budgetTitle;?>' class='text-ellipsis text-right padding-right'><?php echo $budgetTitle;?></td>
<?php $textStyle = $project->budget != 0 ? 'text-right' : 'text-center';?>
<td title='<?php echo $budgetTitle;?>' class="text-ellipsis <?php echo $textStyle;?>"><?php echo $budgetTitle;?></td>
<td class="text-right padding-right" title="<?php echo $project->hours->totalEstimate . ' ' . $lang->execution->workHour;?>"><?php echo $project->hours->totalEstimate . $lang->execution->workHourUnit;?></td>
<td class="text-right padding-right" title="<?php echo $project->hours->totalConsumed . ' ' . $lang->execution->workHour;?>"><?php echo $project->hours->totalConsumed . $lang->execution->workHourUnit;?></td>
<td class='padding-right text-center'>
+9 -5
View File
@@ -26,7 +26,7 @@
</div>
<?php if($product->type == 'platform'):?>
<div class="detail">
<div class="detail-title"><strong><?php echo $lang->product->branchName['platform'];?></strong><a class="btn btn-link pull-right muted"><i class="icon icon-more icon-sm"></i></a></div>
<div class="detail-title"><strong><?php echo $lang->product->branchName['platform'];?></strong><a class="btn btn-link pull-right muted" href="<?php echo $this->createLink('branch', 'manage', "productID={$product->id}")?>"><i class="icon icon-more icon-sm"></i></a></div>
<div class="detail-content">
<ul class="clearfix branch-list">
<?php foreach($branches as $branchName):?>
@@ -114,8 +114,8 @@
<tr>
<th><?php echo $lang->story->statusList['changed'] . $space . $lang->story->common;?></th>
<td><strong><?php echo $product->stories['changed']?></strong></td>
<th><?php echo $lang->product->projects?></th>
<td><strong><?php echo $product->projects?></strong></td>
<th><?php echo $lang->product->releases?></th>
<td><strong><?php echo $product->releases?></strong></td>
<th><?php echo $lang->product->cases?></th>
<td><strong><?php echo $product->cases?></strong></td>
</tr>
@@ -130,8 +130,12 @@
<tr>
<th><?php echo $lang->story->statusList['closed'] . $space . $lang->story->common;?></th>
<td><strong><?php echo $product->stories['closed']?></strong></td>
<th><?php echo $lang->product->releases?></th>
<td><strong><?php echo $product->releases?></strong></td>
<?php if($config->systemMode == 'new'):?>
<th><?php echo $lang->product->projects?></th>
<td><strong><?php echo $product->projects?></strong></td>
<?php endif;?>
<th><?php echo $lang->product->executions?></th>
<td><strong><?php echo $product->executions?></strong></td>
</tr>
</tbody>
</table>
+58 -6
View File
@@ -96,6 +96,7 @@ class productplanModel extends model
$plans = $this->reorder4Children($plans);
$planIdList = array_keys($plans);
$storyCountInTable = $this->dao->select('plan,count(story) as count')->from(TABLE_PLANSTORY)->where('plan')->in($planIdList)->groupBy('plan')->fetchPairs('plan', 'count');
$product = $this->loadModel('product')->getById($product);
if($product->type == 'normal')
{
@@ -127,6 +128,22 @@ class productplanModel extends model
$plan->hour = array_sum($storyPairs);
$plan->projectID = $plan->project;
/* Sync linked stories. */
if(!isset($storyCountInTable[$plan->id]) or $storyCountInTable[$plan->id] != $plan->stories)
{
$this->dao->delete()->from(TABLE_PLANSTORY)->where('plan')->eq($plan->id)->exec();
$order = 1;
foreach($storyPairs as $storyID => $estimate)
{
$planStory = new stdclass();
$planStory->plan = $plan->id;
$planStory->story = $storyID;
$planStory->order = $order ++;
$this->dao->replace(TABLE_PLANSTORY)->data($planStory)->exec();
}
}
if(!isset($parentStories[$plan->parent])) $parentStories[$plan->parent] = 0;
if(!isset($parentBugs[$plan->parent])) $parentBugs[$plan->parent] = 0;
if(!isset($parentHour[$plan->parent])) $parentHour[$plan->parent] = 0;
@@ -292,8 +309,8 @@ class productplanModel extends model
/**
* Get Children plan.
*
* @param int $planID
*
* @param int $planID
* @access public
* @return array
*/
@@ -433,8 +450,8 @@ class productplanModel extends model
/**
* Change parent field by planID.
*
* @param int $planID
*
* @param int $planID
* @access public
* @return void
*/
@@ -560,10 +577,45 @@ class productplanModel extends model
$this->loadModel('action')->create('bug', $bugID, 'unlinkedfromplan', '', $planID);
}
/**
* Link project.
*
* @param int $projectID
* @param array $newPlans
* @param array $oldPlanStories
* @access public
* @return void
*/
public function linkProject($projectID, $newPlans, $oldPlanStories = '')
{
if(!empty($oldPlanStories)) $this->dao->delete()->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->andWhere('story')->in(array_keys($oldPlanStories))->exec();
$this->loadModel('execution');
foreach($newPlans as $planID)
{
$planStories = $planProducts = array();
$planStory = $this->loadModel('story')->getPlanStories($planID);
if(!empty($planStory))
{
foreach($planStory as $id => $story)
{
if($story->status == 'draft')
{
unset($planStory[$id]);
continue;
}
$planProducts[$story->id] = $story->product;
}
$planStories = array_keys($planStory);
$this->execution->linkStory($projectID, $planStories, $planProducts);
}
}
}
/**
* Reorder for children plans.
*
* @param array $plans
*
* @param array $plans
* @access public
* @return array
*/
+11
View File
@@ -25,6 +25,17 @@ $(function()
$('#end').removeAttr('disabled');
}
});
$('#end').change(function()
{
var beginDate = $('#begin').val();
var endDate = $('#end').val();
var begin = new Date(beginDate.replace(/-/g,"/"));
var end = new Date(endDate.replace(/-/g,"/"));
var time = end.getTime() - begin.getTime();
var days = parseInt(time / (1000 * 60 * 60 * 24)) + 1;
if(days != $("input:radio[name='delta']:checked").val()) $("input:radio[name='delta']:checked").attr('checked',false);
})
});
function setCopyProject(copiedProgramID)
+11
View File
@@ -27,5 +27,16 @@ $(function()
}
});
$('#end').change(function()
{
var beginDate = $('#begin').val();
var endDate = $('#end').val();
var begin = new Date(beginDate.replace(/-/g,"/"));
var end = new Date(endDate.replace(/-/g,"/"));
var time = end.getTime() - begin.getTime();
var days = parseInt(time / (1000 * 60 * 60 * 24)) + 1;
if(days != $("input:radio[name='delta']:checked").val()) $("input:radio[name='delta']:checked").attr('checked',false);
})
$('#isCat').change();
});
+1 -1
View File
@@ -103,7 +103,7 @@
<div class='btn-group'>
<button type='button' class='btn dropdown-toggle' data-toggle='dropdown' title="<?php echo $this->lang->more;?>"><i class='icon-more-alt'></i></button>
<ul class='dropdown-menu pull-right text-center' role='menu'>
<?php common::printIcon('project', 'manageProducts', "projectID=$program->id&programID=$program->parent&from=browse", $program, 'list', 'link', '', '', '', "data-app='project'", '', $program->id);?>
<?php common::printIcon('project', 'manageProducts', "projectID=$program->id&from=browse", $program, 'list', 'link', '', '', '', "data-app='project'", '', $program->id);?>
<?php common::printIcon('project', 'whitelist', "projectID=$program->id&module=project&from=browse", $program, 'list', 'shield-check', '', '', '', "data-app='project'", '', $program->id);?>
<?php if(common::hasPriv('project','delete')) echo html::a($this->createLink("project", "delete", "projectID=$program->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn' title='{$this->lang->delete}' data-group='program'");?>
</ul>
+44 -6
View File
@@ -272,6 +272,30 @@ class project extends control
$this->loadModel('action')->create('project', $projectID, 'opened');
/* Link the plan stories. */
if(!empty($_POST['plans']))
{
foreach($_POST['plans'] as $planID)
{
$planStories = $planProducts = array();
$planStory = $this->loadModel('story')->getPlanStories($planID);
if(!empty($planStory))
{
foreach($planStory as $id => $story)
{
if($story->status == 'draft')
{
unset($planStory[$id]);
continue;
}
$planProducts[$story->id] = $story->product;
}
$planStories = array_keys($planStory);
$this->execution->linkStory($projectID, $planStories, $planProducts);
}
}
}
if($this->app->openApp == 'program')
{
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('program', 'browse')));
@@ -376,6 +400,14 @@ class project extends control
if($_POST)
{
$oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs('plan');
$oldPlanStories = $this->dao->select('t1.story')->from(TABLE_PROJECTSTORY)->alias('t1')
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.project=t2.project')
->where('t1.project')->eq($projectID)
->andWhere('t2.plan')->in(array_keys($oldPlans))
->fetchAll('story');
$diffResult = array_diff($oldPlans, $_POST['plans']);
$changes = $this->project->update($projectID);
if(dao::isError()) $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -385,7 +417,14 @@ class project extends control
$this->action->logHistory($actionID, $changes);
}
/* Link the plan stories. */
if(!empty($_POST['plans']) and !empty($diffResult))
{
$this->loadModel('productplan')->linkProject($projectID, $_POST['plans'], $oldPlanStories);
}
$locateLink = $this->session->projectList ? $this->session->projectList : inLink('view', "projectID=$projectID");
if($from == 'projectView') $locateLink = $this->createLink('project', 'view', "projectID=$projectID");
if($from == 'program') $locateLink = $this->createLink('program', 'browse');
if($from == 'programProject') $locateLink = $this->session->programProject ? $this->session->programProject : $this->createLink('program', 'project', "projectID=$projectID");
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locateLink));
@@ -1441,13 +1480,12 @@ class project extends control
/**
* Manage products.
*
* @param int $projectID
* @param int $programID
* @param int $projectID
* @param string $from project|program|programproject
* @access public
* @return void
*/
public function manageProducts($projectID, $programID = 0, $from = 'project')
public function manageProducts($projectID, $from = 'project')
{
$this->loadModel('product');
$this->loadModel('program');
@@ -1486,9 +1524,9 @@ class project extends control
$this->project->setMenu($projectID);
}
$allProducts = $this->program->getProductPairs($project->parent, 'assign', 'noclosed');
$linkedProducts = $this->product->getProducts($project->id);
$linkedBranches = array();
$allProducts = $this->program->getProductPairs($project->parent, 'assign', 'noclosed');
$linkedProducts = $this->product->getProducts($project->id);
$linkedBranches = array();
/* If the story of the product which linked the project, you don't allow to remove the product. */
$unmodifiableProducts = array();
+6
View File
@@ -75,6 +75,12 @@ function computeWorkDays(currentID)
{
beginDate = $('#begin').val();
endDate = $('#end').val();
var begin = new Date(beginDate.replace(/-/g,"/"));
var end = new Date(endDate.replace(/-/g,"/"));
var time = end.getTime() - begin.getTime();
var days = parseInt(time / (1000 * 60 * 60 * 24)) + 1;
if(days != $("input:radio[name='delta']:checked").val()) $("input:radio[name='delta']:checked").attr('checked',false);
}
if(beginDate && endDate)
+1 -1
View File
@@ -1381,7 +1381,7 @@ class projectModel extends model
echo "<div class='btn-group'>";
echo "<button type='button' class='btn dropdown-toggle' data-toggle='context-dropdown' title='{$this->lang->more}'><i class='icon-more-alt'></i></button>";
echo "<ul class='dropdown-menu pull-right text-center' role='menu'>";
common::printIcon('project', 'manageProducts', "projectID=$project->id&programID=$programID", $project, 'list', 'link', '', 'btn-action', '', "data-app=project", $this->lang->project->manageProducts, $project->id);
common::printIcon('project', 'manageProducts', "projectID=$project->id", $project, 'list', 'link', '', 'btn-action', '', "data-app=project", $this->lang->project->manageProducts, $project->id);
if($this->config->systemMode == 'new') common::printIcon('project', 'whitelist', "projectID=$project->id&module=project&from=$from", $project, 'list', 'shield-check', '', 'btn-action', '', "data-app=project", '', $project->id);
if(common::hasPriv('project','delete')) echo html::a(inLink("delete", "projectID=$project->id"), "<i class='icon-trash'></i>", 'hiddenwin', "class='btn btn-action' title='{$this->lang->project->delete}'");
echo "</ul>";
+1 -1
View File
@@ -104,7 +104,7 @@
echo $this->buildOperateMenu($project, 'view');
echo "<div class='divider'></div>";
common::printIcon('project', 'edit', $params, $project, 'button', 'edit', '', '', '', '', $lang->edit);
common::printIcon('project', 'edit', $params . '&from=projectView', $project, 'button', 'edit', '', '', '', '', $lang->edit);
common::printIcon('project', 'delete', $params, $project, 'button', 'trash', 'hiddenwin', '', '', '', $lang->delete);
}
?>
+1
View File
@@ -193,6 +193,7 @@ class projectrelease extends control
public function view($releaseID, $type = 'story', $link = 'false', $param = '', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
{
$this->session->set('buildList', $this->app->getURI(true), 'execution');
$this->session->set('storyList', $this->app->getURI(true), $this->app->openApp);
$this->loadModel('story');
$this->loadModel('bug');
+1 -1
View File
@@ -146,7 +146,7 @@
if(common::hasPriv('story', 'batchClose'))
{
$closeURL = $this->createLink('story', 'batchClose', "productID=$release->product");
$closeURL = $this->createLink('story', 'batchClose');
echo html::a("###", $lang->story->batchClose, '', "onclick='setFormAction(\"$closeURL\", \"\", this)' class='btn'");
}
?>
+1
View File
@@ -3,6 +3,7 @@ $lang->repo->common = 'Repo';
$lang->repo->browse = 'View';
$lang->repo->viewRevision = 'View Revision';
$lang->repo->product = 'Product';
$lang->repo->execution = $lang->execution->common;
$lang->repo->create = 'Create';
$lang->repo->createAction = 'Create Repo';
$lang->repo->maintain = 'Repo List';
+1
View File
@@ -3,6 +3,7 @@ $lang->repo->common = 'Repo';
$lang->repo->browse = 'View';
$lang->repo->viewRevision = 'View Revision';
$lang->repo->product = 'Product';
$lang->repo->execution = $lang->execution->common;
$lang->repo->create = 'Create';
$lang->repo->maintain = 'Repo List';
$lang->repo->edit = 'Edit';
+1
View File
@@ -3,6 +3,7 @@ $lang->repo->common = 'Référentiel';
$lang->repo->browse = 'Aff';
$lang->repo->viewRevision = 'Aff Modifs';
$lang->repo->product = 'Product';
$lang->repo->execution = $lang->execution->common;
$lang->repo->create = 'Créer';
$lang->repo->createAction = 'Créer Ref';
$lang->repo->maintain = 'Liste Ref';
+1
View File
@@ -3,6 +3,7 @@ $lang->repo->common = 'Repo';
$lang->repo->browse = 'Xem';
$lang->repo->viewRevision = 'Xem Revision';
$lang->repo->product = 'Product';
$lang->repo->execution = $lang->execution->common;
$lang->repo->create = 'Tạo';
$lang->repo->createAction = 'Tạo Repo';
$lang->repo->maintain = 'Repo danh sách';
+1 -1
View File
@@ -3,7 +3,7 @@ $lang->repo->common = '代码';
$lang->repo->browse = '浏览';
$lang->repo->viewRevision = '查看修订';
$lang->repo->product = '所属产品';
$lang->repo->execution = '所属' . $lang->executionCommon;
$lang->repo->execution = '所属' . $lang->execution->common;
$lang->repo->create = '创建';
$lang->repo->maintain = '版本库列表';
$lang->repo->edit = '编辑';
+1
View File
@@ -237,6 +237,7 @@ class repoModel extends model
$data = fixer::input('post')
->setIf($this->post->SCM == 'Gitlab', 'password', $this->post->gitlabToken)
->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost)
->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->gitlabProject)
->skipSpecial('path,client,account,password')
->setDefault('product', '')
->join('product', ',')
+3 -3
View File
@@ -20,7 +20,7 @@ if(isset($entry)) $pathInfo .= '&type=file';
<tr>
<th class='w-40px'></th>
<th class='w-80px'><?php echo $lang->repo->revisionA?></th>
<?php if($repo->SCM == 'Git'):?>
<?php if($repo->SCM != 'Subversion'):?>
<th class='w-70px'><?php echo $lang->repo->commit?></th>
<?php endif;?>
<th class='w-80px'><?php echo $lang->repo->time?></th>
@@ -37,8 +37,8 @@ if(isset($entry)) $pathInfo .= '&type=file';
<label></label>
</div>
</td>
<td class='versions'><span class="revision"><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$log->revision}" . $pathInfo), $repo->SCM == 'Git' ? substr($log->revision, 0, 10) : $log->revision, '', "data-app='{$this->app->openApp}'");?></span></td>
<?php if($repo->SCM == 'Git'):?>
<td class='versions'><span class="revision"><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision={$log->revision}" . $pathInfo), $repo->SCM != 'Subversion' ? substr($log->revision, 0, 10) : $log->revision, '', "data-app='{$this->app->openApp}'");?></span></td>
<?php if($repo->SCM != 'Subversion'):?>
<td><?php echo $log->commit?></td>
<?php endif;?>
<td><?php echo substr($log->time, 0, 10);?></td>
+3 -3
View File
@@ -69,7 +69,7 @@ css::import($jsRoot . 'misc/highlight/styles/github.css');
<thead>
<tr>
<td class='w-70px'><?php echo $lang->repo->revision?></td>
<?php if($repo->SCM == 'Git'):?>
<?php if($repo->SCM != 'Subversion'):?>
<td class='w-50px'><?php echo $lang->repo->commit?></td>
<?php endif;?>
<td class='w-100px'><?php echo $lang->repo->committer?></td>
@@ -85,9 +85,9 @@ css::import($jsRoot . 'misc/highlight/styles/github.css');
{
$rowspan = $blame['lines'];
echo '<td rowspan="' . $rowspan . '" class="info" title="' . $blame['revision'] . '">';
echo $repo->SCM == 'Git' ? substr($blame['revision'], 0, 10) : $blame['revision'];
echo $repo->SCM != 'Subversion' ? substr($blame['revision'], 0, 10) : $blame['revision'];
echo '</td>';
if($repo->SCM == 'Git') echo '<td rowspan="' . $rowspan . '" class="info">' . zget($historys, $blame['revision'], '') . '</td>';
if($repo->SCM != 'Subversion') echo '<td rowspan="' . $rowspan . '" class="info">' . zget($historys, $blame['revision'], '') . '</td>';
echo '<td rowspan="' . $rowspan . '" class="info">' . $blame['committer'] . '</td>';
}
?>
+1 -1
View File
@@ -84,7 +84,7 @@
echo html::a($link, $info->name, '', "title='{$info->name}' data-app={$app->openApp}");
?>
</td>
<td align='center'><?php echo $repo->SCM == 'Git' ? substr($info->revision, 0, 10) : $info->revision;?></td>
<td align='center'><?php echo $repo->SCM == 'Subversion' ? $info->revision : substr($info->revision, 0, 10);?></td>
<td><?php echo substr($info->date, 0, 10)?></td>
<td><?php echo $info->committer?></td>
<?php $comment = htmlspecialchars($info->comment, ENT_QUOTES);?>
+4 -4
View File
@@ -29,7 +29,7 @@
<div class="page-title">
<?php
echo html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=&objectID=$objectID"), $repo->name, '', "data-app='{$app->openApp}'");
$paths= explode('/', $entry);
$paths = explode('/', $entry);
$fileName = array_pop($paths);
$postPath = '';
foreach($paths as $pathName)
@@ -38,10 +38,10 @@
echo '/' . ' ' . html::a($this->repo->createLink('browse', "repoID=$repoID&branchID=$branchID&objectID=$objectID&path=" . $this->repo->encodePath($postPath)), trim($pathName, '/'), '', "data-app='{$app->openApp}'");
}
echo '/' . ' ' . $fileName;
if(strpos($repo->SCM, 'Git') !== false)
if(strpos($repo->SCM, 'Subversion') === false)
{
$oldRevision = $oldRevision == '^' ? "$newRevision" : $oldRevision;
echo " <span class='label label-info'>" . substr($oldRevision, 0, 10) . " : " . substr($newRevision, 0, 10) . ' (' . $historys[$oldRevision] . ' : ' . $historys[$newRevision] . ')</span>';
echo " <span class='label label-info'>" . substr($oldRevision, 0, 10) . " : " . substr($newRevision, 0, 10) . ' (' . zget($historys, $oldRevision, '') . ' : ' . zget($historys, $newRevision, '') . ')</span>';
}
else
{
@@ -155,7 +155,7 @@
</div>
<div class='revisions hidden'>
<?php
if(strpos($repo->SCM, 'Git') !== false)
if(strpos($repo->SCM, 'Subversion') === false)
{
$oldRevision = $oldRevision == '^' ? "$newRevision" : $oldRevision;
echo " <span class='label label-info'>" . substr($oldRevision, 0, 10) . " : " . substr($newRevision, 0, 10) . ' (' . $historys[$oldRevision] . ' : ' . $historys[$newRevision] . ')</span>';
+1 -1
View File
@@ -48,7 +48,7 @@
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabProject;?></th>
<td><?php echo html::select('gitlabProject', $projects, '', "class='form-control chosen'");?>
<td><?php echo html::select('gitlabProject', $projects, $repo->extra, "class='form-control chosen'");?>
</tr>
<tr>
<th><?php echo $lang->repo->name; ?></th>
+2 -2
View File
@@ -53,7 +53,7 @@
<tr>
<th class='w-40px'></th>
<th class='w-110px'><?php echo $lang->repo->revision?></th>
<?php if($repo->SCM == 'Git'):?>
<?php if($repo->SCM != 'Subversion'):?>
<th class='w-90px'><?php echo $lang->repo->commit?></th>
<?php endif;?>
<th class='w-150px'><?php echo $lang->repo->date?></th>
@@ -71,7 +71,7 @@
</div>
</td>
<td class='versions'><?php echo html::a($this->repo->createLink('revision', "repoID=$repoID&objectID=$objectID&revision=" . $log->revision), substr($log->revision, 0, 10), '', "data-app='{$app->openApp}'");?></td>
<?php if($repo->SCM == 'Git'):?>
<?php if($repo->SCM != 'Subversion'):?>
<td><?php echo $log->commit?></td>
<?php endif;?>
<td><?php echo $log->time;?></td>
+3 -3
View File
@@ -20,10 +20,10 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php $browseLink = $app->session->revisionList != false ? $app->session->revisionList : $this->repo->createLink('browse', "repoID={$repoID}&branchID=$branchID&objectID=$objectID{$preDir}");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i>" . $lang->goback, '', "class='btn btn-link' data-app='{$app->openApp}'");?>
<?php echo html::a($browseLink, "<i class='icon icon-back'></i>" . $lang->goback, '', "class='btn btn-link'");?>
<div class="divider"></div>
<div class="page-title">
<?php echo $lang->repo->revisionA . ' ' . ($repo->SCM == 'Git' ? $this->repo->getGitRevisionName($revision, $log->commit) : $revision);?>
<?php echo $lang->repo->revisionA . ' ' . ($repo->SCM == 'Subversion' ? $revision : $this->repo->getGitRevisionName($revision, $log->commit));?>
</div>
</div>
</div>
@@ -63,7 +63,7 @@ $typeInfo = $type == 'file' ? '&type=file' : '';
<th><?php echo $lang->repo->revisionA?></th>
<td><?php echo $log->revision?></td>
</tr>
<?php if($repo->SCM == 'Git'):?>
<?php if($repo->SCM != 'Subversion'):?>
<tr>
<th><?php echo $lang->repo->commit?></th>
<td><?php echo $log->commit?></td>
+1 -1
View File
@@ -1015,7 +1015,7 @@ class searchModel extends model
while(true)
{
$query = $this->buildIndexQuery($module);
$dataList = $query->beginIF($lastID)->andWhere('t1.id')->gt($lastID)->fi()->limit($limit)->fetchAll('id');
$dataList = $query->beginIF($lastID)->andWhere('t1.id')->gt($lastID)->fi()->orderBy('t1.id')->limit($limit)->fetchAll('id');
if(empty($dataList))
{
$lastID = 0;
+15 -8
View File
@@ -1195,18 +1195,25 @@ class story extends control
$this->view->position[] = html::a($this->createLink('execution', 'story', "executionID=$execution->id"), $execution->name);
$this->view->title = $execution->name . $this->lang->colon . $this->lang->story->batchClose;
}
/* The stories of my. */
else
{
$this->lang->story->menu = $this->lang->my->menu;
$this->lang->story->menuOrder = $this->lang->my->menuOrder;
$this->loadModel('my')->setMenu();
if($this->app->openApp == 'project')
{
$this->project->setMenu($this->session->project);
$this->view->title = $this->lang->story->batchEdit;
}
else
{
$this->lang->story->menu = $this->lang->my->menu;
$this->lang->story->menuOrder = $this->lang->my->menuOrder;
$this->loadModel('my')->setMenu();
if($from == 'work') $this->lang->my->menu->work['subModule'] = 'story';
if($from == 'contribute') $this->lang->my->menu->contribute['subModule'] = 'story';
if($from == 'work') $this->lang->my->menu->work['subModule'] = 'story';
if($from == 'contribute') $this->lang->my->menu->contribute['subModule'] = 'story';
$this->view->position[] = html::a($this->createLink('my', 'story'), $this->lang->my->story);
$this->view->title = $this->lang->story->batchEdit;
$this->view->position[] = html::a($this->createLink('my', 'story'), $this->lang->my->story);
$this->view->title = $this->lang->story->batchEdit;
}
}
/* Judge whether the editedStories is too large and set session. */
+5 -1
View File
@@ -3337,6 +3337,10 @@ class storyModel extends model
}
}
}
else if($id == 'actions')
{
$class .= ' text-center';
}
echo "<td class='" . $class . "' title='$title' style='$style'>";
if(isset($this->config->bizVersion)) $this->loadModel('flow')->printFlowCell('story', $story, $id);
@@ -3484,7 +3488,7 @@ class storyModel extends model
common::printIcon('story', 'review', $vars . "&from=$story->from", $story, 'list', 'search', '', '', false, "data-group=$story->from");
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
if($story->type != 'requirement') common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
common::printIcon('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&storyID=$story->id", $story, 'list', 'split', '', '', '', '', $this->lang->story->subdivide);
if($this->app->rawModule == 'projectstory') common::printIcon('projectstory', 'unlinkStory', "projectID={$this->session->project}&storyID=$story->id", '', 'list', 'unlink', 'hiddenwin');
}
+1 -1
View File
@@ -84,7 +84,7 @@ var assignedTo = '<?php $story->lastEditedBy ? print($story->lastEditedBy) : pri
<tr>
<td colspan='3' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php if(!isonlybody()) echo html::linkButton($lang->goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id"), 'self', '', 'btn btn-wide');?>
<?php if(!isonlybody()) echo html::a($app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id"), $lang->goback, '', 'class="btn btn-wide"');?>
</td>
</tr>
</table>
+1 -1
View File
@@ -31,7 +31,7 @@
<?php echo html::a('javascript:;', "<i class='icon icon-product'></i>". $projectProducts[$productID]->name . '<span class="caret"></span>', '', 'class="dropdown-toggle" data-toggle="dropdown"');?>
<ul class="dropdown-menu">
<?php foreach($projectProducts as $product): ?>
<li><?php echo html::a($this->createLink('projectstory', 'track', "productID=$product->id"), $product->name);?></li>
<li><?php echo html::a($this->createLink('projectstory', 'track', "projectID={$this->session->project}&productID=$product->id"), $product->name);?></li>
<?php endforeach;?>
</ul>
</div>
+1 -1
View File
@@ -78,7 +78,7 @@
common::printIcon('story', 'change', $vars, $story, 'list', 'fork');
common::printIcon('story', 'review', $vars, $story, 'list', 'glasses');
common::printIcon('story', 'close', $vars, $story, 'list', 'off', '', 'iframe', 'yes');
common::printIcon('story', 'edit', $vars, $story, 'list', 'pencil');
common::printIcon('story', 'edit', $vars, $story, 'list');
$this->app->openApp = 'qa';
common::printIcon('story', 'createCase', "productID=$story->product&branch=0&module=0&from=&param=0&$vars", $story, 'list', 'sitemap');
?>
+1 -1
View File
@@ -677,7 +677,7 @@ class task extends control
/* Set menu. */
$execution = $this->execution->getById($task->execution);
$this->execution->setMenu($execution->id);
if($this->app->openApp == 'execution') $this->execution->setMenu($execution->id);
$this->executeHooks($taskID);
+6 -5
View File
@@ -617,8 +617,6 @@ class testcase extends control
}
}
$product = $this->product->getByID($case->product);
$branches = $product->type == 'normal' ? array() : $this->loadModel('branch')->getPairs($case->product);
$isLibCase = ($case->lib and empty($case->product));
if($isLibCase)
{
@@ -633,6 +631,9 @@ class testcase extends control
else
{
$productID = $case->product;
$product = $this->product->getByID($productID);
$branches = $product->type == 'normal' ? array() : $this->loadModel('branch')->getPairs($productID);
if($this->app->openApp == 'project') $this->loadModel('project')->setMenu($this->session->project);
if($this->app->openApp == 'execution') $this->loadModel('execution')->setMenu($this->session->execution);
if($this->app->openApp == 'qa') $this->testcase->setMenu($this->products, $productID, $case->branch);
@@ -640,6 +641,8 @@ class testcase extends control
$this->view->title = "CASE #$case->id $case->title - " . $this->products[$productID];
$this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]);
$this->view->product = $product;
$this->view->branches = $branches;
$this->view->productName = $this->products[$productID];
$this->view->branchName = $product->type == 'normal' ? '' : zget($branches, $case->branch, '');
}
@@ -659,7 +662,6 @@ class testcase extends control
$this->view->case = $case;
$this->view->from = $from;
$this->view->taskID = $taskID;
$this->view->product = $product;
$this->view->version = $version ? $version : $case->version;
$this->view->modulePath = $this->tree->getParents($case->module);
$this->view->caseModule = empty($case->module) ? '' : $this->tree->getById($case->module);
@@ -669,7 +671,6 @@ class testcase extends control
$this->view->runID = $from == 'testcase' ? 0 : $run->id;
$this->view->isLibCase = $isLibCase;
$this->view->caseFails = $caseFails;
$this->view->branches = $branches;
$this->display();
}
@@ -1522,7 +1523,7 @@ class testcase extends control
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
helper::saveFile($file['tmpname'], $fileName);
move_uploaded_file($file['tmpname'], $fileName);
$rows = $this->file->parseCSV($fileName);
$fields = $this->testcase->getImportFields($productID);
+1 -1
View File
@@ -541,7 +541,7 @@ class testcaseModel extends model
->andWhere('t2.deleted')->eq(0)
->beginIF($auto != 'skip' and $auto != 'unit')->andWhere('t2.auto')->ne('unit')->fi()
->beginIF($auto == 'unit')->andWhere('t2.auto')->eq('unit')->fi()
->orderBy($orderBy)->page($pager)->fetchAll();
->orderBy($orderBy)->page($pager)->fetchAll('id');
}
/**
+1 -1
View File
@@ -54,7 +54,7 @@ js::set('suiteID', $suiteID);
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->testcase->noCase;?></span>
<?php if(common::canModify('product', $product) and common::hasPriv('testcase', 'create') and $browseType != 'bysuite'):?>
<?php if((empty($productID) or common::canModify('product', $product)) and common::hasPriv('testcase', 'create') and $browseType != 'bysuite'):?>
<?php $initModule = isset($moduleID) ? (int)$moduleID : 0;?>
<?php echo html::a($this->createLink('testcase', 'create', "productID=$productID&branch=$branch&moduleID=$initModule"), "<i class='icon icon-plus'></i> " . $lang->testcase->create, '', "class='btn btn-info' data-app='{$this->app->openApp}'");?>
<?php endif;?>
+3 -3
View File
@@ -61,7 +61,7 @@
echo "<div id='bysuiteTab' class='btn-group'>";
echo html::a('javascript:;', "<span class='text'>{$currentLable}</span>" . " <span class='caret'></span>", '', "class='btn btn-link' data-toggle='dropdown'");
if(common::canModify('product', $product))
if(empty($productID) or common::canModify('product', $product))
{
echo "<ul class='dropdown-menu' style='max-height:240px; overflow-y:auto'>";
@@ -130,7 +130,7 @@
</ul>
</div>
<?php endif;?>
<?php if(common::canModify('product', $product)):?>
<?php if(empty($productID) or common::canModify('product', $product)):?>
<?php if(!empty($productID)): ?>
<div class='btn-group'>
<button type='button' class='btn btn-link dropdown-toggle' data-toggle='dropdown' id='importAction'><i class='icon icon-import muted'></i> <?php echo $lang->import ?><span class='caret'></span></button>
@@ -180,7 +180,7 @@
</ul>
<?php endif;?>
</div>
<?php if($this->app->rawMethod == 'browseunits' and common::canModify('product', $product)):?>
<?php if($this->app->rawMethod == 'browseunits' and (empty($productID) or common::canModify('product', $product))):?>
<?php common::printLink('testtask', 'importUnitResult', "product=$productID", "<i class='icon icon-import'></i> " . $lang->testtask->importUnitResult, '', "class='btn btn-primary' data-app='{$this->app->openApp}'");?>
<?php endif;?>
<?php else:?>
+4 -1
View File
@@ -11,6 +11,7 @@
*/
?>
<?php include '../../common/view/header.lite.html.php';?>
<?php js::set('openApp', $app->openApp);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->testcase->createBug;?></h2>
@@ -30,7 +31,9 @@ function createBug(obj)
var onlybody = config.onlybody;
config.onlybody = 'no';
window.open(createLink('bug', 'create', params + ',stepIdList=' + stepIdList), '_parent');
var link = createLink('bug', 'create', params + ',stepIdList=' + stepIdList);
if(openApp == 'my') window.parent.$.apps.open(link, 'qa')
window.open(link, '_parent');
config.onlybody = onlybody;
}
+1 -1
View File
@@ -92,7 +92,7 @@
<td><?php echo $case->stepNumber;?></td>
<td class='c-actions'>
<?php common::printIcon('testcase', 'edit', "caseID=$case->id", $case, 'list');?>
<?php common::printIcon('testcase', 'delete', "caseID=$case->id", $case, 'list', '', 'hiddenwin');?>
<?php common::printIcon('testcase', 'delete', "caseID=$case->id", $case, 'list', 'trash', 'hiddenwin');?>
</td>
</tr>
<?php $i++;?>
+2 -1
View File
@@ -202,7 +202,8 @@
<td>
<?php
$class = isonlybody() ? 'showinonlybody' : 'iframe';
if(isset($case->storyTitle)) echo html::a($this->createLink('story', 'view', "storyID=$case->story", '', true), "#$case->story:$case->storyTitle", '', "class=$class data-width='80%'");
$param = $this->app->openApp == 'project' ? "&version=0&projectID={$this->session->project}" : '';
if(isset($case->storyTitle)) echo html::a($this->createLink('story', 'view', "storyID=$case->story" . $param, '', true), "#$case->story:$case->storyTitle", '', "class=$class data-width='80%'");
if($case->story and $case->storyStatus == 'active' and $case->latestStoryVersion > $case->storyVersion)
{
echo "(<span class='warning'>{$lang->story->changed}</span> ";
+12
View File
@@ -260,6 +260,18 @@ class testreport extends control
die(js::locate('back'));
}
if($this->app->openApp == 'qa')
{
$productID = $this->product->saveState(key($productIdList), $this->products);
$this->loadModel('qa')->setMenu($this->products, $productID);
}
elseif($this->app->openApp == 'project')
{
$projects = $this->project->getPairsByProgram();
$projectID = $this->project->saveState($execution->project, $projects);
$this->project->setMenu($projectID);
}
$builds = $this->build->getByList($buildIdList);
$stories = !empty($builds) ? $this->testreport->getStories4Test($builds) : $this->story->getExecutionStories($execution->id);;
+2 -1
View File
@@ -116,7 +116,8 @@
<?php
if(common::canBeChanged('report', $report))
{
if(common::hasPriv('testreport', 'create')) echo html::a(inLink('create', "objectID=$report->objectID&objectType=$report->objectType&extra=$report->id"), "<i class='icon-refresh'></i>", '', "class='btn' title='{$lang->testreport->recreate}' data-app='{$this->app->openApp}'");
$extra = $report->objectType == 'execution' ? "&extra=$report->tasks" : '';
if(common::hasPriv('testreport', 'create')) echo html::a(inLink('create', "objectID=$report->objectID&objectType=$report->objectType" . $extra), "<i class='icon-refresh'></i>", '', "class='btn' title='{$lang->testreport->recreate}' data-app='{$this->app->openApp}'");
common::printIcon('testreport', 'edit', "reportID=$report->id", '', 'button');
common::printIcon('testreport', 'delete', "reportID=$report->id", '', 'button', 'trash', 'hiddenwin');
}
+1 -1
View File
@@ -100,7 +100,7 @@ class testtask extends control
/* Set menu. */
$productID = $this->product->saveState($productID, $this->products);
if($branch === '') $branch = (int)$this->cookie->preBranch;
$this->loadModel('qa')->setMenu($this->products, $productID, $branch);
$this->loadModel('qa')->setMenu($this->products, $productID, $branch, $type);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
+1 -1
View File
@@ -1628,7 +1628,7 @@ class testtaskModel extends model
$file = $file[0];
$fileName = $this->file->savePath . $this->file->getSaveName($file['pathname']);
helper::saveFile($file['tmpname'], $fileName);
move_uploaded_file($file['tmpname'], $fileName);
if(simplexml_load_file($fileName) === false)
{
dao::$errors[] = $this->lang->testtask->cannotBeParsed;
+8 -2
View File
@@ -279,8 +279,11 @@ class todo extends control
{
$confirmNote = 'confirm' . ucfirst($todo->type);
$confirmURL = $this->createLink($todo->type, 'view', "id=$todo->idvalue");
if($todo->type == 'bug') $app = 'qa';
if($todo->type == 'task') $app = 'execution';
if($todo->type == 'story') $app = 'product';
$cancelURL = $this->server->HTTP_REFERER;
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'parent', 'parent'));
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'window.parent.$.apps.open', 'parent', $app));
}
if(isonlybody())die(js::reload('parent.parent'));
die(js::reload('parent'));
@@ -446,8 +449,11 @@ class todo extends control
{
$confirmNote = 'confirm' . ucfirst($todo->type);
$confirmURL = $this->createLink($todo->type, 'view', "id=$todo->idvalue");
if($todo->type == 'bug') $app = 'qa';
if($todo->type == 'task') $app = 'execution';
if($todo->type == 'story') $app = 'product';
$cancelURL = $this->server->HTTP_REFERER;
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'parent', 'parent'));
die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'window.parent.$.apps.open', 'parent', $app));
}
if(isonlybody())die(js::reload('parent.parent'));
die(js::reload('parent'));
+5 -1
View File
@@ -53,8 +53,12 @@ function loadList(type, id)
{
link = createLink('review', 'ajaxGetUserReviews', param);
}
else if(type == 'feedback')
{
link = createLink('feedback', 'ajaxGetUserFeedback', param);
}
if(type == 'bug' || type == 'task' || type == 'story' || type == 'issue' || type == 'risk' || type == 'testtask' || type == 'review' )
if(type == 'bug' || type == 'task' || type == 'story' || type == 'issue' || type == 'risk' || type == 'testtask' || type == 'review' || type == 'feedback')
{
$.get(link, function(data, status)
{
-1
View File
@@ -83,7 +83,6 @@ class tree extends control
/* Set menu.*/
$products = $this->product->getPairs();
$this->product->saveState($rootID, $products);
$this->product->setMenu($rootID, 0, 0, '', $viewType);
unset($products[$rootID]);
$currentProduct = key($products);
+2 -2
View File
@@ -1475,7 +1475,7 @@ class upgradeModel extends model
$this->saveLogs('Run Method ' . __FUNCTION__);
$mysqlVersion = $this->loadModel('install')->getMysqlVersion();
$ignoreCode = '|1050|1060|1091|1061|';
$ignoreCode = '|1050|1054|1060|1091|1061|';
/* Read the sql file to lines, remove the comment lines, then join theme by ';'. */
$sqls = explode("\n", file_get_contents($sqlFile));
@@ -4304,7 +4304,7 @@ class upgradeModel extends model
$lib->name = $this->lang->doclib->main['project'];
$lib->type = 'project';
$lib->main = '1';
$lib->acl = 'default';
$lib->acl = $project->acl;
$this->dao->insert(TABLE_DOCLIB)->data($lib)->exec();
$this->loadModel('action')->create('project', $projectID, 'openedbysystem');
+15 -2
View File
@@ -765,12 +765,25 @@ class user extends control
*/
public function login($referer = '', $from = '')
{
/* Check if you can operating on the folder. */
$canModifyDIR = true;
if($this->user->checkTmp() === false)
{
$canModifyDIR = false;
$floderPath = $this->app->tmpRoot;
}
elseif(!is_dir($this->app->dataRoot) or substr(base_convert(@fileperms($this->app->dataRoot),10,8),-4) != '0777')
{
$canModifyDIR = false;
$floderPath = $this->app->dataRoot;
}
if(!$canModifyDIR)
{
echo "<html><head><meta charset='utf-8'></head>";
echo "<body><table align='center' style='width:700px; margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td style='padding:8px'>";
echo "<div style='margin-bottom:8px;'>不能创建临时目录,请确认目录<strong style='color:#ed980f'>{$this->app->tmpRoot}</strong>是否存在并有操作权限。</div>";
echo "<div>Can't create tmp directory, make sure the directory <strong style='color:#ed980f'>{$this->app->tmpRoot}</strong> exists and has permission to operate.</div>";
echo "<div style='margin-bottom:8px;'>不能创建临时目录,请确认目录<strong style='color:#ed980f'>{$floderPath}</strong>是否存在并有操作权限。</div>";
echo "<div>Can't create tmp directory, make sure the directory <strong style='color:#ed980f'>{$floderPath}</strong> exists and has permission to operate.</div>";
die("</td></tr></table></body></html>");
}
$this->setReferer($referer);