diff --git a/api/v1/entries/productissue.php b/api/v1/entries/productissue.php
index eecc5704c4..f6a92de5bb 100644
--- a/api/v1/entries/productissue.php
+++ b/api/v1/entries/productissue.php
@@ -53,6 +53,7 @@ class productIssueEntry extends entry
}
break;
+
case 'bug':
$this->app->loadLang('bug');
$bugStatus = array('' => '', 'active' => 'opened', 'resolved' => 'opened', 'closed' => 'closed');
@@ -132,7 +133,9 @@ class productIssueEntry extends entry
$this->send404();
}
- $actions = $this->loadModel('action')->getList($type, $issueID);
+ $actions = $this->loadModel('action')->getList($type, $id);
+
+ $issue->comments = array_values($this->processActions($type, $actions));
/**
* Get all users in issues so that we can bulk get user detail later.
@@ -159,4 +162,52 @@ class productIssueEntry extends entry
$this->send(200, array('issue' => $this->format($issue, 'openedDate:time,lastEditedDate:time')));
}
+
+ /**
+ * Process actions of one issue.
+ *
+ * @param string $type
+ * @param array $actions
+ * @access public
+ * @return array
+ */
+ public function processActions($type, $actions)
+ {
+ $accountsList = array();
+ foreach($actions as $action)
+ {
+ $accountsList[] = $action->actor;
+ ob_start();
+ $this->action->printAction($action);
+ $action->title = ob_get_contents();
+ ob_clean();
+
+ $action->body_html = '';
+
+ if(!empty($action->history))
+ {
+ ob_start();
+ $this->action->printChanges($action->objectType, $action->history);
+ $action->body_html = ob_get_contents();
+ ob_clean();
+ }
+
+ if(!empty($action->comment))
+ {
+ $comment = strip_tags($action->comment) == $action->comment ? nl2br($action->comment) : $action->comment;
+ $action->body_html = "
";
+ }
+ }
+
+ /* Format user detail and date. */
+ $accountsList = array_unique($accountsList);
+ $userDetails = $this->loadModel('user')->getUserDetailsForAPI($accountsList);
+ foreach($actions as $action)
+ {
+ $action->actor = $userDetails[$action->actor];
+ $action->date = gmdate("Y-m-d\TH:i:s\Z", strtotime($action->date));
+ }
+
+ return $actions;
+ }
}
diff --git a/api/v1/entries/productissues.php b/api/v1/entries/productissues.php
index d26b72a76a..6cda85a31d 100644
--- a/api/v1/entries/productissues.php
+++ b/api/v1/entries/productissues.php
@@ -107,32 +107,35 @@ class productIssuesEntry extends entry
$bugFilter = array_unique($bugFilter);
$executions = $this->dao->select('project')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($productID)->fetchPairs();
- if(!empty($taskFilter))
+
+ /* Get tasks. */
+ if(empty($labelTypes) or in_array('task', $labelTypes))
{
$query = $this->dao->select($taskFields)->from(TABLE_TASK)->where('execution')->in(array_values($executions))
->beginIF($search)->andWhere('name')->like("%$search%")->fi()
->beginIF($status)->andWhere('status')->in($taskStatus[$status])->fi()
->andWhere('deleted')->eq(0);
-
foreach($taskFilter as $filter) if($filter != 'all') $query->andWhere('type')->eq($filter);
$tasks = $query->fetchAll();
foreach($tasks as $task) $issues[] = array('id' => $task->id, 'type' => 'task', 'order' => $task->$order, 'status' => $this->getKey($task->status, $taskStatus));
}
- if(!empty($storyFilter))
+ /* Get stories. */
+ if(empty($labelTypes) or in_array('story', $labelTypes))
{
$query = $this->dao->select($storyFields)->from(TABLE_STORY)
->where('product')->eq($productID)
->beginIF($search)->andWhere('title')->like("%$search%")->fi()
->beginIF($status)->andWhere('status')->in($storyStatus[$status])->fi()
->andWhere('deleted')->eq(0);
-
foreach($storyFilter as $filter) if($filter != 'all') $query->andWhere('category')->eq($filter);
$stories = $query->fetchAll();
foreach($stories as $story) $issues[] = array('id' => $story->id, 'type' => 'story', 'order' => $story->$order, 'status' => $this->getKey($story->status, $storyStatus));
}
- if(!empty($bugFilter))
+ /* Get bugs. */
+ /* Get stories. */
+ if(empty($labelTypes) or in_array('bug', $labelTypes))
{
$query = $this->dao->select($bugFields)->from(TABLE_BUG)
->where('product')->eq($productID)
@@ -305,7 +308,7 @@ class productIssuesEntry extends entry
{
foreach($issue->assignedTo as $index => $user)
{
- $issue->assignedTo[$index] = $userDetails[$user];
+ $issue->assignedTo[$index] = $userDetails[$user];
}
$issue->openedBy = $userDetails[$issue->openedBy];
}
diff --git a/config/zentaopms.php b/config/zentaopms.php
index fe193d98ca..bc2ecfea74 100644
--- a/config/zentaopms.php
+++ b/config/zentaopms.php
@@ -139,6 +139,7 @@ $config->openMethods[] = 'index.changelog';
$config->openMethods[] = 'my.preference';
$config->openMethods[] = 'my.changepassword';
$config->openMethods[] = 'my.profile';
+$config->openMethods[] = 'my.settutorialconfig';
/* Define the tables. */
define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`');
diff --git a/framework/api/entry.class.php b/framework/api/entry.class.php
index 225d71cf78..eb498ec90f 100644
--- a/framework/api/entry.class.php
+++ b/framework/api/entry.class.php
@@ -188,7 +188,7 @@ class baseEntry
header("Content-type: application/json");
header("HTTP/1.1 {$this->statusCode[$code]}");
- if($data) echo json_encode($data);
+ if($data) echo json_encode($data, JSON_HEX_TAG);
exit;
}
diff --git a/lib/base/front/front.class.php b/lib/base/front/front.class.php
index c1e9d597f3..a81a355823 100644
--- a/lib/base/front/front.class.php
+++ b/lib/base/front/front.class.php
@@ -490,11 +490,7 @@ class baseHTML
if(helper::inOnlyBodyMode()) return false;
global $lang, $app, $config;
- if(empty($label))
- {
- global $lang, $config;
- $label = $lang->goback;
- }
+ if(empty($label)) $label = $lang->goback;
$tab = $_COOKIE['tab'];
$referer = strtolower($_SERVER['HTTP_REFERER']);
diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php
index 2eae7ec696..373db1cbbc 100644
--- a/module/bug/view/create.html.php
+++ b/module/bug/view/create.html.php
@@ -327,7 +327,7 @@ js::set('moduleID', $moduleID);
session->bugList ? $this->session->bugList : $this->inlink('browse', "productID=$productID");?>
- goback, $browseLink, 'self', '', 'btn btn-wide');?>
+ goback, '', 'class="btn btn-wide"');?>
id);?>
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index d1238f0a8b..df6fe59f6e 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -296,7 +296,7 @@ $lang->createObjects['story'] = 'Story';
$lang->createObjects['task'] = 'Task';
$lang->createObjects['testcase'] = 'Case';
$lang->createObjects['execution'] = $lang->execution->common;
-$lang->createObjects['project'] = $lang->projectCommon;
+$lang->createObjects['project'] = 'Project';
$lang->createObjects['product'] = 'Product';
$lang->createObjects['program'] = 'Program';
$lang->createObjects['doc'] = 'Doc';
diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php
index 979a276a96..414d918862 100644
--- a/module/common/lang/menu.php
+++ b/module/common/lang/menu.php
@@ -94,7 +94,7 @@ $lang->my->menu->work['subMenu']->task = array('link' => "{$lang->task->comm
if($config->URAndSR) $lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
$lang->my->menu->work['subMenu']->story = "$lang->SRCommon|my|work|mode=story";
$lang->my->menu->work['subMenu']->bug = "{$lang->bug->common}|my|work|mode=bug";
-$lang->my->menu->work['subMenu']->testcase = "{$lang->testcase->common}|my|work|mode=testcase&type=assigntome";
+$lang->my->menu->work['subMenu']->testcase = array('link' => "{$lang->testcase->common}|my|work|mode=testcase&type=assigntome", 'subModule' => 'testtask');
$lang->my->menu->work['subMenu']->testtask = "{$lang->testtask->common}|my|work|mode=testtask&type=wait";
$lang->my->menu->work['menuOrder'][5] = 'task';
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index a97923eee7..634f5a18d5 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -296,7 +296,7 @@ $lang->createObjects['story'] = '需求';
$lang->createObjects['task'] = '任务';
$lang->createObjects['testcase'] = '用例';
$lang->createObjects['execution'] = $lang->execution->common;
-$lang->createObjects['project'] = $lang->projectCommon;
+$lang->createObjects['project'] = '项目';
$lang->createObjects['product'] = '产品';
$lang->createObjects['program'] = '项目集';
$lang->createObjects['doc'] = '文档';
diff --git a/module/common/model.php b/module/common/model.php
index e32d9b92a7..1c1d81a7eb 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -367,7 +367,8 @@ class commonModel extends model
foreach($lang->createIcons as $objectType => $objectIcon)
{
if(!isset($config->proVersion) and $objectType == 'effort') continue;
- if($config->systemMode == 'classic' and ($objectType == 'project' or $objectType == 'porgram')) continue;
+ if($config->systemMode == 'classic' and strpos('project|program', $objectType) !== false) continue;
+ if(!empty($_COOKIE['feedbackView']) and strpos('todo|effort', $objectType) === false) continue;
/* Change icon when object type is execution and mode is classic. */
if($config->systemMode == 'classic' and $objectType == 'execution') $objectIcon = 'project';
@@ -392,12 +393,13 @@ class commonModel extends model
$showCreateList = true;
$isOnlyBody = strpos('effort|doc', $objectType) !== false;
$iconWord = $objectType == 'doc' ? 'W' : ''; // No ducument icon, print word instead of icon.
+ $attr = $objectType == 'effort' ? "data-width='95%' class='iframe' data-toggle='modal'" : "class='iframe'";
$params = '';
- if($objectType == 'bug' or $objectType == 'testcase') $params = "productID=$productID";
+ if(strpos('bug|testcase|story', $objectType) !== false) $params = "productID=$productID";
if($objectType == 'doc') $params = "objectType=&objectID=0&libID=0";
- $html .= '' . html::a(helper::createLink($objectType, $createMethod, $params, '', $isOnlyBody), "$iconWord " . $lang->createObjects[$objectType], '', $isOnlyBody ? "class='iframe'" : '') . '';
+ $html .= '' . html::a(helper::createLink($objectType, $createMethod, $params, '', $isOnlyBody), "$iconWord " . $lang->createObjects[$objectType], '', $isOnlyBody ? $attr : '') . '';
}
}
@@ -1350,7 +1352,7 @@ EOD;
$executionPairs = array();
$object = $app->dbh->query('SELECT project,type FROM ' . TABLE_EXECUTION . " WHERE `id` = '$executionID'")->fetch();
$orderBy = $object->type == 'stage' ? 'ORDER BY `id` ASC' : 'ORDER BY `id` DESC';
- $executionList = $app->dbh->query("SELECT id,name FROM " . TABLE_EXECUTION . " WHERE `project` = '{$object->project}' $orderBy")->fetchAll();
+ $executionList = $app->dbh->query("SELECT id,name FROM " . TABLE_EXECUTION . " WHERE `project` = '{$object->project}' AND `deleted` = '0' $orderBy")->fetchAll();
foreach($executionList as $execution)
{
if($execution->id == $executionID) continue;
diff --git a/module/common/view/header.html.php b/module/common/view/header.html.php
index 56521cfb98..8d38bca3ff 100755
--- a/module/common/view/header.html.php
+++ b/module/common/view/header.html.php
@@ -19,7 +19,7 @@ include 'chosen.html.php';
diff --git a/module/custom/js/mode.js b/module/custom/js/mode.js
index b24c0ac56f..e69de29bb2 100644
--- a/module/custom/js/mode.js
+++ b/module/custom/js/mode.js
@@ -1,9 +0,0 @@
-$(function()
-{
- $('[name=mode]').change(function()
- {
- var mode = $(this).val();
- if(mode == 'new') $('#modeTips').html(newTips);
- if(mode == 'classic') $('#modeTips').html(classicTips);
- })
-})
diff --git a/module/custom/view/mode.html.php b/module/custom/view/mode.html.php
index bb1077a87d..1f7fbebd90 100644
--- a/module/custom/view/mode.html.php
+++ b/module/custom/view/mode.html.php
@@ -11,8 +11,6 @@
*/
?>
-upgrade->selectedModeTips['new'])?>
-custom->changeClassicTip)?>
|
diff --git a/module/doc/config.php b/module/doc/config.php
index c00a0fcf33..a8c78892f1 100644
--- a/module/doc/config.php
+++ b/module/doc/config.php
@@ -9,7 +9,7 @@ $config->doc->edit = new stdclass();
$config->doc->createlib->requiredFields = 'name';
$config->doc->editlib->requiredFields = 'name';
-$config->doc->create->requiredFields = 'title';
+$config->doc->create->requiredFields = 'lib,title';
$config->doc->edit->requiredFields = 'title';
$config->doc->customObjectLibs = 'files,customFiles';
diff --git a/module/doc/control.php b/module/doc/control.php
index 267e3b35f0..db0d4cbfe4 100644
--- a/module/doc/control.php
+++ b/module/doc/control.php
@@ -320,14 +320,18 @@ class doc extends control
if($this->config->systemMode == 'classic') unset($this->lang->doc->menu->execution['subMenu']);
}
- $lib = $this->doc->getLibByID($libID);
- $type = !empty($lib) ? $lib->type : 'product';
+ /* Get libs and the default lib id. */
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
+ $libs = $this->doc->getLibs($objectType, $extra = "withObject,$unclosed", $libID, $objectID);
+ if(!$libID and !empty($libs)) $libID = key($libs);
+
+ $lib = $this->doc->getLibByID($libID);
+ $type = !empty($lib) ? $lib->type : 'product';
if(!isonlybody()) $this->view->title = $lib->name . $this->lang->colon . $this->lang->doc->create;
$this->view->libID = $libID;
- $this->view->libs = $this->doc->getLibs($objectType, $extra = "withObject,$unclosed", $libID, $objectID);
+ $this->view->libs = $libs;
$this->view->libName = $this->dao->findByID($libID)->from(TABLE_DOCLIB)->fetch('name');
$this->view->moduleOptionMenu = $this->tree->getOptionMenu($libID, 'doc', $startModuleID = 0);
$this->view->moduleID = $moduleID ? (int)$moduleID : (int)$this->cookie->lastDocModule;
diff --git a/module/doc/js/edit.js b/module/doc/js/edit.js
index 433e028559..bae3663c3e 100644
--- a/module/doc/js/edit.js
+++ b/module/doc/js/edit.js
@@ -7,6 +7,7 @@ $(function()
$('#content').html(draft);
editor = KindEditor.instances[0];
editor.html(draft);
+ $('.kindeditor-ph').remove();
}
}, 100)
diff --git a/module/doc/model.php b/module/doc/model.php
index 0d998ab794..34b2071b52 100644
--- a/module/doc/model.php
+++ b/module/doc/model.php
@@ -61,7 +61,7 @@ class docModel extends model
{
if($lib->product != 0 and !isset($products[$lib->product])) continue;
if($lib->execution != 0 and !isset($executions[$lib->execution])) continue;
- if($lib->project != 0 and !isset($project[$lib->project])) continue;
+ if($lib->project != 0 and !isset($projects[$lib->project]) and $lib->type == 'project') continue;
if($this->checkPrivLib($lib, $extra))
{
@@ -499,6 +499,12 @@ class docModel extends model
->remove('files,labels,uid,contactListMenu')
->get();
+ if(empty($doc->lib))
+ {
+ dao::$errors['lib'] = sprintf($this->lang->error->notempty, $this->lang->doc->lib);
+ return false;
+ }
+
/* Fix bug #2929. strip_tags($this->post->contentMarkdown, $this->config->allowedTags)*/
$doc = $this->loadModel('file')->processImgURL($doc, $this->config->doc->editor->create['id'], $this->post->uid);
$doc->contentMarkdown = $this->post->contentMarkdown;
@@ -2304,7 +2310,7 @@ EOT;
{
$libs = $this->getLibsByObject('book', 0, '', $appendLib);
$this->app->rawMethod = 'book';
- if($libID == 0 and !empty($libs)) $libID = reset($libs)->id;
+ if(!empty($libs) and ($libID == 0 or !isset($libs[$libID]))) $libID = reset($libs)->id;
$this->lang->modulePageNav = $this->select($type, $objects, $objectID, $libs, $libID);
$object = new stdclass();
diff --git a/module/doc/view/tablecontents.html.php b/module/doc/view/tablecontents.html.php
index e54b1de5a8..fa0adfb0db 100644
--- a/module/doc/view/tablecontents.html.php
+++ b/module/doc/view/tablecontents.html.php
@@ -52,7 +52,7 @@ if(empty($type)) $type = 'product';
echo '';
}
- if($type == 'book' and ($canEditLib or $canManageBook))
+ if($type == 'book' and ($canEditLib or $canManageBook) and !empty($libs))
{
echo "