Merge branch '18.x' into zentaoipd

This commit is contained in:
tanghucheng
2023-07-31 08:58:26 +08:00
44 changed files with 1022 additions and 189 deletions
Vendored
+279 -61
View File
@@ -18,6 +18,8 @@ pipeline {
SRC_ZDOOEXT_PATH = "${WORKSPACE}/zdooext"
SRC_ZENTAOEXT_PATH = "${WORKSPACE}/zentaoext"
MIRROR = "true"
}
stages {
@@ -48,6 +50,7 @@ pipeline {
stage("Pull") {
steps {
checkout scm
sh 'env'
}
}
@@ -102,24 +105,13 @@ pipeline {
}
stage("Build") {
environment {
GIT_TAG_BUILD_TYPE = """${sh(
returnStdout: true,
script: 'misc/parse_tag.sh $TAG_NAME type'
).trim()}"""
GIT_TAG_BUILD_GROUP = """${sh(
returnStdout: true,
script: 'misc/parse_tag.sh $TAG_NAME group'
).trim()}"""
}
stages {
stage("make ciCommon") {
steps {
sh "echo $GIT_TAG_BUILD_TYPE/abc"
sh "echo $GIT_TAG_BUILD_GROUP/def"
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}'
@@ -162,6 +154,11 @@ pipeline {
script: 'cat ${SRC_ZENTAOEXT_PATH}/MAXVERSION'
).trim()}"""
GIT_COMMIT = """${sh(
returnStdout: true,
script: 'git rev-parse HEAD'
).trim()}"""
GIT_TAG_BUILD_TYPE = """${sh(
returnStdout: true,
script: 'misc/parse_tag.sh $TAG_NAME type'
@@ -172,11 +169,16 @@ pipeline {
script: 'misc/parse_tag.sh $TAG_NAME group'
).trim()}"""
GIT_TAGGER_NAME = """${sh(
returnStdout: true,
script: 'git for-each-ref --format="%(taggername)" refs/tags/$(git tag --points-at HEAD)'
).trim()}"""
OUTPUT_PKG_PATH = "${ZENTAO_RELEASE_PATH}/output"
ARTIFACT_REPOSITORY = """${sh(
returnStdout: true,
script: 'echo easycorp-snapshot'
script: 'misc/parse_tag.sh $TAG_NAME type | grep release >/dev/null && echo easycorp || echo easycorp-snapshot'
).trim()}"""
ARTIFACT_HOST = "nexus.qc.oop.cc"
ARTIFACT_PROTOCOL = "https"
@@ -185,6 +187,7 @@ pipeline {
stages {
stage("Merge and Upload") {
matrix {
agent {
kubernetes {
@@ -194,10 +197,11 @@ pipeline {
command "sleep"
args "99d"
}
inheritFrom "publish-qiniu"
}
}
options { skipDefaultCheckout() }
options {
skipDefaultCheckout()
}
axes {
axis {
@@ -223,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()}"""
}
@@ -239,7 +247,6 @@ pipeline {
sh 'mkdir $ZENTAO_RELEASE_PATH'
sh '${ZENTAO_BUILD_PATH}/package.sh zip'
sh 'mkdir $OUTPUT_PKG_PATH'
sh 'env | grep GIT_TAG'
}
}
}
@@ -250,7 +257,7 @@ pipeline {
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.base' + '.' + env.GIT_TAG_BUILD_GROUP,
groupId: 'zentao.pmsPack' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.PMS_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
@@ -265,7 +272,7 @@ pipeline {
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.biz' + '.' + env.GIT_TAG_BUILD_GROUP,
groupId: 'zentao.bizPack' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.BIZ_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
@@ -284,7 +291,7 @@ pipeline {
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.max' + '.' + env.GIT_TAG_BUILD_GROUP,
groupId: 'zentao.maxPack' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.MAX_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
@@ -301,18 +308,18 @@ 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
stage("syspack") {
when {
buildingTag()
// environment name: 'GIT_TAG_BUILD_TYPE', value: 'release'
// buildingTag()
environment name: 'GIT_TAG_BUILD_TYPE', value: 'release'
}
steps{
sh 'env | grep GIT_TAG'
@@ -329,28 +336,8 @@ pipeline {
}
steps {
nexusArtifactUploader(
nexusVersion: 'nexus3',
protocol: env.ARTIFACT_PROTOCOL,
nexusUrl: env.ARTIFACT_HOST,
groupId: 'zentao.pms' + '.' + env.GIT_TAG_BUILD_GROUP,
version: env.PMS_VERSION,
repository: env.ARTIFACT_REPOSITORY,
credentialsId: env.ARTIFACT_CRED_ID,
artifacts: [
[artifactId: env.ARTIFACT_NAME,
classifier: env.PHPVERSION + '-1.noarch',
file: env.ZENTAO_RELEASE_PATH + '/zentao.rpm',
type: 'rpm'],
[artifactId: env.ARTIFACT_NAME,
classifier: env.PHPVERSION + '.1.all',
file: env.ZENTAO_RELEASE_PATH + '/zentao.deb',
type: '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'
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
@@ -360,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')
@@ -368,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'
}
}
}
@@ -383,15 +370,246 @@ pipeline {
} // End Merge and Upload Max
stage("Notice") {
stage("Notice ZIP") {
steps {
container('xuanimbot') {
sh 'env | grep GIT'
sh 'git config --global --add safe.directory $(pwd)'
//sh '/usr/local/bin/xuanimbot --users "qishiyao" --title "zentao build with tag ${TAG_NAME} success" --url ""${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/#browse/browse:${ARTIFACT_REPOSITORY}:zentao"" --content "zentaopms build success, click buttom below for browse artifacts" --debug --custom'
sh '/usr/local/bin/xuanimbot --users "qishiyao" --groups "fced7fb3-0d48-449f-b408-ecae52a50f89" --title "zentao build with tag ${TAG_NAME} success" --url ""${ARTIFACT_PROTOCOL}://${ARTIFACT_HOST}/#browse/browse:${ARTIFACT_REPOSITORY}:zentao"" --content "zentaopms build success, click buttom below for browse artifacts" --debug --custom'
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 {
failure {
container('xuanimbot') {
sh 'git config --global --add safe.directory $(pwd)'
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'
}
}
}
} // end publish
}
+2 -2
View File
@@ -23,8 +23,8 @@ class buildsEntry extends entry
if(empty($projectID)) $projectID = $this->param('project', 0);
if(empty($projectID)) return $this->sendError(400, "Need project id.");
$control = $this->loadController('project', 'build');
$control->build($projectID, $this->param('type', 'all'), $this->param('param', 0), $this->param('order', 't1.date_desc,t1.id_desc'));
$control = $this->loadController('projectbuild', 'browse');
$control->browse($projectID, $this->param('type', 'all'), $this->param('param', 0), $this->param('order', 't1.date_desc,t1.id_desc'));
$data = $this->getData();
if(!isset($data->status)) return $this->sendError(400, 'error');
+18
View File
@@ -64,6 +64,24 @@ class ztfSubmitEntry extends baseEntry
->set('ZTFResult')->eq(json_encode($post))
->where('id')->eq($post->task)
->exec();
$result = $this->dao->select('*')->from(TABLE_TESTRESULT)
->where('id')->eq($post->task)
->fetch();
if($result->run)
{
$runStatus = $result->caseResult == 'blocked' ? 'blocked' : 'normal';
$this->dao->update(TABLE_TESTRUN)
->set('lastRunResult')->eq($result->caseResult)
->set('status')->eq($runStatus)
->set('lastRunner')->eq($result->lastRunner)
->set('lastRunDate')->eq($result->date)
->where('id')->eq($result->run)
->exec();
}
$this->dao->update(TABLE_CASE)->set('lastRunner')->eq($result->lastRunner)->set('lastRunDate')->eq($result->date)->set('lastRunResult')->eq($result->caseResult)->where('id')->eq($result->case)->exec();
}
else
{
+1 -1
View File
@@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}}
if(!function_exists('getWebRoot')){function getWebRoot(){}}
/* 基本设置。Basic settings. */
$config->version = '18.5'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->version = '18.6'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it.
$config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite.
$config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP.
$config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time.
+1
View File
@@ -34,6 +34,7 @@ $routes['/configurations/:name'] = 'config';
$routes['/programs/:id/products'] = 'products';
$routes['/products'] = 'products';
$routes['/products/:id'] = 'product';
$routes['/product/:id'] = 'product';
$routes['/productlines'] = 'productLines';
$routes['/productlines/:id'] = 'productLine';
+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;
+7 -7
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,8 +1,8 @@
{
"pkg": {
"xuanxuan": {
"gitVersion": "4786a9a7555ef5cdc6f8b84049d44e2add643a23",
"version": "7.1"
"gitVersion": "v7.2.1-rc.4",
"version": "7.2.1"
},
"zentaoext": {
"gitVersion": "18.x"
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
finishTime=$(date '+%Y-%m-%d %H:%M:%S')
blankLine() {
echo
}
outputFrame() {
printf "$1"
}
outputLine() {
echo "$1"
}
outputLine "构建日期 **$finishTime**"
blankLine
outputLine "#### Git 信息"
outputLine "* 触发 Tag: $TAG_NAME"
outputLine "* CommitId: ${GIT_COMMIT:0:7}"
outputLine "* 触发人: ${GIT_TAGGER_NAME}"
blankLine
# 触发人: qishiyao
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 "\t\t"
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 "\t\t"
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 "\t"
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 "\t\t"
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 "\t"
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)"
+2 -2
View File
@@ -812,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);
@@ -1513,7 +1513,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();
}
+1 -1
View File
@@ -4,7 +4,7 @@
.side-col {width: 240px;}
#sidebar> .cell {width: 220px;}
#data {overflow: scroll;}
#datas {overflow: scroll;}
#data th, #data td, #schema td, #modules li > strong {overflow: hidden; text-overflow: unset; white-space: nowrap;}
#dataContent {margin: 0px; padding: 0px;}
#dataContent .detail {margin: 0px; padding: 0px;}
+131
View File
@@ -17,6 +17,22 @@ $(function()
if(dataview.used) result = confirm(warningDesign);
if(result) window.location.href = url;
});
initPager(pageID, recPerPage, recTotal, fieldCount);
$('.first-page,.left-page,.last-page,.right-page').click(function()
{
pageID = $(this).data('page');
queryTableData();
});
$('.dropup li a').click(function()
{
pageID = 1;
recPerPage = $(this).data('size');
queryTableData();
})
});
/**
@@ -33,3 +49,118 @@ function locate(module, method, params)
var link = createLink(module, method, params);
window.location.href = link;
}
/**
* Query table data.
*
* @return void
*/
function queryTableData()
{
var params = {};
params.pageID = pageID;
params.recPerPage = recPerPage;
params.recTotal = recTotal;
params.table = table;
params.type = type;
$.post(createLink('dataview', 'ajaxGetTableData'), params,function(resp)
{
resp = JSON.parse(resp);
buildTable(resp);
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.
*
* @param int pageID
* @param int recPerPage
* @param int recTotal
* @access public
* @return void
*/
function initPager(pageID, recPerPage, recTotal, fieldCount)
{
var pageID = parseInt(pageID);
var recPerPage = parseInt(recPerPage);
var recTotal = parseInt(recTotal);
var pageTotal = parseInt(Math.ceil(recTotal / recPerPage));
$('.recTotal').html(recTotalTip.replace('%s', recTotal));
$('.recPerPage').html(recPerPageTip.replace('%s', recPerPage));
$('.dropup li').removeClass('active');
$('.dropup li a').each(function()
{
if($(this).data('size') == recPerPage)
{
$(this).parent().addClass('active');
return;
}
});
$('.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);
$('.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));
}
+6 -1
View File
@@ -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)
+75 -20
View File
@@ -12,8 +12,18 @@
?>
<?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
<?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', $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);?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'><?php // common::printAdminSubMenu('dev');?></div>
<div class="btn-toolbar pull-right">
@@ -83,32 +93,77 @@
<div class='tab-content '>
<div class='tab-pane active' id='data'>
<?php if(!empty($fields)):?>
<table class="table table-bordered" style="min-width: <?php echo count($fields)*100;?>px">
<thead>
<tr>
<?php foreach($fields as $key => $field):?>
<?php
$fieldName = isset($dataview->fieldSettings->$key->name) ? $dataview->fieldSettings->$key->name : $key;
if(!empty($dataview->langs))
{
$langs = json_decode($dataview->langs, true);
if(!empty($langs)) $fieldName = $langs[$key][$clientLang] ? $langs[$key][$clientLang] : $fieldName;
}
?>
<th><?php echo $fieldName;?></th>
<?php endforeach;?>
</tr>
</thead>
<tbody>
<div id='datas'>
<table class="table table-bordered" style="min-width: <?php echo count($fields)*100;?>px">
<thead>
<tr>
<?php foreach($fields as $key => $field):?>
<?php
$fieldName = isset($dataview->fieldSettings->$key->name) ? $dataview->fieldSettings->$key->name : $key;
if(!empty($dataview->langs))
{
$langs = json_decode($dataview->langs, true);
if(!empty($langs)) $fieldName = $langs[$key][$clientLang] ? $langs[$key][$clientLang] : $fieldName;
}
?>
<th><?php echo $fieldName;?></th>
<?php endforeach;?>
</tr>
</thead>
<tbody>
<?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;?>
</tbody>
</table>
</tbody>
</table>
</div>
<div class='table-footer'>
<ul class="pager">
<li><div class="pager-label recTotal"></div></li>
<li>
<div class="btn-group pager-size-menu dropup">
<button type="button" class="btn dropdown-toggle recPerPage" data-toggle="dropdown" style="border-radius: 4px;"></button>
<ul class="dropdown-menu">
<li><a href="javascript:;" data-size="5">5</a></li>
<li><a href="javascript:;" data-size="10">10</a></li>
<li><a href="javascript:;" data-size="15">15</a></li>
<li><a href="javascript:;" data-size="20">20</a></li>
<li><a href="javascript:;" data-size="25">25</a></li>
<li><a href="javascript:;" data-size="30">30</a></li>
<li><a href="javascript:;" data-size="35">35</a></li>
<li><a href="javascript:;" data-size="40">40</a></li>
<li><a href="javascript:;" data-size="45">45</a></li>
<li><a href="javascript:;" data-size="50">50</a></li>
<li><a href="javascript:;" data-size="100">100</a></li>
<li><a href="javascript:;" data-size="200">200</a></li>
<li><a href="javascript:;" data-size="500">500</a></li>
<li><a href="javascript:;" data-size="1000">1000</a></li>
<li><a href="javascript:;" data-size="2000">2000</a></li>
</ul>
</div>
</li>
<li class='pager-item-left first-page'>
<a class='pager-item' data-page='1' href='javascript:;'><i class='icon icon-first-page'></i></a>
</li>
<li class='pager-item-left left-page'>
<a class='pager-item' data-page='1' href='javascript:;'><i class='icon icon-angle-left'></i></a>
</li>
<li><div class='pager-label page-number'></div></li>
<li class='pager-item-right right-page'>
<a class='pager-item' data-page='1' href='javascript:;'><i class='icon icon-angle-right'></i></a>
</li>
<li class='pager-item-right last-page'>
<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>
<div class='tab-pane' id='schema'>
+16 -2
View File
@@ -72,7 +72,14 @@ class pivot extends control
$processSqlData = $this->loadModel('chart')->getTables($sql);
$sql = $processSqlData['sql'];
list($data, $configs) = $this->pivot->genSheet(json_decode(json_encode($pivot->fieldSettings), true), $pivot->settings, $sql, $filterFormat, json_decode($pivot->langs, true));
if(isset($pivot->settings['summary']) and $pivot->settings['summary'] =='notuse')
{
list($data, $configs) = $this->pivot->genOriginSheet(json_decode(json_encode($pivot->fieldSettings), true), $pivot->settings, $sql, $filterFormat, json_decode($pivot->langs, true));
}
else
{
list($data, $configs) = $this->pivot->genSheet(json_decode(json_encode($pivot->fieldSettings), true), $pivot->settings, $sql, $filterFormat, json_decode($pivot->langs, true));
}
$this->view->data = $data;
$this->view->configs = $configs;
}
@@ -298,7 +305,14 @@ class pivot extends control
$processSqlData = $this->loadModel('chart')->getTables($sql);
$sql = $processSqlData['sql'];
list($data, $configs) = $this->pivot->genSheet($fields, $settings, $sql, $filterFormat, $langs);
if(isset($settings['summary']) and $settings['summary'] == 'notuse')
{
list($data, $configs) = $this->pivot->genOriginSheet($fields, $settings, $sql, $filterFormat, $langs);
}
else
{
list($data, $configs) = $this->pivot->genSheet($fields, $settings, $sql, $filterFormat, $langs);
}
$this->pivot->buildPivotTable($data, $configs, $fields, $sql);
}
+14 -1
View File
@@ -5,10 +5,11 @@
.parent-position {padding-right: 160px;}
.datagrid {overflow: auto;}
.heading-padding, .datagrid-padding {padding-left: 6px; padding-right: 6px;}
.datagrid-padding {padding-top: 2px;}
.filter-items > .table-row{display: table!important;}
.filter-items .filter-item:first-child {padding-left: 0!important;}
.filterBox {display: flex; margin-bottom: 20px; margin-left: 6px; margin-right: 6px;}
.filterBox {display: flex; margin-bottom: 5px; margin-left: 6px; margin-right: 6px; margin-top: 8px;}
.filter-items {display: flex; flex: 1; flex-wrap: wrap;}
.filter-item {padding: 0 16px 5px 0;}
.filter-item-grow {flex-grow: 1;}
@@ -17,3 +18,15 @@
#filterItems .picker-selections {overflow: hidden; text-overflow: clip; white-space: nowrap;}
#filterItems .picker .picker-selections {width: auto !important;}
.content-border {padding-top: 16px; padding-bottom: 16px; border-bottom: 1px solid #F1F5F9;}
.flex-between {display:flex; justify-content: space-between;}
.flex-start {display:flex; justify-content: flex-start;}
.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;}
.pivot-edit {padding-left: 12px; padding-right: 12px;}
.pivot-delete {padding-left: 12px; padding-right: 8px;}
+8 -3
View File
@@ -139,10 +139,15 @@ function checkFormSetting()
*/
function validate(showError = false)
{
var pivot = DataStorage.pivot;
var pivot = DataStorage.pivot;
var formSettings = pivot.settings;
/* Code for temporary */
var isReady = true;
var isReady = true;
if("summary" in formSettings && formSettings.summary == 'notuse')
{
if(isReady) $('#datagrid-tip').addClass('hidden');
return true;
}
/* check group settings. */
var exist = false;
+58 -17
View File
@@ -5,6 +5,7 @@ $(function()
expandTree();
renderFilters(pivot);
initQueryBtn();
initOriginQueryBtn();
$('body').resize(() => {calcPreviewGrowFilter();});
@@ -20,17 +21,14 @@ function expandTree()
tree.expand($('.pivot-' + pivotID).parents('li'));
}
/*$('.btn-export').click(function()
{
if(typeof pivotID == 'undefined' || !pivotID) return;
pivot = getQueryInfo();
});
*/
function getQueryInfo()
{
var pivotInfo = pivot;
// if not use JSON.parse(JSON.stringify()), edit pivotInfo also affects pivot. If click btn-query-origin, pivot setting also have summary field.
var pivotInfo = JSON.parse(JSON.stringify(pivot));
pivotInfo.searchFilters = JSON.parse(JSON.stringify(pivotInfo.filters));
pivotInfo.step = 4;
if(!pivotInfo.searchFilters) return pivotInfo;
if(isQueryFilter(pivotInfo.filters))
{
@@ -70,7 +68,6 @@ function getQueryInfo()
});
}
pivotInfo.step = 4;
return pivotInfo;
}
@@ -84,17 +81,55 @@ function initQueryBtn()
{
$('.btn-query').click(function()
{
pivotInfo = getQueryInfo();
$.post(createLink('pivot', 'ajaxGetPivot'), pivotInfo,function(resp)
{
var myDatagrid = $('#datagirdInfo');
myDatagrid.find('.reportData').remove();
myDatagrid.append(resp);
});
var pivotInfo = getQueryInfo();
refreshPivot(pivotInfo);
});
}
/**
* Init origin query button.
*
* @access public
* @return void
*/
function initOriginQueryBtn()
{
$('.btn-query-origin').click(function()
{
var pivotInfo = getQueryInfo();
pivotInfo.settings['summary'] = 'notuse';
refreshPivot(pivotInfo, true);
});
}
function refreshPivot(pivotInfo, isOrigin = false)
{
$.post(createLink('pivot', 'ajaxGetPivot'), pivotInfo,function(resp)
{
var myDatagrid = $('#datagirdInfo');
myDatagrid.find('.reportData').remove();
myDatagrid.append(resp);
if(isOrigin)
{
$('#filterItems').addClass('hidden');
$('#filterMargin').removeClass('hidden');
$('#pivot-query').removeClass('hidden');
$('#origin-query').addClass('hidden');
}
else
{
$('#filterItems').removeClass('hidden');
$('#filterMargin').addClass('hidden');
$('#pivot-query').addClass('hidden');
$('#origin-query').removeClass('hidden');
}
});
}
function calcPreviewGrowFilter()
{
if(pivot.filters.length <= 0) return;
@@ -280,3 +315,9 @@ function isQueryFilter(filters)
{
return filters.length > 0 && filters[0].from == 'query';
}
function locate(module, method, params)
{
var link = createLink(module, method, params);
window.location.href = link;
}
+6 -1
View File
@@ -20,6 +20,7 @@ $lang->pivot->design = 'Design pivot';
$lang->pivot->export = 'Export pivot';
$lang->pivot->query = 'Query';
$lang->pivot->browseAction = 'Design in Pivot Table';
$lang->pivot->designAB = 'Design';
$lang->pivot->id = 'ID';
$lang->pivot->name = 'Name';
@@ -71,6 +72,8 @@ $lang->pivot->percent = '%';
$lang->pivot->undefined = 'Undefiniert';
$lang->pivot->project = $lang->projectCommon;
$lang->pivot->PO = 'PO';
$lang->pivot->showPivot = 'Show Pivot';
$lang->pivot->showOrigin = 'Show Origin Data';
$lang->pivot->colors[] = 'AFD8F8';
$lang->pivot->colors[] = 'AFD8F8';
@@ -261,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.';
@@ -332,6 +335,7 @@ $lang->pivot->typeOptions['dept'] = 'Dept';
$lang->pivot->step2 = new stdclass();
$lang->pivot->step2->group = 'Row Grouping';
$lang->pivot->step2->summary = 'Summary Setting';
$lang->pivot->step2->column = 'Column Settings';
$lang->pivot->step2->groupTip = 'Select Field';
$lang->pivot->step2->groupNum = array('One', 'Two', 'Three');
@@ -344,6 +348,7 @@ $lang->pivot->step2->columnField = 'Field';
$lang->pivot->step2->calcMode = 'Calc Mode';
$lang->pivot->step2->moreThanOne = 'Select at least one group field.';
$lang->pivot->step2->summaryTip = 'After this parameter is selected, you can configure Row Grouping, Column Settings, and Show column totals';
$lang->pivot->step2->groupsTip = 'By selecting a grouping field, the data of the SQL query is grouped and displayed hierarchically in the pivot table.';
$lang->pivot->step2->columnsTip = 'Add 1 column to the pivot table and set it.';
+6 -1
View File
@@ -20,6 +20,7 @@ $lang->pivot->design = 'Design pivot';
$lang->pivot->export = 'Export pivot';
$lang->pivot->query = 'Query';
$lang->pivot->browseAction = 'Design in Pivot Table';
$lang->pivot->designAB = 'Design';
$lang->pivot->id = 'ID';
$lang->pivot->name = 'Name';
@@ -71,6 +72,8 @@ $lang->pivot->percent = '%';
$lang->pivot->undefined = 'Undefiniert';
$lang->pivot->project = $lang->projectCommon;
$lang->pivot->PO = 'PO';
$lang->pivot->showPivot = 'Show Pivot';
$lang->pivot->showOrigin = 'Show Origin Data';
$lang->pivot->colors[] = 'AFD8F8';
$lang->pivot->colors[] = 'AFD8F8';
@@ -261,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.';
@@ -332,6 +335,7 @@ $lang->pivot->typeOptions['dept'] = 'Dept';
$lang->pivot->step2 = new stdclass();
$lang->pivot->step2->group = 'Row Grouping';
$lang->pivot->step2->summary = 'Summary Setting';
$lang->pivot->step2->column = 'Column Settings';
$lang->pivot->step2->groupTip = 'Select Field';
$lang->pivot->step2->groupNum = array('One', 'Two', 'Three');
@@ -344,6 +348,7 @@ $lang->pivot->step2->columnField = 'Field';
$lang->pivot->step2->calcMode = 'Calc Mode';
$lang->pivot->step2->moreThanOne = 'Select at least one group field.';
$lang->pivot->step2->summaryTip = 'After this parameter is selected, you can configure Row Grouping, Column Settings, and Show column totals';
$lang->pivot->step2->groupsTip = 'By selecting a grouping field, the data of the SQL query is grouped and displayed hierarchically in the pivot table.';
$lang->pivot->step2->columnsTip = 'Add 1 column to the pivot table and set it.';
+6 -1
View File
@@ -20,6 +20,7 @@ $lang->pivot->design = 'Design pivot';
$lang->pivot->export = 'Export pivot';
$lang->pivot->query = 'Query';
$lang->pivot->browseAction = 'Design in Pivot Table';
$lang->pivot->designAB = 'Design';
$lang->pivot->id = 'ID';
$lang->pivot->name = 'Name';
@@ -71,6 +72,8 @@ $lang->pivot->percent = '%';
$lang->pivot->undefined = 'Undefiniert';
$lang->pivot->project = $lang->projectCommon;
$lang->pivot->PO = 'PO';
$lang->pivot->showPivot = 'Show Pivot';
$lang->pivot->showOrigin = 'Show Origin Data';
$lang->pivot->colors[] = 'AFD8F8';
$lang->pivot->colors[] = 'AFD8F8';
@@ -261,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.';
@@ -332,6 +335,7 @@ $lang->pivot->typeOptions['dept'] = 'Dept';
$lang->pivot->step2 = new stdclass();
$lang->pivot->step2->group = 'Row Grouping';
$lang->pivot->step2->summary = 'Summary Setting';
$lang->pivot->step2->column = 'Column Settings';
$lang->pivot->step2->groupTip = 'Select Field';
$lang->pivot->step2->groupNum = array('One', 'Two', 'Three');
@@ -344,6 +348,7 @@ $lang->pivot->step2->columnField = 'Field';
$lang->pivot->step2->calcMode = 'Calc Mode';
$lang->pivot->step2->moreThanOne = 'Select at least one group field.';
$lang->pivot->step2->summaryTip = 'After this parameter is selected, you can configure Row Grouping, Column Settings, and Show column totals';
$lang->pivot->step2->groupsTip = 'By selecting a grouping field, the data of the SQL query is grouped and displayed hierarchically in the pivot table.';
$lang->pivot->step2->columnsTip = 'Add 1 column to the pivot table and set it.';
+6 -1
View File
@@ -10,6 +10,7 @@ $lang->pivot->design = 'Design pivot';
$lang->pivot->export = 'Export pivot';
$lang->pivot->query = 'Query';
$lang->pivot->browseAction = 'Design in Pivot Table';
$lang->pivot->designAB = 'Design';
$lang->pivot->id = 'ID';
$lang->pivot->name = 'Name';
@@ -61,6 +62,8 @@ $lang->pivot->percent = '%';
$lang->pivot->undefined = 'Undefiniert';
$lang->pivot->project = $lang->projectCommon;
$lang->pivot->PO = 'PO';
$lang->pivot->showPivot = 'Show Pivot';
$lang->pivot->showOrigin = 'Show Origin Data';
$lang->pivot->colors[] = 'AFD8F8';
$lang->pivot->colors[] = 'AFD8F8';
@@ -251,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.';
@@ -322,6 +325,7 @@ $lang->pivot->typeOptions['dept'] = 'Dept';
$lang->pivot->step2 = new stdclass();
$lang->pivot->step2->group = 'Row Grouping';
$lang->pivot->step2->summary = 'Summary Setting';
$lang->pivot->step2->column = 'Column Settings';
$lang->pivot->step2->groupTip = 'Select Field';
$lang->pivot->step2->groupNum = array('One', 'Two', 'Three');
@@ -334,6 +338,7 @@ $lang->pivot->step2->columnField = 'Field';
$lang->pivot->step2->calcMode = 'Calc Mode';
$lang->pivot->step2->moreThanOne = 'Select at least one group field.';
$lang->pivot->step2->summaryTip = 'After this parameter is selected, you can configure Row Grouping, Column Settings, and Show column totals';
$lang->pivot->step2->groupsTip = 'By selecting a grouping field, the data of the SQL query is grouped and displayed hierarchically in the pivot table.';
$lang->pivot->step2->columnsTip = 'Add 1 column to the pivot table and set it.';
+6 -1
View File
@@ -20,6 +20,7 @@ $lang->pivot->design = '设计透视表';
$lang->pivot->export = '导出透视表';
$lang->pivot->query = '查询';
$lang->pivot->browseAction = '进入透视表设计';
$lang->pivot->designAB = '设计';
$lang->pivot->id = 'ID';
$lang->pivot->name = '名称';
@@ -71,6 +72,8 @@ $lang->pivot->percent = '百分比';
$lang->pivot->undefined = '未设定';
$lang->pivot->project = $lang->projectCommon;
$lang->pivot->PO = 'PO';
$lang->pivot->showPivot = '查看透视表';
$lang->pivot->showOrigin = '查看原始数据';
$lang->pivot->colors[] = 'AFD8F8';
$lang->pivot->colors[] = 'F6BD0F';
@@ -261,7 +264,7 @@ $lang->pivot->noChartSelected = '请选择至少一个图表。';
$lang->pivot->beginGtEnd = '开始时间不得大于结束时间。';
$lang->pivot->resetSettings = '查询数据的配置已修改,是否清空透视表设计,并重新设计。';
$lang->pivot->clearSettings = '查询数据的配置已修改,是否清空透视表设计并保存。';
$lang->pivot->draftSave = '已发布的内容被编辑,将覆盖,是否继续?';
$lang->pivot->draftSave = '该透视表已发布,将变为草稿态,是否继续?';
$lang->pivot->cannotAddQuery = '已添加结果筛选器,无法添加查询筛选器';
$lang->pivot->cannotAddResult = '已添加查询筛选器,无法添加结果筛选器';
@@ -332,6 +335,7 @@ $lang->pivot->typeOptions['dept'] = '部门';
$lang->pivot->step2 = new stdclass();
$lang->pivot->step2->group = '行分组';
$lang->pivot->step2->summary = '汇总设置';
$lang->pivot->step2->column = '列设置';
$lang->pivot->step2->groupTip = '选择字段';
$lang->pivot->step2->groupNum = array('一', '二', '三');
@@ -344,6 +348,7 @@ $lang->pivot->step2->columnField = '字段';
$lang->pivot->step2->calcMode = '计算方式';
$lang->pivot->step2->moreThanOne = '至少选择一个分组字段。';
$lang->pivot->step2->summaryTip = '勾选后,可配置行分组、列设置、显示列的汇总。';
$lang->pivot->step2->groupsTip = '通过选择分组字段,对SQL查询的数据进行分组,并分层级显示在透视表中。';
$lang->pivot->step2->columnsTip = '在透视表中添加1列并对其进行设置。';
+72 -2
View File
@@ -2162,8 +2162,7 @@ class pivotModel extends model
*/
public function buildPivotTable($data, $configs, $fields = array(), $sql = '')
{
$clientLang = $this->app->getClientLang();
$width = 128;
$width = 128;
/* Init table. */
$table = "<table class='reportData table table-condensed table-striped table-bordered table-fixed datatable' style='width: auto; min-width: 100%' data-fixed-left-width='400'>";
@@ -2259,6 +2258,77 @@ class pivotModel extends model
return $sql;
}
/**
* replace defined table names.
*
* @param string $sql
* @access public
* @return string
*/
public function genOriginSheet($fields, $settings, $sql, $filters, $langs = array())
{
$sql = $this->initVarFilter($filters, $sql);
/* Create sql. */
$sql = str_replace(';', '', $sql);
if(preg_match_all("/[\$]+[a-zA-Z0-9]+/", $sql, $out))
{
foreach($out[0] as $match) $sql = str_replace($match, "''", $sql);
}
/* Process rows. */
$connectSQL = '';
if(!empty($filters) && !isset($filters[0]['from']))
{
$wheres = array();
foreach($filters as $field => $filter)
{
$wheres[] = "tt.`$field` {$filter['operator']} {$filter['value']}";
}
$whereStr = implode(' and ', $wheres);
$connectSQL .= " where $whereStr";
}
$columnSQL = "select * from ($sql) tt" . $connectSQL;
$rows = $this->dao->query($columnSQL)->fetchAll();
$cols = array();
$clientLang = $this->app->getClientLang();
/* Build cols. */
foreach($fields as $field)
{
$key = $field['field'];
$col = new stdclass();
$col->name = $key;
$col->isGroup = true;
$fieldObject = $field['object'];
$relatedField = $field['field'];
$colLabel = $key;
if($fieldObject)
{
$this->app->loadLang($fieldObject);
if(isset($this->lang->$fieldObject->$relatedField)) $colLabel = $this->lang->$fieldObject->$relatedField;
}
if(isset($langs[$key]) and !empty($langs[$key][$clientLang])) $colLabel = $langs[$key][$clientLang];
$col->label = $colLabel;
$cols[0][] = $col;
}
$data = new stdclass();
$data->cols = $cols;
$data->array = json_decode(json_encode($rows), true);
$configs = array_fill(0, count($rows), array_fill(0, count($fields), 1));
return array($data, $configs);
}
}
/**
+29 -2
View File
@@ -17,6 +17,7 @@
<?php js::set('WIDTH_DATE', $config->pivot->widthDate);?>
<?php js::set('pickerHeight', $config->bi->pickerHeight);?>
<?php js::set('datepickerText', $this->lang->datepicker->dpText);?>
<?php js::set('confirmDesign', $lang->pivot->confirm->design);?>
<?php $queryDom = "<div class='queryBtn query-inside hidden'> <button type='submit' id='submit' class='btn btn-primary btn-query' data-loading='Loading...'>{$lang->pivot->query}</button></div>";?>
<?php js::set('queryDom', $queryDom);?>
@@ -30,21 +31,37 @@
</div>
<hr class="space">
<?php else:?>
<div class='panel-heading heading-padding'>
<div class='panel-heading heading-padding content-border flex-between'>
<div class='panel-title'>
<?php echo $pivot->name;?>
<?php if(!empty($pivot->desc)):?>
<a data-toggle='tooltip' data-placement='auto' title='<?php echo $pivot->desc;?>'><i class='icon-help'></i></a>
<?php endif;?>
</div>
<div class='flex-start'>
<?php $clickable = $this->pivot->isClickable($pivot, 'design');?>
<?php $showLine = ($clickable and (common::hasPriv('pivot', 'design') or common::hasPriv('pivot', 'edit') or common::hasPriv('pivot', 'delete'))) ? 'query-pseudo' : 'query-after';?>
<?php echo html::a('#', "{$lang->pivot->showOrigin}", '', "id='origin-query' class='$showLine btn-query-origin' title='{$lang->pivot->showOrigin}'");?>
<?php echo html::a('#', "{$lang->pivot->showPivot}", '', "id='pivot-query' class='$showLine btn-query hidden' title='{$lang->pivot->showPivot}'");?>
<?php
$params = helper::safe64Encode("dimensionID=$pivot->dimension&groupID=$pivot->group&pivotID=$pivot->id");
$class = !empty($pivot->used) ? "btn-design" : '';
if(common::hasPriv('pivot', 'design') and $clickable) echo html::a($this->createLink('pivot', 'design', "id=$pivot->id&from=preview&param=$params"), "<i class='icon icon-design'></i> {$lang->pivot->designAB}", '', "class='pivot-design $class' title='{$lang->pivot->designAB}'");
if(common::hasPriv('pivot', 'edit') and $clickable) echo html::a($this->createLink('pivot', 'edit', "id=$pivot->id&from=preview&params=$params", '', true), "<i class='icon icon-edit'></i> {$lang->edit}", '', "class='iframe pivot-edit' title='{$lang->edit}' data-width='600'");
if(common::hasPriv('pivot', 'delete') and $clickable) echo html::a($this->createLink('pivot', 'delete', "id=$pivot->id&confirm=no&from=preview"), "<i class='icon icon-trash'></i> {$lang->delete}", 'hiddenwin', "class='pivot-delete' title='{$lang->delete}'");
?>
</div>
</div>
<div class='panel-body' style='padding:0px;'>
<div id="filterItems" class='filterBox'>
<div class='filter-items'></div>
<?php if(!empty($pivot->filters)):?>
<div class='queryBtn query-outside'><?php echo html::submitButton($lang->pivot->query, "", 'btn btn-primary btn-query');?></div>
<div class='queryBtn query-outside visibility-hidden'><?php echo html::submitButton($lang->pivot->query, "", 'btn btn-primary btn-query');?></div>
<?php endif;?>
</div>
<div id="filterMargin" class='hidden'></div>
<div id='datagirdInfo' class='datagrid datagrid-padding'>
<?php $sql = $this->loadModel('chart')->parseSqlVars($pivot->sql, $pivot->filters);?>
<?php $this->pivot->buildPivotTable($data, $configs, json_decode(json_encode($pivot->fieldSettings), true), $sql);?>
@@ -84,3 +101,13 @@
<div class="default-block hidden"><?php echo html::select('default', '', '', "class='form-control form-select multiple'");?></div>
</div>
</template>
<script>
$(function()
{
$('.btn-design').click(function()
{
var result = confirm(confirmDesign);
if(!result) return false;
});
});
</script>
+4
View File
@@ -31,6 +31,10 @@ class pivotZen extends pivot
$this->view->method = $method;
$this->view->params = $params;
/* This session is used to pivot-preview page, when design edit or delete a pivot in pivot-preview, use session to back current dimension and group. */
$this->session->set('backDimension', $dimension);
$this->session->set('backGroup', $groupID);
if(empty($this->view->title)) $this->view->title = $this->lang->pivot->list;
}
+12 -8
View File
@@ -1778,7 +1778,7 @@ class productModel extends model
* @access public
* @return void
*/
public function refreshStats()
public function refreshStats($refreshAll = false)
{
$updateTime = zget($this->app->config->global, 'productStatsTime', '');
$now = helper::now();
@@ -1788,21 +1788,25 @@ class productModel extends model
* Else only refresh the latest products in action table.
*/
$productActions = array();
if($updateTime > date('Y-m-d', strtotime('-14 days')))
$products = array();
if($updateTime < date('Y-m-d', strtotime('-14 days')) or $refreshAll)
{
$products = $this->dao->select('id')->from(TABLE_PRODUCT)->fetchPairs('id');
}
else
{
$productActions = $this->dao->select('distinct product')->from(TABLE_ACTION)
->where('date')->ge($updateTime)
->andWhere('product')->notin(array(',0,', ',,'))
->fetchPairs('product');
if(empty($productActions)) return;
}
$products = array();
foreach($productActions as $productAction)
{
foreach(explode(',', trim($productAction, ',')) as $product)
foreach($productActions as $productAction)
{
$products[$product] = $product;
foreach(explode(',', trim($productAction, ',')) as $product)
{
$products[$product] = $product;
}
}
}
+7 -2
View File
@@ -1301,7 +1301,7 @@ class programModel extends model
* @access public
* @return void
*/
public function refreshStats()
public function refreshStats($refreshAll = false)
{
$updateTime = zget($this->app->config->global, 'projectStatsTime', '');
$now = helper::now();
@@ -1311,7 +1311,11 @@ class programModel extends model
* Else only refresh the latest executions in action table.
*/
$projects = array();
if($updateTime > date('Y-m-d', strtotime('-14 days')))
if($updateTime < date('Y-m-d', strtotime('-14 days')) or $refreshAll)
{
$projects = $this->dao->select('id,project,model')->from(TABLE_PROJECT)->fetchAll('id');
}
else
{
$projects = $this->dao->select('distinct t1.project,t2.model')->from(TABLE_ACTION)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
@@ -1324,6 +1328,7 @@ class programModel extends model
$summary = $this->dao->select('execution, SUM(t1.estimate) AS totalEstimate, SUM(t1.consumed) AS totalConsumed, SUM(t1.`left`) AS totalLeft')->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t1.parent')->le(0) // Ignore child task.
->beginIF(!empty($projects))->andWhere('t1.project')->in(array_keys($projects))->fi()
->groupBy('execution')
->fetchAll();
+10 -2
View File
@@ -564,10 +564,18 @@ class screenModel extends model
$settings = json_decode($chart->settings, true);
$fields = json_decode($chart->fields, true);
$langs = json_decode($chart->langs, true);
list($options, $config) = $this->loadModel('pivot')->genSheet($fields, $settings, $chart->sql, $filters, $langs);
if(isset($settings['summary']) and $settings['summary'] == 'notuse')
{
list($options, $config) = $this->loadModel('pivot')->genOriginSheet($fields, $settings, $chart->sql, $filters, $langs);
}
else
{
list($options, $config) = $this->loadModel('pivot')->genSheet($fields, $settings, $chart->sql, $filters, $langs);
}
$colspan = array();
if($options->columnTotal and $options->columnTotal == 'sum' and !empty($options->array))
if(isset($options->columnTotal) and $options->columnTotal == 'sum' and !empty($options->array))
{
$optionsData = $options->array;
$count = count($optionsData);
+1 -1
View File
@@ -428,7 +428,7 @@ class searchModel extends model
->skipSpecial('sql,form')
->remove('onMenuBar')
->get();
if($this->post->onMenuBar) $query->shortcut = 1;
if($this->post->onMenuBar) $query->shortcut = '1';
$this->dao->insert(TABLE_USERQUERY)->data($query)->autoCheck()->check('title', 'notempty')->exec();
if(!dao::isError())
+1 -1
View File
@@ -578,7 +578,7 @@ class storyModel extends model
{
if(empty($title)) continue;
$stories->reviewer[$i] = array_filter($stories->reviewer[$i]);
$stories->reviewer[$i] = is_array($stories->reviewer[$i]) ? array_filter($stories->reviewer[$i]) : array();
if(empty($stories->reviewer[$i]) and empty($stories->reviewerDitto[$i])) $stories->reviewer[$i] = array();
$reviewers = (isset($stories->reviewDitto[$i])) ? $reviewers : $stories->reviewer[$i];
$stories->reviewer[$i] = $reviewers;
+32 -25
View File
@@ -1341,7 +1341,7 @@ class testtaskModel extends model
$postReals = $postData->reals[$caseID];
$caseResult = $result ? $result : 'pass';
if($postData->node) $caseResult = '';
if(!empty($postData->node)) $caseResult = '';
$stepResults = array();
if($dbSteps)
{
@@ -2230,17 +2230,21 @@ class testtaskModel extends model
$case = new stdclass();
if(!empty($caseResult->id)) $case->id = $caseResult->id;
$case->product = $productID;
if(empty($caseResult->id)) $case->title = $caseResult->title;
$case->pri = 3;
$case->type = 'unit';
$case->stage = 'unittest';
$case->status = 'normal';
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
if(empty($caseResult->id)) $case->auto = 'unit';
$case->frame = $frame;
$case->status = 'normal';
$case->frame = $frame;
if(empty($caseResult->id))
{
$case->type = 'unit';
$case->stage = 'unittest';
$case->product = $productID;
$case->title = $caseResult->title;
$case->pri = 3;
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
$case->auto = 'unit';
}
$result = new stdclass();
$result->case = 0;
@@ -2298,19 +2302,22 @@ class testtaskModel extends model
if(!isset($suites[$suiteIndex])) $suites[$suiteIndex] = $suite;
$case = new stdclass();
if(isset($caseResult->id)) $case->id = $caseResult->id;
if(!isset($caseResult->id)) $case->product = $productID;
$case->title = $caseResult->title;
$case->pri = 3;
$case->type = 'feature';
$case->stage = 'feature';
$case->status = 'normal';
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
$case->auto = 'func';
$case->frame = $frame;
$case->steps = array();
if(!empty($caseResult->id)) $case->id = $caseResult->id;
$case->title = $caseResult->title;
$case->frame = $frame;
$case->status = 'normal';
$case->steps = array();
$case->auto = 'func';
if(empty($caseResult->id))
{
$case->product = $productID;
$case->pri = 3;
$case->type = 'feature';
$case->stage = 'feature';
$case->openedBy = $this->app->user->account;
$case->openedDate = $now;
$case->version = 1;
}
$result = new stdclass();
$result->case = 0;
+2 -1
View File
@@ -18,6 +18,7 @@
<?php js::set('browseType', $browseType);?>
<?php js::set('moduleID', $moduleID);?>
<?php js::set('case2RunMap', $case2RunMap);?>
<?php js::set('taskID', $taskID);?>
<?php js::set('automation', !empty($automation) ? $automation->id : 0);?>
<?php $this->app->loadLang('zanode');?>
<?php js::set('runCaseConfirm', $lang->zanode->runCaseConfirm);?>
@@ -177,7 +178,7 @@ function runAutocase()
runIDList.push(case2RunMap[$(this).val()]);
});
var url = createLink('zanode', 'ajaxRunZTFScript', 'scriptID=' + automation)
var url = createLink('zanode', 'ajaxRunZTFScript', 'scriptID=' + automation + "&taskID=" + taskID)
var postData = {'caseIDList' : caseIDList.join(','), 'runIDList' : runIDList.join(',')};
+4 -2
View File
@@ -38,7 +38,8 @@ $config->upgrade->maxVersion['max4_3'] = '18_3';
$config->upgrade->maxVersion['max4_4_alpha1'] = '18_4_alpha1';
$config->upgrade->maxVersion['max4_4_beta1'] = '18_4_beta1';
$config->upgrade->maxVersion['max4_4'] = '18_4';
$config->upgrade->maxVersion['max4_5'] = '18_5'; // max insert position.
$config->upgrade->maxVersion['max4_5'] = '18_5';
$config->upgrade->maxVersion['max4_6'] = '18_6'; // max insert position.
$config->upgrade->bizVersion = array();
$config->upgrade->bizVersion['biz1_0'] = '9_5_1';
@@ -115,7 +116,8 @@ $config->upgrade->bizVersion['biz8_3'] = '18_3';
$config->upgrade->bizVersion['biz8_4_alpha1'] = '18_4_alpha1';
$config->upgrade->bizVersion['biz8_4_beta1'] = '18_4_beta1';
$config->upgrade->bizVersion['biz8_4'] = '18_4';
$config->upgrade->bizVersion['biz8_5'] = '18_5'; // biz insert position.
$config->upgrade->bizVersion['biz8_5'] = '18_5';
$config->upgrade->bizVersion['biz8_6'] = '18_6'; // biz insert position.
$config->upgrade->proVersion = array();
$config->upgrade->proVersion['pro1_0'] = '3_1';
+5 -3
View File
@@ -179,7 +179,8 @@ $lang->upgrade->fromVersions['18_3'] = '18.3';
$lang->upgrade->fromVersions['18_4_alpha1'] = '18.4.alpha1';
$lang->upgrade->fromVersions['18_4_beta1'] = '18.4.beta1';
$lang->upgrade->fromVersions['18_4'] = '18.4';
$lang->upgrade->fromVersions['18_5'] = '18.5'; // pms insert position.
$lang->upgrade->fromVersions['18_5'] = '18.5';
$lang->upgrade->fromVersions['18_6'] = '18.6'; // pms insert position.
global $config;
/* Lite. */
@@ -363,7 +364,8 @@ $lang->upgrade->fromVersions['biz8_3'] = 'Biz8.3';
$lang->upgrade->fromVersions['biz8_4_alpha1'] = 'Biz8.4.alpha1';
$lang->upgrade->fromVersions['biz8_4_beta1'] = 'Biz8.4.beta1';
$lang->upgrade->fromVersions['biz8_4'] = 'Biz8.4';
$lang->upgrade->fromVersions['biz8_5'] = 'Biz8.5'; // biz insert position.
$lang->upgrade->fromVersions['biz8_5'] = 'Biz8.5';
$lang->upgrade->fromVersions['biz8_6'] = 'Biz8.6'; // biz insert position.
/* Max. */
$lang->upgrade->fromVersions['max2_0_beta4'] = 'Max2.0.beta4';
@@ -408,4 +410,4 @@ $lang->upgrade->fromVersions['max4_4'] = 'Max4.4';
$lang->upgrade->fromVersions['max4_5'] = 'Max4.5'; // max insert position.
/* Ipd */
$lang->upgrade->fromVersions['ipd1_0_beta1'] = 'Ipd1.0.beta1';
$lang->upgrade->fromVersions['ipd1_0_beta1'] = 'Ipd1.0.beta1'; // ipd insert position.
+63 -5
View File
@@ -676,6 +676,11 @@ class upgradeModel extends model
if(strpos($fromVersion, 'ipd') === false) $this->execSQL($this->getUpgradeFile('ipdinstall'));
if($fromVersion == 'ipd1.0.beta1') $this->execSQL($this->getUpgradeFile('ipd1.0.beta1'));
if($this->config->edition == 'ipd' and strpos($fromVersion, 'ipd') === false) $this->addORPriv();
$this->loadModel('product')->refreshStats(true);
$this->loadModel('program')->refreshStats(true);
$this->updatePivotFieldsType();
break;
}
@@ -1488,7 +1493,7 @@ class upgradeModel extends model
try
{
$tableExists = true;
$stmt = $this->dbh->query("show fields from `{$table}`");
$stmt = $this->dbh->query("show fields from `$table`");
while($row = $stmt->fetch()) $fields[$row->Field] = $row->Field;
}
catch(PDOException $e)
@@ -1514,11 +1519,11 @@ class upgradeModel extends model
if(stripos($line, 'auto_increment') !== false) $line .= ' primary key';
try
{
$this->dbh->exec("ALTER TABLE `{$table}` ADD $line");
$this->dbh->exec("ALTER TABLE `$table` ADD $line");
}
catch(PDOException $e)
{
$alterSQL .= "ALTER TABLE `{$table}` ADD $line;\n";
$alterSQL .= "ALTER TABLE `$table` ADD $line;\n";
}
}
}
@@ -9263,8 +9268,18 @@ class upgradeModel extends model
$columns[] = $column;
$data->stage = 'draft';
$data->step = 1;
$this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
$stmt = $this->dbh->query($data->sql);
if(!$stmt)
{
$data->stage = 'draft';
$data->step = 1;
}
else
{
$settings->summary = 'notuse';
}
}
$settings->columns = $columns;
@@ -9603,4 +9618,47 @@ class upgradeModel extends model
}
}
/**
* Update pivot fields type, pivotID maybe is 1008,1012,1013,1015,1020,1027.
*
* @access public
* @return void
*/
public function updatePivotFieldsType()
{
$fieldsPairs = array();
$fieldsPairs[] = array('maybeID' => 1008, 'beforefields' => '"execution":{"object":"project","field":"execution","type":"string"},"type":{"object":"project","field":"type","type":"string"}',
'fields' => '{"id":{"object":"project","field":"id","type":"string"},"project":{"object":"project","field":"project","type":"string"},"execution":{"object":"project","field":"execution","type":"string"},"type":{"object":"task","field":"type","type":"option"},"taskID":{"object":"task","field":"taskID","type":"string"},"projectstatus":{"object":"task","field":"projectstatus","type":"string"}}',
'langs' => '{"project":{"zh-cn":"\\u9879\\u76ee\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"execution":{"zh-cn":"\\u6267\\u884c\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"id":{"zh-cn":"\\u9879\\u76eeID","zh-tw":"","en":"","de":"","fr":""},"type":{"zh-cn":"\\u4efb\\u52a1\\u7c7b\\u578b","zh-tw":"","en":"","de":"","fr":""},"taskID":{"zh-cn":"taskID","zh-tw":"","en":"","de":"","fr":""},"projectstatus":{"zh-cn":"projectstatus","zh-tw":"","en":"","de":"","fr":""}}');
$fieldsPairs[] = array('maybeID' => 1012, 'beforefields' => '"project":{"object":"projectstory","field":"project","type":"string"},"execution":{"object":"project","field":"execution","type":"string"},"status":{"object":"project","field":"status","type":"string"}',
'fields' => '{"id":{"object":"project","field":"id","type":"string"},"project":{"object":"projectstory","field":"project","type":"string"},"execution":{"object":"project","field":"execution","type":"string"},"status":{"object":"story","field":"status","type":"option"}}',
);
$fieldsPairs[] = array('maybeID' => 1013, 'beforefields' => '"execution":{"object":"project","field":"execution","type":"string"},"stage":{"object":"project","field":"stage","type":"string"}}',
'fields' => '{"id":{"object":"project","field":"id","type":"string"},"project":{"object":"projectstory","field":"project","type":"string"},"execution":{"object":"project","field":"execution","type":"string"},"stage":{"object":"story","field":"stage","type":"option"}}',
'langs' => '{"project":{"zh-cn":"\\u9879\\u76ee\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"execution":{"zh-cn":"\\u6267\\u884c\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"id":{"zh-cn":"\\u9879\\u76eeID","zh-tw":"","en":"","de":"","fr":""},"stage":{"zh-cn":"\\u9636\\u6bb5","zh-tw":"","en":"","de":"","fr":""}}');
$fieldsPairs[] = array('maybeID' => 1015, 'beforefields' => '"bugID":{"object":"bug","field":"bugID","type":"string"},"status":{"object":"project","field":"status","type":"string"}',
'fields' => '{"id":{"object":"project","field":"id","type":"string"},"project":{"object":"project","field":"project","type":"string"},"t3id":{"object":"project","field":"t3id","type":"string"},"execution":{"object":"project","field":"execution","type":"string"},"bugID":{"object":"bug","field":"bugID","type":"string"},"status":{"object":"bug","field":"status","type":"option"}}',
);
$fieldsPairs[] = array('maybeID' => 1020, 'beforefields' => '"bugID":{"object":"project","field":"bugID","type":"string"},"type":{"object":"product","field":"type","type":"string"}',
'fields' => '{"id":{"object":"product","field":"id","type":"string"},"name":{"object":"product","field":"name","type":"string"},"bugID":{"object":"project","field":"bugID","type":"string"},"type":{"object":"bug","field":"type","type":"option"}}',
'langs' => '{"count":{"zh-cn":"\\u9700\\u6c42\\u6570","zh-tw":"\\u9700\\u6c42\\u6570","en":"Stories"},"done":{"zh-cn":"\\u5b8c\\u6210\\u6570","zh-tw":"\\u5b8c\\u6210\\u6570","en":"Done"},"id":{"zh-cn":"\\u7f16\\u53f7","zh-tw":"","en":"","de":"","fr":""},"name":{"zh-cn":"\\u4ea7\\u54c1\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"bugID":{"zh-cn":"bugID","zh-tw":"","en":"","de":"","fr":""},"type":{"zh-cn":"Bug\\u7c7b\\u578b","zh-tw":"","en":"","de":"","fr":""}}');
$fieldsPairs[] = array('maybeID' => 1027, 'beforefields' => '"bugID":{"object":"bug","field":"bugID","type":"string"},"type":{"object":"project","field":"type","type":"string"}',
'fields' => '{"id":{"object":"project","field":"id","type":"string"},"project":{"object":"project","field":"project","type":"string"},"t3id":{"object":"project","field":"t3id","type":"string"},"execution":{"object":"project","field":"execution","type":"string"},"bugID":{"object":"bug","field":"bugID","type":"string"},"type":{"object":"bug","field":"type","type":"option"}}',
'langs' => '{"stories":{"zh-cn":"\\u9700\\u6c42\\u6570","zh-tw":"\\u9700\\u6c42\\u6570","en":"Stories"},"tasks":{"zh-cn":"\\u4efb\\u52a1\\u6570","zh-tw":"\\u4efb\\u52a1\\u6570","en":"Tasks"},"undoneStory":{"zh-cn":"\\u5269\\u4f59\\u9700\\u6c42\\u6570","zh-tw":"\\u5269\\u4f59\\u9700\\u6c42\\u6570","en":"Undone Story"},"undoneTask":{"zh-cn":"\\u5269\\u4f59\\u4efb\\u52a1\\u6570","zh-tw":"\\u5269\\u4f59\\u4efb\\u52a1\\u6570","en":"Undone Task"},"consumed":{"zh-cn":"\\u5df2\\u6d88\\u8017\\u5de5\\u65f6","zh-tw":"\\u5df2\\u6d88\\u8017\\u5de5\\u65f6","en":"Cost(h)"},"left":{"zh-cn":"\\u5269\\u4f59\\u5de5\\u65f6","zh-tw":"\\u5269\\u4f59\\u5de5\\u65f6","en":"Left(h)"},"consumedPercent":{"zh-cn":"\\u8fdb\\u5ea6","zh-tw":"\\u8fdb\\u5ea6","en":"Process"},"execution":{"zh-cn":"\\u6267\\u884c\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"id":{"zh-cn":"\\u9879\\u76eeID","zh-tw":"","en":"","de":"","fr":""},"project":{"zh-cn":"\\u9879\\u76ee\\u540d\\u79f0","zh-tw":"","en":"","de":"","fr":""},"bugID":{"zh-cn":"bugID","zh-tw":"","en":"","de":"","fr":""},"type":{"zh-cn":"Bug\\u7c7b\\u578b","zh-tw":"","en":"","de":"","fr":""}}');
foreach($fieldsPairs as $field)
{
$pivot = $this->dao->select('*')->from(TABLE_PIVOT)->where('fields')->like("%{$field['beforefields']}%")->fetchAll();
if(count($pivot) > 1 or count($pivot) == 0) continue;
$pivot = reset($pivot);
$data = new stdclass();
if(isset($field['fields'])) $data->fields = $field['fields'];
if(isset($field['langs'])) $data->langs = $field['langs'];
$this->dao->update(TABLE_PIVOT)->data($data)->where('id')->eq($pivot->id)->exec();
}
}
}
+14 -4
View File
@@ -609,23 +609,33 @@ class zanode extends control
* Ajax: run ZTF script.
*
* @param int $scriptID
* @param string $taskID
* @access public
* @return void
*/
public function ajaxRunZTFScript($scriptID = 0)
public function ajaxRunZTFScript($scriptID = 0, $taskID = 0)
{
if($_POST)
{
$caseIDList = $_POST['caseIDList'];
$runIDList = $_POST['runIDList'];
$runIDList = empty($_POST['runIDList']) ? array() : $_POST['runIDList'];
$script = $this->zanode->getAutomationByID($scriptID);
$cases = $this->loadModel('testcase')->getByList($caseIDList);
$cases = $this->loadModel('testcase')->getByList($caseIDList);
$runs = array();
if($taskID)
{
$runs = $this->dao->select('id, `case`')->from(TABLE_TESTRUN)
->where('`case`')->in($caseIDList)
->andWhere('task')->eq($taskID)->fi()
->fetchPairs('case', 'id');
}
$caseIDListArray = explode(',', $caseIDList);
$runIDListArray = explode(',', $runIDList);
$case2RunMap = array();
foreach($caseIDListArray as $index => $caseID) $case2RunMap[$caseID] = $runIDListArray[$index];
foreach($caseIDListArray as $index => $caseID) $case2RunMap[$caseID] = empty($runIDListArray[$index]) ? 0 : $runIDListArray[$index];
foreach($cases as $id => $case)
{
-1
View File
@@ -1 +0,0 @@
v7.2.1-rc.4
-1
View File
@@ -1 +0,0 @@
7.2.1