This commit is contained in:
lanzongjun
2023-05-05 10:59:05 +08:00
251 changed files with 3591 additions and 1945 deletions
+3 -3
View File
@@ -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';
-20
View File
@@ -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
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -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
View File
File diff suppressed because one or more lines are too long
+431 -397
View File
@@ -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
View File
@@ -1 +1 @@
v7.1.0
e46c36b1746f2bd7326146f634aee8963a19f8fa
+3 -6
View File
@@ -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);
/**
* 设置调用的类名。
+5 -5
View File
@@ -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();
+9 -9
View File
@@ -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();
+1 -1
View File
@@ -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();
+1
View File
@@ -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;
+2 -2
View File
@@ -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))
{
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
}
}
+7 -4
View File
@@ -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();
+1 -1
View File
@@ -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
View File
@@ -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;
}
}
+4 -2
View File
@@ -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);
}
-2
View File
@@ -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'")
+1 -1
View File
@@ -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
View File
@@ -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);
+23 -15
View File
@@ -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);
}
+12 -12
View File
@@ -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 字段字符超出长度
+15 -5
View File
@@ -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
))
))
)
)
)
+1 -4
View File
@@ -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();
+19 -6
View File
@@ -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>
+20 -7
View File
@@ -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
View File
@@ -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;
}
}
+1 -1
View File
@@ -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--)
+2 -2
View File
@@ -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');
+1 -1
View File
@@ -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')
+2 -1
View File
@@ -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)
{
+4 -4
View File
@@ -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';
+4 -4
View File
@@ -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';
+4 -4
View File
@@ -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
View File
@@ -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;
}
}
+24 -22
View File
@@ -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>
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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&param=$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');
+1 -1
View File
@@ -18,7 +18,7 @@ $(function()
$('#saveDraft').click(function()
{
if($('#editorTitle').val() == '')
if($.trim($('#editorTitle').val()) == '')
{
bootbox.alert(titleNotEmpty);
return false;
+1 -1
View File
@@ -8,7 +8,7 @@ $(function()
$('#saveDraft').click(function()
{
if($('#editorTitle').val() == '')
if($.trim($('#editorTitle').val()) == '')
{
bootbox.alert(titleNotEmpty);
return false;
+1 -1
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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;?>
+6 -4
View File
@@ -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);
+1 -1
View File
@@ -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))
{
+5 -3
View File
@@ -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')
+13 -4
View File
@@ -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);
+24 -24
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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');
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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']);
+1 -1
View File
@@ -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&param=$group->id", $group, 'list', 'lock');?>
<?php common::printIcon('group', 'managepriv', "type=byPackage&param=$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'");?>
+2 -2
View File
@@ -80,8 +80,8 @@
<div id='mainContainer'>
<div class='main main-content'>
<div class="btn-group">
<?php echo html::a(inlink('managePriv', "type=byGroupbyPackage&param=$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&param=$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&param=$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();
})
/**
+1 -1
View File
@@ -80,8 +80,8 @@
<div id='mainContainer'>
<div class='main main-content'>
<div class="btn-group">
<?php echo html::a(inlink('managePriv', "type=byGroup&param=$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&param=$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&param=$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>
+5 -3
View File
@@ -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();
+1 -1
View File
@@ -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' => '');
+1 -1
View File
@@ -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' => '');
+1 -1
View File
@@ -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' => '');
+1 -1
View File
@@ -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' => '');
+1 -1
View File
@@ -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';
+1 -1
View File
@@ -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';
+1 -1
View File
@@ -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';
+1 -1
View File
@@ -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 = '我的风险';
+91
View File
@@ -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';
+55 -3
View File
@@ -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);
}
}
+10
View File
@@ -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;}
+15 -5
View File
@@ -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;}
+1 -1
View File
@@ -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&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=bugcreate&params=' + params);
location.href = link;
}
+460
View File
@@ -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);});
}
+298
View File
@@ -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';
}
+1 -1
View File
@@ -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&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=productSummary&params=' + params);
location.href = link;
})
+1 -1
View File
@@ -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&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=projectdeviation&params=' + params);
location.href = link;
}
+1 -1
View File
@@ -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&params=' + params);
var link = createLink('pivot', 'preview', 'dimension=' + dimension + '&group=' + groupID + '&module=pivot&method=workload&params=' + params);
location.href = link;
}
+62 -51
View File
@@ -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':
+5 -6
View File
@@ -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'>
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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&params=$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>';
+2 -4
View File
@@ -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'"));
}
/**
+8 -5
View File
@@ -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')
+4 -4
View File
@@ -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);
}
/**
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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数量
+1 -1
View File
@@ -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
View File
@@ -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