* fix ai prompts and stuff.
This commit is contained in:
@@ -193,9 +193,8 @@ $config->ai->menuPrint = new stdclass();
|
||||
$config->ai->menuPrint->locations = array();
|
||||
$config->ai->menuPrint->locations['story']['view'] = (object)array(
|
||||
'module' => 'story',
|
||||
'targetContainer' => '#mainContent .main-col .cell:first-of-type .detail:first-of-type .detail-title',
|
||||
'class' => 'pull-right',
|
||||
'stylesheet' => '#mainContent .cell:first-of-type .detail:first-of-type .detail-title>button {margin-left: 10px;} #mainContent .cell:first-of-type .detail:first-of-type .detail-content {margin-top: 12px;}'
|
||||
'targetContainer' => '#mainContent .detail-body .section:first-of-type > div:first-of-type',
|
||||
'stylesheet' => '#mainContent .detail-body .section:first-of-type > div:first-of-type {width: 100%; justify-content: space-between;}'
|
||||
);
|
||||
$config->ai->menuPrint->locations['task']['view'] = clone $config->ai->menuPrint->locations['story']['view'];
|
||||
$config->ai->menuPrint->locations['task']['view']->module = 'task';
|
||||
@@ -206,7 +205,7 @@ $config->ai->menuPrint->locations['bug']['view']->module = 'bug';
|
||||
$config->ai->menuPrint->locations['projectstory']['view'] = clone $config->ai->menuPrint->locations['story']['view'];
|
||||
$config->ai->menuPrint->locations['execution']['storyView'] = $config->ai->menuPrint->locations['story']['view'];
|
||||
|
||||
$config->ai->menuPrint->locations['execution']['view'] = (object)array(
|
||||
$config->ai->menuPrint->locations['execution']['view'] = (object)array( // TODO: fix this.
|
||||
'module' => 'execution',
|
||||
'injectMethod' => 'prepend',
|
||||
'targetContainer' => '#mainContent.main-row > .col-4.side-col .detail:first-child > .detail-title',
|
||||
@@ -218,7 +217,7 @@ $config->ai->menuPrint->locations['project']['view']->module = 'project';
|
||||
$config->ai->menuPrint->locations['project']['view'] = clone $config->ai->menuPrint->locations['execution']['view'];
|
||||
$config->ai->menuPrint->locations['project']['view']->module = 'project';
|
||||
|
||||
$config->ai->menuPrint->locations['product']['view'] = (object)array(
|
||||
$config->ai->menuPrint->locations['product']['view'] = (object)array( // TODO: fix this.
|
||||
'module' => 'product',
|
||||
'injectMethod' => 'append',
|
||||
'targetContainer' => '#mainContent.main-row > .col-8.main-col .detail:first-child > .detail-title',
|
||||
@@ -227,7 +226,8 @@ $config->ai->menuPrint->locations['product']['view'] = (object)array(
|
||||
|
||||
$config->ai->menuPrint->locations['productplan']['view'] = (object)array(
|
||||
'module' => 'productplan',
|
||||
'targetContainer' => '#mainMenu>.btn-toolbar.pull-right',
|
||||
'injectMethod' => 'prepend',
|
||||
'targetContainer' => '#mainContent .toolbar',
|
||||
'objectVarName' => 'plan'
|
||||
);
|
||||
$config->ai->menuPrint->locations['projectplan']['view'] = $config->ai->menuPrint->locations['productplan']['view'];
|
||||
@@ -239,11 +239,10 @@ $config->ai->menuPrint->locations['projectrelease']['view']->objectVarName = nul
|
||||
|
||||
$config->ai->menuPrint->locations['doc']['view'] = (object)array(
|
||||
'module' => 'doc',
|
||||
'injectMethod' => 'prepend',
|
||||
'targetContainer' => '#mainMenu>.btn-toolbar.pull-right',
|
||||
'targetContainer' => '#docPanel > .panel-heading > .panel-actions > .toolbar',
|
||||
);
|
||||
|
||||
$config->ai->injectAuditButton = new stdclass();
|
||||
$config->ai->injectAuditButton = new stdclass(); // TODO: fix this.
|
||||
$config->ai->injectAuditButton->locations = array();
|
||||
$config->ai->injectAuditButton->locations['task']['edit'] = array(
|
||||
'toolbar' => (object)array(
|
||||
|
||||
@@ -789,8 +789,9 @@ class ai extends control
|
||||
|
||||
if($prompt->status == 'draft') $_SESSION['auditPrompt']['time'] = time();
|
||||
|
||||
$promptViewLink = $this->inlink('promptview', "promptID=$promptId");
|
||||
echo js::start() . "const currentApp = parent.$.apps.getLastApp().code; parent.$.apps.open('$location'); if(currentApp == 'admin') {location.href = '$promptViewLink';} else if(currentApp != parent.$.apps.getLastApp().code) {parent.$.apps.close(currentApp);}" . js::end();
|
||||
$this->view->formLocation = $location;
|
||||
$this->view->promptViewLink = $this->inlink('promptview', "promptID=$promptId");
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-1
@@ -2019,7 +2019,8 @@ class aiModel extends model
|
||||
$schema = $this->getFunctionCallSchema($prompt->targetForm);
|
||||
if(empty($schema)) return -5;
|
||||
|
||||
$response = $this->{$this->config->ai->models[$this->modelConfig->type] == 'ernie' ? 'converseTwiceForJSON' : 'converseForJSON'}($prompt->model , array((object)array('role' => 'user', 'content' => $wholePrompt)), $schema);
|
||||
$this->useLanguageModel($prompt->model);
|
||||
$response = $this->{$this->config->ai->models[$this->modelConfig->type] == 'ernie' ? 'converseTwiceForJSON' : 'converseForJSON'}($prompt->model, array((object)array('role' => 'user', 'content' => $wholePrompt)), $schema);
|
||||
if(empty($response)) return -6;
|
||||
|
||||
return current($response);
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* The ai input inject ui view file of ai module of ZenTaoPMS.
|
||||
*
|
||||
* This view file is used to inject ai generated result into
|
||||
* input fields. Include this view file in the target forms.
|
||||
*
|
||||
* @copyright Copyright 2009-2024 禅道软件(青岛)有限公司(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 Wenrui LI <liwenrui@easycorp.ltd>
|
||||
* @package ai
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
$inputInject = function()
|
||||
{
|
||||
$this->app->loadConfig('ai');
|
||||
$this->app->loadLang('ai');
|
||||
$module = $this->app->getModuleName();
|
||||
$method = $this->app->getMethodName();
|
||||
if(!isset($this->config->ai->availableForms[$module]) || !in_array($method, $this->config->ai->availableForms[$module])) return;
|
||||
|
||||
if(isset($_SESSION['aiInjectData']) && isset($_SESSION['aiInjectData'][$module]) && isset($_SESSION['aiInjectData'][$module][$method])) $injectData = $_SESSION['aiInjectData'][$module][$method];
|
||||
if(empty($injectData)) return;
|
||||
|
||||
jsVar('window.injectData', $injectData);
|
||||
unset($_SESSION['aiInjectData'][$module]);
|
||||
|
||||
$this->app->loadLang('ai');
|
||||
|
||||
js(<<< JAVASCRIPT
|
||||
window.injectToInputElement = (inputName, data, index) =>
|
||||
{
|
||||
if(typeof index !== 'undefined') inputName = inputName + '[' + index + ']';
|
||||
|
||||
const inputEl = $('[name="' + inputName + '"]');
|
||||
if(!inputEl.length) return;
|
||||
|
||||
const inputType = inputEl.prop('nodeName');
|
||||
switch(inputType) // Contains case fallthroughs, on purpose.
|
||||
{
|
||||
case 'TEXTAREA':
|
||||
/* Textareas might be controlled by KindEditors. */
|
||||
if(typeof KindEditor !== 'undefined' && KindEditor.instances.length)
|
||||
{
|
||||
const editorInstance = KindEditor.instances.find(e => e.srcElement.attr('name') == inputName);
|
||||
if(editorInstance)
|
||||
{
|
||||
if(data === null) data = '';
|
||||
|
||||
/* Set editor content and sync with textarea. */
|
||||
editorInstance.html(data);
|
||||
editorInstance.sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
/* For normal inputs, just set the value is enough. */
|
||||
inputEl.val(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
window.inject = (obj) =>
|
||||
{
|
||||
for(const key in obj)
|
||||
{
|
||||
window.dealWithSpecialInputType(key, obj[key]);
|
||||
if(Array.isArray(obj[key]))
|
||||
{
|
||||
const isStartWith0 = $('[name="' + key + '[0]' + '"]').length;
|
||||
const arr = obj[key];
|
||||
for(let i = 0; i < arr.length; i++)
|
||||
{
|
||||
for(const key in arr[i])
|
||||
{
|
||||
window.injectToInputElement(key, arr[i][key], isStartWith0 ? i : i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(typeof obj[key] === 'Object')
|
||||
{
|
||||
inject(obj[key]);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.injectToInputElement(key, obj[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.dealWithSpecialInputType = (key, value) =>
|
||||
{
|
||||
if(key === 'steps')
|
||||
{
|
||||
const steps = document.getElementById('steps');
|
||||
if(!steps) return;
|
||||
if(value.length > steps.children.length)
|
||||
{
|
||||
const gap = value.length - steps.children.length;
|
||||
for(let i = 0; i < gap; i++)
|
||||
{
|
||||
const addButton = document.querySelector('#steps > tr:last-child > .step-actions button:first-child');
|
||||
if(!addButton) return;
|
||||
addButton.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
const data = JSON.parse(window.injectData);
|
||||
if(!data) return;
|
||||
|
||||
window.inject(data);
|
||||
|
||||
zui.Messager.show({content: '{$this->lang->ai->dataInject->success}', type: 'success'});
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
zui.Messager.show({content:'{$this->lang->ai->dataInject->fail}', type: 'danger'});
|
||||
console.error(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
/* Set injected in oreder to cancel loading class on object view (see ./promptmenu.html.php). */
|
||||
sessionStorage.setItem('ai-prompt-data-injected', true);
|
||||
|
||||
const container = window.frameElement?.closest('.load-indicator');
|
||||
if(container && container.dataset.loading)
|
||||
{
|
||||
sessionStorage.removeItem('ai-prompt-data-injected');
|
||||
delete container.dataset.loading;
|
||||
|
||||
container.classList.remove('loading');
|
||||
container.classList.remove('no-delay');
|
||||
}
|
||||
}
|
||||
});
|
||||
JAVASCRIPT);
|
||||
|
||||
/* TODO: handle prompt audit, see original ../view/inputinject.html.php. */
|
||||
};
|
||||
$inputInject();
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
js("requestAnimationFrame(() => setTimeout(() => openUrl(`{$formLocation}`), 1000));");
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* The ai prompt menu ui view file of ai module of ZenTaoPMS.
|
||||
*
|
||||
* This view file is used to print the prompt menu, acts just like header php files.
|
||||
* Prompt menus are generated with php and injected with javascript. A lot of hacking
|
||||
* went into this, so please don't touch it unless you know what you are doing.
|
||||
*
|
||||
* @copyright Copyright 2009-2024 禅道软件(青岛)有限公司(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 Wenrui LI <liwenrui@easycorp.ltd>
|
||||
* @package ai
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace zin;
|
||||
|
||||
$promptMenuInject = function()
|
||||
{
|
||||
$this->loadModel('ai');
|
||||
if(!$this->ai->hasModelsAvailable() || !commonModel::hasPriv('ai', 'promptExecute')) return;
|
||||
|
||||
$this->app->loadConfig('ai');
|
||||
$module = $this->app->getModuleName();
|
||||
$method = $this->app->getMethodName();
|
||||
if(!isset($this->config->ai->menuPrint->locations[$module][$method])) return;
|
||||
|
||||
$menuOptions = $this->config->ai->menuPrint->locations[$module][$method];
|
||||
$prompts = $this->ai->getPromptsForUser($menuOptions->module);
|
||||
$prompts = $this->ai->filterPromptsForExecution($prompts, true);
|
||||
if(empty($prompts)) return;
|
||||
|
||||
$html = '';
|
||||
$objectVarName = empty($menuOptions->objectVarName) ? $menuOptions->module : $menuOptions->objectVarName;
|
||||
$currentObjectId = !empty($this->view->$objectVarName) ? $this->view->$objectVarName->id : 0;
|
||||
if(count($prompts) > 1)
|
||||
{
|
||||
$html .= '<div class="prompts dropdown' . ((isset($menuOptions->class) ? ' ' . $menuOptions->class : '') . (isset($menuOptions->dropdownClass) ? ' ' . $menuOptions->dropdownClass : '')) . '"><button class="btn ghost size-sm font-medium' . (isset($menuOptions->buttonClass) ? ' ' . $menuOptions->buttonClass : '') . '" type="button" data-toggle="dropdown">' . $this->lang->ai->promptMenu->dropdownTitle . ' <i class="icon-caret-down"></i></button><menu class="dropdown-menu menu">';
|
||||
foreach($prompts as $prompt) $html .= '<li class="menu-item">' . html::linkButton($prompt->name . ($prompt->status != 'active' ? '<span class="label label-info label-badge" style="margin-left: 4px;">' . $this->lang->ai->prompts->statuses[$prompt->status] . '</span>' : ''), helper::createLink('ai', 'promptExecute', "promptId=$prompt->id&objectId=$currentObjectId"), 'self', "style='width: 100%;'" . (empty($prompt->unauthorized) ? '' : ' disabled') . (empty($prompt->desc) ? '' : " data-toggle='popover' data-container='body' data-trigger='hover' data-content='$prompt->desc' data-title='$prompt->name' data-placement='left'"), 'btn ghost size-sm font-medium text-left') . '</li>';
|
||||
$html .= '</menu></div>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$prompt = current($prompts);
|
||||
$html .= html::linkButton($prompt->name . ($prompt->status != 'active' ? '<span class="label label-info label-badge" style="margin-left: 4px;">' . $this->lang->ai->prompts->statuses[$prompt->status] . '</span>' : ''), helper::createLink('ai', 'promptExecute', "promptId=$prompt->id&objectId=$currentObjectId"), 'self', (empty($prompt->unauthorized) ? '' : 'disabled') . (empty($prompt->desc) ? '' : " data-toggle='popover' data-container='body' data-trigger='hover' data-content='$prompt->desc' data-title='$prompt->name' data-placement='bottom'"), 'prompt btn ghost size-sm font-medium' . ((isset($menuOptions->class) ? ' ' . $menuOptions->class : '') . (isset($menuOptions->buttonClass) ? ' ' . $menuOptions->buttonClass : '')));
|
||||
}
|
||||
|
||||
/* Assemble injector script. */
|
||||
$script = <<< JAVASCRIPT
|
||||
if(window.location.search.includes('onlybody')) return;
|
||||
const container = window.frameElement?.closest('.load-indicator');
|
||||
if(container && container.dataset.loading)
|
||||
{
|
||||
delete container.dataset.loading;
|
||||
container.classList.remove('loading');
|
||||
container.classList.remove('no-delay');
|
||||
}
|
||||
JAVASCRIPT;
|
||||
$script .= "$(`$menuOptions->targetContainer`)." . (!empty($menuOptions->injectMethod) ? $menuOptions->injectMethod : 'append') . "(`$html`);\n";
|
||||
$script .= <<< JAVASCRIPT
|
||||
$('[data-toggle="popover"]').popover({template: '<div class="popover"><h3 class="popover-title"></h3><div class="popover-content"></div></div>'});
|
||||
JAVASCRIPT;
|
||||
$script .= count($prompts) > 1 ? "$('.prompts.dropdown .dropdown-menu').on('click', 'a', e =>" : "$('.prompt').on('click', e =>";
|
||||
$script .= <<< JAVASCRIPT
|
||||
{
|
||||
if(!container) return;
|
||||
container.dataset.loading = e.target.querySelector('.label') ? '{$this->lang->ai->execute->auditing}' : '{$this->lang->ai->execute->loading}';
|
||||
container.classList.add('loading');
|
||||
container.classList.add('no-delay');
|
||||
|
||||
/* Checks for session storage to cancel loading status (see inputinject.html.php). */
|
||||
sessionStorage.removeItem('ai-prompt-data-injected');
|
||||
const loadCheckInterval = setInterval(() =>
|
||||
{
|
||||
if(sessionStorage.getItem('ai-prompt-data-injected'))
|
||||
{
|
||||
if(container && container.dataset.loading)
|
||||
{
|
||||
delete container.dataset.loading;
|
||||
container.classList.remove('loading');
|
||||
container.classList.remove('no-delay');
|
||||
}
|
||||
|
||||
sessionStorage.removeItem('ai-prompt-data-injected');
|
||||
clearInterval(loadCheckInterval);
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
JAVASCRIPT;
|
||||
|
||||
/* Perform injection. */
|
||||
if(isset($menuOptions->stylesheet)) h('style', $menuOptions->stylesheet);
|
||||
js($script);
|
||||
};
|
||||
$promptMenuInject();
|
||||
@@ -11,6 +11,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
$fields = useFields('bug.create');
|
||||
if(!empty($executionType) && $executionType == 'kanban') $fields->merge('bug.kanban');
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('bug', $bug);
|
||||
jsVar('confirmChangeProduct', $lang->bug->notice->confirmChangeProduct);
|
||||
jsVar('moduleID', $bug->module);
|
||||
|
||||
@@ -10,6 +10,9 @@ declare(strict_types=1);
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
jsVar('bugID', $bug->id);
|
||||
jsVar('productID', $bug->product);
|
||||
jsVar('branchID', $bug->branch);
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
featureBar
|
||||
(
|
||||
li(backBtn(setClass('ghost'), set::icon('back'), $lang->goback)),
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
$progress = ($execution->totalConsumed + $execution->totalLeft) ? floor($execution->totalConsumed / ($execution->totalConsumed + $execution->totalLeft) * 1000) / 1000 * 100 : 0;
|
||||
$isKanban = isset($execution->type) && $execution->type == 'kanban';
|
||||
$chartURL = createLink('execution', $isKanban ? 'ajaxGetCFD' : 'ajaxGetBurn', "executionID={$execution->id}");
|
||||
|
||||
@@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
|
||||
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);
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('weekend', $config->execution->weekend);
|
||||
jsVar('productID', $product->id);
|
||||
jsVar('lastLang', $lang->productplan->last);
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('today', helper::today());
|
||||
jsVar('weekend', $config->execution->weekend);
|
||||
jsVar('productID', $productID);
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
$unlinkURL['story'] = helper::createLink('productplan', 'unlinkStory', "storyID=%s&planID={$plan->id}");
|
||||
$unlinkURL['bug'] = helper::createLink('productplan', 'unlinkBug', "bugID=%s&planID={$plan->id}");
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
$fields = $this->config->programplan->form->create;
|
||||
|
||||
/* Generate title that is tailored to specific situation. */
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
jsVar('confirmDeleteTip', $lang->project->confirmDelete);
|
||||
|
||||
$programDom = null;
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
$releaseModule = $app->rawModule == 'projectrelease' ? 'projectrelease' : 'release';
|
||||
|
||||
jsVar('initLink', $link);
|
||||
|
||||
@@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
data('activeMenuID', $type);
|
||||
data('storyType', $type);
|
||||
jsVar('storyType', $type);
|
||||
|
||||
@@ -9,6 +9,8 @@ declare(strict_types=1);
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
include './affected.html.php';
|
||||
|
||||
data('activeMenuID', $story->type);
|
||||
|
||||
@@ -11,6 +11,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
data('storyType', $type);
|
||||
data('activeMenuID', $type);
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
$confirmDelete = $this->lang->story->confirmDelete;
|
||||
if($story->type == 'requirement')
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('window.executionID', $execution->id);
|
||||
jsVar('vision', $config->vision);
|
||||
jsVar('window.lifetime', $execution->lifetime);
|
||||
|
||||
@@ -12,6 +12,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
include './taskteam.html.php';
|
||||
|
||||
/* ====== Preparing and processing page data ====== */
|
||||
|
||||
@@ -9,6 +9,9 @@ declare(strict_types=1);
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
global $lang;
|
||||
|
||||
/* Join mailto. */
|
||||
|
||||
@@ -10,6 +10,9 @@ declare(strict_types=1);
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('tab', $this->app->tab);
|
||||
if($app->tab == 'execution') jsVar('objectID', $executionID);
|
||||
if($app->tab == 'project') jsVar('objectID', $projectID);
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('tab', $this->app->tab);
|
||||
jsVar('isLibCase', $isLibCase);
|
||||
jsVar('caseBranch', $case->branch);
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
|
||||
$canCreateCase = hasPriv('testcase', 'create');
|
||||
|
||||
jsVar('viewParams', "caseID={$case->id}&version={$version}&from={$from}&taskID={$taskID}&stepsType=");
|
||||
|
||||
@@ -10,6 +10,8 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
foreach($reports as $report)
|
||||
{
|
||||
$taskName = '';
|
||||
@@ -63,4 +65,3 @@ dtable
|
||||
);
|
||||
|
||||
render();
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ declare(strict_types=1);
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
|
||||
include($this->app->getModuleRoot() . 'ai/ui/inputinject.html.php');
|
||||
|
||||
jsVar('goalTip', $lang->testreport->goalTip);
|
||||
jsVar('foundBugTip', $lang->testreport->foundBugTip);
|
||||
jsVar('legacyBugTip', $lang->testreport->legacyBugTip);
|
||||
|
||||
Reference in New Issue
Block a user