Merge branch 'release/zentaopms_18.3'

This commit is contained in:
wangyidong
2023-04-10 13:19:50 +08:00
170 changed files with 3050 additions and 4573 deletions
+4
View File
@@ -311,6 +311,7 @@ define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`');
define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`');
define('TABLE_CRON', '`' . $config->db->prefix . 'cron`');
define('TABLE_BLOCK', '`' . $config->db->prefix . 'block`');
define('TABLE_DOCACTION', '`' . $config->db->prefix . 'docaction`');
define('TABLE_DOCCONTENT', '`' . $config->db->prefix . 'doccontent`');
define('TABLE_TESTSUITE', '`' . $config->db->prefix . 'testsuite`');
define('TABLE_SUITECASE', '`' . $config->db->prefix . 'suitecase`');
@@ -442,3 +443,6 @@ $config->featureGroup->agileplus = array();
$config->featureGroup->waterfallplus = array();
$config->featureGroup->assetlib = array();
$config->featureGroup->other = array('devops', 'kanban');
$config->bi = new stdclass();
$config->bi->pickerHeight = 150;
+26 -5
View File
@@ -21,12 +21,12 @@ CREATE TABLE IF NOT EXISTS `zt_pivot` (
`desc` text NOT NULL,
`sql` mediumtext NOT NULL,
`fields` mediumtext NOT NULL,
`langs` mediumtext NOT NULL,
`langs` mediumtext NULL,
`vars` mediumtext NOT NULL,
`objects` mediumtext NULL,
`settings` mediumtext NOT NULL,
`filters` mediumtext NOT NULL,
`step` tinyint(1) unsigned NOT NULL,
`step` tinyint(1) unsigned NOT NULL DEFAULT '',
`stage` enum('draft','published') NOT NULL DEFAULT 'draft',
`builtin` enum('0', '1') NOT NULL DEFAULT '0',
`createdBy` varchar(30) NOT NULL,
@@ -44,10 +44,11 @@ CREATE TABLE `zt_chart_back` SELECT * FROM `zt_chart`;
ALTER TABLE `zt_chart` MODIFY `fields` mediumtext NOT NULL;
ALTER TABLE `zt_chart` MODIFY `group` varchar(255) NOT NULL;
ALTER TABLE `zt_chart` ADD `stage` enum('draft','published') NOT NULL DEFAULT 'draft' AFTER `sql`;
ALTER TABLE `zt_chart` ADD `langs` text NOT NULL AFTER `fields`;
ALTER TABLE `zt_chart` ADD `step` tinyint(1) unsigned NOT NULL AFTER `filters`;
ALTER TABLE `zt_chart` ADD `langs` text NULL AFTER `fields`;
ALTER TABLE `zt_chart` ADD `step` tinyint(1) unsigned NOT NULL DEFAULT '0' AFTER `filters`;
ALTER TABLE `zt_chart` DROP `dataset`;
ALTER TABLE `zt_dataview` ADD `langs` text NOT NULL AFTER `fields`;
ALTER TABLE `zt_dataview` ADD `langs` text NULL AFTER `fields`;
ALTER TABLE `zt_screen` ADD `status` enum('draft','published') NOT NULL DEFAULT 'draft' AFTER `scheme`;
ALTER TABLE `zt_screen` ADD `builtin` enum('0', '1') NOT NULL DEFAULT '0' AFTER `status`;
@@ -151,6 +152,15 @@ SELECT t1.`group`, t1.`module`, 'editCatalog' FROM `zt_grouppriv` AS t1 WHERE t1
INSERT IGNORE INTO `zt_grouppriv` (`group`, `module`, `method`)
SELECT t1.`group`, t1.`module`, 'deleteCatalog' FROM `zt_grouppriv` AS t1 WHERE t1.`module` = 'doc' AND t1.`method` = 'catalog';
INSERT IGNORE INTO `zt_grouppriv` (`group`, `module`, `method`)
SELECT t1.`group`, 'api', 'addCatalog' FROM `zt_grouppriv` AS t1 WHERE t1.`module` = 'doc' AND t1.`method` = 'catalog';
INSERT IGNORE INTO `zt_grouppriv` (`group`, `module`, `method`)
SELECT t1.`group`, 'api', 'editCatalog' FROM `zt_grouppriv` AS t1 WHERE t1.`module` = 'doc' AND t1.`method` = 'catalog';
INSERT IGNORE INTO `zt_grouppriv` (`group`, `module`, `method`)
SELECT t1.`group`, 'api', 'deleteCatalog' FROM `zt_grouppriv` AS t1 WHERE t1.`module` = 'doc' AND t1.`method` = 'catalog';
UPDATE `zt_grouppriv` SET `method` = 'mySpace' WHERE `module` = 'doc' AND `method` = 'browse';
ALTER TABLE `zt_account`
@@ -738,3 +748,14 @@ CHANGE `editedDate` `editedDate` datetime NULL;
ALTER TABLE `zt_zoutput`
CHANGE `editedBy` `editedBy` varchar(30) NOT NULL DEFAULT '',
CHANGE `editedDate` `editedDate` datetime NULL;
CREATE TABLE IF NOT EXISTS `zt_docaction` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`doc` mediumint(8) unsigned NOT NULL,
`action` varchar(80) NOT NULL,
`actor` char(30) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `doc` (`doc`),
KEY `actor` (`actor`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+16 -5
View File
@@ -442,9 +442,9 @@ CREATE TABLE IF NOT EXISTS `zt_chart` (
`desc` text NOT NULL,
`settings` mediumtext NOT NULL,
`filters` mediumtext NOT NULL,
`step` tinyint(1) unsigned NOT NULL,
`step` tinyint(1) unsigned NOT NULL DEFAULT '0',
`fields` mediumtext NOT NULL,
`langs` text NOT NULL,
`langs` text NULL,
`sql` mediumtext,
`stage` enum('draft','published') NOT NULL DEFAULT 'draft',
`builtin` tinyint(1) unsigned NOT NULL,
@@ -584,7 +584,7 @@ CREATE TABLE IF NOT EXISTS `zt_dataview` (
`view` varchar(57) NOT NULL,
`sql` text NOT NULL,
`fields` mediumtext NOT NULL,
`langs` text NOT NULL,
`langs` text NULL,
`objects` mediumtext NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
@@ -686,6 +686,17 @@ CREATE TABLE IF NOT EXISTS `zt_doc` (
KEY `execution` (`execution`),
KEY `lib` (`lib`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_docaction`;
CREATE TABLE IF NOT EXISTS `zt_docaction` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`doc` mediumint(8) unsigned NOT NULL,
`action` varchar(80) NOT NULL,
`actor` char(30) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `doc` (`doc`),
KEY `actor` (`actor`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_doccontent`;
CREATE TABLE IF NOT EXISTS `zt_doccontent` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
@@ -14008,12 +14019,12 @@ CREATE TABLE IF NOT EXISTS `zt_pivot` (
`desc` text NOT NULL,
`sql` mediumtext NOT NULL,
`fields` mediumtext NOT NULL,
`langs` mediumtext NOT NULL,
`langs` mediumtext NULL,
`vars` mediumtext NOT NULL,
`objects` mediumtext NULL,
`settings` mediumtext NOT NULL,
`filters` mediumtext NOT NULL,
`step` tinyint(1) unsigned NOT NULL,
`step` tinyint(1) unsigned NOT NULL DEFAULT '0',
`stage` enum('draft','published') NOT NULL DEFAULT 'draft',
`builtin` enum('0', '1') NOT NULL DEFAULT '0',
`createdBy` varchar(30) NOT NULL,
@@ -83,7 +83,7 @@ $lang->kanbanProject->menu = new stdclass();
$lang->kanbanProject->menu->index = array('link' => "{$lang->dashboard}|project|index|project=%s");
$lang->kanbanProject->menu->execution = array('link' => "$lang->executionKanban|project|execution|status=all&projectID=%s", 'subModule' => 'execution,task');
$lang->kanbanProject->menu->story = array('link' => "{$lang->project->target}|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree,story', 'alias' => 'story,track');
$lang->kanbanProject->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=project&objectID=%s", 'subModule' => 'doc');
$lang->kanbanProject->menu->doc = array('link' => "{$lang->doc->common}|doc|projectSpace|objectID=%s", 'subModule' => 'doc');
$lang->kanbanProject->menu->dynamic = array('link' => "$lang->dynamic|project|dynamic|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');
@@ -117,8 +117,8 @@ $lang->SRCommon = '目标';
/* Doc menu. */
$lang->doc->menu = new stdclass();
$lang->doc->menu->dashboard = array('link' => "{$lang->dashboard}|doc|index");
$lang->doc->menu->my = array('link' => "{$lang->doc->mySpace}|doc|browse|browseTyp=openedbyme", 'alias' => 'my');
$lang->doc->menu->project = array('link' => "{$lang->doc->projectSpace}|doc|tableContents|type=project", 'alias' => 'showfiles,project');
$lang->doc->menu->my = array('link' => "{$lang->doc->mySpace}|doc|mySpace|type=mine", 'alias' => 'my');
$lang->doc->menu->project = array('link' => "{$lang->doc->projectSpace}|doc|projectSpace", 'alias' => 'showfiles,project');
$lang->doc->menu->custom = array('link' => "{$lang->doc->teamSpace}|doc|tableContents|type=custom", 'alias' => 'custom');
$lang->doc->dividerMenu = ',project,';
+43 -30
View File
@@ -584,35 +584,49 @@ $lang->task->methodOrder[125] = 'import';
/* Doc. */
$lang->resource->doc = new stdclass();
$lang->resource->doc->index = 'index';
$lang->resource->doc->browse = 'browse';
$lang->resource->doc->createLib = 'createLib';
$lang->resource->doc->editLib = 'editLib';
$lang->resource->doc->deleteLib = 'deleteLib';
$lang->resource->doc->create = 'create';
$lang->resource->doc->view = 'view';
$lang->resource->doc->edit = 'edit';
$lang->resource->doc->delete = 'delete';
$lang->resource->doc->deleteFile = 'deleteFile';
$lang->resource->doc->allLibs = 'allLibs';
$lang->resource->doc->objectLibs = 'objectLibs';
$lang->resource->doc->collect = 'collectAction';
$lang->resource->doc->tableContents = 'tableContents';
$lang->resource->doc->index = 'index';
$lang->resource->doc->mySpace = 'mySpace';
$lang->resource->doc->myView = 'myView';
$lang->resource->doc->myCollection = 'myCollection';
$lang->resource->doc->myCreation = 'myCreation';
$lang->resource->doc->createLib = 'createLib';
$lang->resource->doc->editLib = 'editLib';
$lang->resource->doc->deleteLib = 'deleteLib';
$lang->resource->doc->create = 'create';
$lang->resource->doc->view = 'view';
$lang->resource->doc->edit = 'edit';
$lang->resource->doc->delete = 'delete';
$lang->resource->doc->deleteFile = 'deleteFile';
$lang->resource->doc->collect = 'collectAction';
$lang->resource->doc->projectSpace = 'projectSpace';
$lang->resource->doc->tableContents = 'teamSpace';
$lang->resource->doc->showFiles = 'showFiles';
$lang->resource->doc->addCatalog = 'addCatalog';
$lang->resource->doc->editCatalog = 'editCatalog';
$lang->resource->doc->deleteCatalog = 'deleteCatalog';
$lang->resource->doc->displaySetting = 'displaySetting';
$lang->doc->methodOrder[0] = 'index';
$lang->doc->methodOrder[5] = 'browse';
$lang->doc->methodOrder[10] = 'createLib';
$lang->doc->methodOrder[15] = 'editLib';
$lang->doc->methodOrder[20] = 'deleteLib';
$lang->doc->methodOrder[25] = 'create';
$lang->doc->methodOrder[30] = 'view';
$lang->doc->methodOrder[35] = 'edit';
$lang->doc->methodOrder[40] = 'delete';
$lang->doc->methodOrder[45] = 'deleteFile';
$lang->doc->methodOrder[50] = 'allLibs';
$lang->doc->methodOrder[55] = 'objectLibs';
$lang->doc->methodOrder[60] = 'collect';
$lang->doc->methodOrder[65] = 'tableContents';
$lang->doc->methodOrder[5] = 'index';
$lang->doc->methodOrder[10] = 'mySpace';
$lang->doc->methodOrder[15] = 'myView';
$lang->doc->methodOrder[20] = 'myCollection';
$lang->doc->methodOrder[25] = 'myCreation';
$lang->doc->methodOrder[30] = 'createLib';
$lang->doc->methodOrder[35] = 'editLib';
$lang->doc->methodOrder[40] = 'deleteLib';
$lang->doc->methodOrder[45] = 'create';
$lang->doc->methodOrder[50] = 'edit';
$lang->doc->methodOrder[55] = 'view';
$lang->doc->methodOrder[60] = 'delete';
$lang->doc->methodOrder[65] = 'deleteFile';
$lang->doc->methodOrder[70] = 'collect';
$lang->doc->methodOrder[75] = 'projectSpace';
$lang->doc->methodOrder[80] = 'tableContents';
$lang->doc->methodOrder[85] = 'showFiles';
$lang->doc->methodOrder[90] = 'addCatalog';
$lang->doc->methodOrder[95] = 'editCatalog';
$lang->doc->methodOrder[100] = 'deleteCatalog';
$lang->doc->methodOrder[105] = 'displaySetting';
/* Mail. */
$lang->resource->mail = new stdclass();
@@ -1171,8 +1185,7 @@ if($config->edition == 'biz' or $config->edition == 'max')
$lang->tree->methodOrder[35] = 'editHost';
$lang->host->methodOrder[40] = 'groupMaintenance';
$lang->resource->doc->diff = 'diffAction';
$lang->resource->doc->catalog = 'catalogAction';
$lang->resource->doc->diff = 'diffAction';
$lang->resource->my->review = 'review';
+33
View File
@@ -398,4 +398,37 @@ class dbh
{
return $this->pdo->lastInsertId($name);
}
/**
* Begin transaction.
*
* @access public
* @return bool
*/
public function beginTransaction()
{
return $this->pdo->beginTransaction();
}
/**
* Roll back if transaction failed.
*
* @access public
* @return bool
*/
public function rollBack()
{
return $this->pdo->rollBack();
}
/**
* Commit transaction.
*
* @access public
* @return bool
*/
public function commit()
{
return $this->pdo->commit();
}
}
+45 -13
View File
@@ -49,6 +49,12 @@ class api extends control
$objectID = $this->objectID;
$isFirstLoad = $libID ? false : true;
if($release)
{
$browseType = 'byrelease';
$param = $release;
}
/* Get all api doc libraries. */
$libs = $this->doc->getApiLibs($appendLib, $objectType, $objectID);
if(empty($libs) and $objectType != 'nolink')
@@ -125,7 +131,7 @@ class api extends control
$this->view->objectID = $objectID;
$this->view->moduleID = $moduleID;
$this->view->version = $version;
$this->view->libTree = $this->doc->getLibTree($libID, $libs, 'api', $moduleID, $objectID, $browseType);
$this->view->libTree = $this->doc->getLibTree($libID, $libs, 'api', $moduleID, $objectID, $browseType, $param);
$this->view->users = $this->user->getPairs('noclosed,noletter');
$this->view->objectDropdown = isset($libs[$libID]) ? $this->generateLibsDropMenu($libs[$libID], $release) : '';
@@ -178,24 +184,22 @@ class api extends control
/**
* Release list.
*
* @param int $libID
* @param int $libID
* @param string $orderBy
* @access public
* @return void
*/
public function releases($libID, $orderBy = 'id', $recTotal = 0, $recPerPage = 15, $pageID = 1)
public function releases($libID, $orderBy = 'id')
{
$libs = $this->doc->getApiLibs();
$this->app->loadClass('pager', $static = true);
$this->lang->modulePageNav = $this->generateLibsDropMenu($libs[$libID]);
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Append id for secend sort. */
$sort = common::appendOrder($orderBy);
$releases = $this->api->getReleaseByQuery($libID, $pager, $sort);
$releases = $this->api->getReleaseByQuery($libID, '', $sort);
$this->view->releases = $releases;
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
$this->view->title = $this->lang->api->managePublish;
$this->view->libID = $libID;
@@ -218,7 +222,7 @@ class api extends control
{
$this->api->deleteRelease($id);
if(dao::isError()) return $this->sendError(dao::getError());
return print(js::locate(inlink('releases', "libID=$libID"), 'parent'));
return print(js::execute("parent.removeRelease($id)"));
}
}
@@ -236,6 +240,7 @@ class api extends control
if(!empty($_POST))
{
$data = fixer::input('post')
->trim('version')
->add('lib', $libID)
->add('addedBy', $this->app->user->account)
->add('addedDate', helper::now())
@@ -316,6 +321,7 @@ class api extends control
$now = helper::now();
$userId = $this->app->user->account;
$data = fixer::input('post')
->trim('name')
->add('lib', $libID)
->skipSpecial('attribute')
->add('addedBy', $userId)
@@ -414,8 +420,6 @@ class api extends control
*/
public function createLib($type = 'product', $objectID = 0)
{
if(!in_array($type, array('product', 'project'))) $type = 'product';
if(!empty($_POST))
{
$libID = $this->doc->createApiLib();
@@ -433,7 +437,8 @@ class api extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('api', 'index', "libID=$libID")));
}
$this->lang->api->aclList['default'] = sprintf($this->lang->api->aclList['default'], $this->lang->{$type}->common);
$defaultAclLang = in_array($type, array('product', 'product')) ? $this->lang->{$type}->common : $this->lang->product->common;
$this->lang->api->aclList['default'] = sprintf($this->lang->api->aclList['default'], $defaultAclLang);
$this->view->type = $type;
$this->view->objectID = $objectID;
@@ -525,6 +530,7 @@ class api extends control
*/
public function edit($apiID)
{
$api = $this->api->getLibById($apiID);
if(helper::isAjaxRequest() && !empty($_POST))
{
$changes = $this->api->update($apiID);
@@ -536,10 +542,9 @@ class api extends control
$this->action->logHistory($actionID, $changes);
}
return $this->sendSuccess(array('locate' => helper::createLink('api', 'index', "libID=0&moduleID=0&apiID=$apiID")));
return $this->sendSuccess(array('locate' => helper::createLink('api', 'index', "libID=$api->lib&moduleID=0&apiID=$apiID")));
}
$api = $this->api->getLibById($apiID);
if($api)
{
$this->view->api = $api;
@@ -931,4 +936,31 @@ class api extends control
$this->display();
}
/**
* Edit a catalog.
*
* @param int $moduleID
* @param string $type doc|api
* @access public
* @return void
*/
public function editCatalog($moduleID, $type)
{
echo $this->fetch('tree', 'edit', "moduleID=$moduleID&type=$type");
}
/**
* Delete a catalog.
*
* @param int $rootID
* @param int $moduleID
* @param string $confirm yes|no
* @access public
* @return void
*/
public function deleteCatalog($rootID, $moduleID, $confirm = 'no')
{
echo $this->fetch('tree', 'delete', "rootID=$rootID&moduleID=$moduleID&confirm=$confirm");
}
}
+1
View File
@@ -3,3 +3,4 @@ form {margin-bottom: 100px;}
table {width: 90% !important;}
#whiteListBox div.input-group {margin-bottom: 2px;}
#whiteListBox .input-group:last-child {margin-top: 10px;}
#aclBox > th {vertical-align: top; padding-top: 18px;}
+2
View File
@@ -2,3 +2,5 @@
.c-actions {width: 60px;}
tbody tr td {white-space: nowrap; overflow: hidden; text-overflow: clip;}
#mainContent {max-height: 400px;}
#releaseListForm {margin-bottom: 20px;}
+3 -1
View File
@@ -1,4 +1,4 @@
$(document).ready(function()
$(function()
{
$('#apiForm').ajaxForm({
success: (data) => {
@@ -10,4 +10,6 @@ $(document).ready(function()
}
}
})
toggleLibType(libType);
});
+3
View File
@@ -61,6 +61,9 @@ $lang->api->zentaoAPI = "Zentao API v1";
$lang->api->search = "Search";
$lang->api->allLibs = "AllLibs";
$lang->api->noLinked = "No Linked";
$lang->api->addCatalog = 'Add Catalog';
$lang->api->editCatalog = 'Edit Catalog';
$lang->api->deleteCatalog = 'Delete Catalog';
/* Common access control lang. */
$lang->api->whiteList = 'Whitelist';
+3
View File
@@ -61,6 +61,9 @@ $lang->api->zentaoAPI = "Zentao API v1";
$lang->api->search = "Search";
$lang->api->allLibs = "AllLibs";
$lang->api->noLinked = "No Linked";
$lang->api->addCatalog = 'Add Catalog';
$lang->api->editCatalog = 'Edit Catalog';
$lang->api->deleteCatalog = 'Delete Catalog';
/* Common access control lang. */
$lang->api->whiteList = 'Whitelist';
+3
View File
@@ -61,6 +61,9 @@ $lang->api->zentaoAPI = "Zentao API v1";
$lang->api->search = "Search";
$lang->api->allLibs = "AllLibs";
$lang->api->noLinked = "No Linked";
$lang->api->addCatalog = 'Add Catalog';
$lang->api->editCatalog = 'Edit Catalog';
$lang->api->deleteCatalog = 'Delete Catalog';
/* Common access control lang. */
$lang->api->whiteList = 'Whitelist';
+3
View File
@@ -61,6 +61,9 @@ $lang->api->zentaoAPI = "禅道API文档v1";
$lang->api->search = "搜索";
$lang->api->allLibs = "全部库";
$lang->api->noLinked = "无关联";
$lang->api->addCatalog = '添加目录';
$lang->api->editCatalog = '编辑目录';
$lang->api->deleteCatalog = '删除目录';
/* Common access control lang. */
$lang->api->whiteList = '白名单';
+3 -7
View File
@@ -168,6 +168,7 @@ class apiModel extends model
$now = helper::now();
$data = fixer::input('post')
->trim('name')
->skipSpecial('attribute')
->add('lib', $old->lib)
->add('editedBy', $this->app->user->account)
@@ -414,10 +415,7 @@ class apiModel extends model
foreach($rel->snap['modules'] as $module)
{
$tmp = explode(',', $module['path']);
if(in_array($moduleID, $tmp))
{
$sub[] = $module['id'];
}
if(in_array($moduleID, $tmp)) $sub[] = $module['id'];
}
if($sub) $where .= 'and module in (' . implode(',', $sub) . ')';
}
@@ -434,9 +432,7 @@ class apiModel extends model
{
$where = 'lib = ' . $libID;
}
$list = $this->dao->select('*')
->from(TABLE_API)
->where($where)
$list = $this->dao->select('*')->from(TABLE_API)->where($where)
->andWhere('deleted')->eq(0)
->page($pager)
->fetchAll();
+1
View File
@@ -79,4 +79,5 @@
</div>
<?php js::set('productLang', $lang->productCommon);?>
<?php js::set('projectLang', $lang->projectCommon);?>
<?php js::set('libType', $type);?>
<?php include '../../common/view/footer.lite.html.php';?>
+2 -2
View File
@@ -26,7 +26,7 @@
if($libTree and common::hasPriv('api', 'releases')) echo html::a($this->createLink('api', 'releases', "libID=$libID", 'html', true), "<i class='icon-version muted'> </i>" . $lang->api->releases, '', "class='btn btn-link iframe' data-width='800px'");
if($libTree and common::hasPriv('api', 'createRelease')) echo html::a($this->createLink('api', 'createRelease', "libID=$libID"), "<i class='icon-publish muted'> </i>" . $lang->api->createRelease, '', "class='btn btn-link iframe' data-width='800px'");
if($libTree and common::hasPriv('api', 'export') and $config->edition != 'open') echo html::a($this->createLink('api', 'export', "libID=$libID&version=$version&release=$release", 'html', true), "<i class='icon-export muted'> </i>" . $lang->export, '', "class='btn btn-link export' data-width='480px' id='export'");
if(common::hasPriv('api', 'createLib')) echo html::a($this->createLink('api', 'createLib', "type=" . ($objectType == 'project' ? 'project' : 'product') . "&objectID=$objectID"), '<i class="icon icon-plus"></i> ' . $lang->api->createLib, '', 'class="btn btn-secondary iframe" data-width="800px"');
if(common::hasPriv('api', 'createLib')) echo html::a($this->createLink('api', 'createLib', "type=" . ($objectType ? $objectType : 'nolink') . "&objectID=$objectID"), '<i class="icon icon-plus"></i> ' . $lang->api->createLib, '', 'class="btn btn-secondary iframe" data-width="800px"');
if($libTree and common::hasPriv('api', 'create')) echo html::a($this->createLink('api', 'create', "libID=$libID&moduleID=$moduleID"), '<i class="icon icon-plus"></i> ' . $lang->api->createApi, '', 'class="btn btn-primary"');
?>
</div>
@@ -37,7 +37,7 @@
<p>
<span class="text-muted"><?php echo $lang->doc->noLib;?></span>
<?php
if(common::hasPriv('api', 'createLib')) echo html::a(helper::createLink('api', 'createLib', "type=$objectType"), '<i class="icon icon-plus"></i> ' . $lang->api->createLib, '', 'class="btn btn-info iframe" data-width="800px"');
if(common::hasPriv('api', 'createLib')) echo html::a(helper::createLink('api', 'createLib', "type=" . ($objectType ? $objectType : 'nolink')), '<i class="icon icon-plus"></i> ' . $lang->api->createLib, '', 'class="btn btn-info iframe" data-width="800px"');
?>
</p>
</div>
+17 -7
View File
@@ -13,7 +13,6 @@
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row fade'>
<div class='main-col'>
<div class="cell" id="queryBox" data-module='user'></div>
<div id='mainMenu' class='clearfix'>
<div class='main-header'>
<h2><?php echo $lang->api->managePublish;?></h2>
@@ -24,11 +23,11 @@
<p><span class="text-muted"><?php echo $lang->noData;?></span></p>
</div>
<?php else:?>
<form class='main-table table-user' data-ride='table' method='post' data-checkable='false' id='userListForm'>
<table class='table has-sort-head' id='userList'>
<form class='main-table' method='post' id='releaseListForm'>
<table class='table has-sort-head' id='releaseList'>
<thead>
<tr>
<?php $vars = "libID={$libID}&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}";?>
<?php $vars = "libID={$libID}&orderBy=%s";?>
<th class='c-id'><?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
<th class='c-version'><?php common::printOrderLink('version', $orderBy, $vars, $lang->api->version);?></th>
<th class='c-name'><?php echo $lang->api->desc;?></th>
@@ -39,10 +38,10 @@
</thead>
<tbody>
<?php foreach($releases as $release):?>
<tr>
<tr data-id="<?php echo $release->id;?>">
<td><?php printf('%03d', $release->id);?></td>
<td title=<?php echo $release->version;?>><?php echo $release->version;?></td>
<td><?php echo $release->desc;?></td>
<td title=<?php echo $release->desc;?>><?php echo $release->desc;?></td>
<td><?php echo zget($users, $release->addedBy, '');?></td>
<td class="c-date"><?php echo $release->addedDate;?></td>
<td class='c-actions'>
@@ -52,7 +51,6 @@
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
</form>
<?php endif;?>
</div>
@@ -62,5 +60,17 @@ parent.$('#triggerModal .modal-content .modal-header .close').click(function()
{
parent.location.reload();
});
/**
* Remove release.
*
* @param int $releaseID
* @access public
* @return void
*/
function removeRelease(releaseID)
{
$('tr[data-id=' + releaseID + ']').remove()
}
</script>
<?php include '../../common/view/footer.html.php';?>
+9
View File
@@ -0,0 +1,9 @@
<?php
$config->chart->widthInput = 128;
$config->chart->widthDate = 248;
$config->chart->dateConvert = array();
$config->chart->dateConvert['year'] = 'YEAR';
$config->chart->dateConvert['month'] = 'MONTH';
$config->chart->dateConvert['week'] = 'YEARWEEK';
$config->chart->dateConvert['day'] = 'DATE';
+257
View File
@@ -0,0 +1,257 @@
<?php
/**
* The control file of chart module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package chart
* @version $Id: model.php 5086 2013-07-10 02:25:22Z wyd621@gmail.com $
* @link http://www.zentao.net
*/
class chart extends control
{
/**
* Preview charts of a group.
*
* @param int $dimensionID
* @param int $groupID
* @access public
* @return void
*/
public function preview($dimensionID = 0, $groupID = 0)
{
$dimensionID = $this->loadModel('dimension')->setSwitcherMenu($dimensionID);
if(!$groupID) $groupID = $this->chart->getFirstChartGroupID($dimensionID);
list($chartTree, $charts) = $this->chart->getPreviewCharts($groupID);
if(!empty($_POST))
{
$charts = array();
foreach($this->post->charts as $value)
{
$chartID = explode('_', $value);
$group = $chartID[0];
$chartID = $chartID[1];
$chart = $this->chart->getByID($chartID);
$chart->currentGroup = $group;
$charts[] = $chart;
}
}
$this->view->title = $this->lang->chart->preview;
$this->view->dimensionID = $dimensionID;
$this->view->group = $this->loadModel('tree')->getByID($groupID);
$this->view->chartTree = $chartTree;
$this->view->charts = $charts;
$this->view->groups = $this->loadModel('tree')->getGroupPairs($dimensionID, 0, 1);
$this->display();
}
/**
* Ajax get filter form html.
*
* @param int $chartID
* @access public
* @return string
*/
public function ajaxGetFilterForm($chartID)
{
$fieldList = $this->post->fieldList;
$filters = $this->post->filters;
$fieldSettings = $this->post->fieldSettings;
$langs = $this->post->langs;
$clientLang = $this->app->getClientLang();
$fieldPairs = array();
foreach($fieldList as $field => $fieldName)
{
$fieldObject = $fieldSettings[$field]['object'];
$relatedField = $fieldSettings[$field]['field'];
$this->app->loadLang($fieldObject);
$fieldPairs[$field] = isset($this->lang->$fieldObject->$relatedField) ? $this->lang->$fieldObject->$relatedField : $field;
if(!isset($langs[$field])) continue;
if(!empty($langs[$field][$clientLang])) $fieldPairs[$field] = $langs[$field][$clientLang];
}
$htmls = array();
foreach($filters as $filter)
{
$field = $filter['field'];
$type = $filter['type'];
$default = isset($filter['default']) ? $filter['default'] : '';
$options = array();
if($type == 'select')
{
$fieldSetting = $fieldSettings[$field];
$options = $this->chart->getSysOptions(zget($fieldSetting, 'type', ''), zget($fieldSetting, 'object', ''), zget($fieldSetting, 'field', ''));
}
$filterHtml = array();
/* field html */
$filterHtml['field'] = html::select('field', $fieldPairs, $field, "class='form-control picker-select' onchange='initFilterForm(this, this.value)'");
/* default html */
$filterHtml['default'] = '';
if($type == 'input') $filterHtml['default'] .= html::input('default', $default, "class='form-control' onchange='changeDefault(this,this.value)'");
if($type == 'date' or $type == 'datetime')
{
if(empty($default)) $default = array('begin' => '', 'end' => '');
$class = $type == 'date' ? 'form-date' : 'form-datetime';
$filterHtml['default'] .= '<div class="input-group">';
$filterHtml['default'] .= html::input('default[begin]', $default['begin'], "class='form-control $class default-begin' placeholder='{$this->lang->chart->unlimited}' onchange='changeDefault(this,this.value)'");
$filterHtml['default'] .= "<span class='input-group-addon fix-border borderBox' style='border-radius: 0px;'>{$this->lang->chart->colon}</span>";
$filterHtml['default'] .= html::input('default[end]', $default['end'], "class='form-control $class default-end' placeholder='{$this->lang->chart->unlimited}' onchange='changeDefault(this,this.value)'");
$filterHtml['default'] .= '</div>';
}
if($type == 'select') $filterHtml['default'] = html::select('default[]', $options, $default, "class='form-control picker-select' onchange='changeDefault(this,this.value)' multiple");
if($type == 'condition')
{
$operator = isset($filter['operator']) ? $filter['operator'] : '';
$value = isset($filter['value']) ? $filter['value'] : '';
$hidden = strpos($operator, 'NULL') !== false ? 'hidden' : '';
$filterHtml['default'] = "<div class='conditionGroup' style='display:flex'>";
$filterHtml['default'] .= html::select('operator', $this->config->bi->conditionList, $operator, "class='form-control picker-select' onchange='changeCondition(this,this.value)'");
$filterHtml['default'] .= html::input('value', $value, "class='form-control $hidden' onchange='changeConditionValue(this,this.value)'");
$filterHtml['default'] .= "<div/>";
}
/* type html */
$filterHtml['type'] = html::select('type', $this->lang->chart->fieldTypeList, $type, "class='form-control picker-select' onchange='changeType(this, this.value)'");
/* filter item html */
$filterHtml['item'] = '';
if($type == 'input') $filterHtml['item'] .= html::input('default', $default, "class='form-control'");
if($type == 'date' or $type == 'datetime')
{
if(empty($default)) $default = array('begin' => '', 'end' => '');
$class = $type == 'date' ? 'form-date' : 'form-datetime';
$filterHtml['item'] .= '<div class="input-group">';
$filterHtml['item'] .= "<input type='text' name='default[begin]' id='default[begin]' value='{$default['begin']}' class='form-control $class default-begin' autocomplete='off' placeholder='{$this->lang->chart->unlimited}' onchange='changeDefault(this, this.value)'>";
$filterHtml['item'] .= '<span class="input-group-addon fix-border borderBox" style="border-radius: 0px;">' . $this->lang->chart->colon . '</span>';
$filterHtml['item'] .= "<input type='text' name='default[end]' id='default[end]' value='{$default['end']}' class='form-control $class default-end' autocomplete='off' placeholder='{$this->lang->chart->unlimited}' onchange='changeDefault(this, this.value)'>";
$filterHtml['item'] .= '</div>';
}
if($type == 'select') $filterHtml['item'] .= html::select('default', array('' => '') + $options, $default, "class='form-control picker-select' multiple");
if($type == 'condition')
{
$operator = isset($filter['operator']) ? $filter['operator'] : '';
$value = isset($filter['value']) ? $filter['value'] : '';
$hidden = strpos($operator, 'NULL') !== false ? 'hidden' : '';
$filterHtml['item'] = "<div class='conditionGroup' style='display:flex'>";
$filterHtml['item'] .= html::select('operator', $this->config->bi->conditionList, $operator, "class='form-control picker-select' onchange='changeCondition(this,this.value, true)'");
$filterHtml['item'] .= html::input('value', $value, "class='form-control $hidden'");
$filterHtml['item'] .= "<div/>";
}
$htmls[] = $filterHtml;
}
echo json_encode($htmls);
}
/**
* Ajax get chart.
*
* @access public
* @return void
*/
public function ajaxGetChart()
{
$post = fixer::input('post')->skipSpecial('settings,filters,sql,langs')->get();
$chartID = $post->id;
$settings = current($post->settings);
$type = $settings['type'];
$filters = isset($_POST['searchFilters']) ? $_POST['searchFilters'] : (isset($_POST['filters']) ? $post->filters : array());
$chart = $this->chart->getByID($chartID);
$filterFormat = array();
foreach($filters as $filter)
{
$field = $filter['field'];
if(!isset($filter['default'])) continue;
$default = $filter['default'];
switch($filter['type'])
{
case 'select':
if(empty($default)) break;
$default = array_filter($default, function($val){return !empty($val);});
$value = "('" . implode("', '", $default) . "')";
$filterFormat[$field] = array('operator' => 'IN', 'value' => $value);
break;
case 'input':
$filterFormat[$field] = array('operator' => 'like', 'value' => "'%$default%'");
break;
case 'date':
case 'datetime':
$begin = $default['begin'];
$end = $default['end'];
if(empty($begin) or empty($end)) break;
$value = "'$begin' and '$end'";
$filterFormat[$field] = array('operator' => 'BETWEEN', 'value' => $value);
break;
case 'condition':
$operator = $filter['operator'];
$value = $filter['value'];
if(in_array($operator, array('IN', 'NOT IN')))
{
$valueArr = explode(',', $value);
foreach($valueArr as $key => $val) $valueArr[$key] = '"' . $val . '"';
$value = '(' . implode(',', $valueArr) . ')';
}
elseif(in_array($operator, array('IS NOT NULL', 'IS NULL')))
{
$value = '';
}
$filterFormat[$field] = array('operator' => $operator, 'value' => $value);
break;
}
}
$sql = str_replace(';', '', "$post->sql");
$fields = $post->fieldSettings;
$langs = isset($post->langs) ? $post->langs : array();
switch($type)
{
case 'line':
$data = $this->chart->genLineChart($fields, $settings, $sql, $filterFormat, $langs);
break;
case 'cluBarX':
$data = $this->chart->genCluBar($fields, $settings, $sql, $filterFormat, '', $langs);
break;
case 'cluBarY':
$data = $this->chart->genCluBar($fields, $settings, $sql, $filterFormat, '', $langs);
break;
case 'pie':
$data = $this->chart->genPie($fields, $settings, $sql, $filterFormat);
break;
case 'radar':
$data = $this->chart->genRadar($fields, $settings, $sql, $filterFormat, $langs);
break;
case 'stackedBar':
$data = $this->chart->genCluBar($fields, $settings, $sql, $filterFormat, 'total', $langs);
break;
case 'stackedBarY':
$data = $this->chart->genCluBar($fields, $settings, $sql, $filterFormat, 'total', $langs);
break;
}
echo json_encode($data);
}
}
+7
View File
@@ -0,0 +1,7 @@
.table-panel {overflow-x: auto;}
.datatable {width: auto;}
.datatable th.header {line-height: 32px !important;}
.header-config {float: right; display: none;}
.header:hover .header-config {display: inline-block;}
.label-outline.label-info {border: unset; line-height: 14px;}
.border-bottom {border-bottom: 1px solid #f4f5f7;}
+51
View File
@@ -0,0 +1,51 @@
.m-chart-preview {color: rgb(49, 60, 82); background-color: rgb(244, 245, 247);}
.main-col .btn-toolbar {margin-bottom: 10px;}
.main-position {position: relative;}
.child-position {position: absolute; right: 0;}
.parent-position{padding-right: 180px;}
#chartGroups li {overflow: hidden; white-space: nowrap;}
#chartGroups .checkbox-primary {margin-left: 8px; display: inline-block;}
#chartGroups .checkbox-primary + a {display: inline-block;}
#chartGroups .checkbox-primary > input[type=checkbox][name^=chart] + label {padding-left: 0px;}
.chart-item + .chart-item {margin-top: 10px;}
.chartbox {
height: 400px;
overflow: overlay;
border: 1px solid #ddd;
}
.ant-table-tbody>tr>td, .ant-table-thead>tr>th {
padding: 8px!important;
}
.table-title {
top: 10px;
right: auto;
bottom: auto;
left: 10px;
width: auto;
height: auto;
margin: 0px 0px 10px 10px;
font-size: 18px;
font-weight: bold;
text-align: left;
}
#subNavbar .nav li.active a {display: none;}
#mainContent .cell {padding: 11px;}
#mainContent .panel {border: 0;}
#mainContent .chart-item.main-row x-vue-echarts {max-height: 460px;}
#mainContent .chart-item.main-row .ant-table-wrapper {max-height: 398px; overflow-y: overlay !important;border: 1px solid #e8e8e8; border-right: 0;}
#mainContent .chart-item.main-row .ant-table-bordered .ant-table-body>table {border: 0;}
#mainContent .chart-item.main-row .ant-table-bordered .ant-table-body>table tr:last-child td {border-bottom: 0;}
.echart-content {width: 100%; min-height: 500px;}
.filterBox{display: flex; margin-bottom: 20px;}
.filter-items{display: flex; flex: 1; flex-wrap: wrap;}
.filter-item{padding: 0 16px 5px 0;}
.filter-item-grow{flex-grow: 1;}
.queryBtn{display: flex; align-items: center; padding-bottom: 5px;}
.filterBox .picker-selections{width: 128px; height: 32px; overflow: hidden; text-overflow: clip; white-space: nowrap;}
+56
View File
@@ -0,0 +1,56 @@
/**
* Ajax get chart data.
*
* @access public
* @return bool
*/
function ajaxGetChart(check = true, chart = DataStorage.chart, echart = window.echart)
{
var chartParams = JSON.parse(JSON.stringify(chart));
if(typeof DataStorage != 'undefined') chartParams.fieldSettings = JSON.parse(JSON.stringify(DataStorage.fieldSettings));
if(typeof DataStorage != 'undefined') chartParams.langs = JSON.parse(JSON.stringify(DataStorage.langs));
/* Redraw echart. */
/* 拿数据并重绘图表。*/
$.post(createLink('chart', 'ajaxGetChart'), chartParams, function(resp)
{
var data = JSON.parse(resp);
if(echart)
{
echart.clear();
echart.setOption(data, true);
$('.btn-export').removeClass('hidden');
}
});
}
/**
* Init picker.
*
* @access public
* @return void
*/
function initPicker($row, pickerName = 'picker-select')
{
$row.find('.' + pickerName).picker({'maxDropHeight': pickerHeight});
$row.find("." + pickerName).each(function(index)
{
if($(this).hasClass('required')) $(this).siblings("div .picker").addClass('required');
});
}
/**
* Init datepicker.
*
* @param object $obj
* @param function callback
* @access public
* @return void
*/
function initDatepicker($obj, callback)
{
$obj.find('.form-date').datepicker();
$obj.find('.form-datetime').datetimepicker();
if(typeof callback == 'function') callback($obj);
}
+215
View File
@@ -0,0 +1,215 @@
$(function()
{
initCheckBox();
initQueryBtn();
$('#exportchart').modalTrigger();
chartMap = new Map();
if(charts.length > 0)
{
charts.forEach(function(chart)
{
var echartDom = $('#chartDraw' + chart.currentGroup + chart.id).get(0);
var echart = echarts.init(echartDom);
ajaxGetChart(false, chart, echart);
renderFilters(chart);
chartMap.set(chart.currentGroup + chart.id, chart);
});
}
calcPreviewGrowFilter();
$('body').resize(() => {calcPreviewGrowFilter(true);});
$('[data-toggle="tooltip"]').tooltip();
})
/**
* Init check box.
*
* @access public
* @return void
*/
function initCheckBox()
{
/* Use parent checked prop set all child. */
$('input[data-type="parent"]').click(function()
{
$(this).parent().siblings('ul').find('input[data-type="child"]').prop('checked', $(this).prop('checked'));
});
$('input[data-type="child"]').click(function()
{
/* If child unchecked after click, set parent unchecked. */
if(!$(this).prop('checked'))
{
$(this).parentsUntil('#chartGroups', 'li').find('div').children('input[data-type="parent"]').prop('checked', false);
}
/* If child checked after click, if all child checked, set parent checked. */
else
{
if($(this).closest('ul').find('input[data-type="child"]').length >= 1)
{
var siblings_checked = $(this).closest('ul').find('input[data-type="child"]:checked').length;
var siblings_total = $(this).closest('ul').find('input[data-type="child"]').length;
if(siblings_checked == siblings_total)
{
$(this).parentsUntil('#chartGroups', 'li').find('div').children('input[data-type="parent"]').prop('checked', true);
}
}
}
});
/* Use click to trigger event. */
charts.forEach(function(item)
{
$("#chart_" + item.currentGroup + '_' + item.id).click();
});
}
/**
* Init query button.
*
* @access public
* @return void
*/
function initQueryBtn()
{
$('.btn-query').click(function()
{
var chartID = $(this).attr('data-chart');
var chartInfo = chartMap.get(chartID);
chartInfo.searchFilters = JSON.parse(JSON.stringify(chartInfo.filters));
// Foreach filters and set current value in searchFilters. */
$('#filterItems' + chartID + ' .filter-items').children().each(function(index)
{
var $child = $(this);
var filter = chartInfo.searchFilters[index];
var type = filter.type;
var value = null;
if(type == 'input' || type == 'select')
{
var value = $child.find('#default').val();
chartInfo.searchFilters[index].default = value;
}
else if(type == 'date' || type == 'datetime')
{
var begin = $child.find('input').first().val();
var end = $child.find('input').last().val();
var value = {"begin":begin, "end":end};
chartInfo.searchFilters[index].default = value;
}
else if(type == 'condition')
{
var operator = $child.find('#operator').data('zui.picker').getValue();
var value = $child.find('#value').val();
chartInfo.searchFilters[index].operator = operator;
chartInfo.searchFilters[index].value = value;
}
});
//* Reload echart. */
var echartDom = $('#chartDraw' + chartID).get(0);
var echartInfo = echarts.init(echartDom);
ajaxGetChart(false, chartInfo, echartInfo);
});
}
function calcPreviewGrowFilter(resize = false)
{
if(charts.length <= 0) return;
charts.forEach(function(chart)
{
/* When body resize, resize echarts. */
if(resize)
{
var echartDom = $('#chartDraw' + chart.currentGroup + chart.id).get(0);
var echart = echarts.init(echartDom);
echart.resize();
}
var $filterItems = $('#filterItems' + chart.currentGroup + chart.id + ' .filter-items');
/* When refreshing this page, ZenTao load this page twice, when the first load isn't complete, jump back to index and load the second time,
the first load can't calc filter width, can't get the element using jQuery at first load. */
var hasInit = true;
chart.filters.forEach(function(filter, index)
{
var nowItem = '.filter-item-' + index;
var $titleSpan = $filterItems.find(nowItem).find('.input-group-addon').first();
if(!$titleSpan.length) hasInit = false;
});
if(!hasInit) return;
var domWidth = $filterItems[0].getBoundingClientRect().width;
var nowWidth = domWidth;
var nowCount = 0;
var canGrowTotal = 0;
chart.filters.forEach(function(filter, index)
{
var nowItem = '.filter-item-' + index;
var leftPadding = parseInt($filterItems.find(nowItem).css('padding-left'));
var rightPadding = parseInt($filterItems.find(nowItem).css('padding-right'));
var spanWidth = $filterItems.find(nowItem).find('.input-group-addon').first()[0].getBoundingClientRect().width;
var filterWidth = ((filter.type == 'input' || filter.type == 'select') ? WIDTH_INPUT : WIDTH_DATE) + (spanWidth + leftPadding + rightPadding);
/* Clear the flex-basis and set flex-basic again. */
$filterItems.find(nowItem).css('flex-basis', '');
$filterItems.find(nowItem).css('flex-basis', filterWidth);
if(nowWidth - filterWidth >= 0)
{
nowWidth -= filterWidth;
nowCount ++;
}
else
{
canGrowTotal += nowCount;
nowWidth = domWidth - filterWidth;
nowCount = 1;
}
});
/* Clear all filter filter-item-grow and add class to support grow element. */
$filterItems.children().removeClass('filter-item-grow');
chart.filters.forEach(function(filter, index)
{
var nowItem = '.filter-item-' + index;
if(canGrowTotal >= index + 1) $filterItems.find(nowItem).addClass('filter-item-grow');
});
});
}
function renderFilters(chart)
{
if(chart.filters.length == 0) return;
var fieldNames = {};
Object.keys(chart.fieldSettings).forEach(function(key){fieldNames[key] = chart.fieldSettings[key].name;});
$.post(createLink('chart', 'ajaxGetFilterForm', 'chartID=' + chart.id), {fieldList: fieldNames, fieldSettings: chart.fieldSettings, filters: chart.filters, langs: chart.langs}, function(resp)
{
resp = JSON.parse(resp);
chart.filters.forEach(function(filter, index)
{
var $filterItems = $('#filterItems' + chart.currentGroup + chart.id + ' .filter-items');
$filterItems.append(renderFilterItem(filter, resp, index));
});
});
}
function renderFilterItem(filter, resp, index, step)
{
var tpl = $('#filterItemTpl').html();
var data =
{
index: index,
name: filter.name,
search: resp[index].item
};
var html = $($.zui.formatString(tpl, data))
initPicker(html);
initDatepicker(html);
return html;
}
+33
View File
@@ -0,0 +1,33 @@
<?php
$lang->chart->preview = 'View Chart';
$lang->chart->query = 'Query';
$lang->chart->toDesign = 'To Design';
$lang->chart->group = 'Group';
$lang->chart->field = 'Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = 'Text';
$lang->chart->fieldTypeList['date'] = 'Date';
$lang->chart->fieldTypeList['datetime'] = 'Time';
$lang->chart->fieldTypeList['select'] = 'Dropdown';
//$lang->chart->fieldTypeList['condition'] = 'Condition';
$lang->chart->groupWeek = 'Week %s,%s';
$lang->chart->noChart = 'No Chart';
$lang->chart->noChartSelected = 'Please select one chart.';
$lang->chart->aggList = array();
$lang->chart->aggList['count'] = 'Count';
$lang->chart->aggList['distinct'] = 'Count after distinct';
$lang->chart->aggList['avg'] = 'AVG';
$lang->chart->aggList['sum'] = 'SUM';
$lang->chart->aggList['max'] = 'MAX';
$lang->chart->aggList['min'] = 'MIN';
+33
View File
@@ -0,0 +1,33 @@
<?php
$lang->chart->preview = 'View Chart';
$lang->chart->query = 'Query';
$lang->chart->toDesign = 'To Design';
$lang->chart->group = 'Group';
$lang->chart->field = 'Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = 'Text';
$lang->chart->fieldTypeList['date'] = 'Date';
$lang->chart->fieldTypeList['datetime'] = 'Time';
$lang->chart->fieldTypeList['select'] = 'Dropdown';
//$lang->chart->fieldTypeList['condition'] = 'Condition';
$lang->chart->groupWeek = 'Week %s,%s';
$lang->chart->noChart = 'No Chart';
$lang->chart->noChartSelected = 'Please select one chart.';
$lang->chart->aggList = array();
$lang->chart->aggList['count'] = 'Count';
$lang->chart->aggList['distinct'] = 'Count after distinct';
$lang->chart->aggList['avg'] = 'AVG';
$lang->chart->aggList['sum'] = 'SUM';
$lang->chart->aggList['max'] = 'MAX';
$lang->chart->aggList['min'] = 'MIN';
+33
View File
@@ -0,0 +1,33 @@
<?php
$lang->chart->preview = 'View Chart';
$lang->chart->query = 'Query';
$lang->chart->toDesign = 'To Design';
$lang->chart->group = 'Group';
$lang->chart->field = 'Field';
$lang->chart->agg = 'Aggregate';
$lang->chart->chooseField = 'Choose field';
$lang->chart->aggType = 'Aggregate type';
$lang->chart->other = 'Other';
$lang->chart->unlimited = 'Unlimited';
$lang->chart->colon = 'To';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = 'Text';
$lang->chart->fieldTypeList['date'] = 'Date';
$lang->chart->fieldTypeList['datetime'] = 'Time';
$lang->chart->fieldTypeList['select'] = 'Dropdown';
//$lang->chart->fieldTypeList['condition'] = 'Condition';
$lang->chart->groupWeek = 'Week %s,%s';
$lang->chart->noChart = 'No Chart';
$lang->chart->noChartSelected = 'Please select one chart.';
$lang->chart->aggList = array();
$lang->chart->aggList['count'] = 'Count';
$lang->chart->aggList['distinct'] = 'Count after distinct';
$lang->chart->aggList['avg'] = 'AVG';
$lang->chart->aggList['sum'] = 'SUM';
$lang->chart->aggList['max'] = 'MAX';
$lang->chart->aggList['min'] = 'MIN';
+33
View File
@@ -0,0 +1,33 @@
<?php
$lang->chart->preview = '查看图表';
$lang->chart->query = '查询';
$lang->chart->toDesign = '进入设计';
$lang->chart->group = '所属分组';
$lang->chart->field = '关联字段';
$lang->chart->agg = '汇总';
$lang->chart->chooseField = '选择字段';
$lang->chart->aggType = '统计方式';
$lang->chart->other = '其他';
$lang->chart->unlimited = '不限';
$lang->chart->colon = '至';
$lang->chart->fieldTypeList = array();
$lang->chart->fieldTypeList['input'] = '文本框';
$lang->chart->fieldTypeList['date'] = '日期';
$lang->chart->fieldTypeList['datetime'] = '时间';
$lang->chart->fieldTypeList['select'] = '下拉菜单';
//$lang->chart->fieldTypeList['condition'] = '条件筛选';
$lang->chart->groupWeek = '%s年第%s周';
$lang->chart->noChart = '暂时没有图表';
$lang->chart->noChartSelected = '请选择至少一个图表。';
$lang->chart->aggList = array();
$lang->chart->aggList['count'] = '计数';
$lang->chart->aggList['distinct'] = '去重后计数';
$lang->chart->aggList['avg'] = '平均值';
$lang->chart->aggList['sum'] = '求和';
$lang->chart->aggList['max'] = '最大值';
$lang->chart->aggList['min'] = '最小值';
+627
View File
@@ -0,0 +1,627 @@
<?php
/**
* The model file of chart module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package chart
* @version $Id: model.php 5086 2013-07-10 02:25:22Z wyd621@gmail.com $
* @link http://www.zentao.net
*/
class chartModel extends model
{
/**
* Get first chart group id.
*
* @param int $dimensionID
* @access public
* @return int
*/
public function getFirstChartGroupID($dimensionID)
{
return $this->dao->select('id')->from(TABLE_MODULE)
->where('deleted')->eq('0')
->andWhere('type')->eq('chart')
->andWhere('root')->eq($dimensionID)
->andWhere('grade')->eq(1)
->orderBy('`order`')
->limit(1)
->fetch('id');
}
/**
* Get chart.
*
* @param int $chartID
* @access public
* @return object
*/
public function getByID($chartID)
{
$chart = $this->dao->select('*')->from(TABLE_CHART)->where('id')->eq($chartID)->fetch();
if(!$chart) return false;
if(!empty($chart->fields) and $chart->fields != 'null')
{
$chart->fieldSettings = json_decode($chart->fields);
$chart->fields = array();
foreach($chart->fieldSettings as $field => $settings) $chart->fields[] = $field;
}
else
{
$chart->fieldSettings = array();
}
if($chart->sql == null) $chart->sql = '';
if(!empty($chart->filters)) $chart->filters = json_decode($chart->filters, true);
return $this->processChart($chart);
}
/**
* Process sql and correct type.
*
* @param object $chart
* @access public
* @return object
*/
public function processChart($chart)
{
if(!empty($chart->sql)) $chart->sql = trim(str_replace(';', '', $chart->sql));
if(!empty($chart->settings)) $chart->settings = json_decode($chart->settings, true);
if(!empty($chart->settings) and is_array($chart->settings))
{
$firstSetting = current($chart->settings);
if(isset($firstSetting['type'])) $chart->type = $firstSetting['type'];
}
return $chart;
}
/**
* Get tree of charts and groups.
*
* @param int $groupID
* @param string $orderBy
* @access public
* @return array
*/
public function getPreviewCharts($groupID, $orderBy = 'id_desc')
{
if(!$groupID) return array('', array());
$currentGroup = $this->loadModel('tree')->getByID($groupID);
if(empty($currentGroup) || $currentGroup->grade != 1) return array('', array());
$groups = $this->dao->select('id, grade, name')->from(TABLE_MODULE)->where('deleted')->eq('0')->andWhere('path')->like("{$currentGroup->path}%")->orderBy('`order`')->fetchAll();
if(!$groups) return array('', array());
$chartGroups = array();
foreach($groups as $group)
{
$chartGroups[$group->id] = $this->dao->select('*')->from(TABLE_CHART)
->where('deleted')->eq(0)
->andWhere("FIND_IN_SET($group->id, `group`)")
->andWhere('stage')->ne('draft')
->orderBy($orderBy)
->fetchAll();
}
if(!$chartGroups) return array('', array());
$readyCharts = array();
foreach($chartGroups as $groupID => $chartGroup)
{
$charts = array();
foreach($chartGroup as $chart)
{
if($chart->stage != 'published') continue;
$charts[] = $chart;
}
if(!empty($charts)) $readyCharts[$groupID] = $charts;
}
$index = 1;
$chartTree = '';
$firstChart = null;
foreach($groups as $group)
{
if(!isset($readyCharts[$group->id])) continue;
if($group->grade == 2)
{
$class = $index == 1 ? 'open' : 'closed';
$chartTree .= "<li class='$class'><div class='checkbox-primary'><input type='checkbox' data-type='parent' name='groups[]' id='group{$group->id}' value='{$group->id}' title='{$group->name}'><label>{$group->name}</label></div><ul>";
}
$charts = $readyCharts[$group->id];
foreach($charts as $chart)
{
$chart->currentGroup = $group->id;
if(!$firstChart) $firstChart = $chart;
$chartTree .= "<li title='{$chart->name}'><div class='checkbox-primary checkbox-inline'><input type='checkbox' data-type='child' name='charts[]' id='chart_{$group->id}_{$chart->id}' value='{$group->id}_{$chart->id}' title='{$chart->name}' data-group='{$group->id}'><label for='chart_{$group->id}_{$chart->id}'></label></div><a>{$chart->name}</a></li>";
}
if($group->grade == 2) $chartTree .= '</ul></li>';
$index++;
}
if($chartTree) $chartTree = "<ul id='chartGroups' class='tree' data-ride='tree'>" . $chartTree . '</ul>';
$charts = array();
if($firstChart)
{
if(!empty($firstChart->settings)) $firstChart->settings = json_decode($firstChart->settings, true);
if(!empty($firstChart->filters)) $firstChart->filters = json_decode($firstChart->filters, true);
if(!empty($firstChart->fields) and $firstChart->fields != 'null')
{
$firstChart->fieldSettings = json_decode($firstChart->fields);
$firstChart->fields = array_keys(json_decode($firstChart->fields, true));
}
$charts[] = $firstChart;
}
return array($chartTree, $charts);
}
/**
* Gen radar.
*
* @param int $fields
* @param int $settings
* @param int $defaultSql
* @param int $filters
* @param array $langs
* @access public
* @return void
*/
public function genRadar($fields, $settings, $defaultSql, $filters, $langs = array())
{
list($group, $metrics, $aggs, $xLabels, $yStats) = $this->getMultiData($settings, $defaultSql, $filters);
$yDatas = array();
$max = 0;
foreach($yStats as $yStat)
{
$data = array();
foreach($xLabels as $xLabel)
{
$yStatXLabel = isset($yStat[$xLabel]) ? $yStat[$xLabel] : 0;
$data[] = $yStatXLabel;
}
if(max($yStat) > $max) $max = max($yStat);
$yDatas[] = $data;
}
$series = array();
$legend = new stdclass();
$series['type'] = 'radar';
$clientLang = $this->app->getClientLang();
foreach($yDatas as $index => $yData)
{
$fieldName = $fields[$metrics[$index]]['name'];
if(!empty($fields[$metrics[$index]]['object']) and !empty($fields[$metrics[$index]]['field']))
{
$relatedObject = $fields[$metrics[$index]]['object'];
$relatedField = $fields[$metrics[$index]]['field'];
$this->app->loadLang($relatedObject);
$fieldName = isset($this->lang->$relatedObject->$relatedField) ? $this->lang->$relatedObject->$relatedField : $fieldName;
}
if(isset($langs[$metrics[$index]]) and !empty($langs[$metrics[$index]][$clientLang])) $fieldName = $langs[$metrics[$index]][$clientLang];
$seriesName = $fieldName . '(' . $this->lang->chart->aggList[$aggs[$index]] . ')';
$series['data'][] = array('name' => $seriesName, 'value' => $yData);
}
$indicator = array();
$optionList = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field']);
foreach($xLabels as $xLabel)
{
$labelName = isset($optionList[$xLabel]) ? $optionList[$xLabel] : $xLabel;
$indicator[] = array('name' => $labelName, 'max' => $max);
}
$options = array('series' => $series, 'legend' => $legend, 'radar' => array('indicator' => $indicator), 'tooltip' => array('trigger' => 'item'));
return $options;
}
/**
* Gen pie.
*
* @param string $schema
* @param object $settings
* @param string $sql
* @param array $filters
* @access public
* @return array
*/
public function genPie($fields, $settings, $sql, $filters)
{
$group = isset($settings['group'][0]['field']) ? $settings['group'][0]['field'] : '';
$date = isset($settings['group'][0]['group']) ? zget($this->config->chart->dateConvert, $settings['group'][0]['group']) : '';
$metric = isset($settings['metric'][0]['field']) ? $settings['metric'][0]['field'] : '';
$agg = isset($settings['metric'][0]['valOrAgg']) ? $settings['metric'][0]['valOrAgg'] : '';
$defaultSql = str_replace(';', '', $sql);
$groupSql = $groupBySql = "tt.`$group`";
if(!empty($date))
{
$groupSql = $date == 'MONTH' ? "YEAR(tt.`$group`) as ttyear, $date(tt.`$group`) as ttgroup" : "$date(tt.`$group`) as $group";
$groupBySql = $date == 'MONTH' ? "YEAR(tt.`$group`), $date(tt.`$group`)" : "$date(tt.`$group`)";
}
if($agg == 'distinct')
{
$aggSQL = "count($agg tt.`$metric`) as `$metric`";
}
else
{
$aggSQL = "$agg(tt.`$metric`) as `$metric`";
}
$sql = "select $groupSql,$aggSQL from ($defaultSql) tt";
if(!empty($filters))
{
$wheres = array();
foreach($filters as $field => $filter)
{
$wheres[] = "$field {$filter['operator']} {$filter['value']}";
}
$whereStr = implode(' and ', $wheres);
$sql .= " where $whereStr";
}
$sql .= " group by $groupBySql";
$rows = $this->dao->query($sql)->fetchAll();
$stat = $this->processRows($rows, $date, $group, $metric);
$maxCount = 50;
if(empty($date)) arsort($stat);
$copyStat = $stat;
$other = array_sum(array_splice($copyStat, $maxCount));
$stat[$this->lang->chart->other] = $other;
if(empty($date)) arsort($stat);
$optionList = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field']);
$data = array();
foreach($stat as $name => $value)
{
if($value == 0) continue;
$value = round($value, 2);
$labelName = isset($optionList[$name]) ? $optionList[$name] : $name;
$data[] = array('name' => $labelName, 'value' => $value);
}
$label = array('show' => true, 'position' => 'outside', 'formatter' => '{b} {d}%');
$legend = new stdclass();
$legend->type = 'scroll';
$legend->orient = 'vertical';
$legend->right = 0;
$series[] = array('data' => $data, 'type' => 'pie', 'label' => $label);
$options = array('series' => $series, 'legend' => $legend, 'tooltip' => array('trigger' => 'item', 'formatter' => "{b}<br/> {c} ({d}%)"));
return $options;
}
/**
* Process rows.
*
* @param array $rows
* @param string $date
* @param string $group
* @param string $metric
* @access public
* @return array
*/
public function processRows($rows, $date, $group, $metric)
{
$stat = array();
foreach($rows as $row)
{
if(!empty($date) and $date == 'MONTH')
{
$stat[sprintf("%04d", $row->ttyear) . '-' . sprintf("%02d", $row->ttgroup)] = $row->$metric;
}
elseif(!empty($date) and $date == 'YEARWEEK')
{
$yearweek = sprintf("%06d", $row->$group);
$year = substr($yearweek, 0, strlen($yearweek) - 2);
$week = substr($yearweek, -2);
$weekIndex = in_array($this->app->getClientLang(), array('zh-cn', 'zh-tw')) ? sprintf($this->lang->chart->groupWeek, $year, $week) : sprintf($this->lang->chart->groupWeek, $week, $year);
$stat[$weekIndex] = $row->$metric;
}
elseif(!empty($date) and $date == 'YEAR')
{
$stat[sprintf("%04d", $row->$group)] = $row->$metric;
}
else
{
$stat[$row->$group] = $row->$metric;
}
}
return $stat;
}
/**
* Gen line.
*
* @param string $schema
* @param object $settings
* @param string $sql
* @param array $filters
* @param array $langs
* @access public
* @return array
*/
public function genLineChart($fields, $settings, $defaultSql, $filters, $langs = array())
{
list($group, $metrics, $aggs, $xLabels, $yStats) = $this->getMultiData($settings, $defaultSql, $filters);
$fieldType = $fields[$settings['xaxis'][0]['field']]['type'];
if($fieldType == 'date') sort($xLabels);
$yDatas = array();
foreach($xLabels as $xLabel)
{
foreach($yStats as $index => $yStat)
{
if(!isset($yDatas[$index])) $yDatas[$index] = array();
$yDatas[$index][] = isset($yStat[$xLabel]) ? $yStat[$xLabel] : 0;
}
}
$optionList = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field']);
foreach($xLabels as $index => $xLabel) $xLabels[$index] = isset($optionList[$xLabel]) ? $optionList[$xLabel] : $xLabel;
$xaxis = array('type' => 'category', 'data' => $xLabels);
$yaxis = array('type' => 'value');
$legend = new stdclass();
$series = array();
$clientLang = $this->app->getClientLang();
foreach($yDatas as $index => $yData)
{
$fieldName = $fields[$metrics[$index]]['name'];
if(!empty($fields[$metrics[$index]]['object']) and !empty($fields[$metrics[$index]]['field']))
{
$relatedObject = $fields[$metrics[$index]]['object'];
$relatedField = $fields[$metrics[$index]]['field'];
$this->app->loadLang($relatedObject);
$fieldName = isset($this->lang->$relatedObject->$relatedField) ? $this->lang->$relatedObject->$relatedField : $fieldName;
}
if(isset($langs[$metrics[$index]]) and !empty($langs[$metrics[$index]][$clientLang])) $fieldName = $langs[$metrics[$index]][$clientLang];
$seriesName = $fieldName . '(' . $this->lang->chart->aggList[$aggs[$index]] . ')';
$series[] = array('name' => $seriesName, 'data' => $yData, 'type' => 'line');
}
$options = array('series' => $series, 'legend' => $legend, 'xAxis' => $xaxis, 'yAxis' => $yaxis, 'tooltip' => array('trigger' => 'axis'));
return $options;
}
/**
* Gen cluBar.
*
* @param int $fields
* @param int $settings
* @param int $defaultSql
* @param int $filters
* @param int $stack
* @param array $langs
* @access public
* @return void
*/
public function genCluBar($fields, $settings, $defaultSql, $filters, $stack = '', $langs = array())
{
list($group, $metrics, $aggs, $xLabels, $yStats) = $this->getMultiData($settings, $defaultSql, $filters);
$yDatas = array();
foreach($yStats as $yStat)
{
$data = array();
foreach($xLabels as $xLabel)
{
$data[] = isset($yStat[$xLabel]) ? $yStat[$xLabel] : 0;
}
$yDatas[] = $data;
}
$optionList = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field']);
foreach($xLabels as $index => $xLabel) $xLabels[$index] = isset($optionList[$xLabel]) ? $optionList[$xLabel] : $xLabel;
$xaxis = array('type' => 'category', 'data' => $xLabels, 'axisLabel' => array('interval' => 0));
$yaxis = array('type' => 'value');
$legend = new stdclass();
/* Cluster bar X graphs and cluster bar Y graphs are really just x and y axes switched, so cluster bar Y $xaixs and $yaxis are swapped so that the method can be reused. */
/* 簇状柱形图和簇状条形图其实只是x轴和y轴换了换,所以交换一下簇状条形图 xAxis和yAxis即可,这样方法就可以复用了。*/
if(in_array($settings['type'], array('cluBarY', 'stackedBarY'))) list($xaxis, $yaxis) = array($yaxis, $xaxis);
$series = array();
$clientLang = $this->app->getClientLang();
foreach($yDatas as $index => $yData)
{
$fieldName = $fields[$metrics[$index]]['name'];
if(!empty($fields[$metrics[$index]]['object']) and !empty($fields[$metrics[$index]]['field']))
{
$relatedObject = $fields[$metrics[$index]]['object'];
$relatedField = $fields[$metrics[$index]]['field'];
$this->app->loadLang($relatedObject);
$fieldName = isset($this->lang->$relatedObject->$relatedField) ? $this->lang->$relatedObject->$relatedField : $fieldName;
}
if(isset($langs[$metrics[$index]]) and !empty($langs[$metrics[$index]][$clientLang])) $fieldName = $langs[$metrics[$index]][$clientLang];
$seriesName = $fieldName . '(' . $this->lang->chart->aggList[$aggs[$index]] . ')';
$series[] = array('name' => $seriesName, 'data' => $yData, 'type' => 'bar', 'stack' => $stack);
}
$options = array('series' => $series, 'legend' => $legend, 'xAxis' => $xaxis, 'yAxis' => $yaxis, 'tooltip' => array('trigger' => 'axis'));
return $options;
}
/**
* Get multi data.
*
* @param int $settings
* @param int $defaultSql
* @param int $filters
* @access public
* @return void
*/
public function getMultiData($settings, $defaultSql, $filters, $sort = false)
{
$group = isset($settings['xaxis'][0]['field']) ? $settings['xaxis'][0]['field'] : '';
$date = isset($settings['xaxis'][0]['group']) ? zget($this->config->chart->dateConvert, $settings['xaxis'][0]['group']) : '';
$metrics = array();
$aggs = array();
foreach($settings['yaxis'] as $yaxis)
{
$metrics[] = $yaxis['field'];
$aggs[] = $yaxis['valOrAgg'];
}
$yCount = count($metrics);
$xLabels = array();
$yStats = array();
for($i = 0; $i < $yCount; $i ++)
{
$metric = $metrics[$i];
$agg = $aggs[$i];
$groupSql = $groupBySql = "tt.`$group`";
if(!empty($date))
{
$groupSql = $date == 'MONTH' ? "YEAR(tt.`$group`) as ttyear, $date(tt.`$group`) as ttgroup" : "$date(tt.`$group`) as $group";
$groupBySql = $date == 'MONTH' ? "YEAR(tt.`$group`), $date(tt.`$group`)" : "$date(tt.`$group`)";
}
if($agg == 'distinct')
{
$aggSQL = "count($agg tt.`$metric`) as `$metric`";
}
else
{
$aggSQL = "$agg(tt.`$metric`) as `$metric`";
}
$sql = "select $groupSql,$aggSQL from ($defaultSql) tt";
if(!empty($filters))
{
$wheres = array();
foreach($filters as $field => $filter)
{
$wheres[] = "$field {$filter['operator']} {$filter['value']}";
}
$whereStr = implode(' and ', $wheres);
$sql .= " where $whereStr";
}
$sql .= " group by $groupBySql";
$rows = $this->dao->query($sql)->fetchAll();
$stat = $this->processRows($rows, $date, $group, $metric);
$maxCount = 50;
if($sort) arsort($stat);
$yStats[] = $stat;
$xLabels = array_merge($xLabels, array_keys($stat));
$xLabels = array_unique($xLabels);
}
return array($group, $metrics, $aggs, $xLabels, $yStats);
}
/**
* Adjust the action is clickable.
*
* @param object $chart
* @param string $action
* @static
* @access public
* @return bool
*/
public static function isClickable($chart, $action)
{
return true;
}
/**
* Get sys options.
*
* @param string $type
* @access public
* @return array
*/
public function getSysOptions($type, $object = '', $field = '')
{
$options = array('' => '');
switch($type)
{
case 'user':
$options = $this->loadModel('user')->getPairs();
break;
case 'product':
$options = $this->loadModel('product')->getPairs();
break;
case 'project':
$options = $this->loadModel('project')->getPairsByProgram();
break;
case 'execution':
$options = $this->loadModel('execution')->getPairs();
break;
case 'dept':
$options = $this->loadModel('dept')->getOptionMenu(0);
break;
case 'option':
if($field)
{
$path = $this->app->getModuleRoot() . 'dataview' . DS . 'table' . DS . "$object.php";
include $path;
$options = $schema->fields[$field]['options'];
}
break;
case 'object':
if($field)
{
$table = zget($this->config->objectTables, $object);
$options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
}
break;
/*case 'string':
if($field)
{
$table = zget($this->config->objectTables, $object);
$options = $this->dao->select("{$field}, {$field}")->from($table)->fetchPairs();
}
break;
*/
}
return $options;
}
}
+113
View File
@@ -0,0 +1,113 @@
<?php
/**
* The preview view file of chart module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Gang Liu <liugang@easycorp.ltd>
* @package chart
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?php js::import($jsRoot . 'moment/moment.min.js');?>
<?php js::import($jsRoot . 'echarts/echarts.common.min.js');?>
<?php js::set('groupID', isset($group->id) ? $group->id : 0);?>
<?php js::set('charts', $charts);?>
<?php js::set('noChartSelected', $lang->chart->noChartSelected);?>
<?php js::set('chartLang', $lang->chart);?>
<?php js::set('WIDTH_INPUT', $config->chart->widthInput);?>
<?php js::set('WIDTH_DATE', $config->chart->widthDate);?>
<?php js::set('pickerHeight', $config->bi->pickerHeight);?>
<div id='mainMenu' class='clearfix main-position'>
<div class='btn-toolBar pull-left parent-position'>
<?php
foreach($groups as $groupID => $groupName)
{
if(!$groupID) continue;
$activeClass = $groupID == $group->id ? 'btn-active-text' : '';
echo html::a(inlink('preview', "dimensionID={$dimensionID}&groupID={$groupID}"), $groupName, '', "class='btn btn-link {$activeClass}' id='{$groupID}Tab'");
}
?>
</div>
<?php if($this->config->edition == 'biz' or $this->config->edition == 'max'):?>
<div class='btn-toolbar pull-right child-position'>
<?php common::printLink('chart', 'exportChart', '', "<i class='icon icon-export muted'> </i> " . $lang->export, '', "class='btn btn-link btn-export' id='exportchart'");?>
<?php common::printLink('chart', 'browse', '', $lang->chart->toDesign, '', "class='btn btn-primary '");?>
</div>
<?php endif;?>
</div>
<div id="mainContent" class='main-row'>
<div class='side-col col-lg'>
<div class='panel'>
<div class='panel-heading'>
<div class='panel-title'><?php echo isset($group->name) ? $group->name : '';?></div>
</div>
<div class='panel-body'>
<?php if(!$chartTree):?>
<hr class="space">
<div class="text-center text-muted">
<?php echo $lang->chart->noChart;?>
</div>
<hr class="space">
<?php elseif($chartTree):?>
<form method='post'>
<?php echo $chartTree;?>
<div class='btn-toolbar'>
<?php echo html::selectAll();?>
<?php echo html::submitButton($lang->chart->preview, '', 'btn btn-primary');?>
</div>
</form>
<?php endif;?>
</div>
</div>
</div>
<div class='main-col'>
<div class='cell'>
<?php if(!$chartTree):?>
<hr class="space">
<div class="text-center text-muted">
<?php echo $lang->chart->noChart;?>
</div>
<hr class="space">
<?php else:?>
<div class='btn-toolbar pull-right'>
</div>
<?php foreach($charts as $chart):?>
<div class='panel'>
<div class='panel-heading'>
<div class='panel-title'>
<?php echo $chart->name;?>
<?php if(!empty($chart->desc)):?>
<a data-toggle='tooltip' data-placement='auto' title=<?php echo $chart->desc;?>><i class='icon-help'></i></a>
<?php endif;?>
</div>
</div>
<div class='panel-body'>
<div id="filterItems<?php echo $chart->currentGroup;?><?php echo $chart->id;?>" class='filterBox'>
<div class='filter-items'></div>
<?php if(!empty($chart->filters)):?>
<div class='queryBtn'><?php echo html::submitButton($lang->chart->query, "data-chart={$chart->currentGroup}{$chart->id}", 'btn btn-primary btn-query');?></div>
<?php endif;?>
</div>
<div id="chartDraw<?php echo $chart->currentGroup;?><?php echo $chart->id;?>" data-group="<?php echo $chart->currentGroup;?>" data-id="<?php echo $chart->id;?>" class='echart-content'></div>
</div>
</div>
<?php endforeach;?>
<?php endif;?>
</div>
</div>
</div>
<?php include $app->getModuleRoot() . 'common/view/footer.html.php';?>
<template id='filterItemTpl'>
<div class='filter-item filter-item-{index}'>
<div class='input-group'>
<span class='input-group-addon field-name'>{name}</span>
{search}
</div>
</div>
</template>
+1
View File
@@ -44,6 +44,7 @@ $lang->user = new stdclass();
$lang->screen = new stdclass();
$lang->report = new stdclass();
$lang->pivot = new stdclass();
$lang->chart = new stdclass();
$lang->repo = new stdclass();
$lang->jenkins = new stdclass();
$lang->gitlab = new stdclass();
+1
View File
@@ -177,6 +177,7 @@ $lang->repo->codeRepo = 'Code Repo';
$lang->screen->common = 'Screen';
$lang->report->common = 'BI';
$lang->pivot->common = 'Pivot Table';
$lang->chart->common = 'Chart';
$lang->system->common = 'System';
$lang->admin->common = 'Admin';
$lang->story->common = 'Story';
+1
View File
@@ -177,6 +177,7 @@ $lang->repo->codeRepo = 'Code Repo';
$lang->screen->common = 'Screen';
$lang->report->common = 'BI';
$lang->pivot->common = 'Pivot Table';
$lang->chart->common = 'Chart';
$lang->system->common = 'System';
$lang->admin->common = 'Admin';
$lang->story->common = 'Story';
+1
View File
@@ -177,6 +177,7 @@ $lang->repo->codeRepo = 'Code Repo';
$lang->screen->common = 'Screen';
$lang->report->common = 'BI';
$lang->pivot->common = 'Pivot Table';
$lang->chart->common = 'Chart';
$lang->system->common = 'System';
$lang->admin->common = 'Admin';
$lang->story->common = 'Story';
+3
View File
@@ -519,10 +519,12 @@ $lang->doc->menuOrder[30] = 'custom';
$lang->report->menu = new stdclass();
$lang->report->menu->screen = array('link' => "{$lang->screen->common}|screen|browse");
$lang->report->menu->pivot = array('link' => "{$lang->pivot->common}|pivot|preview");
$lang->report->menu->chart = array('link' => "{$lang->chart->common}|chart|preview");
/* Report menu order. */
$lang->report->menuOrder[5] = 'screen';
$lang->report->menuOrder[10] = 'pivot';
$lang->report->menuOrder[15] = 'chart';
/* Company menu.*/
$lang->company->menu = new stdclass();
@@ -611,6 +613,7 @@ $lang->navGroup->api = 'doc';
$lang->navGroup->screen = 'report';
$lang->navGroup->pivot = 'report';
$lang->navGroup->chart = 'report';
$lang->navGroup->qa = 'qa';
$lang->navGroup->bug = 'qa';
+1
View File
@@ -177,6 +177,7 @@ $lang->repo->codeRepo = '代码库';
$lang->screen->common = '大屏';
$lang->report->common = 'BI';
$lang->pivot->common = '透视表';
$lang->chart->common = '图表';
$lang->system->common = '组织';
$lang->admin->common = '后台';
$lang->story->common = $lang->SRCommon;
+3
View File
@@ -0,0 +1,3 @@
<?php
$lang->dataview->id = 'ID';
$lang->dataview->name = 'Name';
+3
View File
@@ -0,0 +1,3 @@
<?php
$lang->dataview->id = 'ID';
$lang->dataview->name = 'Name';
+3
View File
@@ -0,0 +1,3 @@
<?php
$lang->dataview->id = 'ID';
$lang->dataview->name = 'Name';
+3
View File
@@ -0,0 +1,3 @@
<?php
$lang->dataview->id = '编号';
$lang->dataview->name = '名称';
+63
View File
@@ -0,0 +1,63 @@
<?php
$this->app->loadLang('bug');
$this->app->loadLang('product');
$this->app->loadLang('story');
$this->app->loadLang('project');
$this->app->loadLang('tree');
$schema = new stdclass();
$schema->primaryTable = 'bug';
$schema->tables = array();
$schema->tables['bug'] = 'zt_bug';
$schema->tables['product'] = 'zt_product';
$schema->tables['story'] = 'zt_story';
$schema->tables['productline'] = 'zt_module';
$schema->tables['program'] = 'zt_project';
$schema->tables['project'] = 'zt_project';
$schema->tables['bugmodule'] = 'zt_module';
$schema->joins = array();
$schema->joins['product'] = 'product.id = bug.product';
$schema->joins['story'] = 'story.id = bug.story';
$schema->joins['productline'] = 'productline.id = product.line';
$schema->joins['program'] = 'program.id = product.program';
$schema->joins['project'] = 'project.id = bug.project';
$schema->joins['bugmodule'] = 'bugmodule.id = bug.module';
$schema->fields = array();
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->bug->id);
$schema->fields['title'] = array('type' => 'string', 'name' => $this->lang->bug->title);
$schema->fields['steps'] = array('type' => 'text', 'name' => $this->lang->bug->steps);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->bug->status, 'options' => $this->lang->bug->statusList);
$schema->fields['confirmed'] = array('type' => 'option', 'name' => $this->lang->bug->confirmed, 'options' => $this->lang->bug->confirmedList);
$schema->fields['severity'] = array('type' => 'option', 'name' => $this->lang->bug->severity, 'options' => $this->lang->bug->severityList);
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->bug->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->bug->project, 'object' => 'project', 'show' => 'project.name');
$schema->fields['bugmodule'] = array('type' => 'object', 'name' => $this->lang->bug->module, 'object' => 'bugmodule', 'show' => 'bugmodule.name');
$schema->fields['story'] = array('type' => 'object', 'name' => $this->lang->story->common, 'object' => 'story', 'show' => 'story.title');
$schema->fields['pri'] = array('type' => 'option', 'name' => $this->lang->bug->pri, 'options' => $this->lang->bug->priList);
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->bug->openedBy);
$schema->fields['openedDate'] = array('type' => 'date', 'name' => $this->lang->bug->openedDate);
$schema->fields['resolvedBy'] = array('type' => 'user', 'name' => $this->lang->bug->resolvedBy);
$schema->fields['resolution'] = array('type' => 'option', 'name' => $this->lang->bug->resolution, 'options' => $this->lang->bug->resolutionList);
$schema->fields['resolvedDate'] = array('type' => 'date', 'name' => $this->lang->bug->resolvedDate);
$schema->objects = array();
$schema->objects['story'] = array();
$schema->objects['story']['id'] = array('type' => 'number', 'name' => $this->lang->story->id);
$schema->objects['story']['title'] = array('type' => 'string', 'name' => $this->lang->story->common);
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->common);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->common);
$schema->objects['bugmodule'] = array();
$schema->objects['bugmodule']['id'] = array('type' => 'number', 'name' => $this->lang->bug->id);
$schema->objects['bugmodule']['name'] = array('type' => 'string', 'name' => $this->lang->tree->module);
+92
View File
@@ -0,0 +1,92 @@
<?php
$this->app->loadLang('bug');
$this->app->loadLang('product');
$this->app->loadLang('testtask');
$this->app->loadLang('build');
$this->app->loadLang('execution');
$this->app->loadLang('project');
$this->app->loadLang('tree');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'bug';
$schema->tables = array();
$schema->tables['bug'] = 'zt_bug';
$schema->tables['product'] = 'zt_product';
$schema->tables['testtask'] = 'zt_testtask';
$schema->tables['testcase'] = 'zt_case';
$schema->tables['build'] = 'zt_build';
$schema->tables['execution'] = 'zt_project';
$schema->tables['project'] = 'zt_project';
$schema->tables['module'] = 'zt_module';
$schema->tables['casemodule'] = 'zt_module';
$schema->joins = array();
$schema->joins['product'] = 'product.id = bug.product';
$schema->joins['testtask'] = 'testtask.id = bug.testtask';
$schema->joins['build'] = 'build.id = testtask.build';
$schema->joins['execution'] = 'execution.id = build.execution';
$schema->joins['project'] = 'project.id = build.project';
$schema->joins['module'] = 'module.id = bug.module';
$schema->joins['testcase'] = 'testcase.id = bug.case';
$schema->joins['casemodule'] = 'casemodule.id = testcase.module';
$schema->fields = array();
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->bug->id);
$schema->fields['title'] = array('type' => 'string', 'name' => $this->lang->bug->title);
$schema->fields['steps'] = array('type' => 'text', 'name' => $this->lang->bug->steps);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->bug->status, 'options' => $this->lang->bug->statusList);
$schema->fields['confirmed'] = array('type' => 'option', 'name' => $this->lang->bug->confirmed, 'options' => $this->lang->bug->confirmedList);
$schema->fields['severity'] = array('type' => 'option', 'name' => $this->lang->bug->severity, 'options' => $this->lang->bug->severityList);
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->bug->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->bug->project, 'object' => 'project', 'show' => 'project.name');
$schema->fields['build'] = array('type' => 'object', 'name' => $this->lang->build->common, 'object' => 'build', 'show' => 'build.name');
$schema->fields['module'] = array('type' => 'object', 'name' => $this->lang->bug->module, 'object' => 'module', 'show' => 'module.name');
$schema->fields['testtask'] = array('type' => 'object', 'name' => $this->lang->testtask->common, 'object' => 'testtask', 'show' => 'testtask.name');
$schema->fields['pri'] = array('type' => 'option', 'name' => $this->lang->bug->pri, 'options' => $this->lang->bug->priList);
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->bug->openedBy);
$schema->fields['openedDate'] = array('type' => 'datetime', 'name' => $this->lang->bug->openedDate);
$schema->fields['resolvedBy'] = array('type' => 'user', 'name' => $this->lang->bug->resolvedBy);
$schema->fields['resolution'] = array('type' => 'option', 'name' => $this->lang->bug->resolution, 'options' => $this->lang->bug->resolutionList);
$schema->fields['resolvedDate'] = array('type' => 'datetime', 'name' => $this->lang->bug->resolvedDate);
$schema->fields['casemodule'] = array('type' => 'object', 'name' => $this->lang->tree->module, 'object' => 'casemodule', 'show' => 'casemodule.name');
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->common);
$schema->objects['testtask'] = array();
$schema->objects['testtask']['id'] = array('type' => 'number', 'name' => $this->lang->testtask->id);
$schema->objects['testtask']['name'] = array('type' => 'string', 'name' => $this->lang->testtask->common);
$schema->objects['build'] = array();
$schema->objects['build']['id'] = array('type' => 'number', 'name' => $this->lang->build->id);
$schema->objects['build']['name'] = array('type' => 'string', 'name' => $this->lang->build->common);
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->common);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->common);
$schema->objects['build'] = array();
$schema->objects['build']['id'] = array('type' => 'number', 'name' => $this->lang->build->id);
$schema->objects['build']['name'] = array('type' => 'string', 'name' => $this->lang->build->common);
$schema->objects['module'] = array();
$schema->objects['module']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['module']['name'] = array('type' => 'string', 'name' => $this->lang->tree->module);
$schema->objects['testcase'] = array();
$schema->objects['testcase']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['testcase']['title'] = array('type' => 'string', 'name' => $this->lang->testcase->common);
$schema->objects['casemodule'] = array();
$schema->objects['casemodule']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['casemodule']['name'] = array('type' => 'string', 'name' => $this->lang->dataview->name);
+45
View File
@@ -0,0 +1,45 @@
<?php
$this->app->loadLang('product');
$this->app->loadLang('project');
$this->app->loadLang('execution');
$this->app->loadLang('build');
$schema = new stdclass();
$schema->primaryTable = 'build';
$schema->tables = array();
$schema->tables['product'] = 'zt_product';
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->tables['build'] = 'zt_build';
$schema->joins = array();
$schema->joins['product'] = 'product.id = build.product';
$schema->joins['project'] = 'project.id = build.project';
$schema->joins['execution'] = 'execution.id = build.execution';
$schema->fields = array();
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->build->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->build->project, 'object' => 'project', 'show' => 'project.name');
$schema->fields['execution'] = array('type' => 'object', 'name' => $this->lang->build->execution, 'object' => 'execution', 'show' => 'execution.name');
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->build->name);
$schema->fields['builder'] = array('type' => 'user', 'name' => $this->lang->build->builder);
$schema->fields['stories'] = array('type' => 'string', 'name' => $this->lang->build->stories);
$schema->fields['bugs'] = array('type' => 'string', 'name' => $this->lang->build->bugs);
$schema->fields['date'] = array('type' => 'date', 'name' => $this->lang->build->date);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->build->desc);
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->execution->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
+18
View File
@@ -0,0 +1,18 @@
<?php
$this->app->loadLang('tree');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'casemodule';
$schema->tables = array();
$schema->tables['casemodule'] = 'zt_module';
$schema->joins = array();
$schema->fields = array();
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->tree->module);
$schema->objects = array();
+30
View File
@@ -0,0 +1,30 @@
<?php
$this->app->loadLang('testcase');
$casestepLang = new stdclass();
$casestepLang->type = '步骤类型';
$casestepLang->typeList['step'] = '步骤';
$casestepLang->typeList['group'] = '分组';
$schema = new stdclass();
$schema->primaryTable = 'casestep';
$schema->tables = array();
$schema->tables['casestep'] = 'zt_casestep';
$schema->tables['testcase'] = 'zt_case';
$schema->joins = array();
$schema->joins['testcase'] = 'testcase.id = casestep.`case`';
$schema->fields = array();
$schema->fields['case'] = array('type' => 'object', 'name' => $this->lang->testcase->common, 'object' => 'testcase', 'show' => 'testcase.title');
$schema->fields['type'] = array('type' => 'option', 'name' => $casestepLang->type, 'options' => $casestepLang->typeList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->testcase->desc);
$schema->fields['expect'] = array('type' => 'string', 'name' => $this->lang->testcase->expect);
$schema->fields['version'] = array('type' => 'number', 'name' => $this->lang->testcase->version);
$schema->objects = array();
$schema->objects['testcase'] = array();
$schema->objects['testcase']['id'] = array('type' => 'number', 'name' => $this->lang->testcase->id);
$schema->objects['testcase']['title'] = array('type' => 'string', 'name' => $this->lang->testcase->title);
+37
View File
@@ -0,0 +1,37 @@
<?php
$this->app->loadLang('execution');
$this->app->loadLang('project');
$this->app->loadLang('product');
$schema = new stdclass();
$schema->primaryTable = 'execution';
$schema->tables = array();
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->joins = array();
$schema->joins['project'] = 'execution.project = project.id';
$schema->fields = array();
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->project->name, 'object' => 'project', 'show' => 'project.name');
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
$schema->fields['code'] = array('type' => 'string', 'name' => $this->lang->execution->code);
$schema->fields['type'] = array('type' => 'option', 'name' => $this->lang->execution->type, 'options' => $this->lang->execution->typeList);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->execution->status, 'options' => $this->lang->execution->statusList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->execution->desc);
$schema->fields['begin'] = array('type' => 'date', 'name' => $this->lang->execution->begin);
$schema->fields['end'] = array('type' => 'date', 'name' => $this->lang->execution->end);
$schema->fields['PO'] = array('type' => 'user', 'name' => $this->lang->product->PO);
$schema->fields['PM'] = array('type' => 'user', 'name' => $this->lang->execution->PM);
$schema->fields['QD'] = array('type' => 'user', 'name' => $this->lang->execution->QD);
$schema->fields['RD'] = array('type' => 'user', 'name' => $this->lang->execution->RD);
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->execution->openedBy);
$schema->fields['openedDate'] = array('type' => 'date', 'name' => $this->lang->execution->openedDate);
$schema->objects = array();
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
+41
View File
@@ -0,0 +1,41 @@
<?php
$this->app->loadLang('product');
$this->app->loadLang('program');
$this->app->loadLang('tree');
$schema = new stdclass();
$schema->primaryTable = 'product';
$schema->tables = array();
$schema->tables['product'] = 'zt_product';
$schema->tables['program'] = 'zt_project';
$schema->tables['line'] = 'zt_module';
$schema->joins = array();
$schema->joins['program'] = 'product.program = program.id';
$schema->joins['line'] = 'product.line = line.id';
$schema->fields = array();
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->fields['program'] = array('type' => 'object', 'name' => $this->lang->product->program, 'object' => 'program', 'show' => 'program.name');
$schema->fields['line'] = array('type' => 'object', 'name' => $this->lang->product->line, 'object' => 'line', 'show' => 'line.name');
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
$schema->fields['code'] = array('type' => 'string', 'name' => $this->lang->product->code);
$schema->fields['type'] = array('type' => 'option', 'name' => $this->lang->product->type, 'options' => $this->lang->product->typeList);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->product->status, 'options' => $this->lang->product->statusList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->product->desc);
$schema->fields['PO'] = array('type' => 'user', 'name' => $this->lang->product->PO);
$schema->fields['QD'] = array('type' => 'user', 'name' => $this->lang->product->QD);
$schema->fields['RD'] = array('type' => 'user', 'name' => $this->lang->product->RD);
$schema->fields['createdBy'] = array('type' => 'user', 'name' => $this->lang->product->createdBy);
$schema->fields['createdDate'] = array('type' => 'date', 'name' => $this->lang->product->createdDate);
$schema->objects = array();
$schema->objects['program'] = array();
$schema->objects['program']['id'] = array('type' => 'number', 'name' => $this->lang->program->id);
$schema->objects['program']['name'] = array('type' => 'string', 'name' => $this->lang->program->name);
$schema->objects['line'] = array();
$schema->objects['line']['name'] = array('type' => 'string', 'name' => $this->lang->product->line);
+28
View File
@@ -0,0 +1,28 @@
<?php
$this->app->loadLang('productplan');
$this->app->loadLang('product');
$schema = new stdclass();
$schema->primaryTable = 'productplan';
$schema->tables = array();
$schema->tables['productplan'] = 'zt_productplan';
$schema->tables['product'] = 'zt_product';
$schema->joins = array();
$schema->joins['product'] = 'productplan.product = product.id';
$schema->fields = array();
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->productplan->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['title'] = array('type' => 'string', 'name' => $this->lang->productplan->title);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->productplan->status, 'options' => $this->lang->productplan->statusList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->productplan->desc);
$schema->fields['begin'] = array('type' => 'date', 'name' => $this->lang->productplan->begin);
$schema->fields['end'] = array('type' => 'date', 'name' => $this->lang->productplan->end);
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
+30
View File
@@ -0,0 +1,30 @@
<?php
$this->app->loadLang('project');
$this->app->loadLang('product');
$schema = new stdclass();
$schema->primaryTable = 'project';
$schema->tables = array();
$schema->tables['project'] = 'zt_project';
$schema->joins = array();
$schema->fields = array();
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->fields['code'] = array('type' => 'string', 'name' => $this->lang->project->code);
$schema->fields['model'] = array('type' => 'option', 'name' => $this->lang->project->model, 'options' => $this->lang->project->modelList);
$schema->fields['type'] = array('type' => 'option', 'name' => $this->lang->project->type, 'options' => $this->lang->project->typeList);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->project->status, 'options' => $this->lang->project->statusList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->project->desc);
$schema->fields['begin'] = array('type' => 'date', 'name' => $this->lang->project->begin);
$schema->fields['end'] = array('type' => 'date', 'name' => $this->lang->project->end);
$schema->fields['PO'] = array('type' => 'user', 'name' => $this->lang->product->PO);
$schema->fields['PM'] = array('type' => 'user', 'name' => $this->lang->project->common . $this->lang->project->PM);
$schema->fields['QD'] = array('type' => 'user', 'name' => $this->lang->project->QD);
$schema->fields['RD'] = array('type' => 'user', 'name' => $this->lang->project->RD);
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->project->openedBy);
$schema->fields['openedDate'] = array('type' => 'date', 'name' => $this->lang->project->openedDate);
$schema->objects = array();
+46
View File
@@ -0,0 +1,46 @@
<?php
$this->app->loadLang('release');
$this->app->loadLang('product');
$this->app->loadLang('project');
$this->app->loadLang('build');
$schema = new stdclass();
$schema->primaryTable = 'release';
$schema->tables = array();
$schema->tables['release'] = 'zt_release';
$schema->tables['product'] = 'zt_product';
$schema->tables['project'] = 'zt_project';
$schema->tables['build'] = 'zt_build';
$schema->joins = array();
$schema->joins['product'] = 'release.product = product.id';
$schema->joins['project'] = 'release.project = project.id';
$schema->joins['build'] = 'release.build = build.id';
$schema->fields = array();
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->release->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->release->project, 'object' => 'project', 'show' => 'project.name');
$schema->fields['build'] = array('type' => 'object', 'name' => $this->lang->release->build, 'object' => 'build', 'show' => 'build.name');
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->release->name);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->release->status, 'options' => $this->lang->release->statusList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->release->desc);
$schema->fields['date'] = array('type' => 'date', 'name' => $this->lang->release->date);
$schema->fields['stories'] = array('type' => 'string', 'name' => $this->lang->release->stories);
$schema->fields['bugs'] = array('type' => 'string', 'name' => $this->lang->release->bugs);
$schema->fields['leftBugs'] = array('type' => 'string', 'name' => $this->lang->release->leftBugs);
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->objects['build'] = array();
$schema->objects['build']['id'] = array('type' => 'number', 'name' => $this->lang->build->id);
$schema->objects['build']['name'] = array('type' => 'string', 'name' => $this->lang->build->common);
+49
View File
@@ -0,0 +1,49 @@
<?php
$this->app->loadLang('product');
$this->app->loadLang('productplan');
$this->app->loadLang('story');
$this->app->loadLang('project');
$this->app->loadLang('tree');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'story';
$schema->tables = array();
$schema->tables['story'] = 'zt_story';
$schema->tables['product'] = 'zt_product';
$schema->tables['productline'] = 'zt_module';
$schema->tables['productplan'] = 'zt_productplan';
$schema->tables['program'] = 'zt_project';
$schema->tables['project'] = 'zt_project';
$schema->tables['storymodule'] = 'zt_module';
$schema->tables['storyspec'] = 'zt_storyspec';
$schema->joins = array();
$schema->joins['product'] = 'product.id = story.product';
$schema->joins['storymodule'] = 'storymodule.id = story.module';
$schema->joins['storyspec'] = 'storyspec.story = story.id';
$schema->fields = array();
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->story->id);
$schema->fields['title'] = array('type' => 'string', 'name' => $this->lang->story->title);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->story->status, 'options' => $this->lang->story->statusList);
$schema->fields['stage'] = array('type' => 'option', 'name' => $this->lang->story->stage, 'options' => $this->lang->story->stageList);
$schema->fields['pri'] = array('type' => 'option', 'name' => $this->lang->story->pri, 'options' => $this->lang->story->priList);
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->story->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['storymodule'] = array('type' => 'object', 'name' => $this->lang->story->module, 'object' => 'storymodule', 'show' => 'storymodule.name');
$schema->fields['closedDate'] = array('type' => 'date', 'name' => $this->lang->story->closedDate);
$schema->fields['closedReason'] = array('type' => 'option', 'name' => $this->lang->story->closedReason, 'options' => $this->lang->story->reasonList);
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->story->openedBy);
$schema->fields['openedDate'] = array('type' => 'date', 'name' => $this->lang->story->openedDate);
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->common);
$schema->objects['storymodule'] = array();
$schema->objects['storymodule']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['storymodule']['name'] = array('type' => 'string', 'name' => $this->lang->tree->name);
+63
View File
@@ -0,0 +1,63 @@
<?php
$this->app->loadLang('task');
$this->app->loadLang('project');
$this->app->loadLang('execution');
$this->app->loadLang('story');
$this->app->loadLang('tree');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'task';
$schema->tables = array();
$schema->tables['task'] = 'zt_task';
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->tables['story'] = 'zt_story';
$schema->tables['taskmodule'] = 'zt_module';
$schema->joins = array();
$schema->joins['execution'] = 'task.execution = execution.id';
$schema->joins['project'] = 'task.project = project.id';
$schema->joins['story'] = 'task.story = story.id';
$schema->joins['taskmodule'] = 'task.module = taskmodule.id';
$schema->fields = array();
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->task->project, 'object' => 'project', 'show' => 'project.name');
$schema->fields['execution'] = array('type' => 'object', 'name' => $this->lang->task->execution, 'object' => 'execution', 'show' => 'execution.name');
$schema->fields['story'] = array('type' => 'object', 'name' => $this->lang->task->story, 'object' => 'story', 'show' => 'story.title');
$schema->fields['taskmodule'] = array('type' => 'object', 'name' => $this->lang->task->module, 'object' => 'taskmodule', 'show' => 'taskmodule.name');
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->task->name);
$schema->fields['pri'] = array('type' => 'option', 'name' => $this->lang->task->pri, 'options' => $this->lang->task->priList);
$schema->fields['type'] = array('type' => 'option', 'name' => $this->lang->task->type, 'options' => $this->lang->task->typeList);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->task->status, 'options' => $this->lang->task->statusList);
$schema->fields['desc'] = array('type' => 'string', 'name' => $this->lang->task->desc);
$schema->fields['estimate'] = array('type' => 'string', 'name' => $this->lang->task->estimate);
$schema->fields['consumed'] = array('type' => 'string', 'name' => $this->lang->task->consumed);
$schema->fields['left'] = array('type' => 'string', 'name' => $this->lang->task->left);
$schema->fields['estStarted'] = array('type' => 'date', 'name' => $this->lang->task->estStarted);
$schema->fields['deadline'] = array('type' => 'date', 'name' => $this->lang->task->deadline);
$schema->fields['assignedTo'] = array('type' => 'user', 'name' => $this->lang->task->assignedTo);
$schema->fields['finishedBy'] = array('type' => 'user', 'name' => $this->lang->task->finishedBy);
$schema->fields['closedBy'] = array('type' => 'user', 'name' => $this->lang->task->closedBy);
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->task->openedBy);
$schema->fields['openedDate'] = array('type' => 'date', 'name' => $this->lang->task->openedDate);
$schema->objects = array();
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->execution->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
$schema->objects['story'] = array();
$schema->objects['story']['id'] = array('type' => 'number', 'name' => $this->lang->story->id);
$schema->objects['story']['title'] = array('type' => 'string', 'name' => $this->lang->story->title);
$schema->objects['taskmodule'] = array();
$schema->objects['taskmodule']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['taskmodule']['name'] = array('type' => 'string', 'name' => $this->lang->tree->name);
+36
View File
@@ -0,0 +1,36 @@
<?php
$this->app->loadLang('task');
$this->app->loadLang('project');
$this->app->loadLang('execution');
$teamLang = new stdclass();
$teamLang->type = '对象类型';
$teamLang->typeList['task'] = '任务';
$teamLang->typeList['execution'] = '执行';
$teamLang->typeList['project'] = '项目';
$schema = new stdclass();
$schema->primaryTable = 'team';
$schema->tables = array();
$schema->tables['team'] = 'zt_team';
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->tables['task'] = 'zt_task';
$schema->joins = array();
$schema->joins['execution'] = 'team.root = execution.id';
$schema->joins['project'] = 'team.root = project.id';
$schema->joins['task'] = 'team.root = task.id';
$schema->fields = array();
$schema->fields['root'] = array('type' => 'object', 'name' => $this->lang->execution->common, 'object' => 'execution', 'show' => 'execution.name');
$schema->fields['account'] = array('type' => 'user', 'name' => $this->lang->team->account);
$schema->fields['type'] = array('type' => 'option', 'name' => $teamLang->type, 'options' => $teamLang->typeList);
$schema->objects = array();
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->execution->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
+52
View File
@@ -0,0 +1,52 @@
<?php
$this->app->loadLang('product');
$this->app->loadLang('testcase');
$this->app->loadLang('testtask');
$this->app->loadLang('tree');
$this->app->loadLang('story');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'testcase';
$schema->tables = array();
$schema->tables['testcase'] = 'zt_case';
$schema->tables['product'] = 'zt_product';
$schema->tables['casemodule'] = 'zt_module';
$schema->tables['story'] = 'zt_story';
$schema->tables['casestep'] = 'zt_casestep';
$schema->joins = array();
$schema->joins['product'] = 'product.id = testcase.product';
$schema->joins['casemodule'] = 'casemodule.id = testcase.module';
$schema->joins['story'] = 'story.id = testcase.story';
$schema->joins['casestep'] = 'casestep.case = testcase.id';
$schema->fields = array();
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->testcase->id);
$schema->fields['title'] = array('type' => 'string', 'name' => $this->lang->testcase->title);
$schema->fields['pri'] = array('type' => 'option', 'name' => $this->lang->testcase->pri, 'options' => $this->lang->testcase->priList);
$schema->fields['type'] = array('type' => 'option', 'name' => $this->lang->testcase->type, 'options' => $this->lang->testcase->typeList);
$schema->fields['stage'] = array('type' => 'option', 'name' => $this->lang->testcase->stage, 'options' => $this->lang->testcase->stageList);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->testcase->status, 'options' => $this->lang->testcase->statusList);
$schema->fields['version'] = array('type' => 'number', 'name' => $this->lang->testcase->version);
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->testcase->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['story'] = array('type' => 'object', 'name' => $this->lang->testcase->story, 'object' => 'story', 'show' => 'story.title');
$schema->fields['casemodule'] = array('type' => 'object', 'name' => $this->lang->testcase->module, 'object' => 'casemodule', 'show' => 'casemodule.name');
$schema->fields['openedBy'] = array('type' => 'user', 'name' => $this->lang->testcase->openedBy);
$schema->fields['openedDate'] = array('type' => 'date', 'name' => $this->lang->testcase->openedDate);
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->common);
$schema->objects['casemodule'] = array();
$schema->objects['casemodule']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['casemodule']['name'] = array('type' => 'string', 'name' => $this->lang->tree->name);
$schema->objects['story'] = array();
$schema->objects['story']['id'] = array('type' => 'number', 'name' => $this->lang->story->id);
$schema->objects['story']['title'] = array('type' => 'string', 'name' => $this->lang->story->title);
+84
View File
@@ -0,0 +1,84 @@
<?php
$this->app->loadLang('testcase');
$this->app->loadLang('testtask');
$this->app->loadLang('project');
$this->app->loadLang('execution');
$this->app->loadLang('tree');
$this->app->loadLang('build');
$this->app->loadLang('caselib');
$this->app->loadLang('product');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'testresult';
$schema->tables = array();
$schema->tables['testcase'] = 'zt_case';
$schema->tables['testrun'] = 'zt_testrun';
$schema->tables['testresult'] = 'zt_testresult';
$schema->tables['testtask'] = 'zt_testtask';
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->tables['casemodule'] = 'zt_module';
$schema->tables['build'] = 'zt_build';
$schema->tables['caselib'] = 'zt_testsuite';
$schema->tables['product'] = 'zt_product';
$schema->joins = array();
$schema->joins['testcase'] = 'testcase.id = testresult.case';
$schema->joins['testrun'] = 'testrun.id = testresult.run';
$schema->joins['testtask'] = 'testrun.task = testtask.id';
$schema->joins['project'] = 'project.id = testtask.project';
$schema->joins['execution'] = 'execution.id = testtask.execution';
$schema->joins['casemodule'] = 'casemodule.id = testcase.module';
$schema->joins['build'] = 'build.id = testtask.build';
$schema->joins['caselib'] = 'caselib.id = testcase.lib';
$schema->joins['product'] = 'product.id = testcase.product';
$schema->fields = array();
$schema->fields['caseResult'] = array('type' => 'option', 'name' => $this->lang->testtask->caseResult, 'options' => $this->lang->testcase->resultList);
$schema->fields['stepResults'] = array('type' => 'json', 'name' => $this->lang->testtask->stepResults);
$schema->fields['lastRunner'] = array('type' => 'user', 'name' => $this->lang->testtask->lastRunner);
$schema->fields['date'] = array('type' => 'date', 'name' => $this->lang->testtask->date);
$schema->fields['testcase'] = array('type' => 'object', 'name' => $this->lang->testcase->common, 'object' => 'testcase', 'show' => 'testcase.title');
$schema->fields['testtask'] = array('type' => 'object', 'name' => $this->lang->testtask->common, 'object' => 'testtask', 'show' => 'testtask.name');
$schema->fields['execution'] = array('type' => 'object', 'name' => $this->lang->execution->common, 'object' => 'execution', 'show' => 'execution.name');
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->project->common, 'object' => 'project', 'show' => 'execution.name');
$schema->fields['casemodule'] = array('type' => 'object', 'name' => $this->lang->tree->common, 'object' => 'casemodule', 'show' => 'casemodule.name');
$schema->fields['build'] = array('type' => 'object', 'name' => $this->lang->build->common, 'object' => 'build', 'show' => 'build.name');
$schema->fields['caselib'] = array('type' => 'object', 'name' => $this->lang->caselib->common, 'object' => 'caselib', 'show' => 'caselib.name');
$schema->objects = array();
$schema->objects['testcase'] = array();
$schema->objects['testcase']['id'] = array('type' => 'number', 'name' => $this->lang->testcase->id);
$schema->objects['testcase']['title'] = array('type' => 'string', 'name' => $this->lang->testcase->title);
$schema->objects['testtask'] = array();
$schema->objects['testtask']['id'] = array('type' => 'number', 'name' => $this->lang->testtask->id);
$schema->objects['testtask']['name'] = array('type' => 'string', 'name' => $this->lang->testtask->name);
$schema->objects['build'] = array();
$schema->objects['build']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['build']['name'] = array('type' => 'string', 'name' => $this->lang->build->name);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->execution->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
$schema->objects['casemodule'] = array();
$schema->objects['casemodule']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['casemodule']['name'] = array('type' => 'string', 'name' => $this->lang->dataview->name);
$schema->objects['caselib'] = array();
$schema->objects['caselib']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['caselib']['name'] = array('type' => 'string', 'name' => $this->lang->caselib->name);
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
+78
View File
@@ -0,0 +1,78 @@
<?php
$this->app->loadLang('testcase');
$this->app->loadLang('testtask');
$this->app->loadLang('tree');
$this->app->loadLang('project');
$this->app->loadLang('execution');
$this->app->loadLang('build');
$this->app->loadLang('product');
$this->app->loadLang('dataview');
$schema = new stdclass();
$schema->primaryTable = 'testrun';
$schema->tables = array();
$schema->tables['testrun'] = 'zt_testrun';
$schema->tables['testcase'] = 'zt_case';
$schema->tables['testtask'] = 'zt_testtask';
$schema->tables['casemodule'] = 'zt_module';
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->tables['build'] = 'zt_build';
$schema->tables['product'] = 'zt_product';
$schema->joins = array();
$schema->joins['testcase'] = 'testcase.id = testrun.case';
$schema->joins['product'] = 'product.id = testcase.product';
$schema->joins['testtask'] = 'testtask.id = testrun.task';
$schema->joins['casemodule'] = 'casemodule.id = testcase.module';
$schema->joins['project'] = 'project.id = testtask.project';
$schema->joins['execution'] = 'execution.id = testtask.execution';
$schema->joins['build'] = 'build.id = testtask.build';
$schema->fields = array();
$schema->fields['testtask'] = array('type' => 'object', 'name' => $this->lang->testtask->common, 'object' => 'testtask', 'show' => 'testtask.name');
$schema->fields['testcase'] = array('type' => 'object', 'name' => $this->lang->testcase->common, 'object' => 'testcase', 'show' => 'testcase.title');
$schema->fields['assignedTo'] = array('type' => 'user', 'name' => $this->lang->testcase->assignedTo);
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->project->common, 'object' => 'project', 'show' => 'execution.name');
$schema->fields['build'] = array('type' => 'object', 'name' => $this->lang->build->common, 'object' => 'build', 'show' => 'build.name');
$schema->fields['execution'] = array('type' => 'object', 'name' => $this->lang->execution->common, 'object' => 'execution', 'show' => 'execution.name');
$schema->fields['casemodule'] = array('type' => 'object', 'name' => $this->lang->tree->common, 'object' => 'casemodule', 'show' => 'casemodule.name');
$schema->fields['lastRunner'] = array('type' => 'user', 'name' => $this->lang->testtask->lastRunner);
$schema->fields['lastRunDate'] = array('type' => 'user', 'name' => $this->lang->testtask->lastRunDate);
$schema->fields['lastRunResult'] = array('type' => 'option', 'name' => $this->lang->testtask->lastRunResult, 'options' => $this->lang->testcase->resultList);
$schema->objects = array();
$schema->objects['testcase'] = array();
$schema->objects['testcase']['id'] = array('type' => 'number', 'name' => $this->lang->testcase->id);
$schema->objects['testcase']['title'] = array('type' => 'string', 'name' => $this->lang->testcase->title);
$schema->objects['testtask'] = array();
$schema->objects['testtask']['id'] = array('type' => 'number', 'name' => $this->lang->testtask->id);
$schema->objects['testtask']['name'] = array('type' => 'string', 'name' => $this->lang->testtask->name);
$schema->objects['testcase'] = array();
$schema->objects['testcase']['id'] = array('type' => 'number', 'name' => $this->lang->testcase->id);
$schema->objects['testcase']['title'] = array('type' => 'string', 'name' => $this->lang->testcase->title);
$schema->objects['build'] = array();
$schema->objects['build']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['build']['name'] = array('type' => 'string', 'name' => $this->lang->build->name);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->execution->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
$schema->objects['casemodule'] = array();
$schema->objects['casemodule']['id'] = array('type' => 'number', 'name' => $this->lang->dataview->id);
$schema->objects['casemodule']['name'] = array('type' => 'string', 'name' => $this->lang->dataview->name);
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
+56
View File
@@ -0,0 +1,56 @@
<?php
$this->app->loadLang('product');
$this->app->loadLang('project');
$this->app->loadLang('execution');
$this->app->loadLang('build');
$this->app->loadLang('testtask');
$schema = new stdclass();
$schema->primaryTable = 'testtask';
$schema->tables = array();
$schema->tables['product'] = 'zt_product';
$schema->tables['project'] = 'zt_project';
$schema->tables['execution'] = 'zt_project';
$schema->tables['build'] = 'zt_build';
$schema->tables['testtask'] = 'zt_testtask';
$schema->joins = array();
$schema->joins['product'] = 'product.id = testtask.product';
$schema->joins['project'] = 'project.id = testtask.project';
$schema->joins['execution'] = 'execution.id = testtask.execution';
$schema->joins['build'] = 'build.id = testtask.build';
$schema->fields = array();
$schema->fields['product'] = array('type' => 'object', 'name' => $this->lang->testtask->product, 'object' => 'product', 'show' => 'product.name');
$schema->fields['project'] = array('type' => 'object', 'name' => $this->lang->testtask->project, 'object' => 'project', 'show' => 'project.name');
$schema->fields['execution'] = array('type' => 'object', 'name' => $this->lang->testtask->execution, 'object' => 'execution', 'show' => 'execution.name');
$schema->fields['build'] = array('type' => 'object', 'name' => $this->lang->testtask->build, 'object' => 'build', 'show' => 'build.name');
$schema->fields['id'] = array('type' => 'number', 'name' => $this->lang->testtask->id);
$schema->fields['name'] = array('type' => 'string', 'name' => $this->lang->testtask->name);
$schema->fields['type'] = array('type' => 'option', 'name' => $this->lang->testtask->type, 'options' => $this->lang->testtask->typeList);
$schema->fields['owner'] = array('type' => 'user', 'name' => $this->lang->testtask->owner);
$schema->fields['pri'] = array('type' => 'option', 'name' => $this->lang->testtask->pri, 'options' => $this->lang->testtask->priList);
$schema->fields['begin'] = array('type' => 'date', 'name' => $this->lang->testtask->begin);
$schema->fields['end'] = array('type' => 'date', 'name' => $this->lang->testtask->end);
$schema->fields['status'] = array('type' => 'option', 'name' => $this->lang->testtask->status, 'options' => $this->lang->testtask->statusList);
$schema->objects = array();
$schema->objects['product'] = array();
$schema->objects['product']['id'] = array('type' => 'number', 'name' => $this->lang->product->id);
$schema->objects['product']['name'] = array('type' => 'string', 'name' => $this->lang->product->name);
$schema->objects['project'] = array();
$schema->objects['project']['id'] = array('type' => 'number', 'name' => $this->lang->project->id);
$schema->objects['project']['name'] = array('type' => 'string', 'name' => $this->lang->project->name);
$schema->objects['execution'] = array();
$schema->objects['execution']['id'] = array('type' => 'number', 'name' => $this->lang->execution->id);
$schema->objects['execution']['name'] = array('type' => 'string', 'name' => $this->lang->execution->name);
$schema->objects['build'] = array();
$schema->objects['build']['id'] = array('type' => 'number', 'name' => $this->lang->build->id);
$schema->objects['build']['name'] = array('type' => 'string', 'name' => $this->lang->build->name);
+14 -17
View File
@@ -106,7 +106,7 @@ class doc extends control
$this->view->param = $param;
$this->view->libID = $libID;
$this->view->lib = $this->doc->getLibById($libID);
$this->view->libTree = $this->doc->getLibTree($libID, $libs, 'mine', 0);
$this->view->libTree = $this->doc->getLibTree($type != 'mine' ? 0 : $libID, $libs, 'mine', 0);
$this->view->pager = $pager;
$this->view->type = $type;
$this->view->objectID = 0;
@@ -163,10 +163,10 @@ class doc extends control
}
}
if($type == 'execution') $objects = $this->execution->getPairs(0, 'all', 'multiple,leaf,noprefix');
if($type == 'execution')
{
$objects = $this->execution->getPairs(0, 'sprint,stage', 'multiple,leaf,noprefix');
$execution = $this->execution->getByID($objectID);
if($execution->type == 'stage') $this->lang->doc->execution = str_replace($this->lang->executionCommon, $this->lang->project->stage, $this->lang->doc->execution);
}
@@ -730,28 +730,21 @@ class doc extends control
*/
public function collect($objectID, $objectType)
{
$table = '';
if($objectType == 'doc') $table = TABLE_DOC;
if($objectType == 'doclib') $table = TABLE_DOCLIB;
if($objectType == 'module') $table = TABLE_MODULE;
$collectors = $this->dao->select('collector')->from($table)->where('id')->eq($objectID)->fetch('collector');
if(empty($table)) return;
$hasCollect = strpos($collectors, ",{$this->app->user->account},") !== false;
if($hasCollect)
$action = $this->doc->getActionByObject($objectID, 'collect');
if($action)
{
$collectors = str_replace(",{$this->app->user->account},", ',', $collectors);
$this->doc->deleteAction($action->id);
}
else
{
$collectors = explode(',', $collectors);
$collectors[] = $this->app->user->account;
$collectors = implode(',', $collectors);
$this->doc->createAction($objectID, 'collect');
}
$collectors = trim($collectors, ',') ? ',' . trim($collectors, ',') . ',' : '';
$this->dao->update($table)->set('collector')->eq($collectors)->where('id')->eq($objectID)->exec();
return $this->send(array('status' => $hasCollect ? 'no' : 'yes'));
return $this->send(array('status' => $action ? 'no' : 'yes'));
}
/**
@@ -810,6 +803,8 @@ class doc extends control
*/
public function ajaxGetModules($objectType, $objectID, $docType = 'doc')
{
if(empty($objectID)) return print(html::select('module', array(), '', "class='form-control'"));
if($docType == 'doc')
{
$unclosed = strpos($this->config->doc->custom->showLibs, 'unclosed') !== false ? 'unclosedProject' : '';
@@ -1131,6 +1126,7 @@ class doc extends control
$doc = $this->doc->getById($docID, $version, true);
if(!$doc) return print(js::error($this->lang->notFound));
$this->doc->createAction($docID, 'view');
if($doc->keywords)
{
$doc->keywords = str_replace(",", ',', $doc->keywords);
@@ -1303,7 +1299,7 @@ class doc extends control
$this->view->isFirstLoad = $isFirstLoad;
$this->view->param = $queryID;
$this->view->users = $this->user->getPairs('noletter');
$this->view->libTree = $this->doc->getLibTree($libID, $libs, $type, $moduleID, $objectID, $browseType);
$this->view->libTree = $this->doc->getLibTree($libID, $libs, $type, $moduleID, $objectID, $browseType, $param);
$this->view->libID = $libID;
$this->view->moduleID = $moduleID;
$this->view->objectDropdown = $objectDropdown;
@@ -1312,6 +1308,7 @@ class doc extends control
$this->view->pager = $pager;
$this->view->objectID = $objectID;
$this->view->orderBy = $orderBy;
$this->view->release = $browseType == 'byrelease' ? $param : 0;
$this->view->canExport = $libType == 'api' ? common::hasPriv('api', 'export') : common::hasPriv('doc', $type . '2export');
$this->view->exportMethod = $libType == 'api' ? 'export' : $type . '2export';
$this->view->apiLibID = key($apiLibs);
-1
View File
@@ -12,7 +12,6 @@
.col-spliter:hover:after,
.row-spliting .col-spliter:before,
.row-spliting .col-spliter:after {opacity: 1;}
@media (max-width: 720px)
{
.split-row > .side-col,
+14 -1
View File
@@ -1 +1,14 @@
#mainContent .c-id > a {color: #0c60e1;}
.flex {display: flex;}
.flex-none {flex: none;}
.flex-auto {flex: auto;}
.flex-full > .panel {box-shadow: none;}
.float-r {float: right;}
.h-full {height: 100%;}
.w-full {width: 100%;}
.overflow-x-auto {overflow-x: auto;}
.overflow-auto {overflow: auto;}
.overflow-visible {overflow: visible;}
.overflow-hidden {overflow: hidden;}
#mainContent > .panel {margin-bottom: 0; height: calc(100vh - 125px); overflow-y: auto;}
#bysearchTab::before {display: none;}
#queryBox #groupAndOr {min-width: 60px;}
+2
View File
@@ -1 +1,3 @@
#lib_chosen.chosen-container .chosen-results {max-height: 100px;}
.radio-inline+.radio-inline { margin-top: 0; margin-left: 0px;}
.radio-inline {margin-right: 10px;}
+2 -1
View File
@@ -9,14 +9,15 @@
.overflow-auto {overflow: auto;}
.overflow-visible {overflow: visible;}
.overflow-hidden {overflow: hidden;}
#main {padding-bottom: 0;}
.img-lib {width: 14px; height: 14px; margin-bottom: 2px; flex: 0 0 14px;}
#main {padding-bottom: 0;}
#mainContent {padding-top: 0; padding-bottom: 0;}
#mainContent #createDropdown {display: inline-block;}
#mainContent #createDropdown ul {position: absolute;}
#pageNav .dropdown-menu {max-height: inherit;}
#mainContent > .panel {margin-bottom: 0; height: calc(100vh - 125px); overflow-y: auto;}
#mainContent > .main-col {padding-left: 0;}
#swapper {margin-right: 15px;}
.no-content {width: 100px; height: 100px; margin: 0 auto;}
.notice {text-align: center; padding-left: 15px; padding-top: 20px;}
+8 -2
View File
@@ -1,3 +1,4 @@
.h-full-adjust {overflow-y: auto; height: calc(100vh - 100px);}
.main-col .block-files .panel-heading {padding-right: 20px;}
.main-col .block-files .panel-heading .panel-title {height: 35px; line-height: 30px;}
.main-col .doc-title {display: flex; font-size: 16px; margin-bottom: 15px;}
@@ -31,7 +32,7 @@
.outline-content a {color: #838A9D;}
.outline-content li.text-ellipsis.active>a {font-weight: 700; color: #0c64eb;}
#outline li.has-list.open:before {content: unset;}
#fileTree {margin-bottom: 40px; max-height: calc(100vh - 180px); overflow: auto;}
#fileTree {margin-bottom: 40px; max-height: calc(100vh - 160px); overflow: auto;}
.title {font-size: 20px !important;}
.article-content.comment {width: 100% !important;}
@@ -47,5 +48,10 @@
.overflow-auto {overflow: auto;}
.overflow-visible {overflow: visible;}
.overflow-hidden {overflow: hidden;}
#mainContent > .panel {margin-bottom: 0; height: calc(100vh - 125px); overflow-y: auto;}
#mainContent > .panel {margin-bottom: 0; overflow-y: auto;}
.detail-title .actions .ajaxCollect > img {width: 20px;}
.actions > .text {color: #8c8c8c; font-size: 14px;}
.flex-content {display: flex; width: 100%; height: 100%;}
.flex-content > #content {flex: auto; overflow-y: auto;}
.flex-content > #history {flex: 0 0 302px;;}
.panel {margin-bottom: 0;}
+17 -6
View File
@@ -10,6 +10,7 @@ function loadObjectModules(objectType, objectID, docType)
{
if(typeof docType == 'undefined') docType = 'doc';
var link = createLink('doc', 'ajaxGetModules', 'objectType=' + objectType + '&objectID=' + objectID + '&type=' + docType);
if(objectType == 'execution' && objectID == 0) var link = createLink('doc', 'ajaxGetModules', 'objectType=project&objectID=' + $('#project').val() + '&type=' + docType);
$('#moduleBox').load(link, function(){$('#moduleBox').find('select').picker(); $('#moduleLabel').remove();});
}
@@ -342,25 +343,35 @@ function locateNewLib(type, objectID, libID)
*/
function setSavePath()
{
var getSubPath = function($obj)
{
var $td = $obj.parent();
var usePicker = $td.find('.picker').length == 1;
var subPath = $obj.find('option:checked').text();
if(usePicker) subPath = $td.find('.picker .picker-selection-text').text();
return subPath;
}
savePath = defaultSave;
if($('#modalBasicInfo #product').length == 1)
{
savePath += $('#modalBasicInfo #product option:checked').text() + '/';
savePath += getSubPath($('#modalBasicInfo #product')) + '/';
}
else if($('#modalBasicInfo #project').length == 1 && $('#modalBasicInfo #execution').length == 0)
{
savePath += $('#modalBasicInfo #project option:checked').text() + '/';
savePath += getSubPath($('#modalBasicInfo #project')) + '/';
}
else if($('#modalBasicInfo #project').length == 1 && $('#modalBasicInfo #execution').length == 1)
{
if($('#modalBasicInfo #execution').val() == '') savePath += $('#modalBasicInfo #project option:checked').text() + '/';
if($('#modalBasicInfo #execution').val() != '') savePath += $('#modalBasicInfo #execution option:checked').text() + '/';
var executionID = $('#modalBasicInfo #execution').val();
if(executionID == '0' || executionID == '') savePath += getSubPath($('#modalBasicInfo #project')) + '/';
if(executionID != '0' && executionID != '') savePath += getSubPath($('#modalBasicInfo #execution')) + '/';
}
else if($('#modalBasicInfo #execution').length == 1)
{
savePath += $('#modalBasicInfo #execution option:checked').text() + '/';
savePath += getSubPath($('#modalBasicInfo #execution')) + '/';
}
savePath += $('#modalBasicInfo #module option:checked').text();
savePath += getSubPath($('#modalBasicInfo #module'));
$('#savePath').html(savePath).attr('title', savePath);
}
+17 -1
View File
@@ -188,7 +188,7 @@ $(function()
simplemde.togglePreview();
}
});
});
})
$('#sidebar .icon.icon-angle-right').click(function()
{
@@ -199,4 +199,20 @@ $(function()
})
$('.outline .outline-toggle i.icon-angle-right').trigger("click");
$('#hisTrigger').on('click', function()
{
var $history = $('#history');
var $icon = $(this);
if($history.hasClass('hidden'))
{
$history.removeClass('hidden');
$icon.addClass('text-primary');
}
else
{
$history.addClass('hidden');
$icon.removeClass('text-primary');
}
})
$('#history').find('.btn.pull-right').removeClass('pull-right');
})
+3 -1
View File
@@ -70,7 +70,7 @@ $lang->doc->project = $lang->projectCommon;
$lang->doc->execution = $lang->execution->common;
$lang->doc->lib = 'Bibliothek';
$lang->doc->module = 'Modul';
$lang->doc->libAndModule = 'Bibliothek & Modul';
$lang->doc->libAndModule = 'Bibliothek&Modul';
$lang->doc->object = 'Object';
$lang->doc->title = 'Titel';
$lang->doc->digest = 'Zusammenfassung';
@@ -121,6 +121,7 @@ $lang->doc->nextStep = 'Next';
$lang->doc->closed = 'Closed';
$lang->doc->saveDraft = 'Save Draft';
$lang->doc->defaultSave = 'Default Save: ';
$lang->doc->position = 'Position';
$lang->doc->moduleDoc = 'Nach Modulen';
$lang->doc->searchDoc = 'Suche';
@@ -137,6 +138,7 @@ $lang->doc->myDoc = 'Meine Dokumente';
$lang->doc->myView = 'Recently Viewed';
$lang->doc->myCollection = 'Meine Favoriten';
$lang->doc->myCreation = 'Created By';
$lang->doc->myLib = 'My Library';
$lang->doc->tableContents = 'Catalog';
$lang->doc->addCatalog = 'Add Catalog';
$lang->doc->editCatalog = 'Edit Catalog';
+3 -1
View File
@@ -70,7 +70,7 @@ $lang->doc->project = $lang->projectCommon;
$lang->doc->execution = $lang->execution->common;
$lang->doc->lib = 'Library';
$lang->doc->module = 'Catalog';
$lang->doc->libAndModule = 'Library & Catalog';
$lang->doc->libAndModule = 'Library&Catalog';
$lang->doc->object = 'Object';
$lang->doc->title = 'Name';
$lang->doc->digest = 'Summary';
@@ -121,6 +121,7 @@ $lang->doc->nextStep = 'Next';
$lang->doc->closed = 'Closed';
$lang->doc->saveDraft = 'Save Draft';
$lang->doc->defaultSave = 'Default Save: ';
$lang->doc->position = 'Position';
$lang->doc->moduleDoc = 'By Module';
$lang->doc->searchDoc = 'Search';
@@ -137,6 +138,7 @@ $lang->doc->myDoc = 'My Documents';
$lang->doc->myView = 'Recently Viewed';
$lang->doc->myCollection = 'My Favorites';
$lang->doc->myCreation = 'Created By';
$lang->doc->myLib = 'My Library';
$lang->doc->tableContents = 'Directory';
$lang->doc->addCatalog = 'Add Catalog';
$lang->doc->editCatalog = 'Edit Catalog';
+3 -1
View File
@@ -70,7 +70,7 @@ $lang->doc->project = $lang->projectCommon;
$lang->doc->execution = $lang->execution->common;
$lang->doc->lib = 'Bibliothèque';
$lang->doc->module = 'Catégorie';
$lang->doc->libAndModule = 'Library & Catalog';
$lang->doc->libAndModule = 'Library&Catalog';
$lang->doc->object = 'Object';
$lang->doc->title = 'Nom';
$lang->doc->digest = 'Résumé';
@@ -121,6 +121,7 @@ $lang->doc->nextStep = 'Next';
$lang->doc->closed = 'Closed';
$lang->doc->saveDraft = 'Save Draft';
$lang->doc->defaultSave = 'Default Save: ';
$lang->doc->position = 'Position';
$lang->doc->moduleDoc = 'Par Module';
$lang->doc->searchDoc = 'Rechercher';
@@ -137,6 +138,7 @@ $lang->doc->myDoc = 'Mes Documents';
$lang->doc->myView = 'Recently Viewed';
$lang->doc->myCollection = 'Mes Favoris';
$lang->doc->myCreation = 'Created By';
$lang->doc->myLib = 'My Library';
$lang->doc->tableContents = 'Catalog';
$lang->doc->addCatalog = 'Add Catalog';
$lang->doc->editCatalog = 'Edit Catalog';
+2
View File
@@ -121,6 +121,7 @@ $lang->doc->nextStep = '下一步';
$lang->doc->closed = '已关闭';
$lang->doc->saveDraft = '存为草稿';
$lang->doc->defaultSave = '默认存入:';
$lang->doc->position = '所在位置';
$lang->doc->moduleDoc = '按模块浏览';
$lang->doc->searchDoc = '搜索';
@@ -137,6 +138,7 @@ $lang->doc->myDoc = '我的文档';
$lang->doc->myView = '最近浏览';
$lang->doc->myCollection = '我的收藏';
$lang->doc->myCreation = '我创建的';
$lang->doc->myLib = '我的个人库';
$lang->doc->tableContents = '目录';
$lang->doc->addCatalog = '添加目录';
$lang->doc->editCatalog = '编辑目录';
+182 -19
View File
@@ -467,11 +467,12 @@ class docModel extends model
}
elseif($browseType == "collectedbyme")
{
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('deleted')->eq(0)
->andWhere('lib')->in($allLibs)
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->andWhere('collector')->like("%,{$this->app->user->account},%")
$docs = $this->dao->select('t1.*')->from(TABLE_DOC)->alias('t1')
->leftJoin(TABLE_DOCACTION)->alias('t2')->on("t1.id=t2.doc && t2.action='collect'")
->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('t2.actor')->eq($this->app->user->account)
->orderBy($sort)
->page($pager)
->fetchAll('id');
@@ -484,9 +485,14 @@ class docModel extends model
$docContents = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->in(array_keys($docs))->orderBy('version,doc')->fetchAll('doc');
$modules = array();
$objects = array('product' => 'products', 'execution' => 'executions', 'project' => 'projects');
$this->loadModel('tree');
foreach($docs as $index => $doc)
{
if(!isset($modules[$doc->lib])) $modules[$doc->lib] = $this->tree->getOptionMenu($doc->lib, 'doc', 0, 0, 'nodeleted', 'all', ' > ');
$doc->moduleName = zget($modules[$doc->lib], $doc->module);
$doc->moduleName = ltrim($doc->moduleName, '/');
foreach($objects as $type => $object)
{
if(!empty($doc->{$type}))
@@ -530,6 +536,7 @@ class docModel extends model
}
}
$docs = $this->processCollector($docs);
return $docs;
}
@@ -621,7 +628,7 @@ class docModel extends model
public function getDocs($libID, $module, $browseType, $orderBy, $pager = null)
{
$docIdList = $this->getPrivDocs($libID, $module, 'children');
return $this->dao->select('*')->from(TABLE_DOC)
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('deleted')->eq(0)
->andWhere('vision')->eq($this->config->vision)
->andWhere('id')->in($docIdList)
@@ -630,6 +637,8 @@ class docModel extends model
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
$docs = $this->processCollector($docs);
return $docs;
}
/**
@@ -684,6 +693,10 @@ class docModel extends model
if(strpos($this->server->http_referer, $loginLink) !== false) return print(js::locate(inlink('index')));
return print(js::locate('back'));
}
$docs = $this->processCollector(array($doc->id => $doc));
$doc = $docs[$doc->id];
$version = $version ? $version : $doc->version;
$docContent = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($doc->id)->andWhere('version')->eq($version)->fetch();
@@ -811,7 +824,8 @@ class docModel extends model
if(empty($docContent->content)) return dao::$errors['content'] = sprintf($this->lang->error->notempty, $this->lang->doc->content);
}
$doc->draft = $docContent->content;
$doc->draft = $docContent->content;
$doc->vision = $this->config->vision;
$this->dao->insert(TABLE_DOC)->data($doc, 'content')->autoCheck()
->batchCheck($requiredFields, 'notempty')
->exec();
@@ -1011,6 +1025,11 @@ class docModel extends model
{
$this->config->doc->search['params']['execution']['values'] = array('' => '') + $this->loadModel('execution')->getPairs($this->session->project, 'sprint,stage', 'multiple,leaf,noprefix') + array('all' => $this->lang->doc->allExecutions);
}
elseif($type == 'mine')
{
unset($this->config->doc->search['fields']['addedBy']);
unset($this->config->doc->search['fields']['editedBy']);
}
else
{
unset($this->config->doc->search['fields']['execution']);
@@ -1587,7 +1606,7 @@ class docModel extends model
->leftjoin(TABLE_DOCLIB)->alias('t2')->on('t2.project=t1.id')
->where("CONCAT(',', t2.users, ',')")->like("%,{$this->app->user->account},%")
->andWhere('t1.vision')->eq($this->config->vision)
->andWhere('t1.model')->ne('kanban')
->beginIF($this->config->vision == 'rnd')->andWhere('model')->ne('kanban')->fi()
->andWhere('t1.deleted')->eq(0)
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->projects)->fi()
->fetchPairs();
@@ -1597,7 +1616,7 @@ class docModel extends model
->where('type')->eq('project')
->andWhere('vision')->eq($this->config->vision)
->andWhere('deleted')->eq(0)
->andWhere('model')->ne('kanban')
->beginIF($this->config->vision == 'rnd')->andWhere('model')->ne('kanban')->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->projects)->fi()
->orderBy('order_asc')
->fetchAll('id');
@@ -2032,11 +2051,16 @@ class docModel extends model
$lately = date('Y-m-d', strtotime('-3 day'));
$statisticInfo = $this->dao->select("count(id) as totalDocs, count(IF(editedDate like '{$today}%', 1, null)) as todayEditedDocs,
count(IF(editedDate > '{$lately}', 1, null)) as lastEditedDocs, count(IF(addedDate > '{$lately}', 1, null)) as lastAddedDocs,
count(IF(collector like '%,{$this->app->user->account},%', 1, null)) as myCollection, count(IF(addedBy = '{$this->app->user->account}', 1, null)) as myDocs")->from(TABLE_DOC)
count(IF(addedBy = '{$this->app->user->account}', 1, null)) as myDocs")->from(TABLE_DOC)
->where('deleted')->eq(0)
->andWhere('vision')->eq($this->config->vision)
->andWhere('id')->in($docIdList)
->fetch();
$statisticInfo->myCollection = $this->dao->select('count(*) as count')->from(TABLE_DOCACTION)
->where('doc')->in($docIdList)
->andWhere('action')->eq('collect')
->andWhere('actor')->eq($this->app->user->account)
->fetch('count');
$statisticInfo->pastEditedDocs = $statisticInfo->totalDocs - $statisticInfo->todayEditedDocs;
$statisticInfo->lastEditedProgress = $statisticInfo->totalDocs ? round($statisticInfo->lastEditedDocs / $statisticInfo->totalDocs, 2) * 100 : 0;
@@ -2316,7 +2340,6 @@ class docModel extends model
}
}
if(isset($moduleDocs[0]))
{
if(!isset($treeMenu[0])) $treeMenu[0] = '';
@@ -2742,16 +2765,19 @@ class docModel extends model
if(strpos($query, "`lib` = 'all'") !== false) $query = str_replace("`lib` = 'all'", '1', $query);
$docIdList = $this->getPrivDocs(array_keys($libs));
return $this->dao->select('*')->from(TABLE_DOC)
$docs = $this->dao->select('*')->from(TABLE_DOC)
->where('deleted')->eq(0)
->andWhere($query)
->andWhere('lib')->in(array_keys($libs))
->andWhere('vision')->eq($this->config->vision)
->beginIF($this->config->doc->notArticleType)->andWhere('type')->notIN($this->config->doc->notArticleType)->fi()
->beginIF(!empty($docIdList))->andWhere('id')->in($docIdList)->fi()
->andWhere("(status = 'normal' or (status = 'draft' and addedBy='{$this->app->user->account}'))")
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
$docs = $this->processCollector($docs);
return $docs;
}
/**
@@ -2787,9 +2813,9 @@ class docModel extends model
* @access public
* @return array
*/
public function getModuleTree($rootID, $moduleID = 0, $type = 'doc', $parent = 0, &$modules = array())
public function getModuleTree($rootID, $moduleID = 0, $type = 'doc', $parent = 0, $modules = array())
{
if(empty($modules))
if(is_array($modules) and empty($modules))
{
$modules = $this->dao->select('*')->from(TABLE_MODULE)
->where('root')->eq((int)$rootID)
@@ -2843,10 +2869,11 @@ class docModel extends model
* @param int $objectID
* @param int $executionID
* @param string $browseType bySearch
* @param int $param
* @access public
* @return array
*/
public function getLibTree($libID, $libs, $type, $moduleID, $objectID = 0, $browseType = '')
public function getLibTree($libID, $libs, $type, $moduleID, $objectID = 0, $browseType = '', $param = 0)
{
if($type == 'project')
{
@@ -2857,16 +2884,23 @@ class docModel extends model
$executionLibs[$lib->execution][$lib->id] = $lib;
}
$executionPairs = $this->dao->select('id,name')->from(TABLE_EXECUTION)
->where('id')->in(array_keys($executionLibs))
->fetchPairs();
$executionPairs = $this->dao->select('id,name')->from(TABLE_EXECUTION)->where('id')->in(array_keys($executionLibs))->fetchPairs();
}
$release = null;
if($browseType == 'byrelease' and $param) $release = $this->loadModel('api')->getRelease(0, 'byId', $param);
$libTree = array($type => array());
$apiLibs = array();
$apiLibIDList = array();
foreach($libs as $lib)
{
$releaseModule = array();
if($release and $release->lib == $lib->id)
{
foreach($release->snap['modules'] as $module) $releaseModule[$module['id']] = (object)$module;
}
$item = new stdclass();
$item->id = $lib->id;
$item->type = $lib->type == 'api' ? 'api' : 'lib';
@@ -2874,7 +2908,7 @@ class docModel extends model
$item->objectType = $type;
$item->objectID = $objectID;
$item->active = $lib->id == $libID && $browseType != 'bySearch' ? 1 : 0;
$item->children = $this->getModuleTree($lib->id, $moduleID, $lib->type == 'api' ? 'api' : 'doc');
$item->children = $this->getModuleTree($lib->id, $moduleID, $lib->type == 'api' ? 'api' : 'doc', 0, $releaseModule);
$showDoc = $this->loadModel('setting')->getItem('owner=' . $this->app->user->account . '&module=doc&key=showDoc');
$showDoc = $showDoc === '0' ? 0 : 1;
if($this->app->rawMethod == 'view' and $lib->type != 'api' and $showDoc)
@@ -2975,6 +3009,47 @@ class docModel extends model
}
if($type != 'project') $libTree = array_values($libTree[$type]);
if($type == 'mine')
{
$myLib = new stdclass();
$myLib->id = 0;
$myLib->name = $this->lang->doc->myLib;
$myLib->type = 'min';
$myLib->objectType = 'doc';
$myLib->objectID = 0;
$myLib->active = 0;
$myLib->hasAction = false;
$myLib->children = $libTree;
$myView = new stdclass();
$myView->id = 0;
$myView->name = $this->lang->doc->myView;
$myView->type = 'view';
$myView->objectType = 'doc';
$myView->objectID = 0;
$myView->hasAction = false;
$myView->active = zget($this->app->rawParams, 'type', '') == 'view' ? 1 : 0;
$myCollection = new stdclass();
$myCollection->id = 0;
$myCollection->name = $this->lang->doc->myCollection;
$myCollection->type = 'collect';
$myCollection->objectType = 'doc';
$myCollection->objectID = 0;
$myCollection->hasAction = false;
$myCollection->active = zget($this->app->rawParams, 'type', '') == 'collect' ? 1 : 0;
$myCreation = new stdclass();
$myCreation->id = 0;
$myCreation->name = $this->lang->doc->myCreation;
$myCreation->type = 'createdBy';
$myCreation->objectType = 'doc';
$myCreation->objectID = 0;
$myCreation->hasAction = false;
$myCreation->active = zget($this->app->rawParams, 'type', '') == 'createdBy' ? 1 : 0;
$libTree = array($myLib, $myView, $myCollection, $myCreation);
}
return $libTree;
}
@@ -3072,4 +3147,92 @@ class docModel extends model
if(count($sameNames) > 0 and $libType == 'project') dao::$errors['name'] = $this->lang->doclib->apiNameUnique[$libType] . sprintf($this->lang->error->unique, $this->lang->doclib->name, $lib->name);
if(count($sameNames) > 0 and $libType == 'nolink') dao::$errors['name'] = $this->lang->doclib->apiNameUnique[$libType] . sprintf($this->lang->error->unique, $this->lang->doclib->name, $lib->name);
}
/**
* Create action.
*
* @param int $docID
* @param string $action view|collect
* @param string $account
* @access public
* @return int|bool
*/
public function createAction($docID, $action, $account = '')
{
$docID = (int)$docID;
if(empty($docID)) return false;
if(empty($account))$account = $this->app->user->account;
if($action == 'collect') $this->dao->delete()->from(TABLE_DOCACTION)->where('doc')->eq($docID)->andWhere('action')->eq('collect')->andWhere('actor')->eq($account)->exec();
$data = new stdclass();
$data->doc = $docID;
$data->action = $action;
$data->actor = $account;
$data->date = helper::now();
$this->dao->insert(TABLE_DOCACTION)->data($data)->autoCheck()->exec();
if(!dao::isError())
{
$actionID = $this->dao->lastInsertID();
if($action == 'view') $this->dao->update(TABLE_DOC)->set('views = views + 1')->where('id')->eq($docID)->exec();
if($action == 'collect')
{
$collectCount = $this->dao->select('count(*) as count')->from(TABLE_DOCACTION)->where('doc')->eq($docID)->andWhere('action')->eq('collect')->fetch('count');
$this->dao->update(TABLE_DOC)->set('collector')->eq($collectCount)->where('id')->eq($docID)->exec();
}
return $actionID;
}
}
/**
* Get action by object.
*
* @param int $docID
* @param string $action view|collect
* @param string $account
* @access public
* @return object
*/
public function getActionByObject($docID, $action, $account = '')
{
if(empty($account)) $account = $this->app->user->account;
return $this->dao->select('*')->from(TABLE_DOCACTION)->where('doc')->eq((int)$docID)->andWhere('action')->eq($action)->andWhere('actor')->eq($account)->fetch();
}
/**
* Delete action.
*
* @param int $actionID
* @access public
* @return void
*/
public function deleteAction($actionID)
{
$action = $this->dao->select('*')->from(TABLE_DOCACTION)->where('id')->eq($actionID)->fetch();
$this->dao->delete()->from(TABLE_DOCACTION)->where('id')->eq($actionID)->exec();
if($action->action == 'collect')
{
$collectCount = $this->dao->select('count(*) as count')->from(TABLE_DOCACTION)->where('doc')->eq($action->doc)->andWhere('action')->eq('collect')->fetch('count');
$this->dao->update(TABLE_DOC)->set('collector')->eq($collectCount)->where('id')->eq($action->doc)->exec();
}
}
/**
* Process collector to account.
*
* @param array $docs
* @access public
* @return array
*/
public function processCollector($docs)
{
$actionGroup = $this->dao->select('*')->from(TABLE_DOCACTION)->where('doc')->in(array_keys($docs))->andWhere('action')->eq('collect')->fetchGroup('doc', 'actor');
foreach($docs as $docID => $doc)
{
$doc->collector = '';
if(isset($actionGroup[$docID])) $doc->collector = ',' . implode(',', array_keys($actionGroup[$docID])) . ',';
}
return $docs;
}
}
+15 -67
View File
@@ -1,7 +1,7 @@
<?php js::set('confirmDelete', $lang->doc->confirmDelete);?>
<?php $sessionString = session_name() . '=' . session_id();?>
<div id="mainContent" class="main-row">
<div class="main-col col-8">
<div style="height:100%" id="h-full">
<div class="main-col col-8 flex-content">
<div class="cell" id="content">
<div class="detail no-padding">
<div class="detail-title no-padding doc-title">
@@ -30,8 +30,9 @@
<div class="time"></div>
</div>
<div class="actions">
<span class='text'><?php echo$lang->doc->diff?></span>
<?php
echo html::a("javascript:fullScreen()", '<i class="icon-fullscreen"></i>', '', "title='{$lang->fullscreen}' class='btn btn-link fullscreen-btn'");
echo html::a("javascript:fullScreen()", '<span class="icon-fullscreen"></span>', '', "title='{$lang->fullscreen}' class='btn btn-link fullscreen-btn'");
if(common::hasPriv('doc', 'edit'))
{
$iframe = '';
@@ -41,12 +42,7 @@
$iframe = 'iframe';
$onlybody = 'true';
}
echo html::a(inlink('edit', "docID=$doc->id&comment=false&objectType=$objectType&objectID=$object->id&libID=$libID", '', $onlybody), '<i class="icon-edit"></i>', '', "title='{$lang->doc->edit}' class='btn btn-link $iframe' data-app='{$this->app->tab}'");
}
if(common::hasPriv('doc', 'delete'))
{
$deleteURL = $this->createLink('doc', 'delete', "docID=$doc->id&confirm=yes&from=lib");
echo html::a("javascript:ajaxDeleteDoc(\"$deleteURL\", \"docList\", confirmDelete)", '<i class="icon-trash"></i>', '', "title='{$lang->doc->delete}' class='btn btn-link'");
echo html::a(inlink('edit', "docID=$doc->id&comment=false&objectType=$objectType&objectID=$object->id&libID=$libID", '', $onlybody), '<span class="icon-edit"></span>', '', "title='{$lang->doc->edit}' class='btn btn-link $iframe' data-app='{$this->app->tab}'");
}
?>
<?php if(common::hasPriv('doc', 'collect')):?>
@@ -54,6 +50,14 @@
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$doc->id&objectType=doc");?>" title="<?php echo $lang->doc->collect;?>" class='ajaxCollect btn btn-link'><?php echo html::image("static/svg/{$star}.svg", "class='$star'");?></a>
<?php endif;?>
<?php
if(common::hasPriv('doc', 'delete'))
{
$deleteURL = $this->createLink('doc', 'delete', "docID=$doc->id&confirm=yes&from=lib");
echo html::a("javascript:ajaxDeleteDoc(\"$deleteURL\", \"docList\", confirmDelete)", '<span class="icon-trash"></span>', '', "title='{$lang->doc->delete}' class='btn btn-link'");
}?>
<a id="hisTrigger" href="###" class="btn btn-link" title=<?php echo $lang->history?>><span class="icon icon-clock"></span></a>
<?php if($this->config->edition == 'max' and $this->app->tab == 'project'):?>
<?php
$canImportToPracticeLib = (common::hasPriv('doc', 'importToPracticeLib') and helper::hasFeature('practicelib'));
@@ -62,7 +66,7 @@
if($canImportToPracticeLib or $canImportToComponentLib)
{
echo "<div class='btn-group' id='more' title='{$lang->import}'>";
echo html::a('javascript:;', "<i class='icon icon-diamond'></i>", '', "data-toggle='dropdown' class='btn btn-link'");
echo html::a('javascript:;', "<span class='icon icon-diamond'></span>", '', "data-toggle='dropdown' class='btn btn-link'");
echo "<ul class='dropdown-menu pull-right'>";
if($canImportToPracticeLib) echo '<li>' . html::a('#importToPracticeLib', $lang->doc->importToPracticeLib, '', 'data-toggle="modal"') . '</li>';
if($canImportToComponentLib) echo '<li>' . html::a('#importToComponentLib', $lang->doc->importToComponentLib, '', 'data-toggle="modal"') . '</li>';
@@ -158,7 +162,7 @@
<?php common::printPreAndNext($preAndNext);?>
</div>
</div>
<div class='cell'>
<div id="history" class='panel hidden' style="margin-left: 2px;">
<?php
$canBeChanged = common::canBeChanged('doc', $doc);
if($canBeChanged) $actionFormLink = $this->createLink('action', 'comment', "objectType=doc&objectID=$doc->id");
@@ -166,62 +170,6 @@
<?php include '../../common/view/action.html.php';?>
</div>
</div>
<div class="side-col col-4" id="sidebar">
<div class="sidebar-toggle"><i class="icon icon-angle-right"></i></div>
<?php if(!empty($doc->digest)):?>
<div class="cell" id='sidebarContent'>
<details class="detail" open>
<summary class="detail-title"><?php echo $lang->doc->digest;?></summary>
<div class="detail-content">
<?php echo !empty($doc->digest) ? $doc->digest : "<div class='text-center text-muted'>" . $lang->noData . '</div>';?>
</div>
</details>
</div>
<?php endif;?>
<div class="cell">
<details class="detail" open>
<summary class="detail-title"><?php echo $lang->doc->basicInfo;?></summary>
<div class="detail-content">
<table class="table table-data">
<tbody>
<?php if($doc->productName):?>
<tr>
<th class='c-product'><?php echo $lang->doc->product;?></th>
<td><?php echo $doc->productName;?></td>
</tr>
<?php endif;?>
<?php if($doc->executionName):?>
<tr>
<th class='c-execution'><?php echo $lang->doc->execution;?></th>
<td><?php echo $doc->executionName;?></td>
</tr>
<?php endif;?>
<tr>
<th class='c-lib'><?php echo $lang->doc->lib;?></th>
<td><?php echo $lib->name;?></td>
</tr>
<tr>
<th><?php echo $lang->doc->module;?></th>
<td><?php echo $doc->moduleName ? $doc->moduleName : '/';?></td>
</tr>
<tr>
<th><?php echo $lang->doc->addedDate;?></th>
<td><?php echo $doc->addedDate;?></td>
</tr>
<tr>
<th><?php echo $lang->doc->editedBy;?></th>
<td><?php echo zget($users, $doc->editedBy);?></td>
</tr>
<tr>
<th><?php echo $lang->doc->editedDate;?></th>
<td><?php echo $doc->editedDate;?></td>
</tr>
</tbody>
</table>
</div>
</details>
</div>
</div>
</div>
<?php if($this->config->edition == 'max'):?>
+4 -4
View File
@@ -68,7 +68,7 @@
<?php if($objectType == 'project'):?>
<tr>
<th><?php echo $lang->doc->project;?></th>
<td class='required'><?php echo html::select('project', $objects, isset($execution) ? $execution->project : $objectID, "class='form-control chosen' onchange=loadExecutions(this.value)");?></td>
<td class='required'><?php echo html::select('project', $objects, isset($execution) ? $execution->project : $objectID, "class='form-control picker-select' onchange=loadExecutions(this.value)");?></td>
<?php if($this->app->tab == 'doc'):?>
<th><?php echo $lang->doc->execution?></th>
<td id='executionBox'><?php echo html::select('execution', $executions, isset($execution) ? $objectID : '', "class='form-control chosen' data-placeholder='{$lang->doc->placeholder->execution}' onchange='loadObjectModules(\"execution\", this.value)'")?></td>
@@ -77,17 +77,17 @@
<?php elseif($objectType == 'execution'):?>
<tr>
<th><?php echo $lang->doc->execution;?></th>
<td class='required'><?php echo html::select('execution', $objects, $objectID, "class='form-control chosen' onchange='loadObjectModules(\"execution\", this.value)'");?></td>
<td class='required'><?php echo html::select('execution', $objects, $objectID, "class='form-control picker-select' onchange='loadObjectModules(\"execution\", this.value)'");?></td>
</tr>
<?php elseif($objectType == 'product'):?>
<tr>
<th><?php echo $lang->doc->product;?></th>
<td class='required'><?php echo html::select('product', $objects, $objectID, "class='form-control chosen' onchange='loadObjectModules(\"product\", this.value)'");?></td>
<td class='required'><?php echo html::select('product', $objects, $objectID, "class='form-control picker-select' onchange='loadObjectModules(\"product\", this.value)'");?></td>
</tr>
<?php endif;?>
<tr>
<th class='w-100px'><?php echo $lang->doc->libAndModule?></th>
<td colspan='3' class='required'><span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control chosen'");?></span></td>
<td colspan='3' class='required'><span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control picker-select'");?></span></td>
</tr>
<tr>
<th><?php echo $lang->doc->keywords;?></th>
+1
View File
@@ -16,6 +16,7 @@ body {margin-bottom: 25px;}
#docListForm th.c-user {width: 80px;}
#docListForm th.c-actions {width: 84px; padding-left: 15px;}
#docListForm .checkbox-primary {line-height: 16px;}
#docListForm table .checkbox-primary {top: -2px;}
#docListForm .checkbox-primary > label {height: 16px; line-height: 16px; padding-left: 16px;}
#docListForm .checkbox-primary > label:before {left: -1px; font-size: 10px;}
#docListForm .checkbox-primary > label:after {width: 12px; height: 12px;}
+2 -2
View File
@@ -70,12 +70,12 @@
<?php if(strpos('product|project|execution', $type) !== false):?>
<tr>
<th><?php echo $lang->doc->project;?></th>
<td class='required'><?php echo html::select($type, $objects, $objectID, "class='form-control chosen' onchange='loadObjectModules(\"{$type}\", this.value)'");?></td>
<td class='required'><?php echo html::select($type, $objects, $objectID, "class='form-control picker-select' onchange='loadObjectModules(\"{$type}\", this.value)'");?></td>
</tr>
<?php endif;?>
<tr>
<th class='w-100px'><?php echo $lang->doc->libAndModule?></th>
<td colspan='3' class='required'><span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $doc->lib . '_' . $doc->module, "class='form-control chosen'");?></span></td>
<td colspan='3' class='required'><span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $doc->lib . '_' . $doc->module, "class='form-control picker-select'");?></span></td>
</tr>
<tr>
<th><?php echo $lang->doc->keywords;?></th>
+74 -41
View File
@@ -23,13 +23,13 @@
.input-tree {width: 120px;}
.tree-icon {position: absolute; right: 0;}
.tree li.has-input {overflow: hidden;}
.tree li.has-input > input {margin-left: 15px;}
.img-lib {flex: 0 0 14px; height: 14px; margin-right: 5px;}
.tree-icon {position: absolute; right: 0;}
.tree li > a {max-width: 100%; padding: 2px;}
.file-tree a.show-icon > div,
.file-tree a.hover > div {padding-right: 15px;}
.tree li.has-input {overflow: hidden;}
.tree-text {overflow: hidden;}
.tree-text {overflow: hidden; min-width: 50px;}
i.btn-info, i.btn-info:hover {border: none; background: #fff; box-shadow: unset;}
.tree-version-trigger {padding: 0 10px; width: 54px; border-radius: 5px; background: #F9F9F9; display: flex; align-items: center;}
.tree-version-trigger > .text {overflow: hidden; flex: 0 0 30px;}
@@ -39,7 +39,7 @@ i.btn-info, i.btn-info:hover {border: none; background: #fff; box-shadow: unset;
/* css for sidebar */
.sidebar-toggle {flex: 0 0 16px;}
.sidebar-toggle > .icon {width: 12px; height: 30px; margin-top: -10px; line-height: 30px; color: #fff; text-align: center; background: #7dcdfe; border-radius: 6px; cursor: pointer; padding-left: 0; padding-top: 0;}
.bottom-btn-tree {position: fixed; bottom: 66px; left: 48px;}
.bottom-btn-tree {position: absolute; bottom: 15px; left: 25px;}
.spliter {flex: 0 0 12px;}
.spliter-btn {height: 28px; width: 10px; background: #fff; position: absolute; top: 30%; left: -1px; border: 1px solid #D9D9D9; border-radius: 2px;}
@@ -92,39 +92,54 @@ js::set('canViewFiles', common::hasPriv('doc', 'showfiles'));
<?php endif;?>
<!-- Code for dropdown menu. -->
<?php $canAddCatalog = common::hasPriv('doc', 'addCatalog');?>
<?php $canEditCatalog = common::hasPriv('doc', 'editCatalog');?>
<?php $canDeleteCatalog = common::hasPriv('doc', 'deleteCatalog');?>
<?php $hasModulePriv = $canAddCatalog || $canEditCatalog || $canDeleteCatalog;?>
<?php js::set('canAddCatalog', $canAddCatalog);?>
<?php js::set('canEditCatalog', $canEditCatalog);?>
<?php js::set('canDeleteCatalog', $canDeleteCatalog);?>
<?php js::set('hasModulePriv', $hasModulePriv);?>
<?php js::set('hasLibPriv', $canAddCatalog || common::hasPriv($app->rawModule, 'editLib') || common::hasPriv($app->rawModule, 'deleteLib'));?>
<?php
$canAddCatalog['doc'] = common::hasPriv('doc', 'addCatalog');
$canAddCatalog['api'] = common::hasPriv('api', 'addCatalog');
$canEditCatalog['doc'] = common::hasPriv('doc', 'editCatalog');
$canEditCatalog['api'] = common::hasPriv('api', 'editCatalog');
$canDeleteCatalog['doc'] = common::hasPriv('doc', 'deleteCatalog');
$canDeleteCatalog['api'] = common::hasPriv('api', 'deleteCatalog');
$hasModulePriv['doc'] = $canAddCatalog['doc'] || $canEditCatalog['doc'] || $canDeleteCatalog['doc'];
$hasModulePriv['api'] = $canAddCatalog['api'] || $canEditCatalog['api'] || $canDeleteCatalog['api'];
$hasLibPriv['doc'] = $canAddCatalog['doc'] || common::hasPriv('doc', 'editLib') || common::hasPriv('doc', 'deleteLib');
$hasLibPriv['api'] = $canAddCatalog['api'] || common::hasPriv('api', 'editLib') || common::hasPriv('api', 'deleteLib');
js::set('canAddCatalog', $canAddCatalog);
js::set('canEditCatalog', $canEditCatalog);
js::set('canDeleteCatalog', $canDeleteCatalog);
js::set('hasModulePriv', $hasModulePriv);
js::set('hasLibPriv', $hasLibPriv);
?>
<div class='hidden' id='dropDownData'>
<ul class='libDorpdown'>
<?php if($canAddCatalog):?>
<?php foreach(array('doc', 'api') as $module):?>
<ul class='<?php echo $module;?>LibDorpdown'>
<?php if($canAddCatalog[$module]):?>
<li data-method="addCataLib" data-has-children='%hasChildren%' data-libid='%libID%' data-moduleid="%moduleID%" data-type="add"><a><i class="icon icon-icon-add-directory"></i><?php echo $lang->doc->libDropdown['addModule'];?></a></li>
<?php endif;?>
<?php if(common::hasPriv($app->rawModule, 'editLib')):?>
<?php if(common::hasPriv($module, 'editLib')):?>
<li data-method="editLib"><a href='<?php echo inlink('editLib', 'libID=%libID%');?>' data-toggle='modal' data-type='iframe'><i class="icon icon-edit"></i><?php echo $lang->doc->libDropdown['editLib'];?></a></li>
<?php endif;?>
<?php if(common::hasPriv($app->rawModule, 'deleteLib')):?>
<?php if(common::hasPriv($module, 'deleteLib')):?>
<li data-method="deleteLib"><a href='<?php echo inlink('deleteLib', 'libID=%libID%');?>' target='hiddenwin'><i class="icon icon-trash"></i><?php echo $lang->doc->libDropdown['deleteLib'];?></a></li>
<?php endif;?>
</ul>
<ul class='moduleDorpdown'>
<?php if($canAddCatalog):?>
<ul class='<?php echo $module;?>ModuleDorpdown'>
<?php if($canAddCatalog[$module]):?>
<li data-method="addCataBro" data-type="add" data-id="%moduleID%"><a><i class="icon icon-icon-add-directory"></i><?php echo $lang->doc->libDropdown['addSameModule'];?></a></li>
<li data-method="addCataChild" data-type="add" data-id="%moduleID%" data-has-children='%hasChildren%'><a><i class="icon icon-icon-add-directory"></i><?php echo $lang->doc->libDropdown['addSubModule'];?></a></li>
<?php endif;?>
<?php if($canEditCatalog):?>
<li data-method="editCata" class='edit-module'><a data-href='<?php echo helper::createLink('doc', 'editCatalog', "moduleID=%moduleID%&type=$app->rawModule");?>'><i class="icon icon-edit"></i><?php echo $lang->doc->libDropdown['editModule'];?></a></li>
<?php if($canEditCatalog[$module]):?>
<li data-method="editCata" class='edit-module'><a data-href='<?php echo helper::createLink($module, 'editCatalog', "moduleID=%moduleID%&type=$app->rawModule");?>'><i class="icon icon-edit"></i><?php echo $lang->doc->libDropdown['editModule'];?></a></li>
<?php endif;?>
<?php if($canDeleteCatalog):?>
<li data-method="deleteCata"><a href='<?php echo helper::createLink('doc', 'deleteCatalog', 'rootID=%libID%&moduleID=%moduleID%');?>' target='hiddenwin'><i class="icon icon-trash"></i><?php echo $lang->doc->libDropdown['delModule'];?></a></li>
<?php if($canDeleteCatalog[$module]):?>
<li data-method="deleteCata"><a href='<?php echo helper::createLink($module, 'deleteCatalog', 'rootID=%libID%&moduleID=%moduleID%');?>' target='hiddenwin'><i class="icon icon-trash"></i><?php echo $lang->doc->libDropdown['delModule'];?></a></li>
<?php endif;?>
</ul>
<?php endforeach;?>
</div>
<div class='hidden' data-id="ulTreeModal">
<ul data-id="liTreeModal" class="menu-active-primary menu-hover-primary has-input">
@@ -160,9 +175,11 @@ $(function()
*/
function renderDropdown(option)
{
var libClass = '.libDorpdown';
if(option.type != 'dropDownLibrary') libClass = '.moduleDorpdown';
var moduleType = option.moduleType == 'lib' ? 'doc' : option.moduleType;
var libClass = '.' + moduleType + 'LibDorpdown';
if(option.type != 'dropDownLibrary') libClass = '.' + moduleType + 'ModuleDorpdown';
if($(libClass).find('li').length == 0) return '';
var dropdown = '<ul class="dropdown-menu dropdown-in-tree" id="' + option.type + '" style="display: unset; left:' + option.left + 'px; top:' + option.top + 'px;">';
dropdown += $(libClass).html().replace(/%libID%/g, option.libID).replace(/%moduleID%/g, option.moduleID).replace(/%hasChildren%/g, option.hasChildren);
dropdown += '</ul>';
@@ -187,15 +204,15 @@ $(function()
}
else
{
var libId;
var lib = 0;
var $lis = '<li><a href="###" data-id=0>' + versionLang + '</a></li>';
for(i = 0; i< versions.length; i++)
{
var version = versions[i];
$lis += '<li><a href="###" data-id="' + version.id + '">' + version.version+ '</a></li>';
libId = version.lib;
lib = version.lib;
}
var $dropdown = '<ul id="versionSwitcher" data-lib-id = "' + libId + '" class="dropdown-menu dropdown-in-tree" style="display: unset; left:' + option.left + 'px; top:' + option.top + 'px;">';
var $dropdown = '<ul id="versionSwitcher" data-lib = "' + lib + '" class="dropdown-menu dropdown-in-tree" style="display: unset; left:' + option.left + 'px; top:' + option.top + 'px;">';
$dropdown += $lis;
$dropdown += '</ul>';
}
@@ -255,7 +272,10 @@ $(function()
}
$item += '<div class="tree-version-trigger" data-id="' + item.id + '"><div class="text">' + (versionName || versionLang) + '</div><div class="caret"></div></div>';
}
if((libClass != 'lib' && hasModulePriv) || (libClass == 'lib' && hasLibPriv)) $item += '<i class="icon icon-drop icon-ellipsis-v hidden tree-icon" data-isCatalogue="' + (libClass ? false : true) + '"></i>';
var moduleType = config.currentModule == 'api' ? 'api' : 'doc';
if(objectType) objectType.indexOf('api') === 0 ? 'api' : 'doc';
if((libClass != 'lib' && hasModulePriv[moduleType]) || (libClass == 'lib' && hasLibPriv[moduleType])) $item += '<i class="icon icon-drop icon-ellipsis-v hidden tree-icon" data-isCatalogue="' + (libClass ? false : true) + '"></i>';
$item += '</div>';
$item += '</a>';
if(item.versions) versionsData[item.id] = item.versions;
@@ -268,8 +288,8 @@ $(function()
if(isFirstLoad) ele.data('zui.tree').collapse();
var $leaf = ele.find('li.active');
if($leaf.length) $leaf[$leaf.length - 1].scrollIntoView(false);
var $leaf = ele.find('li.active > a');
if($leaf.length && $('#fileTree').height() >= $('#sideBar').height()) $('#sideBar')[0].scrollTop = $($leaf[$leaf.length - 1]).offset().top;
ele.on('click', '.icon-drop', function(e)
{
@@ -329,8 +349,9 @@ $(function()
if($(this).data('type') == 'annex') return;
if(!$(this).data('action')) return;
var libClass = '.libDorpdown';
if(!$(this).hasClass('lib')) libClass = '.moduleDorpdown';
var moduleType = $(this).data('type') == 'api' ? 'api' : 'doc';
var libClass = '.' + moduleType + 'LibDorpdown';
if(!$(this).hasClass('lib')) libClass = '.' + moduleType + 'ModuleDorpdown';
$(this).find('.icon').removeClass('hidden');
$(this).addClass('show-icon');
@@ -360,7 +381,7 @@ $(function()
libID = $(this).closest('.lib').data('id');
}
return lcatePage(libID, moduleID, $(this).data('type'));
return locatePage(libID, moduleID, $(this).data('type'));
}).on('click', '.tree-version-trigger', function(e)
{
$('.dropdown-in-tree').remove();
@@ -408,8 +429,10 @@ $(function()
* @access public
* @return void
*/
function lcatePage(libID, moduleID, type)
function locatePage(libID, moduleID, type)
{
if(!libID) libID = 0;
if(!moduleID) moduleID = 0;
linkParams = linkParams.replace('%s', 'libID=' + libID + '&moduleID=' + moduleID);
var methodName = '';
if(config.currentModule == 'api')
@@ -422,10 +445,13 @@ $(function()
methodName = 'showFiles';
linkParams = 'type=' + objectType + '&objectID=' + objectID;
}
else if(objectType == 'mine')
else if(objectType == 'mine' || objectType == 'view' || objectType == 'collect' || objectType == 'createdBy')
{
var mySpaceType = 'mine';
if(type == 'view' || type == 'collect' || type == 'createdBy') mySpaceType = type;
methodName = 'mySpace';
linkParams = 'type=mine&libID=' + libID;
linkParams = 'type='+ mySpaceType + '&libID=' + libID + '&moduleID=' + moduleID;
}
else if(['text', 'word', 'ppt', 'excel'].indexOf(type) !== -1)
{
@@ -509,7 +535,7 @@ $(function()
else
{
var $input = $('[data-id=ulTreeModal]').html();
var $rootDom = $('[data-id=' + item.libid + ']a');
var $rootDom = $('[data-id=' + item.libid + ']a.lib');
var $li = $rootDom.parent();
moduleData.isUpdate = true;
$rootDom.after($input);
@@ -548,9 +574,16 @@ $(function()
}
}).on('click', '#versionSwitcher a', function()
{
var $item = $(this);
linkParams = linkParams.replace('%s', 'libID=' + $item.closest('ul').data('libId') + '&moduleID=0&apiID=0&version=0&release=' + $item.data('id'));
location.href = createLink(config.currentModule, 'index', linkParams);
var libID = $(this).closest('#versionSwitcher').data('lib');
var moduleID = $(this).data('id');
var params = 'libID=' + libID + '&moduleID=0&apiID=0&version=0&release=' + moduleID;
var methodName = config.currentMethod;
if(config.currentModule == 'doc')
{
params = linkParams.replace('%s', 'libID=' + libID + '&moduleID=' + moduleID).replace('browseType=&', 'browseType=byrelease&').replace('param=0', 'param=' + moduleID);
methodName = objectType + 'Space';
}
location.href = createLink(config.currentModule, methodName, params);
}).on('blur', '.file-tree input.input-tree', function()
{
var $input = $(this);
@@ -583,7 +616,7 @@ $(function()
}
var module = result.module;
return lcatePage(module.root, module.id, 'doc');
return locatePage(module.root, module.id, 'doc');
});
}).on('keydown', '.file-tree input.input-tree', function(e)
{
+14 -4
View File
@@ -15,10 +15,10 @@ body {margin-bottom: 25px;}
#docListForm th.c-id {width: 72px;}
#docListForm th.c-user {width: 80px;}
#docListForm th.c-actions {width: 84px; padding-left: 15px;}
#docListForm .checkbox-primary {line-height: 16px;}
#docListForm .checkbox-primary > label {height: 16px; line-height: 16px; padding-left: 16px;}
#docListForm .checkbox-primary > label:before {left: -1px; font-size: 10px;}
#docListForm .checkbox-primary > label:after {width: 12px; height: 12px;}
#docListForm .table .c-name > .doc-title {display: inline-block; max-width: 90%; overflow: hidden; background: transparent; padding-right:0px;}
#docListForm .table .c-name > .draft {background-color:rgba(129, 102, 238, 0.12); color:#8166EE;}
#docListForm .table .c-name > .ajaxCollect {float: right; position: relative; right: 10px; top: 0px;}
#docListForm table.table > thead > tr {height: 32px;}
</style>
<?php if(common::checkNotCN()):?>
<style>
@@ -55,9 +55,14 @@ body {margin-bottom: 25px;}
<?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?>
</th>
<th class="c-name"><?php common::printOrderLink('title', $orderBy, $vars, $lang->doc->title);?></th>
<th class="c-module"><?php common::printOrderLink('module', $orderBy, $vars, $lang->doc->position);?></th>
<?php if($type != 'mine'):?>
<th class="c-user"><?php common::printOrderLink('addedBy', $orderBy, $vars, $lang->doc->addedByAB);?></th>
<?php endif;?>
<th class="c-date"><?php common::printOrderLink('addedDate', $orderBy, $vars, $lang->doc->addedDate);?></th>
<?php if($type != 'mine'):?>
<th class="c-user"><?php common::printOrderLink('editedBy', $orderBy, $vars, $lang->doc->editedBy);?></th>
<?php endif;?>
<th class="c-date"><?php common::printOrderLink('editedDate', $orderBy, $vars, $lang->doc->editedDate);?></th>
<th class="c-actions"><?php echo $lang->actions;?></th>
</tr>
@@ -96,9 +101,14 @@ body {margin-bottom: 25px;}
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$doc->id&objectType=doc");?>" title="<?php echo $collectTitle;?>" class='btn btn-link ajaxCollect'><?php echo html::image("static/svg/{$star}.svg", "class='$star'");?></a>
<?php endif;?>
</td>
<td class="c-module"><?php echo $doc->moduleName;?></td>
<?php if($type != 'mine'):?>
<td class="c-user"><?php echo zget($users, $doc->addedBy);?></td>
<?php endif;?>
<td class="c-datetime"><?php echo formatTime($doc->addedDate, 'Y-m-d');?></td>
<?php if($type != 'mine'):?>
<td class="c-user"><?php echo zget($users, $doc->editedBy);?></td>
<?php endif;?>
<td class="c-datetime"><?php echo formatTime($doc->editedDate, 'Y-m-d');?></td>
<td class="c-actions">
<?php if(common::canBeChanged('doc', $doc)):?>
+1 -1
View File
@@ -23,7 +23,7 @@
<?php foreach($lang->doc->featureBar['tableContents'] as $barType => $barName):?>
<?php $active = $barType == $browseType ? 'btn-active-text' : '';?>
<?php $linkParams = $app->rawMethod == 'tablecontents' ? "type=$type&objectID=$objectID&libID=$libID&moduleID=$moduleID&browseType=$barType": "objectID=$objectID&libID=$libID&moduleID=$moduleID&browseType=$barType";?>
<?php echo html::a($this->createLink('doc', $app->rawMethod, $linkParams), $barName, '', "class='btn btn-link $active' id='{$barType}Tab'");?>
<?php echo html::a($this->createLink('doc', $app->rawMethod, $linkParams), $barName . ($active ? "<span class='label label-light label-badge'>{$pager->recTotal}</span>" : ''), '', "class='btn btn-link $active' id='{$barType}Tab'");?>
<?php endforeach;?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->doc->searchDoc;?></a>
<?php endif;?>
+25 -29
View File
@@ -19,10 +19,10 @@
</div>
<form method='post' class='form-ajax'>
<table class='table table-form'>
<tr><th class='w-100px'></th><td></td><th class='w-100px'></th><td></td></tr>
<tr><th class='w-120px'></th><td></td><th class='w-100px'></th><td></td></tr>
<tr>
<th><?php echo $lang->doc->space?></th>
<td colspan='3'><?php echo html::radio('space', $spaceList, '', "onchange=changeSpace()");?></td>
<td colspan='3'><?php echo html::radio('space', $spaceList, key($spaceList), "onchange=changeSpace()");?></td>
</tr>
<tr id='docType'>
<th><?php echo $lang->doc->type;?></th>
@@ -54,6 +54,8 @@
</div>
<?php js::set('holders', $lang->doc->placeholder);?>
<script>
$(function(){changeSpace()});
/**
* Change space.
*
@@ -62,20 +64,26 @@
*/
function changeSpace()
{
var space = $('[name=space]:checked').val();
var docType = $('[name=type]:checked').val();
console.log();
var space = $('[name=space]:checked').val();
$('.apiTypeTR').toggleClass('hidden', space != 'api');
$('.projectTR').toggleClass('hidden', space != 'project');
$('.productTR').toggleClass('hidden', space != 'product');
$('#typeapi').removeAttr('disabled');
$('#typedoc').removeAttr('disabled');
if(space == 'mine' || space == 'custom') $('#typeapi').attr('disabled', 'disabled');
if(space == 'api') $('#typedoc').attr('disabled', 'disabled');
$('#typedoc').toggleClass('hidden', space == 'api');
$('#typeapi').toggleClass('hidden', space == 'mine' || space == 'custom');
$('#typedoc').closest('.radio-inline').toggleClass('hidden', space == 'api');
$('#typeapi').closest('.radio-inline').toggleClass('hidden', space == 'mine' || space == 'custom');
var docType = $('[name=type]:not(.hidden):checked').val();
if(space == 'project' && docType) $('#project').change();
if(space == 'product' && docType) $('#product').change();
if((space == 'mine' || space == 'custom') && docType) loadDocLibs(space, docType);
if(space == 'api' && docType) changeApiType();
if(!docType)
{
$('[name=type]:not(.hidden):first').prop('checked', true);
changeDocType();
}
}
/**
@@ -92,6 +100,11 @@ function changeApiType()
if(apiType == 'project') $('#project').change();
if(apiType == 'product') $('#product').change();
if(apiType == 'nolink') loadDocLibs('api', 'api');
if(apiType == '')
{
$('#moduleBox').html("<select id='module' name='module' class='form-control'><option value=''></option></select>");
$('#moduleBox #module').picker();
}
}
/**
@@ -102,40 +115,23 @@ function changeApiType()
*/
function changeDocType()
{
var docType = $('[name=type]:checked').val();
$('[name=space]').removeAttr('disabled');
var docType = $('[name=type]:not(.hidden):checked').val();
$('.executionTH').removeClass('hidden');
$('#executionBox').removeClass('hidden');
if(docType == 'api')
{
$('#spacemine').attr('disabled', 'disabled');
$('#spacecustom').attr('disabled', 'disabled');
$('.executionTH').addClass('hidden');
$('#executionBox').addClass('hidden');
$('#project').attr('onchange', "loadObjectModules('project', this.value, '" + docType + "')");
}
if(docType == 'doc')
else if(docType == 'doc')
{
$('#spaceapi').attr('disabled', 'disabled');
$('#project').attr('onchange', "loadExecutions(this.value)");
}
$('#product').attr('onchange', "loadObjectModules('product', this.value, '" + docType + "')");
var space = $('[name=space]:checked').val();
if(space)
{
if(docType == 'doc' && space == 'api')
{
$('[name=space]:checked').prop('checked', false);
$('[name=space]:not(:disabled):first').prop('checked', true);
}
if(docType == 'api' && (space == 'mine' || space == 'custom'))
{
$('[name=space]:checked').prop('checked', false);
$('[name=space]:not(:disabled):first').prop('checked', true);
}
changeSpace();
}
if(space) changeSpace();
$('#submit').removeAttr('disabled');
}
+2 -2
View File
@@ -12,7 +12,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('treeData', $libTree);?>
<?php js::set('linkParams', "objectID=$objectID&%s&browseType=&orderBy=$orderBy");?>
<?php js::set('linkParams', "objectID=$objectID&%s&browseType=&orderBy=$orderBy&param=0");?>
<?php js::set('docLang', $lang->doc);?>
<?php js::set('libType', $libType);?>
<div id="mainMenu" class="clearfix">
@@ -23,7 +23,7 @@
<?php foreach($lang->doc->featureBar['tableContents'] as $barType => $barName):?>
<?php $active = $barType == $browseType ? 'btn-active-text' : '';?>
<?php $linkParams = $app->rawMethod == 'tablecontents' ? "type=$type&objectID=$objectID&libID=$libID&moduleID=$moduleID&browseType=$barType": "objectID=$objectID&libID=$libID&moduleID=$moduleID&browseType=$barType";?>
<?php echo html::a($this->createLink('doc', $app->rawMethod, $linkParams), $barName, '', "class='btn btn-link $active' id='{$barType}Tab'");?>
<?php echo html::a($this->createLink('doc', $app->rawMethod, $linkParams), $barName . ($active ? "<span class='label label-light label-badge'>{$pager->recTotal}</span>" : ''), '', "class='btn btn-link $active' id='{$barType}Tab'");?>
<?php endforeach;?>
<?php endif;?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->doc->searchDoc;?></a>
+2 -2
View File
@@ -21,11 +21,11 @@
<?php endif;?>
<div id='mainContent'class="fade flex">
<?php if($libID):?>
<div id='sideBar' class="panel side side-col col overflow-auto">
<div id='sideBar' class="panel side side-col col overflow-auto h-full-adjust">
<?php include 'lefttree.html.php';?>
</div>
<div class="sidebar-toggle flex-center"><i class="icon icon-angle-left"></i></div>
<div class="main-col" data-min-width="400">
<div class="main-col h-full-adjust" data-min-width="400">
<?php if($docID):?>
<?php include './content.html.php';?>
<?php else:?>
+4
View File
@@ -2204,6 +2204,10 @@ class executionModel extends model
{
$link = helper::createLink('doc', $method, "type=execution&objectID=%s&from=execution");
}
elseif($module == 'api')
{
$link = helper::createLink('doc', 'tableContents', "type=execution&objectID=%s&from=execution");
}
elseif(in_array($module, array('issue', 'risk', 'opportunity', 'pssp', 'auditplan', 'nc', 'meeting')))
{
$link = helper::createLink($module, 'browse', "executionID=%s&from=execution");
+9 -3
View File
@@ -1898,6 +1898,9 @@ $lang->resource->api->deleteStruct = 'deleteStruct';
$lang->resource->api->create = 'create';
$lang->resource->api->edit = 'edit';
$lang->resource->api->delete = 'delete';
$lang->resource->api->addCatalog = 'addCatalog';
$lang->resource->api->editCatalog = 'editCatalog';
$lang->resource->api->deleteCatalog = 'deleteCatalog';
$lang->resource->api->getModel = 'getModel';
$lang->resource->api->debug = 'debug';
@@ -1917,9 +1920,12 @@ $lang->api->methodOrder[50] = 'deleteStruct';
$lang->api->methodOrder[55] = 'create';
$lang->api->methodOrder[60] = 'edit';
$lang->api->methodOrder[65] = 'delete';
$lang->api->methodOrder[70] = 'getModel';
$lang->api->methodOrder[75] = 'debug';
$lang->api->methodOrder[80] = 'sql';
$lang->api->methodOrder[70] = 'addCatalog';
$lang->api->methodOrder[75] = 'editCatalog';
$lang->api->methodOrder[80] = 'deleteCatalog';
$lang->api->methodOrder[85] = 'getModel';
$lang->api->methodOrder[90] = 'debug';
$lang->api->methodOrder[95] = 'sql';
$lang->resource->file = new stdclass();
$lang->resource->file->download = 'download';
+1 -1
View File
@@ -2446,7 +2446,7 @@ class productModel extends model
{
$link = helper::createLink($module, $method, "productID=%s");
}
else if($module == 'doc')
else if($module == 'doc' or $module == 'api')
{
$link = helper::createLink('doc', 'productSpace', "objectID=%s");
}
+1 -1
View File
@@ -670,7 +670,7 @@ class projectModel extends model
{
$link = helper::createLink($module, 'browse', "repoID=&branchID=&objectID=%s") . '#app=project';
}
elseif($module == 'doc')
elseif($module == 'doc' or $module == 'api')
{
$link = helper::createLink($module, 'projectSpace', "objectID=%s") . '#app=project';
}
+2 -1
View File
@@ -325,7 +325,8 @@ class releaseModel extends model
$oldRelease = $this->getById($releaseID);
$release = fixer::input('post')->stripTags($this->config->release->editor->edit['id'], $this->config->allowedTags)
->setDefault('build', '')
->setDefault('build', '')
->setIF($this->post->build == false, 'build', 0)
->setDefault('mailto', '')
->setDefault('deleteFiles', array())
->join('build', ',')
+56 -6
View File
@@ -132,10 +132,11 @@ class treeModel extends model
* @param int|array $branch
* @param string $param
* @param string $grade
* @param string $divide /|>
* @access public
* @return void
*/
public function getOptionMenu($rootID, $type = 'story', $startModule = 0, $branch = 0, $param = 'nodeleted', $grade = 'all')
public function getOptionMenu($rootID, $type = 'story', $startModule = 0, $branch = 0, $param = 'nodeleted', $grade = 'all', $divide = '/')
{
if(empty($branch) and !is_array($branch)) $branch = 0;
if(defined('TUTORIAL'))
@@ -197,7 +198,7 @@ class treeModel extends model
foreach($modules as $module)
{
$branchName = (isset($product) and $product->type != 'normal' and $module->branch === BRANCH_MAIN) ? $this->lang->branch->main : $branch;
$this->buildTreeArray($treeMenu, $modules, $module, (empty($branchName)) ? '/' : "/$branchName/");
$this->buildTreeArray($treeMenu, $modules, $module, (empty($branchName)) ? '/' : "/$branchName/", $divide);
}
}
@@ -373,16 +374,16 @@ class treeModel extends model
* @access public
* @return void
*/
public function buildTreeArray(& $treeMenu, $modules, $module, $moduleName = '/')
public function buildTreeArray(& $treeMenu, $modules, $module, $moduleName = '/', $divide = '/')
{
$parentModules = explode(',', $module->path);
foreach($parentModules as $parentModuleID)
{
if(empty($parentModuleID)) continue;
if(empty($modules[$parentModuleID])) continue;
$moduleName .= $modules[$parentModuleID]->name . '/';
$moduleName .= $modules[$parentModuleID]->name . $divide;
}
$moduleName = rtrim($moduleName, '/');
$moduleName = rtrim($moduleName, $divide);
$moduleName .= "|$module->id\n";
if(isset($treeMenu[$module->id]) and !empty($treeMenu[$module->id]))
@@ -1834,8 +1835,18 @@ class treeModel extends model
$changes = common::createChanges($self, $module);
if(!isset($_POST['branch'])) $module->branch = $self->branch;
if($self)
{
$self->parent = $module->parent;
if($self->root) $module->root = $self->root;
}
$repeatName = $this->checkUnique($self, array("id{$self->id}" => $module->name), array("id{$self->id}" => $module->branch));
if($repeatName) helper::end(js::alert(sprintf($this->lang->tree->repeatName, $repeatName)));
if($repeatName)
{
$tips = in_array($self->type, array('doc', 'api')) ? $this->lang->tree->repeatDirName : $this->lang->tree->repeatName;
helper::end(js::alert(sprintf($tips, $repeatName)));
}
if((empty($module->root) or empty($module->name)) and in_array($self->type, array('doc', 'api')))
{
@@ -2391,4 +2402,43 @@ class treeModel extends model
return $this->getByID($moduleID);
}
/**
* Get group pairs.
*
* @param int $dimensionID
* @param int $parentGroup
* @param int $grade
* @param string $type
* @access public
* @return array
*/
public function getGroupPairs($dimensionID = 0, $parentGroup = 0, $grade = 2, $type = 'chart')
{
$groups = $this->dao->select('id,name,grade,parent')->from(TABLE_MODULE)
->where('root')->eq($dimensionID)
->beginIF(!empty($parentGroup))->andWhere('root')->eq($dimensionID)->fi()
->andWhere('type')->eq($type)
->andWhere('deleted')->eq(0)
->orderBy('order')
->fetchGroup('grade', 'id');
$groupPairs = array();
if(!empty($groups[1]))
{
foreach($groups[1] as $parentGroup)
{
if($grade == 1) $groupPairs[$parentGroup->id] = $parentGroup->name;
if($grade == 2 and !empty($groups[2]))
{
foreach($groups[2] as $childGroup)
{
if($parentGroup->id == $childGroup->parent) $groupPairs[$childGroup->id] = '/' . $parentGroup->name . '/' . $childGroup->name;
}
}
}
}
return $groupPairs;
}
}
+23
View File
@@ -8977,4 +8977,27 @@ class upgradeModel extends model
return $fieldSettings;
}
/**
* Convert doc collect.
*
* @access public
* @return bool
*/
public function convertDocCollect()
{
$this->loadModel('doc');
$stmt = $this->dao->select('id,collector')->from(TABLE_DOC)->where('collector')->ne('')->query();
while($doc = $stmt->fetch())
{
foreach(explode(',', $doc->collector) as $collector)
{
$collector = trim($collector);
if(empty($collector)) continue;
$this->doc->createAction($doc->id, 'collect', $collector);
}
}
return true;
}
}
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
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
import{_ as a}from"./403-24e394e4.js";import{j as c,d as r,r as n,o as u,m as d,e as p,w as i,D as m,E as l,z as t,p as E,H as v,P as x}from"./index.js";const o=e=>(m("data-v-3497d613"),e=e(),l(),e),B={class:"go-error"},h=o(()=>t("div",{class:"text-center"},[t("img",{src:a,alt:""})],-1)),f=o(()=>t("div",{class:"text-center"},[t("h1",{class:"text-base text-gray-500"},"\u62B1\u6B49\uFF0C\u4F60\u65E0\u6743\u8BBF\u95EE\u8BE5\u9875\u9762")],-1)),g=E("\u56DE\u5230\u9996\u9875"),y=r({__name:"403",setup(e){function s(){v(x.BASE_HOME_NAME)}return(C,N)=>{const _=n("n-button");return u(),d("div",B,[h,f,p(_,{type:"primary",onClick:s},{default:i(()=>[g]),_:1})])}}});var I=c(y,[["__scopeId","data-v-3497d613"]]);export{I as default};
-1
View File
@@ -1 +0,0 @@
import{_ as a}from"./404-c00f16ad.js";import{j as c,d as r,r as n,o as u,m as p,e as d,w as i,D as m,E as l,z as t,p as v,H as x,P as B}from"./index.js";const o=e=>(m("data-v-2155c9c8"),e=e(),l(),e),E={class:"go-error"},h=o(()=>t("div",{class:"text-center"},[t("img",{src:a,alt:""})],-1)),f=o(()=>t("div",{class:"text-center"},[t("h1",{class:"text-base text-gray-500"},"\u62B1\u6B49\uFF0C\u4F60\u8BBF\u95EE\u7684\u9875\u9762\u4E0D\u5B58\u5728")],-1)),g=v("\u56DE\u5230\u9996\u9875"),y=r({__name:"404",setup(e){function s(){x(B.BASE_HOME_NAME)}return(C,N)=>{const _=n("n-button");return u(),p("div",E,[h,f,d(_,{type:"primary",onClick:s},{default:i(()=>[g]),_:1})])}}});var I=c(y,[["__scopeId","data-v-2155c9c8"]]);export{I as default};
-1
View File
@@ -1 +0,0 @@
import{_}from"./500-dc262da5.js";import{j as c,d as r,r as n,o as u,m as d,e as p,w as i,D as m,E as l,z as t,p as f,H as v,P as x}from"./index.js";const o=e=>(m("data-v-56b900f1"),e=e(),l(),e),h={class:"go-error"},E=o(()=>t("div",{class:"text-center"},[t("img",{src:_,alt:""})],-1)),g=o(()=>t("div",{class:"text-center"},[t("h1",{class:"text-base text-gray-500"},"\u62B1\u6B49\uFF0C\u670D\u52A1\u5668\u51FA\u9519\u4E86")],-1)),y=f("\u56DE\u5230\u9996\u9875"),B=r({__name:"500",setup(e){function s(){v(x.BASE_HOME_NAME)}return(b,C)=>{const a=n("n-button");return u(),d("div",h,[E,g,p(a,{type:"primary",secondary:"",onClick:s},{default:i(()=>[y]),_:1})])}}});var I=c(B,[["__scopeId","data-v-56b900f1"]]);export{I as default};
@@ -1 +0,0 @@
import{d as i,r as n,o as p,m as c,e as a,w as _,z as u,n as l,F as m}from"./index.js";const x=i({__name:"CollapseItem",props:{name:{type:String,required:!0},expanded:{type:Boolean,required:!1,default:!1}},setup(t){const o=e=>{e.preventDefault(),e.stopPropagation()};return(e,v)=>{const r=n("n-divider"),s=n("n-collapse-item"),d=n("n-collapse");return p(),c(m,null,[a(r,{style:{margin:"10px 0"}}),a(d,{"arrow-placement":"right","default-expanded-names":t.expanded?t.name:null,accordion:""},{"header-extra":_(()=>[u("div",{onClick:o},[l(e.$slots,"header")])]),default:_(()=>[a(s,{title:t.name,name:t.name},{default:_(()=>[l(e.$slots,"default")]),_:3},8,["title","name"])]),_:3},8,["default-expanded-names"])],64)}}});export{x as _};
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1 +0,0 @@
var T=Object.defineProperty;var a=Object.getOwnPropertySymbols;var h=Object.prototype.hasOwnProperty,l=Object.prototype.propertyIsEnumerable;var r=(e,t,s)=>t in e?T(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s,i=(e,t)=>{for(var s in t||(t={}))h.call(t,s)&&r(e,s,t[s]);if(a)for(var s of a(t))l.call(t,s)&&r(e,s,t[s]);return e};import{c3 as g,aA as p,G as u,S as y}from"./index.js";import{u as A}from"./chartEditStore-dd0d0f53.js";var n=(e=>(e.SINGLE="single",e.DOUBLE="double",e))(n||{}),c=(e=>(e.THUMBNAIL="thumbnail",e.TEXT="text",e))(c||{}),S=(e=>(e.LAYERS="layers",e.CHARTS="charts",e.DETAILS="details",e.Chart_TYPE="chartType",e.LAYER_TYPE="layerType",e.PERCENTAGE="percentage",e.RE_POSITION_CANVAS="rePositionCanvas",e))(S||{});const C=A(),{GO_CHART_LAYOUT_STORE:o}=y,L=g(o),d=p({id:"useChartLayoutStore",state:()=>i({layers:!0,charts:!0,details:!1,chartType:n.SINGLE,layerType:c.THUMBNAIL,percentage:0,rePositionCanvas:!1},L),getters:{getLayers(){return this.layers},getCharts(){return this.charts},getDetails(){return this.details},getChartType(){return this.chartType},getLayerType(){return this.layerType},getPercentage(){return this.percentage},getRePositionCanvas(){return this.rePositionCanvas}},actions:{setItem(e,t){this.$patch(s=>{s[e]=t}),u(o,this.$state),this.rePositionCanvas=!0,setTimeout(()=>{C.computedScale()},500)},setItemUnHandle(e,t){this.$patch(s=>{s[e]=t})}}});export{S as C,c as L,n as a,d as u};
-1
View File
@@ -1 +0,0 @@
var f=Object.defineProperty,l=Object.defineProperties;var m=Object.getOwnPropertyDescriptors;var o=Object.getOwnPropertySymbols;var u=Object.prototype.hasOwnProperty,d=Object.prototype.propertyIsEnumerable;var p=(t,e,i)=>e in t?f(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i,r=(t,e)=>{for(var i in e||(e={}))u.call(e,i)&&p(t,i,e[i]);if(o)for(var i of o(e))d.call(e,i)&&p(t,i,e[i]);return t},s=(t,e)=>l(t,m(e));import{ax as h,al as a}from"./index.js";import{e as c}from"./chartEditStore-dd0d0f53.js";import{c as n}from"./index-280cc9d6.js";import"./plugin-ee65bc3f.js";import"./icon-e378f613.js";import"./table_scrollboard-e30c6082.js";import"./SizeSetting.vue_vue_type_style_index_0_scoped_true_lang-ca3566f3.js";import"./useTargetData.hook-feffca05.js";const g={dataset:10*60,useEndDate:!1,endDate:new Date().getTime(),style:"\u65F6\u5206\u79D2",showDay:!1,flipperBgColor:"#16293E",flipperTextColor:"#4A9EF8FF",flipperWidth:30,flipperHeight:50,flipperRadius:5,flipperGap:10,flipperType:"down",flipperSpeed:450};class I extends c{constructor(){super(...arguments),this.key=n.key,this.attr=s(r({},h),{w:500,h:100,zIndex:-1}),this.chartConfig=a(n),this.option=a(g)}}export{I as default,g as option};
-1
View File
@@ -1 +0,0 @@
var d=Object.defineProperty,l=Object.defineProperties;var p=Object.getOwnPropertyDescriptors;var r=Object.getOwnPropertySymbols;var g=Object.prototype.hasOwnProperty,h=Object.prototype.propertyIsEnumerable;var e=(o,t,i)=>t in o?d(o,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):o[t]=i,n=(o,t)=>{for(var i in t||(t={}))g.call(t,i)&&e(o,i,t[i]);if(r)for(var i of r(t))h.call(t,i)&&e(o,i,t[i]);return o},f=(o,t)=>l(o,p(t));import{al as a,ax as m}from"./index.js";import{e as c}from"./chartEditStore-dd0d0f53.js";import{H as s}from"./index-280cc9d6.js";import"./plugin-ee65bc3f.js";import"./icon-e378f613.js";import"./table_scrollboard-e30c6082.js";import"./SizeSetting.vue_vue_type_style_index_0_scoped_true_lang-ca3566f3.js";import"./useTargetData.hook-feffca05.js";const u={text:"",icon:"",textSize:30,textColor:"#ffffff",textWeight:"bold",placement:"left-top",distance:8,hint:"\u8FD9\u662F\u63D0\u793A\u6587\u672C",width:0,height:0,paddingX:16,paddingY:8,borderWidth:1,borderStyle:"solid",borderColor:"#1a77a5",borderRadius:6,color:"#ffffff",textAlign:"left",fontWeight:"normal",backgroundColor:"rgba(89, 196, 230, .2)",fontSize:24};class w extends c{constructor(){super(...arguments),this.key=s.key,this.chartConfig=a(s),this.option=a(u),this.attr=f(n({},m),{w:36,h:36,zIndex:1})}}export{w as default,u as option};

Some files were not shown because too many files have changed in this diff Show More