' . $lang->goback, '', "class='btn btn-secondary'");?>
@@ -344,11 +337,6 @@ js::set('cancel', $lang->cancel);
js::set('rawModule', $this->app->rawModule);
?>
app->getModuleRoot() . 'common/view/syntaxhighlighter.html.php';?>
app->getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/extension/lite/task/ext/view/create.html.php b/extension/lite/task/ext/view/create.html.php
index 87766c920a..227d383766 100644
--- a/extension/lite/task/ext/view/create.html.php
+++ b/extension/lite/task/ext/view/create.html.php
@@ -336,6 +336,7 @@
isINT) and class_exists('common')) ? common::convert2Pinyin($stories) : array());?>
id);?>
+type);?>
+
-
caselib->import;?>
+ port->import;?>
file->importSummary, $allCount, html::input('maxImport', $config->file->maxImport, "style='width:50px'"), ceil($allCount / $config->file->maxImport));?>
import, "id='import'", 'btn btn-primary');?>
@@ -23,118 +44,186 @@ $(function()
-
caselib->import;?>
+ port->import;?>
-
-
-
-
-
+getModuleRoot() . 'common/view/footer.html.php';?>
diff --git a/module/ci/control.php b/module/ci/control.php
index 1118fef65f..5c5ea8fdc2 100644
--- a/module/ci/control.php
+++ b/module/ci/control.php
@@ -149,16 +149,18 @@ class ci extends control
->fetch();
$testtask = new stdclass();
- $testtask->product = $productID;
- $testtask->name = !empty($post->name) ? $post->name : sprintf($this->lang->testtask->titleOfAuto, date('Y-m-d H:i:s'));
- $testtask->owner = $this->app->user->account;
- $testtask->project = $lastProject->project;
- $testtask->execution = $lastProject->id;
- $testtask->build = 'trunk';
- $testtask->auto = strtolower($testType);
- $testtask->begin = date('Y-m-d');
- $testtask->end = date('Y-m-d', time() + 24 * 3600);
- $testtask->status = 'done';
+ $testtask->product = $productID;
+ $testtask->name = !empty($post->name) ? $post->name : sprintf($this->lang->testtask->titleOfAuto, date('Y-m-d H:i:s'));
+ $testtask->owner = $this->app->user->account;
+ $testtask->project = $lastProject->project;
+ $testtask->execution = $lastProject->id;
+ $testtask->build = 'trunk';
+ $testtask->auto = strtolower($testType);
+ $testtask->begin = date('Y-m-d');
+ $testtask->end = date('Y-m-d', time() + 24 * 3600);
+ $testtask->status = 'done';
+ $testtask->createdBy = $this->app->user->account;
+ $testtask->createdDate = helper::now();
$this->dao->insert(TABLE_TESTTASK)->data($testtask)->exec();
$taskID = $this->dao->lastInsertId();
diff --git a/module/ci/model.php b/module/ci/model.php
index 2f5bf854b0..0d27513edc 100644
--- a/module/ci/model.php
+++ b/module/ci/model.php
@@ -26,7 +26,13 @@ class ciModel extends model
}
common::setMenuVars('devops', $this->session->repoID);
- $this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID);
+ if($this->session->repoID)
+ {
+ $repo = $this->loadModel('repo')->getRepoByID($this->session->repoID);
+ if(!in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr);
+
+ $this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID);
+ }
}
/**
diff --git a/module/common/lang/de.php b/module/common/lang/de.php
index e9529dc6f5..9cd57439b5 100644
--- a/module/common/lang/de.php
+++ b/module/common/lang/de.php
@@ -150,6 +150,7 @@ $lang->openedByAB = 'Ersteller';
$lang->assignedToAB = 'Bearbeiter';
$lang->typeAB = 'Typ';
$lang->nameAB = 'Name';
+$lang->code = 'Code';
$lang->pri = 'Priority';
$lang->delayed = 'Delayed';
@@ -372,6 +373,7 @@ $lang->error->companyNotFound = "The domain %s cannot be found!";
$lang->error->length = array("『%s』Length Error. It should be『%s』", "『%s』length should be <=『%s』and >『%s』.");
$lang->error->reg = "『%s』Format Error. It should be『%s』.";
$lang->error->unique = "『%s』『%s』existed. Please go to Admin->System->Data->Recycle to restore it, if you are sure it is deleted.";
+$lang->error->repeat = "『%s』『%s』exists.";
$lang->error->gt = "『%s』should be >『%s』.";
$lang->error->ge = "『%s』should be >=『%s』.";
$lang->error->lt = "『%s』should be <『%s』。";
@@ -429,6 +431,7 @@ $lang->colorPicker->errorTip = 'Not a valid color value';
$lang->downNotify = "Download Desktop Notification";
$lang->clientName = "Desktop";
$lang->downloadClient = "Download ZenTao Desktop";
+$lang->downloadMobile = "Download Mobile Terminal";
$lang->clientHelp = "Client Help";
$lang->clientHelpLink = "https://www.zentao.pm/book/zentaomanual/scrum-tool-im-integration-206.html";
$lang->website = "http://www.zentao.net";
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index 16edf7074d..e8022f9f17 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -150,6 +150,7 @@ $lang->openedByAB = 'CreatedBy';
$lang->assignedToAB = 'AssignedTo';
$lang->typeAB = 'Type';
$lang->nameAB = 'Name';
+$lang->code = 'Code';
$lang->pri = 'Priority';
$lang->delayed = 'Delayed';
@@ -372,6 +373,7 @@ $lang->error->companyNotFound = "The domain %s cannot be found!";
$lang->error->length = array("『%s』length error. It should be『%s』", "『%s』length should be <=『%s』and >『%s』.");
$lang->error->reg = "『%s』format error. It should be『%s』.";
$lang->error->unique = "『%s』『%s』exists. Go to Admin->System->Data->Recycle Bin to restore it, if you are sure it is deleted.";
+$lang->error->repeat = "『%s』『%s』exists.";
$lang->error->gt = "『%s』should be >『%s』.";
$lang->error->ge = "『%s』should be >=『%s』.";
$lang->error->lt = "『%s』should be <『%s』。";
@@ -429,6 +431,7 @@ $lang->colorPicker->errorTip = 'Not a valid color value';
$lang->downNotify = "Download Desktop Notification";
$lang->clientName = "Desktop";
$lang->downloadClient = "Download ZenTao Desktop";
+$lang->downloadMobile = "Download Mobile Terminal";
$lang->clientHelp = "Client Help";
$lang->clientHelpLink = "https://www.zentao.pm/book/zentaomanual/scrum-tool-im-integration-206.html";
$lang->website = "https://www.zentao.pm";
diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php
index d6aad09697..d291be8c95 100644
--- a/module/common/lang/fr.php
+++ b/module/common/lang/fr.php
@@ -150,6 +150,7 @@ $lang->openedByAB = 'Créé par';
$lang->assignedToAB = 'Affecté à';
$lang->typeAB = 'Type';
$lang->nameAB = 'Name';
+$lang->code = 'Code';
$lang->pri = 'Priority';
$lang->delayed = 'Delayed';
@@ -372,6 +373,7 @@ $lang->error->companyNotFound = "Le domaine %s ne peut être trouvé !";
$lang->error->length = array("『 %s 』erreur de longueur. Il devrait être『%s』", "La longueur de 『%s』devrait être <=『%s』et >『%s』.");
$lang->error->reg = "『 %s 』erreur de format. Il devrait être『%s』.";
$lang->error->unique = "『 %s 』『 %s 』existes. Allez à Admin->System->Data->Recycle Bin pour le restaurer, si vous êtes sûr qu'il est supprimé.";
+$lang->error->repeat = "『 %s 』『 %s 』existes.";
$lang->error->gt = "『 %s 』devrait être > 『 %s 』.";
$lang->error->ge = "『 %s 』devrait être >= 『 %s 』.";
$lang->error->lt = "『%s』should be <『%s』。";
@@ -429,6 +431,7 @@ $lang->colorPicker->errorTip = "Ce n'est pas une valeur de couleur valide";
$lang->downNotify = "Télécharger la notification sur le bureau";
$lang->clientName = "Desktop";
$lang->downloadClient = "Télécharger ZenTao Desktop";
+$lang->downloadMobile = "Download Mobile Terminal";
$lang->clientHelp = "Aide Client";
$lang->clientHelpLink = "https://www.zentao.pm/book/zentaomanual/scrum-tool-im-integration-206.html";
$lang->website = "https://www.zentao.pm";
diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php
index b7703e2dc1..67e1345892 100644
--- a/module/common/lang/menu.php
+++ b/module/common/lang/menu.php
@@ -291,16 +291,25 @@ $lang->waterfall->menu->design['subMenu']->ads = array('link' => "{$lang->d
$lang->waterfall->menu->design['subMenu']->bysearch = array('link' => '
' . $lang->searchAB . '');
/* Kanban project menu. */
-$lang->kanbanProject = new stdclass();
-$lang->kanbanProject->menu = new stdclass();
-$lang->kanbanProject->menu->index = array('link' => "{$lang->kanban->common}|project|index|project=%s");
-$lang->kanbanProject->menu->build = array('link' => "{$lang->build->common}|project|build|project=%s");
+$lang->kanbanProject = new stdclass();
+$lang->kanbanProject->menu = new stdclass();
+$lang->kanbanProject->menu->index = array('link' => "{$lang->kanban->common}|project|index|project=%s");
+$lang->kanbanProject->menu->build = array('link' => "{$lang->build->common}|project|build|project=%s");
+$lang->kanbanProject->menu->settings = array('link' => "$lang->settings|project|view|project=%s", 'subModule' => 'stakeholder', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist,team');
-$lang->kanbanProject->menuOrder = array();
-$lang->kanbanProject->menuOrder[5] = 'index';
-$lang->kanbanProject->menuOrder[10] = 'build';
$lang->kanbanProject->dividerMenu = '';
+$lang->kanbanProject->menuOrder = array();
+$lang->kanbanProject->menuOrder[5] = 'index';
+$lang->kanbanProject->menuOrder[10] = 'build';
+$lang->kanbanProject->menuOrder[15] = 'settings';
+
+$lang->kanbanProject->menu->settings['subMenu'] = new stdclass();
+$lang->kanbanProject->menu->settings['subMenu']->view = array('link' => "$lang->overview|project|view|project=%s", 'alias' => 'edit');
+$lang->kanbanProject->menu->settings['subMenu']->products = array('link' => "{$lang->product->common}|project|manageProducts|project=%s", 'alias' => 'manageproducts');
+$lang->kanbanProject->menu->settings['subMenu']->members = array('link' => "{$lang->team->common}|project|team|project=%s", 'alias' => 'managemembers,team');
+$lang->kanbanProject->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|project|whitelist|project=%s", 'subModule' => 'personnel');
+
/* Execution menu. */
$lang->execution->homeMenu = new stdclass();
$lang->execution->homeMenu->all = array('link' => "{$lang->execution->all}|execution|all|", 'alias' => 'create,batchedit');
@@ -488,7 +497,7 @@ $lang->admin->menu = new stdclass();
$lang->admin->menu->index = array('link' => "$lang->indexPage|admin|index", 'alias' => 'register,certifytemail,certifyztmobile,ztcompany');
$lang->admin->menu->company = array('link' => "{$lang->personnel->common}|company|browse|", 'subModule' => ',user,dept,group,');
$lang->admin->menu->model = array('link' => "$lang->model|custom|browsestoryconcept|", 'class' => 'dropdown dropdown-hover', 'exclude' => 'custom-index,custom-set,custom-product,custom-execution,custom-kanban,custom-required,custom-flow,custom-score,custom-feedback,custom-timezone,custom-mode');
-$lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate');
+$lang->admin->menu->custom = array('link' => "{$lang->custom->common}|custom|index", 'exclude' => 'custom-browsestoryconcept,custom-timezone,custom-estimate,custom-code');
$lang->admin->menu->extension = array('link' => "{$lang->extension->common}|extension|browse", 'subModule' => 'extension');
$lang->admin->menu->dev = array('link' => "$lang->redev|dev|api", 'alias' => 'db', 'subModule' => 'dev,editor,entry');
$lang->admin->menu->message = array('link' => "{$lang->message->common}|message|index", 'subModule' => 'message,mail,webhook');
@@ -506,7 +515,10 @@ if($config->systemMode == 'new')
$lang->admin->menu->allModel['subMenu'] = new stdclass();
$lang->admin->menu->allModel['subMenu']->storyConcept = array('link' => "{$lang->storyConcept}|custom|browsestoryconcept|");
-$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept';
+$lang->admin->menu->allModel['subMenu']->code = array('link' => "{$lang->code}|custom|code|");
+
+$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept';
+$lang->admin->menu->allModel['menuOrder'][30] = 'code';
$lang->admin->menu->waterfall['subMenu'] = new stdclass();
$lang->admin->menu->waterfall['subMenu']->stage = array('link' => "{$lang->stage->common}|stage|setType|", 'subModule' => 'stage');
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index c63345b39f..eb4cc5bf63 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -150,6 +150,7 @@ $lang->openedByAB = '创建';
$lang->assignedToAB = '指派';
$lang->typeAB = '类型';
$lang->nameAB = '名称';
+$lang->code = '代号';
$lang->pri = '优先级';
$lang->delayed = '已延期';
@@ -372,6 +373,7 @@ $lang->error->companyNotFound = "您访问的域名 %s 没有对应的公司。"
$lang->error->length = array("『%s』长度错误,应当为『%s』", "『%s』长度应当不超过『%s』,且大于『%s』。");
$lang->error->reg = "『%s』不符合格式,应当为:『%s』。";
$lang->error->unique = "『%s』已经有『%s』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。";
+$lang->error->repeat = "『%s』已经有『%s』这条记录了。";
$lang->error->gt = "『%s』应当大于『%s』。";
$lang->error->ge = "『%s』应当不小于『%s』。";
$lang->error->lt = "『%s』应当小于『%s』。";
@@ -429,6 +431,7 @@ $lang->colorPicker->errorTip = '不是有效的颜色值';
$lang->downNotify = "下载桌面提醒";
$lang->clientName = "客户端";
$lang->downloadClient = "下载客户端";
+$lang->downloadMobile = "下载移动端";
$lang->clientHelp = "客户端使用说明";
$lang->clientHelpLink = "http://www.zentao.net/book/zentaopmshelp/302.html#2";
$lang->website = "https://www.zentao.net";
diff --git a/module/common/model.php b/module/common/model.php
index bb85ca6c40..bbdb5187f8 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -1232,8 +1232,7 @@ class commonModel extends model
/**
* Print the module menu.
*
- * @param string $actveMenu
- * @param string $methodName
+ * @param string $activeMenu
* @static
* @access public
* @return void
@@ -1423,6 +1422,9 @@ class commonModel extends model
echo "';
}
@@ -1521,10 +1523,12 @@ class commonModel extends model
public static function printLink($module, $method, $vars = '', $label = '', $target = '', $misc = '', $newline = true, $onlyBody = false, $object = null)
{
/* Add data-app attribute. */
- global $app;
+ global $app, $config;
+ $currentModule = strtolower($module);
+ $currentMethod = strtolower($method);
if(strpos($misc, 'data-app') === false) $misc .= ' data-app="' . $app->tab . '"';
- if(!commonModel::hasPriv($module, $method, $object)) return false;
+ if(!commonModel::hasPriv($module, $method, $object) and !in_array("$currentModule.$currentMethod", $config->openMethods)) return false;
echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline);
return true;
}
@@ -1966,7 +1970,7 @@ EOD;
}
}
- $changes = array();
+ $changes = array();
foreach($new as $key => $value)
{
if(is_object($value) or is_array($value)) continue;
@@ -2379,8 +2383,7 @@ EOD;
}
$referer = helper::safe64Encode($uri);
- print(js::locate(helper::createLink('user', 'login', "referer=$referer")));
- helper::end();
+ die(js::locate(helper::createLink('user', 'login', "referer=$referer")));
}
}
catch(EndResponseException $endResponseException)
@@ -3084,11 +3087,13 @@ EOD;
* @param string|array $data
* @param array $options This is option and value pair, like CURLOPT_HEADER => true. Use curl_setopt function to set options.
* @param array $headers Set request headers.
+ * @param string $dataType
+ * @param string $method POST|PATCH|PUT
* @static
* @access public
* @return string
*/
- public static function http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data')
+ public static function http($url, $data = null, $options = array(), $headers = array(), $dataType = 'data', $method = 'POST')
{
global $lang, $app;
if(!extension_loaded('curl'))
@@ -3125,7 +3130,8 @@ EOD;
if(!empty($data))
{
if(is_object($data)) $data = (array) $data;
- curl_setopt($curl, CURLOPT_POST, true);
+ if($method == 'POST') curl_setopt($curl, CURLOPT_POST, true);
+ if(in_array($method, array('PATCH', 'PUT'))) curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
@@ -3371,6 +3377,45 @@ EOD;
return $Parsedown->text($markdown);
}
+
+ /**
+ * Sort featureBar.
+ *
+ * @param string $module
+ * @param string $method
+ * @static
+ * @access public
+ * @return bool
+ */
+ public static function sortFeatureMenu($module = '', $method = '')
+ {
+ global $lang, $config, $app;
+
+ $module = $module ? $module : $app->rawModule;
+ $method = $method ? $method : $app->rawMethod;
+
+ /* It will be sorted according to the workflow in the future */
+ if(!empty($config->featureBarSort[$module][$method]))
+ {
+ $featureBar = array();
+ if(empty($lang->$module->featureBar[$method])) return false;
+ foreach($lang->$module->featureBar[$method] as $key => $label)
+ {
+ foreach($config->featureBarSort[$module][$method] as $currentKey => $afterKey)
+ {
+ if($key == $currentKey) continue;
+ $featureBar[$method][$key] = $label;
+ if($key == $afterKey && !empty($lang->$module->featureBar[$method][$currentKey]))
+ {
+ $featureBar[$method][$currentKey] = $lang->$module->featureBar[$method][$currentKey];
+ }
+ }
+ }
+ $lang->$module->featureBar = $featureBar;
+ }
+
+ return true;
+ }
}
class common extends commonModel
diff --git a/module/common/view/datatable.fix.html.php b/module/common/view/datatable.fix.html.php
index 2d434fa2d0..48a26082c2 100644
--- a/module/common/view/datatable.fix.html.php
+++ b/module/common/view/datatable.fix.html.php
@@ -24,12 +24,6 @@ $(function()
{
$dropmenu.append("
moduleName . '&method=' . $this->methodName . '&extra=requirement')?>' data-toggle='modal' data-type='ajax'>datatable->custom?>");
}
- else if(typeof(from) != 'undefined')
- {
-
-
- $dropmenu.append("
moduleName . '&method=' . $this->methodName . "&extra=$fromPage")?>' data-toggle='modal' data-type='ajax'>datatable->custom?>");
- }
else
{
$dropmenu.append("
moduleName . '&method=' . $this->methodName)?>' data-toggle='modal' data-type='ajax'>datatable->custom?>");
diff --git a/module/common/view/gantt.html.php b/module/common/view/gantt.html.php
index 5a111ad848..ec81e3d8c0 100644
--- a/module/common/view/gantt.html.php
+++ b/module/common/view/gantt.html.php
@@ -11,13 +11,18 @@
*/
css::import($jsRoot . 'dhtmlxgantt/min.css');
js::import($jsRoot . 'dhtmlxgantt/min.js');
-js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_critical_path.js');
-js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_fullscreen.js');
-js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_smart_rendering.js');
-js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_marker.js');
$currentLang = $app->getClientLang();
if($currentLang != 'en') js::import($jsRoot . 'dhtmlxgantt/lang/' . $currentLang . '.js');
?>
+
diff --git a/module/common/view/header.html.php b/module/common/view/header.html.php
index 5e3a344972..6d67bb95e8 100755
--- a/module/common/view/header.html.php
+++ b/module/common/view/header.html.php
@@ -7,6 +7,7 @@ include 'chosen.html.php';
app->loadConfig('sso');?>
sso->redirect)) js::set('ssoRedirect', $config->sso->redirect);?>
+showMainMenu):?>
" . $lang->export, '', "class='btn btn-link export'")?>
-
- createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), " " . $lang->programplan->create, '', "class='btn btn-primary'");?>
-
- createLink('execution', 'create', "projectID=$projectID"), " " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-primary create-execution-btn' data-app='execution' onclick='$(this).removeAttr(\"data-toggle\")'");?>
-
+ createLink('execution', 'create'), " " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-primary create-execution-btn' data-app='execution' onclick='$(this).removeAttr(\"data-toggle\")'");?>