Merge branch '15.0.beta3' of https://gitlab.zcorp.cc/easycorp/zentaopms into 15.0.beta3
This commit is contained in:
+3
-2
@@ -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
@@ -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`;
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
$methodName = 'view';
|
||||
if($module == 'caselib')
|
||||
{
|
||||
$methodName = 'libview';
|
||||
$module = 'testsuite';
|
||||
$methodName = 'view';
|
||||
$module = 'caselib';
|
||||
}
|
||||
if(isset($config->action->customFlows[$action->objectType]))
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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¶m=0&orderBy=id_desc");
|
||||
$location = $this->createLink('bug', 'browse', "productID={$this->post->product}&branch=$branch&browseType=byModule¶m={$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)
|
||||
{
|
||||
|
||||
@@ -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>';
|
||||
|
||||
@@ -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 = '相关任务';
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -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})";
|
||||
|
||||
@@ -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})";
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}());
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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=¶m=0&$vars", $story, 'list', 'sitemap');
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
|
||||
@@ -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}¶m=$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);
|
||||
|
||||
@@ -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)'"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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}";
|
||||
|
||||
@@ -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}";
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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>";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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'");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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 = '编辑';
|
||||
|
||||
@@ -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', ',')
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>';
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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);?>
|
||||
|
||||
@@ -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>';
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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=¶m=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=¶m=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');
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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=¶m=0&$vars", $story, 'list', 'sitemap');
|
||||
?>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;?>
|
||||
|
||||
@@ -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:?>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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++;?>
|
||||
|
||||
@@ -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> ";
|
||||
|
||||
@@ -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);;
|
||||
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'));
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user