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

This commit is contained in:
wangyidong
2021-04-15 09:35:00 +08:00
82 changed files with 994 additions and 819 deletions
+1 -1
View File
@@ -1 +1 @@
15.0.rc2
15.0.rc3
+1 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '15.0.rc2'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '15.0.rc3'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
$config->timezone = 'Asia/Shanghai'; // 时区设置。 The time zone setting, for more see http://www.php.net/manual/en/timezones.php.
+1 -1
View File
@@ -4181,7 +4181,7 @@ REPLACE INTO `zt_lang` (`lang`, `module`, `section`, `key`, `value`, `system`) V
('en', 'custom', 'URSRList', '1', '{\"SRName\":\"Story\",\"URName\":\"Epic\"}', '0'),
('en', 'custom', 'URSRList', '2', '{\"SRName\":\"Story\",\"URName\":\"Requirement\"}', '0');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'custom', '', 'hourPoint', '1');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'custom', '', 'hourPoint', '0');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'common', '', 'CRProduct', '1');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'common', '', 'CRExecution', '1');
INSERT INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'custom', '', 'URSR', '2');
-16
View File
@@ -886,22 +886,6 @@ class baseRouter
}
}
/**
* 保存openApp到cookie,下次请求使用,常用在locate, reload方法。
* Save openApp to cookie, use it next visit, when locate, reload page.
*
* @access public
* @return void
*/
public function saveOpenApp()
{
$module = $this->rawModule;
if(isset($this->lang->navGroup->$module) and $this->lang->navGroup->$module != $this->openApp)
{
setCookie('openApp', $this->openApp);
}
}
/**
* 根据用户浏览器的语言设置和服务器配置,选择显示的语言。
* 优先级:$lang参数 > session > cookie > 浏览器 > 配置文件。
+655
View File
@@ -0,0 +1,655 @@
<?php
class gitlab
{
public $client;
public $projectID;
/**
* 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
* @access public
* @return void
*/
public function __construct($client, $root, $username, $password, $encoding = 'UTF-8')
{
$this->client = $client;
$this->root = rtrim($root, '/') . '/';
$this->token = $password;
$this->branch = isset($_COOKIE['repoBranch']) ? $_COOKIE['repoBranch'] : '';
}
/**
* List files.
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function ls($path, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return array();
$api = "tree";
$param = new stdclass();
$param->path = urlencode(ltrim($path, '/'));
$param->ref = $revision;
$param->recursive = 0;
$list = $this->fetch($api, $param);
if(empty($list)) return array();
$infos = array();
foreach($list as $file)
{
$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];
$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;
}
$infos[] = $info;
unset($info);
}
/* Sort by kind */
foreach($infos as $key => $info) $kinds[$key] = $info->kind;
if($infos) array_multisort($kinds, SORT_ASC, $infos);
return $infos;
}
/**
* 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);
$commits = $this->getCommitsByPath($path);
$file->revision = $file->commit_id;
$file->size = $this->formatBytes($file->size);
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));
}
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;
}
/**
* 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);
return $branches;
}
/**
* Get last log.
*
* @param string $path
* @param int $count
* @access public
* @return array
*/
public function getLastLog($path, $count = 10)
{
return $this->log($path);
}
/**
* Get logs.
*
* @param string $path
* @param string $fromRevision
* @param string $toRevision
* @param int $count
* @access public
* @return array
*/
public function log($path, $fromRevision = 0, $toRevision = 'HEAD', $count = 0)
{
if(!scm::checkRevision($fromRevision)) return array();
if(!scm::checkRevision($toRevision)) return array();
$path = ltrim($path, DIRECTORY_SEPARATOR);
$count = $count == 0 ? '' : "-n $count";
$list = $this->getCommitsByPath($path, $fromRevision, $toRevision);
foreach($list as $commit) $commit->diffs = $this->getFilesByCommit($commit->id);
return $this->parseLog($list);
}
/**
* Blame file
*
* @param string $path
* @param string $revision
* @access public
* @return array
*/
public function blame($path, $revision)
{
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;
$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);
$blames[] = $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
* @access public
* @return array
*/
public function diff($path, $fromRevision, $toRevision)
{
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);
foreach($results->diffs as $key => $diff)
{
if($path != '' and strpos($diff->new_path, $path) === false) unset($results->diffs[$key]);
}
return $results->diffs;
}
/**
* Cat file.
*
* @param string $entry
* @param string $revision
* @access public
* @return string
*/
public function cat($entry, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return false;
$file = $this->files($entry, $revision);
return base64_decode($file->content);
}
/**
* Get info.
*
* @param string $entry
* @param string $revision
* @access public
* @return object
*/
public function info($entry, $revision = 'HEAD')
{
if(!scm::checkRevision($revision)) return false;
$info = new stdclass();
$info->kind = 'dir';
$info->path = $entry;
$info->root = '';
if($entry)
{
$parent = dirname($entry);
if($parent == '.') $parent = '/';
if($parent == '') $parent = '/';
$list = $this->tree($parent, 0);
foreach($list as $node) if($node->path == $entry) $file = $node;
$commits = $this->getCommitsByPath($entry);
if(!empty($commits)) $file->revision = zget($commits[0], 'id', '');
$info->kind = $file->type == 'tree' ? 'dir' : 'file';
}
return $info;
}
/**
* Exec git 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');
}
/**
* Parse diff.
*
* @param array $lines
* @access public
* @return array
*/
public function parseDiff($results)
{
if(empty($results)) return array();
foreach($results as $file)
{
$diffFile = new stdclass();
$diffFile->fileName = $file->new_path;
$diff = new stdclass;
$diff->fileName = $file->new_path;
preg_match('/^@@ -(\\d+)(,(\\d+))?\\s+\\+(\\d+)(,(\\d+))?\\s+@@/A', $file->diff, $matches);
if(empty($matches)) continue;
$diff->oldStartLine = $matches[1];
$diff->newStartLine = $matches[4];
$oldCurrentLine = $diff->oldStartLine;
$newCurrentLine = $diff->newStartLine;
if($file->new_file)
{
$oldCurrentLine = $diff->newStartLine;
$newCurrentLine = $diff->oldStartLine;
}
$lines = explode("\n", $file->diff);
$newLines = array();
foreach($lines as $line)
{
if(strpos($line, '@@') === 0) continue;
if(strpos($line, '\ No newline at end of file') === 0) continue;
$sign = empty($line) ? '' : $line[0];
if($sign == '-' and $file->new_file) $sign = '+';
$type = $sign != '-' ? $sign == '+' ? 'new' : 'all' : 'old';
if($sign == '+' or $sign == '-')
{
$line = substr_replace($line, ' ', 1, 0);
if($file->new_file) $line = preg_replace('/^\-/', '+', $line);
}
$newLine = new stdclass();
$newLine->type = $type;
$newLine->oldlc = $type != 'new' ? $oldCurrentLine : '';
$newLine->newlc = $type != 'old' ? $newCurrentLine : '';
$newLine->line = htmlspecialchars($line);
if($type != 'new') $oldCurrentLine++;
if($type != 'old') $newCurrentLine++;
$newLines[] = $newLine;
}
$diffFile->contents[] = $diff;
$diff->lines = $newLines;
$diffs[] = $diffFile;
}
return $diffs;
}
/**
* Get commit count.
*
* @param int $commits
* @param string $lastVersion
* @access public
* @return int
*/
public function getCommitCount($commits = 0, $lastVersion = '')
{
if(!scm::checkRevision($lastVersion)) return false;
chdir($this->root);
$revision = $this->branch ? $this->branch : 'HEAD';
return execCmd(escapeCmd("$this->client rev-list --count $revision -- ./"), 'string');
}
/**
* Get first revision.
*
* @access public
* @return string
*/
public function getFirstRevision()
{
chdir($this->root);
$list = execCmd(escapeCmd("$this->client rev-list --reverse HEAD -- ./"), 'array');
return $list[0];
}
/**
* Get latest revision
*
* @access public
* @return string
*/
public function getLatestRevision()
{
chdir($this->root);
$revision = $this->branch ? $this->branch : 'HEAD';
$list = execCmd(escapeCmd("$this->client rev-list -1 $revision -- ./"), 'array');
return $list[0];
}
/**
* Get commits.
*
* @param string $version
* @param int $count
* @param string $branch
* @access public
* @return array
*/
public function getCommits($version = '', $count = 0, $branch = '')
{
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;
}
$list = $this->fetch($api, $params);
$commits = array();
foreach($list as $commit)
{
$log = new stdclass;
$log->committer = $commit->committer_name;
$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);
}
return array('commits' => $commits, 'files' => $files);
}
/**
* 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);
}
/**
* Get commits by path.
*
* @param string $path
* @access public
* @return array
*/
public function getCommitsByPath($path, $fromRevision = '', $toRevision = '')
{
$path = ltrim($path, DIRECTORY_SEPARATOR);
$api = "commits";
$param = new stdclass();
$param->path = urldecode($path);
$param->ref_name = $this->branch;
if($fromRevision) $fromRevision = $this->getSingleCommit($fromRevision);
if($toRevision) $toRevision = $this->getSingleCommit($toRevision);
if(!$fromRevision) $since = '';
if(!$toRevision) $until = '';
if($fromRevision and $toRevision)
{
$since = min($fromRevision->committed_date, $toRevision->committed_date);
$until = max($fromRevision->committed_date, $toRevision->committed_date);
}
$param->since = $since;
$param->until = $until;
return $this->fetch($api, $param);
}
/**
* Get files by commit.
*
* @param string $commit
* @access public
* @return void
*/
public function getFilesByCommit($revision)
{
if(!scm::checkRevision($revision)) return array();
$api = "commits/{$revision}/diff";
$params = new stdclass;
$params->page = 1;
$params->per_page = 200;
$allResults = array();
while($results = $this->fetch($api, $params))
{
$params->page ++;
$allResults = $allResults + $results;
}
$files = array();
foreach($allResults as $row)
{
$file = new stdclass();
$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';
if($row->deleted_file) $file->action = 'D';
$files[] = $file;
}
return $files;
}
/**
* Repository/tree api.
*
* @param string $path
* @param bool $recursive
* @access public
* @return void
*/
public function tree($path, $recursive = 1)
{
$api = "tree";
$params = array();
$params['path'] = ltrim($path, '/');
$params['ref'] = $this->branch;
$params['recursive'] = (int) $recursive;
return $this->fetch($api, $params);
}
/**
* Fetch data from gitlab api.
*
* @param string $api
* @access public
* @return void
*/
public function fetch($api, $params = array())
{
$params = (array) $params;
$params['private_token'] = $this->token;
$api = ltrim($api, '/');
$api = $this->root . $api . '?' . http_build_query($params);
$response = file_get_contents($api);
return json_decode($response);
}
/**
* Format bytes shown.
*
* @param int $size
* @static
* @access public
* @return string
*/
public static function formatBytes($size)
{
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';
}
/**
* Parse log.
*
* @param array $logs
* @access public
* @return array
*/
public function parseLog($logs)
{
$parsedLogs = array();
$i = 0;
foreach($logs as $commit)
{
$parsedLog = new stdclass();
$parsedLog->revision = $commit->id;
$parsedLog->committer = $commit->committer_name;
$parsedLog->time = date('Y-m-d H:i:s', strtotime($commit->committed_date));
$parsedLog->comment = $commit->message;
$parsedLog->change = array();
foreach($commit->diffs as $diff)
{
$parsedLog->change[$diff->path] = array();
$parsedLog->change[$diff->path]['action'] = $diff->action;
$parsedLog->change[$diff->path]['kind'] = $diff->type;
}
$parsedLogs[] = $parsedLog;
}
return $parsedLogs;
}
}
-1
View File
@@ -431,7 +431,6 @@ $lang->action->dynamicAction->entry['created'] = '添加应用';
$lang->action->dynamicAction->entry['edited'] = '编辑应用';
/* 用来生成相应对象的链接。*/
global $config;
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
$lang->action->label->productplan = "计划|productplan|view|productID=%s";
$lang->action->label->release = '发布|release|view|productID=%s';
+2 -1
View File
@@ -177,11 +177,12 @@ class actionModel extends model
}
/* Only process these object types. */
if(strpos(',story,productplan,release,task,build,bug,case,testtask,doc,', ",{$objectType},") !== false)
if(strpos(',story,productplan,release,task,build,bug,case,testtask,doc,issue,risk,', ",{$objectType},") !== false)
{
if(!isset($this->config->objectTables[$objectType])) return $emptyRecord;
/* Set fields to fetch. */
$fields = '*';
if(strpos('story, productplan, case', $objectType) !== false) $fields = 'product';
if(strpos('build, bug, testtask, doc', $objectType) !== false) $fields = 'product, project, execution';
if($objectType == 'release') $fields = 'product, build';
-5
View File
@@ -11,11 +11,6 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<div class='btn-toolbar pull-left'><?php //common::printAdminSubMenu('system');?></div>
</div>
</div>
<div class="main-row">
<div class='side-col' id='sidebar'>
<div class='cell'>
-3
View File
@@ -11,9 +11,6 @@
*/
?>
<?php include '../../common/view/header.html.php'; ?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left"><?php //common::printAdminSubMenu('sso');?></div>
</div>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
-8
View File
@@ -11,14 +11,6 @@
*/
class automation extends control
{
/**
* Project id.
*
* @var int
* @access public
*/
public $projectID = 0;
/**
* Products.
*
+1 -30
View File
@@ -853,6 +853,7 @@ class block extends control
$this->loadModel('weekly');
$this->app->loadLang('task');
$this->app->loadLang('story');
$this->app->loadLang('bug');
/* Set project status and count. */
$status = isset($this->params->type) ? $this->params->type : 'all';
@@ -975,34 +976,6 @@ class block extends control
$plans[$product] = $plan;
}
/* Get projects. */
$projects = $this->dao->select('t1.product, t2.status, t2.end')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t1.product')->in($productIdList)
->andWhere('t2.deleted')->eq(0)
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->fetchGroup('product');
foreach($projects as $product => $productProjects)
{
$undone= 0;
$done = 0;
$delay = 0;
foreach($productProjects as $project)
{
($project->status == 'done' or $project->status == 'closed') ? $done++ : $undone++;
if($project->status != 'done' && $project->status != 'closed' && $project->status != 'suspended' && $project->end < helper::today()) $delay++;
}
$project = array();
$project['undone'] = $undone;
$project['done'] = $done;
$project['delay'] = $delay;
$project['all'] = count($productProjects);
$projects[$product] = $project;
}
/* Get releases. */
$releases = $this->dao->select('product, status, COUNT(*) AS count')->from(TABLE_RELEASE)
->where('deleted')->eq(0)
@@ -1028,14 +1001,12 @@ class block extends control
{
$product->stories = isset($stories[$productID]) ? $stories[$productID] : 0;
$product->plans = isset($plans[$productID]) ? $plans[$productID] : 0;
$product->projects = isset($projects[$productID]) ? $projects[$productID] : 0;
$product->releases = isset($releases[$productID]) ? $releases[$productID] : 0;
$product->lastRelease = isset($lastReleases[$productID]) ? $lastReleases[$productID] : 0;
}
$this->app->loadLang('story');
$this->app->loadLang('productplan');
$this->app->loadLang('project');
$this->app->loadLang('release');
$this->view->products = $products;
-3
View File
@@ -11,7 +11,6 @@ $(function()
if($blocksList.find('#moduleBlock').val() == 'scrumtest' && $('#paramstype').val() != 'all')
{
console.log($('#paramstype').val());
$titleInput.val(value);
}
else
@@ -19,8 +18,6 @@ $(function()
var lang = config.clientLang;
if(lang.indexOf('zh') >= 0)
{
console.log(preValue, blockTitle);
console.log(blockTitle.indexOf(preValue));
if(blockTitle.indexOf(preValue) >= 0)
{
blockTitle = blockTitle.replace(preValue, value);
-5
View File
@@ -18,12 +18,8 @@ $lang->block->grid = 'Gitter';
$lang->block->color = 'Farbe';
$lang->block->reset = 'Zurücksetzen';
$lang->block->story = 'Story';
$lang->block->bug = 'Bug';
$lang->block->investment = 'Investment';
$lang->block->left = 'Left';
$lang->block->estimate = 'Estimate';
$lang->block->doneBugs = 'Done';
$lang->block->leftBugs = 'Left';
$lang->block->last = 'Last';
$lang->block->account = 'Konto';
@@ -355,7 +351,6 @@ $lang->block->availableBlocks->testtask = 'Testaufgaben';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->availableBlocks->issue = 'My Issues';
global $config;
if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['execution'] = $lang->execution->common;
-5
View File
@@ -18,12 +18,8 @@ $lang->block->grid = 'Position';
$lang->block->color = 'Color';
$lang->block->reset = 'Reset Layout';
$lang->block->story = 'Story';
$lang->block->bug = 'Bug';
$lang->block->investment = 'Investment';
$lang->block->left = 'Left';
$lang->block->estimate = 'Estimate';
$lang->block->doneBugs = 'Done';
$lang->block->leftBugs = 'Left';
$lang->block->last = 'Last';
$lang->block->account = 'Account';
@@ -355,7 +351,6 @@ $lang->block->availableBlocks->testtask = 'Requests';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->availableBlocks->issue = 'My Issues';
global $config;
if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['execution'] = $lang->execution->common;
-5
View File
@@ -18,12 +18,8 @@ $lang->block->grid = 'Position';
$lang->block->color = 'Couleur';
$lang->block->reset = 'Réinit';
$lang->block->story = 'Story';
$lang->block->bug = 'Bug';
$lang->block->investment = 'Investment';
$lang->block->left = 'Left';
$lang->block->estimate = 'Estimate';
$lang->block->doneBugs = 'Done';
$lang->block->leftBugs = 'Left';
$lang->block->last = 'Last';
$lang->block->account = 'Compte';
@@ -355,7 +351,6 @@ $lang->block->availableBlocks->testtask = 'Recettes';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->availableBlocks->issue = 'My Issues';
global $config;
if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['execution'] = $lang->execution->common;
-5
View File
@@ -18,12 +18,8 @@ $lang->block->grid = 'Vị trí';
$lang->block->color = 'Màu';
$lang->block->reset = 'Thiết lập lại giao diện';
$lang->block->story = 'Story';
$lang->block->bug = 'Bug';
$lang->block->investment = 'Investment';
$lang->block->left = 'Left';
$lang->block->estimate = 'Estimate';
$lang->block->doneBugs = 'Done';
$lang->block->leftBugs = 'Left';
$lang->block->last = 'Last';
$lang->block->account = 'Tài khoản';
@@ -355,7 +351,6 @@ $lang->block->availableBlocks->testtask = 'Yêu cầu';
$lang->block->availableBlocks->risk = 'My Risks';
$lang->block->availableBlocks->issue = 'My Issues';
global $config;
if($config->systemMode == 'new') $lang->block->moduleList['project'] = 'Project';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['execution'] = $lang->execution->common;
+5 -10
View File
@@ -18,12 +18,8 @@ $lang->block->grid = '位置';
$lang->block->color = '颜色';
$lang->block->reset = '恢复默认';
$lang->block->story = '需求';
$lang->block->bug = 'Bug';
$lang->block->investment = '投入';
$lang->block->left = '剩余';
$lang->block->estimate = '预计工时';
$lang->block->doneBugs = '已解决';
$lang->block->leftBugs = '未解决';
$lang->block->last = '近期';
$lang->block->account = '所属用户';
@@ -291,11 +287,11 @@ $lang->block->default['full']['my']['3']['params']['count'] = '20';
if($config->systemMode == 'new')
{
$lang->block->default['full']['my']['4']['title'] = '项目统计';
$lang->block->default['full']['my']['4']['block'] = 'statistic';
$lang->block->default['full']['my']['4']['source'] = 'project';
$lang->block->default['full']['my']['4']['grid'] = 8;
$lang->block->default['full']['my']['4']['params']['count'] = '20';
$lang->block->default['full']['my']['4']['title'] = '项目统计';
$lang->block->default['full']['my']['4']['block'] = 'statistic';
$lang->block->default['full']['my']['4']['source'] = 'project';
$lang->block->default['full']['my']['4']['grid'] = 8;
$lang->block->default['full']['my']['4']['params']['count'] = '20';
}
$lang->block->default['full']['my']['5']['title'] = '我的贡献';
@@ -355,7 +351,6 @@ $lang->block->availableBlocks->testtask = '测试版本列表';
$lang->block->availableBlocks->risk = '我的风险';
$lang->block->availableBlocks->issue = '我的问题';
global $config;
if($config->systemMode == 'new') $lang->block->moduleList['project'] = '项目';
$lang->block->moduleList['product'] = $lang->productCommon;
$lang->block->moduleList['execution'] = $lang->execution->common;
@@ -175,10 +175,6 @@ $(function()
</div>
</div>
</div>
<?php $totalProject = $product->projects ? zget($product->projects, 'all', 0) : 0;?>
<?php $undoneProject = $product->projects ? zget($product->projects, 'undone', 0) : 0;?>
<?php $delayProject = $product->projects ? zget($product->projects, 'delay', 0) : 0;?>
<?php $undoneRate = $totalProject ? round($undoneProject / $totalProject * 100, 2) : 0;?>
<div class="product-info">
<?php $totalRelease = $product->releases ? array_sum($product->releases) : 0;?>
<?php $normalRelease = $product->releases ? zget($product->releases, 'normal', 0) : 0;?>
@@ -147,7 +147,7 @@ $(function()
<div class="col data"><?php echo $project->doneStories;?></div>
</div>
<div>
<div class="col dataTitle"><?php echo $lang->block->left . ":";?></div>
<div class="col dataTitle"><?php echo $lang->project->surplus . ":";?></div>
<div class="col data"><?php echo $project->leftStories;?></div>
</div>
</div>
@@ -167,17 +167,17 @@ $(function()
</div>
</div>
<div class="col-4 text-center">
<div><h4><?php echo $lang->block->bug;?></h4></div>
<div><h4><?php echo $lang->bug->common;?></h4></div>
<div>
<div class="col dataTitle"><?php echo $lang->block->totalBug . ":";?></div>
<div class="col data"><?php echo $project->allBugs;?></div>
</div>
<div>
<div class="col dataTitle"><?php echo $lang->block->doneBugs . ":";?></div>
<div class="col dataTitle"><?php echo $lang->bug->statusList['resolved'] . ":";?></div>
<div class="col data"><?php echo $project->doneBugs;?></div>
</div>
<div>
<div class="col dataTitle"><?php echo $lang->block->leftBugs . ":";?></div>
<div class="col dataTitle"><?php echo $lang->bug->unResolved . ":";?></div>
<div class="col data"><?php echo $project->leftBugs;?></div>
</div>
</div>
+6 -1
View File
@@ -509,7 +509,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->products;
$products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed');
$projects = array(0 => '');
if($projectID)
{
@@ -817,6 +817,11 @@ class bug extends control
if($bug->type != $type) unset($this->lang->bug->typeList[$type]);
}
if($this->app->openApp == 'qa')
{
$this->view->products = $this->config->CRProduct ? $this->products : $this->product->getPairs('noclosed');
}
/* Set header and position. */
$this->view->title = $this->lang->bug->edit . "BUG #$bug->id $bug->title - " . $this->products[$productID];
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
+1 -1
View File
@@ -49,7 +49,7 @@
<tr>
<th class='w-50px'><?php echo $lang->idAB;?></th>
<th class='w-110px<?php echo zget($visibleFields, 'type', ' hidden') . zget($requiredFields, 'type', '', ' required');?>'><?php echo $lang->bug->type;?></th>
<th class='w-80px<?php echo zget($visibleFields, 'severity', ' hidden') . zget($requiredFields, 'severity', '', ' required');?>'><?php echo $lang->bug->severityAB;?></th>
<th class='w-80px<?php echo zget($visibleFields, 'severity', ' hidden') . zget($requiredFields, 'severity', '', ' required');?>'><?php echo $lang->bug->severity;?></th>
<th class='w-70px<?php echo zget($visibleFields, 'pri', ' hidden') . zget($requiredFields, 'pri', '', ' required');?>'><?php echo $lang->bug->pri;?></th>
<th class="required <?php if(count($visibleFields) >= 10) echo ' w-150px';?>"><?php echo $lang->bug->title;?></th>
<?php if($branchProduct):?>
+1 -1
View File
@@ -13,7 +13,7 @@
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('sysurl', common::getSysUrl());?>
<?php $browseLink = $app->session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product");?>
<?php $browseLink = $app->session->bugList ? $app->session->bugList : inlink('browse', "productID=$bug->product");?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php if(!isonlybody()):?>
+1 -2
View File
@@ -1,9 +1,8 @@
var executionID = $('#execution').val();
function loadExecutions()
{
var productID = $('#product').val();
var branchID = $('#branch').length > 0 ? $('#branch').val() : 0;
$('#executionsBox').load(createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&executionID=' + executionID + '&branch=' + branchID), function()
$('#executionsBox').load(createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&executionID=0&branch=' + branchID), function()
{
$('#executionsBox #execution').chosen().removeAttr('onchange');
});
-1
View File
@@ -394,7 +394,6 @@ class buildModel extends model
$oldBuild = $this->dao->select('*')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch();
$build = fixer::input('post')->stripTags($this->config->build->editor->edit['id'], $this->config->allowedTags)
->setDefault('product', $oldBuild->product)
->setDefault('branch', $oldBuild->branch)
->cleanInt('product,branch,execution')
->remove('allchecker,resolvedBy,files,labels,uid')
->get();
+1
View File
@@ -154,6 +154,7 @@ $lang->extension->common = 'Extension';
$lang->company->common = 'Company';
$lang->dept->common = 'Dept';
$lang->program->list = 'Program List';
$lang->execution->list = "{$lang->executionCommon} List";
$lang->personnel->common = 'Member';
$lang->personnel->invest = 'Investment';
+4 -4
View File
@@ -226,7 +226,7 @@ $lang->scrum->menu->settings['subMenu']->group = array('link' => "{$lang->
/* Execution menu. */
$lang->execution->homeMenu = new stdclass();
if($config->systemMode == 'new') $lang->execution->homeMenu->index = "$lang->dashboard|execution|index|";
$lang->execution->homeMenu->list = array('link' => "{$lang->executionCommon}列表|execution|all|", 'alias' => 'create,batchedit');
$lang->execution->homeMenu->list = array('link' => "{$lang->execution->list}|execution|all|", 'alias' => 'create,batchedit');
$lang->execution->menu = new stdclass();
$lang->execution->menu->task = array('link' => "{$lang->task->common}|execution|task|executionID=%s", 'subModule' => 'task,tree', 'alias' => 'importtask,importbug');
@@ -330,9 +330,9 @@ $lang->devops->menuOrder[25] = 'rules';
/* Doc menu.*/
$lang->doc->menu = new stdclass();
$lang->doc->menu->dashboard = array('link' => "{$lang->dashboard}|doc|index");
$lang->doc->menu->recent = array('link' => "{$lang->doc->recent}|doc|browse|libID=0&browseTyp=byediteddate", 'alias' => 'recent');
$lang->doc->menu->my = array('link' => "{$lang->doc->my}|doc|browse|libID=0&browseTyp=openedbyme", 'alias' => 'my');
$lang->doc->menu->collect = array('link' => "{$lang->doc->favorite}|doc|browse|libID=0&browseTyp=collectedbyme", 'alias' => 'collect');
$lang->doc->menu->recent = array('link' => "{$lang->doc->recent}|doc|browse|browseTyp=byediteddate", 'alias' => 'recent');
$lang->doc->menu->my = array('link' => "{$lang->doc->my}|doc|browse|browseTyp=openedbyme", 'alias' => 'my');
$lang->doc->menu->collect = array('link' => "{$lang->doc->favorite}|doc|browse|browseTyp=collectedbyme", 'alias' => 'collect');
$lang->doc->menu->product = array('link' => "{$lang->doc->product}|doc|objectLibs|type=product", 'alias' => 'product');
if($config->systemMode == 'new') $lang->doc->menu->project = array('link' => "{$lang->doc->project}|doc|objectLibs|type=project", 'alias' => 'project');
if($config->systemMode == 'classic') $lang->doc->menu->execution = array('link' => "{$lang->doc->execution}|doc|objectLibs|type=execution", 'alias' => 'execution');
+1
View File
@@ -154,6 +154,7 @@ $lang->extension->common = '插件';
$lang->company->common = '公司';
$lang->dept->common = '部门';
$lang->program->list = '项目集列表';
$lang->execution->list = "{$lang->executionCommon}列表";
$lang->personnel->common = '人员';
$lang->personnel->invest = '投入人员';
+1 -1
View File
@@ -84,7 +84,7 @@ $(function()
<?php if($app->moduleName == 'execution' && $app->methodName == 'task'):?>
<tr>
<td><?php echo $lang->datatable->showAllModule;?></td>
<td><?php echo html::radio('showAllModule', $lang->datatable->showAllModuleList, isset($config->project->task->allModule) ? $config->project->task->allModule : 0);?></td>
<td><?php echo html::radio('showAllModule', $lang->datatable->showAllModuleList, isset($config->execution->task->allModule) ? $config->execution->task->allModule : 0);?></td>
</tr>
<?php endif;?>
<tr>
-7
View File
@@ -32,11 +32,4 @@
<?php endif;?>
</div>
</div>
<script>
$(function()
{
$('#mainHeader #navbar li[data-id=model]').removeClass('active');
})
</script>
<?php include '../../common/view/footer.html.php';?>
+8 -197
View File
@@ -26,10 +26,6 @@ class doc extends control
$this->loadModel('product');
$this->loadModel('project');
$this->loadModel('execution');
$this->from = $this->cookie->from ? $this->cookie->from : 'doc';
$this->productID = $this->cookie->product ? $this->cookie->product : '0';
$this->projectID = isset($_GET['project']) ? $_GET['project'] : 0;
if($this->from == 'doc') $this->session->set('project', '');
}
/**
@@ -40,9 +36,6 @@ class doc extends control
*/
public function index()
{
$this->from = 'doc';
setcookie('from', 'doc', $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
$this->session->set('docList', $this->app->getURI(true), 'doc');
$this->app->loadClass('pager', $static = true);
$pager = new pager(0, 5, 1);
@@ -53,9 +46,9 @@ class doc extends control
$this->view->title = $this->lang->doc->common . $this->lang->colon . $this->lang->doc->index;
$this->view->position[] = $this->lang->doc->index;
$this->view->latestEditedDocs = $this->doc->getDocsByBrowseType(0, 'byediteddate', 0, 0, 'editedDate_desc, id_desc', $pager);
$this->view->myDocs = $this->doc->getDocsByBrowseType(0, 'openedbyme', 0, 0, 'addedDate_desc', $pager);
$this->view->collectedDocs = $this->doc->getDocsByBrowseType(0, 'collectedbyme', 0, 0, 'addedDate_desc', $pager);
$this->view->latestEditedDocs = $this->doc->getDocsByBrowseType('byediteddate', 0, 0, 'editedDate_desc, id_desc', $pager);
$this->view->myDocs = $this->doc->getDocsByBrowseType('openedbyme', 0, 0, 'addedDate_desc', $pager);
$this->view->collectedDocs = $this->doc->getDocsByBrowseType('collectedbyme', 0, 0, 'addedDate_desc', $pager);
$this->view->statisticInfo = $this->doc->getStatisticInfo();
$this->view->users = $this->user->getPairs('noletter');
@@ -69,20 +62,15 @@ class doc extends control
* @param string $browseType
* @param int $param
* @param string $orderBy
* @param string $from doc|project|product
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($libID = 0, $browseType = 'all', $param = 0, $orderBy = 'id_desc', $from = 'doc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
public function browse($browseType = 'all', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->session->set('docList', $this->app->getURI(true), 'doc');
$this->from = $from;
setcookie('from', $from, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
$this->loadModel('search');
/* Set browseType.*/
@@ -90,38 +78,8 @@ class doc extends control
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
$moduleID = ($browseType == 'bymodule') ? (int)$param : 0;
$type = '';
$productID = 0;
$executionID = 0;
if($libID)
{
$lib = $this->doc->getLibByID($libID);
$type = $lib->type;
$productID = $lib->product;
$executionID = $lib->execution;
if($type != 'product' and $type != 'execution') $from = 'doc';
}
$this->libs = $this->doc->getLibs($type, '', $libID);
/* According the from, set menus. */
if($from == 'product')
{
$this->product->setMenu($productID);
}
elseif($from == 'project')
{
$this->project->setMenu($lib->project);
}
else
{
$menuType = (!$type && (in_array($browseType, array_keys($this->lang->doc->fastMenuList)) || $browseType == 'bysearch')) ? $browseType : $type;
}
/* Set header and position. */
$this->view->title = $this->lang->doc->common . ($libID ? $this->lang->colon . $this->libs[$libID] : '');
$this->view->position[] = $libID ? $this->libs[$libID] : '';
$this->view->title = $this->lang->doc->common;
/* Load pager. */
$this->app->loadClass('pager', $static = true);
@@ -130,33 +88,8 @@ class doc extends control
/* Append id for secend sort. */
$sort = $this->loadModel('common')->appendOrder($orderBy);
/* Build the search form. */
$actionURL = $this->createLink('doc', 'browse', "lib=$libID&browseType=bySearch&queryID=myQueryID&orderBy=$orderBy");
$this->doc->buildSearchForm($libID, $this->libs, $queryID, $actionURL, $type);
$title = '';
$module = $moduleID ? $this->tree->getByID($moduleID) : '';
if($module) $title = $module->name;
if($libID) $title = html::a(helper::createLink('doc', 'browse', "libID=$libID"), $this->libs[$libID], '');
if(in_array($browseType, array_keys($this->lang->doc->fastMenuList))) $title = $this->lang->doc->fastMenuList[$browseType];
if($browseType == 'bysearch') $title = $this->lang->doc->search;
if($param != 0) $title = $this->doc->buildCrumbTitle($libID, $param, $title);
if($browseType == 'fastsearch')
{
if($this->post->searchDoc) $this->session->set('searchDoc', $this->post->searchDoc);
$title = '"' . $this->session->searchDoc . '" ' . $this->lang->doc->searchResult;
}
else
{
$this->session->set('searchDoc', '');
}
$libs = array();
if($browseType == 'collectedbyme')
{
$libs = $this->doc->getAllLibsByType('collector');
$this->view->itemCounts = $this->doc->statLibCounts(array_keys($libs));
$this->app->rawMethod = 'collect';
}
elseif($browseType == 'openedbyme')
@@ -168,33 +101,13 @@ class doc extends control
$this->app->rawMethod = 'recent';
}
$attachLibs = array();
if(!empty($lib) and (!empty($lib->product) or !empty($lib->execution)) and $browseType != 'bymodule')
{
$count = $this->dao->select('count(*) as count')->from(TABLE_DOCLIB)->where('execution')->eq($lib->execution)->andWhere('product')->eq($lib->product)->fetch('count');
if($count == 1 and $type and isset($lib->$type))
{
$objectLibs = $this->doc->getLibsByObject($type, $lib->$type);
if(isset($objectLibs['execution'])) $attachLibs['execution'] = $objectLibs['execution'];
if(isset($objectLibs['files'])) $attachLibs['files'] = $objectLibs['files'];
}
}
$this->view->breadTitle = $title;
$this->view->libID = $libID;
$this->view->moduleID = $moduleID;
$this->view->modules = $this->doc->getDocMenu($libID, $moduleID, '`order`', $browseType);
$this->view->docs = $this->doc->getDocsByBrowseType($libID, $browseType, $queryID, $moduleID, $sort, $pager);
$this->view->attachLibs = $attachLibs;
$this->view->docs = $this->doc->getDocsByBrowseType($browseType, $queryID, $moduleID, $sort, $pager);
$this->view->users = $this->user->getPairs('noletter');
$this->view->orderBy = $orderBy;
$this->view->browseType = $browseType;
$this->view->param = $param;
$this->view->type = $type;
$this->view->from = $from;
$this->view->pager = $pager;
$this->view->libs = $libs;
$this->view->currentLib = $libID ? $lib : '';
$this->display();
}
@@ -390,20 +303,6 @@ class doc extends control
$lib = $this->doc->getLibByID($libID);
$type = $lib->type;
/* According the from, set menus. */
if($this->from == 'product')
{
$this->product->setMenu($lib->product);
$this->lang->TRActions = common::hasPriv('doc', 'createLib') ? html::a(helper::createLink('doc', 'createLib'), "<i class='icon icon-plus'></i> " . $this->lang->doc->createlib, '', "class='btn btn-secondary iframe' data-width='70%'") : '';
}
elseif($this->from == 'project')
{
$this->project->setMenu($lib->project);
$this->lang->TRActions = common::hasPriv('doc', 'createLib') ? html::a(helper::createLink('doc', 'createLib'), "<i class='icon icon-plus'></i> " . $this->lang->doc->createlib, '', "class='btn btn-secondary iframe' data-width='70%'") : '';
}
$this->view->title = $lib->name . $this->lang->colon . $this->lang->doc->create;
$this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$libID"), $lib->name);
$this->view->position[] = $this->lang->doc->create;
@@ -411,7 +310,7 @@ class doc extends control
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
$this->view->libID = $libID;
$this->view->libs = $this->doc->getLibs($type = 'all', $extra = "withObject,$unclosed", $libID);
$this->view->libs = $this->doc->getLibs($objectType, $extra = "withObject,$unclosed", $libID, $objectID);
$this->view->libName = $this->dao->findByID($libID)->from(TABLE_DOCLIB)->fetch('name');
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($libID, 'doc', $startModuleID = 0);
$this->view->moduleID = $moduleID ? (int)$moduleID : (int)$this->cookie->lastDocModule;
@@ -522,7 +421,7 @@ class doc extends control
$this->view->doc = $doc;
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($libID, 'doc', $startModuleID = 0);
$this->view->type = $type;
$this->view->libs = $this->doc->getLibs('all', $extra = 'withObject|noBook', $libID);
$this->view->libs = $this->doc->getLibs('all', $extra = 'withObject|noBook', $libID, $objectID);
$this->view->groups = $this->loadModel('group')->getPairs();
$this->view->users = $this->user->getPairs('noletter|noclosed|nodeleted', $doc->users);
$this->display();
@@ -576,16 +475,6 @@ class doc extends control
$lib = $this->doc->getLibByID($doc->lib);
$type = $lib->type;
/* According the from, set menus. */
if($this->from == 'product')
{
$this->product->setMenu($lib->product);
}
elseif($this->from == 'project')
{
$this->project->setMenu($lib->project);
}
$this->view->title = "DOC #$doc->id $doc->title - " . $lib->name;
$this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$doc->lib"), $lib->name);
$this->view->position[] = $this->lang->doc->view;
@@ -873,84 +762,6 @@ class doc extends control
$this->display();
}
/**
* Show files for product or execution.
*
* @param string $type
* @param int $objectID
* @param string $from product|project|doc
* @param string $viewType
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function showFiles($type, $objectID, $from = 'doc', $viewType = '', $orderBy = 't1.id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$uri = $this->app->getURI(true);
$this->app->session->set('taskList', $uri, 'execution');
$this->app->session->set('storyList', $uri, 'product');
$this->app->session->set('docList', $uri, 'doc');
if(empty($viewType)) $viewType = !empty($_COOKIE['docFilesViewType']) ? $this->cookie->docFilesViewType : 'card';
setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
$table = $type == 'product' ? TABLE_PRODUCT : TABLE_PROJECT;
$object = $this->dao->select('id,name,status')->from($table)->where('id')->eq($objectID)->fetch();
/* According the from, set menus. */
if($this->from == 'product')
{
$this->product->setMenu($lib->product);
}
elseif($this->from == 'project')
{
$this->project->setMenu($objectID);
}
else
{
$crumb = html::a(inlink('allLibs', "type=$type"), $type == 'product' ? $this->lang->productCommon : $this->lang->executionCommon) . $this->lang->doc->separator;
if($this->productID and $type == 'execution') $crumb = $this->doc->getProductCrumb($this->productID, $objectID);
$crumb .= html::a(inlink('objectLibs', "type=$type&objectID=$objectID"), $object->name);
$crumb .= $this->lang->doc->separator . ' ' . $this->lang->doclib->files;
$productID = 0;
$executionID = 0;
if($type == 'product')
{
$productID = $objectID;
if(!$this->product->checkPriv($objectID)) $this->accessDenied();
}
if($type == 'execution')
{
$executionID = $objectID;
if(!$this->execution->checkPriv($objectID)) $this->accessDenied();
}
}
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
$this->view->title = $object->name;
$this->view->position[] = $object->name;
$this->view->type = $type;
$this->view->object = $object;
$this->view->files = $this->doc->getLibFiles($type, $objectID, $orderBy, $pager);
$this->view->users = $this->user->getPairs('noletter');
$this->view->pager = $pager;
$this->view->viewType = $viewType;
$this->view->orderBy = $orderBy;
$this->view->objectID = $objectID;
$this->view->canBeChanged = common::canModify($type, $object); // Determines whether an object is editable.
$this->display();
}
/**
* Show accessDenied response.
*
+1 -1
View File
@@ -16,7 +16,7 @@
.main-col .doc-title .actions a {margin-right: 8px;}
.main-col .doc-title .actions i {font-size: 15px; color: #8c8c8c;}
#sidebar {width: 275px;}
#sidebar>.cell {width: 265px;}
#sidebar>.cell {width: 100%;}
#sidebar>.sidebar-toggle {left: 3px; right: auto;}
.hide-sidebar #sidebar>.cell {left: -270px;}
.hide-sidebar #sidebar>.sidebar-toggle>.icon:before {content: "\e314";}
-24
View File
@@ -1,24 +0,0 @@
/* Browse by module. */
function browseByModule()
{
$('.divider').removeClass('hidden');
$('#bymoduleTab').addClass('active');
$('#allTab').removeClass('active');
}
function browseBySearch()
{
$('.divider').addClass('hidden');
$('#bymoduleTab').removeClass('active');
$('#allTab').addClass('active');
}
$(function()
{
if(browseType == 'bysearch') return;
if(browseType == 'byediteddate' || browseType == 'openedbyme' || browseType == 'collectedbyme')
{
$('#pageActions ul.dropdown-menu').css('left', '0px');
}
$('#' + browseType + 'Tab').addClass('active');
});
+12 -121
View File
@@ -31,43 +31,16 @@ class docModel extends model
* @param string $type
* @param string $extra
* @param string $appendLibs
* @param int $projectID
* @access public
* @return array
*/
public function getLibs($type = '', $extra = '', $appendLibs = '')
public function getLibs($type = '', $extra = '', $appendLibs = '', $objectID = 0)
{
$projectID = $this->session->project;
if($type == 'product' or $type == 'project')
if($type == 'all')
{
$idList = array();
if($type == 'product') $idList = $this->loadModel('product')->getProductIDByProject($projectID, false);
if($type == 'execution')
{
$status = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'undone' : 'all';
$idList = $this->loadModel('execution')->getIdList($projectID, $status);
}
$table = $type == 'product' ? TABLE_PRODUCT : TABLE_PROJECT;
$stmt = $this->dao->select('*')->from(TABLE_DOCLIB)
->where($type)->in($idList)
->andWhere('deleted')->eq('0')
->query();
}
elseif($type == 'all')
{
/* If extra have unclosedProject then ignore unclosed project libs. */
$status = (strpos($extra, 'unclosedProject') !== false) ? 'undone' : 'all';
$executionIdList = $this->loadModel('execution')->getIdList($projectID, $status);
$productIdList = $this->loadModel('product')->getProductIDByProject($projectID, false);
$stmt = $this->dao->select('*')->from(TABLE_DOCLIB)
->where('deleted')->eq(0)
->andWhere()
->markLeft(1)
->where('`type`')->eq('custom')
->orWhere('execution')->in($executionIdList)
->orWhere('product')->in($productIdList)
->markRight(1)
->orderBy('id_desc')
->query();
}
@@ -79,11 +52,9 @@ class docModel extends model
->orderBy('`order`, id desc')->query();
}
if(strpos($extra, 'withObject') !== false)
{
$products = $this->loadModel('product')->getProductPairsByProject($projectID);
$executions = $this->loadModel('execution')->getPairs($projectID, 'all', 'noclosed');
}
$products = $this->loadModel('product')->getPairs();
$projects = $this->loadModel('project')->getPairsByProgram();
$executions = $this->loadModel('execution')->getPairs();
$libPairs = array();
while($lib = $stmt->fetch())
@@ -93,6 +64,7 @@ class docModel extends model
if(strpos($extra, 'withObject') !== false)
{
if($lib->product != 0) $lib->name = zget($products, $lib->product, '') . '/' . $lib->name;
if($lib->project != 0) $lib->name = zget($projects, $lib->project, '') . '/' . $lib->name;
if($lib->execution != 0) $lib->name = zget($executions, $lib->execution, '') . '/' . $lib->name;
}
@@ -211,7 +183,6 @@ class docModel extends model
/**
* Get docs by browse type.
*
* @param string $libID
* @param string $browseType
* @param int $queryID
* @param int $moduleID
@@ -220,10 +191,10 @@ class docModel extends model
* @access public
* @return array
*/
public function getDocsByBrowseType($libID, $browseType, $queryID, $moduleID, $sort, $pager)
public function getDocsByBrowseType($browseType, $queryID, $moduleID, $sort, $pager)
{
$allLibs = array_keys($this->getLibs('all'));
$docIdList = $this->getPrivDocs($libID, $moduleID);
$docIdList = $this->getPrivDocs(0, $moduleID);
$files = $this->dao->select('*')->from(TABLE_FILE)
->where('objectType')->eq('doc')
@@ -232,13 +203,12 @@ class docModel extends model
if($browseType == "all")
{
$docs = $this->getDocs($libID, 0, $sort, $pager);
$docs = $this->getDocs(0, 0, $sort, $pager);
}
elseif($browseType == "openedbyme")
{
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('deleted')->eq(0)
->beginIF($libID)->andWhere('lib')->in($libID)->fi()
->andWhere('lib')->in($allLibs)
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->andWhere('addedBy')->eq($this->app->user->account)
@@ -256,7 +226,6 @@ class docModel extends model
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('deleted')->eq(0)
->andWhere('id')->in(array_keys($docIDList))
->beginIF($libID)->andWhere('lib')->in($libID)->fi()
->andWhere('lib')->in($allLibs)
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->orderBy($sort)
@@ -278,7 +247,6 @@ class docModel extends model
{
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('deleted')->eq(0)
->beginIF($libID)->andWhere('lib')->in($libID)->fi()
->andWhere('lib')->in($allLibs)
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->andWhere('collector')->like("%,{$this->app->user->account},%")
@@ -286,83 +254,6 @@ class docModel extends model
->page($pager)
->fetchAll('id');
}
elseif($browseType == "bymodule")
{
$modules = 0;
if($moduleID)
{
$modules = array($moduleID => $moduleID);
if(strpos($this->config->doc->custom->showLibs, 'children') !== false) $modules = $this->loadModel('tree')->getAllChildId($moduleID);
}
$docs = $this->getDocs($libID, $modules, $sort, $pager);
}
elseif($browseType == "bygrid")
{
$docs = $this->getDocs($libID, 0, $sort, $pager);
}
elseif($browseType == "bysearch")
{
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
if($query)
{
$this->session->set('docQuery', $query->sql);
$this->session->set('docForm', $query->form);
}
else
{
$this->session->set('docQuery', ' 1 = 1');
}
}
else
{
if($this->session->docQuery == false) $this->session->set('docQuery', ' 1 = 1');
}
$libCond = strpos($this->session->docQuery, "`lib` = ") !== false;
$allLibCond = strpos($this->session->docQuery, "`lib` = 'all'") !== false;
$docQuery = str_replace("`product` = 'all'", '1', $this->session->docQuery); // Search all product.
$docQuery = str_replace("`execution` = 'all'", '1', $docQuery); // Search all execution.
$docQuery = str_replace("`lib` = 'all'", '1', $docQuery); // Search all lib.
$docs = $this->dao->select('*')->from(TABLE_DOC)->where($docQuery)
->beginIF(!$libCond and $libID != 0)->andWhere("lib")->eq($libID)->fi()
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->andWhere('deleted')->eq(0)
->fetchAll('id');
foreach($docs as $docID => $doc)
{
if(!$this->checkPrivDoc($doc)) unset($docs[$docID]);
}
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('id')->in(array_keys($docs))
->andWhere('lib')->in($allLibs)
->orderBy($sort)
->page($pager)
->fetchAll('id');
}
elseif($browseType == 'fastsearch')
{
if($this->session->searchDoc == false) return array();
$docIdList = $this->getPrivDocs($libID, $moduleID);
$docs = $this->dao->select('t1.*')->from(TABLE_DOC)->alias('t1')
->leftJoin(TABLE_DOCCONTENT)->alias('t2')->on('t2.doc = t1.id')
->where('t1.deleted')->eq(0)
->beginIF(!empty($docIdList))->andWhere('t1.id')->in($docIdList)->fi()
->andWhere('t1.title', true)->like("%{$this->session->searchDoc}%")
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->orWhere('t2.content')->like("%{$this->session->searchDoc}%")->markRight(1)
->andWhere('t1.lib')->in($allLibs)
->orderBy($sort)
->page($pager)
->fetchAll('id');
foreach($docs as $doc) $doc->title = str_replace($this->session->searchDoc, "<span style='color:red'>{$this->session->searchDoc}</span>", $doc->title);
}
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'doc', false);
if(!$docs) return array();
$docContents = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->in(array_keys($docs))->orderBy('version,doc')->fetchAll('doc');
foreach($docs as $index => $doc)
@@ -743,7 +634,7 @@ class docModel extends model
->orderBy($orderBy)
->fetchAll('id');
$docCounts= $this->dao->select("module, count(id) as docCount")->from(TABLE_DOC)
$docCounts = $this->dao->select("module, count(id) as docCount")->from(TABLE_DOC)
->where('module')->in(array_keys($modules))
->andWhere('deleted')->eq(0)
->groupBy('module')
@@ -1761,7 +1652,7 @@ class docModel extends model
$actions .= "<ul class='dropdown-menu'>";
foreach($this->lang->doc->fastMenuList as $key => $fastMenu)
{
$link = helper::createLink('doc', 'browse', "libID=0&browseTyp={$key}");
$link = helper::createLink('doc', 'browse', "libID=0&browseType={$key}");
$actions .= '<li>' . html::a($link, "<i class='icon {$this->lang->doc->fastMenuIconList[$key]}'></i> {$fastMenu}") . '</li>';
}
$actions .='</ul>';
+5 -72
View File
@@ -15,27 +15,14 @@
<?php include '../../common/view/datepicker.html.php';?>
<?php js::set('browseType', $browseType);?>
<?php js::set('confirmDelete', $lang->doc->confirmDelete)?>
<?php js::set('libID', $libID);?>
<?php if($this->from != 'doc') js::set('type', 'doc');?>
<?php $spliter = (empty($this->app->user->feedback) && !$this->cookie->feedbackView && $this->from == 'doc') ? true : false;?>
<div class="main-row fade <?php if($spliter) echo 'split-row';?>" id="mainRow">
<div class="main-row fade" id="mainRow">
<div id="mainContent">
<div class="cell<?php if($browseType == 'bysearch') echo ' show';?>" id="queryBox" data-module='doc'></div>
<div class="panel block-files block-sm no-margin">
<?php if(empty($docs) and $browseType == 'bysearch'):?>
<div class="table-empty-tip">
<p><span class="text-muted"><?php echo $lang->doc->noSearchedDoc;?></span></p>
</div>
<?php elseif(empty($docs) and empty($modules) and empty($libs) and empty($attachLibs)):?>
<?php if(empty($docs)):?>
<div class="table-empty-tip">
<p>
<?php if($libID):?>
<span class="text-muted"><?php echo $lang->doc->noDoc;?></span>
<?php if(common::hasPriv('doc', 'create') and common::canBeChanged('doc', $currentLib)):?>
<?php echo html::a($this->createLink('doc', 'create', "libID={$libID}&moduleID=$moduleID&type=&from={$lang->navGroup->doc}"), "<i class='icon icon-plus'></i> " . $lang->doc->create, '', "class='btn btn-info'");?>
<?php endif;?>
<?php elseif($browseType == 'byediteddate'):?>
<?php if($browseType == 'byediteddate'):?>
<span class="text-muted"><?php echo $lang->doc->noEditedDoc;?></span>
<?php elseif($browseType == 'openedbyme'):?>
<span class="text-muted"><?php echo $lang->doc->noOpenedDoc;?></span>
@@ -58,60 +45,6 @@
</tr>
</thead>
<tbody>
<?php if(!empty($libs) and $browseType != 'bysearch'):?>
<?php foreach($libs as $lib):?>
<?php $star = strpos($lib->collector, ',' . $this->app->user->account . ',') !== false ? 'icon-star text-yellow' : 'icon-star-empty';?>
<?php $collectTitle = strpos($lib->collector, ',' . $this->app->user->account . ',') !== false ? $lang->doc->cancelCollection : $lang->doc->collect;?>
<tr>
<td class="c-name"><?php echo html::a(inlink('browse', "libID={$lib->id}&browseType=all&param=0&orderBy=$orderBy&from=$from"), "<i class='icon icon-folder text-yellow'></i> &nbsp;" . $lib->name);?></td>
<td class="c-num"></td>
<td class="c-user"></td>
<td class="c-datetime"></td>
<td class="c-datetime"></td>
<td>
<?php if(common::hasPriv('doc', 'collect')):?>
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$lib->id&objectType=doclib");?>" title="<?php echo $collectTitle;?>" class='btn btn-link ajaxCollect'><i class='icon <?php echo $star;?>'></i></a>
<?php endif;?>
<?php common::printLink('doc', 'editLib', "libID=$lib->id", "<i class='icon icon-edit'></i>", '', "title='{$lang->edit}' class='btn btn-link iframe'")?>
<?php common::printLink('tree', 'browse', "rootID=$lib->id&viewType=doc&currentModuleID=0&branch=0&from=$from", "<i class='icon icon-cog'></i>", '', "title='{$lang->tree->manage}' class='btn btn-link'")?>
</td>
</tr>
<?php endforeach;?>
<?php endif;?>
<?php if(!empty($attachLibs) and $browseType != 'bysearch'):?>
<?php foreach($attachLibs as $libType => $attachLib):?>
<tr>
<?php if($libType == 'execution'):?>
<td class="c-name"><?php echo html::a(inlink('allLibs', "type=execution&product={$currentLib->product}"), "<i class='icon icon-folder text-yellow'></i> &nbsp;" . $attachLib->name);?></td>
<?php elseif($libType == 'files'):?>
<td class="c-name"><?php echo html::a(inlink('showFiles', "type=$type&objectID={$currentLib->$type}&from=$from"), "<i class='icon icon-folder text-yellow'></i> &nbsp;" . $attachLib->name);?></td>
<?php endif;?>
<td class="c-num"></td>
<td class="c-user"></td>
<td class="c-datetime"></td>
<td class="c-datetime"></td>
<td></td>
</tr>
<?php endforeach;?>
<?php endif;?>
<?php if(isset($modules) and $browseType != 'bysearch'):?>
<?php foreach($modules as $module):?>
<?php $star = strpos($module->collector, ',' . $this->app->user->account . ',') !== false ? 'icon-star text-yellow' : 'icon-star-empty';?>
<?php $collectTitle = strpos($module->collector, ',' . $this->app->user->account . ',') !== false ? $lang->doc->cancelCollection : $lang->doc->collect;?>
<tr>
<td class="c-name"><?php echo html::a(inlink('browse', "libID=$libID&browseType=bymodule&param=$module->id&orderBy=$orderBy&from=$from"), "<i class='icon icon-folder text-yellow'></i> &nbsp;" . $module->name);?></td>
<td class="c-num"></td>
<td class="c-user"></td>
<td class="c-datetime"></td>
<td class="c-datetime"></td>
<td class="c-actions">
<?php if(common::hasPriv('doc', 'collect')):?>
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$module->id&objectType=module");?>" title="<?php echo $collectTitle;?>" class='btn btn-link ajaxCollect'><i class='icon <?php echo $star;?>'></i></a>
<?php endif;?>
</td>
</tr>
<?php endforeach;?>
<?php endif;?>
<?php foreach($docs as $doc):?>
<?php $star = strpos($doc->collector, ',' . $this->app->user->account . ',') !== false ? 'icon-star text-yellow' : 'icon-star-empty';?>
<?php $collectTitle = strpos($doc->collector, ',' . $this->app->user->account . ',') !== false ? $lang->doc->cancelCollection : $lang->doc->collect;?>
@@ -126,8 +59,8 @@
<?php if(common::hasPriv('doc', 'collect')):?>
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$doc->id&objectType=doc");?>" title="<?php echo $collectTitle;?>" class='btn btn-link ajaxCollect'><i class='icon <?php echo $star;?>'></i></a>
<?php endif;?>
<?php common::printLink('doc', 'edit', "docID=$doc->id&comment=false&from={$lang->navGroup->doc}", "<i class='icon icon-edit'></i>", '', "title='{$lang->edit}' class='btn btn-link iframe'", true, true)?>
<?php common::printLink('doc', 'delete', "docID=$doc->id&confirm=no&from={$lang->navGroup->doc}", "<i class='icon icon-trash'></i>", 'hiddenwin', "title='{$lang->delete}' class='btn btn-link'")?>
<?php common::printLink('doc', 'edit', "docID=$doc->id&comment=false&from=$app->openApp", "<i class='icon icon-edit'></i>", '', "title='{$lang->edit}' class='btn btn-link iframe'", true, true)?>
<?php common::printLink('doc', 'delete', "docID=$doc->id&confirm=no&from=$app->openApp", "<i class='icon icon-trash'></i>", 'hiddenwin', "title='{$lang->delete}' class='btn btn-link'")?>
<?php endif;?>
</td>
</tr>
+2
View File
@@ -38,8 +38,10 @@ $sessionString .= session_name() . '=' . session_id();
echo html::a("javascript:ajaxDeleteDoc(\"$deleteURL\", \"docList\", confirmDelete)", '<i class="icon-trash"></i>', '', "title='{$lang->doc->delete}' class='btn btn-link'");
}
?>
<?php if(common::hasPriv('doc', 'collect')):?>
<?php $star = strpos($doc->collector, ',' . $this->app->user->account . ',') !== false ? 'icon-star text-yellow' : 'icon-star-empty';?>
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$doc->id&objectType=doc");?>" title="<?php echo $lang->doc->collect;?>" class='ajaxCollect btn btn-link'><i class='icon <?php echo $star;?>'></i></a>
<?php endif;?>
</div>
</div>
<div class="detail-content article-content">
+3 -3
View File
@@ -21,7 +21,7 @@
<div class="panel-heading">
<div class="panel-title"><?php echo $lang->doc->orderByEdit;?></div>
<nav class="panel-actions nav nav-default">
<li><?php echo html::a($this->createLink('doc', 'browse', "libID=0&browseTyp=byediteddate"), '<i class="icon icon-more icon-sm"></i>', '', "title='{$lang->more}'");?></li>
<li><?php echo html::a($this->createLink('doc', 'browse', "browseType=byediteddate"), '<i class="icon icon-more icon-sm"></i>', '', "title='{$lang->more}'");?></li>
</nav>
</div>
<div class="panel-body has-table">
@@ -127,7 +127,7 @@
<div class="panel-heading">
<div class="panel-title"><?php echo $lang->doc->myDoc;?></div>
<nav class="panel-actions nav nav-default">
<li><?php echo html::a($this->createLink('doc', 'browse', "libID=0&browseTyp=openedbyme"), '<i class="icon icon-more icon-sm"></i>', '', "title='{$lang->more}'");?></li>
<li><?php echo html::a($this->createLink('doc', 'browse', "browseType=openedbyme"), '<i class="icon icon-more icon-sm"></i>', '', "title='{$lang->more}'");?></li>
</nav>
</div>
<div class="panel-body has-table">
@@ -159,7 +159,7 @@
<div class="panel-heading">
<div class="panel-title"><?php echo $lang->doc->myCollection;?></div>
<nav class="panel-actions nav nav-default">
<li><?php echo html::a($this->createLink('doc', 'browse', "libID=0&browseTyp=collectedbyme"), '<i class="icon icon-more icon-sm"></i>', '', "title='{$lang->more}'");?></li>
<li><?php echo html::a($this->createLink('doc', 'browse', "browseType=collectedbyme"), '<i class="icon icon-more icon-sm"></i>', '', "title='{$lang->more}'");?></li>
</nav>
</div>
<div class="panel-body has-table">
-209
View File
@@ -1,209 +0,0 @@
<?php
/**
* The showFiles view file of doc module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yidong Wang <yidong@cnezsoft.com>
* @package doc
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php $pageCSS .= $this->doc->appendNavCSS();?>
<?php include '../../common/view/header.html.php';?>
<div class="main-row fade <?php if($this->from == 'doc') echo 'split-row';?>" id="mainRow">
<?php if($this->from == 'doc'):?>
<?php include './side.html.php';?>
<div class="col-spliter"></div>
<?php endif;?>
<div class="main-col" data-min-width="400">
<div class="panel block-files block-sm no-margin">
<div class="panel-heading">
<div class="panel-title font-normal"><i class="icon icon-folder-open-o text-muted"></i> <?php echo $lang->doclib->files;?></div>
<nav class="panel-actions btn-toolbar">
<div class="btn-group">
<form class='input-control has-icon-right table-col' method='get'>
<?php
if($config->requestType == 'GET')
{
echo html::hidden('m', 'doc');
echo html::hidden('f', 'showFiles');
echo html::hidden('type', $type);
echo html::hidden('objectID', $object->id);
echo html::hidden('viewType', ($viewType == 'list' ? 'list' : 'card'));
echo html::hidden('recTotal', isset($this->get->recTotal) ? $this->get->recTotal : 0);
echo html::hidden('recPerPage', isset($this->get->recPerPage) ? $this->get->recPerPage : 0);
echo html::hidden('pageID', isset($this->get->pageID) ? $this->get->pageID : 0);
}
?>
<?php echo html::hidden('onlybody', isonlybody() ? 'yes' : 'no');?>
<?php echo html::input('title', $this->get->title, "class='form-control' placeholder='{$lang->doc->fileTitle}'");?>
<?php echo html::submitButton("<i class='icon icon-search'></i>", '', "btn btn-icon btn-link input-control-icon-right");?>
</form>
</div>
<div class="btn-group">
<?php $from = $lang->navGroup->doc;?>
<?php echo html::a(inlink('showFiles', "type=$type&objectID=$objectID&from=$from&viewType=card"), "<i class='icon icon-cards-view'></i>", '', "title={$lang->doc->browseTypeList['grid']} class='btn btn-icon" . ($viewType != 'list' ? ' text-primary' : '') . "'");?>
<?php echo html::a(inlink('showFiles', "type=$type&objectID=$objectID&from=$from&viewType=list"), "<i class='icon icon-bars'></i>" , '', "title={$lang->doc->browseTypeList['list']} class='btn btn-icon" . ($viewType == 'list' ? ' text-primary' : '') . "'");?>
</div>
</nav>
</div>
<?php if($viewType == 'list'):?>
<div class="panel-body">
<table class="table table-borderless table-hover table-files table-fixed no-margin">
<thead>
<tr class="text-center">
<th class="w-80px"><?php echo $lang->doc->id;?></th>
<th class='text-left'><?php echo $lang->doc->fileTitle;?></th>
<th class='text-left'><?php echo $lang->doc->filePath;?></th>
<th class="w-80px"><?php echo $lang->doc->extension;?></th>
<th class="w-60px"><?php echo $lang->doc->size;?></th>
<th class="w-100px"><?php echo $lang->doc->addedBy;?></th>
<th class="w-160px"><?php echo $lang->doc->addedDate;?></th>
<th class="w-80px"><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach($files as $file):?>
<?php if(empty($file->pathname)) continue;?>
<tr>
<td class="text-center"><?php echo sprintf('%03d', $file->id);?></td>
<td class="c-url">
<?php
if($type == 'execution' && in_array($file->objectType, array('task', 'build')))
{
$objectLink = $this->createLink($file->objectType, 'view', "objectID=$file->objectID", '', '', $file->project);
}
if($type == 'product' && in_array($file->objectType, array('bug', 'release', 'testcase', 'testreport')))
{
$objectLink = $this->createLink($file->objectType, 'view', "objectID=$file->objectID", '', '', $file->project);
}
else
{
$objectLink = $this->createLink($file->objectType, 'view', "objectID=$file->objectID");
}
?>
<a href='<?php echo $objectLink;?>'><?php echo $file->title . ' [' . strtoupper($file->objectType) . ' #' . $file->objectID . ']';?></a>
</td>
<td> <?php echo $file->pathname;?> </td>
<td class="text-center"><?php echo $file->extension;?></td>
<td><?php echo number_format($file->size / 1024 , 1) . 'K';?></td>
<td class="text-center"><?php echo isset($file->addedBy) ? zget($users, $file->addedBy) : '';?></td>
<td class="text-center"><?php echo isset($file->addedDate) ? substr($file->addedDate, 0, 10) : '';?></td>
<td class="c-actions">
<?php
common::printLink('file', 'download', "fileID=$file->id", '<i class="icon-import"></i>', "data-toggle='modal'", "class='btn' title={$lang->doc->download}", true, false, $file);
if($canBeChanged) common::printLink('file', 'delete', "fileID=$file->id", '<i class="icon-trash"></i>', 'hiddenwin', "class='btn' title={$lang->delete}", true, false, $file);
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
</div>
<?php else:?>
<div class="panel-body">
<div class="row row-grid files-grid" data-size="300">
<?php foreach($files as $file):?>
<?php if(empty($file->pathname)) continue;?>
<div class='col'>
<div class='lib-file'>
<?php
$imageWidth = 0;
if(stripos('jpg|jpeg|gif|png|bmp', $file->extension) !== false and file_exists($file->realPath))
{
$imageSize = getimagesize($file->realPath);
$imageWidth = $imageSize ? $imageSize[0] : 0;
}
$sessionString = $config->requestType == 'PATH_INFO' ? '?' : '&';
$sessionString .= session_name() . '=' . session_id();
$fileID = $file->id;
$url = helper::createLink('file', 'download', 'fileID=' . $fileID) . $sessionString ;
?>
<div class='file'>
<a href='<?php echo $url;?>' title='<?php echo $file->title;?>' target='_blank' onclick="return downloadFile(<?php echo $file->id?>, '<?php echo $file->extension?>', <?php echo $imageWidth?>)">
<?php
$downloadLink = $this->createLink('file', 'download', "fileID=$file->id&mouse=left");
if(in_array($file->extension, $config->file->imageExtensions))
{
echo "<div class='img-holder' style='background-image: url($file->webPath)'><img src='$file->webPath'/></div>";
}
else
{
$iconClass = 'icon-file';
if(strpos('zip,tar,gz,bz2,rar', $file->extension) !== false) $iconClass = 'icon-file-archive';
else if(strpos('csv,xls,xlsx', $file->extension) !== false) $iconClass = 'icon-file-excel';
else if(strpos('doc,docx', $file->extension) !== false) $iconClass = 'icon-file-word';
else if(strpos('ppt,pptx', $file->extension) !== false) $iconClass = 'icon-file-powerpoint';
else if(strpos('pdf', $file->extension) !== false) $iconClass = 'icon-file-pdf';
else if(strpos('mp3,ogg,wav', $file->extension) !== false) $iconClass = 'icon-file-audio';
else if(strpos('avi,mp4,mov', $file->extension) !== false) $iconClass = 'icon-file-video';
else if(strpos('txt,md', $file->extension) !== false) $iconClass = 'icon-file-text';
else if(strpos('html,htm', $file->extension) !== false) $iconClass = 'icon-globe';
echo "<i class='file-icon icon $iconClass'></i>";
}
?>
</a>
<?php
if($type == 'execution' && in_array($file->objectType, array('task', 'build')))
{
$objectLink = $this->createLink($file->objectType, 'view', "objectID=$file->objectID", '', '', $file->project);
}
else
{
$objectLink = $this->createLink($file->objectType, 'view', "objectID=$file->objectID");
}
?>
<div class='file-name'><a href='<?php echo $objectLink;?>' title='<?php echo substr($file->addedDate, 0, 10)?>'><?php echo $file->title . ' [' . strtoupper($file->objectType) . ' #' . $file->objectID . ']';?></a></div>
</div>
<div class='actions'>
<?php if(common::hasPriv('file', 'delete') and $canBeChanged): ?>
<a href='<?php echo $this->createLink('file', 'delete', "fileID=$file->id"); ?>' target='hiddenwin' title='<?php echo $lang->delete?>' class='delete btn btn-link'><i class='icon icon-trash'></i></a>
<?php endif?>
</div>
</div>
</div>
<?php endforeach;?>
</div>
<?php if(!empty($files)):?>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
<?php else:?>
<div class='table-empty-tip text-muted'><?php echo $lang->pager->noRecord;?></div>
<?php endif?>
</div>
</div>
<?php endif?>
</div>
</div>
</div>
<?php js::set('type', 'doc');?>
<script>
<?php
$sessionString = $config->requestType == 'PATH_INFO' ? '?' : '&';
$sessionString .= session_name() . '=' . session_id();
?>
function downloadFile(fileID, extension, imageWidth)
{
if(!fileID) return;
var fileTypes = 'txt,jpg,jpeg,gif,png,bmp';
var sessionString = '<?php echo $sessionString;?>';
var windowWidth = $(window).width();
var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left') + sessionString;
width = (windowWidth > imageWidth) ? ((imageWidth < windowWidth*0.5) ? windowWidth*0.5 : imageWidth) : windowWidth;
if(fileTypes.indexOf(extension) >= 0)
{
$('<a>').modalTrigger({url: url, type: 'iframe', width: width}).trigger('click');
}
else
{
window.open(url, '_blank');
}
return false;
}
</script>
<?php include '../../common/view/footer.html.php';?>
+1 -1
View File
@@ -15,7 +15,7 @@
<?php include '../../common/view/kindeditor.html.php';?>
<?php echo css::internal($keTableCSS);?>
<style>.detail-content .file-image {padding: 0 50px 0 10px;}</style>
<?php $browseLink = $this->session->docList ? $this->session->docList : inlink('browse', 'libID=0&browseTyp=byediteddate');?>
<?php $browseLink = $this->session->docList ? $this->session->docList : inlink('browse', 'libID=0&browseType=byediteddate');?>
<?php
$sessionString = $config->requestType == 'PATH_INFO' ? '?' : '&';
$sessionString .= session_name() . '=' . session_id();
+3 -2
View File
@@ -1216,7 +1216,8 @@ class execution extends control
$this->app->loadLang('programplan');
if($executionID)
{
if(!empty($planID))
$execution = $this->execution->getById($executionID);
if(!empty($planID) and $execution->lifetime != 'ops')
{
if($confirm == 'yes')
{
@@ -1224,7 +1225,7 @@ class execution extends control
}
else
{
die(js::confirm($this->lang->execution->importPlanStory, inlink('create', "projectID=$projectID&executionID=$executionID&copyExecutionID=&planID=$planID&confirm=yes"), inlink('create', "projectID=$projectID&executionID=$executionID"), 'parent', 'parent'));
die(js::confirm($this->lang->execution->importPlanStory, inlink('create', "projectID=$projectID&executionID=$executionID&copyExecutionID=&planID=$planID&confirm=yes"), inlink('create', "projectID=$projectID&executionID=$executionID")));
}
}
$this->view->title = $this->lang->execution->tips;
-1
View File
@@ -194,7 +194,6 @@ $lang->execution->copy = "Copy {$lang->executionCommon}";
$lang->execution->delete = "Delete {$lang->executionCommon}";
$lang->execution->deleteAB = "Delete Execution";
$lang->execution->browse = "{$lang->executionCommon} List";
$lang->execution->list = "{$lang->executionCommon} List";
$lang->execution->edit = "Edit {$lang->executionCommon}";
$lang->execution->editAction = "Edit Execution";
$lang->execution->batchEdit = "Edit";
-1
View File
@@ -194,7 +194,6 @@ $lang->execution->copy = "复制{$lang->executionCommon}";
$lang->execution->delete = "删除{$lang->executionCommon}";
$lang->execution->deleteAB = "删除{$lang->execution->common}";
$lang->execution->browse = "浏览{$lang->execution->common}";
$lang->execution->list = "{$lang->executionCommon}列表";
$lang->execution->edit = "编辑{$lang->executionCommon}";
$lang->execution->editAction = "编辑{$lang->execution->common}";
$lang->execution->batchEdit = "编辑";
+9 -9
View File
@@ -69,16 +69,12 @@ class executionModel extends model
/* Unset story, bug, build and testtask if type is ops. */
$execution = $this->getByID($executionID);
/*
if($execution and $execution->lifetime == 'ops')
{
unset($this->lang->execution->menu->story);
unset($this->lang->execution->menu->qa);
unset($this->lang->execution->subMenu->qa->bug);
unset($this->lang->execution->subMenu->qa->build);
unset($this->lang->execution->subMenu->qa->testtask);
unset($this->lang->execution->menu->build);
}
*/
/* Hide story and qa menu when execution is story or design type. */
/*
@@ -1482,7 +1478,8 @@ class executionModel extends model
->leftJoin(TABLE_PRODUCT)->alias('t2')
->on('t1.product = t2.id')
->where('t1.project')->eq((int)$executionID)
->andWhere('t2.deleted')->eq(0);
->andWhere('t2.deleted')->eq(0)
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->products)->fi();
if(!$withBranch) return $query->fetchPairs('id', 'name');
return $query->fetchAll('id');
}
@@ -2058,12 +2055,13 @@ class executionModel extends model
$planStories = array();
$planProducts = array();
$count = 0;
$this->loadModel('story');
if(!empty($plans))
{
foreach($plans as $planID => $productID)
{
if(empty($planID)) continue;
$planStory = $this->loadModel('story')->getPlanStories($planID);
$planStory = $this->story->getPlanStories($planID);
if(!empty($planStory))
{
foreach($planStory as $id => $story)
@@ -2080,9 +2078,11 @@ class executionModel extends model
}
}
}
$projectID = $this->session->project;
$this->linkStory($executionID, $planStories, $planProducts);
$this->linkStory($this->session->project, $planStories, $planProducts);
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate(helper::createLink('execution', 'create', "productID=&executionID=$executionID"));
$this->linkStory($projectID, $planStories, $planProducts);
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate(helper::createLink('execution', 'create', "projectID=$projectID&executionID=$executionID"));
}
/**
+1 -1
View File
@@ -12,7 +12,7 @@
?>
<?php if(isset($tips)):?>
<?php $defaultURL = $config->systemMode == 'new' ? $this->createLink('project', 'execution', "status=all&projectID=$projectID") : $this->createLink('execution', 'task', 'executionID=' . $executionID);?>
<?php include '../../common/view/header.lite.html.php';?>
<?php include '../../common/view/header.html.php';?>
<body>
<div class='modal-dialog mw-500px' id='tipsModal'>
<div class='modal-header'>
+1 -1
View File
@@ -2,7 +2,7 @@
<p><strong><?php echo $lang->execution->afterInfo;?></strong></p>
<div>
<?php echo html::a($this->createLink('execution', 'team', "executionID=$executionID"), $lang->execution->setTeam, '', "class='btn' data-app='execution'");?>
<?php if($execution->type != 'ops') echo html::a($this->createLink('execution', 'linkstory', "executionID=$executionID"), $lang->execution->linkStory, '', "class='btn' data-app='execution'");?>
<?php if($execution->lifetime != 'ops') echo html::a($this->createLink('execution', 'linkstory', "executionID=$executionID"), $lang->execution->linkStory, '', "class='btn' data-app='execution'");?>
<?php echo html::a($this->createLink('task', 'create', "execution=$executionID"), $lang->execution->createTask, '', "class='btn' data-app='execution'");?>
<?php echo html::a($this->createLink('execution', 'task', "executionID=$executionID"), $lang->execution->goback, '', "class='btn' data-app='execution'");?>
</div>
+1 -1
View File
@@ -89,7 +89,7 @@ class extension extends control
{
/* Init vars. */
$type = strtolower($type);
$moduleID = $type == 'bymodule' ? (int)$param : 0;
$moduleID = $type == 'bymodule' ? (int)base64_decode($param) : 0;
$extensions = array();
$pager = null;
+2
View File
@@ -1 +1,3 @@
.pager {margin-top: 0;}
.tree li>a:hover {color: #fff; background-color: #0c64eb;}
.tree li>a.active {color: #fff; background-color: #0c64eb;}
+4 -10
View File
@@ -1016,13 +1016,10 @@ $lang->resource->doc->create = 'create';
$lang->resource->doc->view = 'view';
$lang->resource->doc->edit = 'edit';
$lang->resource->doc->delete = 'delete';
//$lang->resource->doc->deleteFile = 'deleteFile';
$lang->resource->doc->deleteFile = 'deleteFile';
$lang->resource->doc->allLibs = 'allLibs';
//$lang->resource->doc->showFiles = 'showFiles';
$lang->resource->doc->objectLibs = 'objectLibs';
//$lang->resource->doc->sort = 'sort';
$lang->resource->doc->collect = 'collectAction';
//$lang->resource->doc->diff = 'diff';
$lang->doc->methodOrder[0] = 'index';
$lang->doc->methodOrder[5] = 'browse';
@@ -1033,13 +1030,10 @@ $lang->doc->methodOrder[25] = 'create';
$lang->doc->methodOrder[30] = 'view';
$lang->doc->methodOrder[35] = 'edit';
$lang->doc->methodOrder[40] = 'delete';
//$lang->doc->methodOrder[45] = 'deleteFile';
$lang->doc->methodOrder[45] = 'deleteFile';
$lang->doc->methodOrder[50] = 'allLibs';
//$lang->doc->methodOrder[55] = 'showFiles';
$lang->doc->methodOrder[60] = 'objectLibs';
//$lang->doc->methodOrder[65] = 'sort';
$lang->doc->methodOrder[70] = 'collect';
//$lang->doc->methodOrder[55] = 'diff';
$lang->doc->methodOrder[55] = 'objectLibs';
$lang->doc->methodOrder[60] = 'collect';
/* Mail. */
$lang->resource->mail = new stdclass();
+2
View File
@@ -84,6 +84,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = 'Letzte Version';
$lang->misc->feature->detailed = 'Details';
$lang->misc->releaseDate['15.0.rc3'] = '2021-04-16';
$lang->misc->releaseDate['15.0.rc2'] = '2021-04-09';
$lang->misc->releaseDate['15.0.rc1'] = '2021-04-05';
$lang->misc->releaseDate['12.5.3'] = '2021-01-06';
@@ -140,6 +141,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['15.0.rc3'][] = array('title' => 'Adjust details,Fix bug', 'desc' => '');
$lang->misc->feature->all['15.0.rc2'][] = array('title' => 'Fix Bug.', 'desc' => '');
$lang->misc->feature->all['15.0.rc1'][] = array('title' => 'Upgrade to 15,reframe menu, add program.', 'desc' => '');
$lang->misc->feature->all['12.5.3'][] = array('title' => 'Adjust annual data.', 'desc' => '');
+2
View File
@@ -84,6 +84,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = 'Latest Version';
$lang->misc->feature->detailed = 'Detail';
$lang->misc->releaseDate['15.0.rc3'] = '2021-04-16';
$lang->misc->releaseDate['15.0.rc2'] = '2021-04-09';
$lang->misc->releaseDate['15.0.rc1'] = '2021-04-05';
$lang->misc->releaseDate['12.5.3'] = '2021-01-06';
@@ -140,6 +141,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['15.0.rc3'][] = array('title' => 'Adjust details,Fix bug', 'desc' => '');
$lang->misc->feature->all['15.0.rc2'][] = array('title' => 'Fix Bug.', 'desc' => '');
$lang->misc->feature->all['15.0.rc1'][] = array('title' => 'Upgrade to 15,reframe menu, add program.', 'desc' => '');
$lang->misc->feature->all['12.5.3'][] = array('title' => 'Adjust annual data.', 'desc' => '');
+2
View File
@@ -84,6 +84,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = 'Dernière Version';
$lang->misc->feature->detailed = 'Détail';
$lang->misc->releaseDate['15.0.rc3'] = '2021-04-16';
$lang->misc->releaseDate['15.0.rc2'] = '2021-04-09';
$lang->misc->releaseDate['15.0.rc1'] = '2021-04-05';
$lang->misc->releaseDate['12.5.3'] = '2021-01-06';
@@ -140,6 +141,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['15.0.rc3'][] = array('title' => 'Adjust details, fix bug.', 'desc' => '');
$lang->misc->feature->all['15.0.rc2'][] = array('title' => 'Fix Bug.', 'desc' => '');
$lang->misc->feature->all['15.0.rc1'][] = array('title' => 'Upgrade to 15,reframe menu, add program.', 'desc' => '');
$lang->misc->feature->all['12.5.3'][] = array('title' => 'Adjust annual data.', 'desc' => '');
+2
View File
@@ -84,6 +84,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = 'Latest Version';
$lang->misc->feature->detailed = 'Chi tiết';
$lang->misc->releaseDate['15.0.rc3'] = '2021-04-16';
$lang->misc->releaseDate['15.0.rc2'] = '2021-04-09';
$lang->misc->releaseDate['15.0.rc1'] = '2021-04-05';
$lang->misc->releaseDate['12.5.3'] = '2021-01-06';
@@ -140,6 +141,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['15.0.rc3'][] = array('title' => 'Adjust detail, fix bug.', 'desc' => '');
$lang->misc->feature->all['15.0.rc2'][] = array('title' => 'Fix Bug.', 'desc' => '');
$lang->misc->feature->all['15.0.rc1'][] = array('title' => 'Upgrade to 15,reframe menu, add program.', 'desc' => '');
$lang->misc->feature->all['12.5.3'][] = array('title' => 'Adjust annual data.', 'desc' => '');
+2
View File
@@ -84,6 +84,7 @@ $lang->misc->feature = new stdclass();
$lang->misc->feature->lastest = '最新版本';
$lang->misc->feature->detailed = '详情';
$lang->misc->releaseDate['15.0.rc3'] = '2021-04-16';
$lang->misc->releaseDate['15.0.rc2'] = '2021-04-09';
$lang->misc->releaseDate['15.0.rc1'] = '2021-04-05';
$lang->misc->releaseDate['12.5.3'] = '2021-01-06';
@@ -140,6 +141,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22';
$lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
$lang->misc->feature->all['15.0.rc3'][] = array('title' => '完善细节,修复Bug', 'desc' => '');
$lang->misc->feature->all['15.0.rc2'][] = array('title' => '修复Bug,优化界面交互', 'desc' => '');
$lang->misc->feature->all['15.0.rc1'][] = array('title' => '升级到15版本,重构导航、文档库,增加项目集管理', 'desc' => '');
$lang->misc->feature->all['12.5.3'][] = array('title' => '优化年度总结', 'desc' => '');
+5 -8
View File
@@ -125,14 +125,11 @@ class my extends control
{
/* Save session. */
$uri = $this->app->getURI(true);
if($this->app->viewType != 'json')
{
$this->session->set('todoList', $uri, 'my');
$this->session->set('bugList', $uri, 'qa');
$this->session->set('taskList', $uri, 'execution');
$this->session->set('storyList', $uri, 'product');
$this->session->set('testtaskList', $uri, 'qa');
}
$this->session->set('todoList', $uri, 'my');
$this->session->set('bugList', $uri, 'qa');
$this->session->set('taskList', $uri, 'execution');
$this->session->set('storyList', $uri, 'product');
$this->session->set('testtaskList', $uri, 'qa');
/* Load pager. */
$this->app->loadClass('pager', $static = true);
+4 -1
View File
@@ -11,7 +11,10 @@
*/
?>
<?php if($preferenceSetted):?>
<style> #submit{margin-top: 45px} </style>
<style>
#submit{margin-top: 45px}
.chosen-container-single .chosen-single div b {top: 7px !important;}
</style>
<?php include '../../common/view/header.html.php';?>
<?php else:?>
<?php include '../../common/view/header.lite.html.php';?>
+5 -1
View File
@@ -340,6 +340,10 @@ class product extends control
$rdUsers = $this->user->getPairs('nodeleted|devfirst|noclosed', '', $this->config->maxCount);
if(!empty($this->config->user->moreLink)) $this->config->moreLinks["RD"] = $this->config->user->moreLink;
$lines = array();
if($programID) $lines = array('') + $this->product->getLinePairs($programID);
if($this->config->systemMode == 'classic') $lines = array('') + $this->product->getLinePairs();
$this->view->title = $this->lang->product->create;
$this->view->position[] = $this->view->title;
$this->view->groups = $this->loadModel('group')->getPairs();
@@ -349,7 +353,7 @@ class product extends control
$this->view->rdUsers = $rdUsers;
$this->view->users = $this->user->getPairs('nodeleted|noclosed');
$this->view->programs = array('') + $this->loadModel('program')->getTopPairs('', 'noclosed');
$this->view->lines = $this->config->systemMode == 'new' ? array() : array('' => '') + $this->product->getLinePairs();
$this->view->lines = $lines;
$this->view->URSRPairs = $this->loadModel('custom')->getURSRPairs();
unset($this->lang->product->typeList['']);
+1 -1
View File
@@ -35,7 +35,7 @@
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->productplan->noPlan;?></span>
<?php if(common::canModify('product', $product) and common::hasPriv('productplan', 'create')):?>
<?php if(common::canModify('product', $product) and common::hasPriv('productplan', 'create') and $browseType != 'overdue'):?>
<?php echo html::a($this->createLink('productplan', 'create', "productID=$product->id&branch=$branch"), "<i class='icon icon-plus'></i> " . $lang->productplan->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
+8 -4
View File
@@ -286,7 +286,7 @@ class project extends control
if($model == 'waterfall')
{
$productID = $this->loadModel('product')->getProductIDByProject($projectID, true);
$this->session->set('programPlanList', $this->createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=lists", '', '', $projectID), 'project');
$this->session->set('projectPlanList', $this->createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=lists", '', '', $projectID), 'project');
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('programplan', 'create', "projectID=$projectID", '', '', $projectID)));
}
@@ -606,14 +606,18 @@ class project extends control
$this->session->set('productPlanList', $uri, 'product');
$this->session->set('releaseList', $uri, 'product');
$this->session->set('storyList', $uri, 'product');
$this->session->set('projectList', $uri, 'project');
$this->session->set('executionList', $uri, 'execution');
$this->session->set('taskList', $uri, 'execution');
$this->session->set('buildList', $uri, 'execution');
$this->session->set('bugList', $uri, 'qa');
$this->session->set('caseList', $uri, 'qa');
$this->session->set('testtaskList', $uri, 'qa');
if(isset($this->config->maxVersion))
{
$this->session->set('riskList', $uri, 'project');
$this->session->set('issueList', $uri, 'project');
}
/* Append id for secend sort. */
$orderBy = $direction == 'next' ? 'date_desc' : 'date_asc';
$sort = $this->loadModel('common')->appendOrder($orderBy);
@@ -712,7 +716,7 @@ class project extends control
$this->loadModel('product');
/* Save session. */
$this->session->set('bugList', $this->app->getURI(true), 'qa');
$this->session->set('bugList', $this->app->getURI(true), 'project');
$this->project->setMenu($projectID);
$project = $this->project->getByID($projectID);
+1 -1
View File
@@ -820,7 +820,7 @@ class projectModel extends model
$lib->name = $this->lang->doclib->main['product'];
$lib->type = 'product';
$lib->main = '1';
$lib->acl = $product->acl;
$lib->acl = 'default';
$this->dao->insert(TABLE_DOCLIB)->data($lib)->exec();
}
+3
View File
@@ -54,6 +54,9 @@ js::set('browseType', $browseType);
<div class="sidebar-toggle"><i class="icon icon-angle-left"></i></div>
<div class="cell">
<?php echo $programTree;?>
<div class="text-center">
<?php common::printLink('project', 'programTitle', '', $lang->project->moduleSetting, '', "class='btn btn-info btn-wide iframe'", true, true);?>
</div>
</div>
</div>
<?php endif;?>
+4
View File
@@ -42,6 +42,10 @@ $config->repo->edit->requiredFields = 'product,SCM,name,path,encoding,client';
$config->repo->svn = new stdclass();
$config->repo->svn->requiredFields = 'account,password';
$config->repo->gitlab = new stdclass;
$config->repo->gitlab->perPage = 300;
$config->repo->gitlab->apiPath = "%s/api/v4/projects/%s/repository/";
$config->repo->rules['module']['task'] = 'Task';
$config->repo->rules['module']['bug'] = 'Bug';
$config->repo->rules['module']['story'] = 'Story';
+31
View File
@@ -165,6 +165,14 @@ class repo extends control
$this->app->loadLang('action');
if($repo->SCM == 'Gitlab')
{
$projects = $this->repo->getGitlabProjects($repo->client, $repo->password);
$options = array();
foreach($projects as $project) $options[$project->id] = $project->name . ':' . $project->http_url_to_repo;
$this->view->projects = $options;
}
$repo->repoType = $repo->id . '-' . $repo->SCM;
$this->view->repo = $repo;
$this->view->repoID = $repoID;
@@ -1072,6 +1080,29 @@ class repo extends control
die($reposHtml);
}
/**
* Ajax get gitlab projects.
*
* @param string $host
* @param string $token
* @access public
* @return void
*/
public function ajaxGetGitlabProjects($host, $token)
{
$host = helper::safe64Decode($host);
$projects = $this->repo->getGitlabProjects($host, $token);
if(!$projects) $this->send(array('message' => array()));
$options = '';
foreach($projects as $project)
{
$options .= "<option value='{$project->id}' data-name='{$project->name}'>{$project->name}:{$project->http_url_to_repo}</option>";
}
die($options);
}
/**
* Ajax get branch drop menu.
*
+27 -2
View File
@@ -6,16 +6,38 @@ $(function()
$form = $(this).closest('form');
$form.css('min-height', $form.height());
})
$('#gitlabHost, #gitlabToken').change(function()
{
host = Base64.encode($('#gitlabHost').val());
token = $('#gitlabToken').val();
url = createLink('repo', 'ajaxgetgitlabprojects', "host=" + host + '&token=' + token);
if(host == '' || token == '') return false;
$.get(url, function(response)
{
$('#gitlabProject').html('').append(response);
$('#gitlabProject').chosen().trigger("chosen:updated");;
});
});
$('#gitlabProject').change(function()
{
$option = $(this).find('option:selected');
$('#name').val($option.data('name'));
});
});
function scmChanged(scm) {
function scmChanged(scm)
{
if(scm == 'Git')
{
$('.account-fields').addClass('hidden');
$('.tips-git').removeClass('hidden');
$('.tips-svn').addClass('hidden');
}
}
else
{
$('.account-fields').removeClass('hidden');
@@ -23,4 +45,7 @@ function scmChanged(scm) {
$('.tips-git').addClass('hidden');
$('.tips-svn').removeClass('hidden');
}
$('tr.gitlab').toggle(scm == 'Gitlab');
$('tr.hide-gitlab').toggle(scm != 'Gitlab');
}
+28 -1
View File
@@ -6,9 +6,33 @@ $(function()
$form = $(this).closest('form');
$form.css('min-height', $form.height());
})
$('#gitlabHost, #gitlabToken').change(function()
{
host = Base64.encode($('#gitlabHost').val());
token = $('#gitlabToken').val();
url = createLink('repo', 'ajaxgetgitlabprojects', "host=" + host + '&token=' + token);
if(host == '' || token == '') return false;
$.get(url, function(response)
{
$('#gitlabProject').html('').append(response);
$('#gitlabProject').chosen().trigger("chosen:updated");;
});
});
$('#gitlabProject').change(function()
{
$option = $(this).find('option:selected');
if(!$option.data('name')) return false;
$('#name').val($option.data('name'));
$(this).chosen().trigger("chosen:updated");
});
});
function scmChanged(scm) {
function scmChanged(scm)
{
if(scm == 'Git')
{
$('.account-fields').addClass('hidden');
@@ -23,4 +47,7 @@ function scmChanged(scm) {
$('.tips-git').addClass('hidden');
$('.tips-svn').removeClass('hidden');
}
$('tr.gitlab').toggle(scm == 'Gitlab');
$('tr.hide-gitlab').toggle(scm != 'Gitlab');
}
+8
View File
@@ -124,6 +124,14 @@ $lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Git'] = 'Git';
$lang->repo->scmList['Subversion'] = 'SVN';
$lang->repo->scmList['Gitlab'] = 'Gitlab';
$lang->repo->gitlabHost = 'Gitlab Host';
$lang->repo->gitlabToken = 'Gitlab Token';
$lang->repo->gitlabProject = 'Projects';
$lang->repo->placeholder = new stdclass;
$lang->repo->placeholder->gitlabHost = 'Input url of gitlab';
$lang->repo->notice = new stdclass();
$lang->repo->notice->syncing = 'Synchronizing. Please wait ...';
+8
View File
@@ -124,6 +124,14 @@ $lang->repo->encodingList['gbk'] = 'GBK';
$lang->repo->scmList['Git'] = 'Git';
$lang->repo->scmList['Subversion'] = 'Subversion';
$lang->repo->scmList['Gitlab'] = 'Gitlab';
$lang->repo->gitlabHost = 'Gitlab 地址';
$lang->repo->gitlabToken = 'Gitlab Token';
$lang->repo->gitlabProject = '项目';
$lang->repo->placeholder = new stdclass;
$lang->repo->placeholder->gitlabHost = '请填写gitlab访问地址';
$lang->repo->notice = new stdclass();
$lang->repo->notice->syncing = '正在同步中, 请稍等...';
+41 -2
View File
@@ -235,11 +235,21 @@ class repoModel extends model
if(!$this->checkConnection()) return false;
$data = fixer::input('post')
->setIf($this->post->SCM == 'Gitlab', 'password', $this->post->gitlabToken)
->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost)
->skipSpecial('path,client,account,password')
->setDefault('product', '')
->join('product', ',')
->get();
if($this->post->SCM == 'Gitlab')
{
$data->path = sprintf($this->config->repo->gitlab->apiPath, $data->gitlabHost, $this->post->gitlabProject);
unset($data->gitlabHost);
unset($data->gitlabToken);
}
$data->acl = empty($data->acl) ? '' : json_encode($data->acl);
if($data->SCM == 'Subversion')
@@ -252,8 +262,9 @@ class repoModel extends model
}
if($data->encrypt == 'base64') $data->password = base64_encode($data->password);
$this->dao->insert(TABLE_REPO)->data($data)
$this->dao->insert(TABLE_REPO)->data($data, $skip = 'gitlabProject')
->batchCheck($this->config->repo->create->requiredFields, 'notempty')
->checkIF($data->SCM == 'GitLab', 'gitlabProject', 'notempty')
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->autoCheck()
->exec();
@@ -282,6 +293,16 @@ class repoModel extends model
->skipSpecial('path,client,account,password')
->join('product', ',')
->get();
if($this->post->SCM == 'Gitlab')
{
$data->path = sprintf($this->config->repo->gitlab->apiPath, $data->gitlabHost, $this->post->gitlabProject);
unset($data->gitlabHost);
unset($data->gitlabToken);
unset($data->gitlabProject);
}
$data->acl = empty($data->acl) ? '' : json_encode($data->acl);
if($data->SCM == 'Subversion' and $data->path != $repo->path)
@@ -301,9 +322,10 @@ class repoModel extends model
if(!$this->checkConnection()) return false;
if($data->encrypt == 'base64') $data->password = base64_encode($data->password);
$this->dao->update(TABLE_REPO)->data($data)
$this->dao->update(TABLE_REPO)->data($data, $skip = 'gitlabProject')
->batchCheck($this->config->repo->edit->requiredFields, 'notempty')
->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty')
->checkIF($data->SCM == 'GitLab', 'gitlabProject', 'notempty')
->autoCheck()
->where('id')->eq($id)->exec();
@@ -1754,4 +1776,21 @@ class repoModel extends model
return $buildedURL;
}
/**
* Get gitlab projects.
*
* @param string $host
* @param string $token
* @access public
* @return array
*/
public function getGitlabProjects($host, $token)
{
$host = rtrim($host, '/');
$host .= '/api/v4/projects';
$projects = file_get_contents($host . "?private_token=$token");
return json_decode($projects);
}
}
+17 -4
View File
@@ -10,6 +10,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::import($jsRoot . 'misc/base64.js');?>
<?php if(common::checkNotCN()):?>
<style>.user-addon {padding-right: 16px; padding-left: 16px;}</style>
<?php endif;?>
@@ -31,12 +32,24 @@
<td style="width:550px"><?php echo html::select('SCM', $lang->repo->scmList, 'Git', "onchange='scmChanged(this.value)' class='form-control'"); ?></td>
<td class="tips-git"><?php echo $lang->repo->syncTips; ?></td>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabHost;?></th>
<td><?php echo html::input('gitlabHost', '', "class='form-control' placeholder='{$lang->repo->placeholder}'");?>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabToken;?></th>
<td><?php echo html::input('gitlabToken', '', "class='form-control'");?>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabProject;?></th>
<td><?php echo html::select('gitlabProject', array(''), '', "class='form-control chosen'");?>
</tr>
<tr>
<th><?php echo $lang->repo->name; ?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'"); ?></td>
<td></td>
</tr>
<tr>
<tr class='hide-gitlab'>
<th><?php echo $lang->repo->path; ?></th>
<td class='required'><?php echo html::input('path', '', "class='form-control'"); ?></td>
<td class='muted'>
@@ -49,7 +62,7 @@
<td class='required'><?php echo html::input('encoding', 'utf-8', "class='form-control'"); ?></td>
<td class='muted'><?php echo $lang->repo->encodingsTips; ?></td>
</tr>
<tr>
<tr class='hide-gitlab'>
<th><?php echo $lang->repo->client;?></th>
<td class='required'><?php echo html::input('client', '', "class='form-control'")?></td>
<td class='muted'>
@@ -57,11 +70,11 @@
<span class="tips-svn"><?php echo $lang->repo->example->client->svn;?></span>
</td>
</tr>
<tr class="account-fields">
<tr class="account-fields hide-gitlab">
<th><?php echo $lang->repo->account;?></th>
<td><?php echo html::input('account', '', "class='form-control'");?></td>
</tr>
<tr class="account-fields">
<tr class="account-fields hide-gitlab">
<th><?php echo $lang->repo->password;?></th>
<td>
<div class='input-group'>
+17 -4
View File
@@ -12,6 +12,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::import($jsRoot . 'misc/base64.js');?>
<?php if(common::checkNotCN()):?>
<style>
.user-addon{padding-right: 16px; padding-left: 16px;}
@@ -37,12 +38,24 @@
<span class="tips-git"><?php echo $lang->repo->syncTips; ?></span>
</td>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabHost;?></th>
<td><?php echo html::input('gitlabHost', $repo->client, "class='form-control' placeholder='{$lang->repo->placeholder}'");?>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabToken;?></th>
<td><?php echo html::input('gitlabToken', $repo->password, "class='form-control'");?>
</tr>
<tr class='gitlab hide'>
<th><?php echo $lang->repo->gitlabProject;?></th>
<td><?php echo html::select('gitlabProject', $projects, '', "class='form-control chosen'");?>
</tr>
<tr>
<th><?php echo $lang->repo->name; ?></th>
<td class='required'><?php echo html::input('name', $repo->name, "class='form-control'"); ?></td>
<td></td>
</tr>
<tr>
<tr class='hide-gitlab'>
<th><?php echo $lang->repo->path; ?></th>
<td class='required'><?php echo html::input('path', $repo->path, "class='form-control'"); ?></td>
<td class='muted'>
@@ -55,7 +68,7 @@
<td class='required'><?php echo html::input('encoding', $repo->encoding, "class='form-control'"); ?></td>
<td class='muted'><?php echo $lang->repo->encodingsTips; ?></td>
</tr>
<tr>
<tr class='hide-gitlab'>
<th><?php echo $lang->repo->client;?></th>
<td class='required'><?php echo html::input('client', $repo->client, "class='form-control'")?></td>
<td class='muted'>
@@ -63,11 +76,11 @@
<span class="tips-svn"><?php echo $lang->repo->example->client->svn;?></span>
</td>
</tr>
<tr class="account-fields">
<tr class="account-fields hide-gitlab">
<th><?php echo $lang->repo->account;?></th>
<td><?php echo html::input('account', $repo->account, "class='form-control'");?></td>
</tr>
<tr class="account-fields">
<tr class="account-fields hide-gitlab">
<th><?php echo $lang->repo->password;?></th>
<td>
<div class='input-group'>
+1
View File
@@ -1513,6 +1513,7 @@ class story extends control
public function zeroCase($productID = 0, $branchID = 0, $orderBy = 'id_desc')
{
$this->session->set('storyList', $this->app->getURI(true) . '#app=' . $this->app->openApp, 'product');
$this->session->set('caseList', $this->app->getURI(true), $this->app->openApp);
$this->loadModel('testcase');
if($this->app->openApp == 'project')
+2 -2
View File
@@ -526,7 +526,7 @@ class storyModel extends model
$story = fixer::input('post')
->callFunc('title', 'trim')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('lastEditedDate', $now)
->add('lastEditedDate', $now)
->setIF($this->post->assignedTo == '', 'assignedTo', $oldStory->assignedTo)
->setIF($this->post->assignedTo != '' and $this->post->assignedTo != $oldStory->assignedTo, 'assignedDate', $now)
->setIF($specChanged, 'version', $oldStory->version + 1)
@@ -2743,7 +2743,7 @@ class storyModel extends model
}
elseif($type == 'full')
{
$property = '(' . $this->lang->story->pri . ':' . (!empty($this->lang->story->priList[$story->pri]) ? $this->lang->story->priList[$story->pri] : 0) . ',' . $this->lang->story->estimate . ':' . $this->lang->hourCommon . ')';
$property = '(' . $this->lang->story->pri . ':' . (!empty($this->lang->story->priList[$story->pri]) ? $this->lang->story->priList[$story->pri] : 0) . ',' . $this->lang->story->estimate . ':' . $story->estimate . ')';
}
else
{
+1
View File
@@ -30,6 +30,7 @@
<div class='panel-body'>
<form method='post' id='chartTypesForm'>
<div class='checkboxes'>
<?php if($storyType == 'requirement') unset($lang->story->report->charts['storysPerPlan']);?>
<?php echo html::checkBox('charts', $lang->story->report->charts, $checkedCharts, '', 'block');?>
</div>
<div class='btn-toolbar'>
+20 -1
View File
@@ -269,7 +269,7 @@ class task extends control
$storyLink = $this->session->storyList ? $this->session->storyList : $this->createLink('execution', 'story', "executionID=$executionID");
/* Set menu. */
$this->execution->setMenu($this->execution->getPairs(), $execution->id);
$this->execution->setMenu($execution->id);
/* When common task are child tasks, query whether common task are consumed. */
$taskConsumed = 0;
@@ -1228,6 +1228,13 @@ class task extends control
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
if(!empty($this->view->task->team))
{
$members = array();
foreach($this->view->task->team as $account => $member) $members[$account] = zget($this->view->members, $account);
$this->view->members = $members;
}
if(!isset($this->view->members[$this->view->task->finishedBy])) $this->view->members[$this->view->task->finishedBy] = $this->view->task->finishedBy;
$this->view->title = $this->view->execution->name . $this->lang->colon . $this->lang->task->activate;
$this->view->position[] = $this->lang->task->activate;
@@ -1560,6 +1567,18 @@ class task extends control
if(isset($users[$task->closedBy])) $task->closedBy = $users[$task->closedBy];
if(isset($users[$task->lastEditedBy])) $task->lastEditedBy = $users[$task->lastEditedBy];
/* Convert username to real name. */
if(!empty($task->mailto))
{
$mailtoList = explode(',', $task->mailto);
$task->mailto = '';
foreach($mailtoList as $mailto)
{
if(!empty($mailto)) $task->mailto .= ',' . zget($users, $mailto);
}
}
if($task->parent > 0 && strpos($task->name, htmlentities('>')) !== 0) $task->name = '>' . $task->name;
if(!empty($task->team)) $task->name = '[' . $taskLang->multipleAB . '] ' . $task->name;
+1 -1
View File
@@ -1,2 +1,2 @@
.thWidth {width: 80px !important;}
.thWidth {width: 93px !important;}
.lifeThWidth {width: 80px !important;}
-1
View File
@@ -335,7 +335,6 @@ function markTestStory()
var $tr = $(this);
storiesHasTest[$tr.find('select[name^="testStory"]').val()] = true;
});
console.log(storiesHasTest);
return storiesHasTest;
};
+1 -1
View File
@@ -934,7 +934,6 @@ class taskModel extends model
->checkIF($task->status == 'done' and $task->closedReason, 'closedReason', 'equal', 'done')
->batchCheckIF($task->status == 'done', 'canceledBy, canceledDate', 'empty')
->checkIF($task->status == 'closed', 'closedReason', 'notempty')
->batchCheckIF($task->closedReason == 'cancel', 'finishedBy, finishedDate', 'empty')
->where('id')->eq((int)$taskID)->exec();
@@ -1491,6 +1490,7 @@ class taskModel extends model
$data->status = $task->status;
$data->lastEditedBy = $this->app->user->account;
$data->lastEditedDate = $now;
if(helper::isZeroDate($task->realStarted)) $data->realStarted = $now;
if($left == 0)
{
+1 -1
View File
@@ -160,7 +160,7 @@ $config->testcase->datatable->fieldList['lastRunResult']['required'] = 'no';
$config->testcase->datatable->fieldList['status']['title'] = 'statusAB';
$config->testcase->datatable->fieldList['status']['fixed'] = 'no';
$config->testcase->datatable->fieldList['status']['width'] = '60';
$config->testcase->datatable->fieldList['status']['width'] = '70';
$config->testcase->datatable->fieldList['status']['required'] = 'no';
$config->testcase->datatable->fieldList['lastEditedBy']['title'] = 'lastEditedBy';
+1 -1
View File
@@ -1600,7 +1600,7 @@ class testcase extends control
if(empty($libraries))
{
echo js::alert($this->lang->testcase->noLibrary);
die(js::locate(inlink('browse')));
die(js::locate($this->session->caseList));
}
if(empty($libID) or !isset($libraries[$libID])) $libID = key($libraries);
+2 -2
View File
@@ -113,7 +113,7 @@
<i class='icon icon-export muted'></i> <?php echo $lang->export ?>
<span class='caret'></span>
</button>
<ul class='dropdown-menu' id='exportActionMenu'>
<ul class='dropdown-menu pull-right' id='exportActionMenu'>
<?php
$class = common::hasPriv('testcase', 'export') ? '' : "class=disabled";
$misc = common::hasPriv('testcase', 'export') ? "class='export'" : "class=disabled";
@@ -132,7 +132,7 @@
<?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>
<ul class='dropdown-menu' id='importActionMenu'>
<ul class='dropdown-menu pull-right' id='importActionMenu'>
<?php
$class = common::hasPriv('testcase', 'import') ? '' : "class=disabled";
$misc = common::hasPriv('testcase', 'import') ? "class='export'" : "class=disabled";
+1
View File
@@ -146,6 +146,7 @@ class testtask extends control
{
/* Save session. */
$this->session->set('testtaskList', $this->app->getURI(true), 'qa');
$this->session->set('caseList', $this->app->getURI(true), $this->app->openApp);
$this->session->set('buildList', $this->app->getURI(true) . '#app=' . $this->app->openApp, 'execution');
$this->loadModel('testcase');
$this->app->loadLang('tree');
+1
View File
@@ -134,3 +134,4 @@ $lang->upgrade->fromVersions['12_5_1'] = '12.5.1';
$lang->upgrade->fromVersions['12_5_2'] = '12.5.2';
$lang->upgrade->fromVersions['12_5_3'] = '12.5.3';
$lang->upgrade->fromVersions['15_0_rc1'] = '15.0.rc1';
$lang->upgrade->fromVersions['15_0_rc2'] = '15.0.rc2';
+3
View File
@@ -643,6 +643,9 @@ class upgradeModel extends model
$this->saveLogs('Execute 15_0_rc1');
$this->adjustUserView();
$this->appendExec('15_0_rc1');
case '15_0_rc2':
$this->saveLogs('Execute 15_0_rc2');
$this->appendExec('15_0_rc2');
}
$this->deletePatch();
+2
View File
@@ -35,7 +35,9 @@
<tr>
<td><?php echo html::a($executionLink, $execution->id);?></td>
<td>
<?php if(isset($config->maxVersion)):?>
<span class='project-type-label label label-info label-outline'><?php echo zget($lang->user->executionTypeList, $execution->type);?></span>
<?php endif;?>
<?php echo html::a($executionLink, $execution->name);?>
</td>
<?php if(isset($execution->delay)):?>