Merge branch 'master' of https://github.com/easysoft/zentaopms
This commit is contained in:
@@ -16,6 +16,7 @@ clean:
|
||||
rm -fr lampp
|
||||
common:
|
||||
mkdir zentaopms
|
||||
cp -fr api zentaopms/
|
||||
cp -fr bin zentaopms/
|
||||
cp -fr config zentaopms/ && rm -fr zentaopms/config/my.php
|
||||
cp -fr db zentaopms/
|
||||
|
||||
@@ -11,7 +11,7 @@ class bugsEntry extends entry
|
||||
public function get($productID)
|
||||
{
|
||||
$control = $this->loadController('bug', 'browse');
|
||||
$control->browse($productID);
|
||||
$control->browse($productID, $this->param('branch', ''), $this->param('status', ''), 0, $this->param('order', ''), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
|
||||
@@ -11,7 +11,7 @@ class executionsEntry extends entry
|
||||
public function get($projectID = 0)
|
||||
{
|
||||
$control = $this->loadController('execution', 'all');
|
||||
$control->all($this->param('status', 'all'), $this->param('project', $projectID));
|
||||
$control->all($this->param('status', 'all'), $this->param('project', $projectID), $this->param('order', 'id_desc'), 0, $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* 禅道API的my地盘资源类
|
||||
* 版本V1
|
||||
*
|
||||
* The bug entry point of zentaopms
|
||||
* Version 1
|
||||
*/
|
||||
class myEntry extends entry
|
||||
{
|
||||
public function get()
|
||||
{
|
||||
$info = $this->loadModel('my')->getInfo();
|
||||
|
||||
if(!$info) return $this->sendError(400, $info->message);
|
||||
$this->send(200, $info);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class ProgramsEntry extends Entry
|
||||
public function get()
|
||||
{
|
||||
$program = $this->loadController('program', 'browse');
|
||||
$program->browse();
|
||||
$program->browse($this->param('status', 'all'), $this->param('order', 'order_asc'));
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* 禅道API的project issues资源类
|
||||
* 版本V1
|
||||
* 目前适用于Gitlab
|
||||
*
|
||||
* The project issues entry point of zentaopms
|
||||
* Version 1
|
||||
*/
|
||||
class projectIssueEntry extends entry
|
||||
{
|
||||
public function get($issueID)
|
||||
{
|
||||
$this->loadModel('entry');
|
||||
$this->setParam('timeFormat', 'utc');
|
||||
|
||||
$idParams = explode('-', $issueID);
|
||||
if(count($idParams) < 2) $this->sendError(400, 'The id of issue is wrong.');
|
||||
|
||||
$type = $idParams[0];
|
||||
$id = intval($idParams[1]);
|
||||
|
||||
$issue = new stdclass();
|
||||
switch($type)
|
||||
{
|
||||
case 'story':
|
||||
$this->app->loadLang('story');
|
||||
$storyStatus = array('' => '', 'draft' => 'opened', 'active' => 'opened', 'changed' => 'opened', 'closed' => 'closed');
|
||||
|
||||
$story = $this->dao->select('*')->from(TABLE_STORY)->where('id')->eq($id)->fetch();
|
||||
if(!$story) $this->send404();
|
||||
|
||||
$issue->id = $issueID;
|
||||
$issue->title = $story->title;
|
||||
$issue->labels = array($this->app->lang->story->common, zget($this->app->lang->story->categoryList, $story->category));
|
||||
$issue->pri = $story->pri;
|
||||
$issue->assignedTo = $this->entry->getAssignees('story', $story);
|
||||
$issue->openedDate = $story->openedDate;
|
||||
$issue->openedBy = $this->entry->getUser($story->openedBy);
|
||||
$issue->lastEditedDate = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedDate : $story->lastEditedDate;
|
||||
$issue->lastEditedBy = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedBy : $story->lastEditedBy;
|
||||
$issue->status = $storyStatus[$story->status];
|
||||
$issue->url = helper::createLink('story', 'view', "storyID=$id");
|
||||
|
||||
$storySpec = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('story')->eq($id)->andWhere('version')->eq($story->version)->fetch();
|
||||
$issue->desc = $storySpec->spec;
|
||||
break;
|
||||
case 'bug':
|
||||
$this->app->loadLang('bug');
|
||||
$bugStatus = array('' => '', 'active' => 'opened', 'resolved' => 'opened', 'closed' => 'closed');
|
||||
|
||||
$bug = $this->dao->select('*')->from(TABLE_BUG)->where('id')->eq($id)->fetch();
|
||||
if(!$bug) $this->send404();
|
||||
|
||||
$issue->id = $issueID;
|
||||
$issue->title = $bug->title;
|
||||
$issue->labels = array($this->app->lang->bug->common, zget($this->app->lang->bug->typeList, $bug->type));
|
||||
$issue->pri = $bug->pri;
|
||||
$issue->assignedTo = $this->entry->getAssignees('bug', $bug);
|
||||
$issue->openedDate = $bug->openedDate;
|
||||
$issue->openedBy = $this->entry->getUser($bug->openedBy);
|
||||
$issue->lastEditedDate = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedDate : $bug->lastEditedDate;
|
||||
$issue->lastEditedBy = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedBy : $bug->lastEditedBy;
|
||||
$issue->status = $bugStatus[$bug->status];
|
||||
$issue->url = helper::createLink('bug', 'view', "bugID=$id");
|
||||
$issue->desc = $bug->steps;
|
||||
break;
|
||||
case 'task':
|
||||
$this->app->loadLang('task');
|
||||
$taskStatus = array('' => '', 'wait' => 'opened', 'doing' => 'opened', 'done' => 'opened', 'pause' => 'opened', 'cancel' => 'opened', 'closed' => 'closed');
|
||||
|
||||
$task = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($id)->fetch();
|
||||
if(!$task) $this->send404();
|
||||
|
||||
$issue->id = $issueID;
|
||||
$issue->title = $task->name;
|
||||
$issue->labels = array($this->app->lang->task->common, zget($this->app->lang->task->typeList, $task->type));
|
||||
$issue->pri = $task->pri;
|
||||
$issue->assignedTo = $this->entry->getAssignees('task', $task);
|
||||
$issue->openedDate = $task->openedDate;
|
||||
$issue->openedBy = $this->entry->getUser($task->openedBy);
|
||||
$issue->lastEditedDate = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedDate : $task->lastEditedDate;
|
||||
$issue->lastEditedBy = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedBy : $task->lastEditedBy;
|
||||
$issue->status = $taskStatus[$task->status];
|
||||
$issue->url = helper::createLink('task', 'view', "taskID=$id");
|
||||
$issue->desc = $task->desc;
|
||||
|
||||
break;
|
||||
default:
|
||||
$this->send404();
|
||||
}
|
||||
|
||||
$actions = $this->loadModel('action')->getList($type, $issueID);
|
||||
|
||||
$this->send(200, array('issue' => $this->format($issue, 'openedDate:time,lastEditedDate:time')));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
/**
|
||||
* 禅道API的project issues资源类
|
||||
* 版本V1
|
||||
* 目前适用于Gitlab
|
||||
*
|
||||
* The project issues entry point of zentaopms
|
||||
* Version 1
|
||||
*/
|
||||
class projectIssuesEntry extends entry
|
||||
{
|
||||
public function get($productID)
|
||||
{
|
||||
if(!is_numeric($productID)) $this->sendError(400, 'The project_id is not supported');
|
||||
|
||||
$this->setParam('timeFormat', 'utc');
|
||||
|
||||
$taskFields = 'id,status';
|
||||
$taskStatus = array('' => '');
|
||||
$taskStatus['opened'] = 'wait,doing,done,pause';
|
||||
$taskStatus['closed'] = 'closed';
|
||||
|
||||
$storyFields = 'id,status';
|
||||
$storyStatus = array('' => '');
|
||||
$storyStatus['opened'] = 'draft,active,changed';
|
||||
$storyStatus['closed'] = 'closed';
|
||||
|
||||
$bugFields = 'id,status';
|
||||
$bugStatus = array('' => '');
|
||||
$bugStatus['opened'] = 'active,resolved';
|
||||
$bugStatus['closed'] = 'closed';
|
||||
|
||||
$productID = (int)$productID;
|
||||
$status = $this->param('status', '');
|
||||
$label = $this->param('label', '');
|
||||
$search = $this->param('search', '');
|
||||
$page = intval($this->param('page', 1));
|
||||
$limit = intval($this->param('limit', 20));
|
||||
$order = $this->param('order', 'openedDate_desc');
|
||||
|
||||
$orderParams = explode('_', $order);
|
||||
$order = $orderParams[0];
|
||||
$sort = (isset($orderParams[1]) and strtolower($orderParams[1]) == 'asc') ? 'asc' : 'desc';
|
||||
|
||||
if($status == 'all') $status = '';
|
||||
if(!in_array($status, array('opened', 'closed', ''))) $this->sendError(400, 'The status is not supported');
|
||||
|
||||
switch($order)
|
||||
{
|
||||
case 'openedDate':
|
||||
$taskFields .= ',openedDate';
|
||||
$storyFields .= ',openedDate';
|
||||
$bugFields .= ',openedDate';
|
||||
break;
|
||||
case 'title':
|
||||
$taskFields .= ',name as title';
|
||||
$storyFields .= ',title';
|
||||
$bugFields .= ',title';
|
||||
break;
|
||||
case 'lastEditedDate':
|
||||
$taskFields .= ",if(lastEditedDate < '1970-01-01 01-01-01', openedDate, lastEditedDate) as lastEditedDate";
|
||||
$storyFields .= ",if(lastEditedDate < '1970-01-01 01-01-01', openedDate, lastEditedDate) as lastEditedDate";
|
||||
$bugFields .= ",if(lastEditedDate < '1970-01-01 01-01-01', openedDate, lastEditedDate) as lastEditedDate";
|
||||
break;
|
||||
default:
|
||||
$this->sendError(400, 'The order is not supported');
|
||||
}
|
||||
|
||||
$issues = array();
|
||||
|
||||
$executions = $this->dao->select('project')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($productID)->fetchPairs();
|
||||
$tasks = $this->dao->select($taskFields)->from(TABLE_TASK)->where('execution')->in(array_values($executions))
|
||||
->beginIF($search)->andWhere('name')->like("%$search%")->fi()
|
||||
->beginIF($label)->andWhere('type')->eq($label)->fi()
|
||||
->beginIF($status)->andWhere('status')->in($taskStatus[$status])->fi()
|
||||
->andWhere('deleted')->eq(0)
|
||||
->fetchAll();
|
||||
foreach($tasks as $task) $issues[] = array('id' => $task->id, 'type' => 'task', 'order' => $task->$order, 'status' => $this->getKey($task->status, $taskStatus));
|
||||
|
||||
$stories = $this->dao->select($storyFields)->from(TABLE_STORY)->where('product')->eq($productID)
|
||||
->beginIF($search)->andWhere('title')->like("%$search%")->fi()
|
||||
->beginIF($label)->andWhere('type')->eq($label)->fi()
|
||||
->beginIF($status)->andWhere('status')->in($storyStatus[$status])->fi()
|
||||
->andWhere('deleted')->eq(0)
|
||||
->fetchAll();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
$issues[] = array('id' => $story->id, 'type' => 'story', 'order' => $story->$order, 'status' => $this->getKey($story->status, $storyStatus));
|
||||
}
|
||||
|
||||
$bugs = $this->dao->select($bugFields)->from(TABLE_BUG)->where('product')->eq($productID)
|
||||
->beginIF($search)->andWhere('title')->like("%$search%")->fi()
|
||||
->beginIF($label)->andWhere('type')->eq($label)->fi()
|
||||
->beginIF($status)->andWhere('status')->in($bugStatus[$status])->fi()
|
||||
->andWhere('deleted')->eq(0)
|
||||
->fetchAll();
|
||||
foreach($bugs as $bug)
|
||||
{
|
||||
$issues[] = array('id' => $bug->id, 'type' => 'bug', 'order' => $bug->$order, 'status' => $this->getKey($bug->status, $bugStatus));
|
||||
}
|
||||
|
||||
array_multisort(array_column($issues, 'order'), $sort == 'asc' ? SORT_ASC : SORT_DESC, $issues);
|
||||
$total = count($issues);
|
||||
$issues = $page < 1 ? array() : array_slice($issues, ($page-1) * $limit, $limit);
|
||||
|
||||
$result = $this->processIssues($issues);
|
||||
$this->send(200, array('page' => $page, 'total' => $total, 'limit' => $limit, 'issues' => $result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process issues, format fields.
|
||||
*
|
||||
* @param array $issues
|
||||
* @param int $page
|
||||
* @param int $limit
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function processIssues($issues)
|
||||
{
|
||||
$this->app->loadLang('task');
|
||||
$this->app->loadLang('story');
|
||||
$this->app->loadLang('bug');
|
||||
|
||||
$this->loadModel('entry');
|
||||
|
||||
$tasks = array();
|
||||
$stories = array();
|
||||
$bugs = array();
|
||||
foreach($issues as $issue)
|
||||
{
|
||||
if($issue['type'] == 'story') $stories[] = $issue['id'];
|
||||
if($issue['type'] == 'task') $tasks[] = $issue['id'];
|
||||
if($issue['type'] == 'bug') $bugs[] = $issue['id'];
|
||||
}
|
||||
|
||||
if(!empty($tasks)) $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('id')->in($tasks)->fetchAll('id');
|
||||
if(!empty($stories)) $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($stories)->fetchAll('id');
|
||||
if(!empty($bugs)) $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($bugs)->fetchAll('id');
|
||||
|
||||
$result = array();
|
||||
foreach($issues as $issue)
|
||||
{
|
||||
$r = new stdclass();
|
||||
if($issue['type'] == 'task')
|
||||
{
|
||||
$task = $tasks[$issue['id']];
|
||||
|
||||
$r->id = 'task-' . $task->id;
|
||||
$r->title = $task->name;
|
||||
$r->labels = array($this->app->lang->task->common, zget($this->app->lang->task->typeList, $task->type));
|
||||
$r->pri = $task->pri;
|
||||
$r->assignedTo = $this->entry->getAssignees('task', $task);
|
||||
$r->openedDate = $task->openedDate;
|
||||
$r->openedBy = $this->entry->getUser($task->openedBy);
|
||||
$r->lastEditedDate = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedDate : $task->lastEditedDate;
|
||||
$r->lastEditedBy = $task->lastEditedDate < '1970-01-01 01:01:01' ? $task->openedBy : $task->lastEditedBy;
|
||||
$r->status = $issue['status'];
|
||||
$r->url = helper::createLink('task', 'view', "taskID=$task->id");
|
||||
}
|
||||
else if($issue['type'] == 'story')
|
||||
{
|
||||
$story = $stories[$issue['id']];
|
||||
|
||||
$r->id = 'story-' . $story->id;
|
||||
$r->title = $story->title;
|
||||
$r->labels = array($this->app->lang->story->common, zget($this->app->lang->story->categoryList, $story->category));
|
||||
$r->pri = $story->pri;
|
||||
$r->assignedTo = $this->entry->getAssignees('story', $story);
|
||||
$r->openedDate = $story->openedDate;
|
||||
$r->openedBy = $this->entry->getUser($story->openedBy);
|
||||
$r->lastEditedDate = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedDate : $story->lastEditedDate;
|
||||
$r->lastEditedBy = $story->lastEditedDate < '1970-01-01 01:01:01' ? $story->openedBy : $story->lastEditedBy;
|
||||
$r->status = $issue['status'];
|
||||
$r->url = helper::createLink('story', 'view', "storyID=$story->id");
|
||||
}
|
||||
else if($issue['type'] == 'bug')
|
||||
{
|
||||
$bug = $bugs[$issue['id']];
|
||||
|
||||
$r->id = 'bug-' . $bug->id;
|
||||
$r->title = $bug->title;
|
||||
$r->labels = array($this->app->lang->bug->common, zget($this->app->lang->bug->typeList, $bug->type));
|
||||
$r->pri = $bug->pri;
|
||||
$r->assignedTo = $this->entry->getAssignees('bug', $bug);
|
||||
$r->openedDate = $bug->openedDate;
|
||||
$r->openedBy = $this->entry->getUser($bug->openedBy);
|
||||
$r->lastEditedDate = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedDate : $bug->lastEditedDate;
|
||||
$r->lastEditedBy = $bug->lastEditedDate < '1970-01-01 01:01:01' ? $bug->openedBy : $bug->lastEditedBy;
|
||||
$r->status = $issue['status'];
|
||||
$r->url = helper::createLink('bug', 'view', "bugID=$bug->id");
|
||||
}
|
||||
|
||||
$result[] = $this->format($r, 'openedDate:time,lastEditedDate:time');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get key in array by value.
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $array
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function getKey($value, $array)
|
||||
{
|
||||
foreach($array as $key => $values)
|
||||
{
|
||||
if($values and strpos($values, $value) !== FALSE) return $key;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -11,18 +11,18 @@ class projectsEntry extends entry
|
||||
public function get()
|
||||
{
|
||||
$control = $this->loadController('project', 'browse');
|
||||
$control->browse();
|
||||
$control->browse(0, $this->param('status', 'all'), 0, $this->param('order', 'order_asc'), 0, $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
{
|
||||
$pager = $data->data->pager;
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($data->data->projectStats as $project)
|
||||
{
|
||||
$result[] = $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'projects' => $result));
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => (int)$pager->recPerPage, 'projects' => $result));
|
||||
}
|
||||
|
||||
if(isset($data->status) and $data->status == 'fail')
|
||||
|
||||
@@ -11,7 +11,7 @@ class storiesEntry extends entry
|
||||
public function get($productID)
|
||||
{
|
||||
$control = $this->loadController('product', 'browse');
|
||||
$control->browse($productID);
|
||||
$control->browse($productID, $this->param('branch', 0), $this->param('type', ''), 0, 'story', $this->param('order', ''), $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
|
||||
@@ -11,7 +11,7 @@ class tasksEntry extends entry
|
||||
public function get($executionID)
|
||||
{
|
||||
$control = $this->loadController('execution', 'task');
|
||||
$control->task($executionID, 'all');
|
||||
$control->task($executionID, $this->param('status', 'all'), 0, $this->param('order', ''), $this->param('total', 0), $this->param('limit', 100), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(isset($data->status) and $data->status == 'success')
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
|
||||
if(!function_exists('getWebRoot')){function getWebRoot(){}}
|
||||
|
||||
/* 基本设置。Basic settings. */
|
||||
$config->version = '15.2'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
|
||||
$config->version = '15.3'; // 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.
|
||||
@@ -109,7 +109,7 @@ $config->framework->purifier = true; // 是否对数据做purifier处理
|
||||
$config->framework->logDays = 14; // 日志文件保存的天数。 The days to save log files.
|
||||
$config->framework->autoRepairTable = true;
|
||||
$config->framework->autoLang = false;
|
||||
$config->framework->filterCSRF = false;
|
||||
$config->framework->filterCSRF = true;
|
||||
$config->framework->setCookieSecure = true;
|
||||
$config->framework->sendXCTO = true; // Send X-Content-Type-Options header.
|
||||
$config->framework->sendXXP = true; // Send X-XSS-Protection header.
|
||||
|
||||
@@ -36,6 +36,7 @@ $filter->branch = new stdclass();
|
||||
$filter->qa = new stdclass();
|
||||
$filter->story = new stdclass();
|
||||
$filter->task = new stdclass();
|
||||
$filter->execution = new stdclass();
|
||||
$filter->testcase = new stdclass();
|
||||
$filter->program = new stdclass();
|
||||
$filter->project = new stdclass();
|
||||
@@ -57,6 +58,7 @@ $filter->git = new stdclass();
|
||||
$filter->svn = new stdclass();
|
||||
$filter->search = new stdclass();
|
||||
$filter->gitlab = new stdclass();
|
||||
$filter->ci = new stdclass();
|
||||
|
||||
$filter->block->default = new stdclass();
|
||||
$filter->block->main = new stdclass();
|
||||
@@ -112,6 +114,7 @@ $filter->svn->cat = new stdclass();
|
||||
$filter->svn->diff = new stdclass();
|
||||
$filter->task->create = new stdclass();
|
||||
$filter->task->export = new stdclass();
|
||||
$filter->execution->story = new stdclass();
|
||||
$filter->testcase->default = new stdclass();
|
||||
$filter->testcase->create = new stdclass();
|
||||
$filter->testcase->browse = new stdclass();
|
||||
@@ -133,6 +136,7 @@ $filter->repo->ajaxsynccommit = new stdclass();
|
||||
$filter->search->index = new stdclass();
|
||||
$filter->gitlab->webhook = new stdclass();
|
||||
$filter->gitlab->importissue = new stdclass();
|
||||
$filter->ci->checkCompileStatus = new stdclass();
|
||||
|
||||
$filter->bug->batchcreate->cookie['preBranch'] = 'int';
|
||||
$filter->bug->browse->cookie['bugModule'] = 'int';
|
||||
@@ -187,6 +191,7 @@ $filter->project->default->cookie['lastProject'] = 'int';
|
||||
$filter->project->default->cookie['lastPRJ'] = 'int';
|
||||
$filter->project->default->cookie['projectMode'] = 'code';
|
||||
$filter->project->browse->cookie['involved'] = 'code';
|
||||
$filter->project->browse->cookie['projectType'] = 'code';
|
||||
$filter->project->story->cookie['storyModuleParam'] = 'int';
|
||||
$filter->project->story->cookie['storyPreProjectID'] = 'int';
|
||||
$filter->project->story->cookie['storyProductParam'] = 'int';
|
||||
@@ -212,6 +217,12 @@ $filter->story->export->cookie['checkedItem'] = 'reg::checked';
|
||||
$filter->task->create->cookie['lastTaskModule'] = 'int';
|
||||
$filter->task->export->cookie['checkedItem'] = 'reg::checked';
|
||||
|
||||
$filter->execution->story->cookie['storyPreExecutionID'] = 'int';
|
||||
$filter->execution->story->cookie['storyModuleParam'] = 'int';
|
||||
$filter->execution->story->cookie['storyProductParam'] = 'int';
|
||||
$filter->execution->story->cookie['storyBranchParam'] = 'int';
|
||||
$filter->execution->story->cookie['executionStoryOrder'] = 'code';
|
||||
|
||||
$filter->testcase->browse->cookie['caseModule'] = 'int';
|
||||
$filter->testcase->browse->cookie['caseSuite'] = 'int';
|
||||
$filter->testcase->browse->cookie['preBranch'] = 'int';
|
||||
@@ -323,3 +334,4 @@ $filter->gitlab->importissue->get['product'] = 'string';
|
||||
$filter->gitlab->importissue->get['project'] = 'int';
|
||||
$filter->gitlab->importissue->get['repo'] = 'int';
|
||||
|
||||
$filter->ci->checkCompileStatus->get['gitlabOnly'] = 'string';
|
||||
|
||||
+4
-1
@@ -33,9 +33,12 @@ $routes['/tasks/:id/finish'] = 'taskFinish';
|
||||
|
||||
$routes['/users'] = 'users';
|
||||
$routes['/users/:id'] = 'user';
|
||||
$routes['/user'] = 'user';
|
||||
$routes['/my'] = 'my';
|
||||
|
||||
$routes['/programs'] = 'programs';
|
||||
$routes['/programs/:id'] = 'program';
|
||||
|
||||
$routes['/issues/:issueID'] = 'projectIssue';
|
||||
$routes['/projects/:projectID/issues'] = 'projectIssues';
|
||||
|
||||
$config->routes = $routes;
|
||||
|
||||
@@ -98,8 +98,8 @@ $config->hourPointCommonList['vi'][0] = 'giờ';
|
||||
$config->hourPointCommonList['vi'][1] = 'điểm';
|
||||
$config->hourPointCommonList['vi'][2] = 'function point';
|
||||
|
||||
$config->manualUrl['home'] = 'https://www.zentao.net/book/zentaopmshelp.html?fullScreen=zentao';
|
||||
$config->manualUrl['int'] = 'https://www.zentao.pm/book/zentaomanual/zentao-installation-11.html?fullScreen=zentao';
|
||||
$config->manualUrl['home'] = 'https://www.zentao.net/book/zentaopmshelp.html?fullScreen=zentao&theme=' . $_COOKIE['theme'];
|
||||
$config->manualUrl['int'] = 'https://www.zentao.pm/book/zentaomanual/zentao-installation-11.html?fullScreen=zentao&theme=' . $_COOKIE['theme'];
|
||||
|
||||
/* Supported charsets. */
|
||||
$config->charsets['zh-cn']['utf-8'] = 'UTF-8';
|
||||
@@ -137,6 +137,8 @@ $config->openMethods[] = 'sso.gettodolist';
|
||||
$config->openMethods[] = 'file.read';
|
||||
$config->openMethods[] = 'index.changelog';
|
||||
$config->openMethods[] = 'my.preference';
|
||||
$config->openMethods[] = 'my.changepassword';
|
||||
$config->openMethods[] = 'my.profile';
|
||||
|
||||
/* Define the tables. */
|
||||
define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`');
|
||||
@@ -226,6 +228,7 @@ if(!defined('TABLE_SEARCHDICT')) define('TABLE_SEARCHDICT', $config->db->prefi
|
||||
$config->objectTables['product'] = TABLE_PRODUCT;
|
||||
$config->objectTables['productplan'] = TABLE_PRODUCTPLAN;
|
||||
$config->objectTables['story'] = TABLE_STORY;
|
||||
$config->objectTables['requirement'] = TABLE_STORY;
|
||||
$config->objectTables['release'] = TABLE_RELEASE;
|
||||
$config->objectTables['program'] = TABLE_PROJECT;
|
||||
$config->objectTables['project'] = TABLE_PROJECT;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,3 +3,6 @@ ADD `engine` varchar(20) NOT NULL AFTER `frame`,
|
||||
CHANGE `jkHost` `server` mediumint(0) UNSIGNED NOT NULL AFTER `frame`,
|
||||
CHANGE `jkJob` `pipeline` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL AFTER `server`;
|
||||
|
||||
UPDATE `zt_job` SET `engine` = 'jenkins' WHERE `engine` = '';
|
||||
UPDATE `zt_cron` SET `remark` = '执行DevOps构建任务' WHERE `remark` = '执行Jenkins任务';
|
||||
UPDATE `zt_cron` SET `remark` = '同步DevOps构建任务状态' WHERE `remark` = '同步Jenkins任务状态';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE `zt_testtask` ADD `realFinishedDate` datetime NOT NULL AFTER `end`;
|
||||
+15
-3
@@ -858,7 +858,7 @@ CREATE TABLE IF NOT EXISTS `zt_searchdict` (
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||
-- DROP TABLE IF EXISTS `zt_searchindex`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_searchindex` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`objectType` char(20) NOT NULL,
|
||||
`objectID` mediumint(9) NOT NULL,
|
||||
`title` text NOT NULL,
|
||||
@@ -1153,6 +1153,7 @@ CREATE TABLE IF NOT EXISTS `zt_testtask` (
|
||||
`pri` tinyint(3) unsigned NOT NULL default '0',
|
||||
`begin` date NOT NULL,
|
||||
`end` date NOT NULL,
|
||||
`realFinishedDate` datetime NOT NULL,
|
||||
`mailto` text,
|
||||
`desc` text NOT NULL,
|
||||
`report` text NOT NULL,
|
||||
@@ -1325,8 +1326,8 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=admin&methodName=deleteLog', '删除过期日志', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('1', '0', '*', '*', '*', 'moduleName=ci&methodName=initQueue', '创建周期性任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkCompileStatus', '同步Jenkins任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行Jenkins任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkCompileStatus', '同步DevOps构建任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'),
|
||||
('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行DevOps构建任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
|
||||
INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
|
||||
(1, 'ADMIN', 'admin', 'for administrator'),
|
||||
@@ -1445,6 +1446,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1,'doc','edit'),
|
||||
(1,'doc','editLib'),
|
||||
(1,'doc','index'),
|
||||
(1,'doc','tableContents'),
|
||||
(1,'doc','objectLibs'),
|
||||
(1,'doc','showFiles'),
|
||||
(1,'doc','sort'),
|
||||
@@ -1860,6 +1862,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(2,'doc','create'),
|
||||
(2,'doc','edit'),
|
||||
(2,'doc','index'),
|
||||
(2,'doc','tableContents'),
|
||||
(2,'doc','objectLibs'),
|
||||
(2,'doc','showFiles'),
|
||||
(2,'doc','view'),
|
||||
@@ -2055,6 +2058,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(3,'doc','create'),
|
||||
(3,'doc','edit'),
|
||||
(3,'doc','index'),
|
||||
(3,'doc','tableContents'),
|
||||
(3,'doc','objectLibs'),
|
||||
(3,'doc','showFiles'),
|
||||
(3,'doc','view'),
|
||||
@@ -2305,6 +2309,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(4,'doc','edit'),
|
||||
(4,'doc','editLib'),
|
||||
(4,'doc','index'),
|
||||
(4,'doc','tableContents'),
|
||||
(4,'doc','objectLibs'),
|
||||
(4,'doc','showFiles'),
|
||||
(4,'doc','view'),
|
||||
@@ -2599,6 +2604,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(5,'doc','edit'),
|
||||
(5,'doc','editLib'),
|
||||
(5,'doc','index'),
|
||||
(5,'doc','tableContents'),
|
||||
(5,'doc','objectLibs'),
|
||||
(5,'doc','showFiles'),
|
||||
(5,'doc','view'),
|
||||
@@ -2921,6 +2927,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(6,'doc','edit'),
|
||||
(6,'doc','editLib'),
|
||||
(6,'doc','index'),
|
||||
(6,'doc','tableContents'),
|
||||
(6,'doc','objectLibs'),
|
||||
(6,'doc','showFiles'),
|
||||
(6,'doc','view'),
|
||||
@@ -3197,6 +3204,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(7,'doc','edit'),
|
||||
(7,'doc','editLib'),
|
||||
(7,'doc','index'),
|
||||
(7,'doc','tableContents'),
|
||||
(7,'doc','objectLibs'),
|
||||
(7,'doc','showFiles'),
|
||||
(7,'doc','view'),
|
||||
@@ -3485,6 +3493,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(8,'doc','edit'),
|
||||
(8,'doc','editLib'),
|
||||
(8,'doc','index'),
|
||||
(8,'doc','tableContents'),
|
||||
(8,'doc','objectLibs'),
|
||||
(8,'doc','showFiles'),
|
||||
(8,'doc','view'),
|
||||
@@ -3768,6 +3777,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(9,'doc','edit'),
|
||||
(9,'doc','editLib'),
|
||||
(9,'doc','index'),
|
||||
(9,'doc','tableContents'),
|
||||
(9,'doc','objectLibs'),
|
||||
(9,'doc','showFiles'),
|
||||
(9,'doc','view'),
|
||||
@@ -3980,6 +3990,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(10,'doc','allLibs'),
|
||||
(10,'doc','browse'),
|
||||
(10,'doc','index'),
|
||||
(10,'doc','tableContents'),
|
||||
(10,'doc','objectLibs'),
|
||||
(10,'doc','showFiles'),
|
||||
(10,'doc','view'),
|
||||
@@ -4101,6 +4112,7 @@ INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(11,'doc','allLibs'),
|
||||
(11,'doc','browse'),
|
||||
(11,'doc','index'),
|
||||
(11,'doc','tableContents'),
|
||||
(11,'doc','objectLibs'),
|
||||
(11,'doc','showFiles'),
|
||||
(11,'doc','view'),
|
||||
|
||||
+106
-1
@@ -1,3 +1,108 @@
|
||||
2021-08-04 15.3
|
||||
完成的需求
|
||||
27092 文档下拉菜单中增加附件库的选择
|
||||
26857 禅道右下角显示禅道版本号方便商务支持同事排查问题节省交互时间
|
||||
26773 在文档全屏的时候显示上一篇、下一篇的操作
|
||||
26772 文档增加全屏查看功能
|
||||
26771 文档大纲支持展开/收起功能
|
||||
26770 文档详情页面增加文档大纲功能
|
||||
15718 项目集列表中,负责人名称前显示头像
|
||||
26766 目录的操作按钮放置到目录页面的右侧
|
||||
26765 对创建下拉菜单中的内容进行分组
|
||||
26764 在具体的文档库页面增加我的收藏快速入口
|
||||
26763 文档库增加目录页面
|
||||
26469 文档名称的font-size使用20px
|
||||
26467 编辑文档页面,去掉三级导航
|
||||
26465 创建文档页面,去掉三级导航
|
||||
26463 手册模块中增加目录的高度
|
||||
26461 文档模块中增加目录信息
|
||||
26400 创建文档名称调整为创建
|
||||
26768 将关键词作为标签放到文档名称下面
|
||||
27489 实现附件库的卡片展示方式
|
||||
27488 实现附件库的列表展示方式
|
||||
27477 执行二级导航中执行名称前显示项目名称
|
||||
27476 禅道升级新版本后,引导用户使用青春蓝的主题
|
||||
27474 禅道更新全新icon
|
||||
27433 禅道新增配色样式
|
||||
27432 实现项目卡片展示方式
|
||||
27098 项目库下拉菜单中可以搜索和查看已结束的项目文档
|
||||
27430 项目列表增加卡片视图的切换方式
|
||||
27429 调整产品列表中字段的显示顺序
|
||||
27428 产品列表中增加项目集、产品线列表的数据统计
|
||||
27427 产品列表中将编辑产品线调整到添加产品按钮前面
|
||||
27426 项目集列表中项目名称前的项目icon调整为模型icon
|
||||
27425 项目集列表增加进度显示
|
||||
27424 调整项目集列表中字段的显示顺序
|
||||
27421 项目集列表调整项目和项目集添加方式的位置
|
||||
27389 任务bug列表把截止日期展示出来
|
||||
27270 升级程序中的sql需要兼容引擎只支持innodb的环境
|
||||
27260 文档目录中在具体的文档前面增加icon
|
||||
27431 项目卡片视图中增加项目集筛选菜单
|
||||
修复的Bug
|
||||
11198 升级到旗舰版后系统用户默认权限没有添加导致用户登录后无法正常访问
|
||||
12197 项目下新建文档保存后页面未正确展示
|
||||
12318 max2.0rc1 关于工作流:1.字段-公示类型的,无法生效 2.详情 动作界面,编辑--区块,无法添加
|
||||
12573 客户端消息右键创建任务页面所属执行没有列出阶段
|
||||
12846 word类型文档编辑页面文档类型没有默认值
|
||||
13141 新版本动作界面附件字段不显示
|
||||
13386 biz4.1按老版本习惯升级后,待办转任务未关联处项目数据
|
||||
13460 工作流项目流程字段和动作展示问题
|
||||
13536 请假详情页点击拒绝后跳转到了编辑页
|
||||
13039 任务看板导出和页面显示内容不一致
|
||||
13092 所有产品、项目不支持导出
|
||||
13377 pro7.1按老版本习惯升级后,新建产品保存时有错误提示信息
|
||||
12807 数据量多的时候创建索引时间很久
|
||||
12476 客户端中进入禅道相关页面加载错误
|
||||
12930 年底统计报表中需求创建数量不对
|
||||
13420 集成gitlab后查看代码页面报错
|
||||
13638 gitlab类型的版本库页面有代码报错
|
||||
13639 关联issue页面有代码报错
|
||||
13722 执行动态页面报错
|
||||
13647 创建需求、任务、Bug同步到gitlab,有js报错
|
||||
11269 beta3中有测试代码导致报错
|
||||
12412 主表设计下载的模板全是报错
|
||||
12422 主表字段导入确认页面显示问题
|
||||
12673 干系人相关动态文案需修改
|
||||
12928 权限分组列表显示的数据不全
|
||||
13059 创建的scrum项目无法保存
|
||||
13096 项目矩阵显示了与该项目无关的需求
|
||||
13097 任务不能记录日志
|
||||
13238 问题确认弹窗显示异常,无法操作
|
||||
13239 问题解决方式为转任务后,保存提示开始时间不能为空
|
||||
13278 旗舰版新增工作流发布在执行二级导航时,页面跳转有问题
|
||||
13332 瀑布模式单独创建阶段还需要维护阶段代号
|
||||
13346 通过阶段设置插入阶段会修改之前阶段的ID
|
||||
13512 评审页面查看用例所属的产品时闪现代码
|
||||
13523 集成测试用例评审页面查看用例时有代码报错
|
||||
13530 自定义配置的模板类型发起评审时也列出来了
|
||||
13532 评审用户需求说明书页面有代码报错
|
||||
13538 评审软件需求说明书页面有代码报错
|
||||
13717 给瀑布项目会显示“所属迭代”
|
||||
13486 创建FAQ页面有代码报错
|
||||
13559 项目内置流程新增字段在列表不显示
|
||||
13608 工作流新增字段默认值设置不生效
|
||||
12201 统计里报表涉及到项目的都显示为执行了
|
||||
13213 专业版App发布详情页有报错
|
||||
13243 变更需求导出 word 最后编辑日期为 0000-00-00
|
||||
13244 需求导出 word 展示模块取值错误
|
||||
13258 需求导出 word 图片大小适配问题
|
||||
13265 产品项目列表的迭代改为项目
|
||||
13564 自定义报表中项目计划完成日期统计有问题
|
||||
13724 移动端需求排序报错
|
||||
12106 批量编辑需求阶段显示报错
|
||||
13716 权限名称和对应页面菜单名字不一致
|
||||
6900 搜索用户名时,不显示用户名信息
|
||||
13045 新建产品是否需要强制关联产品规则统一
|
||||
13216 php5.3环境代码兼容问题
|
||||
13516 早上在执行下面操作完成第一个任务后会提示你无权限访问该迭代
|
||||
13616 再次编辑飞书配置时丢失秘钥
|
||||
13632 测试单中查看报表报错
|
||||
13659 测试单生成报表报错
|
||||
13701 批量编辑任务页面起止日期字段显示不全
|
||||
13703 甘特图百分比统计错误
|
||||
13721 按老版本习惯升级后,jenkins服务器数据丢失
|
||||
13725 测试-用例-导出模板-CSV文件名字拼错
|
||||
|
||||
2021-07-20 15.2
|
||||
完成的需求
|
||||
27297 调整产品下拉菜单信息展现方式
|
||||
@@ -2122,7 +2227,7 @@
|
||||
1601 版本列表区块,版本ID显示为1、2,统一为001、002
|
||||
1600 Bug详情页,解决操作没有图标,严重程度图标数字太靠上
|
||||
1599 右上角,用户名--切换语言。显示的是英文 language ,简体和繁体下应显示为中文
|
||||
1597 永久关闭区块的提示文案,第二句开头少一个‘关’字,最后少个句号 [BUG#1597]
|
||||
1597 永久关闭区块的提示文案,第二句开头少一个‘关’字,最后少个句号
|
||||
1595 我的地盘里,编辑页面的 保存和取消 按钮的间距宽度比较宽,是否整个系统里统一一下保存和取消(返回)的间距宽度
|
||||
1592 我的待办区块,添加待办成功后,跳转到区块底部
|
||||
1591 我的待办区块,点击待办名称,然后编辑,待办名称必填项与边框有重叠
|
||||
|
||||
@@ -10,6 +10,8 @@ class entry extends baseEntry
|
||||
parent::__construct();
|
||||
|
||||
if(!isset($this->app->user)) $this->sendError(401, 'Unauthorized');
|
||||
|
||||
$this->dao = $this->loadModel('common')->dao;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +49,9 @@ class baseEntry
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
global $app;
|
||||
$this->app = $app;
|
||||
global $app, $config;
|
||||
$this->app = $app;
|
||||
$this->config = $config;
|
||||
|
||||
$this->parseRequestBody();
|
||||
}
|
||||
@@ -83,6 +86,20 @@ class baseEntry
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求参数
|
||||
* Set request param.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public function setParam($key, $value)
|
||||
{
|
||||
$_GET[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析请求数据
|
||||
* Parse body of request data.
|
||||
@@ -202,6 +219,17 @@ class baseEntry
|
||||
$this->send($code, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send 404 response.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function send404()
|
||||
{
|
||||
$this->sendError(404, '404 Not found');
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载禅道的控制器类
|
||||
* Load controller of zentaopms
|
||||
@@ -305,9 +333,8 @@ class baseEntry
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
$output = ob_get_clean();
|
||||
$output = helper::removeUTF8Bom(ob_get_clean());
|
||||
$output = json_decode($output);
|
||||
|
||||
if(isset($output->data)) $output->data = json_decode($output->data);
|
||||
|
||||
return $output;
|
||||
@@ -476,9 +503,8 @@ class baseEntry
|
||||
return gmdate("Y-m-d\TH:i:s\Z", strtotime($value));
|
||||
}
|
||||
return $value;
|
||||
case 'int':
|
||||
case 'bool':
|
||||
return $value;
|
||||
return boolval($value) ? true : false;
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
/**
|
||||
* ZenTaoAPI的helper类。
|
||||
* The helper class file of ZenTao API.
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
*/
|
||||
include dirname(dirname(__FILE__)) . '/base/helper.class.php';
|
||||
class helper extends baseHelper
|
||||
{
|
||||
public static function getViewType($source = false)
|
||||
{
|
||||
global $config, $app;
|
||||
if($config->requestType != 'GET')
|
||||
{
|
||||
$pathInfo = $app->getPathInfo();
|
||||
if(!empty($pathInfo))
|
||||
{
|
||||
$dotPos = strrpos($pathInfo, '.');
|
||||
if($dotPos)
|
||||
{
|
||||
$viewType = substr($pathInfo, $dotPos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif($config->requestType == 'GET')
|
||||
{
|
||||
if(isset($_GET[$config->viewVar]))
|
||||
{
|
||||
$viewType = $_GET[$config->viewVar];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set default view when url has not module name. such as only domain. */
|
||||
$config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view;
|
||||
}
|
||||
}
|
||||
if($source and isset($viewType)) return $viewType;
|
||||
|
||||
if(isset($viewType) and strpos($config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view;
|
||||
return isset($viewType) ? $viewType : $config->default->view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode json for $.parseJSON
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $options
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function jsonEncode4Parse($data, $options = 0)
|
||||
{
|
||||
$json = json_encode($data);
|
||||
if($options) $json = str_replace(array("'", '"'), array('\u0027', '\u0022'), $json);
|
||||
|
||||
$escapers = array("\\", "/", "\"", "'", "\n", "\r", "\t", "\x08", "\x0c", "\\\\u");
|
||||
$replacements = array("\\\\", "\\/", "\\\"", "\'", "\\n", "\\r", "\\t", "\\f", "\\b", "\\u");
|
||||
return str_replace($escapers, $replacements, $json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert encoding.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $fromEncoding
|
||||
* @param string $toEncoding
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function convertEncoding($string, $fromEncoding, $toEncoding = 'utf-8')
|
||||
{
|
||||
$toEncoding = str_replace('utf8', 'utf-8', $toEncoding);
|
||||
if(function_exists('mb_convert_encoding'))
|
||||
{
|
||||
/* Remove like utf-8//TRANSLIT. */
|
||||
$position = strpos($toEncoding, '//');
|
||||
if($position !== false) $toEncoding = substr($toEncoding, 0, $position);
|
||||
|
||||
/* Check string encoding. */
|
||||
$encodings = array_merge(array('GB2312','GBK','BIG5'), mb_list_encodings());
|
||||
$encoding = strtolower(mb_detect_encoding($string, $encodings));
|
||||
if($encoding == $toEncoding) return $string;
|
||||
return mb_convert_encoding($string, $toEncoding, $encoding);
|
||||
}
|
||||
elseif(function_exists('iconv'))
|
||||
{
|
||||
if($fromEncoding == $toEncoding) return $string;
|
||||
$convertString = @iconv($fromEncoding, $toEncoding, $string);
|
||||
/* iconv error then return original. */
|
||||
if(!$convertString) return $string;
|
||||
return $convertString;
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate two working days.
|
||||
*
|
||||
* @param string $begin
|
||||
* @param string $end
|
||||
*
|
||||
* @return bool|float
|
||||
*/
|
||||
public static function workDays($begin, $end)
|
||||
{
|
||||
$begin = strtotime($begin);
|
||||
$end = strtotime($end);
|
||||
if($end < $begin) return false;
|
||||
|
||||
$double = floor(($end - $begin) / (7 * 24 * 3600));
|
||||
$begin = date('w', $begin);
|
||||
$end = date('w', $end);
|
||||
$end = $begin > $end ? $end + 5 : $end;
|
||||
return $double * 5 + $end - $begin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unify string to standard chars.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $to
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public static function unify($string, $to = ',')
|
||||
{
|
||||
$labels = array('_', '、', ' ', '-', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', ',', '。');
|
||||
$string = str_replace($labels, $to, $string);
|
||||
return preg_replace("/[{$to}]+/", $to, trim($string, $to));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create url of issue.
|
||||
*
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param string $vars
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlyBody = false)
|
||||
{
|
||||
global $config;
|
||||
$link = parent::createLink($moduleName, $methodName, $vars, 'html');
|
||||
$pos = strpos($link, '.php');
|
||||
|
||||
/* The requestTypes are: GET, PATH_INFO2, PATH_INFO */
|
||||
if($config->requestType == 'GET')
|
||||
{
|
||||
$link = '/index' . substr($link, $pos);
|
||||
}
|
||||
elseif($config->requestType == 'PATH_INFO2')
|
||||
{
|
||||
$link = substr($link, $pos + 4);
|
||||
}
|
||||
return common::getSysURL() . $link;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否是onlybody模式。
|
||||
* Check exist onlybody param.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function isonlybody()
|
||||
{
|
||||
return helper::inOnlyBodyMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time.
|
||||
*
|
||||
* @param int $time
|
||||
* @param string $format
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function formatTime($time, $format = '')
|
||||
{
|
||||
$time = str_replace('0000-00-00', '', $time);
|
||||
$time = str_replace('00:00:00', '', $time);
|
||||
if(trim($time) == '') return ;
|
||||
if($format) return date($format, strtotime($time));
|
||||
return trim($time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix for session error.
|
||||
*
|
||||
* @param int $class
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
function autoloader($class)
|
||||
{
|
||||
if(!class_exists($class))
|
||||
{
|
||||
if($class == 'post_max_size' or $class == 'max_input_vars') eval('class ' . $class . ' {};');
|
||||
}
|
||||
}
|
||||
|
||||
spl_autoload_register('autoloader');
|
||||
@@ -843,7 +843,7 @@ function getWebRoot($full = false)
|
||||
|
||||
/**
|
||||
* 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。
|
||||
* When the $var has the $key, return it, esle result one default value.
|
||||
* When there is a $key in the array/object $var, it returns it or $valueWhenExists, otherwise returns $key or $valueWhenNone.
|
||||
*
|
||||
* @param array|object $var
|
||||
* @param string|int $key
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
@@ -17,7 +17,7 @@ class baseModel
|
||||
/**
|
||||
* 全局对象$app。
|
||||
* The global $app object.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -26,7 +26,7 @@ class baseModel
|
||||
/**
|
||||
* 应用名称$appName。
|
||||
* The global appName.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
@@ -35,7 +35,7 @@ class baseModel
|
||||
/**
|
||||
* 全局对象$config。
|
||||
* The global $config object.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ class baseModel
|
||||
/**
|
||||
* 全局对象$lang。
|
||||
* The global $lang object.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -53,7 +53,7 @@ class baseModel
|
||||
/**
|
||||
* 全局对象$dbh,数据库连接句柄。
|
||||
* The global $dbh object, the database connection handler.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ class baseModel
|
||||
/**
|
||||
* $dao对象,用于访问或者更新数据库。
|
||||
* The $dao object, used to access or update database.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -71,7 +71,7 @@ class baseModel
|
||||
/**
|
||||
* $post对象,用于访问$_POST变量。
|
||||
* The $post object, used to access the $_POST var.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -80,7 +80,7 @@ class baseModel
|
||||
/**
|
||||
* $get对象,用于访问$_GET变量。
|
||||
* The $get object, used to access the $_GET var.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -89,7 +89,7 @@ class baseModel
|
||||
/**
|
||||
* $session对象,用于访问$_SESSION变量。
|
||||
* The $session object, used to access the $_SESSION var.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -98,7 +98,7 @@ class baseModel
|
||||
/**
|
||||
* $server对象,用于访问$_SERVER变量。
|
||||
* The $server object, used to access the $_SERVER var.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -107,7 +107,7 @@ class baseModel
|
||||
/**
|
||||
* $cookie对象,用于访问$_COOKIE变量。
|
||||
* The $cookie object, used to access the $_COOKIE var.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -116,7 +116,7 @@ class baseModel
|
||||
/**
|
||||
* $global对象,用于访问$_GLOBAL变量。
|
||||
* The $global object, used to access the $_GLOBAL var.
|
||||
*
|
||||
*
|
||||
* @var object
|
||||
* @access public
|
||||
*/
|
||||
@@ -126,12 +126,12 @@ class baseModel
|
||||
* 构造方法。
|
||||
* 1. 将全局变量设为model类的成员变量,方便model的派生类调用;
|
||||
* 2. 设置$config, $lang, $dbh, $dao。
|
||||
*
|
||||
*
|
||||
* The construct function.
|
||||
* 1. global the global vars, refer them by the class member such as $this->app.
|
||||
* 2. set the pathes, config, lang of current module
|
||||
*
|
||||
* @param string $appName
|
||||
* @param string $appName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -158,7 +158,7 @@ class baseModel
|
||||
* 这个方法通过去掉该model类名的'ext'和'model'字符串,来获取当前模块名。
|
||||
* 不要使用$app->getModuleName(),因为其返回的是用户请求的模块名。
|
||||
* 另一个model可以通过loadModel()加载进来,与请求的模块名不一致。
|
||||
*
|
||||
*
|
||||
* Get the module name of this model. Not the module user visiting.
|
||||
*
|
||||
* This method replace the 'ext' and 'model' string from the model class name, thus get the module name.
|
||||
@@ -180,7 +180,7 @@ class baseModel
|
||||
/**
|
||||
* 设置全局超级变量。
|
||||
* Set the super vars.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -198,7 +198,7 @@ class baseModel
|
||||
* 比如:loadModel('user')引入user模块的model实例对象,可以通过$this->user来访问它。
|
||||
*
|
||||
* Load the model of one module. After loaded, can use $this->$moduleName to visit the model object.
|
||||
*
|
||||
*
|
||||
* @param string $moduleName
|
||||
* @access public
|
||||
* @return object|bool the model object or false if model file not exists.
|
||||
@@ -207,6 +207,7 @@ class baseModel
|
||||
{
|
||||
if(empty($moduleName)) return false;
|
||||
if(empty($appName)) $appName = $this->appName;
|
||||
$moduleName = strtolower($moduleName);
|
||||
|
||||
global $loadedModels;
|
||||
if(isset($loadedModels[$appName][$moduleName]))
|
||||
@@ -242,9 +243,9 @@ class baseModel
|
||||
* And call them by the ext/model/$extension.php like this: $this->loadExtension('myextension')->method().
|
||||
* You can encrypt the code in ext/model/class/*.class.php.
|
||||
* Because the framework will merge the extension files in ext/model/*.php to the module/model.php.
|
||||
*
|
||||
* @param string $extensionName
|
||||
* @param string $moduleName
|
||||
*
|
||||
* @param string $extensionName
|
||||
* @param string $moduleName
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -253,8 +254,9 @@ class baseModel
|
||||
if(empty($extensionName)) return false;
|
||||
|
||||
/* 设置扩展的名字和相应的文件。Set extenson name and extension file. */
|
||||
$extensionName = strtolower($extensionName);
|
||||
$moduleName = $moduleName ? $moduleName : $this->getModuleName();
|
||||
$moduleName = strtolower($moduleName);
|
||||
$extensionName = strtolower($extensionName);
|
||||
$moduleExtPath = $this->app->getModuleExtPath($this->appName, $moduleName, 'model');
|
||||
if(!empty($moduleExtPath['site'])) $extensionFile = $moduleExtPath['site'] . 'class/' . $extensionName . '.class.php';
|
||||
if(!isset($extensionFile) or !file_exists($extensionFile)) $extensionFile = $moduleExtPath['common'] . 'class/' . $extensionName . '.class.php';
|
||||
@@ -278,7 +280,7 @@ class baseModel
|
||||
/**
|
||||
* 加载DAO。
|
||||
* Load DAO.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -290,7 +292,7 @@ class baseModel
|
||||
/**
|
||||
* 删除记录。
|
||||
* Delete one record.
|
||||
*
|
||||
*
|
||||
* @param string $table the table name
|
||||
* @param string $id the id value of the record to be deleted
|
||||
* @access public
|
||||
|
||||
@@ -609,8 +609,12 @@ class baseRouter
|
||||
if($this->config->framework->filterCSRF)
|
||||
{
|
||||
$httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
|
||||
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https';
|
||||
if(isset($_SERVER['REQUEST_SCHEME']) and strtolower($_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https';
|
||||
|
||||
$httpHost = $_SERVER['HTTP_HOST'];
|
||||
if((!defined('RUN_MODE') or RUN_MODE != 'api') and strpos($this->server->http_referer, "$httpType://$httpHost") !== 0) $_FILES = $_POST = array();
|
||||
$isAPI = (defined('RUN_MODE') && RUN_MODE == 'api') || isset($_GET[$this->config->sessionVar]);
|
||||
if(!$isAPI && strpos($this->server->http_referer, "$httpType://$httpHost") !== 0) $_FILES = $_POST = array();
|
||||
}
|
||||
|
||||
$_FILES = validater::filterFiles();
|
||||
@@ -849,23 +853,22 @@ class baseRouter
|
||||
*/
|
||||
public function startSession()
|
||||
{
|
||||
if(!defined('SESSION_STARTED'))
|
||||
{
|
||||
/* If request header has token, use it as session for authentication. */
|
||||
if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']);
|
||||
if(defined('SESSION_STARTED')) return;
|
||||
|
||||
$sessionName = $this->config->sessionVar;
|
||||
session_name($sessionName);
|
||||
session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session');
|
||||
session_start();
|
||||
/* If request header has token, use it as session for authentication. */
|
||||
if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']);
|
||||
|
||||
$this->sessionID = session_id();
|
||||
$sessionName = $this->config->sessionVar;
|
||||
session_name($sessionName);
|
||||
session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session');
|
||||
session_start();
|
||||
|
||||
if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]);
|
||||
$this->sessionID = session_id();
|
||||
|
||||
define('SESSION_STARTED', true);
|
||||
}
|
||||
if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]);
|
||||
|
||||
define('SESSION_STARTED', true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+12
-13
@@ -513,11 +513,9 @@ class router extends baseRouter
|
||||
if($methodName == 'batchOperate') array_unshift($params, $this->rawMethod); // $params = array('close', 1);
|
||||
if($methodName == 'browse')
|
||||
{
|
||||
if(!(isset($params[0]) and $params[0] == 'bysearch'))
|
||||
{
|
||||
array_unshift($params, 'browse');
|
||||
}
|
||||
if(!(isset($params[0]) and $params[0] == 'bysearch')) array_unshift($params, 'browse');
|
||||
}
|
||||
|
||||
array_unshift($params, $this->rawModule); // $params = array($module, 'close', 1);
|
||||
array_unshift($params, $methodName); // $params = array('operate', $module, 'close', 1);
|
||||
array_unshift($params, $moduleName); // $params = array('flow', 'operate', $module, 'close', 1);
|
||||
@@ -541,22 +539,23 @@ class router extends baseRouter
|
||||
/* Prepend other params. */
|
||||
if($methodName == 'browse')
|
||||
{
|
||||
if(isset($params['label']) and $params['label'] == 'bysearch')
|
||||
{
|
||||
$params['label'] = '';
|
||||
$params['mode'] = 'bysearch';
|
||||
}
|
||||
else
|
||||
{
|
||||
$params['mode'] = 'browse';
|
||||
}
|
||||
if(!(isset($params['mode']) and $params['mode'] == 'bysearch')) $params['mode'] = 'browse';
|
||||
}
|
||||
|
||||
$params['module'] = $this->rawModule; // $param = array('label' => 1, 'mode' => 'search', 'module' => $module);
|
||||
$params[$this->config->methodVar] = $methodName; // $param = array('label' => 1, 'mode' => 'search', 'module' => $module, 'f' => 'browse');
|
||||
$params[$this->config->moduleVar] = $moduleName; // $param = array('label' => 1, 'mode' => 'search', 'module' => $module, 'f' => 'browse', 'm' => 'flow');
|
||||
|
||||
$params = array_reverse($params); // $params = array('m' => 'flow', 'f' => 'browse', 'module' => $module, 'mode' => 'search', 'label' => 1);
|
||||
|
||||
/* Reset $_GET for setParamsByGET. */
|
||||
$get = $params;
|
||||
foreach($_GET as $key => $value)
|
||||
{
|
||||
if(!isset($get[$key])) $get[$key] = $value;
|
||||
}
|
||||
$_GET = $get;
|
||||
|
||||
$this->URI = $path . '?' . http_build_query($params); // $this->URI = '/index.php?m=flow&f=browse&module=$module&mode=search&label=1';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,10 +131,10 @@ class basePager
|
||||
$this->setModuleName();
|
||||
$this->setMethodName();
|
||||
|
||||
$this->setRecTotal($recTotal);
|
||||
$this->setRecPerPage($recPerPage);
|
||||
$this->setRecTotal((int)$recTotal);
|
||||
$this->setRecPerPage((int)$recPerPage);
|
||||
$this->setPageTotal();
|
||||
$this->setPageID($pageID);
|
||||
$this->setPageID((int)$pageID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
@@ -15,7 +15,7 @@ helper::import(dirname(dirname(__FILE__)) . '/base/pager/pager.class.php');
|
||||
/**
|
||||
* pager类.
|
||||
* Pager class.
|
||||
*
|
||||
*
|
||||
* @package framework
|
||||
*/
|
||||
class pager extends basePager
|
||||
@@ -23,7 +23,7 @@ class pager extends basePager
|
||||
/**
|
||||
* 设置模块名。
|
||||
* Set the $moduleName property.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ class pager extends basePager
|
||||
/**
|
||||
* 设置方法名。
|
||||
* Set the $methodName property.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -65,7 +65,7 @@ class pager extends basePager
|
||||
/**
|
||||
* 如果设置了请求的原始模块名和方法名,则去掉module参数,以便分页功能生成原始请求的URL而不是转换后的工作流URL。
|
||||
* If the original module name and method name of the request are set, the module parameter is removed so that
|
||||
* the paging function generates the URL of the original request instead of the converted workflow URL.
|
||||
* the paging function generates the URL of the original request instead of the converted workflow URL.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -87,9 +87,9 @@ class pager extends basePager
|
||||
|
||||
/**
|
||||
* Show pager.
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type
|
||||
*
|
||||
* @param string $align
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -111,6 +111,7 @@ class gitlab
|
||||
if(!empty($commits))
|
||||
{
|
||||
$commit = $commits[0];
|
||||
$file->revision = $commit->id;
|
||||
$file->committer = $commit->committer_name;
|
||||
$file->comment = $commit->message;
|
||||
$file->date = date('Y-m-d H:i:s', strtotime($commit->committed_date));
|
||||
@@ -168,10 +169,15 @@ class gitlab
|
||||
$list = $this->fetch($api, $params);
|
||||
if(empty($list)) break;
|
||||
|
||||
foreach($list as $branch) $branches[$branch->name] = $branch->name;
|
||||
foreach($list as $branch)
|
||||
{
|
||||
if(!isset($branch->name)) continue;
|
||||
$branches[$branch->name] = $branch->name;
|
||||
}
|
||||
if(count($list) < $params['per_page']) break;
|
||||
}
|
||||
|
||||
if(empty($branches)) $branches['master'] = 'master';
|
||||
asort($branches);
|
||||
return $branches;
|
||||
}
|
||||
@@ -517,7 +523,8 @@ class gitlab
|
||||
if(!scm::checkRevision($version)) return array();
|
||||
$api = "commits";
|
||||
|
||||
if(empty($count)) $count = 100;
|
||||
/* TODO Put getCommits into cron job. And check best size of $count. */
|
||||
if(empty($count)) $count = 10;
|
||||
|
||||
$params = array();
|
||||
$params['ref_name'] = $branch;
|
||||
@@ -617,7 +624,6 @@ class gitlab
|
||||
$params->per_page = 100;
|
||||
|
||||
$allResults = array();
|
||||
$files = array();
|
||||
while(true)
|
||||
{
|
||||
$results = $this->fetch($api, $params);
|
||||
|
||||
@@ -125,7 +125,6 @@ class GitRepo
|
||||
$list = execCmd($cmd . ' 2>&1', 'array', $result);
|
||||
if($result) return array();
|
||||
|
||||
|
||||
$branches = array();
|
||||
foreach($list as $localBranch)
|
||||
{
|
||||
|
||||
@@ -46,3 +46,4 @@ $config->action->majorList['execution'] = array('opened', 'edited');
|
||||
|
||||
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
|
||||
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,';
|
||||
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,pipeline,jenkins,';
|
||||
|
||||
@@ -441,6 +441,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Hide Document';
|
||||
|
||||
$lang->action->dynamicAction->user['created'] = 'Create User';
|
||||
$lang->action->dynamicAction->user['edited'] = 'Edit User';
|
||||
$lang->action->dynamicAction->user['deleted'] = 'Delete User';
|
||||
$lang->action->dynamicAction->user['login'] = 'Login';
|
||||
$lang->action->dynamicAction->user['logout'] = 'Logout';
|
||||
$lang->action->dynamicAction->user['undeleted'] = 'Restore User';
|
||||
|
||||
@@ -103,7 +103,9 @@ $lang->action->objectTypes['entry'] = 'Entry';
|
||||
$lang->action->objectTypes['webhook'] = 'Webhook';
|
||||
$lang->action->objectTypes['team'] = 'Team';
|
||||
$lang->action->objectTypes['whitelist'] = 'Whitelist';
|
||||
$lang->action->objectTypes['pipeline'] = 'GitLib';
|
||||
$lang->action->objectTypes['pipeline'] = 'GitLab';
|
||||
$lang->action->objectTypes['gitlab'] = 'GitLab';
|
||||
$lang->action->objectTypes['jenkins'] = 'Jenkins';
|
||||
|
||||
/* Used to describe operation history. */
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -445,6 +447,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Hide Document';
|
||||
|
||||
$lang->action->dynamicAction->user['created'] = 'Create User';
|
||||
$lang->action->dynamicAction->user['edited'] = 'Edit User';
|
||||
$lang->action->dynamicAction->user['deleted'] = 'Delete User';
|
||||
$lang->action->dynamicAction->user['login'] = 'Login';
|
||||
$lang->action->dynamicAction->user['logout'] = 'Logout';
|
||||
$lang->action->dynamicAction->user['undeleted'] = 'Restore User';
|
||||
@@ -477,7 +480,7 @@ $lang->action->label->testtask = 'Request|testtask|view|caseID=%s';
|
||||
$lang->action->label->testsuite = 'Test Suite|testsuite|view|suiteID=%s';
|
||||
$lang->action->label->caselib = 'Case Library|caselib|view|libID=%s';
|
||||
$lang->action->label->todo = 'Todo|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = 'Doc Library|doc|browse|libID=%s';
|
||||
$lang->action->label->doclib = 'Doc Library|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s';
|
||||
$lang->action->label->doc = 'Doc|doc|view|docID=%s';
|
||||
$lang->action->label->user = 'User|user|view|account=%s';
|
||||
$lang->action->label->testreport = 'Report|testreport|view|report=%s';
|
||||
|
||||
@@ -454,6 +454,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Masquer Document';
|
||||
|
||||
$lang->action->dynamicAction->user['created'] = 'Créer User';
|
||||
$lang->action->dynamicAction->user['edited'] = 'Editer User';
|
||||
$lang->action->dynamicAction->user['deleted'] = 'Delete User';
|
||||
$lang->action->dynamicAction->user['login'] = 'Connexion';
|
||||
$lang->action->dynamicAction->user['logout'] = 'Déconnexion';
|
||||
$lang->action->dynamicAction->user['undeleted'] = 'Restaure User';
|
||||
|
||||
@@ -441,6 +441,7 @@ $lang->action->dynamicAction->doc['hidden'] = 'Ẩn tài liệu';
|
||||
|
||||
$lang->action->dynamicAction->user['created'] = 'Tạo người dùng';
|
||||
$lang->action->dynamicAction->user['edited'] = 'Sửa người dùng';
|
||||
$lang->action->dynamicAction->user['deleted'] = 'Delete User';
|
||||
$lang->action->dynamicAction->user['login'] = 'Đăng nhập';
|
||||
$lang->action->dynamicAction->user['logout'] = 'Thoát';
|
||||
$lang->action->dynamicAction->user['undeleted'] = 'Khôi phục người dùng';
|
||||
|
||||
@@ -103,7 +103,9 @@ $lang->action->objectTypes['entry'] = '应用';
|
||||
$lang->action->objectTypes['webhook'] = 'Webhook';
|
||||
$lang->action->objectTypes['team'] = '团队';
|
||||
$lang->action->objectTypes['whitelist'] = '白名单';
|
||||
$lang->action->objectTypes['pipeline'] = 'GitLib';
|
||||
$lang->action->objectTypes['pipeline'] = 'GitLab';
|
||||
$lang->action->objectTypes['gitlab'] = 'GitLab';
|
||||
$lang->action->objectTypes['jenkins'] = 'Jenkins';
|
||||
|
||||
/* 用来描述操作历史记录。*/
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -445,6 +447,7 @@ $lang->action->dynamicAction->doc['hidden'] = '隐藏文档';
|
||||
|
||||
$lang->action->dynamicAction->user['created'] = '创建用户';
|
||||
$lang->action->dynamicAction->user['edited'] = '编辑用户';
|
||||
$lang->action->dynamicAction->user['deleted'] = '删除用户';
|
||||
$lang->action->dynamicAction->user['login'] = '用户登录';
|
||||
$lang->action->dynamicAction->user['logout'] = '用户退出';
|
||||
$lang->action->dynamicAction->user['undeleted'] = '还原用户';
|
||||
@@ -477,7 +480,7 @@ $lang->action->label->testtask = '测试单|testtask|view|caseID=%s';
|
||||
$lang->action->label->testsuite = '测试套件|testsuite|view|suiteID=%s';
|
||||
$lang->action->label->caselib = '用例库|caselib|view|libID=%s';
|
||||
$lang->action->label->todo = '待办|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = '文档库|doc|objectLibs|type=&objectID=&libID=%s';
|
||||
$lang->action->label->doclib = '文档库|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s';
|
||||
$lang->action->label->doc = '文档|doc|view|docID=%s';
|
||||
$lang->action->label->user = '用户|user|view|account=%s';
|
||||
$lang->action->label->testreport = '报告|testreport|view|report=%s';
|
||||
|
||||
@@ -103,7 +103,9 @@ $lang->action->objectTypes['entry'] = '應用';
|
||||
$lang->action->objectTypes['webhook'] = 'Webhook';
|
||||
$lang->action->objectTypes['team'] = '團隊';
|
||||
$lang->action->objectTypes['whitelist'] = '白名單';
|
||||
$lang->action->objectTypes['pipeline'] = 'GitLib';
|
||||
$lang->action->objectTypes['pipeline'] = 'GitLab';
|
||||
$lang->action->objectTypes['gitlab'] = 'GitLab';
|
||||
$lang->action->objectTypes['jenkins'] = 'Jenkins';
|
||||
|
||||
/* 用來描述操作歷史記錄。*/
|
||||
$lang->action->desc = new stdclass();
|
||||
@@ -445,6 +447,7 @@ $lang->action->dynamicAction->doc['hidden'] = '隱藏文檔';
|
||||
|
||||
$lang->action->dynamicAction->user['created'] = '創建用戶';
|
||||
$lang->action->dynamicAction->user['edited'] = '編輯用戶';
|
||||
$lang->action->dynamicAction->user['deleted'] = '刪除用戶';
|
||||
$lang->action->dynamicAction->user['login'] = '用戶登錄';
|
||||
$lang->action->dynamicAction->user['logout'] = '用戶退出';
|
||||
$lang->action->dynamicAction->user['undeleted'] = '還原用戶';
|
||||
@@ -477,7 +480,7 @@ $lang->action->label->testtask = '測試單|testtask|view|caseID=%s';
|
||||
$lang->action->label->testsuite = '測試套件|testsuite|view|suiteID=%s';
|
||||
$lang->action->label->caselib = '用例庫|caselib|view|libID=%s';
|
||||
$lang->action->label->todo = '待辦|todo|view|todoID=%s';
|
||||
$lang->action->label->doclib = '文檔庫|doc|objectLibs|type=&objectID=&libID=%s';
|
||||
$lang->action->label->doclib = '文檔庫|doc|objectLibs|type=%s&objectID=%s&libID=%s&docID=&version=&appendLib=%s';
|
||||
$lang->action->label->doc = '文檔|doc|view|docID=%s';
|
||||
$lang->action->label->user = '用戶|user|view|account=%s';
|
||||
$lang->action->label->testreport = '報告|testreport|view|report=%s';
|
||||
|
||||
+44
-9
@@ -36,7 +36,7 @@ class actionModel extends model
|
||||
|
||||
$actor = $actor ? $actor : $this->app->user->account;
|
||||
$actionType = strtolower($actionType);
|
||||
$actor = $actionType == 'openedbysystem' ? '' : $actor;
|
||||
$actor = ($actionType == 'openedbysystem' or $actionType == 'closedbysystem') ? '' : $actor;
|
||||
if($actor == 'guest' and $actionType == 'logout') return false;
|
||||
|
||||
$objectType = str_replace('`', '', $objectType);
|
||||
@@ -49,8 +49,7 @@ class actionModel extends model
|
||||
$action->date = helper::now();
|
||||
$action->extra = $extra;
|
||||
|
||||
if($objectType == 'story' and $actionType !== 'reviewed' and strpos('reviewclosed,passreviewed,clarifyreviewed', $actionType) !== false) $action->actor = 'System';
|
||||
|
||||
if($objectType == 'story' and $actionType !== 'reviewed' and strpos(',reviewclosed,passreviewed,clarifyreviewed,', ",$actionType,") !== false) $action->actor = 'System';
|
||||
|
||||
/* Use purifier to process comment. Fix bug #2683. */
|
||||
$action->comment = fixer::stripDataTags($comment);
|
||||
@@ -570,12 +569,29 @@ class actionModel extends model
|
||||
$objectIds = array_unique($objectIds);
|
||||
$table = $this->config->objectTables[$objectType];
|
||||
$field = $this->config->action->objectNameFields[$objectType];
|
||||
|
||||
$objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs();
|
||||
if($objectType == 'pipeline')
|
||||
{
|
||||
$objectNames['jenkins'] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->andWhere('type')->eq('jenkins')->fetchPairs();
|
||||
$objectNames['gitlab'] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->andWhere('type')->eq('gitlab')->fetchPairs();
|
||||
}
|
||||
else
|
||||
{
|
||||
$objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs();
|
||||
}
|
||||
}
|
||||
|
||||
/* Add name field to the trashes. */
|
||||
foreach($trashes as $trash) $trash->objectName = isset($objectNames[$trash->objectType][$trash->objectID]) ? $objectNames[$trash->objectType][$trash->objectID] : '';
|
||||
foreach($trashes as $trash)
|
||||
{
|
||||
$objectType = $trash->objectType;
|
||||
if($objectType == 'pipeline')
|
||||
{
|
||||
if(isset($objectNames['gitlab'][$trash->objectID])) $objectType = 'gitlab';
|
||||
if(isset($objectNames['jenkins'][$trash->objectID])) $objectType = 'jenkins';
|
||||
$trash->objectType = $objectType;
|
||||
}
|
||||
$trash->objectName = isset($objectNames[$objectType][$trash->objectID]) ? $objectNames[$objectType][$trash->objectID] : '';
|
||||
}
|
||||
return $trashes;
|
||||
}
|
||||
|
||||
@@ -928,6 +944,7 @@ class actionModel extends model
|
||||
public function transformActions($actions)
|
||||
{
|
||||
$this->app->loadLang('todo');
|
||||
$this->app->loadLang('stakeholder');
|
||||
$requirements = array();
|
||||
|
||||
/* Get commiters. */
|
||||
@@ -948,7 +965,7 @@ class actionModel extends model
|
||||
$objectName = array();
|
||||
$objectProject = array();
|
||||
|
||||
if(strpos($this->config->action->needGetProjectType, $objectType) !== false)
|
||||
if(strpos(",{$this->config->action->needGetProjectType},", ",{$objectType},") !== false)
|
||||
{
|
||||
$objectInfo = $this->dao->select("id, project, $field AS name")->from($table)->where('id')->in($objectIds)->fetchAll();
|
||||
foreach($objectInfo as $object)
|
||||
@@ -989,6 +1006,13 @@ class actionModel extends model
|
||||
if($object->type == 'project') $objectProject[$object->id] = $object->id;
|
||||
}
|
||||
}
|
||||
elseif($objectType == 'stakeholder'){
|
||||
$objectName = $this->dao->select("t1.id, t2.realname")->from($table)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')->on("t1.{$field} = t2.account")
|
||||
->where('t1.id')->in($objectIds)
|
||||
->fetchPairs();
|
||||
$objectProject = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$objectName = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs();
|
||||
@@ -1029,7 +1053,7 @@ class actionModel extends model
|
||||
$objectType = strtolower($action->objectType);
|
||||
$action->originalDate = $action->date;
|
||||
$action->date = date(DT_MONTHTIME2, strtotime($action->date));
|
||||
$action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : $action->action;
|
||||
$action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : (isset($this->lang->$objectType->$actionType) ? $this->lang->$objectType->$actionType : $action->action);
|
||||
$action->objectLabel = $objectType;
|
||||
if(isset($this->lang->action->label->$objectType))
|
||||
{
|
||||
@@ -1086,7 +1110,18 @@ class actionModel extends model
|
||||
}
|
||||
else
|
||||
{
|
||||
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID);
|
||||
if($action->objectType == 'doclib')
|
||||
{
|
||||
$docLib = $this->dao->select('type,product,project,execution,deleted')->from(TABLE_DOCLIB)->where('id')->eq($action->objectID)->fetch();
|
||||
$docLib->type = $docLib->type == 'execution' ? 'project' : $docLib->type;
|
||||
$docLib->objectID = strpos('product,project', $docLib->type) !== false ? $docLib->{$docLib->type} : 0;
|
||||
$appendLib = $docLib->deleted == '1' ? $action->objectID : 0;
|
||||
$action->objectLink = helper::createLink('doc', 'objectLibs', sprintf($vars, $docLib->type, $docLib->objectID, $action->objectID, $appendLib));
|
||||
}
|
||||
else
|
||||
{
|
||||
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID);
|
||||
}
|
||||
}
|
||||
$action->objectLabel = $objectLabel;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
$flow = $config->action->customFlows[$action->objectType];
|
||||
$module = $flow->module;
|
||||
}
|
||||
if(strpos(',doclib,module,webhook,', ",{$module},") !== false)
|
||||
if(strpos($this->config->action->noLinkModules, ",{$module},") !== false)
|
||||
{
|
||||
echo $action->objectName;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<?php echo $lang->backup->history?>
|
||||
</h2>
|
||||
<div class='pull-right'>
|
||||
<?php common::printLink('backup', 'setting', '', "<i class='icon icon-cog'></i>" . $lang->backup->setting, '', "data-width='500' class='iframe btn btn-primary'");?>
|
||||
<?php common::printLink('backup', 'setting', '', "<i class='icon icon-cog'></i> " . $lang->backup->setting, '', "data-width='500' class='iframe btn btn-primary'");?>
|
||||
<?php common::printLink('backup', 'backup', 'reload=yes', "<i class='icon icon-copy'></i> " . $lang->backup->backup, 'hiddenwin', "class='btn btn-primary backup'");?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1750,7 +1750,7 @@ class block extends control
|
||||
$today = helper::today();
|
||||
$now = date('H:i:s', strtotime(helper::now()));
|
||||
|
||||
$meetings = $this->dao->select('*')->from(TABLE_MEETING)
|
||||
$stmt = $this->dao->select('*')->from(TABLE_MEETING)
|
||||
->Where('deleted')->eq('0')
|
||||
->andWhere('(date')->gt($today)
|
||||
->orWhere('(begin')->gt($now)
|
||||
@@ -1759,9 +1759,10 @@ class block extends control
|
||||
->andwhere('(host')->eq($this->app->user->account)
|
||||
->orWhere('participant')->in($this->app->user->account)
|
||||
->markRight(1)
|
||||
->orderBy('id_desc')
|
||||
->beginIF(isset($params->meetingNum))->limit($params->meetingNum)
|
||||
->fetchAll();
|
||||
->orderBy('id_desc');
|
||||
|
||||
if(isset($params->meetingNum)) $stmt->limit($params->meetingNum);
|
||||
$meetings = $stmt->fetchAll();
|
||||
|
||||
$count['meeting'] = count($meetings);
|
||||
$this->view->meetings = $meetings;
|
||||
@@ -1832,6 +1833,8 @@ class block extends control
|
||||
|
||||
/* Get projects. */
|
||||
$this->app->loadLang('task');
|
||||
$this->app->loadLang('program');
|
||||
$this->app->loadLang('execution');
|
||||
$this->view->projects = $this->loadModel('project')->getOverviewList('byStatus', $status, $orderBy, $count);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,6 @@ $(function()
|
||||
custom: response.data.content,
|
||||
width: 600
|
||||
});
|
||||
myModalTrigger.show();
|
||||
$('#showAnnual').click(function(){myModalTrigger.close()});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
<td class="c-hours" title="<?php echo $execution->hours->totalLeft . ' ' . $lang->execution->workHour;?>"><?php echo $execution->hours->totalLeft . $lang->execution->workHourUnit;?></td>
|
||||
<?php endif;?>
|
||||
<td class="c-progress">
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#00da88' data-value='<?php echo $execution->hours->progress;?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo $execution->hours->progress;?></div>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($execution->hours->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($execution->hours->progress);?></div>
|
||||
</div>
|
||||
</td>
|
||||
<?php if($longBlock):?>
|
||||
|
||||
@@ -157,7 +157,7 @@ $(function()
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="actions">
|
||||
<?php common::printLink('productplan', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i>" . $lang->productplan->create, '', "class='btn btn-info'");?>
|
||||
<?php common::printLink('productplan', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i> " . $lang->productplan->create, '', "class='btn btn-info'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="type-info">
|
||||
@@ -190,7 +190,7 @@ $(function()
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="actions">
|
||||
<?php common::printLink('release', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i>" . $lang->release->create, '', "class='btn btn-info'");?>
|
||||
<?php common::printLink('release', 'create', "productID={$product->id}", "<i class='icon icon-plus'></i> " . $lang->release->create, '', "class='btn btn-info'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="type-info">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<?php if($longBlock):?>
|
||||
<td class='text-center'><?php echo $project->teamCount;?></td>
|
||||
<td class='text-right' title="<?php echo $project->consumed . ' ' . $lang->execution->workHour;?>"><?php echo $project->consumed . $lang->execution->workHourUnit;?></td>
|
||||
<?php $programBudget = in_array($this->app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?>
|
||||
<?php $programBudget = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);?>
|
||||
<td class='text-right'><?php echo $project->budget != 0 ? zget($lang->project->currencySymbol, $project->budgetUnit) . ' ' . $programBudget : $lang->project->future;?></td>
|
||||
<td class='text-center'><?php echo $project->leftStories;?></td>
|
||||
<td class='text-center'><?php echo $project->leftTasks;?></td>
|
||||
|
||||
@@ -221,7 +221,7 @@ $(function()
|
||||
<span><?php echo $lang->project->budget . ':';?></span>
|
||||
<span class='project-info'>
|
||||
<?php
|
||||
$projectBudget = in_array($this->app->getClientLang(), ['zh-cn','zh-tw']) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);
|
||||
$projectBudget = in_array($this->app->getClientLang(), array('zh-cn','zh-tw')) ? round((float)$project->budget / 10000, 2) . $this->lang->project->tenThousand : round((float)$project->budget, 2);
|
||||
echo $project->budget != 0 ? $projectBudget : $this->lang->project->future;
|
||||
?>
|
||||
</span>
|
||||
@@ -229,7 +229,7 @@ $(function()
|
||||
<div class="col-1-5"></div>
|
||||
</div>
|
||||
<div class="table-row text-center waterfall-title small col-12 center-block">
|
||||
<?php $isChineseLang = in_array($this->app->getClientLang(), ['zh-cn','zh-tw']);?>
|
||||
<?php $isChineseLang = in_array($this->app->getClientLang(), array('zh-cn','zh-tw'));?>
|
||||
<div class="col-1-5"><?php echo $isChineseLang ? $lang->project->pv . '(' . $lang->project->pvTitle . ')' : $lang->project->pv; ?></div>
|
||||
<div class="col-1-5"><?php echo $isChineseLang ? $lang->project->ev . '(' . $lang->project->evTitle . ')' : $lang->project->ev;?></div>
|
||||
<div class="col-1-5"><?php echo $isChineseLang ? $lang->project->ac . '(' . $lang->project->acTitle . ')' : $lang->project->ac;?></div>
|
||||
|
||||
@@ -57,8 +57,8 @@
|
||||
<td class="c-hours" title="<?php echo $execution->hours->totalLeft . ' ' . $lang->execution->workHour;?>"><?php echo $execution->hours->totalLeft . $lang->execution->workHourUnit;?></td>
|
||||
<?php endif;?>
|
||||
<td class="c-progress">
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#00da88' data-value='<?php echo $execution->hours->progress;?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo $execution->hours->progress;?></div>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo round($execution->hours->progress);?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo round($execution->hours->progress);?></div>
|
||||
</div>
|
||||
</td>
|
||||
<?php if($longBlock):?>
|
||||
|
||||
+29
-45
@@ -38,7 +38,6 @@ class bug extends control
|
||||
public function __construct($moduleName = '', $methodName = '')
|
||||
{
|
||||
parent::__construct($moduleName, $methodName);
|
||||
$products = array();
|
||||
$this->loadModel('product');
|
||||
$this->loadModel('tree');
|
||||
$this->loadModel('user');
|
||||
@@ -48,25 +47,32 @@ class bug extends control
|
||||
$this->loadModel('qa');
|
||||
|
||||
/* Get product data. */
|
||||
$products = array();
|
||||
$objectID = 0;
|
||||
if($this->app->openApp == 'project')
|
||||
$openApp = ($this->app->openApp == 'project' or $this->app->openApp == 'execution') ? $this->app->openApp : 'qa';
|
||||
if(!isonlybody())
|
||||
{
|
||||
$objectID = $this->session->project;
|
||||
$products = $this->loadModel('project')->getProducts($objectID, false);
|
||||
}
|
||||
elseif($this->app->openApp == 'execution')
|
||||
{
|
||||
$objectID = $this->session->execution;
|
||||
$products = $this->loadModel('execution')->getProducts($objectID, false);
|
||||
if($this->app->openApp == 'project')
|
||||
{
|
||||
$objectID = $this->session->project;
|
||||
$products = $this->loadModel('project')->getProducts($objectID, false);
|
||||
}
|
||||
elseif($this->app->openApp == 'execution')
|
||||
{
|
||||
$objectID = $this->session->execution;
|
||||
$products = $this->loadModel('execution')->getProducts($objectID, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
$products = $this->product->getPairs('', 0, 'program_asc');
|
||||
}
|
||||
if(empty($products) and !helper::isAjaxRequest()) die($this->locate($this->createLink('product', 'showErrorNone', "moduleName=$openApp&activeMenu=bug&objectID=$objectID")));
|
||||
}
|
||||
else
|
||||
{
|
||||
$products = $this->product->getPairs('', 0, 'program_asc');
|
||||
}
|
||||
|
||||
$this->view->products = $this->products = $products;
|
||||
$openApp = ($this->app->openApp == 'project' or $this->app->openApp == 'execution') ? $this->app->openApp : 'qa';
|
||||
if(empty($this->products) and !helper::isAjaxRequest()) die($this->locate($this->createLink('product', 'showErrorNone', "moduleName=$openApp&activeMenu=bug&objectID=$objectID")));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,15 +104,13 @@ class bug extends control
|
||||
{
|
||||
$this->loadModel('datatable');
|
||||
|
||||
$products = $this->loadModel('product')->getPairs('noclosed');
|
||||
$productID = $this->product->saveState($productID, $products);
|
||||
$this->qa->setMenu($products, $productID, $branch);
|
||||
$productID = $this->product->saveState($productID, $this->products);
|
||||
$this->qa->setMenu($this->products, $productID, $branch);
|
||||
|
||||
/* Set browse type. */
|
||||
$browseType = strtolower($browseType);
|
||||
|
||||
/* Set productID, moduleID, queryID and branch. */
|
||||
if(!$this->projectID) $productID = $this->product->saveState($productID, $this->products);
|
||||
$branch = ($branch == '') ? (int)$this->cookie->preBranch : (int)$branch;
|
||||
setcookie('preProductID', $productID, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
setcookie('preBranch', (int)$branch, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
@@ -521,7 +525,7 @@ class bug extends control
|
||||
$projects = array(0 => '');
|
||||
if($executionID)
|
||||
{
|
||||
$products = array();
|
||||
$products = array();
|
||||
$linkedProducts = $this->loadModel('execution')->getProducts($executionID);
|
||||
foreach($linkedProducts as $product) $products[$product->id] = $product->name;
|
||||
|
||||
@@ -569,17 +573,6 @@ class bug extends control
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->showFields = $this->config->bug->custom->createFields;
|
||||
|
||||
/* Set gitlabProjects. */
|
||||
$this->loadModel('gitlab');
|
||||
$allGitlabs = $this->gitlab->getPairs();
|
||||
$gitlabProjects = $this->gitlab->getProjectsByExecution($executionID);
|
||||
foreach($allGitlabs as $id => $name)
|
||||
{
|
||||
if($id and !isset($gitlabProjects[$id])) unset($allGitlabs[$id]);
|
||||
}
|
||||
$this->view->gitlabList = $allGitlabs;
|
||||
$this->view->gitlabProjects = $gitlabProjects;
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->create;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
$this->view->position[] = $this->lang->bug->create;
|
||||
@@ -749,6 +742,11 @@ class bug extends control
|
||||
$this->repo->setMenu($repos);
|
||||
$this->lang->navGroup->bug = 'devops';
|
||||
}
|
||||
if($this->app->openApp == 'product')
|
||||
{
|
||||
$this->loadModel('product')->setMenu($bug->product);
|
||||
$this->lang->product->menu->plan['subModule'] .= ',bug';
|
||||
}
|
||||
}
|
||||
|
||||
/* Get product info. */
|
||||
@@ -1298,9 +1296,6 @@ class bug extends control
|
||||
$this->qa->setMenu($this->products, $productID, $bug->branch);
|
||||
|
||||
$this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve;
|
||||
$this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]);
|
||||
$this->view->position[] = $this->lang->bug->resolve;
|
||||
|
||||
$this->view->bug = $bug;
|
||||
$this->view->users = $users;
|
||||
$this->view->assignedTo = $assignedTo;
|
||||
@@ -1478,16 +1473,8 @@ class bug extends control
|
||||
$_POST = array();
|
||||
|
||||
$bugs = $this->bug->getByList($bugIDList);
|
||||
$this->loadModel('gitlab');
|
||||
foreach($bugs as $bugID => $bug)
|
||||
{
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if(!empty($relation))
|
||||
{
|
||||
$currentIssue = $this->gitlab->apiGetSingleIssue($relation->gitlabID, $relation->projectID, $relation->issueID);
|
||||
if($currentIssue->state != 'closed') $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug);
|
||||
}
|
||||
|
||||
if($bug->status != 'resolved')
|
||||
{
|
||||
if($bug->status != 'closed') $skipBugs[$bugID] = $bugID;
|
||||
@@ -1571,11 +1558,6 @@ class bug extends control
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Delete related issue in gitlab. */
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if(!empty($relation)) $this->gitlab->deleteIssue('bug', $bugID, $relation->issueID);
|
||||
|
||||
$this->bug->delete(TABLE_BUG, $bugID);
|
||||
if($bug->toTask != 0)
|
||||
{
|
||||
@@ -1592,7 +1574,9 @@ class bug extends control
|
||||
$this->executeHooks($bugID);
|
||||
|
||||
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
|
||||
die(js::locate($this->session->bugList, 'parent'));
|
||||
|
||||
$locateLink = $this->session->bugList ? $this->session->bugList : inlink('browse', "productID={$bug->product}");
|
||||
die(js::locate($locateLink, 'parent'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
.chosen-choices li.search-choice {word-break: break-all;}
|
||||
#linkBugBox > li {margin-left: -56px;}
|
||||
#branch {width: 95px;}
|
||||
#storyIdBox .chosen-auto-max-width {width: 215px !important;}
|
||||
|
||||
@@ -525,7 +525,11 @@ function loadAssignedTo(executionID, selectedUser)
|
||||
$('#assignedTo').next('.picker').remove();
|
||||
$('#assignedTo').replaceWith(data);
|
||||
var defaultAssignedTo = $('#assignedTo').val();
|
||||
if(defaultAssignedTo !== oldAssignedTo && selectedUser == '') $('#assignedTo').append(defaultOption);
|
||||
if(defaultAssignedTo !== oldAssignedTo && selectedUser == '')
|
||||
{
|
||||
if($('#assignedTo option[value="' + oldAssignedTo + '"]').length > 0) $('#assignedTo option[value="' + oldAssignedTo + '"]').remove();
|
||||
$('#assignedTo').append(defaultOption);
|
||||
}
|
||||
$('#assignedTo').chosen();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -168,21 +168,3 @@ $(function()
|
||||
$(window).unload(function(){
|
||||
if(blockID) window.parent.refreshBlock($('#block' + blockID));
|
||||
});
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#gitlab').change(function()
|
||||
{
|
||||
host = $('#gitlab').val();
|
||||
if(host == '') return false;
|
||||
projects = '';
|
||||
$.each(gitlabProjects[host], function(id, obj){projects = projects + ',' + obj.gitlabProject});
|
||||
url = createLink('repo', 'ajaxgetgitlabprojects', "host=" + host + "&projects=" + projects);
|
||||
|
||||
$.get(url, function(response)
|
||||
{
|
||||
$('#gitlabProject').html('').append(response);
|
||||
$('#gitlabProject').chosen().trigger("chosen:updated");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ $lang->bug->lastEditedDate = 'Bearbeitet am';
|
||||
$lang->bug->fromCase = 'Von Fall';
|
||||
$lang->bug->toCase = 'Zu Fall';
|
||||
$lang->bug->colorTag = 'Farb Tag';
|
||||
$lang->bug->repairRate = 'Repair Rate';
|
||||
$lang->bug->fixedRate = 'Fixed Rate';
|
||||
|
||||
/* 方法列表。*/
|
||||
$lang->bug->index = 'Home';
|
||||
|
||||
@@ -24,7 +24,6 @@ $lang->bug->storyVersion = 'Story Version';
|
||||
$lang->bug->color = 'Color';
|
||||
$lang->bug->task = 'Task';
|
||||
$lang->bug->title = 'Title';
|
||||
$lang->bug->sync2gitlab = 'Sync gitlab';
|
||||
$lang->bug->severity = 'Severity';
|
||||
$lang->bug->severityAB = 'S';
|
||||
$lang->bug->pri = 'Priority';
|
||||
@@ -80,7 +79,7 @@ $lang->bug->lastEditedDate = 'EditedDate';
|
||||
$lang->bug->fromCase = 'From Case';
|
||||
$lang->bug->toCase = 'To Case';
|
||||
$lang->bug->colorTag = 'Color';
|
||||
$lang->bug->repairRate = 'Repair Rate';
|
||||
$lang->bug->fixedRate = 'Fixed Rate';
|
||||
|
||||
/* Method list. */
|
||||
$lang->bug->index = 'Bug Home';
|
||||
|
||||
@@ -79,7 +79,7 @@ $lang->bug->lastEditedDate = 'Date Modif';
|
||||
$lang->bug->fromCase = 'du CasTest';
|
||||
$lang->bug->toCase = 'vers CasTest';
|
||||
$lang->bug->colorTag = 'Couleur';
|
||||
$lang->bug->repairRate = 'Repair Rate';
|
||||
$lang->bug->fixedRate = 'Repair Rate';
|
||||
|
||||
/* 方法列表。*/
|
||||
$lang->bug->index = 'Accueil Bug';
|
||||
|
||||
@@ -79,7 +79,7 @@ $lang->bug->lastEditedDate = 'Ngày sửa';
|
||||
$lang->bug->fromCase = 'Từ tình huống';
|
||||
$lang->bug->toCase = 'Tới tình huống';
|
||||
$lang->bug->colorTag = 'Màu';
|
||||
$lang->bug->repairRate = 'Repair Rate';
|
||||
$lang->bug->fixedRate = 'Repair Rate';
|
||||
|
||||
/* Method list. */
|
||||
$lang->bug->index = 'Trang Bug';
|
||||
|
||||
@@ -24,7 +24,6 @@ $lang->bug->storyVersion = "{$lang->SRCommon}版本";
|
||||
$lang->bug->color = '标题颜色';
|
||||
$lang->bug->task = '相关任务';
|
||||
$lang->bug->title = 'Bug标题';
|
||||
$lang->bug->sync2gitlab = '同步gitlab';
|
||||
$lang->bug->severity = '严重程度';
|
||||
$lang->bug->severityAB = '级别';
|
||||
$lang->bug->pri = '优先级';
|
||||
@@ -80,7 +79,7 @@ $lang->bug->lastEditedDate = '修改日期';
|
||||
$lang->bug->fromCase = '来源用例';
|
||||
$lang->bug->toCase = '生成用例';
|
||||
$lang->bug->colorTag = '颜色标签';
|
||||
$lang->bug->repairRate = '修复率';
|
||||
$lang->bug->fixedRate = '修复率';
|
||||
|
||||
/* 方法列表。*/
|
||||
$lang->bug->index = '首页';
|
||||
|
||||
@@ -24,7 +24,6 @@ $lang->bug->storyVersion = "{$lang->SRCommon}版本";
|
||||
$lang->bug->color = '標題顏色';
|
||||
$lang->bug->task = '相關任務';
|
||||
$lang->bug->title = 'Bug標題';
|
||||
$lang->bug->sync2gitlab = '同步gitlab';
|
||||
$lang->bug->severity = '嚴重程度';
|
||||
$lang->bug->severityAB = '級別';
|
||||
$lang->bug->pri = '優先順序';
|
||||
@@ -60,6 +59,7 @@ $lang->bug->resolvedBuild = '解決版本';
|
||||
$lang->bug->resolvedDate = '解決日期';
|
||||
$lang->bug->resolvedDateAB = '解決日期';
|
||||
$lang->bug->deadline = '截止日期';
|
||||
$lang->bug->deadlineAB = '截止';
|
||||
$lang->bug->plan = '所屬' . '計劃';
|
||||
$lang->bug->closedBy = '由誰關閉';
|
||||
$lang->bug->closedDate = '關閉日期';
|
||||
@@ -79,6 +79,7 @@ $lang->bug->lastEditedDate = '修改日期';
|
||||
$lang->bug->fromCase = '來源用例';
|
||||
$lang->bug->toCase = '生成用例';
|
||||
$lang->bug->colorTag = '顏色標籤';
|
||||
$lang->bug->fixedRate = '修復率';
|
||||
|
||||
/* 方法列表。*/
|
||||
$lang->bug->index = '首頁';
|
||||
|
||||
+3
-63
@@ -84,13 +84,11 @@ class bugModel extends model
|
||||
/* Use classic mode to replace required project. */
|
||||
if($this->config->systemMode == 'classic' and strpos($this->config->bug->create->requiredFields, 'project') !== false) $this->config->bug->create->requiredFields = str_replace('project', 'execution', $this->config->bug->create->requiredFields);
|
||||
|
||||
$this->dao->insert(TABLE_BUG)->data($bug, $skip = 'gitlab,gitlabProject')->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec();
|
||||
$this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec();
|
||||
if(!dao::isError())
|
||||
{
|
||||
$bugID = $this->dao->lastInsertID();
|
||||
|
||||
$this->loadModel('gitlab')->apiCreateIssue($this->post->gitlab, $this->post->gitlabProject, 'bug', $bugID, $bug);
|
||||
|
||||
$this->file->updateObjectID($this->post->uid, $bugID, 'bug');
|
||||
$this->file->saveUpload('bug', $bugID);
|
||||
empty($bug->case) ? $this->loadModel('score')->create('bug', 'create', $bugID) : $this->loadModel('score')->create('bug', 'createFormCase', $bug->case);
|
||||
@@ -342,7 +340,7 @@ class bugModel extends model
|
||||
elseif($browseType == 'bysearch') $bugs = $this->getBySearch($productIDList, $branch, $queryID, $sort, '', $pager, $projectID);
|
||||
elseif($browseType == 'overduebugs') $bugs = $this->getOverdueBugs($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID);
|
||||
|
||||
return $this->checkDelayBugs($bugs);
|
||||
return $this->checkDelayedBugs($bugs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,7 +350,7 @@ class bugModel extends model
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function checkDelayBugs($bugs)
|
||||
public function checkDelayedBugs($bugs)
|
||||
{
|
||||
foreach ($bugs as $bug) $bug = $this->checkDelayBug($bug);
|
||||
|
||||
@@ -675,12 +673,6 @@ class bugModel extends model
|
||||
if(!empty($bug->resolvedBy)) $this->loadModel('score')->create('bug', 'resolve', $bugID);
|
||||
$this->file->updateObjectID($this->post->uid, $bugID, 'bug');
|
||||
|
||||
if(!empty($bug))
|
||||
{
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
}
|
||||
return common::createChanges($oldBug, $bug);
|
||||
}
|
||||
}
|
||||
@@ -802,11 +794,6 @@ class bugModel extends model
|
||||
$this->executeHooks($bugID);
|
||||
|
||||
$allChanges[$bugID] = common::createChanges($oldBug, $bug);
|
||||
|
||||
/* update bug to gitlab issue. */
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -859,15 +846,8 @@ class bugModel extends model
|
||||
}
|
||||
|
||||
/* Update bugs. */
|
||||
$this->loadModel('gitlab');
|
||||
foreach($activateBugs as $bugID => $bug)
|
||||
{
|
||||
if(!empty($bug))
|
||||
{
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', (Object)$bug, $bugID);
|
||||
}
|
||||
|
||||
$oldBug = $bugs[$bugID];
|
||||
$this->dao->update(TABLE_BUG)->data($bug, $skipFields = 'comment')->autoCheck()->where('id')->eq((int)$bugID)->exec();
|
||||
if(dao::isError()) die(js::error('bug#' . $bugID . dao::getError(true)));
|
||||
@@ -902,16 +882,6 @@ class bugModel extends model
|
||||
->autoCheck()
|
||||
->where('id')->eq($bugID)->exec();
|
||||
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
$bug = $this->getById($bugID); // Get full bug object to update issue.
|
||||
$bug->assignee_id = $this->gitlab->getGitlabUserID($relation->gitlabID, $bug->assignedTo);
|
||||
if($bug->assignee_id != '')
|
||||
{
|
||||
/* TODO(dingguodong) we should alert to operator when can not find the user, and the operator should reconfigure user binding. */
|
||||
$this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
}
|
||||
|
||||
if(!dao::isError()) return common::createChanges($oldBug, $bug);
|
||||
}
|
||||
|
||||
@@ -956,7 +926,6 @@ class bugModel extends model
|
||||
{
|
||||
$now = helper::now();
|
||||
$bugs = $this->getByList($bugIDList);
|
||||
$this->loadModel('gitlab');
|
||||
foreach($bugIDList as $bugID)
|
||||
{
|
||||
if($bugs[$bugID]->confirmed) continue;
|
||||
@@ -967,12 +936,6 @@ class bugModel extends model
|
||||
$bug->lastEditedDate = $now;
|
||||
$bug->confirmed = 1;
|
||||
|
||||
if(!empty($bug))
|
||||
{
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec();
|
||||
$this->executeHooks($bugID);
|
||||
}
|
||||
@@ -1064,10 +1027,6 @@ class bugModel extends model
|
||||
/* Link bug to build and release. */
|
||||
$this->linkBugToBuild($bugID, $bug->resolvedBuild);
|
||||
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
|
||||
return common::createChanges($oldBug, $bug);
|
||||
}
|
||||
|
||||
@@ -1197,11 +1156,6 @@ class bugModel extends model
|
||||
$this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec();
|
||||
$this->executeHooks($bugID);
|
||||
|
||||
/* batch resolve issure bugs.*/
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
|
||||
$changes[$bugID] = common::createChanges($oldBug, $bug);
|
||||
}
|
||||
|
||||
@@ -1259,13 +1213,6 @@ class bugModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($bug))
|
||||
{
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if($relation) $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
}
|
||||
|
||||
$bug->activatedCount += 1;
|
||||
return common::createChanges($oldBug, $bug);
|
||||
}
|
||||
@@ -1295,13 +1242,6 @@ class bugModel extends model
|
||||
|
||||
$this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec();
|
||||
|
||||
$this->loadModel('gitlab');
|
||||
$relation = $this->gitlab->getRelationByObject('bug', $bugID);
|
||||
if(!empty($relation))
|
||||
{
|
||||
$currentIssue = $this->gitlab->apiGetSingleIssue($relation->gitlabID, $relation->projectID, $relation->issueID);
|
||||
if($currentIssue->state != 'closed') $this->gitlab->apiUpdateIssue($relation->gitlabID, $relation->projectID, $relation->issueID, 'bug', $bug, $bugID);
|
||||
}
|
||||
return common::createChanges($oldBug, $bug);
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow
|
||||
<li <?php echo $disabled?>>
|
||||
<?php
|
||||
$batchLink = $this->createLink('bug', 'batchCreate', "productID=$productID&branch=$branch&executionID=0&moduleID=$moduleID");
|
||||
echo "<li>" . html::a($batchLink, "<i class='icon icon-plus'></i>" . $lang->bug->batchCreate) . "</li>";
|
||||
echo "<li>" . html::a($batchLink, "<i class='icon icon-plus'></i> " . $lang->bug->batchCreate) . "</li>";
|
||||
?>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<div id="mainMenu" class="clearfix">
|
||||
<div class="btn-toolbar pull-left">
|
||||
<?php echo html::a($this->createLink('bug', 'browse', "productID=$productID&branch=0&browseType=$browseType&moduleID=$moduleID"), "<i class='icon icon-back icon-sm'> </i>" . $lang->goback, '', "class='btn btn-link'");?>
|
||||
<?php echo html::a($this->createLink('bug', 'browse', "productID=$productID&branch=0&browseType=$browseType&moduleID=$moduleID"), "<i class='icon icon-back icon-sm'> </i> " . $lang->goback, '', "class='btn btn-link'");?>
|
||||
<div class='divider'></div>
|
||||
<div class='page-title'>
|
||||
<span class='text'><?php echo $lang->bug->report->common;?></span>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<div class="btn-toolbar pull-right">
|
||||
<?php if(common::canModify('product', $product)):?>
|
||||
<?php $openApp = strpos('|execution|project|qa|', $this->app->openApp) !== false ? $this->app->openApp : 'qa';?>
|
||||
<?php common::printLink('bug', 'create', "productID={$bug->product}&branch={$bug->branch}&extra=moduleID={$bug->module},projectID={$bug->project},executionID={$bug->execution}", "<i class='icon icon-plus'></i>" . $lang->bug->create, '', "class='btn btn-primary' data-app='$openApp'"); ?>
|
||||
<?php if($this->app->openApp != 'product') common::printLink('bug', 'create', "productID={$bug->product}&branch={$bug->branch}&extra=moduleID={$bug->module},projectID={$bug->project},executionID={$bug->execution}", "<i class='icon icon-plus'></i> " . $lang->bug->create, '', "class='btn btn-primary' data-app='$openApp'"); ?>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
@@ -86,14 +86,20 @@
|
||||
common::printIcon('bug', 'close', $params, $bug, 'button', '', '', 'text-danger iframe showinonlybody', true);
|
||||
common::printIcon('bug', 'activate', $params, $bug, 'button', '', '', 'text-success iframe showinonlybody', true);
|
||||
|
||||
common::printIcon('bug', 'toStory', "product=$bug->product&branch=$bug->branch&module=0&story=0&execution=0&bugID=$bug->id", $bug, 'button', $lang->icons['story'], '', '', '', "data-app='" . ($this->app->openApp == 'project' ? 'project' : 'product') . "'", $lang->bug->toStory);
|
||||
common::printIcon('bug', 'createCase', $convertParams, $bug, 'button', 'sitemap');
|
||||
if($this->app->openApp != 'product')
|
||||
{
|
||||
common::printIcon('bug', 'toStory', "product=$bug->product&branch=$bug->branch&module=0&story=0&execution=0&bugID=$bug->id", $bug, 'button', $lang->icons['story'], '', '', '', "data-app='" . ($this->app->openApp == 'project' ? 'project' : 'product') . "'", $lang->bug->toStory);
|
||||
common::printIcon('bug', 'createCase', $convertParams, $bug, 'button', 'sitemap');
|
||||
}
|
||||
|
||||
echo $this->buildOperateMenu($bug, 'view');
|
||||
|
||||
echo "<div class='divider'></div>";
|
||||
common::printIcon('bug', 'edit', $params, $bug);
|
||||
common::printIcon('bug', 'create', $copyParams, $bug, 'button', 'copy', '', '', false, "data-app='qa'");
|
||||
if($this->app->openApp != 'product')
|
||||
{
|
||||
common::printIcon('bug', 'create', $copyParams, $bug, 'button', 'copy', '', '', false, "data-app='qa'");
|
||||
}
|
||||
common::printIcon('bug', 'delete', $params, $bug, 'button', 'trash', 'hiddenwin');
|
||||
?>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -274,7 +274,9 @@ class build extends control
|
||||
*/
|
||||
public function delete($buildID, $confirm = 'no')
|
||||
{
|
||||
if($confirm == 'no') { die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes")));
|
||||
if($confirm == 'no')
|
||||
{
|
||||
die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes")));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -227,18 +227,19 @@ class buildModel extends model
|
||||
*
|
||||
* @param int $executionID
|
||||
* @param int $productID
|
||||
* @param int $branch
|
||||
* @param string $params noempty|notrunk, can be a set of them
|
||||
* @param int $buildID
|
||||
* @param string $buildIDList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getExecutionBuildPairs($executionID, $productID, $branch = 0, $params = '', $buildID = 0)
|
||||
public function getExecutionBuildPairs($executionID, $productID, $branch = 0, $params = '', $buildIDList = '')
|
||||
{
|
||||
$sysBuilds = array();
|
||||
$selectedBuilds = array();
|
||||
if(strpos($params, 'noempty') === false) $sysBuilds = array('' => '');
|
||||
if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => $this->lang->trunk);
|
||||
if($buildID != 0) $selectedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->in($buildID)->andWhere('execution')->eq($executionID)->fetchPairs();
|
||||
if($buildIDList) $selectedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->in($buildIDList)->andWhere('execution')->eq($executionID)->fetchPairs();
|
||||
|
||||
$executionBuilds = $this->dao->select('t1.id, t1.name, t1.execution, t2.status as executionStatus, t3.id as releaseID, t3.status as releaseStatus, t4.name as branchName')->from(TABLE_BUILD)->alias('t1')
|
||||
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution = t2.id')
|
||||
|
||||
@@ -475,7 +475,7 @@ class caselibModel extends model
|
||||
}
|
||||
else
|
||||
{
|
||||
$caseData->project = $this->session->project;
|
||||
$caseData->project = (int)$this->session->project;
|
||||
$caseData->version = 1;
|
||||
$caseData->openedBy = $this->app->user->account;
|
||||
$caseData->openedDate = $now;
|
||||
|
||||
@@ -51,16 +51,16 @@ js::set('flow', $config->global->flow);
|
||||
if(common::hasPriv('caselib', 'view'))
|
||||
{
|
||||
$link = helper::createLink('caselib', 'view', "libID=$libID");
|
||||
echo html::a($link, "<i class='icon icon-list-alt muted'> </i>" . $this->lang->caselib->view, '', "class='btn btn-link'");
|
||||
echo html::a($link, "<i class='icon icon-list-alt muted'> </i> " . $this->lang->caselib->view, '', "class='btn btn-link'");
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class='btn-toolbar pull-right'>
|
||||
<div class='btn-group'>
|
||||
<?php common::printLink('caselib', 'exportTemplet', "libID=$libID", "<i class='icon icon-export muted'> </i>" . $lang->caselib->exportTemplet, '', "class='btn btn-link export' data-width='40%'");?>
|
||||
<?php common::printLink('caselib', 'import', "libID=$libID", "<i class='icon muted icon-import'> </i>" . $lang->testcase->fileImport, '', "class='btn btn-link export'");?>
|
||||
<?php common::printLink('caselib', 'exportTemplet', "libID=$libID", "<i class='icon icon-export muted'> </i> " . $lang->caselib->exportTemplet, '', "class='btn btn-link export' data-width='40%'");?>
|
||||
<?php common::printLink('caselib', 'import', "libID=$libID", "<i class='icon muted icon-import'> </i> " . $lang->testcase->fileImport, '', "class='btn btn-link export'");?>
|
||||
</div>
|
||||
<?php echo html::a($this->createLink('caselib', 'create'), "<i class='icon icon-plus'> </i>" . $lang->caselib->create, '', 'class="btn btn-secondary"');?>
|
||||
<?php echo html::a($this->createLink('caselib', 'create'), "<i class='icon icon-plus'> </i> " . $lang->caselib->create, '', 'class="btn btn-secondary"');?>
|
||||
<div class='btn-group dropdown'>
|
||||
<?php
|
||||
$params = "libID=$libID&moduleID=" . (isset($moduleID) ? $moduleID : 0);
|
||||
|
||||
@@ -41,10 +41,10 @@
|
||||
if(count($moduleOptionMenu) == 1)
|
||||
{
|
||||
echo "<span class='input-group-btn'>";
|
||||
echo html::a($this->createLink('tree', 'browse', "rootID=$libID&view=caselib¤tModuleID=0"), "<i class='icon icon-cog'></i>", '_blank', "data-toggle='tooltip' class='btn' title='{$lang->tree->manage}'");
|
||||
echo html::a($this->createLink('tree', 'browse', "rootID=$libID&view=caselib¤tModuleID=0", 'html', true), "<i class='icon icon-cog'></i>", '', "data-toggle='tooltip' class='btn iframe' title='{$lang->tree->manage}'");
|
||||
echo '</span>';
|
||||
echo "<span class='input-group-btn'>";
|
||||
echo html::a("javascript:loadLibModules($libID)", "<i class='icon icon-refresh'></i>", '', "data-toggle='tooltip' class='btn' title='{$lang->refresh}'");
|
||||
echo html::a("javascript:void(0)", "<i class='icon icon-refresh'></i>", '', "class='btn refresh' title='{$lang->refresh}' onclick='loadLibModules($libID)'");
|
||||
echo '</span>';
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -59,22 +59,23 @@ class ci extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to jenkins to check build status.
|
||||
* Send a request to jenkins or gitlab to check build status.
|
||||
*
|
||||
* @param int $compileID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkCompileStatus()
|
||||
public function checkCompileStatus($compileID = 0)
|
||||
{
|
||||
$this->ci->checkCompileStatus();
|
||||
$this->ci->checkCompileStatus($compileID);
|
||||
|
||||
if(dao::isError())
|
||||
{
|
||||
echo json_encode(dao::getError());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'success';
|
||||
}
|
||||
|
||||
echo 'success';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,6 +123,7 @@ class ci extends control
|
||||
$caseResult = $post->funcResult;
|
||||
$firstCase = array_shift($caseResult);
|
||||
$productID = $firstCase->productId;
|
||||
if(empty($productID) and !empty($firstCase->id)) $productID = $this->dao->select('product')->from(TABLE_CASE)->where('id')->eq((int)$firstCase->id)->fetch('product');
|
||||
}
|
||||
if(empty($productID)) die(json_encode(array('result' => 'fail', 'message' => 'productID is not found')));
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
$lang->ci->common = 'CI';
|
||||
$lang->ci->commitResult = 'Interface: Commit Test Result.';
|
||||
$lang->ci->common = 'CI';
|
||||
$lang->ci->commitResult = 'Interface: Commit Test Result.';
|
||||
$lang->ci->checkCompileStatus = 'Interface: Fetch Test Result.';
|
||||
|
||||
$lang->ci->job = 'Job';
|
||||
$lang->ci->task = 'Task';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
$lang->ci->common = '持续集成';
|
||||
$lang->ci->commitResult = '接口:提交测试结果';
|
||||
$lang->ci->common = '持续集成';
|
||||
$lang->ci->commitResult = '接口:提交测试结果';
|
||||
$lang->ci->checkCompileStatus = '接口:获取测试结果';
|
||||
|
||||
$lang->ci->job = '构建';
|
||||
$lang->ci->task = '构建任务';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
$lang->ci->common = '持續整合';
|
||||
$lang->ci->commitResult = '介面:提交測試結果';
|
||||
$lang->ci->common = '持續整合';
|
||||
$lang->ci->commitResult = '介面:提交測試結果';
|
||||
$lang->ci->checkCompileStatus = '介面:獲取測試結果';
|
||||
|
||||
$lang->ci->job = '構建';
|
||||
$lang->ci->task = '構建任務';
|
||||
|
||||
+66
-11
@@ -23,20 +23,23 @@ class ciModel extends model
|
||||
/**
|
||||
* Send a request to jenkins to check build status.
|
||||
*
|
||||
* @param int $compileID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function checkCompileStatus()
|
||||
public function checkCompileStatus($compileID = 0)
|
||||
{
|
||||
$compiles = $this->dao->select('t1.*, t2.pipeline, t3.name as jenkinsName,t3.url,t3.account,t3.token,t3.password')
|
||||
->from(TABLE_COMPILE)->alias('t1')
|
||||
->leftJoin(TABLE_JOB)->alias('t2')->on('t1.job=t2.id')
|
||||
->leftJoin(TABLE_PIPELINE)->alias('t3')->on('t2.server=t3.id')
|
||||
->where('t1.status')->ne('success')
|
||||
->andWhere('t1.status')->ne('failure')
|
||||
->andWhere('t1.status')->ne('create_fail')
|
||||
->andWhere('t1.status')->ne('timeout')
|
||||
->andWhere('t1.createdDate')->gt(date(DT_DATETIME1, strtotime("-1 day")))
|
||||
$compiles = $this->dao->select('compile.*, job.engine,job.pipeline, pipeline.name as jenkinsName,job.server,pipeline.url,pipeline.account,pipeline.token,pipeline.password')
|
||||
->from(TABLE_COMPILE)->alias('compile')
|
||||
->leftJoin(TABLE_JOB)->alias('job')->on('compile.job=job.id')
|
||||
->leftJoin(TABLE_PIPELINE)->alias('pipeline')->on('job.server=pipeline.id')
|
||||
->where('compile.status')->ne('success')
|
||||
->andWhere('compile.status')->ne('failure')
|
||||
->andWhere('compile.status')->ne('create_fail')
|
||||
->andWhere('compile.status')->ne('timeout')
|
||||
->andWhere('compile.status')->ne('canceled')
|
||||
->beginIf($compileID)->andWhere('compile.id')->eq($compileID)->fi()
|
||||
->andWhere('compile.createdDate')->gt(date(DT_DATETIME1, strtotime("-1 day")))
|
||||
->fetchAll();
|
||||
|
||||
foreach($compiles as $compile) $this->syncCompileStatus($compile);
|
||||
@@ -57,6 +60,7 @@ class ciModel extends model
|
||||
return false;
|
||||
}
|
||||
|
||||
if($compile->engine == 'gitlab') return $this->syncGitlabTaskStatus($compile);
|
||||
$jenkinsServer = $compile->url;
|
||||
$jenkinsUser = $compile->account;
|
||||
$jenkinsPassword = $compile->token ? $compile->token : base64_decode($compile->password);
|
||||
@@ -65,7 +69,7 @@ class ciModel extends model
|
||||
|
||||
$response = common::http($queueUrl, '', array(CURLOPT_USERPWD => $userPWD));
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->set('times = times + 1')->where('id')->eq($compile->id)->exec();
|
||||
if($compile->engine != 'gitlab') $this->dao->update(TABLE_COMPILE)->set('times = times + 1')->where('id')->eq($compile->id)->exec();
|
||||
if(strripos($response, "404") > -1)
|
||||
{
|
||||
$infoUrl = sprintf("%s/job/%s/api/xml?tree=builds[id,number,result,queueId]&xpath=//build[queueId=%s]", $jenkinsServer, $compile->pipeline, $compile->queue);
|
||||
@@ -112,6 +116,57 @@ class ciModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync gitlab task status.
|
||||
*
|
||||
* @param object $compile
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function syncGitlabTaskStatus($compile)
|
||||
{
|
||||
$this->loadModel('gitlab');
|
||||
|
||||
$now = helper::now();
|
||||
$pipeline = $this->gitlab->apiGetSinglePipeline($compile->server, $compile->pipeline, $compile->queue);
|
||||
$jobs = $this->gitlab->apiGetJobs($compile->server, $compile->pipeline, $compile->queue);
|
||||
|
||||
$data = new stdclass;
|
||||
$data->status = $pipeline->status;
|
||||
$data->updateDate = $now;
|
||||
|
||||
foreach($jobs as $job)
|
||||
{
|
||||
if(empty($job->duration) or $job->duration == '') $job->duration = '-';
|
||||
$data->logs = "<font style='font-weight:bold'>>>> Job: $job->name, Stage: $job->stage, Status: $job->status, Duration: $job->duration Sec\r\n </font>";
|
||||
$data->logs .= "Job URL: <a href=\"$job->web_url\" target='_blank'>$job->web_url</a> \r\n";
|
||||
$data->logs .= $this->transformAnsiToHtml($this->gitlab->apiGetJobLog($compile->server, $compile->pipeline, $job->id));
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_COMPILE)->data($data)->where('id')->eq($compile->id)->exec();
|
||||
$this->dao->update(TABLE_JOB)->set('lastExec')->eq($now)->set('lastStatus')->eq($pipeline->status)->where('id')->eq($compile->job)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform ansi text to html.
|
||||
*
|
||||
* @param string $text
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function transformAnsiToHtml($text)
|
||||
{
|
||||
$text = preg_replace("/\x1B\[31;40m/", '<font style="color: red">', $text);
|
||||
$text = preg_replace("/\x1B\[32;1m/", '<font style="color: green">', $text);
|
||||
$text = preg_replace("/\x1B\[32;1m/", '<font style="color: green">', $text);
|
||||
$text = preg_replace("/\x1B\[36;1m/", '<font style="color: cyan">', $text);
|
||||
$text = preg_replace("/\x1B\[0;33m/", '<font style="color: yellow">', $text);
|
||||
$text = preg_replace("/\x1B\[1m/", '<font style="font-weight:bold">', $text);
|
||||
$text = preg_replace("/\x1B\[0;m/", '</font><br>', $text);
|
||||
$text = preg_replace("/\x1B\[0K/", '<br>', $text);
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ci build status.
|
||||
*
|
||||
|
||||
@@ -269,6 +269,7 @@ $lang->lang = 'Sprache';
|
||||
/* Theme style. */
|
||||
$lang->theme = 'Theme';
|
||||
$lang->themes['default'] = 'ZenTao Blau (Standard)';
|
||||
$lang->themes['blue'] = 'Blau';
|
||||
$lang->themes['green'] = 'Grün';
|
||||
$lang->themes['red'] = 'Rot';
|
||||
$lang->themes['purple'] = 'Lila';
|
||||
|
||||
+19
-16
@@ -25,21 +25,22 @@ $lang->ellipsis = '…';
|
||||
$lang->percent = '%';
|
||||
$lang->dash = '-';
|
||||
|
||||
$lang->zentaoPMS = 'ZenTao';
|
||||
$lang->logoImg = 'zt-logo-en.png';
|
||||
$lang->welcome = "%s ALM";
|
||||
$lang->logout = 'Logout';
|
||||
$lang->login = 'Login';
|
||||
$lang->help = 'Help';
|
||||
$lang->aboutZenTao = 'About';
|
||||
$lang->profile = 'Profile';
|
||||
$lang->changePassword = 'Password';
|
||||
$lang->unfoldMenu = 'Unfold Menu';
|
||||
$lang->collapseMenu = 'Collapse Menu';
|
||||
$lang->preference = 'Preference';
|
||||
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>Time %s MS, Memory %s KB, Query %s. </div></div>";
|
||||
$lang->agreement = "I have read and agreed to the terms and conditions of <a href='http://zpl.pub/page/zplv12.html' target='_blank'> Z PUBLIC LICENSE 1.2 </a>. <span class='text-danger'>Without authorization, I should not remove, hide or cover any logos/links of ZenTao.</span>";
|
||||
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> AIUX</a>";
|
||||
$lang->zentaoPMS = 'ZenTao';
|
||||
$lang->proName = 'Pro';
|
||||
$lang->logoImg = 'zt-logo-en.png';
|
||||
$lang->welcome = "%s ALM";
|
||||
$lang->logout = 'Logout';
|
||||
$lang->login = 'Login';
|
||||
$lang->help = 'Help';
|
||||
$lang->aboutZenTao = 'About';
|
||||
$lang->profile = 'Profile';
|
||||
$lang->changePassword = 'Password';
|
||||
$lang->unfoldMenu = 'Unfold Menu';
|
||||
$lang->collapseMenu = 'Collapse Menu';
|
||||
$lang->preference = 'Preference';
|
||||
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>Time %s MS, Memory %s KB, Query %s. </div></div>";
|
||||
$lang->agreement = "I have read and agreed to the terms and conditions of <a href='http://zpl.pub/page/zplv12.html' target='_blank'> Z PUBLIC LICENSE 1.2 </a>. <span class='text-danger'>Without authorization, I should not remove, hide or cover any logos/links of ZenTao.</span>";
|
||||
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> AIUX</a>";
|
||||
|
||||
$lang->reset = 'Reset';
|
||||
$lang->cancel = 'Cancel';
|
||||
@@ -112,7 +113,7 @@ $lang->loading = 'Loading...';
|
||||
$lang->notFound = 'Not found!';
|
||||
$lang->notPage = 'Sorry, the features you are visiting are in development!';
|
||||
$lang->showAll = '[[Show All]]';
|
||||
$lang->selectedItems = 'Seleted <strong>{0}</strong> items';
|
||||
$lang->selectedItems = 'Selected <strong>{0}</strong> items';
|
||||
|
||||
$lang->future = 'Waiting';
|
||||
$lang->year = 'Year';
|
||||
@@ -153,6 +154,7 @@ $lang->custom->common = 'Custom';
|
||||
$lang->extension->common = 'Extension';
|
||||
$lang->company->common = 'Company';
|
||||
$lang->dept->common = 'Dept';
|
||||
$lang->upgrade->common = 'Update';
|
||||
$lang->program->list = 'Program List';
|
||||
$lang->execution->list = "{$lang->executionCommon} List";
|
||||
|
||||
@@ -288,6 +290,7 @@ $lang->lang = 'Language';
|
||||
/* Theme style. */
|
||||
$lang->theme = 'Theme';
|
||||
$lang->themes['default'] = 'Default';
|
||||
$lang->themes['blue'] = 'Blue';
|
||||
$lang->themes['green'] = 'Green';
|
||||
$lang->themes['red'] = 'Red';
|
||||
$lang->themes['purple'] = 'Purple';
|
||||
|
||||
@@ -269,6 +269,7 @@ $lang->lang = 'Langue';
|
||||
/* Theme style. */
|
||||
$lang->theme = 'Theme';
|
||||
$lang->themes['default'] = 'Default';
|
||||
$lang->themes['blue'] = 'Blue';
|
||||
$lang->themes['green'] = 'Green';
|
||||
$lang->themes['red'] = 'Red';
|
||||
$lang->themes['purple'] = 'Purple';
|
||||
|
||||
@@ -146,7 +146,7 @@ $lang->product->menu->release = array('link' => "{$lang->release->common}|re
|
||||
$lang->product->menu->roadmap = array('link' => "{$lang->roadmap}|product|roadmap|productID=%s");
|
||||
$lang->product->menu->project = array('link' => "{$lang->project->common}|product|project|status=all&productID=%s");
|
||||
$lang->product->menu->track = array('link' => "{$lang->track}|story|track|productID=%s");
|
||||
$lang->product->menu->doc = array('link' => "{$lang->doc->common}|doc|objectLibs|type=product&objectID=%s", 'subModule' => 'doc');
|
||||
$lang->product->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=product&objectID=%s", 'subModule' => 'doc');
|
||||
$lang->product->menu->dynamic = array('link' => "{$lang->dynamic}|product|dynamic|productID=%s");
|
||||
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
|
||||
|
||||
@@ -184,7 +184,7 @@ $lang->scrum->menu = new stdclass();
|
||||
$lang->scrum->menu->index = array('link' => "{$lang->dashboard}|project|index|project=%s");
|
||||
$lang->scrum->menu->execution = array('link' => "$lang->executionCommon|project|execution|status=all&projectID=%s", 'exclude' => 'execution-testreport');
|
||||
$lang->scrum->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree', 'alias' => 'story,track');
|
||||
$lang->scrum->menu->doc = array('link' => "{$lang->doc->common}|doc|objectLibs|type=project&objectID=%s", 'subModule' => 'doc');
|
||||
$lang->scrum->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=project&objectID=%s", 'subModule' => 'doc');
|
||||
$lang->scrum->menu->qa = array('link' => "{$lang->qa->common}|project|bug|projectID=%s", 'subModule' => 'testcase,testtask,bug,testreport,execution', 'alias' => 'bug,testtask,testcase,testreport', 'exclude' => 'execution-create,execution-batchedit');
|
||||
$lang->scrum->menu->devops = array('link' => "{$lang->repo->common}|repo|browse|repoID=0&branchID=&objectID=%s", 'subModule' => 'repo');
|
||||
$lang->scrum->menu->build = array('link' => "{$lang->build->common}|project|build|project=%s");
|
||||
@@ -236,7 +236,7 @@ $lang->execution->menu->view = array('link' => "$lang->view|execution|groupt
|
||||
$lang->execution->menu->story = array('link' => "$lang->SRCommon|execution|story|executionID=%s", 'subModule' => 'story', 'alias' => 'batchcreate,linkstory,storykanban');
|
||||
$lang->execution->menu->qa = array('link' => "{$lang->qa->common}|execution|bug|executionID=%s", 'subModule' => 'bug,testcase,testtask,testreport', 'alias' => 'qa,bug,testcase,testtask,testreport');
|
||||
$lang->execution->menu->devops = array('link' => "{$lang->repo->common}|repo|browse|repoID=0&branchID=&objectID=%s", 'subModule' => 'repo');
|
||||
$lang->execution->menu->doc = array('link' => "{$lang->doc->common}|doc|objectLibs|type=execution&objectID=%s", 'subModule' => 'doc');
|
||||
$lang->execution->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=execution&objectID=%s", 'subModule' => 'doc');
|
||||
$lang->execution->menu->build = array('link' => "{$lang->build->common}|execution|build|executionID=%s", 'subModule' => 'build');
|
||||
$lang->execution->menu->action = array('link' => "$lang->dynamic|execution|dynamic|executionID=%s");
|
||||
$lang->execution->menu->settings = array('link' => "$lang->settings|execution|view|executionID=%s", 'subModule' => 'personnel', 'alias' => 'edit,manageproducts,team,whitelist,addwhitelist,managemembers', 'class' => 'dropdown dropdown-hover');
|
||||
@@ -329,16 +329,16 @@ $lang->devops->menuOrder[20] = 'jenkins';
|
||||
$lang->devops->menuOrder[25] = 'maintain';
|
||||
$lang->devops->menuOrder[30] = 'rules';
|
||||
|
||||
/* Doc menu.*/
|
||||
/* 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|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');
|
||||
$lang->doc->menu->custom = array('link' => "{$lang->doc->custom}|doc|objectLibs|type=custom", 'alias' => 'custom');
|
||||
$lang->doc->menu->product = array('link' => "{$lang->doc->product}|doc|tableContents|type=product", 'alias' => 'showfiles,product');
|
||||
if($config->systemMode == 'new') $lang->doc->menu->project = array('link' => "{$lang->doc->project}|doc|tableContents|type=project", 'alias' => 'showfiles,project');
|
||||
if($config->systemMode == 'classic') $lang->doc->menu->execution = array('link' => "{$lang->doc->execution}|doc|tableContents|type=execution", 'alias' => 'showfiles,execution');
|
||||
$lang->doc->menu->custom = array('link' => "{$lang->doc->custom}|doc|tableContents|type=custom", 'alias' => 'custom');
|
||||
|
||||
$lang->doc->dividerMenu = ',product,';
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ $lang->lang = 'Ngôn ngữ';
|
||||
/* Theme style. */
|
||||
$lang->theme = 'Theme';
|
||||
$lang->themes['default'] = 'Mặc định';
|
||||
$lang->themes['blue'] = 'Blue';
|
||||
$lang->themes['green'] = 'Green';
|
||||
$lang->themes['red'] = 'Red';
|
||||
$lang->themes['purple'] = 'Purple';
|
||||
|
||||
@@ -25,21 +25,22 @@ $lang->ellipsis = '…';
|
||||
$lang->percent = '%';
|
||||
$lang->dash = '-';
|
||||
|
||||
$lang->zentaoPMS = '禅道';
|
||||
$lang->logoImg = 'zt-logo.png';
|
||||
$lang->welcome = "%s项目管理系统";
|
||||
$lang->logout = '退出';
|
||||
$lang->login = '登录';
|
||||
$lang->help = '帮助';
|
||||
$lang->aboutZenTao = '关于禅道';
|
||||
$lang->profile = '个人档案';
|
||||
$lang->changePassword = '修改密码';
|
||||
$lang->unfoldMenu = '展开导航';
|
||||
$lang->collapseMenu = '收起导航';
|
||||
$lang->preference = '个性化设置';
|
||||
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>时间: %s 毫秒, 内存: %s KB, 查询: %s. </div></div>";
|
||||
$lang->agreement = "已阅读并同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授权协议1.2》</a>。<span class='text-danger'>未经许可,不得去除、隐藏或遮掩禅道软件的任何标志及链接。</span>";
|
||||
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> 艾体验设计</a>";
|
||||
$lang->zentaoPMS = '禅道';
|
||||
$lang->proName = '专业版';
|
||||
$lang->logoImg = 'zt-logo.png';
|
||||
$lang->welcome = "%s项目管理系统";
|
||||
$lang->logout = '退出';
|
||||
$lang->login = '登录';
|
||||
$lang->help = '帮助';
|
||||
$lang->aboutZenTao = '关于禅道';
|
||||
$lang->profile = '个人档案';
|
||||
$lang->changePassword = '修改密码';
|
||||
$lang->unfoldMenu = '展开导航';
|
||||
$lang->collapseMenu = '收起导航';
|
||||
$lang->preference = '个性化设置';
|
||||
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>时间: %s 毫秒, 内存: %s KB, 查询: %s. </div></div>";
|
||||
$lang->agreement = "已阅读并同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授权协议1.2》</a>。<span class='text-danger'>未经许可,不得去除、隐藏或遮掩禅道软件的任何标志及链接。</span>";
|
||||
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> 艾体验设计</a>";
|
||||
|
||||
$lang->reset = '重填';
|
||||
$lang->cancel = '取消';
|
||||
@@ -153,6 +154,7 @@ $lang->custom->common = '自定义';
|
||||
$lang->extension->common = '插件';
|
||||
$lang->company->common = '公司';
|
||||
$lang->dept->common = '部门';
|
||||
$lang->upgrade->common = '升级';
|
||||
$lang->program->list = '项目集列表';
|
||||
$lang->execution->list = "{$lang->executionCommon}列表";
|
||||
|
||||
@@ -288,6 +290,7 @@ $lang->lang = 'Language';
|
||||
/* 风格列表。*/
|
||||
$lang->theme = '主题';
|
||||
$lang->themes['default'] = '禅道蓝(默认)';
|
||||
$lang->themes['blue'] = '青春蓝';
|
||||
$lang->themes['green'] = '叶兰绿';
|
||||
$lang->themes['red'] = '赤诚红';
|
||||
$lang->themes['purple'] = '玉烟紫';
|
||||
|
||||
@@ -25,21 +25,22 @@ $lang->ellipsis = '…';
|
||||
$lang->percent = '%';
|
||||
$lang->dash = '-';
|
||||
|
||||
$lang->zentaoPMS = '禪道';
|
||||
$lang->logoImg = 'zt-logo.png';
|
||||
$lang->welcome = "%s項目管理系統";
|
||||
$lang->logout = '退出';
|
||||
$lang->login = '登錄';
|
||||
$lang->help = '幫助';
|
||||
$lang->aboutZenTao = '關於禪道';
|
||||
$lang->profile = '個人檔案';
|
||||
$lang->changePassword = '修改密碼';
|
||||
$lang->unfoldMenu = '展開導航';
|
||||
$lang->collapseMenu = '收起導航';
|
||||
$lang->preference = '個性化設置';
|
||||
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>時間: %s 毫秒, 內存: %s KB, 查詢: %s. </div></div>";
|
||||
$lang->agreement = "已閲讀並同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授權協議1.2》</a>。<span class='text-danger'>未經許可,不得去除、隱藏或遮掩禪道軟件的任何標誌及連結。</span>";
|
||||
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> 艾體驗設計</a>";
|
||||
$lang->zentaoPMS = '禪道';
|
||||
$lang->proName = '專業版';
|
||||
$lang->logoImg = 'zt-logo.png';
|
||||
$lang->welcome = "%s項目管理系統";
|
||||
$lang->logout = '退出';
|
||||
$lang->login = '登錄';
|
||||
$lang->help = '幫助';
|
||||
$lang->aboutZenTao = '關於禪道';
|
||||
$lang->profile = '個人檔案';
|
||||
$lang->changePassword = '修改密碼';
|
||||
$lang->unfoldMenu = '展開導航';
|
||||
$lang->collapseMenu = '收起導航';
|
||||
$lang->preference = '個性化設置';
|
||||
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>時間: %s 毫秒, 內存: %s KB, 查詢: %s. </div></div>";
|
||||
$lang->agreement = "已閲讀並同意<a href='http://zpl.pub/page/zplv12.html' target='_blank'>《Z PUBLIC LICENSE授權協議1.2》</a>。<span class='text-danger'>未經許可,不得去除、隱藏或遮掩禪道軟件的任何標誌及連結。</span>";
|
||||
$lang->designedByAIUX = "<a href='https://api.zentao.net/goto.php?item=aiux' class='link-aiux' target='_blank'><i class='icon icon-aiux'></i> 艾體驗設計</a>";
|
||||
|
||||
$lang->reset = '重填';
|
||||
$lang->cancel = '取消';
|
||||
@@ -153,6 +154,7 @@ $lang->custom->common = '自定義';
|
||||
$lang->extension->common = '插件';
|
||||
$lang->company->common = '公司';
|
||||
$lang->dept->common = '部門';
|
||||
$lang->upgrade->common = '升級';
|
||||
$lang->program->list = '項目集列表';
|
||||
$lang->execution->list = "{$lang->executionCommon}列表";
|
||||
|
||||
@@ -288,6 +290,7 @@ $lang->lang = 'Language';
|
||||
/* 風格列表。*/
|
||||
$lang->theme = '主題';
|
||||
$lang->themes['default'] = '禪道藍(預設)';
|
||||
$lang->themes['blue'] = '青春藍';
|
||||
$lang->themes['green'] = '葉蘭綠';
|
||||
$lang->themes['red'] = '赤誠紅';
|
||||
$lang->themes['purple'] = '玉煙紫';
|
||||
|
||||
+84
-20
@@ -185,6 +185,7 @@ class commonModel extends model
|
||||
if($this->loadModel('user')->isLogon() or ($this->app->company->guest and $this->app->user->account == 'guest'))
|
||||
{
|
||||
if(stripos($method, 'ajax') !== false) return true;
|
||||
if($module == 'my' and $method == 'guidechangetheme') return true;
|
||||
if($module == 'misc' and $method == 'downloadclient') return true;
|
||||
if($module == 'misc' and $method == 'changelog') return true;
|
||||
if($module == 'tutorial' and $method == 'start') return true;
|
||||
@@ -544,7 +545,8 @@ class commonModel extends model
|
||||
|
||||
if($config->systemMode == 'classic' and $openApp == 'execution') $icon = zget($lang->navIcons, 'project', '');
|
||||
$link = helper::createLink($currentModule, $currentMethod);
|
||||
$html = $link ? html::a($link, "$icon {$lang->$openApp->common}", '', "class='btn'") : "$icon {$lang->$openApp->common}";
|
||||
$className = $openApp == 'devops' ? 'btn num' : 'btn';
|
||||
$html = $link ? html::a($link, "$icon {$lang->$openApp->common}", '', "class='$className'") : "$icon {$lang->$openApp->common}";
|
||||
|
||||
echo "<div class='btn-group header-btn'>" . $html . '</div>';
|
||||
}
|
||||
@@ -576,7 +578,24 @@ class commonModel extends model
|
||||
/* When last divider is not used in mainNav, use it next menu. */
|
||||
$divider = ($divider || ($lastItem != $key) && strpos($lang->dividerMenu, ",{$group},") !== false) ? true : false;
|
||||
|
||||
if(!common::hasPriv($currentModule, $currentMethod)) continue;
|
||||
if(!common::hasPriv($currentModule, $currentMethod))
|
||||
{
|
||||
$hidden = true;
|
||||
if($currentModule == 'assetlib')
|
||||
{
|
||||
$methodList = array('caselib', 'issuelib', 'risklib', 'opportunitylib', 'practicelib', 'componentlib');
|
||||
foreach($methodList as $method)
|
||||
{
|
||||
if(common::hasPriv($currentModule, $method))
|
||||
{
|
||||
$hidden = false;
|
||||
$currentMethod = $method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($hidden) continue;
|
||||
}
|
||||
|
||||
if($divider and !empty($items))
|
||||
{
|
||||
@@ -1333,7 +1352,14 @@ EOD;
|
||||
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->pre->$id) : helper::createLink($moduleName, 'view', "ID={$preAndNext->pre->$id}");
|
||||
$link .= '#app=' . $app->openApp;
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-left"></i>', '', "id='prevPage' class='btn' title='{$title}'");
|
||||
if(isset($preAndNext->pre->objectType) and $preAndNext->pre->objectType == 'doc')
|
||||
{
|
||||
echo html::a('javascript:void(0)', '<i class="icon-pre icon-chevron-left"></i>', '', "id='prevPage' class='btn' title='{$title}' data-url='{$link}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-left"></i>', '', "id='prevPage' class='btn' title='{$title}'");
|
||||
}
|
||||
}
|
||||
if(isset($preAndNext->next) and $preAndNext->next)
|
||||
{
|
||||
@@ -1342,7 +1368,14 @@ EOD;
|
||||
$title = '#' . $preAndNext->next->$id . ' ' . $title . ' ' . $lang->nextShortcutKey;
|
||||
$link = $linkTemplate ? sprintf($linkTemplate, $preAndNext->next->$id) : helper::createLink($moduleName, 'view', "ID={$preAndNext->next->$id}");
|
||||
$link .= '#app=' . $app->openApp;
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-right"></i>', '', "id='nextPage' class='btn' title='$title'");
|
||||
if(isset($preAndNext->next->objectType) and $preAndNext->next->objectType == 'doc')
|
||||
{
|
||||
echo html::a('javascript:void(0)', '<i class="icon-pre icon-chevron-right"></i>', '', "id='nextPage' class='btn' title='$title' data-url='{$link}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo html::a($link, '<i class="icon-pre icon-chevron-right"></i>', '', "id='nextPage' class='btn' title='$title'");
|
||||
}
|
||||
}
|
||||
echo '</nav>';
|
||||
}
|
||||
@@ -1350,13 +1383,14 @@ EOD;
|
||||
/**
|
||||
* Create changes of one object.
|
||||
*
|
||||
* @param mixed $old the old object
|
||||
* @param mixed $new the new object
|
||||
* @param mixed $old the old object
|
||||
* @param mixed $new the new object
|
||||
* @param string $moduleName
|
||||
* @static
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public static function createChanges($old, $new)
|
||||
public static function createChanges($old, $new, $moduleName = '')
|
||||
{
|
||||
global $app, $config;
|
||||
|
||||
@@ -1373,7 +1407,7 @@ EOD;
|
||||
|
||||
if($oldID && $oldStatus && $newStatus && !$newSubStatus && $oldStatus != $newStatus)
|
||||
{
|
||||
$moduleName = $app->getModuleName();
|
||||
if(empty($moduleName)) $moduleName = $app->getModuleName();
|
||||
|
||||
$field = $app->dbh->query('SELECT options FROM ' . TABLE_WORKFLOWFIELD . " WHERE `module` = '$moduleName' AND `field` = 'subStatus'")->fetch();
|
||||
if(!empty($field->options)) $field->options = json_decode($field->options, true);
|
||||
@@ -1963,6 +1997,7 @@ EOD;
|
||||
{
|
||||
$httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
|
||||
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https';
|
||||
if(isset($_SERVER['REQUEST_SCHEME']) and strtolower($_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https';
|
||||
$httpHost = $_SERVER['HTTP_HOST'];
|
||||
return "$httpType://$httpHost";
|
||||
}
|
||||
@@ -2024,6 +2059,29 @@ EOD;
|
||||
return $convertedItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an entry of new API.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
private function checkNewEntry()
|
||||
{
|
||||
$entry = $this->loadModel('entry')->getByKey(session_id());
|
||||
if(!$entry or !$entry->account or !$this->checkIP($entry->ip)) return false;
|
||||
|
||||
$user = $this->dao->findByAccount($entry->account)->from(TABLE_USER)->andWhere('deleted')->eq(0)->fetch();
|
||||
if(!$user) return false;
|
||||
|
||||
$user->last = time();
|
||||
$user->rights = $this->loadModel('user')->authorize($user->account);
|
||||
$user->groups = $this->user->getGroups($user->account);
|
||||
$user->view = $this->user->grantUserView($user->account, $user->rights['acls']);
|
||||
$user->admin = strpos($this->app->company->admins, ",{$user->account},") !== false;
|
||||
$this->session->set('user', $user);
|
||||
$this->app->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check an entry.
|
||||
*
|
||||
@@ -2032,20 +2090,18 @@ EOD;
|
||||
*/
|
||||
public function checkEntry()
|
||||
{
|
||||
if($this->isOpenMethod($_GET[$this->config->moduleVar], $_GET[$this->config->methodVar])) return true;
|
||||
/* if the API is new version, goto checkNewEntry. */
|
||||
if($this->app->version) return $this->checkNewEntry();
|
||||
|
||||
$this->loadModel('entry');
|
||||
if($this->session->valid_entry)
|
||||
{
|
||||
if(!$this->session->entry_code) $this->response('SESSION_CODE_MISSING');
|
||||
if($this->session->valid_entry != md5(md5($this->get->code) . $this->server->remote_addr)) $this->response('SESSION_VERIFY_FAILED');
|
||||
return true;
|
||||
}
|
||||
/* Old version. */
|
||||
if(!isset($_GET[$this->config->moduleVar]) or !isset($_GET[$this->config->methodVar])) $this->response('EMPTY_ENTRY');
|
||||
if($this->isOpenMethod($_GET[$this->config->moduleVar], $_GET[$this->config->methodVar])) return true;
|
||||
|
||||
if(!$this->get->code) $this->response('PARAM_CODE_MISSING');
|
||||
if(!$this->get->token) $this->response('PARAM_TOKEN_MISSING');
|
||||
|
||||
$entry = $this->entry->getByCode($this->get->code);
|
||||
$entry = $this->loadModel('entry')->getByCode($this->get->code);
|
||||
|
||||
if(!$entry) $this->response('EMPTY_ENTRY');
|
||||
if(!$entry->key) $this->response('EMPTY_KEY');
|
||||
if(!$this->checkIP($entry->ip)) $this->response('IP_DENIED');
|
||||
@@ -2205,10 +2261,18 @@ EOD;
|
||||
public function response($code)
|
||||
{
|
||||
$response = new stdclass();
|
||||
$response->errcode = $this->config->entry->errcode[$code];
|
||||
$response->errmsg = urlencode($this->lang->entry->errmsg[$code]);
|
||||
if(isset($this->config->entry->errcode))
|
||||
{
|
||||
$response->errcode = $this->config->entry->errcode[$code];
|
||||
$response->errmsg = urlencode($this->lang->entry->errmsg[$code]);
|
||||
|
||||
die(urldecode(json_encode($response)));
|
||||
die(urldecode(json_encode($response)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$response->error = $code;
|
||||
die(urldecode(json_encode($response)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,8 +10,6 @@ $editor['id'] = explode(',', $editor['id']);
|
||||
<?php js::import($jsRoot . 'markdown/simplemde.min.js'); ?>
|
||||
<style>
|
||||
.CodeMirror,.CodeMirror-scroll{min-height:200px!important;}
|
||||
.CodeMirror-fullscreen + .editor-preview-side{display:block;}
|
||||
.CodeMirror-fullscreen, .editor-preview-side{margin-bottom:40px;}
|
||||
.editor-preview-side table > tbody > tr:last-child td{border:1px solid #e5e5e5 !important}
|
||||
.editor-toolbar {padding: 1px;}
|
||||
.editor-toolbar .icon-html:before {content:"HTML"; font-size: 12px; padding: 0 2px;}
|
||||
@@ -37,15 +35,29 @@ $editor['id'] = explode(',', $editor['id']);
|
||||
$(function()
|
||||
{
|
||||
var markdownEditor = <?php echo json_encode($editor);?>;
|
||||
var toolbar = ["bold", "italic", "heading", "|", "quote", "unordered-list", "ordered-list", "|", "link", "image", "code", "table", "|", "preview", "side-by-side", "fullscreen", "|", "guide"];
|
||||
var withchange = ["bold", "italic", "heading", "|", "quote", "unordered-list", "ordered-list", "|", "link", "image", "code", "table", "|", "preview", "side-by-side", "fullscreen", "|", "guide", {name: "html", action: function customFunction(editor){toggleEditor("html")}, className:'icon icon-html', title:"HTML"}];
|
||||
const customFullscreen =
|
||||
{
|
||||
name: 'fullscreen',
|
||||
className: 'icon icon-expand-full',
|
||||
title: 'Fullscreen',
|
||||
action: function(editor)
|
||||
{
|
||||
editor.toggleFullScreen();
|
||||
if(editor.isFullscreenActive() && !editor.isSideBySideActive())
|
||||
{
|
||||
editor.toggleSideBySide();
|
||||
}
|
||||
}
|
||||
};
|
||||
var toolbar = ["bold", "italic", "heading", "|", "quote", "unordered-list", "ordered-list", "|", "link", "image", "code", "table", "|", "preview", "side-by-side", customFullscreen, "|", "guide"];
|
||||
var withchange = ["bold", "italic", "heading", "|", "quote", "unordered-list", "ordered-list", "|", "link", "image", "code", "table", "|", "preview", "side-by-side", customFullscreen, "|", "guide", {name: "html", action: function customFunction(editor){toggleEditor && toggleEditor("html")}, className:'icon icon-html', title:"HTML"}];
|
||||
function initMarkdown(config, afterInit)
|
||||
{
|
||||
config = config || markdownEditor;
|
||||
$.each(markdownEditor.id, function(key, markdownEditorID)
|
||||
{
|
||||
if(typeof(markdownEditor.tools) != 'undefined' && markdownEditor.tools == 'withchange') toolbar = withchange;
|
||||
var options =
|
||||
var options =
|
||||
{
|
||||
toolbar: toolbar,
|
||||
element: $('#' + markdownEditorID)[0],
|
||||
@@ -56,11 +68,6 @@ $(function()
|
||||
var markdown = new SimpleMDE(options);
|
||||
if(!window.markdownEditor) window.markdownEditor = {};
|
||||
window.markdownEditor['#'] = window.markdownEditor[markdownEditorID] = markdown;
|
||||
// markdown.codemirror.on('focus', function(){window.markdownEditor[markdownEditorID].toggleSideBySide();});
|
||||
// markdown.codemirror.on('change', function()
|
||||
// {
|
||||
// if($('#' + markdownEditorID).parent().find('.editor-preview-active-side').size() == 0) window.markdownEditor[markdownEditorID].toggleSideBySide();
|
||||
// });
|
||||
});
|
||||
|
||||
if($.isFunction(afterInit)) afterInit();
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<style>
|
||||
tbody.sortable > tr.drag-shadow {display: none}
|
||||
tbody.sortable > tr > td.sort-handler {cursor: move; color: #999;}
|
||||
tbody.sortable > tr > td.sort-handler > i {position: relative; top: 2px}
|
||||
tbody.sortable-sorting > tr {transition: all .2s; position: relative; z-index: 5; opacity: .3;}
|
||||
tbody.sortable-sorting {cursor: move;}
|
||||
tbody.sortable-sorting > tr.drag-row {opacity: 1; z-index: 10; box-shadow: 0 2px 4px red}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<?php $openApp = '';?>
|
||||
<?php if($action->objectType == 'meeting') $openApp = $action->project ? "data-app='project'" : "data-app='my'";?>
|
||||
<?php
|
||||
if(isset($config->maxVersion) and strpos($config->action->assetType, $action->objectType) !== false and empty($action->objectName))
|
||||
if((isset($config->maxVersion) and strpos($config->action->assetType, $action->objectType) !== false) or empty($action->objectName))
|
||||
{
|
||||
echo '#' . $action->objectID;
|
||||
}
|
||||
|
||||
@@ -64,8 +64,11 @@ class compile extends control
|
||||
public function logs($buildID)
|
||||
{
|
||||
$build = $this->compile->getByID($buildID);
|
||||
$job = $this->loadModel('job')->getByID($build->job);
|
||||
|
||||
$this->view->logs = str_replace("\r\n","<br />", $build->logs);
|
||||
$this->view->build = $build;
|
||||
$this->view->job = $job;
|
||||
|
||||
$this->view->title = $this->lang->ci->job . $this->lang->colon . $this->lang->compile->logs;
|
||||
$this->view->position[] = html::a($this->createLink('job', 'browse'), $this->lang->ci->job);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
$().ready(function()
|
||||
{
|
||||
$('#refreshBtn').click(function()
|
||||
{
|
||||
$url = $(this).attr('href');
|
||||
$.get($url, function(response)
|
||||
{
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -3,15 +3,20 @@ $lang->compile->common = 'Compile';
|
||||
$lang->compile->browse = 'History';
|
||||
$lang->compile->logs = 'Log';
|
||||
|
||||
$lang->compile->id = 'ID';
|
||||
$lang->compile->name = 'Name';
|
||||
$lang->compile->status = 'Status';
|
||||
$lang->compile->time = 'Time';
|
||||
$lang->compile->result = 'Result';
|
||||
$lang->compile->id = 'ID';
|
||||
$lang->compile->name = 'Name';
|
||||
$lang->compile->buildType = 'Engine';
|
||||
$lang->compile->status = 'Status';
|
||||
$lang->compile->time = 'Time';
|
||||
$lang->compile->result = 'Result';
|
||||
$lang->compile->refresh = 'Refresh';
|
||||
|
||||
$lang->compile->statusList['success'] = 'Done';
|
||||
$lang->compile->statusList['failure'] = 'Failed';
|
||||
$lang->compile->statusList['created'] = 'Created';
|
||||
$lang->compile->statusList['building'] = 'Creating';
|
||||
$lang->compile->statusList['pending'] = 'Pending';
|
||||
$lang->compile->statusList['running'] = 'Running';
|
||||
$lang->compile->statusList['building'] = 'Building';
|
||||
$lang->compile->statusList['create_fail'] = 'Failed to create';
|
||||
$lang->compile->statusList['timeout'] = 'Timeout';
|
||||
$lang->compile->statusList['canceled'] = 'Canceled';
|
||||
|
||||
@@ -9,10 +9,14 @@ $lang->compile->buildType = '构建引擎';
|
||||
$lang->compile->status = '构建状态';
|
||||
$lang->compile->time = '构建时间';
|
||||
$lang->compile->result = '构建结果';
|
||||
$lang->compile->refresh = '刷新';
|
||||
|
||||
$lang->compile->statusList['success'] = '成功';
|
||||
$lang->compile->statusList['failure'] = '失败';
|
||||
$lang->compile->statusList['created'] = '新建';
|
||||
$lang->compile->statusList['pending'] = '队列中';
|
||||
$lang->compile->statusList['running'] = '运行中';
|
||||
$lang->compile->statusList['building'] = '构建中';
|
||||
$lang->compile->statusList['create_fail'] = '创建失败';
|
||||
$lang->compile->statusList['timeout'] = '执行超时';
|
||||
$lang->compile->statusList['canceled'] = '已取消';
|
||||
|
||||
@@ -3,15 +3,20 @@ $lang->compile->common = '構建';
|
||||
$lang->compile->browse = '構建歷史';
|
||||
$lang->compile->logs = '構建日誌';
|
||||
|
||||
$lang->compile->id = 'ID';
|
||||
$lang->compile->name = '構建名稱';
|
||||
$lang->compile->status = '構建狀態';
|
||||
$lang->compile->time = '構建時間';
|
||||
$lang->compile->result = '構建結果';
|
||||
$lang->compile->id = 'ID';
|
||||
$lang->compile->name = '構建名稱';
|
||||
$lang->compile->buildType = '構建引擎';
|
||||
$lang->compile->status = '構建狀態';
|
||||
$lang->compile->time = '構建時間';
|
||||
$lang->compile->result = '構建結果';
|
||||
$lang->compile->refresh = '刷新';
|
||||
|
||||
$lang->compile->statusList['success'] = '成功';
|
||||
$lang->compile->statusList['failure'] = '失敗';
|
||||
$lang->compile->statusList['created'] = '新建';
|
||||
$lang->compile->statusList['pending'] = '隊列中';
|
||||
$lang->compile->statusList['running'] = '運行中';
|
||||
$lang->compile->statusList['building'] = '構建中';
|
||||
$lang->compile->statusList['create_fail'] = '創建失敗';
|
||||
$lang->compile->statusList['timeout'] = '執行超時';
|
||||
$lang->compile->statusList['canceled'] = '已取消';
|
||||
|
||||
+15
-15
@@ -12,9 +12,9 @@
|
||||
class compileModel extends model
|
||||
{
|
||||
/**
|
||||
* Get by id
|
||||
*
|
||||
* @param int $buildID
|
||||
* Get by id
|
||||
*
|
||||
* @param int $buildID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
@@ -25,10 +25,10 @@ class compileModel extends model
|
||||
|
||||
/**
|
||||
* Get build list.
|
||||
*
|
||||
* @param int $jobID
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
*
|
||||
* @param int $jobID
|
||||
* @param string $orderBy
|
||||
* @param object $pager
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -48,7 +48,7 @@ class compileModel extends model
|
||||
|
||||
/**
|
||||
* Get unexecuted list.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
@@ -59,7 +59,7 @@ class compileModel extends model
|
||||
|
||||
/**
|
||||
* Get last result.
|
||||
*
|
||||
*
|
||||
* @param int $jobID
|
||||
* @access public
|
||||
* @return object
|
||||
@@ -71,7 +71,7 @@ class compileModel extends model
|
||||
|
||||
/**
|
||||
* Get build url.
|
||||
*
|
||||
*
|
||||
* @param object $jenkins
|
||||
* @access public
|
||||
* @return object
|
||||
@@ -91,10 +91,10 @@ class compileModel extends model
|
||||
|
||||
/**
|
||||
* Save build by job
|
||||
*
|
||||
* @param int $jobID
|
||||
* @param string $data
|
||||
* @param string $type
|
||||
*
|
||||
* @param int $jobID
|
||||
* @param string $data
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -114,7 +114,7 @@ class compileModel extends model
|
||||
|
||||
/**
|
||||
* Execute compile
|
||||
*
|
||||
*
|
||||
* @param object $compile
|
||||
* @access public
|
||||
* @return bool
|
||||
|
||||
@@ -19,7 +19,11 @@
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if(empty($buildList)):?>
|
||||
<div class="table-empty-tip">
|
||||
<p><span class="text-muted"><?php echo $lang->noData;?></span></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div id='mainContent'>
|
||||
<form class='main-table' id='ajaxForm' method='post'>
|
||||
<table id='buildList' class='table has-sort-head table-fixed'>
|
||||
@@ -40,7 +44,7 @@
|
||||
<?php foreach($buildList as $id => $build):?>
|
||||
<tr>
|
||||
<td class='text-center'><?php echo $id;?></td>
|
||||
<td title='<?php echo $build->name;?>'><?php echo common::hasPriv('job', 'view') ? html::a($this->createLink('job', 'view', "jobID={$build->job}&compileID={$build->id}", 'html', true), $build->name, '', "class='iframe' data-width='90%'") : $build->name;?></td>
|
||||
<td class='c-name' title='<?php echo $build->name;?>'><?php echo common::hasPriv('job', 'view') ? html::a($this->createLink('job', 'view', "jobID={$build->job}&compileID={$build->id}", 'html', true), $build->name, '', "class='iframe' data-width='90%'") : $build->name;?></td>
|
||||
<td title='<?php echo $build->engine;?>'><?php echo $build->engine;?></td>
|
||||
<td title='<?php echo $build->repoName;?>'><?php echo $build->repoName;?></td>
|
||||
<?php $jenkins = urldecode($build->pipeline) . '@' . $build->jenkinsName;?>
|
||||
@@ -67,4 +71,5 @@
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-toolbar pull-right">
|
||||
<?php if($job->engine == 'gitlab') echo html::a(helper::createLink('ci', "checkCompileStatus", "compileID={$build->id}"), "<i class='icon icon-eye icon-sm'></i> ". $lang->compile->refresh, '', "class='btn btn-secondary' id='refreshBtn'");?>
|
||||
<?php echo html::a(helper::createLink('compile', "browse", "jobID=$build->job"), "<i class='icon icon-back icon-sm'></i> ". $lang->goback, '', "class='btn btn-secondary'");?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
common::printLink('custom', $sysObject, "", "<span class='text'>{$lang->custom->$sysObject}</span>", '', "class='btn btn-link' id='{$sysObject}Tab'");
|
||||
}
|
||||
|
||||
common::printLink('custom', 'mode', "", "<span class='text'>{$lang->custom->mode}</span>", '', "class='btn btn-link' id='modeTab'");
|
||||
if($config->systemMode == 'classic') common::printLink('custom', 'mode', "", "<span class='text'>{$lang->custom->mode}</span>", '', "class='btn btn-link' id='modeTab'");
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -28,6 +28,15 @@ $config->doc->editor->view = array('id' => 'comment,lastComment', 'tools' => '
|
||||
$config->doc->markdown = new stdclass();
|
||||
$config->doc->markdown->create = array('id' => 'contentMarkdown', 'tools' => 'withchange');
|
||||
|
||||
$config->doc->collectionLimit = 10;
|
||||
|
||||
$config->doc->iconList['html'] = 'rich-text';
|
||||
$config->doc->iconList['markdown'] = 'markdown';
|
||||
$config->doc->iconList['url'] = 'text-link';
|
||||
$config->doc->iconList['word'] = 'word';
|
||||
$config->doc->iconList['ppt'] = 'ppt';
|
||||
$config->doc->iconList['excel'] = 'excel';
|
||||
|
||||
$config->doc->search['module'] = 'doc';
|
||||
$config->doc->search['fields']['title'] = $lang->doc->title;
|
||||
$config->doc->search['fields']['id'] = $lang->doc->id;
|
||||
|
||||
+179
-98
@@ -70,7 +70,12 @@ class doc extends control
|
||||
*/
|
||||
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');
|
||||
/* Save session, load module. */
|
||||
$uri = $this->app->getURI(true);
|
||||
$this->session->set('docList', $uri, 'doc');
|
||||
$this->session->set('productList', $uri, 'product');
|
||||
$this->session->set('executionList', $uri, 'execution');
|
||||
$this->session->set('projectList', $uri, 'project');
|
||||
$this->loadModel('search');
|
||||
|
||||
/* Set browseType.*/
|
||||
@@ -163,9 +168,9 @@ class doc extends control
|
||||
}
|
||||
|
||||
$libTypeList = $this->lang->doc->libTypeList;
|
||||
if(empty($products)) unset($libTypeList['product']);
|
||||
if(empty($projects)) unset($libTypeList['project']);
|
||||
if(empty($executions)) unset($libTypeList['execution']);
|
||||
if(empty($products)) unset($libTypeList['product']);
|
||||
if(empty($projects)) unset($libTypeList['project']);
|
||||
if(empty($executions) or ($this->config->systemMode == 'new' and $this->app->openApp == 'doc')) unset($libTypeList['execution']);
|
||||
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->users = $this->user->getPairs('nocode');
|
||||
@@ -223,16 +228,18 @@ class doc extends control
|
||||
* Delete a library.
|
||||
*
|
||||
* @param int $libID
|
||||
* @param string $confirm yes|no
|
||||
* @param string $confirm yes|no
|
||||
* @param string $from lib|book
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deleteLib($libID, $confirm = 'no')
|
||||
public function deleteLib($libID, $confirm = 'no', $from = 'lib')
|
||||
{
|
||||
if($libID == 'product' or $libID == 'execution') die();
|
||||
if($confirm == 'no')
|
||||
{
|
||||
die(js::confirm($this->lang->doc->confirmDeleteLib, $this->createLink('doc', 'deleteLib', "libID=$libID&confirm=yes")));
|
||||
$deleteTip = $from == 'book' ? $this->lang->doc->confirmDeleteBook : $this->lang->doc->confirmDeleteLib;
|
||||
die(js::confirm($deleteTip, $this->createLink('doc', 'deleteLib', "libID=$libID&confirm=yes")));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -291,7 +298,8 @@ class doc extends control
|
||||
|
||||
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $docID));
|
||||
$objectID = zget($lib, $lib->type, '');
|
||||
$params = "type={$lib->type}&objectID=$objectID&libID={$lib->id}&docID=" . $docResult['id'];
|
||||
$libType = ($lib->type == 'execution' and $this->app->openApp != 'execution') ? 'project' : $lib->type;
|
||||
$params = "type={$libType}&objectID=$objectID&libID={$lib->id}&docID=" . $docResult['id'];
|
||||
$link = $this->createLink('doc', 'objectLibs', $params);
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $link));
|
||||
}
|
||||
@@ -315,8 +323,9 @@ class doc extends control
|
||||
{
|
||||
$this->app->rawMethod = $objectType;
|
||||
unset($this->lang->doc->menu->product['subMenu']);
|
||||
if($this->config->systemMode == 'new') unset($this->lang->doc->menu->project['subMenu']);
|
||||
unset($this->lang->doc->menu->custom['subMenu']);
|
||||
if($this->config->systemMode == 'new') unset($this->lang->doc->menu->project['subMenu']);
|
||||
if($this->config->systemMode == 'classic') unset($this->lang->doc->menu->execution['subMenu']);
|
||||
}
|
||||
|
||||
$lib = $this->doc->getLibByID($libID);
|
||||
@@ -419,8 +428,9 @@ class doc extends control
|
||||
$this->app->rawMethod = $objectType;
|
||||
|
||||
unset($this->lang->doc->menu->product['subMenu']);
|
||||
if($this->config->systemMode == 'new') unset($this->lang->doc->menu->project['subMenu']);
|
||||
unset($this->lang->doc->menu->custom['subMenu']);
|
||||
if($this->config->systemMode == 'new') unset($this->lang->doc->menu->project['subMenu']);
|
||||
if($this->config->systemMode == 'classic') unset($this->lang->doc->menu->execution['subMenu']);
|
||||
|
||||
/* High light menu. */
|
||||
if(strpos(',product,project,execution,custom,book,', ",$objectType,") !== false)
|
||||
@@ -742,6 +752,63 @@ class doc extends control
|
||||
die($select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show files.
|
||||
*
|
||||
* @param string $type
|
||||
* @param int $objectID
|
||||
* @param string $viewType
|
||||
* @param string $orderBy
|
||||
* @param int $recTotal
|
||||
* @param int $recPerPage
|
||||
* @param int $pageID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function showFiles($type, $objectID, $viewType = '', $orderBy = 't1.id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
if(empty($viewType)) $viewType = !empty($_COOKIE['docFilesViewType']) ? $this->cookie->docFilesViewType : 'card';
|
||||
setcookie('docFilesViewType', $viewType, $this->config->cookieLife, $this->config->webRoot, '', false, true);
|
||||
|
||||
$objects = $this->doc->getOrderedObjects($type);
|
||||
$objectID = $this->{$type}->saveState($objectID, $objects);
|
||||
$libs = $this->doc->getLibsByObject($type, $objectID);
|
||||
$this->lang->modulePageNav = $this->doc->select($type, $objects, $objectID, $libs);
|
||||
|
||||
$openApp = strpos('doc,product,project,execution', $this->app->openApp) !== false ? $this->app->openApp : 'doc';
|
||||
if($openApp != 'doc') $this->loadModel($openApp)->setMenu($objectID);
|
||||
|
||||
$table = $this->config->objectTables[$type];
|
||||
$object = $this->dao->select('id,name,status')->from($table)->where('id')->eq($objectID)->fetch();
|
||||
|
||||
$this->lang->TRActions = $this->doc->buildCollectButton4Doc();
|
||||
$this->lang->TRActions .= $this->doc->buildBrowseSwitch($type, $objectID, $viewType);
|
||||
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
$files = $this->doc->getLibFiles($type, $objectID, $orderBy, $pager);
|
||||
|
||||
$this->view->title = $object->name;
|
||||
$this->view->position[] = $object->name;
|
||||
|
||||
$this->view->type = $type;
|
||||
$this->view->object = $object;
|
||||
$this->view->files = $files;
|
||||
$this->view->users = $this->loadModel('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->view->summary = $this->doc->summary($files);
|
||||
$this->view->sourcePairs = $this->doc->getFileSourcePairs($files);
|
||||
$this->view->fileIcon = $this->doc->getFileIcon($files);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show all libs by type.
|
||||
*
|
||||
@@ -815,95 +882,17 @@ class doc extends control
|
||||
* @param int $libID
|
||||
* @param int $docID
|
||||
* @param int $version
|
||||
* @param int $appendLib
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function objectLibs($type, $objectID = 0, $libID = 0, $docID = 0, $version = 0)
|
||||
public function objectLibs($type, $objectID = 0, $libID = 0, $docID = 0, $version = 0, $appendLib = 0)
|
||||
{
|
||||
if(empty($type))
|
||||
{
|
||||
$doclib = $this->doc->getLibById($libID);
|
||||
$type = $doclib->type == 'execution' ? 'project' : $doclib->type;
|
||||
$objectID = $type == 'custom' or $type == 'book' ? 0 : $doclib->$type;
|
||||
}
|
||||
$lib = $this->doc->getLibById($libID);
|
||||
if(!empty($lib) and $lib->deleted == '1') $appendLib = $libID;
|
||||
|
||||
$this->session->set('docList', $this->app->getURI(true), $this->app->openApp);
|
||||
|
||||
$objects = $this->doc->getOrderedObjects($type);
|
||||
|
||||
if($type == 'custom')
|
||||
{
|
||||
$libs = $this->doc->getLibsByObject('custom', 0);
|
||||
$this->app->rawMethod = 'custom';
|
||||
if($libID == 0) $libID = key($libs);
|
||||
$this->lang->modulePageNav = $this->doc->select($type, $objects, $objectID, $libs, $libID);
|
||||
|
||||
$object = new stdclass();
|
||||
$object->id = 0;
|
||||
}
|
||||
elseif($type == 'book')
|
||||
{
|
||||
$libs = $this->doc->getLibsByObject('book', 0);
|
||||
$this->app->rawMethod = 'book';
|
||||
if($libID == 0 and !empty($libs)) $libID = reset($libs)->id;
|
||||
$this->lang->modulePageNav = $this->doc->select($type, $objects, $objectID, $libs, $libID);
|
||||
|
||||
if(!$docID) $docID = $this->dao->select('id')->from(TABLE_DOC)
|
||||
->where('lib')->eq($libID)
|
||||
->andWhere('type')->eq('article')
|
||||
->andWhere('deleted')->eq(0)
|
||||
->orderBy('editedDate_desc,id_desc')
|
||||
->fetch('id');
|
||||
|
||||
$object = new stdclass();
|
||||
$object->id = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if($type == 'product')
|
||||
{
|
||||
$objectID = $this->product->saveState($objectID, $objects);
|
||||
$table = TABLE_PRODUCT;
|
||||
|
||||
$libs = $this->doc->getLibsByObject('product', $objectID);
|
||||
|
||||
if($libID == 0) $libID = key($libs);
|
||||
$this->lang->modulePageNav = $this->doc->select($type, $objects, $objectID, $libs, $libID);
|
||||
|
||||
$this->app->rawMethod = 'product';
|
||||
}
|
||||
else if($type == 'project')
|
||||
{
|
||||
$objectID = $this->project->saveState($objectID, $objects);
|
||||
$table = TABLE_PROJECT;
|
||||
|
||||
$libs = $this->doc->getLibsByObject('project', $objectID);
|
||||
|
||||
if($libID == 0) $libID = key($libs);
|
||||
$this->lang->modulePageNav = $this->doc->select($type, $objects, $objectID, $libs, $libID);
|
||||
|
||||
$this->app->rawMethod = 'project';
|
||||
}
|
||||
else if($type == 'execution')
|
||||
{
|
||||
$objectID = $this->execution->saveState($objectID, $objects);
|
||||
$table = TABLE_EXECUTION;
|
||||
$libs = $this->doc->getLibsByObject('execution', $objectID);
|
||||
|
||||
if($libID == 0) $libID = key($libs);
|
||||
$this->lang->modulePageNav = $this->doc->select($type, $objects, $objectID, $libs, $libID);
|
||||
|
||||
$this->app->rawMethod = 'execution';
|
||||
}
|
||||
|
||||
$object = $this->dao->select('id,name,status')->from($table)->where('id')->eq($objectID)->fetch();
|
||||
if(empty($object)) $this->locate($this->createLink($type, 'create', '', '', '', $this->session->project));
|
||||
}
|
||||
|
||||
if(!$libID) $libID = key($libs);
|
||||
|
||||
$openApp = strpos('doc,product,project,execution', $this->app->openApp) !== false ? $this->app->openApp : 'doc';
|
||||
if($openApp != 'doc') $this->loadModel($openApp)->setMenu($objectID);
|
||||
if($this->config->systemMode == 'classic' and $type == 'project') $type = 'execution';
|
||||
list($libs, $libID, $object, $objectID) = $this->doc->setMenuByType($type, $objectID, $libID, $appendLib);
|
||||
|
||||
/* Set Custom. */
|
||||
foreach(explode(',', $this->config->doc->customObjectLibs) as $libType) $customObjectLibs[$libType] = $this->lang->doc->customObjectLibs[$libType];
|
||||
@@ -911,8 +900,6 @@ class doc extends control
|
||||
$actionURL = $this->createLink('doc', 'browse', "lib=0&browseType=bySearch&queryID=myQueryID");
|
||||
$this->doc->buildSearchForm(0, array(), 0, $actionURL, 'objectLibs');
|
||||
|
||||
$this->lang->TRActions = common::hasPriv('doc', 'create') ? $this->doc->buildCreateButton4Doc($type, $objectID, $libID) : '';
|
||||
|
||||
$moduleTree = $type == 'book' ? $this->doc->getBookStructure($libID) : $this->doc->getTreeMenu($type, $objectID, $libID, 0, $docID);
|
||||
|
||||
/* Get doc. */
|
||||
@@ -923,7 +910,7 @@ class doc extends control
|
||||
|
||||
if($doc->keywords)
|
||||
{
|
||||
$doc->keywords = preg_replace("/(\n)|(\s)|(\t)|(\')|(')|(,)/", ',', $doc->keywords);
|
||||
$doc->keywords = str_replace(",", ',', $doc->keywords);
|
||||
$doc->keywords = explode(',', $doc->keywords);
|
||||
}
|
||||
|
||||
@@ -934,6 +921,70 @@ class doc extends control
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($doc) and ($doc->type == 'text' || $doc->type == 'article'))
|
||||
{
|
||||
/* Split content into an array. */
|
||||
$content = explode("\n", $doc->content);
|
||||
|
||||
/* Get the head element, for example h1,h2,etc. */
|
||||
$includeHeadElement = array();
|
||||
foreach($content as $index => $element)
|
||||
{
|
||||
preg_match('/<(h[1-6])([\S\s]*?)>([\S\s]*?)<\/\1>/', $element, $headElement);
|
||||
|
||||
if(isset($headElement[1]) and !in_array($headElement[1], $includeHeadElement) and strip_tags($headElement[3]) != '') $includeHeadElement[] = $headElement[1];
|
||||
}
|
||||
|
||||
/* Get the two elements with the highest rank. */
|
||||
sort($includeHeadElement);
|
||||
$includeHeadElement = array_slice($includeHeadElement, 0, 2);
|
||||
|
||||
if($includeHeadElement)
|
||||
{
|
||||
$outline = '<ul class="tree tree-angles" data-ride="tree" id="outline">';
|
||||
$preElement = '';
|
||||
foreach($content as $index => $element)
|
||||
{
|
||||
preg_match('/<(h[1-6])([\S\s]*?)>([\S\s]*?)<\/\1>/', $element, $headElement);
|
||||
|
||||
/* The current element is existed, the element is in the includeHeadElement, and the text in the element is not null. */
|
||||
if(isset($headElement[1]) and in_array($headElement[1], $includeHeadElement) and strip_tags($headElement[3]) != '')
|
||||
{
|
||||
/* The element is the first level. */
|
||||
if(array_search($headElement[1], $includeHeadElement) == 0)
|
||||
{
|
||||
/* The second level is existed, and previous element is the second level element. */
|
||||
if(isset($includeHeadElement[1]) and $preElement == $includeHeadElement[1]) $outline .= '</ul></li>';
|
||||
if($preElement == $includeHeadElement[0]) $outline .= '</li>';
|
||||
|
||||
/* Add the anchor to the element. */
|
||||
$content[$index] = str_replace('<' . $includeHeadElement[0] . $headElement[2] . '>', '<' . $includeHeadElement[0] . $headElement[2] . " id='anchor{$index}'" . '>', $content[$index]);
|
||||
$outline .= '<li class="text-ellipsis">' . html::a('#anchor' . $index, strip_tags($headElement[3]), '', "title='" . strip_tags($headElement[3]) . "'");
|
||||
|
||||
$preElement = $headElement[1];
|
||||
}
|
||||
elseif(array_search($headElement[1], $includeHeadElement) == 1)
|
||||
{
|
||||
if($preElement == '') $outline .= '<li><ul>';
|
||||
if($preElement == $includeHeadElement[0]) $outline .= '<ul>';
|
||||
|
||||
/* Add the anchor to the element. */
|
||||
$content[$index] = str_replace('<' . $includeHeadElement[1] . $headElement[2] . '>', '<' . $includeHeadElement[1] . $headElement[2] . " id='anchor{$index}'" . '>', $content[$index]);
|
||||
$outline .= '<li class="text-ellipsis">' . html::a('#anchor' . $index, strip_tags($headElement[3]), '', "title='" . strip_tags($headElement[3]) . "'") . '</li>';
|
||||
|
||||
$preElement = $includeHeadElement[1];
|
||||
}
|
||||
}
|
||||
if(isset($includeHeadElement[1]) and $preElement == $includeHeadElement[1] and !isset($content[$index+1])) $outline .= '</ul></li>';
|
||||
}
|
||||
$outline .= '</ul>';
|
||||
|
||||
$doc->content = implode("\n", $content);
|
||||
|
||||
$this->view->outline = $outline;
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->customObjectLibs = $customObjectLibs;
|
||||
$this->view->showLibs = $this->config->doc->custom->objectLibs;
|
||||
|
||||
@@ -949,12 +1000,42 @@ class doc extends control
|
||||
$this->view->objectType = $type;
|
||||
$this->view->libID = $libID;
|
||||
$this->view->lib = isset($libs[$libID]) ? $libs[$libID] : new stdclass();
|
||||
|
||||
$this->view->libs = $this->doc->getLibsByObject($type, $objectID);
|
||||
$this->view->moduleTree = $moduleTree;
|
||||
$this->view->canBeChanged = common::canModify($type, $object); // Determines whether an object is editable.
|
||||
$this->view->actions = $docID ? $this->action->getList('doc', $docID) : array();
|
||||
$this->view->users = $this->user->getPairs('noclosed,noletter');
|
||||
$this->view->preAndNext = $this->doc->getPreAndNextDoc($docID, $libID);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the catalog of the doc library.
|
||||
*
|
||||
* @param string $type
|
||||
* @param int $objectID
|
||||
* @param int $libID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function tableContents($type, $objectID = 0, $libID = 0)
|
||||
{
|
||||
list($libs, $libID, $object, $objectID) = $this->doc->setMenuByType($type, $objectID, $libID);
|
||||
|
||||
$libID = empty($libID) ? 0 : $libID;
|
||||
|
||||
$moduleTree = $type == 'book' ? $this->doc->getBookStructure($libID) : $this->doc->getTreeMenu($type, $objectID, $libID);
|
||||
|
||||
$title = ($type == 'book' or $type == 'custom') ? $this->lang->doc->tableContents : $object->name . $this->lang->colon . $this->lang->doc->tableContents;
|
||||
|
||||
$this->view->title = $title;
|
||||
$this->view->type = $type;
|
||||
$this->view->libs = $libs;
|
||||
$this->view->objectID = $objectID;
|
||||
$this->view->libID = $libID;
|
||||
$this->view->moduleTree = $moduleTree;
|
||||
$this->view->users = $this->user->getPairs('noletter');
|
||||
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,4 +80,14 @@ td.c-name a:visited {color: #082999;}
|
||||
|
||||
#pageNav .dropdown-menu {max-height: 350px; overflow-y: auto;}
|
||||
|
||||
#createDropdown ul.dropdown-menu {width: 100%;}
|
||||
ol, ul {margin-bottom: 0}
|
||||
#subHeader #dropMenu .table-col .list-group {padding-top: 5px;}
|
||||
#createDropdown ul.dropdown-menu {text-align: left;}
|
||||
#collection-menu {max-width: 300px;}
|
||||
#collection-menu li a {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
#project, #product, #custom, #book, #execution {min-height: 160px;}
|
||||
#title .menu-title {font-size: 15px; font-weight: 600; position: relative; padding: 2px 0 2px 15px; list-style: none;}
|
||||
#title .dropdown-menu {top: 38px;}
|
||||
.tree li > a {white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
|
||||
.side-col .menu-actions {position: absolute; top: 0; right: 0; padding: 7px 8px;}
|
||||
.menu-actions i {font-size: 15px; color: #8c8c8c;}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
#whiteListBox .input-group:last-child {margin-top: 10px;}
|
||||
#mainContent .main-header h2 {width: 90%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
.addbtn {padding-top: 22px; height: 63px; border: 1px dashed #ddd; width: 60px;}
|
||||
.addbtn .icon-plus {font-size: 18px; display: block; opacity: 0.5; transition: opacity .2s; text-shadow: 1px 1px 3px rgba(0,0,0,.2);}
|
||||
.addbtn:hover .icon-plus {opacity: .9; animation: flash-icon 1s linear alternate infinite;}
|
||||
#dropMenu {min-width: 250px; box-sizing: inhert;}
|
||||
#dropMenu .table-col .list-group {padding-top: 10px;}
|
||||
#subHeader #dropMenu {min-width: 250px; box-sizing: inhert; max-height: inherit;}
|
||||
#subHeader #dropMenu .table-col .list-group {padding-top: 10px;}
|
||||
.main-col .block-files .panel-heading {padding-right: 20px;}
|
||||
.main-col .block-files .panel-heading .panel-title {height: 35px; line-height: 30px;}
|
||||
.side-col .action a {margin: 0 auto 3px; display: block; max-width: 200px;}
|
||||
@@ -13,20 +13,30 @@
|
||||
.main-col .doc-title .info {flex: 1 1 0;}
|
||||
.main-col .doc-title .version a {font-size: 13px; color: #8c8c8c;}
|
||||
.main-col .doc-title .version .dropdown-menu a:hover {color: #ffffff;}
|
||||
.main-col .doc-title .actions a {margin-right: 8px;}
|
||||
.main-col .doc-title .actions a + a {margin-left: 8px;}
|
||||
.main-col .doc-title .actions i {font-size: 15px; color: #8c8c8c;}
|
||||
#content .title {max-width: 54%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
#mainContent .scrollbar-hover {max-height: 2000px; overflow: scroll;}
|
||||
#sidebar {width: 275px;}
|
||||
#sidebar>.cell {width: 100%;}
|
||||
#sidebar>.sidebar-toggle {left: 3px; right: auto;}
|
||||
#project, #product, #custom, #book {min-height: 160px;}
|
||||
#title .menu-title {font-size: 15px; font-weight: 600; position: relative; padding: 2px 0 2px 15px;list-style: none;}
|
||||
#title .dropdown-menu-book {left: -67px; top: 38px;}
|
||||
#title .dropdown-menu-doc {left: -80px; top: 38px;}
|
||||
.hide-sidebar #sidebar>.cell {left: -270px;}
|
||||
.hide-sidebar #sidebar>.cell {display: none;}
|
||||
.hide-sidebar #sidebar>.sidebar-toggle>.icon:before {content: "\e314";}
|
||||
.detail.empty {line-height: 200px;}
|
||||
.main-col+.side-col {padding-left: 16px;}
|
||||
.main-col iframe {min-height: 380px;}
|
||||
.menu-actions {position: absolute; top: 0; right: 0; padding: 7px 8px;}
|
||||
.menu-actions i {font-size: 15px; color: #8c8c8c;}
|
||||
.article-content .keywords {margin-bottom: 15px;}
|
||||
|
||||
.article-content {width: 100%; display: inline-block;}
|
||||
.outline {position: relative;}
|
||||
.outline .outline-toggle i.icon-angle-right, i.icon-angle-left {width: 18px; height: 18px; background: #efefef; border-radius: 50%; position: absolute; padding-left: 2px; padding-top: 1px;}
|
||||
.outline .outline-toggle i.icon-angle-right:before {content: "\e314"; cursor: pointer;}
|
||||
.outline .outline-toggle i.icon-angle-left:before {content: "\e315"; cursor: pointer;}
|
||||
.outline ul li {list-style: none;}
|
||||
.outline-content {display: none; padding-top: 18px;}
|
||||
.outline-content a {color: #838A9D;}
|
||||
.outline-content li.text-ellipsis.active>a {font-weight: 700; color: #0c64eb;}
|
||||
#outline li.has-list.open:before {content: unset;}
|
||||
|
||||
.title {font-size: 20px !important;}
|
||||
.article-content.comment {width: 100% !important;}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
.main-content {padding-top: 0; padding-bottom: 0;}
|
||||
.main-content #createDropdown {display: inline-block;}
|
||||
.main-content #createDropdown ul {position: absolute;}
|
||||
#pageNav .dropdown-menu {max-height: inherit;}
|
||||
|
||||
.no-content {width: 100px; height: 100px; margin: 0 auto;}
|
||||
.notice {text-align: center; padding-left: 15px; padding-top: 20px;}
|
||||
.no-content-button {text-align: center; padding-top: 20px;}
|
||||
.no-content-button a:nth-child(2) {margin-left: 20px;}
|
||||
|
||||
.cell .detail .detail-title {padding-left: 5px; list-style: none;}
|
||||
.menu-actions {position: absolute; top: 7px; right: 45px; padding: 7px 8px;}
|
||||
.catalog>a {color: #838a9d !important;}
|
||||
.detail ul {position: relative;}
|
||||
.tail-info {position: absolute; right: 0; padding-left: 10px; padding-top: 1px;}
|
||||
.tail-info, .doc-title, span.item {background: #fff;}
|
||||
span.item>a {padding-left: 6px;}
|
||||
span.dotted-line+a {display: block;}
|
||||
#modules li.doc:before, .chapterNode:before, .independent:before {content: " "; width: 100%; border-bottom: 1px dashed #b5b9c5; position: absolute; top: 13px; right: 0; left: 30px;}
|
||||
.doc-title {display: inline-block !important; position: relative; padding-right: 10px;}
|
||||
.tree li.has-list.open:before {content: unset;}
|
||||
#modules i.icon-file-text {color: #D0D2D6; font-size: 14px;}
|
||||
.tree li>a {max-width: 80%;}
|
||||
@@ -0,0 +1,7 @@
|
||||
$('.ajaxCollect').click(function()
|
||||
{
|
||||
if(browseType == 'collectedbyme')
|
||||
{
|
||||
window.location.reload();
|
||||
}
|
||||
})
|
||||
+18
-18
@@ -46,7 +46,7 @@ function setBrowseType(type)
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
// hide #module chosen dropdown on #lib dropdown show
|
||||
/* hide #module chosen dropdown on #lib dropdown show */
|
||||
$('#lib').on('chosen:showing_dropdown', function()
|
||||
{
|
||||
$('#module').trigger('chosen:close');
|
||||
@@ -85,8 +85,7 @@ $(document).ready(function()
|
||||
|
||||
var NAME = 'zui.splitRow'; // model name
|
||||
|
||||
// File input list
|
||||
// The SplitRow model class
|
||||
/* The SplitRow model class */
|
||||
var SplitRow = function(element, options)
|
||||
{
|
||||
var that = this;
|
||||
@@ -166,7 +165,8 @@ $(document).ready(function()
|
||||
if (options.middleSize) $col.toggleClass('col-md-size', $col.width() < options.middleSize);
|
||||
};
|
||||
|
||||
var resizeCols = function() {
|
||||
var resizeCols = function()
|
||||
{
|
||||
var cellHeight = $(window).height() - $('#footer').outerHeight() - $('#header').outerHeight() - 42;
|
||||
$cols.children('.panel').height(cellHeight).css('maxHeight', cellHeight).find('.panel-body').css('position', 'absolute');
|
||||
var sideHeight = cellHeight - $cols.find('.nav-tabs').height() - $cols.find('.side-footer').height() - 35;
|
||||
@@ -181,7 +181,7 @@ $(document).ready(function()
|
||||
resizeCols();
|
||||
};
|
||||
|
||||
// default options
|
||||
/* default options */
|
||||
SplitRow.DEFAULTS =
|
||||
{
|
||||
spliter: '<div class="col-spliter"></div>',
|
||||
@@ -189,7 +189,7 @@ $(document).ready(function()
|
||||
middleSize: 850
|
||||
};
|
||||
|
||||
// Extense jquery element
|
||||
/* Extense jquery element */
|
||||
$.fn.splitRow = function(option)
|
||||
{
|
||||
return this.each(function()
|
||||
@@ -205,7 +205,7 @@ $(document).ready(function()
|
||||
|
||||
$.fn.splitRow.Constructor = SplitRow;
|
||||
|
||||
// Auto call splitRow after document load complete
|
||||
/* Auto call splitRow after document load complete */
|
||||
$(function()
|
||||
{
|
||||
$('.split-row').splitRow();
|
||||
@@ -225,17 +225,17 @@ $(document).ready(function()
|
||||
var url = obj.data('url');
|
||||
$.get(url, function(response)
|
||||
{
|
||||
if(response.status == 'yes')
|
||||
{
|
||||
obj.children('i').removeClass().addClass('icon icon-star text-yellow');
|
||||
obj.parent().prev().children('.file-name').children('i').remove('.icon');
|
||||
obj.parent().prev().children('.file-name').prepend('<i class="icon icon-star text-yellow"></i> ');
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.children('i').removeClass().addClass('icon icon-star-empty');
|
||||
obj.parent().prev().children('.file-name').children('i').remove(".icon");
|
||||
}
|
||||
if(response.status == 'yes')
|
||||
{
|
||||
obj.children('i').removeClass().addClass('icon icon-star text-yellow');
|
||||
obj.parent().prev().children('.file-name').children('i').remove('.icon');
|
||||
obj.parent().prev().children('.file-name').prepend('<i class="icon icon-star text-yellow"></i> ');
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.children('i').removeClass().addClass('icon icon-star-empty');
|
||||
obj.parent().prev().children('.file-name').children('i').remove(".icon");
|
||||
}
|
||||
}, 'json');
|
||||
return false;
|
||||
});
|
||||
|
||||
+115
-12
@@ -19,7 +19,7 @@ function ajaxDeleteDoc(link, replaceID, notice)
|
||||
$.get(link, function(data)
|
||||
{
|
||||
location.href = JSON.parse(data).locate;
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,38 +44,141 @@ function deleteFile(fileID)
|
||||
*/
|
||||
function fullScreen()
|
||||
{
|
||||
var element = document.getElementById("content");
|
||||
var element = document.getElementById('content');
|
||||
var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen;
|
||||
if(requestMethod)
|
||||
{
|
||||
$('#content .actions').addClass('hidden');
|
||||
requestMethod.call(element);
|
||||
$.cookie('isFullScreen', 1);
|
||||
var afterEnterFullscreen = function()
|
||||
{
|
||||
$('#mainActions').removeClass('hidden');
|
||||
$('#content').addClass('scrollbar-hover');
|
||||
$('#content .actions').addClass('hidden');
|
||||
$('#content .file-image .right-icon').addClass('hidden');
|
||||
$('#content .detail').eq(1).addClass('hidden');
|
||||
$.cookie('isFullScreen', 1);
|
||||
};
|
||||
var whenFailEnterFullscreen = function(error)
|
||||
{
|
||||
$.cookie('isFullScreen', 0);
|
||||
};
|
||||
try
|
||||
{
|
||||
var result = requestMethod.call(element);
|
||||
if(result && (typeof result.then === 'function' || result instanceof window.Promise))
|
||||
{
|
||||
result.then(afterEnterFullscreen).catch(whenFailEnterFullscreen);
|
||||
}
|
||||
else
|
||||
{
|
||||
afterEnterFullscreen();
|
||||
}
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
whenFailEnterFullscreen(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit full screen.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function exitFullScreen()
|
||||
{
|
||||
$('#mainActions').addClass('hidden');
|
||||
$('#content').removeClass('scrollbar-hover');
|
||||
$('#content .actions').removeClass('hidden');
|
||||
$('#content .file-image .right-icon').removeClass('hidden');
|
||||
$('#content .detail').eq(1).removeClass('hidden');
|
||||
$.cookie('isFullScreen', 0);
|
||||
}
|
||||
|
||||
document.addEventListener("fullscreenchange", function (e)
|
||||
document.addEventListener('fullscreenchange', function (e)
|
||||
{
|
||||
if(!document.fullscreenElement) exitFullScreen();
|
||||
})
|
||||
});
|
||||
|
||||
document.addEventListener("webkitfullscreenchange", function (e)
|
||||
document.addEventListener('webkitfullscreenchange', function (e)
|
||||
{
|
||||
if(!document.webkitFullscreenElement) exitFullScreen();
|
||||
})
|
||||
});
|
||||
|
||||
document.addEventListener("mozfullscreenchange", function (e)
|
||||
document.addEventListener('mozfullscreenchange', function (e)
|
||||
{
|
||||
if(!document.mozFullScreenElement) exitFullScreen();
|
||||
})
|
||||
});
|
||||
|
||||
document.addEventListener("msfullscreenChange", function (e)
|
||||
document.addEventListener('msfullscreenChange', function (e)
|
||||
{
|
||||
if(!document.msfullscreenElement) exitFullScreen();
|
||||
});
|
||||
|
||||
$(function()
|
||||
{
|
||||
$(document).keydown(function(event)
|
||||
{
|
||||
if($.cookie('isFullScreen') == 1)
|
||||
{
|
||||
if(event.keyCode == 37) $('#prevPage').click();
|
||||
if(event.keyCode == 39) $('#nextPage').click();
|
||||
}
|
||||
});
|
||||
|
||||
$('.outline').height($('.article-content').height());
|
||||
|
||||
$('#content').on('click', '.outline .outline-toggle i.icon-angle-right', function()
|
||||
{
|
||||
$('.article-content').width('85%');
|
||||
$('.outline').css({'min-width' : '180px', 'border-left' : '2px solid #efefef'});
|
||||
$(this).removeClass('icon-angle-right').addClass('icon-angle-left').css('left', '-9px');
|
||||
$('.outline-content').show();
|
||||
if($('#sidebar>.cell').is(':visible')) $('#sidebar .icon.icon-angle-right').trigger("click");
|
||||
}).on('click', '.outline .outline-toggle i.icon-angle-left', function()
|
||||
{
|
||||
$('.article-content').width('100%');
|
||||
$(this).removeClass('icon-angle-left').addClass('icon-angle-right');
|
||||
$('.outline-content').hide();
|
||||
}).on('click', '#outline li', function(e)
|
||||
{
|
||||
$('#outline li.active').removeClass('active');
|
||||
$(e.target).closest('li').addClass('active');
|
||||
});
|
||||
|
||||
$('#outline li.has-list').addClass('open in');
|
||||
$('#outline li.has-list>i+ul').prev('i').remove();
|
||||
|
||||
$(document).on('click', '.detail-content a', function(event)
|
||||
{
|
||||
var target = $(this).attr('target');
|
||||
if($.cookie('isFullScreen') == 1 && target != '_blank') exitFullScreen();
|
||||
})
|
||||
|
||||
/* Update doc content silently on switch doc version, story #40503 */
|
||||
$(document).on('click', '.doc-version-menu a, #mainActions .container a', function(event)
|
||||
{
|
||||
var $tmpDiv = $('<div>');
|
||||
$tmpDiv.load($(this).data('url') + ' #mainContent', function()
|
||||
{
|
||||
$('#content').html($tmpDiv.find('#content').html());
|
||||
$('#sidebarContent').html($tmpDiv.find('#sidebarContent').html());
|
||||
$('#actionbox .histories-list').html($tmpDiv.find('#actionbox .histories-list').html());
|
||||
if($.cookie('isFullScreen') == 1) fullScreen();
|
||||
$('#content [data-ride="tree"]').tree();
|
||||
$('#outline li.has-list').addClass('open in');
|
||||
$('#outline li.has-list>i+ul').prev('i').remove();
|
||||
});
|
||||
});
|
||||
|
||||
$('#sidebar .icon.icon-angle-right').click(function()
|
||||
{
|
||||
if($('#sidebar>.cell').is(':hidden') && $('.outline-content').is(':visible'))
|
||||
{
|
||||
$('.outline .outline-toggle i.icon-angle-left').trigger("click");
|
||||
}
|
||||
})
|
||||
|
||||
$('.outline .outline-toggle i.icon-angle-right').trigger("click");
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user