This commit is contained in:
liyuchun
2022-08-19 15:42:01 +08:00
1249 changed files with 327227 additions and 2100 deletions
+5 -3
View File
@@ -44,6 +44,7 @@ $config->action->objectNameFields['kanbancard'] = 'name';
$config->action->objectNameFields['sonarqube'] = 'name';
$config->action->objectNameFields['gitlab'] = 'name';
$config->action->objectNameFields['gitea'] = 'name';
$config->action->objectNameFields['gogs'] = 'name';
$config->action->objectNameFields['stage'] = 'name';
$config->action->objectNameFields['apistruct'] = 'name';
$config->action->objectNameFields['repo'] = 'name';
@@ -60,9 +61,10 @@ $config->action->majorList['program'] = array('opened', 'edited');
$config->action->majorList['project'] = array('opened', 'edited');
$config->action->majorList['execution'] = array('opened', 'edited');
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,';
$config->action->needGetProjectType = 'build,task,bug,case,testcase,caselib,testtask,testsuite,testreport,doc,issue,release,risk,design,opportunity,trainplan,gapanalysis,researchplan,researchreport,';
$config->action->needGetRelateField = ',story,productplan,release,task,build,bug,testcase,case,testtask,testreport,doc,doclib,issue,risk,opportunity,trainplan,gapanalysis,team,whitelist,researchplan,researchreport,meeting,kanbanlane,kanbancolumn,module,';
$config->action->noLinkModules = ',doclib,module,webhook,gitlab,gitea,gogs,sonarqube,pipeline,jenkins,kanban,kanbanspace,kanbancolumn,kanbanlane,kanbanregion,kanbancard,execution,project,traincategory,apistruct,program,product,user,entry,repo,';
$config->action->ignoreObjectType4Dynamic = 'kanbanregion,kanbanlane,kanbancolumn';
$config->action->preferredTypeNum = 10;
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = 'Der Verlauf darf nicht leer sein.';
$lang->action->noDynamic = 'Kein Verlauf. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".';
$lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLib';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = 'The history EditBy cannot be empty.';
$lang->action->noDynamic = 'No dynamics. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".';
$lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLab Server';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = "l'historique Edité Par ne peut pas être v
$lang->action->noDynamic = "Pas d'historique.";
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->repeatChange = '%s with the same name and code already exists in the system, After recovery, the name are \"%s\",the code are \"%s\".';
$lang->action->nameRepeatChange = '%s with the same name already exists in the system, After recovery, the name are \"%s\".';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLib';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+34 -16
View File
@@ -30,13 +30,16 @@ $lang->action->editComment = 'Sửa nhận xét';
$lang->action->create = 'Thêm nhận xét';
$lang->action->comment = 'Nhận xét';
$lang->action->trashTips = 'Ghi chú: Xóa trong ZenTao là hợp lệ.';
$lang->action->textDiff = 'Định dạng văn bản';
$lang->action->original = 'Định dạng gốc';
$lang->action->confirmHideAll = 'Bạn có muốn ẩn tất cả ghi nhận này?';
$lang->action->needEdit = '%s mà bạn muốn khôi phục. Vui lòng edit it.';
$lang->action->historyEdit = 'Lịch sử người cập nhật không thể trống.';
$lang->action->noDynamic = 'Không có lịch sử. ';
$lang->action->trashTips = 'Ghi chú: Xóa trong ZenTao là hợp lệ.';
$lang->action->textDiff = 'Định dạng văn bản';
$lang->action->original = 'Định dạng gốc';
$lang->action->confirmHideAll = 'Bạn có muốn ẩn tất cả ghi nhận này?';
$lang->action->needEdit = '%s mà bạn muốn khôi phục. Vui lòng edit it.';
$lang->action->historyEdit = 'Lịch sử người cập nhật không thể trống.';
$lang->action->noDynamic = 'Không có lịch sử. ';
$lang->action->undeletedTips = 'This data did not participate in the merging process during the version upgrade process, so restore is not supported.';
$lang->action->executionNoProject = 'The execution does not belong to a project,please restore the project first';
$lang->action->repoNoServer = 'The repo does not belong to a server,please restore the server first';
$lang->action->history = new stdclass();
$lang->action->history->action = 'Liên kết';
@@ -102,6 +105,7 @@ $lang->action->objectTypes['whitelist'] = 'Whitelist';
$lang->action->objectTypes['pipeline'] = 'GitLib';
$lang->action->objectTypes['gitlab'] = 'GitLab Server';
$lang->action->objectTypes['gitea'] = 'Gitea Server';
$lang->action->objectTypes['gogs'] = 'Gogs Server';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = 'Merge Request';
$lang->action->objectTypes['gitlabproject'] = 'GitLab Project';
@@ -112,6 +116,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab Protected Branches';
$lang->action->objectTypes['gitlabtag'] = 'GitLab Tag';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab Tag Protected';
$lang->action->objectTypes['giteauser'] = 'Gitea User';
$lang->action->objectTypes['gogsuser'] = 'Gogs User';
$lang->action->objectTypes['kanbanspace'] = 'Kanban Space';
$lang->action->objectTypes['kanban'] = 'Kanban';
$lang->action->objectTypes['kanbanregion'] = 'Kanban Region';
@@ -493,19 +498,32 @@ $lang->action->dynamicAction->job['executed'] = 'Execute Job';
$lang->action->dynamicAction->job['deleted'] = 'Delete Job';
$lang->action->dynamicAction->job['undeleted'] = 'Undelete Job';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['created'] = 'Create SonarQube Server';
$lang->action->dynamicAction->sonarqube['edited'] = 'Edit SonarQube Server';
$lang->action->dynamicAction->sonarqube['deleted'] = 'Delete SonarQube Server';
$lang->action->dynamicAction->sonarqube['undeleted'] = 'Undelete SonarQube Server';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = 'Delete SonarQube Project';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['created'] = 'Create GitLab Server';
$lang->action->dynamicAction->gitlab['edited'] = 'Edit GitLab Server';
$lang->action->dynamicAction->gitlab['deleted'] = 'Delete GitLab Server';
$lang->action->dynamicAction->gitlab['undeleted'] = 'Undelete GitLab Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['created'] = 'Create Gitea Server';
$lang->action->dynamicAction->gitea['edited'] = 'Edit Gitea Server';
$lang->action->dynamicAction->gitea['deleted'] = 'Delete Gitea Server';
$lang->action->dynamicAction->gitea['undeleted'] = 'Undelete Gitea Server';
$lang->action->dynamicAction->gogs['created'] = 'Create Gogs Server';
$lang->action->dynamicAction->gogs['edited'] = 'Edit Gogs Server';
$lang->action->dynamicAction->gogs['deleted'] = 'Delete Gogs Server';
$lang->action->dynamicAction->gogs['undeleted'] = 'Undelete Gogs Server';
$lang->action->dynamicAction->repo['created'] = 'Create Repo';
$lang->action->dynamicAction->repo['edited'] = 'Edit Repo';
$lang->action->dynamicAction->repo['deleted'] = 'Delete Repo';
$lang->action->dynamicAction->repo['undeleted'] = 'Undelete Repo';
/* Generate the corresponding object link. */
global $config;
+25 -9
View File
@@ -57,6 +57,7 @@ $lang->action->historyEdit = '历史记录编辑不能为空。';
$lang->action->noDynamic = '暂时没有动态。';
$lang->action->undeletedTips = '该数据在版本升级过程中未参与数据归并流程,不支持还原。';
$lang->action->executionNoProject = '该执行没有所属的项目,请先还原项目再还原执行';
$lang->action->repoNoServer = '该代码库没有所属的服务器,请先还原服务器再还原代码库';
$lang->action->repeatChange = '系统内已有同名、同代号的%s,恢复后名称为\"%s\"、代号为\"%s\"。';
$lang->action->nameRepeatChange = '系统内已有同名的%s,恢复后名称为\"%s\"。';
@@ -128,6 +129,7 @@ $lang->action->objectTypes['whitelist'] = '白名单';
$lang->action->objectTypes['pipeline'] = 'GitLab服务器';
$lang->action->objectTypes['gitlab'] = 'GitLab服务器';
$lang->action->objectTypes['gitea'] = 'Gitea服务器';
$lang->action->objectTypes['gogs'] = 'Gogs服务器';
$lang->action->objectTypes['jenkins'] = 'Jenkins';
$lang->action->objectTypes['mr'] = '合并请求';
$lang->action->objectTypes['gitlabproject'] = 'GitLab项目';
@@ -138,6 +140,7 @@ $lang->action->objectTypes['gitlabbranchpriv'] = 'GitLab保护分支';
$lang->action->objectTypes['gitlabtag'] = 'GitLab标签';
$lang->action->objectTypes['gitlabtagpriv'] = 'GitLab标签保护';
$lang->action->objectTypes['giteauser'] = 'Gitea用户';
$lang->action->objectTypes['gogsuser'] = 'Gogs用户';
$lang->action->objectTypes['kanbanspace'] = '看板空间';
$lang->action->objectTypes['kanban'] = '看板';
$lang->action->objectTypes['kanbanregion'] = '看板区域';
@@ -637,19 +640,32 @@ $lang->action->dynamicAction->job['executed'] = '执行构建任务';
$lang->action->dynamicAction->job['deleted'] = '删除构建任务';
$lang->action->dynamicAction->job['undeleted'] = '还原构建任务';
$lang->action->dynamicAction->sonarqube['created'] = '创建SonarQube服务器';
$lang->action->dynamicAction->sonarqube['edited'] = '设置SonarQube服务器';
$lang->action->dynamicAction->sonarqube['deleted'] = '删除SonarQube服务器';
$lang->action->dynamicAction->sonarqube['created'] = '创建SonarQube服务器';
$lang->action->dynamicAction->sonarqube['edited'] = '设置SonarQube服务器';
$lang->action->dynamicAction->sonarqube['deleted'] = '删除SonarQube服务器';
$lang->action->dynamicAction->sonarqube['undeleted'] = '还原SonarQube服务器';
$lang->action->dynamicAction->sonarqubeproject['deleted'] = '删除SonarQube项目';
$lang->action->dynamicAction->gitlab['created'] = '创建GitLab服务器';
$lang->action->dynamicAction->gitlab['edited'] = '编辑GitLab服务器';
$lang->action->dynamicAction->gitlab['deleted'] = '删除GitLab服务器';
$lang->action->dynamicAction->gitlab['created'] = '创建GitLab服务器';
$lang->action->dynamicAction->gitlab['edited'] = '编辑GitLab服务器';
$lang->action->dynamicAction->gitlab['deleted'] = '删除GitLab服务器';
$lang->action->dynamicAction->gitlab['undeleted'] = '还原GitLab服务器';
$lang->action->dynamicAction->gitea['created'] = '创建Gitea服务器';
$lang->action->dynamicAction->gitea['edited'] = '编辑Gitea服务器';
$lang->action->dynamicAction->gitea['deleted'] = '删除Gitea服务器';
$lang->action->dynamicAction->gitea['created'] = '创建Gitea服务器';
$lang->action->dynamicAction->gitea['edited'] = '编辑Gitea服务器';
$lang->action->dynamicAction->gitea['deleted'] = '删除Gitea服务器';
$lang->action->dynamicAction->gitea['undeleted'] = '还原Gitea服务器';
$lang->action->dynamicAction->gogs['created'] = '创建Gogs服务器';
$lang->action->dynamicAction->gogs['edited'] = '编辑Gogs服务器';
$lang->action->dynamicAction->gogs['deleted'] = '删除Gogs服务器';
$lang->action->dynamicAction->gogs['undeleted'] = '还原Gogs服务器';
$lang->action->dynamicAction->repo['created'] = '创建代码库';
$lang->action->dynamicAction->repo['edited'] = '编辑代码库';
$lang->action->dynamicAction->repo['deleted'] = '删除代码库';
$lang->action->dynamicAction->repo['undeleted'] = '还原代码库';
/* 用来生成相应对象的链接。*/
$lang->action->label->product = $lang->productCommon . '|product|view|productID=%s';
+25 -4
View File
@@ -1053,7 +1053,7 @@ class actionModel extends model
/* Get actions. */
$actions = $this->dao->select('*')->from(TABLE_ACTION)
->where('objectType')->notIN('kanbanregion,kanbanlane,kanbancolumn')
->where('objectType')->notIN($this->config->action->ignoreObjectType4Dynamic)
->andWhere('vision')->eq($this->config->vision)
->beginIF($period != 'all')->andWhere('date')->gt($begin)->fi()
->beginIF($period != 'all')->andWhere('date')->lt($end)->fi()
@@ -1216,6 +1216,7 @@ class actionModel extends model
$this->app->loadLang('todo');
$this->app->loadLang('stakeholder');
$this->app->loadLang('branch');
$this->app->loadLang('execution');
/* Get commiters and the same department users. */
$commiters = $this->loadModel('user')->getCommiters();
@@ -1258,6 +1259,10 @@ class actionModel extends model
$modules = $this->dao->select('id,name')->from(TABLE_MODULE)->where('id')->in(explode(',', $action->extra))->fetchPairs('id');
$action->objectName = implode(',', $modules);
}
elseif($action->objectType == 'mr' and $action->action == 'deleted')
{
$action->objectName = $action->extra;
}
$projectID = isset($relatedProjects[$action->objectType][$action->objectID]) ? $relatedProjects[$action->objectType][$action->objectID] : 0;
@@ -1273,14 +1278,14 @@ class actionModel extends model
/* If action type is login or logout, needn't link. */
if($actionType == 'svncommited' or $actionType == 'gitcommited') $action->actor = zget($commiters, $action->actor);
/* Get gitlab or gitea objectname. */
if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea')) $action->objectName = $action->extra;
/* Get gitlab, gitea or gogs objectname. */
if(empty($action->objectName) and (substr($objectType, 0, 6) == 'gitlab' or substr($objectType, 0, 5) == 'gitea' or substr($objectType, 0, 4) == 'gogs')) $action->objectName = $action->extra;
/* Other actions, create a link. */
$this->setObjectLink($action, $deptUsers);
/* Set merge request link. */
if(empty($action->objectName) and $action->objectType == 'mr') $action->objectLink = '';
if((empty($action->objectName) or $action->action == 'deleted') and $action->objectType == 'mr') $action->objectLink = '';
$action->major = (isset($this->config->action->majorList[$action->objectType]) && in_array($action->action, $this->config->action->majorList[$action->objectType])) ? 1 : 0;
}
@@ -1723,6 +1728,16 @@ class actionModel extends model
if((int)$projectCount == 0) return print(js::error($this->lang->action->executionNoProject));
}
if($action->objectType == 'repo')
{
$repo = $this->dao->select('*')->from(TABLE_REPO)->where('id')->eq($action->objectID)->fetch();
if($repo and in_array($repo->SCM, array('Gitlab', 'Gitea', 'Gogs')))
{
$server = $this->dao->select('*')->from(TABLE_PIPELINE)->where('id')->eq($repo->serviceHost)->andWhere('deleted')->eq('0')->fetch();
if(empty($server)) return print(js::error($this->lang->action->repoNoServer));
}
}
if($action->objectType == 'product')
{
$product = $this->dao->select('id,name,code,acl')->from(TABLE_PRODUCT)->where('id')->eq($action->objectID)->fetch();
@@ -1751,6 +1766,12 @@ class actionModel extends model
{
$products = $this->product->getProducts($project->id, 'all', '', false);
if(!empty($products)) $this->loadModel('user')->updateUserView(array_keys($products), 'product');
if($action->objectType == 'execution')
{
$execution = $this->dao->select('id, project, grade, parent, status, deleted')->from(TABLE_EXECUTION)->where('id')->eq($action->objectID)->fetch();
$this->loadModel('common')->syncExecutionByChild($execution);
}
}
/* Revert doclib when undelete product or project. */
+12
View File
@@ -2,3 +2,15 @@ $(function()
{
$("#mainHeader #navbar li[data-id='system']").addClass('active');
})
/**
* When changeWeask change.
*
* @param bool changeWeak
* @access public
* @return void
*/
function changeWeakChange(changeWeak)
{
$('#mainContent .table td.notice').html(changeWeak == 1 ? adminLang.safe.noticeWeakMode : adminLang.safe.noticeMode);
}
+1
View File
@@ -75,6 +75,7 @@ $lang->admin->safe->checkWeak = 'Schwache Passwörter prüfen';
$lang->admin->safe->changeWeak = 'Ihr Passwort ist schwach. Bitte ändern.';
$lang->admin->safe->loginCaptcha = 'Login using CAPTCHA';
$lang->admin->safe->modifyPasswordFirstLogin = 'Passwort nach der ersten Anmeldung ändern';
$lang->admin->safe->passwordStrengthWeak = 'The password strength is weaker than the system settings.';
$lang->admin->safe->modeList[0] = 'N/A';
$lang->admin->safe->modeList[1] = 'Medium';
+1
View File
@@ -75,6 +75,7 @@ $lang->admin->safe->checkWeak = 'Weak Password Scan';
$lang->admin->safe->changeWeak = 'Force to change weak password';
$lang->admin->safe->loginCaptcha = 'Login using CAPTCHA';
$lang->admin->safe->modifyPasswordFirstLogin = 'Force to change password after first login';
$lang->admin->safe->passwordStrengthWeak = 'The password strength is weaker than the system settings.';
$lang->admin->safe->modeList[0] = 'I don\'t care.';
$lang->admin->safe->modeList[1] = 'Medium';
+1
View File
@@ -75,6 +75,7 @@ $lang->admin->safe->checkWeak = 'Balayage des mots de passe faibl
$lang->admin->safe->changeWeak = 'Forcer le changement des mots de passe faibles';
$lang->admin->safe->loginCaptcha = 'Login using CAPTCHA';
$lang->admin->safe->modifyPasswordFirstLogin = 'Forcer le changement du mot de passe après la première connexion';
$lang->admin->safe->passwordStrengthWeak = 'Le mot de passe est moins fort que les paramètres du système.';
$lang->admin->safe->modeList[0] = "Contrôle Modéré";
$lang->admin->safe->modeList[1] = 'Contrôle Moyen';
+1
View File
@@ -75,6 +75,7 @@ $lang->admin->safe->checkWeak = '弱口令扫描';
$lang->admin->safe->changeWeak = '修改弱口令密码';
$lang->admin->safe->loginCaptcha = '登录使用验证码';
$lang->admin->safe->modifyPasswordFirstLogin = '首次登录修改密码';
$lang->admin->safe->passwordStrengthWeak = '密码强度小于系统设置';
$lang->admin->safe->modeList[0] = '不检查';
$lang->admin->safe->modeList[1] = '中';
-7
View File
@@ -234,13 +234,6 @@ class adminModel extends model
{
$weaks = array();
/* Check weak password when login. */
if($this->app->moduleName == 'user' and $this->app->methodName == 'login')
{
if(!isset($_POST['passwordStrength'])) return false;
if(isset($this->config->safe->mode) and $this->post->passwordStrength < $this->config->safe->mode) return true;
}
foreach(explode(',', $this->config->safe->weak) as $weak)
{
$weak = md5(trim($weak));
+2 -1
View File
@@ -15,6 +15,7 @@
.icon-exclamation-sign.icon {color:#2667E3; margin-right: 8px;}
.notice {color:#2667E3; margin-left: 12px;}
</style>
<?php js::set('adminLang', $lang->admin);?>
<?php include '../../common/view/header.html.php';?>
<div id='mainMenu' class='clearfix'>
<div class='btn-toolbar pull-left'>
@@ -62,7 +63,7 @@
</tr>
<tr>
<th><?php echo $lang->admin->safe->changeWeak?></th>
<td colspan='2'><?php echo html::radio('changeWeak', $lang->admin->safe->modifyPasswordList, isset($config->safe->changeWeak) ? $config->safe->changeWeak : 0)?></td>
<td colspan='2'><?php echo html::radio('changeWeak', $lang->admin->safe->modifyPasswordList, isset($config->safe->changeWeak) ? $config->safe->changeWeak : 0, "onchange='changeWeakChange(this.value)'")?></td>
</tr>
<tr>
<th><?php echo $lang->admin->safe->modifyPasswordFirstLogin?></th>
+7 -16
View File
@@ -888,6 +888,7 @@ class block extends control
/* Load models and langs. */
$this->loadModel('project');
$this->loadModel('weekly');
$this->loadModel('execution');
$this->app->loadLang('task');
$this->app->loadLang('story');
$this->app->loadLang('bug');
@@ -898,7 +899,7 @@ class block extends control
/* Get projects. */
$excludedModel = $this->config->edition == 'max' ? '' : 'waterfall';
$projects = $this->loadModel('project')->getOverviewList('byStatus', $status, 'order_asc', $count, $excludedModel);
$projects = $this->project->getOverviewList('byStatus', $status, 'order_asc', $count, $excludedModel);
if(empty($projects))
{
$this->view->projects = $projects;
@@ -924,7 +925,7 @@ class block extends control
$this->app->loadClass('pager', $static = true);
$pager = pager::init(0, 3, 1);
$project->progress = $project->allStories == 0 ? 0 : round($project->doneStories / $project->allStories, 3) * 100;
$project->executions = $this->project->getStats($projectID, 'all', 0, 0, 30, 'id_desc', $pager);
$project->executions = $this->execution->getStatData($projectID, 'all', 0, 0, false, '', 'id_desc', $pager);
}
elseif($project->model == 'waterfall')
{
@@ -1356,8 +1357,8 @@ class block extends control
$this->app->loadClass('pager', $static = true);
$pager = pager::init(0, $count, 1);
$this->app->loadLang('execution');
$this->view->executionStats = !defined('TUTORIAL') ? $this->loadModel('project')->getStats($this->session->project, $type, 0, 0, 30, 'id_desc', $pager) : array($this->loadModel('tutorial')->getExecution());
$this->loadModel('execution');
$this->view->executionStats = !defined('TUTORIAL') ? $this->execution->getStatData($this->session->project, $type, 0, 0, false, '', 'id_desc', $pager) : array($this->loadModel('tutorial')->getExecution());
}
/**
@@ -1692,7 +1693,7 @@ class block extends control
$count = isset($this->params->count) ? (int)$this->params->count : 0;
$status = isset($this->params->type) ? $this->params->type : 'all';
$this->app->loadLang('execution');
$this->loadModel('execution');
$this->app->loadClass('pager', true);
$pager = pager::init(0, $count, 1);
@@ -1700,18 +1701,8 @@ class block extends control
if($this->config->systemMode == 'new') $projectPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('type')->eq('project')->fetchPairs('id', 'name');
$projectID = $this->view->block->module == 'my' ? 0 : (int)$this->session->project;
$executions = $this->loadModel('project')->getStats($projectID, $status, 0, 0, 30, 'id_asc', $pager);
foreach($executions as $index => $execution)
{
if(empty($execution->children)) continue;
foreach($execution->children as $child) $executions[] = $child;
unset($executions[$index]);
}
$this->view->executionStats = $executions;
$this->view->projectPairs = $projectPairs;
$this->view->executionStats = $this->execution->getStatData($projectID, $status, 0, 0, false, 'skipParent', 'id_asc', $pager);
}
/**
@@ -43,7 +43,6 @@
<?php
$appid = isset($_GET['entry']) ? "class='app-btn text-center' data-id='{$this->get->entry}'" : "class='text-center'";
$viewLink = $this->createLink('execution', 'task', 'executionID=' . $execution->id);
if($config->systemMode == 'new' and isset($projectPairs[$execution->project])) $execution->name = zget($projectPairs, $execution->project, '') . ' / ' . $execution->name;
?>
<tr <?php echo $appid?>>
<td class='c-name text-left' title='<?php echo $execution->name;?>'><nobr><?php echo html::a($viewLink, $execution->name, '', "title='$execution->name'");?></nobr></td>
+10 -17
View File
@@ -133,35 +133,28 @@ $config->bug->search['params']['branch'] = array('operator' => '=',
$config->bug->search['params']['plan'] = array('operator' => '=', 'control' => 'select', 'values' => '');
$config->bug->search['params']['module'] = array('operator' => 'belong', 'control' => 'select', 'values' => 'modules');
$config->bug->search['params']['execution'] = array('operator' => '=', 'control' => 'select', 'values' => 'executions');
$config->bug->search['params']['severity'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->severityList);
$config->bug->search['params']['pri'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->priList);
$config->bug->search['params']['type'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->typeList);
$config->bug->search['params']['os'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->osList);
$config->bug->search['params']['browser'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->browserList);
$config->bug->search['params']['os'] = array('operator' => 'include', 'control' => 'select', 'values' => $lang->bug->osList);
$config->bug->search['params']['browser'] = array('operator' => 'include', 'control' => 'select', 'values' => $lang->bug->browserList);
$config->bug->search['params']['resolution'] = array('operator' => '=', 'control' => 'select', 'values' => $lang->bug->resolutionList);
$config->bug->search['params']['activatedCount']= array('operator' => '>=', 'control' => 'input', 'values' => '');
$config->bug->search['params']['toTask'] = array('operator' => '=', 'control' => 'input', 'values' => '');
$config->bug->search['params']['toStory'] = array('operator' => '=', 'control' => 'input', 'values' => '');
$config->bug->search['params']['openedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->bug->search['params']['closedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->bug->search['params']['lastEditedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->bug->search['params']['mailto'] = array('operator' => 'include', 'control' => 'select', 'values' => 'users');
$config->bug->search['params']['mailto'] = array('operator' => 'include', 'control' => 'select', 'values' => 'users');
$config->bug->search['params']['openedBuild'] = array('operator' => 'include', 'control' => 'select', 'values' => 'builds');
$config->bug->search['params']['resolvedBuild'] = array('operator' => '=', 'control' => 'select', 'values' => 'builds');
$config->bug->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['assignedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['resolvedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['closedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['lastEditedDate']= array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['deadline'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['activatedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['assignedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['resolvedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['closedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['lastEditedDate']= array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['deadline'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->search['params']['activatedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->bug->datatable = new stdclass();
$config->bug->datatable->defaultField = array('id', 'severity', 'pri', 'confirmed', 'title', 'status', 'openedBy', 'openedDate', 'assignedTo', 'resolution', 'actions');
+4 -2
View File
@@ -859,6 +859,7 @@ class bug extends control
$this->view->moduleID = $moduleID;
$this->view->branch = $branch;
$this->view->branches = $branches;
$this->display();
}
@@ -1132,6 +1133,8 @@ class bug extends control
$moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0, $bug->branch);
if(!isset($moduleOptionMenu[$bug->module])) $moduleOptionMenu += $this->tree->getModulesName($bug->module);
$cases = $this->loadmodel('testcase')->getPairsByProduct($bug->product, array(0, $bug->branch));
/* Get assigned to member. */
if($bug->execution)
{
@@ -1165,6 +1168,7 @@ class bug extends control
$this->view->testtasks = $this->loadModel('testtask')->getPairs($bug->product, $bug->execution, $bug->testtask);
$this->view->users = $this->user->getPairs('', "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy,$bug->openedBy");
$this->view->assignedToList = $assignedToList;
$this->view->cases = array('' => '') + $cases;
$this->view->openedBuilds = $openedBuilds;
$this->view->resolvedBuilds = array('' => '') + $openedBuilds + $oldResolvedBuild;
$this->view->actions = $this->action->getList('bug', $bugID);
@@ -1379,8 +1383,6 @@ class bug extends control
$this->view->priList = array('0' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->priList;
$this->view->resolutionList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->resolutionList;
$this->view->statusList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->statusList;
$this->view->osList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->osList;
$this->view->browserList = array('' => '', 'ditto' => $this->lang->bug->ditto) + $this->lang->bug->browserList;
$this->view->bugs = $bugs;
$this->view->branch = $branch;
$this->view->users = $users;
+1
View File
@@ -55,3 +55,4 @@ html[lang='de'] #keywordsAddonLabel, .task {width: 73px;}
#executionLabel {display: inline; position: relative; width: 50%; left: 37%;}
#projectLabel {display: inline;}
#openedBuildLabel {display: inline; position: relative; width: 50%; left: 14%;}
#bugTypeInputGroup > .table-col {width: 40% !important;}
+2
View File
@@ -5,3 +5,5 @@
.tab-pane table {border: 1px solid #ddd; border-top: none;}
.btn-edit-comment {z-index: 100;}
.select-project-modal .modal-body {right: 15px;}
.osContent, .browserContent {margin: 0 0 5px;}
.browserContent {margin-left: -4px;}
+23
View File
@@ -8,4 +8,27 @@ $(function()
$("#sidebarHeader").toggle("fast");
});
if($("main").is(".hide-sidebar")) $("#sidebarHeader").hide();
$('#bugList').on('change', "[name='bugIDList[]']", checkClosed);
});
/**
* Closed bugs are not assignable.
*
* @access public
* @return void
*/
function checkClosed()
{
var disabledAssigned = $('#bugList tr.checked .c-assignedTo a').length > 0 ? true : false;
$('#bugList tr.checked .c-assignedTo a').each(function()
{
if(!$(this).hasClass('disabled'))
{
disabledAssigned = false;
return false;
}
});
$('#mulAssigned').prop('disabled', disabledAssigned);
}
+32 -45
View File
@@ -232,51 +232,39 @@ $lang->bug->priList[2] = '2';
$lang->bug->priList[3] = '3';
$lang->bug->priList[4] = '4';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = 'Alle';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['vista'] = 'Windows Vista';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['win2012'] = 'Windows 2012';
$lang->bug->osList['win2008'] = 'Windows 2008';
$lang->bug->osList['win2003'] = 'Windows 2003';
$lang->bug->osList['win2000'] = 'Windows 2000';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['wp8'] = 'WP8';
$lang->bug->osList['wp7'] = 'WP7';
$lang->bug->osList['symbian'] = 'Symbian';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['freebsd'] = 'FreeBSD';
$lang->bug->osList['osx'] = 'OS X';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = 'Andere';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = 'Alle';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win11'] = 'Windows 11';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['osx'] = 'Mac OS';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['ubuntu'] = 'Ubuntu';
$lang->bug->osList['chromeos'] = 'Chrome OS';
$lang->bug->osList['fedora'] = 'Fedora';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = 'Andere';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = 'Alle';
$lang->bug->browserList['ie'] = 'IE series';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['ie7'] = 'IE7';
$lang->bug->browserList['ie6'] = 'IE6';
$lang->bug->browserList['chrome'] = 'chrome';
$lang->bug->browserList['firefox'] = 'Firefox series';
$lang->bug->browserList['firefox4'] = 'Firefox4';
$lang->bug->browserList['firefox3'] = 'Firefox3';
$lang->bug->browserList['firefox2'] = 'Firefox2';
$lang->bug->browserList['opera'] = 'Opera series';
$lang->bug->browserList['oprea11'] = 'Opera11';
$lang->bug->browserList['oprea10'] = 'Opera10';
$lang->bug->browserList['opera9'] = 'Opera9';
$lang->bug->browserList['safari'] = 'Safari';
$lang->bug->browserList['maxthon'] = 'Maxthon';
$lang->bug->browserList['uc'] = 'UC';
$lang->bug->browserList['other'] = 'Andere';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = 'Alle';
$lang->bug->browserList['chrome'] = 'Chrome';
$lang->bug->browserList['edge'] = 'Edge';
$lang->bug->browserList['ie'] = 'IE series';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['firefox'] = 'Firefox series';
$lang->bug->browserList['opera'] = 'Opera series';
$lang->bug->browserList['safari'] = 'Safari';
$lang->bug->browserList['360'] = '360 series';
$lang->bug->browserList['qq'] = 'QQ series';
$lang->bug->browserList['other'] = 'Andere';
$lang->bug->typeList[''] = '';
$lang->bug->typeList['codeerror'] = 'Code Fehler';
@@ -428,7 +416,6 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
+32 -45
View File
@@ -232,51 +232,39 @@ $lang->bug->priList[2] = '2';
$lang->bug->priList[3] = '3';
$lang->bug->priList[4] = '4';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = 'All';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['vista'] = 'Windows Vista';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['win2012'] = 'Windows 2012';
$lang->bug->osList['win2008'] = 'Windows 2008';
$lang->bug->osList['win2003'] = 'Windows 2003';
$lang->bug->osList['win2000'] = 'Windows 2000';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['wp8'] = 'WP8';
$lang->bug->osList['wp7'] = 'WP7';
$lang->bug->osList['symbian'] = 'Symbian';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['freebsd'] = 'FreeBSD';
$lang->bug->osList['osx'] = 'OS X';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = 'Others';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = 'All';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win11'] = 'Windows 11';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['osx'] = 'Mac OS';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['ubuntu'] = 'Ubuntu';
$lang->bug->osList['chromeos'] = 'Chrome OS';
$lang->bug->osList['fedora'] = 'Fedora';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = 'Others';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = 'All';
$lang->bug->browserList['ie'] = 'IE series';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['ie7'] = 'IE7';
$lang->bug->browserList['ie6'] = 'IE6';
$lang->bug->browserList['chrome'] = 'Chrome';
$lang->bug->browserList['firefox'] = 'Firefox series';
$lang->bug->browserList['firefox4'] = 'Firefox4';
$lang->bug->browserList['firefox3'] = 'Firefox3';
$lang->bug->browserList['firefox2'] = 'Firefox2';
$lang->bug->browserList['opera'] = 'Opera series';
$lang->bug->browserList['oprea11'] = 'Opera11';
$lang->bug->browserList['oprea10'] = 'Opera10';
$lang->bug->browserList['opera9'] = 'Opera9';
$lang->bug->browserList['safari'] = 'Safari';
$lang->bug->browserList['maxthon'] = 'Maxthon';
$lang->bug->browserList['uc'] = 'UC';
$lang->bug->browserList['other'] = 'Others';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = 'All';
$lang->bug->browserList['chrome'] = 'Chrome';
$lang->bug->browserList['edge'] = 'Edge';
$lang->bug->browserList['ie'] = 'IE series';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['firefox'] = 'Firefox series';
$lang->bug->browserList['opera'] = 'Opera series';
$lang->bug->browserList['safari'] = 'Safari';
$lang->bug->browserList['360'] = '360 series';
$lang->bug->browserList['qq'] = 'QQ series';
$lang->bug->browserList['other'] = 'Others';
$lang->bug->typeList[''] = '';
$lang->bug->typeList['codeerror'] = 'CodeError';
@@ -428,7 +416,6 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
+32 -45
View File
@@ -232,51 +232,39 @@ $lang->bug->priList[2] = '2';
$lang->bug->priList[3] = '3';
$lang->bug->priList[4] = '4';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = 'Tous';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['vista'] = 'Windows Vista';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['win2012'] = 'Windows 2012';
$lang->bug->osList['win2008'] = 'Windows 2008';
$lang->bug->osList['win2003'] = 'Windows 2003';
$lang->bug->osList['win2000'] = 'Windows 2000';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['wp8'] = 'WP8';
$lang->bug->osList['wp7'] = 'WP7';
$lang->bug->osList['symbian'] = 'Symbian';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['freebsd'] = 'FreeBSD';
$lang->bug->osList['osx'] = 'OS X';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = 'Autres';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = 'Tous';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win11'] = 'Windows 11';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['osx'] = 'Mac OS';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['ubuntu'] = 'Ubuntu';
$lang->bug->osList['chromeos'] = 'Chrome OS';
$lang->bug->osList['fedora'] = 'Fedora';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = 'Autres';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = 'Tous';
$lang->bug->browserList['ie'] = 'IE series';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['ie7'] = 'IE7';
$lang->bug->browserList['ie6'] = 'IE6';
$lang->bug->browserList['chrome'] = 'Chrome';
$lang->bug->browserList['firefox'] = 'Firefox series';
$lang->bug->browserList['firefox4'] = 'Firefox4';
$lang->bug->browserList['firefox3'] = 'Firefox3';
$lang->bug->browserList['firefox2'] = 'Firefox2';
$lang->bug->browserList['opera'] = 'Opera series';
$lang->bug->browserList['oprea11'] = 'Opera11';
$lang->bug->browserList['oprea10'] = 'Opera10';
$lang->bug->browserList['opera9'] = 'Opera9';
$lang->bug->browserList['safari'] = 'Safari';
$lang->bug->browserList['maxthon'] = 'Maxthon';
$lang->bug->browserList['uc'] = 'UC';
$lang->bug->browserList['other'] = 'Autres';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = 'Tous';
$lang->bug->browserList['chrome'] = 'Chrome';
$lang->bug->browserList['edge'] = 'Edge';
$lang->bug->browserList['ie'] = 'IE series';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['firefox'] = 'Firefox series';
$lang->bug->browserList['opera'] = 'Opera series';
$lang->bug->browserList['safari'] = 'Safari';
$lang->bug->browserList['360'] = '360 series';
$lang->bug->browserList['qq'] = 'QQ series';
$lang->bug->browserList['other'] = 'Autres';
$lang->bug->typeList[''] = '';
$lang->bug->typeList['codeerror'] = 'Code Erreur';
@@ -428,7 +416,6 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed;
$lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe;
$lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe;
$lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
+32 -45
View File
@@ -232,51 +232,39 @@ $lang->bug->priList[2] = '2';
$lang->bug->priList[3] = '3';
$lang->bug->priList[4] = '4';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = '全部';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['vista'] = 'Windows Vista';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['win2012'] = 'Windows 2012';
$lang->bug->osList['win2008'] = 'Windows 2008';
$lang->bug->osList['win2003'] = 'Windows 2003';
$lang->bug->osList['win2000'] = 'Windows 2000';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['wp8'] = 'WP8';
$lang->bug->osList['wp7'] = 'WP7';
$lang->bug->osList['symbian'] = 'Symbian';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['freebsd'] = 'FreeBSD';
$lang->bug->osList['osx'] = 'OS X';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = '其他';
$lang->bug->osList[''] = '';
$lang->bug->osList['all'] = '全部';
$lang->bug->osList['windows'] = 'Windows';
$lang->bug->osList['win11'] = 'Windows 11';
$lang->bug->osList['win10'] = 'Windows 10';
$lang->bug->osList['win8'] = 'Windows 8';
$lang->bug->osList['win7'] = 'Windows 7';
$lang->bug->osList['winxp'] = 'Windows XP';
$lang->bug->osList['osx'] = 'Mac OS';
$lang->bug->osList['android'] = 'Android';
$lang->bug->osList['ios'] = 'IOS';
$lang->bug->osList['linux'] = 'Linux';
$lang->bug->osList['ubuntu'] = 'Ubuntu';
$lang->bug->osList['chromeos'] = 'Chrome OS';
$lang->bug->osList['fedora'] = 'Fedora';
$lang->bug->osList['unix'] = 'Unix';
$lang->bug->osList['others'] = '其他';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = '全部';
$lang->bug->browserList['ie'] = 'IE系列';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['ie7'] = 'IE7';
$lang->bug->browserList['ie6'] = 'IE6';
$lang->bug->browserList['chrome'] = 'chrome';
$lang->bug->browserList['firefox'] = 'firefox系列';
$lang->bug->browserList['firefox4'] = 'firefox4';
$lang->bug->browserList['firefox3'] = 'firefox3';
$lang->bug->browserList['firefox2'] = 'firefox2';
$lang->bug->browserList['opera'] = 'opera系列';
$lang->bug->browserList['oprea11'] = 'opera11';
$lang->bug->browserList['oprea10'] = 'opera10';
$lang->bug->browserList['opera9'] = 'opera9';
$lang->bug->browserList['safari'] = 'safari';
$lang->bug->browserList['maxthon'] = '傲游';
$lang->bug->browserList['uc'] = 'UC';
$lang->bug->browserList['other'] = '其他';
$lang->bug->browserList[''] = '';
$lang->bug->browserList['all'] = '全部';
$lang->bug->browserList['chrome'] = 'Chrome';
$lang->bug->browserList['edge'] = 'Edge';
$lang->bug->browserList['ie'] = 'IE系列';
$lang->bug->browserList['ie11'] = 'IE11';
$lang->bug->browserList['ie10'] = 'IE10';
$lang->bug->browserList['ie9'] = 'IE9';
$lang->bug->browserList['ie8'] = 'IE8';
$lang->bug->browserList['firefox'] = 'firefox系列';
$lang->bug->browserList['opera'] = 'Opera系列';
$lang->bug->browserList['safari'] = 'safari';
$lang->bug->browserList['360'] = '360浏览器';
$lang->bug->browserList['qq'] = 'QQ浏览器';
$lang->bug->browserList['other'] = '其他';
$lang->bug->typeList[''] = '';
$lang->bug->typeList['codeerror'] = '代码错误';
@@ -432,7 +420,6 @@ $lang->bug->featureBar['browse']['assignedbyme'] = $lang->bug->assignedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
+50 -19
View File
@@ -76,6 +76,8 @@ class bugModel extends model
->trim('title')
->join('openedBuild', ',')
->join('mailto', ',')
->join('os', ',')
->join('browser', ',')
->remove('files,labels,uid,oldTaskID,contactListMenu,region,lane')
->get();
@@ -163,25 +165,24 @@ class bugModel extends model
$execution = 0;
$type = '';
$pri = 0;
$os = '';
$browser = '';
foreach($data->title as $i => $title)
{
$oses = array_filter($data->oses[$i]);
$browsers = array_filter($data->browsers[$i]);
if($data->modules[$i] != 'ditto') $module = (int)$data->modules[$i];
if($data->projects[$i] != 'ditto') $project = (int)$data->projects[$i];
if($data->executions[$i] != 'ditto') $execution = (int)$data->executions[$i];
if($data->types[$i] != 'ditto') $type = $data->types[$i];
if($data->pris[$i] != 'ditto') $pri = $data->pris[$i];
if($data->oses[$i] != 'ditto') $os = $data->oses[$i];
if($data->browsers[$i] != 'ditto') $browser = $data->browsers[$i];
$data->modules[$i] = (int)$module;
$data->projects[$i] = (int)$project;
$data->executions[$i] = (int)$execution;
$data->types[$i] = $type;
$data->pris[$i] = $pri;
$data->oses[$i] = $os;
$data->browsers[$i] = $browser;
$data->oses[$i] = implode(',', $oses);
$data->browsers[$i] = implode(',', $browsers);
}
/* Get bug data. */
@@ -689,6 +690,8 @@ class bugModel extends model
->stripTags($this->config->bug->editor->edit['id'], $this->config->allowedTags)
->setDefault('product,module,execution,story,task,duplicateBug,branch', 0)
->setDefault('openedBuild', '')
->setDefault('os', '')
->setDefault('browser', '')
->setDefault('plan', 0)
->setDefault('deadline', '0000-00-00')
->setDefault('resolvedDate', '0000-00-00 00:00:00')
@@ -699,6 +702,8 @@ class bugModel extends model
->join('openedBuild', ',')
->join('mailto', ',')
->join('linkBug', ',')
->join('os', ',')
->join('browser', ',')
->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now)
->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now)
@@ -716,6 +721,7 @@ class bugModel extends model
->setIF($this->post->resolution != '', 'confirmed', 1)
->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story))
->setIF(!$this->post->linkBug, 'linkBug', '')
->setIF($this->post->case === '', 'case', 0)
->remove('comment,files,labels,uid,contactListMenu')
->get();
@@ -805,8 +811,6 @@ class bugModel extends model
if($data->assignedTos[$bugID] == 'ditto') $data->assignedTos[$bugID] = isset($prev['assignedTo']) ? $prev['assignedTo'] : '';
if($data->resolvedBys[$bugID] == 'ditto') $data->resolvedBys[$bugID] = isset($prev['resolvedBy']) ? $prev['resolvedBy'] : '';
if($data->resolutions[$bugID] == 'ditto') $data->resolutions[$bugID] = isset($prev['resolution']) ? $prev['resolution'] : '';
if($data->os[$bugID] == 'ditto') $data->os[$bugID] = isset($prev['os']) ? $prev['os'] : '';
if($data->browsers[$bugID] == 'ditto') $data->browsers[$bugID] = isset($prev['browser']) ? $prev['browser'] : '';
if(isset($data->branches[$bugID]) and $data->branches[$bugID] == 'ditto') $data->branches[$bugID] = isset($prev['branch']) ? $prev['branch'] : 0;
$prev['type'] = $data->types[$bugID];
@@ -817,8 +821,6 @@ class bugModel extends model
$prev['assignedTo'] = $data->assignedTos[$bugID];
$prev['resolvedBy'] = $data->resolvedBys[$bugID];
$prev['resolution'] = $data->resolutions[$bugID];
$prev['os'] = $data->os[$bugID];
$prev['browser'] = $data->browsers[$bugID];
}
/* Initialize bugs from the post data.*/
@@ -828,6 +830,9 @@ class bugModel extends model
{
$oldBug = $oldBugs[$bugID];
$os = array_filter($data->os[$bugID]);
$browsers = array_filter($data->browsers[$bugID]);
$bug = new stdclass();
$bug->id = $bugID;
$bug->lastEditedBy = $this->app->user->account;
@@ -840,12 +845,12 @@ class bugModel extends model
$bug->plan = empty($data->plans[$bugID]) ? 0 : $data->plans[$bugID];
$bug->branch = empty($data->branches[$bugID]) ? 0 : $data->branches[$bugID];
$bug->module = $data->modules[$bugID];
$bug->assignedTo = $data->assignedTos[$bugID];
$bug->assignedTo = $bug->status == 'closed' ? $oldBug->assignedTo : $data->assignedTos[$bugID];
$bug->deadline = $data->deadlines[$bugID];
$bug->resolvedBy = $data->resolvedBys[$bugID];
$bug->keywords = $data->keywords[$bugID];
$bug->os = $data->os[$bugID];
$bug->browser = $data->browsers[$bugID];
$bug->os = implode(',', $os);
$bug->browser = implode(',', $browsers);
$bug->resolution = $data->resolutions[$bugID];
$bug->duplicateBug = $data->duplicateBugs[$bugID] ? $data->duplicateBugs[$bugID] : $oldBug->duplicateBug;
@@ -1004,6 +1009,8 @@ class bugModel extends model
{
$now = helper::now();
$oldBug = $this->getById($bugID);
if($oldBug->status == 'closed') return false;
$bug = fixer::input('post')
->add('id', $bugID)
->setDefault('lastEditedBy', $this->app->user->account)
@@ -3170,9 +3177,25 @@ class bugModel extends model
}
}
$bugLink = helper::createLink('bug', 'view', "bugID=$bug->id");
$account = $this->app->user->account;
$id = $col->id;
$bugLink = helper::createLink('bug', 'view', "bugID=$bug->id");
$account = $this->app->user->account;
$id = $col->id;
$os = '';
$browser = '';
$osList = explode(',', $bug->os);
$browserList = explode(',', $bug->browser);
foreach($osList as $value)
{
if(empty($value)) continue;
$os .= $this->lang->bug->osList[$value] . ',';
}
foreach($browserList as $value)
{
if(empty($value)) continue;
$browser .= $this->lang->bug->browserList[$value] . ',';
}
$os = trim($os, ',');
$browser = trim($browser, ',');
if($col->show)
{
$class = "c-$id";
@@ -3221,6 +3244,14 @@ class bugModel extends model
$class .= ' text-ellipsis';
$title = "title='" . $bug->resolvedBuild . "'";
break;
case 'os':
$class .= ' text-ellipsis';
$title = "title='" . $os . "'";
break;
case 'browser':
$class .= ' text-ellipsis';
$title = "title='" . $browser . "'";
break;
}
if($id == 'deadline' && isset($bug->delay) && $bug->status == 'active') $class .= ' delayed';
@@ -3319,10 +3350,10 @@ class bugModel extends model
echo $bug->keywords;
break;
case 'os':
echo zget($this->lang->bug->osList, $bug->os);
echo $os;
break;
case 'browser':
echo zget($this->lang->bug->browserList, $bug->browser);
echo $browser;
break;
case 'mailto':
$mailto = explode(',', $bug->mailto);
@@ -3528,7 +3559,7 @@ class bugModel extends model
$toStoryParams = "product=$bug->product&branch=$bug->branch&module=0&story=0&execution=0&bugID=$bug->id";
$menu .= $this->buildMenu('bug', 'confirmBug', $params, $bug, $type, 'ok', '', "iframe", true);
if($type == 'view') $menu .= $this->buildMenu('bug', 'assignTo', $params, $bug, $type, '', '', "iframe", true);
if($type == 'view' and $bug->status != 'closed') $menu .= $this->buildMenu('bug', 'assignTo', $params, $bug, $type, '', '', "iframe", true);
$menu .= $this->buildMenu('bug', 'resolve', $params, $bug, $type, 'checked', '', "iframe showinonlybody", true);
$menu .= $this->buildMenu('bug', 'close', $params, $bug, $type, '', '', "text-danger iframe showinonlybody", true);
if($type == 'view') $menu .= $this->buildMenu('bug', 'activate', $params, $bug, $type, '', '', "text-success iframe showinonlybody", true);
+8 -14
View File
@@ -92,8 +92,6 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
$executions += array('ditto' => $lang->bug->ditto);
$lang->bug->typeList += array('ditto' => $lang->bug->ditto);
$lang->bug->priList += array('ditto' => $lang->bug->ditto);
$lang->bug->osList += array('ditto' => $lang->bug->ditto);
$lang->bug->browserList += array('ditto' => $lang->bug->ditto);
?>
<?php $i = 1; ?>
<?php if(!empty($titles)):?>
@@ -104,8 +102,6 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
$executionID = $i == 1 ? $executionID : 'ditto';
$type = $i == 1 ? '' : 'ditto';
$pri = $i == 1 ? 0 : 'ditto';
$os = $i == 1 ? '' : 'ditto';
$browser = $i == 1 ? '' : 'ditto';
?>
<tr>
<td class='text-left'><?php echo $i;?></td>
@@ -139,8 +135,8 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
<td class='<?php echo zget($visibleFields, 'type', 'hidden')?> typeBox' style='overflow:visible'> <?php echo html::select("types[$i]", $lang->bug->typeList, $type, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'pri', 'hidden')?> priBox' style='overflow:visible'> <?php echo html::select("pris[$i]", $lang->bug->priList, $pri, "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'severity', 'hidden')?> severityBox' style='overflow:visible'><?php echo html::select("severities[$i]", $lang->bug->severityList, '3', "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[$i]", $lang->bug->osList, $os, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[$i]", $lang->bug->browserList, $browser, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[$i][]", $lang->bug->osList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[$i][]", $lang->bug->browserList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?> keywordsBox'><?php echo html::input("keywords[$i]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
@@ -164,8 +160,6 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
$executionID = $i - $nextStart == 0 ? $executionID : 'ditto';
$type = $i - $nextStart == 0 ? '' : 'ditto';
$pri = $i - $nextStart == 0 ? 0 : 'ditto';
$os = $i - $nextStart == 0 ? '' : 'ditto';
$browser = $i - $nextStart == 0 ? '' : 'ditto';
?>
<tr>
<td><?php echo $i;?></td>
@@ -199,8 +193,8 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
<td class='<?php echo zget($visibleFields, 'type', 'hidden')?> typeBox' style='overflow:visible'> <?php echo html::select("types[$i]", $lang->bug->typeList, $type, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'pri', 'hidden')?> priBox' style='overflow:visible'> <?php echo html::select("pris[$i]", $lang->bug->priList, $pri, "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'severity', 'hidden')?> severityBox' style='overflow:visible'><?php echo html::select("severities[$i]", $lang->bug->severityList, '3', "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[$i]", $lang->bug->osList, $os, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[$i]", $lang->bug->browserList, $browser, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[$i][]", $lang->bug->osList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[$i][]", $lang->bug->browserList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?> keywordsBox'><?php echo html::input("keywords[$i]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
@@ -258,8 +252,8 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
<td class='<?php echo zget($visibleFields, 'type', 'hidden')?> typeBox' style='overflow:visible'> <?php echo html::select("types[%s]", $lang->bug->typeList, $type, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'pri', 'hidden')?> priBox' style='overflow:visible'> <?php echo html::select("pris[%s]", $lang->bug->priList, $pri, "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'severity', 'hidden')?> severityBox' style='overflow:visible'><?php echo html::select("severities[%s]", $lang->bug->severityList, '3', "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[%s]", $lang->bug->osList, $os, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[%s]", $lang->bug->browserList, $browser, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[%s][]", $lang->bug->osList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[%s][]", $lang->bug->browserList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?> keywordsBox'><?php echo html::input("keywords[%s]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
@@ -307,8 +301,8 @@ foreach(explode(',', $config->bug->create->requiredFields) as $field)
<td class='<?php echo zget($visibleFields, 'type', 'hidden')?> typeBox' style='overflow:visible'> <?php echo html::select("types[$i]", $lang->bug->typeList, $type, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'pri', 'hidden')?> priBox' style='overflow:visible'> <?php echo html::select("pris[$i]", $lang->bug->priList, $pri, "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'severity', 'hidden')?> severityBox' style='overflow:visible'><?php echo html::select("severities[$i]", $lang->bug->severityList, '3', "class='form-control'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[$i]", $lang->bug->osList, $os, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[$i]", $lang->bug->browserList, $browser, "class='form-control chosen'");?></td>
<td class='<?php echo zget($visibleFields, 'os', 'hidden')?> osBox' style='overflow:visible'> <?php echo html::select("oses[$i][]", $lang->bug->osList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'browser', 'hidden')?> browserBox' style='overflow:visible'> <?php echo html::select("browsers[$i][]", $lang->bug->browserList, '', "class='form-control chosen' multiple");?></td>
<td class='<?php echo zget($visibleFields, 'keywords', 'hidden')?> keywordsBox'><?php echo html::input("keywords[$i]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
+3 -3
View File
@@ -132,10 +132,10 @@
unset($assignedToList['closed']);
}
?>
<td class='<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo html::select("assignedTos[$bugID]", $assignedToList, $bug->assignedTo, "class='form-control picker-select' data-drop-width='135px'");?></td>
<td class='<?php echo zget($visibleFields, 'assignedTo', ' hidden')?>' style='overflow:visible'><?php echo $bug->status == 'closed' ? html::input("assignedTos[$bugID]", ucfirst($bug->assignedTo), 'class=form-control disabled') : html::select("assignedTos[$bugID]", $assignedToList, $bug->assignedTo, "class='form-control picker-select' data-drop-width='135px'");?></td>
<td class='<?php echo zget($visibleFields, 'deadline', ' hidden')?>' style='overflow:visible'><?php echo html::input("deadlines[$bugID]", helper::isZeroDate($bug->deadline) ? '' : $bug->deadline, "class='form-control form-date'");?></td>
<td <?php echo zget($visibleFields, 'os', "class='hidden'")?>><?php echo html::select("os[$bugID]", $osList, $bug->os, 'class=form-control');?></td>
<td <?php echo zget($visibleFields, 'browser', "class='hidden'")?>><?php echo html::select("browsers[$bugID]", $browserList, $bug->browser, 'class=form-control');?></td>
<td <?php echo zget($visibleFields, 'os', "class='hidden'")?>><?php echo html::select("os[$bugID][]", $lang->bug->osList, $bug->os, 'class="form-control chosen" multiple');?></td>
<td <?php echo zget($visibleFields, 'browser', "class='hidden'")?>><?php echo html::select("browsers[$bugID][]", $lang->bug->browserList, $bug->browser, 'class="form-control chosen" multiple');?></td>
<td <?php echo zget($visibleFields, 'keywords', "class='hidden'")?>><?php echo html::input("keywords[$bugID]", $bug->keywords, 'class=form-control');?></td>
<td class='<?php echo zget($visibleFields, 'resolvedBy', ' hidden')?>' style='overflow:visible'><?php echo html::select("resolvedBys[$bugID]", $users, $bug->resolvedBy, "class='form-control picker-select' data-drop-width='auto'");?></td>
<td <?php echo zget($visibleFields, 'resolution', "class='hidden'")?>>
+1 -1
View File
@@ -403,7 +403,7 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow
<?php endif;?>
<?php if($canBatchAssignTo):?>
<div class="btn-group dropup">
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->bug->assignedTo;?> <span class="caret"></span></button>
<button data-toggle="dropdown" type="button" class="btn" id="mulAssigned"><?php echo $lang->bug->assignedTo;?> <span class="caret"></span></button>
<?php $withSearch = count($memberPairs) > 6;?>
<?php if($withSearch):?>
<div class="dropdown-menu search-list search-box-sink" data-ride="searchList">
+14 -6
View File
@@ -91,12 +91,20 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
<div class='input-group' id='bugTypeInputGroup'>
<?php echo html::select('type', $lang->bug->typeList, $type, "class='form-control'");?>
<?php if($showOS):?>
<span class='input-group-addon fix-border'><?php echo $lang->bug->os?></span>
<?php echo html::select('os', $lang->bug->osList, $os, "class='form-control'");?>
<div class='table-col'>
<div class='input-group'>
<span class='input-group-addon fix-border'><?php echo $lang->bug->os?></span>
<?php echo html::select('os[]', $lang->bug->osList, $os, "class='form-control chosen' multiple");?>
</div>
</div>
<?php endif;?>
<?php if($showBrowser):?>
<span class='input-group-addon fix-border'><?php echo $lang->bug->browser?></span>
<?php echo html::select('browser', $lang->bug->browserList, $browser, "class='form-control'");?>
<div class='table-col'>
<div class='input-group'>
<span class='input-group-addon fix-border'><?php echo $lang->bug->browser?></span>
<?php echo html::select('browser[]', $lang->bug->browserList, $browser, "class='form-control chosen' multiple");?>
</div>
</div>
<?php endif;?>
</div>
</td>
@@ -186,7 +194,7 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
<div class='table-col' id='osBox'>
<div class='input-group'>
<span class='input-group-addon fix-border'><?php echo $lang->bug->os?></span>
<?php echo html::select('os', $lang->bug->osList, $os, "class='form-control chosen'");?>
<?php echo html::select('os[]', $lang->bug->osList, $os, "class='form-control chosen' multiple");?>
</div>
</div>
<?php endif;?>
@@ -194,7 +202,7 @@ if($this->app->tab == 'project') js::set('objectID', $projectID);
<div class='table-col'>
<div class='input-group'>
<span class='input-group-addon fix-border'><?php echo $lang->bug->browser?></span>
<?php echo html::select('browser', $lang->bug->browserList, $browser, "class='form-control chosen'");?>
<?php echo html::select('browser[]', $lang->bug->browserList, $browser, "class='form-control chosen' multiple");?>
</div>
</div>
<?php endif;?>
+8 -6
View File
@@ -153,10 +153,14 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
<tr>
<th><?php echo $lang->bug->assignedTo;?></th>
<td>
<?php if($bug->status == 'closed'):?>
<?php echo ucfirst($bug->assignedTo);?>
<?php else:?>
<div class='input-group'>
<?php echo html::select('assignedTo', $assignedToList, $bug->assignedTo, "class='form-control chosen'");?>
<span class='input-group-btn'><?php echo html::commonButton($lang->bug->allUsers, "class='btn btn-default' onclick='loadAllUsers()' data-toggle='tooltip'");?></span>
</div>
<?php endif;?>
</td>
</tr>
<tr>
@@ -173,11 +177,11 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
</tr>
<tr>
<th><?php echo $lang->bug->os;?></th>
<td><?php echo html::select('os', $lang->bug->osList, $bug->os, "class='form-control chosen'");?></td>
<td><?php echo html::select('os[]', $lang->bug->osList, $bug->os, "class='form-control chosen' multiple");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->browser;?></th>
<td><?php echo html::select('browser', $lang->bug->browserList, $bug->browser, "class='form-control chosen'");?></td>
<td><?php echo html::select('browser[]', $lang->bug->browserList, $bug->browser, "class='form-control chosen' multiple");?></td>
</tr>
<tr>
<th><?php echo $lang->bug->keywords;?></th>
@@ -282,7 +286,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
<th class='thWidth'><?php echo $lang->bug->linkBug;?></th>
<td><?php if(common::hasPriv('bug', 'linkBugs')) echo html::a($this->createLink('bug', 'linkBugs', "bugID=$bug->id", '', true), $lang->bug->linkBugs, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='95%'");?></td>
</tr>
<tr>
<tr <?php if(!isset($bug->linkBugTitles)) echo 'class="hidden"';?>>
<th></th>
<td>
<ul class='list-unstyled'>
@@ -306,12 +310,10 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project);
<th><?php echo $lang->bug->testtask;?></th>
<td id='testtaskBox'><?php echo html::select('testtask', $testtasks, $bug->testtask, 'class="form-control chosen"');?></td>
</tr>
<?php if($bug->case):?>
<tr>
<th><?php echo $lang->bug->fromCase;?></th>
<td><?php echo html::input('case', $bug->case, 'class="form-control"');?></td>
<td><?php echo html::select('case', $cases, $bug->case, 'class="form-control picker-select"');?></td>
</tr>
<?php endif;?>
</tbody>
</table>
</div>
+1 -1
View File
@@ -90,7 +90,7 @@ $(function()
output += checkbox;
});
$.closeModal();
parent.$('#linkBugsBox').html(output);
parent.$('#linkBugsBox').html(output).closest('tr').removeClass('hidden');
return false;
});
});
+20 -2
View File
@@ -232,11 +232,29 @@
</tr>
<tr>
<th><?php echo $lang->bug->os;?></th>
<td><?php echo $lang->bug->osList[$bug->os];?></td>
<td>
<?php $osList = explode(',', $bug->os);?>
<?php if($osList):?>
<p class='osContent'>
<?php foreach($osList as $os):?>
<?php if($os) echo "<span class='label label-outline'>" . zget($lang->bug->osList, $os) . "</span>";?>
<?php endforeach;?>
</p>
<?php endif;?>
</td>
</tr>
<tr>
<th><?php echo $lang->bug->browser;?></th>
<td><?php echo $lang->bug->browserList[$bug->browser];?></td>
<td>
<?php $browserList = explode(',', $bug->browser);?>
<?php if($browserList):?>
<p class='browserContent'>
<?php foreach($browserList as $browser):?>
<?php if($os) echo "<span class='label label-outline'>" . zget($lang->bug->browserList, $browser) . "</span>";?>
<?php endforeach;?>
</p>
<?php endif;?>
</td>
</tr>
<tr>
<th><?php echo $lang->bug->keywords;?></th>
+22
View File
@@ -795,4 +795,26 @@ class caselib extends control
$this->view->dataInsert = $insert;
$this->display();
}
/**
* For lib sort
*
* @access public
* @return void
*/
public function libSort()
{
$idList = explode(',', trim($this->post->caselib, ','));
$order = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('id')->in($idList)->andWhere('type')->eq('library')->orderBy('order_asc')->fetch('order');
$idList = array_reverse($idList);
/* Init Order. */
if(empty($order)) $order = 1;
foreach($idList as $caselibID)
{
$this->dao->update(TABLE_TESTSUITE)->set('`order`')->eq($order)->where('id')->eq($caselibID)->andWhere('type')->eq('library')->exec();
$order++;
}
}
}
+2 -2
View File
@@ -145,7 +145,7 @@ class caselibModel extends model
->where('product')->eq(0)
->andWhere('deleted')->eq(0)
->andWhere('type')->eq('library')
->orderBy('id_desc')
->orderBy('order_desc, id_desc')
->fetchPairs('id', 'name');
}
@@ -647,7 +647,7 @@ class caselibModel extends model
$menu = '';
$params = "caseID=$case->id";
if($this->config->testcase->needReview || !empty($this->config->testcase->forceReview))
if($case->status == 'wait' and ($this->config->testcase->needReview or !empty($this->config->testcase->forceReview)))
{
$menu .= $this->buildMenu('testcase', 'review', $params, $case, 'browse', 'glasses', '', 'iframe');
}
+6 -3
View File
@@ -29,9 +29,11 @@ class ciModel extends model
if($this->session->repoID)
{
$repo = $this->loadModel('repo')->getRepoByID($this->session->repoID);
if(!in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr);
if(!empty($repo) and !in_array(strtolower($repo->SCM), $this->config->repo->gitServiceList)) unset($this->lang->devops->menu->mr);
$this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID);
$tab = $this->app->tab;
$repos = $this->repo->getRepoPairs($tab);
if(count($repos) > 1) $this->lang->switcherMenu = $this->loadModel('repo')->getSwitcher($this->session->repoID);
}
}
@@ -180,11 +182,12 @@ class ciModel extends model
$data = new stdclass;
$data->status = $pipeline->status;
$data->updateDate = $now;
$data->logs = '';
foreach($jobs as $job)
{
if(empty($job->duration) or $job->duration == '') $job->duration = '-';
$data->logs = "<font style='font-weight:bold'>&gt;&gt;&gt; Job: $job->name, Stage: $job->stage, Status: $job->status, Duration: $job->duration Sec\r\n </font>";
$data->logs .= "<font style='font-weight:bold'>&gt;&gt;&gt; Job: $job->name, Stage: $job->stage, Status: $job->status, Duration: $job->duration Sec\r\n </font>";
$data->logs .= "Job URL: <a href=\"$job->web_url\" target='_blank'>$job->web_url</a> \r\n";
$data->logs .= $this->transformAnsiToHtml($this->gitlab->apiGetJobLog($compile->server, $compile->project, $job->id));
}
+1
View File
@@ -44,6 +44,7 @@ $lang->repo = new stdclass();
$lang->jenkins = new stdclass();
$lang->gitlab = new stdclass();
$lang->gitea = new stdclass();
$lang->gogs = new stdclass();
$lang->mr = new stdclass();
$lang->compile = new stdclass();
$lang->job = new stdclass();
+5 -3
View File
@@ -163,7 +163,7 @@ $lang->product->menu->release = array('link' => "{$lang->release->common}|relea
$lang->product->menu->roadmap = array('link' => "{$lang->roadmap}|product|roadmap|productID=%s");
if($config->systemMode == 'new') $lang->product->menu->project = array('link' => "{$lang->project->common}|product|project|status=all&productID=%s");
if($config->systemMode == 'classic') $lang->product->menu->project = array('link' => "{$lang->execution->common}|product|project|status=all&productID=%s");
$lang->product->menu->track = array('link' => "{$lang->track}|story|track|productID=%s");
$lang->product->menu->track = array('link' => "{$lang->track}|product|track|productID=%s");
$lang->product->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=product&objectID=%s", 'subModule' => 'doc');
$lang->product->menu->dynamic = array('link' => "{$lang->dynamic}|product|dynamic|productID=%s");
$lang->product->menu->settings = array('link' => "{$lang->settings}|product|view|productID=%s", 'subModule' => 'tree,branch', 'alias' => 'edit,whitelist,addwhitelist');
@@ -411,7 +411,7 @@ $lang->devops->menu->code = array('link' => "{$lang->repo->common}|repo|brows
$lang->devops->menu->mr = array('link' => "{$lang->devops->mr}|mr|browse|repoID=%s");
$lang->devops->menu->compile = array('link' => "{$lang->devops->compile}|job|browse|repoID=%s", 'subModule' => 'compile,job');
$lang->devops->menu->app = array('link' => "{$lang->app->common}|app|serverlink|%s");
$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea', 'alias' => 'setrules,create,edit');
$lang->devops->menu->set = array('link' => "{$lang->devops->set}|repo|maintain", 'subModule' => 'gitlab,jenkins,sonarqube,gitea,gogs', 'alias' => 'setrules,create,edit');
$lang->devops->menuOrder[5] = 'code';
$lang->devops->menuOrder[10] = 'mr';
@@ -424,6 +424,7 @@ $lang->devops->dividerMenu = ',set,';
$lang->devops->menu->set['subMenu'] = new stdclass();
$lang->devops->menu->set['subMenu']->repo = array('link' => "{$lang->devops->repo}|repo|maintain", 'alias' => 'create,edit');
$lang->devops->menu->set['subMenu']->gitlab = array('link' => 'GitLab|gitlab|browse', 'subModule' => 'gitlab');
$lang->devops->menu->set['subMenu']->gogs = array('link' => 'Gogs|gogs|browse', 'subModule' => 'gogs');
$lang->devops->menu->set['subMenu']->gitea = array('link' => 'Gitea|gitea|browse', 'subModule' => 'gitea');
$lang->devops->menu->set['subMenu']->jenkins = array('link' => 'Jenkins|jenkins|browse', 'subModule' => '');
$lang->devops->menu->set['subMenu']->sonarqube = array('link' => 'SonarQube|sonarqube|browse', 'subModule' => 'sonarqube');
@@ -513,7 +514,7 @@ if($config->edition == 'max') $lang->admin->menu->model['dropMenu']->scrum = arr
if($config->systemMode == 'new')
{
$lang->admin->menu->model['dropMenu']->waterfall = array('link' => "{$lang->waterfallModel}|stage|setType|", 'subModule' => 'stage,auditcl,cmcl,process,activity,zoutput,classify,reviewcl,reviewsetting');
$lang->admin->menu->model['dropMenu']->waterfall = array('link' => "{$lang->waterfallModel}|stage|setType|", 'subModule' => 'stage,auditcl,cmcl,process,activity,zoutput,classify,reviewcl,reviewsetting,design');
}
$lang->admin->menu->allModel['subMenu'] = new stdclass();
@@ -662,6 +663,7 @@ $lang->navGroup->job = 'devops';
$lang->navGroup->jenkins = 'devops';
$lang->navGroup->mr = 'devops';
$lang->navGroup->gitlab = 'devops';
$lang->navGroup->gogs = 'devops';
$lang->navGroup->gitea = 'devops';
$lang->navGroup->sonarqube = 'devops';
$lang->navGroup->sonarqubeproject = 'devops';
+1 -1
View File
@@ -203,7 +203,7 @@ $lang->product->viewMenu->plan = array('link' => "Plan|productplan|browse
$lang->product->viewMenu->release = array('link' => "Release|release|browse|productID=%s", 'subModule' => 'release');
$lang->product->viewMenu->roadmap = 'Roadmap|product|roadmap|productID=%s';
$lang->product->viewMenu->project = "Project|product|project|status=all&productID=%s";
$lang->product->viewMenu->track = array('link' => "Track|story|track|productID=%s");
$lang->product->viewMenu->track = array('link' => "Track|product|track|productID=%s");
$lang->product->viewMenu->doc = array('link' => 'Doc|doc|objectLibs|type=product&objectID=%s&from=product', 'subModule' => 'doc');
$lang->product->viewMenu->dynamic = 'Dynamic|product|dynamic|productID=%s';
$lang->product->viewMenu->set = array('link' => 'Setting|product|view|productID=%s', 'subModule' => 'tree,branch', 'alias' => 'edit');
+33 -2
View File
@@ -66,7 +66,7 @@ class commonModel extends model
if($rawModule == 'execution')
{
$executionID = $objectID;
$execution = $this->dao->select('id, project, grade, parent')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch();
$execution = $this->dao->select('id, project, grade, parent, status, deleted')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch();
$this->syncExecutionByChild($execution);
$project = $this->syncProjectStatus($execution);
$this->syncProgramStatus($project);
@@ -153,7 +153,7 @@ class commonModel extends model
$today = helper::today();
$parentExecution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($parentExecutionID)->fetch();
if($parentExecution->status == 'wait')
if($execution->deleted == '0' and $execution->status == 'doing' and in_array($parentExecution->status, array('wait', 'closed')))
{
$this->dao->update(TABLE_EXECUTION)
->set('status')->eq('doing')
@@ -163,6 +163,32 @@ class commonModel extends model
$this->loadModel('action')->create('execution', $parentExecutionID, 'syncexecutionbychild');
}
if($parentExecution->type == 'stage')
{
$childExecutions = $this->dao->select('*')->from(TABLE_EXECUTION)->where('parent')->eq($parentExecutionID)->andWhere('deleted')->eq('0')->fetchAll('id');
if($execution->deleted == '1' and count($childExecutions) > 0)
{
$childWait = true;
$childClosed = true;
foreach($childExecutions as $childExecution)
{
if($childExecution->status != 'wait') $childWait = false;
if($childExecution->status != 'closed') $childClosed = false;
}
if($childWait and $parentExecution->status != 'wait')
{
$this->dao->update(TABLE_EXECUTION)->set('status')->eq('wait')->where('id')->eq($parentExecutionID)->exec();
$this->loadModel('action')->create('execution', $parentExecutionID, 'waitbychilddelete');
}
if($childClosed and $parentExecution->status != 'closed')
{
$this->dao->update(TABLE_EXECUTION)->set('status')->eq('closed')->where('id')->eq($parentExecutionID)->exec();
$this->loadModel('action')->create('execution', $parentExecutionID, 'closebychilddelete');
}
}
}
return $parentExecution;
}
@@ -185,6 +211,11 @@ class commonModel extends model
{
$this->dao->update(TABLE_EXECUTION)->set('status')->eq('doing')->set('realBegan')->eq($today)->where('id')->eq($execution->id)->exec();
$this->loadModel('action')->create('execution', $execution->id, 'syncexecution');
if($execution->parent)
{
$execution = $this->dao->select('*')->from(TABLE_EXECUTION)->where('id')->eq($execution->id)->fetch(); // Get updated execution.
$this->syncExecutionByChild($execution);
}
}
return $execution;
}
-2
View File
@@ -27,7 +27,5 @@ function submitForm(type)
$('.modal-body #insert').val(type == 'insert' ? 1 : 0);
$('#importNoticeModal .form-actions .btn').addClass('disabled');
$("button[data-target='#importNoticeModal']").closest('form').submit();
setTimeout(function(){$('#importNoticeModal .form-actions .btn').removeClass('disabled');}, 1000);
}
</script>
+25 -1
View File
@@ -47,6 +47,8 @@ class compile extends control
$this->view->job = $job;
}
$this->compile->syncCompile($repoID, $jobID);
$this->app->loadLang('job');
$this->loadModel('ci')->setMenu($repoID);
@@ -77,7 +79,11 @@ class compile extends control
$build = $this->compile->getByID($buildID);
$job = $this->loadModel('job')->getByID($build->job);
$this->view->logs = str_replace("\r\n","<br />", $build->logs);
if(empty($build->logs) and !in_array($build->status, array('created', 'pending'))) $build->logs = $this->compile->getLogs($job, $build);
$logs = str_replace("\r\n", "<br />", $build->logs);
$logs = str_replace("\n", "<br />", $logs);
$this->view->logs = $logs;
$this->view->build = $build;
$this->view->job = $job;
@@ -87,5 +93,23 @@ class compile extends control
$this->view->position[] = $this->lang->compile->logs;
$this->display();
}
/**
* Sync compiles.
*
* @access public
* @return bool
*/
public function syncCompile()
{
$this->compile->syncCompile();
if(dao::isError())
{
echo json_encode(dao::getError());
return true;
}
echo 'success';
}
}
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Logs';
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Logs';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Name';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Log';
$lang->compile->common = 'Compile';
$lang->compile->browse = 'History';
$lang->compile->logs = 'Log';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Name';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Build';
$lang->compile->browse = 'Historique Builds';
$lang->compile->logs = 'Logs des Builds';
$lang->compile->common = 'Build';
$lang->compile->browse = 'Historique Builds';
$lang->compile->logs = 'Logs des Builds';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Nom';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = 'Compile';
$lang->compile->browse = 'Lịch sử';
$lang->compile->logs = 'Nhật ký';
$lang->compile->common = 'Compile';
$lang->compile->browse = 'Lịch sử';
$lang->compile->logs = 'Nhật ký';
$lang->compile->syncCompile = 'Interface: Sync Compiles.';
$lang->compile->id = 'ID';
$lang->compile->name = 'Tên';
+4 -3
View File
@@ -1,7 +1,8 @@
<?php
$lang->compile->common = '构建';
$lang->compile->browse = '构建历史';
$lang->compile->logs = '构建日志';
$lang->compile->common = '构建';
$lang->compile->browse = '构建历史';
$lang->compile->logs = '构建日志';
$lang->compile->syncCompile = '接口:同步构建记录';
$lang->compile->id = 'ID';
$lang->compile->name = '构建名称';
+184
View File
@@ -134,6 +134,59 @@ class compileModel extends model
return $url;
}
/**
* Get compile logs.
*
* @param object $job
* @param object $compile
* @access public
* @return string
*/
public function getLogs($job, $compile)
{
$logs = '';
if($job->engine == 'jenkins')
{
$jenkins = $this->loadModel('jenkins')->getByID($job->server);
$jenkinsUser = $jenkins->account;
$jenkinsPassword = $jenkins->token ? $jenkins->token : base64_decode($jenkins->password);
$userPWD = "$jenkinsUser:$jenkinsPassword";
$infoUrl = sprintf('%s/job/%s/api/xml?tree=builds[id,number,queueId]&xpath=//build[queueId=%s]', $jenkins->url, $job->pipeline, $compile->queue);
$response = common::http($infoUrl, '', array(CURLOPT_USERPWD => $userPWD));
if($response)
{
$buildInfo = simplexml_load_string($response);
$buildNumber = $buildInfo->number;
if(empty($buildNumber)) return '';
$logUrl = sprintf('%s/job/%s/%s/consoleText', $jenkins->url, $job->pipeline, $buildNumber);
$logs = common::http($logUrl, '', array(CURLOPT_USERPWD => $userPWD));
$this->dao->update(TABLE_COMPILE)->set('logs')->eq($logs)->where('id')->eq($compile->id)->exec();
}
}
else
{
/* Get jobs by pipeline. */
$pipeline = json_decode($job->pipeline);
$projectID = isset($pipeline->project) ? $pipeline->project : '';
$jobs = $this->loadModel('gitlab')->apiGetJobs($job->server, $projectID, $compile->queue);
$this->loadModel('ci');
foreach($jobs as $gitlabJob)
{
if(empty($gitlabJob->duration) or $gitlabJob->duration == '') $gitlabJob->duration = '-';
$logs .= "<font style='font-weight:bold'>&gt;&gt;&gt; Job: $gitlabJob->name, Stage: $gitlabJob->stage, Status: $gitlabJob->status, Duration: $gitlabJob->duration Sec\r\n </font>";
$logs .= "Job URL: <a href=\"$gitlabJob->web_url\" target='_blank'>$gitlabJob->web_url</a> \r\n";
$logs .= $this->ci->transformAnsiToHtml($this->gitlab->apiGetJobLog($job->server, $projectID, $gitlabJob->id));
}
}
if(!empty($logs)) $this->dao->update(TABLE_COMPILE)->set('logs')->eq($logs)->where('id')->eq($compile->id)->exec();
return $logs;
}
/**
* Save build by job
*
@@ -157,6 +210,137 @@ class compileModel extends model
$this->dao->insert(TABLE_COMPILE)->data($build)->exec();
}
/**
* Sync compiles.
*
* @param int $repoID
* @param int $repoID
* @access public
* @return void
*/
public function syncCompile($repoID = 0, $jobID = 0)
{
if($jobID)
{
$jobList[$jobID] = $this->loadModel('job')->getByID($jobID);
}
else
{
$jobList = $this->loadModel('job')->getList($repoID);
}
$jenkinsPairs = $this->loadModel('pipeline')->getList('jenkins');
$gitlabPairs = $this->loadModel('pipeline')->getList('gitlab');
foreach($jobList as $job)
{
if($job->engine == 'jenkins')
{
$server = zget($jenkinsPairs, $job->server);
$this->syncJenkinsBuildList($server, $job);
}
else
{
$server = zget($gitlabPairs, $job->server);
$this->syncGitLabBuildList($server, $job);
}
}
}
/**
* Sync jenkins build list.
*
* @param object $jenkins
* @param object $job
* @access public
* @return void
*/
public function syncJenkinsBuildList($jenkins, $job)
{
$jenkinsUser = $jenkins->account;
$jenkinsPassword = $jenkins->token ? $jenkins->token : base64_decode($jenkins->password);
/* Get build list by API. */
$url = sprintf('%s/job/%s/api/json?tree=builds[id,number,result,queueId,timestamp]', $jenkins->url, $job->pipeline);
$response = common::http($url, '', array(CURLOPT_USERPWD => "$jenkinsUser:$jenkinsPassword"));
if(!$response) return false;
$compilePairs = $this->dao->select('queue,job')->from(TABLE_COMPILE)->where('job')->eq($job->id)->andWhere('queue')->gt(0)->fetchPairs();
$jobInfo = json_decode($response);
foreach($jobInfo->builds as $build)
{
$lastSyncTime = strtotime($job->lastSyncDate);
if($build->timestamp < $lastSyncTime * 1000) break;
if(isset($compilePairs[$build->queueId])) continue;
$data = new stdclass();
$data->name = $job->name;
$data->job = $job->id;
$data->queue = $build->queueId;
$data->status = $build->result == 'SUCCESS' ? 'success' : 'failure';
$data->createdBy = 'guest';
$data->createdDate = date('Y-m-d H:i:s', $build->timestamp / 1000);
$data->updateDate = $data->createdDate;
$this->dao->insert(TABLE_COMPILE)->data($data)->exec();
}
$now = helper::now();
$this->dao->update(TABLE_JOB)->set('lastSyncDate')->eq($now)->where('id')->eq($job->id)->exec();
}
/**
* Sync gitlab build list.
*
* @param object $gitlab
* @param object $job
* @access public
* @return void
*/
public function syncGitlabBuildList($gitlab, $job)
{
$pipeline = json_decode($job->pipeline);
$projectID = isset($pipeline->project) ? $pipeline->project : '';
$ref = isset($pipeline->reference) ? $pipeline->reference : '';
$url = sprintf($this->loadModel('gitlab')->getApiRoot($gitlab->id, false), "/projects/{$projectID}/pipelines");
/* Get build list by API. */
for($page = 1; true; $page++)
{
$param = $job->lastSyncDate ? '&updated_after=' . date('YYYY-MM-DDThh:mm:ssZ', strtotime($job->lastSyncDate)) : '';
$builds = json_decode(commonModel::http($url . "&ref={$ref}&order_by=id&sort=asc&page={$page}&per_page=100" . $param));
if(!is_array($builds)) break;
if(!empty($builds))
{
$queueIDList = array();
foreach($builds as $build) $queueIDList[] = $build->id;
$compilePairs = $this->dao->select('queue,job')->from(TABLE_COMPILE)->where('job')->eq($job->id)->andWhere('queue')->in($queueIDList)->fetchPairs();
foreach($builds as $build)
{
if(isset($compilePairs[$build->id])) continue;
$data = new stdclass();
$data->name = $job->name;
$data->job = $job->id;
$data->queue = $build->id;
$data->status = $build->status;
$data->createdBy = 'guest';
$data->createdDate = date('Y-m-d H:i:s', strtotime($build->created_at));
$data->updateDate = date('Y-m-d H:i:s', strtotime($build->updated_at));
$this->dao->insert(TABLE_COMPILE)->data($data)->exec();
}
}
if(count($builds) < 100) break;
}
$now = helper::now();
$this->dao->update(TABLE_JOB)->set('lastSyncDate')->eq($now)->where('id')->eq($job->id)->exec();
}
/**
* Execute compile
*
+10 -1
View File
@@ -403,7 +403,16 @@ class designModel extends model
*/
public function setMenu($projectID, $products, $productID = 0)
{
if($this->app->rawMethod != 'browse') unset($this->lang->waterfall->menu->design['subMenu']->bysearch);
/* Show custom design types. */
$this->lang->waterfall->menu->design['subMenu'] = new stdclass();
$this->lang->waterfall->menu->design['subMenu']->all = array('link' => "{$this->lang->all}|design|browse|projectID=%s&productID=0&browseType=all");
foreach(array_filter($this->lang->design->typeList) as $key => $value)
{
$this->lang->waterfall->menu->design['subMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}");
}
if($this->app->rawMethod == 'browse') $this->lang->waterfall->menu->design['subMenu']->bysearch = array('link' => '<a href="javascript:;" class="querybox-toggle"><i class="icon-search icon"></i> ' . $this->lang->searchAB . '</a>');
if(empty($products) || !$productID) return '';
$currentProduct = $this->loadModel('product')->getById($productID);
setCookie("lastProduct", $productID, $this->config->cookieLife, $this->config->webRoot, '', false, true);
+1 -1
View File
@@ -1126,7 +1126,7 @@ class doc extends control
foreach(explode(',', $this->config->doc->customObjectLibs) as $libType) $customObjectLibs[$libType] = $this->lang->doc->customObjectLibs[$libType];
$actionURL = $this->createLink('doc', 'browse', "lib=0&browseType=bySearch&queryID=myQueryID");
$this->doc->buildSearchForm(0, array(), 0, $actionURL, 'objectLibs');
$this->doc->buildSearchForm(0, array(), 0, $actionURL, $type);
$moduleTree = $type == 'book' ? $this->doc->getBookStructure($libID) : $this->doc->getTreeMenu($type, $objectID, $libID, 0, $docID);
+6 -5
View File
@@ -1,10 +1,11 @@
<?php
$config->execution = new stdclass();
$config->execution->defaultWorkhours = '7.0';
$config->execution->orderBy = 'isDone,status,order_desc';
$config->execution->maxBurnDay = '31';
$config->execution->weekend = '2';
$config->execution->ownerFields = array('PO', 'PM', 'QD', 'RD');
$config->execution->defaultWorkhours = '7.0';
$config->execution->orderBy = 'isDone,status,order_desc';
$config->execution->maxBurnDay = '31';
$config->execution->weekend = '2';
$config->execution->ownerFields = array('PO', 'PM', 'QD', 'RD');
$config->execution->defaultBurnPeriod = 30;
$config->execution->list = new stdclass();
$config->execution->list->exportFields = 'id,name,projectName,code,PM,begin,end,status,totalEstimate,totalConsumed,totalLeft,progress';
+20 -21
View File
@@ -469,10 +469,13 @@ class execution extends control
*
* @param int $executionID
* @param int $fromExecution
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function importTask($toExecution, $fromExecution = 0)
public function importTask($toExecution, $fromExecution = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
if(!empty($_POST))
{
@@ -509,13 +512,20 @@ class execution extends control
$tasks2Imported = zget($tasks, $fromExecution, array());
}
/* Pager. */
$this->app->loadClass('pager', $static = true);
$recTotal = count($tasks2Imported);
$pager = new pager($recTotal, $recPerPage, $pageID);
$tasks2ImportedList = array_chunk($tasks2Imported, $pager->recPerPage, true);
/* Save session. */
$this->app->session->set('taskList', $this->app->getURI(true), 'execution');
$this->view->title = $execution->name . $this->lang->colon . $this->lang->execution->importTask;
$this->view->pager = $pager;
$this->view->position[] = html::a(inlink('browse', "executionID=$toExecution"), $execution->name);
$this->view->position[] = $this->lang->execution->importTask;
$this->view->tasks2Imported = $tasks2Imported;
$this->view->tasks2Imported = empty($tasks2ImportedList) ? $tasks2ImportedList : $tasks2ImportedList[$pageID - 1];
$this->view->executions = $executions;
$this->view->executionID = $execution->id;
$this->view->fromExecution = $fromExecution;
@@ -632,7 +642,7 @@ class execution extends control
$this->config->bug->search['params']['product']['values'] = array(''=>'');
}
$this->config->bug->search['params']['execution']['values'] = array(''=>'') + $executions + array('all'=>$this->lang->execution->aboveAllExecution);
$this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs(array_keys($products));
$this->config->bug->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs(array_keys($products));
$this->config->bug->search['module'] = 'importBug';
$this->config->bug->search['params']['confirmed']['values'] = array('' => '') + $this->lang->bug->confirmedList;
@@ -2179,15 +2189,9 @@ class execution extends control
if(!empty($_POST))
{
$this->loadModel('action');
$changes = $this->execution->activate($executionID);
$this->execution->activate($executionID);
if(dao::isError()) return print(js::error(dao::getError()));
if($this->post->comment != '' or !empty($changes))
{
$actionID = $this->action->create($this->objectType, $executionID, 'Activated', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($executionID);
if(isonlybody() and $from == 'kanban')
{
@@ -2230,16 +2234,10 @@ class execution extends control
if(!empty($_POST))
{
$this->loadModel('action');
$this->execution->computeBurn($executionID);
$changes = $this->execution->close($executionID);
$this->execution->close($executionID);
if(dao::isError()) return print(js::error(dao::getError()));
if($this->post->comment != '' or !empty($changes))
{
$actionID = $this->action->create($this->objectType, $executionID, 'Closed', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($executionID);
if(isonlybody() and $from == 'kanban')
{
@@ -2552,7 +2550,7 @@ class execution extends control
{
$this->loadModel('project');
$projects = $this->project->getPairsByProgram('', 'noclosed');
$executions = $this->project->getStats(0, 'all', 0, 0, 30, 'id_desc');
$executions = $this->execution->getStatData(0, 'all', 0, 0, false, '', 'id_desc');
$teams = $this->dao->select('root,account')->from(TABLE_TEAM)
->where('root')->in($this->app->user->view->sprints)
@@ -2890,6 +2888,7 @@ class execution extends control
$this->dao->update(TABLE_EXECUTION)->set('deleted')->eq(1)->where('id')->eq($executionID)->exec();
$this->loadModel('action')->create('execution', $executionID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
$this->execution->updateUserView($executionID);
$this->loadModel('common')->syncPPEStatus($executionID);
$this->session->set('execution', '');
$message = $this->executeHooks($executionID);
@@ -3731,7 +3730,7 @@ class execution extends control
$this->view->title = $this->lang->execution->allExecutions;
$this->view->position[] = $this->lang->execution->allExecutions;
$executionStats = $this->project->getStats(0, $status, $productID, 0, 30, $orderBy, $pager, false, $queryID);
$executionStats = $this->execution->getStatData(0, $status, $productID, 0, false, $queryID, $orderBy, $pager);
$parentIdList = array();
foreach($executionStats as $execution)
@@ -3742,7 +3741,7 @@ class execution extends control
$parents = array();
if($parentIdList) $parents = $this->execution->getByIdList($parentIdList);
$allExecutionsNum = $this->project->getStats(0, 'all');
$allExecutionsNum = $this->execution->getStatData(0, 'all');
$this->view->allExecutionsNum = count($allExecutionsNum);
$this->view->executionStats = $executionStats;
@@ -3853,7 +3852,7 @@ class execution extends control
}
$project = $this->project->getByID($projectID);
$executionStats = $this->project->getStats($projectID, $status == 'byproduct' ? 'all' : $status, $productID, 0, 30, 'id_asc');
$executionStats = $this->execution->getStatData($projectID, $status == 'byproduct' ? 'all' : $status, $productID, 0, false, '', 'id_asc');
if(isset($project->model) and $project->model == 'waterfall')
{
$stageList = array();
+2 -1
View File
@@ -1,3 +1,4 @@
#fromproject_chosen .chosen-single {width: 220px;}
.c-name {width: 200px;}
.c-name {min-width: 200px;}
.c-hour {width: 80px;}
#importTaskForm {min-height: 350px;}
+23
View File
@@ -2,4 +2,27 @@ $(function()
{
if(browseType != 'bysearch') $('#module' + param).closest('li').addClass('active');
if($('#bugList thead th.c-title').width() < 150) $('#bugList thead th.c-title').width(150);
$('#bugList').on('change', "[name='bugIDList[]']", checkClosed);
});
/**
* Closed bugs are not assignable.
*
* @access public
* @return void
*/
function checkClosed()
{
var disabledAssigned = $('#bugList tr.checked .c-assignedTo a').length > 0 ? true : false;
$('#bugList tr.checked .c-assignedTo a').each(function()
{
if(!$(this).hasClass('disabled'))
{
disabledAssigned = false;
return false;
}
});
$('#mulAssigned').prop('disabled', disabledAssigned);
}
+13 -4
View File
@@ -536,10 +536,19 @@ $lang->execution->treeLevel['task'] = 'Aufgabe anzeigen';
$lang->execution->treeLevel['story'] = 'Story anzeigen';
$lang->execution->action = new stdclass();
$lang->execution->action->opened = '$date, created by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->managed = '$date, managed by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->edited = '$date, edited by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->extra = 'Linked products is %s.';
$lang->execution->action->opened = '$date, created by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->managed = '$date, managed by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->edited = '$date, edited by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->extra = 'Linked products is %s.';
$lang->execution->action->startbychildactivate = '$date, activating the sub stage sets the execution status as Ongoing.' . "\n";
$lang->execution->action->waitbychilddelete = '$date, deleting the sub stage sets the execution status as waitting.' . "\n";
$lang->execution->action->closebychilddelete = '$date, deleting the sub stage sets the execution status as closing.' . "\n";
$lang->execution->action->closebychildclose = '$date, closing the sub stage sets the execution status as closing.' . "\n";
$lang->execution->startbychildactivate = 'activated';
$lang->execution->waitbychilddelete = 'stop';
$lang->execution->closebychilddelete = 'closed';
$lang->execution->closebychildclose = 'closed';
$lang->execution->statusColorList = array();
$lang->execution->statusColorList['wait'] = '#0991FF';
+13 -4
View File
@@ -536,10 +536,19 @@ $lang->execution->treeLevel['task'] = 'Stories&Tasks';
$lang->execution->treeLevel['story'] = 'Only Stories';
$lang->execution->action = new stdclass();
$lang->execution->action->opened = '$date, created by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->managed = '$date, managed by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->edited = '$date, edited by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->extra = 'Linked products is %s.';
$lang->execution->action->opened = '$date, created by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->managed = '$date, managed by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->edited = '$date, edited by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->extra = 'Linked products is %s.';
$lang->execution->action->startbychildactivate = '$date, activating the sub stage sets the execution status as Ongoing.' . "\n";
$lang->execution->action->waitbychilddelete = '$date, deleting the sub stage sets the execution status as waitting.' . "\n";
$lang->execution->action->closebychilddelete = '$date, deleting the sub stage sets the execution status as closing.' . "\n";
$lang->execution->action->closebychildclose = '$date, closing the sub stage sets the execution status as closing.' . "\n";
$lang->execution->startbychildactivate = 'activated';
$lang->execution->waitbychilddelete = 'stop';
$lang->execution->closebychilddelete = 'closed';
$lang->execution->closebychildclose = 'closed';
$lang->execution->statusColorList = array();
$lang->execution->statusColorList['wait'] = '#0991FF';
+13 -4
View File
@@ -536,10 +536,19 @@ $lang->execution->treeLevel['task'] = 'Stories&Tâches';
$lang->execution->treeLevel['story'] = 'Seulement Stories';
$lang->execution->action = new stdclass();
$lang->execution->action->opened = '$date, created by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->managed = '$date, managed by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->edited = '$date, edited by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->extra = 'Linked products is %s.';
$lang->execution->action->opened = '$date, created by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->managed = '$date, managed by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->edited = '$date, edited by <strong>$actor</strong>. $extra' . "\n";
$lang->execution->action->extra = 'Linked products is %s.';
$lang->execution->action->startbychildactivate = '$date, activating the sub stage sets the execution status as Ongoing.' . "\n";
$lang->execution->action->waitbychilddelete = '$date, deleting the sub stage sets the execution status as waitting.' . "\n";
$lang->execution->action->closebychilddelete = '$date, deleting the sub stage sets the execution status as closing.' . "\n";
$lang->execution->action->closebychildclose = '$date, closing the sub stage sets the execution status as closing.' . "\n";
$lang->execution->startbychildactivate = 'activated';
$lang->execution->waitbychilddelete = 'stop';
$lang->execution->closebychilddelete = 'closed';
$lang->execution->closebychildclose = 'closed';
$lang->execution->statusColorList = array();
$lang->execution->statusColorList['wait'] = '#0991FF';
+13 -4
View File
@@ -536,10 +536,19 @@ $lang->execution->treeLevel['task'] = '全部显示';
$lang->execution->treeLevel['story'] = "只看{$lang->SRCommon}";
$lang->execution->action = new stdclass();
$lang->execution->action->opened = '$date, 由 <strong>$actor</strong> 创建。$extra' . "\n";
$lang->execution->action->managed = '$date, 由 <strong>$actor</strong> 维护。$extra' . "\n";
$lang->execution->action->edited = '$date, 由 <strong>$actor</strong> 编辑。$extra' . "\n";
$lang->execution->action->extra = '相关产品为 %s。';
$lang->execution->action->opened = '$date, 由 <strong>$actor</strong> 创建。$extra' . "\n";
$lang->execution->action->managed = '$date, 由 <strong>$actor</strong> 维护。$extra' . "\n";
$lang->execution->action->edited = '$date, 由 <strong>$actor</strong> 编辑。$extra' . "\n";
$lang->execution->action->extra = '相关产品为 %s。';
$lang->execution->action->startbychildactivate = '$date, 系统判断由于子阶段激活,将' . $lang->executionCommon . '状态置为进行中。' . "\n";
$lang->execution->action->waitbychilddelete = '$date, 系统判断由于子阶段删除,将' . $lang->executionCommon . '状态置为未开始。' . "\n";
$lang->execution->action->closebychilddelete = '$date, 系统判断由于子阶段删除,将' . $lang->executionCommon . '状态置为已关闭。' . "\n";
$lang->execution->action->closebychildclose = '$date, 系统判断由于子阶段关闭,将' . $lang->executionCommon . '状态置为已关闭。' . "\n";
$lang->execution->startbychildactivate = '激活了';
$lang->execution->waitbychilddelete = '停止了';
$lang->execution->closebychilddelete = '关闭了';
$lang->execution->closebychildclose = '关闭了';
$lang->execution->statusColorList = array();
$lang->execution->statusColorList['wait'] = '#0991FF';
+223 -5
View File
@@ -1005,17 +1005,26 @@ class executionModel extends model
}
}
$changes = common::createChanges($oldExecution, $execution);
if($this->post->comment != '' or !empty($changes))
{
$this->loadModel('action');
$actionID = $this->action->create('execution', $executionID, 'Activated', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
/* Update the status of the parent stage. */
if($oldExecution->type == 'stage')
{
$parent = $this->getByID($oldExecution->parent);
if($parent->type == 'stage' and $parent->status == 'closed')
if($parent->type == 'stage' and in_array($parent->status, array('closed', 'wait')))
{
$this->dao->update(TABLE_EXECUTION)->set('status')->eq('doing')->where('id')->eq($parent->id)->exec();
$this->loadModel('action')->create('execution', $parent->id, 'startbychildactivate');
}
}
if(!dao::isError()) return common::createChanges($oldExecution, $execution);
return $changes;
}
/**
@@ -1058,6 +1067,15 @@ class executionModel extends model
if(!dao::isError())
{
$changes = common::createChanges($oldExecution, $execution);
if($this->post->comment != '' or !empty($changes))
{
$this->loadModel('action');
$actionID = $this->action->create('execution', $executionID, 'Closed', $this->post->comment);
$this->action->logHistory($actionID, $changes);
}
/* Update the status of the parent stage. */
if($oldExecution->type == 'stage')
{
@@ -1071,12 +1089,16 @@ class executionModel extends model
if($childExecution->status != 'closed') $isClosed = false;
}
if($isClosed) $this->dao->update(TABLE_EXECUTION)->set('status')->eq('closed')->where('id')->eq($parent->id)->exec();
if($isClosed)
{
$this->dao->update(TABLE_EXECUTION)->set('status')->eq('closed')->where('id')->eq($parent->id)->exec();
$this->loadModel('action')->create('execution', $parent->id, 'closebychildclose');
}
}
}
$this->loadModel('score')->create('execution', 'close', $oldExecution);
return common::createChanges($oldExecution, $execution);
return $changes;
}
}
@@ -1409,6 +1431,129 @@ class executionModel extends model
->fetchPairs('id', 'id');
}
/**
* Get execution stat data.
* @param int $projectID
* @param string $browseType all|undone|wait|doing|suspended|closed|involved|bySearch|review
* @param int $productID
* @param int $branch
* @param bool $withTasks
* @param string|int $param skipParent
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getStatData($projectID = 0, $browseType = 'undone', $productID = 0, $branch = 0, $withTasks = false, $param = '', $orderBy = 'id_asc', $pager = null)
{
/* Construct the query SQL at search executions. */
$executionQuery = '';
if($browseType == 'bySearch')
{
$queryID = (int)$param;
if($queryID)
{
$query = $this->loadModel('search')->getQuery($queryID);
if($query)
{
$this->session->set('executionQuery', $query->sql);
$this->session->set('executionForm', $query->form);
}
}
if($this->session->executionQuery == false) $this->session->set('executionQuery', ' 1 = 1');
$executionQuery = $this->session->executionQuery;
$allProject = "`project` = 'all'";
if(strpos($executionQuery, $allProject) !== false) $executionQuery = str_replace($allProject, '1', $executionQuery);
$executionQuery = preg_replace('/(`\w*`)/', 't1.$1',$executionQuery);
}
/* Get involved executions. */
$myExecutionIDList = array();
if($browseType == 'involved')
{
$myExecutionIDList = $this->dao->select('root')->from(TABLE_TEAM)
->where('account')->eq($this->app->user->account)
->andWhere('type')->eq('execution')
->fetchPairs();
}
$executions = $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->beginIF($productID)->leftJoin(TABLE_PROJECTPRODUCT)->alias('t3')->on('t1.id=t3.project')->fi()
->where('t1.type')->in('sprint,stage,kanban')
->andWhere('t1.deleted')->eq('0')
->andWhere('t1.vision')->eq($this->config->vision)
->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->sprints)->fi()
->beginIF(!empty($executionQuery))->andWhere($executionQuery)->fi()
->beginIF($productID)->andWhere('t3.product')->eq($productID)->fi()
->beginIF($projectID)->andWhere('t1.project')->eq($projectID)->fi()
->beginIF(!in_array($browseType, array('all', 'undone', 'involved', 'review', 'bySearch')))->andWhere('t1.status')->eq($browseType)->fi()
->beginIF($browseType == 'undone')->andWhere('t1.status')->notIN('done,closed')->fi()
->beginIF($browseType == 'review')
->andWhere("FIND_IN_SET('{$this->app->user->account}', t1.reviewers)")
->andWhere('t1.reviewStatus')->eq('doing')
->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
$hours = $this->loadModel('project')->computerProgress($executions);
$burns = $this->getBurnData($executions);
if($withTasks) $executionTasks = $this->getTaskGroupByExecution(array_keys($executions));
/* Process executions. */
$this->app->loadConfig('task');
$emptyHour = array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0);
$today = helper::today();
foreach($executions as $key => $execution)
{
/* Process the end time. */
$execution->end = date(DT_DATE1, strtotime($execution->end));
/* Judge whether the execution is delayed. */
if($execution->status != 'done' and $execution->status != 'closed' and $execution->status != 'suspended')
{
$delay = helper::diffDate($today, $execution->end);
if($delay > 0) $execution->delay = $delay;
}
/* Process the burns. */
$execution->burns = array();
$burnData = isset($burns[$execution->id]) ? $burns[$execution->id] : array();
foreach($burnData as $data) $execution->burns[] = $data->value;
/* Process the hours. */
$execution->hours = isset($hours[$execution->id]) ? $hours[$execution->id] : (object)$emptyHour;
if(isset($executionTasks) and isset($executionTasks[$execution->id]))
{
$tasks = array_chunk($executionTasks[$execution->id], $this->config->task->defaultLoadCount, true);
$execution->tasks = $tasks[0];
}
/* In the case of the waterfall model, calculate the sub-stage. */
if($param == 'skipParent')
{
if($execution->parent < 0 and $execution->type == 'stage') unset($executions[$key]);
if($this->config->systemMode == 'new' and $execution->projectName) $execution->name = $execution->projectName . ' / ' . $execution->name;
}
else
{
if(isset($executions[$execution->parent]) and $execution->type == 'stage')
{
$executions[$execution->parent]->children[$key] = $execution;
unset($executions[$key]);
}
}
}
return array_values($executions);
}
/**
* Get executions by project.
*
@@ -1800,6 +1945,38 @@ class executionModel extends model
return $tasks;
}
/**
* Get the task data group by execution id list.
*
* @param array $executionIdList
* @access public
* @return array
*/
public function getTaskGroupByExecution($executionIdList = array())
{
if(empty($executionIdList)) return array();
$executionTasks = $this->dao->select('*')->from(TABLE_TASK)
->where('deleted')->eq(0)
->andWhere('status')->notin('closed,cancel')
->andWhere('execution')->in($executionIdList)
->orderBy('id_asc')
->fetchGroup('execution', 'id');
foreach($executionTasks as $executionID => $tasks)
{
foreach($tasks as $task)
{
if($task->parent > 0 and isset($executionTasks[$executionID][$task->parent]))
{
$executionTasks[$executionID][$task->parent]->children[$task->id] = $task;
unset($executionTasks[$executionID][$task->id]);
}
}
}
return $executionTasks;
}
/**
* Get the execution by ID.
*
@@ -2534,7 +2711,7 @@ class executionModel extends model
$this->story->setStage($storyID);
$this->linkCases($executionID, (int)$products[$storyID], $storyID);
$action = $executionID == $this->session->project ? 'linked2project' : 'linked2execution';
$action = $execution->type == 'project' ? 'linked2project' : 'linked2execution';
if($action == 'linked2execution' and $execution->type == 'kanban') $action = 'linked2kanban';
$this->action->create('story', $storyID, $action, '', $executionID);
}
@@ -3236,6 +3413,47 @@ class executionModel extends model
return $burnData;
}
/**
* Get execution burn data.
*
* @param array $executions
* @access public
* @return array
*/
public function getBurnData($executions)
{
if(empty($executions)) return array();
/* Get burndown charts datas. */
$burns = $this->dao->select('execution, date AS name, `left` AS value')
->from(TABLE_BURN)
->where('execution')->in(array_keys($executions))
->andWhere('task')->eq(0)
->orderBy('date desc')
->fetchGroup('execution', 'name');
foreach($burns as $executionID => $executionBurns)
{
/* If executionBurns > $itemCounts, split it, else call processBurnData() to pad burns. */
$begin = $executions[$executionID]->begin;
$end = $executions[$executionID]->end;
if(helper::isZeroDate($begin)) $begin = $executions[$executionID]->openedDate;
$executionBurns = $this->processBurnData($executionBurns, $this->config->execution->defaultBurnPeriod, $begin, $end);
/* Shorter names. */
foreach($executionBurns as $executionBurn)
{
$executionBurn->name = substr($executionBurn->name, 5);
unset($executionBurn->execution);
}
ksort($executionBurns);
$burns[$executionID] = $executionBurns;
}
return $burns;
}
/**
* Process burndown datas when the sets is smaller than the itemCounts.
*
+1 -1
View File
@@ -162,7 +162,7 @@
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<div class="table-actions btn-toolbar">
<div class="btn-group dropup">
<button data-toggle="dropdown" type="button" class="btn"><?php echo $lang->bug->assignedTo?> <span class="caret"></span></button>
<button data-toggle="dropdown" type="button" class="btn" id="mulAssigned"><?php echo $lang->bug->assignedTo?> <span class="caret"></span></button>
<?php
$withSearch = count($memberPairs) > 10;
$actionLink = $this->createLink('bug', 'batchAssignTo', "executionID={$execution->id}&type=execution");
@@ -95,6 +95,7 @@
<?php echo html::backButton('','','btn');?>
<?php endif;?>
</div>
<?php $pager->show('right', 'pagerjs');?>
</div>
<?php endif;?>
</form>
+5 -1
View File
@@ -441,10 +441,14 @@ class extensionModel extends model
else
{
$parentDir = mb_substr($path, 0, strripos($path, '/'));
if(!is_writable($parentDir) or !@mkdir($path, 0777, true))
if(!is_dir($path) and !mkdir($path, 0777, true))
{
$return->errors .= sprintf($this->lang->extension->errorTargetPathNotExists, $path) . '<br />';
$return->mkdirCommands .= "sudo mkdir -p $path<br />";
}
if(!is_writable($parentDir))
{
$return->errors .= sprintf($this->lang->extension->errorTargetPathNotWritable, $path) . '<br />';
$return->chmodCommands .= "sudo chmod -R 777 $path<br />";
}
$return->dirs2Created[] = $path;
+1
View File
@@ -130,6 +130,7 @@ class file extends control
if(!$this->file->checkPriv($file))
{
echo(js::alert($this->lang->file->accessDenied));
if(isonlybody()) return print(js::reload('parent.parent'));
return print(js::locate(helper::createLink('my', 'index')));
}
+1 -1
View File
@@ -565,7 +565,7 @@ class fileModel extends model
}
elseif($objectType == 'feedback')
{
$productID = $this->dao->findById($objectID)->from(TABLE_FEEDBACK)->fetch();
$productID = $this->dao->findById($objectID)->from(TABLE_FEEDBACK)->fetch('product');
$grantProducts = $this->loadModel('feedback')->getGrantProducts();
return in_array($productID, array_keys($grantProducts));
}
+3 -2
View File
@@ -3,6 +3,7 @@
.file-input .file-editbox{max-width:40%;}
.file-input-list .input-group-btn{float:left}
.fileAction {color: #0c64eb !important;}
.backgroundColor {background: #eff5ff; }
</style>
<?php js::set('dangerExtensions', ',' . $this->config->file->dangers . ',');?>
<?php js::set('maxUploadSize', $maxUploadSize);?>
@@ -26,8 +27,8 @@
<small class="file-size muted"></small>
</div>
<div class="input-group-btn">
<button type="button" class="fileAction btn btn-link file-input-rename"><?php echo $lang->file->edit;?></button>
<button type="button" class="fileAction btn btn-link file-input-delete"><?php echo $lang->delete;?></button>
<button type="button" class="fileAction btn btn-link file-input-rename" title="<?php echo $lang->file->edit;?>"><i class='icon icon-pencil-alt'></i></button>
<button type="button" class="fileAction btn btn-link file-input-delete" title="<?php echo $lang->delete;?>"><i class='icon icon-trash'></i></button>
</div>
</div>
<input type="file" name="<?php echo $filesName;?>[]" onchange="checkDangerExtension(this)" />
+132 -115
View File
@@ -5,122 +5,139 @@
<div class="detail-title"><?php echo $lang->file->common;?> <i class="icon icon-paper-clip icon-sm"></i></div>
<div class="detail-content">
<?php endif;?>
<style>
.file {padding-top: 2px;}
.files-list>li>a {display: inline; word-wrap: break-word;}
.files-list>li>.right-icon {opacity: 1;}
.fileAction {color: #0c64eb !important;}
.renameFile {display: flex;}
.renameFile .input-group {margin-left: 10px;}
.renameFile .icon {margin-top: 8px;}
.renameFile .input-group-addon {width: 60px;}
</style>
<script>
/**
* Delete a file.
*
* @param int $fileID
* @access public
* @return void
*/
function deleteFile(fileID)
{
if(!fileID) return;
hiddenwin.location.href = createLink('file', 'delete', 'fileID=' + fileID);
}
<style>
.file {padding-top: 2px;}
.files-list>li>a {display: inline; word-wrap: break-word;}
.files-list>li>.right-icon {opacity: 1;}
.fileAction {color: #0c64eb !important;}
.renameFile {display: flex;}
.renameFile .input-group {margin-left: 10px;}
.renameFile .icon {margin-top: 8px;}
.renameFile .input-group-addon {width: 60px;}
.backgroundColor {background: #eff5ff; }
.icon.icon-file-text {margin-left: 4px;}
</style>
<script>
$(document).ready(function()
{
$('li.file').mouseover(function()
{
$(this).children('span.right-icon').removeClass("hidden");
$(this).addClass('backgroundColor');
});
/**
* Download a file, append the mouse to the link. Thus we call decide to open the file in browser no download it.
*
* @param int $fileID
* @param int $extension
* @param int $imageWidth
* @param string $fileTitle
* @access public
* @return void
*/
function downloadFile(fileID, extension, imageWidth, fileTitle)
{
if(!fileID) return;
var fileTypes = 'txt,jpg,jpeg,gif,png,bmp';
var windowWidth = $(window).width();
var width = (windowWidth > imageWidth) ? ((imageWidth < windowWidth * 0.5) ? windowWidth * 0.5 : imageWidth) : windowWidth;
var checkExtension = fileTitle.lastIndexOf('.' + extension) == (fileTitle.length - extension.length - 1);
$('li.file').mouseout(function()
{
$(this).children('span.right-icon').addClass("hidden");
$(this).removeClass('backgroundColor');
});
});
var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left');
url += url.indexOf('?') >= 0 ? '&' : '?';
url += '<?php echo $sessionString;?>';
/**
* Delete a file.
*
* @param int $fileID
* @access public
* @return void
*/
function deleteFile(fileID)
{
if(!fileID) return;
hiddenwin.location.href = createLink('file', 'delete', 'fileID=' + fileID);
}
if(fileTypes.indexOf(extension) >= 0 && checkExtension && config.onlybody != 'yes')
{
$('<a>').modalTrigger({url: url, type: 'iframe', width: width}).trigger('click');
}
else
{
url = url.replace('?onlybody=yes&', '?');
url = url.replace('?onlybody=yes', '?');
url = url.replace('&onlybody=yes', '');
/**
* Download a file, append the mouse to the link. Thus we call decide to open the file in browser no download it.
*
* @param int $fileID
* @param int $extension
* @param int $imageWidth
* @param string $fileTitle
* @access public
* @return void
*/
function downloadFile(fileID, extension, imageWidth, fileTitle)
{
if(!fileID) return;
var fileTypes = 'txt,jpg,jpeg,gif,png,bmp';
var windowWidth = $(window).width();
var width = (windowWidth > imageWidth) ? ((imageWidth < windowWidth * 0.5) ? windowWidth * 0.5 : imageWidth) : windowWidth;
var checkExtension = fileTitle.lastIndexOf('.' + extension) == (fileTitle.length - extension.length - 1);
window.open(url, '_blank');
}
return false;
}
var url = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left');
url += url.indexOf('?') >= 0 ? '&' : '?';
url += '<?php echo $sessionString;?>';
/* Show edit box for editing file name. */
/**
* Show edit box for editing file name.
*
* @param int $fileID
* @access public
* @return void
*/
function showRenameBox(fileID)
{
$('#renameFile' + fileID).closest('li').addClass('hidden');
$('#renameBox' + fileID).removeClass('hidden');
}
if(fileTypes.indexOf(extension) >= 0 && checkExtension && config.onlybody != 'yes')
{
$('<a>').modalTrigger({url: url, type: 'iframe', width: width}).trigger('click');
}
else
{
url = url.replace('?onlybody=yes&', '?');
url = url.replace('?onlybody=yes', '?');
url = url.replace('&onlybody=yes', '');
/**
* Show File.
*
* @param int $fileID
* @access public
* @return void
*/
function showFile(fileID)
{
$('#renameBox' + fileID).addClass('hidden');
$('#renameFile' + fileID).closest('li').removeClass('hidden');
}
window.open(url, '_blank');
}
return false;
}
/**
* Smooth refresh file name.
*
* @param int $fileID
* @access public
* @return void
*/
function setFileName(fileID)
{
var fileName = $('#fileName' + fileID).val();
var extension = $('#extension' + fileID).val();
var postData = {'fileName' : fileName, 'extension' : extension};
$('#renameBox' + fileID ).addClass('hidden');
$.ajax(
{
url:createLink('file', 'edit', 'fileID=' + fileID),
dataType: 'json',
method: 'post',
data: postData,
success: function(data)
{
$('#fileTitle' + fileID).html("<i class='icon icon-file-text'></i> &nbsp;" + data['title']);
$('#renameFile' + fileID).closest('li').removeClass('hidden');
$('#renameBox' + fileID).addClass('hidden');
}
})
}
</script>
/* Show edit box for editing file name. */
/**
* Show edit box for editing file name.
*
* @param int $fileID
* @access public
* @return void
*/
function showRenameBox(fileID)
{
$('#renameFile' + fileID).closest('li').addClass('hidden');
$('#renameBox' + fileID).removeClass('hidden');
}
/**
* Show File.
*
* @param int $fileID
* @access public
* @return void
*/
function showFile(fileID)
{
$('#renameBox' + fileID).addClass('hidden');
$('#renameFile' + fileID).closest('li').removeClass('hidden');
}
/**
* Smooth refresh file name.
*
* @param int $fileID
* @access public
* @return void
*/
function setFileName(fileID)
{
var fileName = $('#fileName' + fileID).val();
var extension = $('#extension' + fileID).val();
var postData = {'fileName' : fileName, 'extension' : extension};
$('#renameBox' + fileID ).addClass('hidden');
$.ajax(
{
url:createLink('file', 'edit', 'fileID=' + fileID),
dataType: 'json',
method: 'post',
data: postData,
success: function(data)
{
$('#fileTitle' + fileID).html("<i class='icon icon-file-text'></i> &nbsp;" + data['title']);
$('#renameFile' + fileID).closest('li').removeClass('hidden');
$('#renameBox' + fileID).addClass('hidden');
}
})
}
</script>
<ul class="files-list">
<?php foreach($files as $file):?>
<?php if(common::hasPriv('file', 'download')):?>
@@ -165,7 +182,7 @@
$objectType = zget($this->config->file->objectType, $file->objectType);
if(common::hasPriv($objectType, 'edit', $object))
{
echo "<span class='right-icon'>&nbsp; ";
echo "<span class='right-icon hidden'>&nbsp; ";
/* Determines whether the file supports preview. */
if($file->extension == 'txt')
@@ -179,7 +196,7 @@
/* For the open source version of the file judgment. */
if(stripos('txt|jpg|jpeg|gif|png|bmp', $file->extension) !== false)
{
echo html::a($downloadLink, $lang->file->preview, '_blank', "class='fileAction btn btn-link text-primary' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\"");
echo html::a($downloadLink, "<i class='icon icon-eye'></i>", '_blank', "class='fileAction btn btn-link text-primary' title='{$lang->file->preview}' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\"");
}
/* For the max version of the file judgment. */
@@ -188,13 +205,13 @@
$officeTypes = 'doc|docx|xls|xlsx|ppt|pptx|pdf';
if(stripos($officeTypes, $file->extension) !== false)
{
echo html::a($downloadLink, $lang->file->preview, '_blank', "class='fileAction btn btn-link text-primary' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\"");
echo html::a($downloadLink, "<i class='icon icon-eye'></i>", '_blank', "class='fileAction btn btn-link text-primary' title='{$lang->file->preview}' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title')\"");
}
}
common::printLink('file', 'download', "fileID=$file->id", $lang->file->downloadFile, '_blank', "class='fileAction btn btn-link text-primary' title='{$lang->file->downloadFile}'");
if(common::hasPriv('file', 'edit')) echo html::a('###', $lang->file->edit, '', "id='renameFile$file->id' class='fileAction btn btn-link edit text-primary' onclick='showRenameBox($file->id)' title='{$lang->file->edit}'");
if(common::hasPriv('file', 'delete')) echo html::a('###', $lang->delete, '', "class='fileAction btn btn-link text-primary' onclick='deleteFile($file->id)' title='$lang->delete'");
common::printLink('file', 'download', "fileID=$file->id", "<i class='icon icon-download'></i>", '_blank', "class='fileAction btn btn-link text-primary' title='{$lang->file->downloadFile}'");
if(common::hasPriv('file', 'edit')) echo html::a('###', "<i class='icon icon-pencil-alt'></i>", '', "id='renameFile$file->id' class='fileAction btn btn-link edit text-primary' onclick='showRenameBox($file->id)' title='{$lang->file->edit}'");
if(common::hasPriv('file', 'delete')) echo html::a('###', "<i class='icon icon-trash'></i>", '', "class='fileAction btn btn-link text-primary' onclick='deleteFile($file->id)' title='$lang->delete'");
echo '</span>';
}
echo '</li>';?>
+36 -25
View File
@@ -34,24 +34,30 @@ class git extends control
{
if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
$path = helper::safe64Decode($path);
if(common::hasPriv('repo', 'diff'))
$path = helper::safe64Decode($path);
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab,Gogs,Gitea', 'haspriv');
$currentRepo = null;
foreach($repos as $repo)
{
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab', 'haspriv');
foreach($repos as $repo)
{
if(strpos($path, $repo->path) === 0)
{
$entry = $this->repo->encodePath(str_replace($repo->path, '', $path));
$oldRevision = "$revision^";
$this->locate($this->repo->createLink('diff', "repoID=$repo->id&objectID=0&entry=$entry&oldRevision=$oldRevision&revision=$revision", 'html', 'true'));
}
}
if(!empty($repo->path) and strpos($path, $repo->path) === 0) $currentRepo = $repo;
}
if($currentRepo and common::hasPriv('repo', 'diff'))
{
$entry = $this->repo->encodePath(str_replace($currentRepo->path, '', $path));
$oldRevision = "$revision^";
return $this->locate($this->repo->createLink('diff', "repoID=$currentRepo->id&objectID=0&entry=$entry&oldRevision=$oldRevision&revision=$revision", 'html', 'true'));
}
if($currentRepo)
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($currentRepo);
}
$this->view->path = $path;
$this->view->revision = $revision;
$this->view->diff = $this->git->diff($path, $revision);
$this->view->diff = $currentRepo ? $scm->diff($path, $revision) : '';
$this->display();
}
@@ -68,23 +74,28 @@ class git extends control
{
if(isset($_GET['repoUrl'])) $path = $this->get->repoUrl;
$path = helper::safe64Decode($path);
if(common::hasPriv('repo', 'view'))
$path = helper::safe64Decode($path);
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab,Gogs,Gitea', 'haspriv');
$currentRepo = null;
foreach($repos as $repo)
{
$repos = $this->loadModel('repo')->getListBySCM('Git,Gitlab', 'haspriv');
foreach($repos as $repo)
{
if(strpos($path, $repo->path) === 0)
{
$entry = $this->repo->encodePath(str_replace($repo->path, '', $path));
$this->locate($this->repo->createLink('view', "repoID=$repo->id&objectID=0&entry=$entry&revision=$revision", 'html', true));
}
}
if(!empty($repo->path) and strpos($path, $repo->path) === 0) $currentRepo = $repo;
}
if($currentRepo and common::hasPriv('repo', 'view'))
{
$entry = $this->repo->encodePath(str_replace($currentRepo->path, '', $path));
return $this->locate($this->repo->createLink('view', "repoID=$currentRepo->id&objectID=0&entry=$entry&revision=$revision", 'html', true));
}
if($currentRepo)
{
$scm = $this->app->loadClass('scm');
$scm->setEngine($currentRepo);
}
$this->view->path = $path;
$this->view->revision = $revision;
$this->view->code = $this->git->cat($path, $revision);
$this->view->code = $currentRepo ? $scm->cat($path, $revision) : '';
$this->display();
}
+14 -8
View File
@@ -128,18 +128,24 @@ class gitModel extends model
$branches = $this->repo->getBranches($repo);
$commits = $repo->commits;
$gitlabAccountPairs = array();
$accountPairs = array();
if($repo->SCM == 'Gitlab')
{
$gitlabUserList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService);
foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
$userList = $this->loadModel('gitlab')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitlab->getUserIdAccountPairs($repo->gitService);
foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
}
elseif($repo->SCM == 'Gitea')
{
$gitlabUserList = $this->loadModel('gitea')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account');
foreach($gitlabUserList as $gitlabUser) $gitlabAccountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
$userList = $this->loadModel('gitea')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gitea->getUserAccountIdPairs($repo->gitService, 'openID,account');
foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
}
elseif($repo->SCM == 'Gogs')
{
$userList = $this->loadModel('gogs')->apiGetUsers($repo->gitService);
$acountIDPairs = $this->gogs->getUserAccountIdPairs($repo->gitService, 'openID,account');
foreach($userList as $gitlabUser) $accountPairs[$gitlabUser->realname] = zget($acountIDPairs, $gitlabUser->id, '');
}
/* Update code commit history. */
@@ -183,7 +189,7 @@ class gitModel extends model
' task:' . join(' ', $objects['tasks']) .
' bug:' . join(',', $objects['bugs']));
if($lastVersion != $version) $this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $gitlabAccountPairs);
if($lastVersion != $version) $this->repo->saveAction2PMS($objects, $log, $this->repoRoot, $repo->encoding, 'git', $accountPairs);
}
else
{
+1 -1
View File
@@ -141,9 +141,9 @@ class gitea extends control
{
if($confirm != 'yes') return print(js::confirm($this->lang->gitea->confirmDelete, inlink('delete', "id=$giteaID&confirm=yes")));
$oldGitea = $this->loadModel('pipeline')->getByID($giteaID);
$actionID = $this->pipeline->delete($giteaID, 'gitea');
if(!$actionID) return print(js::error($this->lang->pipeline->delError));
$gitea = $this->pipeline->getByID($giteaID);
$changes = common::createChanges($oldGitea, $gitea);
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = 'Gitea Browse';
$lang->gitea->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = '浏览Gitea';
$lang->gitea->search = '搜索';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitea = new stdclass;
$lang->gitea->common = 'Gitea';
$lang->gitea->browse = '浏览Gitea';
$lang->gitea->search = '搜索';
+9 -16
View File
@@ -228,11 +228,10 @@ class gitlab extends control
{
if($confirm != 'yes') return print(js::confirm($this->lang->gitlab->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
$oldGitLab = $this->gitlab->getByID($id);
$this->loadModel('action');
$this->gitlab->delete(TABLE_PIPELINE, $id);
$oldGitLab = $this->loadModel('pipeline')->getByID($id);
$actionID = $this->pipeline->delete($id, 'gitlab');
if(!$actionID) return print(js::error($this->lang->pipeline->delError));
$actionID = $this->dao->lastInsertID();
$gitLab = $this->gitlab->getByID($id);
$changes = common::createChanges($oldGitLab, $gitLab);
$this->action->logHistory($actionID, $changes);
@@ -722,7 +721,7 @@ class gitlab extends control
$gitlab = $this->gitlab->getByID($gitlabID);
$repos = $this->loadModel('repo')->getRepoListByClient($gitlabID);
$repoPairs = array();
foreach($repos as $repo) $repoPairs[$repo->path] = $repo->id;
foreach($repos as $repo) $repoPairs[$repo->serviceProject] = $repo->id;
$this->view->gitlab = $gitlab;
$this->view->keyword = urldecode(urldecode($keyword));
@@ -966,17 +965,13 @@ class gitlab extends control
/**
* Import gitlab issue to zentaopms.
*
* @param int $repoID
* @param int $gitlabID
* @param int $projectID
* @access public
* @return void
*/
public function importIssue($repoID)
public function importIssue($gitlabID, $projectID)
{
$repo = $this->loadModel('repo')->getRepoByID($repoID);
$productIDList = explode(',', $repo->product);
$gitlabID = $repo->gitService;
$projectID = $repo->project;
$gitlab = $this->gitlab->getByID($gitlabID);
if($gitlab) $user = $this->gitlab->apiGetCurrentUser($gitlab->url, $gitlab->token);
if(empty($user->is_admin)) return print(js::alert($this->lang->gitlab->tokenLimit) . js::locate($this->createLink('gitlab', 'edit', array('gitlabID' => $gitlabID))));
@@ -1053,13 +1048,11 @@ class gitlab extends control
}
}
$products = array('' => '');
$this->loadModel("product");
foreach($productIDList as $productID) $products[$productID] = $this->product->getByID($productID)->name;
$products = $this->loadModel("product")->getPairs();
$this->view->title = $this->lang->gitlab->common . $this->lang->colon . $this->lang->gitlab->importIssue;
$this->view->importable = empty($gitlabIssues) ? false : true;
$this->view->products = $products;
$this->view->products = array('' => '') + $products;
$this->view->gitlabID = $gitlabID;
$this->view->gitlabProjectID = $projectID;
$this->view->objectTypes = $this->config->gitlab->objectTypes;
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = 'GitLab Browse';
$lang->gitlab->search = 'Search';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = '浏览GitLab';
$lang->gitlab->search = '搜索';
-1
View File
@@ -1,5 +1,4 @@
<?php
$lang->gitlab = new stdclass;
$lang->gitlab->common = 'GitLab';
$lang->gitlab->browse = '瀏覽GitLab';
$lang->gitlab->search = '搜索';
+17 -1
View File
@@ -986,7 +986,7 @@ class gitlabModel extends model
*/
public function apiGetSingleProject($gitlabID, $projectID)
{
$url = sprintf($this->getApiRoot($gitlabID), "/projects/$projectID");
$url = sprintf($this->getApiRoot($gitlabID, false), "/projects/$projectID");
return json_decode(commonModel::http($url));
}
@@ -2879,4 +2879,20 @@ class gitlabModel extends model
$html .= '</div>';
return $html;
}
/**
* Get pipeline with api.
*
* @param int $gitlabID
* @param int $projectID
* @param string $branch
* @access public
* @return object|array
*/
public function apiGetPipeline($gitlabID, $projectID, $branch)
{
$apiRoot = $this->getApiRoot($gitlabID);
$url = sprintf($apiRoot, "/projects/$projectID/pipelines") . "&ref=$branch";
return json_decode(commonModel::http($url));
}
}
+1 -1
View File
@@ -56,7 +56,7 @@
<td><?php echo $gitlabUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gitlabUser->id]", $userPairs, $gitlabUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$gitlabUser->zentaoAccount])):?>
<?php if(in_array($gitlabUser->id, $bindedUsers)):?>
<?php $zentaoAccount = zget($userPairs, $gitlabUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php echo $lang->gitlab->binded;?>
+13 -9
View File
@@ -60,15 +60,19 @@
<td class='text' title='<?php echo substr($gitlabProject->last_activity_at, 0, 10);?>'><?php echo substr($gitlabProject->last_activity_at, 0, 10);?></td>
<td class='c-actions'>
<?php
echo common::buildIconButton('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'treemap', '', '', false, '', $this->lang->gitlab->browseBranch, 0, $gitlabProject->default_branch);
echo common::buildIconButton('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag', '', '', false, '', $this->lang->gitlab->browseTag, 0, $gitlabProject->default_branch);
echo common::buildIconButton('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', '', false, '', $this->lang->gitlab->browseBranchPriv, 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch));
echo common::buildIconButton('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', '', false, '', $this->lang->gitlab->browseTagPriv, 0, ($gitlabProject->isMaintainer and $gitlabProject->default_branch));
echo common::buildIconButton('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id]));
echo common::buildIconButton('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id]));
echo common::buildIconButton('gitlab', 'importIssue', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'link', '', '', false, '', '', 0, isset($repoPairs[$gitlabProject->id]));
echo common::buildIconButton('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', '', false, '', '', 0, $gitlabProject->adminer);
echo common::buildIconButton('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', '', false, '', '', 0, $gitlabProject->adminer);
$hasRepoClass = isset($repoPairs[$gitlabProject->id]) ? '' : 'disabled';
$adminerClass = $gitlabProject->adminer ? '' : 'disabled';
$maintainerClass = $gitlabProject->isMaintainer ? '' : 'disabled';
$defaultBranchClass = $gitlabProject->adminer ? '' : 'disabled';
echo common::printIcon('gitlab', 'browseBranch', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'treemap', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseBranch);
echo common::printIcon('gitlab', 'browseTag', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag', '', $defaultBranchClass, false, '', $this->lang->gitlab->browseTag);
echo common::printIcon('gitlab', 'manageBranchPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'branch-lock', '', $defaultBranchClass . ' ' . $maintainerClass, false, '', $this->lang->gitlab->browseBranchPriv);
echo common::printIcon('gitlab', 'manageTagPriv', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'tag-lock', '', $defaultBranchClass . ' ' . $maintainerClass, false, '', $this->lang->gitlab->browseTagPriv);
echo common::printIcon('gitlab', 'manageProjectMembers', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'team', '', $hasRepoClass);
echo common::printIcon('gitlab', 'createWebhook', 'repoID=' . zget($repoPairs, $gitlabProject->id), '', 'list', 'change', 'hiddenwin', $hasRepoClass);
echo common::printIcon('gitlab', 'importIssue', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'link');
echo common::printIcon('gitlab', 'editProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'edit', '', $adminerClass);
echo common::printIcon('gitlab', 'deleteProject', "gitlabID=$gitlabID&projectID=$gitlabProject->id", '', 'list', 'trash', 'hiddenwin', $adminerClass);
?>
</td>
</tr>
+6
View File
@@ -0,0 +1,6 @@
<?php
$config->gogs->create = new stdclass;
$config->gogs->create->requiredFields = 'name,url,token';
$config->gogs->edit = new stdclass;
$config->gogs->edit->requiredFields = 'name,url,token';
+222
View File
@@ -0,0 +1,222 @@
<?php
/**
* The control file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Liyuchun <liyuchun@easycorp.ltd>
* @package product
* @version $Id: ${FILE_NAME} 5144 2022-08-01 liyuchun@easycorp.ltd $
* @link http://www.zentao.net
*/
class gogs extends control
{
/**
* The gogs constructor.
* @param string $moduleName
* @param string $methodName
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
/* This is essential when changing tab(menu) from gogs to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
$this->loadModel('ci')->setMenu();
}
/**
* Browse gogs.
*
* @param string $orderBy
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
/* Admin user don't need bind. */
$gogsList = $this->gogs->getList($orderBy, $pager);
$myGogses = $this->gogs->getGogsListByAccount();
foreach($gogsList as $gogs)
{
$gogs->isBindUser = true;
if(!$this->app->user->admin and !isset($myGogses[$gogs->id])) $gogs->isBindUser = false;
}
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->browse;
$this->view->gogsList = $gogsList;
$this->view->orderBy = $orderBy;
$this->view->pager = $pager;
$this->display();
}
/**
* Create a gogs.
*
* @access public
* @return void
*/
public function create()
{
if($_POST)
{
$this->checkToken();
$gogsID = $this->gogs->create();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$actionID = $this->loadModel('action')->create('gogs', $gogsID, 'created');
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->lblCreate;
$this->display();
}
/**
* View a gogs.
* @param int $gogsID
* @access public
* @return void
*/
public function view($gogsID)
{
$gogs = $this->gogs->getByID($gogsID);
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->view;
$this->view->gogs = $gogs;
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
$this->view->actions = $this->loadModel('action')->getList('gogs', $gogsID);
$this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('pipeline', $gogsID);
$this->display();
}
/**
* Edit a gogs.
*
* @param int $gogsID
* @access public
* @return void
*/
public function edit($gogsID)
{
$oldGogs = $this->gogs->getByID($gogsID);
if($_POST)
{
$this->checkToken();
$this->gogs->update($gogsID);
$gogs = $this->gogs->getByID($gogsID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->loadModel('action');
$actionID = $this->action->create('gogs', $gogsID, 'edited');
$changes = common::createChanges($oldGogs, $gogs);
$this->action->logHistory($actionID, $changes);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('browse')));
}
$this->view->title = $this->lang->gogs->common . $this->lang->colon . $this->lang->gogs->edit;
$this->view->gogs = $oldGogs;
$this->display();
}
/**
* Delete a gogs.
*
* @param int $gogsID
* @access public
* @return void
*/
public function delete($gogsID, $confirm = 'no')
{
if($confirm != 'yes') return print(js::confirm($this->lang->gogs->confirmDelete, inlink('delete', "id=$gogsID&confirm=yes")));
$oldGogs = $this->loadModel('pipeline')->getByID($gogsID);
$actionID = $this->pipeline->delete($gogsID, 'gogs');
if(!$actionID) return print(js::error($this->lang->pipeline->delError));
$gogs = $this->pipeline->getByID($gogsID);
$changes = common::createChanges($oldGogs, $gogs);
$this->loadModel('action')->logHistory($actionID, $changes);
return print(js::reload('parent'));
}
/**
* Check post token has admin permissions.
*
* @access protected
* @return void
*/
protected function checkToken()
{
$gogs = fixer::input('post')->trim('url,token')->get();
$this->dao->update('gogs')->data($gogs)->batchCheck($this->config->gogs->create->requiredFields, 'notempty');
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$result = $this->gogs->checkTokenAccess($gogs->url, $gogs->token);
if($result === false) return $this->send(array('result' => 'fail', 'message' => array('url' => array($this->lang->gogs->hostError))));
if(!$result) return $this->send(array('result' => 'fail', 'message' => array('token' => array($this->lang->gogs->tokenLimit))));
return true;
}
/**
* Bind gogs user to zentao users.
*
* @param int $gogsID
* @access public
* @return void
*/
public function bindUser($gogsID)
{
$zentaoUsers = $this->dao->select('account,email,realname')->from(TABLE_USER)->fetchAll('account');
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
if($_POST)
{
$this->gogs->bindUser($gogsID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->server->http_referer));
}
$this->view->title = $this->lang->gogs->bindUser;
$this->view->userPairs = $userPairs;
$this->view->gogsUsers = $this->gogs->apiGetUsers($gogsID);
$this->view->bindedUsers = $this->gogs->getUserAccountIdPairs($gogsID);
$this->view->matchedResult = $this->gogs->getMatchedUsers($gogsID, $this->view->gogsUsers, $zentaoUsers);
$this->display();
}
/**
* Ajax getProjectBranches
*
* @param int $gogsID
* @param string $project
* @access public
* @return void
*/
public function ajaxGetProjectBranches($gogsID, $project)
{
if(!$gogsID or !$project) return $this->send(array('message' => array()));
$project = urldecode(base64_decode($project));
$branches = $this->gogs->apiGetBranches($gogsID, $project);
$options = "<option value=''></option>";
foreach($branches as $branch)
{
$options .= "<option value='{$branch->name}'>{$branch->name}</option>";
}
$this->send($options);
}
}
+2
View File
@@ -0,0 +1,2 @@
.c-id {width: 60px;}
.c-name {width: 200px;}
+2
View File
@@ -0,0 +1,2 @@
#publicTip {padding-left: 10px;}
.table-form>tbody>tr>th {width: 110px;}
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = 'Gogs Browse';
$lang->gogs->search = 'Search';
$lang->gogs->create = 'Create Gogs';
$lang->gogs->edit = 'Edit Gogs';
$lang->gogs->view = 'View Gogs';
$lang->gogs->delete = 'Delete Gogs';
$lang->gogs->confirmDelete = 'Do you want to delete this Gogs server?';
$lang->gogs->gogsAvatar = 'Avatar';
$lang->gogs->bindUser = 'Bind User';
$lang->gogs->gogsEmail = 'Email';
$lang->gogs->gogsAccount = 'Gogs Account';
$lang->gogs->zentaoAccount = 'Zentao Account';
$lang->gogs->bindingStatus = 'Binding Status';
$lang->gogs->notBind = 'Not bind';
$lang->gogs->binded = 'Binded';
$lang->gogs->bindDynamic = '%s and Zentao user %s';
$lang->gogs->browseAction = 'Gogs List';
$lang->gogs->deleteAction = 'Delete Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "Server Name";
$lang->gogs->url = 'Server URL';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "The current token has no admin privilege. Please regenerate one with root user in Gogs.";
$lang->gogs->hostError = "So the current Gogs server address is invalid, please confirm that the current server can be accessed and try again.";
$lang->gogs->bindUserError = "Can not bind users repeatedly %s";
$lang->gogs->server = "Server List";
$lang->gogs->lblCreate = 'Create Gogs Server';
$lang->gogs->emptyError = " cannot be empty";
$lang->gogs->createSuccess = "Create success";
+35
View File
@@ -0,0 +1,35 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = '浏览Gogs';
$lang->gogs->search = '搜索';
$lang->gogs->create = '添加Gogs';
$lang->gogs->edit = '编辑Gogs';
$lang->gogs->view = '查看Gogs';
$lang->gogs->delete = '删除Gogs';
$lang->gogs->confirmDelete = '确认删除该Gogs吗?';
$lang->gogs->bindUser = '绑定用户';
$lang->gogs->gogsAvatar = '头像';
$lang->gogs->gogsAccount = 'Gogs用户';
$lang->gogs->gogsEmail = '邮箱';
$lang->gogs->zentaoAccount = '禅道用户';
$lang->gogs->bindingStatus = '绑定状态';
$lang->gogs->notBind = '未绑定';
$lang->gogs->binded = '已绑定';
$lang->gogs->bindDynamic = '%s与禅道用户%s';
$lang->gogs->browseAction = 'Gogs列表';
$lang->gogs->deleteAction = '删除Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "服务器名称";
$lang->gogs->url = '服务器地址';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "Gogs Token权限不足。";
$lang->gogs->hostError = "当前Gogs服务器地址无效,请确认当前服务器可被访问";
$lang->gogs->bindUserError = "不能重复绑定用户 %s";
$lang->gogs->server = "服务器列表";
$lang->gogs->lblCreate = '添加Gogs服务器';
$lang->gogs->emptyError = "不能为空";
$lang->gogs->createSuccess = "创建成功";
+32
View File
@@ -0,0 +1,32 @@
<?php
$lang->gogs->common = 'Gogs';
$lang->gogs->browse = '浏览Gogs';
$lang->gogs->search = '搜索';
$lang->gogs->create = '添加Gogs';
$lang->gogs->edit = '编辑Gogs';
$lang->gogs->view = '查看Gogs';
$lang->gogs->delete = '删除Gogs';
$lang->gogs->confirmDelete = '确认删除该Gogs吗?';
$lang->gogs->bindUser = '绑定用户';
$lang->gogs->gogsAccount = 'Gogs用户';
$lang->gogs->zentaoAccount = '禅道用户';
$lang->gogs->bindingStatus = '绑定状态';
$lang->gogs->notBind = '未绑定';
$lang->gogs->binded = '已绑定';
$lang->gogs->bindDynamic = '%s与禅道用户%s';
$lang->gogs->browseAction = 'Gogs列表';
$lang->gogs->deleteAction = '删除Gogs';
$lang->gogs->id = 'ID';
$lang->gogs->name = "服务器名称";
$lang->gogs->url = '服务器地址';
$lang->gogs->token = 'Token';
$lang->gogs->tokenLimit = "Gogs Token权限不足。";
$lang->gogs->hostError = "当前Gogs服务器地址无效,请确认当前服务器可被访问";
$lang->gogs->server = "服务器列表";
$lang->gogs->lblCreate = '添加Gogs服务器';
$lang->gogs->emptyError = "不能为空";
$lang->gogs->createSuccess = "创建成功";
+583
View File
@@ -0,0 +1,583 @@
<?php
/**
* The model file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Chenqi <chenqi@cnezsoft.com>
* @package product
* @version $Id: $
* @link http://www.zentao.net
*/
class gogsModel extends model
{
/**
* Get a gogs by id.
*
* @param int $id
* @access public
* @return object
*/
public function getByID($id)
{
return $this->loadModel('pipeline')->getByID($id);
}
/**
* Get gogs list.
*
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getList($orderBy = 'id_desc', $pager = null)
{
$gogsList = $this->loadModel('pipeline')->getList('gogs', $orderBy, $pager);
return $gogsList;
}
/**
* Get gogs pairs.
*
* @access public
* @return array
*/
public function getPairs()
{
return $this->loadModel('pipeline')->getPairs('gogs');
}
/**
* Get gogs api base url by gogs id.
*
* @param int $gogsID
* @access public
* @return string
*/
public function getApiRoot($gogsID)
{
$gogs = $this->getByID($gogsID);
if(!$gogs) return '';
return rtrim($gogs->url, '/') . '/api/v1%s' . "?token={$gogs->token}";
}
/**
* Create a gogs.
*
* @access public
* @return bool
*/
public function create()
{
return $this->loadModel('pipeline')->create('gogs');
}
/**
* Update a gogs.
*
* @param int $id
* @access public
* @return bool
*/
public function update($id)
{
return $this->loadModel('pipeline')->update($id);
}
/**
* Bind users.
*
* @param int $gogsID
* @access public
* @return array
*/
public function bindUser($gogsID)
{
$userPairs = $this->loadModel('user')->getPairs('noclosed|noletter');
$users = $this->post->zentaoUsers;
$gogsNames = $this->post->gogsUserNames;
$accountList = array();
$repeatUsers = array();
foreach($users as $openID => $user)
{
if(empty($user)) continue;
if(isset($accountList[$user])) $repeatUsers[] = zget($userPairs, $user);
$accountList[$user] = $openID;
}
if(count($repeatUsers))
{
dao::$errors[] = sprintf($this->lang->gogs->bindUserError, join(',', $repeatUsers));
return false;
}
$user = new stdclass;
$user->providerID = $gogsID;
$user->providerType = 'gogs';
$oldUsers = $this->dao->select('*')->from(TABLE_OAUTH)->where('providerType')->eq($user->providerType)->andWhere('providerID')->eq($user->providerID)->fetchAll('openID');
foreach($users as $openID => $account)
{
$existAccount = isset($oldUsers[$openID]) ? $oldUsers[$openID] : '';
if($existAccount and $existAccount->account != $account)
{
$this->dao->delete()
->from(TABLE_OAUTH)
->where('openID')->eq($openID)
->andWhere('providerType')->eq($user->providerType)
->andWhere('providerID')->eq($user->providerID)
->exec();
$this->loadModel('action')->create('gogsuser', $gogsID, 'unbind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$existAccount->account]->realname));
}
if(!$existAccount or $existAccount->account != $account)
{
if(!$account) continue;
$user->account = $account;
$user->openID = $openID;
$this->dao->insert(TABLE_OAUTH)->data($user)->exec();
$this->loadModel('action')->create('gogsuser', $gogsID, 'bind', '', sprintf($this->lang->gogs->bindDynamic, $gogsNames[$openID], $zentaoUsers[$account]->realname));
}
}
}
/**
* Api error handling.
*
* @param object $response
* @access public
* @return bool
*/
public function apiErrorHandling($response)
{
if(!empty($response->error))
{
dao::$errors[] = $response->error;
return false;
}
if(!empty($response->message))
{
if(is_string($response->message))
{
$errorKey = array_search($response->message, $this->lang->gogs->apiError);
dao::$errors[] = $errorKey === false ? $response->message : zget($this->lang->gogs->errorLang, $errorKey);
}
else
{
foreach($response->message as $field => $fieldErrors)
{
if(is_string($fieldErrors))
{
$errorKey = array_search($fieldErrors, $this->lang->gogs->apiError);
if($fieldErrors) dao::$errors[$field][] = $errorKey === false ? $fieldErrors : zget($this->lang->gogs->errorLang, $errorKey);
}
else
{
foreach($fieldErrors as $error)
{
$errorKey = array_search($error, $this->lang->gogs->apiError);
if($error) dao::$errors[$field][] = $errorKey === false ? $error : zget($this->lang->gogs->errorLang, $errorKey);
}
}
}
}
}
if(!$response) dao::$errors[] = false;
return false;
}
/**
* Check token access.
*
* @param string $url
* @param string $token
* @access public
* @return void
*/
public function checkTokenAccess($url = '', $token = '')
{
$apiRoot = rtrim($url, '/') . '/api/v1%s' . "?token={$token}";
$url = sprintf($apiRoot, "/user");
$httpData = commonModel::httpWithHeader($url);
$user = json_decode($httpData['body']);
if(empty($httpData['header'])) return false;
if(empty($user)) return null;
/* Check whether the token belongs to the administrator by edit user. */
$editUserUrl = sprintf($apiRoot, "/admin/users/" . $user->username);
$data = new stdclass();
$data->login_name = $user->login;
$data->email = $user->email;
$result = commonModel::http($editUserUrl, $data, array(), array(), 'data', 'PATCH');
$user = json_decode($result);
if(empty($user)) return null;
return true;
}
/**
* Get Gogs id list by user account.
*
* @param string $account
* @access public
* @return array
*/
public function getGogsListByAccount($account = '')
{
if(!$account) $account = $this->app->user->account;
return $this->dao->select('providerID,openID')->from(TABLE_OAUTH)
->where('providerType')->eq('gogs')
->andWhere('account')->eq($account)
->fetchPairs('providerID');
}
/**
* Get zentao account gogs user id pairs of one gogs.
*
* @param int $gogsID
* @access public
* @return array
*/
public function getUserAccountIdPairs($gogsID, $fields = 'account,openID')
{
return $this->dao->select($fields)->from(TABLE_OAUTH)
->where('providerType')->eq('gogs')
->andWhere('providerID')->eq($gogsID)
->fetchPairs();
}
/**
* Get gogs user id by zentao account.
*
* @param int $gogsID
* @param string $zentaoAccount
* @access public
* @return array
*/
public function getUserIDByZentaoAccount($gogsID, $zentaoAccount)
{
return $this->dao->select('openID')->from(TABLE_OAUTH)
->where('providerType')->eq('gogs')
->andWhere('providerID')->eq($gogsID)
->andWhere('account')->eq($zentaoAccount)
->fetch('openID');
}
/**
* Get matched gogs users.
*
* @param int $gogsID
* @param array $gogsUsers
* @param array $zentaoUsers
* @access public
* @return array
*/
public function getMatchedUsers($gogsID, $gogsUsers, $zentaoUsers)
{
$matches = new stdclass;
foreach($gogsUsers as $gogsUser)
{
foreach($zentaoUsers as $zentaoUser)
{
if($gogsUser->account == $zentaoUser->account) $matches->accounts[$gogsUser->account][] = $zentaoUser->account;
if($gogsUser->realname == $zentaoUser->realname) $matches->names[$gogsUser->realname][] = $zentaoUser->account;
if($gogsUser->email == $zentaoUser->email) $matches->emails[$gogsUser->email][] = $zentaoUser->account;
}
}
$bindedUsers = $this->getUserAccountIdPairs($gogsID, 'openID,account');
$matchedUsers = array();
foreach($gogsUsers as $gogsUser)
{
if(isset($bindedUsers[$gogsUser->account]))
{
$gogsUser->zentaoAccount = $bindedUsers[$gogsUser->account];
$matchedUsers[] = $gogsUser;
continue;
}
$matchedZentaoUsers = array();
if(isset($matches->accounts[$gogsUser->account])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->accounts[$gogsUser->account]);
if(isset($matches->emails[$gogsUser->email])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->emails[$gogsUser->email]);
if(isset($matches->names[$gogsUser->realname])) $matchedZentaoUsers = array_merge($matchedZentaoUsers, $matches->names[$gogsUser->realname]);
$matchedZentaoUsers = array_unique($matchedZentaoUsers);
if(count($matchedZentaoUsers) == 1)
{
$gogsUser->zentaoAccount = current($matchedZentaoUsers);
$matchedUsers[] = $gogsUser;
}
}
return $matchedUsers;
}
/**
* Get project by api.
*
* @param int $gogsID
* @param int $projectID
* @access public
* @return void
*/
public function apiGetSingleProject($gogsID, $projectID)
{
$apiRoot = $this->getApiRoot($gogsID);
if(!$apiRoot) return array();
$url = sprintf($apiRoot, "/repos/$projectID");
$project = json_decode(commonModel::http($url));
if(isset($project->name))
{
$project->name_with_namespace = $project->full_name;
$project->path_with_namespace = $project->full_name;
$project->http_url_to_repo = $project->html_url;
$project->name_with_namespace = $project->full_name;
$gogs = $this->getByID($gogsID);
$oauth = "oauth2:{$gogs->token}@";
$project->tokenCloneUrl = preg_replace('/(http(s)?:\/\/)/', "\$1$oauth", $project->html_url);
}
return $project;
}
/**
* Get projects by api.
*
* @param int $gogsID
* @access public
* @return array
*/
public function apiGetProjects($gogsID)
{
$apiRoot = $this->getApiRoot($gogsID);
if(!$apiRoot) return array();
$user = $this->apiGetAdminer($gogsID);
if(!$user) return array();
$url = sprintf($apiRoot, "/users/{$user->username}/repos");
$allResults = array();
for($page = 1; true; $page++)
{
$results = json_decode(commonModel::http($url . "&page={$page}&limit=50"));
if(!is_array($results)) break;
if(!empty($results)) $allResults = array_merge($allResults, $results);
if(count($results) < 50) break;
}
return $allResults;
}
/**
* Api get adminer.
*
* @param int $gogsID
* @access public
* @return void
*/
public function apiGetAdminer($gogsID)
{
$apiRoot = $this->getApiRoot($gogsID);
if(!$apiRoot) return array();
$url = sprintf($apiRoot, "/user");
$user = json_decode(commonModel::http($url));
return isset($user->username) ? $user : null;
}
/**
* Get gogs user list.
*
* @param int $gogsID
* @param bool $onlyLinked
* @access public
* @return array
*/
public function apiGetUsers($gogsID, $onlyLinked = false)
{
$response = array();
$apiRoot = $this->getApiRoot($gogsID);
for($page = 1; true; $page++)
{
$url = sprintf($apiRoot, "/admin/users") . "&page={$page}&limit=20";
$result = json_decode(commonModel::http($url));
if(empty($result->data)) break;
$response = array_merge($response, $result->data);
$page += 1;
}
if(empty($response)) return array();
/* Get linked users. */
$linkedUsers = array();
if($onlyLinked) $linkedUsers = $this->getUserAccountIdPairs($gogsID, 'openID,account');
$users = array();
foreach($response as $gogsUser)
{
if($onlyLinked and !isset($linkedUsers[$gogsUser->id])) continue;
$user = new stdclass;
$user->id = $gogsUser->id;
$user->realname = $gogsUser->full_name ? $gogsUser->full_name : $gogsUser->username;
$user->account = $gogsUser->username;
$user->email = zget($gogsUser, 'email', '');
$user->avatar = $gogsUser->avatar_url;
$user->createdAt = zget($gogsUser, 'created', '');
$user->lastActivityOn = zget($gogsUser, 'login', '');
$users[] = $user;
}
return $users;
}
/**
* Get project repository branches by api.
*
* @param int $gogsID
* @param string $project
* @access public
* @return object
*/
public function apiGetBranches($gogsID, $project, $pager = null)
{
$url = sprintf($this->getApiRoot($gogsID), "/repos/{$project}/branches");
$allResults = array();
for($page = 1; true; $page++)
{
$results = json_decode(commonModel::http($url . "&page={$page}&limit=50"));
if(!is_array($results)) break;
if(!empty($results)) $allResults = array_merge($allResults, $results);
if(count($results) < 100) break;
}
return $allResults;
}
/**
* Get upstream project by API.
*
* @param int $gogsID
* @param string $project
* @access public
* @return void
*/
public function apiGetUpstream($gogsID, $project)
{
$currentProject = $this->apiGetSingleProject($gogsID, $project);
if(isset($currentProject->parent->full_name)) return $currentProject->parent->full_name;
return array();
}
/**
* Get branches.
*
* @param int $gogsID
* @param string $project
* @access public
* @return array
*/
public function getBranches($gogsID, $project)
{
$rawBranches = $this->apiGetBranches($gogsID, $project);
$branches = array();
foreach($rawBranches as $branch) $branches[] = $branch->name;
return $branches;
}
/**
* Get gogs user id and realname pairs of one gogs.
*
* @param int $gogsID
* @access public
* @return array
*/
public function getUserIdRealnamePairs($gogsID)
{
return $this->dao->select('oauth.openID as openID,user.realname as realname')
->from(TABLE_OAUTH)->alias('oauth')
->leftJoin(TABLE_USER)->alias('user')
->on("oauth.account = user.account")
->where('providerType')->eq('gogs')
->andWhere('providerID')->eq($gogsID)
->fetchPairs();
}
/**
* Get single branch by API.
*
* @param int $gogsID
* @param string $project
* @param string $branchName
* @access public
* @return object
*/
public function apiGetSingleBranch($gogsID, $project, $branchName)
{
$url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branches/$branchName");
$branch = json_decode(commonModel::http($url));
if($branch)
{
$gogs = $this->getByID($gogsID);
$branch->web_url = "{$gogs->url}/$project/src/$branchName";
}
return $branch;
}
/**
* Get protect branches of one project.
*
* @param int $gogsID
* @param string $project
* @param string $keyword
* @access public
* @return array
*/
public function apiGetBranchPrivs($gogsID, $project, $keyword = '')
{
$keyword = urlencode($keyword);
$url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branch_protections");
$branches = json_decode(commonModel::http($url));
if(!is_array($branches)) return array();
$newBranches = array();
foreach($branches as $branch)
{
$branch->name = $branch->Name;
if(empty($keyword) || stristr($branch->name, $keyword)) $newBranches[] = $branch;
}
return $newBranches;
}
/**
* Api delete branch.
*
* @param int $gogsID
* @param string $project
* @param string $branch
* @access public
* @return void
*/
public function apiDeleteBranch($gogsID, $project, $branch)
{
$url = sprintf($this->getApiRoot($gogsID), "/repos/$project/branches/$branch");
return json_decode(commonModel::http($url, null, array(CURLOPT_CUSTOMREQUEST => 'DELETE')));
}
}
+85
View File
@@ -0,0 +1,85 @@
<?php
/**
* The bind user view of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Yuchun Li <liyuchun@easycorp.ltd>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainContent" class="main-content">
<div class="main-header">
<h2><?php echo $lang->gogs->bindUser;?></h2>
</div>
<form method='post' class='load-indicator main-form form-ajax' enctype='multipart/form-data'>
<div class="table-responsive">
<table class="table table-borderless w-800px">
<thead>
<tr>
<th class='w-60px'><?php echo $lang->gogs->gogsAvatar;?></th>
<th><?php echo $lang->gogs->gogsAccount;?></th>
<th><?php echo $lang->gogs->gogsEmail;?></th>
<th class='w-150px'><?php echo $lang->gogs->zentaoAccount;?></th>
<th><?php echo $lang->gogs->bindingStatus;?></th>
</tr>
</thead>
<tbody>
<?php foreach($gogsUsers as $gogsUser):?>
<?php if(isset($gogsUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gogsUserNames[$gogsUser->account]", $gogsUser->realname);?>
<tr>
<td><?php echo html::image($gogsUser->avatar, "height=40");?></td>
<td class='text-left'>
<strong><?php echo $gogsUser->realname;?></strong>
<br>
<?php echo $gogsUser->account;?>
</td>
<td><?php echo $gogsUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gogsUser->account]", $userPairs, '', "class='form-control select chosen'" );?></td>
<td><?php echo $lang->gogs->notBind;?></td>
</tr>
<?php endforeach;?>
<?php foreach($gogsUsers as $gogsUser):?>
<?php if(!isset($gogsUser->zentaoAccount)) continue;?>
<?php echo html::hidden("gogsUserNames[$gogsUser->account]", $gogsUser->realname);?>
<tr>
<td><?php echo html::image($gogsUser->avatar, "height=40");?></td>
<td>
<strong><?php echo $gogsUser->realname;?></strong>
<br>
<?php echo $gogsUser->account;?>
</td>
<td><?php echo $gogsUser->email;?></td>
<td><?php echo html::select("zentaoUsers[$gogsUser->account]", $userPairs, $gogsUser->zentaoAccount, "class='form-control select chosen'" );?></td>
<td>
<?php if(isset($bindedUsers[$gogsUser->zentaoAccount])):?>
<?php $zentaoAccount = zget($userPairs, $gogsUser->zentaoAccount, '');?>
<?php if(!empty($zentaoAccount)):?>
<?php echo $lang->gogs->binded;?>
<?php else:?>
<?php echo '<span class="text-red">' . $lang->gogs->bindedError . '</span>';?>
<?php endif;?>
<?php else:?>
<?php echo $lang->gogs->notBind;?>
<?php endif;?>
</td>
</tr>
<?php endforeach;?>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-center form-actions">
<?php echo html::submitButton();?>
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+73
View File
@@ -0,0 +1,73 @@
<?php
/**
* The browse view file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
<?php echo html::a($this->createLink('gogs', 'browse'), "<span class='text'>{$lang->gogs->server}</span>", '', "class='btn btn-link btn-active-text'");?>
</div>
<div class="btn-toolbar pull-right">
<?php if(common::hasPriv('gogs', 'create')) common::printLink('gogs', 'create', "", "<i class='icon icon-plus'></i> " . $lang->gogs->create, '', "class='btn btn-primary'");?>
</div>
</div>
<?php if(empty($gogsList)):?>
<div class="table-empty-tip">
<p>
<span class="text-muted"><?php echo $lang->noData;?></span>
<?php if(common::hasPriv('gogs', 'create')):?>
<?php echo html::a($this->createLink('gogs', 'create'), "<i class='icon icon-plus'></i> " . $lang->gogs->create, '', "class='btn btn-info'");?>
<?php endif;?>
</p>
</div>
<?php else:?>
<div id='mainContent' class='main-row'>
<form class='main-table' id='ajaxForm' method='post'>
<table id='gogsList' class='table has-sort-head table-fixed'>
<thead>
<tr>
<?php $vars = "orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<th class='c-id'><?php common::printOrderLink('id', $orderBy, $vars, $lang->gogs->id);?></th>
<th class='c-name w-300px'><?php common::printOrderLink('name', $orderBy, $vars, $lang->gogs->name);?></th>
<th class='text'><?php common::printOrderLink('url', $orderBy, $vars, $lang->gogs->url);?></th>
<th class='c-actions-3 text-center'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php foreach ($gogsList as $id => $gogs): ?>
<tr class='text'>
<td class='text'><?php echo $id;?></td>
<td class='text-c-name' title='<?php echo $gogs->name;?>'>
<?php if(common::hasPriv('gogs', 'view')):?>
<a class="iframe" href="<?php echo $this->createLink('gogs', 'view', "gogsID=$id", '', true); ?>"><?php echo $gogs->name;?></a>
<?php else:?>
<?php echo $gogs->name;?>
<?php endif;?>
</td>
<td class='text' title='<?php echo $gogs->url;?>'><?php echo html::a($gogs->url, $gogs->url, '_target');?></td>
<td class='c-actions'>
<?php
common::printIcon('gogs', 'edit', "gogsID=$id", '', 'list', 'edit');
echo common::buildIconButton('gogs', 'bindUser', "gogsID=$id", '', 'list', 'link', '', '', false, '', '', 0, $gogs->isBindUser);
common::printIcon('gogs', 'delete', "gogsID=$id", '', 'list', 'trash', 'hiddenwin');
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php if($gogsList):?>
<div class='table-footer'><?php $pager->show('right', 'pagerjs');?></div>
<?php endif;?>
</form>
</div>
<?php endif;?>
<?php include '../../common/view/footer.html.php';?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The create view file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='main-col main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->gogs->lblCreate;?></h2>
</div>
<form id='gogsForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->gogs->name;?></th>
<td class='required'><?php echo html::input('name', '', "class='form-control'");?></td>
<td class="tips-git"></td>
</tr>
<tr>
<th><?php echo $lang->gogs->url;?></th>
<td class='required'><?php echo html::input('url', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->gogs->token;?></th>
<td><?php echo html::input('token', '', "class='form-control'");?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+45
View File
@@ -0,0 +1,45 @@
<?php
/**
* The edit view file of gogs module of ZenTaoPMS.
*
* @copyright Copyright 2009-2017 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Gang Liu <liugang@cnezsoft.com>
* @package gogs
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-row'>
<div class='main-col main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->gogs->edit;?></h2>
</div>
<form id='gogsForm' method='post' class='form-ajax'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->gogs->name;?></th>
<td class='required'><?php echo html::input('name', isset($gogs->name) ? $gogs->name : '', "class='form-control'");?></td>
<td class="tips-git"></td>
</tr>
<tr>
<th><?php echo $lang->gogs->url;?></th>
<td class='required'><?php echo html::input('url', isset($gogs->url) ? $gogs->url : '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->gogs->token;?></th>
<td><?php echo html::input('token', isset($gogs->token) ? $gogs->token : '', "class='form-control'");?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>

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