* Merged 18.x

This commit is contained in:
zenggang
2023-08-28 09:30:26 +00:00
207 changed files with 4262 additions and 680 deletions
Vendored
+261 -26
View File
@@ -18,6 +18,8 @@ pipeline {
SRC_ZDOOEXT_PATH = "${WORKSPACE}/zdooext"
SRC_ZENTAOEXT_PATH = "${WORKSPACE}/zentaoext"
MIRROR = "true"
}
stages {
@@ -106,6 +108,10 @@ pipeline {
stages {
stage("make ciCommon") {
steps {
container('xuanimbot') {
sh 'git config --global --add safe.directory $(pwd)'
sh '/usr/local/bin/xuanimbot --groups 84be4c6e-02e3-4fdc-b081-318c0c1eca02 --groups 31a0008b-6e3e-4b7f-9b7b-396a46b1f8f4 --title "Start build zentaopms" --url "${BUILD_URL}" --content "Build by Tag ${TAG_NAME}" --debug --custom'
}
withCredentials([gitUsernamePassword(credentialsId: 'git-zcorp-cc-jenkins-bot-http',gitToolName: 'git-tool')]) {
container('package') {
sh 'mkdir ${ZENTAO_RELEASE_PATH} && chown 1000:1000 ${ZENTAO_RELEASE_PATH}'
@@ -181,6 +187,7 @@ pipeline {
stages {
stage("Merge and Upload") {
matrix {
agent {
kubernetes {
@@ -190,10 +197,11 @@ pipeline {
command "sleep"
args "99d"
}
inheritFrom "publish-qiniu"
}
}
options { skipDefaultCheckout() }
options {
skipDefaultCheckout()
}
axes {
axis {
@@ -219,11 +227,15 @@ pipeline {
}
stages {
stage("frame") {
stage("ZIP") {
environment {
ARTIFACT_NAME = """${sh(
returnStdout: true,
script: 'test ${ZLANG} = cn && echo -n zentaopms || echo -n zentaoalm'
script: 'test ${ZLANG} = cn && echo -n ZenTaoPMS || echo -n ZenTaoALM'
).trim()}"""
INT_FLAG = """${sh(
returnStdout: true,
script: 'test ${ZLANG} = cn && echo -n "int." || echo -n ""'
).trim()}"""
}
@@ -296,11 +308,11 @@ pipeline {
)
sh 'mkdir ${OUTPUT_PKG_PATH}/${PMS_VERSION} ${OUTPUT_PKG_PATH}/${BIZ_VERSION} ${OUTPUT_PKG_PATH}/${MAX_VERSION}'
sh 'cp ${ZENTAO_RELEASE_PATH}/base.zip ${OUTPUT_PKG_PATH}/${PMS_VERSION}/${ARTIFACT_NAME}-${PMS_VERSION}-${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/biz.zip ${OUTPUT_PKG_PATH}/${BIZ_VERSION}/${ARTIFACT_NAME}-${BIZ_VERSION}-${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/biz.update.zip ${OUTPUT_PKG_PATH}/${BIZ_VERSION}/${ARTIFACT_NAME}.update-${BIZ_VERSION}-${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/max.zip ${OUTPUT_PKG_PATH}/${MAX_VERSION}/${ARTIFACT_NAME}-${MAX_VERSION}-${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/max.update.zip ${OUTPUT_PKG_PATH}/${MAX_VERSION}/${ARTIFACT_NAME}.update-${MAX_VERSION}-${PHPVERSION}.zip'
sh 'cp ${ZENTAO_RELEASE_PATH}/base.zip ${OUTPUT_PKG_PATH}/${PMS_VERSION}/${ARTIFACT_NAME}.${PMS_VERSION}.${INT_FLAG}${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/biz.zip ${OUTPUT_PKG_PATH}/${BIZ_VERSION}/${ARTIFACT_NAME}.${BIZ_VERSION}.${INT_FLAG}${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/biz.update.zip ${OUTPUT_PKG_PATH}/${BIZ_VERSION}/${ARTIFACT_NAME}.${BIZ_VERSION}.${INT_FLAG}update.${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/max.zip ${OUTPUT_PKG_PATH}/${MAX_VERSION}/${ARTIFACT_NAME}.${MAX_VERSION}.${INT_FLAG}${PHPVERSION}.zip'
sh 'mv ${ZENTAO_RELEASE_PATH}/max.update.zip ${OUTPUT_PKG_PATH}/${MAX_VERSION}/${ARTIFACT_NAME}.${MAX_VERSION}.${INT_FLAG}update.${PHPVERSION}.zip'
}
} // End upload zip
@@ -324,8 +336,8 @@ pipeline {
}
steps {
sh 'mv ${ZENTAO_RELEASE_PATH}/zentao.rpm ${OUTPUT_PKG_PATH}/${PMS_VERSION}/${ARTIFACT_NAME}-${PMS_VERSION}-${PHPVERSION}-1.noarch.rpm'
sh 'mv ${ZENTAO_RELEASE_PATH}/zentao.deb ${OUTPUT_PKG_PATH}/${PMS_VERSION}/${ARTIFACT_NAME}-${PMS_VERSION}-${PHPVERSION}.1.all.deb'
sh 'mv ${ZENTAO_RELEASE_PATH}/zentao.rpm ${OUTPUT_PKG_PATH}/${PMS_VERSION}/${ARTIFACT_NAME}.${PMS_VERSION}.${PHPVERSION}.1.noarch.rpm'
sh 'mv ${ZENTAO_RELEASE_PATH}/zentao.deb ${OUTPUT_PKG_PATH}/${PMS_VERSION}/${ARTIFACT_NAME}.${PMS_VERSION}.${PHPVERSION}.1.all.deb'
}
} // End upload syspack cn
@@ -335,7 +347,7 @@ pipeline {
}
environment {
QINIU_BUCKET = "qisytest"
QINIU_BUCKET = "download"
OBJECT_KEY_PREFIX = "zentao/"
QINIU_ACCESS_KEY = credentials('qiniu-upload-ak')
QINIU_SECRET_KEY = credentials('qiniu-upload-sk')
@@ -343,10 +355,10 @@ pipeline {
steps {
sh 'ls -l ${OUTPUT_PKG_PATH}'
container('qiniu') {
sh "qshell account $QINIU_ACCESS_KEY $QINIU_SECRET_KEY uploader"
sh "qshell qupload2 --bucket ${QINIU_BUCKET} --overwrite --src-dir ${OUTPUT_PKG_PATH} --key-prefix ${OBJECT_KEY_PREFIX}"
}
container('jnlp') {
sh 'qshell account $QINIU_ACCESS_KEY $QINIU_SECRET_KEY uploader'
sh 'qshell qupload2 --bucket $QINIU_BUCKET --overwrite --src-dir $OUTPUT_PKG_PATH --key-prefix $OBJECT_KEY_PREFIX'
}
}
}
@@ -357,22 +369,245 @@ pipeline {
} // End matrix
} // End Merge and Upload Max
stage("Notice ZIP") {
steps {
container('xuanimbot') {
sh 'env | grep GIT'
sh 'git config --global --add safe.directory $(pwd)'
sh './misc/gen_build_report.sh > /tmp/success.md'
sh '/usr/local/bin/xuanimbot --groups 84be4c6e-02e3-4fdc-b081-318c0c1eca02 --groups 31a0008b-6e3e-4b7f-9b7b-396a46b1f8f4 --title "zentaopms package success" --url "${RUN_DISPLAY_URL}" --content-file /tmp/success.md --debug --custom'
}
}
}
stage("Docker Image") {
agent {
kubernetes {
inheritFrom "dind xuanim"
}
}
stages() {
stage("prepare") {
steps {
checkout scmGit(branches: [[name: "master"]],
extensions: [cloneOption(depth: 2, noTags: false, reference: '', shallow: true)],
userRemoteConfigs: [[credentialsId: 'git-zcorp-cc-jenkins-bot-http', url: 'https://git.zcorp.cc/app/zentao.git']]
)
container('docker') {
sh "sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories"
sh "apk --no-cache add make bash jq git"
sh "docker run --privileged --rm tonistiigi/binfmt --install all"
sh "docker buildx create --name mybuilder --driver docker-container --bootstrap"
sh "docker buildx use mybuilder"
sh "make markdown-init"
}
}
}
stage("docker pms") {
environment {
ZENTAO_URL = """${sh(
returnStdout: true,
script: "echo ${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/repository/${ARTIFACT_REPOSITORY}/zentao/pmsPack/`echo ${GIT_TAG_BUILD_GROUP} | tr . /`/ZenTaoPMS"
).trim()}"""
}
steps {
container('docker') {
sh 'env | grep ZENTAO'
sh 'make build'
}
}
}
stage("docker biz") {
environment {
ZENTAO_URL = """${sh(
returnStdout: true,
script: "echo ${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/repository/${ARTIFACT_REPOSITORY}/zentao/bizPack/`echo ${GIT_TAG_BUILD_GROUP} | tr . /`/ZenTaoPMS"
).trim()}"""
}
steps {
container('docker') {
sh 'make build-biz'
sh 'make build-biz-k8s'
}
}
}
stage("docker max") {
environment {
ZENTAO_URL = """${sh(
returnStdout: true,
script: "echo ${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/repository/${ARTIFACT_REPOSITORY}/zentao/maxPack/`echo ${GIT_TAG_BUILD_GROUP} | tr . /`/ZenTaoPMS"
).trim()}"""
}
steps {
container('docker') {
sh 'make build-max'
sh 'make build-max-k8s'
}
}
}
stage("Image Notice") {
steps {
container('docker') {
sh 'make markdown-render > ./report.md'
}
container('xuanimbot') {
sh 'git config --global --add safe.directory $(pwd)'
sh '/usr/local/bin/xuanimbot --groups 84be4c6e-02e3-4fdc-b081-318c0c1eca02 --groups 31a0008b-6e3e-4b7f-9b7b-396a46b1f8f4 --title "zentaopms build image success" --url "${RUN_DISPLAY_URL}" --content-file ./report.md --debug --custom'
}
}
}
}
} // End Docker Image
stage("Zbox") {
agent {
kubernetes {
containerTemplate {
name "docker"
image "docker:23.0.6-dind-alpine3.17"
command "sleep"
args "99d"
}
inheritFrom "dind xuanim"
}
}
stages() {
stage("Prepare") {
steps {
checkout scmGit(branches: [[name: "main"]],
extensions: [cloneOption(depth: 2, noTags: false, reference: '', shallow: true)],
userRemoteConfigs: [[credentialsId: 'git-zcorp-cc-jenkins-bot-http', url: 'https://git.zcorp.cc/devops/zbox-builder.git']]
)
container('docker') {
sh "sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories"
sh "apk --no-cache add make bash jq git curl wget libarchive-tools p7zip mariadb-client"
sh "docker run --privileged --rm tonistiigi/binfmt --install all"
sh "docker buildx create --name mybuilder --driver docker-container --bootstrap"
sh "docker buildx use mybuilder"
sh 'curl https://pkg.qucheng.com/files/stacksmith/render-template-1.0.1-10-debian-11-amd64.tar.gz | tar zxf - -C /'
}
}
}
stage("Build Zbox") {
environment {
// printf "$PKG_URL_FORMATTER" pmsPack ZenTaoPMS 18.5 ZenTaoPMS-18.5-php8.1.zip
PKG_URL_FORMATTER = """${sh(
returnStdout: true,
script: "echo ${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/repository/${ARTIFACT_REPOSITORY}/zentao/%s/`echo ${GIT_TAG_BUILD_GROUP} | tr . /`/%s/%s/%s"
).trim()}"""
}
steps {
container('docker') {
sh 'bash build-zbox.sh zh-cn linux $PMS_VERSION $BIZ_VERSION $MAX_VERSION ipd1.0'
sh 'bash build-zbox.sh en linux $PMS_VERSION $BIZ_VERSION $MAX_VERSION ipd1.0'
sh 'ls -l release'
}
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.pmsPack' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.PMS_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
artifacts: [
[artifactId: 'ZenTaoPMS',
classifier: 'zbox_64',
file: './release/zh-cn/' + PMS_VERSION + '/ZenTaoPMS.' + PMS_VERSION + '.zbox_64.tar.gz',
type: 'tar.gz'],
[artifactId: 'ZenTaoALM',
classifier: 'zbox_64',
file: './release/en/' + PMS_VERSION + '/ZenTaoALM.' + PMS_VERSION + '.int.zbox_64.tar.gz',
type: 'tar.gz']
]
)
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.bizPack' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.BIZ_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
artifacts: [
[artifactId: 'ZenTaoPMS',
classifier: 'zbox_64',
file: './release/zh-cn/' + BIZ_VERSION + '/ZenTaoPMS.' + BIZ_VERSION + '.zbox_64.tar.gz',
type: 'tar.gz'],
[artifactId: 'ZenTaoALM',
classifier: 'zbox_64',
file: './release/en/' + BIZ_VERSION + '/ZenTaoALM.' + BIZ_VERSION + '.int.zbox_64.tar.gz',
type: 'tar.gz']
]
)
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.maxPack' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.MAX_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
artifacts: [
[artifactId: 'ZenTaoPMS',
classifier: 'zbox_64',
file: './release/zh-cn/' + MAX_VERSION + '/ZenTaoPMS.' + MAX_VERSION + '.zbox_64.tar.gz',
type: 'tar.gz'],
[artifactId: 'ZenTaoALM',
classifier: 'zbox_64',
file: './release/en/' + MAX_VERSION + '/ZenTaoALM.' + MAX_VERSION + '.int.zbox_64.tar.gz',
type: 'tar.gz']
]
)
sh 'script/lib/gen_report.sh > zbox-success.md'
container('xuanimbot') {
sh 'git config --global --add safe.directory $(pwd)'
sh '/usr/local/bin/xuanimbot --groups 84be4c6e-02e3-4fdc-b081-318c0c1eca02 --groups 31a0008b-6e3e-4b7f-9b7b-396a46b1f8f4 --title "zentaopms build zbox success" --url "${RUN_DISPLAY_URL}" --content-file zbox-success.md --debug --custom'
}
}
}
stage("Upload Zbox to Qiniu") {
when {
environment name: 'GIT_TAG_BUILD_TYPE', value: 'release'
}
environment {
QINIU_BUCKET = "download"
OBJECT_KEY_PREFIX = "zentao/"
QINIU_ACCESS_KEY = credentials('qiniu-upload-ak')
QINIU_SECRET_KEY = credentials('qiniu-upload-sk')
}
steps {
container('jnlp') {
sh 'qshell account $QINIU_ACCESS_KEY $QINIU_SECRET_KEY uploader'
sh 'qshell qupload2 --bucket $QINIU_BUCKET --overwrite --src-dir ./release/zh-cn --key-prefix $OBJECT_KEY_PREFIX'
sh 'qshell qupload2 --bucket $QINIU_BUCKET --overwrite --src-dir ./release/en --key-prefix $OBJECT_KEY_PREFIX'
}
}
} // End Upload Zbox to Qiniu
}
} // End Zbox
}
post {
success {
container('xuanimbot') {
sh 'env | grep GIT'
sh 'git config --global --add safe.directory $(pwd)'
sh './misc/gen_build_report.sh > /tmp/success.md'
sh '/usr/local/bin/xuanimbot --users "qishiyao" --title "zentaopms build success" --url "${RUN_DISPLAY_URL}" --content-file /tmp/success.md --debug --custom'
sh '/usr/local/bin/xuanimbot --groups "84be4c6e-02e3-4fdc-b081-318c0c1eca02" --title "zentaopms build success" --url "${RUN_DISPLAY_URL}" --content-file /tmp/success.md --debug --custom'
}
}
failure {
container('xuanimbot') {
sh 'git config --global --add safe.directory $(pwd)'
sh '/usr/local/bin/xuanimbot --users qishiyao --users ${GIT_TAGGER_NAME} --title "zentaopms build failed" --url "${BUILD_URL}" --content "" --debug --custom'
sh '/usr/local/bin/xuanimbot --users "${GIT_TAGGER_NAME}" --groups 31a0008b-6e3e-4b7f-9b7b-396a46b1f8f4 --title "zentaopms build failed" --url "${BUILD_URL}" --content "" --debug --custom'
}
}
}
+3 -3
View File
@@ -298,7 +298,7 @@ class userEntry extends entry
$info->issue = array('total' => 0, 'issues' => array());
if(!common::hasPriv('my', 'work')) break;
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
global $app;
$app->rawMethod = 'work';
@@ -318,7 +318,7 @@ class userEntry extends entry
$info->risk = array('total' => 0, 'risks' => array());
if(!common::hasPriv('my', 'work')) break;
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
global $app;
$app->rawMethod = 'work';
@@ -338,7 +338,7 @@ class userEntry extends entry
$info->meeting = array('total' => 0, 'meetings' => array());
if(!common::hasPriv('my', 'work')) break;
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
global $app;
$app->rawMethod = 'work';
+3 -1
View File
@@ -34,7 +34,7 @@ $config->methodVar = 'f'; // 请求类型为GET:模块
$config->viewVar = 't'; // 请求类型为GET:视图变量名。 requestType=GET: the view var name.
$config->sessionVar = 'zentaosid'; // 请求类型为GET:session变量名。 requestType=GET: the session var name.
$config->views = ',html,json,mhtml,xhtml,'; // 支持的视图类型。 Supported view formats.
$config->visions = ',rnd,lite,'; // 支持的界面类型。 Supported vision formats.
$config->visions = ',or,rnd,lite,'; // 支持的界面类型。 Supported vision formats.
/* 支持的主题和语言。Supported thems and languages. */
$config->themes['default'] = 'default';
@@ -222,9 +222,11 @@ if($config->edition != 'open')
{
$config->version = $config->edition . $config->{$config->edition . 'Version'};
if($config->edition != 'max') unset($config->maxVersion);
if($config->edition != 'ipd') unset($config->ipdVersion);
}
else
{
unset($config->bizVersion);
unset($config->maxVersion);
unset($config->ipdVersion);
}
+1
View File
@@ -303,6 +303,7 @@ $filter->project->task->cookie['windowWidth'] = 'int';
$filter->project->export->cookie['checkedItem'] = 'reg::checked';
$filter->project->execution->cookie['pagerExecutionAll'] = 'int';
$filter->project->execution->cookie['showTask'] = 'code';
$filter->project->execution->cookie['showStage'] = 'code';
$filter->project->testcase->cookie['showAutoCase'] = 'int';
$filter->project->testcase->cookie['onlyScene'] = 'code';
+1
View File
@@ -469,6 +469,7 @@ $config->programPriv->scrum = array('story', 'requirement', 'productplan
$config->programPriv->waterfall = array_merge($config->programPriv->scrum, array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'issue', 'risk', 'opportunity', 'measrecord', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport'));
$config->programPriv->agileplus = $config->programPriv->scrum;
$config->programPriv->waterfallplus = $config->programPriv->waterfall;
$config->programPriv->ipd = $config->programPriv->waterfall;
$config->safeFileTimeout = 3600;
$config->waterfallModules = array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'opportunity', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport');
+2
View File
@@ -52,3 +52,5 @@ UPDATE `zt_privlang` SET `value`='删除风险' WHERE `objectID`=197 AND `object
UPDATE `zt_auditcl` SET `deleted` = '0' WHERE `deleted` = '';
UPDATE `zt_workflowdatasource` SET `vision` = 'rnd' WHERE `code` IN ('products','projects','productLines','stories','tasks','bugs','groups','users','branches','builds','modules','plans','productType','productStatus','productAcl','projectType','projectStatus','projectAcl','releaseStatus','storySource','storyPri','storyStatus','storyStage','bugSeverity','bugPri','bugType','bugOs','bugBrowser','bugStatus','taskType','taskPri','taskStatus','testcasePri','testcaseType','testcaseStage','testcaseStatus','testtaskPri','testtaskStatus','feedbackStatus','bugResolution','cases','feedbackModules','storyType','executions','projectModel','feedbackType','feedbackSolution','feedbackclosedReason','taskReason','testsuiteAuth','programs','storyClosedReason');
UPDATE `zt_product` SET `shadow` = 1 WHERE `vision` = 'lite';
+2
View File
@@ -0,0 +1,2 @@
UPDATE `zt_chart` SET `sql` = 'SELECT IF(t3.id IS NOT NULL, t3.`name`, \"空\") AS deptName,count(1) as count, \r\nIF(t3.id IS NOT NULL, t3.`order`, 9999) AS deptOrder \r\nFROM zt_user AS t1 \r\nLEFT JOIN zt_dept AS t2 ON t1.dept = t2.id\r\nLEFT JOIN zt_dept AS t3 ON FIND_IN_SET(TRIM(\',\' FROM t3.path), TRIM(\',\' FROM t2.path)) AND t3.grade = \'1\'\r\nWHERE t1.deleted = \'0\'\r\nGROUP BY deptName, deptOrder \r\nORDER BY deptOrder ASC'
WHERE `id` = 1049;
+260
View File
@@ -0,0 +1,260 @@
CREATE TABLE `zt_demandpool` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`desc` mediumtext NOT NULL,
`status` char(30) NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` date NOT NULL,
`owner` text NOT NULL,
`reviewer` text NOT NULL,
`acl` char(30) NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `zt_demand` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`pool` int(8) NOT NULL,
`module` int(8) NOT NULL,
`product` mediumint(8) NOT NULL,
`parent` mediumint(8) NOT NULL,
`pri` char(30) NOT NULL,
`category` char(30) NOT NULL,
`source` char(30) NOT NULL,
`sourceNote` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`feedbackedBy` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`assignedTo` char(30) NOT NULL,
`assignedDate` datetime NOT NULL,
`reviewedBy` text NOT NULL,
`reviewedDate` datetime NOT NULL,
`status` char(30) NOT NULL,
`duration` char(30) NOT NULL,
`BSA` char(30) NOT NULL,
`story` mediumint(8) NOT NULL,
`roadmap` mediumint(8) NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` datetime NOT NULL,
`mailto` text NOT NULL,
`duplicateDemand` mediumint(8) NOT NULL,
`childDemands` varchar(255) NOT NULL,
`version` varchar(255) NOT NULL,
`vision` varchar(255) NOT NULL DEFAULT 'or',
`color` varchar(255) NOT NULL,
`changedBy` char(30) NOT NULL,
`changedDate` datetime NOT NULL,
`closedBy` char(30) NOT NULL,
`closedDate` datetime NOT NULL,
`closedReason` varchar(30) NOT NULL,
`submitedBy` varchar(30) NOT NULL,
`lastEditedBy` varchar(30) NOT NULL DEFAULT '',
`lastEditedDate` datetime NOT NULL,
`activatedDate` datetime NOT NULL,
`distributedBy` varchar(30) NOT NULL DEFAULT '',
`distributedDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `zt_demandspec` (
`demand` mediumint(9) NOT NULL,
`version` smallint(6) NOT NULL,
`title` varchar(255) NOT NULL,
`spec` mediumtext NOT NULL,
`verify` mediumtext NOT NULL,
`files` text NOT NULL,
UNIQUE KEY `demand` (`demand`,`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `zt_demandreview` (
`demand` mediumint(9) NOT NULL,
`version` smallint(6) NOT NULL,
`reviewer` varchar(30) NOT NULL,
`result` varchar(30) NOT NULL,
`reviewDate` datetime NOT NULL,
UNIQUE KEY `demand` (`demand`,`version`,`reviewer`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `zt_charter` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`level` int(8) NOT NULL,
`category` char(30) NOT NULL,
`market` varchar(30) NOT NULL,
`appliedBy` char(30) NOT NULL,
`appliedDate` datetime NOT NULL,
`budget` char(30) NOT NULL,
`budgetUnit` char(30) NOT NULL,
`product` mediumint(8) NOT NULL,
`roadmap` mediumint(8) NOT NULL,
`spec` mediumtext NOT NULL,
`status` char(30) NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` datetime NOT NULL,
`charterFiles` text NOT NULL,
`reviewedBy` char(30) NOT NULL,
`reviewedResult` char(30) NOT NULL,
`reviewedDate` datetime NOT NULL,
`meetingDate` date NOT NULL,
`meetingLocation` varchar(255) NOT NULL,
`meetingMinutes` mediumtext NOT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('or', 'system', 'demand', '', 'reviewRules', 'allpass');
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('or', 'system', 'demand', '', 'needReview', 1);
ALTER TABLE `zt_story` ADD `BSA` char(30) NOT NULL AFTER `notifyEmail`;
ALTER TABLE `zt_story` ADD `duration` char(30) NOT NULL AFTER `notifyEmail`;
ALTER TABLE `zt_story` ADD `demand` mediumint(8) NOT NULL AFTER `notifyEmail`;
ALTER TABLE `zt_product` ADD `PMT` text COLLATE 'utf8_general_ci' NOT NULL AFTER `reviewer`;
ALTER TABLE `zt_story` ADD `submitedBy` varchar(30) NOT NULL AFTER `changedDate`;
ALTER TABLE `zt_story` ADD `roadmap` VARCHAR(255) NOT NULL DEFAULT '' AFTER `plan`;
ALTER TABLE `zt_charter` ADD `check` enum('0','1') NOT NULL DEFAULT '0';
ALTER TABLE `zt_charter` modify column reviewedBy varchar(255);
CREATE TABLE `zt_roadmap` (
`id` mediumint(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`product` mediumint(8) NOT NULL,
`branch` mediumint(8) NOT NULL,
`name` varchar(255) NOT NULL,
`status` char(30) NOT NULL,
`begin` date NOT NULL,
`end` date NOT NULL,
`desc` longtext NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` date NOT NULL,
`closedBy` char(30) NOT NULL,
`closedDate` datetime NOT NULL,
`closedReason` enum('done','canceled') DEFAULT NULL,
`deleted` enum('0','1') NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `zt_roadmapstory` (
`roadmap` mediumint(8) unsigned NOT NULL,
`story` mediumint(8) unsigned NOT NULL,
`order` MEDIUMINT UNSIGNED NOT NULL,
UNIQUE KEY `roadmap_story` (`roadmap`,`story`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `zt_story` MODIFY `status` enum('','changing','active','draft','closed','reviewing','launched','developing') NOT NULL DEFAULT '' AFTER `estimate`;
ALTER TABLE `zt_project`
ADD `charter` mediumint(8) NOT NULL DEFAULT 0 AFTER `project`,
ADD `category` char(30) COLLATE 'utf8_general_ci' NOT NULL AFTER `type`;
REPLACE INTO `zt_stage` (`name`, `percent`, `type`, `projectType`, `createdBy`, `createdDate`, `editedBy`, `editedDate`, `deleted`) VALUES
('概念', '10', 'concept', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
('计划', '10', 'plan', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
('开发', '50', 'develop', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
('验证', '15', 'qualify', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
('发布', '10', 'launch', 'ipd', 'admin', '2020-02-08 21:08:30', 'admin', '2020-02-12 13:50:27', '0'),
('全生命周期', '5', 'lifecycle', 'ipd', 'admin', '2020-02-08 21:08:45', 'admin', '2020-02-12 13:50:27', '0');
ALTER TABLE `zt_review` ADD `begin` date NULL AFTER `createdDate`;
ALTER TABLE `zt_review` MODIFY `doc` varchar(255);
ALTER TABLE `zt_review` MODIFY `docVersion` varchar(255);
ALTER TABLE `zt_object` ADD `end` date NULL AFTER `designEst`;
ALTER TABLE `zt_charter` ADD `closedBy` char(30) NULL;
ALTER TABLE `zt_charter` ADD `closedDate` datetime NULL;
ALTER TABLE `zt_charter` ADD `closedReason` varchar(255) NULL;
ALTER TABLE `zt_charter` ADD `activatedBy` char(30) NULL;
ALTER TABLE `zt_charter` ADD `activatedDate` datetime NULL;
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'requirement' AND `method` = 'import';
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'requirement' AND `method` = 'exportTemplate';
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('', 'system', 'common', 'global', 'mode', 'PLM');
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('', 'system', 'custom', '', 'URAndSR', '1');
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('', 'system', 'common', '', 'disabledFeatures', '');
REPLACE INTO `zt_config` (`vision`, `owner`, `module`, `section`, `key`, `value`) VALUES ('', 'system', 'common', '', 'closedFeatures', '');
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('demand', 'export', '643', ',ipd,', ',or,', '1', '210');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'de', 'demand-export', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'en', 'demand-export', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'fr', 'demand-export', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'zh-cn', 'demand-export', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2109, 'priv', 'zh-tw', 'demand-export', '', '');
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('demand', 'exportTemplate', '643', ',ipd,', ',or,', '1', '220');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'de', 'demand-exportTemplate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'en', 'demand-exportTemplate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'fr', 'demand-exportTemplate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'zh-cn', 'demand-exportTemplate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2110, 'priv', 'zh-tw', 'demand-exportTemplate', '', '');
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('demand', 'import', '643', ',ipd,', ',or,', '1', '230');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'de', 'demand-import', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'en', 'demand-import', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'fr', 'demand-import', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'zh-cn', 'demand-import', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2111, 'priv', 'zh-tw', 'demand-import', '', '');
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2109, 'depend', 2075);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2109, 'recommend', 2110);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2109, 'recommend', 2111);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2110, 'depend', 2075);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2110, 'recommend', 2109);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'depend', 2075);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'depend', 2110);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'recommend', 2109);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'recommend', 2076);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2111, 'recommend', 2077);
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('requirement', 'batchChangeRoadmap', '32', ',ipd,', ',or,', '1', '125');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'de', 'requirement-batchChangeRoadmap', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'en', 'requirement-batchChangeRoadmap', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'fr', 'requirement-batchChangeRoadmap', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'zh-cn', 'requirement-batchChangeRoadmap', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2112, 'priv', 'zh-tw', 'requirement-batchChangeRoadmap', '', '');
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'depend', 65);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'recommend', 121);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'recommend', 122);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2112, 'recommend', 123);
UPDATE `zt_privlang` SET `value` = '创建维护立项' WHERE `objectID` = 638 and `objectType` = 'manager';
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('charter', 'close', '638', ',ipd,', ',or,', '1', '80');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'de', 'charter-close', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'en', 'charter-close', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'fr', 'charter-close', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'zh-cn', 'charter-close', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2113, 'priv', 'zh-tw', 'charter-close', '', '');
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('charter', 'activate', '638', ',ipd,', ',or,', '1', '90');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'de', 'charter-activate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'en', 'charter-activate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'fr', 'charter-activate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'zh-cn', 'charter-activate', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2114, 'priv', 'zh-tw', 'charter-activate', '', '');
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'depend', 2061);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'depend', 2064);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'recommend', 2062);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'recommend', 2063);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2113, 'recommend', 2114);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'depend', 2061);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'depend', 2064);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'recommend', 2062);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'recommend', 2063);
REPLACE INTO `zt_privrelation` (priv, `type`, relationPriv) VALUES(2114, 'recommend', 2113);
REPLACE INTO `zt_priv` (`module`, `method`, `parent`, `edition`, `vision`, `system`, `order`) VALUES ('requirement', 'relation', '32', ',max,ipd,', ',rnd,', '1', '130');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'de', 'requirement-relation', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'en', 'requirement-relation', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'fr', 'requirement-relation', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'zh-cn', 'requirement-relation', '', '');
REPLACE INTO `zt_privlang` (`objectID`, `objectType`, `lang`, `key`, `value`, `desc`) VALUES (2115, 'priv', 'zh-tw', 'requirement-relation', '', '');
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'export';
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'exportTemplate';
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'import';
UPDATE `zt_priv` SET `vision` = ',rnd,or,' WHERE `module` = 'user' AND `method` = 'importldap';
Executable → Regular
+985 -14
View File
File diff suppressed because one or more lines are too long
+107
View File
@@ -1,3 +1,110 @@
2023-07-27 ipd1.0
完成的需求
42981 实现需求的导入功能
42982 实现导出需求模板功能
42983 实现导出需求数据功能
43034 在需求列表的右上角打印导入导出按钮
43407 实现关闭路标功能
43408 实现删除路标功能
43413 实现在路标用户需求列表的批量操作按钮组中打印路标菜单
43414 实现在路标的用户需求列表中批量移除用户需求功能
43415 实现在路标的用户需求列表中批量编辑用户需求功能
43416 实现在路标的用户需求列表中批量调整所属路标功能
43432 实现激活路标功能
43511 实现将产品用户需求批量关联到路标中
43974 实现关闭立项申请功能
44225 实现激活立项申请功能
44913 甘特图中可以修改评审点的截止日期
44914 阶段列表中可以修改评审点的截止日期
45138 根据关联的产品用户需求判断需求池需求的状态
46700 一级导航中菜单名称与图标上下居中对齐显示
46708 产品中提交需求保存后返回到全部列表
46709 需求池中提交需求保存后返回到全部列表
46710 产品提需求页面中BSA字段增加解释信息
47058 地盘使用帮助中界面切换增加需求与市场管理界面
47289 实现从禅道其他版本升级到IPD版本功能
47395 用户需求详情页面增加所属路标字段
修复的Bug
35072 发起评审,相关文档内容及顺序显示错误
35191 OR界面下导出的产品字段与页面不一致
35252 英法德语下提交立项页面的类型显示不全
35253 分发需求可以选择所有状态的路标
35262 评审点都通过了,子阶段也都关闭了,但是父阶段仍是进行中的状态
35312 将路标与立项解除关联,路标状态未改变
35333 编辑需求所属产品下拉菜单宽度没有限制
35418 研发用户到达授权人数,提示信息不准确
35422 甘特图列表中可以点父级阶段进入阶段中
35438 评审点计划完成时间显示错误
35471 Windows新版一键安装包,系统右下角没有隐藏升级按钮
35472 地盘-仪表盘中界面切换隐藏
35473 OR界面点击仪表盘最新动态更多跳转到了组织动态页面
35480 需求列表中细分需求的按钮与用户需求按钮不对齐
35485 编辑需求页面所属产品下拉样式错误
35490 阶段列表中评审点评审完成后还高亮评审按钮
35493 多分支产品,研发需求无法关联到用户需求
35523 运用管理界面中反馈办公工作流没有权限包
36122 权限包信息显示不完整
36477 OR界面产品列表中代码报错
36479 激活立项后立项的状态显示成了英文
36480 OR界面产品列表页代码报错
36497 批量移除路标的用户需求,点击取消后移除按钮变白了
36522 立项关闭后列表和详细页显示closed
36533 阶段列表页草稿状态的评审点没有显示编辑按钮
36536 阶段列表中编辑按钮只有icon部分可以点
36551 英文下激活立项弹窗中没有显示提示文案
36623 在路标的用户需求列表批量指派需求提示没有研发需求批量指派权限
36624 甘特图中计划完成的编辑按钮可触范围与按钮大小不匹配
36625 分支下的用户需求批量关联路标时列出了主干的路标
36638 IPD界面产品路标下访问用户需求详情页提示访问对象不存在
36645 批量编辑阶段更改状态可无视阶段进度
36660 超级管理员在IPD界面项目用户需求列表中无法全选
36672 15.3升级ipd1.0后,admin用户默认没有需求与管理界面的权限
36677 IPD1.0.beta1升级到IPD1.0.stable版本删除文件后有报错
36678 IPD界面下全局搜索项目集后进入项目集下可访问人员有代码报错
36684 需求池导入需求,没有带入指派给和类别
36687 需求池草稿需求提交评审提示502
36689 修改评审点计划完成计划时间翻页时,控件位置移动到了左上角
36696 OR界面添加产品区块报错
36697 OR界面区块,没有统计未关闭产品信息
36706 超级管理员在IPD项目用户需求列表页无法全选
36707 超级管理员在IPD项目的用户需求列表页时,二级导航高亮了两个
36710 分批次创建的阶段,会默认从最新添加的阶段开始
36711 需求的指派给和最后修改时间应显示为空
36712 地盘待处理不显示待我评审的用户需求
36713 max4.5轻量模式升级到IPD1.0不是全生命周期模式
36714 max4.0升级到ipd1.0,OR界面产品列表页代码报错
36715 升级至ipd版本,用户需求应该默认开启
36716 max4.0升级到ipd1.0后,无法创建IPD类型的项目
36717 升级成功后超级管理员维护“需求与市场管理界面”权限保存后界面和内容不对应
36718 关闭路标选择关闭原因后点保存控制台有报错
36719 给admin OR界面权限后,界面显示错误
36720 升级后OR界面没有默认权限分组
36721 biz8.5升级ipd1.0,普通用户在OR界面看不到
36726 需求池下导入权限有多余
36728 需求池导入需求时提示需求名称不符合
36740 批量编辑产品下用户需求可以将非激活状态需求编辑到路标下
36741 升级后开启用户需求后二级导航同时高亮了用户需求和研发需求
36743 18.4升ipd1.0,BI显示开源版的引导弹窗
36744 路标关联了非激活状态的需求后,解除关联,需求状态变为了激活
36745 没有打开用户需求功能的IPD界面,点击路标的需求列表的用户需求超链接二级导航没有高亮
36747 路标中批量操作按钮应该隐藏评审按钮
36748 IPD项目下编辑阶段页面选择父阶段后提示信息中显示undefined
36749 biz4.1.3升级到ipd1.0.授权没替换成功
36750 IPD界面学堂从云端导入课程,发送邮件内容有误
36753 路标关联需求点击搜索搜索不到内容
36760 1.0beta1升级到1.0stable版本后IPD项目下可以创建多套阶段
36765 ipd项目创建评审,评审文档错误
36766 创建文档保存后会保存两个文档
36767 评审页面报错
36771 IPD研发项目下打基线页面三级导航缺失
36772 提交评审时选择一个以上文档,在评审页面文档内容为空
36786 工单转研发需求选择来源后有代码报错
36795 IPD界面创建的产品,在OR界面批量编辑后变成了已关闭状态
36800 研发需求提交评审变成了页面
36810 项目集列表页IPD项目前未显示复选框
36831 瀑布/融合瀑布项目下的配置菜单没有了
36858 OR界面产品总览区块统计数据不正确
2023-07-05 18.5
完成的需求
开源版:
+1 -1
View File
@@ -963,7 +963,7 @@ $lang->resource->projectreview = new stdclass();
$lang->resource->projecttrack = new stdclass();
$lang->resource->projectqa = new stdclass();
if($config->edition == 'biz' or $config->edition == 'max')
if($config->edition != 'open')
{
/* My module. */
$lang->resource->my->effort = 'effort'; // pro effort
+3 -2
View File
@@ -1,10 +1,11 @@
<?php
public function getExecutionStoryPairs($executionID = 0, $productID = 0, $branch = 'all', $moduleIdList = 0, $type = 'full', $status = 'all')
public function getExecutionStoryPairs($executionID = 0, $productID = 0, $branch = 'all', $moduleIdList = 0, $type = 'full', $status = 'all', $storyType = 'story')
{
if($this->config->vision == 'lite')
{
$execution = $this->loadModel('execution')->getById($executionID);
if($execution->project) $executionID = $execution->project;
}
return parent::getExecutionStoryPairs($executionID, $productID, $branch, $moduleIdList, $type, $status);
return parent::getExecutionStoryPairs($executionID, $productID, $branch, $moduleIdList, $type, $status, $storyType);
}
+119
View File
@@ -0,0 +1,119 @@
<?php
$lang->SRCommon = 'Requirement';
$lang->demandpool = new stdclass();
$lang->demandpool->common = 'RM Hub';
$lang->demand = new stdclass();
$lang->demand->common = 'Demand';
$lang->charter = new stdclass();
$lang->charter->common = 'Charter';
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
/* Main Navigation. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
//if($config->edition != 'open')
//{
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
//
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . 'Feedback|feedback|browse|browseType=unclosed';
//
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
//}
$lang->mainNav->menuOrder[5] = 'my';
$lang->mainNav->menuOrder[10] = 'demandpool';
$lang->mainNav->menuOrder[15] = 'product';
$lang->mainNav->menuOrder[20] = 'charter';
//$lang->mainNav->menuOrder[25] = 'feedback';
$lang->mainNav->menuOrder[30] = 'doc';
$lang->mainNav->menuOrder[35] = 'admin';
$lang->navGroup->demandpool = 'demandpool';
$lang->navGroup->demand = 'demandpool';
$lang->navGroup->roadmap = 'product';
$lang->navGroup->charter = 'charter';
$lang->demandpool->menu = new stdclass();
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
//$lang->demandpool->menu->review = array('link' => "Review|demand|review|poolID=%s");
//$lang->demandpool->menu->kanban = array('link' => "Kanban|demand|kanban|poolID=%s");
//$lang->demandpool->menu->track = array('link' => "Track|demand|track|demandID=%s");
//$lang->demandpool->menu->insight = array('link' => "Insight|demand|insight|demandID=%s");
$lang->demandpool->menu->view = array('link' => "View|demandpool|view|poolID=%s", 'alias' => 'edit');
$lang->demandpool->menuOrder[5] = 'browse';
$lang->demandpool->menuOrder[10] = 'review';
$lang->demandpool->menuOrder[15] = 'kanban';
$lang->demandpool->menuOrder[20] = 'track';
$lang->demandpool->menuOrder[25] = 'insight';
$lang->demandpool->menuOrder[30] = 'view';
$lang->product->menu = new stdclass();
$lang->product->menu->requirement = array('link' => "Requirement|product|browse|productID=%s&branch=&browseType=assignedtome&param=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->roadmap = array('link' => "Roadmap|roadmap|browse|productID=%s");
#$lang->product->menu->initiating = array('link' => "Initiating|product|initiating|productID=%s");
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
$lang->product->menu->settings['subMenu'] = new stdclass();
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
$lang->product->menuOrder = array();
$lang->product->menuOrder[5] = 'requirement';
$lang->product->menuOrder[10] = 'roadmap';
$lang->product->menuOrder[15] = 'initiating';
$lang->product->menuOrder[20] = 'settings';
unset($lang->product->homeMenu->home);
unset($lang->product->homeMenu->kanban);
$lang->charter->menu = new stdclass();
$lang->charter->menu->all = array('link' => "All|charter|browse|browseType=all");
$lang->charter->menu->wait = array('link' => "Wait|charter|browse|browseType=wait");
$lang->charter->menu->launched = array('link' => "Launched|charter|browse|browseType=launched");
$lang->charter->menu->failed = array('link' => "Failed|charter|browse|browseType=failed");
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
unset($lang->my->menu->project);
unset($lang->my->menu->execution);
unset($lang->my->menu->contribute);
unset($lang->my->menu->meeting);
unset($lang->doc->menu->project);
unset($lang->doc->menu->api);
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
$lang->my->menu->work['subMenu'] = new stdclass();
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
unset($lang->createIcons['bug']);
unset($lang->createIcons['story']);
unset($lang->createIcons['task']);
unset($lang->createIcons['testcase']);
unset($lang->createIcons['program']);
unset($lang->createIcons['project']);
unset($lang->createIcons['execution']);
unset($lang->createIcons['kanbanspace']);
unset($lang->createIcons['kanban']);
$lang->searchObjects = array();
$lang->searchObjects['all'] = 'All';
$lang->searchObjects['story'] = 'Requirement';
$lang->searchObjects['demandpool'] = 'DemandPool';
$lang->searchObjects['demand'] = 'Demand';
$lang->searchObjects['roadmap'] = 'Roadmap';
$lang->searchObjects['charter'] = 'Charter';
$lang->searchObjects['product'] = $lang->productCommon;
$lang->searchObjects['doc'] = 'Document';
$lang->searchTips = 'ID(ctrl+g)';
+119
View File
@@ -0,0 +1,119 @@
<?php
$lang->SRCommon = 'Requirement';
$lang->demandpool = new stdclass();
$lang->demandpool->common = 'RM Hub';
$lang->demand = new stdclass();
$lang->demand->common = 'Demand';
$lang->charter = new stdclass();
$lang->charter->common = 'Charter';
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
/* Main Navigation. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
//if($config->edition != 'open')
//{
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
//
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . 'Feedback|feedback|browse|browseType=unclosed';
//
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
//}
$lang->mainNav->menuOrder[5] = 'my';
$lang->mainNav->menuOrder[10] = 'demandpool';
$lang->mainNav->menuOrder[15] = 'product';
$lang->mainNav->menuOrder[20] = 'charter';
//$lang->mainNav->menuOrder[25] = 'feedback';
$lang->mainNav->menuOrder[30] = 'doc';
$lang->mainNav->menuOrder[35] = 'admin';
$lang->navGroup->demandpool = 'demandpool';
$lang->navGroup->demand = 'demandpool';
$lang->navGroup->roadmap = 'product';
$lang->navGroup->charter = 'charter';
$lang->demandpool->menu = new stdclass();
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
//$lang->demandpool->menu->review = array('link' => "Review|demand|review|poolID=%s");
//$lang->demandpool->menu->kanban = array('link' => "Kanban|demand|kanban|poolID=%s");
//$lang->demandpool->menu->track = array('link' => "Track|demand|track|demandID=%s");
//$lang->demandpool->menu->insight = array('link' => "Insight|demand|insight|demandID=%s");
$lang->demandpool->menu->view = array('link' => "View|demandpool|view|poolID=%s", 'alias' => 'edit');
$lang->demandpool->menuOrder[5] = 'browse';
$lang->demandpool->menuOrder[10] = 'review';
$lang->demandpool->menuOrder[15] = 'kanban';
$lang->demandpool->menuOrder[20] = 'track';
$lang->demandpool->menuOrder[25] = 'insight';
$lang->demandpool->menuOrder[30] = 'view';
$lang->product->menu = new stdclass();
$lang->product->menu->requirement = array('link' => "Requirement|product|browse|productID=%s&branch=&browseType=assignedtome&param=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->roadmap = array('link' => "Roadmap|roadmap|browse|productID=%s");
#$lang->product->menu->initiating = array('link' => "Initiating|product|initiating|productID=%s");
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
$lang->product->menu->settings['subMenu'] = new stdclass();
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
$lang->product->menuOrder = array();
$lang->product->menuOrder[5] = 'requirement';
$lang->product->menuOrder[10] = 'roadmap';
$lang->product->menuOrder[15] = 'initiating';
$lang->product->menuOrder[20] = 'settings';
unset($lang->product->homeMenu->home);
unset($lang->product->homeMenu->kanban);
$lang->charter->menu = new stdclass();
$lang->charter->menu->all = array('link' => "All|charter|browse|browseType=all");
$lang->charter->menu->wait = array('link' => "Wait|charter|browse|browseType=wait");
$lang->charter->menu->launched = array('link' => "Launched|charter|browse|browseType=launched");
$lang->charter->menu->failed = array('link' => "Failed|charter|browse|browseType=failed");
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
unset($lang->my->menu->project);
unset($lang->my->menu->execution);
unset($lang->my->menu->contribute);
unset($lang->my->menu->meeting);
unset($lang->doc->menu->project);
unset($lang->doc->menu->api);
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
$lang->my->menu->work['subMenu'] = new stdclass();
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
unset($lang->createIcons['bug']);
unset($lang->createIcons['story']);
unset($lang->createIcons['task']);
unset($lang->createIcons['testcase']);
unset($lang->createIcons['program']);
unset($lang->createIcons['project']);
unset($lang->createIcons['execution']);
unset($lang->createIcons['kanbanspace']);
unset($lang->createIcons['kanban']);
$lang->searchObjects = array();
$lang->searchObjects['all'] = 'All';
$lang->searchObjects['story'] = 'Requirement';
$lang->searchObjects['demandpool'] = 'DemandPool';
$lang->searchObjects['demand'] = 'Demand';
$lang->searchObjects['roadmap'] = 'Roadmap';
$lang->searchObjects['charter'] = 'Charter';
$lang->searchObjects['product'] = $lang->productCommon;
$lang->searchObjects['doc'] = 'Document';
$lang->searchTips = 'ID(ctrl+g)';
+119
View File
@@ -0,0 +1,119 @@
<?php
$lang->SRCommon = 'Requirement';
$lang->demandpool = new stdclass();
$lang->demandpool->common = 'RM Hub';
$lang->demand = new stdclass();
$lang->demand->common = 'Demand';
$lang->charter = new stdclass();
$lang->charter->common = 'Charter';
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
/* Main Navigation. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
//if($config->edition != 'open')
//{
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
//
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . 'Feedback|feedback|browse|browseType=unclosed';
//
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
//}
$lang->mainNav->menuOrder[5] = 'my';
$lang->mainNav->menuOrder[10] = 'demandpool';
$lang->mainNav->menuOrder[15] = 'product';
$lang->mainNav->menuOrder[20] = 'charter';
//$lang->mainNav->menuOrder[25] = 'feedback';
$lang->mainNav->menuOrder[30] = 'doc';
$lang->mainNav->menuOrder[35] = 'admin';
$lang->navGroup->demandpool = 'demandpool';
$lang->navGroup->demand = 'demandpool';
$lang->navGroup->roadmap = 'product';
$lang->navGroup->charter = 'charter';
$lang->demandpool->menu = new stdclass();
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
//$lang->demandpool->menu->review = array('link' => "Review|demand|review|poolID=%s");
//$lang->demandpool->menu->kanban = array('link' => "Kanban|demand|kanban|poolID=%s");
//$lang->demandpool->menu->track = array('link' => "Track|demand|track|demandID=%s");
//$lang->demandpool->menu->insight = array('link' => "Insight|demand|insight|demandID=%s");
$lang->demandpool->menu->view = array('link' => "View|demandpool|view|poolID=%s", 'alias' => 'edit');
$lang->demandpool->menuOrder[5] = 'browse';
$lang->demandpool->menuOrder[10] = 'review';
$lang->demandpool->menuOrder[15] = 'kanban';
$lang->demandpool->menuOrder[20] = 'track';
$lang->demandpool->menuOrder[25] = 'insight';
$lang->demandpool->menuOrder[30] = 'view';
$lang->product->menu = new stdclass();
$lang->product->menu->requirement = array('link' => "Requirement|product|browse|productID=%s&branch=&browseType=assignedtome&param=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->roadmap = array('link' => "Roadmap|roadmap|browse|productID=%s");
#$lang->product->menu->initiating = array('link' => "Initiating|product|initiating|productID=%s");
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
$lang->product->menu->settings['subMenu'] = new stdclass();
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
$lang->product->menuOrder = array();
$lang->product->menuOrder[5] = 'requirement';
$lang->product->menuOrder[10] = 'roadmap';
$lang->product->menuOrder[15] = 'initiating';
$lang->product->menuOrder[20] = 'settings';
unset($lang->product->homeMenu->home);
unset($lang->product->homeMenu->kanban);
$lang->charter->menu = new stdclass();
$lang->charter->menu->all = array('link' => "All|charter|browse|browseType=all");
$lang->charter->menu->wait = array('link' => "Wait|charter|browse|browseType=wait");
$lang->charter->menu->launched = array('link' => "Launched|charter|browse|browseType=launched");
$lang->charter->menu->failed = array('link' => "Failed|charter|browse|browseType=failed");
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
unset($lang->my->menu->project);
unset($lang->my->menu->execution);
unset($lang->my->menu->contribute);
unset($lang->my->menu->meeting);
unset($lang->doc->menu->project);
unset($lang->doc->menu->api);
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
$lang->my->menu->work['subMenu'] = new stdclass();
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
unset($lang->createIcons['bug']);
unset($lang->createIcons['story']);
unset($lang->createIcons['task']);
unset($lang->createIcons['testcase']);
unset($lang->createIcons['program']);
unset($lang->createIcons['project']);
unset($lang->createIcons['execution']);
unset($lang->createIcons['kanbanspace']);
unset($lang->createIcons['kanban']);
$lang->searchObjects = array();
$lang->searchObjects['all'] = 'All';
$lang->searchObjects['story'] = 'Requirement';
$lang->searchObjects['demandpool'] = 'DemandPool';
$lang->searchObjects['demand'] = 'Demand';
$lang->searchObjects['roadmap'] = 'Roadmap';
$lang->searchObjects['charter'] = 'Charter';
$lang->searchObjects['product'] = $lang->productCommon;
$lang->searchObjects['doc'] = 'Document';
$lang->searchTips = 'ID(ctrl+g)';
+119
View File
@@ -0,0 +1,119 @@
<?php
$lang->SRCommon = '用户需求';
$lang->demandpool = new stdclass();
$lang->demandpool->common = '需求池';
$lang->demand = new stdclass();
$lang->demand->common = '需求';
$lang->charter = new stdclass();
$lang->charter->common = '立项';
$lang->navIcons['demandpool'] = "<i class='icon icon-bars'></i>";
/* Main Navigation. */
$lang->mainNav = new stdclass();
$lang->mainNav->my = "{$lang->navIcons['my']} {$lang->my->shortCommon}|my|index|";
$lang->mainNav->demandpool = "{$lang->navIcons['demandpool']} {$lang->demandpool->common}|demandpool|browse|";
$lang->mainNav->product = "{$lang->navIcons['product']} {$lang->productCommon}|product|all|";
$lang->mainNav->charter = "{$lang->navIcons['project']} {$lang->charter->common}|charter|browse|";
$lang->mainNav->doc = "{$lang->navIcons['doc']} {$lang->doc->common}|doc|index|";
$lang->mainNav->admin = "{$lang->navIcons['admin']} {$lang->admin->common}|admin|index|";
//if($config->edition != 'open')
//{
// $lang->navIcons['feedback'] = "<i class='icon icon-feedback'></i>";
//
// $lang->mainNav->feedback = $lang->navIcons['feedback'] . '反馈|feedback|browse|browseType=unclosed';
//
// if($config->visions == ',lite,') unset($lang->mainNav->feedback);
//}
$lang->mainNav->menuOrder[5] = 'my';
$lang->mainNav->menuOrder[10] = 'demandpool';
$lang->mainNav->menuOrder[15] = 'product';
$lang->mainNav->menuOrder[20] = 'charter';
//$lang->mainNav->menuOrder[25] = 'feedback';
$lang->mainNav->menuOrder[30] = 'doc';
$lang->mainNav->menuOrder[35] = 'admin';
$lang->navGroup->demandpool = 'demandpool';
$lang->navGroup->demand = 'demandpool';
$lang->navGroup->roadmap = 'product';
$lang->navGroup->charter = 'charter';
$lang->demandpool->menu = new stdclass();
$lang->demandpool->menu->browse = array('link' => "{$lang->demand->common}|demand|browse|poolID=%s", 'alias' => 'create,batchcreate,edit,managetree,view,tostory,showimport,review,change');
//$lang->demandpool->menu->review = array('link' => "评审|demand|review|poolID=%s");
//$lang->demandpool->menu->kanban = array('link' => "看板|demand|kanban|poolID=%s");
//$lang->demandpool->menu->track = array('link' => "矩阵图|demand|track|demandID=%s");
//$lang->demandpool->menu->insight = array('link' => "洞察|demand|insight|demandID=%s");
$lang->demandpool->menu->view = array('link' => "概况|demandpool|view|poolID=%s", 'alias' => 'edit');
$lang->demandpool->menuOrder[5] = 'browse';
$lang->demandpool->menuOrder[10] = 'review';
$lang->demandpool->menuOrder[15] = 'kanban';
$lang->demandpool->menuOrder[20] = 'track';
$lang->demandpool->menuOrder[25] = 'insight';
$lang->demandpool->menuOrder[30] = 'view';
$lang->product->menu = new stdclass();
$lang->product->menu->requirement = array('link' => "{$lang->URCommon}|product|browse|productID=%s&branch=&browseType=assignedtome&param=0&storyType=requirement", 'alias' => 'batchedit', 'subModule' => 'story');
$lang->product->menu->roadmap = array('link' => "路标|roadmap|browse|productID=%s");
#$lang->product->menu->initiating = array('link' => "立项|product|initiating|productID=%s");
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
$lang->product->menu->settings['subMenu'] = new stdclass();
$lang->product->menu->settings['subMenu']->view = array('link' => "{$lang->overview}|product|view|productID=%s", 'alias' => 'edit');
$lang->product->menu->settings['subMenu']->module = array('link' => "{$lang->module}|tree|browse|product=%s&view=story", 'subModule' => 'tree');
$lang->product->menu->settings['subMenu']->branch = array('link' => "@branch@|branch|manage|product=%s", 'subModule' => 'branch');
$lang->product->menu->settings['subMenu']->whitelist = array('link' => "{$lang->whitelist}|product|whitelist|product=%s", 'subModule' => 'personnel');
$lang->product->menuOrder = array();
$lang->product->menuOrder[5] = 'requirement';
$lang->product->menuOrder[10] = 'roadmap';
$lang->product->menuOrder[15] = 'initiating';
$lang->product->menuOrder[20] = 'settings';
unset($lang->product->homeMenu->home);
unset($lang->product->homeMenu->kanban);
$lang->charter->menu = new stdclass();
$lang->charter->menu->all = array('link' => "全部|charter|browse|browseType=all");
$lang->charter->menu->wait = array('link' => "待立项|charter|browse|browseType=wait");
$lang->charter->menu->launched = array('link' => "已立项|charter|browse|browseType=launched");
$lang->charter->menu->failed = array('link' => "未通过|charter|browse|browseType=failed");
//$lang->charter->menu->settings = array('link' => "{$lang->settings}|charter|view|charterID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
unset($lang->my->menu->project);
unset($lang->my->menu->execution);
unset($lang->my->menu->contribute);
unset($lang->my->menu->meeting);
unset($lang->doc->menu->project);
unset($lang->doc->menu->api);
$lang->my->menu->work = array('link' => "{$lang->my->work}|my|work|mode=requirement", 'subModule' => 'task');
$lang->my->menu->work['subMenu'] = new stdclass();
$lang->my->menu->work['subMenu']->requirement = "$lang->URCommon|my|work|mode=requirement";
unset($lang->createIcons['bug']);
unset($lang->createIcons['story']);
unset($lang->createIcons['task']);
unset($lang->createIcons['testcase']);
unset($lang->createIcons['program']);
unset($lang->createIcons['project']);
unset($lang->createIcons['execution']);
unset($lang->createIcons['kanbanspace']);
unset($lang->createIcons['kanban']);
$lang->searchObjects = array();
$lang->searchObjects['all'] = '全部';
$lang->searchObjects['story'] = '需求';
$lang->searchObjects['demandpool'] = '需求池';
$lang->searchObjects['demand'] = '需求池需求';
$lang->searchObjects['roadmap'] = '路标';
$lang->searchObjects['charter'] = '立项';
$lang->searchObjects['product'] = $lang->productCommon;
$lang->searchObjects['doc'] = '文档';
$lang->searchTips = '编号(ctrl+g)';
+10 -10
View File
@@ -33,29 +33,29 @@ subGroupPath=`echo $GIT_TAG_BUILD_GROUP | sed 's/\./\//'`
outputLine "#### 下载地址"
outputLine "##### 开源版"
outputFrame "[${PMS_VERSION} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/pmsPack/$subGroupPath/zentaopms/${PMS_VERSION}/)"
outputFrame "[${PMS_VERSION} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/pmsPack/$subGroupPath/ZenTaoPMS/${PMS_VERSION}/)"
outputFrame "\t\t"
outputLine "[${PMS_VERSION} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/pmsPack/$subGroupPath/zentaoalm/${PMS_VERSION}/)"
outputLine "[${PMS_VERSION} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/pmsPack/$subGroupPath/ZenTaoALM/${PMS_VERSION}/)"
outputLine "##### 企业版"
outputFrame "[${BIZ_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/zentaopms/${BIZ_VERSION}/)"
outputFrame "[${BIZ_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/ZenTaoPMS/${BIZ_VERSION}/)"
outputFrame "\t\t"
outputLine "[${BIZ_VERSION:3} 升级包 (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/zentaopms.update/${BIZ_VERSION}/)"
outputLine "[${BIZ_VERSION:3} 升级包 (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/ZenTaoPMS.update/${BIZ_VERSION}/)"
outputFrame "[${BIZ_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/zentaoalm/${BIZ_VERSION}/)"
outputFrame "[${BIZ_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/ZenTaoALM/${BIZ_VERSION}/)"
outputFrame "\t"
outputLine "[${BIZ_VERSION:3} 升级包 (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/zentaoalm.update/${BIZ_VERSION}/)"
outputLine "[${BIZ_VERSION:3} 升级包 (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/bizPack/$subGroupPath/ZenTaoALM.update/${BIZ_VERSION}/)"
outputLine "##### 旗舰版"
outputFrame "[${MAX_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/zentaopms/${MAX_VERSION}/)"
outputFrame "[${MAX_VERSION:3} (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/ZenTaoPMS/${MAX_VERSION}/)"
outputFrame "\t\t"
outputLine "[${MAX_VERSION:3} 升级包 (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/zentaopms.update/${MAX_VERSION}/)"
outputLine "[${MAX_VERSION:3} 升级包 (中文)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/ZenTaoPMS.update/${MAX_VERSION}/)"
outputFrame "[${MAX_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/zentaoalm/${MAX_VERSION}/)"
outputFrame "[${MAX_VERSION:3} (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/ZenTaoALM/${MAX_VERSION}/)"
outputFrame "\t"
outputLine "[${MAX_VERSION:3} 升级包 (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/zentaoalm.update/${MAX_VERSION}/)"
outputLine "[${MAX_VERSION:3} 升级包 (English)](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/service/rest/repository/browse/${ARTIFACT_REPOSITORY}/zentao/maxPack/$subGroupPath/ZenTaoALM.update/${MAX_VERSION}/)"
outputLine "##### 历史版本"
outputLine "[查看历史版本](${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/#browse/browse:easycorp-snapshot)"
+51 -10
View File
@@ -406,13 +406,23 @@ class actionModel extends model
$productID = trim($action->product, ',');
$name = $project->name;
$method = $project->model == 'kanban' ? 'index' : 'view';
if($name) $action->extra = common::hasPriv('project', $method) ? html::a(helper::createLink('project', $method, "projectID=$action->project"), $name) : $name;
if($name) $action->extra = (common::hasPriv('project', $method) and $this->config->vision != 'or') ? html::a(helper::createLink('project', $method, "projectID=$action->project"), $name) : $name;
}
elseif($actionName == 'linked2plan')
{
$title = $this->dao->select('title')->from(TABLE_PRODUCTPLAN)->where('id')->eq($action->extra)->fetch('title');
if($title) $action->extra = common::hasPriv('productplan', 'view') ? html::a(helper::createLink('productplan', 'view', "planID=$action->extra"), $title) : $title;
}
elseif($actionName == 'changedbycharter')
{
$name = $this->dao->select('name')->from(TABLE_CHARTER)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('charter', 'view') ? html::a(helper::createLink('charter', 'view', "charterID=$action->extra"), $name) : $name;
}
elseif($actionName == 'linked2roadmap' and $action->objectType == 'story')
{
$name = $this->dao->select('name')->from(TABLE_ROADMAP)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('roadmap', 'view') ? html::a(helper::createLink('roadmap', 'view', "roadmapID=$action->extra"), $name) : $name;
}
elseif($actionName == 'linked2build')
{
$name = $this->dao->select('name')->from(TABLE_BUILD)->where('id')->eq($action->extra)->fetch('name');
@@ -477,6 +487,11 @@ class actionModel extends model
$title = $this->dao->select('title')->from(TABLE_PRODUCTPLAN)->where('id')->eq($action->extra)->fetch('title');
if($title) $action->extra = common::hasPriv('productplan', 'view') ? html::a(helper::createLink('productplan', 'view', "planID=$action->extra"), "#$action->extra " . $title) : "#$action->extra " . $title;
}
elseif($actionName == 'unlinkedfromroadmap' and $action->objectType == 'story')
{
$name = $this->dao->select('name')->from(TABLE_ROADMAP)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('roadmap', 'view') ? html::a(helper::createLink('roadmap', 'view', "roadmapID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
}
elseif($actionName == 'unlinkedfromtesttask')
{
$name = $this->dao->select('name')->from(TABLE_TESTTASK)->where('id')->eq($action->extra)->fetch('name');
@@ -533,6 +548,11 @@ class actionModel extends model
$name = $this->dao->select('title')->from(TABLE_STORY)->where('id')->eq($action->extra)->fetch('title');
if($name) $action->extra = common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
}
elseif($actionName == 'deletechildrendemand')
{
$name = $this->dao->select('title')->from(TABLE_DEMAND)->where('id')->eq($action->extra)->fetch('title');
if($name) $action->extra = common::hasPriv('demand', 'view') ? html::a(helper::createLink('demand', 'view', "demandID=$action->extra"), "#$action->extra " . $name) : "#$action->extra " . $name;
}
elseif($actionName == 'buildopened')
{
$name = $this->dao->select('name')->from(TABLE_BUILD)->where('id')->eq($action->objectID)->fetch('name');
@@ -548,7 +568,7 @@ class actionModel extends model
$name = $this->dao->select('name')->from(TABLE_TESTSUITE)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('caselib', 'browse') ? html::a(helper::createLink('caselib', 'browse', "libID=$action->extra"), $name) : $name;
}
elseif(strpos(',importfromstorylib,importfromrisklib,importfromissuelib,importfromopportunitylib,', ",{$actionName},") !== false and $this->config->edition == 'max')
elseif(strpos(',importfromstorylib,importfromrisklib,importfromissuelib,importfromopportunitylib,', ",{$actionName},") !== false and ($this->config->edition == 'max' or $this->config->edition == 'ipd'))
{
$name = $this->dao->select('name')->from(TABLE_ASSETLIB)->where('id')->eq($action->extra)->fetch('name');
if($name) $action->extra = common::hasPriv('assetlib', $action->objectType) ? html::a(helper::createLink('assetlib', $action->objectType, "libID=$action->extra"), $name) : $name;
@@ -569,6 +589,21 @@ class actionModel extends model
}
}
}
elseif($actionName == 'closed' and $action->objectType == 'demand')
{
$action->appendLink = '';
if(strpos($action->extra, '|') !== false) $action->extra = substr($action->extra, 0, strpos($action->extra, '|'));
if(strpos($action->extra, ':') !== false)
{
list($extra, $id) = explode(':', $action->extra);
$action->extra = $extra;
if($id)
{
$name = $this->dao->select('title')->from(TABLE_DEMAND)->where('id')->eq($id)->fetch('title');
if($name) $action->appendLink = html::a(helper::createLink($action->objectType, 'view', "id=$id"), "#$id " . $name);
}
}
}
elseif($actionName == 'finished' and $objectType == 'todo')
{
$action->appendLink = '';
@@ -613,7 +648,7 @@ class actionModel extends model
if($history->field == 'git') $history->diff = str_replace('+', '%2B', $history->diff);
}
}
elseif(strpos(',linkstory,unlinkstory,createchildrenstory,', ",$actionName,") !== false)
elseif(strpos(',linkstory,unlinkstory,createchildrenstory,linkur,unlinkur,', ",$actionName,") !== false)
{
$extra = '';
foreach(explode(',', $action->extra) as $id) $extra .= common::hasPriv('story', 'view') ? html::a(helper::createLink('story', 'view', "storyID=$id"), "#$id ") . ', ' : "#$id, ";
@@ -777,7 +812,7 @@ class actionModel extends model
$trashQuery = $this->session->trashQuery;
$trashQuery = str_replace(array('`objectID`', '`actor`', '`date`'), array('t1.`objectID`', 't1.`actor`', 't1.`date`'), $trashQuery);
$table = $this->config->objectTables[$objectType];
$nameField = isset($this->config->action->objectNameFields[$objectType]) ? 't2.' . "`{$this->config->action->objectNameFields[$objectType]}`" : '';
$nameField = isset($this->config->action->objectNameFields[$objectType]) ? 't2.' . '`' . $this->config->action->objectNameFields[$objectType] . '`' : '';
if($nameField) $trashQuery = preg_replace("/`objectName`/", $nameField, $trashQuery);
@@ -1123,7 +1158,7 @@ class actionModel extends model
*/
if(empty($desc))
{
if($action->objectType == 'story' and $action->action == 'reviewed' and strpos($action->extra, ',') !== false)
if(($action->objectType == 'story' or $action->objectType == 'demand') and $action->action == 'reviewed' and strpos($action->extra, ',') !== false)
{
$desc = $this->lang->$objectType->action->rejectreviewed;
}
@@ -1145,7 +1180,7 @@ class actionModel extends model
$this->app->loadLang('mr');
$desc = sprintf($this->lang->mr->$mrAction, $mrDate, $mrActor, $mrLink);
}
elseif($this->config->edition == 'max' and strpos($this->config->action->assetType, ",{$action->objectType},") !== false and $action->action == 'approved')
elseif(($this->config->edition == 'max' or $this->config->edition == 'ipd') and strpos($this->config->action->assetType, ",{$action->objectType},") !== false and $action->action == 'approved')
{
$desc = empty($this->lang->action->approve->{$action->extra}) ? '' : $this->lang->action->approve->{$action->extra};
}
@@ -1210,7 +1245,7 @@ class actionModel extends model
$actionDesc = str_replace('$extra', $action->extra, $desc['main']);
}
if($action->objectType == 'story' and $action->action == 'reviewed')
if(($action->objectType == 'story' or $action->objectType == 'demand') and $action->action == 'reviewed')
{
if(strpos($action->extra, ',') !== false)
{
@@ -1714,7 +1749,7 @@ class actionModel extends model
elseif($objectType == 'stakeholder')
{
$objectName = $this->dao->select("t1.id, t2.realname")->from($table)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on("t1.`{$field}` = t2.account")
->leftJoin(TABLE_USER)->alias('t2')->on("t1.`$field` = t2.account")
->where('t1.id')->in($objectIdList)
->fetchPairs();
}
@@ -1791,7 +1826,7 @@ class actionModel extends model
}
}
if($this->config->edition == 'max' and $objectType == 'assetlib')
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') and $objectType == 'assetlib')
{
$libType = $this->dao->select('type')->from(TABLE_ASSETLIB)->where('id')->eq($objectID)->fetch('type');
if(strpos('story,issue,risk,opportunity,practice,component', $libType) !== false) $actionObjectLabel = $this->lang->action->label->{$libType . 'assetlib'};
@@ -1835,7 +1870,7 @@ class actionModel extends model
if($objectDeleted) return $action;
}
if($this->config->edition == 'max'
if(($this->config->edition == 'max' or $this->config->edition == 'ipd')
and strpos($this->config->action->assetType, ",{$action->objectType},") !== false
and empty($action->project) and empty($action->product) and empty($action->execution))
{
@@ -2239,6 +2274,12 @@ class actionModel extends model
$this->dao->update(TABLE_DOCLIB)->set('deleted')->eq(0)->where($action->objectType)->eq($action->objectID)->exec();
}
if($action->objectType == 'demand')
{
$demand = $this->dao->select('*')->from(TABLE_DEMAND)->where('id')->eq($action->objectID)->fetch();
if($demand->parent) $this->loadModel('demand')->updateParentStatus($action->objectID, $demand->parent);
}
/* Revert productplan parent status. */
if($action->objectType == 'productplan') $this->loadModel('productplan')->changeParentField($action->objectID);
+2 -2
View File
@@ -223,7 +223,7 @@ $lang->admin->menuList->platform['menuOrder']['25'] = 'setrules';
$lang->admin->menuList->platform['dividerMenu'] = ',plat,setrules,';
if($config->edition != 'max')
if($config->edition != 'max' and $config->edition != 'ipd')
{
unset($lang->admin->menuList->model['subMenu']['scrum']);
unset($lang->admin->menuList->model['subMenu']['agileplus']);
@@ -241,7 +241,7 @@ if(!helper::hasFeature('waterfallplus'))
unset($lang->admin->menuList->model['subMenu']['waterfallplus']);
unset($lang->admin->menuList->model['menuOrder']['25']);
}
if($config->edition == 'max')
if($config->edition == 'max' or $config->edition == 'ipd')
{
if(!helper::hasFeature('scrum_auditplan') and !helper::hasFeature('scrum_process')) unset($lang->admin->menuList->model['subMenu']['scrum'], $lang->admin->menuList->model['menuOrder']['10']);
if(!helper::hasFeature('agileplus_auditplan') and !helper::hasFeature('agileplus_process')) unset($lang->admin->menuList->model['subMenu']['agileplus'], $lang->admin->menuList->model['menuOrder']['20']);
+1 -1
View File
@@ -139,7 +139,7 @@
</div>
<?php endforeach;?>
</div>
<?php if($config->edition != 'max'):?>
<?php if(!in_array($config->edition, array('max', 'ipd'))):?>
<div class="border-gray mb-16 radius-4">
<div class="h-40 pl-16 flex align-center justify-between">
<div class="panel-title"><?php echo $lang->admin->upgradeRecommend?></div>
+18 -17
View File
@@ -64,10 +64,10 @@ class block extends control
}
$closedBlock = isset($this->config->block->closed) ? $this->config->block->closed : '';
if(strpos(",$closedBlock,", ",|assigntome,") === false) $modules['assigntome'] = $this->lang->block->assignToMe;
if(strpos(",$closedBlock,", ",|assigntome,") === false and $this->config->vision != 'or') $modules['assigntome'] = $this->lang->block->assignToMe;
if(strpos(",$closedBlock,", ",|dynamic,") === false) $modules['dynamic'] = $this->lang->block->dynamic;
if(strpos(",$closedBlock,", ",|guide,") === false and $this->config->global->flow == 'full') $modules['guide'] = $this->lang->block->guide;
if(strpos(",$closedBlock,", ",|welcome,") === false and $this->config->global->flow == 'full') $modules['welcome'] = $this->lang->block->welcome;
if($this->config->edition != 'ipd' and strpos(",$closedBlock,", ",|welcome,") === false and $this->config->global->flow == 'full') $modules['welcome'] = $this->lang->block->welcome;
if(strpos(",$closedBlock,", ",|html,") === false) $modules['html'] = 'HTML';
if(strpos(",$closedBlock,", ",|contribute,") === false and $this->config->vision == 'rnd') $modules['contribute'] = $this->lang->block->contribute;
$modules = array('' => '') + $modules;
@@ -83,7 +83,7 @@ class block extends control
{
$this->get->set('dashboard', 'project');
if($this->config->edition == 'max' and $this->app->tab == 'project')
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') and $this->app->tab == 'project')
{
$project = $this->loadModel('project')->getByID($this->session->project);
if(isset($project->model) and !helper::hasFeature("{$project->model}_issue"))
@@ -975,7 +975,7 @@ class block extends control
$count = isset($this->params->count) ? (int)$this->params->count : 15;
/* Get projects. */
$excludedModel = $this->config->edition == 'max' ? '' : 'waterfall';
$excludedModel = ($this->config->edition == 'max' or $this->config->edition == 'ipd') ? '' : 'waterfall';
$projects = $this->project->getOverviewList('byStatus', $status, 'order_asc', $count, $excludedModel);
if(empty($projects))
{
@@ -1012,7 +1012,7 @@ class block extends control
$project->progress = $project->allStories == 0 ? 0 : round($project->doneStories / $project->allStories, 3) * 100;
$project->executions = $this->execution->getStatData($projectID, 'all', 0, 0, false, '', 'id_desc', $pager);
}
elseif(in_array($project->model, array('waterfall', 'waterfallplus')))
elseif(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd')))
{
$begin = $project->begin;
$weeks = $this->weekly->getWeekPairs($begin);
@@ -1735,6 +1735,7 @@ class block extends control
$closed = 0;
$products = $this->loadModel('product')->getList();
foreach($products as $product)
{
if(!$this->product->checkPriv($product->id)) continue;
@@ -1853,23 +1854,23 @@ class block extends control
$hasMeeting = helper::hasFeature('meeting');
$hasViewPriv = array();
if(common::hasPriv('todo', 'view')) $hasViewPriv['todo'] = true;
if(common::hasPriv('task', 'view')) $hasViewPriv['task'] = true;
if(common::hasPriv('bug', 'view') and $this->config->vision != 'lite') $hasViewPriv['bug'] = true;
if(common::hasPriv('story', 'view') and $this->config->vision != 'lite') $hasViewPriv['story'] = true;
if($this->config->URAndSR and common::hasPriv('story', 'view') and $this->config->vision != 'lite') $hasViewPriv['requirement'] = true;
if(common::hasPriv('risk', 'view') and $this->config->edition == 'max' and $this->config->vision != 'lite' && $hasRisk) $hasViewPriv['risk'] = true;
if(common::hasPriv('issue', 'view') and $this->config->edition == 'max' and $this->config->vision != 'lite' && $hasIssue) $hasViewPriv['issue'] = true;
if(common::hasPriv('meeting', 'view') and $this->config->edition == 'max' and $this->config->vision != 'lite' && $hasMeeting) $hasViewPriv['meeting'] = true;
if(common::hasPriv('feedback', 'view') and in_array($this->config->edition, array('max', 'biz'))) $hasViewPriv['feedback'] = true;
if(common::hasPriv('ticket', 'view') and in_array($this->config->edition, array('max', 'biz'))) $hasViewPriv['ticket'] = true;
if(common::hasPriv('todo', 'view')) $hasViewPriv['todo'] = true;
if(common::hasPriv('task', 'view')) $hasViewPriv['task'] = true;
if(common::hasPriv('bug', 'view') and $this->config->vision != 'lite') $hasViewPriv['bug'] = true;
if(common::hasPriv('story', 'view') and $this->config->vision != 'lite') $hasViewPriv['story'] = true;
if($this->config->URAndSR and common::hasPriv('story', 'view') and $this->config->vision != 'lite') $hasViewPriv['requirement'] = true;
if(common::hasPriv('risk', 'view') and ($this->config->edition == 'max' or $this->config->edition == 'ipd') and $this->config->vision != 'lite' && $hasRisk) $hasViewPriv['risk'] = true;
if(common::hasPriv('issue', 'view') and ($this->config->edition == 'max' or $this->config->edition == 'ipd') and $this->config->vision != 'lite' && $hasIssue) $hasViewPriv['issue'] = true;
if(common::hasPriv('meeting', 'view') and ($this->config->edition == 'max' or $this->config->edition == 'ipd') and $this->config->vision != 'lite' && $hasMeeting) $hasViewPriv['meeting'] = true;
if(common::hasPriv('feedback', 'view') and $this->config->edition != 'open') $hasViewPriv['feedback'] = true;
if(common::hasPriv('ticket', 'view') and $this->config->edition != 'open') $hasViewPriv['ticket'] = true;
$params = $this->get->param;
$params = json_decode(base64_decode($params));
$count = array();
$objectList = array('todo' => 'todos', 'task' => 'tasks', 'bug' => 'bugs', 'story' => 'stories', 'requirement' => 'requirements');
$objectCountList = array('todo' => 'todoCount', 'task' => 'taskCount', 'bug' => 'bugCount', 'story' => 'storyCount', 'requirement' => 'requirementCount');
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
if($hasRisk)
{
@@ -2011,7 +2012,7 @@ class block extends control
$hasViewPriv['review'] = true;
$count['review'] = count($reviews);
$this->view->reviews = $reviews;
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$this->app->loadLang('approval');
$this->view->flows = $this->dao->select('module,name')->from(TABLE_WORKFLOW)->where('buildin')->eq(0)->fetchPairs('module', 'name');
+23 -6
View File
@@ -141,6 +141,7 @@ $lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfallplus'] = $lang->block->default['waterfall'];
$lang->block->default['ipd'] = $lang->block->default['waterfall'];
$lang->block->default['scrum']['project']['1']['title'] = $lang->projectCommon . ' Overall';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
@@ -425,15 +426,19 @@ $lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = '
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfallplus']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['ipd']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . ' Berichte';
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . ' Übersicht';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . ' Liste';
$lang->block->modules['product']->availableBlocks->story = 'Story';
$lang->block->modules['product']->availableBlocks->plan = 'Plan';
$lang->block->modules['product']->availableBlocks->release = 'Release';
if($this->config->vision != 'or')
{
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . ' Berichte';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . ' Liste';
$lang->block->modules['product']->availableBlocks->story = 'Story';
$lang->block->modules['product']->availableBlocks->plan = 'Plan';
$lang->block->modules['product']->availableBlocks->release = 'Release';
}
$lang->block->modules['execution'] = new stdclass();
$lang->block->modules['execution']->availableBlocks = new stdclass();
@@ -630,7 +635,7 @@ $lang->block->zentaoclient->edition->linux64 = 'Linux';
$lang->block->zentaoclient->edition->mac64 = 'Mac OS';
$lang->block->guideTabs['flowchart'] = 'Flowchart';
$lang->block->guideTabs['systemMode'] = 'Operating Modes';
//$lang->block->guideTabs['systemMode'] = 'Operating Modes';
$lang->block->guideTabs['visionSwitch'] = 'Interface Switch';
$lang->block->guideTabs['themeSwitch'] = 'Theme Switch';
$lang->block->guideTabs['preference'] = 'Personalized setting';
@@ -655,6 +660,18 @@ $lang->block->visions['lite'] = new stdclass();
$lang->block->visions['lite']->key = 'lite';
$lang->block->visions['lite']->title = 'Operation Management Interface';
$lang->block->visions['lite']->text = "Specially designed for Non-R&D teams, and based on the visual Kanban {$lang->projectCommon} management model.";
if($config->edition == 'ipd')
{
$lang->block->visionTitle = 'The user interface of ZenTao is divided into 【OR & MM Interface】【IPD Interface】 and 【Operation Management Interface】.';
$lang->block->visions['rnd']->title = 'IPD Interface';
$lang->block->visions['rnd']->text = "Doing things right by integrating the program, {$lang->productCommon}, {$lang->projectCommon}, execution,test, etc., and provide the lifecycle {$lang->projectCommon} management solution.";
$lang->block->visions['or'] = new stdclass();
$lang->block->visions['or']->key = 'or';
$lang->block->visions['or']->title = 'OR & MM Interface';
$lang->block->visions['or']->text = "Doing the right thing by integrating RM Hub, requirements, {$lang->productCommon}, roadmap planning, and project initiation, empowering effective requirement and market management.";
}
$lang->block->customModes['light'] = 'Light Mode';
$lang->block->customModes['ALM'] = 'ALM Mode';
+24 -7
View File
@@ -141,6 +141,7 @@ $lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfallplus'] = $lang->block->default['waterfall'];
$lang->block->default['ipd'] = $lang->block->default['waterfall'];
$lang->block->default['scrum']['project']['1']['title'] = $lang->projectCommon . ' Overview';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
@@ -425,15 +426,19 @@ $lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = '
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfallplus']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['ipd']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . ' Report';
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . ' Overview';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . ' List';
$lang->block->modules['product']->availableBlocks->story = 'Story';
$lang->block->modules['product']->availableBlocks->plan = 'Plan';
$lang->block->modules['product']->availableBlocks->release = 'Release';
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . ' Übersicht';
if($this->config->vision != 'or')
{
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . ' Berichte';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . ' Liste';
$lang->block->modules['product']->availableBlocks->story = 'Story';
$lang->block->modules['product']->availableBlocks->plan = 'Plan';
$lang->block->modules['product']->availableBlocks->release = 'Release';
}
$lang->block->modules['execution'] = new stdclass();
$lang->block->modules['execution']->availableBlocks = new stdclass();
@@ -630,7 +635,7 @@ $lang->block->zentaoclient->edition->linux64 = 'Linux';
$lang->block->zentaoclient->edition->mac64 = 'Mac OS';
$lang->block->guideTabs['flowchart'] = 'Flowchart';
$lang->block->guideTabs['systemMode'] = 'Operating Modes';
//$lang->block->guideTabs['systemMode'] = 'Operating Modes';
$lang->block->guideTabs['visionSwitch'] = 'Interface Switch';
$lang->block->guideTabs['themeSwitch'] = 'Theme Switch';
$lang->block->guideTabs['preference'] = 'Personalized setting';
@@ -655,6 +660,18 @@ $lang->block->visions['lite'] = new stdclass();
$lang->block->visions['lite']->key = 'lite';
$lang->block->visions['lite']->title = 'Operation Management Interface';
$lang->block->visions['lite']->text = "Specially designed for Non-R&D teams, and based on the visual Kanban {$lang->projectCommon} management model.";
if($config->edition == 'ipd')
{
$lang->block->visionTitle = 'The user interface of ZenTao is divided into 【OR & MM Interface】【IPD Interface】 and 【Operation Management Interface】.';
$lang->block->visions['rnd']->title = 'IPD Interface';
$lang->block->visions['rnd']->text = "Doing things right by integrating the program, {$lang->productCommon}, {$lang->projectCommon}, execution,test, etc., and provide the lifecycle {$lang->projectCommon} management solution.";
$lang->block->visions['or'] = new stdclass();
$lang->block->visions['or']->key = 'or';
$lang->block->visions['or']->title = 'OR & MM Interface';
$lang->block->visions['or']->text = "Doing the right thing by integrating RM Hub, requirements, {$lang->productCommon}, roadmap planning, and project initiation, empowering effective requirement and market management.";
}
$lang->block->customModes['light'] = 'Light Mode';
$lang->block->customModes['ALM'] = 'ALM Mode';
+24 -7
View File
@@ -141,6 +141,7 @@ $lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfallplus'] = $lang->block->default['waterfall'];
$lang->block->default['ipd'] = $lang->block->default['waterfall'];
$lang->block->default['scrum']['project']['1']['title'] = $lang->projectCommon . ' Overall';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
@@ -425,15 +426,19 @@ $lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt = '
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = 'Dynamics';
$lang->block->modules['waterfallplus']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['ipd']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
$lang->block->modules['product']->availableBlocks->statistic = 'Rapport de ' . $lang->productCommon;
$lang->block->modules['product']->availableBlocks->overview = "Vue d'ensemble du " . $lang->productCommon;
$lang->block->modules['product']->availableBlocks->list = 'Liste ' . $lang->productCommon;
$lang->block->modules['product']->availableBlocks->story = 'Story';
$lang->block->modules['product']->availableBlocks->plan = 'Plan';
$lang->block->modules['product']->availableBlocks->release = 'Release';
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . ' Übersicht';
if($this->config->vision != 'or')
{
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . ' Berichte';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . ' Liste';
$lang->block->modules['product']->availableBlocks->story = 'Story';
$lang->block->modules['product']->availableBlocks->plan = 'Plan';
$lang->block->modules['product']->availableBlocks->release = 'Release';
}
$lang->block->modules['execution'] = new stdclass();
$lang->block->modules['execution']->availableBlocks = new stdclass();
@@ -630,7 +635,7 @@ $lang->block->zentaoclient->edition->linux64 = 'Linux';
$lang->block->zentaoclient->edition->mac64 = 'Mac OS';
$lang->block->guideTabs['flowchart'] = 'Flowchart';
$lang->block->guideTabs['systemMode'] = 'Operating Modes';
//$lang->block->guideTabs['systemMode'] = 'Operating Modes';
$lang->block->guideTabs['visionSwitch'] = 'Interface Switch';
$lang->block->guideTabs['themeSwitch'] = 'Theme Switch';
$lang->block->guideTabs['preference'] = 'Personalized setting';
@@ -655,6 +660,18 @@ $lang->block->visions['lite'] = new stdclass();
$lang->block->visions['lite']->key = 'lite';
$lang->block->visions['lite']->title = 'Operation Management Interface';
$lang->block->visions['lite']->text = "Specially designed for Non-R&D teams, and based on the visual Kanban {$lang->projectCommon} management model.";
if($config->edition == 'ipd')
{
$lang->block->visionTitle = 'The user interface of ZenTao is divided into 【OR & MM Interface】【IPD Interface】 and 【Operation Management Interface】.';
$lang->block->visions['rnd']->title = 'IPD Interface';
$lang->block->visions['rnd']->text = "Doing things right by integrating the program, {$lang->productCommon}, {$lang->projectCommon}, execution,test, etc., and provide the lifecycle {$lang->projectCommon} management solution.";
$lang->block->visions['or'] = new stdclass();
$lang->block->visions['or']->key = 'or';
$lang->block->visions['or']->title = 'OR & MM Interface';
$lang->block->visions['or']->text = "Doing the right thing by integrating RM Hub, requirements, {$lang->productCommon}, roadmap planning, and project initiation, empowering effective requirement and market management.";
}
$lang->block->customModes['light'] = 'Light Mode';
$lang->block->customModes['ALM'] = 'ALM Mode';
+23 -6
View File
@@ -141,6 +141,7 @@ $lang->block->default['waterfall']['project']['6']['grid'] = 4;
$lang->block->default['waterfall']['project']['6']['source'] = 'project';
$lang->block->default['waterfallplus'] = $lang->block->default['waterfall'];
$lang->block->default['ipd'] = $lang->block->default['waterfall'];
$lang->block->default['scrum']['project']['1']['title'] = $lang->projectCommon . '概况';
$lang->block->default['scrum']['project']['1']['block'] = 'scrumoverview';
@@ -425,15 +426,19 @@ $lang->block->modules['waterfall']['index']->availableBlocks->waterfallgantt
$lang->block->modules['waterfall']['index']->availableBlocks->projectdynamic = '最新动态';
$lang->block->modules['waterfallplus']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['ipd']['index'] = $lang->block->modules['waterfall']['index'];
$lang->block->modules['product'] = new stdclass();
$lang->block->modules['product']->availableBlocks = new stdclass();
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . '统计';
$lang->block->modules['product']->availableBlocks->overview = $lang->productCommon . '总览';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . '列表';
$lang->block->modules['product']->availableBlocks->story = "{$lang->SRCommon}列表";
$lang->block->modules['product']->availableBlocks->plan = "计划列表";
$lang->block->modules['product']->availableBlocks->release = '发布列表';
if($this->config->vision != 'or')
{
$lang->block->modules['product']->availableBlocks->statistic = $lang->productCommon . '统计';
$lang->block->modules['product']->availableBlocks->list = $lang->productCommon . '列表';
$lang->block->modules['product']->availableBlocks->story = "{$lang->SRCommon}列表";
$lang->block->modules['product']->availableBlocks->plan = "计划列表";
$lang->block->modules['product']->availableBlocks->release = '发布列表';
}
$lang->block->modules['execution'] = new stdclass();
$lang->block->modules['execution']->availableBlocks = new stdclass();
@@ -630,7 +635,7 @@ $lang->block->zentaoclient->edition->linux64 = 'Linux版';
$lang->block->zentaoclient->edition->mac64 = 'Mac版';
$lang->block->guideTabs['flowchart'] = '流程图';
$lang->block->guideTabs['systemMode'] = '运行模式';
//$lang->block->guideTabs['systemMode'] = '运行模式';
$lang->block->guideTabs['visionSwitch'] = '界面切换';
$lang->block->guideTabs['themeSwitch'] = '主题切换';
$lang->block->guideTabs['preference'] = '个性化设置';
@@ -655,6 +660,18 @@ $lang->block->visions['lite'] = new stdclass();
$lang->block->visions['lite']->key = 'lite';
$lang->block->visions['lite']->title = '运营管理界面';
$lang->block->visions['lite']->text = "专为非研发团队打造,主要以直观、可视化的看板{$lang->projectCommon}管理模型为主。";
if($config->edition == 'ipd')
{
$lang->block->visionTitle = '禅道使用界面分为【需求与市场管理界面】【IPD研发管理界面】和【运营管理界面】。';
$lang->block->visions['rnd']->title = 'IPD研发管理界面';
$lang->block->visions['rnd']->text = "正确的做事,集项目集、{$lang->productCommon}、{$lang->projectCommon}、执行、测试等多维度管理于一体,提供全过程{$lang->projectCommon}管理解决方案。";
$lang->block->visions['or'] = new stdclass();
$lang->block->visions['or']->key = 'or';
$lang->block->visions['or']->title = '需求与市场管理界面';
$lang->block->visions['or']->text = "做正确的事,融合了需求池、需求、{$lang->productCommon}、路标规划、立项等需求与市场管理功能。";
}
$lang->block->customModes['light'] = '轻量管理模式';
$lang->block->customModes['ALM'] = '全生命周期管理模式';
+1 -1
View File
@@ -830,7 +830,7 @@ class blockModel extends model
$params->bugCount['default'] = 20;
$params->bugCount['control'] = 'input';
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
if(helper::hasFeature('risk'))
{
+1 -1
View File
@@ -32,7 +32,7 @@
<div class="tile-title"><?php echo $lang->block->createdCases;?></div>
<div class="tile-amount"><?php echo empty($data['createdCases']) ? 0 : html::a($this->createLink('my', 'contribute', 'mode=testcase&type=openedbyme'), (int)$data['createdCases']);?></div>
</div>
<?php if($this->config->edition == 'max'):?>
<?php if($this->config->edition == 'max' or $this->config->edition == 'ipd'):?>
<?php if(helper::hasFeature('risk')):?>
<div class="col-xs-4 tile">
<div class="tile-title"><?php echo $lang->block->createdRisks;?></div>
+3 -1
View File
@@ -87,7 +87,7 @@
<th class='w-120px'><?php echo $lang->my->storyConcept;?></th>
<td><?php echo html::select('URSR', $URSRList, $URSR, "class='form-control picker URSR'");?></td>
</tr>
<?php if($this->config->systemMode == 'ALM'):?>
<?php if(in_array($config->systemMode, array('ALM', 'PLM'))):?>
<tr>
<th><?php echo $lang->my->programLink;?></th>
<td><?php echo html::select('programLink', $lang->my->programLinkList, $programLink, "class='form-control picker programLink'");?></td>
@@ -97,6 +97,7 @@
<th><?php echo $lang->my->productLink;?></th>
<td><?php echo html::select('productLink', $lang->my->productLinkList, $productLink, "class='form-control picker productLink'");?></td>
</tr>
<?php if($config->vision != 'or'):?>
<tr>
<th><?php echo $lang->my->projectLink;?></th>
<td><?php echo html::select('projectLink', $lang->my->projectLinkList, $projectLink, "class='form-control picker projectLink'");?></td>
@@ -105,6 +106,7 @@
<th><?php echo $lang->my->executionLink;?></th>
<td><?php echo html::select('executionLink', $lang->my->executionLinkList, $executionLink, "class='form-control picker executionLink'");?></td>
</tr>
<?php endif;?>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
+3
View File
@@ -13,7 +13,10 @@
<div class='vision-switch'>
<p><?php echo $lang->block->visionTitle;?></p>
<div class="vision-switch-container">
<?php if($config->edition == 'ipd') $lang->block->visions = array('or' => $lang->block->visions['or']) + $lang->block->visions;?>
<?php $userVisions = explode(',', $app->user->visions);?>
<?php foreach($lang->block->visions as $vision):?>
<?php if(!in_array($vision->key, $userVisions)) continue;?>
<?php $active = $this->config->vision == $vision->key ? 'active' : '';?>
<a href="<?php echo $this->createLink('my', 'ajaxSwitchVision', "vision=$vision->key");?>" data-type="ajax" class='vision <?php echo $active;?>' data-value="<?php echo $vision->key;?>">
<div class='vision-img'>
+3 -2
View File
@@ -398,7 +398,7 @@ class bug extends control
$this->dao->update(TABLE_TODO)->set('status')->eq('done')->where('id')->eq($output['todoID'])->exec();
$this->action->create('todo', $output['todoID'], 'finished', '', "BUG:$bugID");
if($this->config->edition == 'biz' || $this->config->edition == 'max')
if($this->config->edition != 'open')
{
$todo = $this->dao->select('type, idvalue')->from(TABLE_TODO)->where('id')->eq($output['todoID'])->fetch();
if($todo->type == 'feedback' && $todo->idvalue) $this->loadModel('feedback')->updateStatus('todo', $todo->idvalue, 'done');
@@ -1189,7 +1189,8 @@ class bug extends control
$this->view->branchOption = $branchOption;
$this->view->branchTagOption = $branchTagOption;
$this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution);
$this->view->users = $this->user->getPairs('', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->testtasks = $this->loadModel('testtask')->getPairs($bug->product, $bug->execution, $bug->testtask);
$this->view->users = $this->user->getPairs('noclosed', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->assignedToList = $assignedToList;
$this->view->cases = array('' => '') + $cases;
$this->view->actions = $this->action->getList('bug', $bugID);
-1
View File
@@ -29,7 +29,6 @@ th.c-confirmed {text-align: center;}
body {margin-bottom: 25px;}
#mainMenu .btn-toolbar .btn-group .dropdown-menu .btn-active-text:hover .text {color: #fff;}
#mainMenu .btn-toolbar .btn-group .dropdown-menu .btn-active-text:hover .text:after {border-bottom: unset;}
.btn-group a i.icon-plus {font-size: 16px;}
.btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.3);}
.btn-group button.dropdown-toggle.btn-primary {padding:6px;}
#bugForm tbody tr td .label {max-width: 100px; text-overflow: unset;}
+5 -11
View File
@@ -800,7 +800,7 @@ class bugModel extends model
if($bug->execution and $bug->status != $oldBug->status) $this->loadModel('kanban')->updateLane($bug->execution, 'bug');
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
if($this->config->edition != 'open' && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
$this->file->processFile4Object('bug', $oldBug, $bug);
return common::createChanges($oldBug, $bug);
@@ -912,9 +912,6 @@ class bugModel extends model
unset($bug);
}
$isBiz = $this->config->edition == 'biz';
$isMax = $this->config->edition == 'max';
/* Update bugs. */
foreach($bugs as $bugID => $bug)
{
@@ -937,7 +934,7 @@ class bugModel extends model
$allChanges[$bugID] = common::createChanges($oldBug, $bug);
if(($isBiz || $isMax) && $oldBug->feedback && !isset($feedbacks[$oldBug->feedback]))
if($this->config->edition != 'open' && $oldBug->feedback && !isset($feedbacks[$oldBug->feedback]))
{
$feedbacks[$oldBug->feedback] = $oldBug->feedback;
$this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
@@ -1242,7 +1239,7 @@ class bugModel extends model
/* Link bug to build and release. */
$this->linkBugToBuild($bugID, $bug->resolvedBuild);
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
if($this->config->edition != 'open' && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
return common::createChanges($oldBug, $bug);
}
@@ -1368,9 +1365,6 @@ class bugModel extends model
$modules = array();
while($module = $stmt->fetch()) $modules[$module->id] = $module;
$isBiz = $this->config->edition == 'biz';
$isMax = $this->config->edition == 'max';
$changes = array();
foreach($bugIDList as $i => $bugID)
{
@@ -1417,7 +1411,7 @@ class bugModel extends model
if($oldBug->execution) $this->loadModel('kanban')->updateLane($oldBug->execution, 'bug');
$changes[$bugID] = common::createChanges($oldBug, $bug);
if(($isBiz || $isMax) && $oldBug->feedback && !isset($feedbacks[$oldBug->feedback]))
if($this->config->edition != 'open' && $oldBug->feedback && !isset($feedbacks[$oldBug->feedback]))
{
$feedbacks[$oldBug->feedback] = $oldBug->feedback;
$this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
@@ -1532,7 +1526,7 @@ class bugModel extends model
if(isset($output['toColID'])) $this->kanban->moveCard($bugID, $output['fromColID'], $output['toColID'], $output['fromLaneID'], $output['toLaneID']);
}
if(($this->config->edition == 'biz' || $this->config->edition == 'max') && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
if($this->config->edition != 'open' && $oldBug->feedback) $this->loadModel('feedback')->updateStatus('bug', $oldBug->feedback, $bug->status, $oldBug->status);
return common::createChanges($oldBug, $bug);
}
+1 -1
View File
@@ -13,7 +13,7 @@
<?php include '../../common/view/header.html.php';?>
<?php
if($this->config->edition == 'biz' || $this->config->edition == 'max')
if($this->config->edition != 'open')
{
$action = $this->loadModel('workflowaction')->getByModuleAndAction('bug', 'batchactivate');
if($action->js) echo "<script>{$action->js}</script>";
-1
View File
@@ -20,7 +20,6 @@ js::set('batchDelete', $lang->testcase->confirmBatchDelete);
js::set('flow', $config->global->flow);
?>
<style>
.btn-group a i.icon-plus {font-size: 16px;}
.btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.2);}
.btn-group button.dropdown-toggle.btn-primary {padding:6px;}
</style>
+1 -1
View File
@@ -34,7 +34,7 @@
}
?>
</div>
<?php if($this->config->edition == 'biz' or $this->config->edition == 'max'):?>
<?php if($this->config->edition != 'open'):?>
<div class='btn-toolbar pull-right child-position'>
<?php common::printLink('chart', 'export', '', "<i class='icon icon-export muted'> </i> " . $lang->export, '', "class='btn btn-link btn-export' id='exportchart'");?>
<?php common::printLink('chart', 'browse', '', $lang->chart->toDesign, '', "class='btn btn-primary '");?>
+2 -1
View File
@@ -433,7 +433,8 @@ $lang->exportTypeList['all'] = 'Alle';
$lang->exportTypeList['selected'] = 'Ausgewählte';
$lang->visionList = array();
$lang->visionList['rnd'] = 'Full Feature Interface';
$lang->visionList['or'] = 'OR & MM Interface';
$lang->visionList['rnd'] = 'IPD Interface';
$lang->visionList['lite'] = 'Operation Management Interface';
$lang->createObjects['todo'] = 'Todo';
+2 -1
View File
@@ -435,7 +435,8 @@ $lang->exportTypeList['all'] = 'All Data';
$lang->exportTypeList['selected'] = 'Selected Data';
$lang->visionList = array();
$lang->visionList['rnd'] = 'Full Feature Interface';
$lang->visionList['or'] = 'OR & MM Interface';
$lang->visionList['rnd'] = 'IPD Interface';
$lang->visionList['lite'] = 'Operation Management Interface';
$lang->createObjects['todo'] = 'Todo';
+2 -1
View File
@@ -433,7 +433,8 @@ $lang->exportTypeList['all'] = 'Toutes les Données';
$lang->exportTypeList['selected'] = 'Données sélectionnées';
$lang->visionList = array();
$lang->visionList['rnd'] = 'Full Feature Interface';
$lang->visionList['or'] = 'OR & MM Interface';
$lang->visionList['rnd'] = 'IPD Interface';
$lang->visionList['lite'] = 'Operation Management Interface';
$lang->createObjects['todo'] = 'Todo';
+2 -1
View File
@@ -433,7 +433,8 @@ $lang->exportTypeList['all'] = '全部记录';
$lang->exportTypeList['selected'] = '选中记录';
$lang->visionList = array();
$lang->visionList['rnd'] = '研发综合界面';
$lang->visionList['or'] = '需求与市场管理界面';
$lang->visionList['rnd'] = 'IPD研发管理界面';
$lang->visionList['lite'] = '运营管理界面';
$lang->createObjects['todo'] = '待办';
+10 -8
View File
@@ -295,7 +295,7 @@ class commonModel extends model
public function setApproval()
{
$this->config->openedApproval = false;
if($this->config->edition == 'max' && $this->config->vision == 'rnd') $this->config->openedApproval = true;
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') && $this->config->vision == 'rnd') $this->config->openedApproval = true;
}
/**
@@ -992,6 +992,7 @@ class commonModel extends model
{
global $lang;
global $app;
global $config;
$app->loadLang('my');
@@ -1041,7 +1042,7 @@ class commonModel extends model
/* Check whether other preference item under the module have permissions. If yes, point to other methods. */
$moduleLinkList = $currentModule . 'LinkList';
if(!$display and isset($lang->my->$moduleLinkList))
if(!$display and isset($lang->my->$moduleLinkList) and $config->vision != 'or')
{
foreach($lang->my->$moduleLinkList as $key => $linkList)
{
@@ -1057,7 +1058,7 @@ class commonModel extends model
}
/* Check whether other methods under the module have permissions. If yes, point to other methods. */
if($display == false and isset($lang->$currentModule->menu) and !in_array($currentModule, array('program', 'product', 'project', 'execution')))
if($display == false and isset($lang->$currentModule->menu) and !in_array($currentModule, array('program', 'product', 'project', 'execution', 'demandpool')))
{
foreach($lang->$currentModule->menu as $menu)
{
@@ -1081,7 +1082,7 @@ class commonModel extends model
}
/* Check whether the menu of this group have permissions. If yes, point to them. */
if($display == false and isset($lang->$group->menu))
if($display == false and isset($lang->$group->menu) and $config->vision != 'or')
{
foreach($lang->$group->menu as $menu)
{
@@ -1779,13 +1780,13 @@ EOF;
}
if($type == 'button')
{
if($method != 'edit' and $method != 'copy' and $method != 'delete')
if($method == 'edit' or $method == 'copy' or $method == 'delete' or ($method == 'review' and $module == 'charter'))
{
return html::a($link, "<i class='$class'></i> " . "<span class='text'>{$title}</span>", $target, "class='btn btn-link $extraClass' $misc", true);
return html::a($link, "<i class='$class'></i>", $target, "class='btn btn-link $extraClass' title=\"$title\" $misc", false);
}
else
{
return html::a($link, "<i class='$class'></i>", $target, "class='btn btn-link $extraClass' title=\"$title\" $misc", false);
return html::a($link, "<i class='$class'></i> " . "<span class='text'>{$title}</span>", $target, "class='btn btn-link $extraClass' $misc", true);
}
}
else
@@ -2596,11 +2597,12 @@ EOF;
*/
public static function hasPriv($module, $method, $object = null, $vars = '')
{
global $app, $lang;
global $app, $lang, $config;
$module = strtolower($module);
$method = strtolower($method);
parse_str($vars, $params);
if($config->vision == 'or' and $module == 'story') $module = 'requirement';
if(empty($params['storyType']) and $module == 'story' and !empty($app->params['storyType']) and strpos(",story,requirement,", ",{$app->params['storyType']},") !== false) $module = $app->params['storyType'];
if($module == 'story' and !empty($params['storyType']) and strpos(",story,requirement,", ",{$params['storyType']},") !== false) $module = $params['storyType'];
if($module == 'product' and $method == 'browse' and !empty($app->params['storyType']) and $app->params['storyType'] == 'requirement') $method = 'requirement';
+5 -5
View File
@@ -69,19 +69,19 @@ class custom extends control
$this->view->unitList = explode(',', $unitList);
$this->view->defaultCurrency = zget($this->config->$module, 'defaultCurrency', 'CNY');
}
if($module == 'story' and $field == 'reviewRules')
if(($module == 'story' or $module == 'demand') and $field == 'reviewRules')
{
$this->app->loadConfig($module);
$this->view->reviewRule = zget($this->config->$module, 'reviewRules', '1');
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
$this->view->superReviewers = zget($this->config->$module, 'superReviewers', '');
}
if(($module == 'story' or $module == 'testcase') and $field == 'review')
if(($module == 'story' or $module == 'testcase' or $module == 'demand') and $field == 'review')
{
$this->app->loadConfig($module);
$this->loadModel('user');
if($module == 'story')
if($module == 'story' or $module == 'demand')
{
$this->view->depts = $this->loadModel('dept')->getDeptPairs();
@@ -139,7 +139,7 @@ class custom extends control
if(empty($data->defaultCurrency)) return $this->send(array('result' => 'fail', 'message' => $this->lang->custom->defaultNotEmpty));
$this->loadModel('setting')->setItems("system.$module", $data);
}
elseif($module == 'story' and $field == 'review')
elseif(($module == 'story' or $module == 'demand') and $field == 'review')
{
$data = fixer::input('post')
->setDefault('forceReview', '')
@@ -165,7 +165,7 @@ class custom extends control
$this->loadModel('setting')->setItems("system.$module@{$this->config->vision}", $data);
}
elseif($module == 'story' and $field == 'reviewRules')
elseif(($module == 'story' or $module == 'demand') and $field == 'reviewRules')
{
$data = fixer::input('post')->setDefault('superReviewers', '')->join('superReviewers', ',')->get();
$this->loadModel('setting')->setItems("system.$module@{$this->config->vision}", $data);
+1
View File
@@ -254,6 +254,7 @@ $lang->custom->selectProgramTips = "After switching to the Light Mode, in order
$lang->custom->modeList['light'] = 'Light Mode';
$lang->custom->modeList['ALM'] = 'ALM Mode';
$lang->custom->modeList['PLM'] = 'IPD Mode';
$lang->custom->modeIntroductionList['light'] = "Provides the core function of {$lang->projectCommon} management, suitable for small R&D teams";
$lang->custom->modeIntroductionList['ALM'] = 'The concept is more complete and rigorous, and the function is more abundant. It is suitable for medium and large R&D teams';
+2 -1
View File
@@ -187,7 +187,7 @@ $lang->custom->notice->forceReview = '%s review is required for committe
$lang->custom->notice->forceNotReview = "%s review is not required for committers selected.";
$lang->custom->notice->longlife = 'Define stalled bugs.';
$lang->custom->notice->invalidNumberKey = 'The key should be =< 255.';
$lang->custom->notice->invalidStringKey = 'The key should be lowercase letters, numbers or underlines.';
$lang->custom->notice->invalidStringKey = 'The key should be letters, numbers or underlines.';
$lang->custom->notice->cannotSetTimezone = 'date_default_timezone_set does not exist or is disabled. Timezone cannot be set.';
$lang->custom->notice->noClosedBlock = 'You have no blocks that are closed permanently.';
$lang->custom->notice->required = 'The selected field is required.';
@@ -254,6 +254,7 @@ $lang->custom->selectProgramTips = "After switching to the Light Mode, in order
$lang->custom->modeList['light'] = 'Light Mode';
$lang->custom->modeList['ALM'] = 'ALM Mode';
$lang->custom->modeList['PLM'] = 'IPD Mode';
$lang->custom->modeIntroductionList['light'] = "Provides the core function of {$lang->projectCommon} management, suitable for small R&D teams";
$lang->custom->modeIntroductionList['ALM'] = 'The concept is more complete and rigorous, and the function is more abundant. It is suitable for medium and large R&D teams';
+1
View File
@@ -254,6 +254,7 @@ $lang->custom->selectProgramTips = "After switching to the Light Mode, in order
$lang->custom->modeList['light'] = 'Light Mode';
$lang->custom->modeList['ALM'] = 'ALM Mode';
$lang->custom->modeList['PLM'] = 'IPD Mode';
$lang->custom->modeIntroductionList['light'] = "Provides the core function of {$lang->projectCommon} management, suitable for small R&D teams";
$lang->custom->modeIntroductionList['ALM'] = 'The concept is more complete and rigorous, and the function is more abundant. It is suitable for medium and large R&D teams';
+2 -1
View File
@@ -187,7 +187,7 @@ $lang->custom->notice->forceReview = "指定人提交的%s必须评审
$lang->custom->notice->forceNotReview = "指定人提交的%s不需要评审。";
$lang->custom->notice->longlife = 'Bug列表页面的久未处理标签中,列出设置天数之前未处理的Bug。';
$lang->custom->notice->invalidNumberKey = '键值应为不大于255的数字';
$lang->custom->notice->invalidStringKey = '键值应当为小写英文字母、数字或下划线的组合';
$lang->custom->notice->invalidStringKey = '键值应当为大小写英文字母、数字或下划线的组合';
$lang->custom->notice->cannotSetTimezone = 'date_default_timezone_set方法不存在或禁用,不能设置时区。';
$lang->custom->notice->noClosedBlock = '没有永久关闭的区块';
$lang->custom->notice->required = '页面提交时,选中的字段必填';
@@ -254,6 +254,7 @@ $lang->custom->selectProgramTips = "切换到轻量管理模式后,为确保
$lang->custom->modeList['light'] = '轻量级管理模式';
$lang->custom->modeList['ALM'] = '全生命周期管理模式';
$lang->custom->modeList['PLM'] = 'IPD集成产品开发模式';
$lang->custom->modeIntroductionList['light'] = "提供了{$lang->projectCommon}管理的核心功能,适用于小型研发团队";
$lang->custom->modeIntroductionList['ALM'] = '概念更加完整、严谨,功能更加丰富,适用于中大型研发团队';
+9 -9
View File
@@ -731,7 +731,7 @@ class customModel extends model
if(strpos(",$fields,", ",$field,") === false) $fields = "$field,$fields";
}
$requiredFields[$method]['requiredFields'] = $fields;
$requiredFields[$method]['requiredFields'] = trim($fields, ',');
}
}
@@ -889,7 +889,7 @@ class customModel extends model
$enabledScrumFeatures = array();
$disabledScrumFeatures = array();
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
foreach($this->config->custom->scrumFeatures as $scrumFeature)
{
@@ -1048,7 +1048,7 @@ class customModel extends model
*/
public function hasAssetlibData()
{
if($this->config->edition == 'max') return $this->dao->select('*')->from(TABLE_ASSETLIB)->where('deleted')->eq(0)->count();
if($this->config->edition == 'max' or $this->config->edition == 'ipd') return $this->dao->select('*')->from(TABLE_ASSETLIB)->where('deleted')->eq(0)->count();
return false;
}
@@ -1060,7 +1060,7 @@ class customModel extends model
*/
public function hasScrumIssueData()
{
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
return $this->dao->select('t1.*')->from(TABLE_ISSUE)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
@@ -1080,7 +1080,7 @@ class customModel extends model
*/
public function hasScrumRiskData()
{
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
return $this->dao->select('t1.*')->from(TABLE_RISK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
@@ -1100,7 +1100,7 @@ class customModel extends model
*/
public function hasScrumOpportunityData()
{
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
return $this->dao->select('id')->from(TABLE_OPPORTUNITY)->where('execution')->ne('0')->andWhere('deleted')->eq('0')->count();
}
@@ -1115,7 +1115,7 @@ class customModel extends model
*/
public function hasScrumMeetingData()
{
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
return $this->dao->select('id')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_MEETING)->alias('t2')->on('t1.id = t2.project')
@@ -1135,7 +1135,7 @@ class customModel extends model
*/
public function hasScrumAuditplanData()
{
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
return $this->dao->select('id')->from(TABLE_PROJECT)->alias('t1')
->leftJoin(TABLE_AUDITPLAN)->alias('t2')->on('t1.id = t2.project')
@@ -1155,7 +1155,7 @@ class customModel extends model
*/
public function hasScrumProcessData()
{
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
return $this->dao->select('id')->from(TABLE_PROGRAMACTIVITY)->where('execution')->ne('0')->andWhere('deleted')->eq('0')->count();
}
+5 -5
View File
@@ -36,7 +36,7 @@ EOT;
<?php js::set('field', $field)?>
<?php js::set('confirmReviewCase', $lang->custom->notice->confirmReviewCase)?>
<?php js::set('stopSubmit', true)?>
<?php if($module == 'story' and $field == 'review'):?>
<?php if(($module == 'story' or $module == 'demand') and $field == 'review'):?>
<style>
.table-form>tbody>tr>th {width: 120px !important}
.checkbox-primary {margin-bottom: 0px; width: 82px !important;}
@@ -72,7 +72,7 @@ EOT;
<td colspan='4' class='text-center'><?php echo html::submitButton();?></td>
</tr>
</table>
<?php elseif($module == 'story' and $field == 'reviewRules'):?>
<?php elseif(in_array($module, array('story', 'demand')) and $field == 'reviewRules'):?>
<table class='table table-form mw-700px'>
<tr>
<th class='thWidth'><?php echo $lang->custom->reviewRule;?></th>
@@ -87,13 +87,13 @@ EOT;
<td colspan='2' class='text-center'><?php echo html::submitButton();?></td>
</tr>
</table>
<?php elseif(($module == 'story' or $module == 'testcase') and $field == 'review'):?>
<?php elseif(in_array($module, array('story', 'testcase', 'demand')) and $field == 'review'):?>
<table class='table table-form'>
<tr class='reviewBox'>
<th class='thWidth'><?php echo $lang->custom->storyReview;?></th>
<td><?php echo html::radio('needReview', $lang->custom->reviewList, $needReview);?></td>
</tr>
<?php if($module == 'story'):?>
<?php if($module == 'story' or $module == 'demand'):?>
<tr>
<?php $space = ($app->getClientLang() != 'zh-cn' and $app->getClientLang() != 'zh-tw') ? ' ': '';?>
<td colspan='3' class='storyReviewTip<?php if($needReview) echo " hidden"?>'><div><?php echo sprintf($lang->custom->notice->forceReview, $lang->$module->common) . $lang->custom->notice->storyReviewTip;?></td>
@@ -249,7 +249,7 @@ EOT;
</form>
</div>
</div>
<?php if($module == 'story' and $field == 'review'):?>
<?php if(in_array($module, array('story', 'demand')) and $field == 'review'):?>
<script>
$(function()
{
+56 -6
View File
@@ -18,7 +18,7 @@ $(function()
if(result) window.location.href = url;
});
initPager(pageID, recPerPage, recTotal);
initPager(pageID, recPerPage, recTotal, fieldCount);
$('.first-page,.left-page,.last-page,.right-page').click(function()
{
@@ -66,14 +66,61 @@ function queryTableData()
$.post(createLink('dataview', 'ajaxGetTableData'), params,function(resp)
{
resp = JSON.parse(resp);
$('#datas').empty();
$('#datas').append(resp.html);
buildTable(resp);
recTotal = resp.recTotal;
initPager(pageID, recPerPage, recTotal);
recTotal = resp.recTotal;
fieldCount = resp.fieldCount;
initPager(pageID, recPerPage, recTotal, fieldCount);
});
}
/**
* Build dataview data table.
*
* @param object resp
* @return void
*/
function buildTable(resp)
{
var dataview = resp.dataview;
var clientLang = resp.clientLang;
var minWidth = resp.fieldCount * 100 + 'px';
var html = "<table class='table table-bordered' style='min-width:" + minWidth + "'>";
html += "<thead><tr>";
for(var field in resp.fields)
{
var fieldName = dataview?.fieldSettings?.[field]?.name ? dataview.fieldSettings[field].name : field;
if(dataview?.langs)
{
var langs = JSON.parse(dataview.langs);
if(langs) fieldName = langs?.[field]?.[clientLang] ? langs[field][clientLang] : fieldName;
}
html += "<th>" + fieldName + "</th>";
}
html += "</tr></thead>";
html += "<tbody>";
for(var index in resp.datas)
{
var data = resp.datas[index];
html += '<tr>';
for(var field in resp.fields)
{
var tdValue = data?.[field] ? data[field] : 'null';
html += "<td title='" + tdValue + "'>" + tdValue + "</td>";
}
html += '</tr>';
}
html += '</tbody>';
html += '</table>';
$('#datas').empty();
$('#datas').append(html);
}
/**
* Init pager.
*
@@ -83,7 +130,7 @@ function queryTableData()
* @access public
* @return void
*/
function initPager(pageID, recPerPage, recTotal)
function initPager(pageID, recPerPage, recTotal, fieldCount)
{
var pageID = parseInt(pageID);
var recPerPage = parseInt(recPerPage);
@@ -105,6 +152,7 @@ function initPager(pageID, recPerPage, recTotal)
$('.page-number').html('<strong>' + pageID + '</strong>/<strong>' + pageTotal + '</strong>');
$('.first-page').data('page', 1);
$('.left-page').data('page', pageID - 1);
$('.right-page').data('page', pageID + 1);
$('.last-page').data('page', pageTotal);
@@ -112,5 +160,7 @@ function initPager(pageID, recPerPage, recTotal)
$('.first-page,.left-page,.last-page,.right-page').removeClass('disabled');
if(pageID == 1) $('.first-page,.left-page').addClass('disabled');
if(pageID == pageTotal) $('.last-page,.right-page').addClass('disabled');
$('#queryResult').html(viewResult.replace('%s', recTotal).replace('%s', fieldCount));
}
+1 -1
View File
@@ -2,7 +2,7 @@ $(function()
{
var fileName = dataview != '' ? dataview.name : '';
var exportModal = new $.zui.ModalTrigger({url: createLink('dataview', 'export', 'type=query&table=&fileName=' + fileName, '', true), type: 'iframe', width: 900});
document.getElementById('export').addEventListener('click', function(e)
document.getElementById('exportDataview').addEventListener('click', function(e)
{
tryQuery(e);
showModel(exportModal);
+8 -3
View File
@@ -40,7 +40,7 @@ function query(callback) {
$('#querying').addClass('hidden');
if(resp.result !== 'success')
{
$('#export').addClass('hidden');
$('#exportDataview').addClass('hidden');
var message = resp.message.errorInfo ? resp.message.errorInfo[2] : resp.message;
$('.error').removeClass('hidden');
$('.error td').html(message);
@@ -48,7 +48,7 @@ function query(callback) {
}
else
{
$('#export').removeClass('hidden');
$('#exportDataview').removeClass('hidden');
DataStorage.fields = resp.fields;
DataStorage.columns = resp.columns;
DataStorage.rows = resp.rows;
@@ -140,6 +140,7 @@ function saveSettings()
{
var fieldSettings = DataStorage.clone('fieldSettings');
var relatedObject = DataStorage.relatedObject;
var objectFields = DataStorage.objectFields;
for(let index in DataStorage.fields)
{
var relatedTable = $('#relatedTable' + index).val();
@@ -147,7 +148,11 @@ function saveSettings()
fieldSettings[index].object = relatedTable;
fieldSettings[index].field = relatedField;
if(relatedTable != relatedObject[index]) fieldSettings[index].type = 'object';
if(relatedTable != relatedObject[index])
{
fieldSettings[index].type = 'object';
if(typeof(objectFields) != 'undefined' && typeof(objectFields[relatedTable]) != 'undefined' && typeof(objectFields[relatedTable][index]) != 'undefined') fieldSettings[index].type = objectFields[relatedTable][index].type == 'object' ? 'string' : objectFields[relatedTable][index].type;
}
if(relatedTable == relatedObject[index] && fieldSettings[index].type == 'object') fieldSettings[index].type = 'string';
}
+1
View File
@@ -158,6 +158,7 @@ $lang->dataview->error->warningDelete = 'The custom table has been referenced. D
$lang->dataview->querying = 'Querying, please wait...';
$lang->dataview->queryResult = 'Query data in row %s x %s column';
$lang->dataview->viewResult = '%s x %s rows of data';
$lang->dataview->recTotalTip = '<strong> %s </strong> items in total';
$lang->dataview->recPerPageTip = "<strong> %s </strong> items per page <span class='caret'></span>";
+1
View File
@@ -158,6 +158,7 @@ $lang->dataview->error->warningDelete = 'The custom table has been referenced. D
$lang->dataview->querying = 'Querying, please wait...';
$lang->dataview->queryResult = 'Query data in row %s x %s column';
$lang->dataview->viewResult = '%s x %s rows of data';
$lang->dataview->recTotalTip = '<strong> %s </strong> items in total';
$lang->dataview->recPerPageTip = "<strong> %s </strong> items per page <span class='caret'></span>";
+1
View File
@@ -158,6 +158,7 @@ $lang->dataview->error->warningDelete = 'The custom table has been referenced. D
$lang->dataview->querying = 'Querying, please wait...';
$lang->dataview->queryResult = 'Query data in row %s x %s column';
$lang->dataview->viewResult = '%s x %s rows of data';
$lang->dataview->recTotalTip = '<strong> %s </strong> items in total';
$lang->dataview->recPerPageTip = "<strong> %s </strong> items per page <span class='caret'></span>";
+1
View File
@@ -158,6 +158,7 @@ $lang->dataview->error->warningDelete = '中间表已被引用,删除会导致
$lang->dataview->querying = '正在查询,请稍后...';
$lang->dataview->queryResult = '查询到 %s行 x %s列数据';
$lang->dataview->viewResult = '共 %s行 x %s列数据';
$lang->dataview->recTotalTip = '共 <strong> %s </strong> 项';
$lang->dataview->recPerPageTip = "每页 <strong> %s </strong> 项 <span class='caret'></span>";
+48 -4
View File
@@ -61,16 +61,52 @@ class dataviewModel extends model
return $moduleNames;
}
/**
* Get alias names.
*
* @param object $statement
* @param array $moduleNames
* @access public
* @return array
*/
public function getAliasNames($statement, $moduleNames)
{
$aliasNames = array();
if(isset($statement->from))
{
foreach($statement->from as $from)
{
if(isset($moduleNames[$from->table]))
{
$aliasNames[$from->alias] = $from->table;
}
}
}
if(isset($statement->join))
{
foreach($statement->join as $join)
{
if(isset($moduleNames[$join->expr->table]))
{
$aliasNames[$join->expr->alias] = $join->expr->table;
}
}
}
return $aliasNames;
}
/**
* Merge fields.
*
* @param int $dataFields
* @param int $sqlFields
* @param int $moduleNames
* @param array $dataFields
* @param array $sqlFields
* @param array $moduleNames
* @param array $aliasNames
* @access public
* @return void
*/
public function mergeFields($dataFields, $sqlFields, $moduleNames)
public function mergeFields($dataFields, $sqlFields, $moduleNames, $aliasNames = array())
{
$mergeFields = array();
$relatedObject = array();
@@ -94,6 +130,14 @@ class dataviewModel extends model
$relatedObject[$field] = $moduleName;
continue;
}
elseif(isset($aliasNames[$table]))
{
$moduleName = $aliasNames[$table];
if(strpos($moduleName, 'flow_') !== false) $moduleName = substr($moduleName, 5);
$mergeFields[$field] = isset($this->lang->$moduleName->$fieldName) ? $this->lang->$moduleName->$fieldName : $field;
$relatedObject[$field] = $moduleName;
continue;
}
}
if(strpos(join(',', $sqlFields), '.*') !== false)
+8 -4
View File
@@ -14,11 +14,13 @@
<?php js::set('table', $selectedTable);?>
<?php js::set('type', $type);?>
<?php js::set('dataview', $dataview);?>
<?php js::set('fieldCount', count($fields));?>
<?php js::set('warningDesign', $lang->dataview->error->warningDesign);?>
<?php js::set('viewResult', $lang->dataview->viewResult);?>
<?php js::set('pageID', 1);?>
<?php js::set('recPerPage', 25);?>
<?php js::set('recTotal', $dataCount);?>
<?php js::set('pageID', $pageID);?>
<?php js::set('recPerPage', $recPerPage);?>
<?php js::set('recTotal', $recTotal);?>
<?php js::set('recTotalTip', $lang->dataview->recTotalTip);?>
<?php js::set('recPerPageTip', $lang->dataview->recPerPageTip);?>
@@ -112,7 +114,8 @@
<?php foreach($data as $value):?>
<?php echo '<tr>';?>
<?php foreach($fields as $key => $field):?>
<td title='<?php echo isset($value->$key) ? $value->$key : 'null';?>'><?php echo isset($value->$key) ? $value->$key : 'null';?></td>
<?php $tdValue = isset($value->$key) ? $value->$key : 'null';?>
<td title='<?php echo $tdValue;?>'><?php echo $tdValue;?></td>
<?php endforeach;?>
<?php echo '</tr>';?>
<?php endforeach;?>
@@ -159,6 +162,7 @@
<a class='pager-item' data-page='1' href='javascript:;'><i class='icon icon-last-page'></i></a>
</li>
</ul>
<span style="float:left;line-height:28px" id="queryResult"></span>
</div>
<?php endif;?>
</div>
+2 -2
View File
@@ -32,8 +32,8 @@
<div class='btn-active-text'>
<span class='text'><?php echo $lang->dataview->result;?></span>
<button type="button" class="btn btn-link fieldSettings pull-right"><i class='icon icon-cog-outline'></i> <?php echo $lang->dataview->fieldSettings;?></button>
<?php if(common::hasPriv('dataview', 'export')):?>
<button type="button" id='export' class="btn btn-link hidden dataview-export pull-right"><i class='icon icon-export'></i> <?php echo $lang->dataview->export;?></button>
<?php if($this->app->rawModule == 'dataview' and common::hasPriv('dataview', 'export')):?>
<button type="button" id='exportDataview' class="btn btn-link hidden dataview-export pull-right"><i class='icon icon-export'></i> <?php echo $lang->dataview->export;?></button>
<?php endif;?>
</div>
</div>
+1 -1
View File
@@ -91,7 +91,7 @@ class design extends control
/* Print top and right actions. */
$this->lang->TRActions = '<div class="btn-toolbar pull-right">';
if($this->config->edition == 'max' and common::hasPriv('design', 'submit'))
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') and common::hasPriv('design', 'submit'))
{
$this->lang->TRActions .= '<div class="btn-group">';
$this->lang->TRActions .= html::a($this->createLink('design', 'submit', "productID=$productID", '', true), "<i class='icon-plus'></i> {$this->lang->design->submit}", '', "class='btn btn-secondary iframe'");
+1 -1
View File
@@ -405,7 +405,7 @@ class designModel extends model
public function setMenu($projectID, $products, $productID = 0)
{
$project = $this->loadModel('project')->getByID($projectID);
if(!empty($project) and $project->model == 'waterfall') $typeList = 'typeList';
if(!empty($project) and (in_array($project->model, array('waterfall', 'ipd')))) $typeList = 'typeList';
if(!empty($project) and $project->model == 'waterfallplus') $typeList = 'plusTypeList';
/* Show custom design types. */
-1
View File
@@ -16,7 +16,6 @@
<?php js::set('projectID', $projectID);?>
<?php js::set('productID', $productID);?>
<style>
.btn-group a i.icon-plus {font-size: 16px;}
.btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.3);}
.btn-group button.dropdown-toggle.btn-primary {padding:6px;}
</style>
+2 -1
View File
@@ -962,8 +962,9 @@ class doc extends control
$docs = $this->dao->select('id, title')->from(TABLE_DOC)
->where('lib')->eq($libID)
->andWhere('deleted')->eq(0)
->andWhere('status')->eq('normal')
->andWhere('id')->in($docIdList)
->orderBy('`order` asc')
->orderBy('`id` desc')
->fetchPairs();
return print(html::select('doc', array('' => '') + $docs, '', "class='form-control chosen'"));
+9 -2
View File
@@ -16,7 +16,7 @@ $(function()
$('#modalBasicInfo #copyTitle').html($('.doc-title #editorTitle').val().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"));
});
$('#saveDraft').click(function()
$('#saveDraft').click(function(event)
{
if($.trim($('#editorTitle').val()) == '')
{
@@ -24,9 +24,16 @@ $(function()
return false;
}
$('#status').val('draft');
event.preventDefault();
submit(this);
});
$('#releaseBtn').click(function(){submit(this);});
$('#releaseBtn').click(function(event)
{
event.preventDefault();
submit(this);
});
$('#basicInfoLink').click(function()
{
if($('#editorTitle').val() == '')
+7 -7
View File
@@ -848,11 +848,11 @@ class docModel extends model
*/
public function getByIdList($docIdList = array())
{
return $this->dao->select('*,t1.id as docID,t1.type as docType,t2.type as contentType')->from(TABLE_DOC)->alias('t1')
return $this->dao->select('*,t1.id as docID,t1.type as docType,t1.version as docVersion,t2.type as contentType')->from(TABLE_DOC)->alias('t1')
->leftJoin(TABLE_DOCCONTENT)->alias('t2')->on('t1.id=t2.doc and t1.version=t2.version')
->where('t1.id')->in($docIdList)
->andWhere('deleted')->eq(0)
->fetchAll('id');
->fetchAll('docID');
}
@@ -1692,11 +1692,11 @@ class docModel extends model
if($append and !isset($products[$append])) $products[$append] = $this->product->getByID($append);
foreach($products as $id => $product)
{
if($product->status == 'normal' and $product->PO == $this->app->user->account)
if($product->status != 'closed' and $product->PO == $this->app->user->account)
{
$myObjects[$id] = $product->name;
}
elseif($product->status == 'normal' and !($product->PO == $this->app->user->account))
elseif($product->status != 'closed' and !($product->PO == $this->app->user->account))
{
$normalObjects[$id] = $product->name;
}
@@ -1902,7 +1902,7 @@ class docModel extends model
$projectIDList = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($objectID)->orWhere('project')->eq($objectID)->fetchPairs('id', 'id');
$storyIDList = $this->dao->select('story')->from(TABLE_PROJECTSTORY)->where('project')->in($projectIDList)->fetchPairs('story', 'story');
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$issueIdList = $this->dao->select('id')->from(TABLE_ISSUE)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
$meetingIdList = $this->dao->select('id')->from(TABLE_MEETING)->where('project')->eq($objectID)->andWhere('deleted')->eq('0')->andWhere('project')->in($this->app->user->view->projects)->get();
@@ -3242,7 +3242,7 @@ class docModel extends model
if(!common::hasPriv('doc', 'create') or !isset($lib->id)) return null;
$objectID = zget($lib, $lib->type, 0);
$templateParam = $this->config->edition == 'max' ? '&from=template' : '';
$templateParam = ($this->config->edition == 'max' or $this->config->edition == 'ipd') ? '&from=template' : '';
$class = $from == 'list' ? 'btn-info' : 'btn-primary';
$html = "<div class='dropdown btn-group createDropdown'>";
$html .= html::a(helper::createLink('doc', 'create', "objectType={$lib->type}&objectID=$objectID&libID={$lib->id}&moduleID=$moduleID&type=html$templateParam"), "<i class='icon icon-plus'></i> {$this->lang->doc->create}", '', "class='btn $class' data-app='{$this->app->tab}'");
@@ -3256,7 +3256,7 @@ class docModel extends model
$attr = "data-app='{$this->app->tab}'";
$class = strpos($this->config->doc->officeTypes, $typeKey) !== false ? 'iframe' : '';
$params = "objectType={$lib->type}&objectID=$objectID&libID={$lib->id}&moduleID=$moduleID&type=$typeKey";
if($typeKey == 'template' and $this->config->edition == 'max') $params = "objectType={$lib->type}&objectID=$objectID&libID={$lib->id}&moduleID=$moduleID&type=html&from=template";
if($typeKey == 'template' and ($this->config->edition == 'max' or $this->config->edition == 'ipd')) $params = "objectType={$lib->type}&objectID=$objectID&libID={$lib->id}&moduleID=$moduleID&type=html&from=template";
$html .= "<li>";
$html .= html::a(helper::createLink('doc', 'create', $params, '', $class ? true : false), $icon . ' ' . $typeName, '', "class='$class' $attr");
+2 -2
View File
@@ -46,7 +46,7 @@
<a data-url="<?php echo $this->createLink('doc', 'collect', "objectID=$doc->id&objectType=doc");?>" title="<?php echo $lang->doc->collect;?>" class='ajaxCollect btn btn-link'><?php echo html::image("static/svg/{$star}.svg", "class='$star'");?></a>
<?php endif;?>
<?php if($config->vision == 'rnd' and $config->edition == 'max' and $app->tab == 'project'):?>
<?php if($config->vision == 'rnd' and ($config->edition == 'max' or $config->edition == 'ipd') and $app->tab == 'project'):?>
<?php
$canImportToPracticeLib = (common::hasPriv('doc', 'importToPracticeLib') and helper::hasFeature('practicelib'));
$canImportToComponentLib = (common::hasPriv('doc', 'importToComponentLib') and helper::hasFeature('componentlib'));
@@ -214,7 +214,7 @@
</div>
</div>
<?php if($this->config->edition == 'max'):?>
<?php if($config->edition == 'max' or $config->edition == 'ipd'):?>
<div class="modal fade" id="importToPracticeLib">
<div class="modal-dialog mw-500px">
<div class="modal-content">
+30 -14
View File
@@ -1896,7 +1896,7 @@ class execution extends control
$this->view->code = $code;
$this->view->team = $team;
$this->view->teams = array(0 => '') + $this->execution->getCanCopyObjects((int)$projectID);
$this->view->allProjects = array(0 => '') + $this->project->getPairsByModel('all', 0, 'noclosed,multiple');
$this->view->allProjects = array(0 => '') + $this->project->getPairsByModel("scrum,agileplus,waterfall,waterfallplus,kanban", 0, 'noclosed,multiple');
$this->view->copyProjects = $copyProjects;
$this->view->copyExecutions = array('' => '') + $this->execution->getList($copyProjectID, 'all', 'all', 0, 0, 0, null, false);
$this->view->executionID = $executionID;
@@ -1916,7 +1916,7 @@ class execution extends control
$this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed');
$this->view->copyExecution = isset($copyExecution) ? $copyExecution : '';
$this->view->from = $this->app->tab;
$this->view->isStage = (isset($project->model) and ($project->model == 'waterfall' or $project->model == 'waterfallplus')) ? true : false;
$this->view->isStage = (isset($project->model) and (in_array($project->model, array('waterfall', 'waterfallplus', 'ipd'))));
$this->view->project = $project;
$this->view->division = !empty($project) ? $project->division : 1;
$this->view->type = $type;
@@ -2101,7 +2101,7 @@ class execution extends control
$project = $this->project->getById($execution->project);
if(!$project->hasProduct) $this->lang->execution->PO = $this->lang->common->story . $this->lang->execution->owner;
if($project->model == 'waterfall' or $project->model == 'waterfallplus')
if(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd')))
{
$parentStage = $this->project->getByID($execution->parent, 'stage');
@@ -2182,6 +2182,7 @@ class execution extends control
$this->project->setMenu($projectID);
$this->view->project = $project;
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->lang->execution->common = $this->lang->execution->stage;
if($project->model == 'ipd') $this->config->execution->customBatchEditFields = 'days,teamname,desc,PO,QD,PM,RD';
}
else
{
@@ -2490,7 +2491,7 @@ class execution extends control
if(dao::isError()) return print(js::error(dao::getError()));
$project = $this->loadModel('project')->getById($execution->project);
if($project->model == 'waterfall' or $project->model == 'waterfallplus') $this->loadModel('programplan')->computeProgress($executionID, 'close');
if(in_array($project->model, array('waterfall', 'waterfallplus', 'ipd'))) $this->loadModel('programplan')->computeProgress($executionID, 'close');
$this->executeHooks($executionID);
if(isonlybody() and $from == 'kanban')
@@ -3404,10 +3405,11 @@ class execution extends control
* @param int $recPerPage
* @param int $pageID
* @param string $extra
* @param string $storyType
* @access public
* @return void
*/
public function linkStory($objectID = 0, $browseType = '', $param = 0, $recTotal = 0, $recPerPage = 50, $pageID = 1, $extra = '')
public function linkStory($objectID = 0, $browseType = '', $param = 0, $recTotal = 0, $recPerPage = 50, $pageID = 1, $extra = '', $storyType = 'story')
{
$this->loadModel('story');
$this->loadModel('product');
@@ -3420,7 +3422,7 @@ class execution extends control
/* Transfer object id when version lite */
if($this->config->vision == 'lite')
{
$kanban = $this->project->getByID($objectID, 'kanban');
$kanban = $this->project->getByID($objectID, 'kanban');
$objectID = $kanban->project;
}
@@ -3429,7 +3431,7 @@ class execution extends control
$products = $this->product->getProducts($objectID);
$queryID = ($browseType == 'bySearch') ? (int)$param : 0;
$browseLink = $this->session->executionStoryList;
if($this->app->tab == 'project' and $object->multiple) $browseLink = $this->createLink('projectstory', 'story', "objectID=$objectID");
if($this->app->tab == 'project' and $object->multiple and !$browseLink) $browseLink = $this->createLink('projectstory', 'story', "objectID=$objectID&productID=0&branch=0&browseType=&param=0&storyType=$storyType");
if($object->type == 'kanban' && !$object->hasProduct) $this->lang->productCommon = $this->lang->project->common;
$this->session->set('storyList', $this->app->getURI(true), $this->app->tab); // Save session.
@@ -3443,8 +3445,8 @@ class execution extends control
if(!empty($_POST))
{
if($object->type != 'project' and $object->project != 0) $this->execution->linkStory($object->project);
$this->execution->linkStory($objectID, array(), array(), $extra);
if($object->type != 'project' and $object->project != 0) $this->execution->linkStory($object->project, array(), array(), '', array(), $storyType);
$this->execution->linkStory($objectID, array(), array(), $extra, array(), $storyType);
if(isonlybody())
{
@@ -3515,21 +3517,29 @@ class execution extends control
}
}
if($storyType == 'requirement')
{
$this->lang->story->title = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->title);
$this->lang->projectstory->whyNoStories = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->projectstory->whyNoStories);
$this->lang->execution->linkStory = str_replace($this->lang->SRCommon, $this->lang->URCommon, $this->lang->story->linkStory);
}
/* Build the search form. */
$actionURL = $this->createLink($this->app->rawModule, 'linkStory', "objectID=$objectID&browseType=bySearch&queryID=myQueryID");
$actionURL = $this->createLink($this->app->rawModule, 'linkStory', "objectID=$objectID&browseType=bySearch&queryID=myQueryID&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID&storyType=$storyType");
$branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
$this->execution->buildStorySearchForm($products, $branchGroups, $modules, $queryID, $actionURL, 'linkStory', $object);
$this->execution->buildStorySearchForm($products, $branchGroups, $modules, $queryID, $actionURL, 'linkStory', $object, $storyType);
if($browseType == 'bySearch')
{
$allStories = $this->story->getBySearch('', '', $queryID, 'id', $objectID);
$allStories = $this->story->getBySearch('', '', $queryID, 'id', $objectID, $storyType);
}
else
{
$allStories = $this->story->getProductStories(array_keys($products), $branchIDList, $moduleID = '0', $status = 'active', 'story', 'id_desc', $hasParent = false, '', $pager = null);
$status = $storyType == 'story' ? 'active' : 'launched';
$allStories = $this->story->getProductStories(array_keys($products), $branchIDList, $moduleID = '0', $status, $storyType, 'id_desc', $hasParent = false, '', $pager = null);
}
$linkedStories = $this->story->getExecutionStoryPairs($objectID);
$linkedStories = $this->story->getExecutionStoryPairs($objectID, 0, 'all', 0, 'full', 'all', $storyType);
foreach($allStories as $id => $story)
{
if(isset($linkedStories[$story->id])) unset($allStories[$id]);
@@ -3568,6 +3578,8 @@ class execution extends control
$this->view->branchGroups = $branchGroups;
$this->view->browseLink = $browseLink;
$this->view->project = $project;
$this->view->storyType = $storyType;
if($this->config->edition == 'ipd') $this->view->roadmaps = $this->loadModel('roadmap')->getPairs(array_keys($products));
$this->display();
}
@@ -3589,6 +3601,10 @@ class execution extends control
if($confirm == 'no')
{
$tip = $this->app->rawModule == 'projectstory' ? $this->lang->execution->confirmUnlinkExecutionStory : $this->lang->execution->confirmUnlinkStory;
$story = $this->loadModel('story')->getByID($storyID);
if($story->type == 'requirement') $tip = str_replace($this->lang->SRCommon, $this->lang->URCommon, $tip);
return print(js::confirm($tip, $this->createLink('execution', 'unlinkstory', "executionID=$executionID&storyID=$storyID&confirm=yes&from=$from&laneID=$laneID&columnID=$columnID")));
}
else
+14
View File
@@ -0,0 +1,14 @@
$(function()
{
$('#navbar .nav li').removeClass('active');
$("#navbar .nav li[data-id=" + storyType + ']').addClass('active');
$('#subNavbar li[data-id="' + storyType + '"]').addClass('active');
if($('#navbar .nav>li[data-id=story] .dropdown-menu').length)
{
$('#navbar .nav li[data-id=story]').addClass('active');
$("#navbar>ul>li[data-id='story']>ul>li[data-id!='" + storyType + "']").removeClass('active');
$("#navbar>ul>li[data-id='story']>ul>li[data-id='" + storyType + "']").addClass('active');
$('#navbar .nav>li[data-id=story]>a').html($('#navbar .nav li.active [data-id=' + storyType + ']').text() + '<span class="caret"></span>');
}
})
+79 -23
View File
@@ -440,7 +440,7 @@ class executionModel extends model
if(!empty($sprint->percent) and isset($this->config->setPercent) and $this->config->setPercent == 1) $this->checkWorkload('create', $sprint->percent, $sprint->project);
/* Set planDuration and realDuration. */
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$sprint->planDuration = $this->loadModel('programplan')->getDuration($sprint->begin, $sprint->end);
if(!empty($sprint->realBegan) and !empty($sprint->realEnd)) $sprint->realDuration = $this->loadModel('programplan')->getDuration($sprint->realBegan, $sprint->realEnd);
@@ -632,7 +632,7 @@ class executionModel extends model
if(!empty($execution->percent) and isset($this->config->setPercent) and $this->config->setPercent == 1) $this->checkWorkload('update', $execution->percent, $oldExecution);
/* Set planDuration and realDuration. */
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$execution->planDuration = $this->loadModel('programplan')->getDuration($execution->begin, $execution->end);
if(!empty($execution->realBegan) and !empty($execution->realEnd)) $execution->realDuration = $this->programplan->getDuration($execution->realBegan, $execution->realEnd);
@@ -1760,7 +1760,7 @@ class executionModel extends model
->beginIF($status == 'undone')->andWhere('t2.status')->notIN('done,closed')->fi()
->beginIF($branch)->andWhere('t1.branch')->eq($branch)->fi()
->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi()
->beginIF(!$this->app->user->admin)->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->beginIF(!$this->app->user->admin and isset($this->app->user->view))->andWhere('t2.id')->in($this->app->user->view->sprints)->fi()
->beginIF(!$withChildren)->andWhere('grade')->eq(1)->fi()
->orderBy('order_desc')
->page($pager)
@@ -1777,7 +1777,7 @@ class executionModel extends model
->beginIF($projectID)->andWhere('project')->eq($projectID)->fi()
->beginIF($status == 'undone')->andWhere('status')->notIN('done,closed')->fi()
->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi()
->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi()
->beginIF(!$this->app->user->admin and isset($this->app->user->view))->andWhere('id')->in($this->app->user->view->sprints)->fi()
->beginIF(!$withChildren)->andWhere('grade')->eq(1)->fi()
->orderBy('order_desc')
->page($pager)
@@ -2709,10 +2709,11 @@ class executionModel extends model
* @param string $actionURL
* @param string $type
* @param object $execution
* @param string $storyType
* @access public
* @return void
*/
public function buildStorySearchForm($products, $branchGroups, $modules, $queryID, $actionURL, $type = 'executionStory', $execution = null)
public function buildStorySearchForm($products, $branchGroups, $modules, $queryID, $actionURL, $type = 'executionStory', $execution = null, $storyType = 'story')
{
$this->app->loadLang('branch');
$branchPairs = array(BRANCH_MAIN => $this->lang->branch->main);
@@ -2739,10 +2740,7 @@ class executionModel extends model
}
/* Build search form. */
if($type == 'executionStory')
{
$this->config->product->search['module'] = 'executionStory';
}
if($type == 'executionStory') $this->config->product->search['module'] = 'executionStory';
$this->config->product->search['fields']['title'] = str_replace($this->lang->SRCommon, $this->lang->SRCommon, $this->lang->story->title);
$this->config->product->search['actionURL'] = $actionURL;
@@ -2770,6 +2768,7 @@ class executionModel extends model
$this->config->product->search['fields']['branch'] = sprintf($this->lang->product->branch, $this->lang->product->branchName[$productType]);
$this->config->product->search['params']['branch']['values'] = array('' => '') + $branchPairs;
}
$this->config->product->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => $this->lang->story->statusList);
$project = $execution;
@@ -2781,6 +2780,16 @@ class executionModel extends model
if($project->model != 'kanban') unset($this->config->product->search['fields']['plan']);
}
if($storyType == 'requirement')
{
unset($this->config->product->search['fields']['plan']);
if($project->model == 'ipd')
{
unset($this->config->product->search['fields']['stage']);
unset($this->config->product->search['fields']['status']);
}
}
$this->loadModel('search')->setSearchParams($this->config->product->search);
}
@@ -3290,11 +3299,12 @@ class executionModel extends model
* @param array $products
* @param string $extra
* @param array $lanes
* @param string $storyType
*
* @access public
* @return bool
*/
public function linkStory($executionID, $stories = array(), $products = array(), $extra = '', $lanes = array())
public function linkStory($executionID, $stories = array(), $products = array(), $extra = '', $lanes = array(), $storyType = 'story')
{
if(empty($executionID)) return false;
if(empty($stories)) $stories = $this->post->stories;
@@ -3340,6 +3350,7 @@ class executionModel extends model
$action = $execution->type == 'project' ? 'linked2project' : 'linked2execution';
if($action == 'linked2execution' and $execution->type == 'kanban') $action = 'linked2kanban';
if($execution->multiple or $execution->type == 'project') $this->action->create('story', $storyID, $action, '', $executionID);
if($storyType == 'requirement' and $execution->model == 'ipd') $this->dao->update(TABLE_STORY)->set('status')->eq('developing')->where('id')->eq($storyID)->exec();
}
if(!isset($output['laneID']) or !isset($output['columnID'])) $this->kanban->updateLane($executionID, 'story');
@@ -3443,6 +3454,7 @@ class executionModel extends model
public function unlinkStory($executionID, $storyID, $laneID = 0, $columnID = 0)
{
$execution = $this->dao->findById($executionID)->from(TABLE_EXECUTION)->fetch();
$storyType = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch('type');
if($execution->type == 'project')
{
$executions = $this->dao->select('*')->from(TABLE_EXECUTION)->where('parent')->eq($executionID)->fetchAll('id');
@@ -3451,6 +3463,9 @@ class executionModel extends model
}
$this->dao->delete()->from(TABLE_PROJECTSTORY)->where('project')->eq($executionID)->andWhere('story')->eq($storyID)->limit(1)->exec();
/* In ipd project, unlink stories change it's status to launched. */
if($execution->model == 'ipd' and $storyType == 'requirement') $this->dao->update(TABLE_STORY)->set('status')->eq('launched')->where('id')->eq($storyID)->exec();
/* Resolve TABLE_KANBANCELL's field cards. */
if($execution->type == 'kanban')
{
@@ -5229,14 +5244,15 @@ class executionModel extends model
/**
* Print execution nested list.
*
* @param object $execution
* @param bool $isChild
* @param array $users
* @param int $execution
* @param int $isChild
* @param int $users
* @param int $productID
* @param string $project
* @access public
* @return void
*/
public function printNestedList($execution, $isChild, $users, $productID)
public function printNestedList($execution, $isChild, $users, $productID, $project = '')
{
$this->loadModel('task');
$this->loadModel('execution');
@@ -5295,18 +5311,28 @@ class executionModel extends model
echo "<td class='status-{$execution->status} text-center'>" . zget($this->lang->project->statusList, $execution->status) . '</td>';
echo '<td>' . zget($users, $execution->PM) . '</td>';
echo helper::isZeroDate($execution->begin) ? '<td class="c-date"></td>' : '<td class="c-date">' . $execution->begin . '</td>';
echo helper::isZeroDate($execution->end) ? '<td class="c-date"></td>' : '<td class="c-date">' . $execution->end . '</td>';
echo helper::isZeroDate($execution->end) ? '<td class="endDate c-date"></td>' : '<td class="endDate c-date">' . $execution->end . '</td>';
echo "<td class='hours text-right' title='{$execution->estimate}{$this->lang->execution->workHour}'>" . $execution->estimate . $this->lang->execution->workHourUnit . '</td>';
echo "<td class='hours text-right' title='{$execution->consumed}{$this->lang->execution->workHour}'>" . $execution->consumed . $this->lang->execution->workHourUnit . '</td>';
echo "<td class='hours text-right' title='{$execution->left}{$this->lang->execution->workHour}'>" . $execution->left . $this->lang->execution->workHourUnit . '</td>';
echo '<td>' . html::ring($execution->progress) . '</td>';
echo "<td id='spark-{$execution->id}' class='sparkline text-left no-padding' values='$burns'></td>";
echo '<td class="c-actions text-center">';
common::printIcon('execution', 'start', "executionID={$execution->id}", $execution, 'list', '', '', 'iframe', true);
echo '<td class="c-actions text-left">';
$title = '';
$disabled = '';
$this->app->loadLang('stage');
if($project and $project->model == 'ipd' and !$isChild)
{
$title = $execution->ipdStage['canStart'] ? '' : sprintf($this->lang->execution->disabledTip->startTip, $this->lang->stage->ipdTypeList[$execution->ipdStage['preAttribute']], $this->lang->stage->ipdTypeList[$execution->attribute]);
$disabled = $execution->ipdStage['canStart'] ? '' : 'disabled';
}
common::printIcon('execution', 'start', "executionID={$execution->id}", $execution, 'list', '', '', 'iframe', true, $disabled, $title);
$class = !empty($execution->children) ? 'disabled' : '';
common::printIcon('task', 'create', "executionID={$execution->id}", '', 'list', '', '', $class, false, "data-app='execution'");
$project = $this->loadModel('project')->getByID($execution->project);
if(empty($project)) $project = $this->loadModel('project')->getByID($execution->project);
if($execution->type == 'stage' or ($this->app->tab == 'project' and !empty($project->model) and $project->model == 'waterfallplus'))
{
$isCreateTask = $this->loadModel('programplan')->isCreateTask($execution->id);
@@ -5326,9 +5352,17 @@ class executionModel extends model
}
$disabled = !empty($execution->children) ? ' disabled' : '';
if($this->config->systemMode == 'PLM' and in_array($execution->attribute, array_keys($this->lang->stage->ipdTypeList))) $disabled = '';
if($execution->status != 'closed' and common::hasPriv('execution', 'close', $execution))
{
common::printIcon('execution', 'close', "stageID=$execution->id", $execution, 'list', 'off', 'hiddenwin' , $disabled . ' iframe', true, '', $this->lang->execution->close);
$ipdDisabled = '';
$title = $this->lang->execution->close;
if(isset($execution->ipdStage['canClose']) and !$execution->ipdStage['canClose'] and !$isChild)
{
$ipdDisabled = ' disabled ';
$title = $execution->attribute == 'launch' ? $this->lang->execution->disabledTip->launchTip : $this->lang->execution->disabledTip->closeTip;
}
common::printIcon('execution', 'close', "stageID=$execution->id", $execution, 'list', 'off', 'hiddenwin' , $disabled . $ipdDisabled . ' iframe', true, '', $title);
}
elseif($execution->status == 'closed' and common::hasPriv('execution', 'activate', $execution))
{
@@ -5347,7 +5381,7 @@ class executionModel extends model
foreach($execution->children as $child)
{
$child->division = $execution->division;
$this->printNestedList($child, true, $users, $productID);
$this->printNestedList($child, true, $users, $productID, $project);
}
}
@@ -5359,6 +5393,12 @@ class executionModel extends model
echo $this->task->buildNestedList($execution, $task, false, $showmore, $users);
}
}
if(!empty($execution->points) and $this->cookie->showStage)
{
$pendingReviews = $this->loadModel('approval')->getPendingReviews('review');
foreach($execution->points as $point) echo $this->buildPointList($execution, $point, $pendingReviews);
}
}
/**
@@ -5434,12 +5474,28 @@ class executionModel extends model
$menu = '';
$params = "executionID=$execution->id";
$this->app->loadLang('stage');
$title = '';
$disabled = '';
$menu .= "<div class='divider'></div>";
$menu .= $this->buildMenu('execution', 'start', $params, $execution, $type, '', '', 'iframe', true);
if($this->config->systemMode == 'PLM' and in_array($execution->attribute, array_keys($this->lang->stage->ipdTypeList)))
{
$execution->ipdStage = $this->canStageStart($execution);
if($execution->ipdStage['canStart']) $menu .= $this->buildMenu('execution', 'start', $params, $execution, $type, '', '', 'iframe', true, $disabled, $title);
}
else
{
$menu .= $this->buildMenu('execution', 'start', $params, $execution, $type, '', '', 'iframe', true, $disabled, $title);
}
$menu .= $this->buildMenu('execution', 'activate', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'putoff', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'suspend', $params, $execution, $type, '', '', 'iframe', true);
$menu .= $this->buildMenu('execution', 'close', $params, $execution, $type, '', '', 'iframe', true);
$canClose = true;
if($this->config->systemMode == 'PLM' and in_array($execution->attribute, array_keys($this->lang->stage->ipdTypeList))) $canClose = $this->canStageClose($execution->id);
if($canClose) $menu .= $this->buildMenu('execution', 'close', $params, $execution, $type, '', '', 'iframe', true);
$menu .= "<div class='divider'></div>";
$menu .= $this->buildFlowMenu('execution', $execution, 'view', 'direct');
@@ -5746,7 +5802,7 @@ class executionModel extends model
{
$label = $execution->type == 'stage' ? 'label-warning' : 'label-info';
$link = $execution->type == 'kanban' ? helper::createLink('execution', 'kanban', "id=$execution->id") : helper::createLink('execution', 'task', "id=$execution->id");
$execution->name = "<span class='project-type-label label label-outline $label'>{$this->lang->execution->typeList[$execution->type]}</span> " . (empty($execution->children) ? html::a($link, $execution->name, '_self', 'class="text-primary"') : $execution->name) . (strtotime($today) > strtotime($execution->end) ? '<span class="label label-danger label-badge">' . $this->lang->execution->delayed . '</span>' : '');;
$execution->name = "<span class='project-type-label label label-outline $label'>{$this->lang->execution->typeList[$execution->type]}</span> " . (empty($execution->children) ? html::a($link, $execution->name, '_self', 'class="text-primary"') : $execution->name) . ((strtotime($today) > strtotime($execution->end) and $execution->status != 'closed')? '<span class="label label-danger label-badge">' . $this->lang->execution->delayed . '</span>' : '');;
$execution->project = $execution->projectName;
$execution->parent = ($execution->parent and $execution->grade > 1) ? $execution->parent : '';
$execution->asParent = !empty($execution->children);
+1 -1
View File
@@ -113,7 +113,7 @@
<?php
if($isStage)
{
echo html::select('attribute', $lang->stage->typeList, '', "class='form-control chosen'");
echo html::select('attribute', $project->model == 'ipd' ? $lang->stage->ipdTypeList : $lang->stage->typeList, '', "class='form-control chosen'");
}
else
{
+5 -3
View File
@@ -87,17 +87,17 @@
</div>
</td>
</tr>
<?php if($project->model == 'waterfall' or $project->model == 'waterfallplus'):?>
<?php if(in_array($project->model, array('waterfall', 'waterfallplus'))):?>
<tr>
<th><?php echo $lang->stage->type;?></th>
<td>
<?php echo $enableOptionalAttr ? html::select('attribute', $lang->stage->typeList, $execution->attribute, "class='form-control chosen'") : zget($lang->stage->typeList, $execution->attribute); ?>
<?php echo $enableOptionalAttr ? html::select('attribute', $project->model == 'ipd' ? $lang->stage->ipdTypeList : $lang->stage->typeList, $execution->attribute, "class='form-control chosen'") : zget($lang->stage->typeList, $execution->attribute); ?>
</td>
<td>
<icon class='icon icon-help' data-toggle='popover' data-trigger='focus hover' data-placement='right' data-tip-class='text-muted popover-sm' data-content="<?php echo $lang->execution->typeTip;?>"></icon>
</td>
</tr>
<?php elseif($execution->type != 'kanban'):?>
<?php elseif($execution->type != 'kanban' and $project->model != 'ipd'):?>
<tr>
<th><?php echo $lang->execution->type;?></th>
<td>
@@ -109,10 +109,12 @@
<th><?php echo $lang->execution->teamname;?></th>
<td><?php echo html::input('team', $execution->team, "class='form-control'");?></td>
</tr>
<?php if($project->model != 'ipd'):?>
<tr>
<th><?php echo $lang->execution->status;?></th>
<td><?php echo html::select('status', $lang->execution->statusList, $execution->status, "class='form-control chosen'");?></td>
</tr>
<?php endif;?>
<tr>
<th rowspan='2'><?php echo $lang->execution->owner;?></th>
<td>
+18 -3
View File
@@ -15,6 +15,7 @@
<style>
.search-form .form-actions {padding-bottom: 10px!important;}
</style>
<?php js::set('storyType', $storyType);?>
<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->execution->linkStory;?></span></span>
@@ -47,19 +48,26 @@
<th class='c-object'><?php echo $lang->story->product;?></th>
<?php endif;?>
<th class='c-module'><?php echo $lang->story->module;?></th>
<th class='c-plan <?php if(empty($project->hasProduct) && $project->model != 'scrum') echo 'hide';?>'><?php echo $lang->story->plan;?></th>
<th class='c-plan <?php if((empty($project->hasProduct) && $project->model != 'scrum') || $storyType != 'story') echo 'hide';?>'><?php echo $lang->story->plan;?></th>
<?php if($object->model == 'ipd' and $storyType == 'requirement'):?>
<th class='c-plan'><?php echo $lang->story->roadmap;?></th>
<th class='c-status'><?php echo $lang->story->status;?></th>
<?php else:?>
<th class='c-stage'><?php echo $lang->story->stage;?></th>
<?php endif;?>
<?php if($project->hasProduct && $productType != 'normal'):?>
<th class='c-branch'><?php echo $lang->product->branchName[$productType];?></th>
<?php endif;?>
<th class='c-user'><?php echo $lang->openedByAB;?></th>
<?php if($storyType != 'requirement'):?>
<th class='c-estimate text-right'><?php echo $lang->story->estimateAB;?></th>
<?php endif;?>
</tr>
</thead>
<tbody>
<?php $storyCount = 0;?>
<?php foreach($allStories as $story):?>
<?php $storyLink = $this->createLink('execution', 'storyView', "storyID=$story->id", '', true);?>
<?php $storyLink = $this->app->tab == 'execution' ? $this->createLink('execution', 'storyView', "storyID=$story->id", '', true) : $this->createLink('projectstory', 'view', "storyID=$story->id", '', true);?>
<tr>
<td class='cell-id'>
<?php echo html::checkbox('stories', array($story->id => sprintf('%03d', $story->id)));?>
@@ -87,13 +95,20 @@
<td class='text-left' title='<?php echo $products[$story->product]->name?>'><?php echo html::a($this->createLink('product', 'browse', "productID=$story->product&branch=$story->branch&browseType=&param=0&storyType=story&orderBy=&recTotal=0&recPerPage=20&pageID=1&projectID={$project->id}"), $products[$story->product]->name);?></td>
<?php endif;?>
<td class='c-module text-left' title='<?php echo zget($modules, $story->module, '')?>'><?php echo zget($modules, $story->module, '')?></td>
<td class='text-ellipsis <?php if(empty($project->hasProduct) && $project->model != 'scrum') echo 'hide';?>' title='<?php echo $story->planTitle;?>'><?php echo $story->planTitle;?></td>
<td class='text-ellipsis <?php if((empty($project->hasProduct) && $project->model != 'scrum') || $storyType != 'story') echo 'hide';?>' title='<?php echo $story->planTitle;?>'><?php echo $story->planTitle;?></td>
<?php if($object->model == 'ipd' and $storyType == 'requirement'):?>
<td title="<?php echo zget($roadmaps, $story->roadmap, '');?>"><?php echo zget($roadmaps, $story->roadmap, '');?></td>
<td><?php echo zget($lang->story->statusList, $story->status);?></td>
<?php else:?>
<td><?php echo zget($lang->story->stageList, $story->stage);?></td>
<?php endif;?>
<?php if($project->hasProduct && $productType != 'normal'):?>
<td><?php if(isset($branchGroups[$story->product][$story->branch])) echo $branchGroups[$story->product][$story->branch];?></td>
<?php endif;?>
<td class='c-user'><?php echo zget($users, $story->openedBy);?></td>
<?php if($storyType != 'requirement'):?>
<td class='text-right c-estimate' title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
<?php endif;?>
</tr>
<?php $storyCount++;?>
<?php endforeach;?>
-1
View File
@@ -30,7 +30,6 @@
<?php js::set('linkedTaskStories', $linkedTaskStories);?>
<?php js::set('confirmStoryToTask', $lang->execution->confirmStoryToTask);?>
<style>
.btn-group a i.icon-plus, .btn-group a i.icon-link {font-size: 16px;}
.btn-group a.btn-secondary, .btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.2);}
.btn-group button.dropdown-toggle.btn-secondary, .btn-group button.dropdown-toggle.btn-primary {padding:6px;}
.export {margin-left: 0px !important;}
-1
View File
@@ -30,7 +30,6 @@ js::set('foldAll', $lang->execution->treeLevel['root']);
?>
<style>
body {margin-bottom: 25px;}
.btn-group a i.icon-plus {font-size: 16px;}
.btn-group a.btn-primary {border-right: 1px solid rgba(255,255,255,0.2);}
.btn-group button.dropdown-toggle.btn-primary {padding:6px;}
</style>
+1 -1
View File
@@ -237,7 +237,7 @@ class group extends control
$changelogs = ',' . join(',', $changelog) . ',';
$this->lang->custom->common = $this->lang->group->config;
if($this->config->edition == 'max' and $this->config->vision == 'rnd' and isset($this->lang->baseline)) $this->lang->baseline->common = $this->lang->group->docTemplate;
if(($this->config->edition == 'max' or $this->config->edition == 'ipd') and $this->config->vision == 'rnd' and isset($this->lang->baseline)) $this->lang->baseline->common = $this->lang->group->docTemplate;
$modules = $this->group->getPrivManagerPairs('module', $menu);
+11 -8
View File
@@ -452,6 +452,7 @@ $lang->resource->product->dynamic = 'dynamic';
$lang->resource->product->project = 'project';
$lang->resource->product->dashboard = 'dashboard';
$lang->resource->product->close = 'closeAction';
$lang->resource->product->activate = 'activateAction';
$lang->resource->product->updateOrder = 'orderAction';
$lang->resource->product->all = 'list';
$lang->resource->product->kanban = 'kanban';
@@ -475,14 +476,16 @@ $lang->product->methodOrder[50] = 'dynamic';
$lang->product->methodOrder[55] = 'project';
$lang->product->methodOrder[60] = 'dashboard';
$lang->product->methodOrder[65] = 'close';
$lang->product->methodOrder[70] = 'updateOrder';
$lang->product->methodOrder[75] = 'all';
$lang->product->methodOrder[80] = 'kanban';
$lang->product->methodOrder[85] = 'manageLine';
$lang->product->methodOrder[90] = 'export';
$lang->product->methodOrder[95] = 'whitelist';
$lang->product->methodOrder[100] = 'addWhitelist';
$lang->product->methodOrder[105] = 'unbindWhitelist';
$lang->product->methodOrder[70] = 'activate';
$lang->product->methodOrder[75] = 'updateOrder';
$lang->product->methodOrder[80] = 'all';
$lang->product->methodOrder[85] = 'kanban';
$lang->product->methodOrder[90] = 'manageLine';
$lang->product->methodOrder[95] = 'build';
$lang->product->methodOrder[100] = 'export';
$lang->product->methodOrder[105] = 'whitelist';
$lang->product->methodOrder[110] = 'addWhitelist';
$lang->product->methodOrder[115] = 'unbindWhitelist';
/* Branch. */
$lang->resource->branch = new stdclass();
+164
View File
@@ -22,6 +22,8 @@ class groupModel extends model
public function create()
{
$group = fixer::input('post')->get();
$group->vision = $this->config->vision;
if(isset($group->limited))
{
unset($group->limited);
@@ -1496,6 +1498,168 @@ class groupModel extends model
die('success');
}
/**
* Super Model: Init views, modules and privileges for IPD.
*
* @access public
* @return bool
*/
public function initPrivs4IPD()
{
$views = array_keys(json_decode(json_encode($this->lang->mainNav), true));
$resources = json_decode(json_encode($this->lang->resource), true);
$hasStoredPrivs = $this->dao->select('*')->from(TABLE_PRIV)->fetchAll('id');
foreach($hasStoredPrivs as $privID => $hasStoredPriv)
{
$hasStoredPrivs["{$hasStoredPriv->module}-{$hasStoredPriv->method}"] = $hasStoredPriv;
unset($hasStoredPrivs[$privID]);
}
$hasStoredManagered = $this->dao->select('*')->from(TABLE_PRIVMANAGER)->where('type')->ne('package')->fetchGroup('type', 'code');
$hasStoredViews = $hasStoredManagered['view'];
$hasStoredModules = $hasStoredManagered['module'];
$viewOrder = 1;
$viewPairs = array();
foreach($views as $view)
{
if($view == 'menuOrder') continue;
if(!empty($hasStoredViews[$view]))
{
$vision = strpos($hasStoredViews[$view]->vision, ",{$this->config->vision},") !== false ? $hasStoredViews[$view]->vision : $hasStoredViews[$view]->vision . "{$this->config->vision},";
$edition = strpos($hasStoredViews[$view]->edition, ",{$this->config->edition},") !== false ? $hasStoredViews[$view]->edition : $hasStoredViews[$view]->edition . "{$this->config->edition},";
$viewID = $hasStoredViews[$view]->id;
$this->dao->update(TABLE_PRIVMANAGER)
->set('vision')->eq($vision)
->set('edition')->eq($edition)
->where('id')->eq($viewID)
->exec();
}
else
{
$viewManager = new stdclass();
$viewManager->parent = 0;
$viewManager->code = $view;
$viewManager->type = 'view';
$viewManager->edition = ',ipd,';
$viewManager->vision = ",{$this->config->vision},";
$viewManager->order = $viewOrder * 10;
$viewOrder ++;
$this->dao->insert(TABLE_PRIVMANAGER)->data($viewManager)->exec();
$viewID = $this->dao->lastInsertId();
foreach($this->config->langs as $lang => $langValue)
{
$viewLang = new stdclass();
$viewLang->objectID = $viewID;
$viewLang->objectType = 'manager';
$viewLang->lang = $lang;
$viewLang->key = $view;
$viewLang->value = '';
$viewLang->desc = '';
$this->dao->insert(TABLE_PRIVLANG)->data($viewLang)->exec();
}
}
$viewPairs[$view] = $viewID;
}
$moduleOrder = 1;
foreach($resources as $module => $privs)
{
if(!empty($hasStoredModules[$module]))
{
$vision = strpos($hasStoredModules[$module]->vision, ",{$this->config->vision},") !== false ? $hasStoredModules[$module]->vision : $hasStoredModules[$module]->vision . "{$this->config->vision},";
$edition = strpos($hasStoredModules[$module]->edition, ",{$this->config->edition},") !== false ? $hasStoredModules[$module]->edition : $hasStoredModules[$module]->edition . "{$this->config->edition},";
$moduleID = $hasStoredModules[$module]->id;
$this->dao->update(TABLE_PRIVMANAGER)
->set('vision')->eq($vision)
->set('edition')->eq($edition)
->where('id')->eq($moduleID)
->exec();
}
else
{
$moduleMenu = isset($this->lang->navGroup->{$module}) ? $this->lang->navGroup->{$module} : '';
$moduleManager = new stdclass();
$moduleManager->parent = $moduleMenu ? $viewPairs[$moduleMenu] : 0;
$moduleManager->code = $module;
$moduleManager->type = 'module';
$moduleManager->edition = ',ipd,';
$moduleManager->vision = ",{$this->config->vision},";
$moduleManager->order = $moduleOrder * 10;
$moduleOrder ++;
$this->dao->insert(TABLE_PRIVMANAGER)->data($moduleManager)->exec();
$moduleID = $this->dao->lastInsertId();
foreach($this->config->langs as $lang => $langValue)
{
$moduleLang = new stdclass();
$moduleLang->objectID = $moduleID;
$moduleLang->objectType = 'manager';
$moduleLang->lang = $lang;
$moduleLang->key = $module;
$moduleLang->value = '';
$moduleLang->desc = '';
$this->dao->insert(TABLE_PRIVLANG)->data($moduleLang)->exec();
}
}
$privOrder = 1;
foreach($privs as $methodName => $methodLang)
{
if(!empty($hasStoredPrivs["$module-$methodName"]))
{
$vision = strpos($hasStoredPrivs["$module-$methodName"]->vision, ",{$this->config->vision},") !== false ? $hasStoredPrivs["$module-$methodName"]->vision : $hasStoredPrivs["$module-$methodName"]->vision . "{$this->config->vision},";
$edition = strpos($hasStoredPrivs["$module-$methodName"]->edition, ",{$this->config->edition},") !== false ? $hasStoredPrivs["$module-$methodName"]->edition : $hasStoredPrivs["$module-$methodName"]->edition . "{$this->config->edition},";
$this->dao->update(TABLE_PRIV)
->set('vision')->eq($vision)
->set('edition')->eq($edition)
->where('id')->eq($hasStoredPrivs["$module-$methodName"]->id)
->exec();
}
else
{
$priv = new stdclass();
$priv->module = $module;
$priv->method = $methodName;
$priv->parent = $moduleID;
$priv->edition = ',ipd,';
$priv->vision = ",{$this->config->vision},";
$priv->system = '1';
$priv->order = $privOrder * 10;
$privOrder ++;
$this->dao->insert(TABLE_PRIV)->data($priv)->exec();
$privID = $this->dao->lastInsertId();
foreach($this->config->langs as $lang => $langValue)
{
$privLang = new stdclass();
$privLang->objectID = $privID;
$privLang->objectType = 'priv';
$privLang->lang = $lang;
$privLang->key = "{$module}-{$methodLang}";
$privLang->value = '';
$privLang->desc = '';
$this->dao->replace(TABLE_PRIVLANG)->data($privLang)->exec();
}
}
}
}
return true;
}
/**
* Get priv by id.
*
+2
View File
@@ -101,6 +101,7 @@
<?php endif;?>
</td>
</tr>
<?php if($config->vision != 'or'):?>
<tr>
<th class='text-right text-top'><?php echo $lang->group->dynamic?></th>
<td class='pl-0px pt-0px'>
@@ -168,6 +169,7 @@
</table>
</td>
</tr>
<?php endif;?>
<tr>
<td colspan='2' class='form-actions text-center'>
<?php echo html::submitButton();?>
+2
View File
@@ -768,6 +768,7 @@ $.extend(
var searchMethod = typeof(types[1]) == 'undefined' ? 'view' : types[1];
var searchLink = createLink(searchModule, searchMethod, "id=" + objectValue);
var assetType = ',story,issue,risk,opportunity,doc,';
if(vision == 'or' && searchModule == 'story') searchLink = createLink(searchModule, searchMethod, "id=" + objectValue + '&version=0&param=0&storyType=requirement');
if(assetType.indexOf(',' + searchModule + ',') > -1)
{
var link = createLink('index', 'ajaxGetViewMethod' , 'objectID=' + objectValue + '&objectType=' + searchModule);
@@ -926,6 +927,7 @@ function changeSearchObject()
if(searchObjectList.indexOf(',' + searchType + ',') == -1) var searchType = 'bug';
if(vision == 'lite') var searchType = 'story';
if(vision == 'or') var searchType = 'demand';
if(searchType == 'program') var searchType = 'program-product';
if(searchType == 'deploystep') var searchType = 'deploy-viewstep';
+1 -1
View File
@@ -42,7 +42,7 @@ js::set('isIntranet', helper::isIntranet());
#menuMoreList > li.active:after {content: attr(data-tip); display: block; position: absolute; left: 100%; background-color: #f1a325; color: #fff; top: 3px; white-space: nowrap; line-height: 16px; padding: 8px 10px; margin-left: 5px; border-radius: 4px;}
<?php endif;?>
<?php if($this->config->vision == 'lite'):?>
<?php if($config->vision == 'lite' or $config->vision == 'or'):?>
#searchbox .dropdown-menu.show-quick-go.with-active {min-height: 180px;}
<?php endif;?>
</style>
+5
View File
@@ -271,6 +271,11 @@ $lang->install->groupList['LITEPROJECT']['desc'] = 'Operation Management Interf
$lang->install->groupList['LITETEAM']['name'] = 'LITETEAM';
$lang->install->groupList['LITETEAM']['desc'] = 'Operation Management Interface Team';
$lang->install->groupList['IPDPRODUCTPLAN']['name'] = 'PRODUCT PLANING';
$lang->install->groupList['IPDDEMAND']['name'] = 'DEMAND ANALYSIS';
$lang->install->groupList['IPDPMT']['name'] = 'IPDPMT';
$lang->install->groupList['IPDADMIN']['name'] = 'IPDADMIN';
$lang->install->cronList[''] = 'Cron Anzeigen';
$lang->install->cronList['moduleName=execution&methodName=computeBurn'] = 'Update Burndown Chart';
$lang->install->cronList['moduleName=report&methodName=remind'] = 'Täglicher Aufgaben reminder';
+5
View File
@@ -271,6 +271,11 @@ $lang->install->groupList['LITEPROJECT']['desc'] = 'Operation Management Interf
$lang->install->groupList['LITETEAM']['name'] = 'LITETEAM';
$lang->install->groupList['LITETEAM']['desc'] = 'Operation Management Interface Team';
$lang->install->groupList['IPDPRODUCTPLAN']['name'] = 'PRODUCT PLANING';
$lang->install->groupList['IPDDEMAND']['name'] = 'DEMAND ANALYSIS';
$lang->install->groupList['IPDPMT']['name'] = 'IPDPMT';
$lang->install->groupList['IPDADMIN']['name'] = 'IPDADMIN';
$lang->install->cronList[''] = 'Monitor Cron';
$lang->install->cronList['moduleName=execution&methodName=computeBurn'] = 'Update Burndown Chart';
$lang->install->cronList['moduleName=report&methodName=remind'] = 'Daily Task Reminder';
+5
View File
@@ -175,6 +175,11 @@ $lang->install->cronList['moduleName=ci&methodName=initQueue'] = 'Tạo
$lang->install->cronList['moduleName=ci&methodName=checkCompileStatus'] = 'Đồng bộ Jenkins tình trạng';
$lang->install->cronList['moduleName=ci&methodName=exec'] = 'Xử lý Jenkins';
$lang->install->groupList['IPDPRODUCTPLAN']['name'] = 'PRODUCT PLANING';
$lang->install->groupList['IPDDEMAND']['name'] = 'DEMAND ANALYSIS';
$lang->install->groupList['IPDPMT']['name'] = 'IPDPMT';
$lang->install->groupList['IPDADMIN']['name'] = 'IPDADMIN';
$lang->install->success = "Đã được cài đặt!";
$lang->install->login = 'Đăng nhập ZenTao';
$lang->install->register = 'Đăng ký cộng đồng ZenTao';
+5
View File
@@ -271,6 +271,11 @@ $lang->install->groupList['LITEPROJECT']['desc'] = '运营管理界面用户分
$lang->install->groupList['LITETEAM']['name'] = '团队成员';
$lang->install->groupList['LITETEAM']['desc'] = '运营管理界面用户分组';
$lang->install->groupList['IPDPRODUCTPLAN']['name'] = '产品规划人员';
$lang->install->groupList['IPDDEMAND']['name'] = '需求分析人员';
$lang->install->groupList['IPDPMT']['name'] = 'PMT团队人员';
$lang->install->groupList['IPDADMIN']['name'] = '管理人员';
$lang->install->cronList[''] = '监控定时任务';
$lang->install->cronList['moduleName=execution&methodName=computeBurn'] = '更新燃尽图';
$lang->install->cronList['moduleName=report&methodName=remind'] = '每日任务提醒';
+3 -2
View File
@@ -497,13 +497,14 @@ class installModel extends model
$this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->exec();
if(!dao::isError())
{
$visions = $this->config->edition == 'ipd' ? 'or,rnd,lite' : 'rnd,lite';
/* Set admin. */
$admin = new stdclass();
$admin->account = $this->post->account;
$admin->realname = $this->post->account;
$admin->password = md5($this->post->password);
$admin->gender = 'f';
$admin->visions = 'rnd,lite';
$admin->visions = $visions;
$this->dao->replace(TABLE_USER)->data($admin)->exec();
}
}
@@ -558,7 +559,7 @@ class installModel extends model
}
}
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
/* Update process by lang. */
foreach($this->lang->install->processList as $id => $name)
+3 -3
View File
@@ -155,12 +155,12 @@ class my extends control
$qaCount = 0;
$meetingCount = 0;
$ticketCount = 0;
$isMax = $this->config->edition == 'max' ? 1 : 0;
$isMax = ($this->config->edition == 'max' or $this->config->edition == 'ipd') ? 1 : 0;
$feedbackCount = 0;
$isBiz = $this->config->edition == 'biz' ? 1 : 0;
if($isBiz or $isMax)
if($this->config->edition != 'open')
{
$feedbacks = $this->loadModel('feedback')->getList('assigntome', 'id_desc', $pager);
$feedbackCount = $pager->recTotal;
@@ -980,7 +980,7 @@ EOF;
}
$this->view->flows = array();
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$this->app->loadLang('approval');
$this->view->flows = $this->dao->select('module,name')->from(TABLE_WORKFLOW)->where('buildin')->eq(0)->fetchPairs('module', 'name');
+2 -1
View File
@@ -143,9 +143,10 @@ $lang->my->featureBar['todo']['assignedToOther'] = 'Assigned To Other';
$lang->my->featureBar['todo']['cycle'] = 'Recurrence';
$lang->my->featureBar['audit']['all'] = 'All';
$lang->my->featureBar['audit']['demand'] = 'Demand';
$lang->my->featureBar['audit']['story'] = 'Story';
$lang->my->featureBar['audit']['testcase'] = 'Test case';
if($config->edition == 'max' and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if(($config->edition == 'max' or $config->edition == 'ipd') and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if($config->edition != 'open') $lang->my->featureBar['audit']['feedback'] = 'Feedback';
if($config->edition != 'open' and helper::hasFeature('OA')) $lang->my->featureBar['audit']['oa'] = 'OA';
+2 -1
View File
@@ -143,9 +143,10 @@ $lang->my->featureBar['todo']['assignedToOther'] = 'Assigned To Other';
$lang->my->featureBar['todo']['cycle'] = 'Recurrence';
$lang->my->featureBar['audit']['all'] = 'All';
$lang->my->featureBar['audit']['demand'] = 'Demand';
$lang->my->featureBar['audit']['story'] = 'Story';
$lang->my->featureBar['audit']['testcase'] = 'Test case';
if($config->edition == 'max' and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if(($config->edition == 'max' or $config->edition == 'ipd') and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if($config->edition != 'open') $lang->my->featureBar['audit']['feedback'] = 'Feedback';
if($config->edition != 'open' and helper::hasFeature('OA')) $lang->my->featureBar['audit']['oa'] = 'OA';
+2 -1
View File
@@ -143,9 +143,10 @@ $lang->my->featureBar['todo']['assignedToOther'] = 'Assigned To Other';
$lang->my->featureBar['todo']['cycle'] = 'Récurrence';
$lang->my->featureBar['audit']['all'] = 'All';
$lang->my->featureBar['audit']['demand'] = 'Demand';
$lang->my->featureBar['audit']['story'] = 'Story';
$lang->my->featureBar['audit']['testcase'] = 'Test case';
if($config->edition == 'max' and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if(($config->edition == 'max' or $config->edition == 'ipd') and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if($config->edition != 'open') $lang->my->featureBar['audit']['feedback'] = 'Feedback';
if($config->edition != 'open' and helper::hasFeature('OA')) $lang->my->featureBar['audit']['oa'] = 'OA';
+2 -1
View File
@@ -143,9 +143,10 @@ $lang->my->featureBar['todo']['assignedToOther'] = '指派他人';
$lang->my->featureBar['todo']['cycle'] = '周期';
$lang->my->featureBar['audit']['all'] = '全部';
$lang->my->featureBar['audit']['demand'] = '需求池需求';
$lang->my->featureBar['audit']['story'] = '需求';
$lang->my->featureBar['audit']['testcase'] = '用例';
if($config->edition == 'max' and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if(($config->edition == 'max' or $config->edition == 'ipd') and (helper::hasFeature('waterfall') or helper::hasFeature('waterfallplus'))) $lang->my->featureBar['audit']['project'] = $lang->projectCommon;
if($config->edition != 'open') $lang->my->featureBar['audit']['feedback'] = '反馈';
if($config->edition != 'open' and helper::hasFeature('OA')) $lang->my->featureBar['audit']['oa'] = '办公';
+43
View File
@@ -1023,6 +1023,7 @@ class myModel extends model
public function getReviewingTypeList()
{
$typeList = array();
if($this->getReviewingDemands('id_desc', true)) $typeList[] = 'demand';
if($this->getReviewingStories('id_desc', true)) $typeList[] = 'story';
if($this->getReviewingCases('id_desc', true)) $typeList[] = 'testcase';
if($this->getReviewingApprovals('id_desc', true)) $typeList[] = 'project';
@@ -1054,6 +1055,7 @@ class myModel extends model
public function getReviewingList($browseType, $orderBy = 'time_desc', $pager = null)
{
$reviewList = array();
if($browseType == 'all' or $browseType == 'demand') $reviewList = array_merge($reviewList, $this->getReviewingDemands());
if($browseType == 'all' or $browseType == 'story') $reviewList = array_merge($reviewList, $this->getReviewingStories());
if($browseType == 'all' or $browseType == 'testcase') $reviewList = array_merge($reviewList, $this->getReviewingCases());
if($browseType == 'all' or $browseType == 'project') $reviewList = array_merge($reviewList, $this->getReviewingApprovals());
@@ -1090,6 +1092,47 @@ class myModel extends model
return $reviewList;
}
/**
* Get reviewing demands.
*
* @param string $orderBy
* @param bool $checkExists
* @access public
* @return array
*/
public function getReviewingDemands($orderBy = 'id_desc', $checkExists = false)
{
if(!common::hasPriv('demand', 'review')) return array();
$this->app->loadLang('demand');
$stmt = $this->dao->select("t1.*")->from(TABLE_DEMAND)->alias('t1')
->leftJoin(TABLE_DEMANDREVIEW)->alias('t2')->on('t1.id = t2.demand and t1.version = t2.version')
->where('t1.deleted')->eq(0)
->andWhere('t2.reviewer')->eq($this->app->user->account)
->andWhere('t2.result')->eq('')
->andWhere('t1.vision')->eq($this->config->vision)
->andWhere('t1.status')->eq('reviewing')
->orderBy($orderBy)
->query();
$demands = array();
while($data = $stmt->fetch())
{
if($checkExists) return true;
$demand = new stdclass();
$demand->id = $data->id;
$demand->title = $data->title;
$demand->type = 'demand';
$demand->time = $data->createdDate;
$demand->status = $data->status;
$demands[$demand->id] = $demand;
}
$actions = $this->dao->select('objectID,`date`')->from(TABLE_ACTION)->where('objectType')->eq('demand')->andWhere('objectID')->in(array_keys($demands))->andWhere('action')->eq('submitreview')->orderBy('`date`')->fetchPairs('objectID', 'date');
foreach($actions as $demandID => $date) $demands[$demandID]->time = $date;
return array_values($demands);
}
/**
* Get reviewing stories.
*
+2 -2
View File
@@ -64,7 +64,7 @@
$statusList = array();
if(isset($lang->$type->statusList)) $statusList = $lang->$type->statusList;
if($type == 'attend') $statusList = $lang->attend->reviewStatusList;
if(!in_array($type, array('story', 'testcase', 'feedback', 'review')) and strpos(",{$config->my->oaObjectType},", ",$type,") === false)
if(!in_array($type, array('demand', 'story', 'testcase', 'feedback', 'review')) and strpos(",{$config->my->oaObjectType},", ",$type,") === false)
{
if($rawMethod == 'audit') $statusList = $lang->approval->nodeList;
if(isset($flows[$review->type])) $statusList = $rawMethod == 'audit' ? $lang->approval->nodeList : $lang->approval->statusList;
@@ -124,7 +124,7 @@
{
common::printLink($module, 'view', $params, $reviewIcon, '', "class='btn' data-toggle='modal' title='{$lang->review->common}'", true, true);
}
elseif(!in_array($module, array('story', 'testcase', 'feedback')))
elseif(!in_array($module, array('demand', 'story', 'testcase', 'feedback')))
{
common::printLink($module, 'approvalreview', $params, $reviewIcon, '', "class='btn' data-toggle='modal' title='{$lang->review->common}'", true, true);
}
+1 -1
View File
@@ -67,7 +67,7 @@
<?php if($action->objectType == 'meeting') $tab = $action->project ? "data-app='project'" : "data-app='my'";?>
<span class='label-name'>
<?php
if(($config->edition == 'max' and strpos($config->action->assetType, ",{$action->objectType},") !== false) and empty($action->objectName))
if((($config->edition == 'max' or $config->edition == 'ipd') and strpos($config->action->assetType, ",{$action->objectType},") !== false) and empty($action->objectName))
{
echo '#' . $action->objectID;
}
+1
View File
@@ -2,3 +2,4 @@
.c-phone {width: 120px;}
.c-email {width: 200px;}
.c-role {width: 105px;}
#userList td{overflow:hidden}
+2 -2
View File
@@ -130,7 +130,7 @@ class personnelModel extends model
$executionPairs = $this->getInvolvedExecutions($projects);
$taskInvest = $this->getProjectTaskInvest($projects, $accountPairs);
$bugAndStoryInvest = $this->getBugAndStoryInvest($accountPairs, $programID);
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$issueInvest = $this->getIssueInvest($accountPairs, $projects);
$riskInvest = $this->getRiskInvest($accountPairs, $projects);
@@ -153,7 +153,7 @@ class personnelModel extends model
$personnelList[$user->role][$account] += $taskInvest[$account];
$personnelList[$user->role][$account] += $bugAndStoryInvest[$account];
if($this->config->edition == 'max')
if($this->config->edition == 'max' or $this->config->edition == 'ipd')
{
$personnelList[$user->role][$account] += $issueInvest[$account];
$personnelList[$user->role][$account] += $riskInvest[$account];
@@ -40,6 +40,7 @@
<?php $i = 1;?>
<?php $whitelistUsers = array();?>
<?php foreach($whitelist as $user):?>
<?php unset($users[$user->account]);?>
<tr id="whitelist<?php echo $i;?>" data-id="<?php echo $i;?>">
<td>
<input type='text' name='realnames[]' value='<?php echo $user->realname;?>' readonly class='form-control' />
+3 -3
View File
@@ -29,7 +29,7 @@
<th colspan="3"><?php echo $lang->personnel->task;?></th>
<th colspan="3"><?php echo $lang->personnel->bug;?></th>
<th <?php echo $config->URAndSR ? "colspan='2'" : "rowspan='2'";?> class="c-story"><?php echo $lang->personnel->createStories;?></th>
<?php if($this->config->edition == 'max'): ?>
<?php if($this->config->edition == 'max' or $this->config->edition == 'ipd'): ?>
<th colspan="3"><?php echo $lang->personnel->issue;?></th>
<th colspan="3"><?php echo $lang->personnel->risk;?></th>
<?php endif;?>
@@ -47,7 +47,7 @@
<th><?php echo $lang->personnel->UR;?></th>
<th><?php echo $lang->personnel->SR;?></th>
<?php endif;?>
<?php if($this->config->edition == 'max'): ?>
<?php if($this->config->edition == 'max' or $this->config->edition == 'ipd'): ?>
<th><?php echo $lang->personnel->created;?></th>
<th><?php echo $lang->personnel->resolved;?></th>
<th><?php echo $lang->personnel->wait;?></th>
@@ -77,7 +77,7 @@
<td><?php echo $personnel['UR'];?></td>
<?php endif;?>
<td><?php echo $personnel['SR'];?></td>
<?php if($this->config->edition == 'max'): ?>
<?php if($this->config->edition == 'max' or $this->config->edition == 'ipd'): ?>
<td><?php echo $personnel['createdIssue'];?></td>
<td><?php echo $personnel['resolvedIssue'];?></td>
<td><?php echo $personnel['pendingIssue'];?></td>
+3 -2
View File
@@ -22,8 +22,9 @@
.flex-between {display:flex; justify-content: space-between;}
.flex-start {display:flex; justify-content: flex-start;}
.query-after {position: relative; padding-right: 24px; padding-top: 1px;}
.query-after::after {content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 1px; background-color: #F1F5F9;}
.query-after {padding-right: 8px; padding-top: 1px;}
.query-pseudo {position: relative; padding-right: 24px; padding-top: 1px;}
.query-pseudo::after {content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 1px; background-color: #F1F5F9;}
#filterMargin {padding-top: 8px; padding-bottom: 5px;}
.pivot-design {padding-left: 24px; padding-right: 12px;}
+1 -1
View File
@@ -264,7 +264,7 @@ $lang->pivot->noChartSelected = 'Please select one pivot.';
$lang->pivot->beginGtEnd = 'Begin time should not be >= end time.';
$lang->pivot->resetSettings = 'The configuration of the query data has been modified, requiring redesign of the pivot, whether to continue.';
$lang->pivot->clearSettings = 'The configuration of the query data has been modified, whether to clear the pivot and save.';
$lang->pivot->draftSave = 'Released content is edited, will be overwritten, whether to continue?';
$lang->pivot->draftSave = 'The pivot table has been published and will be in draft state. Do you want to continue?';
$lang->pivot->cannotAddQuery = 'Result filter has been added, query filter cannot be added.';
$lang->pivot->cannotAddResult = 'Query filter has been added, result filter cannot be added.';
+1 -1
View File
@@ -264,7 +264,7 @@ $lang->pivot->noChartSelected = 'Please select one pivot.';
$lang->pivot->beginGtEnd = 'Begin time should not be >= end time.';
$lang->pivot->resetSettings = 'The configuration of the query data has been modified, requiring redesign of the pivot, whether to continue.';
$lang->pivot->clearSettings = 'The configuration of the query data has been modified, whether to clear the pivot and save.';
$lang->pivot->draftSave = 'Released content is edited, will be overwritten, whether to continue?';
$lang->pivot->draftSave = 'The pivot table has been published and will be in draft state. Do you want to continue?';
$lang->pivot->cannotAddQuery = 'Result filter has been added, query filter cannot be added.';
$lang->pivot->cannotAddResult = 'Query filter has been added, result filter cannot be added.';
+1 -1
View File
@@ -264,7 +264,7 @@ $lang->pivot->noChartSelected = 'Please select one pivot.';
$lang->pivot->beginGtEnd = 'Begin time should not be >= end time.';
$lang->pivot->resetSettings = 'The configuration of the query data has been modified, requiring redesign of the pivot, whether to continue.';
$lang->pivot->clearSettings = 'The configuration of the query data has been modified, whether to clear the pivot and save.';
$lang->pivot->draftSave = 'Released content is edited, will be overwritten, whether to continue?';
$lang->pivot->draftSave = 'The pivot table has been published and will be in draft state. Do you want to continue?';
$lang->pivot->cannotAddQuery = 'Result filter has been added, query filter cannot be added.';
$lang->pivot->cannotAddResult = 'Query filter has been added, result filter cannot be added.';
+1 -1
View File
@@ -254,7 +254,7 @@ $lang->pivot->noChartSelected = 'Please select one pivot.';
$lang->pivot->beginGtEnd = 'Begin time should not be >= end time.';
$lang->pivot->resetSettings = 'The configuration of the query data has been modified, requiring redesign of the pivot, whether to continue.';
$lang->pivot->clearSettings = 'The configuration of the query data has been modified, whether to clear the pivot and save.';
$lang->pivot->draftSave = 'Released content is edited, will be overwritten, whether to continue?';
$lang->pivot->draftSave = 'The pivot table has been published and will be in draft state. Do you want to continue?';
$lang->pivot->cannotAddQuery = 'Result filter has been added, query filter cannot be added.';
$lang->pivot->cannotAddResult = 'Query filter has been added, result filter cannot be added.';

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