Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* 禅道API的my地盘资源类
|
||||
* 版本V1
|
||||
*
|
||||
* The bug entry point of zentaopms
|
||||
* Version 1
|
||||
*/
|
||||
class myEntry extends entry
|
||||
{
|
||||
public function get()
|
||||
{
|
||||
$info = $this->loadModel('my')->getInfo();
|
||||
$info->products = $this->loadModel('my')->getProducts();
|
||||
$info->projects = $this->loadModel('my')->getProjects();
|
||||
$info->joinProjectCount = count($info->projects);
|
||||
$info->dynamic = $this->loadModel('my')->getDynamic();
|
||||
|
||||
if(!$info) return $this->sendError(400, $info->message);
|
||||
$this->send(200, $info);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ class productEntry extends Entry
|
||||
$control->view($productID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->status) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->status) and $data->status == 'success') return $this->send(200, $this->format($data->data->product, 'createdDate:time'));
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
|
||||
@@ -33,9 +33,8 @@ class productIssueEntry extends entry
|
||||
$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->openedBy = $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];
|
||||
@@ -43,6 +42,16 @@ class productIssueEntry extends entry
|
||||
|
||||
$storySpec = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('story')->eq($id)->andWhere('version')->eq($story->version)->fetch();
|
||||
$issue->desc = $storySpec->spec;
|
||||
|
||||
if($story->assignedTo == "")
|
||||
{
|
||||
$issue->assignedTo = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$issue->assignedTo = array($story->assignedTo);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'bug':
|
||||
$this->app->loadLang('bug');
|
||||
@@ -55,15 +64,25 @@ class productIssueEntry extends entry
|
||||
$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->openedBy = $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;
|
||||
|
||||
if($bug->assignedTo == "")
|
||||
{
|
||||
$issue->assignedTo = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$issue->assignedTo = array($bug->assignedTo);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'task':
|
||||
$this->app->loadLang('task');
|
||||
$taskStatus = array('' => '', 'wait' => 'opened', 'doing' => 'opened', 'done' => 'opened', 'pause' => 'opened', 'cancel' => 'opened', 'closed' => 'closed');
|
||||
@@ -75,22 +94,69 @@ class productIssueEntry extends entry
|
||||
$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->openedBy = $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;
|
||||
|
||||
/* Get assignees for task, the task object has the type of multiple assign only so far. */
|
||||
$users = $this->dao->select('account')->from(TABLE_TEAM)
|
||||
->where('type')->eq('task')
|
||||
->andWhere('root')->eq($task->id)
|
||||
->fetchAll();
|
||||
if($users)
|
||||
{
|
||||
foreach($users as $user)
|
||||
{
|
||||
$issue->assignedTo[] = $user->account;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($task->assignedTo == "")
|
||||
{
|
||||
$issue->assignedTo = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$issue->assignedTo = array($task->assignedTo);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->send404();
|
||||
}
|
||||
|
||||
$actions = $this->loadModel('action')->getList($type, $issueID);
|
||||
|
||||
/**
|
||||
* Get all users in issues so that we can bulk get user detail later.
|
||||
*
|
||||
*/
|
||||
$userList = array();
|
||||
foreach($issue->assignedTo as $user)
|
||||
{
|
||||
$userList[] = $user;
|
||||
}
|
||||
$userList[] = $issue->openedBy;
|
||||
$userList = array_unique($userList);
|
||||
$userDetails = $this->loadModel('user')->getUserDetailsForAPI($userList);
|
||||
|
||||
/**
|
||||
* Set the user detail to assignedTo and openedBy.
|
||||
*
|
||||
*/
|
||||
foreach($issue->assignedTo as $index => $user)
|
||||
{
|
||||
$issue->assignedTo[$index] = $userDetails[$user];
|
||||
}
|
||||
$issue->openedBy = $userDetails[$issue->openedBy];
|
||||
|
||||
$this->send(200, array('issue' => $this->format($issue, 'openedDate:time,lastEditedDate:time')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class productIssuesEntry extends entry
|
||||
->beginIF($storyFilter != 'all')->andWhere('category')->in($storyFilter)->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));
|
||||
foreach($stories as $story) $issues[] = array('id' => $story->id, 'type' => 'story', 'order' => $story->$order, 'status' => $this->getKey($story->status, $storyStatus));
|
||||
}
|
||||
|
||||
if($bugFilter)
|
||||
@@ -136,7 +136,7 @@ class productIssuesEntry extends entry
|
||||
->beginIF($bugFilter != 'all')->andWhere('type')->in($bugFilter)->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));
|
||||
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);
|
||||
@@ -190,13 +190,38 @@ class productIssuesEntry extends entry
|
||||
$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->openedBy = $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");
|
||||
$r->assignedTo = array();
|
||||
|
||||
/* Get assignees for task, the task object has the type of multiple assign only so far. */
|
||||
$users = $this->dao->select('account')->from(TABLE_TEAM)
|
||||
->where('type')->eq('task')
|
||||
->andWhere('root')->eq($task->id)
|
||||
->fetchAll();
|
||||
if($users)
|
||||
{
|
||||
foreach($users as $user)
|
||||
{
|
||||
$r->assignedTo[] = $user->account;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if($task->assignedTo == "")
|
||||
{
|
||||
$r->assignedTo = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$r->assignedTo = array($task->assignedTo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if($issue['type'] == 'story')
|
||||
{
|
||||
@@ -206,13 +231,21 @@ class productIssuesEntry extends entry
|
||||
$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->openedBy = $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");
|
||||
|
||||
if($story->assignedTo == "")
|
||||
{
|
||||
$r->assignedTo = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$r->assignedTo = array($story->assignedTo);
|
||||
}
|
||||
}
|
||||
else if($issue['type'] == 'bug')
|
||||
{
|
||||
@@ -222,18 +255,55 @@ class productIssuesEntry extends entry
|
||||
$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->openedBy = $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");
|
||||
|
||||
if($bug->assignedTo == "")
|
||||
{
|
||||
$r->assignedTo = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$r->assignedTo = array($bug->assignedTo);
|
||||
}
|
||||
}
|
||||
|
||||
$result[] = $this->format($r, 'openedDate:time,lastEditedDate:time');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users in issues so that we can bulk get user detail later.
|
||||
*
|
||||
*/
|
||||
$userList = array();
|
||||
foreach($result as $issue)
|
||||
{
|
||||
foreach($issue->assignedTo as $user)
|
||||
{
|
||||
$userList[] = $user;
|
||||
}
|
||||
$userList[] = $issue->openedBy;
|
||||
}
|
||||
$userList = array_unique($userList);
|
||||
$userDetails = $this->loadModel('user')->getUserDetailsForAPI($userList);
|
||||
|
||||
/**
|
||||
* Set the user detail to assignedTo and openedBy.
|
||||
*
|
||||
*/
|
||||
foreach($result as $issue)
|
||||
{
|
||||
foreach($issue->assignedTo as $index => $user)
|
||||
{
|
||||
$issue->assignedTo[$index] = $userDetails[$user];
|
||||
}
|
||||
$issue->openedBy = $userDetails[$issue->openedBy];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@ class userEntry extends Entry
|
||||
{
|
||||
public function get($userID = 0)
|
||||
{
|
||||
/* Get my info defaultly. */
|
||||
if(!$userID) return $this->getInfo();
|
||||
|
||||
/* Get user by id. */
|
||||
$control = $this->loadController('user', 'profile');
|
||||
$control->profile($userID);
|
||||
|
||||
@@ -20,6 +24,25 @@ class userEntry extends Entry
|
||||
$this->send(200, $this->format($user, 'last:time,locked:time'));
|
||||
}
|
||||
|
||||
private function getInfo()
|
||||
{
|
||||
$info = $this->loadModel('my')->getInfo();
|
||||
|
||||
$products = $this->my->getProducts();
|
||||
$info->product = new stdclass();
|
||||
$info->product->total = count($products);
|
||||
$info->product->products = $products;
|
||||
|
||||
$projects = $this->my->getProjects();
|
||||
$info->project = new stdclass();
|
||||
$info->project->total = count($projects);
|
||||
$info->project->projects = $projects;
|
||||
|
||||
$info->actions = $this->my->getActions();
|
||||
|
||||
$this->send(200, $info);
|
||||
}
|
||||
|
||||
public function put($userID)
|
||||
{
|
||||
$oldUser = $this->loadModel('user')->getByID($userID, 'id');
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ $routes['/tasks/:id/finish'] = 'taskFinish';
|
||||
|
||||
$routes['/users'] = 'users';
|
||||
$routes['/users/:id'] = 'user';
|
||||
$routes['/my'] = 'my';
|
||||
$routes['/user'] = 'user';
|
||||
|
||||
$routes['/programs'] = 'programs';
|
||||
$routes['/programs/:id'] = 'program';
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
ALTER TABLE `zt_testtask` ADD `realFinishedDate` datetime NOT NULL AFTER `end`;
|
||||
ALTER TABLE `zt_doc` ADD `tempContent` longtext NOT NULL AFTER `views`;
|
||||
ALTER TABLE `zt_doc` ADD `draft` longtext NOT NULL AFTER `views`;
|
||||
ALTER TABLE `zt_release` ADD `mailto` text AFTER `desc`;
|
||||
ALTER TABLE `zt_release` ADD `notify` varchar(255) AFTER `mailto`;
|
||||
|
||||
+2
-2
@@ -310,7 +310,7 @@ CREATE TABLE IF NOT EXISTS `zt_doc` (
|
||||
`keywords` varchar(255) NOT NULL,
|
||||
`type` varchar(30) NOT NULL,
|
||||
`views` smallint(5) unsigned NOT NULL,
|
||||
`tempContent` longtext NOT NULL,
|
||||
`draft` longtext NOT NULL,
|
||||
`collector` text NOT NULL,
|
||||
`addedBy` varchar(30) NOT NULL,
|
||||
`addedDate` datetime NOT NULL,
|
||||
@@ -1345,7 +1345,7 @@ INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
|
||||
(10, 'OTHERS', 'others', 'for others.'),
|
||||
(11, 'guest', 'guest', 'For guest'),
|
||||
(12, 'LIMITED', 'limited', 'For limited user'),
|
||||
(13, '项目管理员', 'projectAdmin', '项目管理员可以维护项目的权限');
|
||||
(13, 'Project Admin', 'projectAdmin', 'Project Admins manage project privileges');
|
||||
|
||||
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
|
||||
(1,'action','editComment'),
|
||||
|
||||
@@ -151,30 +151,32 @@ class gitlab
|
||||
}
|
||||
|
||||
/**
|
||||
* Get branch
|
||||
* Get branches.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function branch()
|
||||
{
|
||||
$branches = array();
|
||||
$api = "branches";
|
||||
|
||||
/* Max size of per_page in gitlab API is 100. */
|
||||
$params = array();
|
||||
$params['per_page'] = '100';
|
||||
|
||||
$branches = array();
|
||||
for($page = 1; true; $page ++)
|
||||
{
|
||||
$params['page'] = $page;
|
||||
$list = $this->fetch($api, $params);
|
||||
if(empty($list)) break;
|
||||
$branchList = $this->fetch("branches", $params);
|
||||
if(empty($branchList)) break;
|
||||
|
||||
foreach($list as $branch)
|
||||
foreach($branchList as $branch)
|
||||
{
|
||||
if(!isset($branch->name)) continue;
|
||||
$branches[$branch->name] = $branch->name;
|
||||
}
|
||||
if(count($list) < $params['per_page']) break;
|
||||
|
||||
/* Last page. */
|
||||
if(count($branchList) < $params['per_page']) break;
|
||||
}
|
||||
|
||||
if(empty($branches)) $branches['master'] = 'master';
|
||||
@@ -523,7 +525,6 @@ class gitlab
|
||||
if(!scm::checkRevision($version)) return array();
|
||||
$api = "commits";
|
||||
|
||||
/* TODO Put getCommits into cron job. And check best size of $count. */
|
||||
if(empty($count)) $count = 10;
|
||||
|
||||
$params = array();
|
||||
|
||||
@@ -23,8 +23,7 @@ $lang->action->action = 'Action';
|
||||
$lang->action->actionID = 'Action ID';
|
||||
$lang->action->date = 'Date';
|
||||
$lang->action->extra = 'Extra';
|
||||
|
||||
$lang->action->system = 'System';
|
||||
$lang->action->system = 'System';
|
||||
|
||||
$lang->action->trash = 'Recycle';
|
||||
$lang->action->undelete = 'Restore';
|
||||
|
||||
@@ -23,8 +23,7 @@ $lang->action->action = '动作';
|
||||
$lang->action->actionID = '记录ID';
|
||||
$lang->action->date = '日期';
|
||||
$lang->action->extra = '附加值';
|
||||
|
||||
$lang->action->system = '系统';
|
||||
$lang->action->system = '系统';
|
||||
|
||||
$lang->action->trash = '回收站';
|
||||
$lang->action->undelete = '还原';
|
||||
|
||||
@@ -23,8 +23,7 @@ $lang->action->action = '動作';
|
||||
$lang->action->actionID = '記錄ID';
|
||||
$lang->action->date = '日期';
|
||||
$lang->action->extra = '附加值';
|
||||
|
||||
$lang->action->system = '系統';
|
||||
$lang->action->system = '系統';
|
||||
|
||||
$lang->action->trash = '資源回收筒';
|
||||
$lang->action->undelete = '還原';
|
||||
|
||||
@@ -1006,7 +1006,8 @@ class actionModel extends model
|
||||
if($object->type == 'project') $objectProject[$object->id] = $object->id;
|
||||
}
|
||||
}
|
||||
elseif($objectType == 'stakeholder'){
|
||||
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)
|
||||
@@ -1055,7 +1056,8 @@ 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 : (isset($this->lang->$objectType->$actionType) ? $this->lang->$objectType->$actionType : $action->action);
|
||||
$action->actionLabel = isset($this->lang->$objectType->$actionType) ? $this->lang->$objectType->$actionType : $action->action;
|
||||
$action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : $action->actionLabel;
|
||||
$action->objectLabel = $objectType;
|
||||
if(isset($this->lang->action->label->$objectType))
|
||||
{
|
||||
@@ -1108,25 +1110,24 @@ class actionModel extends model
|
||||
$method = $this->config->action->assetViewMethod[$action->objectType];
|
||||
}
|
||||
|
||||
$action->objectLink = helper::createLink('assetlib', $method, sprintf($vars, $action->objectID), '', '', $projectID);
|
||||
$action->objectLink = helper::createLink('assetlib', $method, sprintf($vars, $action->objectID));
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
$docLib->objectID = strpos('product,project,execution', $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));
|
||||
}
|
||||
elseif($action->objectType == 'user')
|
||||
{
|
||||
$action->objectLink = !isset($deptUsers[$action->objectID]) ? 'javascript:void(0)' : helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID);
|
||||
$action->objectLink = !isset($deptUsers[$action->objectID]) ? 'javascript:void(0)' : helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID));
|
||||
}
|
||||
else
|
||||
{
|
||||
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID);
|
||||
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID));
|
||||
}
|
||||
}
|
||||
$action->objectLabel = $objectLabel;
|
||||
|
||||
@@ -285,7 +285,7 @@ class bugModel extends model
|
||||
public function createBugFromGitlabIssue($bug, $executionID)
|
||||
{
|
||||
$bug->openedBy = $this->app->user->account;
|
||||
$bug->openedDate = helper::now(); // TODO(dingguodong) use from issue->created_at ?
|
||||
$bug->openedDate = helper::now();
|
||||
$bug->assignedDate = isset($bug->assignedTo) ? helper::now() : 0;
|
||||
$bug->openedBuild = 'trunk';
|
||||
$bug->story = 0;
|
||||
@@ -1817,7 +1817,7 @@ class bugModel extends model
|
||||
$bugSteps .= $this->lang->bug->tplResult;
|
||||
$bugSteps .= $this->lang->bug->tplExpect;
|
||||
}
|
||||
|
||||
|
||||
if(!empty($run->task)) $testtask = $this->loadModel('testtask')->getById($run->task);
|
||||
$executionID = isset($testtask->execution) ? $testtask->execution : 0;
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ $lang->help = 'Help';
|
||||
$lang->aboutZenTao = 'About';
|
||||
$lang->profile = 'Profile';
|
||||
$lang->changePassword = 'Password';
|
||||
$lang->unfoldMenu = 'Unfold Menu';
|
||||
$lang->collapseMenu = 'Collapse Menu';
|
||||
$lang->unfoldMenu = 'Unfold';
|
||||
$lang->collapseMenu = 'Collapse';
|
||||
$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>";
|
||||
@@ -86,8 +86,8 @@ $lang->importSuccess = 'Saved';
|
||||
$lang->fail = 'Fail';
|
||||
$lang->addFiles = 'Added Files';
|
||||
$lang->files = 'Files ';
|
||||
$lang->pasteText = 'Multi-lines Paste';
|
||||
$lang->uploadImages = 'Multi-images Upload';
|
||||
$lang->pasteText = 'Multi-line Paste';
|
||||
$lang->uploadImages = 'Multi-image Upload';
|
||||
$lang->timeout = 'Timeout. Check your newtwork connections, or try it again!';
|
||||
$lang->repairTable = 'Database table might be damaged. Run phpmyadmin or myisamchk to fix it.';
|
||||
$lang->duplicate = '%s has the same title as a file existed.';
|
||||
@@ -144,7 +144,7 @@ $lang->admin->common = 'Admin';
|
||||
$lang->task->common = 'Task';
|
||||
$lang->bug->common = 'Bug';
|
||||
$lang->testcase->common = 'Testcase';
|
||||
$lang->testtask->common = 'Testtask';
|
||||
$lang->testtask->common = 'Request';
|
||||
$lang->score->common = 'Score';
|
||||
$lang->build->common = 'Build';
|
||||
$lang->testreport->common = 'Report';
|
||||
@@ -185,7 +185,7 @@ $lang->track = 'Track';
|
||||
$lang->settings = 'Settings';
|
||||
$lang->overview = 'Overview';
|
||||
$lang->module = 'Module';
|
||||
$lang->priv = 'Priv Group';
|
||||
$lang->priv = 'Privilege';
|
||||
$lang->design = 'Design';
|
||||
$lang->other = 'Other';
|
||||
$lang->estimation = 'Estimation';
|
||||
|
||||
@@ -5,8 +5,7 @@ $.initSidebar();
|
||||
<?php if($extView = $this->getExtViewFile(__FILE__)){include $extView; return helper::cd();}?>
|
||||
|
||||
<iframe frameborder='0' name='hiddenwin' id='hiddenwin' scrolling='no' class='debugwin hidden'></iframe>
|
||||
|
||||
<?php if($onlybody != 'yes'):?>
|
||||
<?php if($onlybody != 'yes' and $app->viewType != 'xhtml'):?>
|
||||
</main><?php /* end '#wrap' in 'header.html.php'. */ ?>
|
||||
<div id="noticeBox"><?php echo $this->loadModel('score')->getNotice(); ?></div>
|
||||
<script>
|
||||
|
||||
@@ -28,8 +28,6 @@ $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';
|
||||
|
||||
@@ -739,15 +739,15 @@ class doc extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax save temporary content of doc.
|
||||
* Ajax save draft.
|
||||
*
|
||||
* @param int $docID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxSaveContent($docID)
|
||||
public function ajaxSaveDraft($docID)
|
||||
{
|
||||
$this->doc->saveTempContent($docID);
|
||||
$this->doc->saveDraft($docID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1020,7 +1020,7 @@ class doc extends control
|
||||
{
|
||||
list($libs, $libID, $object, $objectID) = $this->doc->setMenuByType($type, $objectID, $libID);
|
||||
|
||||
$libID = empty($libID) ? 0 : $libID;
|
||||
$libID = (int)$libID;
|
||||
|
||||
$moduleTree = $type == 'book' ? $this->doc->getBookStructure($libID) : $this->doc->getTreeMenu($type, $objectID, $libID);
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
$(function()
|
||||
{
|
||||
if(needUpdateContent)
|
||||
if(needUpdateContent && confirm(confirmUpdateContent))
|
||||
{
|
||||
if(confirm(confirmUpdateContent))
|
||||
{
|
||||
$('#content').html(tempContent);
|
||||
editor = KindEditor.instances[0];
|
||||
editor.html(tempContent);
|
||||
}
|
||||
$('#content').html(draft);
|
||||
editor = KindEditor.instances[0];
|
||||
editor.html(draft);
|
||||
}
|
||||
|
||||
$('#top-submit').click(function()
|
||||
@@ -91,6 +88,6 @@ $(function()
|
||||
function saveTempContent()
|
||||
{
|
||||
var content = $('#content').val();
|
||||
var link = createLink('doc', 'ajaxSaveContent', 'docID=' + docID);
|
||||
var link = createLink('doc', 'ajaxSaveDraft', 'docID=' + docID);
|
||||
$.post(link, {content: content});
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ $lang->doc->libName = 'Document Library';
|
||||
$lang->doc->libType = 'Category';
|
||||
$lang->doc->custom = 'Custom Document Library';
|
||||
$lang->doc->customAB = 'Custom Doc Lib';
|
||||
$lang->doc->createLib = 'Create Document Library';
|
||||
$lang->doc->createLib = 'Document Library';
|
||||
$lang->doc->allLibs = 'Library List';
|
||||
$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Libraries";
|
||||
$lang->doc->showFiles = 'Attachments';
|
||||
@@ -108,7 +108,7 @@ $lang->doc->fixedMenu = 'Fix to Menu';
|
||||
$lang->doc->removeMenu = 'Remove from Menu';
|
||||
$lang->doc->search = 'Search';
|
||||
$lang->doc->allCollections = 'All Collections';
|
||||
$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.';
|
||||
$lang->doc->keywordsTips = 'Please use commas to separate keywords.';
|
||||
|
||||
global $config;
|
||||
/* Query condition list. */
|
||||
|
||||
+46
-28
@@ -255,21 +255,8 @@ class docModel extends model
|
||||
->fetchAll('id');
|
||||
}
|
||||
|
||||
$projects = $this->dao->select('t1.id, t1.name')->from(TABLE_PROJECT)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.id=t2.project')
|
||||
->where('t2.id')->in(array_keys($docs))
|
||||
->andWhere('t2.execution')->eq(0)
|
||||
->fetchPairs();
|
||||
|
||||
$executions = $this->dao->select('t1.id, t1.name')->from(TABLE_EXECUTION)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.id=t2.execution')
|
||||
->where('t2.id')->in(array_keys($docs))
|
||||
->fetchPairs();
|
||||
|
||||
$products = $this->dao->select('t1.id, t1.name')->from(TABLE_PRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.id=t2.product')
|
||||
->where('t2.id')->in(array_keys($docs))
|
||||
->fetchPairs();
|
||||
/* Get projects, executions and products by docIdList. */
|
||||
list($projects, $executions, $products) = $this->getObjectsByDoc(array_keys($docs));
|
||||
|
||||
$docContents = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->in(array_keys($docs))->orderBy('version,doc')->fetchAll('doc');
|
||||
|
||||
@@ -322,6 +309,36 @@ class docModel extends model
|
||||
return $docs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get projects, executions and products by docIdList.
|
||||
*
|
||||
* @param array $docIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getObjectsByDoc($docIdList = array())
|
||||
{
|
||||
if(empty($docIdList)) return array();
|
||||
|
||||
$projects = $this->dao->select('t1.id, t1.name')->from(TABLE_PROJECT)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.id=t2.project')
|
||||
->where('t2.id')->in($docIdList)
|
||||
->andWhere('t2.execution')->eq(0)
|
||||
->fetchPairs();
|
||||
|
||||
$executions = $this->dao->select('t1.id, t1.name')->from(TABLE_EXECUTION)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.id=t2.execution')
|
||||
->where('t2.id')->in($docIdList)
|
||||
->fetchPairs();
|
||||
|
||||
$products = $this->dao->select('t1.id, t1.name')->from(TABLE_PRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on('t1.id=t2.product')
|
||||
->where('t2.id')->in($docIdList)
|
||||
->fetchPairs();
|
||||
|
||||
return array($projects, $executions, $products);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get docs.
|
||||
*
|
||||
@@ -421,7 +438,7 @@ class docModel extends model
|
||||
$doc->content = isset($docContent->content) ? $docContent->content : '';
|
||||
$doc->contentType = isset($docContent->type) ? $docContent->type : '';
|
||||
|
||||
if($doc->type != 'url' and $doc->contentType != 'markdown') $doc = $this->loadModel('file')->replaceImgURL($doc, 'content,tempContent');
|
||||
if($doc->type != 'url' and $doc->contentType != 'markdown') $doc = $this->loadModel('file')->replaceImgURL($doc, 'content,draft');
|
||||
if($setImgSize) $doc->content = $this->file->setImgSize($doc->content);
|
||||
$doc->files = $docFiles;
|
||||
|
||||
@@ -515,7 +532,7 @@ class docModel extends model
|
||||
if(empty($docContent->content)) return dao::$errors['content'] = sprintf($this->lang->error->notempty, $this->lang->doc->content);
|
||||
}
|
||||
|
||||
$doc->tempContent = $docContent->content;
|
||||
$doc->draft = $docContent->content;
|
||||
$this->dao->insert(TABLE_DOC)->data($doc, 'content')->autoCheck()
|
||||
->batchCheck($requiredFields, 'notempty')
|
||||
->exec();
|
||||
@@ -623,7 +640,7 @@ class docModel extends model
|
||||
}
|
||||
unset($doc->contentType);
|
||||
|
||||
$doc->tempContent = $doc->content;
|
||||
$doc->draft = $doc->content;
|
||||
$this->dao->update(TABLE_DOC)->data($doc, 'content')
|
||||
->autoCheck()
|
||||
->batchCheck($requiredFields, 'notempty')
|
||||
@@ -631,29 +648,29 @@ class docModel extends model
|
||||
->exec();
|
||||
if(!dao::isError())
|
||||
{
|
||||
unset($doc->tempContent);
|
||||
unset($doc->draft);
|
||||
$this->file->updateObjectID($this->post->uid, $docID, 'doc');
|
||||
return array('changes' => $changes, 'files' => $files);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save temporary doc content.
|
||||
* Save draft.
|
||||
*
|
||||
* @param int $docID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function saveTempContent($docID)
|
||||
public function saveDraft($docID)
|
||||
{
|
||||
$data = fixer::input('post')
|
||||
->stripTags($this->config->doc->editor->edit['id'], $this->config->allowedTags)
|
||||
->get();
|
||||
$doc = new stdclass();
|
||||
$doc->tempContent = $data->content;
|
||||
$doc->draft = $data->content;
|
||||
|
||||
$docType = $this->dao->select('type')->from(TABLE_DOCCONTENT)->where('doc')->eq((int)$docID)->orderBy('version_desc')->fetch();
|
||||
if($docType == 'markdown') $doc->tempContent = $this->post->content;
|
||||
if($docType == 'markdown') $doc->draft = $this->post->content;
|
||||
|
||||
$this->dao->update(TABLE_DOC)->data($doc)->where('id')->eq($docID)->exec();
|
||||
}
|
||||
@@ -1238,7 +1255,7 @@ class docModel extends model
|
||||
$orderedExecutions = array();
|
||||
foreach($executions as $id => $execution)
|
||||
{
|
||||
$execution->name = zget($projectPairs, $execution->project) . '/' . $execution->name;
|
||||
$execution->name = zget($projectPairs, $execution->project) . ' / ' . $execution->name;
|
||||
|
||||
if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM == $this->app->user->account)
|
||||
{
|
||||
@@ -1829,15 +1846,16 @@ class docModel extends model
|
||||
*/
|
||||
public function buildCollectButton4Doc()
|
||||
{
|
||||
$allLibs = array_keys($this->getLibs('all'));
|
||||
$docs = $this->dao->select('t1.id,t1.title,t1.lib,t2.type,t2.product,t2.project,t2.execution')->from(TABLE_DOC)->alias('t1')
|
||||
$favoritesLimit = 10;
|
||||
$allLibs = array_keys($this->getLibs('all'));
|
||||
$docs = $this->dao->select('t1.id,t1.title,t1.lib,t2.type,t2.product,t2.project,t2.execution')->from(TABLE_DOC)->alias('t1')
|
||||
->leftJoin(TABLE_DOCLIB)->alias('t2')->on('t1.lib=t2.id')
|
||||
->where('t1.deleted')->eq(0)
|
||||
->andWhere('t1.lib')->in($allLibs)
|
||||
->beginIF($this->config->doc->notArticleType)->andWhere('t1.type')->notIN($this->config->doc->notArticleType)->fi()
|
||||
->andWhere('t1.collector')->like("%,{$this->app->user->account},%")
|
||||
->orderBy('t1.id_desc')
|
||||
->limit($this->config->doc->collectionLimit)
|
||||
->limit($favoritesLimit)
|
||||
->fetchAll();
|
||||
|
||||
$html = "<div class='btn-group dropdown-hover'>";
|
||||
@@ -1865,7 +1883,7 @@ class docModel extends model
|
||||
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
|
||||
->andWhere('collector')->like("%,{$this->app->user->account},%")
|
||||
->fetch('count');
|
||||
if($collectionCount > $this->config->doc->collectionLimit) $html .= '<li>' . html::a(inlink('browse', "type=collectedByMe"), $this->lang->doc->allCollections) . '</li>';
|
||||
if($collectionCount > $favoritesLimit) $html .= '<li>' . html::a(inlink('browse', "type=collectedByMe"), $this->lang->doc->allCollections) . '</li>';
|
||||
|
||||
$html .= '</ul></div>';
|
||||
return $html;
|
||||
|
||||
@@ -49,14 +49,15 @@
|
||||
<?php $star = strpos($doc->collector, ',' . $this->app->user->account . ',') !== false ? 'icon-star text-yellow' : 'icon-star-empty';?>
|
||||
<?php $collectTitle = strpos($doc->collector, ',' . $this->app->user->account . ',') !== false ? $lang->doc->cancelCollection : $lang->doc->collect;?>
|
||||
<tr>
|
||||
<td class="c-name"><?php echo html::a($this->createLink('doc', 'view', "docID=$doc->id&version=0", '', true), "<i class='icon icon-file-text text-muted'></i> " . $doc->title, '', "title={$doc->title} class='iframe' data-width='90%'");?></td>
|
||||
<td class="c-name"><?php echo html::a($this->createLink('doc', 'view', "docID=$doc->id&version=0", '', true), "<i class='icon icon-file-text text-muted'></i> " . $doc->title, '', "title='{$doc->title}' class='iframe' data-width='90%'");?></td>
|
||||
<td class='c-name'>
|
||||
<?php if(!empty($doc->objectType)):?>
|
||||
<?php echo $lang->{$doc->objectType}->common . ' : ';?>
|
||||
<a title='<?php echo $doc->objectName;?>' href='<?php echo $this->createLink($doc->objectType, 'view', "objectID=$doc->objectID");?>' data-app="<?php echo $doc->objectType;?>">
|
||||
<?php echo $doc->objectName;?>
|
||||
</a>
|
||||
<?php endif;?>
|
||||
<?php
|
||||
if(!empty($doc->objectType))
|
||||
{
|
||||
echo $lang->{$doc->objectType}->common . ' : ';
|
||||
echo html::a($this->createLink($doc->objectType, 'view', "objectID={$doc->objectID}"), $doc->objectName, '', "data-app='{$doc->objectType}' title='{$doc->objectName}'");
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="c-num"><?php echo $doc->fileSize ? $doc->fileSize : '-';?></td>
|
||||
<td class="c-user"><?php echo zget($users, $doc->addedBy);?></td>
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php if($doc->contentType == 'html') include '../../common/view/kindeditor.html.php';?>
|
||||
<?php if($doc->contentType == 'markdown') include '../../common/view/markdown.html.php';?>
|
||||
<?php js::set('needUpdateContent', $doc->content != $doc->tempContent);?>
|
||||
<?php js::set('needUpdateContent', $doc->content != $doc->draft);?>
|
||||
<?php js::set('confirmUpdateContent', $lang->doc->confirmUpdateContent);?>
|
||||
<?php js::set('docID', $doc->id);?>
|
||||
<?php js::set('tempContent', $doc->tempContent);?>
|
||||
<?php js::set('draft', $doc->draft);?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
|
||||
@@ -175,60 +175,4 @@ class entryModel extends model
|
||||
$this->dao->insert(TABLE_LOG)->data($log)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the detail of the user.
|
||||
*
|
||||
* @param string $account
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getUser($account)
|
||||
{
|
||||
$this->loadModel('user');
|
||||
$user = $this->user->getById($account, $feild = 'account');
|
||||
|
||||
$detail = new stdclass;
|
||||
$detail->id = $user->id;
|
||||
$detail->account = $user->account;
|
||||
$detail->realname = $user->realname;
|
||||
$detail->url = helper::createLink('user', 'profile', "userID={$user->id}");
|
||||
|
||||
if($user->avatar != "")
|
||||
$detail->avatar = common::getSysURL() . $user->avatar;
|
||||
else
|
||||
$detail->avatar = "https://www.gravatar.com/avatar/" . md5($user->account) . "?d=identicon&s=80";
|
||||
|
||||
return $detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details of assigned users.
|
||||
*
|
||||
* @param string $objectType
|
||||
* @param object $object
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getAssignees($objectType, $object)
|
||||
{
|
||||
$users = $this->dao
|
||||
->select('account')->from(TABLE_TEAM)
|
||||
->where('type')->eq($objectType)
|
||||
->andWhere('root')->eq($object->id)
|
||||
->fetchAll();
|
||||
|
||||
if($users)
|
||||
{
|
||||
$details = array();
|
||||
foreach($users as $user)
|
||||
{
|
||||
$details[] = $this->getUser($user->account);
|
||||
}
|
||||
return $details;
|
||||
}
|
||||
|
||||
return ($object->assignedTo == "" or $object->assignedTo == "closed") ? array() : array($this->getUser($object->assignedTo));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1903,20 +1903,11 @@ class execution extends control
|
||||
|
||||
$statusCount[$status] += isset($kanbanGroup[$projectID][$status]) ? count($kanbanGroup[$projectID][$status]) : 0;
|
||||
|
||||
/* Up to five closed executions are displayed. */
|
||||
/* Max 5 closed executions. */
|
||||
if($status == 'closed')
|
||||
{
|
||||
if(isset($myExecutions[$status]) and count($myExecutions[$status]) >= 5)
|
||||
{
|
||||
$myExecutions[$status] = array_slice($myExecutions[$status], 0, 5, true);
|
||||
$myExecutions[$status]['more'] = $this->lang->execution->showMore;
|
||||
}
|
||||
|
||||
if(isset($kanbanGroup[$projectID][$status]) and count($kanbanGroup[$projectID][$status]) >= 5)
|
||||
{
|
||||
$kanbanGroup[$projectID][$status] = array_slice($kanbanGroup[$projectID][$status], 0, 5, true);
|
||||
$kanbanGroup[$projectID][$status]['more'] = $this->lang->execution->showMore;
|
||||
}
|
||||
if(isset($myExecutions[$status]) and count($myExecutions[$status]) >= 5) $myExecutions[$status] = array_slice($myExecutions[$status], 0, 5, true);
|
||||
if(isset($kanbanGroup[$projectID][$status]) and count($kanbanGroup[$projectID][$status]) >= 5) $kanbanGroup[$projectID][$status] = array_slice($kanbanGroup[$projectID][$status], 0, 5, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2287,7 +2278,7 @@ class execution extends control
|
||||
|
||||
$currentMembers = $this->execution->getTeamMembers($executionID);
|
||||
$members2Import = $this->execution->getMembers2Import($team2Import, array_keys($currentMembers));
|
||||
$teams2Import = $this->loadModel('personnel')->getCopyObjects($executionID, 'sprint');
|
||||
$teams2Import = $this->loadModel('personnel')->getCopiedObjects($executionID, 'sprint');
|
||||
$teams2Import = array('' => '') + $teams2Import;
|
||||
|
||||
/* Append users for get users. */
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
.board-title {padding-right: 20px;}
|
||||
.board-actions {position: absolute; right: 3px; top: 3px;}
|
||||
.board-actions.nav > li > a {padding: 3px 3px;}
|
||||
#kanban {overflow-y: auto; min-height:350px;}
|
||||
|
||||
#kanban {overflow-y: auto; min-height: 350px;}
|
||||
#kanban > .table {min-width: 1100px; table-layout: auto;}
|
||||
#kanban.dragging .boards.dragging .board {background: #eee; opacity: .35; border-color: #f1f1f1;}
|
||||
#kanban thead > tr > th {padding-left: 0; padding-right: 0;}
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
#importTeams .input-group +.input-group {margin-left: 5px;}
|
||||
|
||||
#dept_chosen .chosen-single {width: 220px;}
|
||||
#execution_chosen .chosen-single {width: 220px;}
|
||||
#execution_chosen .chosen-single {width: 230px;}
|
||||
#execution_chosen .chosen-drop ul li .label {margin-top: 2px; background: #fff; color: #838a9d; border: 1px solid #d8d8d8;}
|
||||
.radio-inline {line-height: normal;}
|
||||
|
||||
#teamForm .table tr > td:first-child {padding-left: 10px;}
|
||||
|
||||
@@ -33,9 +33,9 @@ $(function()
|
||||
/* Assign value to the manage products by the different request type.*/
|
||||
var product = $('#products0');
|
||||
if(copyExecutionID) productID = product.val();
|
||||
$(product).val(productID);
|
||||
$(product).trigger("chosen:updated");
|
||||
loadBranches($(product));
|
||||
product.val(productID);
|
||||
product.trigger("chosen:updated");
|
||||
loadBranches(product);
|
||||
|
||||
var adjustMainCol = function()
|
||||
{
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
$(function()
|
||||
{
|
||||
$('#execution_chosen').click(function()
|
||||
{
|
||||
if(systemMode == 'new') $('#execution_chosen ul li:first').append(' <label class="label">' + projectCommon + '</label>')
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Set role when select an account.
|
||||
*
|
||||
|
||||
@@ -100,7 +100,6 @@ $lang->execution->copyNoExecution = 'There are no ' . $lang->executionCommon . '
|
||||
$lang->execution->noTeam = 'No team members at the moment';
|
||||
$lang->execution->or = ' or ';
|
||||
$lang->execution->selectProject = 'Please select project';
|
||||
$lang->execution->showMore = 'View closed executions';
|
||||
|
||||
if($this->config->systemMode == 'new') $lang->execution->copyTeamTip = "select Project/{$lang->execution->common} to copy its members";
|
||||
if($this->config->systemMode == 'classic') $lang->execution->copyTeamTip = "select Project/{$lang->executionCommon} to copy its members";
|
||||
|
||||
@@ -101,7 +101,6 @@ $lang->execution->copyNoExecution = 'There are no ' . $lang->executionCommon . '
|
||||
$lang->execution->noTeam = 'No team members at the moment';
|
||||
$lang->execution->or = ' or ';
|
||||
$lang->execution->selectProject = 'Please select project';
|
||||
$lang->execution->showMore = 'View closed executions';
|
||||
|
||||
if($this->config->systemMode == 'new') $lang->execution->copyTeamTip = "select Project/{$lang->execution->common} to copy its members";
|
||||
if($this->config->systemMode == 'classic') $lang->execution->copyTeamTip = "select Project/{$lang->executionCommon} to copy its members";
|
||||
|
||||
@@ -100,7 +100,6 @@ $lang->execution->copyNoExecution = 'There are no ' . $lang->executionCommon . '
|
||||
$lang->execution->noTeam = 'No team members at the moment';
|
||||
$lang->execution->or = ' or ';
|
||||
$lang->execution->selectProject = 'Please select project';
|
||||
$lang->execution->showMore = 'View closed executions';
|
||||
|
||||
if($this->config->systemMode == 'new') $lang->execution->copyTeamTip = "select Project/{$lang->execution->common} to copy its members";
|
||||
if($this->config->systemMode == 'classic') $lang->execution->copyTeamTip = "select Project/{$lang->executionCommon} to copy its members";
|
||||
|
||||
@@ -101,7 +101,6 @@ $lang->execution->copyNoExecution = 'There are no ' . $lang->executionCommon . '
|
||||
$lang->execution->noTeam = 'No team members at the moment';
|
||||
$lang->execution->or = ' or ';
|
||||
$lang->execution->selectProject = 'Please select project';
|
||||
$lang->execution->showMore = 'View closed executions';
|
||||
|
||||
if($this->config->systemMode == 'new') $lang->execution->copyTeamTip = "select Project/{$lang->execution->common} to copy its members";
|
||||
if($this->config->systemMode == 'classic') $lang->execution->copyTeamTip = "select Project/{$lang->executionCommon} to copy its members";
|
||||
|
||||
@@ -101,7 +101,6 @@ $lang->execution->copyNoExecution = '没有可用的' . $lang->executionCommon .
|
||||
$lang->execution->noTeam = '暂时没有团队成员';
|
||||
$lang->execution->or = '或';
|
||||
$lang->execution->selectProject = '请选择项目';
|
||||
$lang->execution->showMore = '点击查看所有已关闭的执行';
|
||||
|
||||
if($this->config->systemMode == 'new') $lang->execution->copyTeamTip = "可以选择复制项目或{$lang->execution->common}团队的成员";
|
||||
if($this->config->systemMode == 'classic') $lang->execution->copyTeamTip = "可以选择复制{$lang->executionCommon}团队的成员";
|
||||
|
||||
@@ -100,7 +100,6 @@ $lang->execution->recent = '近期訪問:';
|
||||
$lang->execution->copyNoExecution = '沒有可用的' . $lang->executionCommon . '來複制';
|
||||
$lang->execution->noTeam = '暫時沒有團隊成員';
|
||||
$lang->execution->selectProject = '請選擇項目';
|
||||
$lang->execution->showMore = '點擊查看所有已關閉的執行';
|
||||
|
||||
$lang->execution->start = "開始";
|
||||
$lang->execution->activate = "激活";
|
||||
|
||||
@@ -506,7 +506,7 @@ class executionModel extends model
|
||||
->checkIF($execution->begin != '', 'begin', 'date')
|
||||
->checkIF($execution->end != '', 'end', 'date')
|
||||
->checkIF($execution->end != '', 'end', 'gt', $execution->begin)
|
||||
->check('code', 'unique', "id!=$executionID and code!='' and deleted='0'")
|
||||
->check('code', 'unique', "id != $executionID and code != '' and deleted = '0'")
|
||||
->where('id')->eq($executionID)
|
||||
->limit(1)
|
||||
->exec();
|
||||
@@ -1299,15 +1299,15 @@ class executionModel extends model
|
||||
{
|
||||
$link = helper::createLink('repo', 'browse', "repoID=0&branchID=&executionID=%s");
|
||||
}
|
||||
elseif($module == 'doc')
|
||||
{
|
||||
$link = helper::createLink('doc', $method, "type=execution&objectID=%s&from=execution");
|
||||
}
|
||||
else
|
||||
{
|
||||
$link = helper::createLink($module, $method, "executionID=%s");
|
||||
}
|
||||
|
||||
if($module == 'doc')
|
||||
{
|
||||
$link = helper::createLink('doc', $method, "type=execution&objectID=%s&from=execution");
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#tabContent {margin-top: 10px; z-index: 900;}
|
||||
#tabContent ul {list-style: none; margin: 0}
|
||||
#tabContent .tab-pane>ul {padding-left: 7px;}
|
||||
#tabContent .tab-pane>ul>li.hide-in-search>div {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
#tabContent .tab-pane>ul>li>div {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
#tabContent .tab-pane>ul>li label {background: rgba(255,255,255,0.5); line-height: unset; color: #838a9d; border: 1px solid #d8d8d8; border-radius: 2px; padding: 1px 4px;}
|
||||
#tabContent li a i.icon {font-size: 15px !important;}
|
||||
#tabContent li a i.icon:before {min-width: 16px !important;}
|
||||
@@ -23,8 +23,12 @@
|
||||
#tabContent .tree li>.list-toggle {line-height: 24px;}
|
||||
#tabContent .tree li.has-list.open:before {content: unset;}
|
||||
|
||||
#swapper li.hide-in-search>div>a:focus, #swapper li.hide-in-search>div>a:hover {color: #838a9d; cursor: default;}
|
||||
#swapper li>div.hide-in-search>a:focus, #swapper li>div.hide-in-search>a:hover {color: #838a9d; cursor: default;}
|
||||
a.executionName:focus, a.executionName:hover {background: #0c64eb; color: #fff !important;}
|
||||
|
||||
#swapper li > a {padding-top: 4px; padding-bottom: 4px;}
|
||||
#swapper li {padding-top: 0; padding-bottom: 0;}
|
||||
#swapper .tree li>.list-toggle {top: -1px;}
|
||||
</style>
|
||||
<?php
|
||||
$executionCounts = array();
|
||||
@@ -62,8 +66,8 @@ foreach($executions as $projectID => $projectExecutions)
|
||||
$projectName = zget($projects, $projectID);
|
||||
$preFix = $projectName . ' / ';
|
||||
|
||||
if($executionCounts[$projectID]['myExecution']) $myExecutionsHtml .= '<li class="hide-in-search"><div><a class="text-muted" title="' . $projectName . '">' . $projectName . '</a> <label class="label">' . $lang->project->common . '</label></div><ul>';
|
||||
if($executionCounts[$projectID]['others']) $normalExecutionsHtml .= '<li class="hide-in-search"><div><a class="text-muted" title="' . $projectName . '">' . $projectName . '</a> <label class="label">' . $lang->project->common . '</label></div><ul>';
|
||||
if($executionCounts[$projectID]['myExecution']) $myExecutionsHtml .= '<li><div class="hide-in-search"><a class="text-muted" title="' . $projectName . '">' . $projectName . '</a> <label class="label">' . $lang->project->common . '</label></div><ul>';
|
||||
if($executionCounts[$projectID]['others']) $normalExecutionsHtml .= '<li><div class="hide-in-search"><a class="text-muted" title="' . $projectName . '">' . $projectName . '</a> <label class="label">' . $lang->project->common . '</label></div><ul>';
|
||||
}
|
||||
|
||||
foreach($projectExecutions as $index => $execution)
|
||||
@@ -144,5 +148,18 @@ $(function()
|
||||
})
|
||||
|
||||
$('#tabContent [data-ride="tree"]').tree('expand');
|
||||
|
||||
$('#swapper #dropMenu .search-box').on('onSearchChange', function(event, value)
|
||||
{
|
||||
if(value != '')
|
||||
{
|
||||
$('div.hide-in-search').siblings('i').addClass('hide-in-search');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('div.hide-in-search').siblings('i').removeClass('hide-in-search');
|
||||
$('li.has-list div.hide-in-search').removeClass('hidden');
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<tr>
|
||||
<th><?php echo $lang->execution->doingProject . ' (' . $projectCount . ')';?></th>
|
||||
<?php foreach($lang->execution->kanbanColType as $status => $colName):?>
|
||||
<th><?php echo $colName . ' (' . $statusCount[$status] . ')';?></th>
|
||||
<th><?php echo $colName . ($status != 'closed' ? ' (' . $statusCount[$status] . ')' : '');?></th>
|
||||
<?php endforeach;?>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -45,21 +45,7 @@
|
||||
<div class="board s-<?php echo $colStatus?>">
|
||||
<div>
|
||||
<?php if(!empty($executionList[$colStatus])):?>
|
||||
<?php foreach($executionList[$colStatus] as $executionID => $execution):?>
|
||||
<?php if($executionID == 'more'):?>
|
||||
<div class='text-center'>
|
||||
<?php
|
||||
if(common::hasPriv('execution', 'all'))
|
||||
{
|
||||
echo html::a($this->createLink('execution', 'all', "status=closed&projectID=$projectID"), $execution, '', "title='$execution'");
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<span title='$execution'>$execution</span>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<?php foreach($executionList[$colStatus] as $execution):?>
|
||||
<div class='board-item' <?php if($execution->status == 'doing' and isset($execution->delay)) echo "style='border-left: 3px solid red';";?>>
|
||||
<div class='table-row'>
|
||||
<div class='table-col'>
|
||||
@@ -85,7 +71,6 @@
|
||||
<?php endif?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif?>
|
||||
<?php endforeach?>
|
||||
<?php endif?>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php js::set('systemMode', $config->systemMode);?>
|
||||
<?php js::set('projectCommon', $lang->projectCommon);?>
|
||||
<?php js::set('executionID', $execution->id);?>
|
||||
<?php js::set('team2Import', $team2Import);?>
|
||||
<?php js::set('roles', $roles);?>
|
||||
|
||||
@@ -623,7 +623,6 @@ class gitlabModel extends model
|
||||
*/
|
||||
public function apiGetIssues($gitlabID, $projectID, $options = null)
|
||||
{
|
||||
/* TODO(dingguodong) not pagination yet. */
|
||||
if($options)
|
||||
{
|
||||
$url = sprintf($this->getApiRoot($gitlabID), "/projects/{$projectID}/issues") . '&per_page=20' . $options;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
$lang->index->common = 'Home';
|
||||
$lang->index->index = 'Home';
|
||||
$lang->index->pleaseInput = 'Please input';
|
||||
$lang->index->pleaseInput = 'Enter';
|
||||
$lang->index->search = 'Search';
|
||||
|
||||
$lang->index->app = new stdClass();
|
||||
@@ -14,4 +14,4 @@ $lang->index->upgradeNow = 'Upgrade now';
|
||||
$lang->index->upgrade = 'Upgrade';
|
||||
$lang->index->log = 'Log';
|
||||
$lang->index->detailed = 'Details';
|
||||
$lang->index->website = 'Please visit the official website';
|
||||
$lang->index->website = 'Visit ZenTao official website';
|
||||
|
||||
@@ -15,7 +15,7 @@ class messageModel extends model
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_NOTIFY)
|
||||
->where('objectType')->eq('message')
|
||||
->andWhere('toList')->eq($this->app->user->account)
|
||||
->andWhere('toList')->like("%,{$this->app->user->account},%")
|
||||
->beginIF($status)->andWhere('status')->eq($status)->fi()
|
||||
->fetchAll('id');
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class messageModel extends model
|
||||
$notify = new stdclass();
|
||||
$notify->objectType = 'message';
|
||||
$notify->action = $actionID;
|
||||
$notify->toList = $toList;
|
||||
$notify->toList = str_replace(",{$actor},", '', ",$toList,");
|
||||
$notify->data = $data;
|
||||
$notify->status = 'wait';
|
||||
$notify->createdBy = $actor;
|
||||
@@ -168,12 +168,9 @@ class messageModel extends model
|
||||
{
|
||||
/* Get notifiy persons. */
|
||||
$notifyPersons = array();
|
||||
if(!empty($toList->notify)) $notifyPersons = $this->loadModel('release')->getNotifyPersons($object->notify, $object->product, $object->build);
|
||||
if(!empty($object->notify)) $notifyPersons = $this->loadModel('release')->getNotifyPersons($object->notify, $object->product, $object->build);
|
||||
|
||||
foreach($notifyPersons as $account)
|
||||
{
|
||||
if(strpos($object->mailto . ',', ",{$account},") === false) $toList .= ',' . $account;
|
||||
}
|
||||
if(!empty($notifyPersons)) $toList = implode(',', $notifyPersons);
|
||||
}
|
||||
|
||||
if($toList == 'closed') $toList = '';
|
||||
|
||||
@@ -19,7 +19,7 @@ $lang->misc->zentao->labels['about'] = 'About ZenTao';
|
||||
$lang->misc->zentao->labels['support'] = 'Tech Support';
|
||||
$lang->misc->zentao->labels['cowin'] = 'Help Us';
|
||||
$lang->misc->zentao->labels['service'] = 'Service';
|
||||
$lang->misc->zentao->labels['others'] = 'EasyCorp Products';
|
||||
$lang->misc->zentao->labels['others'] = 'From EasyCorp';
|
||||
|
||||
$lang->misc->zentao->icons['about'] = 'group';
|
||||
$lang->misc->zentao->icons['support'] = 'question-sign';
|
||||
@@ -69,7 +69,7 @@ $lang->misc->tableName = "Table Name";
|
||||
$lang->misc->tableStatus = "Status";
|
||||
$lang->misc->novice = "New to ZenTao? Do you want to start ZenTao Tutorial?";
|
||||
$lang->misc->showAnnual = 'Add Annual Summary';
|
||||
$lang->misc->annualDesc = 'After version 12.0, the Annual Summary can be viewed on 『Report->Annual Summary』 page. <a href="%s" target="_blank" id="showAnnual" class="btn btn-mini btn-primary">See now</a>.';
|
||||
$lang->misc->annualDesc = 'After version 12.0, Annual Summary can be viewed on 『Report->Annual Summary』 page. <a href="%s" target="_blank" id="showAnnual" class="btn btn-mini btn-primary">See now</a>.';
|
||||
$lang->misc->remind = 'New feature reminders';
|
||||
|
||||
$lang->misc->noticeRepair = "<h5>If you are not Administrator, contact your ZenTao Administrator to repair tables.</h5>
|
||||
|
||||
+61
-59
@@ -58,7 +58,7 @@ class myModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* My charged products.
|
||||
* Get my charged products.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -114,11 +114,12 @@ class myModel extends model
|
||||
if(isset($stories[$product->id])) $product->stories = $stories[$product->id];
|
||||
if(isset($executions[$product->id])) $product->executions = $executions[$product->id];
|
||||
}
|
||||
|
||||
return array_values($products);
|
||||
}
|
||||
|
||||
/**
|
||||
* All projects.
|
||||
* Get my projects.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
@@ -130,21 +131,21 @@ class myModel extends model
|
||||
{
|
||||
if($project->status == 'doing')
|
||||
{
|
||||
$workhour = $this->loadModel('project')->getWorkhour($project->id);
|
||||
$workhour = $this->project->getWorkhour($project->id);
|
||||
$projects[$key]->progress = ($workhour->totalConsumed + $workhour->totalLeft) ? floor($workhour->totalConsumed / ($workhour->totalConsumed + $workhour->totalLeft) * 1000) / 1000 * 100 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($projects);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic.
|
||||
* Get latest actions.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getDynamic()
|
||||
public function getActions()
|
||||
{
|
||||
$actions = $this->loadModel('action')->getDynamic('all', 'today', 'date_desc');
|
||||
$users = $this->loadModel('user')->getPairs('noletter');
|
||||
@@ -174,12 +175,12 @@ class myModel extends model
|
||||
if(common::hasPriv('task', 'view'))
|
||||
{
|
||||
$tasks = $this->dao->select('*')->from(TABLE_TASK)
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
$info->task->dynamic = $tasks;
|
||||
}
|
||||
|
||||
@@ -190,12 +191,12 @@ class myModel extends model
|
||||
if(common::hasPriv('story', 'view'))
|
||||
{
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
$info->story->dynamic = $stories;
|
||||
}
|
||||
|
||||
@@ -207,30 +208,30 @@ class myModel extends model
|
||||
{
|
||||
$this->app->loadLang('bug');
|
||||
$bugs = $this->dao->select('*')->from(TABLE_BUG)
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
$info->bug->dynamic = $bugs;
|
||||
}
|
||||
|
||||
/* My todos. */
|
||||
$info->todo = new stdclass();
|
||||
$info->todo->total = (int) $this->dao->select('count(*) AS count')->from(TABLE_TODO)->where('assignedTo')->eq($this->app->user->account)->andWhere('status')->ne('closed')->andWhere('deleted')->eq(0)->fetch('count');
|
||||
$info->todo->dynamic = new stdclass();
|
||||
$info->todo->dynamic = array();
|
||||
if(common::hasPriv('todo', 'view'))
|
||||
{
|
||||
$this->app->loadClass('date');
|
||||
$todos = $this->dao->select('*')->from(TABLE_TODO)
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('cycle')->eq(0)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('status')->eq('wait')
|
||||
->orderBy('`date` desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('cycle')->eq(0)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('status')->eq('wait')
|
||||
->orderBy('`date` desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
foreach($todos as $key => $todo)
|
||||
{
|
||||
$todo->begin = date::formatTime($todo->begin);
|
||||
@@ -242,16 +243,16 @@ class myModel extends model
|
||||
/* My risks. */
|
||||
$info->risk = new stdclass();
|
||||
$info->risk->total = 0;
|
||||
$info->risk->dynamic = new stdclass();
|
||||
$info->risk->dynamic = array();
|
||||
if(common::hasPriv('risk', 'view') and isset($this->config->maxVersion))
|
||||
{
|
||||
$risks = $this->dao->select('*')->from(TABLE_RISK)
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
$info->risk->total = (int) $this->dao->select('count(*) AS count')->from(TABLE_RISK)->where('assignedTo')->eq($this->app->user->account)->andWhere('status')->ne('closed')->andWhere('deleted')->eq(0)->fetch('count');
|
||||
$info->risk->dynamic = $risks;
|
||||
}
|
||||
@@ -259,23 +260,23 @@ class myModel extends model
|
||||
/* My meetings. */
|
||||
$info->meeting = new stdclass();
|
||||
$info->meeting->total = 0;
|
||||
$info->meeting->dynamic = new stdclass();
|
||||
$info->meeting->dynamic = array();
|
||||
if(common::hasPriv('meeting', 'view') and isset($this->config->maxVersion))
|
||||
{
|
||||
$today = helper::today();
|
||||
$now = date('H:i:s', strtotime(helper::now()));
|
||||
|
||||
$meetings = $this->dao->select('*')->from(TABLE_MEETING)
|
||||
->Where('deleted')->eq('0')
|
||||
->andWhere('(date')->gt($today)
|
||||
->orWhere('(begin')->gt($now)
|
||||
->andWhere('date')->eq($today)
|
||||
->markRight(2)
|
||||
->andwhere('(host')->eq($this->app->user->account)
|
||||
->orWhere('participant')->in($this->app->user->account)
|
||||
->markRight(1)
|
||||
->orderBy('id_desc')
|
||||
->fetchAll();
|
||||
->Where('deleted')->eq('0')
|
||||
->andWhere('(date')->gt($today)
|
||||
->orWhere('(begin')->gt($now)
|
||||
->andWhere('date')->eq($today)
|
||||
->markRight(2)
|
||||
->andwhere('(host')->eq($this->app->user->account)
|
||||
->orWhere('participant')->in($this->app->user->account)
|
||||
->markRight(1)
|
||||
->orderBy('id_desc')
|
||||
->fetchAll();
|
||||
$info->meeting->total = count($meetings);
|
||||
$info->meeting->dynamic = array_slice($meetings, 0, 3);
|
||||
}
|
||||
@@ -283,22 +284,23 @@ class myModel extends model
|
||||
/* My issues. */
|
||||
$info->issue = new stdclass();
|
||||
$info->issue->total = 0;
|
||||
$info->issue->dynamic = new stdclass();
|
||||
$info->issue->dynamic = array();
|
||||
if(common::hasPriv('issue', 'view') and isset($this->config->maxVersion))
|
||||
{
|
||||
$issues = $this->dao->select('*')->from(TABLE_ISSUE)
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
->where('assignedTo')->eq($this->app->user->account)
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere('status')->ne('closed')
|
||||
->orderBy('id_desc')
|
||||
->limit(3)
|
||||
->fetchAll();
|
||||
$info->issue->total = (int) $this->dao->select('count(*) AS count')->from(TABLE_ISSUE)->where('assignedTo')->eq($this->app->user->account)->andWhere('status')->ne('closed')->andWhere('deleted')->eq(0)->fetch('count');
|
||||
$info->issue->dynamic = $issues;
|
||||
}
|
||||
|
||||
/* Some count. */
|
||||
$info->createdDocs = $this->dao->select('count(*) AS count')->from(TABLE_DOC)->where('addedBy')->eq($this->app->user->account)->andWhere('deleted')->eq('0')->fetch('count');
|
||||
/* Get count of docs created by me. */
|
||||
$info->doc = new stdclass();
|
||||
$info->doc->total = $this->dao->select('count(*) AS count')->from(TABLE_DOC)->where('addedBy')->eq($this->app->user->account)->andWhere('deleted')->eq('0')->fetch('count');
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ class personnel extends control
|
||||
$this->view->objectID = $objectID;
|
||||
$this->view->objectType = $objectType;
|
||||
$this->view->objectName = $objectName;
|
||||
$this->view->objects = array('' => '') + $this->personnel->getCopyObjects($objectID, $objectType);
|
||||
$this->view->objects = array('' => '') + $this->personnel->getCopiedObjects($objectID, $objectType);
|
||||
$this->view->module = $module;
|
||||
$this->view->deptID = $deptID;
|
||||
$this->view->appendUsers = $appendUsers;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#object_chosen .chosen-single, #dept_chosen .chosen-single {width: 220px;}
|
||||
#object_chosen .chosen-drop ul li .label {margin-top: 2px; background: #fff; color: #838a9d; border: 1px solid #d8d8d8;}
|
||||
@@ -136,4 +136,9 @@ $(function()
|
||||
showItem(val);
|
||||
});
|
||||
});
|
||||
|
||||
$('#object_chosen').click(function()
|
||||
{
|
||||
if(systemMode == 'new' && objectType == 'sprint') $('#object_chosen ul li:first').append(' <label class="label">' + projectCommon + '</label>')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -457,14 +457,14 @@ class personnelModel extends model
|
||||
}
|
||||
|
||||
/**
|
||||
* Get objects to copy whitelist.
|
||||
* Get objects to copy.
|
||||
*
|
||||
* @param int $objectID
|
||||
* @param int $objectType
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCopyObjects($objectID, $objectType)
|
||||
public function getCopiedObjects($objectID, $objectType)
|
||||
{
|
||||
$objects = array();
|
||||
|
||||
@@ -485,8 +485,7 @@ class personnelModel extends model
|
||||
->fetchPairs();
|
||||
foreach($objects as $id => &$object)
|
||||
{
|
||||
if($id == $parentID) $object = $this->lang->projectCommon . '-' . $object;
|
||||
if($id != $parentID) $object = $this->lang->execution->common . '-' . $object;
|
||||
if($id != $parentID) $object = ' ' . $object;
|
||||
}
|
||||
}
|
||||
elseif($objectType == 'project')
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php js::set('objectID', $objectID);?>
|
||||
<?php js::set('objectType', $objectType);?>
|
||||
<style>#object_chosen .chosen-single, #dept_chosen .chosen-single {width: 220px;}</style>
|
||||
<?php js::set('systemMode', $config->systemMode);?>
|
||||
<?php js::set('projectCommon', $lang->projectCommon);?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<span class='btn btn-link btn-active-text'>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#createActionMenu .dropdown-menu {width: 100%;}
|
||||
#productStoryForm table tbody tr td {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
#productStoryForm table tbody tr td {overflow: hidden; white-space: nowrap;}
|
||||
|
||||
.dropdown-menu.with-search {padding: 0; min-width: 150px; overflow: hidden; max-height: 302px;}
|
||||
.dropdown-menu > .menu-search .input-group {width: 100%;}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#tabContent {margin-top: 10px; z-index: 900;}
|
||||
#tabContent ul {list-style: none; margin: 0}
|
||||
#tabContent .tab-pane>ul {padding-left: 7px;}
|
||||
#tabContent .tab-pane>ul>li.hide-in-search>div {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
#tabContent .tab-pane>ul>li>div {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
#tabContent .tab-pane>ul>li label {background: rgba(255,255,255,0.5); line-height: unset; color: #838a9d; border: 1px solid #d8d8d8; border-radius: 2px; padding: 1px 4px;}
|
||||
#tabContent li a i.icon {font-size: 15px !important;}
|
||||
#tabContent li a i.icon:before {min-width: 16px !important;}
|
||||
@@ -24,8 +24,12 @@
|
||||
#tabContent .tree li>.list-toggle {line-height: 24px;}
|
||||
#tabContent .tree li.has-list.open:before {content: unset;}
|
||||
|
||||
#swapper li.hide-in-search>div>a:focus, #swapper li.hide-in-search>div>a:hover {color: #838a9d; cursor: default;}
|
||||
#swapper li>div.hide-in-search>a:focus, #swapper li>div.hide-in-search>a:hover {color: #838a9d; cursor: default;}
|
||||
a.productName:focus, a.productName:hover {background: #0c64eb; color: #fff !important;}
|
||||
|
||||
#swapper li > a {padding-top: 4px; padding-bottom: 4px;}
|
||||
#swapper li {padding-top: 0; padding-bottom: 0;}
|
||||
#swapper .tree li>.list-toggle {top: -1px;}
|
||||
</style>
|
||||
<?php
|
||||
$productCounts = array();
|
||||
@@ -64,8 +68,8 @@ foreach($products as $programID => $programProducts)
|
||||
$programName = zget($programs, $programID);
|
||||
$preFix = $programName . ' / ';
|
||||
|
||||
if($productCounts[$programID]['myProduct']) $myProductsHtml .= '<li class="hide-in-search"><div><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
if($productCounts[$programID]['others']) $normalProductsHtml .= '<li class="hide-in-search"><div><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
if($productCounts[$programID]['myProduct']) $myProductsHtml .= '<li><div class="hide-in-search"><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
if($productCounts[$programID]['others']) $normalProductsHtml .= '<li><div class="hide-in-search"><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
}
|
||||
|
||||
foreach($programProducts as $index => $product)
|
||||
@@ -151,5 +155,18 @@ $(function()
|
||||
})
|
||||
|
||||
$('#tabContent [data-ride="tree"]').tree('expand');
|
||||
|
||||
$('#swapper #dropMenu .search-box').on('onSearchChange', function(event, value)
|
||||
{
|
||||
if(value != '')
|
||||
{
|
||||
$('div.hide-in-search').siblings('i').addClass('hide-in-search');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('div.hide-in-search').siblings('i').removeClass('hide-in-search');
|
||||
$('li.has-list div.hide-in-search').removeClass('hidden');
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -345,6 +345,9 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
|
||||
$misc = $canBatchClose ? "onclick=\"setFormAction('$actionLink', '', '#productStoryForm')\"" : '';
|
||||
echo "<li $class>" . html::a('#', $lang->close, '', $misc) . "</li>";
|
||||
|
||||
$class = $canBatchUnlink ? '' : "class='disabled'";
|
||||
echo "<li $class>" . html::a('#', $lang->story->unlink, '', "id='batchUnlinkStory'") . "</li>";
|
||||
|
||||
if($canBatchReview)
|
||||
{
|
||||
echo "<li class='dropdown-submenu'>";
|
||||
@@ -517,13 +520,6 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : '';
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
<?php
|
||||
if($canBatchUnlink)
|
||||
{
|
||||
echo html::commonButton($lang->projectstory->unlinkStory, "id='batchUnlinkStory'");
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if($canBatchImportToLib):?>
|
||||
<?php echo html::a('#batchImportToLib', $lang->story->importToLib, '', 'class="btn" data-toggle="modal" id="importToLib"');?>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -49,23 +49,28 @@ $(function()
|
||||
}
|
||||
})
|
||||
|
||||
$('#cancelBtn').click(function()
|
||||
$('#cancelBTN').click(function()
|
||||
{
|
||||
$('#syncPRJUnit').val('false');
|
||||
$('#exchangeRate').val('');
|
||||
})
|
||||
|
||||
$('#confirmBtn').click(function()
|
||||
$('#confirmBTN').click(function()
|
||||
{
|
||||
var exchangeRate = $('#rate').val();
|
||||
if(!exchangeRate)
|
||||
{
|
||||
alert(exRateNotEmpty);
|
||||
bootbox.alert(exRateNotEmpty);
|
||||
return false;
|
||||
}
|
||||
else if(isNaN(exchangeRate))
|
||||
{
|
||||
bootbox.alert(exRateNum);
|
||||
return false;
|
||||
}
|
||||
else if(exchangeRate < 0)
|
||||
{
|
||||
alert(exRateNotNegative);
|
||||
bootbox.alert(exRateNotNegative);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ class programModel extends model
|
||||
{
|
||||
$totalProgress = array();
|
||||
$projectCount = array();
|
||||
$userPrjCount = array();
|
||||
$userPRJCount = array();
|
||||
$progressList = array();
|
||||
$programPairs = $this->getPairs();
|
||||
$projectStats = $this->getProjectStats(0, 'all', 0, 'id_desc', null, 0, 0, true);
|
||||
@@ -257,7 +257,7 @@ class programModel extends model
|
||||
{
|
||||
$totalProgress[$programID] = 0;
|
||||
$projectCount[$programID] = 0;
|
||||
$userPrjCount[$programID] = 0;
|
||||
$userPRJCount[$programID] = 0;
|
||||
$progressList[$programID] = 0;
|
||||
|
||||
foreach($projectStats as $project)
|
||||
@@ -265,7 +265,7 @@ class programModel extends model
|
||||
if(strpos($project->path, ',' . $programID . ',') === false) continue;
|
||||
|
||||
/* The number of projects under this program that the user can view. */
|
||||
if(strpos(',' . $this->app->user->view->projects . ',', ',' . $project->id . ',') !== false) $userPrjCount[$programID] ++;
|
||||
if(strpos(',' . $this->app->user->view->projects . ',', ',' . $project->id . ',') !== false) $userPRJCount[$programID] ++;
|
||||
|
||||
$totalProgress[$programID] += $project->hours->progress;
|
||||
$projectCount[$programID] ++;
|
||||
@@ -274,7 +274,7 @@ class programModel extends model
|
||||
if(empty($projectCount[$programID])) continue;
|
||||
|
||||
/* Program progress can't see when this user don't have all projects priv. */
|
||||
if(!$this->app->user->admin and $userPrjCount[$programID] != $projectCount[$programID])
|
||||
if(!$this->app->user->admin and $userPRJCount[$programID] != $projectCount[$programID])
|
||||
{
|
||||
unset($progressList[$programID]);
|
||||
continue;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<?php js::set('budgetUnitList', $budgetUnitList);?>
|
||||
<?php js::set('oldBudgetUnit', $program->budgetUnit);?>
|
||||
<?php js::set('exRateNotEmpty', sprintf($lang->error->notempty, $lang->program->exchangeRate));?>
|
||||
<?php js::set('exRateNum', sprintf($lang->error->float, $lang->program->exchangeRate));?>
|
||||
<?php js::set('exRateNotNegative', $lang->program->exRateNotNegative);?>
|
||||
<?php $aclList = $program->parent ? $lang->program->subAclList : $lang->program->aclList;?>
|
||||
<?php $requiredFields = $config->program->edit->requiredFields;?>
|
||||
@@ -135,13 +136,13 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo '1' . zget($budgetUnitList, $program->budgetUnit);?></th>
|
||||
<td><div class='input-group'><span class='input-group-addon'><?php echo "=";?></span><?php echo html::number('rate', '', "class='form-control' required");?> <span class='input-group-addon' id='currentUnit'></span></div></td>
|
||||
<td><div class='input-group'><span class='input-group-addon'><?php echo "=";?></span><?php echo html::input('rate', '', "class='form-control' required");?> <span class='input-group-addon' id='currentUnit'></span></div></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='3' class='text-center'>
|
||||
<?php echo html::commonButton($lang->confirm, "id='confirmBtn'", 'btn btn-primary btn-wide');?>
|
||||
<?php echo html::commonButton($lang->cancel, "data-dismiss='modal' id='cancelBtn'", 'btn btn-default btn-wide');?>
|
||||
<?php echo html::commonButton($lang->confirm, "id='confirmBTN'", 'btn btn-primary btn-wide');?>
|
||||
<?php echo html::commonButton($lang->cancel, "data-dismiss='modal' id='cancelBTN'", 'btn btn-default btn-wide');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -447,10 +447,11 @@ class project extends control
|
||||
* Edit a project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $from
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function edit($projectID = 0)
|
||||
public function edit($projectID = 0, $from = '')
|
||||
{
|
||||
$this->loadModel('action');
|
||||
$this->loadModel('custom');
|
||||
@@ -485,7 +486,7 @@ class project extends control
|
||||
|
||||
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
|
||||
|
||||
$locateLink = $this->session->projectList ? $this->session->projectList : inLink('view', "projectID=$projectID");
|
||||
$locateLink = ($this->session->projectList and $from != 'view') ? $this->session->projectList : inLink('view', "projectID=$projectID");
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $locateLink));
|
||||
}
|
||||
|
||||
@@ -609,7 +610,6 @@ class project extends control
|
||||
}
|
||||
|
||||
$this->project->setMenu($projectID);
|
||||
$this->session->set('projectList', $this->app->getURI(true), 'project');
|
||||
|
||||
$products = $this->loadModel('product')->getProducts($projectID);
|
||||
$linkedBranches = array();
|
||||
@@ -1257,7 +1257,7 @@ class project extends control
|
||||
$this->view->depts = array('' => '') + $this->dept->getOptionMenu();
|
||||
$this->view->currentMembers = $currentMembers;
|
||||
$this->view->members2Import = $members2Import;
|
||||
$this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopyObjects($projectID, 'project');
|
||||
$this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopiedObjects($projectID, 'project');
|
||||
$this->view->copyProjectID = $copyProjectID;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.side-col {padding-right: 20px; width: 18%;}
|
||||
#sidebar>.cell {width: 100%;}
|
||||
|
||||
th.c-budget {text-align:right;}
|
||||
th.c-budget {text-align: right;}
|
||||
td.c-actions {overflow: visible;}
|
||||
.c-actions .btn {overflow: visible;}
|
||||
#programBox {float: left; margin-right: 10px; width: 170px !important;}
|
||||
|
||||
@@ -1,3 +1,45 @@
|
||||
/**
|
||||
* Save team members.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function saveMemebers()
|
||||
{
|
||||
var isDeleted = false;
|
||||
var accountList = [];
|
||||
$("[name^='accounts']").each(function()
|
||||
{
|
||||
if($(this).val()) accountList.push($(this).val());
|
||||
})
|
||||
|
||||
oldAccountList.forEach(function(account)
|
||||
{
|
||||
if(accountList.indexOf(account) < 0)
|
||||
{
|
||||
isDeleted = true;
|
||||
return false;
|
||||
}
|
||||
})
|
||||
|
||||
if(!isDeleted)
|
||||
{
|
||||
$('#saveBtn').addClass('hidden');
|
||||
$('#submit').removeClass('hidden');
|
||||
$('#submit').click();
|
||||
}
|
||||
else
|
||||
{
|
||||
bootbox.confirm(unlinkExecutionMembers, function(result)
|
||||
{
|
||||
$('#saveBtn').addClass('hidden');
|
||||
$('#submit').removeClass('hidden');
|
||||
if(result) $('#removeExecution').val('yes');
|
||||
$('#submit').click();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set role when select an account.
|
||||
*
|
||||
|
||||
+30
-21
@@ -2,40 +2,49 @@
|
||||
* Delete memeber of project team.
|
||||
*
|
||||
* @param projectID $projectID
|
||||
* @param account $account
|
||||
* @param userID $userID
|
||||
* @param account $account
|
||||
* @param userID $userID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function deleteMemeber(projectID, account, userID)
|
||||
{
|
||||
if(confirm(confirmUnlinkMember))
|
||||
bootbox.confirm(confirmUnlinkMember, function(result)
|
||||
{
|
||||
if(!result) return true;
|
||||
|
||||
var removeConfirm = '';
|
||||
var tipsLink = createLink('project', 'ajaxGetUnlinkTips', 'projectID=' + projectID + '&account=' + account);
|
||||
$.get(tipsLink, function(tips)
|
||||
{
|
||||
if(!tips)
|
||||
var unlinkURL = createLink('project', 'unlinkMember', 'projectID=' + projectID + '&userID=' + userID + '&confirm=yes');
|
||||
|
||||
if(!tips) unlinkMember(unlinkURL);
|
||||
if(tips)
|
||||
{
|
||||
var unlinkURL = createLink('project', 'unlinkMember', 'projectID=' + projectID + '&userID=' + userID + '&confirm=yes&removeExecution=no');
|
||||
}
|
||||
else
|
||||
{
|
||||
if(confirm(tips))
|
||||
bootbox.confirm(tips, function(result)
|
||||
{
|
||||
var unlinkURL = createLink('project', 'unlinkMember', 'projectID=' + projectID + '&userID=' + userID + '&confirm=yes&removeExecution=yes');
|
||||
}
|
||||
else
|
||||
{
|
||||
var unlinkURL = createLink('project', 'unlinkMember', 'projectID=' + projectID + '&userID=' + userID + '&confirm=yes&removeExecution=no');
|
||||
}
|
||||
if(result) unlinkURL = createLink('project', 'unlinkMember', 'projectID=' + projectID + '&userID=' + userID + '&confirm=yes&removeExecution=yes');
|
||||
unlinkMember(unlinkURL);
|
||||
})
|
||||
}
|
||||
|
||||
$.get(unlinkURL, function(data)
|
||||
{
|
||||
data = JSON.parse(data);
|
||||
if(data.result == 'success') window.location.reload();
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink member from project.
|
||||
*
|
||||
* @param unlinkURL $unlinkURL
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function unlinkMember(unlinkURL)
|
||||
{
|
||||
$.get(unlinkURL, function(data)
|
||||
{
|
||||
data = JSON.parse(data);
|
||||
if(data.result == 'success') window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ $lang->project->multiLinkedProductsTip = 'The following products linked to this
|
||||
$lang->project->linkStoryByPlanTips = "This action will associate all {$lang->SRCommon} under the selected plan to this project";
|
||||
$lang->project->createExecution = "There is no {$lang->executionCommon} under this project, please create {$lang->executionCommon} first";
|
||||
$lang->project->unlinkExecutionMember = "The user participated in %s executions such as %s%s. Do you want to remove the user from those executions as well? (The data related to this user will not be deleted.)";
|
||||
$lang->project->unlinkExecutionMembers = "The team members you are removing are also in the execution team of this project. Do you want to remove them from the execution team too?";
|
||||
|
||||
$lang->project->tenThousand = '';
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ $lang->project->multiLinkedProductsTip = '该项目关联的如下产品还关
|
||||
$lang->project->linkStoryByPlanTips = "此操作会将所选计划下面的{$lang->SRCommon}全部关联到此项目中";
|
||||
$lang->project->createExecution = "该项目下没有{$lang->executionCommon},请先创建{$lang->executionCommon}";
|
||||
$lang->project->unlinkExecutionMember = "该用户参与了%s%s%s个{$lang->execution->common},是否同时将其移除?(该用户所产生的数据不会受影响。)";
|
||||
$lang->project->unlinkExecutionMembers = "移除的团队成员还参与了项目下的执行,是否同步从执行团队中移除?";
|
||||
|
||||
$lang->project->tenThousand = '万';
|
||||
|
||||
|
||||
@@ -1269,15 +1269,16 @@ class projectModel extends model
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_TEAM)->where('root')->eq((int)$projectID)->andWhere('type')->eq('project')->andWhere('account')->eq($account)->exec();
|
||||
|
||||
$this->loadModel('user');
|
||||
$this->user->updateUserView($projectID, 'project', array($account));
|
||||
|
||||
if($removeExecution == 'yes')
|
||||
{
|
||||
$executions = $this->loadModel('execution')->getByProject($projectID, 'undone', 0, true);
|
||||
$this->dao->delete()->from(TABLE_TEAM)->where('root')->in(array_keys($executions))->andWhere('type')->eq('execution')->andWhere('account')->eq($account)->exec();
|
||||
$this->user->updateUserView(array_keys($executions), 'sprint', array($account));
|
||||
}
|
||||
|
||||
$this->loadModel('user');
|
||||
$this->user->updateUserView($projectID, 'project', array($account));
|
||||
|
||||
$linkedProducts = $this->loadModel('product')->getProductPairsByProject($projectID);
|
||||
if(!empty($linkedProducts)) $this->user->updateUserView(array_keys($linkedProducts), 'product', array($account));
|
||||
}
|
||||
@@ -1324,8 +1325,8 @@ class projectModel extends model
|
||||
|
||||
/* Only changed account update userview. */
|
||||
$oldAccounts = array_keys($oldJoin);
|
||||
$changedAccounts = array_diff($accounts, $oldAccounts);
|
||||
$changedAccounts = array_merge($changedAccounts, array_diff($oldAccounts, $accounts));
|
||||
$removedAccounts = array_diff($oldAccounts, $accounts);
|
||||
$changedAccounts = array_merge($removedAccounts, array_diff($accounts, $oldAccounts));
|
||||
$changedAccounts = array_unique($changedAccounts);
|
||||
|
||||
$childSprints = $this->dao->select('id')->from(TABLE_PROJECT)->where('project')->eq($projectID)->andWhere('type')->in('stage,sprint')->andWhere('deleted')->eq('0')->fetchPairs();
|
||||
@@ -1334,6 +1335,16 @@ class projectModel extends model
|
||||
$this->loadModel('user')->updateUserView(array($projectID), 'project', $changedAccounts);
|
||||
if(!empty($childSprints)) $this->user->updateUserView($childSprints, 'sprint', $changedAccounts);
|
||||
if(!empty($linkedProducts)) $this->user->updateUserView(array_keys($linkedProducts), 'product', $changedAccounts);
|
||||
|
||||
/* Remove execution members. */
|
||||
if($removeExecution == 'yes' and !empty($childSprints) and !empty($removedAccounts))
|
||||
{
|
||||
$this->dao->delete()->from(TABLE_TEAM)
|
||||
->where('root')->in($childSprints)
|
||||
->andWhere('type')->eq('execution')
|
||||
->andWhere('account')->in($removedAccounts)
|
||||
->exec();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1617,7 +1628,7 @@ class projectModel extends model
|
||||
return $this->dao->select('account, role, hours')
|
||||
->from(TABLE_TEAM)
|
||||
->where('root')->eq($projectID)
|
||||
->andWhere('type')->in('project')
|
||||
->andWhere('type')->eq('project')
|
||||
->andWhere('account')->notIN($currentMembers)
|
||||
->fetchAll('account');
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#tabContent {margin-top: 10px; z-index: 900;}
|
||||
#tabContent ul {list-style: none; margin: 0}
|
||||
#tabContent .tab-pane>ul {padding-left: 7px;}
|
||||
#tabContent .tab-pane>ul>li.hide-in-search>div {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
#tabContent .tab-pane>ul>li>div {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
|
||||
#tabContent .tab-pane>ul>li label {background: rgba(255,255,255,0.5); line-height: unset; color: #838a9d; border: 1px solid #d8d8d8; border-radius: 2px; padding: 1px 4px;}
|
||||
#tabContent li a i.icon {font-size: 15px !important;}
|
||||
#tabContent li a i.icon:before {min-width: 16px !important;}
|
||||
@@ -23,8 +23,12 @@
|
||||
#tabContent .tree li>.list-toggle {line-height: 24px;}
|
||||
#tabContent .tree li.has-list.open:before {content: unset;}
|
||||
|
||||
#swapper li.hide-in-search>div>a:focus, #swapper li.hide-in-search>div>a:hover {color: #838a9d; cursor: default;}
|
||||
#swapper li>div.hide-in-search>a:focus, #swapper li>div.hide-in-search>a:hover {color: #838a9d; cursor: default;}
|
||||
a.projectName:focus, a.projectName:hover {background: #0c64eb; color: #fff !important;}
|
||||
|
||||
#swapper li > a {padding-top: 4px; padding-bottom: 4px;}
|
||||
#swapper li {padding-top: 0; padding-bottom: 0;}
|
||||
#swapper .tree li>.list-toggle {top: -1px;}
|
||||
</style>
|
||||
<?php
|
||||
$projectCounts = array();
|
||||
@@ -62,8 +66,8 @@ foreach($projects as $programID => $programProjects)
|
||||
$programName = zget($programs, $programID);
|
||||
$preFix = $programName . ' / ';
|
||||
|
||||
if($projectCounts[$programID]['myProject']) $myProjectsHtml .= '<li class="hide-in-search"><div><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
if($projectCounts[$programID]['others']) $normalProjectsHtml .= '<li class="hide-in-search"><div><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
if($projectCounts[$programID]['myProject']) $myProjectsHtml .= '<li><div class="hide-in-search"><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
if($projectCounts[$programID]['others']) $normalProjectsHtml .= '<li><div class="hide-in-search"><a class="text-muted" title="' . $programName . '">' . $programName . '</a> <label class="label">' . $lang->program->common . '</label></div><ul>';
|
||||
}
|
||||
|
||||
foreach($programProjects as $index => $project)
|
||||
@@ -152,5 +156,18 @@ $(function()
|
||||
})
|
||||
|
||||
$('#tabContent [data-ride="tree"]').tree('expand');
|
||||
|
||||
$('#swapper #dropMenu .search-box').on('onSearchChange', function(event, value)
|
||||
{
|
||||
if(value != '')
|
||||
{
|
||||
$('div.hide-in-search').siblings('i').addClass('hide-in-search');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('div.hide-in-search').siblings('i').removeClass('hide-in-search');
|
||||
$('li.has-list div.hide-in-search').removeClass('hidden');
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -149,11 +149,11 @@
|
||||
if($count > 2) continue;
|
||||
if(!isset($users[$member]))
|
||||
{
|
||||
$project->teamCount -= 1;
|
||||
$project->teamCount --;
|
||||
continue;
|
||||
}
|
||||
$count ++;
|
||||
?>
|
||||
<?php $count += 1;?>
|
||||
<a href='<?php echo helper::createLink('project', 'team', "projectID=$projectID");?>' title="<?php echo $users[$member];?>">
|
||||
<div class="avatar bg-secondary avatar-circle avatar-<?php echo $member;?>">
|
||||
<?php echo !empty($usersAvatar[$member]) ? html::image(zget($usersAvatar, $member)) : strtoupper($member[0]);?>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
<?php js::set('roles', $roles);?>
|
||||
<?php js::set('deptID', $dept);?>
|
||||
<?php js::set('copyProjectID', $copyProjectID);?>
|
||||
<?php js::set('oldAccountList', array_keys($currentMembers));?>
|
||||
<?php js::set('unlinkExecutionMembers', $lang->project->unlinkExecutionMembers);?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<span class='btn btn-link btn-active-text'>
|
||||
@@ -105,7 +107,9 @@
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan='6' class='text-center form-actions'>
|
||||
<?php echo html::submitButton() . html::backButton();?>
|
||||
<?php echo html::hidden('removeExecution', 'no');?>
|
||||
<?php echo html::submitButton('', '', 'hidden btn btn-wide btn-primary');?>
|
||||
<?php echo html::commonButton($lang->save, 'onclick="saveMemebers()" id="saveBtn"', 'btn btn-wide btn-primary') . html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
echo $this->buildOperateMenu($project, 'view');
|
||||
|
||||
echo "<div class='divider'></div>";
|
||||
common::printIcon('project', 'edit', $params, $project, 'button', 'edit', '', '', '', '', $lang->edit);
|
||||
common::printIcon('project', 'edit', $params . '&from=view', $project, 'button', 'edit', '', '', '', '', $lang->edit);
|
||||
common::printIcon('project', 'delete', $params, $project, 'button', 'trash', 'hiddenwin', '', '', '', $lang->delete);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
|
||||
|
||||
/* Notice. */
|
||||
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
|
||||
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
|
||||
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
|
||||
|
||||
global $app;
|
||||
$app->loadLang('product');
|
||||
|
||||
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
|
||||
|
||||
/* Notice. */
|
||||
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
|
||||
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
|
||||
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
|
||||
|
||||
global $app;
|
||||
$app->loadLang('product');
|
||||
|
||||
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
|
||||
|
||||
/* Notice. */
|
||||
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
|
||||
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
|
||||
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
|
||||
|
||||
global $app;
|
||||
$app->loadLang('product');
|
||||
|
||||
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
|
||||
|
||||
/* Notice. */
|
||||
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
|
||||
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
|
||||
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
|
||||
|
||||
global $app;
|
||||
$app->loadLang('product');
|
||||
|
||||
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = '确定';
|
||||
|
||||
/* Notice. */
|
||||
$lang->projectstory->whyNoStories = "看起来没有{$lang->SRCommon}可以关联。请检查下项目关联的{$lang->productCommon}中有没有{$lang->SRCommon},而且要确保它们已经审核通过。";
|
||||
$lang->projectstory->batchUnlinkTip = '如下需求已与该项目下执行相关联,请从执行中移除后再操作。';
|
||||
$lang->projectstory->batchUnlinkTip = '其他需求已经移除,如下需求已与该项目下执行相关联,请从执行中移除后再操作。';
|
||||
|
||||
global $app;
|
||||
$app->loadLang('product');
|
||||
|
||||
+12
-11
@@ -229,6 +229,7 @@ class releaseModel extends model
|
||||
->join('mailto', ',')
|
||||
->join('notify', ',')
|
||||
->setIF(!$this->post->marker, 'marker', 0)
|
||||
->setIF(!$this->post->notify, 'notify', '')
|
||||
->cleanInt('product')
|
||||
->remove('files,labels,allchecker,uid')
|
||||
->get();
|
||||
@@ -271,14 +272,14 @@ class releaseModel extends model
|
||||
|
||||
/* Init vars. */
|
||||
$notifyPersons = array();
|
||||
$managers = '';
|
||||
$notifyList = explode($notifyList, ',');
|
||||
$managerFields = '';
|
||||
$notifyList = explode(',', $notifyList);
|
||||
|
||||
foreach($notifyList as $notify)
|
||||
{
|
||||
if($notify == 'PO' or $notify == 'QD' or $notify == 'feedback')
|
||||
{
|
||||
$managers .= $notify . ',';
|
||||
$managerFields .= $notify . ',';
|
||||
}
|
||||
elseif($notify == 'SC' and !empty($buildID))
|
||||
{
|
||||
@@ -287,14 +288,14 @@ class releaseModel extends model
|
||||
|
||||
if(empty($stories)) continue;
|
||||
|
||||
$createUsers = $this->dao->select('openedBy')->from(TABLE_STORY)->where('id')->in($stories)->fetchPairs();
|
||||
$notifyPersons += $createUsers;
|
||||
$openedByList = $this->dao->select('openedBy')->from(TABLE_STORY)->where('id')->in($stories)->fetchPairs();
|
||||
$notifyPersons += $openedByList;
|
||||
}
|
||||
elseif(($notify == 'ET' or $notify == 'PT') and !empty($buildID))
|
||||
{
|
||||
$type = $notify == 'ET' ? 'execution' : 'project';
|
||||
$type = $notify == 'ET' ? 'execution' : 'project';
|
||||
$members = $this->dao->select('t2.account')->from(TABLE_BUILD)->alias('t1')
|
||||
->leftJoin(TABLE_TEAM)->alias('t2')->on('t1.' . $type .'=t2.root')
|
||||
->leftJoin(TABLE_TEAM)->alias('t2')->on('t1.' . $type . '=t2.root')
|
||||
->where('t2.type')->eq($type)
|
||||
->fetchPairs();
|
||||
|
||||
@@ -304,13 +305,13 @@ class releaseModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($managers))
|
||||
if(!empty($managerFields))
|
||||
{
|
||||
$managers = trim($managers, ',');
|
||||
$managerUsers = $this->dao->select($managers)->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
|
||||
$managerFields = trim($managerFields, ',');
|
||||
$managerUsers = $this->dao->select($managerFields)->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch();
|
||||
foreach($managerUsers as $account)
|
||||
{
|
||||
if(!isset($notifyPersons[$account])) $notifyPersons += array($account => $account);
|
||||
if(!isset($notifyPersons[$account])) $notifyPersons[$account] = $account;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
#sidebar>.sidebar-toggle>.icon {right: -2px; left: auto;}
|
||||
.main-row {width: 99%;}
|
||||
.btn-toolbar > .last-sync-time {display: inline-block; float: left; margin-right: 10px;}
|
||||
.dropdown-menu>li.selected>a:after {content: '';}
|
||||
.dropdown-menu > li.selected > a:after {content: '';}
|
||||
|
||||
@@ -614,6 +614,7 @@ class repoModel extends model
|
||||
{
|
||||
$repo = $this->getRepoByID($repoID);
|
||||
if(empty($repo)) return array();
|
||||
|
||||
return $this->dao->select('id,name')->from(TABLE_PRODUCT)
|
||||
->where('id')->in($repo->product)
|
||||
->andWhere('deleted')->eq(0)
|
||||
@@ -1787,10 +1788,11 @@ class repoModel extends model
|
||||
*/
|
||||
public function processGitlab($repo)
|
||||
{
|
||||
$gitlab = $this->loadModel('gitlab')->getByID($repo->client); // The $repo->client is gitlabID
|
||||
$gitlab = $this->loadModel('gitlab')->getByID($repo->client); // The $repo->client is gitlabID.
|
||||
if(!$gitlab) return $repo;
|
||||
|
||||
$repo->gitlab = $gitlab->id;
|
||||
$repo->project = $repo->path; // The projectID in gitlab
|
||||
$repo->project = $repo->path; // The projectID in gitlab.
|
||||
$repo->path = sprintf($this->config->repo->gitlab->apiPath, $gitlab->url, $repo->path);
|
||||
$repo->client = $gitlab->url;
|
||||
$repo->password = $gitlab->token;
|
||||
|
||||
@@ -13,7 +13,7 @@ $(document).ready(function()
|
||||
}
|
||||
else
|
||||
{
|
||||
className = response.type + 'count';
|
||||
className = response.type + 'count';
|
||||
$typeCount = $('#resultBox .' + className)
|
||||
if($typeCount.length == 0)
|
||||
{
|
||||
|
||||
@@ -30,7 +30,7 @@ class searchModel extends model
|
||||
if($module == 'projectStory') $flowModule = 'story';
|
||||
if($module == 'projectBug') $flowModule = 'bug';
|
||||
|
||||
$fields = $this->loadModel('workflowfield')->getList($flowModule);
|
||||
$fields = $this->loadModel('workflowfield')->getList($flowModule);
|
||||
$maxCount = $this->config->maxCount;
|
||||
$this->config->maxCount = 0;
|
||||
|
||||
@@ -947,6 +947,8 @@ class searchModel extends model
|
||||
{
|
||||
$words = explode(' ', trim($keywords, ' '));
|
||||
$markedWords = array();
|
||||
$leftMark = '|0000';
|
||||
$rightMark = '0000|';
|
||||
|
||||
foreach($words as $key => $word)
|
||||
{
|
||||
@@ -962,10 +964,11 @@ class searchModel extends model
|
||||
{
|
||||
$words[$key] = strlen($word) == 5 ? str_replace('_', '', $word) : $word;
|
||||
}
|
||||
$markedWords[] = "<span class='text-danger'>" . $this->decode($word) . "</span > ";
|
||||
$markedWords[] = $leftMark . $this->decode($word) . $rightMark;
|
||||
}
|
||||
|
||||
$content = str_replace($words, $markedWords, $content . ' ');
|
||||
$content = str_replace(array($leftMark, $rightMark), array("<span class='text-danger'>", "</span > "), $content);
|
||||
$content = str_replace("</span > <span class='text-danger'>", '', $content);
|
||||
$content = str_replace("</span >", '</span>', $content);
|
||||
|
||||
|
||||
+36
-35
@@ -792,36 +792,38 @@ class storyModel extends model
|
||||
$_POST['reviewer'] = array_filter($_POST['reviewer']);
|
||||
$oldReviewer = $this->getReviewerPairs($storyID, $oldStory->version);
|
||||
$oldStory->reviewers = implode(',', array_keys($oldReviewer));
|
||||
|
||||
/* Update story reviewer. */
|
||||
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->andWhere('reviewer')->notin(implode(',', $_POST['reviewer']))->exec();
|
||||
foreach($_POST['reviewer'] as $reviewer)
|
||||
if(array_diff($_POST['reviewer'], array_keys($oldReviewer)) or array_diff(array_keys($oldReviewer), $_POST['reviewer']))
|
||||
{
|
||||
if(in_array($reviewer, array_keys($oldReviewer))) continue;
|
||||
|
||||
$reviewData = new stdclass();
|
||||
$reviewData->story = $storyID;
|
||||
$reviewData->version = $oldStory->version;
|
||||
$reviewData->reviewer = $reviewer;
|
||||
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
|
||||
}
|
||||
|
||||
/* Update the story status by review rules. */
|
||||
$reviewerList = $this->getReviewerPairs($storyID, $oldStory->version);
|
||||
$story->reviewers = implode(',', array_keys($reviewerList));
|
||||
$reviewedBy = explode(',', trim($oldStory->reviewedBy, ','));
|
||||
if(!array_diff(array_keys($reviewerList), $reviewedBy))
|
||||
{
|
||||
$status = $this->setStatusByReviewRules($reviewerList);
|
||||
$story->status = $status ? $status : $oldStory->status;
|
||||
if($story->status == 'closed')
|
||||
/* Update story reviewer. */
|
||||
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->andWhere('reviewer')->notin(implode(',', $_POST['reviewer']))->exec();
|
||||
foreach($_POST['reviewer'] as $reviewer)
|
||||
{
|
||||
$story->closedBy = $this->app->user->account;
|
||||
$story->closedDate = $now;
|
||||
$story->assignedTo = 'closed';
|
||||
$story->assignedDate = $now;
|
||||
$story->stage = 'closed';
|
||||
if($this->post->closedReason == 'done') $story->stage = 'released';
|
||||
if(in_array($reviewer, array_keys($oldReviewer))) continue;
|
||||
|
||||
$reviewData = new stdclass();
|
||||
$reviewData->story = $storyID;
|
||||
$reviewData->version = $oldStory->version;
|
||||
$reviewData->reviewer = $reviewer;
|
||||
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
|
||||
}
|
||||
|
||||
/* Update the story status by review rules. */
|
||||
$reviewerList = $this->getReviewerPairs($storyID, $oldStory->version);
|
||||
$story->reviewers = implode(',', array_keys($reviewerList));
|
||||
$reviewedBy = explode(',', trim($oldStory->reviewedBy, ','));
|
||||
if(!array_diff(array_keys($reviewerList), $reviewedBy))
|
||||
{
|
||||
$status = $this->setStatusByReviewRules($reviewerList);
|
||||
$story->status = $status ? $status : $oldStory->status;
|
||||
if($story->status == 'closed')
|
||||
{
|
||||
$story->closedBy = $this->app->user->account;
|
||||
$story->closedDate = $now;
|
||||
$story->assignedTo = 'closed';
|
||||
$story->assignedDate = $now;
|
||||
$story->stage = 'closed';
|
||||
if($this->post->closedReason == 'done') $story->stage = 'released';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3579,7 +3581,7 @@ class storyModel extends model
|
||||
$canBatchChangeModule = common::hasPriv('story', 'batchChangeModule');
|
||||
$canBatchChangePlan = common::hasPriv('story', 'batchChangePlan');
|
||||
$canBatchAssignTo = common::hasPriv('story', 'batchAssignTo');
|
||||
$canBatchUnlinkStory = common::hasPriv('projectstory', 'unlinkStory');
|
||||
$canBatchUnlinkStory = common::hasPriv('projectstory', 'batchUnlinkStory');
|
||||
|
||||
$canBatchAction = ($canBatchEdit or $canBatchClose or $canBatchReview or $canBatchChangeStage or $canBatchChangeBranch or $canBatchChangeModule or $canBatchChangePlan or $canBatchAssignTo or $canBatchUnlinkStory);
|
||||
|
||||
@@ -3797,11 +3799,11 @@ class storyModel extends model
|
||||
break;
|
||||
}
|
||||
|
||||
common::printIcon('story', 'change', $vars . "&from=$story->from", $story, 'list', 'alter', '', '', false, "data-group=$story->from");
|
||||
common::printIcon('story', 'review', $vars . "&from=$story->from", $story, 'list', 'search', '', '', false, "data-group=$story->from");
|
||||
common::printIcon('story', 'change', $vars . "&from=$story->from", $story, 'list', 'alter', '', '', false, "data-group=$story->from");
|
||||
common::printIcon('story', 'review', $vars . "&from=$story->from", $story, 'list', 'search', '', '', false, "data-group=$story->from");
|
||||
if($this->app->openApp != 'project') common::printIcon('story', 'recall', $vars, $story, 'list', 'back', 'hiddenwin', '', '', '', $this->lang->story->recall);
|
||||
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
|
||||
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
|
||||
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
|
||||
if($story->type != 'requirement') common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=¶m=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
|
||||
common::printIcon('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&storyID=$story->id", $story, 'list', 'split', '', '', '', '', $this->lang->story->subdivide);
|
||||
if($this->app->rawModule == 'projectstory') common::printIcon('projectstory', 'unlinkStory', "projectID={$this->session->project}&storyID=$story->id", '', 'list', 'unlink', 'hiddenwin');
|
||||
@@ -4514,7 +4516,7 @@ class storyModel extends model
|
||||
$comment = isset($_POST['comment']) ? $this->post->comment : '';
|
||||
$actionID = !empty($result) ? $this->loadModel('action')->create('story', $story->id, 'Reviewed', $comment, ucfirst($result) . $reasonParam) : '';
|
||||
|
||||
if(ucfirst($result) != 'Revert')
|
||||
if(strtolower($result) != 'revert')
|
||||
{
|
||||
if($story->status == 'closed') $this->action->create('story', $story->id, 'ReviewClosed');
|
||||
if($story->status == 'active') $this->action->create('story', $story->id, 'PassReviewed');
|
||||
@@ -4523,5 +4525,4 @@ class storyModel extends model
|
||||
|
||||
return $actionID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ $lang->task->lblTestStory = 'Story Tested';
|
||||
$lang->task->recordEstimateAction = 'Record Estimate';
|
||||
|
||||
$lang->task->ditto = 'Ditto';
|
||||
$lang->task->dittoNotice = "This Task is not linked to the %s as the previous one is!";
|
||||
$lang->task->dittoNotice = "This Task is not linked to %s like the last one!";
|
||||
$lang->task->selectTestStory = 'Select Story Testd';
|
||||
$lang->task->selectAllUser = 'All Users';
|
||||
$lang->task->noStory = 'No Story Linked';
|
||||
@@ -175,8 +175,8 @@ $lang->task->reasonList['done'] = 'Done';
|
||||
$lang->task->reasonList['cancel'] = 'Cancelled';
|
||||
|
||||
$lang->task->afterChoices['continueAdding'] = ' Continue Adding Tasks';
|
||||
$lang->task->afterChoices['toTaskList'] = 'Go to Task List Page';
|
||||
$lang->task->afterChoices['toStoryList'] = 'Go to Story List Page';
|
||||
$lang->task->afterChoices['toTaskList'] = 'Go to Task List';
|
||||
$lang->task->afterChoices['toStoryList'] = 'Go to Story List';
|
||||
|
||||
$lang->task->legendBasic = 'Basic Info';
|
||||
$lang->task->legendEffort = 'Effort';
|
||||
@@ -202,7 +202,7 @@ $lang->task->deniedNotice = 'Only the %s can %s the task.';
|
||||
$lang->task->noTask = 'No tasks yet. ';
|
||||
$lang->task->createDenied = 'Create Task is denied in this project';
|
||||
$lang->task->cannotDeleteParent = 'Cannot delete parent task';
|
||||
$lang->task->addChildTask = 'Because the task has already consumed consumption, to ensure data consistency, we will help you create a subtask with the same name to record the consumption.';
|
||||
$lang->task->addChildTask = 'Because the task has cost hours, ZenTao will create a child task with the same name to record the cost housrs to ensure data consistency.';
|
||||
|
||||
$lang->task->error = new stdclass();
|
||||
$lang->task->error->totalNumber = '"Total Cost" must be numbers.';
|
||||
|
||||
@@ -2143,7 +2143,7 @@ class taskModel extends model
|
||||
}
|
||||
|
||||
$projectList = array();
|
||||
foreach($tasks as $task) $projectList[] = $task->project;
|
||||
foreach($tasks as $task) $projectList[$task->project] = $task->project;
|
||||
$projectPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('id')->in($projectList)->fetchPairs('id');
|
||||
foreach($tasks as $task) $task->projectName = zget($projectPairs, $task->project);
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
<?php endif;?>
|
||||
<tr>
|
||||
<th><?php echo $lang->testcase->type;?></th>
|
||||
<?php unset($lang->testcase->typeList['unit']);?>
|
||||
<?php if($case->type != 'unit') unset($lang->testcase->typeList['unit']);?>
|
||||
<td><?php echo html::select('type', (array)$lang->testcase->typeList, $case->type, "class='form-control chosen'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -48,12 +48,12 @@ $lang->testtask->allTasks = 'All Requests';
|
||||
$lang->testtask->collapseAll = 'Collapse';
|
||||
$lang->testtask->expandAll = 'Expand';
|
||||
|
||||
$lang->testtask->viewAction = "View Testtask";
|
||||
$lang->testtask->viewAction = "View Request";
|
||||
$lang->testtask->casesAction = 'View Case';
|
||||
$lang->testtask->activateAction = "Activate Testtask";
|
||||
$lang->testtask->blockAction = "Block Testtask";
|
||||
$lang->testtask->closeAction = "Close Testtask";
|
||||
$lang->testtask->startAction = "Start Testtask";
|
||||
$lang->testtask->activateAction = "Activate Request";
|
||||
$lang->testtask->blockAction = "Block Request";
|
||||
$lang->testtask->closeAction = "Close Request";
|
||||
$lang->testtask->startAction = "Start Request";
|
||||
$lang->testtask->resultsAction = "Case Result";
|
||||
$lang->testtask->reportAction = 'Report';
|
||||
|
||||
@@ -203,7 +203,7 @@ $lang->testtask->unitTag['lastWeek'] = 'Last week';
|
||||
$lang->testtask->unitTag['thisMonth'] = 'This month';
|
||||
$lang->testtask->unitTag['lastMonth'] = 'Last month';
|
||||
|
||||
$lang->testtask->typeList['integrate'] = 'Integrate';
|
||||
$lang->testtask->typeList['integrate'] = 'Integration';
|
||||
$lang->testtask->typeList['system'] = 'System';
|
||||
$lang->testtask->typeList['acceptance'] = 'Acceptance';
|
||||
$lang->testtask->typeList['performance'] = 'Performance';
|
||||
|
||||
@@ -4702,9 +4702,9 @@ class upgradeModel extends model
|
||||
$today = helper::today();
|
||||
foreach($projectTeams as $projectID => $projectMember)
|
||||
{
|
||||
unset($projectMember['']);
|
||||
$project = zget($projects, $projectID, '');
|
||||
$users = implode(',', $projectMember);
|
||||
$projectMember = array_filter($projectMember);
|
||||
$project = zget($projects, $projectID, '');
|
||||
$users = implode(',', $projectMember);
|
||||
|
||||
$this->dao->update(TABLE_DOCLIB)
|
||||
->set('users')->eq($users)
|
||||
@@ -5251,7 +5251,7 @@ class upgradeModel extends model
|
||||
if(empty($doc->content)) continue;
|
||||
|
||||
$this->dao->update(TABLE_DOC)
|
||||
->set('tempContent')->eq($doc->content)
|
||||
->set('draft')->eq($doc->content)
|
||||
->where('id')->eq($docID)
|
||||
->exec();
|
||||
}
|
||||
|
||||
@@ -17,3 +17,6 @@ $config->user->contactField = 'mobile,phone,qq,dingding,weixin,skype,whatsapp,sl
|
||||
$config->user->failTimes = 6;
|
||||
$config->user->lockMinutes = 10;
|
||||
$config->user->batchCreate = 10;
|
||||
|
||||
/* user detail fields for API against JIHU GitLab. */
|
||||
$config->user->detailFields = 'id,account,realname,avatar';
|
||||
|
||||
+12
-12
@@ -11,8 +11,8 @@
|
||||
*/
|
||||
$lang->user->common = 'User';
|
||||
$lang->user->id = 'ID';
|
||||
$lang->user->inside = 'Inside Members';
|
||||
$lang->user->outside = 'Outside Members';
|
||||
$lang->user->inside = 'Internal';
|
||||
$lang->user->outside = 'Outsiders';
|
||||
$lang->user->company = 'Company';
|
||||
$lang->user->dept = 'Department';
|
||||
$lang->user->account = 'Account';
|
||||
@@ -54,8 +54,8 @@ $lang->user->score = 'Score';
|
||||
$lang->user->name = 'Name';
|
||||
$lang->user->type = 'User Type';
|
||||
$lang->user->cropAvatar = 'Crop Avatar';
|
||||
$lang->user->cropAvatarTip = 'Drag and drop the box to select the image clipping range.';
|
||||
$lang->user->cropImageTip = 'The image used is too small, the recommended image size is at least 48x48, the current image size is %s';
|
||||
$lang->user->cropAvatarTip = 'Drag and drop the box to crop the image.';
|
||||
$lang->user->cropImageTip = 'The image is too small. The recommended image size is at least 48x48. The current image size is %s';
|
||||
$lang->user->captcha = 'Captcha';
|
||||
|
||||
$lang->user->legendBasic = 'Basic Information';
|
||||
@@ -89,7 +89,7 @@ $lang->user->else = 'Else';
|
||||
$lang->user->saveTemplate = 'Save as Template';
|
||||
$lang->user->setPublic = 'Set as Public Template';
|
||||
$lang->user->deleteTemplate = 'Delete Template';
|
||||
$lang->user->setTemplateTitle = 'Please enter the title of template.';
|
||||
$lang->user->setTemplateTitle = 'Please enter the title of the template.';
|
||||
$lang->user->applyTemplate = 'Templates';
|
||||
$lang->user->confirmDeleteTemplate = 'Do you want to delete this template?';
|
||||
$lang->user->setPublicTemplate = 'Set as Public Template';
|
||||
@@ -128,7 +128,7 @@ $lang->user->loginFailed = "Login failed. Please check your account and passwor
|
||||
$lang->user->lockWarning = "You can try %s times.";
|
||||
$lang->user->loginLocked = "Please contact the administrator to unlock your account or try %s minutes later.";
|
||||
$lang->user->weakPassword = "Your password does not meet the requirements.";
|
||||
$lang->user->errorWeak = "Passwords cannot use [%s] these commonly used weak passwords.";
|
||||
$lang->user->errorWeak = "Passwords cannot use [%s] weak passwords.";
|
||||
$lang->user->errorCaptcha = "Captcha Error";
|
||||
|
||||
$lang->user->roleList[''] = '';
|
||||
@@ -199,10 +199,10 @@ $lang->user->error->account = "ID %s,account must be >= 3 letters, unde
|
||||
$lang->user->error->accountDupl = "ID %s,account is used.";
|
||||
$lang->user->error->realname = "ID %s,must be real name";
|
||||
$lang->user->error->password = "ID %s,password must be >= 6 characters.";
|
||||
$lang->user->error->mail = "ID %s,please enter valid Email address";
|
||||
$lang->user->error->mail = "ID %s,enter valid Email address";
|
||||
$lang->user->error->reserved = "ID %s,account is reserved.";
|
||||
$lang->user->error->weakPassword = "ID %s,the password strength is less than the system setting.";
|
||||
$lang->user->error->dangerPassword = "ID %s,Passwords cannot be used with [%s] these commonly used if-passwords.";
|
||||
$lang->user->error->dangerPassword = "ID %s,passwords cannot be used with [%s] these commonly used if-passwords.";
|
||||
|
||||
$lang->user->error->verifyPassword = "Verification failed. Please enter your Login Password.";
|
||||
$lang->user->error->originalPassword = "Old password is incorrect.";
|
||||
@@ -247,13 +247,13 @@ $lang->user->noticeResetFile = "<h5>Contact the Administrator to reset your pas
|
||||
<li>If the file exists, remove it and create it again.</li>
|
||||
</ol>";
|
||||
$lang->user->notice4Safe = "Warning: Weak password of one click package detected";
|
||||
$lang->user->process4DIR = "It is detected that you may be using the one click installation package environment. Other sites in the environment are still using simple passwords. For security reasons, if you do not use other sites, please handle them in time. Delete or rename the %s directory. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
|
||||
$lang->user->process4DB = "It is detected that you may be using the one click installation package environment. Other sites in the environment are still using simple passwords. For security reasons, if you do not use other sites, please handle them in time. Please login database and modify password field of zt_user table of %s database. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
|
||||
$lang->user->process4DIR = "It is detected that you might use the one-click installation package environment. Other sites in the environment are still using weak passwords. For security reasons, if you do not use other sites, please handle them in time. Delete or rename the %s directory. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
|
||||
$lang->user->process4DB = "It is detected that you might use the one-click installation package environment. Other sites in the environment are still using simple passwords. For security reasons, if you do not use other sites, please handle them in time. Please login database and modify password field of zt_user table of %s database. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
|
||||
$lang->user->mkdirWin = <<<EOT
|
||||
<html><head><meta charset='utf-8'></head>
|
||||
<body><table align='center' style='width:700px; margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td style='padding:8px'>
|
||||
<div style='margin-bottom:8px;'>不能创建临时目录,请确认目录<strong style='color:#ed980f'>%s</strong>是否存在并有操作权限。</div>
|
||||
<div>Can't create tmp directory, make sure the directory <strong style='color:#ed980f'>%s</strong> exists and has permission to operate.</div>
|
||||
<div>A tmp directory cannot be created. Make sure the directory <strong style='color:#ed980f'>%s</strong> exists and you have the right permission.</div>
|
||||
</td></tr></table></body></html>
|
||||
EOT;
|
||||
$lang->user->mkdirLinux = <<<EOT
|
||||
@@ -261,7 +261,7 @@ $lang->user->mkdirLinux = <<<EOT
|
||||
<body><table align='center' style='width:700px; margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td style='padding:8px'>
|
||||
<div style='margin-bottom:8px;'>不能创建临时目录,请确认目录<strong style='color:#ed980f'>%s</strong>是否存在并有操作权限。</div>
|
||||
<div style='margin-bottom:8px;'>命令为:<strong style='color:#ed980f'>chmod o=rwx -R %s</strong>。</div>
|
||||
<div>Can't create tmp directory, make sure the directory <strong style='color:#ed980f'>%s</strong> exists and has permission to operate.</div>
|
||||
<div>A tmp directory cannot be created. Make sure the directory <strong style='color:#ed980f'>%s</strong> exists and you have the right permission.</div>
|
||||
<div style='margin-bottom:8px;'>Commond: <strong style='color:#ed980f'>chmod o=rwx -R %s</strong>.</div>
|
||||
</td></tr></table></body></html>
|
||||
EOT;
|
||||
|
||||
@@ -2552,4 +2552,34 @@ class userModel extends model
|
||||
|
||||
return $personalData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get users details for API.
|
||||
*
|
||||
* @param array $userList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getUserDetailsForAPI($userList)
|
||||
{
|
||||
$users = $this->dao->select($this->config->user->detailFields)->from(TABLE_USER)->where("account")->in($userList)->fetchAll();
|
||||
|
||||
$userDetails = array();
|
||||
foreach($users as $index => $user)
|
||||
{
|
||||
$user->url = helper::createLink('user', 'profile', "userID={$user->id}");
|
||||
|
||||
if($user->avatar != "")
|
||||
{
|
||||
$user->avatar = common::getSysURL() . $user->avatar;
|
||||
}
|
||||
else
|
||||
{
|
||||
$user->avatar = "https://www.gravatar.com/avatar/" . md5($user->account) . "?d=identicon&s=80";
|
||||
}
|
||||
|
||||
$userDetails[$user->account] = $user;
|
||||
}
|
||||
return $userDetails;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,6 +588,14 @@ class webhookModel extends model
|
||||
$toList = $this->loadModel('message')->getToList($object, $action->objectType);
|
||||
if(!empty($object->mailto)) $toList .= ',' . $object->mailto;
|
||||
if(empty($toList)) return false;
|
||||
|
||||
/* Remove duplicate people. */
|
||||
if($action->objectType == 'release')
|
||||
{
|
||||
$toList = array_unique(explode(',', $toList));
|
||||
$toList = implode(',', $toList);
|
||||
}
|
||||
|
||||
$toList = str_replace(",{$this->app->user->account},", '', ",$toList,");
|
||||
|
||||
$openIdList = $this->getBoundUsers($webhookID, $toList);
|
||||
|
||||
+3
-3
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -83,7 +83,7 @@
|
||||
<glyph unicode="" glyph-name="color" d="M512-227.536c-282.759 0-511.98 229.221-511.98 511.98s229.221 511.98 511.98 511.98c282.759 0 508.252-204.169 511.98-447.983 1.318-86.219-30.006-212.303-192.409-275.415-69.232-26.904-186.27-1.378-234.428-25.237-64.809-32.11-47.245-111.882-22.099-133.338 43.832-37.4 17.103-141.988-63.044-141.988zM749.952 342.969c0-53.017 42.979-95.996 95.996-95.996s95.996 42.979 95.996 95.996c0 53.017-42.979 95.996-95.996 95.996s-95.996-42.979-95.996-95.996zM246.317 300.233c23.242 47.652 3.452 105.122-44.198 128.363s-105.122 3.452-128.363-44.198c-23.242-47.652-3.452-105.122 44.198-128.363s105.122-3.452 128.363 44.198zM380.748 471.568c51.658 11.927 83.868 63.472 71.941 115.13s-63.472 83.868-115.13 71.941c-51.658-11.927-83.868-63.472-71.941-115.13s63.472-83.868 115.13-71.941zM611.036 497.827c41.203-33.365 101.651-27.011 135.015 14.19s27.011 101.651-14.19 135.015c-41.203 33.365-101.651 27.011-135.015-14.19s-27.011-101.651 14.19-135.015z" />
|
||||
<glyph unicode="" glyph-name="paper-clip" d="M453.734-121.983l429.193 429.193c82.479 82.479 82.479 216.090 0 298.57s-216.090 82.479-298.57 0l-466.514-466.514c-51.503-51.503-51.503-135.102 0-186.605s135.102-51.503 186.605 0l391.873 391.873c20.526 20.526 20.526 54.116 0 74.642s-54.116 20.526-74.642 0l-354.55-354.55-55.981 55.981 354.55 354.55c51.503 51.503 135.102 51.503 186.605 0s51.503-135.102 0-186.605l-391.873-391.873c-82.479-82.479-216.090-82.479-298.57 0s-82.479 216.090 0 298.57l466.514 466.514c113.456 113.456 297.076 113.456 410.533 0s113.456-297.076 0-410.533l-429.193-429.193-55.981 55.981z" />
|
||||
<glyph unicode="" glyph-name="arrow-right" d="M849.601 267.375c4.266 8.534 4.266 21.332 0 34.134-4.266 4.266-4.266 8.534-8.534 12.798l-298.667 298.667c-17.069 17.069-42.666 17.069-59.732 0s-17.069-42.666 0-59.732l226.133-226.133h-494.934c-25.602 0-42.666-17.069-42.666-42.666s17.069-42.666 42.666-42.666h494.934l-226.133-226.133c-17.069-17.069-17.069-42.666 0-59.732 8.534-8.534 21.332-12.798 29.867-12.798s21.332 4.266 29.867 12.798l298.667 298.667c4.266 4.266 8.534 8.534 8.534 12.798z" />
|
||||
<glyph unicode="" glyph-name="back" d="M160.311-170.157c-0.23-0.002-0.461-0.003-0.692-0.003-37.104 0-67.175 30.073-67.175 67.177 0 37.097 30.073 67.175 67.175 67.175 2.813 0 5.585-0.173 8.307-0.508h462.609c111.3 0 201.527 90.226 201.527 201.527s-90.226 201.527-201.527 201.527h-470.224v134.343h469.777c185.319 0 335.556-150.433 335.556-336 0-185.564-150.234-336-335.556-336h-469.777v0.763zM82.125 484.904l293.273 251.415c5.634 4.828 14.116 4.18 18.944-1.456 2.786-3.25 3.858-7.628 2.884-11.799l-67.463-289.161 67.463-289.161c1.689-7.225-2.807-14.452-10.030-16.137-4.169-0.971-8.549 0.1-11.799 2.884l-293.273 251.415c-28.169 24.148-31.426 66.553-7.278 94.722 2.235 2.61 4.67 5.044 7.278 7.278h0.002z" />
|
||||
<glyph unicode="" glyph-name="back" d="M300.686 720.36c12.534-13.805 11.502-35.154-2.298-47.685l-121.189-110.039h436.075c187.398 0 337.58-160.388 337.58-354.461s-150.184-354.461-337.58-354.461h-371.339c-18.642 0-33.759 15.114-33.759 33.759s15.114 33.759 33.759 33.759h371.339c146.814 0 270.066 126.778 270.066 286.944s-123.25 286.944-270.066 286.944h-436.075l121.189-110.042c13.805-12.533 14.832-33.882 2.298-47.682-12.534-13.805-33.882-14.834-47.685-2.298l-157.188 142.725c-30.222 26.91-30.222 75.201 0.001 102.113l157.187 142.727c13.805 12.534 35.154 11.502 47.685-2.298z" />
|
||||
<glyph unicode="" glyph-name="chat, message" d="M512 1.686l-224.594-174.669c-22.332-17.345-54.497-13.302-71.842 9.031-6.973 8.979-10.76 20.022-10.764 31.391v134.247h-102.4c-56.554 0-102.4 45.846-102.4 102.4 0 0 0 0 0 0v546.15c0 56.554 45.846 102.4 102.4 102.4h819.2c56.554 0 102.4-45.846 102.4-102.4v-546.15c0-56.554-45.846-102.4-102.4-102.4h-409.601zM273.050-97.626l197.010 153.209c12.003 9.309 26.751 14.404 41.94 14.404h409.6c18.822 0.027 34.074 15.279 34.101 34.101v546.15c0 18.841-15.26 34.123-34.101 34.149h-819.2c-18.86 0-34.149-15.289-34.149-34.149 0 0 0 0 0 0v-546.15c0-18.815 15.286-34.101 34.149-34.101h102.4c37.727 0 68.25-30.573 68.25-68.3v-99.314zM716.8 325.987v0c-28.277 0-51.2 22.923-51.2 51.2s22.923 51.2 51.2 51.2c0 0 0 0 0 0v0c28.277 0 51.2-22.923 51.2-51.2s-22.923-51.2-51.2-51.2v0zM512 325.987v0c-28.277 0-51.2 22.923-51.2 51.2s22.923 51.2 51.2 51.2c0 0 0 0 0 0v0c28.277 0 51.2-22.923 51.2-51.2s-22.923-51.2-51.2-51.2v0zM307.199 325.987v0c-28.277 0-51.2 22.923-51.2 51.2s22.923 51.2 51.2 51.2c0 0 0 0 0 0v0c28.277 0 51.2-22.923 51.2-51.2s-22.923-51.2-51.2-51.2v0z" />
|
||||
<glyph unicode="" glyph-name="person" d="M723.15 247.068c115.4 0 208.952-93.512 208.952-208.868v0-105.532c0-57.070-46.282-103.336-103.376-103.336v0h-633.452c-57.094 0-103.376 46.264-103.376 103.336v0 105.532c0 115.353 93.55 208.868 208.952 208.868v0zM723.15 181.108h-422.302c-78.958 0-142.967-63.982-142.967-142.909v0-105.532c0-20.643 16.741-37.376 37.392-37.376v0h633.452c20.65 0 37.392 16.734 37.392 37.376v0 105.532c0 78.926-64.008 142.909-142.967 142.909v0zM512 739.556c115.4 0 208.952-93.512 208.952-208.868s-93.55-208.868-208.952-208.868c-115.4 0-208.952 93.512-208.952 208.868s93.55 208.868 208.952 208.868zM512 673.597c-78.958 0-142.967-63.982-142.967-142.909s64.008-142.909 142.967-142.909c78.959 0 142.967 63.982 142.967 142.909s-64.008 142.909-142.967 142.909z" />
|
||||
<glyph unicode="" glyph-name="folder-account" d="M85.333-56.895c0 15.709-12.736 28.444-28.446 28.444h28.446v-28.444zM85.333-28.449v682.671h288.302l80.842-113.778h484.189v-42.997h85.333v71.441c0 31.419-25.47 56.889-56.889 56.889h-468.584l-63.833 89.839c-10.67 15.018-27.952 23.939-46.374 23.939h-331.43c-31.419 0-56.889-25.47-56.889-56.889v-739.561c0-31.419 25.47-56.889 56.889-56.889l355.669 0.006-0.001 85.333-327.223-0.004zM85.333 654.222v28.444c0-15.709-12.736-28.444-28.444-28.444h28.444zM388.319 654.222c-9.211 0-17.852 4.46-23.188 11.969l8.504-11.969h14.683zM967.111 540.444c-15.709 0-28.444 12.736-28.444 28.444v-28.444h28.444zM938.667 568.888c0-15.709 12.736-28.444 28.444-28.444h-28.444v28.444zM938.667 497.447h85.333v71.441c0 31.419-25.47 56.889-56.889 56.889h-468.584l-63.833 89.839c-10.67 15.018-27.952 23.939-46.374 23.939h-331.43c-31.419 0-56.889-25.47-56.889-56.889v-739.561c0-31.419 25.47-56.889 56.889-56.889l355.669 0.006-0.001 85.333-327.223-0.004v682.671h288.302l80.842-113.778h484.189v-42.997zM388.319 654.222c-9.211 0-17.852 4.46-23.188 11.969l8.504-11.969h14.683zM56.889 654.222c15.709 0 28.444 12.736 28.444 28.444v-28.444h-28.444zM56.888-28.449c15.711 0 28.446-12.736 28.446-28.444v28.444h-28.446zM1023.318-75.202c0.448-2.122 0.682-4.322 0.682-6.577 0-17.673-14.456-32-32.288-32-0.022 0-0.043 0-0.066 0-0.011 0-0.023 0-0.034 0-196.601 0-345.434 0-446.5 0-0.098 0-0.196 0.001-0.291 0.004-0.177-0.003-0.354-0.004-0.532-0.004-17.832 0-32.288 14.327-32.288 32 0 1.13 0.059 2.246 0.174 3.344-0.016 0.392 0.010 0.823 0.078 1.298 13.262 91.708 75.569 167.727 159.737 201.118-35.96 28.129-59.042 71.712-59.042 120.64 0 84.831 69.388 153.6 154.981 153.6s154.981-68.769 154.981-153.6c0-48.927-23.082-92.511-59.042-120.64 83.576-33.156 145.597-108.341 159.45-199.183zM981.333 455.111c23.564 0 42.667 19.102 42.667 42.667s-19.102 42.667-42.667 42.667c-23.564 0-42.667-19.102-42.667-42.667s19.102-42.667 42.667-42.667zM412.444-113.778c23.564 0 42.667 19.102 42.667 42.667s-19.102 42.667-42.667 42.667c-23.564 0-42.667-19.102-42.667-42.667s19.102-42.667 42.667-42.667z" />
|
||||
|
||||
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user