Merge branch 'master' into sprint/feedback_module

This commit is contained in:
wangyidong
2022-10-11 09:33:25 +08:00
381 changed files with 17770 additions and 2099 deletions
+41 -30
View File
@@ -1,11 +1,13 @@
stages:
- sonar
- unit_test
- uitest
- cleanup_packages
- sonarqube
- unit-test
- ui-test
- package
sonarqube:
stage: sonar
- cleanup-packages
- notify
program-static-analysis:
stage: sonarqube
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
@@ -18,6 +20,25 @@ sonarqube:
allow_failure: true
only:
- master # or the name of your main branch
unit-test:
stage: unit-test
script:
- "/home/gitlab-runner/bin/zentao-unittest.sh ${CI_PROJECT_DIR}"
allow_failure: true
only:
- master
- merge_requests
ui-test:
stage: ui-test
script:
- "/home/gitlab-runner/bin/zentao-uitest.sh ${CI_PROJECT_DIR}"
allow_failure: true
only:
- master
- merge_requests
package:
stage: package
script:
@@ -25,30 +46,20 @@ package:
allow_failure: true
only:
- master
unit_test:
stage: unit_test
script:
- "/home/gitlab-runner/bin/zentao-unittest.sh ${CI_PROJECT_DIR}"
allow_failure: true
only:
- master
- merge_requests
uitest:
stage: uitest
script:
- "/home/gitlab-runner/bin/zentao-uitest.sh ${CI_PROJECT_DIR}"
allow_failure: true
only:
- master
- merge_requests
#notify:
# script:
# - 'curl --location --request POST ''http://api.lf.oop.cc/api/v1/xuan/chatMessage'' --header ''Content-Type: application/json'' --data-raw ''{"gid": "84be4c6e-02e3-4fdc-b081-318c0c1eca02", "title": "开源包下载地址", "content": "点击查看详情链接", "url": "http://10.0.7.242:8080/allpacks/"}'''
# when: on_success
# only:
# - master
cleanup_packages:
stage: cleanup_packages
cleanup-packages:
stage: cleanup-packages
script:
- make clean
when: on_failure
only:
- master
notify:
stage: notify
script:
- "/home/gitlab-runner/bin/ci-notify.php"
when: on_success
only:
- master
- merge_requests
+5
View File
@@ -102,6 +102,11 @@ zentaoxx:
mkdir zentaoxx/db/
cp zentaoxx/db_bak/upgradexuanxuan*.sql zentaoxx/db_bak/xuanxuan.sql zentaoxx/db/
rm -rf zentaoxx/db_bak/
sed -i "s/\$$accountAdmin = \$$this->dao->select('account, admin')->from(TABLE_USER)->where('id')->eq(\$$userID)->fetch();/\$$accountAdmin = \$$this->dao->select('account')->from(TABLE_USER)->where('id')->eq(\$$userID)->fetch();\n\$$admins = \$$this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq(\$$this->app->company->id)->fetch('admins');\n\$$adminArray = explode(',', \$$admins);\n\$$accountAdmin->admin = in_array(\$$accountAdmin->account, \$$adminArray) ? 'super' : '';\n/" zentaoxx/extension/xuan/im/model/chat.php
sed -i "/->on('tc.ownedBy=tu.account')/{ N ; s/type/tc.type/}" zentaoxx/extension/xuan/im/model/chat.php
sed -i "s/\$$super = \$$this->dao->select('admin')->from(TABLE_USER)->where('id')->eq(\$$userID)->fetch('admin');/\$$account = \$$this->dao->select('account')->from(TABLE_USER)->where('id')->eq(\$$userID)->fetch('account');\n\$$admins = \$$this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq(\$$this->app->company->id)->fetch('admins');\n\$$adminArray = explode(',', \$$admins);\n\$$super = in_array(\$$account, \$$adminArray) ? 'super' : '';/g" zentaoxx/extension/xuan/im/control.php
sed -i "/foreach(\$$users as \$$user)/i \$$admins = \$$this->dao->select('admins')->from(TABLE_COMPANY)->where('id')->eq(\$$this->app->company->id)->fetch('admins');\$$adminArray = explode(',', \$$admins);" zentaoxx/extension/xuan/im/model/user.php
sed -i "/if(\!isset(\$$user->signed)) \$$user->signed = 0;/a \$$user->admin = in_array(\$$user->account, \$$adminArray) ? 'super' : '';" zentaoxx/extension/xuan/im/model/user.php
sed -i 's/XXBVERSION/$(XVERSION)/g' zentaoxx/config/ext/_0_xuanxuan.php
sed -i "/\$$config->xuanxuan->backend /c\\\$$config->xuanxuan->backend = 'zentao';" zentaoxx/config/ext/_0_xuanxuan.php
sed -i 's/site,//' zentaoxx/extension/xuan/im/model/user.php
+64 -30
View File
@@ -1,47 +1,81 @@
## 1. What is ZenTao?
English | [中文](Readme_zh.md)
ZenTao is an open source project management software, developed by Qingdao Nature Easy Soft Network Technology Co. Ltd. Combining product management, project management, QA management, document management, company management and todo management. It is a professional project management software, covering the core process of software development projects.
<p align="center"><a href="https://www.zentao.pm" target="_blank" rel="noopener noreferrer"><img src="doc/img/zentao-en.png" alt="ZenTao Logo"></a></p>
<p align="center">
<a href="https://www.php.net"><img src="https://img.shields.io/badge/php-%3E=5.6-brightgreen.svg?maxAge=2592000" alt="PHP Version"></a>
<a href="https://github.com/easysoft/zentaopms/releases/latest"><img src="https://img.shields.io/github/release/easysoft/zentaopms.svg" alt="Latest Version"></a>
<a href="mailto:chunsheng@easycorp.ltd"><img src="https://img.shields.io/badge/Email-chunsheng@easycorp.ltd-ea644a" alt="Email" /></a>
<a href="https://github.com/easysoft/zentaopms/blob/master/COPYING"><img src="https://img.shields.io/badge/License-AGPL%20or%20ZPL-blue" alt="ZenTao License"></a>
<a href="https://www.zentao.pm"><img src="https://img.shields.io/badge/Website-www.zentao.pm-blue" alt="ZenTao Website"></a>
</p>
ZenTao is practical and pragmatic. It has full features and beautiful interfaces, and is easy to use. ZenTao is well structured and can be flexibly extended. It also has powerful search features, various forms of statistical reports and complete API.
# Introduction
ZenTao is the first opensource project management software in China. It’s a comprehensive, all-in-one platform that covers the main PM process, from product and project management to quality management, documentation management, organization management, and office management.
ZenTao focuses on development project management!
Since its establishment in 2009, ZenTao has helped tens of thousands of teams and organizations improve their project management structures. Currently, ZenTao is being used by some of the largest companies in the world, ranging from those in the sectors of finance and telecoms to manufacturing and software development. They trust ZenTao for streamlining their processes, simplifying communication between clients and employees, increasing transparency, and improving productivity and efficiency.
## 2. Why is it called ZenTao?
# Design Philosophy
Zen(禅) and Tao(道) are the two Chinese characters that have rich meanings in both religion and culture. ZenTao Project Management Software takes the cultural meaning of Zen and Tao, and is expected to convey our understanding and thinking of management. Inspired by The Tao of Programming and The Zen of Programming, we named our software ZenTao.
The name ZenTao came from combining two Chinese characters, Zen(禅) and Tao(道), which have rich inspirations pertaining to culture and history. With its name referring to highly respected aspects of life, it’s only logical to convey their meaning in management by providing transparency, orderliness, and accessibility.
## 3. Design philosophy of ZenTao Project Management Software
ZenTao management concept is built on the 3 popular management methodologies: Scrum, Waterfall, and Kanban:
The main design philosophy of ZenTao Project Management Software is based on Scrum, an internationally popular Agile methodology. Scrum is very pragmatic and easy to operate, so it fits in the fast iterative development of software projects. However, Scrum only defines the core management framework. There are still many details and processes that have to be extended and developed. Based on the philosophy of Scrum and with the observation of the current development situations in China, ZenTao integrates bug management, test case management, release management and document management, and it completely covers the entire lifecycle of software development. In ZenTao, the concepts of product, project and test are clearly defined. Product team, development team and QA team coordinate and check with each other while they function differently. The three teams interact with each other through stories, tasks and bugs, and eventually deliver the product with quality.
- The Scrum model built-in ZenTao is adaptable and flexible, which perfectly matches the rapid iterations of software development projects.
- The Waterfall model built-in ZenTao lays emphasis on stages division and strict process control, which is ideal for projects that are well defined in advance and with fewer changes.
- The Kanban model built-in ZenTao pays more attention to value flow and visualization, which is suitable for the team with a transparent process and efficient transmission of information.
## 4. Why choose ZenTao Project Management Software?
ZenTao clearly defines the concepts of product, project, and QA to help the product owners, developers, and testers coordinate with each other while maintaining separate functionalities. Through stories, tasks, and bugs, the whole teams interact and track issues and improvements to ensure the delivery of quality products.
* ZenTao is a professional development project management software and cannot be replaced by any simple project management software.
* ZenTao has precise and pragmatic management philosphy, which will accelerate Agile development.
* ZenTao has full features as a project management software, so you don’t have to integrate several systems together, like mantisbt + trac + testlink.
* Open source codes and flexible extension mechanism. It is convenient to use and develop based on ZenTao.
* Underlying framework and frontend UI framework are developed independently; robust and stable with beautiful interface and friendly interaction.
* Perfect community mechanism; you can get technical support and help in time.
* Zero input, which means you have no risk for choosing ZenTao, compared with other commercial software that cost you thousands of dollars.
* Support various deployments, either private or cloud.
Besides, with ZenTao's feature-rich modules including data visualization, measurement, DevOps, Doc asset management, and automated testing, ZenTao offers flexible solutions to cover the entire process of software development, allows organizations to work efficiently and productivity, and helps them better control time, cost, and quality.
# Official Website
## 5. Features of ZenTao Project Management Software
- [Website](https://www.zentao.pm/)
- [Manual](https://www.zentao.pm/book/)
- [FAQ](https://www.zentao.pm/page/faq.html)
- [Extension](https://www.zentao.pm/extension-browse.html)
* Product management: including products, stories, plans, releases and roadmaps;
* Project management: including projects, tasks, teams, builds and burn-down charts;
* Quality management: including bugs, test cases, test tasks and test results;
* Document management: including product document library, project document library and customized document library;
* Work management: including to-do management and personal management, such as my tasks, my bugs, my story and my projects;
* Organization management: including department, users, groups and privileges;
* Statistics: various reports;
* Search: powerful search functions to help you find the data you need.
* Extension mechanism: extensible in almost any parts of ZenTao;
* API mechanism: convenient for integration with other systems.
# Demo
## 6. Website
- [ZenTao Opensource](https://demo15.zentao.pm)
- [ZenTao Biz](https://biz.demo15.zentao.pm)
- [ZenTao Max](https://max.demo15.zentao.pm)
Our website is: [www.zentao.pm](http://www.zentao.pm)
# Security Vulnerabilities
If you find any vulnerability in ZenTao system please feel free to contact us at chunsheng@easycorp.ltd. We do appreciate your time and effort.
# License
ZenTao is an opensource project management software licensed on [AGPL](https://www.gnu.org/licenses/agpl-3.0.en.html) and [ZPL](http://zpl.pub/page/zplv12.html).
<details>
<summary><h1>Enhanced version<h1/></summary>
ZenTao Biz, ZenTao Max, and ZenTao Cloud are available for you if ZenTao Opensource can not meet your feature requirement.
> [Learn more about the comparison between ZenTao Opensource, ZenTao Biz, and ZenTao Max](https://www.zentao.pm/page/vs.html).
## ZenTao Biz
ZenTao Biz has more powerful functions based on the ZenTao Open Source. It also expands horizontally based on the project management process and covers more roles.
On the one hand, ZenTao Biz provides more complete services for enterprises and its enhanced functions are more suitable for the internal process management of the companies.
On the other hand, ZenTao Biz has more added functions such as operation and maintenance management, OA office management, feedback management, as well as document version management, and online preview. It can support the customer's related work more effectively outside the development process, and provide more comprehensive support for the project management process.
## ZenTao Max
ZenTao Max, the most advanced ZenTao version, allows users to easily monitor and track the entire process of project management. It also helps improve the robustness and maturity of enterprises to greatly increase the probability of project success.
The features such as process control, process definition, project measurement, issue management, risk management, quality assurance, and project reporting are strong enhanced in ZenTao Max. It's also supported the implementation of CMMI standards, help enterprises pass CMMI assessment.
## ZenTao Cloud
> Learn more about [ZenTao Cloud](https://www.zentao.pm/page/saas-pricing.html).
ZenTao Cloud provides a flexible solution for users who prefer the SaaS service and running businesses anywhere and anytime. It's easy to use and super convenient in that it only needs one click to activate an account. Besides, ZenTao Cloud requires no maintenance and will keep updating automatically. With HTTPS agreement, your data will keep safe and no worry about information disclosure. Even better, data on ZenTao Cloud will backup automatically and users can download the backup file at any time.
</details>
+77 -29
View File
@@ -1,41 +1,89 @@
一、什么是禅道项目管理软件?
[English](README.md) | 中文
禅道是第一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、 组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整地覆盖了项目管理的核心流程。禅道管理思想注重实效,软件架构合理,操作简洁高效,代码实现合理,内置灵活的扩展机制和api调用机制,支持多语言。
<p align="center"><a href="https://www.zentao.net" target="_blank" rel="noopener noreferrer"><img src="doc/img/zentao-cn.png" alt="ZenTao Logo"></a></p>
二、为什么用“禅道”这个名字?
<p align="center">
<a href="https://www.php.net"><img src="https://img.shields.io/badge/php-%3E=5.6-brightgreen.svg?maxAge=2592000" alt="PHP Version"></a>
<a href="https://github.com/easysoft/zentaopms/releases/latest"><img src="https://img.shields.io/github/release/easysoft/zentaopms.svg" alt="Latest Version"></a>
<a href="mailto:chunsheng@easycorp.ltd"><img src="https://img.shields.io/badge/Email-chunsheng@easycorp.ltd-ea644a" alt="Email" /></a>
<a href="https://github.com/easysoft/zentaopms/blob/master/COPYING"><img src="https://img.shields.io/badge/License-AGPL%20or%20ZPL-blue" alt="ZenTao License"></a>
<a href="https://www.zentao.net"><img src="https://img.shields.io/badge/Website-www.zentao.net-blue" alt="ZenTao Website"></a>
</p>
# 介绍
禅道是第一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、 组织管理和事务管理于一体,是一款专业的研发项目管理软件,完整地覆盖了项目管理的核心流程。
禅道管理思想注重实效,功能完备丰富,操作简洁高效,界面美观大方,搜索功能强大,统计报表丰富多样,软件架构合理,扩展灵活,有完善的 API 可以调用。
# 设计理念
禅和道是中国文化中极具代表意义的两个字,是中国传统文化的结晶。我们之所以选用“禅道”作为我们软件的名字,是希望通过这两个字来传达我们对管理的理解和思考。我们希望通过禅道来进行的管理,可以摒弃繁文缛节,还原管理的本质!
三、禅道的设计理念
禅道项目管理软件的主要管理思想基于国际流行的`Scrum`模型、瀑布模型和看板模型三种项目管理方法:
禅道项目管理软件的主要管理思想基于国际流行的敏捷项目管理方 式——Scrum。scrum是一种注重实效的敏捷项目管理方式。它规定了核心的管理框架,但具体的细节还需要团队自行扩充。禅道在遵循其管理方式基础上,又融入了国内研发现状的很多需求,比如bug管理,测试用例管理,发布管理,文档管理等。因此禅道不仅仅是一款scrum敏捷项目管理工 具,更是一款完备的项目管理软件。基于scrum,又不局限于scrum。
- `Scrum`模型方法注重实效,操作性强,非常适合软件研发项目的快速迭代开发。
禅道还首次创造性的将产品、项目、测试这三者的概念明确分开,互相配合,又互相制约,通过需求、任务、bug来进行交相互动,终通过项目拿到合格的产品。
- 瀑布模型方法注重阶段清晰、流程严谨、范围可控,非常适合预先有明确定义且变动不大的产品研发管理。
四、选择禅道的八大理由:
1. 开源的软件,保证了您使用的放心和灵活。
2. 先进的管理思想,让您在竞争中拔得头筹。
3. 完备的管理功能,无需再整合其他多个系统。
4. 国产软件,中文支持,操作习惯更符合国人。
5. 灵活的扩展机制,可以保证您不局限于禅道自身的功能。
6. 日趋完善的社区机制,可以获得及时的技术支持和帮助,保证您无后顾之忧。
7. 几乎为零的投入,禅道作为开源软件,其投入几乎为零,相比动辄十几万的商业软件,您选择禅道没有任何风险。
8. 开发团队已经公司化运作,保证软件的持久发展。我们从04年从事开源软件开发以来,已经坚持了六年。
- 看板模型方式注重价值流转和可视化,非常适合流程公开透明和信息高效传递的团队。
五、禅道的功能列表:
禅道首次创造性的将产品、项目、测试这三者的概念明确分开,产品人员、开发团队、测试人员,三者分立,互相配合,又互相制约,通过需求、任务、`BUG` 来进行交相互动,终通过项目拿到合格的产品。
1. 产品管理:包括产品、需求、计划、发布、路线图等功能。
2. 项目管理:包括项目、任务、团队、build、燃尽图等功能。
3. 质量管理:包括bug、测试用例、测试任务、测试结果等功能。
4. 文档管理:包括产品文档库、项目文档库、自定义文档库等功能。
5. 事务管理:包括todo管理,我的任务、我的Bug、我的需求、我的项目等个人事务管理功能。
6. 组织管理:包括部门、用户、分组、权限等功能。
7. 统计功能:丰富的统计表。
8. 搜索功能:强大的搜索,帮助您找到相应的数据。
9. 灵活的扩展机制,几乎可以对禅道的任何地方进行扩展。
10. 强大的api机制,方便与其他系统集成。
在数据可视化、度量、`DevOPS`、文档资产管理和自动化测试等模块的加持下,禅道软件形成了项目流程管理、`DevOps`一体化、自动化测试等三大解决方案,完整的覆盖了产品研发的全生命周期管理,助力广大企业高效协作、降本提效。
也许您已经"众里寻她千百度",那么让禅道带给您“蓦然回首,那人却在灯火阑珊处”的惊喜吧!Let's zentao!
# 官方网站
禅道官方网站: [www.zentao.net](http://www.zentao.net)
- [官网](https://www.zentao.net)
- [文档](https://www.zentao.net/book/zentaopms.html)
- [常见问题](https://www.zentao.net/faq.html)
- [插件库](https://www.zentao.net/extension-browse.html)
## Demo
- [开源版](https://demo16.zentao.net)
- [企业版](https://biz.demo16.zentao.net)
- [旗舰版](http://zentaomax.demo.zentao.net)
# 安全漏洞
如果您发现禅道项目管理软件中存在安全漏洞,请发送电子邮件至禅道官方团队,电子邮件地址为 chunsheng@easycorp.ltd ,所有安全漏洞都会被及时的解决。
# 开源协议
禅道是一个基于 [AGPL](https://www.gnu.org/licenses/agpl-3.0.en.html) 和 [ZPL](http://zpl.pub/page/zplv12.html) 双协议的开源项目管理软件。
----
也许您已经"众里寻她千百度",那么让禅道带给您"蓦然回首,那人却在灯火阑珊处"的惊喜吧!
<details>
<summary><h1>增强版本<h1/></summary>
如果开源版的功能不能满足您的需要,可以考虑禅道[企业版](https://www.zentao.net/page/enterprise.html)、[旗舰版](https://www.zentao.net/page/max.html)或[云禅道](https://www.chandao.net)。
## 企业版
> 前往查看[企业版和开源版的对比](https://www.zentao.net/page/enterprise.html#diff)。
禅道企业版是在禅道开源版的基础上增加增强功能的版本,该版本也基于项目管理的流程做了横向拓展,覆盖了更多的角色。
一方面,企业版可以企业提供更完善的服务;增强功能更加适合企业的内部流程化管理。
另一方面,企业版还增加了运维管理、OA办公管理、反馈管理,以及文档的版本管理及在线预览等功能,可以更有效地支持客户在研发管理流程之外的相关工作,为企业项目管理流程提供更全面的支撑。
## 旗舰版
> 前往查看[旗舰版功能对比](https://www.zentao.net/page/max.html#diff)。
旗舰版作为禅道最高的版本系列,可以完整覆盖项目管理的各个过程,帮助企业建立研发管理体系,提高企业管理流程的稳健性和项目管理成熟度,大大增加项目成功的概率。
旗舰版增强了流程控制、过程定义、项目度量、问题管理、风险管控、质量保证、项目报告等方面的功能,同时可以支持CMMI标准的落地实施,帮助企业通过CMMI评估,提升研发管理能力。
## 云禅道
> 前往了解和体验[云禅道](https://www.chandao.net)。
云禅道是禅道企业版和旗舰版的 SaaS 服务,使用便捷,一键即可开通,无需维护,禅道版本自动升级;资源与服务支持灵活扩容,资源按需购买;提供覆盖全国的CDN服务,访问更快;HTTPS协议加密,更加安全;数据自动备份,随时下载备份至本地。
</details>
+1 -1
View File
@@ -1 +1 @@
17.6
17.6.2
+3 -3
View File
@@ -11,7 +11,7 @@
**/
class bugResolveEntry extends Entry
{
/**
/**
* POST method.
*
* @param int $bugID
@@ -19,7 +19,7 @@ class bugResolveEntry extends Entry
* @return void
*/
public function post($bugID)
{
{
$fields = 'resolution,resolvedBuild,resolvedDate,duplicateBug,assignedTo,uid,comment';
$this->batchSetPost($fields);
@@ -33,6 +33,6 @@ class bugResolveEntry extends Entry
$bug = $this->loadModel('bug')->getByID($bugID);
$this->send(200, $this->format($bug, 'openedBy:user,openedDate:time,assignedTo:user,assignedDate:time,reviewedBy:user,reviewedDate:time,resolvedDate:time,lastEditedBy:user,lastEditedDate:time,closedBy:user,closedDate:time,deleted:bool,mailto:userList'));
}
}
}
+1 -1
View File
@@ -53,7 +53,7 @@ class buildsEntry extends entry
$project = $this->loadModel('project')->getByID($projectID);
if(!$project) return $this->send404();
$fields = 'execution,product,name,builder,date,scmPath,filePath,desc';
$fields = 'execution,product,name,builder,date,scmPath,filePath,desc,branch';
$this->batchSetPost($fields);
$control = $this->loadController('build', 'create');
+1 -1
View File
@@ -22,7 +22,7 @@ class feedbacksEntry extends entry
if(strpos(strtolower($this->param('fields')), 'moduleandproduct') !== false) return $this->getModuleAndProduct();
$control = $this->loadController('feedback', 'admin');
$control->admin($this->param('solution', 'unclosed'), 0, $this->param('orderBy', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
$control->admin($this->param('status', 'unclosed'), 0, $this->param('orderBy', 'id_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
$data = $this->getData();
if(!$data or !isset($data->status)) return $this->sendError(400, 'error');
+1 -1
View File
@@ -25,7 +25,7 @@ class productProjectsEntry extends entry
$appendFields = $this->param('fields', '');
$control = $this->loadController('product', 'project');
$control->project($this->param('status', 'all'), $productID, $this->param('branch', 0), $this->param('involved', 0), $this->param('order', 'order_desc'));
$control->project($this->param('status', 'all'), $productID, $this->param('branch', 0), $this->param('involved', 0), $this->param('order', 'order_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
$data = $this->getData();
if(isset($data->status) and $data->status == 'success')
+3 -1
View File
@@ -23,8 +23,10 @@ class projectReleasesEntry extends entry
if(empty($projectID)) $projectID = $this->param('project');
if(empty($projectID)) return $this->sendError(400, 'Need project id.');
$page = intval($this->param('page', 1));
$limit = intval($this->param('limit', 20));
$control = $this->loadController('projectrelease', 'browse');
$control->browse($projectID, $this->param('execution', 0), $this->param('status', 'all'), $this->param('order', 't1.date_desc'));
$control->browse($projectID, $this->param('execution', 0), $this->param('status', 'all'), $this->param('order', 't1.date_desc'), 0, $limit, $page);
/* Response */
$data = $this->getData();
+1 -1
View File
@@ -24,7 +24,7 @@ class releasesEntry extends entry
if(empty($productID)) return $this->sendError(400, 'Need product id.');
$control = $this->loadController('release', 'browse');
$control->browse($productID, $this->param('branch', 0), $this->param('status', 'all'), $this->param('order', 't1.date_desc'));
$control->browse($productID, $this->param('branch', 0), $this->param('status', 'all'), $this->param('order', 't1.date_desc'), 0, $this->param('limit', 20), $this->param('page', 1));
/* Response */
$data = $this->getData();
+2 -3
View File
@@ -176,7 +176,7 @@ class reportsEntry extends entry
foreach(array_keys($statusList) as $status)
{
$statusName = zget($this->lang->project->statusList, $status);
if($status == 'all') $statusName = $this->lang->project->featureBar['all'];
if($status == 'all') $statusName = $this->lang->project->featureBar['browse']['all'];
$statusList[$status]['code'] = $status;
$statusList[$status]['name'] = $statusName;
@@ -193,8 +193,7 @@ class reportsEntry extends entry
*/
public function executionProgress()
{
$executions = $this->loadModel('project')->getStats(0, 'all', 0, 0, 30, 'id_desc');
$this->app->loadLang('execution');
$executions = $this->loadModel('execution')->getStatData(0, 'all', 0, 0, false, '', 'id_desc');
$processedExecutions = array();
$statusList['all']['total'] = 0;
+1 -1
View File
@@ -26,7 +26,7 @@ class testcasesEntry extends entry
$this->app->cookie->caseModule = 0;
$this->app->cookie->caseSuite = 0;
$type = 'all';
$type = $this->param('status', 'all');
$param = 0;
$moduleID = $this->param('module', 0);
if($moduleID)
+12
View File
@@ -196,6 +196,8 @@ class userEntry extends Entry
if(!common::hasPriv('my', 'work')) break;
$this->config->openMethods[] = 'my.task';
global $app;
$app->rawMethod = 'work';
$control = $this->loadController('my', 'task');
$control->task($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
$data = $this->getData();
@@ -212,6 +214,8 @@ class userEntry extends Entry
if(!common::hasPriv('my', 'work')) break;
$this->config->openMethods[] = 'my.bug';
global $app;
$app->rawMethod = 'work';
$control = $this->loadController('my', 'bug');
$control->bug($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
$data = $this->getData();
@@ -269,6 +273,8 @@ class userEntry extends Entry
if(!common::hasPriv('my', 'work')) break;
$this->config->openMethods[] = 'my.story';
global $app;
$app->rawMethod = 'work';
$control = $this->loadController('my', 'story');
$control->story($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
$data = $this->getData();
@@ -293,6 +299,8 @@ class userEntry extends Entry
if($this->config->edition == 'max')
{
global $app;
$app->rawMethod = 'work';
$this->config->openMethods[] = 'my.issue';
$control = $this->loadController('my', 'issue');
$control->issue('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1);
@@ -311,6 +319,8 @@ class userEntry extends Entry
if($this->config->edition == 'max')
{
global $app;
$app->rawMethod = 'work';
$this->config->openMethods[] = 'my.risk';
$control = $this->loadController('my', 'risk');
$control->risk('assignedTo', 0, 'id_desc', 0, $this->param('limit', 5), 1);
@@ -329,6 +339,8 @@ class userEntry extends Entry
if($this->config->edition == 'max')
{
global $app;
$app->rawMethod = 'work';
$this->config->openMethods[] = 'my.myMeeting';
$control = $this->loadController('my', 'myMeeting');
$control->myMeeting('futureMeeting', '', 'id_desc', 0, $this->param('limit', 5), 1);
+6 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '17.6'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '17.6.2'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
@@ -97,6 +97,11 @@ $config->domainPostfix .= "|international|house|coffee|florist|rich|ceo|camp|edu
$config->CSPs = array();
$config->CSPs[] = "form-action 'self';connect-src 'self'";
/* Config for kanban col setting */
$config->colWidth = 264;
$config->minColWidth = 180;
$config->maxColWidth = 384;
/* 系统框架配置。Framework settings. */
$config->framework = new stdclass();
$config->framework->autoConnectDB = true; // 是否自动连接数据库。 Whether auto connect database or not.
+24 -14
View File
@@ -97,6 +97,7 @@ $filter->mail->batchdelete = new stdclass();
$filter->misc->checkupdate = new stdclass();
$filter->file->download = new stdclass();
$filter->product->browse = new stdclass();
$filter->product->all = new stdclass();
$filter->product->default = new stdclass();
$filter->product->index = new stdclass();
$filter->product->export = new stdclass();
@@ -108,6 +109,7 @@ $filter->program->default = new stdclass();
$filter->program->pgmproject = new stdclass();
$filter->program->prjbrowse = new stdclass();
$filter->program->project = new stdclass();
$filter->program->product = new stdclass();
$filter->program->browse = new stdclass();
$filter->program->export = new stdclass();
$filter->program->pgmbrowse = new stdclass();
@@ -169,6 +171,8 @@ $filter->execution->export = new stdclass();
$filter->tree->browse = new stdclass();
$filter->productplan->browse = new stdclass();
$filter->kanban->space = new stdclass();
$filter->execution->kanban = new stdclass();
$filter->execution->all = new stdclass();
$filter->index->index->get['open'] = 'reg::base64';
@@ -235,6 +239,7 @@ $filter->product->browse->cookie['productStoryOrder'] = 'reg::orderBy';
$filter->product->browse->cookie['storyModule'] = 'int';
$filter->product->browse->cookie['storyBranch'] = 'int';
$filter->product->browse->cookie['treeBranch'] = 'reg::word';
$filter->product->all->cookie['showProductBatchEdit'] = 'int';
$filter->product->default->cookie['lastProduct'] = 'int';
$filter->product->default->cookie['preProductID'] = 'int';
$filter->product->index->cookie['preBranch'] = 'reg::word';
@@ -246,19 +251,22 @@ $filter->product->dynamic->cookie['preBranch'] = 'reg::word';
$filter->branch->default->cookie['preBranch'] = 'reg::word';
$filter->program->default->cookie['lastPGM'] = 'int';
$filter->program->default->cookie['lastPRJ'] = 'int';
$filter->program->prjbrowse->cookie['programType'] = 'code';
$filter->program->project->cookie['involved'] = 'code';
$filter->program->browse->cookie['showClosed'] = 'code';
$filter->program->export->cookie['checkedItem'] = 'reg::checked';
$filter->program->ajaxgetdropmenu->cookie['showClosed'] = 'code';
$filter->program->default->cookie['lastPGM'] = 'int';
$filter->program->default->cookie['lastPRJ'] = 'int';
$filter->program->prjbrowse->cookie['programType'] = 'code';
$filter->program->project->cookie['involved'] = 'code';
$filter->program->project->cookie['showProjectBatchEdit'] = 'int';
$filter->program->product->cookie['showProductBatchEdit'] = 'int';
$filter->program->browse->cookie['showClosed'] = 'code';
$filter->program->export->cookie['checkedItem'] = 'reg::checked';
$filter->program->ajaxgetdropmenu->cookie['showClosed'] = 'code';
$filter->project->default->cookie['lastProject'] = 'int';
$filter->project->default->cookie['lastPRJ'] = 'int';
$filter->project->default->cookie['projectMode'] = 'code';
$filter->project->default->cookie['kanbanview'] = 'code';
$filter->project->browse->cookie['involved'] = 'code';
$filter->project->browse->cookie['showProjectBatchEdit'] = 'int';
$filter->project->export->cookie['involved'] = 'code';
$filter->project->browse->cookie['projectType'] = 'code';
$filter->project->story->cookie['storyModuleParam'] = 'int';
@@ -293,13 +301,15 @@ $filter->productplan->browse->cookie['viewType'] = 'code';
$filter->task->create->cookie['lastTaskModule'] = 'int';
$filter->task->export->cookie['checkedItem'] = 'reg::checked';
$filter->execution->default->cookie['kanbanview'] = 'code';
$filter->execution->story->cookie['storyPreExecutionID'] = 'int';
$filter->execution->story->cookie['storyModuleParam'] = 'int';
$filter->execution->story->cookie['storyProductParam'] = 'int';
$filter->execution->story->cookie['storyBranchParam'] = 'int';
$filter->execution->story->cookie['executionStoryOrder'] = 'code';
$filter->execution->export->cookie['checkedItem'] = 'reg::checked';
$filter->execution->default->cookie['kanbanview'] = 'code';
$filter->execution->story->cookie['storyPreExecutionID'] = 'int';
$filter->execution->story->cookie['storyModuleParam'] = 'int';
$filter->execution->story->cookie['storyProductParam'] = 'int';
$filter->execution->story->cookie['storyBranchParam'] = 'int';
$filter->execution->story->cookie['executionStoryOrder'] = 'code';
$filter->execution->export->cookie['checkedItem'] = 'reg::checked';
$filter->execution->kanban->cookie['taskToOpen'] = 'int';
$filter->execution->all->cookie['showExecutionBatchEdit'] = 'int';
$filter->testcase->browse->cookie['caseModule'] = 'int';
$filter->testcase->browse->cookie['caseSuite'] = 'int';
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
UPDATE `zt_workflowlabel` SET `label` = '全部' where `label` = '所有' AND `action` = 'browse';
+6
View File
@@ -0,0 +1,6 @@
ALTER TABLE `zt_kanban` ADD `colWidth` smallint(4) NOT NULL DEFAULT '264' AFTER `fluidBoard`;
ALTER TABLE `zt_kanban` ADD `minColWidth` smallint(4) NOT NULL DEFAULT '180' AFTER `colWidth`;
ALTER TABLE `zt_kanban` ADD `maxColWidth` smallint(4) NOT NULL DEFAULT '384' AFTER `minColWidth`;
ALTER TABLE `zt_project` ADD `colWidth` smallint(4) NOT NULL DEFAULT '264' AFTER `fluidBoard`;
ALTER TABLE `zt_project` ADD `minColWidth` smallint(4) NOT NULL DEFAULT '180' AFTER `colWidth`;
ALTER TABLE `zt_project` ADD `maxColWidth` smallint(4) NOT NULL DEFAULT '384' AFTER `minColWidth`;
+1 -1
View File
@@ -11,7 +11,7 @@ CREATE TABLE `zt_taskteam` (
PRIMARY KEY (`id`),
KEY `task` (`task`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `zt_taskestimate` ADD `order` tinyint unsigned NULL DEFAULT '0';
ALTER TABLE `zt_taskestimate` ADD `order` tinyint unsigned NOT NULL DEFAULT '0';
ALTER TABLE `zt_effort` ADD `order` tinyint unsigned NOT NULL DEFAULT '0' AFTER `end`;
REPLACE INTO `zt_config` (`owner`, `module`, `section`, `key`, `value`) VALUES ('system', 'common', 'global', 'syncProductFeedback', '0');
+6
View File
@@ -835,6 +835,9 @@ CREATE TABLE IF NOT EXISTS `zt_kanban` (
`displayCards` smallint(6) NOT NULL default '0',
`showWIP` enum('0','1') NOT NULL DEFAULT '1',
`fluidBoard` enum('0','1') NOT NULL DEFAULT '0',
`colWidth` tinyint(3) NOT NULL DEFAULT '0',
`minColWidth` tinyint(3) NOT NULL DEFAULT '0',
`maxColWidth` tinyint(3) NOT NULL DEFAULT '0',
`object` varchar(255) NOT NULL,
`alignment` varchar(10) NOT NULL default 'center',
`createdBy` char(30) NOT NULL,
@@ -1193,6 +1196,9 @@ CREATE TABLE IF NOT EXISTS `zt_project` (
`vision` varchar(10) NOT NULL DEFAULT 'rnd',
`displayCards` smallint(6) NOT NULL default '0',
`fluidBoard` enum('0','1') NOT NULL DEFAULT '0',
`colWidth` tinyint(3) NOT NULL DEFAULT '0',
`minColWidth` tinyint(3) NOT NULL DEFAULT '0',
`maxColWidth` tinyint(3) NOT NULL DEFAULT '0',
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `parent` (`parent`),
+171
View File
@@ -1,3 +1,174 @@
2022-09-23 17.6.2
完成的需求
开源版:
37324 敏捷项目下的迭代列表没有任务时中,隐藏名称前的展开、收起按钮
36946 私有产品的访问权限增加项目集负责人(反馈)
32322 Bug批量导入页面中先校验必填字段再校验重复数据
36977 增加全局头像下拉菜单的点击热区面积
67327 实现禅道中文件上传组件支持选择一次性多个文件(反馈)
37262 列表中“所有”标签修改为“全部”
37866 项目集列表中名称字段样式优化
37869 删除项目集列表中项目的图标
37862 项目集列表删除“显示已关闭”的勾选按钮
37868 项目集列表操作列的更多按钮调整
37861 用例列表操作列交换开始和结果按钮的位置
37854 bug列表确认字段的内容颜色调整
37864 项目集列表中延期标签位置调整
37833 叶兰绿主题风格更新
37842 禅道蓝主题风格更新
37813 列表中优先级颜色调整
37816 列表检索标签选中样式优化
38002 多人串行任务中,团队日志页去掉操作区域
38006 多人串行任务开始任务的弹窗,总计消耗改名为我的总消耗
37997 多人串行任务,用户打开工时填写页,默认打开我的日志页
37993 工时记录页,日期、工作内容、消耗、剩余增加必填项校验(开源版不校验工作内容)
37218 调整看板区域标题栏名称的对齐方式
37207 去掉看板中选中单个产品规划的背景
37206 调整看板区域检索标签组件样式
37132 将指派他人的待办列表中“由谁指派”字段修改为“指派给”
37831 项目统计报表增加权限判断,过滤掉没有访问权限的项目
32626 产品统计报表增加权限判断,过滤掉没有访问权限的产品
37064 长期项目的概况上计划完成显示“长期”
企业版:
37221 组织日志列表增加项目字段
35025 需求导入模板增加由谁评审字段
旗舰版:
35042 旗舰版周报3个工作项列表能显示总数
修复的Bug
27875 工时记录页面日期控件展开后显示遮挡
27778 创建项目和编辑项目的所属项目集字段显示不一致
27690 创建项目页面提示信息窗口建议向右展开
27632 复制bug时希望可以同步反馈者和通知邮箱两个字段的信息
27561 提需求页面所属产品右侧边框线缺失
27547 编辑项目集预算,点击保存,提示有未提交表单
2022-09-08 17.6.1
完成的需求
开源版:
31896 Scrum看板列中动态加载卡片数据
34361 需求编辑页面增加附件信息的显示
35317 禅道可以支持腾讯云和阿里云数据库
35436 批量创建和编辑页面保存时,增加名称必填项校验
35475 并行多人任务完成后重新激活无法再完成
35909 通用看板增加区域的检索标签
36259 需求详情中的附件去掉删除操作
36444 多人串行任务,状态为“未开始”时,可以维护自己的工时日志
36445 多人串行任务,只有指派人可以开始任务或完成任务
36448 多人串行任务,状态为“进行中”时,可以新增工序和成员
36451 多人串行任务,状态为“进行中”时,可以修改工序和成员
36452 多人串行任务,状态为“进行中”时,可以删除工序和成员
36453 多人串行任务,状态为“已完成”时,不可以编辑工序和团队成员
36454 多人任务,只有编辑人可以修改自己的日志
36455 多人串行任务的状态为“进行中”,且指派人为自己时,可以编辑当前工序的工时日志
36457 多人串行任务的状态为“已完成”,可以修改自己已经填写的工时
36458 多人串行任务状态为已关闭或已完成时,可以激活
36459 多人串行任务,状态为“未开始”时,可以维护工序和团队成员
36460 多人并行任务,状态为“未开始”时,可以维护团队成员
36461 创建和编辑多人任务团队时,预计剩余不为0
36462 多人并行任务,状态为“进行中”时,可以修改团队成员
36463 多人并行任务,状态为“进行中”时,可以添加团队成员
36464 多人并行任务,状态为“进行中”时,可以删除团队成员
36465 多人并行任务,状态为“已完成”时,不能维护团队成员
36466 多人并行任务中,自己可以维护自己创建的日志
36467 多人串行任务状态为“已取消”时,激活后选择继续或重新开始
36468 多人串行任务状态为已关闭、已暂停、已取消时不能维护团队和日志
36469 多人并行任务状态为已关闭、已暂停、已取消时不能维护团队
36470 多人并行任务状态为已关闭、已暂停、已取消时可以维护日志
36471 多人并行任务状态为已关闭或已完成时,可以激活
36663 任务日志列表展示”最初预计“和”累积耗时“
36664 多人串行任务的日志,根据团队成员的状态展示我的日志和所有日志
36666 维护多人串行任务日志时,根据团队成员的状态判断是新增日志还是追加日志
36678 单人任务和多人并行任务,日志页展示历史的日志和新增日志入口
36720 通过面板二维码下载移动端时,可以自动判断当前版本匹配的移动端版本
36723 测试单列表增加搜索功能
36730 需求变更评审时,系统根据需求不同评审结果进行后续处理
36783 变更需求时,附件删除操作记录版本号
36784 需求的附件跟随版本变化
36785 变更需求时,附件删除操作保存后再生效
36795 权限分组的视野维护中,项目集下拉菜单支持按树状结构进行显示和选择
36998 执行概况的燃尽图中增加延期状态的标签
企业版:
30912 地盘日志列表新建日志时对象与执行的展示顺序修改
旗舰版:
36984 实现瀑布项目总体进展统计区块
36989 项目周报中将进度调整为本周进度
34731 瀑布项目里评审下的基线评审列表增加删除功能
36744 复制项目的执行的时间填写后,自动计算可用工作日
36813 瀑布项目评审下的问题列表增加删除权限
36839 QA质量保证计划可以在地盘待处理显示
禅道客户端:
35987 群成员管理列表点击成员头像或名称显示成员名片的功能
35878 实现群成员管理列表的搜索功能
35875 实现群管理列表的搜索功能
35873 实现群成员管理列表中设置群主功能
35853 实现群成员管理列表中单个移除成员的功能
35852 实现群成员管理列表中添加成员功能
35976 实现讨论组成员管理列表的右键菜单及功能
35850 实现群成员管理列表
35974 实现群管理列表的右键菜单及功能
35848 实现群管理列表
35986 客户端应用中增加讨论组管理的应用入口
36496 系统默认讨论组分组不支持重命名
36447 扩展API应用分组、排序功能优化
36446 扩展API应用搜索功能优化
36443 扩展API应用界面优化
36425 扩展API应用增加介绍模块
36090 重新规划扩展API应用分组维度
36426 新建讨论组时可以将其增加到分组
21476 讨论组的分组功能可以有明确的添加入口
36030 实现在线编辑喧喧文件的功能(word文件/excel文件)
36037 实现群管理列表按表头排序的功能
36039 实现群成员管理列表按表头排序的功能
修复的Bug
23401 经典模式项目树状图下点击模块后导航错乱,点击报错
23957 批量创建用例超过10条相关需求不显示
24830 创建Bug页面进入维护模块页面再关闭维护模块页面后所属产品变了
24894 待办名称过长时会将整个页面撑开
25409 在“待处理”中添加待办后“我的待办”的保存按钮置灰
25515 组织日志页面数据较多下滑到最下时出现2个滚动条
25695 英文下,复选框文案没有根据个性化设置动态变化
25904 代号关闭后,已保存的搜索条件代号被填充到了第一个搜索框中
25942 创建项目集页面预算右侧边框样式问题
26122 日志信息在任务列表和日志详情中不一致
26181 产品发布下关联需求页面点击返回后二级导航缺失
26193 输入两次不同密码后强度校验了md5值
26235 展开收起模块树会导致Bug标题显示不出来
26298 项目集日期超出父项目集起止日期时提示信息优化
26412 选择某个研发需求点击移除已选项数量仍然是一项
26466 经典模式升级全新模式弱密码设置仍跳转重置密码界面
26469 项目下的执行列表没有显示已延期
26551 产品下未完成的项目列表表统计错误
26619 创建测试任务时第2条软件需求的日程规划未显示“同上”
26622 创建任务选择日期后,同上没有隐藏掉
26632 专业研发看板/scrum看板下创建测试任务页面样式问题
26646 删除附件时页面全局刷新了
26648 发布时选了项目团队成员,不在这个项目的人也能收到通知
26659 点击动态中的设计名称,在设计详情页返回后提示无项目权限
26660 项目列表中人数统计与团队人数不一致
26670 编辑项目页面选择计划起止日期时页面抖动
26681 批量编辑用户页面密码输入位置问题
26687 创建测试任务时,删除需求列表的第一行仍显示同上复选框
26715 新建项目时切换顶级项目集预算未刷新
26724 未关闭标签下无数据
26725 编辑任务时仍能选到已关闭的迭代
26758 编辑任务中相关研发需求下拉框显示不友好
26842 测试单再关联新的用例后,已生成的测试报告中的统计信息被影响
26936 项目列表无法根据状态搜索
26963 执行看板中的需求无法拖动
26971 权限分组视野中维护可访问项目集后不生效
26994 多分支产品,在列表批量修改计划,数据库存储有逗号,导致按计划排序有问题
27007 年度统计没有所有用户选项
27020 在选择项目集创建项目时“关联产品”项没有添加必填项标识
27034 点击执行树状图下的相关用例后,二级导航不显示了
27068 编辑用例时,所属模块和相关研发需求的判断问题
27135 点击卡片更多操作已归档卡片展示未收起
27186 研发需求或者用户需求中点击取消相关用户需求或相关研发需求后页面显示“删除中”
27192 创建测试类型任务页面截止时间小于预计开始时没有校验
27258 编辑模块点击保存时希望不要弹出新窗口提醒
26082 勾选设置的初始化会议状态账号一直处于会议状态
26085 LDAP配置不对时,提示需要优化
26207 修复了会话新建分组时无法输入中文的问题
2022-08-25 17.6
完成的需求
开源版:
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

+24 -4
View File
@@ -35,8 +35,15 @@
</div>
<?php else:?>
<form id='myTaskForm' class="main-table table-task skip-iframe-modal" method="post">
<?php $canBatchEdit = (common::hasPriv('task', 'batchEdit') and $type == 'assignedTo');?>
<?php $canBatchClose = (common::hasPriv('task', 'batchClose') and $type != 'closedBy');?>
<?php
$canBatchEdit = (common::hasPriv('task', 'batchEdit') and $type == 'assignedTo');
$canBatchClose = (common::hasPriv('task', 'batchClose') and $type != 'closedBy');
$canFinish = common::hasPriv('task', 'finish');
$canClose = common::hasPriv('task', 'close');
$canRecordEstimate = common::hasPriv('task', 'recordEstimate');
$canEdit = common::hasPriv('task', 'edit');
$canBatchCreate = common::hasPriv('task', 'batchCreate');
?>
<table class="table has-sort-head table-fixed" id='taskTable'>
<?php $vars = "mode=$mode&type=$type&orderBy=%s&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID"; ?>
<thead>
@@ -134,10 +141,16 @@
}
else
{
$canStart = ($task->status != 'pause' and common::hasPriv('task', 'start'));
$canRestart = ($task->status == 'pause' and common::hasPriv('task', 'restart'));
if($task->status != 'pause') common::printIcon('task', 'start', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
if($task->status == 'pause') common::printIcon('task', 'restart', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'close', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, '', '', $task->project);
if(($canStart or $canRestart or $canFinish or $canClose) and ($canRecordEstimate or $canEdit or $canBatchCreate))
{
echo "<div class='dividing-line'></div>";
}
common::printIcon('task', 'recordEstimate', "taskID=$task->id", $task, 'list', 'time', '', 'iframe', true, '', '', $task->project);
common::printIcon('task', 'edit', "taskID=$task->id", $task, 'list', '', '', 'iframe', true, "data-width='95%'", '', $task->project);
@@ -198,10 +211,17 @@
}
else
{
$canStart = ($child->status != 'pause' and common::hasPriv('task', 'start'));
$canRestart = ($child->status == 'pause' and common::hasPriv('task', 'restart'));
if($child->status != 'pause') common::printIcon('task', 'start', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
if($child->status == 'pause') common::printIcon('task', 'restart', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'close', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'finish', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'close', "taskID=$child->id", $child, 'list', '', '', 'iframe', true, '', '', $child->project);
if(($canStart or $canRestart or $canFinish or $canClose) and ($canRecordEstimate or $canEdit or $canBatchCreate))
{
echo "<div class='dividing-line'></div>";
}
common::printIcon('task', 'recordEstimate', "taskID=$child->id", $child, 'list', 'time', '', 'iframe', true, '', '', $child->project);
common::printIcon('task', 'edit', "taskID=$child->id", $child, 'list', '', '', '', '', '', '', $child->project);
@@ -18,6 +18,7 @@ body {margin-bottom: 25px;}
#mainMenu .btn-toolbar .btn-group .dropdown-menu .btn-active-text:hover .text:after {border-bottom: unset;}
.body-modal #mainMenu>.btn-toolbar {width: auto;}
.assignedTo{border-radius: 4px !important;}
#productStoryForm table tbody tr td.c-actions .dividing-line {width: 1px; height: 16px; display: inline-block; vertical-align: middle; background: #F4F5F7; margin: 0 4px 0 0;}
</style>
<?php js::set('browseType', $browseType);?>
<?php js::set('productID', $productID);?>
+1 -1
View File
@@ -86,7 +86,7 @@
<div class='detail-title'><?php echo $lang->attatch;?></div>
<div class='form-group'>
<?php $canChangeFile = strpos('draft,changing', $story->status) !== false ? true : false;?>
<?php echo $this->fetch('file', 'printFiles', array('files' => $files, 'fieldset' => 'false', 'object' => $story, 'method' => 'edit', 'showDelete' => $canChangeFile));?>
<?php echo $this->fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'false', 'object' => $story, 'method' => 'edit', 'showDelete' => $canChangeFile));?>
<?php echo $canChangeFile ? $this->fetch('file', 'buildform') : '';?>
</div>
</div>
+3 -3
View File
@@ -69,7 +69,7 @@
<div class="detail-title"><?php echo $lang->story->legendSpec;?></div>
<div class="detail-content article-content"><?php echo $story->spec;?></div>
</div>
<?php echo $this->fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true', 'object' => $story));?>
<?php echo $this->fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true', 'object' => $story, 'method' => 'view', 'showDelete' => false));?>
<?php
$canBeChanged = common::canBeChanged('story', $story);
if($canBeChanged) $actionFormLink = $this->createLink('action', 'comment', "objectType=story&objectID=$story->id");
@@ -110,7 +110,7 @@
common::printIcon('story', 'change', "storyID=$child->id", $child, 'list', 'alter');
if(strpos('draft,changing', $child->status) !== false)
{
common::printIcon('story', 'submitReview', "storyID=$child->id", $child, 'list', 'sub-review', '', 'iframe showinonlybody', true);
common::printIcon('story', 'submitReview', "storyID=$child->id", $child, 'list', 'confirm', '', 'iframe showinonlybody', true);
}
else
{
@@ -143,7 +143,7 @@
common::printIcon('story', 'change', "storyID=$story->id", $story, 'button', 'alter', '', 'showinonlybody');
if(strpos('draft,changing', $story->status) !== false)
{
common::printIcon('story', 'submitReview', "storyID=$story->id", $story, 'button', 'sub-review', '', 'iframe showinonlybody', true);
common::printIcon('story', 'submitReview', "storyID=$story->id", $story, 'button', 'confirm', '', 'iframe showinonlybody', true);
}
else
{
+8 -16
View File
@@ -19,8 +19,8 @@
<?php js::set('projectID', $projectID);?>
<?php js::set('productID', $productID);?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
<?php js::set('estimateNotEmpty', sprintf($lang->error->gt, $lang->task->estimate, '0'))?>
<?php if(!empty($storyID)):?>
<style> .title-group.required > .required:after {right: 110px;}</style>
<?php endif;?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
@@ -90,6 +90,10 @@
<button id='selectAllUser' type="button" class="btn btn-link<?php if($task->type !== 'affair') echo ' hidden';?>"><?php echo $lang->task->selectAllUser;?></button>
</td>
</tr>
<tr class='hidden modeBox'>
<th><?php echo $lang->task->mode;?></th>
<td><?php echo html::select('mode', $lang->task->modeList, '', "class='form-control chosen'");?></td>
</tr>
<tr class='hide'>
<th><?php echo $lang->task->status;?></th>
<td><?php echo html::hidden('status', 'wait');?></td>
@@ -283,24 +287,11 @@
<div class='modal-body'>
<table class="table table-form" id='taskTeamEditor'>
<tbody class='sortable'>
<tr class='template'>
<td><?php echo html::select("team[]", $members, '', "class='form-control chosen'");?></td>
<td>
<div class='input-group'>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->estimateAB}'") ?>
<span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php include $app->getModuleRoot() . 'task/view/taskteam.html.php';?>
</tbody>
<tfoot>
<tr>
<td colspan='3' class='text-center'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "class='btn btn-primary' data-dismiss='modal'");?></td>
<td colspan='3' class='text-center'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "class='btn btn-primary'");?></td>
</tr>
</tfoot>
</table>
@@ -351,6 +342,7 @@ $(function()
})
</script>
<?php endif;?>
<?php js::set('newRowCount', 5);?>
<script>
$(function()
{
+10 -2
View File
@@ -996,7 +996,15 @@ class baseRouter
if($writable)
{
$ztSessionHandler = new ztSessionHandler($_GET['tid']);
session_set_save_handler($ztSessionHandler, true);
session_set_save_handler(
array($ztSessionHandler, "open"),
array($ztSessionHandler, "close"),
array($ztSessionHandler, "read"),
array($ztSessionHandler, "write"),
array($ztSessionHandler, "destroy"),
array($ztSessionHandler, "gc")
);
register_shutdown_function('session_write_close');
}
}
@@ -3140,7 +3148,7 @@ class EndResponseException extends \Exception
*
* @package framework
*/
class ztSessionHandler implements SessionHandlerInterface
class ztSessionHandler
{
public $sessSavePath;
public $tagID;
+166
View File
@@ -0,0 +1,166 @@
<?php
/**
* Dtable class.
*
* @copyright Copyright 2009-2022 QingDao Nature Easy Soft Network Technology Co,LTD (www.cnezsoft.com)
* @author guanxiying <guanxiying@easycorp.ltd>
* @package
* @license LGPL
* @version $Id$
* @Link https://www.zentao.net
*/
class dtable
{
/**
* Options of dtable.
*/
public $options;
/**
* cols of dtable options.
*/
public $cols;
/**
* data of dtable options.
*/
public $data;
/**
* Init cols.
*
* @param array $cols
* @access public
* @return object $this
*/
public function colInit($cols)
{
$this->cols = $cols;
return $this;
}
/**
* colSet
*
* @param string $colName
* @param object $col
* @access public
* @return object $this
*/
public function colSet($colName, $col)
{
$this->cols->$colName = $col;
return $this;
}
/**
* Delete one col.
*
* @param string $colName
* @access public
* @return object
*/
public function colDelete($colName)
{
unset($this->cols->$colName);
return $this;
}
/**
* set col attr.
*
* @param string $colName
* @param string $property
* @param mixed $value
* @access public
* @return object
*/
public function colAttr($colName, $property, $value)
{
if(!isset($this->cols->$colName)) $this->cols->$colName = new stdClass;
$this->cols->{$colName}->{$property} = $value;
return $this;
}
/**
* dataInit
*
* @param array $data
* @access public
* @return object
*/
public function dataInit($data)
{
$this->data = $data;
return $this;
}
/**
* dataAappend
*
* @param object $row
* @access public
* @return object
*/
public function dataAappend($row)
{
$this->data[] = $row;
return $this;
}
/**
* dataSet
*
* @param string $index
* @param object $data
* @access public
* @return object
*/
public function dataSet($index, $data)
{
$this->data[$index] = $data;
return $this;
}
/**
* dataBatchSet
*
* @param mixed $scope [1,2,3,4] | all
* @param object $data
* @access public
* @return object
*/
public function dataBatchSet($scope, $data)
{
if($scope == 'all') $scope = array_keys($this->data);
foreach($scope as $index) $this->data[$index] = $data;
return $this;
}
/**
* Get dtable options.
*
* @access public
* @return object
*/
public function getOptions($extra)
{
$this->options = new stdClass;
$this->options->cols = $this->cols;
$this->options->data = $this->data;
return $this->options;
}
/**
* Show dtable codes.
*
* @access public
* @return string
*/
public function show()
{
}
}
+1 -1
View File
@@ -82,7 +82,7 @@ $lang->action->dynamic->all = '所有';
$lang->action->dynamic->hidden = '已隐藏';
$lang->action->dynamic->search = '搜索';
$lang->action->periods['all'] = $lang->action->dynamic->all;
$lang->action->periods['all'] = '全部';
$lang->action->periods['today'] = $lang->action->dynamic->today;
$lang->action->periods['yesterday'] = $lang->action->dynamic->yesterday;
$lang->action->periods['thisweek'] = $lang->action->dynamic->thisWeek;
+18 -5
View File
@@ -330,12 +330,20 @@ class actionModel extends model
->where("objectType IN('project', 'testtask', 'build')")
->andWhere('project')->eq((int)$objectID)
->fi()
->beginIF($objectType == 'story')
->where('objectType')->in('story,requirement')
->andWhere('objectID')->eq((int)$objectID)
->fi()
->beginIF($objectType == 'case')
->where('objectType')->in('case,testcase')
->andWhere('objectID')->eq((int)$objectID)
->fi()
->beginIF($objectType == 'module')
->where('objectType')->eq($objectType)
->andWhere('((action')->ne('deleted')->andWhere('objectID')->eq((int)$objectID)->markRight(1)
->orWhere('(action')->eq('deleted')->andWhere('objectID')->in($modules)->markRight(1)->markRight(1)
->fi()
->beginIF($objectType != 'project' and $objectType != 'module')
->beginIF(strpos('project,case,story,module', $objectType) === false)
->where('objectType')->eq($objectType)
->andWhere('objectID')->eq((int)$objectID)
->fi()
@@ -366,10 +374,10 @@ class actionModel extends model
elseif($actionName == 'linked2execution' or $actionName == 'linked2kanban')
{
$execution = $this->dao->select('name,type')->from(TABLE_PROJECT)->where('id')->eq($action->extra)->fetch();
$name = $execution->name;
$method = $execution->type == 'kanban' ? 'kanban' : 'view';
if($name)
if(!empty($execution))
{
$name = $execution->name;
$method = $execution->type == 'kanban' ? 'kanban' : 'view';
$action->extra = (!common::hasPriv('execution', $method) or ($method == 'kanban' and isonlybody())) ? $name : html::a(helper::createLink('execution', $method, "executionID=$action->execution"), $name);
}
}
@@ -567,7 +575,7 @@ class actionModel extends model
if($history->field == 'git') $history->diff = str_replace('+', '%2B', $history->diff);
}
}
elseif($actionName == 'linkstory' or $actionName == 'unlinkstory')
elseif(strpos('linkstory,unlinkstory,createchildrenstory', $actionName) !== false)
{
$extra = '';
foreach(explode(',', $action->extra) as $id) $extra .= common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$id"), "#$id ") . ', ' : "#$id, ";
@@ -1052,6 +1060,9 @@ class actionModel extends model
$programCondition = empty($this->app->user->view->programs) ? '0' : $this->app->user->view->programs;
$efforts = $this->dao->select('id')->from(TABLE_EFFORT)->where($condition)->fetchPairs();
$efforts = !empty($efforts) ? implode(',', $efforts) : 0;
/* Get actions. */
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('objectType')->notIN($this->config->action->ignoreObjectType4Dynamic)
@@ -1079,6 +1090,7 @@ class actionModel extends model
/* Filter out client login/logout actions. */
->andWhere('action')->notin('disconnectxuanxuan,reconnectxuanxuan,loginxuanxuan,logoutxuanxuan')
->andWhere("IF((objectType = 'program'), (objectID in ($programCondition)), '1=1')")
->andWhere("IF((objectType = 'effort'), (objectID in ($efforts)), '1=1')")
->orderBy($orderBy)
->page($pager)
->fetchAll();
@@ -1687,6 +1699,7 @@ class actionModel extends model
$fieldName = $history->field;
$history->fieldLabel = (isset($this->lang->$objectType) && isset($this->lang->$objectType->$fieldName)) ? $this->lang->$objectType->$fieldName : $fieldName;
if($objectType == 'module') $history->fieldLabel = $this->lang->tree->$fieldName;
if($fieldName == 'fileName') $history->fieldLabel = $this->lang->file->$fieldName;
if(($length = strlen($history->fieldLabel)) > $maxLength) $maxLength = $length;
$history->diff ? $historiesWithDiff[] = $history : $historiesWithoutDiff[] = $history;
}
+1 -1
View File
@@ -14,7 +14,7 @@
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<?php $activeClass = $currentObjectType == 'all' ? 'btn-active-text' : '';?>
<?php echo html::a($this->createLink('action', 'trash', "objectType=all&type=$type"), "<span class='text'>" . $lang->all . "</span>", '', "class='btn btn-link $activeClass'");?>
<?php echo html::a($this->createLink('action', 'trash', "objectType=all&type=$type"), "<span class='text'>" . $lang->action->periods['all'] . "</span>", '', "class='btn btn-link $activeClass'");?>
<?php
/* Output the objectType order by preferredTypeConfig. */
foreach($preferredTypeConfig as $objectType)
+8 -6
View File
@@ -1208,8 +1208,9 @@ class block extends control
$this->view->sv = $this->weekly->getSV($this->view->ev, $this->view->pv);
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$progress = !empty($this->view->pv) ? floor($this->view->ac / $this->view->pv * 1000) / 1000 * 100 : 0;
$this->view->progress = $progress > 100 ? 100 : $progress;
$this->view->current = $current;
$this->view->progress = !empty($this->view->pv) ? floor($this->view->ac / $this->view->pv * 1000) / 1000 * 100 : 0;
}
/**
@@ -1224,14 +1225,15 @@ class block extends control
$this->loadModel('project');
$this->loadModel('weekly');
$PVEV = $this->project->getWaterfallPVEV($this->session->project);
$this->view->pv = (float)$PVEV['PV'];
$this->view->ev = (float)$PVEV['EV'];
$this->view->ac = (float)$this->project->getWaterfallAC($this->session->project);
$data = $this->project->getWaterfallPVEVAC($this->session->project);
$this->view->pv = (float)$data['PV'];
$this->view->ev = (float)$data['EV'];
$this->view->ac = (float)$data['AC'];
$this->view->sv = $this->weekly->getSV($this->view->ev, $this->view->pv);
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$this->view->progress = !empty($this->view->pv) ? floor($this->view->ac / $this->view->pv * 1000) / 1000 * 100 : 0;
$progress = !empty($this->view->pv) ? floor($this->view->ac / $this->view->pv * 1000) / 1000 * 100 : 0;
$this->view->progress = $progress > 100 ? 100 : $progress;
}
/**
+1 -1
View File
@@ -57,6 +57,6 @@ $lang->branch->statusList = array();
$lang->branch->statusList['active'] = '激活';
$lang->branch->statusList['closed'] = '已关闭';
$lang->branch->featureBar['manage']['all'] = '所有';
$lang->branch->featureBar['manage']['all'] = '全部';
$lang->branch->featureBar['manage']['active'] = '激活';
$lang->branch->featureBar['manage']['closed'] = '已关闭';
+72 -72
View File
@@ -24,7 +24,7 @@ $config->bug->list->allFields = 'id, module, execution, story, task,
lastEditedBy,
lastEditedDate';
$config->bug->list->defaultFields = 'id,severity,pri,title,openedBy,assignedTo,resolvedBy,resolution';
$config->bug->list->defaultFields = 'id,title,severity,pri,openedBy,assignedTo,resolvedBy,resolution';
$config->bug->exportFields = 'id, product, branch, module, project, execution, story, task,
title, keywords, severity, pri, type, os, browser,
@@ -159,7 +159,7 @@ $config->bug->search['params']['deadline'] = array('operator' => '=',
$config->bug->search['params']['activatedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->datatable = new stdclass();
$config->bug->datatable->defaultField = array('id', 'severity', 'pri', 'confirmed', 'title', 'status', 'openedBy', 'openedDate', 'assignedTo', 'resolution', 'actions');
$config->bug->datatable->defaultField = array('id', 'title', 'severity', 'pri', 'status', 'openedBy', 'openedDate', 'confirmed', 'assignedTo', 'resolution', 'actions');
$config->bug->datatable->fieldList['id']['title'] = 'idAB';
$config->bug->datatable->fieldList['id']['fixed'] = 'left';
@@ -174,6 +174,12 @@ $config->bug->datatable->fieldList['module']['control'] = 'select';
$config->bug->datatable->fieldList['module']['title'] = 'module';
$config->bug->datatable->fieldList['module']['dataSource'] = array('module' => 'tree', 'method' => 'getOptionMenu', 'params' => '$productID&bug');
$config->bug->datatable->fieldList['title']['title'] = 'title';
$config->bug->datatable->fieldList['title']['fixed'] = 'left';
$config->bug->datatable->fieldList['title']['width'] = 'auto';
$config->bug->datatable->fieldList['title']['required'] = 'yes';
$config->bug->datatable->fieldList['title']['minWidth'] = '200';
$config->bug->datatable->fieldList['severity']['title'] = 'severityAB';
$config->bug->datatable->fieldList['severity']['fixed'] = 'left';
$config->bug->datatable->fieldList['severity']['width'] = '50';
@@ -186,16 +192,10 @@ $config->bug->datatable->fieldList['pri']['width'] = '50';
$config->bug->datatable->fieldList['pri']['required'] = 'no';
$config->bug->datatable->fieldList['pri']['name'] = $lang->bug->pri;
$config->bug->datatable->fieldList['confirmed']['title'] = 'confirmedAB';
$config->bug->datatable->fieldList['confirmed']['fixed'] = 'left';
$config->bug->datatable->fieldList['confirmed']['width'] = '50';
$config->bug->datatable->fieldList['confirmed']['required'] = 'no';
$config->bug->datatable->fieldList['title']['title'] = 'title';
$config->bug->datatable->fieldList['title']['fixed'] = 'left';
$config->bug->datatable->fieldList['title']['width'] = 'auto';
$config->bug->datatable->fieldList['title']['required'] = 'yes';
$config->bug->datatable->fieldList['title']['minWidth'] = '200';
$config->bug->datatable->fieldList['status']['title'] = 'statusAB';
$config->bug->datatable->fieldList['status']['fixed'] = 'left';
$config->bug->datatable->fieldList['status']['width'] = '80';
$config->bug->datatable->fieldList['status']['required'] = 'no';
$config->bug->datatable->fieldList['branch']['title'] = 'branch';
$config->bug->datatable->fieldList['branch']['fixed'] = 'left';
@@ -230,10 +230,66 @@ $config->bug->datatable->fieldList['plan']['fixed'] = 'no';
$config->bug->datatable->fieldList['plan']['width'] = '120';
$config->bug->datatable->fieldList['plan']['required'] = 'no';
$config->bug->datatable->fieldList['status']['title'] = 'statusAB';
$config->bug->datatable->fieldList['status']['fixed'] = 'no';
$config->bug->datatable->fieldList['status']['width'] = '80';
$config->bug->datatable->fieldList['status']['required'] = 'no';
$config->bug->datatable->fieldList['openedBy']['title'] = 'openedByAB';
$config->bug->datatable->fieldList['openedBy']['fixed'] = 'no';
$config->bug->datatable->fieldList['openedBy']['width'] = '80';
$config->bug->datatable->fieldList['openedBy']['required'] = 'no';
$config->bug->datatable->fieldList['openedDate']['title'] = 'openedDateAB';
$config->bug->datatable->fieldList['openedDate']['fixed'] = 'no';
$config->bug->datatable->fieldList['openedDate']['width'] = '90';
$config->bug->datatable->fieldList['openedDate']['required'] = 'no';
$config->bug->datatable->fieldList['openedBuild']['title'] = 'openedBuild';
$config->bug->datatable->fieldList['openedBuild']['fixed'] = 'no';
$config->bug->datatable->fieldList['openedBuild']['width'] = '120';
$config->bug->datatable->fieldList['openedBuild']['required'] = 'no';
$config->bug->datatable->fieldList['openedBuild']['control'] = 'multiple';
$config->bug->datatable->fieldList['openedBuild']['dataSource'] = array('module' => 'build', 'method' =>'getBuildPairs', 'params' => '$productID&$branch&noempty,noterminate,nodone,withbranch');
$config->bug->datatable->fieldList['confirmed']['title'] = 'confirmedAB';
$config->bug->datatable->fieldList['confirmed']['fixed'] = 'no';
$config->bug->datatable->fieldList['confirmed']['width'] = '100';
$config->bug->datatable->fieldList['confirmed']['required'] = 'no';
$config->bug->datatable->fieldList['assignedTo']['title'] = 'assignedToAB';
$config->bug->datatable->fieldList['assignedTo']['fixed'] = 'no';
$config->bug->datatable->fieldList['assignedTo']['width'] = '120';
$config->bug->datatable->fieldList['assignedTo']['required'] = 'no';
$config->bug->datatable->fieldList['assignedTo']['dataSource'] = array('module' => 'user', 'method' =>'getPairs', 'params' => 'noclosed|noletter');
$config->bug->datatable->fieldList['assignedDate']['title'] = 'assignedDate';
$config->bug->datatable->fieldList['assignedDate']['fixed'] = 'no';
$config->bug->datatable->fieldList['assignedDate']['width'] = '90';
$config->bug->datatable->fieldList['assignedDate']['required'] = 'no';
$config->bug->datatable->fieldList['deadline']['title'] = 'deadline';
$config->bug->datatable->fieldList['deadline']['fixed'] = 'no';
$config->bug->datatable->fieldList['deadline']['width'] = '90';
$config->bug->datatable->fieldList['deadline']['required'] = 'no';
$config->bug->datatable->fieldList['deadline']['control'] = 'date';
$config->bug->datatable->fieldList['resolvedBy']['title'] = 'resolvedBy';
$config->bug->datatable->fieldList['resolvedBy']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedBy']['width'] = '100';
$config->bug->datatable->fieldList['resolvedBy']['required'] = 'no';
$config->bug->datatable->fieldList['resolution']['title'] = 'resolutionAB';
$config->bug->datatable->fieldList['resolution']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolution']['width'] = '110';
$config->bug->datatable->fieldList['resolution']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedDate']['title'] = 'resolvedDateAB';
$config->bug->datatable->fieldList['resolvedDate']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedDate']['width'] = '120';
$config->bug->datatable->fieldList['resolvedDate']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['title'] = 'resolvedBuild';
$config->bug->datatable->fieldList['resolvedBuild']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['width'] = '120';
$config->bug->datatable->fieldList['resolvedBuild']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['control'] = 'select';
$config->bug->datatable->fieldList['resolvedBuild']['dataSource'] = array('module' => 'bug', 'method' =>'getRelatedObjects', 'params' => 'resolvedBuild&id,name');
$config->bug->datatable->fieldList['activatedCount']['title'] = 'activatedCountAB';
$config->bug->datatable->fieldList['activatedCount']['fixed'] = 'no';
@@ -283,62 +339,6 @@ $config->bug->datatable->fieldList['mailto']['fixed'] = 'no';
$config->bug->datatable->fieldList['mailto']['width'] = '100';
$config->bug->datatable->fieldList['mailto']['required'] = 'no';
$config->bug->datatable->fieldList['openedBy']['title'] = 'openedByAB';
$config->bug->datatable->fieldList['openedBy']['fixed'] = 'no';
$config->bug->datatable->fieldList['openedBy']['width'] = '80';
$config->bug->datatable->fieldList['openedBy']['required'] = 'no';
$config->bug->datatable->fieldList['openedDate']['title'] = 'openedDateAB';
$config->bug->datatable->fieldList['openedDate']['fixed'] = 'no';
$config->bug->datatable->fieldList['openedDate']['width'] = '90';
$config->bug->datatable->fieldList['openedDate']['required'] = 'no';
$config->bug->datatable->fieldList['openedBuild']['title'] = 'openedBuild';
$config->bug->datatable->fieldList['openedBuild']['fixed'] = 'no';
$config->bug->datatable->fieldList['openedBuild']['width'] = '120';
$config->bug->datatable->fieldList['openedBuild']['required'] = 'no';
$config->bug->datatable->fieldList['openedBuild']['control'] = 'multiple';
$config->bug->datatable->fieldList['openedBuild']['dataSource'] = array('module' => 'build', 'method' =>'getBuildPairs', 'params' => '$productID&$branch&noempty,noterminate,nodone,withbranch');
$config->bug->datatable->fieldList['assignedTo']['title'] = 'assignedToAB';
$config->bug->datatable->fieldList['assignedTo']['fixed'] = 'no';
$config->bug->datatable->fieldList['assignedTo']['width'] = '120';
$config->bug->datatable->fieldList['assignedTo']['required'] = 'no';
$config->bug->datatable->fieldList['assignedTo']['dataSource'] = array('module' => 'bug', 'method' =>'getProductMemberPairs', 'params' => '$productID&$branch');
$config->bug->datatable->fieldList['assignedDate']['title'] = 'assignedDate';
$config->bug->datatable->fieldList['assignedDate']['fixed'] = 'no';
$config->bug->datatable->fieldList['assignedDate']['width'] = '90';
$config->bug->datatable->fieldList['assignedDate']['required'] = 'no';
$config->bug->datatable->fieldList['deadline']['title'] = 'deadline';
$config->bug->datatable->fieldList['deadline']['fixed'] = 'no';
$config->bug->datatable->fieldList['deadline']['width'] = '90';
$config->bug->datatable->fieldList['deadline']['required'] = 'no';
$config->bug->datatable->fieldList['deadline']['control'] = 'date';
$config->bug->datatable->fieldList['resolvedBy']['title'] = 'resolvedByAB';
$config->bug->datatable->fieldList['resolvedBy']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedBy']['width'] = '100';
$config->bug->datatable->fieldList['resolvedBy']['required'] = 'no';
$config->bug->datatable->fieldList['resolution']['title'] = 'resolutionAB';
$config->bug->datatable->fieldList['resolution']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolution']['width'] = '110';
$config->bug->datatable->fieldList['resolution']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedDate']['title'] = 'resolvedDateAB';
$config->bug->datatable->fieldList['resolvedDate']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedDate']['width'] = '120';
$config->bug->datatable->fieldList['resolvedDate']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['title'] = 'resolvedBuild';
$config->bug->datatable->fieldList['resolvedBuild']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['width'] = '120';
$config->bug->datatable->fieldList['resolvedBuild']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['control'] = 'select';
$config->bug->datatable->fieldList['resolvedBuild']['dataSource'] = array('module' => 'bug', 'method' =>'getRelatedObjects', 'params' => 'resolvedBuild&id,name');
$config->bug->datatable->fieldList['closedBy']['title'] = 'closedBy';
$config->bug->datatable->fieldList['closedBy']['fixed'] = 'no';
$config->bug->datatable->fieldList['closedBy']['width'] = '80';
+33 -12
View File
@@ -503,6 +503,8 @@ class bug extends control
$type = 'codeerror';
$pri = 3;
$color = '';
$feedbackBy = '';
$notifyEmail = '';
/* Parse the extras. extract fix php7.2. */
$extras = str_replace(array(',', ' '), array('&', ''), $extras);
@@ -525,9 +527,11 @@ class bug extends control
$severity = $bug->severity;
$type = $bug->type;
$assignedTo = $bug->assignedTo;
$deadline = $bug->deadline;
$deadline = helper::isZeroDate($bug->deadline) ? '' : $bug->deadline;
$color = $bug->color;
$testtask = $bug->testtask;
$feedbackBy = $bug->feedbackBy;
$notifyEmail = $bug->notifyEmail;
if($pri == 0) $pri = '3';
}
@@ -688,6 +692,8 @@ class bug extends control
$this->view->stepsRequired = strpos($this->config->bug->create->requiredFields, 'steps');
$this->view->isStepsTemplate = $steps == $this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect ? true : false;
$this->view->issueKey = $from == 'sonarqube' ? $output['sonarqubeID'] . ':' . $output['issueKey'] : '';
$this->view->feedbackBy = $feedbackBy;
$this->view->notifyEmail = $notifyEmail;
$this->display();
}
@@ -960,14 +966,8 @@ class bug extends control
$changes = $this->bug->update($bugID);
if(dao::isError())
{
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
return $this->send(array('status' => 'error', 'message' => dao::getError()));
}
else
{
return print(js::error(dao::getError()));
}
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'error', 'message' => dao::getError()));
return print(js::error(dao::getError()));
}
}
@@ -1148,10 +1148,17 @@ class bug extends control
$assignedToList = array_filter($assignedToList);
if(empty($assignedToList)) $assignedToList = $this->user->getPairs('devfirst|noclosed');
}
if($bug->assignedTo and !isset($assignedToList[$bug->assignedTo]))
{
/* Fix bug #28378. */
$assignedTo = $this->user->getById($bug->assignedTo);
$assignedToList[$bug->assignedTo] = $assignedTo->realname;
}
if($bug->status == 'closed') $assignedToList['closed'] = 'Closed';
$branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : '';
$productBugs = $this->bug->getProductBugPairs($productID, $branch);
unset($productBugs[$bugID]);
$this->view->bug = $bug;
$this->view->productID = $productID;
@@ -1808,6 +1815,7 @@ class bug extends control
$product = $this->loadModel('product')->getById($productID);
$branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : '';
$productBugs = $this->bug->getProductBugPairs($productID, $branch);
unset($productBugs[$bugID]);
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
@@ -2003,11 +2011,15 @@ class bug extends control
*
* @param int $bugID
* @param string $browseType
* @param string $excludeBugs
* @param int $param
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function linkBugs($bugID, $browseType = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
public function linkBugs($bugID, $browseType = '', $excludeBugs = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
/* Load pager. */
$this->app->loadClass('pager', $static = true);
@@ -2022,11 +2034,11 @@ class bug extends control
$this->qa->setMenu($this->products, $bug->product, $bug->branch);
/* Build the search form. */
$actionURL = $this->createLink('bug', 'linkBugs', "bugID=$bugID&browseType=bySearch&queryID=myQueryID", '', true);
$actionURL = $this->createLink('bug', 'linkBugs', "bugID=$bugID&browseType=bySearch&excludeBugs=$excludeBugs&queryID=myQueryID", '', true);
$this->bug->buildSearchForm($bug->product, $this->products, $queryID, $actionURL);
/* Get bugs to link. */
$bugs2Link = $this->bug->getBugs2Link($bugID, $browseType, $queryID, $pager);
$bugs2Link = $this->bug->getBugs2Link($bugID, $browseType, $queryID, $pager, $excludeBugs);
/* Assign. */
$this->view->title = $this->lang->bug->linkBugs . "BUG #$bug->id $bug->title - " . $this->products[$bug->product];
@@ -2309,6 +2321,15 @@ class bug extends control
{
$this->loadModel('port');
$this->session->set('bugPortParams', array('productID' => $productID, 'executionID' => $executionID, 'branch' => 'all'));
if(!$productID)
{
$this->config->bug->datatable->fieldList['module']['dataSource']['method'] = 'getAllModulePairs';
$this->config->bug->datatable->fieldList['module']['dataSource']['params'] = 'bug';
$this->config->bug->datatable->fieldList['project']['dataSource'] = array('module' => 'project', 'method' => 'getPairsByIdList', 'params' => $executionID);
$this->config->bug->datatable->fieldList['execution']['dataSource'] = array('module' => 'execution', 'method' => 'getPairs', 'params' => $executionID);
}
$this->port->export('bug');
$this->fetch('file', 'export2' . $_POST['fileType'], $_POST);
}
-3
View File
@@ -2,9 +2,6 @@
.closed, .closed a {color: gray; text-decoration:line-through;}
.resolved, .resolved a {color: #8EC21F; text-decoration: none;}
.tree .closed, .tree .closed a {color: #003366; text-decoration: none;}
.confirm0 {color: gray;}
.confirm1 {color: green;}
td.delayed {color: #fff; background: #e84e0f !important;}
#bugForm .setting {height: 25px;}
.datatable-wrapper .table-datatable .datatable-row td {height: 37px;}
+2 -2
View File
@@ -1,2 +1,2 @@
.confirm0 {color:gray; font-size:9px}
.confirm1 {color:green; font-size:9px}
.confirm0 {font-size:9px}
.confirm1 {font-size:9px}
+2 -1
View File
@@ -335,7 +335,8 @@ function loadProductExecutions(productID, projectID = 0)
branch = $('#branch').val();
if(typeof(branch) == 'undefined') branch = 0;
link = createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&projectID=' + projectID + '&branch=' + branch);
var execution = $('#execution').val();
link = createLink('product', 'ajaxGetExecutions', 'productID=' + productID + '&projectID=' + projectID + '&branch=' + branch + '&number=&executionID=' + execution);
$('#executionIdBox').load(link, function()
{
$(this).find('select').chosen();
+14
View File
@@ -26,6 +26,20 @@ $(function()
dropWidth : 'auto',
maxAutoDropWidth : document.body.scrollWidth + document.getElementById('resolution').offsetWidth - document.getElementById('resolution').getBoundingClientRect().right
});
$('#linkBugsLink').click(function()
{
var bugIdList = '';
$('#linkBugsBox input').each(function()
{
bugIdList += $(this).val() + ',';
});
var link = createLink('bug', 'linkBugs', 'bugID=' + bugID + '&browseType=&excludeBugs=' + bugIdList, '', true);
var modalTrigger = new $.zui.ModalTrigger({type: 'iframe', width: '95%', url: link});
modalTrigger.show();
});
});
/**
+3 -2
View File
@@ -187,10 +187,11 @@ $lang->bug->allUsers = 'Alle Benutzer laden';
$lang->bug->allBuilds = 'Alle';
$lang->bug->createBuild = 'Neu';
/* Legend list。*/
global $config;
/* Legend list. */
$lang->bug->legendBasicInfo = 'Basis Info';
$lang->bug->legendAttatch = 'Anlagen';
$lang->bug->legendPRJExecStoryTask = 'Project/' . $lang->executionCommon . '/Story/Task';
$lang->bug->legendPRJExecStoryTask = $config->systemMode == 'new' ? 'Project/' . $lang->executionCommon . '/Story/Task' : $lang->executionCommon . '/Story/Task';
$lang->bug->legendExecStoryTask = $lang->executionCommon . '/Story/Task';
$lang->bug->lblTypeAndSeverity = 'Typ/Schwere';
$lang->bug->lblSystemBrowserAndHardware = 'System/Browser';
+5 -4
View File
@@ -187,10 +187,11 @@ $lang->bug->allUsers = 'Load All Users';
$lang->bug->allBuilds = 'All Builds';
$lang->bug->createBuild = 'New';
/* Legend list。*/
global $config;
/* Legend list. */
$lang->bug->legendBasicInfo = 'Basic Info';
$lang->bug->legendAttatch = 'Files';
$lang->bug->legendPRJExecStoryTask = 'Project/' . $lang->executionCommon . '/Story/Task';
$lang->bug->legendPRJExecStoryTask = $config->systemMode == 'new' ? 'Project/' . $lang->executionCommon . '/Story/Task' : $lang->executionCommon . '/Story/Task';
$lang->bug->legendExecStoryTask = $lang->executionCommon . '/Story/Task';
$lang->bug->lblTypeAndSeverity = 'Type/Severity';
$lang->bug->lblSystemBrowserAndHardware = 'System/Browser';
@@ -284,8 +285,8 @@ $lang->bug->statusList['resolved'] = 'Resolved';
$lang->bug->statusList['closed'] = 'Closed';
$lang->bug->confirmedList[''] = '';
$lang->bug->confirmedList[1] = 'Yes';
$lang->bug->confirmedList[0] = 'No';
$lang->bug->confirmedList[1] = 'confirmed';
$lang->bug->confirmedList[0] = 'unconfirmed';
$lang->bug->resolutionList[''] = '';
$lang->bug->resolutionList['bydesign'] = 'As Designed';
+5 -4
View File
@@ -187,10 +187,11 @@ $lang->bug->allUsers = 'Charger Tous';
$lang->bug->allBuilds = 'Tous les Builds';
$lang->bug->createBuild = 'Nouveau';
/* Legend list。*/
global $config;
/* Legend list. */
$lang->bug->legendBasicInfo = 'Infos de Base';
$lang->bug->legendAttatch = 'Fichiers';
$lang->bug->legendPRJExecStoryTask = 'Project/' . $lang->executionCommon . '/Story/Task';
$lang->bug->legendPRJExecStoryTask = $config->systemMode == 'new' ? 'Project/' . $lang->executionCommon . '/Story/Task' : $lang->executionCommon . '/Story/Task';
$lang->bug->legendExecStoryTask = $lang->executionCommon . '/Story/Tâche';
$lang->bug->lblTypeAndSeverity = 'Type/Severité';
$lang->bug->lblSystemBrowserAndHardware = 'Système/Browser';
@@ -284,8 +285,8 @@ $lang->bug->statusList['resolved'] = 'Résolu';
$lang->bug->statusList['closed'] = 'Fermé';
$lang->bug->confirmedList[''] = '';
$lang->bug->confirmedList[1] = 'Oui';
$lang->bug->confirmedList[0] = 'Non';
$lang->bug->confirmedList[1] = 'confirmé';
$lang->bug->confirmedList[0] = 'non confirmé';
$lang->bug->resolutionList[''] = '';
$lang->bug->resolutionList['bydesign'] = 'Du Design';
+2 -2
View File
@@ -265,8 +265,8 @@ $lang->bug->statusList['active'] = 'Kích hoạt';
$lang->bug->statusList['resolved'] = 'Đã giải quyết';
$lang->bug->statusList['closed'] = 'Đã đóng';
$lang->bug->confirmedList[1] = 'Có';
$lang->bug->confirmedList[0] = 'Không';
$lang->bug->confirmedList[1] = 'đã xác nhận';
$lang->bug->confirmedList[0] = 'chưa được xác nhận';
$lang->bug->resolutionList[''] = '';
$lang->bug->resolutionList['bydesign'] = 'Như thiết kế';
+5 -4
View File
@@ -187,10 +187,11 @@ $lang->bug->allUsers = '加载所有用户';
$lang->bug->allBuilds = '所有';
$lang->bug->createBuild = '创建';
global $config;
/* legend列表。*/
$lang->bug->legendBasicInfo = '基本信息';
$lang->bug->legendAttatch = '附件';
$lang->bug->legendPRJExecStoryTask = "项目/" . $lang->executionCommon . "/{$lang->SRCommon}/任务";
$lang->bug->legendPRJExecStoryTask = $config->systemMode == 'new' ? "项目/" . $lang->executionCommon . "/{$lang->SRCommon}/任务" : $lang->executionCommon . "/{$lang->SRCommon}/任务";
$lang->bug->legendExecStoryTask = $lang->executionCommon . "/{$lang->SRCommon}/任务";
$lang->bug->lblTypeAndSeverity = '类型/严重程度';
$lang->bug->lblSystemBrowserAndHardware = '系统/浏览器';
@@ -284,8 +285,8 @@ $lang->bug->statusList['resolved'] = '已解决';
$lang->bug->statusList['closed'] = '已关闭';
$lang->bug->confirmedList[''] = '';
$lang->bug->confirmedList[1] = '是';
$lang->bug->confirmedList[0] = '否';
$lang->bug->confirmedList[1] = '已确认';
$lang->bug->confirmedList[0] = '未确认';
$lang->bug->resolutionList[''] = '';
$lang->bug->resolutionList['bydesign'] = '设计如此';
@@ -412,7 +413,7 @@ $lang->bug->placeholder = new stdclass();
$lang->bug->placeholder->chooseBuilds = '选择相关版本...';
$lang->bug->placeholder->newBuildName = '新版本名称';
$lang->bug->featureBar['browse']['all'] = $lang->bug->allBugs;
$lang->bug->featureBar['browse']['all'] = '全部';
$lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
+2 -2
View File
@@ -283,8 +283,8 @@ $lang->bug->statusList['resolved'] = '已解決';
$lang->bug->statusList['closed'] = '已關閉';
$lang->bug->confirmedList[''] = '';
$lang->bug->confirmedList[1] = '是';
$lang->bug->confirmedList[0] = '否';
$lang->bug->confirmedList[1] = '已確認';
$lang->bug->confirmedList[0] = '未確認';
$lang->bug->resolutionList[''] = '';
$lang->bug->resolutionList['bydesign'] = '設計如此';
+20 -14
View File
@@ -704,7 +704,7 @@ class bugModel extends model
->setDefault('browser', '')
->setDefault('plan', 0)
->setDefault('deadline', '0000-00-00')
->setDefault('resolvedDate', '0000-00-00 00:00:00')
->setDefault('resolvedDate', '')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('mailto', '')
->setDefault('deleteFiles', array())
@@ -754,7 +754,7 @@ class bugModel extends model
/* Link bug to build and release. */
if($bug->resolution == 'fixed' and !empty($bug->resolvedBuild) and $oldBug->resolvedBuild != $bug->resolvedBuild)
{
if(!empty($oldBug->resolvedBuild)) $this->loadModel('build')->unlinkBug((int)$oldBug->resolvedBuild, (int)$bugID);
if(!empty($oldBug->resolvedBuild)) $this->loadModel('build')->unlinkBug($oldBug->resolvedBuild, (int)$bugID);
$this->linkBugToBuild($bugID, $bug->resolvedBuild);
}
@@ -1014,13 +1014,13 @@ class bugModel extends model
*
* @param int $bugID
* @access public
* @return string
* @return array
*/
public function assign($bugID)
{
$now = helper::now();
$oldBug = $this->getById($bugID);
if($oldBug->status == 'closed') return false;
if($oldBug->status == 'closed') return array();
$bug = fixer::input('post')
->add('id', $bugID)
@@ -1526,15 +1526,16 @@ class bugModel extends model
* @param string $browseType
* @param int $queryID
* @param object $pager
* @param string $excludeBugs
* @access public
* @return array
*/
public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID = 0, $pager = null)
public function getBugs2Link($bugID, $browseType = 'bySearch', $queryID = 0, $pager = null, $excludeBugs = '')
{
if($browseType == 'bySearch')
{
$bug = $this->getById($bugID);
$bugIDList = $bug->id . ',' . $bug->linkBug;
$bugIDList = $bug->id . ',' . $bug->linkBug . ',' . $excludeBugs;
$bugs2Link = $this->getBySearch($bug->product, 'all', $queryID, 'id', $bugIDList, $pager);
return $bugs2Link;
}
@@ -3279,7 +3280,7 @@ class bugModel extends model
$title = "title='" . zget($projectPairs, $bug->project, '') . "'";
break;
case 'plan':
$title = "title='" . zget($plans, $bug->plan) . "'";
$title = "title='" . zget($plans, $bug->plan, '') . "'";
break;
case 'execution':
$title = "title='" . zget($executions, $bug->execution) . "'";
@@ -3296,6 +3297,9 @@ class bugModel extends model
$class .= ' text-ellipsis';
$title = "title='" . $browser . "'";
break;
case 'deadline':
$class .= ' text-center';
break;
}
if($id == 'deadline' && isset($bug->delay) && $bug->status == 'active') $class .= ' delayed';
@@ -3439,7 +3443,7 @@ class bugModel extends model
echo helper::isZeroDate($bug->assignedDate) ? '' : substr($bug->assignedDate, 5, 11);
break;
case 'deadline':
echo helper::isZeroDate($bug->deadline) ? '' : substr($bug->deadline, 5, 11);
echo helper::isZeroDate($bug->deadline) ? '' : '<span>' . substr($bug->deadline, 5, 11) . '</span>';
break;
case 'resolvedBy':
echo zget($users, $bug->resolvedBy, $bug->resolvedBy);
@@ -3484,15 +3488,17 @@ class bugModel extends model
public function printAssignedHtml($bug, $users)
{
$btnTextClass = '';
$btnClass = '';
$assignedToText = !empty($bug->assignedTo) ? zget($users, $bug->assignedTo) : $this->lang->bug->noAssigned;
$btnTextClass = 'text-primary';
if($bug->assignedTo == $this->app->user->account) $btnTextClass = 'text-red';
if(empty($bug->assignedTo)) $btnClass = $btnTextClass = 'assigned-none';
if($bug->assignedTo == $this->app->user->account) $btnClass = $btnTextClass = 'assigned-current';
if(!empty($bug->assignedTo) and $bug->assignedTo != $this->app->user->account) $btnClass = $btnTextClass = 'assigned-other';
$btnClass = $bug->assignedTo == 'closed' ? ' disabled' : '';
$btnClass = "iframe btn btn-icon-left btn-sm {$btnClass}";
$btnClass .= $bug->assignedTo == 'closed' ? ' disabled' : '';
$btnClass .= ' iframe btn btn-icon-left btn-sm';
$assignToLink = helper::createLink('bug', 'assignTo', "bugID=$bug->id", '', true);
$assignToHtml = html::a($assignToLink, "<i class='icon icon-hand-right'></i> <span title='" . zget($users, $bug->assignedTo) . "' class='{$btnTextClass}'>{$assignedToText}</span>", '', "class='$btnClass'");
$assignToHtml = html::a($assignToLink, "<i class='icon icon-hand-right'></i> <span title='" . zget($users, $bug->assignedTo) . "'>{$assignedToText}</span>", '', "class='$btnClass'");
echo !common::hasPriv('bug', 'assignTo', $bug) ? "<span style='padding-left: 21px' class='{$btnTextClass}'>{$assignedToText}</span>" : $assignToHtml;
}
@@ -3637,7 +3643,7 @@ class bugModel extends model
public function getRelatedObjects($object, $pairs = '')
{
/* Get bugs. */
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where($this->session->bugQueryCondition)->fetchAll('id');
$bugs = $this->loadModel('port')->getQueryDatas('bug');
/* Get related objects id lists. */
$relatedObjectIdList = array();
+2 -2
View File
@@ -17,7 +17,7 @@ foreach($products as $product)
}
$productsPinYin = common::convert2Pinyin($productNames);
$linkHtml = $this->product->setParamsForLink($module, $link, $projectID, 0);
$productsHtml = count($products) > 1 ? html::a($linkHtml, $this->lang->bug->allProduct, '', "class='text-important' title='{$this->lang->bug->allProduct}' data-key='" . zget($productsPinYin, $this->lang->bug->allProduct, '') . "' data-app='{$this->app->tab}'") : '';
$productsHtml = count($products) > 1 ? html::a($linkHtml, $this->lang->bug->allProduct, '', "class='text-primary' title='{$this->lang->bug->allProduct}' data-key='" . zget($productsPinYin, $this->lang->bug->allProduct, '') . "' data-app='{$this->app->tab}'") : '';
foreach($products as $product)
{
@@ -26,7 +26,7 @@ foreach($products as $product)
$productName .= $product->line ? zget($lines, $product->line, '') . '/' . $product->name : $product->name;
$objectID = ($product->type != 'platform' && $module == 'branch' && $method == 'manage') ? $productID : $product->id;
$linkHtml = $this->product->setParamsForLink($module, $link, $projectID, $product->id);
$productsHtml .= html::a($linkHtml, $productName, '', "class='text-important $selected' title='{$productName}' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='{$this->app->tab}'");
$productsHtml .= html::a($linkHtml, $productName, '', "class='text-primary $selected' title='{$productName}' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='{$this->app->tab}'");
}
?>
<div class="table-row">
+5 -1
View File
@@ -143,7 +143,11 @@
<tr>
<td class='pd-0'><?php echo html::select("resolutions[$bugID]", $resolutionList, $bug->resolution, "class='form-control' onchange=setDuplicate(this.value,$bugID)");?></td>
<td class='pd-0 w-p50' id='<?php echo 'duplicateBugBox' . $bugID;?>' <?php if($bug->resolution != 'duplicate') echo "style='display:none'";?>>
<?php echo html::select("duplicateBugs[$bugID]", $productBugList[$bug->product][$bug->branch], $bug->duplicateBug, "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?>
<?php
$productBugs = $productBugList[$bug->product][$bug->branch];
if(isset($productBugs[$bug->id])) unset($productBugs[$bug->id]);
?>
<?php echo html::select("duplicateBugs[$bugID]", $productBugs, $bug->duplicateBug, "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?>
</td>
</tr>
</table>
+4 -4
View File
@@ -160,11 +160,11 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
<?php if($showNoticefeedbackBy):?>
<tr>
<th><nobr><?php echo $lang->bug->feedbackBy;?></nobr></th>
<td><?php echo html::input('feedbackBy', '', "class='form-control'");?></td>
<td><?php echo html::input('feedbackBy', $feedbackBy, "class='form-control'");?></td>
<td id='notifyEmailTd'>
<div class='input-group'>
<span class='input-group-addon'><?php echo $lang->bug->notifyEmail?></span>
<span><?php echo html::input('notifyEmail', '', "class='form-control'");?></span>
<span><?php echo html::input('notifyEmail', $notifyEmail, "class='form-control'");?></span>
</div>
</td>
</tr>
@@ -173,9 +173,9 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
<td>
<div class='input-group' id='feedback'>
<span class="input-group-addon"><?php echo $lang->bug->feedbackBy?></span>
<?php echo html::input('feedbackBy', '', "class='form-control'");?>
<?php echo html::input('feedbackBy', $feedbackBy, "class='form-control'");?>
<span class="input-group-addon"><?php echo $lang->bug->notifyEmail?></span>
<?php echo html::input('notifyEmail', '', "class='form-control'");?>
<?php echo html::input('notifyEmail', $notifyEmail, "class='form-control'");?>
</div>
</td>
</tr>
+2 -1
View File
@@ -27,6 +27,7 @@ js::set('oldResolvedBuild' , $bug->resolvedBuild);
js::set('systemMode' , $config->systemMode);
js::set('confirmUnlinkBuild' , sprintf($lang->bug->confirmUnlinkBuild, zget($resolvedBuilds, $bug->resolvedBuild)));
js::set('tab' , $this->app->tab);
js::set('bugID' , $bug->id);
js::set('bugBranch' , $bug->branch);
js::set('isClosedBug' , $bug->status == 'closed');
if($this->app->tab == 'execution') js::set('objectID', $bug->execution);
@@ -287,7 +288,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
<tbody>
<tr class='text-top'>
<th class='thWidth'><?php echo $lang->bug->linkBug;?></th>
<td><?php if(common::hasPriv('bug', 'linkBugs')) echo html::a($this->createLink('bug', 'linkBugs', "bugID=$bug->id", '', true), $lang->bug->linkBugs, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='95%'");?></td>
<td><?php if(common::hasPriv('bug', 'linkBugs')) echo html::a('#', $lang->bug->linkBugs, '', "class='text-primary' id='linkBugsLink'");?></td>
</tr>
<tr <?php if(!isset($bug->linkBugTitles)) echo 'class="hidden"';?>>
<th></th>
+1 -1
View File
@@ -393,7 +393,7 @@
<?php if($bug->case):?>
<tr>
<th><?php echo $lang->bug->fromCase;?></th>
<td><?php echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case&caseVersion=" . ($bug->testtask ? "&from=testtask&taskID={$bug->testtask}" : ''), '', true), "#$bug->case $bug->caseTitle", '', "class='iframe' data-width='80%'");?></td>
<td><?php echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case&caseVersion=$bug->caseVersion", '', true), "#$bug->case $bug->caseTitle", '', "class='iframe' data-width='80%'");?></td>
</tr>
<?php endif;?>
<?php if($bug->toCases):?>
+1 -1
View File
@@ -47,7 +47,7 @@
<td><span class='label-pri label-pri-<?php echo $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri)?></span></td>
<td class='text-left nobr' title='<?php echo $story->title?>'>
<?php
if($story->parent > 0) echo "<span class='label'>{$lang->story->childrenAB}</span>";
if($story->parent > 0) echo "<span class='label label-badge label-light'>{$lang->story->childrenAB}</span>";
echo html::a($this->createLink('story', 'view', "storyID=$story->id&version=0&param=$objectID", '', true), $story->title, '', "data-toggle='modal' data-type='iframe' data-width='90%'");
?>
</td>
+4 -3
View File
@@ -20,6 +20,7 @@
#stories .action {display: none;}
#bugs .action {display: none;}
tbody tr td:first-child input {display: none;}
.page-title .dropdown-menu {top: 40px; left: 70px;}
</style>
<?php endif;?>
<div id='mainMenu' class='clearfix'>
@@ -28,8 +29,8 @@ tbody tr td:first-child input {display: none;}
<?php common::printBack($browseLink, 'btn btn-secondary');?>
<div class='divider'></div>
<div class='page-title'>
<span class='text' title='<?php echo $build->name;?>'>
<?php echo html::a('javascript:void(0)', "<span class='label label-id'>{$build->id}</span> " . $build->name . " <span class='caret'></span>", '', "data-toggle='dropdown' class='btn btn-link btn-active-text'");?>
<span title='<?php echo $build->name;?>'>
<?php echo html::a('javascript:void(0)', "<span class='label label-id'>{$build->id}</span> " . $build->name . " <span class='caret'></span>", '', "data-toggle='dropdown' class='text btn btn-link btn-active-text'");?>
<?php
echo "<ul class='dropdown-menu'>";
foreach($buildPairs as $id => $name)
@@ -103,7 +104,7 @@ tbody tr td:first-child input {display: none;}
<td><span class='label-pri label-pri-<?php echo $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri);?></span></td>
<td class='text-left nobr' title='<?php echo $story->title?>'>
<?php
if($story->parent > 0) echo "<span class='label'>{$lang->story->childrenAB}</span>";
if($story->parent > 0) echo "<span class='label label-badge label-light'>{$lang->story->childrenAB}</span>";
if($this->app->tab == 'execution' and common::hasPriv('execution', 'storyView'))
{
echo html::a($this->createLink('execution', 'storyView', "storyID=$story->id", '', true), $story->title, '', isonlybody() ? "data-width='1000'" : "class='iframe' data-width='1000'");
+1 -1
View File
@@ -45,5 +45,5 @@ $lang->caselib->legendDesc = '描述';
$lang->caselib->libraryDelete = '您确认要删除该用例库吗?';
$lang->caselib->noModule = '<div>您现在还没有模块信息</div><div>请维护用例库模块</div>';
$lang->caselib->featureBar['browse']['all'] = '所有';
$lang->caselib->featureBar['browse']['all'] = '全部';
$lang->caselib->featureBar['browse']['wait'] = '待评审';
+1 -1
View File
@@ -146,7 +146,7 @@ $lang->workingHour = '工时';
$lang->idAB = 'ID';
$lang->priAB = 'P';
$lang->statusAB = '状态';
$lang->openedByAB = '创建';
$lang->openedByAB = '创建者';
$lang->assignedToAB = '指派';
$lang->typeAB = '类型';
$lang->nameAB = '名称';
+1 -1
View File
@@ -136,7 +136,7 @@ $lang->workingHour = '工時';
$lang->idAB = 'ID';
$lang->priAB = 'P';
$lang->statusAB = '狀態';
$lang->openedByAB = '創建';
$lang->openedByAB = '創建者';
$lang->assignedToAB = '指派';
$lang->typeAB = '類型';
$lang->nameAB = '名稱';
+36 -17
View File
@@ -1460,9 +1460,17 @@ class commonModel extends model
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''>";
$appqrcode = self::http('https://www.zentao.net/page/appqrcode.json');
/* Intranet users use local pictures. */
if(!empty($appqrcode))
$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>";
}
@@ -2000,11 +2008,10 @@ EOD;
$oldStatus = zget($old, 'status', '');
$newStatus = zget($new, 'status', '');
$newSubStatus = zget($new, 'subStatus', '');
if(empty($moduleName)) $moduleName = $app->getModuleName();
if($oldID and $oldStatus and $newStatus and !$newSubStatus and $oldStatus != $newStatus)
{
if(empty($moduleName)) $moduleName = $app->getModuleName();
$field = $app->dbh->query('SELECT options FROM ' . TABLE_WORKFLOWFIELD . " WHERE `module` = '$moduleName' AND `field` = 'subStatus'")->fetch();
if(!empty($field->options)) $field->options = json_decode($field->options, true);
@@ -2018,6 +2025,11 @@ EOD;
$new->subStatus = $default;
}
}
$dateFields = array();
$sql = "SELECT `field` FROM " . TABLE_WORKFLOWFIELD . " WHERE `module` = '{$moduleName}' and `control` in ('date', 'datetime')";
$stmt = $app->dbh->query($sql);
while($row = $stmt->fetch()) $dateFields[$row->field] = $row->field;
}
$changes = array();
@@ -2030,24 +2042,29 @@ EOD;
if(strtolower($key) == 'editedby') continue;
if(strtolower($key) == 'editeddate') continue;
if(strtolower($key) == 'uid') continue;
if(strtolower($key) == 'finisheddate' and $value == '') continue;
if(strtolower($key) == 'canceleddate' and $value == '') continue;
if(strtolower($key) == 'hangupeddate' and $value == '') continue;
if(strtolower($key) == 'lastcheckeddate' and $value == '') continue;
if(strtolower($key) == 'activateddate' and $value == '') continue;
if(strtolower($key) == 'closeddate' and $value == '') continue;
if(strtolower($key) == 'finisheddate' and $value == '') continue;
if(strtolower($key) == 'canceleddate' and $value == '') continue;
if(strtolower($key) == 'hangupeddate' and $value == '') continue;
if(strtolower($key) == 'lastcheckeddate' and $value == '') continue;
if(strtolower($key) == 'activateddate' and $value == '') continue;
if(strtolower($key) == 'closeddate' and $value == '') continue;
if(strtolower($key) == 'actualcloseddate' and $value == '') continue;
if(isset($old->$key) and $value != stripslashes($old->$key))
if(isset($old->$key))
{
$diff = '';
if(substr_count($value, "\n") > 1 or
substr_count($old->$key, "\n") > 1 or
strpos('name,title,desc,spec,steps,content,digest,verify,report,definition,analysis,summary,prevention,resolution,outline,schedule,minutes', strtolower($key)) !== false)
if($config->edition != 'open' && isset($dateFields[$key])) $old->$key = formatTime($old->$key);
if($value != stripslashes($old->$key))
{
$diff = commonModel::diff($old->$key, $value);
$diff = '';
if(substr_count($value, "\n") > 1 or
substr_count($old->$key, "\n") > 1 or
strpos('name,title,desc,spec,steps,content,digest,verify,report,definition,analysis,summary,prevention,resolution,outline,schedule,minutes', strtolower($key)) !== false)
{
$diff = commonModel::diff($old->$key, $value);
}
$changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff);
}
$changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff);
}
}
return $changes;
@@ -2132,6 +2149,8 @@ EOD;
{
if(strpos($orderBy, 'priOrder') !== false) $select .= ", IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder";
if(strpos($orderBy, 'severityOrder') !== false) $select .= ", IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder";
$queryCondition = str_replace('t4.status', 'status', $queryCondition);
$sql = $this->dao->select("*$select")->from($table)
->where($queryCondition)
->beginIF($orderBy != false)->orderBy($orderBy)->fi()
+3
View File
@@ -21,6 +21,9 @@
</div>
</div>
</div>
<style>
#importNoticeModal .modal-dialog {top: 15% !important; max-height: 450px; overflow-y: auto;}
</style>
<script>
function submitForm(type)
{
-1
View File
@@ -67,7 +67,6 @@ class datatable extends control
$this->app->loadConfig('testtask');
$this->config->testcase->datatable->defaultField = $this->config->testtask->datatable->defaultField;
$this->config->testcase->datatable->fieldList['actions']['width'] = '100';
$this->config->testcase->datatable->fieldList['status']['title'] = $this->lang->testcase->executionStatus;
$this->config->testcase->datatable->fieldList['status']['width'] = '90';
}
if($module == 'testcase')
+1
View File
@@ -30,6 +30,7 @@ $lang->dept->noDepartment = "No Department";
$lang->dept->confirmDelete = " Möchten Sie diese Abteilung löschen?";
$lang->dept->successSave = " Gespeichert!";
$lang->dept->repeatDepart = " Es gibt einen doppelten Abteilungsnamen, möchten Sie ihn wirklich hinzufügen?";
$lang->dept->error = new stdclass();
$lang->dept->error->hasSons = 'Diese Abteilung hat Unterabteilungen und kann daher nicht gelöscht werden!';
+1
View File
@@ -30,6 +30,7 @@ $lang->dept->noDepartment = "No Department";
$lang->dept->confirmDelete = " Do you want to delete this department?";
$lang->dept->successSave = " Saved!";
$lang->dept->repeatDepart = " There is a duplicate department name, are you sure to add it?";
$lang->dept->error = new stdclass();
$lang->dept->error->hasSons = 'This Department has child departments. You cannot delete it!';
+1
View File
@@ -30,6 +30,7 @@ $lang->dept->noDepartment = "No Department";
$lang->dept->confirmDelete = " Confirmez que vous voulez bien supprimer ce Compartiment ?";
$lang->dept->successSave = " Sauvé !";
$lang->dept->repeatDepart = " Il y a un nom de département en double, êtes-vous sûr de l'ajouter ?";
$lang->dept->error = new stdclass();
$lang->dept->error->hasSons = 'Ce Compartiment possède des domaines. Vous ne pouvez pas le supprimer !';
+1
View File
@@ -26,6 +26,7 @@ $lang->dept->dragAndSort = "Drag để sắp xếp";
$lang->dept->confirmDelete = " Bạn có muốn xóa this department?";
$lang->dept->successSave = " Saved!";
$lang->dept->repeatDepart = " Có một tên bộ phận trùng lặp, bạn có chắc chắn thêm nó không?";
$lang->dept->error = new stdclass();
$lang->dept->error->hasSons = 'This Department has child departments. You cannot xóa it!';
+1
View File
@@ -30,6 +30,7 @@ $lang->dept->noDepartment = "无部门";
$lang->dept->confirmDelete = " 您确定删除该部门吗?";
$lang->dept->successSave = " 修改成功。";
$lang->dept->repeatDepart = " 存在部门名称重复,您确认添加吗?";
$lang->dept->error = new stdclass();
$lang->dept->error->hasSons = '该部门有子部门,不能删除!';
+1
View File
@@ -29,6 +29,7 @@ $lang->dept->dragAndSort = "拖動排序";
$lang->dept->confirmDelete = " 您確定刪除該部門嗎?";
$lang->dept->successSave = " 修改成功。";
$lang->dept->repeatDepart = " 存在部門名稱重複,您確認添加嗎?";
$lang->dept->error = new stdclass();
$lang->dept->error->hasSons = '該部門有子部門,不能刪除!';
+39 -4
View File
@@ -11,6 +11,7 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('repeatDepart', $lang->dept->repeatDepart);?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
<span class='btn btn-link btn-active-text'><span class='text'><?php echo $lang->dept->common;?></span></span>
@@ -33,7 +34,7 @@
<div class='panel-title'><?php echo $lang->dept->manageChild;?></div>
</div>
<div class='panel-body'>
<form method='post' target='hiddenwin' action='<?php echo $this->createLink('dept', 'manageChild');?>'>
<form method='post' target='hiddenwin' action='<?php echo $this->createLink('dept', 'manageChild');?>' id="dataForm">
<table class='table table-form'>
<tr>
<td>
@@ -49,7 +50,7 @@
?>
</nobr>
</td>
<td class='w-300px'>
<td class='w-500px'>
<?php
$maxOrder = 0;
foreach($sons as $sonDept)
@@ -85,7 +86,7 @@ $(function()
name: 'deptTree',
initialState: 'preserve',
data: data,
sortable:
sortable:
{
lazy: true,
nested: true,
@@ -105,7 +106,7 @@ $(function()
$li.append($toggle);
return true;
},
actions:
actions:
{
sort:
{
@@ -172,6 +173,40 @@ $(function()
$(this).addClass('hover');
e.stopPropagation();
});
$("input[name*='depts']").change(function ()
{
var depts = new Array();
var modifyData = $(this).val();
var changedInput = $(this);
changedInput.wrap('<span>');
changedInput.closest('span').addClass('dataField');
$('input[name^="depts"]').not($(this)).each(function()
{
if($(this).val()) depts.push($(this).val());
});
if(depts.indexOf(modifyData) > -1)
{
$('.dataField #depts\\[\\]').addClass('intro');
$('.intro').css({"margin" : "5px 0px 5px 0px", "display" : "inline", "width" : "50%"});
changedInput.after('<span style="padding-left: 15px;color: #1183fb" class="tips">' + repeatDepart + '</span>');
}
});
$("input[name*='depts']").focus(function ()
{
if($('.dataField').length)
{
$('.intro').removeAttr('style');
$('.intro').unwrap();
$('#depts\\[\\]').removeClass('intro');
$('.tips').remove();
}
});
});
</script>
<?php include '../../common/view/footer.html.php';?>
+7 -5
View File
@@ -467,19 +467,21 @@ class designModel extends model
public function printAssignedHtml($design = '', $users = '')
{
$btnTextClass = '';
$btnClass = '';
$assignedToText = zget($users, $design->assignedTo);
if(empty($design->assignedTo))
{
$btnTextClass = 'text-primary';
$btnClass = $btnTextClass = 'assigned-none';
$assignedToText = $this->lang->design->noAssigned;
}
if($design->assignedTo == $this->app->user->account) $btnTextClass = 'text-red';
if($design->assignedTo == $this->app->user->account) $btnClass = $btnTextClass = 'assigned-current';
if(!empty($design->assignedTo) and $design->assignedTo != $this->app->user->account) $btnClass = $btnTextClass = 'assigned-other';
$btnClass = $design->assignedTo == 'closed' ? ' disabled' : '';
$btnClass = "iframe btn btn-icon-left btn-sm {$btnClass}";
$btnClass .= $design->assignedTo == 'closed' ? ' disabled' : '';
$btnClass .= ' iframe btn btn-icon-left btn-sm';
$assignToLink = helper::createLink('design', 'assignTo', "designID=$design->id", '', true);
$assignToHtml = html::a($assignToLink, "<i class='icon icon-hand-right'></i> <span title='" . zget($users, $design->assignedTo) . "' class='{$btnTextClass}'>{$assignedToText}</span>", '', "class='$btnClass'");
$assignToHtml = html::a($assignToLink, "<i class='icon icon-hand-right'></i> <span title='" . zget($users, $design->assignedTo) . "'>{$assignedToText}</span>", '', "class='$btnClass'");
echo !common::hasPriv('design', 'assignTo', $design) ? "<span style='padding-left: 21px' class='{$btnTextClass}'>{$assignedToText}</span>" : $assignToHtml;
}
+1 -1
View File
@@ -25,7 +25,7 @@ foreach($products as $product)
$linkHtml = sprintf($link, $product->id);
if($product->status == 'normal' and $product->PO == $this->app->user->account)
{
$myProductsHtml .= html::a($linkHtml, $productName, '', "class='text-important $selected' title='{$productName}' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$tab'");
$myProductsHtml .= html::a($linkHtml, $productName, '', "class='text-primary $selected' title='{$productName}' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$tab'");
}
else if($product->status == 'normal' and !($product->PO == $this->app->user->account))
{
+12
View File
@@ -629,6 +629,18 @@ class doc extends control
if($this->config->systemMode == 'classic' and $objectType == 'project') $objectType = 'execution';
$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)) @unlink($file->realPath);
}
/* if ajax request, send result. */
if($this->server->ajax)
{
+2
View File
@@ -1 +1,3 @@
#whiteListBox .input-group:last-child {margin-top: 10px;}
#dataform .radio-inline.hidden + .radio-inline {margin-left: 0px;}
#module_chosen.chosen-container .chosen-results {max-height: 200px;}
+1 -1
View File
@@ -9,7 +9,7 @@
.no-content-button a:nth-child(2) {margin-left: 20px;}
.cell .detail .detail-title {padding-left: 5px; list-style: none;}
.menu-actions {position: relative; float: right; top: -34px; right: -15px; padding: 7px 8px;}
.menu-actions {position: absolute; top: 7px; right: 45px; padding: 7px 8px;}
.detail ul {position: relative;}
.tail-info {position: absolute; right: 0; padding-left: 10px; padding-top: 1px;}
.tail-info, .doc-title, span.item {background: #fff;}
+1 -1
View File
@@ -62,7 +62,7 @@ $(function()
if($(".createCustomLib").length == 1) $(".createCustomLib").click(); // Fix bug #15139.
if(!fromGlobal && textType.indexOf(docType) != -1)
if(!fromGlobal && textType.indexOf(docType) != -1 && from == 'doc')
{
var basicInfo = JSON.parse(sessionStorage.getItem('docBasicInfo'));
+1
View File
@@ -10,6 +10,7 @@
* @link http://www.zentao.net
*/
?>
<?php js::set('from', $from);?>
<?php if(strpos($config->doc->textTypes, $docType) !== false and $from == 'doc'):?>
<?php include 'createtexttype.html.php';?>
<?php else:?>
+1 -1
View File
@@ -31,7 +31,7 @@
<tr>
<th><?php echo $lang->doc->module;?></th>
<td>
<span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control chosen'");?></span>
<span id='moduleBox'><?php echo html::select('module', $moduleOptionMenu, $moduleID, "class='form-control chosen' data-drop_direction='down'");?></span>
</td><td></td>
</tr>
<tr>
+13 -9
View File
@@ -8,7 +8,7 @@ $config->execution->ownerFields = array('PO', 'PM', 'QD', 'RD');
$config->execution->defaultBurnPeriod = 30;
$config->execution->list = new stdclass();
$config->execution->list->exportFields = 'id,name,projectName,code,PM,begin,end,status,totalEstimate,totalConsumed,totalLeft,progress';
$config->execution->list->exportFields = 'id,name,projectName,PM,begin,end,status,totalEstimate,totalConsumed,totalLeft,progress';
$config->execution->modelList['scrum'] = 'sprint';
$config->execution->modelList['waterfall'] = 'stage';
@@ -135,6 +135,7 @@ $config->execution->all->search['fields']['realEnd'] = $lang->execution->
$config->execution->all->search['fields']['closedBy'] = $lang->execution->closedBy;
$config->execution->all->search['fields']['lastEditedDate'] = $lang->execution->lastEditedDate;
$config->execution->all->search['fields']['closedDate'] = $lang->execution->closedDate;
$config->execution->all->search['fields']['teamCount'] = $lang->execution->teamCount;
$config->execution->all->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->execution->all->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
@@ -150,6 +151,7 @@ $config->execution->all->search['params']['realEnd'] = array('operator' =
$config->execution->all->search['params']['closedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->execution->all->search['params']['lastEditedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->execution->all->search['params']['closedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->execution->all->search['params']['teamCount'] = array('operator' => '=', 'control' => 'input', 'values' => '');
$config->printKanban = new stdClass();
$config->printKanban->col['story'] = 1;
@@ -173,17 +175,13 @@ $config->execution->gantt->linkType['end']['end'] = 2;
$config->execution->gantt->linkType['begin']['end'] = 3;
$config->execution->datatable = new stdclass();
if((!isset($config->setCode) or $config->setCode == 1) and $config->systemMode == 'new')
if($config->systemMode == 'new')
{
$config->execution->datatable->defaultField = array('id', 'name', 'code', 'project', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
}
elseif($config->systemMode == 'new')
{
$config->execution->datatable->defaultField = array('id', 'name', 'project', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
$config->execution->datatable->defaultField = array('id', 'name', 'project', 'status', 'PM', 'begin', 'end', 'estimate', 'consumed', 'left', 'progress', 'burn');
}
else
{
$config->execution->datatable->defaultField = array('id', 'name', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn');
$config->execution->datatable->defaultField = array('id', 'name', 'status', 'PM', 'begin', 'end', 'estimate', 'consumed', 'left', 'progress', 'burn');
}
$config->execution->datatable->fieldList['id']['title'] = 'idAB';
@@ -208,7 +206,7 @@ if($config->systemMode == 'new')
{
$config->execution->datatable->fieldList['project']['title'] = 'project';
$config->execution->datatable->fieldList['project']['fixed'] = 'no';
$config->execution->datatable->fieldList['project']['width'] = '100';
$config->execution->datatable->fieldList['project']['width'] = '128';
$config->execution->datatable->fieldList['project']['required'] = 'no';
}
@@ -255,6 +253,12 @@ $config->execution->datatable->fieldList['realEnd']['width'] = '90';
$config->execution->datatable->fieldList['realEnd']['required'] = 'no';
$config->execution->datatable->fieldList['realEnd']['sort'] = 'no';
$config->execution->datatable->fieldList['teamCount']['title'] = 'teamCount';
$config->execution->datatable->fieldList['teamCount']['fixed'] = 'no';
$config->execution->datatable->fieldList['teamCount']['width'] = '80';
$config->execution->datatable->fieldList['teamCount']['required'] = 'no';
$config->execution->datatable->fieldList['teamCount']['sort'] = 'no';
$config->execution->datatable->fieldList['estimate']['title'] = 'estimate';
$config->execution->datatable->fieldList['estimate']['fixed'] = 'no';
$config->execution->datatable->fieldList['estimate']['width'] = '70';
+11 -7
View File
@@ -2365,10 +2365,10 @@ class execution extends control
/**
* Kanban.
*
* @param int $executionID
* @param string $browseType
* @param string $orderBy
* @param string $groupBy
* @param int $executionID
* @param string $browseType
* @param string $orderBy
* @param string $groupBy
* @access public
* @return void
*/
@@ -2422,7 +2422,6 @@ class execution extends control
}
foreach($products as $product) $productNames[$product->id] = $product->name;
$plans = $this->execution->getPlans($products, 'skipParent', $executionID);
$allPlans = array('' => '');
if(!empty($plans))
@@ -2430,6 +2429,9 @@ class execution extends control
foreach($plans as $plan) $allPlans += $plan;
}
$taskToOpen = !empty($_COOKIE['taskToOpen']) ? $_COOKIE['taskToOpen'] : 0;
setcookie('taskToOpen', 0, time() - 3600, $this->config->webRoot, '', $this->config->cookieSecure, true);
$this->view->title = $this->lang->kanban->view;
$this->view->users = $users;
$this->view->regions = $kanbanData;
@@ -2448,6 +2450,7 @@ class execution extends control
$this->view->kanbanData = $kanbanData;
$this->view->executionActions = $executionActions;
$this->view->kanban = $this->lang->execution->kanban;
$this->view->taskToOpen = $taskToOpen;
$this->display();
}
@@ -2495,7 +2498,7 @@ class execution extends control
$kanbanGroup = $this->kanban->getExecutionKanban($executionID, $browseType, $groupBy, '', $orderBy);
if(empty($kanbanGroup))
{
$this->kanban->createExecutionLane($executionID, $browseType, $groupBy);
$this->kanban->createExecutionLane($executionID, $browseType);
$kanbanGroup = $this->kanban->getExecutionKanban($executionID, $browseType, $groupBy, '', $orderBy);
}
@@ -3180,7 +3183,7 @@ class execution extends control
{
$this->project->setMenu($object->id);
}
elseif($object->type == 'sprint' or $object->type == 'stage')
elseif($object->type == 'sprint' or $object->type == 'stage' or $object->type == 'kanban')
{
$this->execution->setMenu($object->id);
}
@@ -3757,6 +3760,7 @@ class execution extends control
$this->view->from = $from;
$this->view->param = $param;
$this->view->isStage = (isset($project->model) and $project->model == 'waterfall') ? true : false;
$this->view->showBatchEdit = $this->cookie->showExecutionBatchEdit;
$this->display();
}
+5 -1
View File
@@ -27,7 +27,7 @@ td.flex span.project-type-label {min-width: 40px;}
.c-name > a, .table-children .text-left > a {padding-left: 5px;}
.has-child > span {margin-right: 5px;}
.c-name > .text-ellipsis {text-overflow: clip;}
.c-code, .c-project {overflow: hidden; white-space: nowrap;}
.c-code, .c-project {overflow: hidden; white-space: nowrap; padding: 0 8px;}
th.c-status, .c-begin, .c-end, .c-realBegan, .c-realEnd {text-align: center;}
.c-project{text-overflow: unset !important;}
@@ -38,3 +38,7 @@ canvas {height: 28px;}
#datatable-executionList .table-child-bottom.table-child-top > .c-name.flex {border-bottom: 2px solid #cbd0db !important;}
#datatable-executionList .parent.has-child.c-name.flex {border-bottom: 1px solid #cbd0db !important;}
#datatable-executionList tr:last-child .c-name.flex {margin-top: 1px !important;}
.table thead .c-estimate.text-right,
.table thead .c-consumed.text-right,
.table thead .c-left.text-right {padding-right: 8px;}
+1 -1
View File
@@ -6,7 +6,7 @@
.dropdown-list > li > a {display: block; padding: 3px 20px; clear: both; font-weight: normal; line-height: 1.53846154; color: #141414; white-space: nowrap;}
.dropdown-list > li > a:hover,
.dropdown-list > li > a:focus {color: #1a4f85; text-decoration: none; background-color: #ddd;}
td.delayed {color: #fff; background: #e84e0f !important;}
.c-severity {width: 80px;}
.c-confirmed {overflow: hidden;}
.c-deadline {text-align: center;}
-1
View File
@@ -27,4 +27,3 @@
.c-hours {white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right;}
.c-user, .c-type {width: 70px;}
.c-progress {width: 60px;}
.delayed {background: #e84e0f !important; color: white;}
+1
View File
@@ -121,3 +121,4 @@
#kanban .kanban-affixed .kanban-header-col .title.action-dbc {pointer-events: none;}
#kanban .kanban-affixed .kanban-header-col .title.action-dbc .storyColumn .text {color: #fff;}
#kanban .kanban-affixed .kanban-header-col .title.action-dbc .storyColumn .caret {display: none;}
.kanban-card a[disabled] {color: #313c52;}
+3 -3
View File
@@ -4,6 +4,6 @@
#productsBox .product.checked:hover {background: #E5FFE6; border: 1px solid #229F24;}
#productsBox .product .checkbox-primary {padding: 9px; cursor: pointer;}
#productsBox .product.has-branch {padding-right: 40%;}
#productsBox .product.has-branch > .chosen-container {position: absolute; width: 40% !important; right: 3px; top: 3px;}
#productsBox .product.has-branch > .chosen-container > .chosen-single {background: rgba(0,0,0,.05);}
#productsBox .product.has-branch > .chosen-container > .chosen-single:hover {background: #fff;}
#productsBox .product.has-branch > .picker {position: absolute; width: 40% !important; right: 3px; top: 3px; background-color: unset;}
#productsBox .product.has-branch > .picker > .picker-selections {background: rgba(0,0,0,.05);}
#productsBox .product.has-branch > .picker > .picker-selections:hover {background: #fff;}
+1
View File
@@ -20,3 +20,4 @@ th.c-pri{width:50px;}
.switchBtn {background-color: #fff !important;}
.switchBtn > i {padding-left: 7px;}
#main>.container {padding: 0 20px 20px 23px;}
#executionStoryForm table tbody tr td.c-actions .dividing-line {width: 1px; height: 16px; display: inline-block; vertical-align: middle; background: #F4F5F7; margin: 0 4px 0 0;}
+1 -1
View File
@@ -1,4 +1,3 @@
td.delayed {background: #e84e0f !important; color: white;}
#int-dropdown {margin-left: -8px; border-radius: 4px; border: 1px solid #0c64eb;}
#projectTaskForm table tbody tr td {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.table td.c-estimate, .table td.c-consumed, .table td.c-left {padding-right: 12px;}
@@ -11,3 +10,4 @@ td.delayed {background: #e84e0f !important; color: white;}
#taskList .c-progress{padding-right: 8px; text-align: right;}
#datatable-taskList .c-progress{padding-right: 8px; text-align: right;}
.c-finishedBy, .c-lastEditedBy {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
#executionTaskForm table tbody tr td.c-actions .dividing-line {width: 1px; height: 16px; display: inline-block; vertical-align: middle; background: #F4F5F7; margin: 0 4px 0 0;}
+3 -2
View File
@@ -16,7 +16,7 @@
.kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;}
.kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;}
.kanban-header-col > .actions {padding-top: 22px}
.kanban-header-col > .actions {top: auto!important; right: 5px!important;}
.kanban-header-parent-col .kanban-header-col > .actions {padding-top: 6px; padding-right: 2px;}
.kanban-header-col > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;}
.kanban-header-col > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;}
@@ -46,6 +46,7 @@
#kanbans .kanban-card[data-scale-size="2"] > .infos > .info-pri {transform: scale(.8); vertical-align: top;}
#kanbans .kanban-card[data-scale-size="2"] > .infos > .avatar {display: inline-block; transform: scale(.8); position: relative; top: -2px; vertical-align: top; margin-right: -1px;}
#kanbans .kanban-card[data-scale-size="2"] > .infos > .info-estimate {top: -1px;}
#kanbans .kanban-col {padding: 0px !important;}
#kanbanScaleControl {width: 100px;}
#kanbanScaleControl .input-group-addon {background: #fff; padding: 5px;}
@@ -61,7 +62,6 @@
.c-group {width: 190px !important; overflow: unset;}
.c-type {margin-left: 0px !important;}
.createButton {margin-right: 5px;}
.headerTop {top: 0px !important;}
.kanban-header-col>.actions>a {padding: 0px !important;}
@@ -73,3 +73,4 @@
#kanbans .kanban-affixed .kanban-header-col .title.action-dbc {pointer-events: none;}
#kanbans .kanban-affixed .kanban-header-col .title.action-dbc .storyColumn .text {color: #fff;}
#kanbans .kanban-affixed .kanban-header-col .title.action-dbc .storyColumn .caret {display: none;}
.kanban-card a[disabled] {color: #313c52;}
+62 -3
View File
@@ -1,5 +1,17 @@
$(function()
{
$("#" + status + "Tab").addClass('btn-active-text');
$(document).on('click', '.plan-toggle', function(e)
{
var id = $(this).data('id');
var $toggle = $(this);
var isCollapsed = $toggle.toggleClass('collapsed').hasClass('collapsed');
$toggle.closest('#executionsForm').find('tr.parent-' + id).toggle(!isCollapsed);
e.stopPropagation();
e.preventDefault();
});
$('#executionTableList').on('sort.sortable', function(e, data)
{
var list = '';
@@ -60,6 +72,7 @@ $(function()
}
});
/* Update table summary text. */
$('#executionsForm').table(
{
statisticCreator: function(table)
@@ -67,21 +80,67 @@ $(function()
var $table = table.getTable();
var $checkedRows = $table.find(table.isDataTable ? '.datatable-row-left.checked' : 'tbody>tr.checked');
var $originTable = table.isDataTable ? table.$.find('.datatable-origin') : null;
var $rows = $table.find(table.isDataTable ? '.datatable-rows .datatable-row-left' : 'tbody>tr');
var checkedTotal = $checkedRows.length;
var $rows = checkedTotal ? $checkedRows : $table.find(table.isDataTable ? '.datatable-rows .datatable-row-left' : 'tbody>tr');
var taskIdList = [];
var checkedWait = 0;
var checkedDoing = 0;
var executionIDList = [];
$rows.each(function()
{
var $row = $(this);
if($originTable) $row = $originTable.find('tbody>tr[data-id="' + $row.data('id') + '"]');
var data = $row.data();
taskIdList.push(data.id);
executionIDList.push(data.id);
if(data.status === 'wait') checkedWait++;
if(data.status === 'doing') checkedDoing++;
});
if(status != 'all') return (checkedTotal ? checkedExecutions : executionSummary).replace('%s', $rows.length);
return (checkedTotal ? checkedSummary : pageSummary).replace('%total%', $rows.length).replace('%wait%', checkedWait).replace('%doing%', checkedDoing);
}
})
$('input[name^="showEdit"]').click(function()
{
$.cookie('showExecutionBatchEdit', $(this).is(':checked') ? 1 : 0, {expires: config.cookieLife, path: config.webRoot});
setCheckbox();
});
setCheckbox();
$('#executionTableList tr').on('click', function(e)
{
if($.cookie('showExecutionBatchEdit') != 1) e.stopPropagation();
});
});
/**
* Location to product list.
*
* @param int productID
* @param int projectID
* @param string status
* @access public
* @return void
*/
function byProduct(productID, projectID, status)
{
location.href = createLink('project', 'all', "status=" + status + "&project=" + projectID + "&orderBy=" + orderBy + '&productID=' + productID);
}
/**
* Set batch edit checkbox.
*
* @access public
* @return void
*/
function setCheckbox()
{
$('#executionsForm .checkbox-primary').hide();
$('.check-all, .sortable tr').removeClass('checked');
$(":checkbox[name^='executionIDList']").prop('checked', false);
$('#executionsForm').removeClass('has-row-checked');
if($.cookie('showExecutionBatchEdit') == 1) $('#executionsForm .checkbox-primary').show();
}
+12 -5
View File
@@ -1324,9 +1324,9 @@ function createStoryMenu(options)
var showAction = story.$col.type == 'backlog' || story.$col.type == 'ready' || story.$col.type == 'developing' || story.$col.type == 'developed' || story.$col.type == 'testing' || story.$col.type == 'tested' || story.$col.type == 'verified' || story.$col.type == 'released';
if(priv.canEditStory) items.push({label: storyLang.edit, icon: 'edit', url: createLink('story', 'edit', 'storyID=' + story.id + '&kanbanGroup=' + groupBy, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '95%'}});
if(priv.canChangeStory && showAction) items.push({label: storyLang.change, icon: 'change', url: createLink('story', 'change', 'storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canCreateTask && showAction) items.push({label: executionLang.wbs, icon: 'plus', url: createLink('task', 'create', 'executionID=' + execution.id + '&storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canBatchCreateTask && showAction) items.push({label: executionLang.batchWBS, icon: 'pluses', url: createLink('task', 'batchCreate', 'executionID=' + execution.id + '&storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canChangeStory && showAction && story.status == 'active') items.push({label: storyLang.change, icon: 'change', url: createLink('story', 'change', 'storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canCreateTask && showAction && story.status == 'active') items.push({label: executionLang.wbs, icon: 'plus', url: createLink('task', 'create', 'executionID=' + execution.id + '&storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canBatchCreateTask && showAction && story.status == 'active') items.push({label: executionLang.batchWBS, icon: 'pluses', url: createLink('task', 'batchCreate', 'executionID=' + execution.id + '&storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canActivateStory && story.$col.type == 'closed') items.push({label: executionLang.activate, icon: 'magic', url: createLink('story', 'activate', 'storyID=' + story.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(priv.canUnlinkStory) items.push({label: executionLang.unlinkStory, icon: 'unlink', url: createLink('execution', 'unlinkStory', 'executionID=' + execution.id + '&storyID=' + story.id, '', 'false'), attrs: {target: 'hiddenwin'}});
if(priv.canDeleteStory) items.push({label: storyLang.delete, icon: 'trash', onClick: function(){deleteCard('story', story.id, story.$lane.region)}});
@@ -1450,8 +1450,8 @@ function initKanban($kanban)
data: groupBy == 'default' ? region.groups : kanbanData[groupBy],
maxColHeight: 'auto',
calcColHeight: calcColHeight,
minColWidth: 240,
maxColWidth: 240,
minColWidth: typeof window.minColWidth === 'number' ? window.minColWidth : defaultMinColWidth,
maxColWidth: typeof window.maxColWidth === 'number' ? window.maxColWidth : defaultMaxColWidth,
cardHeight: getCardHeight(),
fluidBoardWidth: fluidBoard,
displayCards: typeof window.displayCards === 'number' ? window.displayCards : 2,
@@ -1474,6 +1474,13 @@ function initKanban($kanban)
{
$.zui.ContextMenu.hide();
});
var kanbanMinColWidth = typeof window.minColWidth === 'number' ? window.minColWidth : defaultMinColWidth;
if(kanbanMinColWidth < 190)
{
var miniColWidth = kanbanMinColWidth * 0.2;
$('.kanban-header-col>.title>span:not(.text)').hide();
$('.kanban-header-col>.title > span.text').css('max-width', miniColWidth + 'px');
}
}
/**
+1
View File
@@ -2,4 +2,5 @@ $(function()
{
var heightType = $("[name='heightType']:checked").val();
setCardCount(heightType);
handleKanbanWidthAttr();
});
+1 -1
View File
@@ -13,7 +13,7 @@ $(function()
adjustTableFooter();
$('body').on('click', '#toggleFold', adjustTableFooter);
$('body').on('click', '.icon.icon-angle-double-right', adjustTableFooter);
$('body').on('click', '.icon.icon-angle-right', adjustTableFooter);
/* The display of the adjusting sidebarHeader is synchronized with the sidebar. */
$(".sidebar-toggle").click(function()
+9 -2
View File
@@ -1232,8 +1232,8 @@ $(function()
var commonOptions =
{
maxColHeight: 'auto',
minColWidth: 240,
maxColWidth: 240,
minColWidth: typeof window.minColWidth === 'number' ? window.minColWidth : defaultMinColWidth,
maxColWidth: typeof window.maxColWidth === 'number' ? window.maxColWidth : defaultMaxColWidth,
cardHeight: getCardHeight(),
showCount: true,
showZeroCount: true,
@@ -1373,6 +1373,13 @@ $(function()
});
}, 10000);
resetKanbanHeight();
var kanbanMinColWidth = typeof window.minColWidth === 'number' ? window.minColWidth : defaultMinColWidth;
if(kanbanMinColWidth < 190)
{
var miniColWidth = kanbanMinColWidth * 0.2;
$('.kanban-header-col>.title>span:not(.text)').hide();
$('.kanban-header-col>.title > span.text').css('max-width', miniColWidth + 'px');
}
});
$('#type').change(function()
+7 -3
View File
@@ -54,6 +54,7 @@ $lang->execution->end = 'Ende';
$lang->execution->dateRange = 'Dauer';
$lang->execution->realBeganAB = 'Actual Begin';
$lang->execution->realEndAB = 'Actual End';
$lang->execution->teamCount = 'Anzahl der Personen';
$lang->execution->realBegan = 'Tatsächlicher Start';
$lang->execution->realEnd = 'Tatsächliches Ende';
$lang->execution->to = 'An';
@@ -341,6 +342,9 @@ $lang->execution->stats = '<strong>%s</strong> Verfügbar, <stron
$lang->execution->taskSummary = "Aufgaben auf dieser Seite: <strong>%s</strong> Total, <strong>%s</strong> Wartend, <strong>%s</strong> In Arbeit; &nbsp;&nbsp;&nbsp; Stunden : <strong>%s</strong> geplant., <strong>%s</strong> genutzt, <strong>%s</strong> Rest.";
$lang->execution->pageSummary = "Aufgaben auf dieser Seite: <strong>%total%</strong>, <strong>%wait%</strong> Wartend, <strong>%doing%</strong> In Arbeit; Stunden: <strong>%estimate%</strong> geplant, <strong>%consumed%</strong> genutzt, <strong>%left%</strong> Rest.";
$lang->execution->checkedSummary = " <strong>%total%</strong> Geprüft, <strong>%wait%</strong> Wartend, <strong>%doing%</strong> In Arbeit; Stunden: <strong>%estimate%</strong> geplant, <strong>%consumed%</strong> genutzt, <strong>%left%</strong> Rest.";
$lang->execution->executionSummary = "Total executions: <strong>%s</strong>.";
$lang->execution->pageExecSummary = "Total executions: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>.";
$lang->execution->checkedExecSummary = "Selected: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>.";
$lang->execution->memberHoursAB = "%s hat <strong>%s</strong> Stunden";
$lang->execution->memberHours = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">%s Arbeitsstunden</div><div class="segment-value">%s</div></div></div></div>';
$lang->execution->countSummary = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">Aufgaben</div><div class="segment-value">%s</div></div><div class="segment"><div class="segment-title">In Arbeit</div><div class="segment-value"><span class="label label-dot label-primary"></span> %s</div></div><div class="segment"><div class="segment-title">Wait</div><div class="segment-value"><span class="label label-dot label-primary muted"></span> %s</div></div></div></div>';
@@ -415,7 +419,7 @@ $lang->execution->storyDragError = "The {$lang->SRCommon} is not ac
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
$lang->execution->checkedExecutions = 'Seleted %s items';
$lang->execution->checkedExecutions = "Seleted %s {$lang->executionCommon}.";
/* Statistics. */
$lang->execution->charts = new stdclass();
@@ -467,7 +471,7 @@ $lang->execution->kanban = "Kanban";
$lang->execution->kanbanSetting = "Kanban Einstellung";
$lang->execution->setKanban = "Kanban Einstellung";
$lang->execution->resetKanban = "Einstellungen zurücksetzen";
$lang->execution->printKanban = "Kanban drucken";
$lang->execution->printKanban = "drucken Kanban";
$lang->execution->fullScreen = "Full Screen";
$lang->execution->bugList = "Bugs";
@@ -487,7 +491,7 @@ $lang->kanbanSetting->optionList['0'] = 'Verstecken';
$lang->kanbanSetting->optionList['1'] = 'Anzeigen';
$lang->printKanban = new stdclass();
$lang->printKanban->common = 'Kanban drucken';
$lang->printKanban->common = 'drucken Kanban';
$lang->printKanban->content = 'Inhanlt';
$lang->printKanban->print = 'Drucken';
+6 -2
View File
@@ -54,6 +54,7 @@ $lang->execution->end = 'Planned End';
$lang->execution->dateRange = 'Plan Duration';
$lang->execution->realBeganAB = 'Actual Begin';
$lang->execution->realEndAB = 'Actual End';
$lang->execution->teamCount = 'number of people';
$lang->execution->realBegan = 'Actual Begin';
$lang->execution->realEnd = 'Actual End';
$lang->execution->to = 'To';
@@ -341,6 +342,9 @@ $lang->execution->stats = 'Available: <strong>%s</strong>(h). Est
$lang->execution->taskSummary = "Total tasks on this page:<strong>%s</strong>. Waiting: <strong>%s</strong>. Doing: <strong>%s</strong>. &nbsp;&nbsp;&nbsp; Estimates: <strong>%s</strong>(h). Cost: <strong>%s</strong>(h). Left: <strong>%s</strong>(h).";
$lang->execution->pageSummary = "Total tasks: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>. Estimates: <strong>%estimate%</strong>(h). Cost: <strong>%consumed%</strong>(h). Left: <strong>%left%</strong>(h).";
$lang->execution->checkedSummary = "Selected: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>. Estimates: <strong>%estimate%</strong>(h). Cost: <strong>%consumed%</strong>(h). Left: <strong>%left%</strong>(h).";
$lang->execution->executionSummary = "Total {$lang->executionCommon}: <strong>%s</strong>.";
$lang->execution->pageExecSummary = "Total {$lang->executionCommon}: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>.";
$lang->execution->checkedExecSummary = "Selected: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>.";
$lang->execution->memberHoursAB = "%s has <strong>%s</ strong> hours.";
$lang->execution->memberHours = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">%s Available Hours</div><div class="segment-value">%s</div></div></div></div>';
$lang->execution->countSummary = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">Tasks</div><div class="segment-value">%s</div></div><div class="segment"><div class="segment-title">Doing</div><div class="segment-value"><span class="label label-dot label-primary"></span> %s</div></div><div class="segment"><div class="segment-title">Waiting</div><div class="segment-value"><span class="label label-dot label-primary muted"></span> %s</div></div></div></div>';
@@ -415,7 +419,7 @@ $lang->execution->storyDragError = "The {$lang->SRCommon} is not ac
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
$lang->execution->checkedExecutions = 'Seleted %s items';
$lang->execution->checkedExecutions = "Seleted %s {$lang->executionCommon}.";
/* Statistics. */
$lang->execution->charts = new stdclass();
@@ -467,7 +471,7 @@ $lang->execution->kanban = "Kanban";
$lang->execution->kanbanSetting = "Settings";
$lang->execution->setKanban = "Set Kanban";
$lang->execution->resetKanban = "Reset";
$lang->execution->printKanban = "Print";
$lang->execution->printKanban = "Print Kanban";
$lang->execution->fullScreen = "Full Screen";
$lang->execution->bugList = "Bugs";
+6 -2
View File
@@ -54,6 +54,7 @@ $lang->execution->end = 'Fin';
$lang->execution->dateRange = 'Durée';
$lang->execution->realBeganAB = 'Actual Begin';
$lang->execution->realEndAB = 'Actual End';
$lang->execution->teamCount = 'nombre de personnes';
$lang->execution->realBegan = 'Début effectif';
$lang->execution->realEnd = 'Clôture effective';
$lang->execution->to = 'à';
@@ -341,6 +342,9 @@ $lang->execution->stats = 'Disponible: <strong>%s</strong>(h). Es
$lang->execution->taskSummary = "Total des tâches de cette page :<strong>%s</strong>. A Faire: <strong>%s</strong>. En cours: <strong>%s</strong>. &nbsp;&nbsp;&nbsp; Estimé: <strong>%s</strong>(h). Coût: <strong>%s</strong>(h). Reste: <strong>%s</strong>(h).";
$lang->execution->pageSummary = "Total des tâches de cette page: <strong>%total%</strong>. A Faire: <strong>%wait%</strong>. En cours: <strong>%doing%</strong>. &nbsp;&nbsp;&nbsp; Estimé: <strong>%estimate%</strong>(h). Coût: <strong>%consumed%</strong>(h). Reste: <strong>%left%</strong>(h).";
$lang->execution->checkedSummary = "Sélectionné: <strong>%total%</strong>. A Faire: <strong>%wait%</strong>. En cours: <strong>%doing%</strong>. &nbsp;&nbsp;&nbsp; Estimé: <strong>%estimate%</strong>(h). Coût: <strong>%consumed%</strong>(h). Reste: <strong>%left%</strong>(h).";
$lang->execution->executionSummary = "Total executions: <strong>%s</strong>.";
$lang->execution->pageExecSummary = "Total executions: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>.";
$lang->execution->checkedExecSummary = "Selected: <strong>%total%</strong>. Waiting: <strong>%wait%</strong>. Doing: <strong>%doing%</strong>.";
$lang->execution->memberHoursAB = "%s a <strong>%s</ strong> heures.";
$lang->execution->memberHours = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">%s Heures Disponibles</div><div class="segment-value">%s</div></div></div></div>';
$lang->execution->countSummary = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">Tâches</div><div class="segment-value">%s</div></div><div class="segment"><div class="segment-title">En Cours</div><div class="segment-value"><span class="label label-dot label-primary"></span> %s</div></div><div class="segment"><div class="segment-title">A Faire</div><div class="segment-value"><span class="label label-dot label-primary muted"></span> %s</div></div></div></div>';
@@ -415,7 +419,7 @@ $lang->execution->storyDragError = "The {$lang->SRCommon} is not ac
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
$lang->execution->week = 'week';
$lang->execution->checkedExecutions = "Pour s électionner l'élément%s";
$lang->execution->checkedExecutions = "Pour s électionner l'élément%s.";
/* Statistics. */
$lang->execution->charts = new stdclass();
@@ -467,7 +471,7 @@ $lang->execution->kanban = "Kanban";
$lang->execution->kanbanSetting = "Paramétrage";
$lang->execution->setKanban = "Paramétrage";
$lang->execution->resetKanban = "Réinitialiser";
$lang->execution->printKanban = "Impression";
$lang->execution->printKanban = "Imprimer Kanban";
$lang->execution->fullScreen = "Full Screen";
$lang->execution->bugList = "Bugs";
+1
View File
@@ -54,6 +54,7 @@ $lang->execution->RD = 'Quản lý phát hành';
$lang->execution->release = 'Phát hành';
$lang->execution->acl = 'Quyền truy cập';
$lang->execution->teamname = 'Tên đội nhóm';
$lang->execution->teamCount = 'số người';
$lang->execution->order = "Đánh giá {$lang->executionCommon}";
$lang->execution->orderAB = "Đánh giá";
$lang->execution->products = "Liên kết {$lang->productCommon}";
+13 -9
View File
@@ -54,6 +54,7 @@ $lang->execution->end = '计划完成';
$lang->execution->dateRange = '计划起止日期';
$lang->execution->realBeganAB = '实际开始';
$lang->execution->realEndAB = '实际完成';
$lang->execution->teamCount = '人数';
$lang->execution->realBegan = '实际开始日期';
$lang->execution->realEnd = '实际完成日期';
$lang->execution->to = '至';
@@ -317,12 +318,12 @@ $lang->execution->groups['finishedBy'] = '完成者分组';
$lang->execution->groups['closedBy'] = '关闭者分组';
$lang->execution->groups['type'] = '类型分组';
$lang->execution->groupFilter['story']['all'] = '所有';
$lang->execution->groupFilter['story']['all'] = '全部';
$lang->execution->groupFilter['story']['linked'] = "已关联{$lang->SRCommon}的任务";
$lang->execution->groupFilter['pri']['all'] = '所有';
$lang->execution->groupFilter['pri']['all'] = '全部';
$lang->execution->groupFilter['pri']['noset'] = '未设置';
$lang->execution->groupFilter['assignedTo']['undone'] = '未完成';
$lang->execution->groupFilter['assignedTo']['all'] = '所有';
$lang->execution->groupFilter['assignedTo']['all'] = '全部';
$lang->execution->byQuery = '搜索';
@@ -341,6 +342,9 @@ $lang->execution->stats = '可用工时 <strong>%s</strong> 工
$lang->execution->taskSummary = "本页共 <strong>%s</strong> 个任务,未开始 <strong>%s</strong>,进行中 <strong>%s</strong>,总预计 <strong>%s</strong> 工时,已消耗 <strong>%s</strong> 工时,剩余 <strong>%s</strong> 工时。";
$lang->execution->pageSummary = "本页共 <strong>%total%</strong> 个任务,未开始 <strong>%wait%</strong>,进行中 <strong>%doing%</strong>,总预计 <strong>%estimate%</strong> 工时,已消耗 <strong>%consumed%</strong> 工时,剩余 <strong>%left%</strong> 工时。";
$lang->execution->checkedSummary = "选中 <strong>%total%</strong> 个任务,未开始 <strong>%wait%</strong>,进行中 <strong>%doing%</strong>,总预计 <strong>%estimate%</strong> 工时,已消耗 <strong>%consumed%</strong> 工时,剩余 <strong>%left%</strong> 工时。";
$lang->execution->executionSummary = "本页共 <strong>%s</strong> 个{$lang->executionCommon}。";
$lang->execution->pageExecSummary = "本页共 <strong>%total%</strong> 个{$lang->executionCommon},未开始 <strong>%wait%</strong>,进行中 <strong>%doing%</strong>。";
$lang->execution->checkedExecSummary = "选中 <strong>%total%</strong> 个{$lang->executionCommon},未开始 <strong>%wait%</strong>,进行中 <strong>%doing%</strong>。";
$lang->execution->memberHoursAB = "<div>%s有 <strong>%s</strong> 工时</div>";
$lang->execution->memberHours = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">%s可用工时</div><div class="segment-value">%s</div></div></div></div>';
$lang->execution->countSummary = '<div class="table-col"><div class="clearfix segments"><div class="segment"><div class="segment-title">总任务</div><div class="segment-value">%s</div></div><div class="segment"><div class="segment-title">进行中</div><div class="segment-value"><span class="label label-dot label-primary"></span> %s</div></div><div class="segment"><div class="segment-title">未开始</div><div class="segment-value"><span class="label label-dot label-primary muted"></span> %s</div></div></div></div>';
@@ -415,7 +419,7 @@ $lang->execution->storyDragError = "该{$lang->SRCommon}不是激
$lang->execution->countTip = '(%s人)';
$lang->execution->pleaseInput = "请输入";
$lang->execution->week = '周';
$lang->execution->checkedExecutions = '已选择%s项';
$lang->execution->checkedExecutions = "共选中%s个{$lang->executionCommon}。";
/* 统计。*/
$lang->execution->charts = new stdclass();
@@ -487,7 +491,7 @@ $lang->kanbanSetting->optionList['0'] = '隐藏';
$lang->kanbanSetting->optionList['1'] = '显示';
$lang->printKanban = new stdclass();
$lang->printKanban->common = '看板打印';
$lang->printKanban->common = '打印看板';
$lang->printKanban->content = '内容';
$lang->printKanban->print = '打印';
@@ -501,7 +505,7 @@ $lang->execution->typeList['stage'] = '阶段';
$lang->execution->typeList['sprint'] = $lang->executionCommon;
$lang->execution->typeList['kanban'] = '看板';
$lang->execution->featureBar['task']['all'] = $lang->execution->allTasks;
$lang->execution->featureBar['task']['all'] = '全部';
$lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed;
$lang->execution->featureBar['task']['assignedtome'] = $lang->execution->assignedToMe;
$lang->execution->featureBar['task']['myinvolved'] = $lang->execution->myInvolved;
@@ -509,17 +513,17 @@ $lang->execution->featureBar['task']['assignedbyme'] = $lang->execution->assigne
$lang->execution->featureBar['task']['needconfirm'] = "{$lang->SRCommon}变更";
$lang->execution->featureBar['task']['status'] = $lang->execution->statusSelects[''];
$lang->execution->featureBar['all']['all'] = $lang->execution->all;
$lang->execution->featureBar['all']['all'] = '全部';
$lang->execution->featureBar['all']['undone'] = $lang->execution->undone;
$lang->execution->featureBar['all']['wait'] = $lang->execution->statusList['wait'];
$lang->execution->featureBar['all']['doing'] = $lang->execution->statusList['doing'];
$lang->execution->featureBar['all']['suspended'] = $lang->execution->statusList['suspended'];
$lang->execution->featureBar['all']['closed'] = $lang->execution->statusList['closed'];
$lang->execution->featureBar['bug']['all'] = '所有';
$lang->execution->featureBar['bug']['all'] = '全部';
$lang->execution->featureBar['bug']['unresolved'] = '未解决';
$lang->execution->featureBar['build']['all'] = '所有版本';
$lang->execution->featureBar['build']['all'] = '全部版本';
$lang->execution->myExecutions = '我参与的';
$lang->execution->doingProject = '进行中的项目';
+2 -1
View File
@@ -54,6 +54,7 @@ $lang->execution->execPM = "{$lang->execution->common}負責人";
$lang->execution->QD = '測試負責人';
$lang->execution->RD = '發佈負責人';
$lang->execution->release = '發佈';
$lang->execution->teamCount = '人數';
$lang->execution->acl = '訪問控制';
$lang->execution->teamname = '團隊名稱';
$lang->execution->updateOrder = '排序';
@@ -410,7 +411,7 @@ $lang->kanbanSetting->optionList['0'] = '隱藏';
$lang->kanbanSetting->optionList['1'] = '顯示';
$lang->printKanban = new stdclass();
$lang->printKanban->common = '看板打印';
$lang->printKanban->common = '打印看板';
$lang->printKanban->content = '內容';
$lang->printKanban->print = '打印';

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