Merge branch 'master' of https://git.zcorp.cc/easycorp/zentaopms
This commit is contained in:
@@ -236,9 +236,9 @@ $config->openMethods[] = 'caselib.index';
|
||||
$config->openMethods[] = 'company.index';
|
||||
$config->openMethods[] = 'user.cropAvatar';
|
||||
$config->openMethods[] = 'custom.index';
|
||||
$config->openMethods[] = 'testcase.getXmindImport';
|
||||
$config->openMethods[] = 'testcase.showXMindImport';
|
||||
$config->openMethods[] = 'testcase.saveXmindImport';
|
||||
$config->openMethods[] = 'testcase.getxmindimport';
|
||||
$config->openMethods[] = 'testcase.showxmindimport';
|
||||
$config->openMethods[] = 'testcase.savexmindimport';
|
||||
|
||||
$config->openModules = array();
|
||||
$config->openModules[] = 'install';
|
||||
|
||||
@@ -654,26 +654,6 @@ CREATE TABLE `zt_chart` (
|
||||
`deleted` tinyint(4) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
CREATE TABLE `zt_chart_back` (
|
||||
`id` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`name` varchar(255) CHARACTER SET utf8 NOT NULL,
|
||||
`dimension` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`type` varchar(30) CHARACTER SET utf8 NOT NULL,
|
||||
`group` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`dataset` varchar(30) CHARACTER SET utf8 NOT NULL,
|
||||
`desc` text CHARACTER SET utf8 NOT NULL,
|
||||
`settings` mediumtext CHARACTER SET utf8 NOT NULL,
|
||||
`filters` mediumtext CHARACTER SET utf8 NOT NULL,
|
||||
`fields` mediumtext CHARACTER SET utf8,
|
||||
`sql` mediumtext CHARACTER SET utf8,
|
||||
`builtin` tinyint(1) unsigned NOT NULL,
|
||||
`objects` mediumtext CHARACTER SET utf8 NOT NULL,
|
||||
`createdBy` char(30) CHARACTER SET utf8 NOT NULL,
|
||||
`createdDate` datetime NOT NULL,
|
||||
`editedBy` varchar(30) CHARACTER SET utf8 NOT NULL,
|
||||
`editedDate` datetime NOT NULL,
|
||||
`deleted` tinyint(4) NOT NULL DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
CREATE TABLE `zt_cmcl` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`type` char(30) NOT NULL,
|
||||
|
||||
+39
-26
File diff suppressed because one or more lines are too long
@@ -7,3 +7,6 @@ ALTER TABLE `zt_todo` CHANGE `idvalue` `objectID` mediumint(8) unsigned default
|
||||
UPDATE `zt_block` SET `dashboard` = `module`;
|
||||
UPDATE `zt_block` SET `module` = IF(`source` != '', `source`, `code`);
|
||||
DROP INDEX account_vision_module_type_order ON `zt_block`;
|
||||
|
||||
ALTER TABLE `zt_block` DROP COLUMN `source`;
|
||||
ALTER TABLE `zt_block` DROP COLUMN `type`;
|
||||
|
||||
+290
-196
File diff suppressed because one or more lines are too long
+431
-397
@@ -1,146 +1,368 @@
|
||||
2023-04-21 18.4.alpha1
|
||||
完成的需求
|
||||
开源版:
|
||||
43977 梳理项目中项目版本的权限逻辑
|
||||
44014 权限支持按照权限包分配
|
||||
44073 执行版本模块增加版本列表的权限
|
||||
44270 更新权限分配页面的修改历史的数据
|
||||
44353 安装升级禅道时可以应对MySQL环境不支持InnoDB格式的情况
|
||||
44706 首页权限默认勾选,界面隐藏不展示
|
||||
44612 检查权限改名后相关功能可以正确使用
|
||||
43134 文档二级菜单调整
|
||||
43143 产品空间增加左侧树形结构
|
||||
43153 项目空间增加左侧树形结构
|
||||
43173 文档列表页面的结构调整
|
||||
43193 文档左侧树形导航中库增加更多操作
|
||||
43194 文档左侧树形导航中目录增加更多操作
|
||||
43211 团队空间的文档列表中增加导出功能
|
||||
43212 产品/项目空间文档列表中增加导出功能
|
||||
43213 执行中文档的列表中增加导出功能
|
||||
43216 文档新建按钮调整
|
||||
43197 产品/项目空间文档搜索功能调整
|
||||
43379 文档左侧树形结构导航支持拖动改变列宽
|
||||
43187 项目空间中WIKI文档库创建表单中的字段调整
|
||||
43192 产品空间创建WIKI文档的交互调整
|
||||
43195 团队空间增加左侧树形导航
|
||||
43200 团队空间文档搜索功能调整
|
||||
43201 接口空间文档搜索功能调整
|
||||
43202 接口空间增加左侧树形导航
|
||||
43204 团队空间中创建库时,访问控制选项调整
|
||||
43209 接口文档列表的调整
|
||||
43214 接口空间中支持创建接口文档
|
||||
43215 接口空间支持创建接口库
|
||||
43222 接口空间的操作按钮调整
|
||||
43223 将原接口库中的版本切换移动到接口空间中
|
||||
43301 产品空间接口库下支持创建接口文档
|
||||
43306 产品空间创建WIKI文档库的表单调整
|
||||
43308 产品空间新增创建接口库的功能
|
||||
43329 项目空间创建WIKI文档时表单字段调整
|
||||
43563 项目文档中WIKI文档库创建表单的字段调整
|
||||
43564 产品文档中创建WIKI文档库的表单调整
|
||||
43567 执行文档中WIKI文档库创建表单中的字段调整
|
||||
43582 项目空间新增创建接口库的功能
|
||||
43584 团队空间创建WIKI文档的创建交互调整
|
||||
43585 产品文档中创建WIKI文档的交互调整
|
||||
43587 项目文档中创建WIKI文档时表单字段调整
|
||||
43588 调整执行模块文档下的搜索功能
|
||||
43589 执行文档中创建WIKI文档时表单字段调整
|
||||
43590 产品模块增加左侧树形导航
|
||||
43591 项目模块增加左侧树形导航
|
||||
43592 执行模块增加左侧树形导航
|
||||
43593 项目空间接口库下支持创建接口文档
|
||||
43594 产品文档中支持创建接口文档
|
||||
43595 项目文档中支持创建接口文档
|
||||
43599 创建WIKI文档时,支持存为草稿
|
||||
43778 产品文档中新增创建接口库的功能
|
||||
43793 项目文档新增创建接口库的功能
|
||||
43957 文档附件库的入口调整及优化
|
||||
43154 将原接口库中的版本管理移动到接口空间中
|
||||
43206 接口空间文档列表中增加导出功能
|
||||
43208 将原接口库中的数据结构移动到接口空间中
|
||||
43210 将原接口库文档页面中的发布接口移动到接口空间中
|
||||
43236 文档中我的空间内容结构
|
||||
43240 我的空间左侧导航区域内容定义
|
||||
43283 我的空间文档列表样式定义
|
||||
43284 我的空间增加文档搜索功能
|
||||
43330 我的空间增加创建WIKI文档功能
|
||||
43331 文档模块的详情页结构调整
|
||||
43344 文档增加浏览和收藏的信息记录
|
||||
43618 文档左侧树形导航区块支持展开收起
|
||||
43650 文档模块的权限调整
|
||||
43687 文档详情的左侧树形导航新增显示设置按钮
|
||||
43817 文档全局创建的交互调整
|
||||
43995 二次开发的接口文档增加RESTful格式的接口文档
|
||||
44321 我的空间支持创建库
|
||||
43156 文档详情页新增面包屑导航
|
||||
43159 文档详情页中新增关键字标签
|
||||
43169 修改文档详情页历史记录位置及交互
|
||||
43172 文档详情页右侧新增文档导航模块
|
||||
43345 文档仪表盘区块调整
|
||||
43348 文档仪表盘文档统计区块新增贡献统计
|
||||
43349 文档仪表盘新增文档动态区块
|
||||
43351 文档仪表盘最近更新区块增加更新时间的信息
|
||||
43377 文档仪表盘增加我的收藏区块
|
||||
43383 当编辑他人正在编辑的文档时,增加提醒信息
|
||||
43385 文档详情页导出逻辑简化
|
||||
43597 产品/项目/执行模块文档详情的导出规则调整
|
||||
43600 产品/项目/执行模块的文档详情页右侧新增文档导航模块
|
||||
43601 产品/项目/执行模块的文档详情页新增面包屑导航
|
||||
43602 产品/项目/执行模块的文档详情页历史记录位置及交互调整
|
||||
43606 产品/项目/执行模块的文档详情页中新增关键字标签
|
||||
43649 文档详情内容区域右上角操作按钮顺序调整
|
||||
43651 产品/项目/执行模块文档详情内容区域右上角操作按钮顺序调整
|
||||
44081 私有文档的动态隐藏
|
||||
44082 我的空间文档列表支持导出
|
||||
44308 文档详情页新增面包屑导航
|
||||
43161 文档详情新增查看编辑者的信息
|
||||
43170 合并文档详情页的历史版本切换和版本对比
|
||||
43346 文档仪表盘新增产品文档区块
|
||||
43603 合并产品/项目/执行模块中文档详情页的历史版本切换和版本对比
|
||||
43604 产品/项目/执行模块的文档详情新增查看编辑者的信息
|
||||
43645 地盘贡献中我创建的文档列表字段和样式调整
|
||||
43646 地盘贡献中我编辑的文档列表字段和样式调整
|
||||
43812 文档标题的下方增加当前文档收藏数显示
|
||||
43813 文档标题的下方增加浏览数量的显示
|
||||
43814 文档仪表盘新增项目文档区块
|
||||
43815 文档仪表盘新增浏览排行榜
|
||||
43816 文档仪表盘新增收藏排行榜
|
||||
44510 文档列表左侧树形结构中目录支持拖拽排序功能
|
||||
44539 我的空间增加我编辑的文档内容
|
||||
44510 文档列表左侧树形结构中目录支持拖拽排序功能
|
||||
44497 开源版BI内置各类维度
|
||||
44353 安装升级禅道时可以应对MySQL环境不支持InnoDB格式的情况
|
||||
44321 我的空间支持创建库
|
||||
44308 文档详情页新增面包屑导航
|
||||
44272 开源版BI改版弹窗的展示
|
||||
44271 开源版BI增加改版弹窗
|
||||
44270 更新权限分配页面的修改历史的数据
|
||||
44085 检查权限删除后相关功能可以正确使用
|
||||
44082 我的空间文档列表支持导出
|
||||
44081 私有文档的动态隐藏
|
||||
44073 执行版本模块增加版本列表的权限
|
||||
44016 权限分配页面样式优化
|
||||
44015 权限分配页面支持展示依赖权限和推荐权限
|
||||
44014 权限支持按照权限包分配
|
||||
44013 权限分配页面增加权限包展示
|
||||
43995 二次开发的接口文档增加RESTful格式的接口文档
|
||||
43977 梳理项目中项目版本的权限逻辑
|
||||
43963 权限的保存逻辑
|
||||
43960 依赖权限的保存逻辑
|
||||
43957 文档附件库的入口调整及优化
|
||||
43942 按模块分配权限功能中支持按照权限包快速筛选
|
||||
43941 推荐权限区块的交互逻辑
|
||||
43940 开源版BI图表保留企业版的部分权限
|
||||
43939 开源版BI图表保留企业版的部分功能
|
||||
43938 依赖权限区块的交互逻辑
|
||||
43937 开源版BI透视表保留企业版的部分权限
|
||||
43936 按模块分配权限功能中的模块、权限包、方法更新至最新版
|
||||
43935 开源版BI维度保留企业版的部分功能
|
||||
43924 用例列表支持导入xmind
|
||||
43923 用例列表支持xmind模版文件含需求数据的导出
|
||||
43922 用例列表支持xmind模版文件无需求数据的导出
|
||||
43907 在用例列表浏览场景
|
||||
43906 在用例列表建场景
|
||||
43904 开源版BI大屏保留企业版的部分权限
|
||||
43903 开源版BI大屏保留企业版的部分功能
|
||||
43899 开源版BI透视表保留企业版的部分功能
|
||||
43879 在用例列表批量建场景
|
||||
43878 在用例列表删除场景
|
||||
43877 在用例列表编辑场景
|
||||
43817 文档全局创建的交互调整
|
||||
43816 文档仪表盘新增收藏排行榜
|
||||
43815 文档仪表盘新增浏览排行榜
|
||||
43814 文档仪表盘新增项目文档区块
|
||||
43813 文档标题的下方增加浏览数量的显示
|
||||
43812 文档标题的下方增加当前文档收藏数显示
|
||||
43793 项目文档新增创建接口库的功能
|
||||
43778 产品文档中新增创建接口库的功能
|
||||
43687 文档详情的左侧树形导航新增显示设置按钮
|
||||
43668 执行看板点击父阶段无法进入
|
||||
43651 产品/项目/执行模块文档详情内容区域右上角操作按钮顺序调整
|
||||
43650 文档模块的权限调整
|
||||
43649 文档详情内容区域右上角操作按钮顺序调整
|
||||
43646 地盘贡献中我编辑的文档列表字段和样式调整
|
||||
43645 地盘贡献中我创建的文档列表字段和样式调整
|
||||
43618 文档左侧树形导航支持展开收起
|
||||
43611 windows一键安装包的xampp\zentao\db\zentao.sql重装时报错
|
||||
43606 产品/项目/执行模块的文档详情页中新增关键字标签
|
||||
43604 产品/项目/执行模块的文档详情新增查看编辑者的信息
|
||||
43603 合并产品/项目/执行模块中文档详情页的历史版本切换和版本对比
|
||||
43602 产品/项目/执行模块的文档详情页历史记录位置及交互调整
|
||||
43601 产品/项目/执行模块的文档详情页新增面包屑导航
|
||||
43600 产品/项目/执行模块的文档详情页右侧新增文档导航模块
|
||||
43599 创建WIKI文档时,支持存为草稿
|
||||
43597 产品/项目/执行模块文档详情的导出规则调整
|
||||
43595 项目文档中支持创建接口文档
|
||||
43594 产品文档中支持创建接口文档
|
||||
43593 项目空间接口库下支持创建接口文档
|
||||
43592 执行模块增加左侧树形导航
|
||||
43591 项目模块增加左侧树形导航
|
||||
43590 产品模块增加左侧树形导航
|
||||
43589 执行文档中创建WIKI文档时表单字段调整
|
||||
43588 调整执行模块文档下的搜索功能
|
||||
43587 项目文档中创建WIKI文档时表单字段调整
|
||||
43585 产品文档中创建WIKI文档的交互调整
|
||||
43584 团队空间创建WIKI文档的创建交互调整
|
||||
43582 项目空间新增创建接口库的功能
|
||||
43567 执行文档中WIKI文档库创建表单中的字段调整
|
||||
43564 产品文档中创建WIKI文档库的表单调整
|
||||
43563 项目文档中WIKI文档库创建表单的字段调整
|
||||
43385 文档详情页导出逻辑简化
|
||||
43383 当编辑他人正在编辑的文档时,增加提醒信息
|
||||
43379 文档左侧树形结构导航支持拖动改变列宽
|
||||
43377 文档仪表盘增加我的收藏区块
|
||||
43351 文档仪表盘最近更新区块增加更新时间的信息
|
||||
43349 文档仪表盘新增文档动态区块
|
||||
43348 文档仪表盘文档统计区块新增贡献统计
|
||||
43346 文档仪表盘新增产品文档区块
|
||||
43345 文档仪表盘区块调整
|
||||
43344 文档增加浏览和收藏的信息记录
|
||||
43331 文档模块的详情页结构调整
|
||||
43330 我的空间增加创建WIKI文档功能
|
||||
43329 项目空间创建WIKI文档时表单字段调整
|
||||
43308 产品空间新增创建接口库的功能
|
||||
43306 产品空间创建WIKI文档库的表单调整
|
||||
43301 产品空间接口库下支持创建接口文档
|
||||
43284 我的空间增加文档搜索功能
|
||||
43283 我的空间文档列表样式定义
|
||||
43240 我的空间左侧导航区域内容定义
|
||||
43236 文档中我的空间内容结构
|
||||
43223 将原接口库中的版本切换移动到接口空间中
|
||||
43222 接口空间的操作按钮调整
|
||||
43216 文档新建按钮调整
|
||||
43215 接口空间支持创建接口库
|
||||
43214 接口空间中支持创建接口文档
|
||||
43213 执行中文档的列表中增加导出功能
|
||||
43212 产品/项目空间文档列表中增加导出功能
|
||||
43211 团队空间的文档列表中增加导出功能
|
||||
43210 将原接口库文档页面中的发布接口移动到接口空间中
|
||||
43209 接口文档列表的调整
|
||||
43208 将原接口库中的数据结构移动到接口空间中
|
||||
43206 接口空间文档列表中增加导出功能
|
||||
43204 团队空间中创建库时,访问控制选项调整
|
||||
43202 接口空间增加左侧树形导航
|
||||
43201 接口空间文档搜索功能调整
|
||||
43200 团队空间文档搜索功能调整
|
||||
43197 产品/项目空间文档搜索功能调整
|
||||
43195 团队空间增加左侧树形导航
|
||||
43194 文档左侧树形导航中目录增加更多操作
|
||||
43193 文档左侧树形导航中库增加更多操作
|
||||
43192 产品空间创建WIKI文档的交互调整
|
||||
43187 项目空间中WIKI文档库创建表单中的字段调整
|
||||
43173 文档列表页面的结构调整
|
||||
43172 文档详情页右侧新增文档导航模块
|
||||
43170 合并文档详情页的历史版本切换和版本对比
|
||||
43169 修改文档详情页历史记录位置及交互
|
||||
43161 文档详情新增查看编辑者的信息
|
||||
43159 文档详情页中新增关键字标签
|
||||
43156 文档详情页新增面包屑导航
|
||||
43154 将原接口库中的版本管理移动到接口空间中
|
||||
43153 项目空间增加左侧树形结构
|
||||
43143 产品空间增加左侧树形结构
|
||||
43134 文档二级菜单调整
|
||||
43098 用户信息列表增加维护职位功能
|
||||
41136 地盘待处理的任务列表展示已暂停状态的任务
|
||||
38422 需求创建后的通知增加评审人
|
||||
企业版:
|
||||
40348 创建图表页面新增图表创建向导组件
|
||||
40353 设计图表时新增查询数据页面
|
||||
40374 设计图表时新增设计图表页面
|
||||
40389 图表向导中的设计页面新增图表展示窗格
|
||||
40390 图表向导中的设计页面新增图表配置项窗格
|
||||
40401 图表向导中的设计页面新增饼图的参数配置
|
||||
40417 设计图表时新增准备发布页面
|
||||
40426 图表向导中准备发布页面新增基础信息窗格
|
||||
40438 设计图表时新增配置筛选器页面
|
||||
40440 图表向导中配置筛选器页面新增图表展示窗格
|
||||
40441 图表向导中配置筛选器页面新增参数配置窗格
|
||||
41559 bi二级菜单新增数据模块
|
||||
41564 创建中间表时调整创建页面顺序
|
||||
41572 对中间表设计时的sql查询器界面进行提升
|
||||
41573 对中间表设计时的保存弹窗进行提升
|
||||
41575 对创建图表弹窗进行提升
|
||||
41579 图表向导中准备发布页面新增图表展示窗格
|
||||
41586 设计图表时将sql查询存为中间表
|
||||
40348 创建图表页面新增图表创建向导组件
|
||||
40374 设计图表时新增设计图表页面
|
||||
40389 图表向导中的设计页面新增图表展示窗格
|
||||
40390 图表向导中的设计页面新增图表配置项窗格
|
||||
40401 图表向导中的设计页面新增饼图的参数配置
|
||||
40417 设计图表时新增准备发布页面
|
||||
40426 图表向导中准备发布页面新增基础信息窗格
|
||||
40438 设计图表时新增配置筛选器页面
|
||||
40440 图表向导中配置筛选器页面新增图表展示窗格
|
||||
40441 图表向导中配置筛选器页面新增参数配置窗格
|
||||
41572 对中间表设计时的sql查询器界面进行提升
|
||||
41579 图表向导中准备发布页面新增图表展示窗格
|
||||
44761 图表后台实现内置图表的提示说明
|
||||
44760 透视表后台实现内置透视表的提示说明
|
||||
44759 维护图表分组时新增删除限制
|
||||
44758 维护透视表分组时新增删除限制
|
||||
44757 透视表前台显示已升级的内置透视表
|
||||
44756 透视表后台列表中显示内置透视表
|
||||
44755 图表前台显示已升级的内置图表
|
||||
44754 图表后台列表中显示内置图表
|
||||
44659 图表前台页面内置大屏中的图表
|
||||
44658 透视表前台页面内置大屏中的透视表
|
||||
44498 企业版BI内置各类维度
|
||||
44451 删除维度时增加提示
|
||||
44450 新增年度完成项目过程数据大屏
|
||||
44449 新增公司质量数据盘点大屏
|
||||
44448 BI新增内置效能管理维度和质量管理度
|
||||
44439 修改大屏设计器引用图表、透视表时的默认尺寸
|
||||
44399 查询筛选器中日期选择控件实现设置日期变量参数
|
||||
44384 统一图表、透视表设计器窗格标题的字号
|
||||
44363 透视表列设置实现计算后的值保留两位小数
|
||||
44344 大屏设计器引用透视表、图表筛选器时的显示规则
|
||||
44335 大屏设计器引用透视表、图表筛选器时的样式
|
||||
44311 调整BI展示窗格中筛选器查询按钮的位置
|
||||
44294 查看大屏时显示大屏引用的图表筛选器
|
||||
44293 查看大屏时显示大屏引用的透视表筛选器
|
||||
44291 大屏设计器实现引用图表的筛选器
|
||||
44290 大屏设计器实现引用透视表的筛选器
|
||||
44183 优化图表结果筛选器参数配置项的文案
|
||||
44182 优化透视表结果筛选器参数配置项的文案
|
||||
44181 优化透视表查询筛选器参数配置项的文案
|
||||
44179 修改图表前台展示页面表格间距
|
||||
44178 查看大屏时实现显示删除或草稿态图表和透视表的占位区域
|
||||
44177 大屏中引用的图表失效时以占位区域的方式展示
|
||||
44176 大屏中引用的透视表失效时以占位区域的方式展示
|
||||
44142 在图表前台新增详情展示
|
||||
44139 大屏设计器实现选择固定尺寸的画布
|
||||
44138 缩小大屏设计器中组件缩略图的尺寸
|
||||
44137 调整透视表后台的查询筛选器参数配置项的文案
|
||||
44135 在透视表前台新增详情展示
|
||||
44134 优化流程向导组件的样式
|
||||
44133 调整透视表设置值的显示方式时表头的命名规则
|
||||
44132 修改图表准备发布页面右侧窗格各组件间距
|
||||
44131 修改图表配置筛选器页面右侧窗格各组件间距
|
||||
44130 修改图表准备发布页面左侧窗格各组件间距
|
||||
44129 修改图表配置筛选器页面左侧窗格各组件间距
|
||||
44128 修改图表设计图表页面右侧窗格各组件间距
|
||||
44127 修改图表设计图表页面左侧窗格各组件间距
|
||||
44126 修改图表配置筛选器页面右侧窗格背景色
|
||||
44125 修改透视表前台展示页面表格间距
|
||||
44124 修改透视表准备发布页面右侧窗格各组件间距
|
||||
44123 修改透视表准备发布页面左侧窗格各组件间距
|
||||
44122 修改透视表配置筛选器页面左侧窗格各组件间距
|
||||
44121 修改透视表配置筛选器页面右侧窗格各组件间距
|
||||
44120 修改透视表配置筛选器页面的字色与字重
|
||||
44119 修改透视表准备发布页面右侧窗格背景色
|
||||
44118 修改透视表配置筛选器页面右侧窗格背景色
|
||||
44117 修改透视表设计透视表页面右侧窗格背景色
|
||||
44116 修改透视表设计透视表页面左侧窗格各组件间距
|
||||
44115 修改透视表设计透视表页面右侧窗格各组件间距
|
||||
44077 大屏中引用透视表与切分列后的透视表保持一致
|
||||
44074 透视表设计时不能对同一个字段进行行分组
|
||||
44004 BI二级导航中新增模块的分割线
|
||||
44003 取消维护维度页面的标题
|
||||
44002 取消维护维度页面的返回按钮
|
||||
44001 在维护维度页面时显示BI的二级导航
|
||||
44000 取消维度导航中去维护的按钮
|
||||
43999 BI新增维度模块作为维护维度页面的入口
|
||||
43927 企业版BI改版弹窗的展示
|
||||
43917 企业版BI增加改版弹窗
|
||||
43874 取消后台权限中BI模块的BI分组
|
||||
43873 将后台权限中部分BI权限调整至项目度量分组
|
||||
43872 调整后台BI权限中的统计首页的权限
|
||||
43868 透视表列设置实现行的汇总值独占一列功能
|
||||
43867 透视表实现前后台导出功能
|
||||
43866 透视表设计器隐藏垂直切分配置项
|
||||
43775 调整后台权限中BI模块内分组顺序
|
||||
43768 调整后台权限中BI模块内权限的分组
|
||||
43751 透视表列设置实现展示行的汇总值
|
||||
43710 透视表列设置实现列引用字段的功能
|
||||
43706 透视表水平分组名称调整为行分组
|
||||
43701 大屏设计器中图片组件的路径参数默认为空
|
||||
43700 大屏设计器中远程网页组件的路径参数默认为空
|
||||
43694 隐藏大屏设计器中的三维地球组件
|
||||
43691 隐藏大屏设计器中的选择组件
|
||||
43690 隐藏大屏设计器中的词云组件
|
||||
43686 进入维护维度页面后隐藏维度导航和BI二级导航
|
||||
43684 发布态的大屏卡片展示发布态的缩略图
|
||||
43683 维护维度页面新增页面标题
|
||||
43682 草稿态的大屏卡片展示草稿态的缩略图
|
||||
43681 维护维度页面打印返回按钮
|
||||
43678 取消BI二级导航中的设置模块
|
||||
43677 维度导航中打印去维护的按钮
|
||||
43643 新增产品bug数量统计
|
||||
43642 新增产品用例数量统计条形图
|
||||
43641 新增产品缺陷数据汇总表
|
||||
43640 新增1、2级bug年度统计堆积柱形图
|
||||
43639 新增bug密度年度趋势图
|
||||
43638 新增有效bug率年度趋势图
|
||||
43637 新增有效bug、bug总数与解决Bug数近30天统计柱形图
|
||||
43636 新增bug类型分布图
|
||||
43635 新增bug解决方案分布图
|
||||
43634 新增bug严重程度分布图
|
||||
43633 新增bug状态分布图
|
||||
43632 新增用例覆盖率、用例密度、Bug密度和Bug修复率水球图
|
||||
43631 新增质量数据概览卡片
|
||||
43613 透视表设计器水平切分名称调整为水平分组
|
||||
43580 新增年度完成项目过程数据大屏
|
||||
43577 新增时间筛选器
|
||||
43576 新增完成项目间单位时间交付需求规模数对比图
|
||||
43575 新增完成项目工时偏差率条形图
|
||||
43574 新增完成项目工期偏差率条形图
|
||||
43573 新增完成项目工时透视表
|
||||
43572 新增完成项目工期透视表
|
||||
43571 新增执行完成分布图
|
||||
43570 新增项目完成分布图
|
||||
43569 新增项目按期完成率、执行按期完成率、项目延期率、执行延期率的环形图
|
||||
43568 新增年度完成项目数据盘点卡片
|
||||
43566 透视表设计器水平分组新增帮助说明
|
||||
43565 透视表列设置新增帮助说明
|
||||
43552 透视表列设置实现列汇总百分比的显示方式
|
||||
43551 透视表列设置实现行汇总百分比的显示方式
|
||||
43549 透视表列设置实现总计百分比的显示方式
|
||||
43548 透视表列设置实现配置值的显示方式
|
||||
43544 透视表列设置实现添加列的功能
|
||||
43468 透视表列设置实现对列进行切片的功能
|
||||
43467 设计或删除被草稿态大屏引用的图表的提示与显示
|
||||
43466 设计或删除被已发布大屏引用的图表的提示与显示
|
||||
43464 设计或删除被草稿态大屏引用的透视表的提示与显示
|
||||
43462 透视表列设置实现按不同方式计算值的功能
|
||||
43460 透视表列设置实现删除列功能
|
||||
43459 透视表实现列设置的参数配置面板
|
||||
43458 透视表列设置实现单独一列展示值的百分比
|
||||
43441 统一前台中图表、透视表导出按钮的位置与样式
|
||||
43439 优化下拉选择查询筛选器的参数配置
|
||||
43438 优化时间选择查询筛选器的参数配置
|
||||
43437 优化日期选择查询筛选器的参数配置
|
||||
43434 统一后台中图表、透视表导出按钮的位置与样式
|
||||
43396 透视表设置水平分组后列名显示分组字段名称
|
||||
43326 优化流程向导组件的交互逻辑及样式
|
||||
43321 设计或删除被已发布大屏引用的透视表的提示与显示
|
||||
43319 图表实现关联多个分组
|
||||
43318 透视表实现关联多个分组
|
||||
43254 设计透视表的基本信息实现多语言设置
|
||||
43096 大屏卡片实现展示大屏的缩略图
|
||||
43047 已添加结果筛选器时不可添加查询筛选器
|
||||
43012 查看图表页实现筛选器查询功能
|
||||
43011 数据表查询数据时实现查询中状态
|
||||
43009 已添加查询筛选器时不可添加结果筛选器
|
||||
43006 修改水平切分的默认展示规则
|
||||
42963 实现导出图表权限
|
||||
42962 查看图表时实现导出功能
|
||||
42961 图表设计时实现导出功能
|
||||
42875 优化后台数据表权限
|
||||
42874 透视表sql查询时实现查询筛选器功能
|
||||
42842 查询数据页面的查询结果区块增加分页器
|
||||
42836 修改设置字段名的位置
|
||||
42824 透视表设计时新增结果筛选器概念
|
||||
42823 透视表设计时取消存为中间表功能
|
||||
42821 设计透视表页面参数配置文案调整
|
||||
42806 设计图表时结果筛选器实现条件筛选类型筛选器
|
||||
42771 查看透视表时实现导出功能
|
||||
42767 实现导出透视表权限
|
||||
42766 透视表设计时实现导出功能
|
||||
42762 创建中间表时实现字段多语言设置
|
||||
42752 自定义水晶报表升级为bi透视表
|
||||
42751 透视表实现查询筛选器的参数配置
|
||||
42750 透视表前台展示查询筛选器
|
||||
42749 透视表展示窗格展示查询筛选器
|
||||
42728 对被引用的中间表实现编辑限制
|
||||
42712 可视化仪表盘升级为bi大屏
|
||||
42709 可视化图表升级为bi图表
|
||||
42679 透视表配置查询条件调整为配置筛选器
|
||||
42675 大屏设计时实现全局筛选器配置
|
||||
42538 实现字段多语言及内容设置的弹窗样式
|
||||
42537 调整图表参数配置窗格样式
|
||||
42535 配置结果筛选器时实现自动对应字段内容
|
||||
42507 查询数据时实现对应字段内容及多语言设置
|
||||
42506 透视表设计器实现展示列的汇总值
|
||||
42492 透视表设计实现去重计数的统计方式
|
||||
42491 图表设计实现Y轴数据的多种统计方式
|
||||
42478 实现bi图表权限配置
|
||||
42473 后台权限控制中统计名称与功能模块保持一致
|
||||
42446 大屏设计时实现全屏设计
|
||||
42445 实现bi大屏权限设置
|
||||
42444 可视化数据集升级为bi数据表
|
||||
42443 大屏设计图表配置窗格新增数据和小组件
|
||||
42438 优化设计透视表页面
|
||||
42437 透视表行分组合并单元格并居中显示
|
||||
42435 透视表设计页面默认展示sql查询结果
|
||||
42433 大屏浏览页面的卡片新增草稿态标签
|
||||
42432 大屏设计时实现将设计存为草稿态
|
||||
42382 查询数据时展示查询结果的统计信息
|
||||
42380 后台设计时增加空页面提示文案
|
||||
42379 修改后台列表的内边距与排列规则
|
||||
42376 实现bi透视表权限配置
|
||||
42375 通过按钮实现bi前后台的切换
|
||||
42374 优化前后台切换按钮的样式
|
||||
42370 调整前台的分组标签样式
|
||||
42310 透视表配置参数后的展示方式
|
||||
42210 配置查询条件页面的展示窗格中实现查询条件查询功能
|
||||
42209 配置筛选器页面的展示窗格中实现筛选器查询功能
|
||||
42208 后台已发布的透视表在前台进行展示
|
||||
42207 后台已发布的图表在前台进行展示
|
||||
42169 修改列表的设计规则
|
||||
42108 设计透视表时配置查询条件页面新增基础参数设置
|
||||
42107 设计透视表时配置查询条件页面新增配置项窗格
|
||||
42106 设计透视表时配置查询条件页面新增透视表展示窗格
|
||||
42105 设计透视表时新增配置查询条件页面
|
||||
42053 透视表与图表的分组样式保持一致
|
||||
41946 年度总结大屏贡献数据图表中测试单展示已关闭数据
|
||||
41914 复用图表设计的交互逻辑
|
||||
41905 后台透视表浏览列表中新增创建者字段
|
||||
41888 在后台透视表浏览列表中新增草稿标签
|
||||
41887 创建透视表流程向导页面实现将透视表存为草稿的功能
|
||||
41827 保持图表及透视表的浏览列表边框线一致
|
||||
41823 后台图表浏览列表中新增创建者字段
|
||||
41822 取消后台图表浏览列表中的分组字段
|
||||
41720 图表向导中的设计页面新增堆积条形图的参数配置
|
||||
41719 图表向导中的设计页面新增堆积柱形图的参数配置
|
||||
41717 图表向导中的设计页面新增雷达图的参数配置
|
||||
41716 图表向导中的设计页面新增簇状条形图的参数配置
|
||||
41715 图表向导中的设计页面新增折线图的参数配置
|
||||
41706 图表向导中的设计页面新增簇状柱形图的参数配置
|
||||
41672 在后台图表浏览列表中新增草稿标签
|
||||
41671 创建图表流程向导页面实现将图表存为草稿的功能
|
||||
41670 提升创建图表时配置筛选器页面的交互逻辑
|
||||
@@ -148,47 +370,6 @@
|
||||
41668 提升创建图表时设计图表页面的交互逻辑
|
||||
41667 提升创建图表时查询数据页面的交互逻辑
|
||||
41666 提升创建图表流程向导中点击标签的交互逻辑
|
||||
41581 建透视表弹窗内容调整
|
||||
41582 建透视表页面新增流程向导
|
||||
41583 建透视表时新增查询数据页面
|
||||
41584 设计透视表时新增设计透视表页面
|
||||
41587 设计透视表时设计透视表页面新增透视表展示窗格
|
||||
41588 设计透视表时设计透视表页面新增透视表配置项窗格
|
||||
41589 设计透视表时设计透视表页面新增基础参数设置
|
||||
41590 设计透视表时新增准备发布页面
|
||||
41591 设计透视表时准备发布页面新增透视表展示窗格
|
||||
41592 设计透视表时准备发布页面新增透视表基础信息窗格
|
||||
41593 修改设计、编辑基本信息、删除按钮的图标
|
||||
41887 创建透视表流程向导页面实现将透视表存为草稿的功能
|
||||
41888 在后台透视表浏览列表中新增草稿标签
|
||||
41905 后台透视表浏览列表中新增创建者字段
|
||||
41914 复用图表设计的交互逻辑
|
||||
42053 透视表与图表的分组样式保持一致
|
||||
42105 设计透视表时新增配置查询条件页面
|
||||
42106 设计透视表时配置查询条件页面新增透视表展示窗格
|
||||
42107 设计透视表时配置查询条件页面新增配置项窗格
|
||||
42108 设计透视表时配置查询条件页面新增基础参数设置
|
||||
42169 修改列表的设计规则
|
||||
42209 配置筛选器页面的展示窗格中实现筛选器查询功能
|
||||
42210 配置查询条件页面的展示窗格中实现查询条件查询功能
|
||||
42310 透视表配置参数后的展示方式
|
||||
42478 实现bi图表权限配置
|
||||
42376 实现bi透视表权限配置
|
||||
42375 通过按钮实现bi前后台的切换
|
||||
42374 优化前后台切换按钮的样式
|
||||
42208 后台已发布的透视表在前台进行展示
|
||||
42207 后台已发布的图表在前台进行展示
|
||||
42473 后台权限控制中统计名称与功能模块保持一致
|
||||
42438 优化设计透视表页面
|
||||
42437 透视表行分组合并单元格并居中显示
|
||||
42382 查询数据时展示查询结果的统计信息
|
||||
42380 后台设计时增加空页面提示文案
|
||||
42379 修改后台列表的内边距与排列规则
|
||||
42370 调整前台的分组标签样式
|
||||
42446 大屏设计时实现全屏设计
|
||||
42445 实现bi大屏权限设置
|
||||
42433 大屏浏览页面的卡片新增草稿态标签
|
||||
42432 大屏设计时实现将设计存为草稿态
|
||||
41611 大屏发布时新增大屏弹窗
|
||||
41606 大屏设计页面工具栏新增发布按钮
|
||||
41605 大屏设计页面新增画布的参数配置
|
||||
@@ -199,230 +380,83 @@
|
||||
41599 创建大屏时新增大屏设计页面
|
||||
41598 实现创建大屏的基本信息
|
||||
41595 大屏卡片实现更多的操作
|
||||
41598 实现创建大屏的基本信息
|
||||
41601 大屏设计页面新增图表参数配置
|
||||
41603 大屏设计页面新增参数配置窗格
|
||||
41605 大屏设计页面新增画布的参数配置
|
||||
42375 通过按钮实现bi前后台的切换
|
||||
42380 后台设计时增加空页面提示文案
|
||||
42382 查询数据时展示查询结果的统计信息
|
||||
42473 后台权限控制中统计名称与功能模块保持一致
|
||||
42435 透视表设计页面默认展示sql查询结果
|
||||
42679 透视表配置查询条件调整为配置筛选器
|
||||
42821 设计透视表页面参数配置文案调整
|
||||
42823 透视表设计时取消存为中间表功能
|
||||
42824 透视表设计时新增结果筛选器概念
|
||||
42836 修改设置字段名的位置
|
||||
41611 大屏发布时新增大屏弹窗
|
||||
42675 大屏设计时实现全局筛选器配置
|
||||
43011 数据表查询数据时实现查询中状态
|
||||
42209 配置筛选器页面的展示窗格中实现筛选器查询功能
|
||||
42749 透视表展示窗格展示查询筛选器
|
||||
42750 透视表前台展示查询筛选器
|
||||
42762 创建中间表时实现字段多语言设置
|
||||
43006 修改水平切分的默认展示规则
|
||||
43012 查看图表页实现筛选器查询功能
|
||||
42728 对被引用的中间表实现编辑限制
|
||||
42963 实现导出图表权限
|
||||
42962 查看图表时实现导出功能
|
||||
42875 优化后台数据表权限
|
||||
42771 查看透视表时实现导出功能
|
||||
42767 实现导出透视表权限
|
||||
43047 已添加结果筛选器时不可添加查询筛选器
|
||||
43009 已添加查询筛选器时不可添加结果筛选器
|
||||
42492 透视表设计实现去重计数的统计方式
|
||||
42491 图表设计实现Y轴数据的多种统计方式
|
||||
43396 透视表设置水平分组后列名显示分组字段名称
|
||||
42507 查询数据时实现对应字段内容及多语言设置
|
||||
42538 实现字段多语言及内容设置的弹窗样式
|
||||
42842 查询数据页面的查询结果区块增加分页器
|
||||
43096 大屏卡片实现展示大屏的缩略图
|
||||
43434 统一后台中图表、透视表导出按钮的位置与样式
|
||||
43441 统一前台中图表、透视表导出按钮的位置与样式
|
||||
43566 透视表设计器水平分组新增帮助说明
|
||||
43613 透视表设计器水平切分名称调整为水平分组
|
||||
42535 配置结果筛选器时实现自动对应字段内容
|
||||
42874 透视表sql查询时实现查询筛选器功能
|
||||
43318 透视表实现关联多个分组
|
||||
43319 图表实现关联多个分组
|
||||
43434 统一后台中图表、透视表导出按钮的位置与样式
|
||||
43437 优化日期选择查询筛选器的参数配置
|
||||
43438 优化时间选择查询筛选器的参数配置
|
||||
43439 优化下拉选择查询筛选器的参数配置
|
||||
43682 草稿态的大屏卡片展示草稿态的缩略图
|
||||
43684 发布态的大屏卡片展示发布态的缩略图
|
||||
43866 透视表设计器隐藏垂直切分配置项
|
||||
43565 透视表列设置新增帮助说明
|
||||
43677 维度导航中打印去维护的按钮
|
||||
43678 取消BI二级导航中的设置模块
|
||||
43681 维护维度页面打印返回按钮
|
||||
43683 维护维度页面新增页面标题
|
||||
43686 进入维护维度页面后隐藏维度导航和BI二级导航
|
||||
43690 隐藏大屏设计器中的词云组件
|
||||
43691 隐藏大屏设计器中的选择组件
|
||||
43694 隐藏大屏设计器中的三维地球组件
|
||||
43700 大屏设计器中远程网页组件的路径参数默认为空
|
||||
43701 大屏设计器中图片组件的路径参数默认为空
|
||||
43706 透视表水平分组名称调整为行分组
|
||||
43254 设计透视表的基本信息实现多语言设置
|
||||
43459 透视表实现列设置的参数配置面板
|
||||
43460 透视表列设置实现删除列功能
|
||||
43462 透视表列设置实现按不同方式计算值的功能
|
||||
43544 透视表列设置实现添加列的功能
|
||||
43548 透视表列设置实现配置值的显示方式
|
||||
43551 透视表列设置实现行汇总百分比的显示方式
|
||||
43775 调整后台权限中BI模块内分组顺序
|
||||
43867 透视表实现前后台导出功能
|
||||
43868 透视表列设置实现行的汇总值独占一列功能
|
||||
42506 透视表设计器实现展示列的汇总值
|
||||
43458 透视表列设置实现单独一列展示值的百分比
|
||||
43468 透视表列设置实现对列进行切片的功能
|
||||
43549 透视表列设置实现总计百分比的显示方式
|
||||
43751 透视表列设置实现展示行的汇总值
|
||||
43768 调整后台权限中BI模块内权限的分组
|
||||
43551 透视表列设置实现行汇总百分比的显示方式
|
||||
43552 透视表列设置实现列汇总百分比的显示方式
|
||||
43710 透视表列设置实现列引用字段的功能
|
||||
44135 在透视表前台新增详情展示
|
||||
44142 在图表前台新增详情展示
|
||||
44178 查看大屏时实现显示删除或草稿态图表和透视表的占位区域
|
||||
44179 修改图表前台展示页面表格间距
|
||||
43872 调整后台BI权限中的统计首页的权限
|
||||
44004 BI二级导航中新增模块的分割线
|
||||
44003 取消维护维度页面的标题
|
||||
44002 取消维护维度页面的返回按钮
|
||||
44001 在维护维度页面时显示BI的二级导航
|
||||
44000 取消维度导航中去维护的按钮
|
||||
43999 BI新增维度模块作为维护维度页面的入口
|
||||
43467 设计或删除被草稿态大屏引用的图表的提示与显示
|
||||
44134 优化流程向导组件的样式
|
||||
44121 修改透视表配置筛选器页面右侧窗格各组件间距
|
||||
44120 修改透视表配置筛选器页面的字色与字重
|
||||
44119 修改透视表准备发布页面右侧窗格背景色
|
||||
44118 修改透视表配置筛选器页面右侧窗格背景色
|
||||
44117 修改透视表设计透视表页面右侧窗格背景色
|
||||
44116 修改透视表设计透视表页面左侧窗格各组件间距
|
||||
43873 将后台权限中部分BI权限调整至项目度量分组
|
||||
44133 调整透视表设置值的显示方式时表头的命名规则
|
||||
44122 修改透视表配置筛选器页面左侧窗格各组件间距
|
||||
44126 修改图表配置筛选器页面右侧窗格背景色
|
||||
44125 修改透视表前台展示页面表格间距
|
||||
44124 修改透视表准备发布页面右侧窗格各组件间距
|
||||
44123 修改透视表准备发布页面左侧窗格各组件间距
|
||||
43464 设计或删除被草稿态大屏引用的透视表的提示与显示
|
||||
43466 设计或删除被已发布大屏引用的图表的提示与显示
|
||||
43467 设计或删除被草稿态大屏引用的图表的提示与显示
|
||||
43917 企业版BI增加改版弹窗
|
||||
43927 企业版BI改版弹窗的展示
|
||||
44135 在透视表前台新增详情展示
|
||||
44142 在图表前台新增详情展示
|
||||
44176 大屏中引用的透视表失效时以占位区域的方式展示
|
||||
44177 大屏中引用的图表失效时以占位区域的方式展示
|
||||
44178 查看大屏时实现显示删除或草稿态图表和透视表的占位区域
|
||||
44179 修改图表前台展示页面表格间距
|
||||
44121 修改透视表配置筛选器页面右侧窗格各组件间距
|
||||
44119 修改透视表准备发布页面右侧窗格背景色
|
||||
44115 修改透视表设计透视表页面右侧窗格各组件间距
|
||||
44077 大屏中引用透视表与切分列后的透视表保持一致
|
||||
43872 调整后台BI权限中的统计首页的权限
|
||||
44004 BI二级导航中新增模块的分割线
|
||||
44003 取消维护维度页面的标题
|
||||
44002 取消维护维度页面的返回按钮
|
||||
44000 取消维度导航中去维护的按钮
|
||||
43999 BI新增维度模块作为维护维度页面的入口
|
||||
43874 取消后台权限中BI模块的BI分组
|
||||
43873 将后台权限中部分BI权限调整至项目度量分组
|
||||
44139 大屏设计器实现选择固定尺寸的画布
|
||||
44133 调整透视表设置值的显示方式时表头的命名规则
|
||||
44131 修改图表配置筛选器页面右侧窗格各组件间距
|
||||
44130 修改图表准备发布页面左侧窗格各组件间距
|
||||
44129 修改图表配置筛选器页面左侧窗格各组件间距
|
||||
44128 修改图表设计图表页面右侧窗格各组件间距
|
||||
44127 修改图表设计图表页面左侧窗格各组件间距
|
||||
44126 修改图表配置筛选器页面右侧窗格背景色
|
||||
44124 修改透视表准备发布页面右侧窗格各组件间距
|
||||
44132 修改图表准备发布页面右侧窗格各组件间距
|
||||
44177 大屏中引用的图表失效时以占位区域的方式展示
|
||||
44176 大屏中引用的透视表失效时以占位区域的方式展示
|
||||
44138 缩小大屏设计器中组件缩略图的尺寸
|
||||
44363 透视表列设置实现计算后的值保留两位小数
|
||||
44384 统一图表、透视表设计器窗格标题的字号
|
||||
44139 大屏设计器实现选择固定尺寸的画布
|
||||
44115 修改透视表设计透视表页面右侧窗格各组件间距
|
||||
44448 BI新增内置效能管理维度和质量管理度
|
||||
44290 大屏设计器实现引用透视表的筛选器
|
||||
44291 大屏设计器实现引用图表的筛选器
|
||||
44293 查看大屏时显示大屏引用的透视表筛选器
|
||||
44294 查看大屏时显示大屏引用的图表筛选器
|
||||
44335 大屏设计器引用透视表、图表筛选器时的样式
|
||||
44344 大屏设计器引用透视表、图表筛选器时的显示规则
|
||||
44498 企业版BI内置各类维度
|
||||
44451 删除维度时增加提示
|
||||
44449 新增公司质量数据盘点大屏
|
||||
44450 新增年度完成项目过程数据大屏
|
||||
44311 调整BI展示窗格中筛选器查询按钮的位置
|
||||
44399 查询筛选器中日期选择控件实现设置日期变量参数
|
||||
44439 修改大屏设计器引用图表、透视表时的默认尺寸
|
||||
44181 优化透视表查询筛选器参数配置项的文案
|
||||
44658 透视表前台页面内置大屏中的透视表
|
||||
44182 优化透视表结果筛选器参数配置项的文案
|
||||
44659 图表前台页面内置大屏中的图表
|
||||
44183 优化图表结果筛选器参数配置项的文案
|
||||
43321 设计或删除被已发布大屏引用的透视表的提示与显示
|
||||
44137 调整透视表后台的查询筛选器参数配置项的文案
|
||||
44074 透视表设计时不能对同一个字段进行行分组
|
||||
42443 大屏设计图表配置窗格新增数据和小组件
|
||||
43326 优化流程向导组件的交互逻辑及样式
|
||||
42752 自定义水晶报表升级为bi透视表
|
||||
42751 透视表实现查询筛选器的参数配置
|
||||
42961 图表设计时实现导出功能
|
||||
42537 调整图表参数配置窗格样式
|
||||
42712 可视化仪表盘升级为bi大屏
|
||||
42709 可视化图表升级为bi图表
|
||||
41720 图表向导中的设计页面新增堆积条形图的参数配置
|
||||
42766 透视表设计时实现导出功能
|
||||
41719 图表向导中的设计页面新增堆积柱形图的参数配置
|
||||
41717 图表向导中的设计页面新增雷达图的参数配置
|
||||
42444 可视化数据集升级为bi数据表
|
||||
41716 图表向导中的设计页面新增簇状条形图的参数配置
|
||||
41715 图表向导中的设计页面新增折线图的参数配置
|
||||
41706 图表向导中的设计页面新增簇状柱形图的参数配置
|
||||
43568 新增年度完成项目数据盘点卡片
|
||||
43569 新增项目按期完成率、执行按期完成率、项目延期率、执行延期率的环形图
|
||||
43570 新增项目完成分布图
|
||||
43571 新增执行完成分布图
|
||||
43572 新增完成项目工期透视表
|
||||
43573 新增完成项目工时透视表
|
||||
43574 新增完成项目工期偏差率条形图
|
||||
43575 新增完成项目工时偏差率条形图
|
||||
43576 新增完成项目间单位时间交付需求规模数对比图
|
||||
43577 新增时间筛选器
|
||||
43580 新增年度完成项目过程数据大屏
|
||||
43631 新增质量数据概览卡片
|
||||
43632 新增用例覆盖率、用例密度、Bug密度和Bug修复率水球图
|
||||
43633 新增bug状态分布图
|
||||
43634 新增bug严重程度分布图
|
||||
43635 新增bug解决方案分布图
|
||||
43636 新增bug类型分布图
|
||||
43637 新增有效bug、bug总数与解决Bug数近30天统计柱形图
|
||||
43638 新增有效bug率年度趋势图
|
||||
43639 新增bug密度年度趋势图
|
||||
43640 新增1、2级bug年度统计堆积柱形图
|
||||
43641 新增产品缺陷数据汇总表
|
||||
43642 新增产品用例数量统计条形图
|
||||
43643 新增产品bug数量统计
|
||||
41593 修改设计、编辑基本信息、删除按钮的图标
|
||||
41592 设计透视表时准备发布页面新增透视表基础信息窗格
|
||||
41591 设计透视表时准备发布页面新增透视表展示窗格
|
||||
41590 设计透视表时新增准备发布页面
|
||||
41589 设计透视表时设计透视表页面新增基础参数设置
|
||||
41588 设计透视表时设计透视表页面新增透视表配置项窗格
|
||||
41587 设计透视表时设计透视表页面新增透视表展示窗格
|
||||
41586 设计图表时将sql查询存为中间表
|
||||
41584 设计透视表时新增设计透视表页面
|
||||
41583 建透视表时新增查询数据页面
|
||||
41582 建透视表页面新增流程向导
|
||||
41581 建透视表弹窗内容调整
|
||||
41579 图表向导中准备发布页面新增图表展示窗格
|
||||
41575 对创建图表弹窗进行提升
|
||||
41573 对中间表设计时的保存弹窗进行提升
|
||||
41572 对中间表设计时的sql查询器界面进行提升
|
||||
41564 创建中间表时调整创建页面顺序
|
||||
41559 bi二级菜单新增数据模块
|
||||
40441 图表向导中配置筛选器页面新增参数配置窗格
|
||||
40440 图表向导中配置筛选器页面新增图表展示窗格
|
||||
40438 设计图表时新增配置筛选器页面
|
||||
40426 图表向导中准备发布页面新增基础信息窗格
|
||||
40417 设计图表时新增准备发布页面
|
||||
40401 图表向导中的设计页面新增饼图的参数配置
|
||||
40390 图表向导中的设计页面新增图表配置项窗格
|
||||
40389 图表向导中的设计页面新增图表展示窗格
|
||||
40374 设计图表时新增设计图表页面
|
||||
40353 设计图表时新增查询数据页面
|
||||
40348 创建图表页面新增图表创建向导组件
|
||||
修复的Bug
|
||||
企业版:
|
||||
34063 透视表设计时进行了设置字段名,大屏中仍显示id
|
||||
33247 大屏组件图片设置有误
|
||||
34477 访问反馈视图时有SQL报错
|
||||
34474 访问办公视图有SQL报错
|
||||
34476 访问运维视图页面有SQL报错
|
||||
34339 任务的报表页面有SQL报错
|
||||
34479 新增工作流有SQL报错
|
||||
34342 导入任务时,页面无响应也无报错
|
||||
旗舰版:
|
||||
33023 反馈转风险类型待办页切换产品后保存时提示访问对象不存在
|
||||
开源版:
|
||||
30727 功能设置关闭敏捷项目的问题,地盘--待处理--问题中没有过滤掉相应数据
|
||||
31007 标题装饰元素保持一致
|
||||
31009 标题为:一级项目集数据概览
|
||||
31011 字体确认
|
||||
31015 标题修改:一级项目集需求完成率与Bug修复率
|
||||
31016 标题修改:公司一级项目集状态分布
|
||||
31022 标题样式不统一
|
||||
31027 修改大屏标题、子标题与内容之间的间距
|
||||
31028 此处饼图改为标准饼图
|
||||
31036 修改大屏首页卡片布局规则
|
||||
31097 公司数据盘点大屏中部门人员分布图中部门展示顺序与后台部门顺序不一致
|
||||
31101 项目集数据概览缺少执行数
|
||||
31143 公司年度新增数据概览大屏需求年度新增和完成趋势图中展示优化
|
||||
31178 年度总结大屏部门处默认显示成了“0”
|
||||
31181 年度总结大屏切换部门sql报错
|
||||
31184 年度总结大屏下基础数据中贡献数不正确
|
||||
31187 年度总结大屏迭代数据和产品数据显示不正确
|
||||
31196 年度总结每月Bug操作情况表没有按照年份筛选展示
|
||||
31237 切换年份页面有代码报错
|
||||
31238 公司数据盘点,页面右侧数据有遮挡
|
||||
31246 燃尽图大屏中横轴纵轴和悬浮窗中没有单位说明
|
||||
31279 公司数据盘点大屏缩略图中标题和页面中标题不一致
|
||||
31282 燃尽图大屏中燃尽图参考线一直是0,没有坡度
|
||||
31302 公司数据盘点大屏下公司角色只展示1个时角色名称显示遮挡
|
||||
31313 bug修复率的柱状图展示比例有误
|
||||
31314 关闭子项目集下的项目,没有统计到完成项目数中
|
||||
31402 迭代燃尽图大屏中会展示阶段的燃尽图建议优化文案
|
||||
31561 使用时长与天数之间的间距过大
|
||||
31720 公司年度汇总数据大屏,项目集年度完成数据概览,数据不对
|
||||
31818 自定义任务类型删除后,列表/详情页类型字段报错
|
||||
31970 迭代燃尽图大屏迭代周期范围调整
|
||||
32155 无迭代项目研发需求批量转任务页面,二级导航不显示了
|
||||
32237 大屏标题统一
|
||||
32238 修改图表标题
|
||||
32240 修改图表间距、内边距
|
||||
32241 增加子标题的背景
|
||||
32555 BI透视表下的产品透视表展示了影子产品
|
||||
32935 通用看板卡片填了工时则显示,不填后续修改卡片补充这2个字段则不显示
|
||||
33330 多分支/平台产品创建需求指派人,保存后指派给不生效
|
||||
33366 项目集-人员-投入人员剩余工时统计问题
|
||||
33554 瀑布项目阶段列表点击编辑阶段负责人不能带出
|
||||
33562 用例库中编辑用例清空用例内容
|
||||
34019 项目型项目在测试模块无法切换
|
||||
34020 一个执行关联多个产品计划,产品计划列表页面,所属执行不显示
|
||||
34169 发布关联版本时带过来的需求不会变成已发布
|
||||
34599 需求拆分任务时会把需求下已删除的附件带出来
|
||||
|
||||
2023-03-15 18.3
|
||||
完成的需求
|
||||
|
||||
@@ -921,6 +921,48 @@ $lang->cron->methodOrder[25] = 'toggle';
|
||||
$lang->cron->methodOrder[30] = 'delete';
|
||||
$lang->cron->methodOrder[35] = 'openProcess';
|
||||
|
||||
$lang->resource->contact = new stdclass();
|
||||
$lang->resource->programstakeholder = new stdclass();
|
||||
$lang->resource->researchplan = new stdclass();
|
||||
$lang->resource->workestimation = new stdclass();
|
||||
$lang->resource->gapanalysis = new stdclass();
|
||||
$lang->resource->executionview = new stdclass();
|
||||
$lang->resource->managespace = new stdclass();
|
||||
$lang->resource->systemteam = new stdclass();
|
||||
$lang->resource->systemschedule = new stdclass();
|
||||
$lang->resource->systemeffort = new stdclass();
|
||||
$lang->resource->systemdynamic = new stdclass();
|
||||
$lang->resource->systemcompany = new stdclass();
|
||||
$lang->resource->pipeline = new stdclass();
|
||||
$lang->resource->devopssetting = new stdclass();
|
||||
$lang->resource->featureswitch = new stdclass();
|
||||
$lang->resource->importdata = new stdclass();
|
||||
$lang->resource->systemsetting = new stdclass();
|
||||
$lang->resource->staffmanage = new stdclass();
|
||||
$lang->resource->modelconfig = new stdclass();
|
||||
$lang->resource->featureconfig = new stdclass();
|
||||
$lang->resource->doctemplate = new stdclass();
|
||||
$lang->resource->notifysetting = new stdclass();
|
||||
$lang->resource->bidesign = new stdclass();
|
||||
$lang->resource->personalsettings = new stdclass();
|
||||
$lang->resource->projectsettings = new stdclass();
|
||||
$lang->resource->dataaccess = new stdclass();
|
||||
$lang->resource->executiongantt = new stdclass();
|
||||
$lang->resource->executionkanban = new stdclass();
|
||||
$lang->resource->executionburn = new stdclass();
|
||||
$lang->resource->executioncfd = new stdclass();
|
||||
$lang->resource->executionstory = new stdclass();
|
||||
$lang->resource->executionqa = new stdclass();
|
||||
$lang->resource->executionsettings = new stdclass();
|
||||
$lang->resource->generalcomment = new stdclass();
|
||||
$lang->resource->generalping = new stdclass();
|
||||
$lang->resource->generaltemplate = new stdclass();
|
||||
$lang->resource->generaleffort = new stdclass();
|
||||
$lang->resource->productsettings = new stdclass();
|
||||
$lang->resource->projectreview = new stdclass();
|
||||
$lang->resource->projecttrack = new stdclass();
|
||||
$lang->resource->projectqa = new stdclass();
|
||||
|
||||
if($config->edition == 'biz' or $config->edition == 'max')
|
||||
{
|
||||
/* My module. */
|
||||
|
||||
@@ -25,7 +25,7 @@ public function getPairs($mode = '', $programID = 0, $append = '', $shadow = 0)
|
||||
->andWhere('t2.vision')->eq($this->config->vision)
|
||||
->fetchPairs('id', 'id');
|
||||
|
||||
$products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed')
|
||||
$products = $this->dao->select("*, IF(INSTR(' closed', status) < 2, 0, 1) AS isClosed")
|
||||
->from(TABLE_PRODUCT)
|
||||
->where('1 = 1')
|
||||
->beginIF(strpos($mode, 'all') === false)->andWhere('deleted')->eq(0)->fi()
|
||||
|
||||
@@ -1 +1 @@
|
||||
v7.1.0
|
||||
e46c36b1746f2bd7326146f634aee8963a19f8fa
|
||||
|
||||
@@ -801,7 +801,6 @@ class baseControl
|
||||
$moduleControlFile = $modulePath . 'control.php';
|
||||
$actionExtPath = $this->app->getModuleExtPath($appName, $moduleName, 'control');
|
||||
$file2Included = $moduleControlFile;
|
||||
$classNameToFetch = $moduleName;
|
||||
|
||||
if(!empty($actionExtPath))
|
||||
{
|
||||
@@ -857,11 +856,9 @@ class baseControl
|
||||
* Load the control file.
|
||||
*/
|
||||
if(!is_file($file2Included)) $this->app->triggerError("The control file $file2Included not found", __FILE__, __LINE__, $exit = true);
|
||||
if(!class_exists($classNameToFetch))
|
||||
{
|
||||
chdir(dirname($file2Included));
|
||||
helper::import($file2Included);
|
||||
}
|
||||
|
||||
chdir(dirname($file2Included));
|
||||
helper::import($file2Included);
|
||||
|
||||
/**
|
||||
* 设置调用的类名。
|
||||
|
||||
@@ -35,7 +35,7 @@ class control extends baseControl
|
||||
|
||||
$this->app->setOpenApp();
|
||||
|
||||
if(!isset($this->config->bizVersion)) return false;
|
||||
if($this->config->edition == 'open') return false;
|
||||
|
||||
/* Code for task #9224. Set requiredFields for workflow. */
|
||||
if($this->dbh and (defined('IN_USE') or (defined('RUN_MODE') and RUN_MODE == 'api')))
|
||||
@@ -425,7 +425,7 @@ class control extends baseControl
|
||||
*/
|
||||
public function buildOperateMenu(object $object, string $type = 'view')
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return false;
|
||||
if($this->config->edition == 'open') return false;
|
||||
|
||||
$moduleName = $this->moduleName;
|
||||
return $this->$moduleName->buildOperateMenu($object, $type);
|
||||
@@ -440,7 +440,7 @@ class control extends baseControl
|
||||
*/
|
||||
public function executeHooks(int $objectID)
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return false;
|
||||
if($this->config->edition == 'open') return false;
|
||||
|
||||
$moduleName = $this->moduleName;
|
||||
return $this->$moduleName->executeHooks($objectID);
|
||||
@@ -454,7 +454,7 @@ class control extends baseControl
|
||||
*/
|
||||
public function getFlowExportFields()
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return array();
|
||||
if($this->config->edition == 'open') return array();
|
||||
|
||||
$moduleName = $this->moduleName;
|
||||
return $this->$moduleName->getFlowExportFields();
|
||||
@@ -478,7 +478,7 @@ class control extends baseControl
|
||||
*/
|
||||
public function printExtendFields(object|string $object, string $type, string $extras = '', bool $print = true, string $moduleName = '', string $methodName = '')
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return false;
|
||||
if($this->config->edition == 'open') return false;
|
||||
|
||||
$moduleName = $moduleName ?: $this->app->getModuleName();
|
||||
$methodName = $methodName ?: $this->app->getMethodName();
|
||||
|
||||
@@ -99,7 +99,7 @@ class model extends baseModel
|
||||
if(empty($method)) $method = $methodName;
|
||||
|
||||
static $actions = array();
|
||||
if(isset($this->config->bizVersion))
|
||||
if($this->config->edition != 'open')
|
||||
{
|
||||
if(empty($actions[$moduleName]))
|
||||
{
|
||||
@@ -155,7 +155,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function buildFlowMenu($module, $data, $type = 'browse', $show = '')
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return '';
|
||||
if($this->config->edition == 'open') return '';
|
||||
|
||||
$moduleName = $module;
|
||||
if(str_contains($module, '.')) [$appName, $moduleName] = explode('.', $module);
|
||||
@@ -233,7 +233,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function processStatus($module, $record)
|
||||
{
|
||||
if(!isset($this->config->bizVersion) or empty($record->subStatus)) return zget($this->lang->$module->statusList, $record->status);
|
||||
if($this->config->edition == 'open' or empty($record->subStatus)) return zget($this->lang->$module->statusList, $record->status);
|
||||
|
||||
return $this->loadModel('workflowfield')->processSubStatus($module, $record);
|
||||
}
|
||||
@@ -247,7 +247,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function processExportData($data)
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return $data;
|
||||
if($this->config->edition == 'open') return $data;
|
||||
|
||||
return $this->loadModel('workflowfield')->processExportData($data);
|
||||
}
|
||||
@@ -261,7 +261,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function processExportOptions($data)
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return $data;
|
||||
if($this->config->edition == 'open') return $data;
|
||||
|
||||
return $this->loadModel('workflowfield')->processExportOptions($data);
|
||||
}
|
||||
@@ -275,7 +275,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function processImportData($data)
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return $data;
|
||||
if($this->config->edition == 'open') return $data;
|
||||
|
||||
return $this->loadModel('workflowfield')->processImportData($data);
|
||||
}
|
||||
@@ -288,7 +288,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function getFlowExtendFields()
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return array();
|
||||
if($this->config->edition == 'open') return array();
|
||||
|
||||
return $this->loadModel('flow')->getExtendFields($this->app->getModuleName(), $this->app->getMethodName());
|
||||
}
|
||||
@@ -301,7 +301,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function getFlowExportFields()
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return array();
|
||||
if($this->config->edition == 'open') return array();
|
||||
|
||||
return $this->loadModel('workflowfield')->getExportFields($this->app->getModuleName());
|
||||
}
|
||||
@@ -315,7 +315,7 @@ class model extends baseModel
|
||||
*/
|
||||
public function executeHooks(int $objectID)
|
||||
{
|
||||
if(!isset($this->config->bizVersion)) return false;
|
||||
if($this->config->edition == 'open') return false;
|
||||
|
||||
$moduleName = $this->app->getModuleName();
|
||||
$methodName = $this->app->getMethodName();
|
||||
|
||||
@@ -482,7 +482,7 @@ class router extends baseRouter
|
||||
if(empty($this->rawMethod)) $this->rawMethod = $this->methodName;
|
||||
|
||||
/* If is not a biz version or is in install mode or in in upgrade mode, call parent method. */
|
||||
if(!isset($this->config->bizVersion) or defined('IN_INSTALL') or defined('IN_UPGRADE')) return parent::setControlFile($exitIfNone);
|
||||
if($this->config->edition == 'open' or defined('IN_INSTALL') or defined('IN_UPGRADE')) return parent::setControlFile($exitIfNone);
|
||||
|
||||
/* Check if the requested module is defined in workflow. */
|
||||
$flow = $this->dbh->query("SELECT * FROM " . TABLE_WORKFLOW . " WHERE `module` = '$this->moduleName'")->fetch();
|
||||
|
||||
@@ -923,6 +923,7 @@ class baseDAO
|
||||
{
|
||||
$rows = $stmt->fetchAll();
|
||||
$result = array();
|
||||
if(!$rows) $rows = array();
|
||||
dao::$cache[$table][$key] = $rows;
|
||||
foreach($rows as $i => $row) $result[$i] = $this->getRow($row);
|
||||
return $result;
|
||||
|
||||
@@ -561,8 +561,8 @@ class baseHTML
|
||||
/* If the link of the referer is not the link of the current page or the link of the index, the cookie and gobackLink will be updated. */
|
||||
if(preg_match("/(?:m=|\/)([a-zA-Z0-9]+)(?:(&f=)|(-?))([a-zA-Z0-9]+)?(?:&|-|\.)?/", strtolower($refererLink), $matches))
|
||||
{
|
||||
if(!isset($matches[2])) $matches[2] = $config->default->method;
|
||||
if(!in_array($matches[1], array($config->default->module, 'search')) or !in_array($matches[2], array($config->default->method, 'buildquery')))
|
||||
if(!isset($matches[4])) $matches[4] = $config->default->method;
|
||||
if(!in_array($matches[1], array($config->default->module, 'search')) or !in_array($matches[4], array($config->default->method, 'buildquery')))
|
||||
{
|
||||
if($matches[1] != 'index' and ($matches[1] != $currentModule or $matches[4] != $currentMethod))
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@ class dbh
|
||||
*/
|
||||
public function __construct($config, $setSchema = true)
|
||||
{
|
||||
$dsn = "{$config->driver}:host={$config->host}:{$config->port}";
|
||||
$dsn = "{$config->driver}:host={$config->host};port={$config->port}";
|
||||
if($setSchema) $dsn .= ";dbname={$config->name}";
|
||||
|
||||
$pdo = new PDO($dsn, $config->user, $config->password);
|
||||
|
||||
@@ -114,7 +114,7 @@ class form extends baseFixer
|
||||
{
|
||||
if(!isset($this->errors[$field])) $this->errors[$field] = array();
|
||||
$fieldName = isset($app->lang->{$app->rawModule}->$field) ? $app->lang->{$app->rawModule}->$field : $field;
|
||||
$this->errors[$field][] = sprintf($lang->error->notempty, $fieldName);
|
||||
$this->errors[$field][] = sprintf($app->lang->error->notempty, $fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1980,10 +1980,7 @@ class actionModel extends model
|
||||
if($case->scene)
|
||||
{
|
||||
$scene = $this->dao->select('*')->from(VIEW_SCENECASE)->where('id')->eq($case->scene)->fetch();
|
||||
if($scene->deleted)
|
||||
{
|
||||
return print(js::error($this->lang->action->refusecase));
|
||||
}
|
||||
if($scene->deleted) return print(js::error($this->lang->action->refusecase));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1997,6 +1994,12 @@ class actionModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
if($action->objectType == 'doc')
|
||||
{
|
||||
$docContent = $this->dao->select('*')->from(TABLE_DOCCONTENT)->where('doc')->eq($action->objectID)->orderBy('version desc')->limit(1)->fetch();
|
||||
if($docContent->files) $this->dao->update(TABLE_FILE)->set('deleted')->eq('0')->where('id')->in($docContent->files)->exec();
|
||||
}
|
||||
|
||||
/* Update deleted field in object table. */
|
||||
$table = $this->config->objectTables[$action->objectType];
|
||||
$this->dao->update($table)->set('deleted')->eq(0)->where('id')->eq($action->objectID)->exec();
|
||||
|
||||
@@ -478,7 +478,7 @@ class admin extends control
|
||||
$response['thisTable'] = '';
|
||||
$response['nextTable'] = '';
|
||||
|
||||
$tableEngines = $this->loadModel('misc')->getTableEngines();
|
||||
$tableEngines = $this->dao->getTableEngines();
|
||||
|
||||
$thisTable = '';
|
||||
$nextTable = '';
|
||||
|
||||
+31
-11
@@ -52,6 +52,15 @@ class api extends control
|
||||
$objectType = $this->objectType;
|
||||
$objectID = $this->objectID;
|
||||
$isFirstLoad = $libID ? false : true;
|
||||
if($libID)
|
||||
{
|
||||
$lib = $this->doc->getLibById($libID);
|
||||
if($objectType == 'nolink' and !$objectID and ($lib->product or $lib->project))
|
||||
{
|
||||
$objectType = $lib->product ? 'product' : 'project';
|
||||
$objectID = $lib->product ? $lib->product : $lib->project;
|
||||
}
|
||||
}
|
||||
|
||||
if($release)
|
||||
{
|
||||
@@ -158,7 +167,7 @@ class api extends control
|
||||
if(!strpos($this->server->http_referer, 'space') and !strpos($this->server->http_referer, 'api')) setCookie("docSpaceParam", '', $this->config->cookieLife, $this->config->webRoot, '', false, true);
|
||||
|
||||
/* Get all api doc libraries. */
|
||||
$libs = $this->doc->getApiLibs($libID);
|
||||
$libs = $this->doc->getApiLibs($libID, $this->objectType, $this->objectID);
|
||||
$api = $this->api->getLibById($apiID, $version, $release);
|
||||
if($api)
|
||||
{
|
||||
@@ -174,7 +183,7 @@ class api extends control
|
||||
}
|
||||
|
||||
/* Crumbs links array. */
|
||||
$lib = zget($libs, $libID);
|
||||
$lib = zget($libs, $libID);
|
||||
$type = $lib->product ? 'product' : ($lib->project ? 'project' : 'unlink');
|
||||
|
||||
$methodName = $type != 'unlink' ? $type . 'Space' : 'index';
|
||||
@@ -609,10 +618,11 @@ class api extends control
|
||||
*
|
||||
* @param int $libID
|
||||
* @param int $moduleID
|
||||
* @param string $space api|project|product
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create($libID, $moduleID = 0)
|
||||
public function create($libID, $moduleID = 0, $space = '')
|
||||
{
|
||||
if(!empty($_POST))
|
||||
{
|
||||
@@ -621,14 +631,14 @@ class api extends control
|
||||
|
||||
$this->action->create('api', $api->id, 'Created');
|
||||
|
||||
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => 'true', 'callback' => "parentLocate({$api->id})"));
|
||||
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => 'true', 'callback' => "parentLocate({$api->id}, {$api->lib}, {$api->module})"));
|
||||
return $this->sendSuccess(array('locate' => helper::createLink('api', 'index', "libID={$api->lib}&moduleID={$api->module}&apiID={$api->id}")));
|
||||
}
|
||||
|
||||
$libs = $this->doc->getLibs('api', '', $libID);
|
||||
if(!$libID and !empty($libs)) $libID = key($libs);
|
||||
|
||||
$this->setMenu($libID);
|
||||
$this->setMenu($libID, $space);
|
||||
|
||||
$lib = $this->doc->getLibByID($libID);
|
||||
$libName = isset($lib->name) ? $lib->name . $this->lang->colon : '';
|
||||
@@ -748,12 +758,14 @@ class api extends control
|
||||
/**
|
||||
* Set api menu by method name.
|
||||
*
|
||||
* @param int $libID
|
||||
* @param int $libID
|
||||
* @param string $space |null|api|project|product
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
private function setMenu($libID = 0)
|
||||
private function setMenu($libID = 0, $space = '')
|
||||
{
|
||||
if($space and strpos('|api|project|product|', "|{$space}|") === false) $space = '';
|
||||
common::setMenuVars('doc', '');
|
||||
|
||||
$lib = $this->loadModel('doc')->getLibByID($libID);
|
||||
@@ -766,14 +778,22 @@ class api extends control
|
||||
$this->loadModel('project')->setMenu($lib->project);
|
||||
}
|
||||
|
||||
if(in_array($this->session->spaceType, array('product', 'project')))
|
||||
$spaceType = $this->session->spaceType;
|
||||
if(empty($spaceType)) $spaceType = 'api';
|
||||
if($space)
|
||||
{
|
||||
$this->lang->doc->menu->api['exclude'] = 'api-' . $this->app->rawMethod;
|
||||
$this->lang->doc->menu->{$this->session->spaceType}['subModule'] = 'api';
|
||||
$spaceType = $space;
|
||||
$this->session->set('spaceType', $space, 'doc');
|
||||
}
|
||||
|
||||
if(in_array($spaceType, array('product', 'project')))
|
||||
{
|
||||
$this->lang->doc->menu->api['exclude'] = 'api-' . $this->app->rawMethod . ',' . $this->app->rawMethod;
|
||||
$this->lang->doc->menu->{$spaceType}['subModule'] = 'api';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->lang->doc->menu->{$this->session->spaceType}['alias'] .= ',' . $this->app->rawMethod;
|
||||
$this->lang->doc->menu->{$spaceType}['alias'] .= ',' . $this->app->rawMethod;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,9 +92,11 @@ var app = new Vue({
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function parentLocate(apiID)
|
||||
function parentLocate(apiID, libID, moduelID)
|
||||
{
|
||||
libID = libID ? libID : 0;
|
||||
moduelID = moduelID ? moduelID : 0;
|
||||
config.onlybody = 'no';
|
||||
var link = createLink('api', 'index', 'libID=0&moduleID=0&apiID=' + apiID) + '#app=doc';
|
||||
var link = createLink('api', 'index', 'libID=' + libID + '&moduleID=' + moduelID + '&apiID=' + apiID) + '#app=doc';
|
||||
window.parent.$.apps.open(link);
|
||||
}
|
||||
|
||||
@@ -781,8 +781,6 @@ class apiModel extends model
|
||||
$lib->baseUrl = $baseUrl;
|
||||
$lib->acl = 'open';
|
||||
$lib->users = ',' . $currentAccount . ',';
|
||||
$lib->addedBy = $currentAccount;
|
||||
$lib->addedDate = helper::now();
|
||||
$this->dao->insert(TABLE_DOCLIB)->data($lib)->autoCheck()
|
||||
->batchCheck($this->config->api->createlib->requiredFields, 'notempty')
|
||||
->check('name', 'unique', "`type` = 'api'")
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<?php foreach($apiList as $api):?>
|
||||
<li class="list-group-item">
|
||||
<div class="heading <?php echo $api->method;?>">
|
||||
<a href="<?php echo helper::createLink('api', 'index', "libID={$api->lib}&moduleID=0&apiID={$api->id}&version=0&release=$release");?>" data-app="<?php echo $app->tab;?>">
|
||||
<a href="<?php echo helper::createLink('api', 'index', "libID={$api->lib}&moduleID=0&apiID={$api->id}&version=0");?>" data-app="<?php echo $app->tab;?>">
|
||||
<span class="label label-primary"><?php echo $api->method;?></span>
|
||||
<span class="path" title="<?php echo $api->path;?>"><?php echo $api->path;?></span>
|
||||
<span class="desc" title="<?php echo $api->title;?>"><?php echo $api->title;?></span>
|
||||
|
||||
+47
-65
@@ -26,6 +26,7 @@ class block extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建区块
|
||||
* Create a block under a dashboard.
|
||||
*
|
||||
* @param string $dashboard
|
||||
@@ -43,7 +44,7 @@ class block extends control
|
||||
$formData->account = $this->app->user->account;
|
||||
$formData->vision = $this->config->vision;
|
||||
$formData->order = $this->block->getMaxOrderByDashboard($dashboard) + 1;
|
||||
$formData->params = helper::jsonEncode($formData->params);
|
||||
$formData->params = json_encode($formData->params);
|
||||
|
||||
$this->block->create($formData);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
@@ -55,12 +56,13 @@ class block extends control
|
||||
$this->view->module = $module;
|
||||
$this->view->code = $code;
|
||||
$this->view->modules = $this->blockZen->getAvailableModules($dashboard);
|
||||
$this->view->codes = $this->blockZen->getAvailableBlocks($dashboard, $module);
|
||||
$this->view->codes = $this->blockZen->getAvailableCodes($dashboard, $module);
|
||||
$this->view->params = $this->blockZen->getAvailableParams($dashboard, $module, $code);
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑区块
|
||||
* Update a block.
|
||||
*
|
||||
* @param string $dashboard
|
||||
@@ -257,59 +259,48 @@ class block extends control
|
||||
|
||||
/**
|
||||
* Print block.
|
||||
* 输出区块
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $blockID
|
||||
* @access public
|
||||
* @return void
|
||||
* @return void|false
|
||||
*/
|
||||
public function printBlock($id, $module = 'my')
|
||||
public function printBlock($blockID)
|
||||
{
|
||||
$block = $this->block->getByID((int)$id);
|
||||
$blockID = (int)$blockID;
|
||||
$block = $this->block->getByID($blockID);
|
||||
|
||||
if(empty($block)) return false;
|
||||
|
||||
$html = '';
|
||||
if($block->code == 'html')
|
||||
switch($block->code)
|
||||
{
|
||||
if (empty($block->params->html))
|
||||
{
|
||||
$html = "<div class='empty-tip'>" . $this->lang->block->emptyTip . "</div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$html = "<div class='panel-body'><div class='article-content'>" . $block->params->html . '</div></div>';
|
||||
}
|
||||
}
|
||||
elseif($block->code == 'dynamic')
|
||||
{
|
||||
$html = $this->fetch('block', 'dynamic');
|
||||
}
|
||||
elseif($block->code == 'guide')
|
||||
{
|
||||
$html = $this->fetch('block', 'guide', "blockID=$block->id");
|
||||
}
|
||||
elseif($block->code == 'assigntome')
|
||||
{
|
||||
$this->get->set('param', base64_encode(json_encode($block->params)));
|
||||
$html = $this->fetch('block', 'printAssignToMeBlock', 'longBlock=' . $this->block->isLongBlock($block));
|
||||
}
|
||||
elseif($block->code == 'welcome')
|
||||
{
|
||||
$html = $this->fetch('block', 'welcome', "blockID=$block->id");
|
||||
}
|
||||
elseif($block->code == 'contribute')
|
||||
{
|
||||
$html = $this->fetch('block', 'contribute');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->get->set('mode', 'getblockdata');
|
||||
$this->get->set('blockTitle', $block->title);
|
||||
$this->get->set('module', $block->module);
|
||||
$this->get->set('source', $block->source);
|
||||
$this->get->set('blockid', $block->code);
|
||||
$this->get->set('param', base64_encode(json_encode($block->params)));
|
||||
$html = $this->fetch('block', 'main', "module={$block->source}&id=$id");
|
||||
case 'html':
|
||||
$html = $this->blockZen->generateHtmlBlock($block);
|
||||
break;
|
||||
|
||||
case 'dynamic':
|
||||
$html = $this->fetch('block', 'dynamic');
|
||||
break;
|
||||
|
||||
case 'guide':
|
||||
$html = $this->fetch('block', 'guide', "blockID=$blockID");
|
||||
break;
|
||||
|
||||
case 'assigntome':
|
||||
$html = $this->blockZen->generateAssignToMeBlock($block);
|
||||
break;
|
||||
|
||||
case 'welcome':
|
||||
$html = $this->fetch('block', 'welcome', "blockID=$blockID");
|
||||
break;
|
||||
|
||||
case 'contribute':
|
||||
$html = $this->fetch('block', 'contribute');
|
||||
break;
|
||||
|
||||
default:
|
||||
$html = $this->blockZen->generateDefaultBlockBySource($block);
|
||||
break;
|
||||
}
|
||||
echo $html;
|
||||
}
|
||||
@@ -437,7 +428,7 @@ class block extends control
|
||||
public function printTodoBlock()
|
||||
{
|
||||
$limit = ($this->viewType == 'json' or !isset($this->params->count)) ? 0 : (int)$this->params->count;
|
||||
$todos = $this->loadModel('todo')->getList('all', $this->app->user->account, 'wait, doing', $limit, $pager = null, $orderBy = 'date, begin');
|
||||
$todos = $this->loadModel('todo')->getList('all', $this->app->user->account, 'wait, doing', $limit, null, 'date, begin');
|
||||
$uri = $this->createLink('my', 'index');
|
||||
|
||||
$this->session->set('todoList', $uri, 'my');
|
||||
@@ -446,16 +437,7 @@ class block extends control
|
||||
$this->session->set('storyList', $uri, 'product');
|
||||
$this->session->set('testtaskList', $uri, 'qa');
|
||||
|
||||
$tasks = $this->loadModel('task')->getUserSuspendedTasks($this->app->user->account);
|
||||
foreach($todos as $key => $todo)
|
||||
{
|
||||
if($todo->date == '2030-01-01')
|
||||
{
|
||||
unset($todos[$key]);
|
||||
continue;
|
||||
}
|
||||
if($todo->type == 'task' and isset($tasks[$todo->idvalue])) unset($todos[$key]);
|
||||
}
|
||||
$todos = $this->blockZen->unsetTodos($todos);
|
||||
|
||||
$this->view->todos = $todos;
|
||||
}
|
||||
@@ -580,7 +562,7 @@ class block extends control
|
||||
$this->session->set('storyList', $this->createLink('my', 'index'), 'product');
|
||||
if(preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
|
||||
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$count = isset($this->params->count) ? (int)$this->params->count : 0;
|
||||
$pager = pager::init(0, $count , 1);
|
||||
$type = isset($this->params->type) ? $this->params->type : 'assignedTo';
|
||||
@@ -686,7 +668,7 @@ class block extends control
|
||||
*/
|
||||
public function printProductBlock()
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
if(!empty($this->params->type) and preg_match('/[^a-zA-Z0-9_]/', $this->params->type)) return;
|
||||
$count = isset($this->params->count) ? (int)$this->params->count : 0;
|
||||
$type = isset($this->params->type) ? $this->params->type : '';
|
||||
@@ -786,7 +768,7 @@ class block extends control
|
||||
{
|
||||
if(in_array($project->model, array('scrum', 'kanban', 'agileplus')))
|
||||
{
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = pager::init(0, 3, 1);
|
||||
$project->progress = $project->allStories == 0 ? 0 : round($project->doneStories / $project->allStories, 3) * 100;
|
||||
$project->executions = $this->execution->getStatData($projectID, 'all', 0, 0, false, '', 'id_desc', $pager);
|
||||
@@ -1235,7 +1217,7 @@ class block extends control
|
||||
$count = isset($this->params->count) ? (int)$this->params->count : 15;
|
||||
$type = isset($this->params->type) ? $this->params->type : 'undone';
|
||||
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = pager::init(0, $count, 1);
|
||||
$this->loadModel('execution');
|
||||
$this->view->executionStats = !defined('TUTORIAL') ? $this->execution->getStatData($this->session->project, $type, 0, 0, false, '', 'id_desc', $pager) : array($this->loadModel('tutorial')->getExecution());
|
||||
@@ -1859,7 +1841,7 @@ class block extends control
|
||||
public function printDocDynamicBlock()
|
||||
{
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = new pager(0, 30, 1);
|
||||
|
||||
$this->view->actions = $this->loadModel('doc')->getDynamic($pager);
|
||||
@@ -1925,7 +1907,7 @@ class block extends control
|
||||
public function printDocViewListBlock()
|
||||
{
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = new pager(0, 6, 1);
|
||||
|
||||
$this->view->docList = $this->loadModel('doc')->getDocsByBrowseType('all', 0, 0,'views_desc', $pager);
|
||||
@@ -1940,7 +1922,7 @@ class block extends control
|
||||
public function printDocCollectListBlock()
|
||||
{
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$this->app->loadClass('pager', true);
|
||||
$pager = new pager(0, 6, 1);
|
||||
|
||||
$this->view->docList = $this->loadModel('doc')->getDocsByBrowseType('all', 0, 0, 'collects_desc', $pager);
|
||||
|
||||
@@ -3,32 +3,40 @@ function getForm(event)
|
||||
const field = $(event.target).attr('id');
|
||||
const module = $('#module').val();
|
||||
const code = field == 'module' ? '' : $('#code').val();
|
||||
const url = $.createLink('block', 'create', 'dashboard='+ dashboard +'&module=' + module + '&code=' + (code ? code : ''));
|
||||
const url = $.createLink('block', 'create', 'dashboard=' + dashboard + '&module=' + module + '&code=' + (code ? code : ''));
|
||||
loadPage(url, '#codesRow, #paramsRow');
|
||||
}
|
||||
|
||||
function onParamsTypeChange(event)
|
||||
/**
|
||||
* Get block title.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function onParamsTypeChange()
|
||||
{
|
||||
const lang = config.clientLang;
|
||||
const $code = document.querySelector('#code');
|
||||
const $code = $('#code')[0];
|
||||
|
||||
/* 在项目仪表盘创建的待测版本区块时,直接取类型名称为该区块的标题。*/
|
||||
/* When creating a test version block in the project dashboard, directly take the name of the block of type.*/
|
||||
if($('#module').val() == 'scrumtest' && $('#paramstype').val() != 'all')
|
||||
{
|
||||
$('#title').val($code.options[$code.selectedIndex].text);
|
||||
return;
|
||||
}
|
||||
|
||||
const $paramstype = $('#paramstype')[0];
|
||||
let blockTitle = '';
|
||||
|
||||
/* Chinese attributives come first, while other language items have attributives placed after. */
|
||||
if(lang.indexOf('zh') >= 0)
|
||||
{
|
||||
blockTitle = $paramstype.options[$paramstype.selectedIndex].text + of + $code.options[$code.selectedIndex].text;
|
||||
}
|
||||
else
|
||||
{
|
||||
const $paramstype = document.querySelector('#paramstype');
|
||||
|
||||
if(lang.indexOf('zh') >= 0)
|
||||
{
|
||||
const blockTitle = $paramstype.options[$paramstype.selectedIndex].text + of + $code.options[$code.selectedIndex].text;
|
||||
}
|
||||
else
|
||||
{
|
||||
const blockTitle = $code.options[$code.selectedIndex].text + of + $paramstype.options[$paramstype.selectedIndex].text;
|
||||
}
|
||||
|
||||
$('#title').val(blockTitle);
|
||||
blockTitle = $code.options[$code.selectedIndex].text + of + $paramstype.options[$paramstype.selectedIndex].text;
|
||||
}
|
||||
|
||||
$('#title').val(blockTitle);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ cid=39
|
||||
- 执行block模块的getByID方法,参数是$newBlockID
|
||||
- 属性account @admin
|
||||
- 属性vision @rnd
|
||||
- 属性module @my
|
||||
- 属性dashboard @my
|
||||
- 属性title @区块123
|
||||
- 属性source @my
|
||||
- 属性block @bug
|
||||
@@ -45,21 +45,21 @@ $tester->loadModel('block');
|
||||
initData();
|
||||
|
||||
$block = new stdclass();
|
||||
$block->account = 'admin';
|
||||
$block->vision = 'rnd';
|
||||
$block->module = 'my';
|
||||
$block->title = '区块123';
|
||||
$block->order = '5';
|
||||
$block->account = 'admin';
|
||||
$block->vision = 'rnd';
|
||||
$block->dashboard = 'my';
|
||||
$block->title = '区块123';
|
||||
$block->order = '5';
|
||||
|
||||
$accoutTooLangBlock = new stdclass();
|
||||
$accoutTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
|
||||
$accoutTooLangBlock->vision = 'rnd';
|
||||
$accoutTooLangBlock->module = 'my';
|
||||
$accoutTooLangBlock->title = 'long account';
|
||||
$accoutTooLangBlock->order = '5';
|
||||
$accoutTooLangBlock->account = 'adminadminadminadminadminadminadminadmin1';
|
||||
$accoutTooLangBlock->vision = 'rnd';
|
||||
$accoutTooLangBlock->dashboard = 'my';
|
||||
$accoutTooLangBlock->title = 'long account';
|
||||
$accoutTooLangBlock->order = '5';
|
||||
|
||||
$blockTest = new blockTest();
|
||||
$newBlockID = $blockTest->createTest($block);
|
||||
|
||||
r($tester->block->getByID($newBlockID)) && p('account,vision,module,title,order') && e('admin,rnd,my,区块123,5'); // 测试获取正常的block的内容
|
||||
r($tester->block->getByID($newBlockID)) && p('account,vision,dashboard,title,order') && e('admin,rnd,my,区块123,5'); // 测试获取正常的block的内容
|
||||
r($blockTest->createTest($accoutTooLangBlock)) && p('account:0') && e('『所属用户』长度应当不超过『30』,且大于『0』。'); // 测试account 字段字符超出长度
|
||||
|
||||
@@ -19,6 +19,16 @@ $paramsRows = array();
|
||||
$showModules = ($dashboard == 'my' and $modules);
|
||||
$showCodes = (($showModules and $module and $codes) or $dashboard != 'my');
|
||||
|
||||
if($module == 'scrumtest' && $code != 'all')
|
||||
{
|
||||
$blockTitle = zget($codes, $code);
|
||||
}
|
||||
else
|
||||
{
|
||||
$typeOptions = isset($params['type']['options']) ? $params['type']['options'] : array();
|
||||
$blockTitle = (count($typeOptions) ? $typeOptions[array_keys($typeOptions)[0]] . $lang->block->of : '') . zget($codes, $code);
|
||||
}
|
||||
|
||||
foreach($params as $key => $row)
|
||||
{
|
||||
$paramsRows[] = formGroup
|
||||
@@ -32,7 +42,7 @@ foreach($params as $key => $row)
|
||||
'id' => "params$key",
|
||||
'type' => $row['control'],
|
||||
'items' => isset($row['options']) ? $row['options'] : null
|
||||
))
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,7 +61,7 @@ form
|
||||
(
|
||||
'type' => 'select',
|
||||
'items' => $modules
|
||||
) : 'input')
|
||||
) : 'input')
|
||||
),
|
||||
div
|
||||
(
|
||||
@@ -79,9 +89,9 @@ form
|
||||
(
|
||||
set::label($lang->block->name),
|
||||
set::name('title'),
|
||||
set::value(zget($codes, $code)),
|
||||
set::value($blockTitle),
|
||||
set::class('form-row'),
|
||||
set::control('input')
|
||||
set::control('input')
|
||||
),
|
||||
$paramsRows,
|
||||
formGroup
|
||||
@@ -93,7 +103,7 @@ form
|
||||
(
|
||||
'type' => 'select',
|
||||
'items' => $lang->block->gridOptions
|
||||
))
|
||||
))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -28,10 +28,7 @@ dtable
|
||||
set::width('100%'),
|
||||
set::height('auto'),
|
||||
set::cols(array_values($config->block->dtable->project->fieldList)),
|
||||
set::data(array_values($projects)),
|
||||
set::footPager(usePager()),
|
||||
set::footer(array('flex', 'pager'))
|
||||
set::data(array_values($projects))
|
||||
);
|
||||
|
||||
|
||||
render();
|
||||
|
||||
@@ -61,6 +61,8 @@ html[lang="de"] .block-productdoc .c-user{width: 105px;}
|
||||
.block-productdoc .table .c-title > .draft {background-color:rgba(129, 102, 238, 0.12); color:#8166EE;}
|
||||
</style>
|
||||
<?php $blockNavId = 'nav-' . uniqid(); ?>
|
||||
<?php js::set('emptyProducts', empty($products));?>
|
||||
<?php js::set('emptyInvolveds', empty($involveds));?>
|
||||
<script>
|
||||
$(function()
|
||||
{
|
||||
@@ -90,6 +92,18 @@ function switch<?php echo "block{$block->id}";?>Product(obj)
|
||||
|
||||
function change<?php echo "block{$block->id}";?>ProductType(type)
|
||||
{
|
||||
var hiddenData = type == 'all' ? emptyProducts : emptyInvolveds;
|
||||
if(hiddenData)
|
||||
{
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> .dataBlock').addClass('hidden');
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').removeClass('hidden');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> .dataBlock').removeClass('hidden');
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').addClass('hidden');
|
||||
}
|
||||
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> .nav.products').toggleClass('hidden', type != 'all');
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> .nav.involveds').toggleClass('hidden', type != 'involved');
|
||||
$('.block-productdoc<?php echo "#block{$block->id}";?> #productType .btn').html($('.block-productdoc<?php echo "#block{$block->id}";?> #productType [data-type=' + type + ']').html() + " <span class='caret'></span>");
|
||||
@@ -112,14 +126,14 @@ function change<?php echo "block{$block->id}";?>ProductType(type)
|
||||
<li><a href="javascript:change<?php echo "block{$block->id}";?>ProductType('all')" data-type='all'><?php echo $lang->product->all;?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php $hiddenBlock = empty($involveds) ? 'hidden' : '';?>
|
||||
<?php $hiddenEmpty = empty($involveds) ? '' : 'hidden';?>
|
||||
<div class="panel-body">
|
||||
<div class="table-row block-statistic">
|
||||
<?php if(empty($products) and empty($involveds)):?>
|
||||
<div class="table-empty-tip">
|
||||
<div class="table-empty-tip <?php echo $hiddenEmpty;?>">
|
||||
<p><span class="text-muted"><?php echo $lang->block->emptyTip;?></span></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="col col-nav">
|
||||
<div class="col col-nav dataBlock <?php echo $hiddenBlock;?>">
|
||||
<ul class="nav nav-stacked nav-secondary scrollbar-hover involveds">
|
||||
<li class='switch-icon prev'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Product(this)'><i class='icon icon-arrow-left'></i></a></li>
|
||||
<?php $selected = key($involveds);?>
|
||||
@@ -142,7 +156,7 @@ function change<?php echo "block{$block->id}";?>ProductType(type)
|
||||
<li class='switch-icon next'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Product(this)'><i class='icon icon-arrow-right'></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col tab-content">
|
||||
<div class="col tab-content dataBlock <?php echo $hiddenBlock;?>">
|
||||
<?php foreach($products as $product):?>
|
||||
<div class="tab-pane fade<?php if($product->id == $selected) echo ' active in';?>" id='<?php echo "tab3{$blockNavId}Content{$product->id}";?>'>
|
||||
<?php if(isset($docGroup[$product->id])):?>
|
||||
@@ -190,6 +204,5 @@ function change<?php echo "block{$block->id}";?>ProductType(type)
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -60,8 +60,10 @@ html[lang="de"] .block-projectdoc .c-user{width: 105px;}
|
||||
.block-projectdoc .table .c-title[data-status=draft] > .doc-title {max-width: calc(100% - 35px);}
|
||||
.block-projectdoc .table .c-title > .draft {background-color:rgba(129, 102, 238, 0.12); color:#8166EE;}
|
||||
</style>
|
||||
<?php $blockNavId = 'nav-' . uniqid();?>
|
||||
<?php js::set('emptyProjects', empty($projects));?>
|
||||
<?php js::set('emptyInvolveds', empty($involveds));?>
|
||||
<script>
|
||||
<?php $blockNavId = 'nav-' . uniqid(); ?>
|
||||
$(function()
|
||||
{
|
||||
if($('.block-projectdoc<?php echo "#block{$block->id}";?> #projectType').length > 1);
|
||||
@@ -90,6 +92,18 @@ function switch<?php echo "block{$block->id}";?>Project(obj)
|
||||
|
||||
function change<?php echo "block{$block->id}";?>ProjectType(type)
|
||||
{
|
||||
var hiddenData = type == 'all' ? emptyProjects : emptyInvolveds;
|
||||
if(hiddenData)
|
||||
{
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> .dataBlock').addClass('hidden');
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').removeClass('hidden');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> .dataBlock').removeClass('hidden');
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> .block-statistic > .table-empty-tip').addClass('hidden');
|
||||
}
|
||||
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> .nav.projects').toggleClass('hidden', type != 'all');
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> .nav.involveds').toggleClass('hidden', type != 'involved');
|
||||
$('.block-projectdoc<?php echo "#block{$block->id}";?> #projectType .btn').html($('.block-projectdoc<?php echo "#block{$block->id}";?> #projectType [data-type=' + type + ']').html() + " <span class='caret'></span>");
|
||||
@@ -112,14 +126,14 @@ function change<?php echo "block{$block->id}";?>ProjectType(type)
|
||||
<li><a href="javascript:change<?php echo "block{$block->id}";?>ProjectType('all')" data-type='all'><?php echo $lang->project->all;?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php $hiddenBlock = empty($involveds) ? 'hidden' : '';?>
|
||||
<?php $hiddenEmpty = empty($involveds) ? '' : 'hidden';?>
|
||||
<div class="panel-body">
|
||||
<div class="table-row block-statistic">
|
||||
<?php if(empty($projects) and empty($involveds)):?>
|
||||
<div class="table-empty-tip">
|
||||
<div class="table-empty-tip <?php echo $hiddenEmpty;?>">
|
||||
<p><span class="text-muted"><?php echo $lang->block->emptyTip;?></span></p>
|
||||
</div>
|
||||
<?php else:?>
|
||||
<div class="col col-nav">
|
||||
<div class="col col-nav dataBlock <?php echo $hiddenBlock;?>">
|
||||
<ul class="nav nav-stacked nav-secondary scrollbar-hover involveds">
|
||||
<li class='switch-icon prev'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Project(this)'><i class='icon icon-arrow-left'></i></a></li>
|
||||
<?php $selected = key($involveds);?>
|
||||
@@ -142,7 +156,7 @@ function change<?php echo "block{$block->id}";?>ProjectType(type)
|
||||
<li class='switch-icon next'><a href='###' onclick='switch<?php echo "block{$block->id}";?>Project(this)'><i class='icon icon-arrow-right'></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col tab-content">
|
||||
<div class="col tab-content dataBlock <?php echo $hiddenBlock;?>">
|
||||
<?php foreach($projects as $project):?>
|
||||
<div class="tab-pane fade<?php if($project->id == $selected) echo ' active in';?>" id='<?php echo "tab3{$blockNavId}Content{$project->id}";?>'>
|
||||
<?php if(isset($docGroup[$project->id])):?>
|
||||
@@ -190,6 +204,5 @@ function change<?php echo "block{$block->id}";?>ProjectType(type)
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+73
-3
@@ -4,14 +4,14 @@ class blockZen extends block
|
||||
/**
|
||||
* 添加或编辑区块时获取可使用的模块选项
|
||||
* Get module options when adding or editing blocks.
|
||||
*
|
||||
*
|
||||
* @param string $dashboard
|
||||
* @access protected
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getAvailableModules(string $dashboard): array
|
||||
{
|
||||
if($dashboard != 'my') return array();
|
||||
if($dashboard != 'my') return array();
|
||||
|
||||
$modules = $this->lang->block->moduleList;
|
||||
unset($modules['doc']);
|
||||
@@ -59,7 +59,7 @@ class blockZen extends block
|
||||
* @access protected
|
||||
* @return string[]|true
|
||||
*/
|
||||
protected function getAvailableBlocks($dashboard, $module): array|bool
|
||||
protected function getAvailableCodes($dashboard, $module): array|bool
|
||||
{
|
||||
if(!$this->selfCall)
|
||||
{
|
||||
@@ -243,4 +243,74 @@ class blockZen extends block
|
||||
|
||||
return array($shortBlocks, $longBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 HTML 区块。
|
||||
* Generate HTML block.
|
||||
*
|
||||
* @param object $block
|
||||
* @return string
|
||||
*/
|
||||
protected function generateHtmlBlock(object $block): string
|
||||
{
|
||||
if(empty($block->params->html))
|
||||
{
|
||||
return "<div class='empty-tip'>" . $this->lang->block->emptyTip . "</div>";
|
||||
}
|
||||
|
||||
return "<div class='panel-body'><div class='article-content'>" . $block->params->html . '</div></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据来源生成默认区块
|
||||
* Generate default block by source.
|
||||
*
|
||||
* @param object $block
|
||||
* @return string
|
||||
*/
|
||||
protected function generateDefaultBlockBySource(object $block): string
|
||||
{
|
||||
$this->get->set('mode', 'getblockdata');
|
||||
$this->get->set('blockTitle', $block->title);
|
||||
$this->get->set('module', $block->module);
|
||||
$this->get->set('blockid', $block->code);
|
||||
$this->get->set('param', base64_encode(json_encode($block->params)));
|
||||
|
||||
return $this->fetch('block', 'main', "module={$block->module}&id={$block->id}");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成指派给我的区块。
|
||||
* Generate assign to me block.
|
||||
*
|
||||
* @param object $block
|
||||
* @return string
|
||||
*/
|
||||
protected function generateAssignToMeBlock(object $block): string
|
||||
{
|
||||
$this->get->set('param', base64_encode(json_encode($block->params)));
|
||||
|
||||
return $this->fetch('block', 'printAssignToMeBlock', 'longBlock=' . $this->block->isLongBlock($block));
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉待定和已暂停的任务。
|
||||
* Remove undetermined and suspended tasks.
|
||||
*
|
||||
* @param array $todos
|
||||
* @return array
|
||||
*/
|
||||
protected function unsetTodos(array $todos): array
|
||||
{
|
||||
$suspendedTasks = $this->loadModel('task')->getUserSuspendedTasks($this->app->user->account);
|
||||
foreach($todos as $key => $todo)
|
||||
{
|
||||
/* '2030-01-01' means undetermined */
|
||||
if($todo->date == '2030-01-01' || ($todo->type == 'task' && isset($suspendedTasks[$todo->idvalue])))
|
||||
{
|
||||
unset($todos[$key]);
|
||||
}
|
||||
}
|
||||
return $todos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ function setLane(regionID, num)
|
||||
*/
|
||||
function loadExecutionBuilds(productID, executionID, index)
|
||||
{
|
||||
var branch = $('#branches' + index).val();
|
||||
var branch = $('#branches' + index).val() ? $('#branches' + index).val() : 0;
|
||||
if(executionID == 'ditto')
|
||||
{
|
||||
for(var i = index - 1; i > 0, executionID == 'ditto'; i--)
|
||||
|
||||
@@ -254,7 +254,7 @@ class buildModel extends model
|
||||
$buildIdList = str_replace('trunk', '0', $buildIdList);
|
||||
$selectedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)
|
||||
->where('id')->in($buildIdList)
|
||||
->beginIF($products)->andWhere('product')->in($productIdList)->fi()
|
||||
->beginIF($products and $products != 'all')->andWhere('product')->in($productIdList)->fi()
|
||||
->beginIF($objectType === 'execution' and $objectID)->andWhere('execution')->eq($objectID)->fi()
|
||||
->beginIF($objectType === 'project' and $objectID)->andWhere('project')->eq($objectID)->fi()
|
||||
->beginIF(strpos($params, 'hasdeleted') === false)->andWhere('deleted')->eq(0)->fi()
|
||||
@@ -274,7 +274,7 @@ class buildModel extends model
|
||||
->beginIF(strpos($params, 'hasdeleted') === false)->andWhere('t1.deleted')->eq(0)->fi()
|
||||
->beginIF(strpos($params, 'hasproject') !== false)->andWhere('t1.project')->ne(0)->fi()
|
||||
->beginIF(strpos($params, 'singled') !== false)->andWhere('t1.execution')->ne(0)->fi()
|
||||
->beginIF($products)->andWhere('t1.product')->in($productIdList)->fi()
|
||||
->beginIF($products and $products != 'all')->andWhere('t1.product')->in($productIdList)->fi()
|
||||
->beginIF($objectType === 'execution' and $objectID)->andWhere('t1.execution')->eq($objectID)->fi()
|
||||
->beginIF($objectType === 'project' and $objectID)->andWhere('t1.project')->eq($objectID)->fi()
|
||||
->orderBy('t1.date desc, t1.id desc')->fetchAll('id');
|
||||
|
||||
@@ -183,7 +183,7 @@ class caselibModel extends model
|
||||
$lib = fixer::input('post')
|
||||
->stripTags($this->config->caselib->editor->create['id'], $this->config->allowedTags)
|
||||
->setForce('type', 'library')
|
||||
->setIF($this->lang->navGroup->caselib != 'qa', 'project', $this->session->project)
|
||||
->setIF($this->lang->navGroup->caselib != 'qa', 'project', (int)$this->session->project)
|
||||
->add('addedBy', $this->app->user->account)
|
||||
->add('addedDate', helper::now())
|
||||
->remove('uid')
|
||||
|
||||
@@ -181,7 +181,8 @@ class chart extends control
|
||||
|
||||
$sql = str_replace(';', '', "$post->sql");
|
||||
$fields = $post->fieldSettings;
|
||||
$langs = isset($post->langs) ? json_decode($post->langs, true) : array();
|
||||
$langs = !empty($post->langs) ? $post->langs : array();
|
||||
if(is_string($langs)) $langs = json_decode($langs, true);
|
||||
|
||||
switch($type)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,7 @@ $lang->chart->typeList = array();
|
||||
$lang->chart->typeList['pie'] = 'Pie';
|
||||
$lang->chart->typeList['line'] = 'Line';
|
||||
$lang->chart->typeList['radar'] = 'Radar';
|
||||
$lang->chart->typeList['cluBarY'] = 'clustered Bar Y';
|
||||
$lang->chart->typeList['stackedBarY'] = 'stacked Bar Y';
|
||||
$lang->chart->typeList['cluBarX'] = 'clustered Bar X';
|
||||
$lang->chart->typeList['stackedBar'] = 'stacked Bar';
|
||||
$lang->chart->typeList['cluBarY'] = 'Clustered Bar Y';
|
||||
$lang->chart->typeList['stackedBarY'] = 'Stacked Bar Y';
|
||||
$lang->chart->typeList['cluBarX'] = 'Clustered Bar X';
|
||||
$lang->chart->typeList['stackedBar'] = 'Stacked Bar';
|
||||
|
||||
@@ -36,7 +36,7 @@ $lang->chart->typeList = array();
|
||||
$lang->chart->typeList['pie'] = 'Pie';
|
||||
$lang->chart->typeList['line'] = 'Line';
|
||||
$lang->chart->typeList['radar'] = 'Radar';
|
||||
$lang->chart->typeList['cluBarY'] = 'clustered Bar Y';
|
||||
$lang->chart->typeList['stackedBarY'] = 'stacked Bar Y';
|
||||
$lang->chart->typeList['cluBarX'] = 'clustered Bar X';
|
||||
$lang->chart->typeList['stackedBar'] = 'stacked Bar';
|
||||
$lang->chart->typeList['cluBarY'] = 'Clustered Bar Y';
|
||||
$lang->chart->typeList['stackedBarY'] = 'Stacked Bar Y';
|
||||
$lang->chart->typeList['cluBarX'] = 'Clustered Bar X';
|
||||
$lang->chart->typeList['stackedBar'] = 'Stacked Bar';
|
||||
|
||||
@@ -36,7 +36,7 @@ $lang->chart->typeList = array();
|
||||
$lang->chart->typeList['pie'] = 'Pie';
|
||||
$lang->chart->typeList['line'] = 'Line';
|
||||
$lang->chart->typeList['radar'] = 'Radar';
|
||||
$lang->chart->typeList['cluBarY'] = 'clustered Bar Y';
|
||||
$lang->chart->typeList['stackedBarY'] = 'stacked Bar Y';
|
||||
$lang->chart->typeList['cluBarX'] = 'clustered Bar X';
|
||||
$lang->chart->typeList['stackedBar'] = 'stacked Bar';
|
||||
$lang->chart->typeList['cluBarY'] = 'Clustered Bar Y';
|
||||
$lang->chart->typeList['stackedBarY'] = 'Stacked Bar Y';
|
||||
$lang->chart->typeList['cluBarX'] = 'Clustered Bar X';
|
||||
$lang->chart->typeList['stackedBar'] = 'Stacked Bar';
|
||||
|
||||
+121
-9
@@ -54,6 +54,12 @@ class chartModel extends model
|
||||
$chart->fieldSettings = array();
|
||||
}
|
||||
|
||||
if(!empty($chart->settings) and $chart->settings != 'null')
|
||||
{
|
||||
$settings = json_decode($chart->settings, true);
|
||||
if(isset($settings[0]) and isset($settings[0]['type'])) $chart->type = $settings[0]['type'];
|
||||
}
|
||||
|
||||
if($chart->sql == null) $chart->sql = '';
|
||||
if(!empty($chart->filters)) $chart->filters = json_decode($chart->filters, true);
|
||||
|
||||
@@ -72,7 +78,7 @@ class chartModel extends model
|
||||
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))
|
||||
if(empty($chart->type) and !empty($chart->settings) and is_array($chart->settings))
|
||||
{
|
||||
$firstSetting = current($chart->settings);
|
||||
if(isset($firstSetting['type'])) $chart->type = $firstSetting['type'];
|
||||
@@ -396,7 +402,7 @@ class chartModel extends model
|
||||
$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, 'boundaryGap' => false);
|
||||
$xaxis = array('type' => 'category', 'data' => $xLabels, 'axisTick' => array('alignWithLabel' => true));
|
||||
$yaxis = array('type' => 'value');
|
||||
$legend = new stdclass();
|
||||
$series = array();
|
||||
@@ -456,7 +462,7 @@ class chartModel extends model
|
||||
$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), 'boundaryGap' => false);
|
||||
$xaxis = array('type' => 'category', 'data' => $xLabels, 'axisLabel' => array('interval' => 0), 'axisTick' => array('alignWithLabel' => true));
|
||||
$yaxis = array('type' => 'value');
|
||||
$legend = new stdclass();
|
||||
|
||||
@@ -615,17 +621,18 @@ class chartModel extends model
|
||||
if($field)
|
||||
{
|
||||
$path = $this->app->getModuleRoot() . 'dataview' . DS . 'table' . DS . "$object.php";
|
||||
if(!is_file($path)) return;
|
||||
|
||||
include $path;
|
||||
$options = $schema->fields[$field]['options'];
|
||||
if(is_file($path))
|
||||
{
|
||||
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();
|
||||
$table = zget($this->config->objectTables, $object, '');
|
||||
if($table) $options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
@@ -696,5 +703,110 @@ class chartModel extends model
|
||||
|
||||
return $filterFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tables.
|
||||
*
|
||||
* @param string $sql
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTables($sql)
|
||||
{
|
||||
$processedSql = trim($sql, ';');
|
||||
$processedSql = str_replace(array("\r\n", "\n"), ' ', $processedSql);
|
||||
$processedSql = str_replace('`', '', $processedSql);
|
||||
preg_match_all('/^select (.+) from (.+)$/i', $processedSql, $selectAndFrom);
|
||||
if(empty($selectAndFrom[2][0])) return false;
|
||||
|
||||
$selectSql = $selectAndFrom[1][0];
|
||||
$tableSql = $fromSql = $selectAndFrom[2][0];
|
||||
if(stripos($fromSql, 'where') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'where')));
|
||||
if(stripos($fromSql, 'limit') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'limit')));
|
||||
if(stripos($fromSql, 'having') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'having')));
|
||||
if(stripos($fromSql, 'group by') !== false) $tableSql = trim(substr($fromSql, 0, stripos($fromSql, 'group by')));
|
||||
|
||||
/* Remove such as "left join|right join|join", "on (t1.id=t2.id)", result like t1, t2 as t3. */
|
||||
$tableSql .= ' ';
|
||||
if(stripos($tableSql, 'join') !== false) $tableSql = preg_replace(array('/join\s+([A-Z]+_\w+ .*)on/Ui', '/,\s*on\s+[^,]+/i'), array(',$1,on', ''), $tableSql);
|
||||
|
||||
/* Match t2 as t3 */
|
||||
preg_match_all('/(\w+) +as +(\w+)/i', $tableSql, $out);
|
||||
|
||||
$fields = explode(',', $selectSql);
|
||||
foreach($fields as $i => $field)
|
||||
{
|
||||
if($field) $asField = '';
|
||||
if(strrpos($field, ' as ') !== false) list($field, $asField) = explode(' as ', $field);
|
||||
if(strrpos($field, ' AS ') !== false) list($field, $asField) = explode(' AS ', $field);
|
||||
|
||||
$field = trim($field);
|
||||
$asField = trim($asField);
|
||||
$fieldName = $field;
|
||||
if(strrpos($field, '.') !== false)
|
||||
{
|
||||
$table = substr($field, 0, strrpos($field, '.'));
|
||||
$fieldName = substr($field, strrpos($field, '.') + 1);
|
||||
if(!empty($out[0]) and in_array($table, $out[2]))
|
||||
{
|
||||
$realTable = $out[1][array_search($table, $out[2])];
|
||||
$tableFieldName = str_replace($table . '.', $realTable . '.', $field);
|
||||
|
||||
if(isset($fields[$fieldName]) && !$asField)
|
||||
{
|
||||
$fieldName = str_replace('.', '', $field);
|
||||
|
||||
$sql = preg_replace(array("/$field/", "/`$field`/"), array("$field AS $fieldName", "`$field` AS $fieldName"), $sql, 1);
|
||||
|
||||
$field = $tableFieldName;
|
||||
}
|
||||
}
|
||||
|
||||
if($fieldName == '*') $fieldName = $field;
|
||||
}
|
||||
|
||||
$fieldName = $asField ? $asField : $fieldName;
|
||||
|
||||
$fields[$fieldName] = $field;
|
||||
unset($fields[$i]);
|
||||
}
|
||||
|
||||
$tableSql = preg_replace('/as +\w+/i', ' ', $tableSql);
|
||||
$tableSql = trim(str_replace(array('(', ')', ','), ' ', $tableSql));
|
||||
$tableSql = preg_replace('/ +/', ' ', $tableSql);
|
||||
|
||||
$tables = explode(' ', $tableSql);
|
||||
|
||||
return array('sql' => $sql, 'tables' => $tables, 'fields' => $fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse variables to null string in sql.
|
||||
*
|
||||
* @param string $sql
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function parseSqlVars($sql, $filters)
|
||||
{
|
||||
if($filters)
|
||||
{
|
||||
foreach($filters as $filter)
|
||||
{
|
||||
if(!isset($filter['default'])) continue;
|
||||
if(isset($filter['from']) and $filter['from'] == 'query')
|
||||
{
|
||||
$default = "'{$filter['default']}'";
|
||||
$sql = str_replace('$' . $filter['field'], $default, $sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(preg_match_all("/[\$]+[a-zA-Z0-9]+/", $sql, $out))
|
||||
{
|
||||
foreach($out[0] as $match) $sql = str_replace($match, "''", $sql);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,31 +44,33 @@
|
||||
|
||||
<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 class="cell">
|
||||
<div class='panel'>
|
||||
<div class='panel-heading text-ellipsis'>
|
||||
<div class='panel-title'><?php echo isset($group->name) ? $group->name : '';?></div>
|
||||
</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 class='panel-body'>
|
||||
<?php if(!$chartTree):?>
|
||||
<hr class="space">
|
||||
<div class="text-center text-muted">
|
||||
<?php echo $lang->chart->noChart;?>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif;?>
|
||||
<?php if($this->config->edition == 'open'):?>
|
||||
<div class='text biz-version'>
|
||||
<span class='text-important'><?php echo (!empty($config->isINT)) ? $lang->bizVersionINT : $lang->bizVersion;?></span>
|
||||
<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;?>
|
||||
<?php if($this->config->edition == 'open'):?>
|
||||
<div class='text biz-version'>
|
||||
<span class='text-important'><?php echo (!empty($config->isINT)) ? $lang->bizVersionINT : $lang->bizVersion;?></span>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -258,7 +258,7 @@ $lang->waterfall->menu = new stdclass();
|
||||
$lang->waterfall->menu->index = array('link' => "$lang->dashboard|project|index|project=%s");
|
||||
$lang->waterfall->menu->execution = array('link' => "{$lang->stage->common}|project|execution|status=all&projectID=%s", 'subModule' => 'programplan,task');
|
||||
$lang->waterfall->menu->storyGroup = array('link' => "{$lang->common->story}|projectstory|story|projectID=%s",'class' => 'dropdown dropdown-hover', 'exclude' => 'tree-browse,projectstory-track');
|
||||
$lang->waterfall->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree', 'alias' => 'story', 'exclude' => 'projectstory-track');
|
||||
$lang->waterfall->menu->story = array('link' => "$lang->SRCommon|projectstory|story|projectID=%s", 'subModule' => 'projectstory,tree', 'alias' => 'story', 'exclude' => 'projectstory-track,tree-browse');
|
||||
$lang->waterfall->menu->design = array('link' => "{$lang->design->common}|design|browse|project=%s");
|
||||
$lang->waterfall->menu->qa = array('link' => "{$lang->qa->common}|project|bug|projectID=%s", 'subModule' => 'testcase,testtask,bug,testreport', 'alias' => 'bug,testtask,testcase,testreport');
|
||||
$lang->waterfall->menu->doc = array('link' => "{$lang->doc->common}|doc|projectSpace|objectID=%s");
|
||||
@@ -266,9 +266,9 @@ $lang->waterfall->menu->devops = array('link' => "{$lang->repo->common}|repo
|
||||
$lang->waterfall->menu->build = array('link' => "{$lang->build->common}|projectbuild|browse|project=%s", 'subModule' => 'projectbuild');
|
||||
$lang->waterfall->menu->release = array('link' => "{$lang->release->common}|projectrelease|browse|project=%s", 'subModule' => 'projectrelease');
|
||||
$lang->waterfall->menu->dynamic = array('link' => "$lang->dynamic|project|dynamic|project=%s");
|
||||
$lang->waterfall->menu->settings = array('link' => "$lang->settings|project|view|project=%s", 'subModule' => 'stakeholder', 'alias' => 'edit,manageproducts,group,managemembers,manageview,managepriv,whitelist,addwhitelist,team', 'exclude' => 'tree-browsetask');
|
||||
|
||||
$lang->waterfall->dividerMenu = ',programplan,build,dynamic,';
|
||||
$lang->waterfall->menu->settings = $lang->scrum->menu->settings;
|
||||
$lang->waterfall->dividerMenu = ',programplan,build,dynamic,';
|
||||
|
||||
$lang->waterfall->menu->storyGroup['dropMenu'] = $lang->scrum->menu->storyGroup['dropMenu'];
|
||||
|
||||
|
||||
+2
-25
@@ -1487,31 +1487,7 @@ class commonModel extends model
|
||||
echo "<a href='javascript:;'>" . "<i class='icon icon-download'></i> " . $lang->clientName . "</a><ul class='dropdown-menu pull-left'>";
|
||||
echo '<li>' . html::a(helper::createLink('misc', 'downloadClient', '', '', true), $lang->downloadClient, '', "title='$lang->downloadClient' class='iframe text-ellipsis' data-width='600'") . '</li>';
|
||||
echo "<li class='dropdown-submenu' id='downloadMobile'><a href='javascript:;'>" . $lang->downloadMobile . "</a><ul class='dropdown-menu pull-left''>";
|
||||
|
||||
/* Intranet users use local pictures. */
|
||||
$connected = false;
|
||||
if(extension_loaded('curl'))
|
||||
{
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://www.zentao.net/page/appqrcode.json');
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT_MS, 200);
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, 200);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$connected = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
}
|
||||
|
||||
if($connected)
|
||||
{
|
||||
echo "<li><div class='mobile-qrcode'><iframe src='https://www.zentao.net/page/appqrcode.html?v={$config->version}' frameborder='0' scrolling='no' seamless></iframe></div></li>";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<li><div class='mobile-qrcode local-img'><img src='{$config->webRoot}theme/default/images/main/mobile_qrcode.png' /><div class='mobile-version'><span>v1.2</span></div></li>";
|
||||
}
|
||||
|
||||
echo "<li><div class='mobile-qrcode local-img'><img src='{$config->webRoot}static/images/app-qrcode.png' /></li>";
|
||||
echo "</ul></li>";
|
||||
echo '<li>' . html::a($lang->clientHelpLink, $lang->clientHelp, '', "title='$lang->clientHelp' target='_blank'") . '</li>';
|
||||
echo '</ul></li>';
|
||||
@@ -2078,6 +2054,7 @@ EOF;
|
||||
if(strtolower($key) == 'assigneddate') continue;
|
||||
if(strtolower($key) == 'editedby') continue;
|
||||
if(strtolower($key) == 'editeddate') continue;
|
||||
if(strtolower($key) == 'editingdate') continue;
|
||||
if(strtolower($key) == 'uid') continue;
|
||||
if(strtolower($key) == 'finisheddate' and $value == '') continue;
|
||||
if(strtolower($key) == 'canceleddate' and $value == '') continue;
|
||||
|
||||
+5
-13
@@ -603,7 +603,7 @@ class doc extends control
|
||||
}
|
||||
elseif($objectType == 'mine')
|
||||
{
|
||||
$this->lang->doc->aclList = $this->lang->doclib->mySpaceAclList['private'];
|
||||
$this->lang->doc->aclList = $this->lang->doclib->mySpaceAclList;
|
||||
}
|
||||
$moduleOptionMenu = $this->doc->getLibsOptionMenu($libs);
|
||||
|
||||
@@ -650,16 +650,7 @@ class doc extends control
|
||||
$this->doc->delete(TABLE_DOC, $docID);
|
||||
|
||||
/* Delete doc files. */
|
||||
$this->loadModel('file');
|
||||
foreach($doc->files as $fileID => $file)
|
||||
{
|
||||
$file = $this->file->getById($fileID);
|
||||
$this->dao->delete()->from(TABLE_FILE)->where('id')->eq($fileID)->exec();
|
||||
$this->loadModel('action')->create($file->objectType, $file->objectID, 'deletedFile', '', $extra=$file->title);
|
||||
|
||||
$fileRecord = $this->dao->select('id')->from(TABLE_FILE)->where('pathname')->eq($file->pathname)->fetch();
|
||||
if(empty($fileRecord)) $this->file->unlinkFile($file);
|
||||
}
|
||||
if($doc->files) $this->dao->update(TABLE_FILE)->set('deleted')->eq('1')->where('id')->in(array_keys($doc->files))->exec();
|
||||
|
||||
/* if ajax request, send result. */
|
||||
if($this->server->ajax)
|
||||
@@ -1318,7 +1309,7 @@ class doc extends control
|
||||
$this->view->libs = $libs;
|
||||
$this->view->apiID = 0;
|
||||
$this->view->release = 0;
|
||||
$this->view->apiList = $browseType == 'bySearch' ? $this->api->getApiListBySearch($libID, $queryID, $type, array_keys($libs)) : $this->api->getListByModuleId($libID, $moduleID, 0, $pager);
|
||||
$this->view->apiList = $browseType == 'bySearch' ? $this->api->getApiListBySearch($libID, $queryID, $type, array_keys($libs)) : $this->api->getListByModuleId($libID, $moduleID, $param, $pager);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1374,7 +1365,7 @@ class doc extends control
|
||||
*/
|
||||
public function productSpace($objectID = 0, $libID = 0, $moduleID = 0, $browseType = 'all', $orderBy = 'status,id_desc', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
|
||||
{
|
||||
$products = $this->product->getPairs('nocode', 0, '', 'all');
|
||||
$products = $this->product->getPairs('nocode');
|
||||
$objectID = $this->product->saveState($objectID, $products);
|
||||
|
||||
echo $this->fetch('doc', 'tableContents', "type=product&objectID=$objectID&libID=$libID&moduleID=$moduleID&browseType=$browseType&orderBy=$orderBy¶m=$param&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID");
|
||||
@@ -1458,6 +1449,7 @@ class doc extends control
|
||||
if(!common::hasPriv('doc', 'teamSpace')) unset($spaceList['custom']);
|
||||
if(!common::hasPriv('api', 'index')) unset($spaceList['api']);
|
||||
if(!common::hasPriv('api', 'create')) unset($spaceList['api'], $typeList['api']);
|
||||
if($this->config->vision == 'lite') unset($spaceList['api'], $spaceList['product'], $typeList['api']);
|
||||
|
||||
$products = $this->loadModel('product')->getPairs();
|
||||
$projects = $this->project->getPairsByProgram('', 'all', false, 'order_asc', 'kanban');
|
||||
|
||||
@@ -18,7 +18,7 @@ $(function()
|
||||
|
||||
$('#saveDraft').click(function()
|
||||
{
|
||||
if($('#editorTitle').val() == '')
|
||||
if($.trim($('#editorTitle').val()) == '')
|
||||
{
|
||||
bootbox.alert(titleNotEmpty);
|
||||
return false;
|
||||
|
||||
@@ -8,7 +8,7 @@ $(function()
|
||||
|
||||
$('#saveDraft').click(function()
|
||||
{
|
||||
if($('#editorTitle').val() == '')
|
||||
if($.trim($('#editorTitle').val()) == '')
|
||||
{
|
||||
bootbox.alert(titleNotEmpty);
|
||||
return false;
|
||||
|
||||
@@ -14,7 +14,7 @@ function redirectParentWindow(objectType, libID, moduleID, docType)
|
||||
var link = '';
|
||||
if(docType == 'api')
|
||||
{
|
||||
link = createLink('api', 'create', 'libID=' + libID + '&moduleID=' + moduleID);
|
||||
link = createLink('api', 'create', 'libID=' + libID + '&moduleID=' + moduleID + '&space=' + objectType);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+49
-27
@@ -47,13 +47,13 @@ class docModel extends model
|
||||
$libs = $this->dao->select('*')->from(TABLE_DOCLIB)
|
||||
->where('deleted')->eq(0)
|
||||
->andWhere('type')->eq('api')
|
||||
->beginIF(!empty($appendLib))->orWhere('id')->eq($appendLib)->fi()
|
||||
->beginIF(!empty($objectType) && $objectID > 0 and $objectType != 'nolink')->andWhere($objectType)->eq($objectID)->fi()
|
||||
->beginIF(!empty($objectType) and $objectID > 0 and $objectType != 'nolink')->andWhere($objectType)->eq($objectID)->fi()
|
||||
->beginIF($objectType == 'nolink')
|
||||
->andWhere('product')->eq(0)
|
||||
->andWhere('project')->eq(0)
|
||||
->andWhere('execution')->eq(0)
|
||||
->fi()
|
||||
->beginIF(!empty($appendLib))->orWhere('id')->eq($appendLib)->fi()
|
||||
->orderBy('order_asc, id_asc')
|
||||
->fetchAll('id');
|
||||
|
||||
@@ -101,7 +101,7 @@ class docModel extends model
|
||||
$projects = $this->loadModel('project')->getPairsByProgram('', 'all', false, 'order_asc', $this->config->vision == 'rnd' ? 'kanban' : '');
|
||||
$executions = $this->loadModel('execution')->getPairs(0, 'sprint,stage', 'multiple,leaf');
|
||||
$waterfalls = array();
|
||||
if(empty($objectID) and $type != 'product' and $type != 'project' and $type != 'custom')
|
||||
if(empty($objectID) and $type == 'execution')
|
||||
{
|
||||
$waterfalls = $this->dao->select('t1.id,t2.name')->from(TABLE_EXECUTION)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
|
||||
@@ -211,6 +211,8 @@ class docModel extends model
|
||||
->remove('uid,contactListMenu,libType')
|
||||
->get();
|
||||
|
||||
if(defined('IN_UPGRADE') and (($this->config->edition == 'open' and version_compare($this->config->version, '18.4.alpha1', '<')) or ($this->config->edition == 'biz' and version_compare($this->config->version, 'biz8.4.alpha1', '<')) or ($this->config->edition == 'max' and version_compare($this->config->version, 'max4.4.alpha1', '<')))) unset($lib->addedBy, $lib->addedDate);
|
||||
|
||||
if($lib->execution) $lib->type = 'execution';
|
||||
if($lib->type == 'execution' and $lib->execution and !$lib->project)
|
||||
{
|
||||
@@ -253,6 +255,8 @@ class docModel extends model
|
||||
->remove('uid,contactListMenu,libType')
|
||||
->get();
|
||||
|
||||
if(defined('IN_UPGRADE') and (($this->config->edition == 'open' and version_compare($this->config->version, '18.4.alpha1', '<')) or ($this->config->edition == 'biz' and version_compare($this->config->version, 'biz8.4.alpha1', '<')) or ($this->config->edition == 'max' and version_compare($this->config->version, 'max4.4.alpha1', '<')))) unset($lib->addedBy, $lib->addedDate);
|
||||
|
||||
$this->app->loadLang('api');
|
||||
|
||||
/* Replace doc library name. */
|
||||
@@ -382,15 +386,18 @@ class docModel extends model
|
||||
*/
|
||||
public function getDocsByBrowseType($browseType, $queryID, $moduleID, $sort, $pager)
|
||||
{
|
||||
$allLibs = $this->getLibs('all');
|
||||
$allLibIDList = array_keys($allLibs);
|
||||
$hasPrivDocIdList = $this->getPrivDocs(0, $moduleID);
|
||||
|
||||
if($browseType == "all")
|
||||
if($browseType == 'all')
|
||||
{
|
||||
$docs = $this->getDocs(0, 0, $browseType, $sort, $pager);
|
||||
}
|
||||
elseif($browseType == 'bySearch')
|
||||
else
|
||||
{
|
||||
$allLibs = $this->getLibs('all');
|
||||
$allLibIDList = array_keys($allLibs);
|
||||
$hasPrivDocIdList = $this->getPrivDocs($allLibIDList, $moduleID);
|
||||
}
|
||||
|
||||
if($browseType == 'bySearch')
|
||||
{
|
||||
if($queryID)
|
||||
{
|
||||
@@ -606,7 +613,7 @@ class docModel extends model
|
||||
*/
|
||||
public function getDocs($libID, $module, $browseType, $orderBy, $pager = null)
|
||||
{
|
||||
if(empty($libID)) return array();
|
||||
if(empty($libID) and $browseType != 'all') return array();
|
||||
|
||||
$docIdList = $this->getPrivDocs($libID, $module, 'children');
|
||||
$docs = $this->dao->select('*')->from(TABLE_DOC)
|
||||
@@ -641,6 +648,9 @@ class docModel extends model
|
||||
$query = preg_replace('/(`\w+`)/', 't1.$1', $query);
|
||||
}
|
||||
|
||||
$allLibs = $this->getLibs('all');
|
||||
$allLibIDList = array_keys($allLibs);
|
||||
$hasPrivDocIdList = $this->getPrivDocs($allLibIDList);
|
||||
if($type == 'view' or $type == 'collect')
|
||||
{
|
||||
$docs = $this->dao->select('t1.*,t3.name as libName,t3.type as objectType,max(t2.`date`) as date')->from(TABLE_DOC)->alias('t1')
|
||||
@@ -648,6 +658,7 @@ class docModel extends model
|
||||
->leftJoin(TABLE_DOCLIB)->alias('t3')->on("t1.lib=t3.id")
|
||||
->where('t1.deleted')->eq(0)
|
||||
->andWhere('t1.lib')->ne('')
|
||||
->andWhere('t1.type')->in('text,word,ppt,excel,url,article')
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('t2.action')->eq($type)
|
||||
->andWhere('t2.actor')->eq($this->app->user->account)
|
||||
@@ -657,6 +668,7 @@ class docModel extends model
|
||||
->beginIF($browseType == 'all' or $browseType == 'bysearch')->andWhere("(t1.status = 'normal' or (t1.status = 'draft' and t1.addedBy='{$this->app->user->account}'))")->fi()
|
||||
->beginIF($browseType == 'draft')->andWhere('t1.status')->eq('draft')->andWhere('t1.addedBy')->eq($this->app->user->account)->fi()
|
||||
->beginIF($browseType == 'bysearch')->andWhere($query)->fi()
|
||||
->beginIF(!empty($hasPrivDocIdList))->andWhere('t1.id')->in($hasPrivDocIdList)->fi()
|
||||
->groupBy('t1.id')
|
||||
->orderBy($orderBy)
|
||||
->page($pager, 't1.id')
|
||||
@@ -680,6 +692,7 @@ class docModel extends model
|
||||
->where('t1.deleted')->eq(0)
|
||||
->andWhere('t1.lib')->ne('')
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('t1.type')->in('text,word,ppt,excel,url,article')
|
||||
->beginIF($type == 'createdby')->andWhere('t1.addedBy')->eq($this->app->user->account)->fi()
|
||||
->beginIF($type == 'editedby')->andWhere('t1.id')->in($docIdList)->fi()
|
||||
->beginIF(!common::hasPriv('doc', 'productSpace'))->andWhere('t2.type')->ne('product')->fi()
|
||||
@@ -899,7 +912,7 @@ class docModel extends model
|
||||
unset($doc->contentMarkdown, $doc->contentType, $doc->url);
|
||||
|
||||
$requiredFields = $this->config->doc->create->requiredFields;
|
||||
if($doc->status == 'draft') $requiredFields = '';
|
||||
if($doc->status == 'draft') $requiredFields = 'title';
|
||||
if(strpos("url|word|ppt|excel", $this->post->type) !== false) $requiredFields = trim(str_replace(",content,", ",", ",{$requiredFields},"), ',');
|
||||
|
||||
$checkContent = strpos(",$requiredFields,", ',content,') !== false;
|
||||
@@ -995,7 +1008,7 @@ class docModel extends model
|
||||
}
|
||||
|
||||
$requiredFields = $this->config->doc->edit->requiredFields;
|
||||
if($doc->status == 'draft') $requiredFields = '';
|
||||
if($doc->status == 'draft') $requiredFields = 'title';
|
||||
if(strpos(",$requiredFields,", ',content,') !== false)
|
||||
{
|
||||
$requiredFields = trim(str_replace(',content,', ',', ",$requiredFields,"), ',');
|
||||
@@ -1275,8 +1288,8 @@ class docModel extends model
|
||||
{
|
||||
if(empty($object)) return false;
|
||||
|
||||
if($this->app->user->admin and ($object->type != 'mine' or ($object->type == 'mine' and $object->addedBy == $this->app->user->account))) return true;
|
||||
|
||||
if($object->type == 'mine' and $object->addedBy == $this->app->user->account) return true;
|
||||
if($this->app->user->admin and $object->type != 'mine') return true;
|
||||
if($object->acl == 'open') return true;
|
||||
|
||||
$account = ',' . $this->app->user->account . ',';
|
||||
@@ -1294,14 +1307,7 @@ class docModel extends model
|
||||
|
||||
if($object->project and !$object->execution and $object->acl == 'default')
|
||||
{
|
||||
$stakeHolders = array();
|
||||
$project = $this->loadModel('project')->getById($object->project);
|
||||
$projectTeams = $this->loadModel('user')->getTeamMemberPairs($object->project);
|
||||
$stakeHolders = $this->loadModel('stakeholder')->getStakeHolderPairs($object->project);
|
||||
|
||||
$authorizedUsers = $this->user->getProjectAuthedUsers($project, $stakeHolders, $projectTeams, array_flip(explode(",", $project->whitelist)));
|
||||
|
||||
if(array_key_exists($this->app->user->account, array_filter($authorizedUsers))) return true;
|
||||
if($this->loadModel('project')->checkPriv($object->project)) return true;
|
||||
}
|
||||
|
||||
if(strpos($extra, 'notdoc') !== false)
|
||||
@@ -1927,6 +1933,7 @@ class docModel extends model
|
||||
|
||||
$files = $this->dao->select('*')->from(TABLE_FILE)->alias('t1')
|
||||
->where('size')->gt('0')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->andWhere("(objectType = '$type' and objectID = $objectID)", true)
|
||||
->orWhere("(objectType = 'doc' and objectID in ($docIdList))")
|
||||
->orWhere("(objectType = 'bug' and objectID in ($bugIdList))")
|
||||
@@ -2165,7 +2172,11 @@ class docModel extends model
|
||||
{
|
||||
$today = date('Y-m-d');
|
||||
$statistic = new stdclass();
|
||||
$statistic->totalDocs = $this->dao->select('count(*) as count')->from(TABLE_DOC)->where('deleted')->eq('0')->andWhere('vision')->eq($this->config->vision)->fetch('count');
|
||||
$statistic->totalDocs = $this->dao->select('count(*) as count')->from(TABLE_DOC)
|
||||
->where('deleted')->eq('0')
|
||||
->andWhere('type')->in('text,word,ppt,excel,url,article')
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->fetch('count');
|
||||
$statistic->todayEditedDocs = $this->dao->select('count(DISTINCT objectID) as count')->from(TABLE_ACTION)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on("t1.objectID=t2.id and t1.objectType='doc'")
|
||||
->where('t1.objectType')->eq('doc')
|
||||
@@ -2174,17 +2185,26 @@ class docModel extends model
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('LEFT(t1.date, 10)')->eq($today)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->andWhere('t2.type')->in('text,word,ppt,excel,url,article')
|
||||
->fetch('count');
|
||||
$statistic->myEditedDocs = $this->dao->select('count(DISTINCT objectID) as count')->from(TABLE_ACTION)->alias('t1')
|
||||
$statistic->myEditedDocs = $this->dao->select('count(DISTINCT t1.objectID) as count')->from(TABLE_ACTION)->alias('t1')
|
||||
->leftJoin(TABLE_DOC)->alias('t2')->on("t1.objectID=t2.id and t1.objectType='doc'")
|
||||
->where('t1.objectType')->eq('doc')
|
||||
->andWhere('t1.action')->eq('edited')
|
||||
->andWhere('t1.actor')->eq($this->app->user->account)
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->andWhere('t2.lib')->ne('')
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->andWhere('t2.type')->in('text,word,ppt,excel,url,article')
|
||||
->fetch('count');
|
||||
|
||||
$my = $this->dao->select("count(*) as myDocs, SUM(views) as docViews, SUM(collects) as docCollects")->from(TABLE_DOC)->where('addedBy')->eq($this->app->user->account)->andWhere('deleted')->eq(0)->andWhere('vision')->eq($this->config->vision)->andWhere('lib')->ne('')->fetch();
|
||||
$my = $this->dao->select("count(*) as myDocs, SUM(views) as docViews, SUM(collects) as docCollects")->from(TABLE_DOC)
|
||||
->where('addedBy')->eq($this->app->user->account)
|
||||
->andWhere('type')->in('text,word,ppt,excel,url,article')
|
||||
->andWhere('deleted')->eq(0)
|
||||
->andWhere('vision')->eq($this->config->vision)
|
||||
->andWhere('lib')->ne('')
|
||||
->fetch();
|
||||
$statistic->myDocs = $my->myDocs;
|
||||
$statistic->myDoc = new stdclass();
|
||||
$statistic->myDoc->docViews = $my->docViews;
|
||||
@@ -2818,7 +2838,7 @@ class docModel extends model
|
||||
else
|
||||
{
|
||||
$libs = $this->getLibsByObject($type, 0, '', $appendLib);
|
||||
if($libID == 0 and !empty($libs)) $libID = reset($libs)->id;
|
||||
if(($libID == 0 or !isset($libs[$libID])) and !empty($libs)) $libID = reset($libs)->id;
|
||||
if(isset($libs[$libID]))
|
||||
{
|
||||
$objectTitle = zget($libs[$libID], 'name', '');
|
||||
@@ -2830,7 +2850,9 @@ class docModel extends model
|
||||
}
|
||||
|
||||
$tab = strpos(',doc,product,project,execution,', ",{$this->app->tab},") !== false ? $this->app->tab : 'doc';
|
||||
$type = $type == 'mine' ? 'my' : $type;
|
||||
if($type == 'mine') $type = 'my';
|
||||
if($type == 'custom') $type = 'team';
|
||||
if($tab == 'doc' and !common::hasPriv('doc', $type . 'Space')) return print(js::locate(helper::createLink('user', 'deny', "module=doc&method={$type}Space")));
|
||||
if($tab != 'doc' and method_exists($type . 'Model', 'setMenu'))
|
||||
{
|
||||
$this->loadModel($type)->setMenu($objectID);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<table class='table table-form'>
|
||||
<?php if(strpos('product|project|execution', $type) !== false):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->doc->project;?></th>
|
||||
<th><?php echo $lang->doc->{$type};?></th>
|
||||
<td class='required'><?php echo html::select($type, $objects, $objectID, "class='form-control chosen' onchange='loadObjectModules(\"{$type}\", this.value)'");?></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
|
||||
@@ -76,6 +76,8 @@ li.drag-shadow ul {display: none !important;}
|
||||
js::set('release', isset($release) ? $release : 0);
|
||||
js::set('versionLang', $lang->build->common);
|
||||
js::set('spaceType', $this->session->spaceType);
|
||||
js::set('rawModule', $this->app->rawModule);
|
||||
js::set('rawMethod', $this->app->rawMethod);
|
||||
|
||||
/* ObjectType and objectID used for other space. */
|
||||
js::set('objectType', isset($type) ? $type : '');
|
||||
@@ -151,7 +153,7 @@ js::set('hasLibPriv', $hasLibPriv);
|
||||
<li data-method="addCataChild" data-type="add" data-id="%moduleID%" data-has-children='%hasChildren%'><a><i class="icon icon-add-directory"></i><?php echo $lang->doc->libDropdown['addSubModule'];?></a></li>
|
||||
<?php endif;?>
|
||||
<?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>
|
||||
<li data-method="editCata" class='edit-module'><a data-href='<?php echo helper::createLink($module, 'editCatalog', "moduleID=%moduleID%&type=" . ($app->rawModule == 'api' ? 'api' : 'doc'));?>'><i class="icon icon-edit"></i><?php echo $lang->doc->libDropdown['editModule'];?></a></li>
|
||||
<?php endif;?>
|
||||
<?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>
|
||||
@@ -473,8 +475,8 @@ $(function()
|
||||
if(!libID) libID = 0;
|
||||
if(!moduleID) moduleID = 0;
|
||||
linkParams = linkParams.replace('%s', 'libID=' + libID + '&moduleID=' + moduleID);
|
||||
if(config.currentModule == 'api' && config.currentMethod == 'view') spaceType = 'api';
|
||||
if(spaceType != 'api' && config.currentModule == 'api') linkParams = 'objectID=' + objectID + '&' + linkParams;
|
||||
if(rawModule == 'api' && rawMethod== 'view') spaceType = 'api';
|
||||
if(spaceType != 'api' && rawModule == 'api') linkParams = 'objectID=' + objectID + '&' + linkParams;
|
||||
var moduleName = spaceType == 'api' ? 'api' : 'doc';
|
||||
var methodName = '';
|
||||
if(spaceType == 'api')
|
||||
@@ -624,7 +626,7 @@ $(function()
|
||||
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;
|
||||
var methodName = rawMethod;
|
||||
if(config.currentModule == 'doc')
|
||||
{
|
||||
params = linkParams.replace('%s', 'libID=' + libID + '&moduleID=0').replace('browseType=&', 'browseType=byrelease&').replace('param=0', 'param=' + moduleID);
|
||||
|
||||
@@ -126,7 +126,7 @@ body {margin-bottom: 25px;}
|
||||
$spaceMethod = zget($config->doc->spaceMethod, $doc->objectType);
|
||||
$spaceParams = "libID={$doc->lib}&moduleID={$doc->module}";
|
||||
if(in_array($doc->objectType, array('product', 'project', 'execution', 'custom'))) $spaceParams = "objectID={$doc->objectID}&$spaceParams";
|
||||
if(in_array($doc->objectType, array('mine', 'custom'))) $spaceParams = "type={$doc->objectType}&$spaceParams";
|
||||
if($doc->objectType == 'mine') $spaceParams = "type={$doc->objectType}&$spaceParams";
|
||||
|
||||
if(common::hasPriv('doc', $spaceMethod))
|
||||
{
|
||||
|
||||
@@ -1864,6 +1864,8 @@ class executionModel extends model
|
||||
{
|
||||
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getExecutionStats($browseType);
|
||||
|
||||
$productID = (int)$productID;
|
||||
|
||||
/* Construct the query SQL at search executions. */
|
||||
$executionQuery = '';
|
||||
if($browseType == 'bySearch')
|
||||
@@ -1906,7 +1908,7 @@ class executionModel extends model
|
||||
->andWhere('t1.multiple')->eq('1')
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->sprints)->fi()
|
||||
->beginIF(!empty($executionQuery))->andWhere($executionQuery)->fi()
|
||||
->beginIF($productID)->andWhere('t3.product')->eq($productID)->fi()
|
||||
->beginIF($productID)->andWhere('t3.product')->eq((int)$productID)->fi()
|
||||
->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
|
||||
->beginIF(!in_array($browseType, array('all', 'undone', 'involved', 'review', 'bySearch')))->andWhere('t1.status')->eq($browseType)->fi()
|
||||
->beginIF($browseType == 'undone')->andWhere('t1.status')->notIN('done,closed')->fi()
|
||||
@@ -3310,7 +3312,7 @@ class executionModel extends model
|
||||
$data->branch = $storyList[$storyID]->branch;
|
||||
$data->story = $storyID;
|
||||
$data->version = $versions[$storyID];
|
||||
$data->order = ++$lastOrder;
|
||||
$data->order = (int)++$lastOrder;
|
||||
$this->dao->replace(TABLE_PROJECTSTORY)->data($data)->exec();
|
||||
|
||||
$this->story->setStage($storyID);
|
||||
@@ -4250,7 +4252,7 @@ class executionModel extends model
|
||||
->page($pager, 't1.id')
|
||||
->fetchAll('id');
|
||||
|
||||
$orderBy = str_replace('pri_', 'priOrder_', $orderBy);
|
||||
$orderBy = str_replace(array('t1.pri_', 't1.`pri'), array('priOrder_', '`priOrder_'), $orderBy);
|
||||
$tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName, IF(t1.`pri` = 0, 999, t1.`pri`) as priOrder')
|
||||
->from(TABLE_TASK)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
|
||||
|
||||
@@ -197,7 +197,7 @@ class group extends control
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function managePriv($type = 'byGroup', $param = 0, $menu = '', $version = '')
|
||||
public function managePriv($type = 'byPackage', $param = 0, $menu = '', $version = '')
|
||||
{
|
||||
if($type == 'byGroup' or $type == 'byPackage') $groupID = $param;
|
||||
|
||||
@@ -251,13 +251,19 @@ class group extends control
|
||||
$privs = $this->group->transformPrivLang($privs);
|
||||
$privs = $this->group->getCustomPrivs($menu, $privs);
|
||||
|
||||
|
||||
$privList = $modules;
|
||||
$privMethods = array();
|
||||
$selectPrivs = array();
|
||||
$selectedPrivIdList = array();
|
||||
$groupPrivsIdList = $this->group->getPrivsIdListByGroup($groupID);
|
||||
foreach($privs as $priv)
|
||||
{
|
||||
if(!empty($version) and strpos($changelogs, ",{$priv->module}-{$priv->method},") === false) continue;
|
||||
if(!empty($version) and strpos($changelogs, ",{$priv->module}-{$priv->method},") === false)
|
||||
{
|
||||
unset($groupPrivsIdList[$priv->id]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!isset($privList[$priv->parentCode])) $privList[$priv->parentCode] = array();
|
||||
if(!is_array($privList[$priv->parentCode])) $privList[$priv->parentCode] = array();
|
||||
@@ -305,7 +311,6 @@ class group extends control
|
||||
}
|
||||
}
|
||||
|
||||
$groupPrivsIdList = $this->group->getPrivsIdListByGroup($groupID);
|
||||
$excludePrivsIdList = array_diff(array_keys($groupPrivsIdList), $selectedPrivIdList);
|
||||
$relatedPrivData = $this->group->getRelatedPrivs($selectedPrivIdList, '', $excludePrivsIdList);
|
||||
|
||||
@@ -329,7 +334,11 @@ class group extends control
|
||||
$privs = $this->group->getCustomPrivs('', $privs);
|
||||
$modules = $this->dao->select('*')->from(TABLE_PRIVMANAGER)->where('type')->eq('module')->fetchAll('code');
|
||||
$modulePairs = $this->group->getPrivManagerPairs('module');
|
||||
$unassignedModules = array_diff(array_keys(array_filter(get_object_vars($this->lang->resource), function($modulePrivs){return !empty((array)$modulePrivs);})), array_keys($modulePairs));
|
||||
|
||||
$privArray = get_object_vars($this->lang->resource);
|
||||
$privArray = array_filter($privArray, function($modulePrivs){$modulePrivs = (array)$modulePrivs; return !empty($modulePrivs);});
|
||||
$unassignedModules = array_diff(array_keys($privArray), array_keys($modulePairs));
|
||||
|
||||
foreach($unassignedModules as $unassignedModule)
|
||||
{
|
||||
$this->app->loadLang($unassignedModule);
|
||||
|
||||
@@ -664,27 +664,27 @@ $lang->changelog['18.3'][] = 'editor-newPage';
|
||||
$lang->changelog['18.3'][] = 'editor-save';
|
||||
$lang->changelog['18.3'][] = 'editor-delete';
|
||||
|
||||
$lang->changelog['18.4'][] = 'doc-mySpace';
|
||||
$lang->changelog['18.4'][] = 'doc-myView';
|
||||
$lang->changelog['18.4'][] = 'doc-myCollection';
|
||||
$lang->changelog['18.4'][] = 'doc-myCreation';
|
||||
$lang->changelog['18.4'][] = 'doc-productSpace';
|
||||
$lang->changelog['18.4'][] = 'doc-projectSpace';
|
||||
$lang->changelog['18.4'][] = 'doc-teamSpace';
|
||||
$lang->changelog['18.4'][] = 'doc-addCatalog';
|
||||
$lang->changelog['18.4'][] = 'doc-editCatalog';
|
||||
$lang->changelog['18.4'][] = 'doc-deleteCatalog';
|
||||
$lang->changelog['18.4'][] = 'doc-displaySetting';
|
||||
$lang->changelog['18.4'][] = 'group-batchChangePackage';
|
||||
$lang->changelog['18.4'][] = 'screen-annualData';
|
||||
$lang->changelog['18.4'][] = 'screen-allAnnualData';
|
||||
$lang->changelog['18.4'][] = 'pivot-preview';
|
||||
$lang->changelog['18.4'][] = 'pivot-productSummary';
|
||||
$lang->changelog['18.4'][] = 'pivot-projectDeviation';
|
||||
$lang->changelog['18.4'][] = 'pivot-bugCreate';
|
||||
$lang->changelog['18.4'][] = 'pivot-bugAssign';
|
||||
$lang->changelog['18.4'][] = 'pivot-workload';
|
||||
$lang->changelog['18.4'][] = 'chart-preview';
|
||||
$lang->changelog['18.4'][] = 'api-addCatalog';
|
||||
$lang->changelog['18.4'][] = 'api-editCatalog';
|
||||
$lang->changelog['18.4'][] = 'api-deleteCatalog';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-mySpace';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-myView';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-myCollection';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-myCreation';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-productSpace';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-projectSpace';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-teamSpace';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-addCatalog';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-editCatalog';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-deleteCatalog';
|
||||
$lang->changelog['18.4.alpha1'][] = 'doc-displaySetting';
|
||||
$lang->changelog['18.4.alpha1'][] = 'group-batchChangePackage';
|
||||
$lang->changelog['18.4.alpha1'][] = 'screen-annualData';
|
||||
$lang->changelog['18.4.alpha1'][] = 'screen-allAnnualData';
|
||||
$lang->changelog['18.4.alpha1'][] = 'pivot-preview';
|
||||
$lang->changelog['18.4.alpha1'][] = 'pivot-productSummary';
|
||||
$lang->changelog['18.4.alpha1'][] = 'pivot-projectDeviation';
|
||||
$lang->changelog['18.4.alpha1'][] = 'pivot-bugCreate';
|
||||
$lang->changelog['18.4.alpha1'][] = 'pivot-bugAssign';
|
||||
$lang->changelog['18.4.alpha1'][] = 'pivot-workload';
|
||||
$lang->changelog['18.4.alpha1'][] = 'chart-preview';
|
||||
$lang->changelog['18.4.alpha1'][] = 'api-addCatalog';
|
||||
$lang->changelog['18.4.alpha1'][] = 'api-editCatalog';
|
||||
$lang->changelog['18.4.alpha1'][] = 'api-deleteCatalog';
|
||||
|
||||
+81
-81
@@ -128,86 +128,86 @@ $lang->privlang->parent = 'Module/Package';
|
||||
$lang->group->copyOptions['copyPriv'] = 'Rechte kopieren';
|
||||
$lang->group->copyOptions['copyUser'] = 'Benutzer kopieren';
|
||||
|
||||
$lang->group->versions[''] = 'Verlauf';
|
||||
$lang->group->versions['18_4'] = 'ZenTao18.4';
|
||||
$lang->group->versions['18_3'] = 'ZenTao18.3';
|
||||
$lang->group->versions['18_2'] = 'ZenTao18.2';
|
||||
$lang->group->versions['18_1'] = 'ZenTao18.1';
|
||||
$lang->group->versions['18_0'] = 'ZenTao18.0';
|
||||
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
|
||||
$lang->group->versions['17_6'] = 'ZenTao17.6';
|
||||
$lang->group->versions['17_5'] = 'ZenTao17.5';
|
||||
$lang->group->versions['17_4'] = 'ZenTao17.4';
|
||||
$lang->group->versions['17_3'] = 'ZenTao17.3';
|
||||
$lang->group->versions['17_2'] = 'ZenTao17.2';
|
||||
$lang->group->versions['17_1'] = 'ZenTao17.1';
|
||||
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
|
||||
$lang->group->versions['16_4'] = 'ZenTao16.4';
|
||||
$lang->group->versions['16_3'] = 'ZenTao16.3';
|
||||
$lang->group->versions['16_2'] = 'ZenTao16.2';
|
||||
$lang->group->versions['16_1'] = 'ZenTao16.1';
|
||||
$lang->group->versions['16_0'] = 'ZenTao16.0';
|
||||
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
|
||||
$lang->group->versions['15_8'] = 'ZenTao15.8';
|
||||
$lang->group->versions['15_7'] = 'ZenTao15.7';
|
||||
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
|
||||
$lang->group->versions['12_5'] = 'ZenTao12.5';
|
||||
$lang->group->versions['12_3'] = 'ZenTao12.3';
|
||||
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
|
||||
$lang->group->versions['10_6'] = 'ZenTao10.6';
|
||||
$lang->group->versions['10_1'] = 'ZenTao10.1';
|
||||
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
|
||||
$lang->group->versions['9_8'] = 'ZenTao9.8';
|
||||
$lang->group->versions['9_6'] = 'ZenTao9.6';
|
||||
$lang->group->versions['9_5'] = 'ZenTao9.5';
|
||||
$lang->group->versions['9_2'] = 'ZenTao9.2';
|
||||
$lang->group->versions['9_1'] = 'ZenTao9.1';
|
||||
$lang->group->versions['9_0'] = 'ZenTao9.0';
|
||||
$lang->group->versions['8_4'] = 'ZenTao8.4';
|
||||
$lang->group->versions['8_3'] = 'ZenTao8.3';
|
||||
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
|
||||
$lang->group->versions['8_0'] = 'ZenTao8.0';
|
||||
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
|
||||
$lang->group->versions['7_3'] = 'ZenTao7.3';
|
||||
$lang->group->versions['7_2'] = 'ZenTao7.2';
|
||||
$lang->group->versions['7_1'] = 'ZenTao7.1';
|
||||
$lang->group->versions['6_4'] = 'ZenTao6.4';
|
||||
$lang->group->versions['6_3'] = 'ZenTao6.3';
|
||||
$lang->group->versions['6_2'] = 'ZenTao6.2';
|
||||
$lang->group->versions['6_1'] = 'ZenTao6.1';
|
||||
$lang->group->versions['5_3'] = 'ZenTao5.3';
|
||||
$lang->group->versions['5_1'] = 'ZenTao5.1';
|
||||
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
|
||||
$lang->group->versions['4_1'] = 'ZenTao4.1';
|
||||
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
|
||||
$lang->group->versions['4_0'] = 'ZenTao4.0';
|
||||
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
|
||||
$lang->group->versions['3_3'] = 'ZenTao3.3';
|
||||
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
|
||||
$lang->group->versions['3_2'] = 'ZenTao3.2';
|
||||
$lang->group->versions['3_1'] = 'ZenTao3.1';
|
||||
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
|
||||
$lang->group->versions['2_4'] = 'ZenTao2.4';
|
||||
$lang->group->versions['2_3'] = 'ZenTao2.3';
|
||||
$lang->group->versions['2_2'] = 'ZenTao2.2';
|
||||
$lang->group->versions['2_1'] = 'ZenTao2.1';
|
||||
$lang->group->versions['2_0'] = 'ZenTao2.0';
|
||||
$lang->group->versions['1_5'] = 'ZenTao1.5';
|
||||
$lang->group->versions['1_4'] = 'ZenTao1.4';
|
||||
$lang->group->versions['1_3'] = 'ZenTao1.3';
|
||||
$lang->group->versions['1_2'] = 'ZenTao1.2';
|
||||
$lang->group->versions['1_1'] = 'ZenTao1.1';
|
||||
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
|
||||
$lang->group->versions[''] = 'Verlauf';
|
||||
$lang->group->versions['18_4_alpha1'] = 'ZenTao18.4.alpha1';
|
||||
$lang->group->versions['18_3'] = 'ZenTao18.3';
|
||||
$lang->group->versions['18_2'] = 'ZenTao18.2';
|
||||
$lang->group->versions['18_1'] = 'ZenTao18.1';
|
||||
$lang->group->versions['18_0'] = 'ZenTao18.0';
|
||||
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
|
||||
$lang->group->versions['17_6'] = 'ZenTao17.6';
|
||||
$lang->group->versions['17_5'] = 'ZenTao17.5';
|
||||
$lang->group->versions['17_4'] = 'ZenTao17.4';
|
||||
$lang->group->versions['17_3'] = 'ZenTao17.3';
|
||||
$lang->group->versions['17_2'] = 'ZenTao17.2';
|
||||
$lang->group->versions['17_1'] = 'ZenTao17.1';
|
||||
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
|
||||
$lang->group->versions['16_4'] = 'ZenTao16.4';
|
||||
$lang->group->versions['16_3'] = 'ZenTao16.3';
|
||||
$lang->group->versions['16_2'] = 'ZenTao16.2';
|
||||
$lang->group->versions['16_1'] = 'ZenTao16.1';
|
||||
$lang->group->versions['16_0'] = 'ZenTao16.0';
|
||||
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
|
||||
$lang->group->versions['15_8'] = 'ZenTao15.8';
|
||||
$lang->group->versions['15_7'] = 'ZenTao15.7';
|
||||
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
|
||||
$lang->group->versions['12_5'] = 'ZenTao12.5';
|
||||
$lang->group->versions['12_3'] = 'ZenTao12.3';
|
||||
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
|
||||
$lang->group->versions['10_6'] = 'ZenTao10.6';
|
||||
$lang->group->versions['10_1'] = 'ZenTao10.1';
|
||||
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
|
||||
$lang->group->versions['9_8'] = 'ZenTao9.8';
|
||||
$lang->group->versions['9_6'] = 'ZenTao9.6';
|
||||
$lang->group->versions['9_5'] = 'ZenTao9.5';
|
||||
$lang->group->versions['9_2'] = 'ZenTao9.2';
|
||||
$lang->group->versions['9_1'] = 'ZenTao9.1';
|
||||
$lang->group->versions['9_0'] = 'ZenTao9.0';
|
||||
$lang->group->versions['8_4'] = 'ZenTao8.4';
|
||||
$lang->group->versions['8_3'] = 'ZenTao8.3';
|
||||
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
|
||||
$lang->group->versions['8_0'] = 'ZenTao8.0';
|
||||
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
|
||||
$lang->group->versions['7_3'] = 'ZenTao7.3';
|
||||
$lang->group->versions['7_2'] = 'ZenTao7.2';
|
||||
$lang->group->versions['7_1'] = 'ZenTao7.1';
|
||||
$lang->group->versions['6_4'] = 'ZenTao6.4';
|
||||
$lang->group->versions['6_3'] = 'ZenTao6.3';
|
||||
$lang->group->versions['6_2'] = 'ZenTao6.2';
|
||||
$lang->group->versions['6_1'] = 'ZenTao6.1';
|
||||
$lang->group->versions['5_3'] = 'ZenTao5.3';
|
||||
$lang->group->versions['5_1'] = 'ZenTao5.1';
|
||||
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
|
||||
$lang->group->versions['4_1'] = 'ZenTao4.1';
|
||||
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
|
||||
$lang->group->versions['4_0'] = 'ZenTao4.0';
|
||||
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
|
||||
$lang->group->versions['3_3'] = 'ZenTao3.3';
|
||||
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
|
||||
$lang->group->versions['3_2'] = 'ZenTao3.2';
|
||||
$lang->group->versions['3_1'] = 'ZenTao3.1';
|
||||
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
|
||||
$lang->group->versions['2_4'] = 'ZenTao2.4';
|
||||
$lang->group->versions['2_3'] = 'ZenTao2.3';
|
||||
$lang->group->versions['2_2'] = 'ZenTao2.2';
|
||||
$lang->group->versions['2_1'] = 'ZenTao2.1';
|
||||
$lang->group->versions['2_0'] = 'ZenTao2.0';
|
||||
$lang->group->versions['1_5'] = 'ZenTao1.5';
|
||||
$lang->group->versions['1_4'] = 'ZenTao1.4';
|
||||
$lang->group->versions['1_3'] = 'ZenTao1.3';
|
||||
$lang->group->versions['1_2'] = 'ZenTao1.2';
|
||||
$lang->group->versions['1_1'] = 'ZenTao1.1';
|
||||
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
|
||||
|
||||
include (dirname(__FILE__) . '/resource.php');
|
||||
|
||||
+81
-81
@@ -128,86 +128,86 @@ $lang->privlang->parent = 'Module/Package';
|
||||
$lang->group->copyOptions['copyPriv'] = 'Copy Privileges';
|
||||
$lang->group->copyOptions['copyUser'] = 'Copy Users';
|
||||
|
||||
$lang->group->versions[''] = 'History';
|
||||
$lang->group->versions['18_4'] = 'ZenTao18.4';
|
||||
$lang->group->versions['18_3'] = 'ZenTao18.3';
|
||||
$lang->group->versions['18_2'] = 'ZenTao18.2';
|
||||
$lang->group->versions['18_1'] = 'ZenTao18.1';
|
||||
$lang->group->versions['18_0'] = 'ZenTao18.0';
|
||||
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
|
||||
$lang->group->versions['17_6'] = 'ZenTao17.6';
|
||||
$lang->group->versions['17_5'] = 'ZenTao17.5';
|
||||
$lang->group->versions['17_4'] = 'ZenTao17.4';
|
||||
$lang->group->versions['17_3'] = 'ZenTao17.3';
|
||||
$lang->group->versions['17_2'] = 'ZenTao17.2';
|
||||
$lang->group->versions['17_1'] = 'ZenTao17.1';
|
||||
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
|
||||
$lang->group->versions['16_4'] = 'ZenTao16.4';
|
||||
$lang->group->versions['16_3'] = 'ZenTao16.3';
|
||||
$lang->group->versions['16_2'] = 'ZenTao16.2';
|
||||
$lang->group->versions['16_1'] = 'ZenTao16.1';
|
||||
$lang->group->versions['16_0'] = 'ZenTao16.0';
|
||||
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
|
||||
$lang->group->versions['15_8'] = 'ZenTao15.8';
|
||||
$lang->group->versions['15_7'] = 'ZenTao15.7';
|
||||
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
|
||||
$lang->group->versions['12_5'] = 'ZenTao12.5';
|
||||
$lang->group->versions['12_3'] = 'ZenTao12.3';
|
||||
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
|
||||
$lang->group->versions['10_6'] = 'ZenTao10.6';
|
||||
$lang->group->versions['10_1'] = 'ZenTao10.1';
|
||||
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
|
||||
$lang->group->versions['9_8'] = 'ZenTao9.8';
|
||||
$lang->group->versions['9_6'] = 'ZenTao9.6';
|
||||
$lang->group->versions['9_5'] = 'ZenTao9.5';
|
||||
$lang->group->versions['9_2'] = 'ZenTao9.2';
|
||||
$lang->group->versions['9_1'] = 'ZenTao9.1';
|
||||
$lang->group->versions['9_0'] = 'ZenTao9.0';
|
||||
$lang->group->versions['8_4'] = 'ZenTao8.4';
|
||||
$lang->group->versions['8_3'] = 'ZenTao8.3';
|
||||
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
|
||||
$lang->group->versions['8_0'] = 'ZenTao8.0';
|
||||
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
|
||||
$lang->group->versions['7_3'] = 'ZenTao7.3';
|
||||
$lang->group->versions['7_2'] = 'ZenTao7.2';
|
||||
$lang->group->versions['7_1'] = 'ZenTao7.1';
|
||||
$lang->group->versions['6_4'] = 'ZenTao6.4';
|
||||
$lang->group->versions['6_3'] = 'ZenTao6.3';
|
||||
$lang->group->versions['6_2'] = 'ZenTao6.2';
|
||||
$lang->group->versions['6_1'] = 'ZenTao6.1';
|
||||
$lang->group->versions['5_3'] = 'ZenTao5.3';
|
||||
$lang->group->versions['5_1'] = 'ZenTao5.1';
|
||||
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
|
||||
$lang->group->versions['4_1'] = 'ZenTao4.1';
|
||||
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
|
||||
$lang->group->versions['4_0'] = 'ZenTao4.0';
|
||||
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
|
||||
$lang->group->versions['3_3'] = 'ZenTao3.3';
|
||||
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
|
||||
$lang->group->versions['3_2'] = 'ZenTao3.2';
|
||||
$lang->group->versions['3_1'] = 'ZenTao3.1';
|
||||
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
|
||||
$lang->group->versions['2_4'] = 'ZenTao2.4';
|
||||
$lang->group->versions['2_3'] = 'ZenTao2.3';
|
||||
$lang->group->versions['2_2'] = 'ZenTao2.2';
|
||||
$lang->group->versions['2_1'] = 'ZenTao2.1';
|
||||
$lang->group->versions['2_0'] = 'ZenTao2.0';
|
||||
$lang->group->versions['1_5'] = 'ZenTao1.5';
|
||||
$lang->group->versions['1_4'] = 'ZenTao1.4';
|
||||
$lang->group->versions['1_3'] = 'ZenTao1.3';
|
||||
$lang->group->versions['1_2'] = 'ZenTao1.2';
|
||||
$lang->group->versions['1_1'] = 'ZenTao1.1';
|
||||
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
|
||||
$lang->group->versions[''] = 'History';
|
||||
$lang->group->versions['18_4_alpha1'] = 'ZenTao18.4.alpha1';
|
||||
$lang->group->versions['18_3'] = 'ZenTao18.3';
|
||||
$lang->group->versions['18_2'] = 'ZenTao18.2';
|
||||
$lang->group->versions['18_1'] = 'ZenTao18.1';
|
||||
$lang->group->versions['18_0'] = 'ZenTao18.0';
|
||||
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
|
||||
$lang->group->versions['17_6'] = 'ZenTao17.6';
|
||||
$lang->group->versions['17_5'] = 'ZenTao17.5';
|
||||
$lang->group->versions['17_4'] = 'ZenTao17.4';
|
||||
$lang->group->versions['17_3'] = 'ZenTao17.3';
|
||||
$lang->group->versions['17_2'] = 'ZenTao17.2';
|
||||
$lang->group->versions['17_1'] = 'ZenTao17.1';
|
||||
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
|
||||
$lang->group->versions['16_4'] = 'ZenTao16.4';
|
||||
$lang->group->versions['16_3'] = 'ZenTao16.3';
|
||||
$lang->group->versions['16_2'] = 'ZenTao16.2';
|
||||
$lang->group->versions['16_1'] = 'ZenTao16.1';
|
||||
$lang->group->versions['16_0'] = 'ZenTao16.0';
|
||||
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
|
||||
$lang->group->versions['15_8'] = 'ZenTao15.8';
|
||||
$lang->group->versions['15_7'] = 'ZenTao15.7';
|
||||
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
|
||||
$lang->group->versions['12_5'] = 'ZenTao12.5';
|
||||
$lang->group->versions['12_3'] = 'ZenTao12.3';
|
||||
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
|
||||
$lang->group->versions['10_6'] = 'ZenTao10.6';
|
||||
$lang->group->versions['10_1'] = 'ZenTao10.1';
|
||||
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
|
||||
$lang->group->versions['9_8'] = 'ZenTao9.8';
|
||||
$lang->group->versions['9_6'] = 'ZenTao9.6';
|
||||
$lang->group->versions['9_5'] = 'ZenTao9.5';
|
||||
$lang->group->versions['9_2'] = 'ZenTao9.2';
|
||||
$lang->group->versions['9_1'] = 'ZenTao9.1';
|
||||
$lang->group->versions['9_0'] = 'ZenTao9.0';
|
||||
$lang->group->versions['8_4'] = 'ZenTao8.4';
|
||||
$lang->group->versions['8_3'] = 'ZenTao8.3';
|
||||
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
|
||||
$lang->group->versions['8_0'] = 'ZenTao8.0';
|
||||
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
|
||||
$lang->group->versions['7_3'] = 'ZenTao7.3';
|
||||
$lang->group->versions['7_2'] = 'ZenTao7.2';
|
||||
$lang->group->versions['7_1'] = 'ZenTao7.1';
|
||||
$lang->group->versions['6_4'] = 'ZenTao6.4';
|
||||
$lang->group->versions['6_3'] = 'ZenTao6.3';
|
||||
$lang->group->versions['6_2'] = 'ZenTao6.2';
|
||||
$lang->group->versions['6_1'] = 'ZenTao6.1';
|
||||
$lang->group->versions['5_3'] = 'ZenTao5.3';
|
||||
$lang->group->versions['5_1'] = 'ZenTao5.1';
|
||||
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
|
||||
$lang->group->versions['4_1'] = 'ZenTao4.1';
|
||||
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
|
||||
$lang->group->versions['4_0'] = 'ZenTao4.0';
|
||||
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
|
||||
$lang->group->versions['3_3'] = 'ZenTao3.3';
|
||||
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
|
||||
$lang->group->versions['3_2'] = 'ZenTao3.2';
|
||||
$lang->group->versions['3_1'] = 'ZenTao3.1';
|
||||
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
|
||||
$lang->group->versions['2_4'] = 'ZenTao2.4';
|
||||
$lang->group->versions['2_3'] = 'ZenTao2.3';
|
||||
$lang->group->versions['2_2'] = 'ZenTao2.2';
|
||||
$lang->group->versions['2_1'] = 'ZenTao2.1';
|
||||
$lang->group->versions['2_0'] = 'ZenTao2.0';
|
||||
$lang->group->versions['1_5'] = 'ZenTao1.5';
|
||||
$lang->group->versions['1_4'] = 'ZenTao1.4';
|
||||
$lang->group->versions['1_3'] = 'ZenTao1.3';
|
||||
$lang->group->versions['1_2'] = 'ZenTao1.2';
|
||||
$lang->group->versions['1_1'] = 'ZenTao1.1';
|
||||
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
|
||||
|
||||
include (dirname(__FILE__) . '/resource.php');
|
||||
|
||||
+81
-81
@@ -128,86 +128,86 @@ $lang->privlang->parent = 'Module/Package';
|
||||
$lang->group->copyOptions['copyPriv'] = 'Copier Privilèges';
|
||||
$lang->group->copyOptions['copyUser'] = 'Copier Utilisateurs';
|
||||
|
||||
$lang->group->versions[''] = 'History';
|
||||
$lang->group->versions['18_4'] = 'ZenTao18.4';
|
||||
$lang->group->versions['18_3'] = 'ZenTao18.3';
|
||||
$lang->group->versions['18_2'] = 'ZenTao18.2';
|
||||
$lang->group->versions['18_1'] = 'ZenTao18.1';
|
||||
$lang->group->versions['18_0'] = 'ZenTao18.0';
|
||||
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
|
||||
$lang->group->versions['17_6'] = 'ZenTao17.6';
|
||||
$lang->group->versions['17_5'] = 'ZenTao17.5';
|
||||
$lang->group->versions['17_4'] = 'ZenTao17.4';
|
||||
$lang->group->versions['17_3'] = 'ZenTao17.3';
|
||||
$lang->group->versions['17_2'] = 'ZenTao17.2';
|
||||
$lang->group->versions['17_1'] = 'ZenTao17.1';
|
||||
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
|
||||
$lang->group->versions['16_4'] = 'ZenTao16.4';
|
||||
$lang->group->versions['16_3'] = 'ZenTao16.3';
|
||||
$lang->group->versions['16_2'] = 'ZenTao16.2';
|
||||
$lang->group->versions['16_1'] = 'ZenTao16.1';
|
||||
$lang->group->versions['16_0'] = 'ZenTao16.0';
|
||||
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
|
||||
$lang->group->versions['15_8'] = 'ZenTao15.8';
|
||||
$lang->group->versions['15_7'] = 'ZenTao15.7';
|
||||
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
|
||||
$lang->group->versions['12_5'] = 'ZenTao12.5';
|
||||
$lang->group->versions['12_3'] = 'ZenTao12.3';
|
||||
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
|
||||
$lang->group->versions['10_6'] = 'ZenTao10.6';
|
||||
$lang->group->versions['10_1'] = 'ZenTao10.1';
|
||||
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
|
||||
$lang->group->versions['9_8'] = 'ZenTao9.8';
|
||||
$lang->group->versions['9_6'] = 'ZenTao9.6';
|
||||
$lang->group->versions['9_5'] = 'ZenTao9.5';
|
||||
$lang->group->versions['9_2'] = 'ZenTao9.2';
|
||||
$lang->group->versions['9_1'] = 'ZenTao9.1';
|
||||
$lang->group->versions['9_0'] = 'ZenTao9.0';
|
||||
$lang->group->versions['8_4'] = 'ZenTao8.4';
|
||||
$lang->group->versions['8_3'] = 'ZenTao8.3';
|
||||
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
|
||||
$lang->group->versions['8_0'] = 'ZenTao8.0';
|
||||
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
|
||||
$lang->group->versions['7_3'] = 'ZenTao7.3';
|
||||
$lang->group->versions['7_2'] = 'ZenTao7.2';
|
||||
$lang->group->versions['7_1'] = 'ZenTao7.1';
|
||||
$lang->group->versions['6_4'] = 'ZenTao6.4';
|
||||
$lang->group->versions['6_3'] = 'ZenTao6.3';
|
||||
$lang->group->versions['6_2'] = 'ZenTao6.2';
|
||||
$lang->group->versions['6_1'] = 'ZenTao6.1';
|
||||
$lang->group->versions['5_3'] = 'ZenTao5.3';
|
||||
$lang->group->versions['5_1'] = 'ZenTao5.1';
|
||||
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
|
||||
$lang->group->versions['4_1'] = 'ZenTao4.1';
|
||||
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
|
||||
$lang->group->versions['4_0'] = 'ZenTao4.0';
|
||||
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
|
||||
$lang->group->versions['3_3'] = 'ZenTao3.3';
|
||||
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
|
||||
$lang->group->versions['3_2'] = 'ZenTao3.2';
|
||||
$lang->group->versions['3_1'] = 'ZenTao3.1';
|
||||
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
|
||||
$lang->group->versions['2_4'] = 'ZenTao2.4';
|
||||
$lang->group->versions['2_3'] = 'ZenTao2.3';
|
||||
$lang->group->versions['2_2'] = 'ZenTao2.2';
|
||||
$lang->group->versions['2_1'] = 'ZenTao2.1';
|
||||
$lang->group->versions['2_0'] = 'ZenTao2.0';
|
||||
$lang->group->versions['1_5'] = 'ZenTao1.5';
|
||||
$lang->group->versions['1_4'] = 'ZenTao1.4';
|
||||
$lang->group->versions['1_3'] = 'ZenTao1.3';
|
||||
$lang->group->versions['1_2'] = 'ZenTao1.2';
|
||||
$lang->group->versions['1_1'] = 'ZenTao1.1';
|
||||
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
|
||||
$lang->group->versions[''] = 'History';
|
||||
$lang->group->versions['18_4_alpha1'] = 'ZenTao18.4.alpha1';
|
||||
$lang->group->versions['18_3'] = 'ZenTao18.3';
|
||||
$lang->group->versions['18_2'] = 'ZenTao18.2';
|
||||
$lang->group->versions['18_1'] = 'ZenTao18.1';
|
||||
$lang->group->versions['18_0'] = 'ZenTao18.0';
|
||||
$lang->group->versions['18_0_beta3'] = 'ZenTao18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = 'ZenTao18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = 'ZenTao18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = 'ZenTao17.6.2';
|
||||
$lang->group->versions['17_6'] = 'ZenTao17.6';
|
||||
$lang->group->versions['17_5'] = 'ZenTao17.5';
|
||||
$lang->group->versions['17_4'] = 'ZenTao17.4';
|
||||
$lang->group->versions['17_3'] = 'ZenTao17.3';
|
||||
$lang->group->versions['17_2'] = 'ZenTao17.2';
|
||||
$lang->group->versions['17_1'] = 'ZenTao17.1';
|
||||
$lang->group->versions['17_0_beta2'] = 'ZenTao17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = 'ZenTao17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = 'ZenTao16.5.beta1';
|
||||
$lang->group->versions['16_4'] = 'ZenTao16.4';
|
||||
$lang->group->versions['16_3'] = 'ZenTao16.3';
|
||||
$lang->group->versions['16_2'] = 'ZenTao16.2';
|
||||
$lang->group->versions['16_1'] = 'ZenTao16.1';
|
||||
$lang->group->versions['16_0'] = 'ZenTao16.0';
|
||||
$lang->group->versions['16_0_beta1'] = 'ZenTao16.0.beta1';
|
||||
$lang->group->versions['15_8'] = 'ZenTao15.8';
|
||||
$lang->group->versions['15_7'] = 'ZenTao15.7';
|
||||
$lang->group->versions['15_0_rc1'] = 'ZenTao15.0.rc1';
|
||||
$lang->group->versions['12_5'] = 'ZenTao12.5';
|
||||
$lang->group->versions['12_3'] = 'ZenTao12.3';
|
||||
$lang->group->versions['11_6_2'] = 'ZenTao11.6.2';
|
||||
$lang->group->versions['10_6'] = 'ZenTao10.6';
|
||||
$lang->group->versions['10_1'] = 'ZenTao10.1';
|
||||
$lang->group->versions['10_0_alpha'] = 'ZenTao10.0.alpha';
|
||||
$lang->group->versions['9_8'] = 'ZenTao9.8';
|
||||
$lang->group->versions['9_6'] = 'ZenTao9.6';
|
||||
$lang->group->versions['9_5'] = 'ZenTao9.5';
|
||||
$lang->group->versions['9_2'] = 'ZenTao9.2';
|
||||
$lang->group->versions['9_1'] = 'ZenTao9.1';
|
||||
$lang->group->versions['9_0'] = 'ZenTao9.0';
|
||||
$lang->group->versions['8_4'] = 'ZenTao8.4';
|
||||
$lang->group->versions['8_3'] = 'ZenTao8.3';
|
||||
$lang->group->versions['8_2_beta'] = 'ZenTao8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = 'ZenTao8.0.1';
|
||||
$lang->group->versions['8_0'] = 'ZenTao8.0';
|
||||
$lang->group->versions['7_4_beta'] = 'ZenTao7.4.beta';
|
||||
$lang->group->versions['7_3'] = 'ZenTao7.3';
|
||||
$lang->group->versions['7_2'] = 'ZenTao7.2';
|
||||
$lang->group->versions['7_1'] = 'ZenTao7.1';
|
||||
$lang->group->versions['6_4'] = 'ZenTao6.4';
|
||||
$lang->group->versions['6_3'] = 'ZenTao6.3';
|
||||
$lang->group->versions['6_2'] = 'ZenTao6.2';
|
||||
$lang->group->versions['6_1'] = 'ZenTao6.1';
|
||||
$lang->group->versions['5_3'] = 'ZenTao5.3';
|
||||
$lang->group->versions['5_1'] = 'ZenTao5.1';
|
||||
$lang->group->versions['5_0_beta2'] = 'ZenTao5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = 'ZenTao5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = 'ZenTao4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = 'ZenTao4.2.beta';
|
||||
$lang->group->versions['4_1'] = 'ZenTao4.1';
|
||||
$lang->group->versions['4_0_1'] = 'ZenTao4.0.1';
|
||||
$lang->group->versions['4_0'] = 'ZenTao4.0';
|
||||
$lang->group->versions['4_0_beta2'] = 'ZenTao4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = 'ZenTao4.0.beta1';
|
||||
$lang->group->versions['3_3'] = 'ZenTao3.3';
|
||||
$lang->group->versions['3_2_1'] = 'ZenTao3.2.1';
|
||||
$lang->group->versions['3_2'] = 'ZenTao3.2';
|
||||
$lang->group->versions['3_1'] = 'ZenTao3.1';
|
||||
$lang->group->versions['3_0_beta2'] = 'ZenTao3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = 'ZenTao3.0.beta1';
|
||||
$lang->group->versions['2_4'] = 'ZenTao2.4';
|
||||
$lang->group->versions['2_3'] = 'ZenTao2.3';
|
||||
$lang->group->versions['2_2'] = 'ZenTao2.2';
|
||||
$lang->group->versions['2_1'] = 'ZenTao2.1';
|
||||
$lang->group->versions['2_0'] = 'ZenTao2.0';
|
||||
$lang->group->versions['1_5'] = 'ZenTao1.5';
|
||||
$lang->group->versions['1_4'] = 'ZenTao1.4';
|
||||
$lang->group->versions['1_3'] = 'ZenTao1.3';
|
||||
$lang->group->versions['1_2'] = 'ZenTao1.2';
|
||||
$lang->group->versions['1_1'] = 'ZenTao1.1';
|
||||
$lang->group->versions['1_0_1'] = 'ZenTao1.0.1';
|
||||
|
||||
include (dirname(__FILE__) . '/resource.php');
|
||||
|
||||
@@ -2062,7 +2062,6 @@ $lang->resource->workestimation = new stdclass();
|
||||
$lang->resource->gapanalysis = new stdclass();
|
||||
$lang->resource->executionview = new stdclass();
|
||||
$lang->resource->managespace = new stdclass();
|
||||
$lang->resource->managespace = new stdclass();
|
||||
$lang->resource->systemteam = new stdclass();
|
||||
$lang->resource->systemschedule = new stdclass();
|
||||
$lang->resource->systemeffort = new stdclass();
|
||||
@@ -2112,6 +2111,7 @@ if(!$inUpgrade)
|
||||
{
|
||||
unset($lang->resource->program);
|
||||
unset($lang->resource->project->programTitle);
|
||||
unset($lang->resource->product->manageLine);
|
||||
}
|
||||
if(!helper::hasFeature('waterfall') and !helper::hasFeature('waterfallplus'))
|
||||
{
|
||||
|
||||
+81
-81
@@ -128,86 +128,86 @@ $lang->privlang->parent = '所属模块/权限包';
|
||||
$lang->group->copyOptions['copyPriv'] = '复制权限';
|
||||
$lang->group->copyOptions['copyUser'] = '复制用户';
|
||||
|
||||
$lang->group->versions[''] = '修改历史';
|
||||
$lang->group->versions['18_4'] = '禅道18.4';
|
||||
$lang->group->versions['18_3'] = '禅道18.3';
|
||||
$lang->group->versions['18_2'] = '禅道18.2';
|
||||
$lang->group->versions['18_1'] = '禅道18.1';
|
||||
$lang->group->versions['18_0'] = '禅道18.0';
|
||||
$lang->group->versions['18_0_beta3'] = '禅道18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = '禅道18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = '禅道18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = '禅道17.6.2';
|
||||
$lang->group->versions['17_6'] = '禅道17.6';
|
||||
$lang->group->versions['17_5'] = '禅道17.5';
|
||||
$lang->group->versions['17_4'] = '禅道17.4';
|
||||
$lang->group->versions['17_3'] = '禅道17.3';
|
||||
$lang->group->versions['17_2'] = '禅道17.2';
|
||||
$lang->group->versions['17_1'] = '禅道17.1';
|
||||
$lang->group->versions['17_0_beta2'] = '禅道17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = '禅道17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = '禅道16.5.beta1';
|
||||
$lang->group->versions['16_4'] = '禅道16.4';
|
||||
$lang->group->versions['16_3'] = '禅道16.3';
|
||||
$lang->group->versions['16_2'] = '禅道16.2';
|
||||
$lang->group->versions['16_1'] = '禅道16.1';
|
||||
$lang->group->versions['16_0'] = '禅道16.0';
|
||||
$lang->group->versions['16_0_beta1'] = '禅道16.0.beta1';
|
||||
$lang->group->versions['15_8'] = '禅道15.8';
|
||||
$lang->group->versions['15_7'] = '禅道15.7';
|
||||
$lang->group->versions['15_0_rc1'] = '禅道15.0.rc1';
|
||||
$lang->group->versions['12_5'] = '禅道12.5';
|
||||
$lang->group->versions['12_3'] = '禅道12.3';
|
||||
$lang->group->versions['11_6_2'] = '禅道11.6.2';
|
||||
$lang->group->versions['10_6'] = '禅道10.6';
|
||||
$lang->group->versions['10_1'] = '禅道10.1';
|
||||
$lang->group->versions['10_0_alpha'] = '禅道10.0.alpha';
|
||||
$lang->group->versions['9_8'] = '禅道9.8';
|
||||
$lang->group->versions['9_6'] = '禅道9.6';
|
||||
$lang->group->versions['9_5'] = '禅道9.5';
|
||||
$lang->group->versions['9_2'] = '禅道9.2';
|
||||
$lang->group->versions['9_1'] = '禅道9.1';
|
||||
$lang->group->versions['9_0'] = '禅道9.0';
|
||||
$lang->group->versions['8_4'] = '禅道8.4';
|
||||
$lang->group->versions['8_3'] = '禅道8.3';
|
||||
$lang->group->versions['8_2_beta'] = '禅道8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = '禅道8.0.1';
|
||||
$lang->group->versions['8_0'] = '禅道8.0';
|
||||
$lang->group->versions['7_4_beta'] = '禅道7.4.beta';
|
||||
$lang->group->versions['7_3'] = '禅道7.3';
|
||||
$lang->group->versions['7_2'] = '禅道7.2';
|
||||
$lang->group->versions['7_1'] = '禅道7.1';
|
||||
$lang->group->versions['6_4'] = '禅道6.4';
|
||||
$lang->group->versions['6_3'] = '禅道6.3';
|
||||
$lang->group->versions['6_2'] = '禅道6.2';
|
||||
$lang->group->versions['6_1'] = '禅道6.1';
|
||||
$lang->group->versions['5_3'] = '禅道5.3';
|
||||
$lang->group->versions['5_1'] = '禅道5.1';
|
||||
$lang->group->versions['5_0_beta2'] = '禅道5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = '禅道5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = '禅道4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = '禅道4.2.beta';
|
||||
$lang->group->versions['4_1'] = '禅道4.1';
|
||||
$lang->group->versions['4_0_1'] = '禅道4.0.1';
|
||||
$lang->group->versions['4_0'] = '禅道4.0';
|
||||
$lang->group->versions['4_0_beta2'] = '禅道4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = '禅道4.0.beta1';
|
||||
$lang->group->versions['3_3'] = '禅道3.3';
|
||||
$lang->group->versions['3_2_1'] = '禅道3.2.1';
|
||||
$lang->group->versions['3_2'] = '禅道3.2';
|
||||
$lang->group->versions['3_1'] = '禅道3.1';
|
||||
$lang->group->versions['3_0_beta2'] = '禅道3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = '禅道3.0.beta1';
|
||||
$lang->group->versions['2_4'] = '禅道2.4';
|
||||
$lang->group->versions['2_3'] = '禅道2.3';
|
||||
$lang->group->versions['2_2'] = '禅道2.2';
|
||||
$lang->group->versions['2_1'] = '禅道2.1';
|
||||
$lang->group->versions['2_0'] = '禅道2.0';
|
||||
$lang->group->versions['1_5'] = '禅道1.5';
|
||||
$lang->group->versions['1_4'] = '禅道1.4';
|
||||
$lang->group->versions['1_3'] = '禅道1.3';
|
||||
$lang->group->versions['1_2'] = '禅道1.2';
|
||||
$lang->group->versions['1_1'] = '禅道1.1';
|
||||
$lang->group->versions['1_0_1'] = '禅道1.0.1';
|
||||
$lang->group->versions[''] = '修改历史';
|
||||
$lang->group->versions['18_4_alpha1'] = '禅道18.4.alpha1';
|
||||
$lang->group->versions['18_3'] = '禅道18.3';
|
||||
$lang->group->versions['18_2'] = '禅道18.2';
|
||||
$lang->group->versions['18_1'] = '禅道18.1';
|
||||
$lang->group->versions['18_0'] = '禅道18.0';
|
||||
$lang->group->versions['18_0_beta3'] = '禅道18.0.beta3';
|
||||
$lang->group->versions['18_0_beta2'] = '禅道18.0.beta2';
|
||||
$lang->group->versions['18_0_beta1'] = '禅道18.0.beta1';
|
||||
$lang->group->versions['17_6_2'] = '禅道17.6.2';
|
||||
$lang->group->versions['17_6'] = '禅道17.6';
|
||||
$lang->group->versions['17_5'] = '禅道17.5';
|
||||
$lang->group->versions['17_4'] = '禅道17.4';
|
||||
$lang->group->versions['17_3'] = '禅道17.3';
|
||||
$lang->group->versions['17_2'] = '禅道17.2';
|
||||
$lang->group->versions['17_1'] = '禅道17.1';
|
||||
$lang->group->versions['17_0_beta2'] = '禅道17.0.beta2';
|
||||
$lang->group->versions['17_0_beta1'] = '禅道17.0.beta1';
|
||||
$lang->group->versions['16_5_beta1'] = '禅道16.5.beta1';
|
||||
$lang->group->versions['16_4'] = '禅道16.4';
|
||||
$lang->group->versions['16_3'] = '禅道16.3';
|
||||
$lang->group->versions['16_2'] = '禅道16.2';
|
||||
$lang->group->versions['16_1'] = '禅道16.1';
|
||||
$lang->group->versions['16_0'] = '禅道16.0';
|
||||
$lang->group->versions['16_0_beta1'] = '禅道16.0.beta1';
|
||||
$lang->group->versions['15_8'] = '禅道15.8';
|
||||
$lang->group->versions['15_7'] = '禅道15.7';
|
||||
$lang->group->versions['15_0_rc1'] = '禅道15.0.rc1';
|
||||
$lang->group->versions['12_5'] = '禅道12.5';
|
||||
$lang->group->versions['12_3'] = '禅道12.3';
|
||||
$lang->group->versions['11_6_2'] = '禅道11.6.2';
|
||||
$lang->group->versions['10_6'] = '禅道10.6';
|
||||
$lang->group->versions['10_1'] = '禅道10.1';
|
||||
$lang->group->versions['10_0_alpha'] = '禅道10.0.alpha';
|
||||
$lang->group->versions['9_8'] = '禅道9.8';
|
||||
$lang->group->versions['9_6'] = '禅道9.6';
|
||||
$lang->group->versions['9_5'] = '禅道9.5';
|
||||
$lang->group->versions['9_2'] = '禅道9.2';
|
||||
$lang->group->versions['9_1'] = '禅道9.1';
|
||||
$lang->group->versions['9_0'] = '禅道9.0';
|
||||
$lang->group->versions['8_4'] = '禅道8.4';
|
||||
$lang->group->versions['8_3'] = '禅道8.3';
|
||||
$lang->group->versions['8_2_beta'] = '禅道8.2.beta';
|
||||
$lang->group->versions['8_0_1'] = '禅道8.0.1';
|
||||
$lang->group->versions['8_0'] = '禅道8.0';
|
||||
$lang->group->versions['7_4_beta'] = '禅道7.4.beta';
|
||||
$lang->group->versions['7_3'] = '禅道7.3';
|
||||
$lang->group->versions['7_2'] = '禅道7.2';
|
||||
$lang->group->versions['7_1'] = '禅道7.1';
|
||||
$lang->group->versions['6_4'] = '禅道6.4';
|
||||
$lang->group->versions['6_3'] = '禅道6.3';
|
||||
$lang->group->versions['6_2'] = '禅道6.2';
|
||||
$lang->group->versions['6_1'] = '禅道6.1';
|
||||
$lang->group->versions['5_3'] = '禅道5.3';
|
||||
$lang->group->versions['5_1'] = '禅道5.1';
|
||||
$lang->group->versions['5_0_beta2'] = '禅道5.0.beta2';
|
||||
$lang->group->versions['5_0_beta1'] = '禅道5.0.beta1';
|
||||
$lang->group->versions['4_3_beta'] = '禅道4.3.beta';
|
||||
$lang->group->versions['4_2_beta'] = '禅道4.2.beta';
|
||||
$lang->group->versions['4_1'] = '禅道4.1';
|
||||
$lang->group->versions['4_0_1'] = '禅道4.0.1';
|
||||
$lang->group->versions['4_0'] = '禅道4.0';
|
||||
$lang->group->versions['4_0_beta2'] = '禅道4.0.beta2';
|
||||
$lang->group->versions['4_0_beta1'] = '禅道4.0.beta1';
|
||||
$lang->group->versions['3_3'] = '禅道3.3';
|
||||
$lang->group->versions['3_2_1'] = '禅道3.2.1';
|
||||
$lang->group->versions['3_2'] = '禅道3.2';
|
||||
$lang->group->versions['3_1'] = '禅道3.1';
|
||||
$lang->group->versions['3_0_beta2'] = '禅道3.0.beta2';
|
||||
$lang->group->versions['3_0_beta1'] = '禅道3.0.beta1';
|
||||
$lang->group->versions['2_4'] = '禅道2.4';
|
||||
$lang->group->versions['2_3'] = '禅道2.3';
|
||||
$lang->group->versions['2_2'] = '禅道2.2';
|
||||
$lang->group->versions['2_1'] = '禅道2.1';
|
||||
$lang->group->versions['2_0'] = '禅道2.0';
|
||||
$lang->group->versions['1_5'] = '禅道1.5';
|
||||
$lang->group->versions['1_4'] = '禅道1.4';
|
||||
$lang->group->versions['1_3'] = '禅道1.3';
|
||||
$lang->group->versions['1_2'] = '禅道1.2';
|
||||
$lang->group->versions['1_1'] = '禅道1.1';
|
||||
$lang->group->versions['1_0_1'] = '禅道1.0.1';
|
||||
|
||||
include (dirname(__FILE__) . '/resource.php');
|
||||
|
||||
+13
-12
@@ -467,10 +467,11 @@ class groupModel extends model
|
||||
$privs[] = $data;
|
||||
}
|
||||
}
|
||||
$this->insertPrivs($privs);
|
||||
$depentedPrivs = $this->getPrivByIdList($depentedPrivs);
|
||||
foreach($depentedPrivs as $privID => $priv)
|
||||
{
|
||||
if(empty($_POST['actions'][$priv->module]) or in_array($priv->method, $_POST['actions'][$priv->module]))
|
||||
if(!empty($_POST['actions'][$priv->module]) and in_array($priv->method, $_POST['actions'][$priv->module]))
|
||||
{
|
||||
unset($depentedPrivs[$privID]);
|
||||
continue;
|
||||
@@ -481,7 +482,7 @@ class groupModel extends model
|
||||
$data->method = $priv->method;
|
||||
$this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec();
|
||||
}
|
||||
$recommendPrivs = $this->getPrivByIdList(zget($_POST, 'recommendPrivs'));
|
||||
$recommendPrivs = $this->getPrivByIdList(zget($_POST, 'recommendPrivs', '0'));
|
||||
foreach($recommendPrivs as $privID => $priv)
|
||||
{
|
||||
if(in_array($priv->method, zget($_POST['actions'], $priv->module, array())))
|
||||
@@ -495,7 +496,6 @@ class groupModel extends model
|
||||
$data->method = $priv->method;
|
||||
$this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec();
|
||||
}
|
||||
$this->insertPrivs($privs);
|
||||
}
|
||||
return !empty($depentedPrivs) ? true : false;
|
||||
}
|
||||
@@ -1540,7 +1540,7 @@ class groupModel extends model
|
||||
if(empty($lang)) $lang = $this->app->getClientLang();
|
||||
$priv = $this->dao->select('t1.*,t2.`key`,t2.value,t2.desc')->from(TABLE_PRIV)->alias('t1')
|
||||
->leftJoin(TABLE_PRIVLANG)->alias('t2')->on('t1.id=t2.objectID')
|
||||
->where('t1.id')->eq($privID)
|
||||
->where('t1.id')->eq((int)$privID)
|
||||
->andWhere('t2.objectType')->eq('priv')
|
||||
->andWhere('t2.lang')->eq($lang)
|
||||
->fetch();
|
||||
@@ -1681,6 +1681,7 @@ class groupModel extends model
|
||||
{
|
||||
$privList = array_merge($privList, zget($privs, $module, array()));
|
||||
}
|
||||
|
||||
return $privList;
|
||||
}
|
||||
|
||||
@@ -2237,8 +2238,8 @@ class groupModel extends model
|
||||
else
|
||||
{
|
||||
list($moduleName, $methodLang) = explode('-', $priv->key);
|
||||
if($moduleName == 'requirement') $moduleName = 'story';
|
||||
$this->app->loadLang($moduleName);
|
||||
$actualModule = $moduleName == 'requirement' ? 'story' : $moduleName;
|
||||
$this->app->loadLang($actualModule);
|
||||
|
||||
$hasLang = (!empty($moduleName) and !empty($methodLang) and isset($this->lang->resource->{$priv->module}) and isset($this->lang->resource->{$priv->module}->{$priv->method}));
|
||||
if(!$hasLang)
|
||||
@@ -2275,6 +2276,7 @@ class groupModel extends model
|
||||
{
|
||||
$key = "{$module}-{$method}";
|
||||
$priv = new stdclass();
|
||||
$priv->id = $key;
|
||||
$priv->module = $module;
|
||||
$priv->method = $method;
|
||||
$priv->action = $key;
|
||||
@@ -2297,6 +2299,7 @@ class groupModel extends model
|
||||
|
||||
$key = "{$module}-{$method}";
|
||||
$priv = new stdclass();
|
||||
$priv->id = $key;
|
||||
$priv->module = $module;
|
||||
$priv->method = $method;
|
||||
$priv->action = $key;
|
||||
@@ -2356,11 +2359,9 @@ class groupModel extends model
|
||||
->markRight(2)
|
||||
->orderBy('t2.`order`_asc, t1.`type` desc')
|
||||
->fetchGroup('parentCode', 'relationPriv');
|
||||
|
||||
$relatedPrivs = array();
|
||||
foreach($modules as $module)
|
||||
{
|
||||
$relatedPrivs = array_merge($relatedPrivs, zget($privs, $module, array()));
|
||||
}
|
||||
foreach($modules as $module) $relatedPrivs = array_merge($relatedPrivs, zget($privs, $module, array()));
|
||||
|
||||
$privList = empty($type) ? array('depend' => array(), 'recommend' => array()) : array($type => array());
|
||||
if(empty($relatedPrivs)) return $privList;
|
||||
@@ -2368,13 +2369,13 @@ class groupModel extends model
|
||||
$managerList = $this->dao->select('*')->from(TABLE_PRIVMANAGER)->fetchAll('id');
|
||||
$relatedPrivs = $this->transformPrivLang($relatedPrivs);
|
||||
|
||||
foreach($relatedPrivs as $privID => $relatedPriv)
|
||||
foreach($relatedPrivs as $relatedPriv)
|
||||
{
|
||||
$module = $managerList[$relatedPriv->parent]->type == 'package' ? $managerList[$managerList[$relatedPriv->parent]->parent]->code : $managerList[$relatedPriv->parent]->code;
|
||||
if(!isset($privList[$relatedPriv->type][$module])) $privList[$relatedPriv->type][$module] = array();
|
||||
$privList[$relatedPriv->type][$module]['title'] = $modulePairs[$module];
|
||||
$privList[$relatedPriv->type][$module]['id'] = $relatedPriv->parent;
|
||||
$privList[$relatedPriv->type][$module]['children'][] = array('title' => $relatedPriv->name, 'relationPriv' => $privID, 'parent' => $relatedPriv->parent, 'module' => $relatedPriv->module, 'method' => $relatedPriv->method);
|
||||
$privList[$relatedPriv->type][$module]['children'][] = array('title' => $relatedPriv->name, 'relationPriv' => $relatedPriv->relationPriv, 'parent' => $relatedPriv->parent, 'module' => $relatedPriv->module, 'method' => $relatedPriv->method);
|
||||
}
|
||||
|
||||
if(empty($type) or $type == 'depend') $privList['depend'] = array_values($privList['depend']);
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<?php echo "<button class='btn disabled'><i class='icon icon-copy disabled' title='{$lang->group->copy}'></i></button>";?>
|
||||
<?php else:?>
|
||||
<?php common::printIcon('group', 'manageView', "groupID=$group->id", $group, 'list', 'eye');?>
|
||||
<?php common::printIcon('group', 'managepriv', "type=byGroup¶m=$group->id", $group, 'list', 'lock');?>
|
||||
<?php common::printIcon('group', 'managepriv', "type=byPackage¶m=$group->id", $group, 'list', 'lock');?>
|
||||
<?php common::printIcon('group', 'manageMember', "groupID=$group->id", $group, 'list', 'persons', '', "iframe", true, "data-width='90%'");?>
|
||||
<?php common::printIcon('group', 'edit', "groupID=$group->id", $group, 'list', '', '', "iframe", true, "data-width='550'");?>
|
||||
<?php common::printIcon('group', 'copy', "groupID=$group->id", $group, 'list', '', '', "iframe", true, "data-width='550'");?>
|
||||
|
||||
@@ -80,8 +80,8 @@
|
||||
<div id='mainContainer'>
|
||||
<div class='main main-content'>
|
||||
<div class="btn-group">
|
||||
<?php echo html::a(inlink('managePriv', "type=byGroupbyPackage¶m=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn text-primary'");?>
|
||||
<?php echo html::a(inlink('managePriv', "type=byPackage¶m=$groupID&menu=$menu&version=$version"), "<i class='icon-has-authority-pack'></i>", '', "class='btn btn-icon switchBtn'");?>
|
||||
<?php echo html::a(inlink('managePriv', "type=byGroup¶m=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn text-primary'");?>
|
||||
</div>
|
||||
<table class='table table-hover table-striped table-bordered' id='privList'>
|
||||
<thead>
|
||||
@@ -216,7 +216,7 @@ $(document).ready(function()
|
||||
$('.menus .icon-plus').click(function()
|
||||
{
|
||||
$(this).toggleClass('icon-minus', 'icon-plus');
|
||||
$('.menus input[name^=actions]:not(input[value=browse])').parent('.checkbox-primary').toggle();
|
||||
$(this).closest('.menus').find('input[name^=actions]:not(input[value=browse])').parent('.checkbox-primary').toggle();
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,8 +80,8 @@
|
||||
<div id='mainContainer'>
|
||||
<div class='main main-content'>
|
||||
<div class="btn-group">
|
||||
<?php echo html::a(inlink('managePriv', "type=byGroup¶m=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn'");?>
|
||||
<?php echo html::a(inlink('managePriv', "type=byPackage¶m=$groupID&menu=$menu&version=$version"), "<i class='icon-has-authority-pack'></i>", '', "class='btn btn-icon switchBtn text-primary'");?>
|
||||
<?php echo html::a(inlink('managePriv', "type=byGroup¶m=$groupID&menu=$menu&version=$version"), "<i class='icon-without-authority-pack'></i>", '', "class='btn btn-icon switchBtn'");?>
|
||||
</div>
|
||||
<table class='table table-hover table-striped table-bordered' id='privPackageList'>
|
||||
<thead>
|
||||
|
||||
@@ -270,7 +270,9 @@ class install extends control
|
||||
if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https';
|
||||
if(isset($_SERVER['REQUEST_SCHEME']) and strtolower($_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https';
|
||||
if(strpos($this->app->getClientLang(), 'zh') === 0) $this->loadModel('api')->createDemoData($this->lang->api->zentaoAPI, "{$httpType}://{$_SERVER['HTTP_HOST']}" . $this->app->config->webRoot . 'api.php/v1', '16.0');
|
||||
$this->loadModel('upgrade')->createDefaultDimension();
|
||||
|
||||
if($this->config->edition != 'open') $this->loadModel('upgrade')->processDataset();
|
||||
|
||||
return print(js::locate(inlink('step6'), 'parent'));
|
||||
}
|
||||
|
||||
@@ -299,9 +301,9 @@ class install extends control
|
||||
$canDelFile = is_writable($this->app->getAppRoot() . 'www');
|
||||
$installFile = $this->app->getAppRoot() . 'www/install.php';
|
||||
$upgradeFile = $this->app->getAppRoot() . 'www/upgrade.php';
|
||||
$installFileDeleted = $canDelFile && is_writable($installFile) ? unlink($installFile) : false;
|
||||
$installFileDeleted = ($canDelFile and file_exists($installFile)) ? unlink($installFile) : false;
|
||||
|
||||
if($canDelFile and is_writable($upgradeFile)) unlink($upgradeFile);
|
||||
if($canDelFile and file_exists($upgradeFile)) unlink($upgradeFile);
|
||||
unset($_SESSION['installing']);
|
||||
session_destroy();
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
|
||||
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
|
||||
|
||||
/* Release Detail. */
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => 'We have enhanced the interaction experience of permissions and documents, while introducing the concept of test scenarios. Moreover, we now provide support for importing use cases with XMIND. Additionally, we have fully revamped the BI module by incorporating large screens, pivot tables, charts, and data capabilities.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.3'][] = array('title' => 'Language item customization is added in secondary development, which supports the definition of language items for menus and search tags; Editor functionality is added in the secondary development, which allows users to turn it on and off on demand; The forms could be saved temporarily when users exits unexpectedly, and the unsaved information will be filled automatically the next time you enter.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
|
||||
|
||||
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
|
||||
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
|
||||
|
||||
/* Release Detail. */
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => 'We have enhanced the interaction experience of permissions and documents, while introducing the concept of test scenarios. Moreover, we now provide support for importing use cases with XMIND. Additionally, we have fully revamped the BI module by incorporating large screens, pivot tables, charts, and data capabilities.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.3'][] = array('title' => 'Language item customization is added in secondary development, which supports the definition of language items for menus and search tags; Editor functionality is added in the secondary development, which allows users to turn it on and off on demand; The forms could be saved temporarily when users exits unexpectedly, and the unsaved information will be filled automatically the next time you enter.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
|
||||
|
||||
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
|
||||
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
|
||||
|
||||
/* Release Detail. */
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => 'We have enhanced the interaction experience of permissions and documents, while introducing the concept of test scenarios. Moreover, we now provide support for importing use cases with XMIND. Additionally, we have fully revamped the BI module by incorporating large screens, pivot tables, charts, and data capabilities.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.3'][] = array('title' => 'Language item customization is added in secondary development, which supports the definition of language items for menus and search tags; Editor functionality is added in the secondary development, which allows users to turn it on and off on demand; The forms could be saved temporarily when users exits unexpectedly, and the unsaved information will be filled automatically the next time you enter.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => 'Agile Plus and Waterfall Plus management models are newly added. Support for unlimited splitting of waterfall project stages. The UI of Admin is completely upgraded and redesigned. Fix bugs.', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => 'The automation testing solution interaction is optimized, while a new snapshot management function is newly added. ZenTao IM implemented online collaboration of PPT documents.Fix bugs.', 'desc' => '');
|
||||
|
||||
@@ -202,7 +202,7 @@ $lang->misc->releaseDate['7.1.stable'] = '2015-03-07';
|
||||
$lang->misc->releaseDate['6.3.stable'] = '2014-11-07';
|
||||
|
||||
/* Release Detail. */
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '', 'desc' => '');
|
||||
$lang->misc->feature->all['18.4.alpha1'][] = array('title' => '优化权限、文档交互体验,测试新增场景概念,用例支持xmind导入,并对BI模块中的大屏、透视表、图表、数据表进行了全面升级。', 'desc' => '');
|
||||
$lang->misc->feature->all['18.3'][] = array('title' => '二次开发增加语言项自定义,支持对菜单和检索标签的语言项进行定义;二次开发增加编辑器功能,支持用户按需开启和关闭;表单意外退出支持表单暂存,下次进入自动代入填写的未保存信息。', 'desc' => '');
|
||||
$lang->misc->feature->all['18.2'][] = array('title' => '新增融合敏捷、融合瀑布管理模型,瀑布项目阶段支持无限级拆分,后台进行全新UI改版。修复Bug。', 'desc' => '');
|
||||
$lang->misc->feature->all['18.1'][] = array('title' => '自动化测试解决方案交互优化、新增快照管理功能。禅道客户端实现了 PPT文档在线协作。修复Bug。', 'desc' => '');
|
||||
|
||||
@@ -17,7 +17,7 @@ $lang->my->story = 'My Stories';
|
||||
$lang->my->doc = "My Docs";
|
||||
$lang->my->createProgram = 'Create Program';
|
||||
$lang->my->project = "My {$lang->projectCommon}s";
|
||||
$lang->my->execution = "My {$lang->executionCommon}s";
|
||||
$lang->my->execution = "My {$lang->execution->common}s";
|
||||
$lang->my->audit = 'Review';
|
||||
$lang->my->issue = 'My Issues';
|
||||
$lang->my->risk = 'My Risks';
|
||||
|
||||
@@ -17,7 +17,7 @@ $lang->my->story = 'My Stories';
|
||||
$lang->my->doc = "My Docs";
|
||||
$lang->my->createProgram = 'Create Program';
|
||||
$lang->my->project = "My {$lang->projectCommon}s";
|
||||
$lang->my->execution = "My {$lang->executionCommon}s";
|
||||
$lang->my->execution = "My {$lang->execution->common}s";
|
||||
$lang->my->audit = 'Review';
|
||||
$lang->my->issue = 'My Issues';
|
||||
$lang->my->risk = 'My Risks';
|
||||
|
||||
@@ -17,7 +17,7 @@ $lang->my->story = 'My Stories';
|
||||
$lang->my->doc = "My Docs";
|
||||
$lang->my->createProgram = 'Create Program';
|
||||
$lang->my->project = "My {$lang->projectCommon}s";
|
||||
$lang->my->execution = "My {$lang->executionCommon}s";
|
||||
$lang->my->execution = "My {$lang->execution->common}s";
|
||||
$lang->my->audit = 'Review';
|
||||
$lang->my->issue = 'My Issues';
|
||||
$lang->my->risk = 'My Risks';
|
||||
|
||||
@@ -17,7 +17,7 @@ $lang->my->story = "我的{$lang->SRCommon}";
|
||||
$lang->my->doc = "我的文档";
|
||||
$lang->my->createProgram = '添加' . $lang->projectCommon;
|
||||
$lang->my->project = '我的' . $lang->projectCommon;
|
||||
$lang->my->execution = "我的{$lang->executionCommon}";
|
||||
$lang->my->execution = "我的{$lang->execution->common}";
|
||||
$lang->my->audit = '审批';
|
||||
$lang->my->issue = '我的问题';
|
||||
$lang->my->risk = '我的风险';
|
||||
|
||||
@@ -1,2 +1,93 @@
|
||||
<?php
|
||||
$config->pivot = new stdclass();
|
||||
$config->pivot->widthInput = 128;
|
||||
$config->pivot->widthDate = 248;
|
||||
|
||||
$config->pivot->fileType = array('xlsx' => 'xlsx', 'xls' => 'xls', 'html' => 'html', 'mht' => 'mht');
|
||||
|
||||
$config->pivot->create = new stdclass();
|
||||
$config->pivot->create->requiredFields = 'type,group';
|
||||
|
||||
$config->pivot->edit = new stdclass();
|
||||
$config->pivot->edit->requiredFields = 'type,group';
|
||||
|
||||
$config->pivot->design = new stdclass();
|
||||
$config->pivot->design->requiredFields = 'group';
|
||||
|
||||
$config->pivot->multiColumn = array('cluBarX' => 'yaxis', 'cluBarY' => 'yaxis', 'radar' => 'yaxis', 'line' => 'yaxis', 'stackedBar' => 'yaxis', 'stackedBarY' => 'yaxis');
|
||||
|
||||
$config->pivot->checkForm = array();
|
||||
$config->pivot->checkForm['line'] = array('cantequal' => 'xaxis,yaxis');
|
||||
$config->pivot->checkForm['cluBarX'] = array('cantequal' => 'xaxis,yaxis');
|
||||
$config->pivot->checkForm['cluBarY'] = array('cantequal' => 'xaxis,yaxis');
|
||||
$config->pivot->checkForm['radar'] = array('cantequal' => 'xaxis,yaxis');
|
||||
$config->pivot->checkForm['stackedBar'] = array('cantequal' => 'xaxis,yaxis');
|
||||
$config->pivot->checkForm['stackedBarY'] = array('cantequal' => 'xaxis,yaxis');
|
||||
global $lang;
|
||||
$config->pivot->settings = array();
|
||||
$config->pivot->settings['cluBarX'] = array();
|
||||
$config->pivot->settings['cluBarX']['xaxis'] = array();
|
||||
$config->pivot->settings['cluBarX']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
|
||||
|
||||
$config->pivot->settings['cluBarX']['yaxis'] = array();
|
||||
$config->pivot->settings['cluBarX']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
$config->pivot->settings['cluBarX']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['cluBarY'] = array();
|
||||
$config->pivot->settings['cluBarY']['xaxis'] = array();
|
||||
$config->pivot->settings['cluBarY']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
|
||||
|
||||
$config->pivot->settings['cluBarY']['yaxis'] = array();
|
||||
$config->pivot->settings['cluBarY']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
$config->pivot->settings['cluBarY']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['stackedBarY'] = array();
|
||||
$config->pivot->settings['stackedBarY']['xaxis'] = array();
|
||||
$config->pivot->settings['stackedBarY']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
|
||||
|
||||
$config->pivot->settings['stackedBarY']['yaxis'] = array();
|
||||
$config->pivot->settings['stackedBarY']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
$config->pivot->settings['stackedBarY']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['line'] = array();
|
||||
$config->pivot->settings['line']['xaxis'] = array();
|
||||
$config->pivot->settings['line']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
|
||||
|
||||
$config->pivot->settings['line']['yaxis'] = array();
|
||||
$config->pivot->settings['line']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
$config->pivot->settings['line']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['pie'] = array();
|
||||
$config->pivot->settings['pie']['group'] = array();
|
||||
$config->pivot->settings['pie']['group'][] = array('field' => 'group', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['pie']['metric'] = array();
|
||||
$config->pivot->settings['pie']['metric'][] = array('field' => 'metric', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['pie']['stat'] = array();
|
||||
$config->pivot->settings['pie']['stat'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['radar'] = array();
|
||||
$config->pivot->settings['radar']['xaxis'] = array();
|
||||
$config->pivot->settings['radar']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
|
||||
|
||||
$config->pivot->settings['radar']['yaxis'] = array();
|
||||
$config->pivot->settings['radar']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
$config->pivot->settings['radar']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['stackedBar'] = array();
|
||||
$config->pivot->settings['stackedBar']['xaxis'] = array();
|
||||
$config->pivot->settings['stackedBar']['xaxis'][] = array('field' => 'xaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 4);
|
||||
|
||||
$config->pivot->settings['stackedBar']['yaxis'] = array();
|
||||
$config->pivot->settings['stackedBar']['yaxis'][] = array('field' => 'yaxis', 'type' => 'select', 'options' => 'field', 'required' => true, 'placeholder' => $lang->pivot->chooseField, 'col' => 2);
|
||||
$config->pivot->settings['stackedBar']['yaxis'][] = array('field' => 'agg', 'type' => 'select', 'options' => 'aggList', 'required' => false, 'placeholder' => $lang->pivot->aggType, 'col' => 2);
|
||||
|
||||
$config->pivot->settings['testingReport'] = array('field' => array('type' => 'td'));
|
||||
|
||||
$config->pivot->transTypes = array();
|
||||
$config->pivot->transTypes['int'] = 'number';
|
||||
$config->pivot->transTypes['float'] = 'number';
|
||||
$config->pivot->transTypes['double'] = 'number';
|
||||
$config->pivot->transTypes['datetime'] = 'date';
|
||||
$config->pivot->transTypes['date'] = 'date';
|
||||
|
||||
@@ -68,10 +68,8 @@ class pivot extends control
|
||||
if($pivot)
|
||||
{
|
||||
list($sql, $filterFormat) = $this->pivot->getFilterFormat($pivot->sql, $pivot->filters);
|
||||
|
||||
$pivot->sql = $sql;
|
||||
|
||||
$processSqlData = $this->loadModel('dataview')->getTables($sql);
|
||||
$processSqlData = $this->loadModel('chart')->getTables($sql);
|
||||
$sql = $processSqlData['sql'];
|
||||
|
||||
list($data, $configs) = $this->pivot->genSheet(json_decode(json_encode($pivot->fieldSettings), true), $pivot->settings, $sql, $filterFormat, json_decode($pivot->langs, true));
|
||||
@@ -251,4 +249,58 @@ class pivot extends control
|
||||
$this->view->submenu = 'staff';
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get sys options.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $object
|
||||
* @param string $field
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function ajaxGetSysOptions($type, $object = '', $field = '')
|
||||
{
|
||||
$sql = isset($_POST['sql']) ? $_POST['sql'] : '';
|
||||
$filters = isset($_POST['filters']) ? $_POST['filters'] : '';
|
||||
|
||||
$sql = $this->loadModel('chart')->parseSqlVars($sql, $filters);
|
||||
$options = $this->pivot->getSysOptions($type, $object, $field, $sql);
|
||||
return print(html::select('default[]', array('' => '') + $options, '', "class='form-control form-select picker-select' multiple"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get pivot table.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetPivot()
|
||||
{
|
||||
$post = fixer::input('post')->skipSpecial('settings,filters,sql,langs')->get();
|
||||
|
||||
$pivotID = $post->id;
|
||||
$settings = $post->settings;
|
||||
$filters = isset($_POST['searchFilters']) ? $_POST['searchFilters'] : (isset($_POST['filters']) ? $post->filters : array());
|
||||
$filterType = 'result';
|
||||
|
||||
$pivot = $this->pivot->getById($pivotID);
|
||||
|
||||
list($sql, $filterFormat) = $this->pivot->getFilterFormat($post->sql, $filters);
|
||||
$post->sql = $sql;
|
||||
|
||||
$settings['filterType'] = $filterType;
|
||||
|
||||
$sql = str_replace(';', '', "$post->sql");
|
||||
$fields = $post->fieldSettings;
|
||||
$langs = isset($post->langs) ? (is_array($post->langs) ? $post->langs : json_decode($post->langs, true)) : array();
|
||||
|
||||
$processSqlData = $this->loadModel('chart')->getTables($sql);
|
||||
$sql = $processSqlData['sql'];
|
||||
|
||||
list($data, $configs) = $this->pivot->genSheet($fields, $settings, $sql, $filterFormat, $langs);
|
||||
|
||||
$this->pivot->buildPivotTable($data, $configs, $fields, $sql);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,3 +35,13 @@ td .deviation {padding-left: 20px; text-align: left;}
|
||||
.checkboxes {margin-bottom: 10px;}
|
||||
.checkboxes .checkbox-primary {margin-bottom: 5px;}
|
||||
.fixed-header-copy thead tr th {color: #fff !important;}
|
||||
|
||||
.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;}
|
||||
.text-center {text-align: center;}
|
||||
.visibility-hidden{visibility: hidden;}
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
#mainContent > .side-col.col-lg {width: 240px;}
|
||||
.main-col .btn-toolbar {margin-bottom: 10px;}
|
||||
.main-position {position: relative;}
|
||||
.toolbar-padding {padding-right: 100px;}
|
||||
.child-position {position: absolute; right: 0;}
|
||||
#pivotGroups .active {background-color: #e9f2fb; color: #006af1 !important;}
|
||||
#pivotGroups li>a, #pivotGroups ul>li>a {overflow: hidden; white-space: nowrap;}
|
||||
.biz-version {padding-top: 10px;}
|
||||
.biz-version a {color: #81511C;}
|
||||
.parent-position {padding-right: 160px;}
|
||||
.datagrid {overflow: auto;}
|
||||
.heading-padding, .datagrid-padding {padding-left: 6px; padding-right: 6px;}
|
||||
|
||||
.filter-items > .table-row{display: table!important;}
|
||||
.filter-items .filter-item:first-child {padding-left: 0!important;}
|
||||
.filterBox {display: flex; margin-bottom: 20px; margin-left: 6px; margin-right: 6px;}
|
||||
.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; flex-basis: 60px;}
|
||||
.filter-item .picker-selections {width: 128px; overflow: hidden; text-overflow: clip; white-space: nowrap;}
|
||||
#filterItems .picker-selections {overflow: hidden; text-overflow: clip; white-space: nowrap;}
|
||||
|
||||
@@ -18,6 +18,6 @@ function changeParams(obj)
|
||||
}
|
||||
|
||||
var params = window.btoa('begin=' + begin + '&end=' + end + '&product=' + product + '&execution=' + execution);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=bugcreate¶ms=' + params);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=bugcreate¶ms=' + params);
|
||||
location.href = link;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,460 @@
|
||||
var filterValues = {};
|
||||
|
||||
/**
|
||||
* Listen filter change.
|
||||
*
|
||||
* @param string field
|
||||
* @param string dateSelect
|
||||
* @param string $filterValue
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function filterChange(field, dateSelect, $filterValue)
|
||||
{
|
||||
var parse = field.split('.');
|
||||
|
||||
field = parse[0];
|
||||
var type = '';
|
||||
if(parse.length == 2) type = parse[1];
|
||||
var id = type.length == 0 ? field : field + '\\[' + type + '\\]';
|
||||
var value = $('#' + id).val();
|
||||
|
||||
if(type.length == 0)
|
||||
{
|
||||
filterValues[field] = value;
|
||||
ajaxGetChart();
|
||||
}
|
||||
else
|
||||
{
|
||||
var check = checkDate(dateSelect, $filterValue);
|
||||
if(!check) return;
|
||||
if(!filterValues[field]) filterValues[field] = {begin: '', end: ''};
|
||||
|
||||
filterValues[field][type] = value;
|
||||
|
||||
var begin = filterValues[field].begin;
|
||||
var end = filterValues[field].end;
|
||||
if((begin.length > 0 && end.length > 0) || (begin.length == 0 && end.length == 0)) ajaxGetChart();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Ajax get pivot data.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function ajaxGetChart()
|
||||
{
|
||||
/* If the same value is detected for the x and y axes, throw error and clear the echart, then return.*/
|
||||
/* 如果x轴和y轴重复了,那么抛出错误并返回。*/
|
||||
if(!checkFormSetting()) return;
|
||||
|
||||
var chartParams = JSON.parse(JSON.stringify(DataStorage.pivot));
|
||||
chartParams.filterValues = filterValues;
|
||||
|
||||
/* Redraw echart. */
|
||||
/* 拿数据并重绘图表。*/
|
||||
$.post(createLink('pivot', 'ajaxGetChart'), chartParams, function(resp)
|
||||
{
|
||||
var data = JSON.parse(resp);
|
||||
echart.clear();
|
||||
echart.setOption(data, true);
|
||||
});
|
||||
}
|
||||
|
||||
function getQueryFilters(pivot)
|
||||
{
|
||||
var filters = '';
|
||||
filters = pivot.filters;
|
||||
|
||||
filters.forEach(function(filter, index)
|
||||
{
|
||||
if(filter.from == 'query')
|
||||
{
|
||||
var find = $('#queryFilters').find('.filter-item-' + index + ' .form-' + filter.type);
|
||||
if(find.length != 0) filter.default = find.val();
|
||||
}
|
||||
});
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the same value is detected for the x and y axias, throw error and clear the echart, then return.
|
||||
*
|
||||
* @access public
|
||||
* @return bool ture|false
|
||||
*/
|
||||
function checkFormSetting()
|
||||
{
|
||||
var pivot = DataStorage.pivot;
|
||||
var type = pivot.settings[0].type;
|
||||
var result = 'success';
|
||||
var errorMsg = '';
|
||||
if(checkForm[type])
|
||||
{
|
||||
for(var key in checkForm[type])
|
||||
{
|
||||
var fields = checkForm[type][key].split(',');
|
||||
var former = fields[0];
|
||||
var latter = fields[1];
|
||||
|
||||
if(key == 'cantequal')
|
||||
{
|
||||
if(pivot.settings[0][latter].includes(pivot.settings[0][former]))
|
||||
{
|
||||
result = 'fail';
|
||||
errorMsg = pivotLang['errorList']['cantequal'];
|
||||
errorMsg = errorMsg.replace(/%s/, pivotLang[type][latter]);
|
||||
errorMsg = errorMsg.replace(/%s/, pivotLang[type][former]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(result == 'fail')
|
||||
{
|
||||
var message = new $.zui.Messager(errorMsg,
|
||||
{
|
||||
html: true,
|
||||
icon: 'exclamation-sign',
|
||||
type: 'danger',
|
||||
close: true,
|
||||
});
|
||||
|
||||
message.show();
|
||||
|
||||
echart.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate form required.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function validate(showError = false)
|
||||
{
|
||||
var pivot = DataStorage.pivot;
|
||||
var formSettings = pivot.settings;
|
||||
/* Code for temporary */
|
||||
var isReady = true;
|
||||
|
||||
/* check group settings. */
|
||||
var exist = false;
|
||||
for(var key in formSettings)
|
||||
{
|
||||
if(key.indexOf('group') != '-1' && formSettings[key].length > 0) exist = true;
|
||||
}
|
||||
|
||||
var tr = $('#step2Content form#groupForm table tbody tr:nth-child(1)');
|
||||
tr.find('#groupLabel').remove();
|
||||
tr.find('#group1').removeClass('has-error');
|
||||
|
||||
if(!exist)
|
||||
{
|
||||
isReady = false;
|
||||
|
||||
if(showError)
|
||||
{
|
||||
var error = '<div id="groupLabel" class="text-danger help-text">' + moreThanOneLang + '</div>';
|
||||
tr.find('#group1').addClass('has-error');
|
||||
tr.find('#group1').next().after(error);
|
||||
}
|
||||
}
|
||||
|
||||
/* check columns settings. */
|
||||
formSettings.columns.forEach(function(value, index)
|
||||
{
|
||||
var $column = $('#step2Content form#columnForm .column-' + index);
|
||||
$column.find('#column' + index + 'Label').remove();
|
||||
$column.find('#stat' + index + 'Label').remove();
|
||||
$column.find('#column').removeClass('has-error');
|
||||
$column.find('#stat').removeClass('has-error');
|
||||
|
||||
if(!value.field || value.field.length == 0)
|
||||
{
|
||||
isReady = false;
|
||||
if(showError)
|
||||
{
|
||||
var error = '<div id="column' + index + 'Label" class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang.step2.columnField) + '</div>';
|
||||
$column.find('#column').addClass('has-error');
|
||||
$column.find('#column').next().after(error);
|
||||
}
|
||||
}
|
||||
|
||||
if(!value.stat || value.stat.length == 0 || value.stat === '')
|
||||
{
|
||||
isReady = false;
|
||||
if(showError)
|
||||
{
|
||||
var error = '<div id="stat' + index + 'Label" class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang.step2.calcMode) + '</div>';
|
||||
$column.find('#stat').addClass('has-error');
|
||||
$column.find('#stat').next().after(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(isReady) $('#datagrid-tip').addClass('hidden');
|
||||
return isReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi Validate.
|
||||
*
|
||||
* @param setting $setting
|
||||
* @param showError $showError
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function multiValidate(setting, showError)
|
||||
{
|
||||
var pivot = DataStorage.pivot;
|
||||
var type = pivot.settings[0].type;
|
||||
var isReady = true;
|
||||
var field = setting.field;
|
||||
var error = '<div id="' + field + 'Label"' + ' class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang[type][field]) + '</div>';
|
||||
$('#pivotForm .table-form').find('.multi-' + field).each(function()
|
||||
{
|
||||
$(this).parent('td').find('#' + field + 'Label').remove();
|
||||
$(this).parent('td').find('#' + field + '_chosen a').removeClass('has-error');
|
||||
|
||||
if(setting.required && $(this).val().length == 0)
|
||||
{
|
||||
isReady = false;
|
||||
if(showError)
|
||||
{
|
||||
$(this).parent('td').find('#' + field + '_chosen a').addClass('has-error');
|
||||
$(this).parent('td').find('#' + field + '_chosen').after(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return isReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check date.
|
||||
*
|
||||
* @param string dateSelect
|
||||
* @param object $filterValue
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function checkDate(dateSelect, $filterValue)
|
||||
{
|
||||
var begin = new Date($(dateSelect).parent().find('.default-begin').val().replace(/-/g, "\/")).getTime();
|
||||
var end = new Date($(dateSelect).parent().find('.default-end').val().replace(/-/g, "\/")).getTime();
|
||||
if(begin > end)
|
||||
{
|
||||
$(dateSelect).val('');
|
||||
if(typeof $filterValue == 'object') $filterValue.val('');
|
||||
bootbox.alert(pivotLang.beginGtEnd);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function waitForRepaint(callback)
|
||||
{
|
||||
window.requestAnimationFrame(function()
|
||||
{
|
||||
window.requestAnimationFrame(callback);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Init picker.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function initPicker($row, pickerName = 'picker-select', onready = false)
|
||||
{
|
||||
$row.find('.' + pickerName).picker(
|
||||
{
|
||||
maxDropHeight: pickerHeight,
|
||||
onReady: function()
|
||||
{
|
||||
if(!onready) return;
|
||||
if(!$row.find('.picker')) return;
|
||||
if(window.getComputedStyle($row.find('.picker').find('.picker-selections')[0]).getPropertyValue('width') !== 'auto')
|
||||
{
|
||||
var pickerWidth = $row.find('.picker')[0].getBoundingClientRect().width;
|
||||
$row.find('.picker').find('.picker-selections').css('width', pickerWidth);
|
||||
}
|
||||
}
|
||||
});
|
||||
$row.find("." + pickerName).each(function(index)
|
||||
{
|
||||
if($(this).hasClass('required')) $(this).siblings("div .picker").addClass('required');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Init datapicker.
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attr date check.
|
||||
*
|
||||
* @param object $obj
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function attrDateCheck($obj)
|
||||
{
|
||||
$obj.find('.form-date').attr('onchange', 'checkDate(this, this.value)');
|
||||
$obj.find('.form-datetime').attr('onchange', 'checkDate(this, this.value)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Export file.
|
||||
*
|
||||
* @param object $domObj
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function exportFile($domObj)
|
||||
{
|
||||
if(typeof $domObj == 'undefined') return;
|
||||
|
||||
var fileName = $('#fileName').val().trim() ? $('#fileName').val().trim() : untitled;
|
||||
var fileType = $('#fileType').val();
|
||||
var tableName = fileName + '.' + fileType;
|
||||
|
||||
if(fileType == 'xlsx' || fileType == 'xls')
|
||||
{
|
||||
const new_sheet = XLSX.utils.table_to_book($domObj, {raw: true});
|
||||
XLSX.writeFile(new_sheet, tableName);
|
||||
}
|
||||
else if(fileType == 'html' || fileType == 'mht')
|
||||
{
|
||||
const htmlContent = $domObj.outerHTML;
|
||||
|
||||
const $temp = $('<div>').html(htmlContent);
|
||||
$temp.find('*').removeAttr('style');
|
||||
$temp.find('*').removeAttr('class');
|
||||
$temp.find('*').removeAttr('data-flex');
|
||||
$temp.find('*').removeAttr('data-width');
|
||||
$temp.find('*').removeAttr('data-type');
|
||||
$temp.find('*').removeAttr('data-fixed-left-width');
|
||||
const cleanTableHTML = $temp.html();
|
||||
|
||||
var head = '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
|
||||
var style = '<style>table, th, td {font-size: 12px; border: 1px solid gray; border-collapse: collapse;}table th, table td {padding: 5px;}</style>';
|
||||
var title = '<title>' + fileName + '</title></head>';
|
||||
var body = '<body>' + cleanTableHTML + '</body>';
|
||||
const finalHTML = head + style + title + body;
|
||||
|
||||
if(fileType == 'html')
|
||||
{
|
||||
const blob = new Blob([finalHTML], { type: 'text/html;charset=utf-8' });
|
||||
saveAs(blob, tableName);
|
||||
}
|
||||
else if(fileType == 'mht')
|
||||
{
|
||||
const data = {html: finalHTML, fileName: fileName};
|
||||
$.post(createLink('file', 'ajaxExport2mht'), data, function(resp)
|
||||
{
|
||||
const blob = new Blob([resp], { type: "application/x-mimearchive" });
|
||||
saveAs(blob, tableName);
|
||||
});
|
||||
}
|
||||
}
|
||||
$('#export').modal('hide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Zui messager alert.
|
||||
*
|
||||
* @param string result success|fail
|
||||
* @param string mes
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function zuiMessage(result, mes)
|
||||
{
|
||||
var icon = result == 'success' ? 'check-circle' : 'exclamation-sign';
|
||||
var type = result == 'success' ? 'success' : 'danger';
|
||||
|
||||
var message = new $.zui.Messager(mes,
|
||||
{
|
||||
html: true,
|
||||
icon: icon,
|
||||
type: type,
|
||||
close: true,
|
||||
});
|
||||
|
||||
message.show();
|
||||
}
|
||||
|
||||
function select(name, options, selected, attrib, callback)
|
||||
{
|
||||
var type = 'option';
|
||||
if(!Array.isArray(options))
|
||||
{
|
||||
type = options;
|
||||
options = [];
|
||||
}
|
||||
$.post(createLink('pivot', 'ajaxGetSelect'),
|
||||
{
|
||||
name: name,
|
||||
type: type,
|
||||
selectedItems: selected,
|
||||
attrib: attrib,
|
||||
options: options
|
||||
}, function(resp)
|
||||
{
|
||||
if(typeof callback == 'function') callback(resp);
|
||||
});
|
||||
}
|
||||
|
||||
function setDateField(query)
|
||||
{
|
||||
var $period = $('#selectPeriod');
|
||||
if(!$period.length)
|
||||
{
|
||||
$period = $("<ul id='selectPeriod' class='dropdown-menu'><li><a href='#MONDAY'>" + datepickerText.TEXT_WEEK_MONDAY + "</a></li><li><a href='#SUNDAY'>" + datepickerText.TEXT_WEEK_SUNDAY + "</a></li><li><a href='#MONTHBEGIN'>" + datepickerText.TEXT_MONTH_BEGIN + "</a></li><li><a href='#MONTHEND'>" + datepickerText.TEXT_MONTH_END + "</a></li></ul>").appendTo('body');
|
||||
$period.find('li > a').click(function(event)
|
||||
{
|
||||
var target = $(query).parents('table, #queryFilters, #filterItems,#filterForm').find('[data-index="' + $period.attr('data-index') + '"]').find('#default:visible');
|
||||
if(target.length)
|
||||
{
|
||||
target.val($(this).attr('href').replace('#', '$'));
|
||||
$period.hide();
|
||||
}
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if(query == '.form-date') $(query).datepicker();
|
||||
if(query == '.form-datetime') $(query).datetimepicker();
|
||||
|
||||
$(query).on('show', function(e)
|
||||
{
|
||||
var $e = $(e.target);
|
||||
var ePos = $e.offset();
|
||||
$period.css({'left': ePos.left + 210, 'top': ePos.top + 29, 'min-height': $('.datetimepicker').outerHeight(), 'z-index': 1110}).show().attr('data-index', $e.parents('.filter-item, .filter').data('index')).find('li.active').removeClass('active');
|
||||
$period.find("li > a[href='" + $e.val().replace('$', '#') + "']").closest('li').addClass('active');
|
||||
}).on('changeDate', function()
|
||||
{
|
||||
$period.hide();
|
||||
}).on('hide', function(){setTimeout(function(){$period.hide();}, 200);});
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
$(function()
|
||||
{
|
||||
if(typeof pivotID == 'undefined' || !pivotID) return;
|
||||
|
||||
expandTree();
|
||||
renderFilters(pivot);
|
||||
initQueryBtn();
|
||||
|
||||
$('body').resize(() => {calcPreviewGrowFilter();});
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
||||
function expandTree()
|
||||
{
|
||||
$('.pivot-' + groupID + '-' + pivotID).addClass('active');
|
||||
|
||||
var $tree = $('#pivotGroups').tree({name:'tree-group'});
|
||||
var tree = $tree.data('zui.tree');
|
||||
tree.expand($('.pivot-' + pivotID).parents('li'));
|
||||
}
|
||||
|
||||
/*$('.btn-export').click(function()
|
||||
{
|
||||
if(typeof pivotID == 'undefined' || !pivotID) return;
|
||||
pivot = getQueryInfo();
|
||||
});
|
||||
*/
|
||||
|
||||
function getQueryInfo()
|
||||
{
|
||||
var pivotInfo = pivot;
|
||||
pivotInfo.searchFilters = JSON.parse(JSON.stringify(pivotInfo.filters));
|
||||
|
||||
if(isQueryFilter(pivotInfo.filters))
|
||||
{
|
||||
pivotInfo.filters.forEach(function(filter, index)
|
||||
{
|
||||
var find = $('#filterItems .filter-items').find('.filter-item-' + index + ' .form-' + filter.type);
|
||||
if(find.length != 0) pivotInfo.searchFilters[index].default = find.val();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
pivotInfo.filters.forEach(function(filter, index)
|
||||
{
|
||||
var filterItem = $('#filterItems .filter-items').find('.filter-item-' + index);
|
||||
var type = filter.type;
|
||||
if(type == 'input')
|
||||
{
|
||||
var find = filterItem.find(' .form-' + type);
|
||||
if(find.length != 0) pivotInfo.searchFilters[index].default = find.val();
|
||||
}
|
||||
else if(type == 'select')
|
||||
{
|
||||
var find = filterItem.find(' .form-' + type);
|
||||
if(find.length != 0) pivotInfo.searchFilters[index].default = find.data('zui.picker').getValue();
|
||||
}
|
||||
else if(type == 'date' || type == 'datetime')
|
||||
{
|
||||
var begin = filterItem.find('.form-' + type + '.begin');
|
||||
var end = filterItem.find('.form-' + type + '.end');
|
||||
|
||||
pivotInfo.searchFilters[index].default =
|
||||
{
|
||||
"begin": begin.length != 0 ? begin.val() : filter.default.begin,
|
||||
"end": end.length != 0 ? end.val() : filter.default.end
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pivotInfo.step = 4;
|
||||
return pivotInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init query button.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function initQueryBtn()
|
||||
{
|
||||
$('.btn-query').click(function()
|
||||
{
|
||||
pivotInfo = getQueryInfo();
|
||||
$.post(createLink('pivot', 'ajaxGetPivot'), pivotInfo,function(resp)
|
||||
{
|
||||
var myDatagrid = $('#datagirdInfo');
|
||||
myDatagrid.find('.reportData').remove();
|
||||
myDatagrid.append(resp);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function calcPreviewGrowFilter()
|
||||
{
|
||||
if(pivot.filters.length <= 0) return;
|
||||
var $filterItems = $('#filterItems .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;
|
||||
pivot.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 lineWrap = false;
|
||||
var nowCount = 0;
|
||||
var canGrowTotal = 0;
|
||||
|
||||
$('.query-inside').addClass('hidden');
|
||||
$('.query-outside').addClass('visibility-hidden');
|
||||
pivot.filters.forEach(function(filter, index)
|
||||
{
|
||||
var nowItem = '.filter-item-' + index;
|
||||
var $nowDom = $filterItems.find(nowItem);
|
||||
var leftPadding = parseInt($nowDom.css('padding-left'));
|
||||
var rightPadding = parseInt($nowDom.css('padding-right'));
|
||||
var spanWidth = $nowDom.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. */
|
||||
$nowDom.css('flex-basis', '');
|
||||
$nowDom.css('flex-basis', filterWidth);
|
||||
if(nowWidth - filterWidth >= 0)
|
||||
{
|
||||
nowWidth -= filterWidth;
|
||||
nowCount ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
canGrowTotal += nowCount;
|
||||
nowWidth = domWidth - filterWidth;
|
||||
nowCount = 1;
|
||||
lineWrap = true;
|
||||
}
|
||||
});
|
||||
|
||||
/* Clear all filter filter-item-grow and add class to support grow element. */
|
||||
$filterItems.children().removeClass('filter-item-grow');
|
||||
pivot.filters.forEach(function(filter, index)
|
||||
{
|
||||
var $nowDom = $filterItems.find('.filter-item-' + index);
|
||||
if(canGrowTotal >= index + 1) $nowDom.addClass('filter-item-grow');
|
||||
if(filter.type == 'select' && $nowDom.find('.picker').length) $nowDom.find('.picker').find('.picker-selections').css('width', WIDTH_INPUT);
|
||||
});
|
||||
|
||||
if(!lineWrap && nowWidth >= 60) $('.query-inside').removeClass('hidden');
|
||||
else $('.query-outside').removeClass('visibility-hidden');
|
||||
|
||||
/* Set picker-selection width, default 128px. */
|
||||
waitForRepaint(function()
|
||||
{
|
||||
pivot.filters.forEach(function(filter, index)
|
||||
{
|
||||
var $nowDom = $filterItems.find('.filter-item-' + index);
|
||||
if(filter.type == 'select' && $nowDom.find('.picker').length)
|
||||
{
|
||||
var pickerWidth = $nowDom.hasClass('filter-item-grow') ? $nowDom.find('.picker')[0].getBoundingClientRect().width : WIDTH_INPUT;
|
||||
$nowDom.find('.picker').find('.picker-selections').css('width', pickerWidth);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function renderFilters(pivot)
|
||||
{
|
||||
if(pivot.filters.length == 0) return;
|
||||
renderFilterItem(pivot.filters);
|
||||
calcPreviewGrowFilter();
|
||||
}
|
||||
|
||||
function renderFilterItem(filters)
|
||||
{
|
||||
$('#filterItems .filter-items').empty();
|
||||
var tpl = isQueryFilter(filters) ? $('#queryFilterItemTpl').html() : $('#resultFilterItemTpl').html();
|
||||
|
||||
filters.forEach(function(filter, index)
|
||||
{
|
||||
var data =
|
||||
{
|
||||
index: index,
|
||||
name: filter.name,
|
||||
defaultValue: filter.default
|
||||
};
|
||||
var html = $($.zui.formatString(tpl, data))
|
||||
$('#filterItems .filter-items').append(html);
|
||||
|
||||
isQueryFilter(filters) ? initQueryControl(html, filter) : initResultControl(html, filter);
|
||||
});
|
||||
$('#filterItems .filter-items').append(queryDom);
|
||||
}
|
||||
|
||||
function initQueryControl(container, filter, object, field)
|
||||
{
|
||||
var type = filter.type;
|
||||
var options = filter.typeOption;
|
||||
var value = filter.default;
|
||||
|
||||
container.find('.default-block').addClass('hidden');
|
||||
container.find('.default-block input[name="default"]').val('');
|
||||
|
||||
var control = container.find('.form-' + type);
|
||||
control.val(filter.default);
|
||||
control.parent('.default-block').removeClass('hidden');
|
||||
|
||||
if(type == 'date') setDateField('.form-date');
|
||||
if(type == 'datetime') setDateField('.form-datetime');
|
||||
if(type == 'select')
|
||||
{
|
||||
var picker = control.data('zui.picker');
|
||||
if(picker) picker.destroy();
|
||||
|
||||
$.post(createLink('pivot', 'ajaxGetSysOptions', 'type=' + options + '&object=' + object + '&field=' + field), function(resp)
|
||||
{
|
||||
control.html($(resp).html());
|
||||
control.picker();
|
||||
control.data('zui.picker').setValue(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initResultControl(container, filter, object, field)
|
||||
{
|
||||
var type = filter.type;
|
||||
var value = filter.default;
|
||||
|
||||
container.find('.default-block').addClass('hidden');
|
||||
container.find('.default-block input[name^="default"]').val('');
|
||||
|
||||
var control = container.find('.form-' + type);
|
||||
if(type == 'date' || type == 'datetime')
|
||||
{
|
||||
container.find('.form-' + type + '.begin').val(filter.default.begin);
|
||||
container.find('.form-' + type + '.end').val(filter.default.end);
|
||||
}
|
||||
else
|
||||
{
|
||||
control.val(filter.default);
|
||||
}
|
||||
control.parents('.default-block').removeClass('hidden');
|
||||
|
||||
if(type == 'date') control.datepicker();
|
||||
if(type == 'datetime') control.datetimepicker();
|
||||
if(type == 'select')
|
||||
{
|
||||
var picker = control.data('zui.picker');
|
||||
if(picker) picker.destroy();
|
||||
|
||||
var fieldSetting = pivot.fieldSettings[filter.field];
|
||||
var options = fieldSetting.type;
|
||||
var object = fieldSetting.object;
|
||||
var field = fieldSetting.field;
|
||||
|
||||
var pickerOptions =
|
||||
{
|
||||
multi: true,
|
||||
maxDropHeight: pickerHeight,
|
||||
onReady: function()
|
||||
{
|
||||
if(!control.parent().find('.picker')) return;
|
||||
if(window.getComputedStyle(control.parent().find('.picker').find('.picker-selections')[0]).getPropertyValue('width') !== 'auto')
|
||||
{
|
||||
var pickerWidth = control.parent().find('.picker')[0].getBoundingClientRect().width;
|
||||
control.parent().find('.picker').find('.picker-selections').css('width', pickerWidth);
|
||||
}
|
||||
}
|
||||
};
|
||||
if(value !== '') pickerOptions.defaultValue = value;
|
||||
|
||||
var pivotParams = {sql: pivot.sql, filters: getQueryFilters(pivot)};
|
||||
$.post(createLink('pivot', 'ajaxGetSysOptions', 'type=' + options + '&object=' + object + '&field=' + field), pivotParams, function(resp)
|
||||
{
|
||||
control.html($(resp).html());
|
||||
control.picker(pickerOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function exportData()
|
||||
{
|
||||
const $domObj = $(".table-condensed")[0];
|
||||
exportFile($domObj);
|
||||
}
|
||||
|
||||
function isQueryFilter(filters)
|
||||
{
|
||||
return filters.length > 0 && filters[0].from == 'query';
|
||||
}
|
||||
@@ -8,6 +8,6 @@ $('#conditions input:checkbox').change(function()
|
||||
conditions = conditions.substring(0, conditions.length - 1);
|
||||
|
||||
var params = window.btoa('conditions=' + conditions);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=productSummary¶ms=' + params);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=productSummary¶ms=' + params);
|
||||
location.href = link;
|
||||
})
|
||||
|
||||
@@ -31,6 +31,6 @@ function changeDate(begin, end)
|
||||
}
|
||||
|
||||
var params = window.btoa('begin=' + begin + '&end=' + end);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=projectdeviation¶ms=' + params);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=projectdeviation¶ms=' + params);
|
||||
location.href = link;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ function changeParams(obj)
|
||||
}
|
||||
|
||||
var params = window.btoa('begin=' + begin + '&end=' + end + '&days=' + days + '&workday=' + workday + '&dept=' + dept + '&assign=' + assign);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + group + '&module=pivot&method=workload¶ms=' + params);
|
||||
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=workload¶ms=' + params);
|
||||
location.href = link;
|
||||
}
|
||||
|
||||
|
||||
+62
-51
@@ -112,9 +112,19 @@ class pivotModel extends model
|
||||
$pivots = array_merge($pivots, $charts);
|
||||
}
|
||||
|
||||
$pager->setRecTotal(count($pivots));
|
||||
$pager->setPageTotal();
|
||||
if($pager->pageID > $pager->pageTotal) $pager->setPageID($pager->pageTotal);
|
||||
if(!empty($pager))
|
||||
{
|
||||
$pager->setRecTotal(count($pivots));
|
||||
$pager->setPageTotal();
|
||||
if($pager->pageID > $pager->pageTotal) $pager->setPageID($pager->pageTotal);
|
||||
|
||||
if($pivots)
|
||||
{
|
||||
$pivots = array_chunk($pivots, $pager->recPerPage);
|
||||
$pivots = $pivots[$pager->pageID - 1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this->processPivot($pivots, false);
|
||||
}
|
||||
@@ -129,7 +139,7 @@ class pivotModel extends model
|
||||
*/
|
||||
public function processDateVar($var, $type = 'date')
|
||||
{
|
||||
if(empty($var)) return $var;
|
||||
if(empty($var)) return NULL;
|
||||
|
||||
$format = $type == 'datetime' ? 'Y-m-d H:i:s' : 'Y-m-d';
|
||||
switch($var)
|
||||
@@ -1390,19 +1400,16 @@ class pivotModel extends model
|
||||
|
||||
/* Process rows. */
|
||||
$connectSQL = '';
|
||||
if(empty($settings['filterType']) or $settings['filterType'] == 'result')
|
||||
if(!empty($filters) && !isset($filters[0]['from']))
|
||||
{
|
||||
if(!empty($filters))
|
||||
$wheres = array();
|
||||
foreach($filters as $field => $filter)
|
||||
{
|
||||
$wheres = array();
|
||||
foreach($filters as $field => $filter)
|
||||
{
|
||||
$wheres[] = "tt.`$field` {$filter['operator']} {$filter['value']}";
|
||||
}
|
||||
|
||||
$whereStr = implode(' and ', $wheres);
|
||||
$connectSQL .= " where $whereStr";
|
||||
$wheres[] = "tt.`$field` {$filter['operator']} {$filter['value']}";
|
||||
}
|
||||
|
||||
$whereStr = implode(' and ', $wheres);
|
||||
$connectSQL .= " where $whereStr";
|
||||
}
|
||||
|
||||
$groupSQL = " group by $groupList";
|
||||
@@ -1411,36 +1418,39 @@ class pivotModel extends model
|
||||
$number = 0;
|
||||
$groupsRow = array();
|
||||
$showColTotal = zget($settings, 'columnTotal', 'noShow');
|
||||
foreach($settings['columns'] as $column)
|
||||
if(isset($settings['columns']))
|
||||
{
|
||||
$stat = $column['stat'];
|
||||
$field = $column['field'];
|
||||
$slice = zget($column, 'slice', 'noSlice');
|
||||
$uuName = $field . $number;
|
||||
$number ++;
|
||||
|
||||
if($stat == 'distinct')
|
||||
foreach($settings['columns'] as $column)
|
||||
{
|
||||
$columnSQL = "count(distinct tt.`$field`) as `$uuName`";
|
||||
}
|
||||
else
|
||||
{
|
||||
$columnSQL = "$stat(tt.`$field`) as `$uuName`";
|
||||
}
|
||||
$stat = $column['stat'];
|
||||
$field = $column['field'];
|
||||
$slice = zget($column, 'slice', 'noSlice');
|
||||
$uuName = $field . $number;
|
||||
$number ++;
|
||||
|
||||
if($slice != 'noSlice') $columnSQL = "select $groupList,`$slice`,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . ",tt.`$slice`" . $orderSQL . ",tt.`$slice`";
|
||||
if($slice == 'noSlice') $columnSQL = "select $groupList,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . $orderSQL;
|
||||
if($stat == 'distinct')
|
||||
{
|
||||
$columnSQL = "count(distinct tt.`$field`) as `$uuName`";
|
||||
}
|
||||
else
|
||||
{
|
||||
$columnSQL = "$stat(tt.`$field`) as `$uuName`";
|
||||
}
|
||||
|
||||
$columnRows = $this->dao->query($columnSQL)->fetchAll();
|
||||
if($slice != 'noSlice') $columnSQL = "select $groupList,`$slice`,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . ",tt.`$slice`" . $orderSQL . ",tt.`$slice`";
|
||||
if($slice == 'noSlice') $columnSQL = "select $groupList,$columnSQL from ($sql) tt" . $connectSQL . $groupSQL . $orderSQL;
|
||||
|
||||
$cols = $this->getTableHeader($columnRows, $column, $fields, $cols, $sql, $langs);
|
||||
if($slice != 'noSlice') $columnRows = $this->processSliceData($columnRows, $groups, $slice, $uuName);
|
||||
$columnRows = $this->processShowData($columnRows, $groups, $column, $showColTotal, $uuName);
|
||||
$columnRows = $this->dao->query($columnSQL)->fetchAll();
|
||||
|
||||
foreach($columnRows as $key => $row)
|
||||
{
|
||||
if(!isset($groupsRow[$key])) $groupsRow[$key] = new stdclass();
|
||||
$groupsRow[$key] = (object)array_merge((array)$groupsRow[$key], (array)$row);
|
||||
$cols = $this->getTableHeader($columnRows, $column, $fields, $cols, $sql, $langs);
|
||||
if($slice != 'noSlice') $columnRows = $this->processSliceData($columnRows, $groups, $slice, $uuName);
|
||||
$columnRows = $this->processShowData($columnRows, $groups, $column, $showColTotal, $uuName);
|
||||
|
||||
foreach($columnRows as $key => $row)
|
||||
{
|
||||
if(!isset($groupsRow[$key])) $groupsRow[$key] = new stdclass();
|
||||
$groupsRow[$key] = (object)array_merge((array)$groupsRow[$key], (array)$row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1463,12 +1473,7 @@ class pivotModel extends model
|
||||
$options = $this->getSysOptions($fields[$group]['type'], $fields[$group]['object'], $fields[$group]['field'], $sql);
|
||||
foreach($groupsRow as $row)
|
||||
{
|
||||
if(isset($row->$group))
|
||||
{
|
||||
$value = $row->$group;
|
||||
$lang = isset($options[$value]) ? $options[$value] : $value;
|
||||
$row->$group = $lang;
|
||||
}
|
||||
if(isset($row->$group)) $row->$group = zget($options, $row->$group);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1773,7 +1778,7 @@ class pivotModel extends model
|
||||
{
|
||||
if(in_array($field, $groups))
|
||||
{
|
||||
$colTotalRow->$field = 0;
|
||||
$colTotalRow->$field = '$togalGroup$';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1906,20 +1911,26 @@ class pivotModel extends model
|
||||
case 'dept':
|
||||
$options = $this->loadModel('dept')->getOptionMenu(0);
|
||||
break;
|
||||
case 'project.status':
|
||||
$this->app->loadLang('project');
|
||||
$options = $this->lang->project->statusList;
|
||||
break;
|
||||
case 'option':
|
||||
if($field)
|
||||
{
|
||||
$path = $this->app->getExtensionRoot() . 'biz' . DS . 'dataview' . DS . 'table' . DS . "$object.php";
|
||||
include $path;
|
||||
|
||||
$options = $schema->fields[$field]['options'];
|
||||
$path = $this->app->getModuleRoot() . 'dataview' . DS . 'table' . DS . "$object.php";
|
||||
if(is_file($path))
|
||||
{
|
||||
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();
|
||||
$table = zget($this->config->objectTables, $object, '');
|
||||
if($table) $options = $this->dao->select("id, {$field}")->from($table)->fetchPairs();
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<script>
|
||||
$('#subNavbar li').not('[data-id=<?php echo $group;?>]').removeClass('active');
|
||||
$('#subNavbar li').not('[data-id=<?php echo $groupID;?>]').removeClass('active');
|
||||
</script>
|
||||
<?php if($this->config->edition != 'open'):?>
|
||||
<style>#mainContent > .side-col.col-lg{width: 210px}</style>
|
||||
<style>.hide-sidebar #sidebar{width: 0 !important}</style>
|
||||
<?php endif;?>
|
||||
<?php js::set('dimension', $dimension);?>
|
||||
<?php js::set('group', $group);?>
|
||||
<?php js::set('groupID', $groupID);?>
|
||||
|
||||
<div id='mainMenu' class='clearfix main-position'>
|
||||
<div class="btn-toolbar pull-left parent-position">
|
||||
<?php foreach($lang->pivot->featureBar['preview'] as $key => $label):?>
|
||||
<?php $active = ($key == $group) ? ' btn-active-text' : '';?>
|
||||
<?php $active = ($key == $groupID) ? ' btn-active-text' : '';?>
|
||||
<?php echo html::a(inlink('preview', "dimension=$dimension&group=$key"), "<span class='text'>$label</span>", '', "class='btn btn-link {$active}'");?>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
@@ -37,8 +36,8 @@ $('#subNavbar li').not('[data-id=<?php echo $group;?>]').removeClass('active');
|
||||
</div>
|
||||
<div class="cell">
|
||||
<div class='panel'>
|
||||
<div class='panel-heading'>
|
||||
<div class='panel-title'><?php echo $lang->pivot->list;?></div>
|
||||
<div class='panel-heading text-ellipsis'>
|
||||
<div class='panel-title'><?php echo isset($group->name) ? $group->name : '';?></div>
|
||||
</div>
|
||||
<div class='panel-body'>
|
||||
<div class='list-group'>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<?php endif;?>
|
||||
</div>
|
||||
<div id='datagirdInfo' class='datagrid datagrid-padding'>
|
||||
<?php $sql = $this->loadModel('dataview')->parseSqlVars($pivot->sql, $pivot->filters);?>
|
||||
<?php $sql = $this->loadModel('chart')->parseSqlVars($pivot->sql, $pivot->filters);?>
|
||||
<?php $this->pivot->buildPivotTable($data, $configs, json_decode(json_encode($pivot->fieldSettings), true), $sql);?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<style>
|
||||
<?php helper::import('../css/workload.css');?>
|
||||
<?php if($this->config->edition != 'open'):?>
|
||||
#mainContent > .side-col.col-lg{width: 210px}
|
||||
.hide-sidebar #sidebar{width: 0 !important}
|
||||
<?php endif;?>
|
||||
</style>
|
||||
|
||||
+16
-10
@@ -5,27 +5,28 @@ class pivotZen extends pivot
|
||||
* Prepare for preview a pivot.
|
||||
*
|
||||
* @param int $dimension
|
||||
* @param string $group
|
||||
* @param string $groupID
|
||||
* @param string $module
|
||||
* @param string $method
|
||||
* @param string $params
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function prepare4Preview($dimension, $group, $module, $method, $params)
|
||||
public function prepare4Preview($dimension, $groupID, $module, $method, $params)
|
||||
{
|
||||
$params = helper::safe64Decode($params);
|
||||
|
||||
if(!$group) $group = $this->getDefaultGroup($dimension);
|
||||
if(!$module || !$method) list($module, $method, $params) = $this->getDefaultPivotParams($dimension, $group);
|
||||
if(!$groupID) $groupID = $this->getDefaultGroup($dimension);
|
||||
if(!$module || !$method) list($module, $method, $params) = $this->getDefaultPivotParams($dimension, $groupID);
|
||||
|
||||
if(!empty($module) && !empty($method) && $method != 'show' && !common::hasPriv($module, $method)) $this->loadModel('common')->deny('pivot', $method);
|
||||
|
||||
$this->setFeatureBar($dimension);
|
||||
|
||||
$this->view->sidebar = $this->getSidebar($dimension, $group, $module, $method, $params);
|
||||
$this->view->sidebar = $this->getSidebar($dimension, $groupID, $module, $method, $params);
|
||||
$this->view->dimension = $dimension;
|
||||
$this->view->group = $group;
|
||||
$this->view->groupID = $groupID;
|
||||
$this->view->group = $this->loadModel('tree')->getByID($groupID);
|
||||
$this->view->module = $module;
|
||||
$this->view->method = $method;
|
||||
$this->view->params = $params;
|
||||
@@ -91,10 +92,13 @@ class pivotZen extends pivot
|
||||
|
||||
foreach($groups as $group)
|
||||
{
|
||||
if($this->config->edition == 'open' && $group->grade == 1) continue;
|
||||
|
||||
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
|
||||
->where("FIND_IN_SET($group->id, `group`)")
|
||||
->andWhere('stage')->ne('draft')
|
||||
->orderBy('id_desc')->fetchAll();
|
||||
->orderBy('id_desc')
|
||||
->fetchAll();
|
||||
if($pivots)
|
||||
{
|
||||
foreach($pivots as $pivot) return array('pivot', 'show', "dimensionID=$dimension&groupID={$group->id}&pivotID={$pivot->id}");
|
||||
@@ -181,6 +185,8 @@ class pivotZen extends pivot
|
||||
$sidebar = '';
|
||||
foreach($groups as $group)
|
||||
{
|
||||
if($this->config->edition == 'open' && $group->grade == 1) continue;
|
||||
|
||||
$pivots = $this->dao->select('*')->from(TABLE_PIVOT)
|
||||
->where("FIND_IN_SET($group->id, `group`)")
|
||||
->andWhere('stage')->ne('draft')
|
||||
@@ -199,19 +205,19 @@ class pivotZen extends pivot
|
||||
|
||||
foreach($pivots as $pivot)
|
||||
{
|
||||
$class = '';
|
||||
$class = "pivot-{$pivot->id}";
|
||||
$pivotName = $pivot->name;
|
||||
$params = helper::safe64Encode("dimensionID=$pivot->dimension&groupID=$pivot->group&pivotID=$pivot->id");
|
||||
|
||||
if($module == 'pivot' && $method == 'show' && $pivotID == $pivot->id)
|
||||
{
|
||||
$class = "class='active'";
|
||||
$class .= ' active';
|
||||
|
||||
$this->view->title = $pivotName;
|
||||
}
|
||||
|
||||
$pivotLink = helper::createLink('pivot', 'preview', "dimension=$dimension&group=$currentGroup->id&module=pivot&method=show¶ms=$params");
|
||||
$sidebar .= "<li $class>" . html::a($pivotLink, $pivotName, '', "title='$pivotName'") . '</li>';
|
||||
$sidebar .= "<li class='$class'>" . html::a($pivotLink, $pivotName, '', "title='$pivotName'") . '</li>';
|
||||
}
|
||||
|
||||
if($group->grade == 2) $sidebar .= '</ul></li>';
|
||||
|
||||
@@ -1213,10 +1213,8 @@ class product extends control
|
||||
{
|
||||
return printf($this->lang->build->noProduct, $this->createLink('execution', 'manageproducts', "executionID=$executionID&from=buildCreate", '', 'true'), 'project');
|
||||
}
|
||||
else
|
||||
{
|
||||
return print(html::select('product', $products, empty($product) ? '' : $product->id, "onchange='loadBranches(this.value);' class='form-control chosen' required data-toggle='modal' data-type='iframe'"));
|
||||
}
|
||||
|
||||
return print(html::select('product', $products, '', "onchange='loadBranches(this.value);' class='form-control chosen' required data-toggle='modal' data-type='iframe'"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -256,6 +256,7 @@ class productModel extends model
|
||||
*/
|
||||
public function getByID(int $productID): object|false
|
||||
{
|
||||
$productID = (int)$productID;
|
||||
if(defined('TUTORIAL')) return $this->loadModel('tutorial')->getProduct();
|
||||
$product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch();
|
||||
if(!$product) return false;
|
||||
@@ -395,6 +396,8 @@ class productModel extends model
|
||||
return $this->loadModel('tutorial')->getExecutionProducts();
|
||||
}
|
||||
|
||||
if(is_string($projectID) and strpos($projectID, 'all') !== false) $projectID = str_replace('all', 0, $projectID);
|
||||
|
||||
if(!empty($append) and is_array($append)) $append = implode(',', $append);
|
||||
|
||||
$views = empty($append) ? $this->app->user->view->products : $this->app->user->view->products . ",$append";
|
||||
@@ -1148,7 +1151,7 @@ class productModel extends model
|
||||
->beginIF(strpos($param, 'multiple') !== false)->andWhere('t2.multiple')->ne('0')->fi()
|
||||
->andWhere('t2.type')->eq('project')
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->projects)->fi()
|
||||
->beginIF($product->type != 'normal' and $branch !== '')->andWhere('t1.branch')->in($branch)->fi()
|
||||
->beginIF($product->type != 'normal' and $branch !== '' and $branch != 'all')->andWhere('t1.branch')->in($branch)->fi()
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->beginIF($appendProject)->orWhere('t2.id')->in($appendProject)->fi()
|
||||
->orderBy('order_asc')
|
||||
@@ -1312,7 +1315,7 @@ class productModel extends model
|
||||
{
|
||||
if(in_array($project->model, array('waterfall', 'waterfallplus'))) $hasWaterfall = true;
|
||||
}
|
||||
$orderBy = $hasWaterfall ? 't2.begin_asc,t2.id_asc' : 't2.begin_desc,t2.id_desc';
|
||||
$waterFallOrderBy = $hasWaterfall ? 't2.begin_asc,t2.id_asc' : 't2.begin_desc,t2.id_desc';
|
||||
|
||||
$executions = $this->dao->select('t2.id,t2.name,t2.project,t2.grade,t2.path,t2.parent,t2.attribute,t2.multiple,t3.name as projectName')->from(TABLE_PROJECTPRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project = t2.id')
|
||||
@@ -1320,12 +1323,12 @@ class productModel extends model
|
||||
->where('t1.product')->eq($productID)
|
||||
->andWhere('t2.type')->in('sprint,kanban,stage')
|
||||
->beginIF($projectID)->andWhere('t2.project')->in($projectID)->fi()
|
||||
->beginIF($branch !== '')->andWhere('t1.branch')->in($branch)->fi()
|
||||
->beginIF($branch !== '' and strpos($branch, 'all') === false)->andWhere('t1.branch')->in($branch)->fi()
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
|
||||
->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('t2.status')->ne('closed')->fi()
|
||||
->beginIF(strpos($mode, 'multiple') !== false)->andWhere('t2.multiple')->eq('1')->fi()
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
->orderBy($orderBy)
|
||||
->orderBy($waterFallOrderBy)
|
||||
->fetchAll('id');
|
||||
|
||||
/* Only show leaf executions. */
|
||||
@@ -1380,7 +1383,7 @@ class productModel extends model
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
|
||||
->where('t1.product')->eq($productID)
|
||||
->andWhere('t2.type')->in('stage,sprint,kanban')
|
||||
->beginIF($branch)->andWhere('t1.branch')->in($branch)->fi()
|
||||
->beginIF($branch and $branch != 'all')->andWhere('t1.branch')->in($branch)->fi()
|
||||
->beginIF($projectID)->andWhere('t2.project')->eq($projectID)->fi()
|
||||
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
|
||||
->andWhere('t2.deleted')->eq('0')
|
||||
|
||||
@@ -79,9 +79,9 @@ class productZen extends product
|
||||
{
|
||||
if($this->app->getViewType() == 'mhtml') return $this->product->setMenu();
|
||||
|
||||
if($moduleName == 'qa') return $this->setShowErrorNoneMenu4QA($activeMenu);
|
||||
if($moduleName == 'project') return $this->setShowErrorNoneMenu4Project($activeMenu, $objectID);
|
||||
if($moduleName == 'execution') return $this->setShowErrorNoneMenu4Execution($activeMenu, $objectID);
|
||||
if($moduleName == 'qa') $this->setShowErrorNoneMenu4QA($activeMenu);
|
||||
if($moduleName == 'project') $this->setShowErrorNoneMenu4Project($activeMenu, $objectID);
|
||||
if($moduleName == 'execution') $this->setShowErrorNoneMenu4Execution($activeMenu, $objectID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,7 +401,7 @@ class productZen extends product
|
||||
$message = $this->executeHooks($productID);
|
||||
if($message) $this->lang->saveSuccess = $message;
|
||||
|
||||
return $this->sendCreateLocate($productID, $programID);
|
||||
$this->sendCreateLocate($productID, $programID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -740,7 +740,7 @@ class project extends control
|
||||
|
||||
/* Check exist extend fields. */
|
||||
$isExtended = false;
|
||||
if(!empty($this->config->bizVersion))
|
||||
if($this->config->edition != 'open')
|
||||
{
|
||||
$extend = $this->loadModel('workflowaction')->getByModuleAndAction('project', 'view');
|
||||
if(!empty($extend) and $extend->extensionType == 'extend') $isExtended = true;
|
||||
|
||||
+13
-76
@@ -116,6 +116,8 @@ class projectModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
setcookie('lastProject', (int)$this->session->project, $this->config->cookieLife, $this->config->webRoot, '', $this->config->cookieSecure, true);
|
||||
|
||||
return $this->session->project;
|
||||
}
|
||||
|
||||
@@ -257,7 +259,7 @@ class projectModel extends model
|
||||
$orderBy = $project->model == 'waterfall' ? 'id_asc' : 'id_desc';
|
||||
$pager = $project->model == 'waterfall' ? null : new pager(0, 1, 1);
|
||||
$project->executions = $this->loadModel('execution')->getStatData($projectID, 'undone', 0, 0, false, '', $orderBy, $pager);
|
||||
$project->teamCount = isset($teams[$projectID]) ? $teams[$projectID]->count : 0;
|
||||
$project->teamCount = isset($teams[$projectID]) ? $teams[$projectID] : 0;
|
||||
$project->estimate = isset($estimates[$projectID]) ? round($estimates[$projectID]->estimate, 2) : 0;
|
||||
$project->parentName = $project->parent ? $this->projectTao->getParentProgram($project->parent, $project->path, $project->grade) : '';
|
||||
}
|
||||
@@ -277,6 +279,7 @@ class projectModel extends model
|
||||
*/
|
||||
public function getOverviewList($queryType = 'byStatus', $param = 'all', $orderBy = 'id_desc', $limit = 15, $excludedModel = '')
|
||||
{
|
||||
/* */
|
||||
$queryType = strtolower($queryType);
|
||||
$projects = $this->dao->select('*')->from(TABLE_PROJECT)
|
||||
->where('type')->eq('project')
|
||||
@@ -292,32 +295,21 @@ class projectModel extends model
|
||||
->fetchAll('id');
|
||||
|
||||
if(empty($projects)) return array();
|
||||
|
||||
$projectIdList = array_keys($projects);
|
||||
$teams = $this->projectTao->fetchMemberCountByIdList($projectIdList);
|
||||
|
||||
$teams = $this->dao->select('t1.root, count(t1.id) as teams')->from(TABLE_TEAM)->alias('t1')
|
||||
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account=t2.account')
|
||||
->where('t1.root')->in($projectIdList)
|
||||
->andWhere('t1.type')->eq('project')
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->groupBy('root')->fetchPairs();
|
||||
$fields = 't2.project, ROUND(SUM(t1.consumed), 1) AS consumed, ROUND(SUM(t1.estimate), 1) AS estimate';
|
||||
$hours = $this->projectTao->fetchTaskEstimateByIdList($projectIdList, $fields);
|
||||
|
||||
$hours = $this->dao->select('t2.project, ROUND(SUM(t1.consumed), 1) AS consumed, ROUND(SUM(t1.estimate), 1) AS estimate')->from(TABLE_TASK)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution = t2.id')
|
||||
->where('t2.project')->in($projectIdList)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->andWhere('t1.parent')->lt(1)
|
||||
->groupBy('t2.project')
|
||||
->fetchAll('project');
|
||||
|
||||
$storySummary = $this->getTotalStoriesByProject($projectIdList);
|
||||
$taskSummary = $this->getTotalTaskByProject($projectIdList);
|
||||
$bugSummary = $this->getTotalBugByProject($projectIdList);
|
||||
$storySummary = $this->projectTao->getTotalStoriesByProject($projectIdList);
|
||||
$taskSummary = $this->projectTao->getTotalTaskByProject($projectIdList);
|
||||
$bugSummary = $this->projectTao->getTotalBugByProject($projectIdList);
|
||||
|
||||
foreach($projects as $projectID => $project)
|
||||
{
|
||||
$project->consumed = isset($hours[$projectID]) ? (float)$hours[$projectID]->consumed : 0;
|
||||
$project->estimate = isset($hours[$projectID]) ? (float)$hours[$projectID]->estimate : 0;
|
||||
$project->consumed = isset($hours[$projectID]) ? round((float)$hours[$projectID]->consumed, 1) : 0;
|
||||
$project->estimate = isset($hours[$projectID]) ? round((float)$hours[$projectID]->estimate, 1) : 0;
|
||||
$project->teamCount = isset($teams[$projectID]) ? $teams[$projectID] : 0;
|
||||
$project->leftBugs = isset($bugSummary[$projectID]) ? $bugSummary[$projectID]->leftBugs : 0;
|
||||
$project->allBugs = isset($bugSummary[$projectID]) ? $bugSummary[$projectID]->allBugs : 0;
|
||||
@@ -331,66 +323,11 @@ class projectModel extends model
|
||||
$project->doingTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->doingTasks : 0;
|
||||
$project->rndDoneTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->doneTasks : 0;
|
||||
$project->liteDoneTasks = isset($taskSummary[$projectID]) ? $taskSummary[$projectID]->litedoneTasks : 0;
|
||||
|
||||
if(is_float($project->consumed)) $project->consumed = round($project->consumed, 1);
|
||||
if(is_float($project->estimate)) $project->estimate = round($project->estimate, 1);
|
||||
}
|
||||
|
||||
return $projects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of stories associated with the project.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalStoriesByProject($projectIdList = 0)
|
||||
{
|
||||
return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changing', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
|
||||
->where('t1.project')->in($projectIdList)
|
||||
->andWhere('t2.type')->eq('story')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->groupBy('project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated bugs by project.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTotalBugByProject($projectIdList)
|
||||
{
|
||||
return $this->dao->select("project, count(id) as allBugs, count(if(status = 'active', 1, null)) as leftBugs, count(if(status = 'resolved', 1, null)) as doneBugs")->from(TABLE_BUG)
|
||||
->where('project')->in($projectIdList)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->groupBy('project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated tasks by project.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTotalTaskByProject($projectIdList)
|
||||
{
|
||||
return $this->dao->select("t1.project, count(t1.id) as allTasks, count(if(t1.status = 'wait', 1, null)) as waitTasks, count(if(t1.status = 'doing', 1, null)) as doingTasks, count(if(t1.status = 'done', 1, null)) as doneTasks, count(if(t1.status = 'wait' or t1.status = 'pause' or t1.status = 'cancel', 1, null)) as leftTasks, count(if(t1.status = 'done' or t1.status = 'closed', 1, null)) as litedoneTasks")->from(TABLE_TASK)->alias('t1')
|
||||
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
|
||||
->where('t1.project')->in($projectIdList)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->groupBy('t1.project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get waterfall project progress.
|
||||
*
|
||||
|
||||
+60
-4
@@ -587,20 +587,21 @@ class projectTao extends projectModel
|
||||
->where('t1.root')->in($projectIdList)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->groupBy('t1.root')
|
||||
->fetchAll('root');
|
||||
->fetchPairs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据项目ID列表查询任务的总预计工时。
|
||||
* Get task all estimate by project id list.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @param array $projectIdList
|
||||
* @param string $fields
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
protected function fetchTaskEstimateByIdList(array $projectIdList): array
|
||||
protected function fetchTaskEstimateByIdList(array $projectIdList, string $fields = 't2.project as project, sum(estimate) as estimate'): array
|
||||
{
|
||||
return $this->dao->select("t2.project as project, sum(estimate) as estimate")->from(TABLE_TASK)->alias('t1')
|
||||
return $this->dao->select($fields)->from(TABLE_TASK)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.execution = t2.id')
|
||||
->where('t1.parent')->lt(1)
|
||||
->andWhere('t2.project')->in($projectIdList)
|
||||
@@ -609,4 +610,59 @@ class projectTao extends projectModel
|
||||
->groupBy('t2.project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过项目ID列表查询需求的数量。
|
||||
* Get the number of stories associated with the project.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTotalStoriesByProject(array $projectIdList): array
|
||||
{
|
||||
return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changing', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id')
|
||||
->where('t1.project')->in($projectIdList)
|
||||
->andWhere('t2.type')->eq('story')
|
||||
->andWhere('deleted')->eq('0')
|
||||
->groupBy('project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过项目ID获取任务数量统计。
|
||||
* Get the number of tasks associated with the project.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTotalTaskByProject(array $projectIdList): array
|
||||
{
|
||||
return $this->dao->select("t1.project, count(t1.id) as allTasks, count(if(t1.status = 'wait', 1, null)) as waitTasks, count(if(t1.status = 'doing', 1, null)) as doingTasks, count(if(t1.status = 'done', 1, null)) as doneTasks, count(if(t1.status = 'wait' or t1.status = 'pause' or t1.status = 'cancel', 1, null)) as leftTasks, count(if(t1.status = 'done' or t1.status = 'closed', 1, null)) as litedoneTasks")->from(TABLE_TASK)->alias('t1')
|
||||
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution=t2.id')
|
||||
->where('t1.project')->in($projectIdList)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->andWhere('t2.deleted')->eq(0)
|
||||
->groupBy('t1.project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过项目ID获取Bug数量统计。
|
||||
* Get the number of bugs associated with the project.
|
||||
*
|
||||
* @param array $projectIdList
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getTotalBugByProject(array $projectIdList): array
|
||||
{
|
||||
return $this->dao->select("project, count(id) as allBugs, count(if(status = 'active', 1, null)) as leftBugs, count(if(status = 'resolved', 1, null)) as doneBugs")->from(TABLE_BUG)
|
||||
->where('project')->in($projectIdList)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->groupBy('project')
|
||||
->fetchAll('project');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->getTotalBugByProject();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取id为11的项目下激活的bug数量 >> 4
|
||||
获取id为27的项目下激活的bug数量 >> 1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('project');
|
||||
|
||||
$projectIdList = array(11, 12, 13, 14, 15, 16, 27);
|
||||
$result = $tester->project->getTotalBugByProject($projectIdList, 'active');
|
||||
|
||||
r($result[11]) && p('allBugs') && e('4'); //获取id为11的项目下激活的bug数量
|
||||
r($result[27]) && p('allBugs') && e('1'); //获取id为27的项目下激活的bug数量
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel::getTotalStoriesByProject;
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
不传入产品ID列表,获取项目11下的所有需求数量 >> 4
|
||||
传入产品ID列表,获取项目11下的所有需求数量 >> 4;4
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('project');
|
||||
|
||||
$projectIdList = array(12,13);
|
||||
$stories1 = $tester->project->getTotalStoriesByProject(11);
|
||||
$stories2 = $tester->project->getTotalStoriesByProject($projectIdList);
|
||||
|
||||
r($stories1[11]) && p('allStories') && e('4'); // 不传入产品ID列表,获取项目11下的所有需求数量
|
||||
r($stories2) && p('12:allStories;13:allStories') && e('4;4'); // 传入产品ID列表,获取项目11下的所有需求数量
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->getTotalTaskByProject();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取id为11的项目下进行中的task数量 >> 4
|
||||
获取id为15的项目下完成的task数量 >> 2
|
||||
获取id为27的项目下激活的task数量 >> 8
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('project');
|
||||
|
||||
$projectIdList = array(11, 12, 13, 14, 15, 16, 27);
|
||||
$result = $tester->project->getTotalTaskByProject($projectIdList);
|
||||
|
||||
r($result[11]) && p('doingTasks') && e('4'); // 获取id为11的项目下进行中的task数量
|
||||
r($result[15]) && p('doneTasks') && e('2'); // 获取id为15的项目下完成的task数量
|
||||
r($result[27]) && p('leftTasks') && e('8'); // 获取id为27的项目下激活的task数量
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('project');
|
||||
$project->id->range('11-19');
|
||||
$project->project->range('11-19');
|
||||
$project->name->prefix("项目")->range('11-19');
|
||||
$project->code->prefix("project")->range('11-19');
|
||||
$project->model->range("scrum");
|
||||
$project->auth->range("[]");
|
||||
$project->path->range("[]");
|
||||
$project->type->range("project");
|
||||
$project->grade->range("1");
|
||||
$project->days->range("1");
|
||||
$project->status->range("wait,doing,suspended,closed");
|
||||
$project->desc->range("[]");
|
||||
$project->budget->range("100000,200000");
|
||||
$project->budgetUnit->range("CNY");
|
||||
$project->percent->range("0-0");
|
||||
$project->openedDate->range("`2023-05-01 10:00:10`");
|
||||
$project->gen(9);
|
||||
|
||||
zdTable('bug')->gen(50);
|
||||
}
|
||||
|
||||
initData();
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->getTotalBugByProject();
|
||||
cid=1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('project');
|
||||
|
||||
|
||||
$projectIdList = array(11, 12, 13, 14, 15, 16, 27);
|
||||
$result = $tester->project->getTotalBugByProject($projectIdList);
|
||||
$result2 = $tester->project->getTotalBugByProject(array());
|
||||
|
||||
r($result) && p('11:allBugs') && e('3'); //获取id为11的项目下bug数量
|
||||
r($result) && p('27:allBugs') && e('Error: Cannot get index 27.'); //获取id为27的项目下bug数量
|
||||
r($result2) && p() && e('0'); //获取项目为空时的bug数量
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('project');
|
||||
$project->id->range('11-19');
|
||||
$project->project->range('11-19');
|
||||
$project->name->prefix("项目")->range('11-19');
|
||||
$project->code->prefix("project")->range('11-19');
|
||||
$project->model->range("scrum");
|
||||
$project->auth->range("[]");
|
||||
$project->path->range("[]");
|
||||
$project->type->range("project");
|
||||
$project->grade->range("1");
|
||||
$project->days->range("1");
|
||||
$project->status->range("wait,doing,suspended,closed");
|
||||
$project->desc->range("[]");
|
||||
$project->budget->range("100000,200000");
|
||||
$project->budgetUnit->range("CNY");
|
||||
$project->percent->range("0-0");
|
||||
$project->openedDate->range("`2023-05-01 10:00:10`");
|
||||
$project->gen(9);
|
||||
|
||||
zdTable('story')->gen(50);
|
||||
zdTable('projectstory')->gen(10);
|
||||
}
|
||||
|
||||
initData();
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel::getTotalStoriesByProject;
|
||||
cid=1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$projectTester = $tester->loadModel('project');
|
||||
|
||||
$noneIdList = array();
|
||||
$notExistsIdList = array(1);
|
||||
$realIdList = array(12, 13);
|
||||
|
||||
r($projectTester->getTotalStoriesByProject($noneIdList)) && p() && e('0'); // 不传入项目ID列表,获取需求数量
|
||||
r($projectTester->getTotalStoriesByProject($notExistsIdList)) && p() && e('0'); // 传入错误的ID列表,获取需求数量
|
||||
r($projectTester->getTotalStoriesByProject($realIdList)) && p('12:allStories;13:allStories') && e('2,2'); // 传入正确的ID列表,获取需求数量
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . "/test/lib/init.php";
|
||||
su('admin');
|
||||
|
||||
function initData()
|
||||
{
|
||||
$project = zdTable('project');
|
||||
$project->id->range('11-19,101-109');
|
||||
$project->project->range('11-19');
|
||||
$project->name->setFields(array(
|
||||
array('field' => 'name1', 'range' => '项目{9},迭代{9}'),
|
||||
array('field' => 'name2', 'range' => '11-19,101-109')
|
||||
));
|
||||
$project->code->setFields(array(
|
||||
array('field' => 'name1', 'range' => 'project{9},execution{9}'),
|
||||
array('field' => 'name2', 'range' => '11-19,101-109')
|
||||
));
|
||||
$project->model->range("scrum{9},[]{9}");
|
||||
$project->auth->range("[]");
|
||||
$project->path->range("[]");
|
||||
$project->type->range("project{9},sprint{9}");
|
||||
$project->grade->range("1");
|
||||
$project->days->range("1");
|
||||
$project->status->range("wait,doing,suspended,closed");
|
||||
$project->desc->range("[]");
|
||||
$project->budget->range("100000,200000");
|
||||
$project->budgetUnit->range("CNY");
|
||||
$project->percent->range("0-0");
|
||||
$project->openedDate->range("`2023-05-01 10:00:10`");
|
||||
$project->gen(18);
|
||||
|
||||
zdTable('task')->gen(10);
|
||||
}
|
||||
|
||||
initData();
|
||||
|
||||
/**
|
||||
|
||||
title=测试 projectModel->getTotalTaskByProject();
|
||||
cid=1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('project');
|
||||
|
||||
$projectIdList = array(11, 12, 13, 14, 15, 16, 27);
|
||||
$result1 = $tester->project->getTotalTaskByProject($projectIdList);
|
||||
$result2 = $tester->project->getTotalTaskByProject(array());
|
||||
|
||||
r($result1) && p('11:waitTasks') && e('1'); // 获取id为11的项目下未开始的task数量
|
||||
r($result1) && p('15:allTasks') && e('1'); // 获取id为15的项目下所有的task数量
|
||||
r($result1) && p('27:waitTasks') && e('Error: Cannot get index 27.'); // 获取id为27的项目下未开始的task数量
|
||||
r($result2) && p() && e('0'); // 获取项目为空的task数量
|
||||
@@ -312,7 +312,7 @@
|
||||
?>
|
||||
<td class='c-build' title='<?php echo $openedBuildName?>'><?php echo $openedBuildName;?></td>
|
||||
<td class='c-user'><?php echo zget($users, $bug->openedBy);?></td>
|
||||
<td class='c-date'><?php echo $bug->openedDate?></td>
|
||||
<td class='c-date'><?php echo helper::isZeroDate($bug->openedDate) ? '' : substr($bug->openedDate, 5, 11);?></td>
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
if(common::hasPriv('projectrelease', 'unlinkBug') and $canBeChanged)
|
||||
|
||||
+14
-20
@@ -118,11 +118,11 @@ class report extends control
|
||||
*
|
||||
* @param string $year
|
||||
* @param string $dept
|
||||
* @param string $userID
|
||||
* @param string $account
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function annualData($year = '', $dept = '', $userID = '')
|
||||
public function annualData($year = '', $dept = '', $account = '')
|
||||
{
|
||||
$this->app->loadLang('story');
|
||||
$this->app->loadLang('task');
|
||||
@@ -131,7 +131,7 @@ class report extends control
|
||||
$this->loadModel('dept');
|
||||
$this->loadModel('user');
|
||||
|
||||
$super = common::hasPriv('report', 'allAnnualData');
|
||||
$super = common::hasPriv('screen', 'allAnnualData');
|
||||
|
||||
$firstAction = $this->dao->select('*')->from(TABLE_ACTION)->orderBy('id')->limit(1)->fetch();
|
||||
$currentYear = date('Y');
|
||||
@@ -154,20 +154,16 @@ class report extends control
|
||||
}
|
||||
|
||||
/* Get users and depts. */
|
||||
$accounts = array();
|
||||
if($userID)
|
||||
if($account)
|
||||
{
|
||||
$user = $this->user->getById($userID, 'id');
|
||||
$dept = $user->dept;
|
||||
$users = array('' => $this->lang->report->annualData->allUser) + $this->dept->getDeptUserPairs($dept, 'id');
|
||||
$accounts = array($user->account => ($user->realname ? $user->realname : $user->account));
|
||||
}
|
||||
else
|
||||
{
|
||||
$users = array('' => $this->lang->report->annualData->allUser) + $this->dept->getDeptUserPairs($dept, 'id');
|
||||
$accounts = $this->dept->getDeptUserPairs($dept);
|
||||
$user = $this->user->getByID($account);
|
||||
$dept = $user->dept;
|
||||
}
|
||||
|
||||
$userPairs = $this->dept->getDeptUserPairs($dept);
|
||||
$accounts = !empty($user) ? array($user->account) : array_keys($userPairs);
|
||||
$users = array('' => $this->lang->report->annualData->allUser) + $userPairs;
|
||||
|
||||
$noDepartment = array('0' => '/' . $this->lang->dept->noDepartment);
|
||||
$depts = $this->dept->getOptionMenu();
|
||||
if(!$super)
|
||||
@@ -182,11 +178,9 @@ class report extends control
|
||||
$depts += $noDepartment;
|
||||
}
|
||||
|
||||
if($accounts) $accounts = array_keys($accounts);
|
||||
|
||||
/* Get annual data. */
|
||||
$data = array();
|
||||
if(!$userID)
|
||||
if(!$account)
|
||||
{
|
||||
$data['users'] = $dept ? count($accounts) : (count($users) - 1);
|
||||
}
|
||||
@@ -208,7 +202,7 @@ class report extends control
|
||||
$yearEfforts = $this->report->getUserYearEfforts($accounts, $year);
|
||||
$data['consumed'] = $yearEfforts->consumed;
|
||||
|
||||
if(empty($dept) and empty($userID)) $data['statusStat'] = $this->report->getAllTimeStatusStat();
|
||||
if(empty($dept) and empty($account)) $data['statusStat'] = $this->report->getAllTimeStatusStat();
|
||||
|
||||
$contributionGroups = array();
|
||||
$maxCount = 0;
|
||||
@@ -240,14 +234,14 @@ class report extends control
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->title = sprintf($this->lang->report->annualData->title, ($userID ? zget($users, $userID, '') : (($dept !== '') ? substr($depts[$dept], strrpos($depts[$dept], '/') + 1) : $depts[''])), $year);
|
||||
$this->view->title = sprintf($this->lang->report->annualData->title, ($account ? zget($users, $account, '') : (($dept !== '') ? substr($depts[$dept], strrpos($depts[$dept], '/') + 1) : '')), $year);
|
||||
$this->view->data = $data;
|
||||
$this->view->year = $year;
|
||||
$this->view->users = $users;
|
||||
$this->view->depts = $depts;
|
||||
$this->view->years = $years;
|
||||
$this->view->dept = $dept;
|
||||
$this->view->userID = $userID;
|
||||
$this->view->account = $account;
|
||||
$this->view->months = $this->report->getYearMonths($year);
|
||||
$this->view->contributionGroups = $contributionGroups;
|
||||
$this->view->radarData = $contributionGroups[$year];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user