* Refactor diff view of mr module.

This commit is contained in:
zhaoke
2023-07-06 15:36:09 +08:00
parent 94736ffcfc
commit 675bb6b5f1
10 changed files with 653 additions and 22 deletions
+4 -4
View File
@@ -558,7 +558,7 @@ class mr extends control
* @param int $pageID
* @return void
*/
public function link($MRID, $type = 'story', $orderBy = 'id_desc', $link = 'false', $param = '', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function link($MRID, $type = 'story', $orderBy = 'id_desc', $link = 'false', $param = '', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
$this->loadModel('story');
$this->loadModel('bug');
@@ -614,7 +614,7 @@ class mr extends control
* @access public
* @return void
*/
public function linkStory($MRID, $productID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function linkStory($MRID, $productID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
if(!empty($_POST['stories']))
{
@@ -704,7 +704,7 @@ class mr extends control
* @access public
* @return void
*/
public function linkBug($MRID, $productID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function linkBug($MRID, $productID = 0, $browseType = '', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
if(!empty($_POST['bugs']))
{
@@ -795,7 +795,7 @@ class mr extends control
* @access public
* @return void
*/
public function linkTask($MRID, $productID = 0, $browseType = 'unclosed', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function linkTask($MRID, $productID = 0, $browseType = 'unclosed', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 10, $pageID = 1)
{
if(!empty($_POST['tasks']))
{
+72
View File
@@ -0,0 +1,72 @@
#fileTabs .nav-tabs {overflow: hidden;position: absolute;height: 35px;background: #efefef;}
#fileTabs .nav-tabs > li.nav-item > a {z-index: 1; background: none;}
#fileTabs .nav-tabs > li > a::after {content: ''; position: absolute; top: 2px; left: 10px; width: 85%; right: 6px; bottom: 0; background: #f8f8f8; border: none; border-radius: 10px 10px 0 0; height: 70%; transform: perspective(4px)scale(1.1, 1.3) rotateX(5deg); z-index: -1;}
#fileTabs .nav-tabs > li > a.active::after {background: #fff;}
#fileTabs > .nav-tabs {overflow: hidden; padding-bottom: 10px; position: relative; height: 35px; background: #efefef;}
#fileTabs > .nav-tabs {position: absolute; display: flex; padding-left: 25px;}
#fileTabs .monaco-close{margin-right: 18px;}
#fileTabs .nav-tabs > li > a > span{margin-left: 18px;font-weight: 700;color: #313c52!important;}
#related .btn-right, #related .btn-left {padding-top: 9px;}
#log .action-btn {margin-top: -7px;}
.repoCode .btn.btn-right, .repoCode .btn.btn-left {margin-right: 0; padding: 6px 6px;}
#related .btn-right, #related .btn-left {padding-top: 9px;}
.btn-left, .btn-right {display: none;}
#linkObject{display: none;}
#related .btn-right, #related .btn-left {padding-top: 9px;}
#monacoTree .tree-item-content span {cursor: pointer;}
.directory {background-image:url('theme/default/images/repo/dir.png');}
.file {background-image:url('theme/default/images/repo/txt.png');}
.mini-icon {display: inline-block; height: 16px; width: 16px; background-color: transparent; background-position: 0 0; background-repeat: no-repeat; vertical-align: text-bottom; margin-right: 5px;}
#monacoTree .tree-item-content {cursor: pointer;}
.sync-content {margin: 10px}
.sync-main-content {padding: 20px;background-color: #fff;border-radius: 4px;}
.sync-line {border-top: 1px solid #e4e4e4; margin: 10px 0;}
.sync-main-content div {width: 100%;}
.sync-main-content h3 {font-size: 16px; font-weight: 700;}
.sync-main-content p {color: #313c52;}
.sync-main-content .alert > [class*="icon-"] {font-size: 42px;opacity: 0.8;}
.repo-linkstory-title {background-color: #e6f0ff; color: #2e7fff; padding: 4px 0 12px;}
#sourceSwapper {text-align: left; margin-bottom: 2px;}
.sidebar {background-color: white}
#monacoTabs .nav > li > a {padding: 8px 10px; display: flex; white-space: pre;}
#monacoTabs .nav-tabs > li > a > span {margin-right: 5px;}
#monacoTabs .tab-pane {display: none;}
#monacoTabs {background: #FFFFFF;}
#monacoTabs .tab-pane.active {display: block;}
#monacoTabs .tab-nav-item {max-width: none !important;}
#monacoTabs .tab-nav-item .icon {line-height: inherit;}
#monacoTabs {overflow: hidden; padding-bottom: 10px; position: relative; height: 100%;}
#monacoTabs > .nav-tabs {position: absolute; display: flex; padding-right: 20px;}
#fileTabs .arrow-left, #fileTabs .arrow-right {line-height: 23px; padding: 6px; width: 26px; background: #efefef;}
#fileTabs .arrow-right {right: 35px;}
#monacoTabs ul {min-width: 100%; padding-left: 25px; z-index: 1;}
#monacoTabs .tab-content {margin-top: 35px;}
#monacoTabsContainer {background: #efefef;}
.monaco-dropmenu{background: #efefef; height: 35px; line-height: 35px;}
#fileTabs > .btn {background: #efefef; border: none; --tw-ring-shadow: none;}
#fileTabs > .btn-right {padding-right: 40px;}
.diff-back-btn {border: none; --tw-ring-shadow: none}
.diff-back-btn::after {border: none;}
.diff-back-btn::before {border: none;}
.label-info {background-color: #37b2fe}
.label-info[href]:focus,.label-info[href]:hover {color: #fff; background-color: #049efe}
.label-info.label-outline {color: #37b2fe; background: 0 0; border: 1px solid #37b2fe}
.label {padding: .2em .6em .2em; color: #fff;text-align: center; white-space: nowrap; vertical-align: middle; border-radius: .25em;}
.diff-label {border: none; --tw-ring-shadow: none; margin-left: 5px; margin-right: 10px}
.label-exchange {background-color: #566F7C; cursor: pointer;}
#fileTabs .tab-pane {display: none;}
#fileTabs .tab-pane.active {display: block;}
#fileTabs .nav-item {max-width: none !important;}
.sidebar .tree{background-color: white;}
.container .sidebar{width: 240px;}
.tree li.tree-item.selected{color: #438EFF !important;}
#monacoTree{overflow: auto;}
.monaco-dropmenu{background: #efefef;}
#fileTabs {flex: 1 1 auto;}
#diff-sidebar-left {width: 100%; align-items: stretch; display: flex; gap: 1rem; justify-content: space-between; flex-direction: row-reverse; margin-top: 10px;}
#mrMenu menu.nav {border-bottom: 1px solid #ddd}
#mrMenu .nav-item>a.active {border-bottom-color: var(--color-primary-500) !important; border-bottom-width: 2px; margin-bottom: -1px;}
.mr-actions {position: absolute; right: 1rem; top: 10px;}
.panel-body .detail-content{margin-top: 10px;}
+409
View File
@@ -0,0 +1,409 @@
var iframeHeight = 0;
var sidebarHeight = 0;
var tabTemp;
var diffAppose = $.cookie.get('renderSideBySide') == 'true';
var distance = 0;
/**
* 左右切换关联信息。
* Aarrow tabs area.
*
* @param string domID
* @param number shift 1|-1
* @param bool hideRightBtn
* @access public
* @return void
*/
function arrowTabs(domID, shift, hideRightBtn)
{
if($('#' + domID).html() == '') return;
var hasParent = $('#' + domID + ' .btn-left').length;
var $leftBtn = hasParent ? $('#' + domID + ' .btn-left') : $('.btn-left');
var $rightBtn = hasParent ? $('#' + domID + ' .btn-right') : $('.btn-right');
$leftBtn.show();
$rightBtn.show();
if(hideRightBtn) $rightBtn.hide();
var tabItemWidth = 0;
if($('#' + domID + ' > .nav-tabs')[0]) tabItemWidth = $('#' + domID + ' > .nav-tabs')[0].clientWidth;
var tabsWidth = $('#' + domID)[0].clientWidth;
if($('#' + domID + ' .close-bugs').length) tabsWidth = tabsWidth * 0.7;
if(tabItemWidth <= tabsWidth)
{
$leftBtn.hide();
$rightBtn.hide();
return;
}
distance += tabsWidth * shift * 0.2;
if(distance > 0) distance = 0;
if(distance == 0)
{
$leftBtn.hide();
}
if((tabItemWidth + distance) <= tabsWidth * 0.75)
{
$rightBtn.hide();
return arrowTabs(domID, 1, true);
}
if(domID == 'monacoTabs' && distance < -60) distance = distance + 60;
$('#' + domID + ' > .nav-tabs')[0].style.transform = 'translateX('+ distance +'px)';
}
/**
* 关闭关联信息tab。
* Close commit relations.
*
* @access public
* @return void
*/
function closeRelation()
{
$('#relationTabs ul li').remove();
$('#relationTabs .tab-content .tab-pane').remove();
$('.history').html('');
$('#log').data('line', 0);
$('#log').hide();
$('#codeContainer').css('height', codeHeight);
$('#related').css('height', 0);
};
/**
* 获取tabs内容高度。
* Get tab-content height.
*
* @access public
* @return void
*/
function getIframeHeight()
{
if(iframeHeight) return iframeHeight;
var windowHeight = $(window).height();
var headerHeight = parseInt($('#header').height());
var mainNavbar = parseInt($('#navbar').height());
var tabsbar = parseInt($('.nav-tabs').height());
var mainMenuHeight = parseInt($('#mainContent').css('padding-top')) + parseInt($('#mainContent').css('padding-bottom'));
var detailHeaderHeight = parseInt($('.detail-header').height());
var mrMenuHeight = parseInt($('#mrMenu').height());
var appTabsHeight = parseInt($('#appTabs').height());
var appsBarHeight = parseInt($('#appsBar').height());
appsBarHeight = appsBarHeight ? appsBarHeight : 0;
appTabsHeight = appTabsHeight ? appTabsHeight : 0;
mainMenuHeight = mainMenuHeight ? mainMenuHeight : 0;
mainNavbar = mainNavbar ? mainNavbar : 0;
iframeHeight = windowHeight - headerHeight - appsBarHeight - appTabsHeight - mainMenuHeight - mainNavbar - tabsbar - detailHeaderHeight - mrMenuHeight - 28;
return iframeHeight;
}
/**
* 获取左侧边栏高度。
* Get sidebar height.
*
* @access public
* @return void
*/
function getSidebarHeight()
{
if(sidebarHeight) return sidebarHeight;
var windowHeight = $(window).height();
var headerHeight = parseInt($('#header').height());
var mainNavbar = parseInt($('#navbar').height());
var mainMenuHeight = parseInt($('#mainContent').css('padding-top')) + parseInt($('#mainContent').css('padding-bottom'));
var appTabsHeight = parseInt($('#appTabs').height());
var appsBarHeight = parseInt($('#appsBar').height());
var detailHeaderHeight = parseInt($('.detail-header').height());
var mrMenuHeight = parseInt($('#mrMenu').height());
appsBarHeight = appsBarHeight ? appsBarHeight : 0;
appTabsHeight = appTabsHeight ? appTabsHeight : 0;
mainMenuHeight = mainMenuHeight ? mainMenuHeight : 0;
mainNavbar = mainNavbar ? mainNavbar : 0;
sidebarHeight = windowHeight - headerHeight - appsBarHeight - appTabsHeight - mainMenuHeight - mainNavbar - detailHeaderHeight - mrMenuHeight - 20;
return sidebarHeight;
}
/**
* 查找选中元素所有的父元素及选中元素的id。
* Find parent nodes and item id of selected tree item.
*
* @access public
* @return string
*/
function findItemInTreeItems(list, key, level) {
for (const item of list) {
if(level === 0)
{
parentTree = [item.key];
}
else
{
parentTree.push(item.key);
}
if (item.key === key) return item;
if (item.items && item.items.length > 0)
{
const findedItem = findItemInTreeItems(item.items, key);
if (findedItem) return findedItem;
}
}
}
/**
* 展开树状结构。
* Expand tree node.
*
* @access public
* @return void
*/
function expandTree()
{
const treeObj = $('#monacoTree').parent().data('zui.Tree');
if(treeObj == undefined || treeObj.$ == undefined) return;
for (const key of parentTree) treeObj.$.expand(key);
}
/* Close tab. */
$('#monacoTabs').on('click', '.monaco-close', function()
{
var eleId = $(this).parent().attr('href');
var tabsEle = $(this).parent().parent().parent();
var isActive = $(this).parent().hasClass('active');
$(this).parent().parent().remove();
$(eleId).remove();
$('#' + eleId.substring(5)).parent().removeClass('selected');
if(isActive) tabsEle.children().last().find('a').trigger('click');
});
window.afterPageUpdate = function()
{
setTimeout(function()
{
var fileAsId = file.replace(/=/g, '-');
/* Resize moaco height. */
$('#monacoTree').css('height', getSidebarHeight() - 8 + 'px');
/* Init tab template. */
if(!tabTemp) tabTemp = $('#monacoTabs ul li').first().clone();
/* Load default tab content. */
var height = getIframeHeight();
$('#tab-' + fileAsId).html("<iframe class='repo-iframe' src='" + $.createLink('repo', 'ajaxGetDiffEditorContent', urlParams.replace('%s', fileAsId)) + "' width='100%' height='" + height + "' scrolling='no'></iframe>")
/* Select default tree item. */
const currentElement = findItemInTreeItems(tree, fileAsId, 0);
$('#' + currentElement.id).parent().addClass('selected');
expandTree();
$('.btn-left').on('click', function() {arrowTabs('monacoTabs', 1);});
$('.btn-right').on('click', function() {arrowTabs('monacoTabs', -2);});
}, 200);
};
/**
* 点击左侧菜单打开详情tab。
* Open new tab when click tree item.
*
* @access public
* @return void
*/
window.treeClick = function(info)
{
if (info.item.items && info.item.items.length > 0) return;
$('#' + info.item.id).parent().addClass('selected');
openTab(info.item.key, info.item.text);
arrowTabs('monacoTabs', -2);
}
/**
* Change code encoding.
*
* @param string encoding
* @access public
* @return void
*/
function changeEncoding(encoding)
{
$('#encoding').val(encoding);
$('#encoding').parents('form').submit();
}
/**
* Html code decode.
*
* @param string str
* @access public
* @return string
*/
function htmlspecialchars_decode(str){
str = str.replace(/&amp;/g, '&');
str = str.replace(/&lt;/g, '<');
str = str.replace(/&gt;/g, '>');
str = str.replace(/&quot;/g, "''");
str = str.replace(/&#039;/g, "'");
return str;
}
/**
* Get diffs by file name.
*
* @param string fileName
* @access public
* @return object
*/
window.getDiffs = function(fileName)
{
if(fileName.indexOf('./') === 0) fileName = fileName.substring(2);
var result = {
'code': {'new': '', 'old': ''},
'line': {'new': [], 'old': []}
};
$.each(diffs, function(i, diff)
{
if(diff.fileName == fileName)
{
if(!diff.contents || typeof diff.contents[0].lines != 'object') return result;
$.each(diff.contents, function(k, content)
{
var lines = content.lines;
$.each(lines, function(l, code)
{
if(code.type == 'all' || code.type == 'new')
{
result.code.new += htmlspecialchars_decode(code.line.substring(1)) + "\n";
result.line.new.push(parseInt(code.newlc));
}
if(code.type == 'all' || code.type == 'old')
{
result.code.old += htmlspecialchars_decode(code.line.substring(1)) + "\n";
result.line.old.push(parseInt(code.oldlc));
}
})
})
return result;
}
});
return result;
}
/**
* 打开新tab。
* Open new tab.
*
* @access public
* @return void
*/
function openTab(entry, name)
{
var eleId = 'tab-' + entry.replace(/=/g, '-');
var element = document.getElementById(eleId);
if (element)
{
$("a[href='" + '#' + eleId + "']").trigger('click');
return;
}
var newTab = tabTemp.clone();
newTab.find('a').attr('href', '#' + eleId);
newTab.find('span').text(name);
$('#monacoTabs .nav-tabs').append(newTab);
var height = getIframeHeight();
$('#monacoTabs .tab-content').append("<div id='" + eleId + "' class='tab-pane active in'><iframe class='repo-iframe' src='" + $.createLink('repo', 'ajaxGetDiffEditorContent', urlParams.replace('%s', entry)) + "' width='100%' height='" + height + "' scrolling='no'></iframe></div>")
setTimeout(() => {
$("a[href='" + '#' + eleId + "']").trigger('click');
updateEditorInline('#' + eleId);
}, 100);
}
function updateEditorInline(eleId)
{
$.cookie.set('renderSideBySide', diffAppose);
if(typeof $(eleId + ' iframe')[0].contentWindow.updateEditorInline == 'function')
{
$(eleId + ' iframe')[0].contentWindow.updateEditorInline(diffAppose);
}
}
$('#monacoTabs .nav-item a').on('click', function()
{
var eleId = $(this).attr('href');
$(eleId + ' iframe')[0].contentWindow.updateEditorInline(diffAppose);
});
$(document).ready(function()
{
if(diffAppose)
{
$('.dropdown-menu #inline').show();
$('.dropdown-menu #appose').hide();
}
else
{
$('.dropdown-menu #appose').show();
$('.dropdown-menu #inline').hide();
}
$('.btn-left').on('click', function() {arrowTabs('monacoTabs', 1);});
$('.btn-right').on('click', function() {arrowTabs('monacoTabs', -2);});
});
$('.inline-appose').on('click', function()
{
$('.inline-appose').hide();
diffAppose = !diffAppose;
if(diffAppose)
{
$('.dropdown-menu #inline').show();
}
else
{
$('.dropdown-menu #appose').show();
}
var tabID = $('#monacoTabs .nav-item .active').attr('href');
updateEditorInline(tabID);
return;
});
$(".label-exchange").on('click', function()
{
var newDiffLink = diffLink.replace('{oldRevision}', newRevision);
newDiffLink = newDiffLink.replace('{newRevision}', oldRevision);
openUrl(newDiffLink);
});
/**
* 在当前页面用modal加载链接。
* Load link object page.
*
* @param string $link
* @access public
* @return void
*/
window.loadLinkPage = function(link)
{
$('#linkObject').attr('href', link);
$('#linkObject').trigger('click');
}
+150
View File
@@ -0,0 +1,150 @@
<?php
declare(strict_types=1);
/**
* The diff file of mr 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 Ke Zhao <zhaoke@easycorp.ltd>
* @package mr
* @link https://www.zentao.net
*/
namespace zin;
detailHeader
(
to::title
(
entityLabel
(
set::entityID($MR->id),
set::level(1),
set::text($MR->title)
),
$MR->deleted ? h::span
(
setClass('label danger'),
$lang->product->deleted,
) : null,
)
);
$entry = count($diffs) ? $diffs[0]->fileName : '';
$currentEntry = $this->repo->encodePath($entry);
$fileInfo = $entry ? pathinfo($entry) : array();
$showBug = isset($showBug) ? $showBug : true;
$objectID = isset($objectID) ? $objectID : 0;
$tree = $this->repo->getFileTree($repo, '', $diffs);
$diffLink = $this->repo->createLink('diff', "repoID=$repoID&objectID=$objectID&entry=" . $file . "&oldrevision={oldRevision}&newRevision={newRevision}");
jsVar('diffs', $diffs);
jsVar('tree', $tree);
jsVar('file', $currentEntry);
jsVar('entry', $entry);
jsVar('diffLink', $diffLink);
jsVar('urlParams', "repoID=$repoID&objectID=$objectID&entry=%s&oldRevision=$oldRevision&newRevision=$newRevision&showBug=$showBug&encoding=$encoding");
$dropMenus = array();
if(common::hasPriv('repo', 'download')) $dropMenus[] = array('text' => $this->lang->repo->downloadDiff, 'icon' => 'download', 'url' => $this->repo->createLink('download', "repoID=$repoID&path=$currentEntry&fromRevision=$oldRevision&toRevision=$newRevision&type=path"), 'target' => '_blank');
$dropMenus[] = array('text' => $this->lang->repo->viewDiffList['inline'], 'icon' => 'snap-house', 'id' => 'inline', 'class' => 'inline-appose');
$dropMenus[] = array('text' => $this->lang->repo->viewDiffList['appose'], 'icon' => 'col-archive', 'id' => 'appose', 'class' => 'inline-appose');
panel
(
setClass('relative'),
div
(
set::id('mrMenu'),
nav
(
li
(
setClass('nav-item'),
a($lang->mr->view, set::href(inlink('view', "MRID={$MR->id}")))
),
li
(
setClass('nav-item'),
a($lang->mr->viewDiff, setClass('active'))
),
li
(
setClass('nav-item story'),
a(icon($lang->icons['story']), $lang->productplan->linkedStories, set::href(inlink('link', "MRID={$MR->id}&type=story")))
),
li
(
setClass('nav-item bug'),
a(icon($lang->icons['bug']), $lang->productplan->linkedBugs, set::href(inlink('link', "MRID={$MR->id}&type=bug")))
),
li
(
setClass('nav-item task'),
a(icon('todo'), $lang->mr->linkedTasks, set::href(inlink('link', "MRID={$MR->id}&type=task")))
),
)
),
empty($diffs) ? p(setClass('detail-content'), $lang->mr->noChanges) : div(
setID('diff-sidebar-left'),
div
(
set::id('fileTabs'),
tabs
(
set::id('monacoTabs'),
set::class('relative'),
div(setStyle(array('position' => 'absolute', 'width' => '100%', 'height' => '35px', 'background' => '#efefef', 'top' => '0px'))),
tabPane
(
set::title($fileInfo['basename']),
set::active(true),
set::key('tab-' . str_replace('=', '-', $currentEntry)),
to::suffix
(
icon
(
'close',
set::class('monaco-close'),
)
),
div(set::id('tab-' . $currentEntry)),
),
dropdown
(
set::arrow(false),
set::staticMenu(true),
set::class('absolute top-0 right-0 z-10 monaco-dropmenu'),
btn
(
setClass('ghost text-black pull-right'),
set::icon('ellipsis-v rotate-90'),
),
set::items
(
$dropMenus
),
),
div(set::class('absolute top-0 left-0 z-20 arrow-left btn-left'), icon('chevron-left')),
div(set::class('absolute top-0 right-0 z-20 arrow-right btn-right'), icon('chevron-right')),
)
),
sidebar
(
set::side('left'),
tree
(
set::id('monacoTree'),
set::items($tree),
set::collapsedIcon('folder'),
set::expandedIcon('folder-open'),
set::normalIcon('file-text-alt'),
set::activeKey($entry),
set::onClickItem(jsRaw('window.treeClick')),
)
),
a(set::class('iframe'), setData('size', '1000px'), setData('toggle', 'modal'), set::id('linkObject'))
)
);
render();
+3 -3
View File
@@ -1,11 +1,11 @@
<?php
declare(strict_types=1);
/**
* The link view file of repo module of ZenTaoPMS.
* The link view file of mr 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 Zeng Gang<zenggang@easycorp.ltd>
* @package repo
* @package mr
* @link https://www.zentao.net
*/
namespace zin;
@@ -128,7 +128,7 @@ panel
(
setClass('mr-actions primary'),
setData('linkType', 'bug'),
setData('size', '1000px'),
setData('size', 'lg'),
setData('toggle', 'modal'),
set::url($this->createLink('mr', 'linkStory', "MRID={$MR->id}&productID={$product->id}{$param}&orderBy={$orderBy}")),
set::icon('link'),
+3 -3
View File
@@ -1,11 +1,11 @@
<?php
declare(strict_types=1);
/**
* The linkstory file of testreport module of ZenTaoPMS.
* The linkbug file of mr 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 Yuting Wang <wangyuting@easycorp.ltd>
* @package testreport
* @author Ke Zhao <zhaoke@easycorp.ltd>
* @package mr
* @link https://www.zentao.net
*/
namespace zin;
+3 -3
View File
@@ -1,11 +1,11 @@
<?php
declare(strict_types=1);
/**
* The linkstory file of testreport module of ZenTaoPMS.
* The linkstory file of mr 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 Yuting Wang <wangyuting@easycorp.ltd>
* @package testreport
* @author Ke Zhao <zhaoke@easycorp.ltd>
* @package mr
* @link https://www.zentao.net
*/
namespace zin;
+3 -3
View File
@@ -1,11 +1,11 @@
<?php
declare(strict_types=1);
/**
* The linkstory file of testreport module of ZenTaoPMS.
* The linkbug file of repo 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 Yuting Wang <wangyuting@easycorp.ltd>
* @package testreport
* @author Ke Zhao <zhaoke@easycorp.ltd>
* @package repo
* @link https://www.zentao.net
*/
namespace zin;
+3 -3
View File
@@ -1,11 +1,11 @@
<?php
declare(strict_types=1);
/**
* The linkstory file of testreport module of ZenTaoPMS.
* The linkstory file of repo 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 Yuting Wang <wangyuting@easycorp.ltd>
* @package testreport
* @author Ke Zhao <zhaoke@easycorp.ltd>
* @package repo
* @link https://www.zentao.net
*/
namespace zin;
+3 -3
View File
@@ -1,11 +1,11 @@
<?php
declare(strict_types=1);
/**
* The linkstory file of testreport module of ZenTaoPMS.
* The linktask file of repo 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 Yuting Wang <wangyuting@easycorp.ltd>
* @package testreport
* @author Ke Zhao <zhaoke@easycorp.ltd>
* @package repo
* @link https://www.zentao.net
*/
namespace zin;