Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* 禅道API的issue资源类
|
||||
* 版本V1
|
||||
*
|
||||
* The issue entry point of zentaopms
|
||||
* Version 1
|
||||
*/
|
||||
class issueEntry extends Entry
|
||||
{
|
||||
public function get($issueID)
|
||||
{
|
||||
$control = $this->loadController('issue', 'view');
|
||||
$control->view($issueID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->status) and $data->status == 'success') $this->send(200, $this->format($data->data->issue, 'createdDate:time,editedDate:time,assignedDate:time'));
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$this->sendError(400, 'error');
|
||||
}
|
||||
|
||||
public function put($issueID)
|
||||
{
|
||||
$oldIssue = $this->loadModel('issue')->getByID($issueID);
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'type,title,severity,pri,assignedTo,deadline,desc';
|
||||
$this->batchSetPost($fields, $oldIssue);
|
||||
|
||||
$control = $this->loadController('issue', 'edit');
|
||||
$control->edit($issueID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(!$data or (isset($data->message) and $data->message == '404 Not found')) return $this->send404();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$issue = $this->issue->getByID($issueID);
|
||||
$this->send(200, $this->format($issue, 'createdDate:time,editedDate:time,assignedDate:time'));
|
||||
}
|
||||
|
||||
public function delete($issueID)
|
||||
{
|
||||
$control = $this->loadController('issue', 'delete');
|
||||
$control->delete($issueID, 'true');
|
||||
|
||||
$this->getData();
|
||||
$this->sendSuccess(200, 'success');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 禅道API的issues资源类
|
||||
* 版本V1
|
||||
*
|
||||
* The issues entry point of zentaopms
|
||||
* Version 1
|
||||
*/
|
||||
class issuesEntry extends entry
|
||||
{
|
||||
public function get()
|
||||
{
|
||||
$control = $this->loadController('my', 'issue');
|
||||
$control->issue($this->param('type', 'assignedTo'), $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1));
|
||||
$data = $this->getData();
|
||||
|
||||
if(!isset($data->status)) return $this->sendError(400, 'error');
|
||||
if(isset($data->status) and $data->status == 'fail') return $this->sendError(400, $data->message);
|
||||
|
||||
$pager = $data->data->pager;
|
||||
$result = array();
|
||||
foreach($data->data->issues as $issue)
|
||||
{
|
||||
$result[] = $this->format($issue, 'createdDate:time,editedDate:time,assignedDate:time');
|
||||
}
|
||||
return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'issues' => $result));
|
||||
}
|
||||
|
||||
public function post($projectID = 0)
|
||||
{
|
||||
if((int) $projectID <= 0) $this->sendError(400, 'The id of project is wrong.');
|
||||
|
||||
$fields = 'type,title,severity,pri,assignedTo,deadline,desc';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
$control = $this->loadController('issue', 'create');
|
||||
$this->requireFields('type,title,severity');
|
||||
|
||||
$control->create($projectID);
|
||||
|
||||
$data = $this->getData();
|
||||
if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message);
|
||||
if(isset($data->result) and!isset($data->id)) return $this->sendError(400, $data->message);
|
||||
|
||||
$issue = $this->loadModel('issue')->getByID($data->id);
|
||||
|
||||
$this->send(201, $this->format($issue, 'createdDate:time,editedDate:time,assignedDate:time'));
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -222,7 +222,8 @@ $filter->project->task->cookie['projectTaskOrder'] = 'reg::orderBy';
|
||||
$filter->project->task->cookie['windowWidth'] = 'int';
|
||||
$filter->project->export->cookie['checkedItem'] = 'reg::checked';
|
||||
|
||||
$filter->projectstory->story->cookie['storyModuleParam'] = 'int';
|
||||
$filter->projectstory->story->cookie['storyModuleParam'] = 'int';
|
||||
$filter->projectstory->story->cookie['pagerProductBrowse'] = 'int';
|
||||
|
||||
$filter->qa->default->cookie['lastProduct'] = 'int';
|
||||
$filter->qa->default->cookie['preBranch'] = 'int';
|
||||
|
||||
@@ -55,4 +55,8 @@ $routes['/projects/:project/risks'] = 'risks';
|
||||
$routes['/risks'] = 'risks';
|
||||
$routes['/risks/:id'] = 'risk';
|
||||
|
||||
$routes['/projects/:project/questions'] = 'issues';
|
||||
$routes['/questions'] = 'issues';
|
||||
$routes['/questions/:id'] = 'issue';
|
||||
|
||||
$config->routes = $routes;
|
||||
|
||||
@@ -897,7 +897,8 @@ class baseControl
|
||||
foreach($data as $key => $value)
|
||||
{
|
||||
if(!is_string($value)) continue;
|
||||
$data[$key] = urlencode($value);
|
||||
/* Retain ["] for json encode when value is jsoned string. */
|
||||
$data[$key] = str_replace('%22', '"', urlencode($value));
|
||||
}
|
||||
|
||||
print(urldecode(json_encode($data)));
|
||||
|
||||
@@ -211,6 +211,115 @@ class html extends baseHTML
|
||||
$value = str_replace("'", ''', $value);
|
||||
return "<input type='number' name='$name' {$id} value='$value' $attrib />\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string to a uni code
|
||||
*
|
||||
* @param string $string
|
||||
* @return int
|
||||
*/
|
||||
static public function stringToCode($string)
|
||||
{
|
||||
$stringLength = strlen($string);
|
||||
if($stringLength == 0) return 0;
|
||||
|
||||
$code = 0;
|
||||
for($i = 0; $i < $stringLength; ++$i)
|
||||
{
|
||||
$code += ($i + 1) * ord($string[$i]);
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create user avatar.
|
||||
*
|
||||
* @param string|object|array $user User object or user avatar address or user account
|
||||
* @param string|int $size Avatar size, can be a number or preset sizes: "xs", "sm", "", "lg", "xl", default is ""
|
||||
* @param string $className Avatar element class name, default is "avatar-circle"
|
||||
* @param string $attrib Extra attributes on avatar element
|
||||
* @param string $tag Avatar element tag name, default is "div"
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
static public function avatar($user, $size = '', $className = 'avatar-circle', $attrib = '', $tag = 'div')
|
||||
{
|
||||
if(is_string($user))
|
||||
{
|
||||
$userObj = new stdClass();
|
||||
if(strlen($user) > 1) $userObj->avatar = $user;
|
||||
else $userObj->account = $user;
|
||||
$user = $userObj;
|
||||
}
|
||||
else if(is_array($user))
|
||||
{
|
||||
$userObj = new stdClass();
|
||||
$userObj->avatar = $user['avatar'];
|
||||
$userObj->account = $user['account'];
|
||||
$user = $userObj;
|
||||
}
|
||||
|
||||
$hasImage = !empty($user->avatar);
|
||||
|
||||
$extraClassName = $hasImage ? ' has-img' : ' has-text';
|
||||
$style = '';
|
||||
|
||||
if($size)
|
||||
{
|
||||
if(is_numeric($size)) $style .= "width: $size" . "px; height: $size" . "px; line-height: $size" . 'px;';
|
||||
$extraClassName .= " avatar-$size";
|
||||
}
|
||||
|
||||
if(!$hasImage)
|
||||
{
|
||||
$colorHue = (html::stringToCode($user->account) * 43) % 360;
|
||||
$style .= "background: hsl($colorHue, 100%, 58%);";
|
||||
}
|
||||
|
||||
if(!empty($style)) $style = "style='$style'";
|
||||
|
||||
$html = "<$tag class='avatar$extraClassName $className' $attrib $style>";
|
||||
|
||||
if($hasImage) $html .= html::image($user->avatar);
|
||||
else $html .= '<span>' . strtoupper($user->account[0]) . '</span>';
|
||||
|
||||
$html .= "</$tag>";
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a small user avatar.
|
||||
*
|
||||
* @param string|object $user User object or user avatar address or user account
|
||||
* @param string $className Avatar element class name, default is "avatar-circle"
|
||||
* @param string $attrib Extra attributes on avatar element
|
||||
* @param string $tag Avatar element tag name, default is "div"
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
static public function smallAvatar($user, $className = 'avatar-circle', $attrib = '', $tag = 'div')
|
||||
{
|
||||
return html::avatar($user, 'sm', $className, $attrib, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a large user avatar.
|
||||
*
|
||||
* @param string|object $user User object or user avatar address or user account
|
||||
* @param string $className Avatar element class name, default is "avatar-circle"
|
||||
* @param string $attrib Extra attributes on avatar element
|
||||
* @param string $tag Avatar element tag name, default is "div"
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
static public function largeAvatar($user, $className = 'avatar-circle', $attrib = '', $tag = 'div')
|
||||
{
|
||||
return html::avatar($user, 'lg', $className, $attrib, $tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#cards .project-detail .progress-text-left .progress-text {width: 50px; left: -50px;}
|
||||
#cards .panel-heading {cursor: pointer;}
|
||||
#cards .project-stages-container {margin: 0 0 -16px 0; padding: 0 4px; height: 46px; overflow-x: auto; position: relative;}
|
||||
#cards .project-stages:after {content: ' '; width: 30px; display: block; right: -16px; top: 16px; bottom: -6px; z-index: 1; background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); position: absolute;}
|
||||
#cards .project-stages:after {content: ' '; width: 30px; display: block; right: -5px; top: 16px; bottom: -5px; z-index: 1; background: linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%); position: absolute;}
|
||||
#cards .project-stages-row {position: relative; height: 30px; z-index: 0;}
|
||||
#cards .project-stage-item {white-space: nowrap; position: absolute; top: 0; min-width: 48px; padding-top: 13px; color: #838A9D;}
|
||||
#cards .project-stage-item > div {white-space: nowrap; overflow: visible; text-align: center; text-overflow: ellipsis;}
|
||||
@@ -73,7 +73,7 @@
|
||||
<span><i class='icon icon-clock'></i> <?php printf($lang->project->hoursUnit, $project->estimate); ?></span>
|
||||
</div>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<?php if($project->model === 'waterfall'): ?>
|
||||
<?php if($project->model !== 'waterfall'): ?>
|
||||
<div class='project-detail project-stages'>
|
||||
<?php
|
||||
$projectProjects = array();
|
||||
|
||||
@@ -281,9 +281,7 @@ class commonModel extends model
|
||||
$isGuest = $app->user->account == 'guest';
|
||||
|
||||
echo "<a class='dropdown-toggle' data-toggle='dropdown'>";
|
||||
echo "<div id='main-avatar' class='avatar avatar bg-secondary avatar-circle'>";
|
||||
echo !empty($app->user->avatar) ? html::image($app->user->avatar) : strtoupper($app->user->account[0]);
|
||||
echo "</div>\n";
|
||||
echo html::avatar($app->user);
|
||||
echo '</a>';
|
||||
echo "<ul class='dropdown-menu pull-right'>";
|
||||
if(!$isGuest)
|
||||
@@ -291,9 +289,7 @@ class commonModel extends model
|
||||
$noRole = (!empty($app->user->role) && isset($lang->user->roleList[$app->user->role])) ? '' : ' no-role';
|
||||
echo '<li class="user-profile-item">';
|
||||
echo "<a href='" . helper::createLink('my', 'profile', '', '', true) . "' data-width='600' class='iframe $noRole'" . '>';
|
||||
echo "<div id='menu-avatar' class='avatar avatar bg-secondary avatar-circle'>";
|
||||
echo $app->user->avatar ? html::image($app->user->avatar) : strtoupper($app->user->account[0]);
|
||||
echo "</div>\n";
|
||||
echo html::avatar($app->user, '', 'avatar-circle', 'id="menu-avatar"');
|
||||
echo '<div class="user-profile-name">' . (empty($app->user->realname) ? $app->user->account : $app->user->realname) . '</div>';
|
||||
if(isset($lang->user->roleList[$app->user->role])) echo '<div class="user-profile-role">' . $lang->user->roleList[$app->user->role] . '</div>';
|
||||
echo '</a></li><li class="divider"></li>';
|
||||
|
||||
+31
-2
@@ -1,9 +1,24 @@
|
||||
/**
|
||||
* Load modules by libID.
|
||||
*
|
||||
* @param int $libID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadModules(libID)
|
||||
{
|
||||
link = createLink('doc', 'ajaxGetModules', 'libID=' + libID);
|
||||
$('#moduleBox').load(link, function(){$('#moduleBox').find('select').chosen()});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle acl.
|
||||
*
|
||||
* @param string $acl
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function toggleAcl(acl, type)
|
||||
{
|
||||
if(acl == 'custom')
|
||||
@@ -27,6 +42,13 @@ function toggleAcl(acl, type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load doc module by libID.
|
||||
*
|
||||
* @param int $libID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function loadDocModule(libID)
|
||||
{
|
||||
link = createLink('doc', 'ajaxGetChild', 'libID=' + libID);
|
||||
@@ -38,6 +60,13 @@ function loadDocModule(libID)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cookie of browse type and reload.
|
||||
*
|
||||
* @param type $type
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setBrowseType(type)
|
||||
{
|
||||
$.cookie('browseType', type, {expires:config.cookieLife, path:config.webRoot});
|
||||
@@ -46,7 +75,7 @@ function setBrowseType(type)
|
||||
|
||||
$(document).ready(function()
|
||||
{
|
||||
/* hide #module chosen dropdown on #lib dropdown show */
|
||||
/* Hide #module chosen dropdown on #lib dropdown show */
|
||||
$('#lib').on('chosen:showing_dropdown', function()
|
||||
{
|
||||
$('#module').trigger('chosen:close');
|
||||
@@ -85,7 +114,7 @@ $(document).ready(function()
|
||||
|
||||
var NAME = 'zui.splitRow'; // model name
|
||||
|
||||
/* The SplitRow model class */
|
||||
/* The SplitRow model class. */
|
||||
var SplitRow = function(element, options)
|
||||
{
|
||||
var that = this;
|
||||
|
||||
@@ -21,7 +21,7 @@ $(function()
|
||||
$('.ke-toolbar .ke-outline:last').after("<span data-name='unlink' class='ke-outline' title='Markdown' onclick='toggleEditor(\"markdown\")' style='font-size: unset; line-height: unset;'>Markdown</span>");
|
||||
}
|
||||
|
||||
$(document).on("mousedown", 'span[data-name="fullscreen"]', function()
|
||||
$(document).on("mouseup", 'span[data-name="fullscreen"]', function()
|
||||
{
|
||||
if($(this).hasClass('ke-selected'))
|
||||
{
|
||||
@@ -35,7 +35,7 @@ $(function()
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("mousedown", 'a[title="Fullscreen"],.icon-columns', function()
|
||||
$(document).on("mouseup", 'a[title="Fullscreen"],.icon-columns', function()
|
||||
{
|
||||
setTimeout(function()
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ $(function()
|
||||
/* Automatically save document contents. */
|
||||
setInterval("saveTempContent()", 60 * 1000);
|
||||
|
||||
$(document).on("mousedown", 'span[data-name="fullscreen"]', function()
|
||||
$(document).on("mouseup", 'span[data-name="fullscreen"]', function()
|
||||
{
|
||||
if(config.onlybody == 'no')
|
||||
{
|
||||
@@ -50,7 +50,7 @@ $(function()
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("mousedown", 'a[title="Fullscreen"],.icon-columns', function()
|
||||
$(document).on("mouseup", 'a[title="Fullscreen"],.icon-columns', function()
|
||||
{
|
||||
if(config.onlybody == 'no')
|
||||
{
|
||||
|
||||
@@ -1875,10 +1875,10 @@ class docModel extends model
|
||||
if($doc->type == 'project') $objectID = $doc->project;
|
||||
if($doc->type == 'execution') $objectID = $doc->execution;
|
||||
|
||||
$app = $this->app->openApp;
|
||||
if($app != 'doc') $app = $objectID ? $doc->type : 'doc';
|
||||
$tab = $this->app->openApp;
|
||||
if($tab != 'doc') $tab = $objectID ? $doc->type : 'doc';
|
||||
|
||||
$html .= '<li>' . html::a(inlink('objectLibs', "type={$doc->type}&objectID=$objectID&libID={$doc->lib}&docID={$doc->id}"), "<i class='icon icon-file-text'></i> " . $doc->title, '', "data-app='$app' title='{$doc->title}'") . '</li>';
|
||||
$html .= '<li>' . html::a(inlink('objectLibs', "type={$doc->type}&objectID=$objectID&libID={$doc->lib}&docID={$doc->id}"), "<i class='icon icon-file-text'></i> " . $doc->title, '', "data-app='$tab' title='{$doc->title}'") . '</li>';
|
||||
}
|
||||
|
||||
$collectionCount = $this->dao->select('count(id) as count')->from(TABLE_DOC)
|
||||
|
||||
@@ -358,7 +358,7 @@ class executionModel extends model
|
||||
->batchcheck($this->config->execution->create->requiredFields, 'notempty')
|
||||
->checkIF($sprint->begin != '', 'begin', 'date')
|
||||
->checkIF($sprint->end != '', 'end', 'date')
|
||||
->checkIF($sprint->end != '', 'end', 'gt', $sprint->begin)
|
||||
->checkIF($sprint->end != '', 'end', 'ge', $sprint->begin)
|
||||
->checkIF(!empty($sprint->code), 'code', 'unique')
|
||||
->exec();
|
||||
|
||||
|
||||
@@ -190,10 +190,13 @@ class gitlab extends control
|
||||
*/
|
||||
public function checkToken()
|
||||
{
|
||||
if(strpos($this->post->url, 'http') !== 0) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gitlab->hostError))));
|
||||
if(!$this->post->token) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
|
||||
$gitlabURL = trim($this->post->url);
|
||||
$token = trim($this->post->token);
|
||||
|
||||
$user = $this->gitlab->apiGetCurrentUser($this->post->url, $this->post->token);
|
||||
if(strpos($gitlabURL, 'http') !== 0) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gitlab->hostError))));
|
||||
if(!$token) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
|
||||
|
||||
$user = $this->gitlab->apiGetCurrentUser($gitlabURL, $token);
|
||||
|
||||
if(!is_object($user)) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gitlab->hostError))));
|
||||
if(!isset($user->is_admin) or !$user->is_admin) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gitlab->tokenError))));
|
||||
@@ -256,6 +259,11 @@ class gitlab extends control
|
||||
$gitlabID = $repo->gitlab;
|
||||
$projectID = $repo->project;
|
||||
|
||||
$gitlab = $this->gitlab->getByID($gitlabID);
|
||||
$user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
|
||||
if(!isset($user->is_admin) or !$user->is_admin) die(js::alert($this->lang->gitlab->tokenLimit) . js::locate($this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID))));
|
||||
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
$executionList = $this->post->executionList;
|
||||
|
||||
@@ -40,6 +40,7 @@ $lang->gitlab->placeholder->token = "Please fill in the access token of an accou
|
||||
|
||||
$lang->gitlab->noImportableIssues = "There are currently no issues available for import.";
|
||||
$lang->gitlab->tokenError = "The current token is not admin rights.";
|
||||
$lang->gitlab->tokenLimit = "The current token has no admin privilege. Please regenerate one with admin user in GitLab.";
|
||||
$lang->gitlab->hostError = "Invalid GitLab service address.";
|
||||
$lang->gitlab->bindUserError = "Can not bind users repeatedly %s";
|
||||
$lang->gitlab->importIssueError = "The execution to which this issue belongs is not selected.";
|
||||
|
||||
@@ -5,8 +5,11 @@ table+table {border-top: 1px solid #eee;}
|
||||
.row td {width: 33%; text-align: left; font-weight: 700;}
|
||||
.main-actions {margin: 5px 0 10px 0; text-align: center;}
|
||||
.user-title {margin: 10px 10px -10px 10px; font-size: 14px; font-weight: bold; padding-left: 10px;}
|
||||
.avatar {display: inline-block; width: 50px; height: 50px; line-height: 50px;}
|
||||
#avatarForm {width: 100%; height: 100%;}
|
||||
.avatar .btn-avatar {padding: 0; vertical-align: revert; border: 0; background-color: auto; color: #fff; font-size: 20px;}
|
||||
.user-name {margin-left: 15px; font-weight: bold;}
|
||||
.user-name, .user-role {line-height: 50px; font-size: 16px; vertical-align: top;}
|
||||
|
||||
#avatarUpload {display: inline-block; width: 50px; height: 50px; position: relative;}
|
||||
#avatarForm {position: absolute; top: 0; left: 0; right: 0; bottom: 0;}
|
||||
#avatarUploadBtn {display: block; position: absolute; top: 0; left: 0; right: 0; bottom: 0;}
|
||||
#avatarUploadBtn {opacity: 0; color: #fff; border-radius: 50%; line-height: 50px;}
|
||||
#avatarUploadBtn:hover {opacity: 1; background-color: rgba(0,0,0,.5);}
|
||||
|
||||
@@ -22,6 +22,8 @@ $(document).ready(function()
|
||||
window.parent.$('#main-avatar, #menu-avatar').html('<img src="' + avatar + '"/>');
|
||||
window.parent.$('#mainContent>.cell>.main-header>.avatar').html('<img src="' + avatar + '"/>');
|
||||
window.parent.$('#mainContent .avatar-' + account).html('<img src="' + avatar + '"/>');
|
||||
|
||||
$('#avatarUploadBtn').tooltip();
|
||||
});
|
||||
|
||||
function uploadAvatar()
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<form class='main-table' id='projectForm' method='post' data-ride='table' data-checkable='false'>
|
||||
<form id='projectForm' method='post' data-ride='table' data-checkable='false'>
|
||||
<table class='table table-fixed' id='docList'>
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
<div id='mainContent'>
|
||||
<div class='cell'>
|
||||
<div class='main-header text-center'>
|
||||
<span class="avatar avatar bg-secondary avatar-circle">
|
||||
<div id="avatarUpload">
|
||||
<?php echo html::avatar($user, 50); ?>
|
||||
<form method='post' class='form-ajax' action=<?php echo inlink('uploadAvatar');?> id='avatarForm' enctype='multipart/form-data'>
|
||||
<input type="file" name="files" id="files" class="form-control hidden">
|
||||
<?php $avatar = $user->avatar ? html::image($user->avatar) : strtoupper($user->account[0]);?>
|
||||
<?php echo html::a('javascript:void(0);', $avatar, '', "class='btn-avatar' id='avatarUploadBtn' data-placement='right'");?>
|
||||
<?php echo html::a('javascript:void(0);', '<i class="icon icon-pencil icon-2x"></i>', '', "class='btn-avatar' id='avatarUploadBtn' data-toggle='tooltip' data-container='body' data-placement='bottom' title='{$lang->my->uploadAvatar}'");?>
|
||||
</form>
|
||||
</span>
|
||||
</div>
|
||||
<span class='user-name'><?php echo $user->realname;?></span>
|
||||
<span class='user-role'><?php echo zget($lang->user->roleList, $user->role, '');?></span>
|
||||
</div>
|
||||
|
||||
@@ -76,6 +76,7 @@ class pipelineModel extends model
|
||||
->add('private',md5(rand(10,113450)))
|
||||
->add('createdBy', $this->app->user->account)
|
||||
->add('createdDate', helper::now())
|
||||
->trim('token')
|
||||
->skipSpecial('url,token,account,password')
|
||||
->get();
|
||||
if($type == 'gitlab') $pipeline->url = rtrim($pipeline->url, '/');
|
||||
@@ -104,6 +105,7 @@ class pipelineModel extends model
|
||||
$pipeline = fixer::input('post')
|
||||
->add('editedBy', $this->app->user->account)
|
||||
->add('editedDate', helper::now())
|
||||
->trim('token')
|
||||
->skipSpecial('url,token,account,password')
|
||||
->get();
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<th class='text-right w-100px'><?php common::printOrderLink('budget', $orderBy, $vars, $lang->project->budget);?></th>
|
||||
<th class='w-100px'><?php common::printOrderLink('begin', $orderBy, $vars, $lang->project->begin);?></th>
|
||||
<th class='w-100px'><?php common::printOrderLink('end', $orderBy, $vars, $lang->project->end);?></th>
|
||||
<th class='w-70px'><?php echo $lang->project->progress;?></th>
|
||||
<th class='w-60px'><?php echo $lang->project->progress;?></th>
|
||||
<th class='text-center w-180px'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -62,9 +62,7 @@
|
||||
<td class='c-status'><span class="status-program status-<?php echo $program->status?>"><?php echo zget($lang->project->statusList, $program->status, '');?></span></td>
|
||||
<td>
|
||||
<?php if(!empty($program->PM)):?>
|
||||
<div class="avatar bg-secondary avatar-circle avatar-<?php echo $program->PM;?>">
|
||||
<?php echo !empty($usersAvatar[$program->PM]) ? html::image($usersAvatar[$program->PM]) : strtoupper($program->PM[0]);?>
|
||||
</div>
|
||||
<?php echo html::smallAvatar(array('avatar' => $usersAvatar[$program->PM], 'account' => $program->PM)); ?>
|
||||
<?php $userID = isset($PMList[$program->PM]) ? $PMList[$program->PM]->id : '';?>
|
||||
<?php $userName = zget($users, $program->PM);?>
|
||||
<?php echo html::a($this->createLink('user', 'profile', "userID=$userID", '', true), $userName, '', "title='{$userName}' data-toggle='modal' data-type='iframe' data-width='600'");?>
|
||||
@@ -76,7 +74,7 @@
|
||||
<td><?php echo $program->end == LONG_TIME ? $lang->program->longTime : $program->end;?></td>
|
||||
<td>
|
||||
<?php if(isset($progressList[$program->id])):?>
|
||||
<div class='progress-pie' data-doughnut-size='90' data-color='#3CB371' data-value='<?php echo $progressList[$program->id]?>' data-width='24' data-height='24' data-back-color='#e8edf3'>
|
||||
<div class='progress-pie' data-doughnut-size='85' data-color='#00DA88' data-value='<?php echo $progressList[$program->id]?>' data-width='26' data-height='26' data-back-color='#e8edf3'>
|
||||
<div class='progress-info'><?php echo $progressList[$program->id];?></div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#cards .project-infos > span + span {margin-left: 15px;}
|
||||
#cards .project-infos > .budget {max-width: 75px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
#cards .project-detail {position: absolute; top: 75px; left: 16px; right: 16px; font-size: 12px;}
|
||||
#cards .project-footer {position: absolute; bottom: 5px;}
|
||||
#cards .project-footer {position: absolute; bottom: 10px; right: 10px; left: 15px;}
|
||||
#cards .pager {margin: 0; float: right;}
|
||||
#cards .pager .btn {border: none}
|
||||
#cards .panel .label-wait {background: #EFEFEF !important; color: #838A9D;}
|
||||
@@ -40,16 +40,18 @@
|
||||
#cards .project-infos .text-red {color: #F85A40 !important;}
|
||||
#cards .project-detail .progress-pie {width: 24px; position: absolute; top: 18px;}
|
||||
#cards .project-detail .leftTasks, .totalLeft {display:block; margin-top: 8px;}
|
||||
#cards .project-members {float: left;}
|
||||
#cards .project-members .avatar {display: inline-block; width: 25px; height: 25px; line-height: 25px; margin-right: 1px;}
|
||||
#cards .project-members a:not(:first-child) {margin-left: -5px;}
|
||||
#cards .totalMembers{display: inline-block; margin-left: 6px; position: absolute; bottom: 8px;}
|
||||
#cards .project-actions {float: right;}
|
||||
#cards .project-actions .menu-actions {padding-right: 20px;}
|
||||
#cards .project-actions ul {min-width: 35px; padding: 5px 6px;}
|
||||
#cards .project-actions .dropdown-hover:hover>.dropdown-menu ul,
|
||||
#cards .project-actions .open>.dropdown-menu ul {display: flex;}
|
||||
#cards .menu-actions .btn.btn-action {margin-bottom: -3px !important; margin-right: 5px;}
|
||||
#cards .project-members {float: left; height: 24px; line-height: 24px;}
|
||||
#cards .project-members > a {display: inline-block; height: 24px;}
|
||||
#cards .project-members > a + a {margin-left: -5px;}
|
||||
#cards .project-members > a > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 1px;}
|
||||
#cards .project-members > span {display: inline-block; color: transparent; width: 2px; height: 2px; background-color: #8990a2; position: relative; border-radius: 50%; top: 3px; margin: 0 3px;}
|
||||
#cards .project-members > span:before,
|
||||
#cards .project-members > span:after {content: ''; display: block; position: absolute; width: 2px; height: 2px; background-color: #8990a2; top: 0; border-radius: 50%}
|
||||
#cards .project-members > span:before {left: -4px;}
|
||||
#cards .project-members > span:after {right: -4px;}
|
||||
#cards .project-members-total {display: inline-block; margin-left: 6px; position: relative; top: 3px}
|
||||
#cards .project-actions {position: absolute; right: -8px; bottom: -5px; white-space: nowrap;}
|
||||
#cards .project-actions .dropdown-menu {padding: 5px 6px; top: -5px; right: 30px;}
|
||||
#cards .icon-ellipsis-v {font-size: 13px;}
|
||||
#cards .teamTitle {margin-bottom: 30px;}
|
||||
</style>
|
||||
@@ -138,41 +140,39 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='project-footer table-row'>
|
||||
<div class='project-footer'>
|
||||
<?php $titleClass = ($project->teamCount == 0 and !$canActions) ? 'teamTitle' : '';?>
|
||||
<?php $count = 0;?>
|
||||
<div class="<?php echo $titleClass?>"><?php echo $lang->project->teamMember;?></div>
|
||||
<?php if(!empty($project->teamMembers)):?>
|
||||
<div class='project-members table-col'>
|
||||
<?php foreach($project->teamMembers as $member):?>
|
||||
<?php
|
||||
if($count > 2) continue;
|
||||
if(!isset($users[$member]))
|
||||
{
|
||||
$project->teamCount --;
|
||||
continue;
|
||||
}
|
||||
$count ++;
|
||||
?>
|
||||
<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]);?>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach;?>
|
||||
<?php if($project->teamCount > 3):?>
|
||||
<?php echo '...';?>
|
||||
<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[end($project->teamMembers)]) ? html::image(zget($usersAvatar, end($project->teamMembers))) : strtoupper($member[0]);?>
|
||||
</div>
|
||||
</a>
|
||||
<div class="clearfix">
|
||||
<?php if(!empty($project->teamMembers)):?>
|
||||
<div class='project-members pull-left'>
|
||||
<?php foreach($project->teamMembers as $member):?>
|
||||
<?php
|
||||
if($count > 2) continue;
|
||||
if(!isset($users[$member]))
|
||||
{
|
||||
$project->teamCount --;
|
||||
continue;
|
||||
}
|
||||
$count ++;
|
||||
?>
|
||||
<a href='<?php echo helper::createLink('project', 'team', "projectID=$projectID");?>' title="<?php echo $users[$member];?>">
|
||||
<?php echo html::smallAvatar(array('avatar' => $usersAvatar[$member], 'account' => $member)); ?>
|
||||
</a>
|
||||
<?php endforeach;?>
|
||||
<?php if($project->teamCount > 3):?>
|
||||
<?php echo '<span>…</span>';?>
|
||||
<a href='<?php echo helper::createLink('project', 'team', "projectID=$projectID");?>' title="<?php echo $users[$member];?>">
|
||||
<?php echo html::smallAvatar(array('avatar' => $usersAvatar[end($project->teamMembers)], 'account' => $member)); ?>
|
||||
</a>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class='project-members-total pull-left'><?php echo html::a(helper::createLink('project', 'team', "projectID=$projectID"), sprintf($lang->project->teamSumCount, $project->teamCount));?></div>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<span class='totalMembers'><?php echo html::a(helper::createLink('project', 'team', "projectID=$projectID"), sprintf($lang->project->teamSumCount, $project->teamCount));?></span>
|
||||
<div class='project-actions table-col'>
|
||||
<div class='menu-actions'>
|
||||
<div class='project-actions'>
|
||||
<div class='dropdown'>
|
||||
<?php if($canActions):?>
|
||||
<?php echo html::a('javascript:;', "<i class='icon icon-ellipsis-v'></i>", '', "data-toggle='dropdown' class='btn btn-link'");?>
|
||||
<ul class='dropdown-menu pull-right'>
|
||||
|
||||
@@ -1234,8 +1234,7 @@ class userModel extends model
|
||||
if(!$uploadResult) return array('result' => 'fail', 'message' => $this->lang->fail);
|
||||
|
||||
$fileIdList = array_keys($uploadResult);
|
||||
$file = $this->file->getByID($fileIdList[0]);
|
||||
$this->dao->update(TABLE_USER)->set('avatar')->eq($file->webPath)->where('account')->eq($this->app->user->account)->exec();
|
||||
$file = $this->file->getByID($fileIdList[0]);
|
||||
|
||||
return array('result' => 'success', 'message' => '', 'locate' => helper::createLink('user', 'cropavatar', "image={$file->id}"));
|
||||
}
|
||||
|
||||
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.
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 200 KiB |
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user