* @package product * @link https://www.zentao.net */ namespace zin; include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php'); /* Flag variable for hiding product code. */ $hiddenCode = (!isset($config->setCode) || $config->setCode == 0 || empty($product->code)); $allStoryCount = array_sum($product->stories); $isEn = $app->getClientLang() == 'en'; $storiesClass = $isEn ? 'px-2' : 'w-1/3'; $membersDom = array(); foreach($config->product->memberFields as $field) { if(empty($product->$field)) continue; if(!isset($members[$product->$field])) continue; $user = $members[$product->$field]; $membersDom[] = div ( setClass('w-1/6 center-y'), avatar ( setClass('primary-outline'), set::size('36'), set::text($user->realname), set::src($user->avatar) ), span(setClass('my-2'), $user->realname), span(setClass('text-gray'), $lang->product->$field) ); } div ( setClass('flex w-full'), cell ( setClass('mr-3 w-2/3'), div ( setClass('flex-auto canvas flex p-4'), div ( setClass('text-center w-1/3 flex flex-col justify-center items-center'), div ( set('class', 'chart pie-chart'), echarts ( set::color(array('#2B80FF', '#E3E4E9')), set::width(120), set::height(120), set::series ( array(array('type' => 'pie', 'radius' => array('80%', '90%'), 'itemStyle' => array('borderRadius' => '40'), 'label' => array('show' => false), 'data' => array($product->storyDeliveryRate, 100 - $product->storyDeliveryRate))) ) ), div ( set::className('pie-chart-title text-center'), div(span(set::className('text-2xl font-bold'), $product->storyDeliveryRate . '%')), div ( span ( setClass('text-sm text-gray'), $lang->product->storyDeliveryRate, icon ( 'help ml-1', toggle::tooltip(array('title' => $lang->product->storyDeliveryRateTip)), set('data-placement', 'right'), set('data-type', 'white'), set('data-class-name', 'text-gray border border-light'), setClass('text-gray ') ) ) ) ) ), div ( setClass('border flex justify-center items-center pl-4 py-2' . ($isEn ? '' : ' w-3/4')), div ( setClass($storiesClass), div ( setClass('text-lg font-bold'), $allStoryCount ), $lang->product->totalStories ), div ( setClass($storiesClass), div ( setClass('text-lg font-bold'), $product->stories['closed'] ), $lang->story->statusList['closed'] ), div ( setClass($storiesClass), div ( setClass('text-lg font-bold'), $allStoryCount - $product->stories['closed'] ), $lang->story->unclosed ) ) ), div ( setClass('flex-none w-2/3'), div ( setClass('flex items-center'), label ( setClass('rounded-full'), $product->id ), div ( setClass('text-md font-bold ml-2 clip'), $product->name ), !$hiddenCode ? label ( setClass('gray-300-outline ml-2 flex-none'), $product->code ) : null, $product->type != 'normal' ? label ( setClass('gray-300-outline ml-2 text-warning flex-none'), $lang->product->typeList[$product->type] ) : null, $product->deleted ? label ( setClass('danger-outline text-dange flex-noner ml-2'), $lang->product->deleted ) : null, label ( setClass("ml-2 flex-none"), setClass($product->status == 'normal' ? 'text-success' : 'text-gray'), $this->processStatus('product', $product) ), div ( setClass('ml-2 flex-none row items-center gap-2'), $lang->product->abbr->aclList[$product->acl], icon ( 'help', toggle::tooltip(array('title' => $lang->product->aclList[$product->acl])), set('data-placement', 'right'), set('data-type', 'white'), set('data-class-name', 'text-gray border border-light'), setClass('text-gray') ) ), div(setClass('ai-menu-box flex-auto')) ), div ( setClass('flex mt-4'), in_array($this->config->systemMode, array('ALM', 'PLM')) && helper::hasFeature('program') && $product->program ? div ( setClass('clip w-1/3'), set::title($lang->product->program), icon('program', setClass('pr-1')), $product->programName ) : null, $product->line ? div ( setClass('clip w-1/3'), set::title($lang->product->line), icon('lane', setClass('pr-1')), $product->lineName ) : null, $config->edition != 'open' && $product->workflowGroup ? div ( setClass('clip w-1/3'), set::title($lang->product->workflowGroup), icon('flow', setClass('pr-1')), zget($workflowGroups, $product->workflowGroup) ) : null ), div ( set::className('detail-content mt-4 overflow-hidden desc-box'), set::title(strip_tags($product->desc)), html($product->desc) ) ) ), div ( setClass('mt-4 p-4 bg-white'), panel ( setClass('mb-4 memberBox'), set::title($lang->product->manager), div(setClass('flex flex-wrap member-list pt-2'), $membersDom) ), panel ( setClass('otherInfoBox'), set::title($lang->product->otherInfo), div ( setClass('flex flex-wrap'), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->plans), span(setClass('ml-2'), $product->plans) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->releases), span(setClass('ml-2'), $product->releases) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->bugs), span(setClass('ml-2'), $product->bugs) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->projects), span(setClass('ml-2'), $product->projects) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->builds), span(setClass('ml-2'), $product->builds) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->docs), span(setClass('ml-2'), $product->docs) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->cases), span(setClass('ml-2'), $product->cases) ), div ( setClass('w-1/4 item mb-3'), span(setClass('text-gray'), $lang->product->executions), span(setClass('ml-2'), $product->executions) ) ) ), html($this->printExtendFields($product, 'html', "position=info", false)) ) ), cell ( setClass('w-1/3'), panel ( to::heading ( div(set('class', 'panel-title'), $lang->execution->latestDynamic) ), to::headingActions ( common::hasPriv('product', 'dynamic') ? btn ( setClass('ghost text-gray font-normal'), set::url(createLink('product', 'dynamic', "productID={$product->id}&type=all")), $lang->more ) : null ), set::bodyClass('h-80 overflow-y-auto pt-0'), set::shadow(false), dynamic() ), html($this->printExtendFields($product, 'html', "position=basic", false)), div ( setClass('mt-4'), history ( set::commentUrl(createLink('action', 'comment', array('objectType' => 'product', 'objectID' => $product->id))), set::bodyClass('maxh-72 overflow-y-auto') ) ) ) ); $actionMenuList = !$product->deleted ? $this->loadModel('common')->buildOperateMenu($product) : array(); div ( setClass('w-2/3 center fixed actions-menu'), setClass($product->deleted ? 'no-divider' : ''), floatToolbar ( isAjaxRequest('modal') ? null : to::prefix(backBtn(set::icon('back'), $lang->goback)), !empty($actionMenuList['mainActions']) ? set::main($actionMenuList['mainActions']) : null, !empty($actionMenuList['suffixActions']) ? set::suffix($actionMenuList['suffixActions']) : null, set::object($product) ) );