mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-15 08:24:10 +01:00
Compare commits
21 Commits
feature/at
...
faf/operat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93600de728 | ||
|
|
98d153fb60 | ||
|
|
8d14753aca | ||
|
|
5eb764293b | ||
|
|
ca5032b9f5 | ||
|
|
dd4c2f2482 | ||
|
|
4d88ef6ed4 | ||
|
|
5cb1102e6e | ||
|
|
bf23e4d98d | ||
|
|
8645b28baa | ||
|
|
eff6fcff49 | ||
|
|
994b08f94a | ||
|
|
19495d8acf | ||
|
|
48a3ea1945 | ||
|
|
a11b2845f7 | ||
|
|
ee72325451 | ||
|
|
ebb59d3ddc | ||
|
|
0193db609d | ||
|
|
ea2caed98a | ||
|
|
09c092782c | ||
|
|
a4166f874e |
18
README.md
18
README.md
@@ -76,7 +76,9 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
|
||||
### Names
|
||||
|
||||
- Al Hallak, Amr (a.k.a [@v4yne1](https://github.com/v4yne1))
|
||||
- Alves, David
|
||||
- Audon, Florian
|
||||
- Beck, Pedro
|
||||
- Beer, Christian (a.k.a [@ChristianBeer](https://www.github.com/ChristianBeer))
|
||||
- Bilger, Jean-François
|
||||
@@ -88,20 +90,26 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
- Colantoni, Maria Laura
|
||||
- Couronné, Guy
|
||||
- Dejin, Bie (a.k.a [@bdejin](https://github.com/bdejin))
|
||||
- Delicado, Elodie
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Giuva, Vincenzo Katriel (a.k.a [@DarkNight97boss](https://github.com/DarkNight97boss))
|
||||
- Gumble, David
|
||||
- Heloir, Arthur
|
||||
- Janssens, Jelle (a.k.a [@janssensjelle](https://github.com/janssensjelle))
|
||||
- Ji, Leeb (冀利斌) (a.k.a [@chileeb](https://github.com/chileeb))
|
||||
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
- Kunin, Vladimir
|
||||
- Lassiter, Dennis
|
||||
- Lassiter, Denis (a.k.a [@delassiter](https://github.com/delassiter))
|
||||
- Lazcano, Federico
|
||||
- Lucas, Jonathan
|
||||
- Malik, Remie
|
||||
- Mantel, Ina
|
||||
- Martin, Pierre (a.k.a [@Worty](https://github.com/worty-syn))
|
||||
- Melchiorre, Romain
|
||||
- Mindêllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam))
|
||||
- Mozart de Oliveira, Eduardo (a.k.a [@eduardomozart](https://github.com/eduardomozart))
|
||||
- Raenker, Martin
|
||||
@@ -113,10 +121,12 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Stetina, Pavel (a.k.a [@Stetinac](https://github.com/Stetinac))
|
||||
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
|
||||
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya-stukalov))
|
||||
- Tarjányi, Csaba (a.k.a [@tacsaby](https://github.com/tacsaby))
|
||||
- Toraya, Chairat (a.k.a [@Kyokito1412](https://github.com/Kyokito1412))
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
- Višnjić, Aldin (a.k.a[@viliald](https://github.com/viliald))
|
||||
- Vlk, Karel (a.k.a [@vlk-charles](https://www.github.com/vlk-charles))
|
||||
|
||||
### Aliases
|
||||
@@ -138,4 +148,6 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
- [ITOMIG](https://www.itomig.de/)
|
||||
- [Pimkie](https://www.pimkie.com/)
|
||||
- [Super-Visions](https://www.super-visions.com/)
|
||||
|
||||
- [Defence Tech Cyber Security - Malware Lab](https://github.com/DefenceTechSecurity)
|
||||
- Orange Cyberdefense
|
||||
- MipihSIB
|
||||
|
||||
@@ -533,6 +533,11 @@ JS
|
||||
$sLabel = Dict::S('Tag:Synchronized');
|
||||
$sSynchroTagId = 'synchro_icon-'.$this->GetKey();
|
||||
$aTags[$sSynchroTagId] = ['title' => $sTip, 'css_classes' => 'ibo-object-details--tag--synchronized', 'decoration_classes' => 'fas fa-lock', 'label' => $sLabel];
|
||||
if (UserRights::IsActionAllowed('SynchroReplica', UR_ACTION_READ)) {
|
||||
$sFilter = 'SELECT SynchroReplica WHERE dest_class=\''.get_class($this).'\' AND dest_id='.$this->GetKey();
|
||||
$sUrlSearchReplica = 'UI.php?operation=search&filter='.urlencode(json_encode([$sFilter, [], []]));
|
||||
$oPage->add_ready_script("$('#$sSynchroTagId').on('click',function() {window.location = '$sUrlSearchReplica' });");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2030,7 +2030,7 @@ class MenuBlock extends DisplayBlock
|
||||
$sSelectedClassName = MetaModel::GetName($sSelectedClass);
|
||||
|
||||
// Check rights on class
|
||||
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY) && ($oReflectionClass->IsSubclassOf('cmdbAbstractObject'));
|
||||
$bIsBulkModifyAllowed = (!MetaModel::IsAbstract($sSelectedClass)) && UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_MODIFY) && (($oReflectionClass->IsSubclassOf('cmdbAbstractObject') || $sSelectedClass === 'SynchroReplica'));
|
||||
$bIsBulkDeleteAllowed = (bool) UserRights::IsActionAllowed($sSelectedClass, UR_ACTION_BULK_DELETE);
|
||||
|
||||
// Refine filter on selected class so bullk actions occur on the right class
|
||||
@@ -2041,7 +2041,15 @@ class MenuBlock extends DisplayBlock
|
||||
// Action label dict code has a specific suffix for "Link" / "Remote" aliases to allow dedicated labels in linksets.
|
||||
$sActionLabelCodeSuffix = in_array($sSelectedAlias, ['Link', 'Remote']) ? $sSelectedAlias : 'Class';
|
||||
if ($bIsBulkModifyAllowed) {
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:ModifyAll:'.$sSelectedAlias, Dict::Format('UI:Menu:ModifyAll_'.$sActionLabelCodeSuffix, $sSelectedClassName));
|
||||
if($sSelectedClass === 'SynchroReplica'){
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:UnlinkAll:', Dict::S('Class:SynchroReplica/Action:unlink_all'),'unlink');
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:UnLinkSynchroAll:', Dict::S('Class:SynchroReplica/Action:unlinksynchro_all'),'unlinksynchro');
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:SynchroAll:', Dict::S('Class:SynchroReplica/Action:synchro_all'),'synchro');
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:AllowDeleteAll:', Dict::S('Class:SynchroReplica/Action:allowdelete_all'),'allowdelete');
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:DenyDeleteAll:', Dict::S('Class:SynchroReplica/Action:denydelete_all'),'denydelete');
|
||||
} else {
|
||||
$this->AddBulkModifyObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:ModifyAll:'.$sSelectedAlias, Dict::Format('UI:Menu:ModifyAll_'.$sActionLabelCodeSuffix, $sSelectedClassName));
|
||||
}
|
||||
}
|
||||
if ($bIsBulkDeleteAllowed) {
|
||||
$this->AddBulkDeleteObjectsMenuAction($aRegularActions, $sSelectedClass, $oSelectedClassFilter->serialize(), 'UI:Menu:BulkDelete:'.$sSelectedAlias, Dict::Format('UI:Menu:BulkDelete_'.$sActionLabelCodeSuffix, $sSelectedClassName));
|
||||
@@ -2523,11 +2531,11 @@ class MenuBlock extends DisplayBlock
|
||||
* @since 3.1.0
|
||||
* @internal
|
||||
*/
|
||||
protected function AddBulkModifyObjectsMenuAction(array &$aActions, string $sClass, string $sFilter, string $sActionIdentifier = 'UI:Menu:ModifyAll', $sActionLabel = 'UI:Menu:ModifyAll'): void
|
||||
protected function AddBulkModifyObjectsMenuAction(array &$aActions, string $sClass, string $sFilter, string $sActionIdentifier = 'UI:Menu:ModifyAll', $sActionLabel = 'UI:Menu:ModifyAll', $sOperationName = 'modify'): void
|
||||
{
|
||||
$aActions[$sActionIdentifier] = [
|
||||
'label' => Dict::S($sActionLabel),
|
||||
'url' => $this->PrepareUrlForStandardMenuAction($sClass, "operation=select_for_modify_all&class=$sClass&filter=".urlencode($sFilter)),
|
||||
'url' => $this->PrepareUrlForStandardMenuAction($sClass, 'operation=select_for_'.$sOperationName.'_all&class='.$sClass.'&filter='.urlencode($sFilter)),
|
||||
] + $this->GetDefaultParamsForMenuAction();
|
||||
}
|
||||
|
||||
|
||||
@@ -3082,13 +3082,17 @@ class AttributeObjectKey extends AttributeDBFieldVoid
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (MetaModel::IsValidObject($proposedValue))
|
||||
{
|
||||
if (MetaModel::IsValidObject($proposedValue)) {
|
||||
return $proposedValue->GetKey();
|
||||
}
|
||||
|
||||
return (int)$proposedValue;
|
||||
}
|
||||
|
||||
public function GetTargetClass($iType = EXTKEY_RELATIVE)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -133,6 +133,7 @@ if (!defined('PORTAL_ID'))
|
||||
|
||||
// Env. vars to be used in templates and others
|
||||
$_ENV['COMBODO_CURRENT_ENVIRONMENT'] = utils::GetCurrentEnvironment();
|
||||
$_ENV['COMBODO_APPROOT'] = APPROOT;
|
||||
$_ENV['COMBODO_ABSOLUTE_URL'] = utils::GetAbsoluteUrlAppRoot();
|
||||
$_ENV['COMBODO_CONF_APP_ICON_URL'] = MetaModel::GetConfig()->Get('app_icon_url');
|
||||
$_ENV['COMBODO_MODULES_ABSOLUTE_URL'] = utils::GetAbsoluteUrlModulesRoot();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
twig:
|
||||
default_path: '%combodo.modules.absolute_path%'
|
||||
paths:
|
||||
'%combodo.approot%images/': ~
|
||||
debug: '%kernel.debug%'
|
||||
strict_variables: '%kernel.debug%'
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ parameters:
|
||||
|
||||
# Used in templates
|
||||
combodo.current_environment: '%env(string:COMBODO_CURRENT_ENVIRONMENT)%'
|
||||
combodo.approot: '%env(string:COMBODO_APPROOT)%'
|
||||
combodo.absolute_url: '%env(string:COMBODO_ABSOLUTE_URL)%'
|
||||
combodo.conf.app_icon_url: '%env(string:COMBODO_CONF_APP_ICON_URL)%'
|
||||
combodo.modules.absolute_url: '%env(string:COMBODO_MODULES_ABSOLUTE_URL)%'
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -4,5 +4,6 @@
|
||||
@import "button";
|
||||
@import "modal";
|
||||
@import "form";
|
||||
@import "illustration";
|
||||
@import "input";
|
||||
@import "caselog";
|
||||
@@ -7,6 +7,8 @@ $ipb--fieldset--border-radius: $common-border-radius-500 !default;
|
||||
$ipb--fieldset--legend--padding-y: $common-spacing-0 !default;
|
||||
$ipb--fieldset--legend--padding-x: 13px !default;
|
||||
|
||||
$ipb--fieldset--inside--fieldset--background-color: $common-color-grey-100 !default;
|
||||
|
||||
$ipb-field--has-tooltip-or-is-mandatory--vertical-align: top !default;
|
||||
$ipb-field--has-tooltip-or-is-mandatory--left: $common-spacing-200 !default;
|
||||
|
||||
@@ -19,13 +21,16 @@ $ipb-field--is-mandatory--font-size: 0.6rem !default;
|
||||
|
||||
.form_fields {
|
||||
fieldset {
|
||||
background-color: $common-color-grey-50;
|
||||
background-color: $ipb--fieldset--background-color;
|
||||
padding: $ipb--fieldset--padding-y $ipb--fieldset--padding-x;
|
||||
border-radius: $ipb--fieldset--border-radius;
|
||||
border: $ipb--fieldset--border;
|
||||
legend {
|
||||
padding: $ipb--fieldset--legend--padding-y $ipb--fieldset--legend--padding-x;
|
||||
}
|
||||
fieldset {
|
||||
background-color: $ipb--fieldset--inside--fieldset--background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
$ipb-svg-illustration--fill: $common-svg-illustration--fill !default;
|
||||
|
||||
|
||||
.ipb-svg-illustration--container > svg *[fill="#6c63ff"]{
|
||||
fill: $ipb-svg-illustration--fill;
|
||||
}
|
||||
@@ -1,13 +1,22 @@
|
||||
$ipb-form-control--color: $common-color-grey-800 !default;
|
||||
$ipb-form-control--border-radius: $common-border-radius-500 !default;
|
||||
$ipb-form-control--border-radius: $common-border-radius-300 !default;
|
||||
$ipb-form-control--box-shadow: none !default;
|
||||
$ipb-form-control--input-group-addon--border-top-right-radius: 0 !default;
|
||||
$ipb-form-control--input-group-addon--border-bottom-right-radius: 0 !default;
|
||||
|
||||
$ipb-input-group-addon--border: 1px solid $ipb-color-grey-300 !default;
|
||||
$ipb-input-group-addon--border-radius: $ipb-form-control--border-radius !default;
|
||||
$ipb-input-group-addon--background-color: $common-color-grey-100 !default;
|
||||
$ipb-input-group-addon--color: $common-color-grey-800 !default;
|
||||
$ipb-input-group-addon--form-control--border-top-left-radius: 0 !default;
|
||||
$ipb-input-group-addon--form-control--border-bottom-left-radius: 0 !default;
|
||||
|
||||
$ipb-form-control--is-focused--border-color: $common-color-primary-700 !default;
|
||||
$ipb-form-control--is-focused--box-shadow: none !default;
|
||||
|
||||
.form-control {
|
||||
color: $ipb-form-control--color;
|
||||
border-radius: $common-border-radius-500 !important;
|
||||
border-radius: $ipb-form-control--border-radius;
|
||||
-webkit-box-shadow: $ipb-form-control--box-shadow;
|
||||
box-shadow: $ipb-form-control--box-shadow;
|
||||
&:focus {
|
||||
@@ -15,4 +24,22 @@ $ipb-form-control--is-focused--box-shadow: none !default;
|
||||
box-shadow: $ipb-form-control--is-focused--box-shadow;
|
||||
-webkit-box-shadow: $ipb-form-control--is-focused--box-shadow;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control:has(+ .input-group-addon) {
|
||||
border-top-right-radius: $ipb-form-control--input-group-addon--border-top-right-radius;
|
||||
border-bottom-right-radius: $ipb-form-control--input-group-addon--border-bottom-right-radius;
|
||||
}
|
||||
|
||||
.input-group-addon {
|
||||
border: $ipb-input-group-addon--border;
|
||||
border-radius: $ipb-input-group-addon--border-radius;
|
||||
background-color: $ipb-input-group-addon--background-color;
|
||||
color: $ipb-input-group-addon--color;
|
||||
|
||||
}
|
||||
|
||||
.form-control + .input-group-addon {
|
||||
border-top-left-radius: $ipb-input-group-addon--form-control--border-top-left-radius;
|
||||
border-bottom-left-radius: $ipb-input-group-addon--form-control--border-bottom-left-radius;
|
||||
}
|
||||
@@ -8,6 +8,7 @@ $ipb-modal--max-height: 90vh !default;
|
||||
$ipb-modal--max-width: 90vw !default;
|
||||
$ipb-modal--border-radius: $common-border-radius-500 !default;
|
||||
|
||||
$ipb-modal--header--padding: $common-spacing-500 !default;
|
||||
$ipb-modal--header--background-color: $common-color-white-100 !default;
|
||||
$ipb-modal--header--color: $common-color-grey-900 !default;
|
||||
$ipb-modal--header--border-radius: $ipb-modal--border-radius $ipb-modal--border-radius 0 0 !default;
|
||||
@@ -16,6 +17,8 @@ $ipb-modal--header--close--color: $common-color-grey-900 !default;
|
||||
$ipb-modal--header--close--opacity: 1 !default;
|
||||
$ipb-modal--header--close--hover--color: $common-color-grey-700 !default;
|
||||
|
||||
$ipb-modal--footer-padding: $ipb-modal--header--padding !default;
|
||||
|
||||
$ipb-modal--backdrop--opacity: 0.6 !default;
|
||||
$ipb-modal--backdrop--background-color: $common-color-blue-grey-800 !default;
|
||||
$ipb-modal--backdrop--backdrop-filter: blur(2px) !default;
|
||||
@@ -26,9 +29,10 @@ $ipb-modal--content--border: 1px solid $common-color-grey-400 !default;
|
||||
$ipb-modal--title--color: $ipb-modal--header--color !default;
|
||||
$ipb-modal--title--to-clipboard--margin: $common-spacing-200 !default;
|
||||
$ipb-modal--title--span--margin-left: 5px !default;
|
||||
$ipb-modal--title--span--separator--margin-right: $common-spacing-200 !default;
|
||||
$ipb-modal--title--span--separator--width: $common-size-100 !default;
|
||||
$ipb-modal--title--span--separator--height: $ipb-modal--title--span--separator--width !default;
|
||||
$ipb-modal--title--span--separator--margin-right: $common-spacing-200 !default;
|
||||
$ipb-modal--title--span--separator--margin-top: calc(-1 * #{$ipb-modal--title--span--separator--height} / 2) !default;
|
||||
$ipb-modal--title--span--separator--border-radius: $common-border-radius-full !default;
|
||||
$ipb-modal--title--span--separator--background-color: $common-color-grey-800 !default;
|
||||
|
||||
@@ -60,6 +64,7 @@ $ipb-modal--title--span--separator--background-color: $common-color-grey-800 !de
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: $ipb-modal--header--padding;
|
||||
border-radius:$ipb-modal--header--border-radius !important;
|
||||
.close {
|
||||
color: $ipb-modal--header--close--color;
|
||||
@@ -72,6 +77,10 @@ $ipb-modal--title--span--separator--background-color: $common-color-grey-800 !de
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: $ipb-modal--footer-padding;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
color: $ipb-modal--title--color !important;
|
||||
display: flex;
|
||||
@@ -84,6 +93,7 @@ $ipb-modal--title--span--separator--background-color: $common-color-grey-800 !de
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: $ipb-modal--title--span--separator--margin-right;
|
||||
margin-top: $ipb-modal--title--span--separator--margin-top;
|
||||
width: $ipb-modal--title--span--separator--width;
|
||||
height: $ipb-modal--title--span--separator--height;
|
||||
border-radius: $ipb-modal--title--span--separator--border-radius;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "navigation-menu";
|
||||
@import "page";
|
||||
@import "home";
|
||||
@import "home";
|
||||
@import "tabs";
|
||||
@@ -0,0 +1,55 @@
|
||||
$ipb-tabs--tab--border: solid 1px $common-color-grey-400 !default;
|
||||
$ipb-tabs--tab--badge--border-radius: $common-border-radius-500 !default;
|
||||
$ipb-tabs--tab--badge--padding-y: 3px !default;
|
||||
$ipb-tabs--tab--badge--padding-x: 5px !default;
|
||||
$ipb-tabs--tab--badge--margin-left: $common-spacing-200 !default;
|
||||
|
||||
$ipb-tabs--tab--background-color: $common-color-grey-100 !default;
|
||||
$ipb-tabs--tab--color: $common-color-grey-900 !default;
|
||||
$ipb-tabs--tab--active--background-color: $common-color-white-100 !default;
|
||||
$ipb-tabs--tab--active--badge--background-color: $common-color-grey-200 !default;
|
||||
$ipb-tabs--tab--active--indicator--background-color: $common-color-primary-600 !default;
|
||||
$ipb-tabs--tab--active--indicator--width: $common-size-150 !default;
|
||||
$ipb-tabs--tab--active--indicator--height: $ipb-tabs--tab--active--indicator--width !default;
|
||||
$ipb-tabs--tab--active--indicator--margin-right: $common-spacing-300 !default;
|
||||
$ipb-tabs--tab--active--indicator--border-radius: $common-border-radius-full !default;
|
||||
|
||||
.ipb-tabs.nav-pills > li{
|
||||
> a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: $ipb-tabs--tab--background-color;
|
||||
color: $ipb-tabs--tab--color;
|
||||
|
||||
@extend %common-font-ral-med-150;
|
||||
|
||||
> .badge {
|
||||
color: $common-color-grey-900;
|
||||
background-color: transparent;
|
||||
border-radius: $ipb-tabs--tab--badge--border-radius;
|
||||
padding: $ipb-tabs--tab--badge--padding-y $ipb-tabs--tab--badge--padding-x;
|
||||
margin-left: $ipb-tabs--tab--badge--margin-left;
|
||||
}
|
||||
|
||||
border: $ipb-tabs--tab--border;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.active > a {
|
||||
background-color: $ipb-tabs--tab--active--background-color;
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
width: $ipb-tabs--tab--active--indicator--width;
|
||||
height: $ipb-tabs--tab--active--indicator--height;
|
||||
margin-right: $ipb-tabs--tab--active--indicator--margin-right;
|
||||
border-radius: $ipb-tabs--tab--active--indicator--border-radius;
|
||||
background-color: $ipb-tabs--tab--active--indicator--background-color;
|
||||
}
|
||||
|
||||
> .badge {
|
||||
background-color: $ipb-tabs--tab--active--badge--background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,8 @@
|
||||
/* SCSS variables */
|
||||
$ipb-following-dot--size: $common-size-150 !default;
|
||||
$ipb-following-dot--color: $common-color-orange-600 !default;
|
||||
$ipb-following-dot--margin-y: auto !default;
|
||||
$ipb-following-dot--margin-top: calc(-1 * #{$ipb-following-dot--size} / 2) !default;
|
||||
$ipb-following-dot--margin-bottom: auto !default;
|
||||
$ipb-following-dot--margin-x: $common-spacing-300 !default;
|
||||
|
||||
@mixin ipb-following-dot($size:$ipb-following-dot--size, $color:$ipb-following-dot--color) {
|
||||
@@ -12,7 +13,7 @@ $ipb-following-dot--margin-x: $common-spacing-300 !default;
|
||||
background-color: $color;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin: $ipb-following-dot--margin-y $ipb-following-dot--margin-x;
|
||||
margin: $ipb-following-dot--margin-top $ipb-following-dot--margin-x $ipb-following-dot--margin-bottom $ipb-following-dot--margin-x;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,13 @@ $ipb-browse-brick--list-group-item--tree-item-wrapper--padding-bottom: $common-s
|
||||
$ipb-browse-brick--list-group--tree--margin: $common-spacing-0 !default;
|
||||
$ipb-browse-brick--list-group--tree--background-color: $common-color-white-100 !default;
|
||||
|
||||
$ipb-browse-brick--no-item--illustration--max-width: 100% !default;
|
||||
$ipb-browse-brick--no-item--illustration--padding-y: $common-spacing-600 !default;
|
||||
$ipb-browse-brick--no-item--illustration--padding-x: $common-spacing-500 !default;
|
||||
$ipb-browse-brick--no-item--illustration--svg--max-width: $common-size-700 !default;
|
||||
|
||||
$ipb-browse-brick--no-item--text--color: $ipb-color-grey-800 !default;
|
||||
|
||||
// Common
|
||||
.ipb-browse-brick-panel {
|
||||
.row {
|
||||
@@ -380,4 +387,21 @@ $ipb-browse-brick--list-group--tree--background-color: $common-color-white-100 !
|
||||
.list-group.tree {
|
||||
margin: $ipb-browse-brick--list-group--tree--margin;
|
||||
background-color: $ipb-browse-brick--list-group--tree--background-color;
|
||||
}
|
||||
|
||||
.ipb-browse-brick--no-item--illustration {
|
||||
width: $ipb-browse-brick--no-item--illustration--max-width;
|
||||
display: flex;
|
||||
flex-direction: column;;
|
||||
padding: $ipb-browse-brick--no-item--illustration--padding-y $ipb-browse-brick--no-item--illustration--padding-x;
|
||||
> svg {
|
||||
max-width: $ipb-browse-brick--no-item--illustration--svg--max-width;
|
||||
height: inherit;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ipb-browse-brick--no-item--text {
|
||||
color: $ipb-browse-brick--no-item--text--color;
|
||||
@extend %common-font-ral-med-300;
|
||||
}
|
||||
@@ -7,24 +7,16 @@ $ipb-manage-brick--panel--body--datatable--row--margin: $common-spacing-0 !defau
|
||||
$ipb-manage-brick--panel--body--datatable--row--padding-y: $common-spacing-0 !default;
|
||||
$ipb-manage-brick--panel--body--datatable--row--padding-x: $common-spacing-400 !default;
|
||||
|
||||
$ipb-manage-brick--tabs--tab--border: solid 1px $common-color-grey-400 !default;
|
||||
$ipb-manage-brick--tabs--tab--badge--border-radius: $common-border-radius-500 !default;
|
||||
$ipb-manage-brick--tabs--tab--badge--padding-y: 3px !default;
|
||||
$ipb-manage-brick--tabs--tab--badge--padding-x: 5px !default;
|
||||
$ipb-manage-brick--tabs--tab--badge--margin-left: $common-spacing-200 !default;
|
||||
|
||||
$ipb-manage-brick--tabs--tab--background-color: $common-color-grey-100 !default;
|
||||
$ipb-manage-brick--tabs--tab--color: $common-color-grey-900 !default;
|
||||
$ipb-manage-brick--tabs--tab--active--background-color: $common-color-white-100 !default;
|
||||
$ipb-manage-brick--tabs--tab--active--badge--background-color: $common-color-grey-200 !default;
|
||||
$ipb-manage-brick--tabs--tab--active--indicator--background-color: $common-color-primary-600 !default;
|
||||
$ipb-manage-brick--tabs--tab--active--indicator--width: $common-size-150 !default;
|
||||
$ipb-manage-brick--tabs--tab--active--indicator--height: $ipb-manage-brick--tabs--tab--active--indicator--width !default;
|
||||
$ipb-manage-brick--tabs--tab--active--indicator--margin-right: $common-spacing-300 !default;
|
||||
$ipb-manage-brick--tabs--tab--active--indicator--border-radius: $common-border-radius-full !default;
|
||||
|
||||
$ipb-manage-brick--panel--body--table--margin-top: $common-spacing-500 !default;
|
||||
|
||||
$ipb-manage-brick--no-result--illustration--width: 100% !default;
|
||||
$ipb-manage-brick--no-result--illustration--padding-y: $common-spacing-600 !default;
|
||||
$ipb-manage-brick--no-result--illustration--padding-x: $common-spacing-500 !default;
|
||||
$ipb-manage-brick--no-result--illustration--svg--max-width: $common-size-700 !default;
|
||||
|
||||
$ipb-manage-brick--no-result--text--color: $common-color-grey-800 !default;
|
||||
|
||||
.ipb-manage-brick--panel--body {
|
||||
padding: $ipb-manage-brick--panel--body--padding-y $ipb-manage-brick--panel--body--padding-x 0 $ipb-manage-brick--panel--body--padding-x;
|
||||
|
||||
@@ -40,45 +32,7 @@ $ipb-manage-brick--panel--body--table--margin-top: $common-spacing-500 !default;
|
||||
|
||||
|
||||
}
|
||||
.ipb-manage-brick--tabs.grouping_tabs.nav-pills > li{
|
||||
> a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: $ipb-manage-brick--tabs--tab--background-color;
|
||||
color: $ipb-manage-brick--tabs--tab--color;
|
||||
|
||||
@extend %common-font-ral-med-150;
|
||||
|
||||
> .badge {
|
||||
color: $common-color-grey-900;
|
||||
background-color: transparent;
|
||||
border-radius: $ipb-manage-brick--tabs--tab--badge--border-radius;
|
||||
padding: $ipb-manage-brick--tabs--tab--badge--padding-y $ipb-manage-brick--tabs--tab--badge--padding-x;
|
||||
margin-left: $ipb-manage-brick--tabs--tab--badge--margin-left;
|
||||
}
|
||||
|
||||
border: $ipb-manage-brick--tabs--tab--border;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.active > a {
|
||||
background-color: $ipb-manage-brick--tabs--tab--active--background-color;
|
||||
|
||||
&:before {
|
||||
content: " ";
|
||||
display: inline-block;
|
||||
width: $ipb-manage-brick--tabs--tab--active--indicator--width;
|
||||
height: $ipb-manage-brick--tabs--tab--active--indicator--height;
|
||||
margin-right: $ipb-manage-brick--tabs--tab--active--indicator--margin-right;
|
||||
border-radius: $ipb-manage-brick--tabs--tab--active--indicator--border-radius;
|
||||
background-color: $ipb-manage-brick--tabs--tab--active--indicator--background-color;
|
||||
}
|
||||
|
||||
> .badge {
|
||||
background-color: $ipb-manage-brick--tabs--tab--active--badge--background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ipb-manage-brick--panel--body--table {
|
||||
margin-top: $ipb-manage-brick--panel--body--table--margin-top !important;
|
||||
@@ -115,4 +69,21 @@ $common-color-blue-300 $common-color-blue-950 "rgb(255, 127, 14)"
|
||||
.c3-chart-arc:has(path[style="fill: #{$originalColor}; cursor: pointer; opacity: 1;"]) text {
|
||||
fill: $text !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ipb-manage-brick--no-result--illustration {
|
||||
width: $ipb-manage-brick--no-result--illustration--width;
|
||||
display: flex;
|
||||
flex-direction: column;;
|
||||
padding: $ipb-manage-brick--no-result--illustration--padding-y $ipb-manage-brick--no-result--illustration--padding-x;
|
||||
> svg {
|
||||
max-width: $ipb-manage-brick--no-result--illustration--svg--max-width;
|
||||
height: inherit;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ipb-manage-brick--no-result--text {
|
||||
color: $ipb-manage-brick--no-result--text--color;
|
||||
@extend %common-font-ral-med-300;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
/* SCSS variables */
|
||||
$form-control--border-radius: $common-border-radius-300 !default;
|
||||
|
||||
|
||||
.form-control {
|
||||
border-radius: $form-control--border-radius!important;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@ $ipb-vendors--datatables--paginate-button--disabled--colors: map-get(map-get(map
|
||||
$ipb-vendors--datatables--paginate-button--active--colors: map-get(map-get(map-get($ipb-button-colors, ''), 'primary'), '') !default;
|
||||
$ipb-vendors--datatables--paginate-button--active--hover--colors: map-get(map-get(map-get($ipb-button-colors, ''), 'primary'), ':hover') !default;
|
||||
|
||||
$ipb-vendors-datatables--row--background-color--is-odd: $common-color-white-100 !default;
|
||||
$ipb-vendors-datatables--row--background-color--is-even: $common-color-white-200 !default;
|
||||
$ipb-vendors-datatables--row--is-odd--background-color: $common-color-white-100 !default;
|
||||
$ipb-vendors-datatables--row--is-even--background-color: $common-color-white-200 !default;
|
||||
$ipb-vendors-datatables--row--is-selected--color: $common-color-blue-900 !default;
|
||||
$ipb-vendors-datatables--row--is-selected--background-color: $common-color-blue-200 !default;
|
||||
$ipb-vendors-datatables--row--is-selected--hover--background-color: $common-color-blue-100 !default;
|
||||
|
||||
$ipb-vendors-datatables--row-highlight--first-cell--width: 3px !default;
|
||||
|
||||
@@ -60,10 +63,10 @@ $ipb-vendors-datatables--row-highlight--first-cell--colors:(
|
||||
}
|
||||
|
||||
.table-striped > tbody > tr{
|
||||
background-color: $ipb-vendors-datatables--row--background-color--is-even;
|
||||
background-color: $ipb-vendors-datatables--row--is-even--background-color;
|
||||
cursor: pointer;
|
||||
&:nth-of-type(2n+1) {
|
||||
background-color: $ipb-vendors-datatables--row--background-color--is-odd;
|
||||
background-color: $ipb-vendors-datatables--row--is-odd--background-color;
|
||||
}
|
||||
@each $sColorLabel, $aAttributes in $ipb-vendors-datatables--row-highlight--colors {
|
||||
$sBgColor: nth($aAttributes, 1);
|
||||
@@ -133,4 +136,16 @@ $ipb-vendors-datatables--row-highlight--first-cell--colors:(
|
||||
|
||||
.dataTables_length, .dataTables_filter, .dataTables_info {
|
||||
@extend %common-font-ral-nor-150;
|
||||
}
|
||||
|
||||
table.dataTable {
|
||||
> thead, tbody, tfoot {
|
||||
> tr.selected {
|
||||
background-color: $ipb-vendors-datatables--row--is-selected--background-color;
|
||||
color: $ipb-vendors-datatables--row--is-selected--color;
|
||||
&:hover {
|
||||
background-color: $ipb-vendors-datatables--row--is-selected--hover--background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block pMainContentHolder%}
|
||||
{% if iItemsCount > 0 or sSearchValue is not null %}
|
||||
{% if iItemsCount > 0 or sSearchValue is not empty %}
|
||||
{% block bBrowseHeaderContent %}
|
||||
{% endblock %}
|
||||
<div class="ipb-panel ipb-browse-brick-panel panel panel-default">
|
||||
@@ -36,7 +36,8 @@
|
||||
{% else %}
|
||||
<div class="ipb-panel panel panel-default">
|
||||
<div class="ipb-panel--body panel-body">
|
||||
<h3 class="text-center">{{ 'Brick:Portal:Browse:Filter:NoData'|dict_s }}</h3>
|
||||
<div class="ipb-browse-brick--no-item--illustration ipb-svg-illustration--container">{{ source('illustrations/undraw_empty_alternative.svg') }}</div>
|
||||
<h3 class="ipb-browse-brick--no-item--text text-center">{{ 'Brick:Portal:Browse:Filter:NoData'|dict_s }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
{% block pMainContentHolder %}
|
||||
{% if aGroupingTabsValues|length > 1 %}
|
||||
<ul class="ipb-manage-brick--tabs nav nav-pills grouping_tabs">
|
||||
<ul class="ipb-manage-brick--tabs ipb-tabs nav nav-pills grouping_tabs">
|
||||
{% for aGroupingTab in aGroupingTabsValues %}
|
||||
<li{% if sGroupingTab is defined and sGroupingTab == aGroupingTab.value %} class="active"{% endif %} data-id="{{ aGroupingTab.value }}" data-label="{{ aGroupingTab.label }}" data-item-count="{{ aGroupingTab.count }}">
|
||||
<a href="{{ app.url_generator.generate('p_manage_brick_display_as', {'sBrickId': sBrickId, 'sDisplayMode': sDisplayMode, 'sGroupingTab': aGroupingTab.value}) }}"
|
||||
@@ -43,9 +43,10 @@
|
||||
{% endif %}
|
||||
|
||||
{% if iTableCount == 0 %}
|
||||
<div class="panel panel-default">
|
||||
<div class="ipb-panel panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h3 class="text-center">{{ 'Brick:Portal:Manage:Table:NoData'|dict_s }}</h3>
|
||||
<div class="ipb-manage-brick--no-result--illustration ipb-svg-illustration--container">{{ source("illustrations/undraw_empty.svg") }}</div>
|
||||
<h3 class="ipb-manage-brick--no-result--text text-center">{{ 'Brick:Portal:Manage:Table:NoData'|dict_s }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-pills _tabs">
|
||||
<ul class="ipb-tabs nav nav-pills _tabs">
|
||||
{% if aTabsValues is defined and aTabsValues|length > 0 %}
|
||||
<li{% if sTab == "user-info" %} class="active"{% endif %} data-id="user-info" data-label="{{ 'MyAccount:UserInfo:Tab:Title'|dict_s }}">
|
||||
<a href="{{ app.url_generator.generate('p_user_profile_brick', {'sBrickId': oBrick.GetId(), 'sDisplayMode': '_self', 'sTab': "user-info"}) }}"
|
||||
|
||||
@@ -964,8 +964,8 @@ The hyperlink is displayed in the tooltip appearing on the “Lock” symbol of
|
||||
'Class:SynchroDataSource/Error:DataTableAlreadyExists' => 'The table %1$s already exists in the database. Please use another name for the synchro data table.',
|
||||
'Core:SynchroReplica:PublicData' => 'Public Data',
|
||||
'Core:SynchroReplica:PrivateDetails' => 'Private Details',
|
||||
'Core:SynchroReplica:BackToDataSource' => 'Go Back to the Synchro Data Source: %1$s',
|
||||
'Core:SynchroReplica:ListOfReplicas' => 'List of Replica',
|
||||
'Core:SynchroReplica:BackToDataSource' => 'Back to the Synchro Data Source',
|
||||
'Core:SynchroReplica:ListOfReplicas' => 'Replicas of the data source: %1$s',
|
||||
'Core:SynchroAttExtKey:ReconciliationById' => 'id (Primary Key)',
|
||||
'Core:SynchroAtt:attcode' => 'Attribute',
|
||||
'Core:SynchroAtt:attcode+' => 'Field of the object',
|
||||
@@ -1018,66 +1018,100 @@ The hyperlink is displayed in the tooltip appearing on the “Lock” symbol of
|
||||
'Class:SynchroAttLinkSet' => 'Synchro Attribute (Linkset)',
|
||||
'Class:SynchroAttLinkSet/Attribute:row_separator' => 'Rows separator',
|
||||
'Class:SynchroAttLinkSet/Attribute:attribute_separator' => 'Attributes separator',
|
||||
'Class:SynchroLog' => 'Synchr Log',
|
||||
'Class:SynchroLog/Attribute:sync_source_id' => 'Synchro Data Source',
|
||||
'Class:SynchroLog/Attribute:start_date' => 'Start Date',
|
||||
'Class:SynchroLog/Attribute:end_date' => 'End Date',
|
||||
'Class:SynchroLog/Attribute:status' => 'Status',
|
||||
'Class:SynchroLog/Attribute:status/Value:completed' => 'Completed',
|
||||
'Class:SynchroLog/Attribute:status/Value:error' => 'Error',
|
||||
'Class:SynchroLog/Attribute:status/Value:running' => 'Still Running',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_seen' => 'Nb replica seen',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_total' => 'Nb replica total',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_deleted' => 'Nb objects deleted',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_deleted_errors' => 'Nb of errors while deleting',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted' => 'Nb objects obsoleted',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted_errors' => 'Nb of errors while obsoleting',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_created' => 'Nb objects created',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_created_errors' => 'Nb or errors while creating',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_updated' => 'Nb objects updated',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_updated_errors' => 'Nb errors while updating',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_reconciled_errors' => 'Nb of errors during reconciliation',
|
||||
'Class:SynchroLog' => 'Synchr Log',
|
||||
'Class:SynchroLog/Attribute:sync_source_id' => 'Synchro Data Source',
|
||||
'Class:SynchroLog/Attribute:start_date' => 'Start Date',
|
||||
'Class:SynchroLog/Attribute:end_date' => 'End Date',
|
||||
'Class:SynchroLog/Attribute:status' => 'Status',
|
||||
'Class:SynchroLog/Attribute:status/Value:completed' => 'Completed',
|
||||
'Class:SynchroLog/Attribute:status/Value:error' => 'Error',
|
||||
'Class:SynchroLog/Attribute:status/Value:running' => 'Still Running',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_seen' => 'Nb replica seen',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_total' => 'Nb replica total',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_deleted' => 'Nb objects deleted',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_deleted_errors' => 'Nb of errors while deleting',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted' => 'Nb objects obsoleted',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_obsoleted_errors' => 'Nb of errors while obsoleting',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_created' => 'Nb objects created',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_created_errors' => 'Nb or errors while creating',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_updated' => 'Nb objects updated',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_updated_errors' => 'Nb errors while updating',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_reconciled_errors' => 'Nb of errors during reconciliation',
|
||||
'Class:SynchroLog/Attribute:stats_nb_replica_disappeared_no_action' => 'Nb replica disappeared',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_new_updated' => 'Nb objects updated',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_new_unchanged' => 'Nb objects unchanged',
|
||||
'Class:SynchroLog/Attribute:last_error' => 'Last error',
|
||||
'Class:SynchroLog/Attribute:traces' => 'Traces',
|
||||
'Class:SynchroReplica' => 'Synchro Replica',
|
||||
'Class:SynchroReplica/Attribute:sync_source_id' => 'Synchro Data Source',
|
||||
'Class:SynchroReplica/Attribute:dest_id' => 'Destination object (ID)',
|
||||
'Class:SynchroReplica/Attribute:dest_class' => 'Destination type',
|
||||
'Class:SynchroReplica/Attribute:status_last_seen' => 'Last seen',
|
||||
'Class:SynchroReplica/Attribute:status' => 'Status',
|
||||
'Class:SynchroReplica/Attribute:status/Value:modified' => 'Modified',
|
||||
'Class:SynchroReplica/Attribute:status/Value:new' => 'New',
|
||||
'Class:SynchroReplica/Attribute:status/Value:obsolete' => 'Obsolete',
|
||||
'Class:SynchroReplica/Attribute:status/Value:orphan' => 'Orphan',
|
||||
'Class:SynchroReplica/Attribute:status/Value:synchronized' => 'Synchronized',
|
||||
'Class:SynchroReplica/Attribute:status_dest_creator' => 'Object Created ?',
|
||||
'Class:SynchroReplica/Attribute:status_last_error' => 'Last Error',
|
||||
'Class:SynchroReplica/Attribute:status_last_warning' => 'Warnings',
|
||||
'Class:SynchroReplica/Attribute:info_creation_date' => 'Creation Date',
|
||||
'Class:SynchroReplica/Attribute:info_last_modified' => 'Last Modified Date',
|
||||
'Class:appUserPreferences' => 'User Preferences',
|
||||
'Class:appUserPreferences/Attribute:userid' => 'User',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_new_updated' => 'Nb objects updated',
|
||||
'Class:SynchroLog/Attribute:stats_nb_obj_new_unchanged' => 'Nb objects unchanged',
|
||||
'Class:SynchroLog/Attribute:last_error' => 'Last error',
|
||||
'Class:SynchroLog/Attribute:traces' => 'Traces',
|
||||
'Class:SynchroReplica' => 'Synchro Replica',
|
||||
'Class:SynchroReplica/Attribute:sync_source_id' => 'Synchro Data Source',
|
||||
'Class:SynchroReplica/Attribute:dest_id' => 'Destination object (ID)',
|
||||
'Class:SynchroReplica/Attribute:dest_class' => 'Destination type',
|
||||
'Class:SynchroReplica/Attribute:status_last_seen' => 'Last seen',
|
||||
'Class:SynchroReplica/Attribute:status' => 'Status',
|
||||
'Class:SynchroReplica/Attribute:status/Value:modified' => 'Modified',
|
||||
'Class:SynchroReplica/Attribute:status/Value:new' => 'New',
|
||||
'Class:SynchroReplica/Attribute:status/Value:obsolete' => 'Obsolete',
|
||||
'Class:SynchroReplica/Attribute:status/Value:orphan' => 'Orphan',
|
||||
'Class:SynchroReplica/Attribute:status/Value:synchronized' => 'Synchronized',
|
||||
'Class:SynchroReplica/Attribute:status_dest_creator' => 'Object Created ?',
|
||||
'Class:SynchroReplica/Attribute:status_last_error' => 'Last Error',
|
||||
'Class:SynchroReplica/Attribute:status_last_warning' => 'Warnings',
|
||||
'Class:SynchroReplica/Attribute:info_creation_date' => 'Creation Date',
|
||||
'Class:SynchroReplica/Attribute:info_last_modified' => 'Last Modified Date',
|
||||
'Class:SynchroReplica/Action:delete+' => 'delete replica',
|
||||
'Class:SynchroReplica/Action:unlink' => 'Unlink',
|
||||
'Class:SynchroReplica/Action:unlink+' => 'Unlink replica with destination object',
|
||||
'Class:SynchroReplica/Action:unlinksynchro' => 'Unlink & Synchro',
|
||||
'Class:SynchroReplica/Action:unlinksynchro+' => 'Unlink replica with destination object and execute synchronization with this replica',
|
||||
'Class:SynchroReplica/Action:synchro' => 'Synchro',
|
||||
'Class:SynchroReplica/Action:synchro+' => 'Execute synchronization with this replica',
|
||||
'Class:SynchroReplica/Action:allowdelete' => 'Allow delete of object linked to this synchro replica',
|
||||
'Class:SynchroReplica/Action:allowdelete+' => 'Object linked to a deleted replica is deleted',
|
||||
'Class:SynchroReplica/Action:denydelete' => 'Deny delete of object linked to this synchro replica',
|
||||
'Class:SynchroReplica/Action:denydelete+' => 'Object linked to a deleted replica is not deleted',
|
||||
|
||||
'Class:SynchroReplica/Action:unlink_all' => 'Unlink Synchro Replica objects',
|
||||
'Class:SynchroReplica/Action:unlink_all+' => 'Unlink replica with destination object',
|
||||
'Class:SynchroReplica/Action:unlinksynchro_all' => 'Unlink & Synchronize Synchro Replica objects',
|
||||
'Class:SynchroReplica/Action:unlinksynchro_all+' => 'Unlink replica with destination object and execute synchronization with this replica',
|
||||
'Class:SynchroReplica/Action:synchro_all' => 'Synchronize Synchro Replica objects',
|
||||
'Class:SynchroReplica/Action:synchro_all+' => 'Execute synchronization with this replica',
|
||||
'Class:SynchroReplica/Action:allowdelete_all' => 'Allow delete of objects linked to Synchro Replica',
|
||||
'Class:SynchroReplica/Action:allowdelete_all+' => 'Object linked to a deleted replica is deleted',
|
||||
'Class:SynchroReplica/Action:denydelete_all' => 'Deny delete of objects linked to Synchro Replica',
|
||||
'Class:SynchroReplica/Action:denydelete_all+' => 'Object linked to a deleted replica is not deleted',
|
||||
|
||||
'UI:UnlinkAllTabTitle' => 'Unlink Synchro Replica objects',
|
||||
'UI:UnlinkAllPageTitle' => 'Unlink Synchro Replica objects',
|
||||
'UI:UnlinkSynchroAllTabTitle' => 'Unlink & Synchronize Synchro Replica objects',
|
||||
'UI:UnlinkSynchroAllPageTitle' => ' Unlink & Synchronize Synchro Replica objects',
|
||||
'UI:SynchroAllTabTitle' => 'Synchronize Synchro Replica objects',
|
||||
'UI:SynchroAllPageTitle' => 'Synchronize Synchro Replica objects',
|
||||
'UI:AllowDeleteAllTabTitle' => 'Allow delete of objects linked to Synchro Replica',
|
||||
'UI:AllowDeleteAllPageTitle' => 'Allow delete of objects linked to Synchro Replica',
|
||||
'UI:DenyDeleteAllTabTitle' => 'Deny delete of objects linked to Synchro Replica',
|
||||
'UI:DenyDeleteAllPageTitle' => 'Deny delete of objects linked to Synchro Replica',
|
||||
|
||||
'Class:appUserPreferences' => 'User Preferences',
|
||||
'Class:appUserPreferences/Attribute:userid' => 'User',
|
||||
'Class:appUserPreferences/Attribute:preferences' => 'Prefs',
|
||||
'Core:ExecProcess:Code1' => 'Wrong command or command finished with errors (e.g. wrong script name)',
|
||||
'Core:ExecProcess:Code255' => 'PHP Error (parsing, or runtime)',
|
||||
'Core:ExecProcess:Code1' => 'Wrong command or command finished with errors (e.g. wrong script name)',
|
||||
'Core:ExecProcess:Code255' => 'PHP Error (parsing, or runtime)',
|
||||
|
||||
// Attribute Duration
|
||||
'Core:Duration_Seconds' => '%1$ds',
|
||||
'Core:Duration_Minutes_Seconds' => '%1$dmin %2$ds',
|
||||
'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds',
|
||||
'Core:Duration_Days_Hours_Minutes_Seconds' => '%1$sd %2$dh %3$dmin %4$ds',
|
||||
'Core:Duration_Seconds' => '%1$ds',
|
||||
'Core:Duration_Minutes_Seconds' => '%1$dmin %2$ds',
|
||||
'Core:Duration_Hours_Minutes_Seconds' => '%1$dh %2$dmin %3$ds',
|
||||
'Core:Duration_Days_Hours_Minutes_Seconds' => '%1$sd %2$dh %3$dmin %4$ds',
|
||||
|
||||
// Explain working time computing
|
||||
'Core:ExplainWTC:ElapsedTime' => 'Time elapsed (stored as "%1$s")',
|
||||
'Core:ExplainWTC:StopWatch-TimeSpent' => 'Time spent for "%1$s"',
|
||||
'Core:ExplainWTC:StopWatch-Deadline' => 'Deadline for "%1$s" at %2$d%%',
|
||||
'Core:ExplainWTC:ElapsedTime' => 'Time elapsed (stored as "%1$s")',
|
||||
'Core:ExplainWTC:StopWatch-TimeSpent' => 'Time spent for "%1$s"',
|
||||
'Core:ExplainWTC:StopWatch-Deadline' => 'Deadline for "%1$s" at %2$d%%',
|
||||
|
||||
// Bulk export
|
||||
'Core:BulkExport:MissingParameter_Param' => 'Missing parameter "%1$s"',
|
||||
'Core:BulkExport:InvalidParameter_Query' => 'Invalid value for the parameter "query". There is no Query Phrasebook corresponding to the id: "%1$s".',
|
||||
'Core:BulkExport:MissingParameter_Param' => 'Missing parameter "%1$s"',
|
||||
'Core:BulkExport:InvalidParameter_Query' => 'Invalid value for the parameter "query". There is no Query Phrasebook corresponding to the id: "%1$s".',
|
||||
'Core:BulkExport:ExportFormatPrompt' => 'Export format:',
|
||||
'Core:BulkExportOf_Class' => '%1$s Export',
|
||||
'Core:BulkExport:ClickHereToDownload_FileName' => 'Click here to download %1$s',
|
||||
|
||||
1
images/illustrations/undraw_empty_alternative.svg
Normal file
1
images/illustrations/undraw_empty_alternative.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 21 KiB |
@@ -401,6 +401,7 @@ return array(
|
||||
'Combodo\\iTop\\Controller\\Base\\Layout\\ActivityPanelController' => $baseDir . '/sources/Controller/Base/Layout/ActivityPanelController.php',
|
||||
'Combodo\\iTop\\Controller\\Base\\Layout\\ObjectController' => $baseDir . '/sources/Controller/Base/Layout/ObjectController.php',
|
||||
'Combodo\\iTop\\Controller\\Links\\LinkSetController' => $baseDir . '/sources/Controller/Links/LinkSetController.php',
|
||||
'Combodo\\iTop\\Controller\\Links\\SynchroReplicaController' => $baseDir . '/sources/Controller/Links/SynchroReplicaController.php',
|
||||
'Combodo\\iTop\\Controller\\Newsroom\\iTopNewsroomController' => $baseDir . '/sources/Controller/Newsroom/iTopNewsroomController.php',
|
||||
'Combodo\\iTop\\Controller\\Notifications\\ActionController' => $baseDir . '/sources/Controller/Notifications/ActionController.php',
|
||||
'Combodo\\iTop\\Controller\\Notifications\\NotificationsCenterController' => $baseDir . '/sources/Controller/Notifications/NotificationsCenterController.php',
|
||||
@@ -3127,6 +3128,7 @@ return array(
|
||||
'Twig\\Util\\DeprecationCollector' => $vendorDir . '/twig/twig/src/Util/DeprecationCollector.php',
|
||||
'Twig\\Util\\ReflectionCallable' => $vendorDir . '/twig/twig/src/Util/ReflectionCallable.php',
|
||||
'Twig\\Util\\TemplateDirIterator' => $vendorDir . '/twig/twig/src/Util/TemplateDirIterator.php',
|
||||
'UI' => $baseDir . '/sources/Controller/UI.php',
|
||||
'UIExtKeyWidget' => $baseDir . '/application/ui.extkeywidget.class.inc.php',
|
||||
'UIHTMLEditorWidget' => $baseDir . '/application/ui.htmleditorwidget.class.inc.php',
|
||||
'UILinksWidget' => $baseDir . '/application/ui.linkswidget.class.inc.php',
|
||||
@@ -3230,5 +3232,5 @@ return array(
|
||||
'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php',
|
||||
'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php',
|
||||
'utils' => $baseDir . '/application/utils.inc.php',
|
||||
'<EFBFBD>' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
'©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
);
|
||||
|
||||
@@ -58,7 +58,7 @@ return array(
|
||||
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
|
||||
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
|
||||
'Pelago\\Emogrifier\\' => array($vendorDir . '/pelago/emogrifier/src'),
|
||||
'League\\OAuth2\\Client\\' => array($vendorDir . '/league/oauth2-client/src', $vendorDir . '/league/oauth2-google/src'),
|
||||
'League\\OAuth2\\Client\\' => array($vendorDir . '/league/oauth2-google/src', $vendorDir . '/league/oauth2-client/src'),
|
||||
'Laminas\\Validator\\' => array($vendorDir . '/laminas/laminas-validator/src'),
|
||||
'Laminas\\Stdlib\\' => array($vendorDir . '/laminas/laminas-stdlib/src'),
|
||||
'Laminas\\ServiceManager\\' => array($vendorDir . '/laminas/laminas-servicemanager/src'),
|
||||
|
||||
@@ -329,8 +329,8 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
),
|
||||
'League\\OAuth2\\Client\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/oauth2-client/src',
|
||||
1 => __DIR__ . '/..' . '/league/oauth2-google/src',
|
||||
0 => __DIR__ . '/..' . '/league/oauth2-google/src',
|
||||
1 => __DIR__ . '/..' . '/league/oauth2-client/src',
|
||||
),
|
||||
'Laminas\\Validator\\' =>
|
||||
array (
|
||||
@@ -791,6 +791,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'Combodo\\iTop\\Controller\\Base\\Layout\\ActivityPanelController' => __DIR__ . '/../..' . '/sources/Controller/Base/Layout/ActivityPanelController.php',
|
||||
'Combodo\\iTop\\Controller\\Base\\Layout\\ObjectController' => __DIR__ . '/../..' . '/sources/Controller/Base/Layout/ObjectController.php',
|
||||
'Combodo\\iTop\\Controller\\Links\\LinkSetController' => __DIR__ . '/../..' . '/sources/Controller/Links/LinkSetController.php',
|
||||
'Combodo\\iTop\\Controller\\Links\\SynchroReplicaController' => __DIR__ . '/../..' . '/sources/Controller/Links/SynchroReplicaController.php',
|
||||
'Combodo\\iTop\\Controller\\Newsroom\\iTopNewsroomController' => __DIR__ . '/../..' . '/sources/Controller/Newsroom/iTopNewsroomController.php',
|
||||
'Combodo\\iTop\\Controller\\Notifications\\ActionController' => __DIR__ . '/../..' . '/sources/Controller/Notifications/ActionController.php',
|
||||
'Combodo\\iTop\\Controller\\Notifications\\NotificationsCenterController' => __DIR__ . '/../..' . '/sources/Controller/Notifications/NotificationsCenterController.php',
|
||||
@@ -3517,6 +3518,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'Twig\\Util\\DeprecationCollector' => __DIR__ . '/..' . '/twig/twig/src/Util/DeprecationCollector.php',
|
||||
'Twig\\Util\\ReflectionCallable' => __DIR__ . '/..' . '/twig/twig/src/Util/ReflectionCallable.php',
|
||||
'Twig\\Util\\TemplateDirIterator' => __DIR__ . '/..' . '/twig/twig/src/Util/TemplateDirIterator.php',
|
||||
'UI' => __DIR__ . '/../..' . '/sources/Controller/UI.php',
|
||||
'UIExtKeyWidget' => __DIR__ . '/../..' . '/application/ui.extkeywidget.class.inc.php',
|
||||
'UIHTMLEditorWidget' => __DIR__ . '/../..' . '/application/ui.htmleditorwidget.class.inc.php',
|
||||
'UILinksWidget' => __DIR__ . '/../..' . '/application/ui.linkswidget.class.inc.php',
|
||||
@@ -3620,7 +3622,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f
|
||||
'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
|
||||
'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
|
||||
'utils' => __DIR__ . '/../..' . '/application/utils.inc.php',
|
||||
'<EFBFBD>' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
'©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
||||
184
pages/UI.php
184
pages/UI.php
@@ -8,7 +8,6 @@ use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Form\Form;
|
||||
use Combodo\iTop\Application\UI\Base\Component\GlobalSearch\GlobalSearchHelper;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||
@@ -22,6 +21,7 @@ use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Application\WelcomePopup\WelcomePopupService;
|
||||
use Combodo\iTop\Controller\Base\Layout\ObjectController;
|
||||
use Combodo\iTop\Controller\Links\SynchroReplicaController;
|
||||
use Combodo\iTop\Controller\WelcomePopupController;
|
||||
use Combodo\iTop\Service\Router\Router;
|
||||
|
||||
@@ -200,68 +200,6 @@ function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form (checkboxes) to select the objects for which to apply a given action
|
||||
* Only the objects for which the action is valid can be checked. By default all valid objects are checked
|
||||
*
|
||||
* @param WebPage $oP WebPage The page for output
|
||||
* @param \DBSearch $oFilter DBSearch The filter that defines the list of objects
|
||||
* @param string $sNextOperation string The next operation (code) to be executed when the form is submitted
|
||||
* @param ActionChecker $oChecker ActionChecker The helper class/instance used to check for which object the action is valid
|
||||
* @param array $aExtraFormParams
|
||||
* @param array $aDisplayParams
|
||||
*
|
||||
* @since 3.0.0 $aDisplayParams parameter
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function DisplayMultipleSelectionForm(WebPage $oP, DBSearch $oFilter, string $sNextOperation, ActionChecker $oChecker, array $aExtraFormParams = [], array $aDisplayParams = [])
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$iBulkActionAllowed = $oChecker->IsAllowed();
|
||||
$aExtraParams = array('selection_type' => 'multiple', 'selection_mode' => true, 'display_limit' => false, 'menu' => false);
|
||||
if ($iBulkActionAllowed == UR_ALLOWED_DEPENDS) {
|
||||
$aExtraParams['selection_enabled'] = $oChecker->GetAllowedIDs();
|
||||
} else {
|
||||
if (UR_ALLOWED_NO) {
|
||||
throw new ApplicationException(Dict::Format('UI:ActionNotAllowed'));
|
||||
}
|
||||
}
|
||||
|
||||
$oForm = new Form();
|
||||
$oForm->SetAction('./UI.php');
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', $sNextOperation));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('class', $oFilter->GetClass()));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('filter', utils::HtmlEntities($oFilter->Serialize())));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('transaction_id', utils::GetNewTransactionId()));
|
||||
foreach ($aExtraFormParams as $sName => $sValue) {
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden($sName, $sValue));
|
||||
}
|
||||
$oForm->AddSubBlock($oAppContext->GetForFormBlock());
|
||||
$oDisplayBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
//by default all the elements are selected
|
||||
$aExtraParams['selectionMode'] = 'negative';
|
||||
if(array_key_exists('icon', $aDisplayParams) || array_key_exists('title', $aDisplayParams)){
|
||||
$aExtraParams['surround_with_panel'] = true;
|
||||
if(array_key_exists('icon', $aDisplayParams)){
|
||||
$aExtraParams['panel_icon'] = $aDisplayParams['icon'];
|
||||
}
|
||||
if(array_key_exists('title', $aDisplayParams)){
|
||||
$aExtraParams['panel_title'] = $aDisplayParams['title'];
|
||||
}
|
||||
}
|
||||
$oForm->AddSubBlock($oDisplayBlock->GetDisplay($oP, 1, $aExtraParams));
|
||||
$oToolbarButtons = ToolbarUIBlockFactory::MakeStandard(null);
|
||||
$oToolbarButtons->AddCSSClass('ibo-toolbar--button');
|
||||
$oForm->AddSubBlock($oToolbarButtons);
|
||||
$oToolbarButtons->AddSubBlock(ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel'), 'cancel')->SetOnClickJsCode('window.history.back()'));
|
||||
$oToolbarButtons->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Next'), 'next', Dict::S('UI:Button:Next'), true));
|
||||
|
||||
$oP->AddUiBlock($oForm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oP
|
||||
* @param $aResults
|
||||
@@ -354,7 +292,6 @@ try
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch($operation)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -696,6 +633,23 @@ try
|
||||
UI::OperationFormForModifyAll($oP, $oAppContext);
|
||||
break;
|
||||
|
||||
case 'form_for_unlink_all': // Form to modify multiple objects (bulk modify)
|
||||
SynchroReplicaController::OperationUnlinkAll($oP, $oAppContext,'unlink');
|
||||
break;
|
||||
case 'form_for_unlinksynchro_all': // Form to modify multiple objects (bulk modify)
|
||||
SynchroReplicaController::OperationUnlinkAll($oP, $oAppContext,'unlinksynchro');
|
||||
break;
|
||||
case 'form_for_synchro_all': // Form to modify multiple objects (bulk modify)
|
||||
SynchroReplicaController::OperationUnlinkAll($oP, $oAppContext,'synchro');
|
||||
break;
|
||||
|
||||
case 'form_for_allowdelete_all': // Form to modify multiple objects (bulk modify)
|
||||
SynchroReplicaController::OperationUnlinkAll($oP, $oAppContext,'allowdelete');
|
||||
break;
|
||||
case 'form_for_denydelete_all': // Form to modify multiple objects (bulk modify)
|
||||
SynchroReplicaController::OperationUnlinkAll($oP, $oAppContext,'denydelete');
|
||||
break;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
case 'preview_or_modify_all': // Preview or apply bulk modify
|
||||
@@ -739,7 +693,7 @@ try
|
||||
'title' => Dict::S('UI:BulkDeleteTitle'),
|
||||
];
|
||||
$oChecker = new ActionChecker($oFilter, UR_ACTION_BULK_DELETE);
|
||||
DisplayMultipleSelectionForm($oP, $oFilter, 'bulk_delete', $oChecker, [], $aDisplayParams);
|
||||
UI::DisplayMultipleSelectionForm($oP, $oFilter, 'bulk_delete', $oChecker, [], $aDisplayParams);
|
||||
break;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -845,7 +799,7 @@ try
|
||||
];
|
||||
$oChecker = new StimulusChecker($oFilter, $sState, $sStimulus);
|
||||
$aExtraFormParams = array('stimulus' => $sStimulus, 'state' => $sState);
|
||||
DisplayMultipleSelectionForm($oP, $oFilter, 'bulk_stimulus', $oChecker, $aExtraFormParams, $aDisplayParams);
|
||||
UI::DisplayMultipleSelectionForm($oP, $oFilter, 'bulk_stimulus', $oChecker, $aExtraFormParams, $aDisplayParams);
|
||||
break;
|
||||
|
||||
case 'bulk_stimulus':
|
||||
@@ -1550,101 +1504,3 @@ catch (Exception $e) {
|
||||
}
|
||||
|
||||
|
||||
class UI
|
||||
{
|
||||
|
||||
/**
|
||||
* Operation select_for_modify_all
|
||||
*
|
||||
* @param iTopWebPage $oP
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function OperationSelectForModifyAll(iTopWebPage $oP): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$oP->set_title(Dict::S('UI:ModifyAllPageTitle'));
|
||||
$sFilter = utils::ReadParam('filter', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
if (empty($sFilter)) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'filter'));
|
||||
}
|
||||
$oFilter = DBObjectSearch::unserialize($sFilter); //TODO : check that the filter is valid
|
||||
// Add user filter
|
||||
$oFilter->UpdateContextFromUser();
|
||||
$oChecker = new ActionChecker($oFilter, UR_ACTION_BULK_MODIFY);
|
||||
$sClass = $oFilter->GetClass();
|
||||
$sClassName = MetaModel::GetName($sClass);
|
||||
|
||||
$aDisplayParams = [
|
||||
'icon' => MetaModel::GetClassIcon($sClass, false),
|
||||
'title' => Dict::Format('UI:Modify_ObjectsOf_Class', $sClassName),
|
||||
];
|
||||
DisplayMultipleSelectionForm($oP, $oFilter, 'form_for_modify_all', $oChecker, [], $aDisplayParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation form_for_modify_all
|
||||
*
|
||||
* @param iTopWebPage $oP
|
||||
* @param \ApplicationContext $oAppContext
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function OperationFormForModifyAll(iTopWebPage $oP, ApplicationContext $oAppContext): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$sFilter = utils::ReadParam('filter', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
$sClass = utils::ReadParam('class', '', false, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
||||
$oFullSetFilter = DBObjectSearch::unserialize($sFilter);
|
||||
// Add user filter
|
||||
$oFullSetFilter->UpdateContextFromUser();
|
||||
$aSelectedObj = utils::ReadMultipleSelection($oFullSetFilter);
|
||||
$sCancelUrl = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
|
||||
$aContext = array('filter' => utils::EscapeHtml($sFilter));
|
||||
cmdbAbstractObject::DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, 'preview_or_modify_all', $sCancelUrl, array(), $aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation preview_or_modify_all
|
||||
*
|
||||
* @param iTopWebPage $oP
|
||||
* @param \ApplicationContext $oAppContext
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function OperationPreviewOrModifyAll(iTopWebPage $oP, ApplicationContext $oAppContext): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
|
||||
$oFilter = DBObjectSearch::unserialize($sFilter); // TO DO : check that the filter is valid
|
||||
// Add user filter
|
||||
$oFilter->UpdateContextFromUser();
|
||||
|
||||
$sClass = utils::ReadParam('class', '', false, 'class');
|
||||
$bPreview = utils::ReadParam('preview_mode', '');
|
||||
$sSelectedObj = utils::ReadParam('selectObj', '', false, 'raw_data');
|
||||
if (empty($sClass) || empty($sSelectedObj)) // TO DO: check that the class name is valid !
|
||||
{
|
||||
throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObj'));
|
||||
}
|
||||
$aSelectedObj = explode(',', $sSelectedObj);
|
||||
$sCancelUrl = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
|
||||
$aContext = array(
|
||||
'filter' => utils::EscapeHtml($sFilter),
|
||||
'selectObj' => $sSelectedObj,
|
||||
);
|
||||
cmdbAbstractObject::DoBulkModify($oP, $sClass, $aSelectedObj, 'preview_or_modify_all', $bPreview, $sCancelUrl, $aContext);
|
||||
}
|
||||
}
|
||||
138
sources/Controller/Links/SynchroReplicaController.php
Normal file
138
sources/Controller/Links/SynchroReplicaController.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Controller\Links;
|
||||
|
||||
use ApplicationContext;
|
||||
use ApplicationException;
|
||||
use Combodo\iTop\Application\TwigBase\Controller\Controller;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
|
||||
use DBObjectSearch;
|
||||
use Dict;
|
||||
use Exception;
|
||||
use iTopWebPage;
|
||||
use MetaModel;
|
||||
use utils;
|
||||
|
||||
class SynchroReplicaController extends Controller
|
||||
{
|
||||
public const ROUTE_NAMESPACE = 'synchroreplica';
|
||||
|
||||
public function __construct($sViewPath = '', $sModuleName = 'core', $aAdditionalPaths = [])
|
||||
{
|
||||
$sViewPath = APPROOT.'synchro';
|
||||
parent::__construct($sViewPath, $sModuleName, $aAdditionalPaths);
|
||||
|
||||
// Previously in index.php
|
||||
$this->DisableInDemoMode();
|
||||
$this->AllowOnlyAdmin();
|
||||
$this->CheckAccess();
|
||||
}
|
||||
|
||||
public static function OperationUnlinkAll(iTopWebPage $oP, ApplicationContext $oAppContext, $sOperation = 'unlink'): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$sClass = utils::ReadParam('class', '', false, 'class');
|
||||
$sFilter = utils::ReadPostedParam('filter', '', 'raw_data');
|
||||
$oFullSetFilter = DBObjectSearch::unserialize($sFilter);
|
||||
// Add user filter
|
||||
$oFullSetFilter->UpdateContextFromUser();
|
||||
$aSelectObject = utils::ReadMultipleSelection($oFullSetFilter);
|
||||
if ( empty($sClass) || empty($aSelectObject)) // TO DO: check that the class name is valid !
|
||||
{
|
||||
throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObject[]'));
|
||||
}
|
||||
$sCancelUrl = "./UI.php?operation=search&filter=".urlencode($sFilter)."&".$oAppContext->GetForLink();
|
||||
$aContext = array(
|
||||
'filter' => utils::EscapeHtml($sFilter),
|
||||
'selectObj' => $aSelectObject,
|
||||
);
|
||||
|
||||
$aHeaders = array(
|
||||
'object' => array('label' => MetaModel::GetName($sClass), 'description' => Dict::S('UI:ModifiedObject')),
|
||||
'status' => array(
|
||||
'label' => Dict::S('UI:BulkModifyStatus'),
|
||||
'description' => Dict::S('UI:BulkModifyStatus+'),
|
||||
),
|
||||
'errors' => array(
|
||||
'label' => Dict::S('UI:BulkModifyErrors'),
|
||||
'description' => Dict::S('UI:BulkModifyErrors+'),
|
||||
),
|
||||
);
|
||||
$aRows = array();
|
||||
|
||||
|
||||
$sHeaderTitle = Dict::Format('UI:Modify_N_ObjectsOf_Class', count($aSelectObject), MetaModel::GetName($sClass));
|
||||
$sClassIcon = MetaModel::GetClassIcon($sClass, false);
|
||||
|
||||
// Not in preview mode, do the update for real
|
||||
$sTransactionId = utils::ReadPostedParam('transaction_id', '', 'transaction_id');
|
||||
if (!utils::IsTransactionValid($sTransactionId, false)) {
|
||||
throw new Exception(Dict::S('UI:Error:ObjectAlreadyUpdated'));
|
||||
}
|
||||
utils::RemoveTransaction($sTransactionId);
|
||||
|
||||
// Avoid too many events
|
||||
$iPreviousTimeLimit = ini_get('max_execution_time');
|
||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||
$aErrors = [];
|
||||
foreach ($aSelectObject as $iId) {
|
||||
set_time_limit(intval($iLoopTimeLimit));
|
||||
/** @var \cmdbAbstractObject $oObj */
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$bResult = true;
|
||||
try {
|
||||
if (in_array($sOperation, ['unlink', 'unlinksynchro'])) {
|
||||
$oReplica->UnLink();
|
||||
}
|
||||
if (in_array($sOperation, ['synchro', 'unlinksynchro'])) {
|
||||
$oStatLog = $oReplica->ReSynchro();
|
||||
$aErrors = $oStatLog->GetTraces();
|
||||
}
|
||||
if ($sOperation == 'allowdelete') {
|
||||
$oReplica->Set('status_dest_creator', 1);
|
||||
$oReplica->DBUpdate();
|
||||
}
|
||||
if ($sOperation == 'denydelete') {
|
||||
$oReplica->Set('status_dest_creator', 0);
|
||||
$oReplica->DBUpdate();
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$bResult = false;
|
||||
$aErrors[] = $e->getMessage();
|
||||
}
|
||||
catch (Error $e) {
|
||||
$bResult = false;
|
||||
$aErrors[] = $e->getMessage();
|
||||
}
|
||||
|
||||
$sStatus = $bResult ? Dict::S('UI:BulkModifyStatusModified') : Dict::S('UI:BulkModifyStatusSkipped');
|
||||
|
||||
$aErrorsToDisplay = array_map(function ($sError) {
|
||||
return utils::HtmlEntities($sError);
|
||||
}, $aErrors);
|
||||
$aRows[] = array(
|
||||
'object' => $oReplica->GetHyperlink(),
|
||||
'status' => $sStatus,
|
||||
'errors' => '<p>'.($bResult ? '' : implode('</p><p>', $aErrorsToDisplay)).'</p>',
|
||||
);
|
||||
}
|
||||
|
||||
set_time_limit(intval($iPreviousTimeLimit));
|
||||
$oTable = DataTableUIBlockFactory::MakeForForm('BulkModify', $aHeaders, $aRows);
|
||||
$oTable->AddOption("bFullscreen", true);
|
||||
|
||||
$oPanel = PanelUIBlockFactory::MakeForClass($sClass, '');
|
||||
$oPanel->SetIcon($sClassIcon);
|
||||
$oPanel->SetTitle($sHeaderTitle);
|
||||
$oPanel->AddCSSClass('ibo-datatable-panel');
|
||||
$oPanel->AddSubBlock($oTable);
|
||||
|
||||
$oP->AddUiBlock($oPanel);
|
||||
$oP->AddSubBlock(ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Done')))->SetOnClickJsCode("window.location.href='$sCancelUrl'")->AddCSSClass('mt-5');
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
167
sources/Controller/UI.php
Normal file
167
sources/Controller/UI.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Form\Form;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
|
||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
|
||||
class UI
|
||||
{
|
||||
|
||||
/**
|
||||
* Operation select_for_modify_all
|
||||
*
|
||||
* @param iTopWebPage $oP
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function OperationSelectForModifyAll(iTopWebPage $oP, $sTitleTab = 'UI:ModifyAllPageTitle', $sTitleCode = 'UI:Modify_ObjectsOf_Class', $sNextOperation = 'form_for_modify_all'): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$oP->set_title(Dict::S($sTitleTab));
|
||||
$sFilter = utils::ReadParam('filter', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
if (empty($sFilter)) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'filter'));
|
||||
}
|
||||
$oFilter = DBObjectSearch::unserialize($sFilter); //TODO : check that the filter is valid
|
||||
// Add user filter
|
||||
$oFilter->UpdateContextFromUser();
|
||||
$oChecker = new ActionChecker($oFilter, UR_ACTION_BULK_MODIFY);
|
||||
$sClass = $oFilter->GetClass();
|
||||
$sClassName = MetaModel::GetName($sClass);
|
||||
|
||||
$aDisplayParams = [
|
||||
'icon' => MetaModel::GetClassIcon($sClass, false),
|
||||
'title' => Dict::Format($sTitleCode, $sClassName),
|
||||
];
|
||||
self::DisplayMultipleSelectionForm($oP, $oFilter, $sNextOperation, $oChecker, [], $aDisplayParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation form_for_modify_all
|
||||
*
|
||||
* @param iTopWebPage $oP
|
||||
* @param \ApplicationContext $oAppContext
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function OperationFormForModifyAll(iTopWebPage $oP, ApplicationContext $oAppContext): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$sFilter = utils::ReadParam('filter', '', false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
|
||||
$sClass = utils::ReadParam('class', '', false, utils::ENUM_SANITIZATION_FILTER_CLASS);
|
||||
$oFullSetFilter = DBObjectSearch::unserialize($sFilter);
|
||||
// Add user filter
|
||||
$oFullSetFilter->UpdateContextFromUser();
|
||||
$aSelectedObj = utils::ReadMultipleSelection($oFullSetFilter);
|
||||
$sCancelUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&filter=' . urlencode($sFilter) . '&' . $oAppContext->GetForLink();
|
||||
$aContext = array('filter' => utils::EscapeHtml($sFilter));
|
||||
cmdbAbstractObject::DisplayBulkModifyForm($oP, $sClass, $aSelectedObj, 'preview_or_modify_all', $sCancelUrl, array(), $aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation preview_or_modify_all
|
||||
*
|
||||
* @param iTopWebPage $oP
|
||||
* @param \ApplicationContext $oAppContext
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public static function OperationPreviewOrModifyAll(iTopWebPage $oP, ApplicationContext $oAppContext): void
|
||||
{
|
||||
$oP->DisableBreadCrumb();
|
||||
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
|
||||
$oFilter = DBObjectSearch::unserialize($sFilter); // TO DO : check that the filter is valid
|
||||
// Add user filter
|
||||
$oFilter->UpdateContextFromUser();
|
||||
|
||||
$sClass = utils::ReadParam('class', '', false, 'class');
|
||||
$bPreview = utils::ReadParam('preview_mode', '');
|
||||
$sSelectedObj = utils::ReadParam('selectObj', '', false, 'raw_data');
|
||||
if (empty($sClass) || empty($sSelectedObj)) // TO DO: check that the class name is valid !
|
||||
{
|
||||
throw new ApplicationException(Dict::Format('UI:Error:2ParametersMissing', 'class', 'selectObj'));
|
||||
}
|
||||
$aSelectedObj = explode(',', $sSelectedObj);
|
||||
$sCancelUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&filter=' . urlencode($sFilter) . '&' . $oAppContext->GetForLink();
|
||||
$aContext = array(
|
||||
'filter' => utils::EscapeHtml($sFilter),
|
||||
'selectObj' => $sSelectedObj,
|
||||
);
|
||||
cmdbAbstractObject::DoBulkModify($oP, $sClass, $aSelectedObj, 'preview_or_modify_all', $bPreview, $sCancelUrl, $aContext);
|
||||
}/**
|
||||
* Displays a form (checkboxes) to select the objects for which to apply a given action
|
||||
* Only the objects for which the action is valid can be checked. By default all valid objects are checked
|
||||
*
|
||||
* @param WebPage $oP WebPage The page for output
|
||||
* @param \DBSearch $oFilter DBSearch The filter that defines the list of objects
|
||||
* @param string $sNextOperation string The next operation (code) to be executed when the form is submitted
|
||||
* @param ActionChecker $oChecker ActionChecker The helper class/instance used to check for which object the action is valid
|
||||
* @param array $aExtraFormParams
|
||||
* @param array $aDisplayParams
|
||||
*
|
||||
* @throws \ApplicationException
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*@since 3.0.0 $aDisplayParams parameter
|
||||
*
|
||||
*/
|
||||
public static function DisplayMultipleSelectionForm(WebPage $oP, DBSearch $oFilter, string $sNextOperation, ActionChecker $oChecker, array $aExtraFormParams = [], array $aDisplayParams = [])
|
||||
{
|
||||
$oAppContext = new ApplicationContext();
|
||||
$iBulkActionAllowed = $oChecker->IsAllowed();
|
||||
$aExtraParams = array('selection_type' => 'multiple', 'selection_mode' => true, 'display_limit' => false, 'menu' => false);
|
||||
if ($iBulkActionAllowed == UR_ALLOWED_DEPENDS) {
|
||||
$aExtraParams['selection_enabled'] = $oChecker->GetAllowedIDs();
|
||||
} else {
|
||||
if (UR_ALLOWED_NO) {
|
||||
throw new ApplicationException(Dict::Format('UI:ActionNotAllowed'));
|
||||
}
|
||||
}
|
||||
|
||||
$oForm = new Form();
|
||||
$oForm->SetAction( utils::GetAbsoluteUrlAppRoot().'pages/UI.php');
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', $sNextOperation));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('class', $oFilter->GetClass()));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('filter', utils::HtmlEntities($oFilter->Serialize())));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('transaction_id', utils::GetNewTransactionId()));
|
||||
foreach ($aExtraFormParams as $sName => $sValue) {
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden($sName, $sValue));
|
||||
}
|
||||
$oForm->AddSubBlock($oAppContext->GetForFormBlock());
|
||||
$oDisplayBlock = new DisplayBlock($oFilter, 'list', false);
|
||||
//by default all the elements are selected
|
||||
$aExtraParams['selectionMode'] = 'negative';
|
||||
if (array_key_exists('icon', $aDisplayParams) || array_key_exists('title', $aDisplayParams)) {
|
||||
$aExtraParams['surround_with_panel'] = true;
|
||||
if (array_key_exists('icon', $aDisplayParams)) {
|
||||
$aExtraParams['panel_icon'] = $aDisplayParams['icon'];
|
||||
}
|
||||
if (array_key_exists('title', $aDisplayParams)) {
|
||||
$aExtraParams['panel_title'] = $aDisplayParams['title'];
|
||||
}
|
||||
}
|
||||
$oForm->AddSubBlock($oDisplayBlock->GetDisplay($oP, 1, $aExtraParams));
|
||||
$oToolbarButtons = ToolbarUIBlockFactory::MakeStandard(null);
|
||||
$oToolbarButtons->AddCSSClass('ibo-toolbar--button');
|
||||
$oForm->AddSubBlock($oToolbarButtons);
|
||||
$oToolbarButtons->AddSubBlock(ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel'), 'cancel')->SetOnClickJsCode('window.history.back()'));
|
||||
$oToolbarButtons->AddSubBlock(ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Next'), 'next', Dict::S('UI:Button:Next'), true));
|
||||
|
||||
$oP->AddUiBlock($oForm);
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,17 @@
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
use Combodo\iTop\Application\WebPage\iTopWebPage;
|
||||
use UI;
|
||||
|
||||
require_once('../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin();
|
||||
LoginWebPage::DoLogin();
|
||||
|
||||
$sOperation = utils::ReadParam('operation', 'menu');
|
||||
$oAppContext = new ApplicationContext();
|
||||
@@ -33,46 +36,122 @@ $oP = new iTopWebPage("iTop - Synchro Replicas");
|
||||
|
||||
// Main program
|
||||
$sOperation = utils::ReadParam('operation', 'details');
|
||||
try
|
||||
{
|
||||
switch($sOperation)
|
||||
{
|
||||
|
||||
try {
|
||||
switch ($sOperation) {
|
||||
case 'details':
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null)
|
||||
{
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
case 'oql':
|
||||
$sOQL = utils::ReadParam('oql', null, false, 'raw_data');
|
||||
if ($sOQL == null)
|
||||
{
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql'));
|
||||
}
|
||||
$oFilter = DBObjectSearch::FromOQL($sOQL);
|
||||
$oBlock1 = new DisplayBlock($oFilter, 'search', false, array('menu' => false, 'table_id' => '1'));
|
||||
$oBlock1->Display($oP, 0);
|
||||
$oP->add('<p class="page-header">'.MetaModel::GetClassIcon('SynchroReplica').Dict::S('Core:SynchroReplica:ListOfReplicas').'</p>');
|
||||
$iSourceId = utils::ReadParam('datasource', null);
|
||||
if ($iSourceId != null)
|
||||
{
|
||||
$oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId);
|
||||
$oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).'</a>');
|
||||
}
|
||||
$oBlock = new DisplayBlock($oFilter, 'list', false, array('menu'=>false));
|
||||
$oBlock->Display($oP, 1);
|
||||
break;
|
||||
$iSourceId = utils::ReadParam('datasource', null);
|
||||
if ($iSourceId != null) {
|
||||
$oSource = MetaModel::GetObject('SynchroDataSource', $iSourceId);
|
||||
//$oP->p(Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetHyperlink()).'</a>');
|
||||
//$oBackButton = ButtonUIBlockFactory::MakeIconLink('fas fa-chevron-left', Dict::Format('Core:SynchroReplica:BackToDataSource', $oSource->GetName()), ApplicationContext::MakeObjectUrl('SynchroDataSource', $iSourceId));
|
||||
$oBackButton = ButtonUIBlockFactory::MakeLinkNeutral( ApplicationContext::MakeObjectUrl('SynchroDataSource', $iSourceId), Dict::S('Core:SynchroReplica:BackToDataSource'), 'fas fa-chevron-left');
|
||||
$oP->AddUiBlock($oBackButton);
|
||||
$oP->AddUiBlock(TitleUIBlockFactory::MakeForPage(Dict::Format('Core:SynchroReplica:ListOfReplicas', $oSource->GetName())));
|
||||
}
|
||||
|
||||
$sOQL = utils::ReadParam('oql', null, false, 'raw_data');
|
||||
if ($sOQL == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql'));
|
||||
}
|
||||
$oFilter = DBObjectSearch::FromOQL($sOQL);
|
||||
$oBlock1 = new DisplayBlock($oFilter, 'search', false, array('menu' => true, 'table_id' => '1'));
|
||||
$oBlock1->Display($oP, 0);
|
||||
|
||||
//$oBlock = new DisplayBlock($oFilter, 'list', false, array('menu' => true));
|
||||
//$oBlock->Display($oP, 1);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
case 'select_for_deletion':
|
||||
// Redirect to the page that implements bulk delete
|
||||
$sDelete = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?'.$_SERVER['QUERY_STRING'];
|
||||
header("Location: $sDelete");
|
||||
break;
|
||||
// Redirect to the page that implements bulk delete
|
||||
$sDelete = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?'.$_SERVER['QUERY_STRING'];
|
||||
header("Location: $sDelete");
|
||||
break;
|
||||
|
||||
case 'unlinksynchro':
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oReplica->UnLink();
|
||||
|
||||
$oStatLog = $oReplica->ReSynchro();
|
||||
$oP->add(implode('<br>', $oStatLog->GetTraces()));
|
||||
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
case 'unlink':
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oReplica->UnLink();
|
||||
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
case 'synchro':
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oStatLog = $oReplica->ReSynchro();
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
case 'allowdelete':
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oStatLog = $oReplica->Set('status_dest_creator',1);
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
case 'denydelete': // Select the list of objects to be modified (bulk modify)
|
||||
$iId = utils::ReadParam('id', null);
|
||||
if ($iId == null) {
|
||||
throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'id'));
|
||||
}
|
||||
$oReplica = MetaModel::GetObject('SynchroReplica', $iId);
|
||||
$oStatLog = $oReplica->Set('status_dest_creator', 0);
|
||||
$oReplica->DisplayDetails($oP);
|
||||
break;
|
||||
|
||||
case 'select_for_unlink_all': // Select the list of objects to be modified (bulk modify)
|
||||
UI::OperationSelectForModifyAll($oP,'UI:UnlinkAllTabTitle', 'UI:UnlinkAllPageTitle', 'form_for_unlink_all');
|
||||
break;
|
||||
|
||||
case 'select_for_unlinksynchro_all': // Select the list of objects to be modified (bulk modify)
|
||||
UI::OperationSelectForModifyAll($oP,'UI:UnlinkSynchroAllTabTitle', 'UI:UnlinkSynchroAllPageTitle', 'form_for_unlinksynchro_all');
|
||||
break;
|
||||
|
||||
case 'select_for_synchro_all': // Select the list of objects to be modified (bulk modify)
|
||||
UI::OperationSelectForModifyAll($oP,'UI:SynchroAllTabTitle', 'UI:SynchroAllPageTitle','form_for_synchro_all');
|
||||
break;
|
||||
|
||||
case 'select_for_allowdelete_all': // Select the list of objects to be modified (bulk modify)
|
||||
UI::OperationSelectForModifyAll($oP,'UI:AllowDeleteAllTabTitle', 'UI:AllowDeleteAllPageTitle','form_for_allowdelete_all');
|
||||
break;
|
||||
|
||||
case 'select_for_denydelete_all': // Select the list of objects to be modified (bulk modify)
|
||||
UI::OperationSelectForModifyAll($oP,'UI:DenyDeleteAllTabTitle', 'UI:DenyDeleteAllPageTitle','form_for_denydelete_all');
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(CoreException $e)
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenu;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
|
||||
use Combodo\iTop\Core\CMDBChange\CMDBChangeOrigin;
|
||||
|
||||
class SynchroDataSource extends cmdbAbstractObject
|
||||
{
|
||||
@@ -2117,6 +2123,12 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
public function InitExtendedData($oSource)
|
||||
{
|
||||
$sSQLTable = $oSource->GetDataTable();
|
||||
$this->m_aExtendedData = $this->LoadExtendedDataFromTable($sSQLTable);
|
||||
}
|
||||
|
||||
public function __construct($aRow = null, $sClassAlias = '', $aAttToLoad = null, $aExtendedDataSpec = null)
|
||||
{
|
||||
parent::__construct($aRow, $sClassAlias, $aAttToLoad, $aExtendedDataSpec);
|
||||
@@ -2201,6 +2213,15 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
$this->Set('status_last_error', $sText);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disassociate the replica from the destination object and set the status to "new" to be synchronized with the next operation
|
||||
*/
|
||||
public function UnLink(){
|
||||
$this->Set('dest_id', '');
|
||||
$this->Set('dest_class', '');
|
||||
$this->Set('status', 'new');
|
||||
$this->DBWrite();
|
||||
}
|
||||
|
||||
public function Synchro($oDataSource, $aReconciliationKeys, $aAttributes, $oChange, &$oStatLog)
|
||||
{
|
||||
@@ -2399,6 +2420,89 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
$oStatLog->AddTrace('<<< End of SynchroReplica::Synchro.', $this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \SynchroLog
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \CoreWarning
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
* @throws \SynchroExceptionNotStarted
|
||||
*/
|
||||
public function ReSynchro(): SynchroLog
|
||||
{
|
||||
$oDataSource = MetaModel::GetObject('SynchroDataSource', $this->Get('sync_source_id'));
|
||||
|
||||
$oStatLog = new SynchroLog();
|
||||
$oStatLog->Set('sync_source_id', $oDataSource->GetKey());
|
||||
$oStatLog->Set('start_date', time());
|
||||
$oStatLog->Set('status', 'running');
|
||||
$oStatLog->AddTrace('Manual synchro');
|
||||
|
||||
// Get the list of SQL columns
|
||||
$aAttCodesExpected = array();
|
||||
$aAttCodesToReconcile = array();
|
||||
$aAttCodesToUpdate = array();
|
||||
$sSelectAtt = 'SELECT SynchroAttribute WHERE sync_source_id = :source_id AND (update = 1 OR reconcile = 1)';
|
||||
$oSetAtt = new DBObjectSet(DBObjectSearch::FromOQL($sSelectAtt), array() /* order by*/, array('source_id' => $oDataSource->GetKey()) /* aArgs */);
|
||||
while ($oSyncAtt = $oSetAtt->Fetch()) {
|
||||
if ($oSyncAtt->Get('update')) {
|
||||
$aAttCodesToUpdate[$oSyncAtt->Get('attcode')] = $oSyncAtt;
|
||||
}
|
||||
if ($oSyncAtt->Get('reconcile')) {
|
||||
$aAttCodesToReconcile[$oSyncAtt->Get('attcode')] = $oSyncAtt;
|
||||
}
|
||||
$aAttCodesExpected[$oSyncAtt->Get('attcode')] = $oSyncAtt;
|
||||
}
|
||||
|
||||
// Get the list of attributes, determine reconciliation keys and update targets
|
||||
//
|
||||
if ($oDataSource->Get('reconciliation_policy') == 'use_attributes') {
|
||||
$aReconciliationKeys = $aAttCodesToReconcile;
|
||||
} elseif ($oDataSource->Get('reconciliation_policy') == 'use_primary_key') {
|
||||
// Override the settings made at the attribute level !
|
||||
$aReconciliationKeys = array('primary_key' => null);
|
||||
}
|
||||
|
||||
if (count($aAttCodesToUpdate) == 0) {
|
||||
$oStatLog->AddTrace('No attribute to update');
|
||||
throw new SynchroExceptionNotStarted('There is no attribute to update');
|
||||
}
|
||||
if (count($aReconciliationKeys) == 0) {
|
||||
$oStatLog->AddTrace('No attribute for reconciliation');
|
||||
throw new SynchroExceptionNotStarted('No attribute for reconciliation');
|
||||
}
|
||||
|
||||
|
||||
$aAttributesToUpdate = array();
|
||||
foreach ($aAttCodesToUpdate as $sAttCode => $oSyncAtt) {
|
||||
$oAttDef = MetaModel::GetAttributeDef($oDataSource->GetTargetClass(), $sAttCode);
|
||||
if ($oAttDef->IsWritable()) {
|
||||
$aAttributesToUpdate[$sAttCode] = $oSyncAtt;
|
||||
}
|
||||
}
|
||||
// Create a change used for logging all the modifications/creations happening during the synchro
|
||||
$oChange = MetaModel::NewObject('CMDBChange');
|
||||
$oChange->Set('date', time());
|
||||
$sUserString = CMDBChange::GetCurrentUserName();
|
||||
$oChange->Set('userinfo', $sUserString.' '.Dict::S('Core:SyncDataExchangeComment'));
|
||||
$oChange->Set('origin', CMDBChangeOrigin::SYNCHRO_DATA_SOURCE);
|
||||
$oChange->DBInsert();
|
||||
CMDBObject::SetCurrentChange($oChange);
|
||||
|
||||
$this->InitExtendedData($oDataSource);
|
||||
|
||||
$this->Synchro($oDataSource, $aReconciliationKeys, $aAttributesToUpdate, $oChange, $oStatLog);
|
||||
$this->DBUpdate();
|
||||
|
||||
return $oStatLog;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the destination object with the Extended data found in the synchro_data_XXXX table
|
||||
*
|
||||
@@ -2759,13 +2863,119 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
function DisplayDetails(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
// Object's details
|
||||
//$this->DisplayBareHeader($oPage, $bEditMode);
|
||||
$this->DisplayBareHeader($oPage, $bEditMode);
|
||||
|
||||
$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
|
||||
$oPage->SetCurrentTab('UI:PropertiesTab');
|
||||
$this->DisplayBareProperties($oPage, $bEditMode);
|
||||
}
|
||||
|
||||
public function DisplayBareHeader(WebPage $oPage, $bEditMode = false)
|
||||
{
|
||||
$oBlock = UIContentBlockUIBlockFactory::MakeStandard('title-for-replica', ['ibo-page-header--replica-title']);
|
||||
$oPage->AddSubBlock($oBlock);
|
||||
$oPage->add_style('.ibo-page-header--replica-title{ display: table; width: 100%;}');
|
||||
$oPage->add_style('.ibo-page-header--replica-title>.ibo-toolbar--button{ display: table-cell; vertical-align:middle;}');
|
||||
|
||||
$sId = $this->GetKey();
|
||||
$oTitle = TitleUIBlockFactory::MakeNeutral(Dict::S('Class:SynchroReplica'));
|
||||
$oBlock->AddSubBlock($oTitle);
|
||||
$oActionsToolbar = ToolbarUIBlockFactory::MakeForButton(MenuBlock::ACTIONS_TOOLBAR_ID_PREFIX.$sId);
|
||||
$oActionsToolbar->AddCSSClass('ibo-panel--toolbar');
|
||||
$oBlock->AddSubBlock($oActionsToolbar);
|
||||
|
||||
$sClass = get_class($this);
|
||||
$sRootUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$sUIPage = cmdbAbstractObject::ComputeStandardUIPage($sClass);
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sContext = $oAppContext->GetForLink();
|
||||
if (utils::IsNotNullOrEmptyString($sContext)) {
|
||||
$sContext = '&'.$sContext;
|
||||
}
|
||||
|
||||
$aActions = [];
|
||||
//Delete
|
||||
if (UserRights::IsActionAllowed($sClass, UR_ACTION_DELETE)) {
|
||||
$aActions['UI:Menu:Delete'] = array(
|
||||
'label' => Dict::S('UI:Menu:Delete'),
|
||||
'url' => "{$sRootUrl}pages/$sUIPage?operation=delete&class=$sClass&id=$sId{$sContext}",
|
||||
'tooltip' => Dict::S('Class:SynchroReplica/Action:delete+'),
|
||||
);
|
||||
}
|
||||
|
||||
if (UserRights::IsActionAllowed($sClass, UR_ACTION_MODIFY)) {
|
||||
if (count($aActions) > 0) {
|
||||
$sSeparator = '<hr class="menu-separator"/>';
|
||||
$aActions['sep_0'] = array('label' => $sSeparator, 'url' => '');
|
||||
}
|
||||
$sUrl = "{$sRootUrl}synchro/replica.php?operation=unlink&class=$sClass&id=$sId{$sContext}";
|
||||
$aActions['Class:SynchroReplica/Action:unlink'] = [
|
||||
'label' => Dict::S('Class:SynchroReplica/Action:unlink'),
|
||||
'url' => $sUrl,
|
||||
'tooltip' => Dict::S('Class:SynchroReplica/Action:unlink+'),
|
||||
];
|
||||
|
||||
$sUrl = "{$sRootUrl}synchro/replica.php?operation=unlinksynchro&class=$sClass&id=$sId{$sContext}";
|
||||
$aActions['Class:SynchroReplica/Action:unlinksynchro'] = [
|
||||
'label' => Dict::S('Class:SynchroReplica/Action:unlinksynchro'),
|
||||
'url' => $sUrl,
|
||||
'tooltip' => Dict::S('Class:SynchroReplica/Action:unlinksynchro+'),
|
||||
];
|
||||
|
||||
$sUrl = "{$sRootUrl}synchro/replica.php?operation=synchro&class=$sClass&id=$sId{$sContext}";
|
||||
$aActions['Class:SynchroReplica/Action:synchro'] = [
|
||||
'label' => Dict::S('Class:SynchroReplica/Action:synchro'),
|
||||
'url' => $sUrl,
|
||||
'tooltip' => Dict::S('Class:SynchroReplica/Action:synchro+'),
|
||||
];
|
||||
|
||||
if ($this->Get('status_dest_creator') == 1) {
|
||||
$sUrl = "{$sRootUrl}synchro/replica.php?operation=denydelete&class=$sClass&id=$sId{$sContext}";
|
||||
$aActions['Class:SynchroReplica/Action:denydelete'] = [
|
||||
'label' => Dict::S('Class:SynchroReplica/Action:denydelete'),
|
||||
'url' => $sUrl,
|
||||
'tooltip' => Dict::S('Class:SynchroReplica/Action:denydelete+'),
|
||||
];
|
||||
} else {
|
||||
$sUrl = "{$sRootUrl}synchro/replica.php?operation=allowdelete&class=$sClass&id=$sId{$sContext}";
|
||||
$aActions['Class:SynchroReplica/Action:allowdelete'] = [
|
||||
'label' => Dict::S('Class:SynchroReplica/Action:allowdelete'),
|
||||
'url' => $sUrl,
|
||||
'tooltip' => Dict::S('Class:SynchroReplica/Action:allowdelete+'),
|
||||
];
|
||||
}
|
||||
}
|
||||
if (count($aActions) > 0) {
|
||||
$sRegularActionsMenuTogglerId = "ibo-regular-actions-menu-toggler-{$sId}";
|
||||
$sRegularActionsPopoverMenuId = "ibo-regular-actions-popover-{$sId}";
|
||||
|
||||
$oActionButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', Dict::S('UI:Menu:Actions'), 'UI:Menu:Actions', '', false, $sRegularActionsMenuTogglerId)
|
||||
->AddCSSClasses(['ibo-action-button', 'ibo-regular-action-button']);
|
||||
|
||||
$oRegularActionsMenu = $oPage->GetPopoverMenu($sRegularActionsPopoverMenuId, $aActions)
|
||||
->SetTogglerJSSelector("#$sRegularActionsMenuTogglerId")
|
||||
->SetContainer(PopoverMenu::ENUM_CONTAINER_BODY);
|
||||
|
||||
$oActionsToolbar->AddSubBlock($oActionButton)
|
||||
->AddSubBlock($oRegularActionsMenu);
|
||||
|
||||
$oActionButton = ButtonUIBlockFactory::MakeIconLink('fas fa-search', Dict::Format('UI:SearchFor_Class', MetaModel::GetName($sClass)), "{$sRootUrl}pages/UI.php?operation=search_form&do_search=0&class=$sClass{$sContext}", '', 'UI:SearchFor_Class');
|
||||
$oActionButton->AddCSSClasses(['ibo-action-button', 'ibo-regular-action-button']);
|
||||
$oActionsToolbar->AddSubBlock($oActionButton);
|
||||
}
|
||||
|
||||
$sUrl = "{$sRootUrl}pages/$sUIPage?operation=display&class=$sClass&id=$sId{$sContext}";
|
||||
$oActionButton = ButtonUIBlockFactory::MakeAlternativeNeutral('', 'UI:Button:Refresh');
|
||||
$oActionButton->SetIconClass('fas fa-sync-alt')
|
||||
->SetOnClickJsCode('window.location.href=\''.$sUrl.'\'')
|
||||
->SetTooltip(Dict::S('UI:Button:Refresh'))
|
||||
->AddCSSClasses(['ibo-action-button', 'ibo-regular-action-button']);
|
||||
$oActionsToolbar->AddSubBlock($oActionButton);
|
||||
|
||||
return $oBlock;
|
||||
}
|
||||
|
||||
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
|
||||
{
|
||||
if ($bEditMode) {
|
||||
|
||||
Reference in New Issue
Block a user