From d47e5a06f7e4d9e590b0cfadd622c40fd46391a2 Mon Sep 17 00:00:00 2001 From: Yagami Date: Thu, 9 Feb 2023 14:10:27 +0800 Subject: [PATCH] * Code for execution dtable. --- module/execution/config.php | 45 ++++----- module/execution/js/all.js | 144 +++++++++++++++++++++++++++++ module/execution/model.php | 78 ++++++++++++++++ module/execution/view/all.html.php | 133 ++++++++++++++++++-------- 4 files changed, 334 insertions(+), 66 deletions(-) create mode 100644 module/execution/js/all.js diff --git a/module/execution/config.php b/module/execution/config.php index 51e1f94d58..049167340c 100644 --- a/module/execution/config.php +++ b/module/execution/config.php @@ -184,94 +184,89 @@ else $config->execution->datatable->defaultField = array('id', 'name', 'project', 'PM', 'status', 'progress', 'begin', 'end', 'estimate', 'consumed', 'left', 'burn'); } - $config->execution->datatable->fieldList['id']['title'] = 'idAB'; $config->execution->datatable->fieldList['id']['fixed'] = 'left'; $config->execution->datatable->fieldList['id']['width'] = '70'; $config->execution->datatable->fieldList['id']['required'] = 'yes'; +$config->execution->datatable->fieldList['id']['sortType'] = true; -$config->execution->datatable->fieldList['name']['title'] = 'execName'; -$config->execution->datatable->fieldList['name']['fixed'] = 'left'; -$config->execution->datatable->fieldList['name']['width'] = 'auto'; -$config->execution->datatable->fieldList['name']['required'] = 'yes'; - - -$config->execution->datatable->fieldList['project']['title'] = 'project'; -$config->execution->datatable->fieldList['project']['fixed'] = 'no'; -$config->execution->datatable->fieldList['project']['width'] = '128'; -$config->execution->datatable->fieldList['project']['required'] = 'no'; +$config->execution->datatable->fieldList['name']['name'] = 'name'; +$config->execution->datatable->fieldList['name']['title'] = $lang->execution->name; +$config->execution->datatable->fieldList['name']['width'] = 356; +$config->execution->datatable->fieldList['name']['type'] = 'html'; +$config->execution->datatable->fieldList['name']['flex'] = 1; +$config->execution->datatable->fieldList['name']['fixed'] = 'left'; +$config->execution->datatable->fieldList['name']['nestedToggle'] = true; +$config->execution->datatable->fieldList['name']['checkbox'] = true; +$config->execution->datatable->fieldList['name']['iconRender'] = true; +$config->execution->datatable->fieldList['name']['sortType'] = true; +$config->execution->datatable->fieldList['name']['required'] = 'yes'; if(!isset($config->setCode) or $config->setCode == 1) { $config->execution->datatable->fieldList['code']['title'] = 'execCode'; - $config->execution->datatable->fieldList['code']['fixed'] = 'no'; - $config->execution->datatable->fieldList['code']['width'] = '95'; + $config->execution->datatable->fieldList['code']['width'] = '120'; + $config->execution->datatable->fieldList['code']['fixed'] = 'left'; $config->execution->datatable->fieldList['code']['required'] = 'no'; } +$config->execution->datatable->fieldList['project']['title'] = 'project'; +$config->execution->datatable->fieldList['project']['width'] = '200'; +$config->execution->datatable->fieldList['project']['required'] = 'no'; + $config->execution->datatable->fieldList['status']['title'] = 'execStatus'; -$config->execution->datatable->fieldList['status']['fixed'] = 'no'; +$config->execution->datatable->fieldList['status']['type'] = 'status'; $config->execution->datatable->fieldList['status']['width'] = '100'; $config->execution->datatable->fieldList['status']['required'] = 'no'; $config->execution->datatable->fieldList['PM']['title'] = 'owner'; -$config->execution->datatable->fieldList['PM']['fixed'] = 'no'; $config->execution->datatable->fieldList['PM']['width'] = '70'; $config->execution->datatable->fieldList['PM']['required'] = 'no'; $config->execution->datatable->fieldList['openedDate']['title'] = 'openedDate'; -$config->execution->datatable->fieldList['openedDate']['fixed'] = 'no'; $config->execution->datatable->fieldList['openedDate']['width'] = '85'; $config->execution->datatable->fieldList['openedDate']['required'] = 'no'; $config->execution->datatable->fieldList['begin']['title'] = 'begin'; -$config->execution->datatable->fieldList['begin']['fixed'] = 'no'; $config->execution->datatable->fieldList['begin']['width'] = '100'; $config->execution->datatable->fieldList['begin']['required'] = 'no'; $config->execution->datatable->fieldList['end']['title'] = 'end'; -$config->execution->datatable->fieldList['end']['fixed'] = 'no'; $config->execution->datatable->fieldList['end']['width'] = '90'; $config->execution->datatable->fieldList['end']['required'] = 'no'; $config->execution->datatable->fieldList['realBegan']['title'] = 'realBegan'; -$config->execution->datatable->fieldList['realBegan']['fixed'] = 'no'; $config->execution->datatable->fieldList['realBegan']['width'] = '90'; $config->execution->datatable->fieldList['realBegan']['required'] = 'no'; $config->execution->datatable->fieldList['realBegan']['sort'] = 'no'; $config->execution->datatable->fieldList['realEnd']['title'] = 'realEnd'; -$config->execution->datatable->fieldList['realEnd']['fixed'] = 'no'; $config->execution->datatable->fieldList['realEnd']['width'] = '90'; $config->execution->datatable->fieldList['realEnd']['required'] = 'no'; $config->execution->datatable->fieldList['realEnd']['sort'] = 'no'; $config->execution->datatable->fieldList['estimate']['title'] = 'estimate'; -$config->execution->datatable->fieldList['estimate']['fixed'] = 'no'; $config->execution->datatable->fieldList['estimate']['width'] = '70'; $config->execution->datatable->fieldList['estimate']['required'] = 'no'; $config->execution->datatable->fieldList['estimate']['sort'] = 'no'; $config->execution->datatable->fieldList['consumed']['title'] = 'consumed'; -$config->execution->datatable->fieldList['consumed']['fixed'] = 'no'; $config->execution->datatable->fieldList['consumed']['width'] = '75'; $config->execution->datatable->fieldList['consumed']['required'] = 'no'; $config->execution->datatable->fieldList['consumed']['sort'] = 'no'; $config->execution->datatable->fieldList['left']['title'] = 'left'; -$config->execution->datatable->fieldList['left']['fixed'] = 'no'; $config->execution->datatable->fieldList['left']['width'] = '70'; $config->execution->datatable->fieldList['left']['required'] = 'no'; $config->execution->datatable->fieldList['left']['sort'] = 'no'; $config->execution->datatable->fieldList['progress']['title'] = 'progress'; -$config->execution->datatable->fieldList['progress']['fixed'] = 'no'; +$config->execution->datatable->fieldList['progress']['type'] = 'circleProgress'; $config->execution->datatable->fieldList['progress']['width'] = '70'; $config->execution->datatable->fieldList['progress']['required'] = 'no'; $config->execution->datatable->fieldList['progress']['sort'] = 'no'; $config->execution->datatable->fieldList['burn']['title'] = 'burn'; -$config->execution->datatable->fieldList['burn']['fixed'] = 'no'; $config->execution->datatable->fieldList['burn']['width'] = '80'; $config->execution->datatable->fieldList['burn']['required'] = 'no'; $config->execution->datatable->fieldList['burn']['sort'] = 'no'; diff --git a/module/execution/js/all.js b/module/execution/js/all.js new file mode 100644 index 0000000000..6c61bd28d5 --- /dev/null +++ b/module/execution/js/all.js @@ -0,0 +1,144 @@ +$(function() +{ + $("#" + status + "Tab").addClass('btn-active-text'); + $(document).on('click', '.plan-toggle', function(e) + { + var id = $(this).data('id'); + var $toggle = $(this); + var isCollapsed = $toggle.toggleClass('collapsed').hasClass('collapsed'); + $toggle.closest('#executionsForm').find('tr.parent-' + id).toggle(!isCollapsed); + + e.stopPropagation(); + e.preventDefault(); + }); + + if($('#executionList thead th.c-name').width() < 260) $('#executionList thead th.c-name').width(260); + + $('#executionTableList').on('sort.sortable', function(e, data) + { + var list = ''; + for(i = 0; i < data.list.length; i++) list += $(data.list[i].item).attr('data-id') + ','; + $.post(createLink('execution', 'updateOrder'), {'executions' : list, 'orderBy' : orderBy}); + }); + + toggleFold('#executionsForm', unfoldExecutions, 0, 'execution'); + + $('.table td.has-child > .plan-toggle').each(function() + { + var fold = $(this).hasClass('collapsed'); + var parentID = $(this).closest('tr').attr('data-id'); + if(fold) + { + $('.parent-' + parentID).hide(); + $(this).closest('td').removeClass('parent'); + } + else + { + $('.parent-' + parentID).show(); + $(this).closest('td').addClass('parent'); + } + }); + + /* Expand and fold substages. */ + $('.table td.has-child > .plan-toggle').click(function() + { + var parentID = $(this).closest('tr').attr('data-id'); + $('.parent-' + parentID).toggle(); + + if($('.parent-' + parentID).css('display') == 'none') + { + $(this).closest('td').removeClass('parent'); + } + else + { + $(this).closest('td').addClass('parent'); + } + }); + + $(document).on('click', "#toggleFold", function() + { + var fold = $(this).hasClass('collapsed'); + if(fold) + { + $('.has-child.c-name.flex').removeClass('parent'); + $('.table td.has-child > .plan-toggle').addClass('collapsed'); + } + else + { + $('.has-child.c-name.flex').addClass('parent'); + $('.table td.has-child > .plan-toggle').removeClass('collapsed'); + } + }); + + /* Update table summary text. */ + $('#executionsForm').table( + { + statisticCreator: function(table) + { + var $table = table.getTable(); + var $checkedRows = $table.find(table.isDataTable ? '.datatable-row-left.checked' : 'tbody>tr.checked'); + var $originTable = table.isDataTable ? table.$.find('.datatable-origin') : null; + var checkedTotal = $checkedRows.length; + var $rows = checkedTotal ? $checkedRows : $table.find(table.isDataTable ? '.datatable-rows .datatable-row-left' : 'tbody>tr'); + + var checkedWait = 0; + var checkedDoing = 0; + var executionIDList = []; + $rows.each(function() + { + var $row = $(this); + if($originTable) $row = $originTable.find('tbody>tr[data-id="' + $row.data('id') + '"]'); + + var data = $row.data(); + executionIDList.push(data.id); + + if(data.status === 'wait') checkedWait++; + if(data.status === 'doing') checkedDoing++; + }); + + if(status != 'all') return (checkedTotal ? checkedExecutions : executionSummary).replace('%s', $rows.length); + return (checkedTotal ? checkedSummary : pageSummary).replace('%total%', $rows.length).replace('%wait%', checkedWait).replace('%doing%', checkedDoing); + } + }) + + $('input[name^="showEdit"]').click(function() + { + $.cookie('showExecutionBatchEdit', $(this).is(':checked') ? 1 : 0, {expires: config.cookieLife, path: config.webRoot}); + setCheckbox(); + }); + setCheckbox(); + + $('#executionTableList tr').on('click', function(e) + { + if($.cookie('showExecutionBatchEdit') != 1) e.stopPropagation(); + }); +}); + +/** + * Location to product list. + * + * @param int productID + * @param int projectID + * @param string status + * @access public + * @return void + */ +function byProduct(productID, projectID, status) +{ + location.href = createLink('project', 'all', "status=" + status + "&project=" + projectID + "&orderBy=" + orderBy + '&productID=' + productID); +} + +/** + * Set batch edit checkbox. + * + * @access public + * @return void + */ +function setCheckbox() +{ + $('#executionsForm .checkbox-primary').hide(); + $('.check-all, .sortable tr').removeClass('checked'); + $(":checkbox[name^='executionIDList']").prop('checked', false); + $('#executionsForm').removeClass('has-row-checked'); + if($.cookie('showExecutionBatchEdit') == 1) $('#executionsForm .checkbox-primary').show(); +} diff --git a/module/execution/model.php b/module/execution/model.php index 56930ddc25..07577d865e 100755 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -5158,6 +5158,84 @@ class executionModel extends model } } + public function generateCol() + { + $this->loadModel('datatable'); + + $setting = ''; + if(isset($this->config->datatable->executionAll->cols)) $setting = json_decode($this->config->datatable->executionAll->cols); + + $fieldList = $this->config->execution->datatable->fieldList; + + foreach($fieldList as $field => $items) + { + $title = zget($this->lang->execution, $items['title'], zget($this->lang, $items['title'], $items['title'])); + $fieldList[$field]['title'] = $title; + } + + if(empty($setting)) + { + $setting = $this->config->execution->datatable->defaultField; + $order = 1; + foreach($setting as $key => $value) + { + $id = $value; + $set = new stdclass();; + $set->order = $order++; + $set->show = true; + $set->name = $value; + $set->title = $fieldList[$id]['title']; + + if(isset($fieldList[$id]['checkbox'])) $set->nestedToggle = $fieldList[$id]['checkbox']; + if(isset($fieldList[$id]['nestedToggle'])) $set->nestedToggle = $fieldList[$id]['nestedToggle']; + if(isset($fieldList[$id]['fixed'])) $set->fixed = $fieldList[$id]['fixed']; + if(isset($fieldList[$id]['width'])) $set->width = $fieldList[$id]['width']; + if(isset($fieldList[$id]['type'])) $set->type = $fieldList[$id]['type']; + if(isset($fieldList[$id]['sortType'])) $set->sortType = $fieldList[$id]['sortType']; + if(isset($fieldList[$id]['flex'])) $set->flex = $fieldList[$id]['flex']; + if(isset($fieldList[$id]['minWidth'])) $set->minWidth = $fieldList[$id]['minWidth']; + if(isset($fieldList[$id]['maxWidth'])) $set->maxWidth = $fieldList[$id]['maxWidth']; + if(isset($fieldList[$id]['pri'])) $set->pri = $fieldList[$id]['pri']; + + $setting[$key] = $set; + } + } + else + { + foreach($setting as $key => $set) + { + if($set->id == 'actions') $set->width = $fieldList[$set->id]['width']; + $set->title = $fieldList[$set->id]['title']; + if(isset($fieldList[$id]['sortType'])) $set->sortType = $fieldList[$id]['sortType']; + } + } + + usort($setting, array('datatableModel', 'sortCols')); + + return $setting; + } + + public function generateRow($executions, $users, $productID) + { + $canBatchEdit = common::hasPriv('execution', 'batchEdit'); + + foreach($executions as $id => $execution) + { + $label = $execution->type == 'stage' ? 'label-warning' : 'label-info'; + $link = $execution->type == 'kanban' ? helper::createLink('execution', 'kanban', "id=$execution->id") : helper::createLink('execution', 'task', "id=$execution->id"); + $execution->name = "{$this->lang->execution->typeList[$execution->type]} " . html::a($link, $execution->name); + $execution->project = $execution->projectName; + $execution->status = zget($this->lang->execution->statusList, $execution->status); + $execution->PM = zget($users, $execution->PM); + $execution->progress = $execution->hours->progress; + $execution->estimate = $execution->hours->totalEstimate; + $execution->consumed = $execution->hours->totalConsumed; + $execution->left = $execution->hours->totalLeft; + } + + return $executions; + } + /* * Build search form * diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 0a9c3d2c2a..1f4800def6 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -1,47 +1,98 @@ - - datatable->getSetting('execution'); - $widths = $this->datatable->setFixedFieldWidth($setting); +js::import($jsRoot . 'dtable/min.js'); +css::import($jsRoot . 'dtable/min.css'); + +$cols = $this->execution->generateCol(); +$executions = $this->execution->generateRow($executionStats, $users, $productID); + +js::set('cols', json_encode($cols)); +js::set('data', json_encode($executions)); + +js::set('orderBy', $orderBy); +js::set('status', $status); +js::set('unfoldExecutions', array()); +js::set('from', $from); + +/* Replace Iteration to Execution. */ +js::set('checkedSummary', str_replace($lang->executionCommon, $lang->execution->common, $lang->execution->checkedExecSummary)); +js::set('pageSummary', str_replace($lang->executionCommon, $lang->execution->common, $lang->execution->pageExecSummary)); +js::set('executionSummary', str_replace($lang->executionCommon, $lang->execution->common, $lang->execution->executionSummary)); +js::set('checkedExecutions', str_replace($lang->executionCommon, $lang->execution->common, $lang->execution->checkedExecutions)); +/* Set unfold parent executionID. */ +js::set('unfoldAll', $lang->execution->treeLevel['all']); +js::set('foldAll', $lang->execution->treeLevel['root']); +js::set('isCNLang', !$this->loadModel('common')->checkNotCN()) ?> -
- +
+
+ +
+

+ execution->noExecutions : $lang->execution->noExecution;?> + + + createLink('execution', 'create'), " " . ($from == 'execution' ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-info' data-app='execution'");?> + + +

+
+ +
'> +
+ +
+ + +