mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°931: Tags admin menu
This commit is contained in:
@@ -96,12 +96,27 @@ abstract class TagSetFieldData extends cmdbAbstractObject
|
||||
public function ComputeValues()
|
||||
{
|
||||
$sClassName = get_class($this);
|
||||
$aRes = static::ExtractTagFieldName($sClassName);
|
||||
$this->_Set('tag_class', $aRes['tag_class']);
|
||||
$this->_Set('tag_attcode', $aRes['tag_attcode']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract Tag class and attcode from the TagFieldData class name
|
||||
* @param $sClassName
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function ExtractTagFieldName($sClassName)
|
||||
{
|
||||
$aRes = array();
|
||||
// Extract class and attcode from class name using pattern TagSetFieldDataFor_<class>_<attcode>>;
|
||||
if (preg_match('@^TagSetFieldDataFor_(?<class>\w+)_(?<attcode>\w+)$@', $sClassName, $aMatches))
|
||||
{
|
||||
$this->_Set('tag_class', $aMatches['class']);
|
||||
$this->_Set('tag_attcode', $aMatches['attcode']);
|
||||
$aRes['tag_class'] = $aMatches['class'];
|
||||
$aRes['tag_attcode'] = $aMatches['attcode'];
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,6 +203,51 @@ abstract class TagSetFieldData extends cmdbAbstractObject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display Tag Usage
|
||||
*
|
||||
* @param \WebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
parent::DisplayBareRelations($oPage, $bEditMode);
|
||||
if (!$bEditMode)
|
||||
{
|
||||
$sClass = $this->Get('tag_class');
|
||||
$sAttCode = $this->Get('tag_attcode');
|
||||
$sTagCode = $this->Get('tag_code');
|
||||
$oFilter = DBSearch::FromOQL("SELECT $sClass WHERE $sAttCode MATCHES '$sTagCode'");
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
$iCount = $oSet->Count();
|
||||
$oPage->SetCurrentTab(Dict::Format('Core:TagSetFieldData:WhereIsThisTagTab', $iCount));
|
||||
$aClassLabels = array();
|
||||
foreach(MetaModel::EnumChildClasses($sClass) as $sCurrentClass)
|
||||
{
|
||||
$aClassLabels[$sCurrentClass] = MetaModel::GetName($sCurrentClass);
|
||||
}
|
||||
|
||||
foreach($aClassLabels as $sClass => $sClassLabel)
|
||||
{
|
||||
$oFilter = DBSearch::FromOQL("SELECT $sClass WHERE $sAttCode MATCHES '$sTagCode'");
|
||||
$oSet = new DBObjectSet($oFilter);
|
||||
if ($oSet->CountExceeds(0))
|
||||
{
|
||||
$oPage->add("<h2>$sClassLabel</h2>");
|
||||
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oResultBlock->Display($oPage, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sClass
|
||||
* @param $sAttCode
|
||||
|
||||
@@ -8423,5 +8423,12 @@
|
||||
</cells>
|
||||
</definition>
|
||||
</menu>
|
||||
<menu id="TagAdminMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>100</rank>
|
||||
<parent>Catalogs</parent>
|
||||
<url>$pages/tagadmin.php</url>
|
||||
<enable_class>TagSetFieldData</enable_class>
|
||||
<enable_action>UR_ACTION_MODIFY</enable_action>
|
||||
</menu>
|
||||
</menus>
|
||||
</itop_design>
|
||||
|
||||
@@ -76,7 +76,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:Ticket/Attribute:private_log+' => '',
|
||||
'Class:Ticket/Attribute:contacts_list' => 'Contacts',
|
||||
'Class:Ticket/Attribute:contacts_list+' => 'All the contacts linked to this ticket',
|
||||
'Class:Ticket/Attribute:tagfield' => 'Tag',
|
||||
'Class:Ticket/Attribute:tagfield' => 'Tags',
|
||||
'Class:Ticket/Attribute:functionalcis_list' => 'CIs',
|
||||
'Class:Ticket/Attribute:functionalcis_list+' => 'All the configuration items impacted by this ticket. Items marked as "Computed" have been automatically marked as impacted. Items marked as "Not impacted" are excluded from the impact.',
|
||||
'Class:Ticket/Attribute:workorders_list' => 'Work orders',
|
||||
|
||||
@@ -922,4 +922,6 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Core:TagSetFieldData:ErrorTagCodeSyntax' => 'Tags code should contain between 3 and 20 alphanumeric characters',
|
||||
'Core:TagSetFieldData:ErrorTagLabelSyntax' => 'Tags label should not contain | nor be empty',
|
||||
'Core:TagSetFieldData:ErrorCodeUpdateNotAllowed' => 'Tags code cannot be changed',
|
||||
'Core:TagSetFieldData:FieldDescription' => '%2$s of class %1$s',
|
||||
'Core:TagSetFieldData:WhereIsThisTagTab' => 'Tag usage (%1$d)',
|
||||
));
|
||||
|
||||
@@ -956,7 +956,12 @@ When associated with a trigger, each action is given an "order" number, specifyi
|
||||
'UI:NotificationsMenu:OnStateLeave' => 'When an object leaves a given state',
|
||||
'UI:NotificationsMenu:Actions' => 'Actions',
|
||||
'UI:NotificationsMenu:AvailableActions' => 'Available actions',
|
||||
|
||||
|
||||
'Menu:TagAdminMenu' => 'Tags configuration',
|
||||
'Menu:TagAdminMenu+' => 'Tags values management',
|
||||
'UI:TagAdminMenu:Title' => 'Tags configuration',
|
||||
'UI:TagSetFieldData:Error' => 'Error: %1$s',
|
||||
|
||||
'Menu:AuditCategories' => 'Audit Categories', // Duplicated into itop-welcome-itil (will be removed from here...)
|
||||
'Menu:AuditCategories+' => 'Audit Categories', // Duplicated into itop-welcome-itil (will be removed from here...)
|
||||
'Menu:Notifications:Title' => 'Audit Categories', // Duplicated into itop-welcome-itil (will be removed from here...)
|
||||
|
||||
@@ -770,4 +770,6 @@ Opérateurs :<br/>
|
||||
'Core:TagSetFieldData:ErrorTagCodeSyntax' => 'Le code de l\'étiquette doit contenir entre 3 et 20 caractères alphanumériques.',
|
||||
'Core:TagSetFieldData:ErrorTagLabelSyntax' => 'Le nom de l\'étiquette ne doit pas être vide ni contenir le caractère \'|\'',
|
||||
'Core:TagSetFieldData:ErrorCodeUpdateNotAllowed' => 'Le code de l\'étiquette ne peut pas être changé',
|
||||
'Core:TagSetFieldData:FieldDescription' => '%2$s pour la classe %1$s',
|
||||
'Core:TagSetFieldData:WhereIsThisTagTab' => 'Utilisation (%1$d)',
|
||||
));
|
||||
|
||||
@@ -1343,6 +1343,12 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
|
||||
|
||||
'UI:Search:Criteria:Raw:Filtered' => 'Filtré',
|
||||
'UI:Search:Criteria:Raw:FilteredOn' => 'Filtré sur %1$s',
|
||||
|
||||
// - Tags admin
|
||||
'Menu:TagAdminMenu' => 'Etiquettes',
|
||||
'Menu:TagAdminMenu+' => 'Gestion des étiquettes',
|
||||
'UI:TagAdminMenu:Title' => 'Gestion des étiquettes',
|
||||
'UI:TagSetFieldData:Error' => 'Erreur: %1$s',
|
||||
));
|
||||
|
||||
|
||||
|
||||
152
pages/tagadmin.php
Normal file
152
pages/tagadmin.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
// Copyright (C) 2010-2018 Combodo SARL
|
||||
//
|
||||
// This file is part of iTop.
|
||||
//
|
||||
// iTop is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// iTop is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
|
||||
/**
|
||||
* Page to configuration the tag sets
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2018 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
require_once('../approot.inc.php');
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/itopwebpage.class.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
require_once(APPROOT.'application/loginwebpage.class.inc.php');
|
||||
|
||||
try
|
||||
{
|
||||
LoginWebPage::DoLogin();
|
||||
// Check user rights and prompt if needed
|
||||
ApplicationMenu::CheckMenuIdEnabled("TagAdminMenu");
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
|
||||
// Main program
|
||||
//
|
||||
$oP = new iTopWebPage(Dict::S('Menu:TagAdminMenu+'));
|
||||
$oP->add_linked_script("../js/json.js");
|
||||
$oP->add_linked_script("../js/forms-json-utils.js");
|
||||
$oP->add_linked_script("../js/wizardhelper.js");
|
||||
$oP->add_linked_script("../js/wizard.utils.js");
|
||||
$oP->add_linked_script("../js/linkswidget.js");
|
||||
$oP->add_linked_script("../js/extkeywidget.js");
|
||||
$oP->add_linked_script("../js/jquery.blockUI.js");
|
||||
|
||||
$sBaseClass = 'TagSetFieldData';
|
||||
$sClass = utils::ReadParam('class', '', false, 'class');
|
||||
$sOQLClause = utils::ReadParam('oql_clause', '', false, 'raw_data');
|
||||
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
$oP->add('<div class="page_header" style="padding:0.5em;">');
|
||||
$oP->add('<h1>'.dict::S('UI:TagAdminMenu:Title').'</h1>');
|
||||
$oP->add('</div>');
|
||||
|
||||
$oP->SetBreadCrumbEntry('ui-tool-tag-admin', Dict::S('Menu:TagAdminMenu'), Dict::S('Menu:TagAdminMenu+'));
|
||||
|
||||
$sSearchHeaderForceDropdown = '<select id="select_class" name="class" onChange="this.form.submit();">';
|
||||
$aClassLabels = array();
|
||||
foreach(MetaModel::EnumChildClasses($sBaseClass) as $sCurrentClass)
|
||||
{
|
||||
$aClassLabels[$sCurrentClass] = MetaModel::GetName($sCurrentClass);
|
||||
}
|
||||
asort($aClassLabels);
|
||||
foreach($aClassLabels as $sCurrentClass => $sLabel)
|
||||
{
|
||||
if (empty($sClass))
|
||||
{
|
||||
$sClass = $sCurrentClass;
|
||||
}
|
||||
$aTagFieldInfo = TagSetFieldData::ExtractTagFieldName($sCurrentClass);
|
||||
$sClassDesc = MetaModel::GetName($aTagFieldInfo['tag_class']);
|
||||
$sAttDesc = MetaModel::GetAttributeDef($aTagFieldInfo['tag_class'], $aTagFieldInfo['tag_attcode'])->GetLabel();
|
||||
$sDescription = Dict::Format('Core:TagSetFieldData:FieldDescription', $sClassDesc, $sAttDesc);
|
||||
$sSelected = ($sCurrentClass == $sClass) ? " SELECTED" : "";
|
||||
$sSearchHeaderForceDropdown .= "<option value=\"$sCurrentClass\" title=\"$sDescription\"$sSelected>$sDescription</option>";
|
||||
}
|
||||
$sSearchHeaderForceDropdown .= "</select>\n";
|
||||
|
||||
try
|
||||
{
|
||||
if ($sOperation == 'search_form')
|
||||
{
|
||||
$sOQL = "SELECT $sClass $sOQLClause";
|
||||
$oFilter = DBObjectSearch::FromOQL($sOQL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second part: advanced search form:
|
||||
if (!empty($sFilter))
|
||||
{
|
||||
$oFilter = DBSearch::unserialize($sFilter);
|
||||
}
|
||||
else if (!empty($sClass))
|
||||
{
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CoreException $e)
|
||||
{
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
$oP->P("<b>".Dict::Format('UI:TagSetFieldData:Error', $e->getHtmlDesc())."</b>");
|
||||
}
|
||||
|
||||
if ($oFilter != null)
|
||||
{
|
||||
$oSet = new CMDBObjectSet($oFilter);
|
||||
$oBlock = new DisplayBlock($oFilter, 'search', false);
|
||||
$aExtraParams = $oAppContext->GetAsHash();
|
||||
$aExtraParams['open'] = true;
|
||||
$aExtraParams['class'] = $sClass;
|
||||
$aExtraParams['action'] = utils::GetAbsoluteUrlAppRoot().'pages/tagadmin.php';
|
||||
$aExtraParams['table_id'] = '1';
|
||||
$aExtraParams['search_header_force_dropdown'] = $sSearchHeaderForceDropdown;
|
||||
$oBlock->Display($oP, 0, $aExtraParams);
|
||||
|
||||
// Search results
|
||||
$oResultBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
$oResultBlock->Display($oP, 1);
|
||||
|
||||
// Breadcrumb
|
||||
//$iCount = $oBlock->GetDisplayedCount();
|
||||
$sPageId = "ui-search-".$oFilter->GetClass();
|
||||
$sLabel = MetaModel::GetName($oFilter->GetClass());
|
||||
$oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', '../images/breadcrumb-search.png');
|
||||
|
||||
// Menu node
|
||||
$sFilter = $oFilter->ToOQL();
|
||||
$oP->add("\n<!-- $sFilter -->\n");
|
||||
}
|
||||
$oP->add("</div>\n");
|
||||
|
||||
$oP->output();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
require_once(APPROOT.'setup/setuppage.class.inc.php');
|
||||
|
||||
$oP = new SetupPage(Dict::S('UI:PageTitle:FatalError'));
|
||||
$oP->add("<h1>".Dict::S('UI:FatalErrorMessage')."</h1>\n");
|
||||
//$oP->error(Dict::Format('UI:Error_Details', $e->getMessage()));
|
||||
$oP->output();
|
||||
|
||||
IssueLog::Error($e->getMessage());
|
||||
}
|
||||
@@ -2671,7 +2671,7 @@ EOF;
|
||||
* @param bool $bIsAbstractClass
|
||||
* @param string $sMethods
|
||||
*
|
||||
* @param string $aRequiredFiles
|
||||
* @param array $aRequiredFiles
|
||||
* @param string $sCodeComment
|
||||
*
|
||||
* @return string php code for the class
|
||||
|
||||
Reference in New Issue
Block a user