From 369ba47f5c40ed62f30361756f1616348d075e97 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sat, 10 Jun 2023 09:29:55 +0800 Subject: [PATCH 01/17] * Add score::config. --- module/score/config/dtable.php | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 module/score/config/dtable.php diff --git a/module/score/config/dtable.php b/module/score/config/dtable.php new file mode 100644 index 0000000000..d37d2ccad7 --- /dev/null +++ b/module/score/config/dtable.php @@ -0,0 +1,35 @@ +score->dtable = new stdclass(); + +$config->score->dtable->fieldList['module']['name'] = 'module'; +$config->score->dtable->fieldList['module']['title'] = $lang->score->module; +$config->score->dtable->fieldList['module']['type'] = 'category'; +$config->score->dtable->fieldList['module']['fixed'] = 'left'; + +$config->score->dtable->fieldList['method']['name'] = 'method'; +$config->score->dtable->fieldList['method']['title'] = $lang->score->method; +$config->score->dtable->fieldList['method']['type'] = 'category'; +$config->score->dtable->fieldList['method']['fixed'] = 'left'; + +$config->score->dtable->fieldList['times']['name'] = 'times'; +$config->score->dtable->fieldList['times']['title'] = $lang->score->times; +$config->score->dtable->fieldList['times']['type'] = 'number'; +$config->score->dtable->fieldList['times']['sortType'] = false; +$config->score->dtable->fieldList['times']['group'] = 2; + +$config->score->dtable->fieldList['hour']['name'] = 'hour'; +$config->score->dtable->fieldList['hour']['title'] = $lang->score->hour; +$config->score->dtable->fieldList['hour']['type'] = 'number'; +$config->score->dtable->fieldList['hour']['sortType'] = false; +$config->score->dtable->fieldList['hour']['group'] = 2; + +$config->score->dtable->fieldList['score']['name'] = 'score'; +$config->score->dtable->fieldList['score']['title'] = $lang->score->score; +$config->score->dtable->fieldList['score']['type'] = 'number'; +$config->score->dtable->fieldList['score']['sortType'] = false; +$config->score->dtable->fieldList['score']['group'] = 2; + +$config->score->dtable->fieldList['desc']['name'] = 'desc'; +$config->score->dtable->fieldList['desc']['title'] = $lang->score->desc; +$config->score->dtable->fieldList['desc']['type'] = 'desc'; From 34a0daff1168f5fc1815d2f569fe007020f4e069 Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sat, 10 Jun 2023 09:30:23 +0800 Subject: [PATCH 02/17] * Add score::rule ui page. --- module/score/ui/rule.html.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 module/score/ui/rule.html.php diff --git a/module/score/ui/rule.html.php b/module/score/ui/rule.html.php new file mode 100644 index 0000000000..c70cee1f32 --- /dev/null +++ b/module/score/ui/rule.html.php @@ -0,0 +1,35 @@ + + * @package my + * @link https://www.zentao.net + */ +namespace zin; + +featureBar +( + set::current('all'), +); + +toolbar +( + btn + ( + setClass('btn primary'), + set::url(helper::createLink('my', 'score')), + $lang->score->common + ), +); + +dtable +( + set::cols(array_values($config->score->dtable->fieldList)), + set::data($rules), + set::fixedLeftWidth('0.2'), +); + +render(); From 9a1e080120ee250a5b43032454ea1d839a43f39b Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sat, 10 Jun 2023 09:31:56 +0800 Subject: [PATCH 03/17] * Code for score lang. --- module/score/lang/de.php | 2 ++ module/score/lang/en.php | 2 ++ module/score/lang/fr.php | 64 +++++++++++++++++++------------------ module/score/lang/zh-cn.php | 2 ++ 4 files changed, 39 insertions(+), 31 deletions(-) diff --git a/module/score/lang/de.php b/module/score/lang/de.php index b1c9d0cd91..093426570e 100644 --- a/module/score/lang/de.php +++ b/module/score/lang/de.php @@ -86,3 +86,5 @@ $lang->score->extended['bug']['resolve'] = 'Nach dem Lösen eines Bugs, $lang->score->extended['bug']['confirm'] = 'Wenn ein Bug bestätigt wurde, werden die Punkte nach der Dringlichkeit vergeben. S1, + ##severity,3##; S2 + ##severity,2##, S3 + ##severity,1##.'; $lang->score->extended['task']['finish'] = 'Wenn eine Aufgabe erledigt wurde, werden folgende Punkte vergeben: runde(Mannstunden / 10 Schätzung / Verbraucht) + Prirität (p1 ##pri,1##, p2 ##pri,2##).'; $lang->score->extended['story']['close'] = 'Wenn eine Story geschlossen wurde, bekommt der Ersteler ##createID## Punkte.'; + +$lang->score->featureBar['rule']['all'] = 'Score Rules'; diff --git a/module/score/lang/en.php b/module/score/lang/en.php index d528bf0079..b9bc6fe563 100644 --- a/module/score/lang/en.php +++ b/module/score/lang/en.php @@ -86,3 +86,5 @@ $lang->score->extended['bug']['resolve'] = 'After a bug is resolved, get $lang->score->extended['bug']['confirm'] = 'After a bug is confirmed, get extra points according to its severity. S1, + ##severity,1##; S2 + ##severity,2##, S3 + ##severity,3##.'; $lang->score->extended['task']['finish'] = 'After a task is done, get extra points by round(man-hour / 10 Estimates / Cost) + Priority point (p1 ##pri,1##, p2 ##pri,2##).'; $lang->score->extended['story']['close'] = 'After a story is closed, its creator will get extra ##createID## points.'; + +$lang->score->featureBar['rule']['all'] = 'Score Rules'; diff --git a/module/score/lang/fr.php b/module/score/lang/fr.php index fc562cbe27..10bf2dfd9e 100644 --- a/module/score/lang/fr.php +++ b/module/score/lang/fr.php @@ -3,12 +3,12 @@ $lang->score->common = 'Mes Points'; $lang->score->record = 'Points'; $lang->score->current = 'Mes Points'; $lang->score->level = 'Niveau de Points'; -$lang->score->reset = 'Réinitialiser'; +$lang->score->reset = 'R?initialiser'; $lang->score->tips = 'Points obtenus hier : %d
Total Points: %d'; -$lang->score->resetTips = 'Ca va prendre un moment. Ne fermez pas la fenêtre.'; -$lang->score->resetStart = 'Démarrer'; +$lang->score->resetTips = 'Ca va prendre un moment. Ne fermez pas la fen?tre.'; +$lang->score->resetStart = 'D?marrer'; $lang->score->resetLoading = 'Calcul en cours : '; -$lang->score->resetFinish = 'Terminé'; +$lang->score->resetFinish = 'Termin?'; $lang->score->id = 'ID'; $lang->score->userID = 'UserID'; @@ -17,14 +17,14 @@ $lang->score->module = 'Module'; $lang->score->method = 'Actions'; $lang->score->before = 'Avant'; $lang->score->score = '+/-'; -$lang->score->after = 'Après'; +$lang->score->after = 'Apr?s'; $lang->score->time = 'Heure'; $lang->score->desc = 'Description'; $lang->score->noLimit = 'Sans limite'; $lang->score->times = 'Heures'; $lang->score->hour = 'Heures'; -$lang->score->modules['task'] = 'Tâche'; +$lang->score->modules['task'] = 'T?che'; $lang->score->modules['tutorial'] = 'Tutoriel'; $lang->score->modules['user'] = 'User'; $lang->score->modules['ajax'] = 'Autre'; @@ -41,48 +41,50 @@ $lang->score->modules['release'] = 'Release'; $lang->score->modules['block'] = 'Bloc'; $lang->score->modules['search'] = 'Recherche'; -$lang->score->methods['task']['create'] = 'Créer Tâche'; -$lang->score->methods['task']['close'] = 'Fermer Tâche'; -$lang->score->methods['task']['finish'] = 'Terminer Tâche'; +$lang->score->methods['task']['create'] = 'Cr?er T?che'; +$lang->score->methods['task']['close'] = 'Fermer T?che'; +$lang->score->methods['task']['finish'] = 'Terminer T?che'; $lang->score->methods['tutorial']['finish'] = 'Terminer Tutoriel'; $lang->score->methods['user']['login'] = 'Connexion'; $lang->score->methods['user']['changePassword'] = 'Changer Password'; $lang->score->methods['user']['editProfile'] = 'Editer Profil'; -$lang->score->methods['ajax']['selectTheme'] = 'Changer Thème'; +$lang->score->methods['ajax']['selectTheme'] = 'Changer Th?me'; $lang->score->methods['ajax']['selectLang'] = 'Changer Langue'; -$lang->score->methods['ajax']['showSearchMenu'] = 'Recherche Avancée'; -$lang->score->methods['ajax']['customMenu'] = 'Menu Personnalisé'; -$lang->score->methods['ajax']['dragSelected'] = 'Déplacez sur Page de Liste'; +$lang->score->methods['ajax']['showSearchMenu'] = 'Recherche Avanc?e'; +$lang->score->methods['ajax']['customMenu'] = 'Menu Personnalis?'; +$lang->score->methods['ajax']['dragSelected'] = 'D?placez sur Page de Liste'; $lang->score->methods['ajax']['lastNext'] = 'Raccourci Page Suivante'; $lang->score->methods['ajax']['switchToDataTable'] = 'Switch Data Table'; $lang->score->methods['ajax']['submitPage'] = 'Changer Pagination Nb#'; $lang->score->methods['ajax']['quickJump'] = 'Saut Rapide'; -$lang->score->methods['ajax']['batchCreate'] = 'Créer par Lot Premier'; +$lang->score->methods['ajax']['batchCreate'] = 'Cr?er par Lot Premier'; $lang->score->methods['ajax']['batchEdit'] = 'Editer par Lot Premier'; $lang->score->methods['ajax']['batchOther'] = 'Autres Actions par Lot'; -$lang->score->methods['doc']['create'] = 'Créer Document'; -$lang->score->methods['todo']['create'] = 'Créer Entrée Agenda'; -$lang->score->methods['story']['create'] = 'Créer Story'; +$lang->score->methods['doc']['create'] = 'Cr?er Document'; +$lang->score->methods['todo']['create'] = 'Cr?er Entr?e Agenda'; +$lang->score->methods['story']['create'] = 'Cr?er Story'; $lang->score->methods['story']['close'] = 'Fermer Story'; $lang->score->methods['bug']['create'] = 'Signaler un Bug'; $lang->score->methods['bug']['confirmBug'] = 'Confirmer Bug'; -$lang->score->methods['bug']['createFormCase'] = 'Créer Formulaire Bug'; -$lang->score->methods['bug']['resolve'] = 'Résoudre Bug'; -$lang->score->methods['bug']['saveTplModal'] = 'Sauver Modèle'; +$lang->score->methods['bug']['createFormCase'] = 'Cr?er Formulaire Bug'; +$lang->score->methods['bug']['resolve'] = 'R?soudre Bug'; +$lang->score->methods['bug']['saveTplModal'] = 'Sauver Mod?le'; $lang->score->methods['testtask']['runCase'] = 'Jouer CasTest'; -$lang->score->methods['testcase']['create'] = 'Créer CasTest'; -$lang->score->methods['build']['create'] = 'Créer Build'; -$lang->score->methods['execution']['create'] = "Créer {$lang->executionCommon}"; +$lang->score->methods['testcase']['create'] = 'Cr?er CasTest'; +$lang->score->methods['build']['create'] = 'Cr?er Build'; +$lang->score->methods['execution']['create'] = "Cr?er {$lang->executionCommon}"; $lang->score->methods['execution']['close'] = "Terminer {$lang->executionCommon}"; -$lang->score->methods['productplan']['create'] = 'Créer Plan'; -$lang->score->methods['release']['create'] = 'Créer Release'; +$lang->score->methods['productplan']['create'] = 'Cr?er Plan'; +$lang->score->methods['release']['create'] = 'Cr?er Release'; $lang->score->methods['block']['set'] = 'Personnaliser Bloc'; $lang->score->methods['search']['saveQuery'] = 'Sauver Query'; -$lang->score->methods['search']['saveQueryAdvanced'] = 'Recherche Avancée'; +$lang->score->methods['search']['saveQueryAdvanced'] = 'Recherche Avanc?e'; $lang->score->extended['user']['changePassword'] = "Obtenez ##strength,1## points, si le mot de passe est moyen. Obtenez ##strength,2## points, s'il est fort."; -$lang->score->extended['execution']['close'] = "Après que le projet soit fermé, le Project Manager obtient ##manager,close## points et les membres de l'équipe obtiennent ##member,close## points. S'il a été réalisé dans les temps ou plus vite, le Project Manager obtient ##manager,onTime## points et les membres de l'équipe obtiennent ##member,onTime## points."; -$lang->score->extended['bug']['resolve'] = 'Après un bug résolu, obtenez des extra-points en fonction de sa sévérité. S1, + ##severity,3##; S2 + ##severity,2##, S3 + ##severity,1##.'; -$lang->score->extended['bug']['confirmBug'] = 'Après un bug confirmé, obtenez des extra-points en fonction de sa sévérité. S1, + ##severity,3##; S2 + ##severity,2##, S3 + ##severity,1##.'; -$lang->score->extended['task']['finish'] = 'Après une tâche accomplie, obtenez des extra-points par arrondi(heures-homme / 10 Estimés / Coût) + Points de Priorité (p1 ##pri,1##, p2 ##pri,2##).'; -$lang->score->extended['story']['close'] = "Après la fermeture d'une Story, son créateur recevra extra ##createID## points."; +$lang->score->extended['execution']['close'] = "Apr?s que le projet soit ferm?, le Project Manager obtient ##manager,close## points et les membres de l'?quipe obtiennent ##member,close## points. S'il a ?t? r?alis? dans les temps ou plus vite, le Project Manager obtient ##manager,onTime## points et les membres de l'?quipe obtiennent ##member,onTime## points."; +$lang->score->extended['bug']['resolve'] = 'Apr?s un bug r?solu, obtenez des extra-points en fonction de sa s?v?rit?. S1, + ##severity,3##; S2 + ##severity,2##, S3 + ##severity,1##.'; +$lang->score->extended['bug']['confirmBug'] = 'Apr?s un bug confirm?, obtenez des extra-points en fonction de sa s?v?rit?. S1, + ##severity,3##; S2 + ##severity,2##, S3 + ##severity,1##.'; +$lang->score->extended['task']['finish'] = 'Apr?s une t?che accomplie, obtenez des extra-points par arrondi(heures-homme / 10 Estim?s / Co?t) + Points de Priorit? (p1 ##pri,1##, p2 ##pri,2##).'; +$lang->score->extended['story']['close'] = "Apr?s la fermeture d'une Story, son cr?ateur recevra extra ##createID## points."; + +$lang->score->featureBar['rule']['all'] = 'Score Rules'; diff --git a/module/score/lang/zh-cn.php b/module/score/lang/zh-cn.php index 68b1784791..5a827b1d11 100644 --- a/module/score/lang/zh-cn.php +++ b/module/score/lang/zh-cn.php @@ -86,3 +86,5 @@ $lang->score->extended['bug']['resolve'] = 'Bug解决后,额外增加 $lang->score->extended['bug']['confirm'] = 'Bug确认后,额外增加严重程度积分:s1 + ##severity,1##, s2 + ##severity,2##, s3 + ##severity,3##。'; $lang->score->extended['task']['finish'] = '额外增加工时积分 round(工时 / 10 * 预计 / 消耗) + 优先级积分(p1 ##pri,1##, p2 ##pri,2##)。'; $lang->score->extended['story']['close'] = "{$lang->SRCommon}的创建者额外增加##createID##分"; + +$lang->score->featureBar['rule']['all'] = '积分规则'; From ecfb3bf746be12116a949dc158970e65292993bf Mon Sep 17 00:00:00 2001 From: sunguangming Date: Sat, 10 Jun 2023 09:32:13 +0800 Subject: [PATCH 04/17] * Add build rules method for rule list. --- module/score/control.php | 3 ++- module/score/model.php | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/module/score/control.php b/module/score/control.php index b18cffe279..c364e631d3 100644 --- a/module/score/control.php +++ b/module/score/control.php @@ -33,7 +33,8 @@ class score extends control { $this->app->loadLang('my'); - $this->view->title = $this->lang->my->scoreRule; + $this->view->title = $this->lang->my->scoreRule; + $this->view->rules = $this->score->buildRules(); $this->display(); } diff --git a/module/score/model.php b/module/score/model.php index e1392099f2..8a7e1e7f81 100644 --- a/module/score/model.php +++ b/module/score/model.php @@ -231,6 +231,60 @@ class scoreModel extends model return $data; } + /** + * Build rules for list. + * + * @access public + * @return array + */ + public function buildRules() + { + $allRules = array(); + foreach($this->config->score->rule as $module => $moduleRule) + { + foreach($moduleRule as $method => $rule) + { + $rules['module'] = $this->lang->score->modules[$module]; + $rules['method'] = $this->lang->score->methods[$module][$method]; + $rules['times'] = empty($rule['times']) ? $this->lang->score->noLimit : $rule['times']; + $rules['hour'] = empty($rule['hour']) ? $this->lang->score->noLimit : $rule['hour']; + $rules['score'] = $rule['score']; + + $desc = ''; + if(isset($this->lang->score->extended[$module][$method])) + { + $desc = $this->lang->score->extended[$module][$method]; + $descRule = explode('##', $desc); + if(!empty($descRule)) + { + foreach($descRule as $key => $value) + { + if($key % 2 == 1) + { + $match = explode(',', $value); + if(count($match) == 2) + { + $score = $this->config->score->ruleExtended[$module][$method][$match[0]][$match[1]]; + } + else + { + $score = $this->config->score->ruleExtended[$module][$method][$match[0]]; + } + $desc = str_replace('##' . $value . '##', $score, $desc); + } + } + } + } + + $rules['desc'] = $desc; + + $allRules[] = $rules; + } + } + + return $allRules; + } + /** * Score reset. * From d654384371e45eaafb454b2f46fc30fcae6e9940 Mon Sep 17 00:00:00 2001 From: daitingting Date: Sat, 10 Jun 2023 01:31:59 +0000 Subject: [PATCH 05/17] * Display different fields in different tab. --- module/my/ui/bug.html.php | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/module/my/ui/bug.html.php b/module/my/ui/bug.html.php index 7c04347c70..007541d5ef 100644 --- a/module/my/ui/bug.html.php +++ b/module/my/ui/bug.html.php @@ -17,10 +17,30 @@ featurebar li(searchToggle()), ); +$canBatchEdit = common::hasPriv('bug', 'batchEdit') && $type == 'assignedTo'; +$canBatchConfirm = common::hasPriv('bug', 'batchConfirm') && $type != 'closedBy'; +$canBatchClose = common::hasPriv('bug', 'batchClose') && strtolower($type) != 'closedby'; +$canBatchAssignTo = common::hasPriv('bug', 'batchAssignTo'); +$canBatchAction = $canBatchEdit || $canBatchConfirm || $canBatchClose || $canBatchAssignTo; + +if($type == 'openedBy') unset($config->my->bug->dtable->fieldList['openedBy']); +if($type == 'assignedTo') unset($config->my->bug->dtable->fieldList['assignedTo']); +if($type == 'resolvedBy') unset($config->my->bug->dtable->fieldList['resolvedBy']); +if($app->rawMethod != 'work') unset($config->my->bug->dtable->fieldList['deadline']); +if(!$canBatchAction) $config->my->bug->dtable->fieldList['id']['type'] = 'id'; + $bugs = initTableData($bugs, $config->my->bug->dtable->fieldList, $this->bug); $cols = array_values($config->my->bug->dtable->fieldList); $bugs = array_values($bugs); +$footToolbar = array('items' => array +( + array('text' => $lang->edit, 'className' => 'batch-btn ' . ($canBatchEdit ? '' : 'hidden'), 'data-url' => helper::createLink('bug', 'batchEdit')), + array('text' => $lang->confirm, 'className' => 'batch-btn ajax-btn ' . ($canBatchConfirm ? '' : 'hidden'), 'data-url' => helper::createLink('bug', 'batchConfirm')), + array('text' => $lang->close, 'className' => 'batch-btn ajax-btn ' . ($canBatchClose ? '' : 'hidden'), 'data-url' => helper::createLink('bug', 'batchClose')), + array('text' => $lang->bug->assignedTo, 'className' => ($canBatchAssignTo ? '' : 'hidden'), 'caret' => 'up', 'url' => '#navAssignedTo','data-toggle' => 'dropdown', 'data-placement' => 'top-start'), +), 'btnProps' => array('size' => 'sm', 'btnType' => 'secondary')); + $assignedToItems = array(); foreach ($memberPairs as $key => $value) { @@ -34,22 +54,14 @@ menu set::items($assignedToItems) ); -$footToolbar = array('items' => array -( - array('text' => $lang->edit, 'className' => 'batch-btn ' . (common::hasPriv('bug', 'batchEdit') ? '' : 'hidden'), 'data-url' => helper::createLink('bug', 'batchEdit')), - array('text' => $lang->confirm, 'className' => 'batch-btn ajax-btn ' . (common::hasPriv('bug', 'batchConfirm') && $type != 'closedBy' ? '' : 'hidden'), 'data-url' => helper::createLink('bug', 'batchConfirm')), - array('text' => $lang->close, 'className' => 'batch-btn ajax-btn ' . (common::hasPriv('bug', 'batchClose') && $type != 'closedBy' ? '' : 'hidden'), 'data-url' => helper::createLink('bug', 'batchClose')), - array('text' => $lang->bug->assignedTo, 'caret' => 'up', 'url' => '#navAssignedTo','data-toggle' => 'dropdown', 'data-placement' => 'top-start'), -), 'btnProps' => array('size' => 'sm', 'btnType' => 'secondary')); - dtable ( set::cols($cols), set::data($bugs), set::userMap($users), set::onRenderCell(jsRaw('window.renderCell')), - set::checkable(true), - set::footToolbar($footToolbar), + set::checkable($canBatchAction ? true : false), + $canBatchAction ? set::footToolbar($footToolbar) : null, set::footPager(usePager()), ); From b903d1a1146056af5d44d79a3a86e2f303f3beb6 Mon Sep 17 00:00:00 2001 From: zenggang Date: Sat, 10 Jun 2023 01:36:40 +0000 Subject: [PATCH 06/17] * Repo import --- module/repo/control.php | 32 ++++++-------- module/repo/css/import.ui.css | 1 + module/repo/js/import.ui.js | 45 ++++++++++++++++++++ module/repo/model.php | 24 +++-------- module/repo/test/model/batchcreate.php | 46 ++++++++++++++++++++ module/repo/test/repo.class.php | 9 ++++ module/repo/ui/import.html.php | 59 ++++++++++++++++++++++++++ module/repo/zen.php | 53 +++++++++++++++++++++++ test/data/pipeline.yaml | 8 ++-- 9 files changed, 234 insertions(+), 43 deletions(-) create mode 100644 module/repo/css/import.ui.css create mode 100644 module/repo/js/import.ui.js create mode 100644 module/repo/test/model/batchcreate.php create mode 100644 module/repo/ui/import.html.php diff --git a/module/repo/control.php b/module/repo/control.php index 9b074ae9e1..7760611843 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -1363,47 +1363,39 @@ class repo extends control } /** + * 导入版本库。 * Import repos. * - * @param int $server + * @param int $server * @access public * @return void */ - public function import($server = 0) + public function import(int $server = 0) { if($this->viewType !== 'json') $this->commonAction(); + if($_POST) { - $this->repo->batchCreate(); + $repos = $this->repoZen->prepareBatchCreate(); + if($repos) $this->repo->batchCreate($repos, (int)$_POST['serviceHost']); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->repo->createLink('maintain'))); } $gitlabList = $this->loadModel('gitlab')->getList(); $gitlab = empty($server) ? array_shift($gitlabList) : $this->gitlab->getById($server); - $repoList = array(); - if(!empty($gitlab)) - { - $repoList = $this->gitlab->apiGetProjects($gitlab->id); - $existRepoList = $this->dao->select('serviceProject,name')->from(TABLE_REPO) - ->where('SCM')->eq(ucfirst($gitlab->type)) - ->andWhere('serviceHost')->eq($gitlab->id) - ->fetchPairs(); - foreach($repoList as $key => $repo) - { - if(isset($existRepoList[$repo->id])) unset($repoList[$key]); - } - } + $repoList = $this->repoZen->getGitlabNotExistRepos($gitlab); $products = $this->loadModel('product')->getPairs('', 0, '', 'all'); $this->view->gitlabPairs = $this->gitlab->getPairs(); - $this->view->products = $products; - $this->view->projects = $this->product->getProjectPairsByProductIDList(array_keys($products)); - $this->view->gitlab = $gitlab; - $this->view->repoList = array_values($repoList); + $this->view->products = $products; + $this->view->projects = $this->product->getProjectPairsByProductIDList(array_keys($products)); + $this->view->gitlab = $gitlab; + $this->view->repoList = array_values($repoList); $this->display(); } diff --git a/module/repo/css/import.ui.css b/module/repo/css/import.ui.css new file mode 100644 index 0000000000..df15df964d --- /dev/null +++ b/module/repo/css/import.ui.css @@ -0,0 +1 @@ +.form-batch-row-actions>button:first-child {display: none;} diff --git a/module/repo/js/import.ui.js b/module/repo/js/import.ui.js new file mode 100644 index 0000000000..ea65652b19 --- /dev/null +++ b/module/repo/js/import.ui.js @@ -0,0 +1,45 @@ +$(function() +{ + checkItem(); + $('.form-batch-row-actions .form-batch-btn').each(function() + { + if($(this).data('type') == 'add') $(this).addClass('hidden'); + }); +}); + +/** + * Check the project. + * + * @access public + * @return void + */ +function checkItem() +{ + if(!$("#repoList tbody tr").length) $("#submit").prop('disabled', true); +} + +/** + * Change server. + * + * @access public + * @return void + */ +function selectServer() +{ + var server = $('#servers').val(); + window.location.href = $.createLink('repo', 'import', 'server=' + server); +} + +function loadProductProjects(event) +{ + const $target = $(event.target); + const $currentRow = $target.closest('tr'); + const products = $target.val(); + const projects = $currentRow.find('.form-batch-input[data-name="projects"]'); + const projectIds = $(projects).val(); + + $.post($.createLink('repo', 'ajaxProjectsOfProducts'), {products : products, projects: projectIds, number : 1}, function(response) + { + $(projects).html(response); + }); +} diff --git a/module/repo/model.php b/module/repo/model.php index 19be38cccb..2919a648e4 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -218,33 +218,19 @@ class repoModel extends model } /** + * 批量创建版本库。 * Batch create repos. * + * @param array $repos * @access public * @return bool */ - public function batchCreate() + public function batchCreate(array $repos, int $serviceHost): bool { - $repos = fixer::input('post')->get(); - - $dataAry = array(); - foreach($repos as $key => $val) - { - if(strpos($key, 'serviceProject') === 0) - { - $i = substr($key, 14); - if(empty($repos->{'product' . $i})) dao::$errors['product' . $i][] = sprintf($this->lang->error->notempty, $this->lang->repo->product); - if(empty($repos->{'name' . $i})) dao::$errors['name' . $i][] = sprintf($this->lang->error->notempty, $this->lang->repo->name); - - if(!empty($repos->{'product' . $i}) and !empty($repos->{'name' . $i})) $dataAry[] = array('serviceProject' => $repos->{'serviceProject' . $i}, 'product' => implode(',', $repos->{'product' . $i}), 'name' => $repos->{'name' . $i}, 'projects' => empty($repos->projects[$i]) ? '' : implode(',', $repos->projects[$i])); - } - } - if(dao::isError()) return false; - - foreach($dataAry as $data) + foreach($repos as $data) { $repo = new stdclass(); - $repo->serviceHost = $repos->serviceHost; + $repo->serviceHost = $serviceHost; $repo->serviceProject = $data['serviceProject']; $repo->product = $data['product']; $repo->name = $data['name']; diff --git a/module/repo/test/model/batchcreate.php b/module/repo/test/model/batchcreate.php new file mode 100644 index 0000000000..7ac36ca399 --- /dev/null +++ b/module/repo/test/model/batchcreate.php @@ -0,0 +1,46 @@ +#!/usr/bin/env php +batchCreate(); +timeout=0 +cid=1 + +- 批量创建一个版本库 + - 第2条的name属性 @imortRepo1 + - 第2条的SCM属性 @Gitlab + +- 批量创建二个版本库 + - 第4条的name属性 @imortRepo3 + - 第4条的SCM属性 @Gitlab + +- 批量创建已存在版本库 @『名称』已经有『imortRepo2』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。 + +- 批量创建已存在仓库 @『仓库』已经有『1599』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。 + +- 批量创建二个版本库,关联多项目 + - 第6条的name属性 @imortRepo5 + - 第6条的projects属性 @5,6,7 + +*/ + +zdTable('pipeline')->gen(5); +zdTable('repo')->gen(1); + +$serviceHosts = array(1); +$repo1 = array('serviceProject' => 1552, 'product' => 1, 'name' => 'imortRepo1', 'projects' => 1); +$repo2 = array('serviceProject' => 1574, 'product' => 2, 'name' => 'imortRepo2', 'projects' => 2); +$repo3 = array('serviceProject' => 1599, 'product' => 3, 'name' => 'imortRepo3', 'projects' => 3); +$repo4 = array('serviceProject' => 1617, 'product' => 4, 'name' => 'imortRepo4', 'projects' => 4); +$repo5 = array('serviceProject' => 1618, 'product' => 5, 'name' => 'imortRepo5', 'projects' => '5,6,7'); + +$repo = new repoTest(); +r($repo->batchCreateTest(array($repo1), $serviceHosts[0])) && p('2:name,SCM') && e('imortRepo1,Gitlab'); //批量创建一个版本库 +r($repo->batchCreateTest(array($repo2, $repo3), $serviceHosts[0])) && p('4:name,SCM') && e('imortRepo3,Gitlab'); //批量创建二个版本库 +r($repo->batchCreateTest(array($repo2), $serviceHosts[0])) && p('name:0') && e('『名称』已经有『imortRepo2』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。'); //批量创建已存在版本库 +r($repo->batchCreateTest(array($repo3), $serviceHosts[0])) && p('serviceProject:0') && e('『仓库』已经有『1599』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。'); //批量创建已存在仓库 +r($repo->batchCreateTest(array($repo4, $repo5), $serviceHosts[0])) && p('6:name:projects', ':') && e('imortRepo5:5,6,7'); //批量创建二个版本库,关联多项目 \ No newline at end of file diff --git a/module/repo/test/repo.class.php b/module/repo/test/repo.class.php index 09749a4785..49d30e43f3 100644 --- a/module/repo/test/repo.class.php +++ b/module/repo/test/repo.class.php @@ -95,6 +95,15 @@ class repoTest return $this->objectModel->getRepoByID($repoID); } + public function batchCreateTest($repos, $serviceHost) + { + $repoID = $this->objectModel->batchCreate($repos, $serviceHost); + + if(dao::isError()) return dao::getError(); + + return $this->objectModel->getList(); + } + public function updateTest($id) { $objects = $this->objectModel->update($id); diff --git a/module/repo/ui/import.html.php b/module/repo/ui/import.html.php new file mode 100644 index 0000000000..5b90eedcc6 --- /dev/null +++ b/module/repo/ui/import.html.php @@ -0,0 +1,59 @@ + + * @package repo + * @link https://www.zentao.net + */ +namespace zin; + +$items = array(); +$items[] = array('name' => 'serviceProject', 'hidden' => true); +$items[] = array('name' => 'name_with_namespace', 'label' => $lang->repo->gitlabList, 'control' => 'static'); +$items[] = array('name' => 'name', 'label' => $lang->repo->importName); +$items[] = array('name' => 'product', 'label' => $lang->repo->product, 'control' => array('type' => 'picker', 'multiple' => true), 'items' => $products); +$items[] = array('name' => 'projects', 'label' => $lang->repo->projects, 'control' => array('type' => 'picker', 'multiple' => true), 'items' => $projects); + +foreach($repoList as $repo) +{ + $repo->serviceProject = $repo->id; +} + +featureBar +( + h::a + ( + setClass('form-title'), + set::href($this->createLink('repo', 'import')), + $lang->repo->importAction, + ), + inputGroup + ( + setClass('ml-3'), + $lang->repo->importServer, + select + ( + on::change('selectServer()'), + set::name('servers'), + set::id('servers'), + set::items($gitlabPairs), + set::value($gitlab->id) + ) + ) +); + +formBatchPanel +( + set::id('repoList'), + set::mode('add'), + set::addRowIcon('false'), + set::items($items), + set::data($repoList), + set::maxRows(count($repoList)), + on::change('[data-name="product"]', 'loadProductProjects'), +); + +render(); diff --git a/module/repo/zen.php b/module/repo/zen.php index f041226864..a1809e13a7 100644 --- a/module/repo/zen.php +++ b/module/repo/zen.php @@ -256,5 +256,58 @@ class repoZen extends repo $this->display(); } + + /** + * 准备批量创建版本库的数据。 + * Prepare batch create repo data. + * + * @access protected + * @return array|false + */ + protected function prepareBatchCreate(): array|false + { + $data = array(); + foreach($_POST as $key => $val) + { + if(strpos($key, 'serviceProject') === 0) + { + $i = substr($key, 14); + if($this->post->{'product' . $i} == '') dao::$errors['product' . $i][] = sprintf($this->lang->error->notempty, $this->lang->repo->product); + if($this->post->{'name' . $i} == '') dao::$errors['name' . $i][] = sprintf($this->lang->error->notempty, $this->lang->repo->name); + if(dao::isError()) continue; + + $data[] = array('serviceProject' => $this->post->{'serviceProject' . $i}, 'product' => implode(',', $this->post->{'product' . $i}), 'name' => $this->post->{'name' . $i}, 'projects' => empty($_POST['projects'][$i]) ? '' : implode(',', $this->post->projects[$i])); + } + } + if(dao::isError()) return false; + + return $data; + } + + /** + * 获取gitlab还没存在禅道的项目列表。 + * Get gitlab not exist repos. + * + * @param object $gitlab + * @access protected + * @return array + */ + protected function getGitlabNotExistRepos(object $gitlab): array + { + $repoList = array(); + if(!empty($gitlab)) + { + $repoList = $this->loadModel('gitlab')->apiGetProjects($gitlab->id); + $existRepoList = $this->dao->select('serviceProject,name')->from(TABLE_REPO) + ->where('SCM')->eq(ucfirst($gitlab->type)) + ->andWhere('serviceHost')->eq($gitlab->id) + ->fetchPairs(); + foreach($repoList as $key => $repo) + { + if(isset($existRepoList[$repo->id])) unset($repoList[$key]); + } + } + return $repoList; + } } diff --git a/test/data/pipeline.yaml b/test/data/pipeline.yaml index 1e69ac16b3..ed7875cb8a 100644 --- a/test/data/pipeline.yaml +++ b/test/data/pipeline.yaml @@ -9,11 +9,11 @@ fields: - field: name range: GitLab服务器,SonarQube服务器,Jenkins服务器,Gitea服务器,Gogs服务器 - field: url - range: [http://10.0.7.242:9980],[http://10.0.7.242:9990],[http://10.0.7.242:9580],[http://10.0.7.242:9020],[http://10.0.7.242:9021] + range: "[http://10.0.7.242:9980],[http://10.0.7.242:9990],[http://10.0.7.242:9580],[http://10.0.7.242:9020],[http://10.0.7.242:9021]" - field: account - range: [],[admin]{2},[]{2} + range: "[],[admin]{2},[]{2}" - field: password - range: [],[U2h3N0NldHlsc1ozYkVTVjBreXM=],[TThFbEJqcVZsNmJXcTdNSmJZN3U=],[]{2} + range: "[],[U2h3N0NldHlsc1ozYkVTVjBreXM=],[TThFbEJqcVZsNmJXcTdNSmJZN3U=],[]{2}" - field: token range: x88fZokrp5hShia2jyBN,YWRtaW46U2h3N0NldHlsc1ozYkVTVjBreXM=,1196c85ba525a268570df9da627e3a7b2d,c6769e6761a7d719129b2421dcb3112d936e2b1f,9ff43f9d1a369465bcf0781a3785f46bcef782d1 - field: private @@ -21,6 +21,6 @@ fields: - field: createdBy range: admin - field: createdDate - range: [2022-08-01 09:09:37] + range: "[2022-08-01 09:09:37]" - field: deleted range: 0 From b42bb63cf2fd236f93ead402d8b47047787e6827 Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Sat, 10 Jun 2023 09:45:38 +0800 Subject: [PATCH 07/17] + Add default col setting. --- module/datatable/config.php | 70 +++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/module/datatable/config.php b/module/datatable/config.php index 3909fefff3..21a146d44c 100644 --- a/module/datatable/config.php +++ b/module/datatable/config.php @@ -8,3 +8,73 @@ $config->datatable->moduleAlias['project-bug'] = 'bug'; $config->datatable->moduleAlias['execution-bug'] = 'bug'; $config->datatable->noProductModule = ',review,'; + +$config->datatable->defaultColConfig['id']['width'] = 60; +$config->datatable->defaultColConfig['id']['fixed'] = 'left'; +$config->datatable->defaultColConfig['id']['required'] = true; + +$config->datatable->defaultColConfig['checkID']['width'] = 80; +$config->datatable->defaultColConfig['checkID']['fixed'] = 'left'; +$config->datatable->defaultColConfig['checkID']['required'] = true; + +$config->datatable->defaultColConfig['title']['width'] = 0.44; +$config->datatable->defaultColConfig['title']['fixed'] = 'left'; +$config->datatable->defaultColConfig['title']['required'] = true; + +$config->datatable->defaultColConfig['shortTitle']['width'] = 0.2; +$config->datatable->defaultColConfig['shortTitle']['fixed'] = 'left'; +$config->datatable->defaultColConfig['shortTitle']['required'] = true; + +$config->datatable->defaultColConfig['nestedTitle']['width'] = 0.5; +$config->datatable->defaultColConfig['nestedTitle']['fixed'] = 'left'; +$config->datatable->defaultColConfig['nestedTitle']['required'] = true; + +$config->datatable->defaultColConfig['shortNestedTitle']['width'] = 0.33; +$config->datatable->defaultColConfig['shortNestedTitle']['fixed'] = 'left'; +$config->datatable->defaultColConfig['shortNestedTitle']['required'] = true; + +$config->datatable->defaultColConfig['actions']['minWidth'] = 120; +$config->datatable->defaultColConfig['actions']['fixed'] = 'right'; +$config->datatable->defaultColConfig['actions']['required'] = true; + +$config->datatable->defaultColConfig['pri']['width'] = 68; + +$config->datatable->defaultColConfig['icon']['width'] = 52; + +$config->datatable->defaultColConfig['time']['width'] = 64; + +$config->datatable->defaultColConfig['burn']['width'] = 88; + +$config->datatable->defaultColConfig['date']['width'] = 96; + +$config->datatable->defaultColConfig['user']['width'] = 80; + +$config->datatable->defaultColConfig['text']['width'] = 136; + +$config->datatable->defaultColConfig['desc']['width'] = 160; + +$config->datatable->defaultColConfig['count']['width'] = 92; + +$config->datatable->defaultColConfig['money']['width'] = 96; + +$config->datatable->defaultColConfig['avatar']['width'] = 44; + +$config->datatable->defaultColConfig['number']['width'] = 64; + +$config->datatable->defaultColConfig['status']['width'] = 80; + +$config->datatable->defaultColConfig['percent']['width'] = 64; + +$config->datatable->defaultColConfig['assign']['width'] = 108; + +$config->datatable->defaultColConfig['progress']['width'] = 64; + +$config->datatable->defaultColConfig['category']['width'] = 80; + +$config->datatable->defaultColConfig['severity']['width'] = 92; + +$config->datatable->defaultColConfig['datetime']['width'] = 128; + +$config->datatable->defaultColConfig['avatarBtn']['width'] = 108; + +$config->datatable->defaultColConfig['avatarName']['width'] = 108; From 707665bb6e4f77a59df7bc3cfb644adcddd7590b Mon Sep 17 00:00:00 2001 From: dingguodong Date: Sat, 10 Jun 2023 09:22:59 +0800 Subject: [PATCH 08/17] * Add comment for story type. --- module/product/zen.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/product/zen.php b/module/product/zen.php index e95369efbe..ac6693d2bf 100644 --- a/module/product/zen.php +++ b/module/product/zen.php @@ -963,7 +963,7 @@ class productZen extends product * @param string $branchID * @param string $moduleID * @param int $param - * @param string $storyType + * @param string $storyType requirement|story * @param string $browseType * @param string $orderBy * @param object $pager From 2ea5d9558f712984c5acfd50105d042aef2fb300 Mon Sep 17 00:00:00 2001 From: dingguodong Date: Sat, 10 Jun 2023 09:54:48 +0800 Subject: [PATCH 09/17] * Reformat comments. --- module/product/model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/product/model.php b/module/product/model.php index af8cfa1363..957e59f24c 100755 --- a/module/product/model.php +++ b/module/product/model.php @@ -1609,8 +1609,8 @@ class productModel extends model * Set menu. * * @param int $productID - * @param string|int $branch all|''|int - * @param string $extra + * @param string|int $branch all|''|int + * @param string $extra requirement|story * @access public * @return void */ From 22594051fde8001dfbcbedb092f97320af17cd97 Mon Sep 17 00:00:00 2001 From: dingguodong Date: Sat, 10 Jun 2023 09:55:28 +0800 Subject: [PATCH 10/17] * Change access type in comment. --- module/product/zen.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/product/zen.php b/module/product/zen.php index ac6693d2bf..905966e425 100644 --- a/module/product/zen.php +++ b/module/product/zen.php @@ -1061,7 +1061,7 @@ class productZen extends product * @param string $storyType * @param string $browseType * @param bool $isProjectStory - * @access private + * @access protected * @return void */ protected function saveSession4Browse(object $product, string $storyType, string $browseType, bool $isProjectStory): void From 2a9ff784264519543588c94f98c92a8bab3d4005 Mon Sep 17 00:00:00 2001 From: dingguodong Date: Sat, 10 Jun 2023 09:56:04 +0800 Subject: [PATCH 11/17] * Remove extra characters. --- module/product/zen.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/product/zen.php b/module/product/zen.php index 905966e425..8eadecaa54 100644 --- a/module/product/zen.php +++ b/module/product/zen.php @@ -792,7 +792,7 @@ class productZen extends product return; } - $this->product->setMenu($productID, $branch, "storyType=$storyType"); + $this->product->setMenu($productID, $branch, $storyType); } /** From de4a677605dc0c5ab1aa0f1bfd388e42659077bb Mon Sep 17 00:00:00 2001 From: caoyanyi Date: Sat, 10 Jun 2023 10:01:30 +0800 Subject: [PATCH 12/17] * Compatible object array format. --- lib/zin/wg/dtable/v1.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/zin/wg/dtable/v1.php b/lib/zin/wg/dtable/v1.php index d4952e235c..0c0202e5a4 100644 --- a/lib/zin/wg/dtable/v1.php +++ b/lib/zin/wg/dtable/v1.php @@ -28,11 +28,13 @@ class dtable extends wg $module = $this->prop('module', $app->rawModule); if(!isset($app->lang->$module)) $app->loadLang($module); + /* Set col default name and title. */ $colConfigs = $this->prop('cols'); foreach($colConfigs as $field => &$config) { - if(!isset($config['name'])) $config['name'] = $field; + if(is_object($config)) $config = (array)$config; + if(!isset($config['name'])) $config['name'] = $field; if(!isset($config['title'])) $config['title'] = zget($app->lang->{$module}, $config['name'], zget($app->lang, $config['name'])); } $this->setProp('cols', array_values($colConfigs)); From bf80df98b9ad87c81e639a70baf9ee316802e63a Mon Sep 17 00:00:00 2001 From: wangyuting Date: Sat, 10 Jun 2023 10:19:52 +0800 Subject: [PATCH 13/17] * Finish my testcase page. the task id #94602. --- module/my/config/table.php | 32 ++++++++++++++++++++++++++++ module/my/control.php | 4 +++- module/my/js/testcase.ui.js | 19 +++++++++++++++++ module/my/model.php | 2 +- module/my/ui/testcase.html.php | 39 ++++++++++++++++++++++++++++++++++ module/testcase/model.php | 4 +++- 6 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 module/my/js/testcase.ui.js create mode 100644 module/my/ui/testcase.html.php diff --git a/module/my/config/table.php b/module/my/config/table.php index 2b10349bac..7897609e61 100644 --- a/module/my/config/table.php +++ b/module/my/config/table.php @@ -6,7 +6,9 @@ $app->loadLang('task'); $app->loadLang('story'); $app->loadLang('doc'); $app->loadLang('testtask'); +$app->loadLang('testcase'); $app->loadModuleConfig('testtask'); +$app->loadModuleConfig('testcase'); $config->my->todo = new stdclass(); $config->my->todo->actionList = array(); @@ -492,6 +494,36 @@ $config->my->testtask->dtable->fieldList['actions']['sortType'] = false; $config->my->testtask->dtable->fieldList['actions']['list'] = $config->testtask->actionList; $config->my->testtask->dtable->fieldList['actions']['menu'] = array('cases', 'linkCase', 'report', 'view', 'edit', 'delete'); +$config->my->testcase = new stdclass(); +$config->my->testcase->dtable = new stdclass(); +$config->my->testcase->dtable->fieldList['id']['name'] = 'id'; +$config->my->testcase->dtable->fieldList['id']['title'] = $lang->idAB; +$config->my->testcase->dtable->fieldList['id']['type'] = 'checkID'; +$config->my->testcase->dtable->fieldList['id']['fixed'] = 'left'; + +$config->my->testcase->dtable->fieldList['title']['name'] = 'title'; +$config->my->testcase->dtable->fieldList['title']['title'] = $lang->testcase->title; +$config->my->testcase->dtable->fieldList['title']['type'] = 'title'; +$config->my->testcase->dtable->fieldList['title']['link'] = helper::createLink('testcase', 'view', 'testcaseID={id}&version={version}'); +$config->my->testcase->dtable->fieldList['title']['fixed'] = 'left'; + +$config->my->testcase->dtable->fieldList['pri'] = $config->testcase->dtable->fieldList['pri']; +$config->my->testcase->dtable->fieldList['type'] = $config->testcase->dtable->fieldList['type']; +$config->my->testcase->dtable->fieldList['status'] = $config->testcase->dtable->fieldList['status']; + +$config->my->testcase->dtable->fieldList['testtask']['name'] = 'taskName'; +$config->my->testcase->dtable->fieldList['testtask']['title'] = $lang->testtask->common; +$config->my->testcase->dtable->fieldList['testtask']['type'] = 'text'; +$config->my->testcase->dtable->fieldList['testtask']['group'] = 'testtask'; + +$config->my->testcase->dtable->fieldList['openedBy'] = $config->testcase->dtable->fieldList['openedBy']; +$config->my->testcase->dtable->fieldList['lastRunner'] = $config->testcase->dtable->fieldList['lastRunner']; +$config->my->testcase->dtable->fieldList['lastRunDate'] = $config->testcase->dtable->fieldList['lastRunDate']; +$config->my->testcase->dtable->fieldList['lastRunResult'] = $config->testcase->dtable->fieldList['lastRunResult']; +$config->my->testcase->dtable->fieldList['actions'] = $config->testcase->dtable->fieldList['actions']; + +$config->my->testcase->dtable->fieldList['actions']['menu'] = array('runCase', 'runResult', 'edit', 'createBug', 'create'); + $config->my->audit->dtable = new stdclass(); $config->my->audit->dtable->fieldList['id']['name'] = 'id'; $config->my->audit->dtable->fieldList['id']['title'] = $lang->idAB; diff --git a/module/my/control.php b/module/my/control.php index fc4fb187fe..26fc744db2 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -86,6 +86,8 @@ class my extends control */ public function work($mode = 'task', $type = 'assignedTo', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) { + if($mode == 'testcase' && $type == 'assignedTo') $type = 'assigntome'; + $this->lang->my->featureBar[$this->app->rawMethod] = $this->lang->my->featureBar[$this->app->rawMethod][$mode]; echo $this->fetch('my', $mode, "type=$type¶m=$param&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID"); //$this->showWorkCount($recTotal, $recPerPage, $pageID); @@ -697,7 +699,7 @@ EOF; /* Build the search form. */ $currentMethod = $this->app->rawMethod; $actionURL = $this->createLink('my', $currentMethod, "mode=testcase&type=bysearch¶m=myQueryID&orderBy={$orderBy}&recTotal={$recTotal}&recPerPage={$recPerPage}&pageID={$pageID}"); - $this->my->buildTestcaseSearchForm($queryID, $actionURL, $currentMethod); + $this->my->buildTestCaseSearchForm($queryID, $actionURL, $currentMethod); /* Assign. */ $this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->myTestCase; diff --git a/module/my/js/testcase.ui.js b/module/my/js/testcase.ui.js new file mode 100644 index 0000000000..4feb7af164 --- /dev/null +++ b/module/my/js/testcase.ui.js @@ -0,0 +1,19 @@ +$(document).on('click', '.batch-btn', function() +{ + const dtable = zui.DTable.query($(this).target); + const checkedList = dtable.$.getChecks(); + if(!checkedList.length) return; + + const url = $(this).data('url'); + const form = new FormData(); + checkedList.forEach((id) => form.append('caseIdList[]', id)); + + if($(this).hasClass('ajax-btn')) + { + $.ajaxSubmit({url, data: form}); + } + else + { + postAndLoadPage(url, form); + } +}); diff --git a/module/my/model.php b/module/my/model.php index 68651c8aba..9fed6f7521 100644 --- a/module/my/model.php +++ b/module/my/model.php @@ -419,7 +419,7 @@ class myModel extends model $scene = $this->loadModel('testcase')->getSceneMenu(0, 0); $queryName = $type == 'contribute' ? 'contributeTestcase' : 'workTestcase'; - $this->app->loadConfig('testcase'); + $this->app->loadModuleConfig('testcase'); $this->config->testcase->search['module'] = $queryName; $this->config->testcase->search['queryID'] = $queryID; $this->config->testcase->search['actionURL'] = $actionURL; diff --git a/module/my/ui/testcase.html.php b/module/my/ui/testcase.html.php new file mode 100644 index 0000000000..3349a84c34 --- /dev/null +++ b/module/my/ui/testcase.html.php @@ -0,0 +1,39 @@ + + * @package my + * @link https://www.zentao.net + */ +namespace zin; + +featureBar +( + set::current($type), + set::linkParams("mode=testcase&type={key}¶m={$param}"), + li(searchToggle()) +); + +$footToolbar = array('items' => array +( + array('text' => $lang->edit, 'className' => 'batch-btn ' . (common::hasPriv('testcase', 'batchEdit') ? '' : 'hidden'), 'data-url' => helper::createLink('testcase', 'batchEdit', 'productID=0&branch=all&type=case&tab=my')) +), 'btnProps' => array('size' => 'sm', 'btnType' => 'secondary')); + +$cases = initTableData($cases, $config->my->testcase->dtable->fieldList, $this->testcase); +$cols = array_values($config->my->testcase->dtable->fieldList); +$data = array_values($cases); +dtable +( + set::cols($cols), + set::data($data), + set::userMap($users), + set::fixedLeftWidth('44%'), + set::checkable(true), + set::footToolbar($footToolbar), + set::footPager(usePager()), +); + +render(); diff --git a/module/testcase/model.php b/module/testcase/model.php index 728d3c22ef..0d407ccdce 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -657,7 +657,9 @@ class testcaseModel extends model ->andWhere('t3.status')->ne('done') ->beginIF(strpos($auto, 'skip') === false and $auto != 'unit')->andWhere('t2.auto')->ne('unit')->fi() ->beginIF($auto == 'unit')->andWhere('t2.auto')->eq('unit')->fi() - ->orderBy($orderBy)->page($pager)->fetchAll(strpos($auto, 'run') !== false? 'run' : 'id'); + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(strpos($auto, 'run') !== false? 'run' : 'id'); } /** From 3ac1a66b511d7c3521116a5083aaf493bf6aa367 Mon Sep 17 00:00:00 2001 From: wangyuting Date: Sat, 10 Jun 2023 10:40:27 +0800 Subject: [PATCH 14/17] * Add my contribute testcase page. the task is #94603. --- module/my/control.php | 2 +- module/my/ui/testcase.html.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/module/my/control.php b/module/my/control.php index 26fc744db2..c421fd4981 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -250,7 +250,7 @@ EOF; { if(($mode == 'issue' || $mode == 'risk') && $type == 'openedBy') $type = 'createdBy'; if($mode == 'testtask' && $type == 'openedBy') $type = 'done'; - if($mode == 'doc' && $type == 'openedBy') $type = 'openedbyme'; + if(($mode == 'doc' || $mode == 'testcase') && $type == 'openedBy') $type = 'openedbyme'; $this->lang->my->featureBar[$this->app->rawMethod] = $this->lang->my->featureBar[$this->app->rawMethod][$mode]; echo $this->fetch('my', $mode, "type=$type¶m=$param&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID"); diff --git a/module/my/ui/testcase.html.php b/module/my/ui/testcase.html.php index 3349a84c34..394ae94205 100644 --- a/module/my/ui/testcase.html.php +++ b/module/my/ui/testcase.html.php @@ -22,6 +22,12 @@ $footToolbar = array('items' => array array('text' => $lang->edit, 'className' => 'batch-btn ' . (common::hasPriv('testcase', 'batchEdit') ? '' : 'hidden'), 'data-url' => helper::createLink('testcase', 'batchEdit', 'productID=0&branch=all&type=case&tab=my')) ), 'btnProps' => array('size' => 'sm', 'btnType' => 'secondary')); +if($type == 'openedbyme') +{ + unset($config->my->testcase->dtable->fieldList['testtask']); + unset($config->my->testcase->dtable->fieldList['openedBy']); +} + $cases = initTableData($cases, $config->my->testcase->dtable->fieldList, $this->testcase); $cols = array_values($config->my->testcase->dtable->fieldList); $data = array_values($cases); From 844a6666b16025870be762617c432c70adce9a07 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Sat, 10 Jun 2023 10:41:32 +0800 Subject: [PATCH 15/17] * Add datatable config for produtplan-browse page. --- module/productplan/config/table.php | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 module/productplan/config/table.php diff --git a/module/productplan/config/table.php b/module/productplan/config/table.php new file mode 100644 index 0000000000..23b59014d9 --- /dev/null +++ b/module/productplan/config/table.php @@ -0,0 +1,59 @@ +productplan->dtable = new stdclass(); +$config->productplan->dtable->defaultField = array('id', 'title', 'branch', 'begin', 'end', 'stories', 'bugs', 'storyPoint', 'execution', 'desc', 'actions'); + +$config->productplan->dtable->fieldList['id']['name'] = 'id'; +$config->productplan->dtable->fieldList['id']['title'] = $lang->idAB; +$config->productplan->dtable->fieldList['id']['type'] = 'checkID'; +$config->productplan->dtable->fieldList['id']['align'] = 'left'; +$config->productplan->dtable->fieldList['id']['fixed'] = 'left'; +$config->productplan->dtable->fieldList['id']['group'] = '1'; + +$config->productplan->dtable->fieldList['title']['name'] = 'title'; +$config->productplan->dtable->fieldList['title']['title'] = $lang->productplan->title; +$config->productplan->dtable->fieldList['title']['type'] = 'title'; +$config->productplan->dtable->fieldList['title']['minWidth'] = '200'; +$config->productplan->dtable->fieldList['title']['fixed'] = 'left'; +$config->productplan->dtable->fieldList['title']['link'] = helper::createLink('productplan', 'view', "productID={id}"); +$config->productplan->dtable->fieldList['title']['group'] = 'left'; + +$config->productplan->dtable->fieldList['branch']['name'] = 'branch'; +$config->productplan->dtable->fieldList['branch']['title'] = $lang->productplan->branch; +$config->productplan->dtable->fieldList['branch']['type'] = 'branch'; +$config->productplan->dtable->fieldList['branch']['group'] = '2'; + +$config->productplan->dtable->fieldList['begin']['name'] = 'begin'; +$config->productplan->dtable->fieldList['begin']['title'] = $lang->productplan->begin; +$config->productplan->dtable->fieldList['begin']['type'] = 'date'; +$config->productplan->dtable->fieldList['begin']['group'] = '3'; + +$config->productplan->dtable->fieldList['end']['name'] = 'end'; +$config->productplan->dtable->fieldList['end']['title'] = $lang->productplan->end; +$config->productplan->dtable->fieldList['end']['type'] = 'date'; +$config->productplan->dtable->fieldList['end']['group'] = '3'; + +$config->productplan->dtable->fieldList['stories']['name'] = 'stories'; +$config->productplan->dtable->fieldList['stories']['title'] = $lang->productplan->stories; +$config->productplan->dtable->fieldList['stories']['type'] = 'text'; +$config->productplan->dtable->fieldList['stories']['group'] = '4'; + +$config->productplan->dtable->fieldList['bugs']['name'] = 'bugs'; +$config->productplan->dtable->fieldList['bugs']['title'] = $lang->productplan->bugs; +$config->productplan->dtable->fieldList['bugs']['type'] = 'text'; +$config->productplan->dtable->fieldList['bugs']['group'] = '4'; + +$config->productplan->dtable->fieldList['storyPoint']['name'] = 'storyPoint'; +$config->productplan->dtable->fieldList['storyPoint']['title'] = $lang->productplan->storyPoint; +$config->productplan->dtable->fieldList['storyPoint']['width'] = 120; +$config->productplan->dtable->fieldList['storyPoint']['group'] = '4'; + +$config->productplan->dtable->fieldList['execution']['name'] = 'execution'; +$config->productplan->dtable->fieldList['execution']['title'] = $lang->productplan->execution; +$config->productplan->dtable->fieldList['execution']['type'] = 'text'; +$config->productplan->dtable->fieldList['execution']['group'] = '5'; + +$config->productplan->dtable->fieldList['desc']['name'] = 'desc'; +$config->productplan->dtable->fieldList['desc']['title'] = $lang->productplan->desc; +$config->productplan->dtable->fieldList['desc']['type'] = 'text'; +$config->productplan->dtable->fieldList['desc']['group'] = '6'; From 413e927dc083c1ba5c3ed08299dabeb31b77914c Mon Sep 17 00:00:00 2001 From: zhouxin Date: Sat, 10 Jun 2023 10:43:53 +0800 Subject: [PATCH 16/17] * Add datatable to productplan-browse page. --- module/productplan/ui/browse.html.php | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 module/productplan/ui/browse.html.php diff --git a/module/productplan/ui/browse.html.php b/module/productplan/ui/browse.html.php new file mode 100644 index 0000000000..54f07cc789 --- /dev/null +++ b/module/productplan/ui/browse.html.php @@ -0,0 +1,49 @@ + + * @package productplan + * @link https://www.zentao.net + */ +namespace zin; + +featureBar +( + set::current($browseType), + set::linkParams("product=$productID&branch=$branch&browseType={key}"), + li(searchToggle()) +); + +$config->productplan->dtable->fieldList['branch']['map'] = $branches; + +$cols = array_values($config->productplan->dtable->fieldList); +$data = array_values($plans); + +$footToolbar = array('items' => array +( + array('text' => $lang->edit, 'btnType' => 'secondary', 'data-url' => createLink('productplan', 'batchEdit', "productID={$product->id}&branch=$branch")), + array('caret' => 'up', 'text' => $lang->productplan->status, 'btnType' => 'secondary', 'url' => '#navAssignedTo','data-toggle' => 'dropdown', 'data-placement' => 'top-start'), +)); + +dtable +( + set::userMap($users), + set::customCols(true), + set::cols($cols), + set::data($data), + set::checkable(true), + set::footToolbar($footToolbar), + set::footPager + ( + usePager(), + set::page($pager->pageID), + set::recPerPage($pager->recPerPage), + set::recTotal($pager->recTotal), + set::linkCreator(helper::createLink('productplan', 'browse', "productID={$productID}&branch={$branch}&browseType={$browseType}&queryID={$queryID}&orderBy=$orderBy&recTotal={$pager->recTotal}&recPerPage={recPerPage}&page={page}")) + ), +); + +render(); From 60176665a840a8be3adeca8ead62c22074bd937f Mon Sep 17 00:00:00 2001 From: zhouxin Date: Sat, 10 Jun 2023 10:50:03 +0800 Subject: [PATCH 17/17] * Add action config to productplan-browse page. --- module/productplan/config/table.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/module/productplan/config/table.php b/module/productplan/config/table.php index 23b59014d9..05c8582aa0 100644 --- a/module/productplan/config/table.php +++ b/module/productplan/config/table.php @@ -57,3 +57,12 @@ $config->productplan->dtable->fieldList['desc']['name'] = 'desc'; $config->productplan->dtable->fieldList['desc']['title'] = $lang->productplan->desc; $config->productplan->dtable->fieldList['desc']['type'] = 'text'; $config->productplan->dtable->fieldList['desc']['group'] = '6'; + +$config->productplan->dtable->fieldList['actions']['name'] = 'actions'; +$config->productplan->dtable->fieldList['actions']['title'] = $lang->actions; +$config->productplan->dtable->fieldList['actions']['type'] = 'actions'; +$config->productplan->dtable->fieldList['actions']['width'] = '140'; +$config->productplan->dtable->fieldList['actions']['sortType'] = false; +$config->productplan->dtable->fieldList['actions']['fixed'] = 'right'; +$config->productplan->dtable->fieldList['actions']['list'] = $config->productplan->actionList; +$config->productplan->dtable->fieldList['actions']['menu'] = array('start', 'createExecution', 'linkStory', 'linkBug', 'edit', 'more');