| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- <?php
- /**
- * The view view file of todo module of ZenTaoPMS.
- * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
- * @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
- * @author Mengyi Liu <liumengyi@easycorp.ltd>
- * @package todo
- * @link https://www.zentao.net
- */
- namespace zin;
- jsVar('selectProduct', $lang->todo->selectProduct);
- jsVar('selectExecution', $lang->execution->selectExecution);
- jsVar('todoID', $todo->id);
- jsVar('vision', $config->vision);
- $isInModal = isAjaxRequest('modal');
- /* Generate title suffix for bug,task,story type. */
- $fnGenerateTitleSuffix = function() use($todo)
- {
- if($todo->type == 'bug') return btn(set::url(createLink('bug', 'view', "id={$todo->objectID}")), set::text(' BUG#' . $todo->objectID), setClass('ghost'));
- if($todo->type == 'task') return btn(set::url(createLink('task', 'view', "id={$todo->objectID}")), set::text(' TASK#' . $todo->objectID), setClass('ghost'));
- if($todo->type == 'story') return btn(set::url(createLink('story', 'view', "id={$todo->objectID}")), set::text(' STORY#' . $todo->objectID), setClass('ghost'));
- };
- /* Render modal for creating story. */
- if(hasPriv('story', 'create') && $config->vision != 'lite')
- {
- modal
- (
- setID('productModal'),
- set::modalProps(array('title' => $lang->product->select)),
- empty($products) ? div
- (
- setClass('text-center pb-8 mt-2'),
- span($lang->product->noProduct),
- btn
- (
- setID('createProductBtn'),
- setClass('secondary-pale'),
- set::icon('plus'),
- set::url($this->createLink('product', 'create')),
- setData(array('toggle' => 'modal', 'size' => 'lg')),
- $lang->product->create
- )
- ) : form
- (
- setClass('mt-2'),
- set::actions(array()),
- formGroup
- (
- inputGroup
- (
- picker
- (
- set::name('product'),
- set::items($products),
- set::required(true)
- ),
- btn
- (
- setID('toStoryButton'),
- setClass('primary'),
- $lang->todo->reasonList['story'],
- on::click('toStory')
- )
- )
- )
- )
- );
- }
- if(hasPriv('story', 'create') && $config->vision == 'lite')
- {
- modal
- (
- setID('projectModal'),
- set::modalProps(array('title' => $lang->project->select)),
- form
- (
- setClass('mt-2'),
- set::actions(array()),
- formGroup
- (
- inputGroup
- (
- picker
- (
- set::name('projectToStory'),
- set::items($projects),
- set::required(true)
- ),
- btn
- (
- setID('toStoryButton'),
- setClass('primary'),
- $lang->todo->reasonList['story'],
- on::click('toStory')
- )
- )
- )
- )
- );
- }
- /* Render modal for creating task. */
- if(hasPriv('task', 'create'))
- {
- modal
- (
- setID('executionModal'),
- set::modalProps(array('title' => $lang->execution->selectExecution)),
- to::footer
- (
- div
- (
- setClass('toolbar gap-4 w-full justify-center'),
- btn($lang->todo->reasonList['task'], setID('toTaskButton'), setClass('primary')),
- on::click('toTask')
- )
- ),
- form
- (
- setClass('mt-2'),
- set::actions(array()),
- formGroup
- (
- set::label($lang->todo->project),
- picker
- (
- on::change('getExecutionByProject'),
- set::name('project'),
- set::items($projects),
- set::required(true)
- )
- ),
- formGroup
- (
- set::label($lang->todo->execution),
- picker
- (
- set::name('execution'),
- set::items($executions),
- set::required(true)
- )
- )
- )
- );
- }
- /* Render modal for creating bug. */
- if(hasPriv('bug', 'create'))
- {
- modal
- (
- setID('projectProductModal'),
- set::modalProps(array('title' => $lang->product->select)),
- to::footer
- (
- div
- (
- setClass('toolbar gap-4 w-full justify-center'),
- btn($lang->todo->reasonList['bug'], setID('toBugButton'), setClass('primary')),
- on::click('toBug')
- )
- ),
- form
- (
- setClass('mt-2'),
- set::actions(array()),
- formGroup
- (
- set::label($lang->todo->project),
- picker
- (
- set::name('bugProject'),
- set::items($projects),
- set::required(true),
- on::change('getProductByProject')
- )
- ),
- formGroup
- (
- set::label($lang->todo->product),
- picker
- (
- set::name('bugProduct'),
- set::items($projectProducts),
- set::required(true)
- )
- )
- )
- );
- }
- /* Generate goback url. */
- $fnGenerateGoBackUrl = function() use ($app, $todo, $user)
- {
- if($this->session->todoList)
- {
- $browseLink = empty($todo->deleted) ? $this->session->todoList : $this->createLink('action', 'trash');
- }
- elseif($todo->account == $app->user->account)
- {
- $browseLink = $this->createLink('my', 'todo');
- }
- else
- {
- $browseLink = $this->createLink('user', 'todo', "userID=$user->id");
- }
- return $browseLink;
- };
- /* Generate action buttons and related menus within float toolbar. */
- $fnGenerateFloatToolbarBtns = function() use ($lang, $config, $todo, $projects, $isInModal, $fnGenerateGoBackUrl)
- {
- /* Deleted item without action buttons. */
- if($todo->deleted) return array();
- /* Verify privilege of current account. */
- if(!$this->app->user->admin && $this->app->user->account != $todo->account && $this->app->user->account != $todo->assignedTo) return array();
- /* Prepare variables for verifying. */
- $status = $todo->status;
- $canStart = hasPriv('todo', 'start');
- $canActivate = hasPriv('todo', 'activate');
- $canClose = hasPriv('todo', 'close');
- $canEdit = hasPriv('todo', 'edit');
- $canDelete = hasPriv('todo', 'delete');
- $actionList = array('prefix' => array(), 'main' => array(), 'suffix' => array());
- !$isInModal && $actionList['prefix'][] = array('icon' => 'back', 'url' => $fnGenerateGoBackUrl(), 'hint' => $lang->goback . $lang->backShortcutKey, 'text' => $lang->goback);
- /* Common action buttons. */
- $canStart && $status == 'wait' ? $actionList['main'][] = array('icon' => 'play', 'url' => createLink('todo', 'start', "todoID={$todo->id}"), 'text' => $lang->todo->abbr->start, 'class' => 'ajax-submit') : null;
- $canActivate && ($status == 'done' || $status == 'closed') ? $actionList['main'][] = array('icon' => 'magic', 'url' => createLink('todo', 'activate', "todoID={$todo->id}"), 'text' => $lang->activate, 'class' => 'ajax-submit') : null;
- $canClose && $status == 'done' ? $actionList['main'][] = array('icon' => 'off', 'url' => createLink('todo', 'close', "todoID={$todo->id}"), 'text' => $lang->close) : null;
- $canEdit ? $actionList['main'][] = array('icon' => 'edit', 'url' => createLink('todo', 'edit', "todoID={$todo->id}"), 'data-load' => $isInModal ? 'modal' : null, 'text' => $lang->edit) : null;
- $canDelete ? $actionList['main'][] = array('icon' => 'trash', 'url' => createLink('todo', 'delete', "todoID={$todo->id}&confirm=yes"), 'text' => $lang->delete, 'class' => 'ajax-submit', 'data-confirm' => $lang->todo->confirmDelete) : null;
- /* The status is 'done' or 'closed' without more action buttons. */
- if($status == 'done' || $status == 'closed') return $actionList;
- $actionList['main'][] = array('icon' => 'checked', 'url' => createLink('todo', 'finish', "todoID={$todo->id}"), 'text' => $lang->todo->abbr->finish, 'class' => 'ajax-submit');
- $canCreateStory = hasPriv('story', 'create');
- $canCreateTask = hasPriv('task', 'create');
- $canCreateBug = hasPriv('bug', 'create') && $config->vision != 'lite';
- $printBtn = $config->vision == 'lite' && empty($projects) ? false : true;
- /* Render more button. */
- if($printBtn && ($canCreateStory || $canCreateTask || $canCreateBug))
- {
- $actionList['suffix'][] = array('url' => '#navActions', 'text' => $lang->todo->transform, 'data-toggle' => 'dropdown', 'data-placement' => 'top-end', 'caret' => 'up');
- }
- /* Popup menu of more button. */
- $storyTarget = $canCreateStory && $config->vision == 'lite' ? '#projectModal' : '#productModal';
- $suffixItems = array();
- if($canCreateStory) $suffixItems[] = array('text' => $lang->todo->reasonList['story'], 'id' => 'toStoryLink', 'data-url' => '###', 'data-toggle' => 'modal', 'data-target' => $storyTarget, 'data-backdrop' => false, 'data-moveable' => true, 'data-position' => 'center', 'data-size' => 'sm');
- if($canCreateTask) $suffixItems[] = array('text' => $lang->todo->reasonList['task'], 'id' => 'toTaskLink', 'data-url' => '###', 'data-toggle' => 'modal', 'data-target' => '#executionModal', 'data-backdrop' => false, 'data-moveable' => true, 'data-position' => 'center', 'data-size' => 'sm');
- if($canCreateBug) $suffixItems[] = array('text' => $lang->todo->reasonList['bug'], 'id' => 'toBugLink', 'data-url' => '###', 'data-toggle' => 'modal', 'data-target' => '#projectProductModal', 'data-backdrop' => false, 'data-moveable' => true, 'data-position' => 'center', 'data-size' => 'sm');
- menu
- (
- setID('navActions'),
- setClass('menu dropdown-menu'),
- set::items($suffixItems)
- );
- return $actionList;
- };
- $actionList = $fnGenerateFloatToolbarBtns();
- /* Generate from data and item. */
- $fnGenerateFrom = function() use ($app, $lang, $config, $todo)
- {
- if(!in_array($todo->type, array('story', 'task', 'bug')) || empty($todo->object)) return array(null, null);
- /* Generate from data. */
- $app->loadLang($todo->type);
- $objectData = array();
- foreach($config->todo->related[$todo->type]['title'] as $index => $relatedTitle)
- {
- $content = zget($todo->object, $config->todo->related[$todo->type]['content'][$index], '');
- $objectData[] = item
- (
- set::title($lang->{$todo->type}->{$relatedTitle}),
- empty($content) ? $lang->noData : html($content)
- );
- }
- $fromItemData = section
- (
- set::title(zget($lang->todo->fromList, $todo->type)),
- sectionCard
- (
- entityLabel
- (
- set::entityID($todo->objectID),
- set::text($todo->name)
- ),
- $objectData
- )
- );
- /* Generate from item. */
- $fromItem = item
- (
- set::name(zget($lang->todo->fromList, $todo->type)),
- a
- (
- set::href(createLink($todo->type, 'view', "id={$todo->objectID}", '', false)),
- setData
- (
- array
- (
- 'toggle' => 'modal',
- 'data-type' => 'html',
- 'type' => 'ajax'
- )
- ),
- $todo->name
- )
- );
- return array($fromItem, $fromItemData);
- };
- list($fromItem, $fromItemData) = $fnGenerateFrom();
- /* Generate cycle configuration information. */
- $todo->config = json_decode($todo->config);
- $fnGenerateCycleCfg = function() use ($lang, $todo)
- {
- $cfg = '';
- if($todo->config->type == 'day')
- {
- if(isset($todo->config->day)) $cfg .= $lang->todo->every . $todo->config->day . $lang->day;
- if(isset($todo->config->specifiedDate))
- {
- $specifiedNotes = $lang->todo->specify;
- if(isset($todo->config->cycleYear)) $specifiedNotes .= $lang->todo->everyYear;
- $specifiedNotes .= zget($lang->datepicker->monthNames, $todo->config->specify->month) . $todo->config->specify->day . $lang->todo->day;
- $cfg .= $specifiedNotes;
- }
- }
- elseif($todo->config->type == 'week')
- {
- foreach(explode(',', $todo->config->week) as $week) $cfg .= $lang->todo->dayNames[$week] . ' ';
- }
- elseif($todo->config->type == 'month')
- {
- foreach(explode(',', $todo->config->month) as $month) $cfg .= $month . ' ';
- }
- $cfg .= '<br />';
- if($todo->config->beforeDays) $cfg .= sprintf($lang->todo->lblBeforeDays, $todo->config->beforeDays);
- return $cfg;
- };
- /* ZIN: layout. */
- detailHeader
- (
- $isInModal ? to::prefix('') : '',
- to::title
- (
- entityLabel
- (
- set::entityID($todo->id),
- set::level(1),
- set::text($todo->name)
- ),
- $todo->deleted ? span(setClass('label danger circle'), $lang->todo->deleted) : null
- )
- );
- detailBody
- (
- sectionList
- (
- section
- (
- set::title($lang->todo->desc),
- set::content(nl2br($todo->desc)),
- set::useHtml(true),
- to::actions($fnGenerateTitleSuffix())
- ),
- $fromItemData,
- history(),
- /* Render float toolbar. */
- $actionList ? center(floatToolbar(set($actionList))) : null
- ),
- detailSide
- (
- /* Basic information. */
- tabs(set::collapse(true), tabPane
- (
- set::key('legendBasic'),
- set::title($lang->todo->legendBasic),
- set::active(true),
- tableData
- (
- item(set::name($lang->todo->pri), priLabel($todo->pri, set::text($lang->todo->priList))),
- item(set::name($lang->todo->status), zget($lang->todo->statusList, $todo->status)),
- item(set::name($lang->todo->type), zget($lang->todo->typeList, $todo->type)),
- $fromItem,
- item(set::name($lang->todo->account), zget($users, $todo->account)),
- item(set::name($lang->todo->date), formatTime($todo->date, DT_DATE1)),
- item(set::name($lang->todo->beginAndEnd), isset($times[$todo->begin]) ? $times[$todo->begin] : '', isset($times[$todo->end]) ? ' ~ ' . $times[$todo->end] : ''),
- !isset($todo->assignedTo) ? null : item(set::name($lang->todo->assignedTo), zget($users, $todo->assignedTo)),
- !isset($todo->assignedTo) ? null : item(set::name($lang->todo->assignedBy), zget($users, $todo->assignedBy)),
- !isset($todo->assignedTo) ? null : item(set::name($lang->todo->assignedDate), formatTime($todo->assignedDate, DT_DATE1))
- )
- )),
- /* Cycle information. */
- $todo->cycle ? tabs(set::collapse(true), tabPane
- (
- set::key('cycle'),
- set::title($lang->todo->cycle),
- set::active(true),
- tableData
- (
- item(set::name($lang->todo->beginAndEnd), $todo->config->begin . " ~ " . zget($todo->config, 'end', '')),
- item(set::name($lang->todo->cycleConfig), html($fnGenerateCycleCfg()))
- )
- )) : null
- )
- );
- render();
|