mirror of
https://github.com/Combodo/iTop.git
synced 2026-03-26 19:34:15 +01:00
Compare commits
269 Commits
faf/improv
...
3.2.0-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc553ca83c | ||
|
|
14c637c7f3 | ||
|
|
3ce6c8b7cf | ||
|
|
b4cdf5cf6d | ||
|
|
77cc4672b0 | ||
|
|
331e66e594 | ||
|
|
b65e931c4c | ||
|
|
de5a9261df | ||
|
|
46b0dabb1d | ||
|
|
dfbfab7005 | ||
|
|
aa831b632c | ||
|
|
6cb3519308 | ||
|
|
cfb9fae648 | ||
|
|
f4e791734f | ||
|
|
6653ab0668 | ||
|
|
7ab258ba03 | ||
|
|
b5af30a93f | ||
|
|
dad406d208 | ||
|
|
a6d01739ba | ||
|
|
e3501447ad | ||
|
|
2294fce5da | ||
|
|
ce5c05234d | ||
|
|
bbfa601ab1 | ||
|
|
93e1f6ae03 | ||
|
|
2a9add241e | ||
|
|
c9a9ec2fed | ||
|
|
83764deedb | ||
|
|
172b1cb1ff | ||
|
|
8a4e144725 | ||
|
|
5f35effad9 | ||
|
|
e1374a0e6b | ||
|
|
ca356859a3 | ||
|
|
5efe294895 | ||
|
|
6a6dacc8ce | ||
|
|
28feddb6c9 | ||
|
|
e6fa589412 | ||
|
|
18d0b88531 | ||
|
|
3139a0b610 | ||
|
|
e0170ccc7e | ||
|
|
c24e7ef318 | ||
|
|
ffefa5495a | ||
|
|
3f773539fe | ||
|
|
a371b7f03b | ||
|
|
de97a6263f | ||
|
|
233bbebd93 | ||
|
|
f0c5264fc8 | ||
|
|
367aac3e04 | ||
|
|
3b78885f38 | ||
|
|
793f5c7cbe | ||
|
|
1d4cb6034d | ||
|
|
e6814d6860 | ||
|
|
79198f51a3 | ||
|
|
f14b4c32be | ||
|
|
6be5264fe9 | ||
|
|
6a30d6caa9 | ||
|
|
628a7319d1 | ||
|
|
bc8543d88c | ||
|
|
a51242dc36 | ||
|
|
64ba706083 | ||
|
|
ed562c9f73 | ||
|
|
85c576a986 | ||
|
|
3deb74a4d1 | ||
|
|
b9dd891aac | ||
|
|
1f2469e1e4 | ||
|
|
8fa56a6f3f | ||
|
|
22af1a8787 | ||
|
|
5e15fbec45 | ||
|
|
3a6a5ca49d | ||
|
|
3d6509e246 | ||
|
|
cd34f8b5eb | ||
|
|
8357c86361 | ||
|
|
d48b5d7d21 | ||
|
|
efe61201e5 | ||
|
|
a458d98688 | ||
|
|
a3553202d9 | ||
|
|
b10d381dda | ||
|
|
9dc7b6dc0c | ||
|
|
1be67f349f | ||
|
|
4ca92affcf | ||
|
|
3f401e4de0 | ||
|
|
9b198bc76e | ||
|
|
f7230de6d6 | ||
|
|
a4aa494e5d | ||
|
|
8647414a33 | ||
|
|
a58f0bfc0b | ||
|
|
ff1305165e | ||
|
|
d9b87064a1 | ||
|
|
a468bf8f7e | ||
|
|
65c706fdfe | ||
|
|
0853645264 | ||
|
|
e6162fe958 | ||
|
|
25f266ef66 | ||
|
|
fee07960ca | ||
|
|
5a34c76cc4 | ||
|
|
5efb1a0872 | ||
|
|
2c68f78027 | ||
|
|
7f9b60d66f | ||
|
|
816df1b551 | ||
|
|
1278c4b196 | ||
|
|
a7f3bf9a56 | ||
|
|
4eed5bdeb9 | ||
|
|
739afdb1ec | ||
|
|
75a01db959 | ||
|
|
c29bff4d91 | ||
|
|
7b999cef50 | ||
|
|
69e481dbc1 | ||
|
|
279b29a98c | ||
|
|
12b30c1531 | ||
|
|
bcfbacc625 | ||
|
|
36d6c13941 | ||
|
|
4952fc5575 | ||
|
|
7b8634e9e7 | ||
|
|
c86ebba60d | ||
|
|
db4c70cea3 | ||
|
|
e8c4c45c5c | ||
|
|
a3d5712087 | ||
|
|
5b8a3459f5 | ||
|
|
8a983ecbb7 | ||
|
|
e62473d4e9 | ||
|
|
054520cdac | ||
|
|
b38a7c8ab6 | ||
|
|
3588a50597 | ||
|
|
babdd9f163 | ||
|
|
5d8a0f8e9f | ||
|
|
52106fe48c | ||
|
|
e7a04e0e70 | ||
|
|
90458f6048 | ||
|
|
3a990f46d3 | ||
|
|
673b01585d | ||
|
|
3653a4bc90 | ||
|
|
bdfd956825 | ||
|
|
da99a250bf | ||
|
|
d57fd05552 | ||
|
|
5554241877 | ||
|
|
d9232a645d | ||
|
|
def10a9877 | ||
|
|
b29597110e | ||
|
|
c7a8d90364 | ||
|
|
86489dbbe1 | ||
|
|
6098842d9f | ||
|
|
2f30a0146e | ||
|
|
193af6c759 | ||
|
|
1de9e704fc | ||
|
|
f4b9a9a5fe | ||
|
|
561e743fc3 | ||
|
|
fa5d03fc6e | ||
|
|
7b5fa0a912 | ||
|
|
5f88391935 | ||
|
|
29300fd91e | ||
|
|
2c8b2f6c71 | ||
|
|
4cde461876 | ||
|
|
5a3bfa8043 | ||
|
|
c5544a7a1e | ||
|
|
8ffcb01c43 | ||
|
|
5c46b4ef4a | ||
|
|
912c7fa956 | ||
|
|
79cdb837b5 | ||
|
|
db2ea617d3 | ||
|
|
7499e41e40 | ||
|
|
a97935ca01 | ||
|
|
dc6ea37f23 | ||
|
|
87181669d1 | ||
|
|
efd7fb0f59 | ||
|
|
c2f72f713a | ||
|
|
700c4d0b04 | ||
|
|
43a8152de1 | ||
|
|
8c1d986a03 | ||
|
|
f3dd414a51 | ||
|
|
d1a4d333eb | ||
|
|
b934cbe89e | ||
|
|
71a0f8b87d | ||
|
|
a4edf8cb21 | ||
|
|
dbd5ba0377 | ||
|
|
5d6f293956 | ||
|
|
65e6c84477 | ||
|
|
61e04c5a73 | ||
|
|
9cc7ccb1cd | ||
|
|
a337ef3d88 | ||
|
|
27ac1fe276 | ||
|
|
986c24d777 | ||
|
|
763112c179 | ||
|
|
a5efd981d8 | ||
|
|
6450b52697 | ||
|
|
c0e4d04a1c | ||
|
|
289ca7b505 | ||
|
|
2922b22478 | ||
|
|
2af05a437e | ||
|
|
71d9536bc4 | ||
|
|
b1e1a66496 | ||
|
|
d7270c56cd | ||
|
|
7a7b7381c9 | ||
|
|
da32362ef6 | ||
|
|
5569df5950 | ||
|
|
b08b5297cf | ||
|
|
3e6e096f62 | ||
|
|
6377a738c5 | ||
|
|
a9f8dcc5e8 | ||
|
|
9470d9b9ec | ||
|
|
9750fec959 | ||
|
|
969a301cbb | ||
|
|
c325294e17 | ||
|
|
8588757da9 | ||
|
|
f894cb24c6 | ||
|
|
722765c0aa | ||
|
|
5e9b4da68c | ||
|
|
af2c6d9ab8 | ||
|
|
0176905c20 | ||
|
|
5e4f76bde9 | ||
|
|
0c3e839381 | ||
|
|
5be386d03e | ||
|
|
2ced460ec6 | ||
|
|
ae9bda8bbb | ||
|
|
9566963835 | ||
|
|
cf6e8ab22a | ||
|
|
2aa1385958 | ||
|
|
509df0939e | ||
|
|
9032dac314 | ||
|
|
a29b0a8e33 | ||
|
|
fee1897932 | ||
|
|
093a4cec75 | ||
|
|
892a7fa95f | ||
|
|
48f7ae8476 | ||
|
|
10ef277982 | ||
|
|
ebe7da7acb | ||
|
|
9fa036df7e | ||
|
|
c24c1ba73c | ||
|
|
3650cf761d | ||
|
|
34c4d753d3 | ||
|
|
4d1f8e5704 | ||
|
|
7ac283bffb | ||
|
|
c1efad7556 | ||
|
|
f78b57521a | ||
|
|
da490739be | ||
|
|
8e8d586dcc | ||
|
|
e05b4e772c | ||
|
|
02efea4e55 | ||
|
|
17bab06ff5 | ||
|
|
ab4f224a00 | ||
|
|
fe6ee083f6 | ||
|
|
655539c289 | ||
|
|
33ba754277 | ||
|
|
7948793674 | ||
|
|
8c7b33fb06 | ||
|
|
db4dfe1ba3 | ||
|
|
e00112d6e1 | ||
|
|
3404306de8 | ||
|
|
ff7e4d3db6 | ||
|
|
e371db846a | ||
|
|
5bbf3c9c35 | ||
|
|
fe4233e218 | ||
|
|
8490c2a22f | ||
|
|
e758527ca9 | ||
|
|
3e9f4df1bf | ||
|
|
f3fbce7459 | ||
|
|
ff079f7d01 | ||
|
|
d4c54b6e1c | ||
|
|
39d1ddeab8 | ||
|
|
fada9793f0 | ||
|
|
45a8e6d1c8 | ||
|
|
bf4b07a366 | ||
|
|
48de13b5cf | ||
|
|
b867faa355 | ||
|
|
1848b5f231 | ||
|
|
9fa53d43ab | ||
|
|
646e86b207 | ||
|
|
e93c9b8537 | ||
|
|
849c495093 | ||
|
|
e878938e25 | ||
|
|
7453cc184f |
Binary file not shown.
|
After Width: | Height: | Size: 4.8 MiB |
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -65,7 +65,7 @@ Don't remove these lines, check them once done.
|
||||
- [ ] I have performed a self-review of my code
|
||||
- [ ] I have tested all changes I made on an iTop instance
|
||||
- [ ] I have added a unit test, otherwise I have explained why I couldn't
|
||||
- [ ] Is the PR clear and detailled enough so anyone can understand digging in the code?
|
||||
- [ ] Is the PR clear and detailed enough so anyone can understand digging in the code?
|
||||
|
||||
## Checklist of things to do before PR is ready to merge
|
||||
<!--
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -47,6 +47,9 @@ tests/*/vendor/*
|
||||
!/log/index.php
|
||||
!/log/web.config
|
||||
|
||||
# NPM: `jquery-ui` package is just there for vulnerability scans, so we don't want to version its files (only `jquery-ui-dist` is used within the code base)
|
||||
/node_modules/jquery-ui/**
|
||||
|
||||
# PHPUnit: Cache file, local XML working copies
|
||||
/tests/php-unit-tests/.phpunit.result.cache
|
||||
/tests/php-unit-tests/phpunit.xml
|
||||
|
||||
@@ -4,7 +4,7 @@ $iBeginTime = time();
|
||||
chdir(__DIR__);
|
||||
|
||||
$aCommands = [
|
||||
'php composer/rmDeniedTestDir.php',
|
||||
'php composer/rmUnnecessaryFolders.php',
|
||||
'php build/commands/setupCssCompiler.php',
|
||||
// 'bash /tmp/gabuzomeu.sh',
|
||||
];
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2023 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Composer\iTopComposer;
|
||||
|
||||
$iTopFolder = __DIR__ . "/../../" ;
|
||||
|
||||
require_once ("$iTopFolder/approot.inc.php");
|
||||
require_once (APPROOT."/setup/setuputils.class.inc.php");
|
||||
|
||||
if (php_sapi_name() !== 'cli')
|
||||
{
|
||||
throw new \Exception('This script can only run from CLI');
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
|
||||
$oiTopComposer = new iTopComposer();
|
||||
$aDeniedButStillPresent = $oiTopComposer->ListDeniedButStillPresent();
|
||||
|
||||
echo "\n";
|
||||
foreach ($aDeniedButStillPresent as $sDir)
|
||||
{
|
||||
if (false === iTopComposer::IsTestDir($sDir))
|
||||
{
|
||||
echo "ERROR found INVALID denied test dir: '$sDir'\n";
|
||||
throw new \Exception("$sDir must end with /Test/ or /test/");
|
||||
}
|
||||
|
||||
if (false === file_exists($sDir)) {
|
||||
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
SetupUtils::rrmdir($sDir);
|
||||
echo "OK Remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
echo "\nFAILED to remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$aAllowedAndDeniedDirs = array_merge(
|
||||
$oiTopComposer->ListAllowedTestDir(),
|
||||
$oiTopComposer->ListDeniedTestDir()
|
||||
);
|
||||
$aExistingDirs = $oiTopComposer->ListAllTestDir();
|
||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
||||
if (false === empty($aMissing)) {
|
||||
echo "Some new tests dirs exists !\n"
|
||||
.' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n"
|
||||
.' List of dirs:'."\n".var_export($aMissing, true);
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
* @link https://getcomposer.org/doc/03-cli.md#show
|
||||
*/
|
||||
|
||||
$iTopFolder = __DIR__."/../../";
|
||||
$iTopFolder = __DIR__."/../../../";
|
||||
|
||||
require_once("$iTopFolder/approot.inc.php");
|
||||
$sApproot = APPROOT;
|
||||
@@ -13,7 +13,7 @@
|
||||
* @link https://github.com/tecnickcom/TCPDF?tab=readme-ov-file#note TCPDF is in support only mode
|
||||
*/
|
||||
|
||||
$sItopRootFolder = realpath(__DIR__ . "/../../../");
|
||||
$sItopRootFolder = realpath(__DIR__ . "/../../../../");
|
||||
$sCurrentScriptFileName = basename(__FILE__);
|
||||
|
||||
|
||||
51
.make/dependencies/npm/restoreFolderBrowsingProtection.php
Normal file
51
.make/dependencies/npm/restoreFolderBrowsingProtection.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2023 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ensure that the files for folder browsing protection (.htaccess, web.config) are kept after an "npm install/update" command
|
||||
*/
|
||||
|
||||
$iTopFolder = __DIR__."/../../../";
|
||||
|
||||
require_once("$iTopFolder/approot.inc.php");
|
||||
|
||||
$sDependenciesRootFolderAbsPath = APPROOT . "node_modules/";
|
||||
$aFilesToCheck = [
|
||||
".htaccess",
|
||||
"web.config",
|
||||
];
|
||||
|
||||
echo "This command aims at ensuring that folder browsing protection files (.htaccess, web.config) are present in the dependencies folder even after an install/upgrade command\n";
|
||||
echo "Checking files:\n";
|
||||
|
||||
foreach($aFilesToCheck as $sFileToCheck) {
|
||||
if (file_exists($sDependenciesRootFolderAbsPath . $sFileToCheck)) {
|
||||
echo "✔️ $sFileToCheck is present\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// If missing, copy the one from /lib as it contains the necessary allow/deny directives for third-parties
|
||||
copy(APPROOT . "lib/$sFileToCheck", $sDependenciesRootFolderAbsPath . $sFileToCheck);
|
||||
echo "✔️ $sFileToCheck was missing and has been re-created\n";
|
||||
}
|
||||
|
||||
// Ensure separation with following scripts
|
||||
echo "\n";
|
||||
95
.make/dependencies/rmUnnecessaryFolders.php
Normal file
95
.make/dependencies/rmUnnecessaryFolders.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2023 Combodo SARL
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
$iTopFolder = __DIR__ . "/../../" ;
|
||||
|
||||
require_once ("$iTopFolder/approot.inc.php");
|
||||
require_once (APPROOT."/setup/setuputils.class.inc.php");
|
||||
|
||||
if (php_sapi_name() !== 'cli')
|
||||
{
|
||||
throw new \Exception('This script can only run from CLI');
|
||||
}
|
||||
|
||||
clearstatcache();
|
||||
|
||||
// Read params
|
||||
$key = array_search("--manager", $argv);
|
||||
if (false === $key || false === isset($argv[$key + 1]) ) {
|
||||
throw new \InvalidArgumentException("Usage: " . __FILE__ . " --manager composer|npm");
|
||||
}
|
||||
$sDependenciesHandlerCode = $argv[$key + 1];
|
||||
|
||||
switch ($sDependenciesHandlerCode) {
|
||||
case "composer":
|
||||
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\Composer\iTopComposer::class;
|
||||
break;
|
||||
|
||||
case "npm":
|
||||
$sDependenciesHandlerFQCN = \Combodo\iTop\Dependencies\NPM\iTopNPM::class;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception("Invalid dependencies handler code, $sDependenciesHandlerCode given, expected composer|npm");
|
||||
}
|
||||
|
||||
// Start handler
|
||||
$oDependenciesHandler = new $sDependenciesHandlerFQCN();
|
||||
$aDeniedButStillPresent = $oDependenciesHandler->ListDeniedButStillPresentFoldersAbsPaths();
|
||||
|
||||
echo "\n";
|
||||
foreach ($aDeniedButStillPresent as $sDir)
|
||||
{
|
||||
if (false === $oDependenciesHandler::IsQuestionnableFolder($sDir))
|
||||
{
|
||||
echo "ERROR found INVALID denied test dir: '$sDir'\n";
|
||||
throw new \RuntimeException("$sDir is in the denied list but doesn't comply with the rule (see IsQuestionnableFolder method)");
|
||||
}
|
||||
|
||||
if (false === file_exists($sDir)) {
|
||||
echo "INFO $sDir is in denied list, but not existing on disk => skipping !\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
SetupUtils::rrmdir($sDir);
|
||||
echo "✔️ Remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
echo "\n❌ FAILED to remove denied test dir: '$sDir'\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$aAllowedAndDeniedDirs = array_merge(
|
||||
$oDependenciesHandler->ListAllowedFoldersAbsPaths(),
|
||||
$oDependenciesHandler->ListDeniedFoldersAbsPaths()
|
||||
);
|
||||
$aExistingDirs = $oDependenciesHandler->ListAllFoldersAbsPaths();
|
||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
||||
if (false === empty($aMissing)) {
|
||||
echo "Some new tests dirs exists !\n"
|
||||
." They must be declared either in the allowed or denied list in {$sDependenciesHandlerFQCN}\n"
|
||||
.' List of dirs:'."\n".var_export($aMissing, true)."\n";
|
||||
}
|
||||
|
||||
// Ensure separation with following scripts
|
||||
echo "\n";
|
||||
@@ -159,6 +159,6 @@ We have one sticker per contribution type. You might get multiple stickers with
|
||||
* Beta tester: Test and give feedback on beta releases
|
||||
* Extension developer: Develop and publish an extension
|
||||
|
||||
Here is the design of each stickers for year 2022:
|
||||
Here is the design of each stickers for year 2024:
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -2099,8 +2099,16 @@ class RestUtils
|
||||
elseif (is_string($key))
|
||||
{
|
||||
// OQL
|
||||
$oSearch = DBObjectSearch::FromOQL($key);
|
||||
}
|
||||
try {
|
||||
$oSearch = DBObjectSearch::FromOQL($key);
|
||||
} catch (Exception $e) {
|
||||
throw new CoreOqlException('Query failed to execute', [
|
||||
'query' => $key,
|
||||
'exception_class' => get_class($e),
|
||||
'exception_message' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Wrong format for key");
|
||||
@@ -2273,4 +2281,19 @@ interface iKPILoggerExtension
|
||||
* @return mixed
|
||||
*/
|
||||
public function LogOperation($oKpiLogData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this interface to add files to the backup
|
||||
*
|
||||
* @api
|
||||
* @since 3.2.0
|
||||
*/
|
||||
interface iBackupExtraFilesExtension
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
* @return string[] Array of relative paths (from app root) for files and directories to be included in the backup
|
||||
*/
|
||||
public function GetExtraFilesRelPaths(): array;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\Helper\CKEditorHelper;
|
||||
use Combodo\iTop\Application\Helper\FormHelper;
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
@@ -2323,14 +2324,14 @@ JS
|
||||
// To change the default settings of the editor,
|
||||
// a) edit the file /js/ckeditor/config.js
|
||||
// b) or override some of the configuration settings, using the second parameter of ckeditor()
|
||||
$aConfig = utils::GetCkeditorPref();
|
||||
$aConfig = CKEditorHelper::GetCkeditorPref();
|
||||
$aConfig['placeholder'] = Dict::S('UI:CaseLogTypeYourTextHere');
|
||||
|
||||
// - Final config
|
||||
$sConfigJS = json_encode($aConfig);
|
||||
|
||||
WebResourcesHelper::EnableCKEditorToWebPage($oPage);
|
||||
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, $sConfigJS);"); // Transform $iId into a CKEdit
|
||||
$oPage->add_ready_script("CombodoCKEditorHandler.CreateInstance('#$iId')");
|
||||
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
@@ -2429,7 +2430,7 @@ HTML;
|
||||
$sInputType = self::ENUM_INPUT_TYPE_IMAGE;
|
||||
$aEventsList[] = 'validate';
|
||||
$aEventsList[] = 'change';
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/edit_image.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/edit_image.js');
|
||||
$oDocument = $value; // Value is an ormDocument objectm
|
||||
$sDefaultUrl = $oAttDef->Get('default_image');
|
||||
if (is_object($oDocument) && !$oDocument->IsEmpty()) {
|
||||
@@ -2545,11 +2546,11 @@ HTML;
|
||||
$sHTMLValue .= '</div></div>';
|
||||
$sHTMLValue .= '<div>'.$sReloadSpan.'</div>'; // No validation span for this one: it does handle its own validation!
|
||||
$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" type=\"hidden\" id=\"$iId\" value=\"\"/>\n";
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_handler.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/console_form_handler.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_set.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_field.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/subform_field.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/form_handler.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/console_form_handler.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/field_set.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/form_field.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/subform_field.js');
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
$('#{$iId}_field_set').field_set($sFieldSetOptions);
|
||||
@@ -2575,9 +2576,9 @@ JS
|
||||
case 'Set':
|
||||
case 'TagSet':
|
||||
$sInputType = self::ENUM_INPUT_TYPE_TAGSET;
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/selectize.min.js');
|
||||
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/selectize.default.css');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.itop-set-widget.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/selectize.min.js');
|
||||
$oPage->LinkStylesheetFromAppRoot('css/selectize.default.css');
|
||||
$oPage->LinkScriptFromAppRoot('js/jquery.itop-set-widget.js');
|
||||
|
||||
$oPage->add_dict_entry('Core:AttributeSet:placeholder');
|
||||
|
||||
@@ -3452,7 +3453,7 @@ EOF
|
||||
// Dummy collapsible section created in order to get JS files
|
||||
$oCollapsibleSection = new CollapsibleSection('');
|
||||
foreach ($oCollapsibleSection->GetJsFilesUrlRecursively(true) as $sJSFile) {
|
||||
$oPage->add_linked_script($sJSFile);
|
||||
$oPage->LinkScriptFromURI($sJSFile);
|
||||
}
|
||||
}
|
||||
$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs);
|
||||
|
||||
@@ -480,7 +480,7 @@ abstract class Dashboard
|
||||
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
||||
|
||||
$('#attr_auto_reload').change( function(ev) {
|
||||
$('#attr_auto_reload').on('change', function(ev) {
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
|
||||
} );
|
||||
|
||||
@@ -563,8 +563,8 @@ JS
|
||||
}
|
||||
|
||||
if (!$bEditMode) {
|
||||
$oPage->add_linked_script('../js/dashlet.js');
|
||||
$oPage->add_linked_script('../js/dashboard.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/dashlet.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/dashboard.js');
|
||||
}
|
||||
|
||||
return $oDashboard;
|
||||
@@ -1118,8 +1118,8 @@ JS
|
||||
*/
|
||||
protected function RenderEditionTools(WebPage $oPage, DashboardLayoutUIBlock $oDashboard, $aExtraParams)
|
||||
{
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
|
||||
$oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.iframe-transport.js');
|
||||
$oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.fileupload.js');
|
||||
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
|
||||
|
||||
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
|
||||
@@ -1272,6 +1272,7 @@ EOF
|
||||
$sAutoReloadSec = (string) $this->iAutoReloadSec;
|
||||
$sTitle = utils::HtmlEntities($this->sTitle);
|
||||
$sFile = utils::HtmlEntities($this->GetDefinitionFile());
|
||||
$sFileForJS = json_encode($this->GetDefinitionFile());
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
|
||||
$sReloadURL = $this->GetReloadURL();
|
||||
|
||||
@@ -1333,9 +1334,9 @@ $('#dashboard_editor .ui-layout-center').runtimedashboard({
|
||||
auto_reload: $sAutoReload,
|
||||
auto_reload_sec: $sAutoReloadSec,
|
||||
submit_to: '$sUrl',
|
||||
submit_parameters: {operation: 'save_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
submit_parameters: {operation: 'save_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
render_to: '$sUrl',
|
||||
render_parameters: {operation: 'render_dashboard', file: '$sFile', extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
render_parameters: {operation: 'render_dashboard', file: {$sFileForJS}, extra_params: $sJSExtraParams, reload_url: '$sReloadURL'},
|
||||
new_dashlet_parameters: {operation: 'new_dashlet'}
|
||||
});
|
||||
|
||||
|
||||
@@ -187,7 +187,9 @@
|
||||
</menus>
|
||||
<events>
|
||||
<event id="EVENT_DB_BEFORE_WRITE" _delta="define">
|
||||
<description>An object is about to be written into the database. The object can be modified.</description>
|
||||
<name>Before create or update</name>
|
||||
<description><![CDATA[An object is about to be written into the database.
|
||||
The object can be modified.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -208,7 +210,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_CHECK_TO_WRITE" _delta="define">
|
||||
<description>Check an object before it is written into the database (no change possible). Call DBObject::AddCheckIssue() to signal an issue</description>
|
||||
<name>Check to write</name>
|
||||
<description><![CDATA[Check an object before it is written into the database (no change possible).
|
||||
Call $this->AddCheckIssue() to signal an issue.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -229,7 +233,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_AFTER_WRITE" _delta="define">
|
||||
<description>An object has been written into the database. The modifications can be propagated to other objects.</description>
|
||||
<name>After create or update</name>
|
||||
<description><![CDATA[An object has been written into the database.
|
||||
The modifications can be propagated to other objects.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -244,7 +250,7 @@
|
||||
<type>boolean</type>
|
||||
</event_datum>
|
||||
<event_datum id="changes">
|
||||
<description>For updates, the list of changes done during this operation</description>
|
||||
<description><![CDATA[For updates, the list of changes done during this operation]]></description>
|
||||
<type>array</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
@@ -254,7 +260,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_CHECK_TO_DELETE" _delta="define">
|
||||
<description>Check an object before it is deleted from the database. Call DBObject::AddDeleteIssue() to signal an issue</description>
|
||||
<name>Check to delete</name>
|
||||
<description><![CDATA[Check an object before it is deleted from the database.
|
||||
Call $this->AddDeleteIssue() to signal an issue.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -271,7 +279,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_ABOUT_TO_DELETE" _delta="define">
|
||||
<description>An object is about to be deleted from the database</description>
|
||||
<name>Before delete</name>
|
||||
<description><![CDATA[An object is about to be deleted from the database]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -288,7 +297,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_AFTER_DELETE" _delta="define">
|
||||
<description>An object has been deleted into the database</description>
|
||||
<name>After delete</name>
|
||||
<description><![CDATA[An object has been deleted into the database]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -305,7 +315,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_ENUM_TRANSITIONS" _delta="define">
|
||||
<description>Manage the allowed transitions in current object state. The only action allowed is to deny transitions with DBObject::DenyTransition()</description>
|
||||
<name>Enum transitions</name>
|
||||
<description><![CDATA[Manage the allowed transitions in current object state.
|
||||
The only action allowed is to deny transitions with $this->DenyTransition()]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -325,7 +337,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_LINKS_CHANGED" _delta="define">
|
||||
<description>At least one link class was changed</description>
|
||||
<name>Links on object have changed</name>
|
||||
<description><![CDATA[At least one link class was changed]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -341,7 +354,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_OBJECT_RELOAD" _delta="define">
|
||||
<description>An object has been re-loaded from the database</description>
|
||||
<name>Object reload</name>
|
||||
<internal>true</internal>
|
||||
<description><![CDATA[An object has been re-loaded from the database]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -357,7 +372,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_COMPUTE_VALUES" _delta="define">
|
||||
<description>An object needs to be recomputed after changes</description>
|
||||
<name>Recompute object values</name>
|
||||
<description><![CDATA[An object needs to be recomputed after changes]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -374,7 +390,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_ARCHIVE" _delta="define">
|
||||
<description>An object has been archived</description>
|
||||
<name>Object archived</name>
|
||||
<description><![CDATA[An object has been archived]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -390,7 +407,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_UNARCHIVE" _delta="define">
|
||||
<description>An object has been unarchived</description>
|
||||
<name>Object unarchived</name>
|
||||
<description><![CDATA[An object has been unarchived]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -406,7 +424,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_SET_ATTRIBUTES_FLAGS" _delta="define">
|
||||
<description>Set object attributes flags. Call cmdbAbstractObject::AddAttributeFlags() for all the attributes to be set for this target state.</description>
|
||||
<name>Set attributes flags</name>
|
||||
<description><![CDATA[Set object attributes flags.
|
||||
Call $this->AddAttributeFlags() for all the attributes to be set for this target state.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -417,7 +437,7 @@
|
||||
</event_datum>
|
||||
<event_datum id="target_state">
|
||||
<description>The target state in which to evaluate the flags</description>
|
||||
<type>array</type>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
@@ -426,7 +446,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DB_SET_INITIAL_ATTRIBUTES_FLAGS" _delta="define">
|
||||
<description>Set object initial attributes flags. Call cmdbAbstractObject::AddInitialAttributeFlags() for all the initial attributes to be set initially.</description>
|
||||
<name>Set initial attributes flags</name>
|
||||
<description><![CDATA[Set object initial attributes flags.
|
||||
Call $this->AddInitialAttributeFlags() for all the initial attributes to be set initially.]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
@@ -442,7 +464,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DOWNLOAD_DOCUMENT" _delta="define">
|
||||
<description>A document has been downloaded from the GUI</description>
|
||||
<name>Document downloaded</name>
|
||||
<description><![CDATA[A document has been downloaded from the GUI]]></description>
|
||||
<sources>
|
||||
<source id="Document">Document</source>
|
||||
</sources>
|
||||
@@ -470,7 +493,9 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_LOGIN" _delta="define">
|
||||
<description>Inform the listeners about the connection states</description>
|
||||
<name>Login</name>
|
||||
<internal>true</internal>
|
||||
<description><![CDATA[Inform the listeners about the connection states]]></description>
|
||||
<event_data>
|
||||
<event_datum id="code">
|
||||
<description>The login step result code (LoginWebPage::EXIT_CODE_...) </description>
|
||||
|
||||
@@ -326,6 +326,7 @@ class DataTable
|
||||
$sPagesLinks = implode('', $aPagesToDisplay);
|
||||
$sPagesList = '['.implode(',', array_keys($aPagesToDisplay)).']';
|
||||
|
||||
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$sSelectionMode = ($iNbPages == 1) ? '' : 'positive';
|
||||
$sHtml =
|
||||
<<<EOF
|
||||
@@ -333,11 +334,11 @@ class DataTable
|
||||
<div $sPagerStyle>
|
||||
<table id="pager{$this->iListId}" class="pager"><tr>
|
||||
<td>$sPages</td>
|
||||
<td><img src="../images/first.png" class="first"/></td>
|
||||
<td><img src="../images/prev.png" class="prev"/></td>
|
||||
<td><img src="{$sAppRootUrl}images/first.png" class="first"/>AAAA</td>
|
||||
<td><img src="{$sAppRootUrl}images/prev.png" class="prev"/></td>
|
||||
<td><span id="index">$sPagesLinks</span></td>
|
||||
<td><img src="../images/next.png" class="next"/></td>
|
||||
<td><img src="../images/last.png" class="last"/></td>
|
||||
<td><img src="{$sAppRootUrl}images/next.png" class="next"/></td>
|
||||
<td><img src="{$sAppRootUrl}images/last.png" class="last"/></td>
|
||||
<td>$sPageSizeCombo</td>
|
||||
<td><span id="loading"> </span><input type="hidden" name="selectionMode" value="$sSelectionMode"></input>
|
||||
</td>
|
||||
|
||||
@@ -570,7 +570,7 @@ class DisplayBlock
|
||||
} else {
|
||||
// render it as an Ajax (asynchronous) call
|
||||
$oHtml->AddCSSClass("loading");
|
||||
$oHtml->AddHtml("<p><img src=\"../images/indicator_arrows.gif\"> ".Dict::S('UI:Loading').'</p>');
|
||||
$oHtml->AddHtml("<p><img src=\"".utils::GetAbsoluteUrlAppRoot()."images/indicator_arrows.gif\"> ".Dict::S('UI:Loading').'</p>');
|
||||
$oPage->add_script('
|
||||
$.post("ajax.render.php?style='.$this->m_sStyle.'",
|
||||
{ operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" },
|
||||
|
||||
@@ -97,8 +97,8 @@ class LoginWebPage extends NiceWebPage
|
||||
|
||||
public function SetStyleSheet()
|
||||
{
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/login.css');
|
||||
$this->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/font-awesome/css/all.min.css');
|
||||
$this->LinkStylesheetFromAppRoot('css/login.css');
|
||||
$this->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -125,9 +125,7 @@ class ApplicationMenu
|
||||
*/
|
||||
public static function CheckMenuIdEnabled($sMenuId)
|
||||
{
|
||||
self::LoadAdditionalMenus();
|
||||
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
|
||||
if (is_null($oMenuNode) || !$oMenuNode->IsEnabled())
|
||||
if (self::IsMenuIdEnabled($sMenuId) === false)
|
||||
{
|
||||
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||
$oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError'));
|
||||
@@ -138,6 +136,19 @@ class ApplicationMenu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sMenuId
|
||||
*
|
||||
* @return bool true if the menu exists and current user is allowed to see the menu
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static function IsMenuIdEnabled($sMenuId):bool
|
||||
{
|
||||
self::LoadAdditionalMenus();
|
||||
$oMenuNode = self::GetMenuNode(self::GetMenuIndexById($sMenuId));
|
||||
return is_null($oMenuNode) === false && $oMenuNode->IsEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function to add a menu entry into the application, can be called during the definition
|
||||
* of the data model objects
|
||||
@@ -269,9 +280,11 @@ class ApplicationMenu
|
||||
$oMenuNode = static::GetMenuNode($sMenuGroupIdx);
|
||||
|
||||
if (!($oMenuNode instanceof MenuGroup)) {
|
||||
IssueLog::Error('Menu node was not displayed as a menu group as it is actually not a menu group', LogChannels::CONSOLE, [
|
||||
IssueLog::Error('Menu node without parent (root menu) must be of type menu group. Parent menu is missing or not visible to user.', LogChannels::CONSOLE, [
|
||||
'menu_node_class' => get_class($oMenuNode),
|
||||
'menu_node_id' => $oMenuNode->GetMenuID(),
|
||||
'menu_node_label' => $oMenuNode->GetLabel(),
|
||||
'current_user_id' => UserRights::GetUserId(),
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ $("#attr_auto_reload_sec").attr('data-tooltip-content', '$sRateTitle');
|
||||
CombodoTooltip.InitTooltipFromMarkup($("#attr_auto_reload_sec"));
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$('#attr_auto_reload').is(':checked'));
|
||||
|
||||
$('#attr_auto_reload').change( function(ev) {
|
||||
$('#attr_auto_reload').on('change', function(ev) {
|
||||
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
|
||||
} );
|
||||
|
||||
|
||||
@@ -232,12 +232,13 @@ class DisplayTemplate
|
||||
static public function UnitTest()
|
||||
{
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
|
||||
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$sTemplate = '<div class="page_header">
|
||||
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
|
||||
<h1>$class$: <span class="hilite">$name$</span></h1>
|
||||
</div>
|
||||
<img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
|
||||
<img src="'.$sAppRootUrl.'images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
|
||||
<itoptabs>
|
||||
<itoptab name="Interfaces">
|
||||
<itopblock blockclass="DisplayBlock" type="list" encoding="text/oql">SELECT Interface AS i WHERE i.device_id = $id$</itopblock>
|
||||
@@ -350,7 +351,8 @@ class ObjectDetailsTemplate extends DisplayTemplate
|
||||
if ($iFlags & OPT_ATT_SLAVE)
|
||||
{
|
||||
$iSynchroFlags = $this->m_oObj->GetSynchroReplicaFlags($sAttCode, $aReasons);
|
||||
$sSynchroIcon = " <img id=\"synchro_$iInputId\" src=\"../images/transp-lock.png\" style=\"vertical-align:middle\"/>";
|
||||
$sAppRooturl = utils::GetAbsoluteUrlAppRoot();
|
||||
$sSynchroIcon = " <img id=\"synchro_$iInputId\" src=\"{$sAppRooturl}images/transp-lock.png\" style=\"vertical-align:middle\"/>";
|
||||
$sTip = '';
|
||||
foreach($aReasons as $aRow)
|
||||
{
|
||||
|
||||
@@ -161,8 +161,8 @@ class UIExtKeyWidget
|
||||
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array(), &$sInputType = '')
|
||||
{
|
||||
$sTitle = addslashes($sTitle);
|
||||
$oPage->add_linked_script('../js/extkeywidget.js');
|
||||
$oPage->add_linked_script('../js/forms-json-utils.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
|
||||
|
||||
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_MODIFY) && $bAllowTargetCreation);
|
||||
$bExtensions = true;
|
||||
@@ -368,7 +368,7 @@ JS
|
||||
*/
|
||||
public function DisplayRadio(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, DBObjectset $oAllowedValues, $value, $sFieldName, $sDisplayStyle)
|
||||
{
|
||||
$oPage->add_linked_script('../js/forms-json-utils.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
|
||||
|
||||
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
|
||||
$bExtensions = true;
|
||||
@@ -477,8 +477,8 @@ JS
|
||||
$this->bSearchMode = $bSearchMode;
|
||||
}
|
||||
$sTitle = addslashes($sTitle);
|
||||
$oPage->add_linked_script('../js/extkeywidget.js');
|
||||
$oPage->add_linked_script('../js/forms-json-utils.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/extkeywidget.js');
|
||||
$oPage->LinkScriptFromAppRoot('js/forms-json-utils.js');
|
||||
|
||||
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
|
||||
$bExtensions = true;
|
||||
@@ -734,7 +734,7 @@ HTML
|
||||
],
|
||||
});
|
||||
$('#fs_{$this->iId}').on('submit.uiAutocomplete', oACWidget_{$this->iId}.DoSearchObjects);
|
||||
$('#dc_{$this->iId}').resize(oACWidget_{$this->iId}.UpdateSizes);
|
||||
$('#dc_{$this->iId}').on('resize', oACWidget_{$this->iId}.UpdateSizes);
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\Helper\CKEditorHelper;
|
||||
use Combodo\iTop\Application\Helper\WebResourcesHelper;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Renderer\BlockRenderer;
|
||||
|
||||
/**
|
||||
* Class UIHTMLEditorWidget
|
||||
@@ -73,7 +76,7 @@ class UIHTMLEditorWidget
|
||||
// a) edit the file /js/ckeditor/config.js
|
||||
// b) or override some of the configuration settings, using the second parameter of ckeditor()
|
||||
$sJSDefineWidth = '';
|
||||
$aConfig = utils::GetCkeditorPref();
|
||||
$aConfig = CKEditorHelper::GetCkeditorPref();
|
||||
$sWidthSpec = addslashes(trim($this->m_oAttDef->GetWidth()));
|
||||
if ($sWidthSpec != '') {
|
||||
/*N°6543 - the function min allow to keep text inside the column when width is defined*/
|
||||
@@ -84,10 +87,20 @@ class UIHTMLEditorWidget
|
||||
if ($sHeightSpec != '') {
|
||||
$aConfig['height'] = $sHeightSpec;
|
||||
}
|
||||
// TODO 3.2.0 Add the configuration for the editor
|
||||
$sConfigJS = json_encode($aConfig);
|
||||
|
||||
WebResourcesHelper::EnableCKEditorToWebPage($oPage);
|
||||
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, $sConfigJS);"); // Transform $iId into a CKEdit
|
||||
$oPage->add_ready_script("CombodoCKEditorHandler.CreateInstance('#$iId', $sConfigJS)");
|
||||
|
||||
// inject mention item renderer template
|
||||
$oTwig = TwigHelper::GetTwigEnvironment(BlockRenderer::TWIG_BASE_PATH);
|
||||
$sTemplate = $oTwig->render('application/object/set/option_renderer.html.twig');
|
||||
$oPage->add(<<<HTML
|
||||
<template id="{$iId}_items_template">
|
||||
$sTemplate
|
||||
</template>
|
||||
HTML);
|
||||
|
||||
// Please read...
|
||||
// ValidateCKEditField triggers a timer... calling itself indefinitely
|
||||
|
||||
@@ -99,7 +99,7 @@ HTML
|
||||
});
|
||||
$('#dlg_{$this->m_iInputId}').dialog('option', {title:'$sTitle'});
|
||||
$('#SearchFormToAdd_{$this->m_iInputId} form').on('submit.uilinksWizard', oForeignKeysWidget{$this->m_iInputId}.SearchObjectsToAdd);
|
||||
$('#SearchFormToAdd_{$this->m_iInputId}').resize(oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
|
||||
$('#SearchFormToAdd_{$this->m_iInputId}').on('resize', oForeignKeysWidget{$this->m_iInputId}.UpdateSizes);
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class UserDashboard extends DBObject
|
||||
(
|
||||
"category" => "gui",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "user_id",
|
||||
"name_attcode" => array('user_id', 'menu_code'),
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_app_dashboards",
|
||||
@@ -47,6 +47,15 @@ class UserDashboard extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("user_id", array("targetclass"=>"User", "allowed_values"=>null, "sql"=>"user_id", "is_null_allowed"=>false, "on_target_delete"=>DEL_AUTO, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("menu_code", array("allowed_values"=>null, "sql"=>"menu_code", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("contents", array("allowed_values"=>null, "sql"=>"contents", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_SetZListItems('default_search', array (
|
||||
0 => 'user_id',
|
||||
1 => 'menu_code',
|
||||
));
|
||||
MetaModel::Init_SetZListItems('list', array (
|
||||
0 => 'user_id',
|
||||
1 => 'menu_code',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,6 @@ use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
|
||||
use Combodo\iTop\Application\UI\Hook\iKeyboardShortcut;
|
||||
use Combodo\iTop\Application\WebPage\WebPage;
|
||||
use Combodo\iTop\Service\Module\ModuleService;
|
||||
use Combodo\iTop\Test\UnitTest\Application\utilsTest;
|
||||
use ScssPhp\ScssPhp\Compiler;
|
||||
use ScssPhp\ScssPhp\OutputStyle;
|
||||
use ScssPhp\ScssPhp\ValueConverter;
|
||||
@@ -2781,76 +2780,6 @@ SQL;
|
||||
return static::$iNextId++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CKEditor config as an array
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static function GetCkeditorPref()
|
||||
{
|
||||
$sLanguage = strtolower(trim(UserRights::GetUserLanguage()));
|
||||
|
||||
$aDefaultConf = array(
|
||||
'language'=> $sLanguage,
|
||||
'contentsLanguage' => $sLanguage,
|
||||
'extraPlugins' => 'disabler,codesnippet,mentions,objectshortcut,font,uploadimage',
|
||||
'uploadUrl' => utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php',
|
||||
'contentsCss' => array(utils::GetAbsoluteUrlAppRoot().'js/ckeditor/contents.css', utils::GetAbsoluteUrlAppRoot().'css/ckeditor/contents.css'),
|
||||
);
|
||||
|
||||
// Mentions
|
||||
$aMentionsAllowedClasses = MetaModel::GetConfig()->Get('mentions.allowed_classes');
|
||||
if(!empty($aMentionsAllowedClasses)) {
|
||||
$aDefaultConf['mentions'] = [];
|
||||
|
||||
foreach($aMentionsAllowedClasses as $sMentionMarker => $sMentionScope) {
|
||||
// Retrieve mention class
|
||||
// - First test if the conf is a simple Datamodel class
|
||||
if (MetaModel::IsValidClass($sMentionScope)) {
|
||||
$sMentionClass = $sMentionScope;
|
||||
}
|
||||
// - Otherwise it must be a valid OQL
|
||||
else {
|
||||
$oTmpSearch = DBSearch::FromOQL($sMentionScope);
|
||||
$sMentionClass = $oTmpSearch->GetClass();
|
||||
unset($oTmpSearch);
|
||||
}
|
||||
|
||||
// Note: Endpoints are defaults only and should be overloaded by other GUIs such as the end-users portal
|
||||
$sMentionEndpoint = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=cke_mentions&marker='.urlencode($sMentionMarker).'&needle={encodedQuery}';
|
||||
$sMentionItemUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class='.$sMentionClass.'&id={id}';
|
||||
|
||||
$sMentionItemPictureTemplate = (empty(MetaModel::GetImageAttributeCode($sMentionClass))) ? '' : <<<HTML
|
||||
<span class="ibo-vendors-ckeditor--autocomplete-item-image" style="{picture_style}">{initials}</span>
|
||||
HTML;
|
||||
$sMentionItemTemplate = <<<HTML
|
||||
<li class="ibo-vendors-ckeditor--autocomplete-item" data-id="{id}">{$sMentionItemPictureTemplate}<span class="ibo-vendors-ckeditor--autocomplete-item-title">{friendlyname}</span></li>
|
||||
HTML;
|
||||
$sMentionOutputTemplate = <<<HTML
|
||||
<a href="$sMentionItemUrl" data-role="object-mention" data-object-class="{class}" data-object-id="{id}">{$sMentionMarker}{friendlyname}</a>
|
||||
HTML;
|
||||
|
||||
$aDefaultConf['mentions'][] = [
|
||||
'feed' => $sMentionEndpoint,
|
||||
'marker' => $sMentionMarker,
|
||||
'minChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'),
|
||||
'itemTemplate' => $sMentionItemTemplate,
|
||||
'outputTemplate' => $sMentionOutputTemplate,
|
||||
'throttle' => 500,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$aRichTextConfig = json_decode(appUserPreferences::GetPref('richtext_config', '{}'), true);
|
||||
|
||||
|
||||
return array_merge($aDefaultConf, $aRichTextConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sInterface
|
||||
* @param string $sClassNameFilter
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
"symfony/var-dumper": "~6.4.0",
|
||||
"symfony/yaml": "~6.4.0",
|
||||
"tecnickcom/tcpdf": "^6.6.0",
|
||||
"thenetworg/oauth2-azure": "^2.0"
|
||||
"thenetworg/oauth2-azure": "^2.0",
|
||||
"masterminds/html5": "^2.8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/debug-bundle": "~6.4.0",
|
||||
@@ -44,9 +45,10 @@
|
||||
"ext-libsodium": "Required to use the AttributeEncryptedString.",
|
||||
"ext-openssl": "Can be used as a polyfill if libsodium is not installed",
|
||||
"ext-mcrypt": "Can be used as a polyfill if either libsodium and openssl are not installed (libsodium and openssl are more secure)",
|
||||
"ext-apcu": "For better performance and stability",
|
||||
"ext-imap": "Required by the extension \"Mail to ticket automation\"",
|
||||
"ext-ldap": "Required to use LDAP as an identity provider",
|
||||
"ext-posix": "Not required by the core, but some extensions uses it.",
|
||||
"ext-imap": "Required by the extension \"Mail to ticket automation\""
|
||||
"ext-posix": "Not required by the core, but some extensions uses it."
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
@@ -93,13 +95,13 @@
|
||||
"require": "3.4.*"
|
||||
},
|
||||
"runtime": {
|
||||
"dotenv_path": "symfony/.env"
|
||||
"dotenv_path": "resources/symfony/.env"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": ["@rmDeniedTestDir", "@tcpdfCustomFonts"],
|
||||
"post-update-cmd": ["@rmDeniedTestDir", "@tcpdfCustomFonts"],
|
||||
"rmDeniedTestDir": "@php .make/composer/rmDeniedTestDir.php",
|
||||
"tcpdfCustomFonts": "@php .make/composer/tcpdf/tcpdfUpdateFonts.php"
|
||||
"post-install-cmd": ["@rmUnnecessaryFolders", "@tcpdfCustomFonts"],
|
||||
"post-update-cmd": ["@rmUnnecessaryFolders", "@tcpdfCustomFonts"],
|
||||
"rmUnnecessaryFolders": "@php .make/dependencies/rmUnnecessaryFolders.php --manager composer",
|
||||
"tcpdfCustomFonts": "@php .make/dependencies/composer/tcpdf/tcpdfUpdateFonts.php"
|
||||
}
|
||||
}
|
||||
|
||||
69
composer.lock
generated
69
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f12a58e43bfb3a44aba20a73a8fd747f",
|
||||
"content-hash": "c8ab1de6659dd4fa2ded6043615b86e6",
|
||||
"packages": [
|
||||
{
|
||||
"name": "apereo/phpcas",
|
||||
@@ -1018,6 +1018,73 @@
|
||||
},
|
||||
"time": "2023-03-17T15:20:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6",
|
||||
"reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Masterminds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"keywords": [
|
||||
"HTML5",
|
||||
"dom",
|
||||
"html",
|
||||
"parser",
|
||||
"querypath",
|
||||
"serializer",
|
||||
"xml"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.9.0"
|
||||
},
|
||||
"time": "2024-03-31T07:05:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.18.0",
|
||||
|
||||
@@ -60,14 +60,15 @@ function apc_store($key, $var = NULL, $ttl = 0)
|
||||
*/
|
||||
function apc_fetch($key)
|
||||
{
|
||||
if (is_array($key))
|
||||
{
|
||||
$aResult = array();
|
||||
foreach($key as $sKey)
|
||||
{
|
||||
if (is_array($key)) {
|
||||
$aResult = [];
|
||||
foreach ($key as $sKey) {
|
||||
$aResult[$sKey] = apcFile::FetchOneFile($sKey);
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
} elseif (is_null($key)) {
|
||||
return false;
|
||||
}
|
||||
return apcFile::FetchOneFile($key);
|
||||
}
|
||||
@@ -246,21 +247,16 @@ class apcFile
|
||||
*/
|
||||
static public function StoreOneFile($sKey, $value, $iTTL)
|
||||
{
|
||||
if (empty($sKey))
|
||||
{
|
||||
if (empty($sKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_file(self::GetCacheFileName($sKey)))
|
||||
{
|
||||
if (is_file(self::GetCacheFileName($sKey))) {
|
||||
@unlink(self::GetCacheFileName($sKey));
|
||||
}
|
||||
if (is_file(self::GetCacheFileName('-'.$sKey)))
|
||||
{
|
||||
if (is_file(self::GetCacheFileName('-'.$sKey))) {
|
||||
@unlink(self::GetCacheFileName('-'.$sKey));
|
||||
}
|
||||
if ($iTTL > 0)
|
||||
{
|
||||
if ($iTTL > 0) {
|
||||
// hint for ttl management
|
||||
$sKey = '-'.$sKey;
|
||||
}
|
||||
@@ -268,15 +264,14 @@ class apcFile
|
||||
$sFilename = self::GetCacheFileName($sKey);
|
||||
// try to create the folder
|
||||
$sDirname = dirname($sFilename);
|
||||
if (!file_exists($sDirname))
|
||||
{
|
||||
if (!@mkdir($sDirname, 0755, true))
|
||||
{
|
||||
if (!is_dir($sDirname)) {
|
||||
if (!@mkdir($sDirname, 0755, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$bRes = !(@file_put_contents($sFilename, serialize($value), LOCK_EX) === false);
|
||||
self::AddFile($sFilename);
|
||||
|
||||
return $bRes;
|
||||
}
|
||||
|
||||
@@ -360,19 +355,15 @@ class apcFile
|
||||
*/
|
||||
static protected function ReadCacheLocked($sFilename)
|
||||
{
|
||||
if (!is_file($sFilename))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$sContent = false;
|
||||
$file = @fopen($sFilename, 'r');
|
||||
if ($file === false)
|
||||
{
|
||||
return false;
|
||||
if ($file !== false) {
|
||||
if (flock($file, LOCK_SH)) {
|
||||
$sContent = file_get_contents($sFilename);
|
||||
flock($file, LOCK_UN);
|
||||
}
|
||||
fclose($file);
|
||||
}
|
||||
flock($file, LOCK_SH);
|
||||
$sContent = @fread($file, @filesize($sFilename));
|
||||
flock($file, LOCK_UN);
|
||||
fclose($file);
|
||||
return $sContent;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,11 @@ define('DEL_SILENT', 2);
|
||||
*/
|
||||
define('DEL_MOVEUP', 3);
|
||||
|
||||
/**
|
||||
* Do nothing at least automatically
|
||||
*/
|
||||
define('DEL_NONE', 4);
|
||||
|
||||
|
||||
/**
|
||||
* For Link sets: tracking_level
|
||||
@@ -3196,9 +3201,19 @@ class AttributeDecimal extends AttributeDBField
|
||||
{
|
||||
$iNbDigits = $this->Get('digits');
|
||||
$iPrecision = $this->Get('decimals');
|
||||
$iNbIntegerDigits = $iNbDigits - $iPrecision - 1; // -1 because the first digit is treated separately in the pattern below
|
||||
$iNbIntegerDigits = $iNbDigits - $iPrecision;
|
||||
|
||||
return "^[\-\+]?[0-9]\d{0,$iNbIntegerDigits}(\.\d{0,$iPrecision})?$";
|
||||
return "^[\-\+]?\d{1,$iNbIntegerDigits}(\.\d{0,$iPrecision})?$";
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function CheckFormat($value)
|
||||
{
|
||||
$sRegExp = $this->GetValidationPattern();
|
||||
return preg_match("/$sRegExp/", $value);
|
||||
}
|
||||
|
||||
public function GetBasicFilterOperators()
|
||||
@@ -3293,7 +3308,7 @@ class AttributeDecimal extends AttributeDBField
|
||||
|
||||
if (!is_null($value) && ($value !== ''))
|
||||
{
|
||||
$value = sprintf("%01.".$this->Get('decimals')."F", $value);
|
||||
$value = sprintf("%1.".$this->Get('decimals')."F", $value);
|
||||
}
|
||||
return $value; // null or string
|
||||
}
|
||||
@@ -6514,37 +6529,46 @@ class AttributeDateTime extends AttributeDBField
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @param int|string $proposedValue timestamp ({@see DateTime::getTimestamp()) or date as string, following the {@see GetInternalFormat} format.
|
||||
*/
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @param int|DateTime|string $proposedValue possible values :
|
||||
* - timestamp ({@see DateTime::getTimestamp())
|
||||
* - {@see \DateTime} PHP object
|
||||
* - string, following the {@see GetInternalFormat} format.
|
||||
*
|
||||
* @throws \CoreUnexpectedValue if invalid value type or the string passed cannot be converted
|
||||
*/
|
||||
public function MakeRealValue($proposedValue, $oHostObj)
|
||||
{
|
||||
if (is_null($proposedValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (is_string($proposedValue) && ($proposedValue == "") && $this->IsNullAllowed())
|
||||
{
|
||||
return null;
|
||||
|
||||
if (is_numeric($proposedValue)) {
|
||||
return date(static::GetInternalFormat(), $proposedValue);
|
||||
}
|
||||
if (!is_numeric($proposedValue))
|
||||
{
|
||||
// Check the format
|
||||
try
|
||||
{
|
||||
$oFormat = new DateTimeFormat($this->GetInternalFormat());
|
||||
|
||||
if (is_object($proposedValue) && ($proposedValue instanceof DateTime)) {
|
||||
return $proposedValue->format(static::GetInternalFormat());
|
||||
}
|
||||
|
||||
if (is_string($proposedValue)) {
|
||||
if (($proposedValue === '') && $this->IsNullAllowed()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$oFormat = new DateTimeFormat(static::GetInternalFormat());
|
||||
$oFormat->Parse($proposedValue);
|
||||
} catch (Exception $e)
|
||||
{
|
||||
throw new Exception('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"');
|
||||
} catch (Exception $e) {
|
||||
throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode().', expecting "'.$this->GetInternalFormat().'" and got "'.$proposedValue.'"');
|
||||
}
|
||||
|
||||
return $proposedValue;
|
||||
}
|
||||
|
||||
return date(static::GetInternalFormat(), $proposedValue);
|
||||
throw new CoreUnexpectedValue('Wrong format for date attribute '.$this->GetCode());
|
||||
}
|
||||
|
||||
public function ScalarToSQL($value)
|
||||
|
||||
@@ -35,11 +35,37 @@ abstract class CellChangeSpec
|
||||
return $this->m_proposedValue;
|
||||
}
|
||||
|
||||
public function GetDisplayableValue()
|
||||
/**
|
||||
* @throws \Exception
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function GetCLIValue(bool $bLocalizedValues = false): string
|
||||
{
|
||||
if (is_object($this->m_proposedValue)) {
|
||||
if ($this->m_proposedValue instanceof ReportValue) {
|
||||
return $this->m_proposedValue->GetAsCSV($bLocalizedValues, ',', '"');
|
||||
}
|
||||
throw new Exception('Unexpected class : '. get_class($this->m_proposedValue));
|
||||
}
|
||||
return $this->m_proposedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function GetHTMLValue(bool $bLocalizedValues = false): string
|
||||
{
|
||||
if (is_object($this->m_proposedValue)) {
|
||||
if ($this->m_proposedValue instanceof ReportValue) {
|
||||
return $this->m_proposedValue->GetAsHTML($bLocalizedValues);
|
||||
}
|
||||
throw new Exception('Unexpected class : '. get_class($this->m_proposedValue));
|
||||
}
|
||||
return utils::EscapeHtml($this->m_proposedValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
*/
|
||||
@@ -54,12 +80,12 @@ abstract class CellChangeSpec
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.1.0 N°5305
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function GetDisplayableValueAndDescription(): string
|
||||
public function GetCLIValueAndDescription(): string
|
||||
{
|
||||
return sprintf("%s%s",
|
||||
$this->GetDisplayableValue(),
|
||||
$this->GetCLIValue(),
|
||||
$this->GetDescription()
|
||||
);
|
||||
}
|
||||
@@ -108,13 +134,25 @@ class CellStatus_Issue extends CellStatus_Modify
|
||||
parent::__construct($proposedValue, $previousValue);
|
||||
}
|
||||
|
||||
public function GetDisplayableValue()
|
||||
public function GetCLIValue(bool $bLocalizedValues = false): string
|
||||
{
|
||||
if (is_null($this->m_proposedValue)) {
|
||||
return Dict::Format('UI:CSVReport-Value-SetIssue');
|
||||
}
|
||||
return Dict::Format('UI:CSVReport-Value-ChangeIssue',$this->m_proposedValue);
|
||||
}
|
||||
|
||||
public function GetHTMLValue(bool $bLocalizedValues = false): string
|
||||
{
|
||||
if (is_null($this->m_proposedValue))
|
||||
{
|
||||
return Dict::Format('UI:CSVReport-Value-SetIssue');
|
||||
}
|
||||
return Dict::Format('UI:CSVReport-Value-ChangeIssue', \utils::EscapeHtml($this->m_proposedValue));
|
||||
if ($this->m_proposedValue instanceof ReportValue)
|
||||
{
|
||||
return Dict::Format('UI:CSVReport-Value-ChangeIssue', $this->m_proposedValue->GetAsHTML($bLocalizedValues));
|
||||
}
|
||||
return Dict::Format('UI:CSVReport-Value-ChangeIssue',utils::EscapeHtml($this->m_proposedValue));
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
@@ -122,12 +160,12 @@ class CellStatus_Issue extends CellStatus_Modify
|
||||
return $this->m_sReason;
|
||||
}
|
||||
/*
|
||||
* @since 3.1.0 N°5305
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public function GetDisplayableValueAndDescription(): string
|
||||
public function GetCLIValueAndDescription(): string
|
||||
{
|
||||
return sprintf("%s. %s",
|
||||
$this->GetDisplayableValue(),
|
||||
$this->GetCLIValue(),
|
||||
$this->GetDescription()
|
||||
);
|
||||
}
|
||||
@@ -172,7 +210,7 @@ class CellStatus_SearchIssue extends CellStatus_Issue
|
||||
$this->sAllowedValuesSearch = $sAllowedValuesSearch;
|
||||
}
|
||||
|
||||
public function GetDisplayableValue()
|
||||
public function GetCLIValue(bool $bLocalizedValues = false): string
|
||||
{
|
||||
if (null === $this->m_sReason) {
|
||||
return Dict::Format('UI:CSVReport-Value-NoMatch', '');
|
||||
@@ -181,6 +219,15 @@ class CellStatus_SearchIssue extends CellStatus_Issue
|
||||
return $this->m_sReason;
|
||||
}
|
||||
|
||||
public function GetHTMLValue(bool $bLocalizedValues = false): string
|
||||
{
|
||||
if (null === $this->m_sReason) {
|
||||
return Dict::Format('UI:CSVReport-Value-NoMatch', '');
|
||||
}
|
||||
|
||||
return utils::EscapeHtml($this->m_sReason);
|
||||
}
|
||||
|
||||
public function GetDescription()
|
||||
{
|
||||
if (\utils::IsNullOrEmptyString($this->m_sAllowedValues) ||
|
||||
@@ -227,6 +274,33 @@ class CellStatus_NullIssue extends CellStatus_Issue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to differ formatting depending on the caller
|
||||
*/
|
||||
class ReportValue
|
||||
{
|
||||
/**
|
||||
* @param DBObject $oObject
|
||||
* @param string $sAttCode
|
||||
* @param bool $bOriginal
|
||||
*/
|
||||
public function __construct(protected DBObject $oObject, protected string $sAttCode, protected bool $bOriginal){}
|
||||
|
||||
public function GetAsHTML(bool $bLocalizedValues)
|
||||
{
|
||||
if ($this->bOriginal) {
|
||||
return $this->oObject->GetOriginalAsHTML($this->sAttCode, $bLocalizedValues);
|
||||
}
|
||||
return $this->oObject->GetAsHTML($this->sAttCode, $bLocalizedValues);
|
||||
}
|
||||
public function GetAsCSV (bool $bLocalizedValues, string $sCsvSep, string $sCsvDelimiter) {
|
||||
if ($this->bOriginal) {
|
||||
return $this->oObject->GetOriginalAsCSV($this->sAttCode, $sCsvSep, $sCsvDelimiter, $bLocalizedValues);
|
||||
}
|
||||
return $this->oObject->GetAsCSV($this->sAttCode, $sCsvSep, $sCsvDelimiter, $bLocalizedValues);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CellStatus_Ambiguous extends CellStatus_Issue
|
||||
{
|
||||
@@ -413,22 +487,6 @@ class BulkChange
|
||||
$this->m_aExtKeysMappingCache = array();
|
||||
}
|
||||
|
||||
protected $m_bReportHtml = false;
|
||||
protected $m_sReportCsvSep = ',';
|
||||
protected $m_sReportCsvDelimiter = '"';
|
||||
|
||||
public function SetReportHtml()
|
||||
{
|
||||
$this->m_bReportHtml = true;
|
||||
}
|
||||
|
||||
public function SetReportCsv($sSeparator = ',', $sDelimiter = '"')
|
||||
{
|
||||
$this->m_bReportHtml = false;
|
||||
$this->m_sReportCsvSep = $sSeparator;
|
||||
$this->m_sReportCsvDelimiter = $sDelimiter;
|
||||
}
|
||||
|
||||
protected function ResolveExternalKey($aRowData, $sAttCode, &$aResults)
|
||||
{
|
||||
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
@@ -446,7 +504,7 @@ class BulkChange
|
||||
$value = $oForeignAtt->MakeValueFromString($aRowData[$iCol], $this->m_bLocalizedValues);
|
||||
}
|
||||
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
|
||||
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
|
||||
$oExtObjects = new CMDBObjectSet($oReconFilter);
|
||||
@@ -470,7 +528,7 @@ class BulkChange
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject $oTargetObj
|
||||
* @param DBObject $oTargetObj
|
||||
* @param array $aRowData
|
||||
* @param array $aErrors
|
||||
*
|
||||
@@ -533,7 +591,7 @@ class BulkChange
|
||||
}
|
||||
$aCacheKeys[] = $value;
|
||||
$oReconFilter->AddCondition($sReconKeyAttCode, $value, '=');
|
||||
$aResults[$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
$aResults[$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
$sCacheKey = implode('_|_', $aCacheKeys); // Unique key for this query...
|
||||
$iForeignKey = null;
|
||||
@@ -602,7 +660,7 @@ class BulkChange
|
||||
foreach ($aReconKeys as $sReconKeyAttCode => $iCol)
|
||||
{
|
||||
// Report the change on reconciliation values as well
|
||||
$aResults[$iCol] = new CellStatus_Modify(utils::HtmlEntities($aRowData[$iCol]));
|
||||
$aResults[$iCol] = new CellStatus_Modify($aRowData[$iCol]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -680,50 +738,32 @@ class BulkChange
|
||||
// Reporting on fields
|
||||
//
|
||||
$aChangedFields = $oTargetObj->ListChanges();
|
||||
foreach ($this->m_aAttList as $sAttCode => $iCol)
|
||||
{
|
||||
if ($sAttCode == 'id')
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
foreach ($this->m_aAttList as $sAttCode => $iCol) {
|
||||
if ($sAttCode == 'id') {
|
||||
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->m_bReportHtml)
|
||||
{
|
||||
$sCurValue = $oTargetObj->GetAsHTML($sAttCode, $this->m_bLocalizedValues);
|
||||
$sOrigValue = $oTargetObj->GetOriginalAsHTML($sAttCode, $this->m_bLocalizedValues);
|
||||
else {
|
||||
$sCurValue = new ReportValue($oTargetObj, $sAttCode, false);
|
||||
$sOrigValue = new ReportValue($oTargetObj, $sAttCode, true);
|
||||
if (isset($aErrors[$sAttCode])) {
|
||||
$aResults[$iCol]= new CellStatus_Issue($aRowData[$iCol], $sOrigValue, $aErrors[$sAttCode]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCurValue = $oTargetObj->GetAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter, $this->m_bLocalizedValues);
|
||||
$sOrigValue = $oTargetObj->GetOriginalAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter, $this->m_bLocalizedValues);
|
||||
}
|
||||
if (isset($aErrors[$sAttCode]))
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Issue(utils::HtmlEntities($aRowData[$iCol]), $sOrigValue, $aErrors[$sAttCode]);
|
||||
}
|
||||
elseif (array_key_exists($sAttCode, $aChangedFields))
|
||||
{
|
||||
if ($oTargetObj->IsNew())
|
||||
{
|
||||
elseif (array_key_exists($sAttCode, $aChangedFields)){
|
||||
if ($oTargetObj->IsNew()) {
|
||||
$aResults[$iCol]= new CellStatus_Void($sCurValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
$aResults[$iCol]= new CellStatus_Modify($sCurValue, $sOrigValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// By default... nothing happens
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
if ($oAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
if ($oAttDef instanceof AttributeDateTime) {
|
||||
$aResults[$iCol]= new CellStatus_Void($oAttDef->GetFormat()->Format($aRowData[$iCol]));
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
else {
|
||||
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -788,7 +828,7 @@ class BulkChange
|
||||
// Possibles values are displayed to UI user. we have to limit the amount of displayed values
|
||||
$oExtObjectSetWithCurrentUserPermissions->SetLimit(4);
|
||||
for($i = 0; $i < 3; $i++){
|
||||
/** @var \DBObject $oVisibleObject */
|
||||
/** @var DBObject $oVisibleObject */
|
||||
$oVisibleObject = $oExtObjectSetWithCurrentUserPermissions->Fetch();
|
||||
if (is_null($oVisibleObject)){
|
||||
break;
|
||||
@@ -1155,7 +1195,7 @@ class BulkChange
|
||||
if (!preg_match($sRegExp, $sValue))
|
||||
{
|
||||
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue(utils::HtmlEntities($sValue), null, $sErrorMsg);
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue($sValue, null, $sErrorMsg);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -1168,6 +1208,7 @@ class BulkChange
|
||||
}
|
||||
else
|
||||
{
|
||||
// almost impossible ti reproduce since even incorrect dates with correct formats are formated and $oDate will not be false
|
||||
// Leave the cell unchanged
|
||||
$aResult[$iRow]["__STATUS__"]= new RowStatus_Issue(Dict::S('UI:CSVReport-Row-Issue-DateFormat'));
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue($sValue, null, $sErrorMsg);
|
||||
@@ -1307,7 +1348,7 @@ class BulkChange
|
||||
{
|
||||
if (!array_key_exists($iCol, $aResult[$iRow]))
|
||||
{
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
}
|
||||
foreach($this->m_aExtKeys as $sAttCode => $aForeignAtts)
|
||||
@@ -1321,7 +1362,7 @@ class BulkChange
|
||||
if (!array_key_exists($iCol, $aResult[$iRow]))
|
||||
{
|
||||
// The foreign attribute is one of our reconciliation key
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void(utils::HtmlEntities($aRowData[$iCol]));
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1446,7 +1487,7 @@ EOF
|
||||
<<<EOF
|
||||
function OnTruncatedHistoryToggle(bShowAll)
|
||||
{
|
||||
$('#csv_history_reload').html('<img src="../images/indicator.gif"/>');
|
||||
$('#csv_history_reload').html('<img src="' + GetAbsoluteUrlAppRoot() + 'images/indicator.gif"/>');
|
||||
$.get(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?{$sAppContext}', {operation: 'displayCSVHistory', showall: bShowAll}, function(data)
|
||||
{
|
||||
$('#$sAjaxDivId').html(data);
|
||||
|
||||
@@ -549,10 +549,9 @@ class CMDBSource
|
||||
/**
|
||||
* @param string $sSQLQuery
|
||||
*
|
||||
* @return \mysqli_result|null
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \CoreException
|
||||
* @return mysqli_result|null
|
||||
* @throws MySQLException
|
||||
* @throws MySQLHasGoneAwayException
|
||||
*
|
||||
* @since 2.7.0 N°679 handles nested transactions
|
||||
*/
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
{
|
||||
$oRecipientsSearch = DBObjectSearch::FromOQL($this->Get('recipients'));
|
||||
$oRecipientsSearch->AllowAllData();
|
||||
$oRecipientsSet = new DBObjectSet($oRecipientsSearch);
|
||||
$oRecipientsSet = new DBObjectSet($oRecipientsSearch, array(), $aContextArgs);
|
||||
$bIsAsync = $this->IsAsynchronous();
|
||||
[$sPreviousLanguage, $aPreviousPluginProperties] = $this->SetNotificationLanguage();
|
||||
|
||||
@@ -397,6 +397,34 @@
|
||||
</field>
|
||||
</fields>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="date">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="title">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="message">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="contact_id">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="trigger_id">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="action_id">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
<item id="read">
|
||||
<rank>70</rank>
|
||||
</item>
|
||||
<item id="url">
|
||||
<rank>80</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<summary>
|
||||
<items>
|
||||
<item id="date">
|
||||
|
||||
@@ -2319,16 +2319,17 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aUniquenessRuleProperties uniqueness rule properties
|
||||
*
|
||||
* @param string $sUniquenessRuleId uniqueness rule ID
|
||||
* @return \DBSearch
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param string $sUniquenessRuleId uniqueness rule ID
|
||||
* @param array $aUniquenessRuleProperties uniqueness rule properties
|
||||
*
|
||||
* @return \DBSearch
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
* @since 2.6.0 N°659 uniqueness constraint
|
||||
* @api
|
||||
* @since 2.6.0 N°659 uniqueness constraint
|
||||
* @since 2.7.11 3.1.2 3.2.0 N°4314 Fix Uniqueness rules not working with Silo
|
||||
*/
|
||||
protected function GetSearchForUniquenessRule($sUniquenessRuleId, $aUniquenessRuleProperties)
|
||||
{
|
||||
@@ -4744,7 +4745,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
}
|
||||
$oDate->modify($sModifier);
|
||||
$this->Set($sAttCode, $oDate->getTimestamp());
|
||||
$this->Set($sAttCode, $oDate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5361,16 +5362,19 @@ abstract class DBObject implements iDisplay
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
protected function GetReferencingObjects($bAllowAllData = false)
|
||||
protected function GetReferencingObjectsForDeletion($bAllowAllData = false)
|
||||
{
|
||||
$aDependentObjects = array();
|
||||
$aRererencingMe = MetaModel::EnumReferencingClasses(get_class($this));
|
||||
foreach($aRererencingMe as $sRemoteClass => $aExtKeys)
|
||||
{
|
||||
/** @var \AttributeExternalKey $oExtKeyAttDef */
|
||||
foreach($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef)
|
||||
{
|
||||
// skip if external key doesn't require the deletion cascading
|
||||
if($oExtKeyAttDef->GetDeletionPropagationOption() === DEL_NONE) continue;
|
||||
|
||||
// skip if this external key is behind an external field
|
||||
/** @var \AttributeDefinition $oExtKeyAttDef */
|
||||
if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) continue;
|
||||
|
||||
$oSearch = new DBObjectSearch($sRemoteClass);
|
||||
@@ -5434,13 +5438,11 @@ abstract class DBObject implements iDisplay
|
||||
$this->CheckToWriteForTargetObjects(true);
|
||||
$oDeletionPlan->SetDeletionIssues($this, $this->m_aDeleteIssues, $this->m_bSecurityIssue);
|
||||
|
||||
$aDependentObjects = $this->GetReferencingObjects(true /* allow all data */);
|
||||
|
||||
// Getting and setting time limit are not symmetric:
|
||||
// www.php.net/manual/fr/function.set-time-limit.php#72305
|
||||
$iPreviousTimeLimit = ini_get('max_execution_time');
|
||||
|
||||
foreach ($aDependentObjects as $aPotentialDeletes)
|
||||
foreach ($this->GetReferencingObjectsForDeletion(true /* allow all data */) as $aPotentialDeletes)
|
||||
{
|
||||
foreach ($aPotentialDeletes as $aData)
|
||||
{
|
||||
|
||||
@@ -6,102 +6,7 @@
|
||||
|
||||
/** @internal Dev hack for disabling some query build optimizations (Folding/Merging) */
|
||||
define('ENABLE_OPT', true);
|
||||
class DBSharedSearch extends DBObjectSearch {
|
||||
|
||||
public function MakeSelectQuery($aOrderBy = array(), $aArgs = array(), $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false, $bBeautifulSQL = true)
|
||||
{
|
||||
// Check the order by specification, and prefix with the class alias
|
||||
// and make sure that the ordering columns are going to be selected
|
||||
//
|
||||
$sClass = $this->GetClass();
|
||||
$sClassAlias = $this->GetClassAlias();
|
||||
$aOrderSpec = array();
|
||||
foreach ($aOrderBy as $sFieldAlias => $bAscending)
|
||||
{
|
||||
if (!is_bool($bAscending))
|
||||
{
|
||||
throw new CoreException("Wrong direction in ORDER BY spec, found '$bAscending' and expecting a boolean value");
|
||||
}
|
||||
|
||||
$iDotPos = strpos($sFieldAlias, '.');
|
||||
if ($iDotPos === false)
|
||||
{
|
||||
$sAttClass = $sClass;
|
||||
$sAttClassAlias = $sClassAlias;
|
||||
$sAttCode = $sFieldAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAttClassAlias = substr($sFieldAlias, 0, $iDotPos);
|
||||
$sAttClass = $this->GetClassName($sAttClassAlias);
|
||||
$sAttCode = substr($sFieldAlias, $iDotPos + 1);
|
||||
}
|
||||
|
||||
if ($sAttCode != 'id')
|
||||
{
|
||||
MyHelpers::CheckValueInArray('field name in ORDER BY spec', $sAttCode, MetaModel::GetAttributesList($sAttClass));
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef($sAttClass, $sAttCode);
|
||||
foreach($oAttDef->GetOrderBySQLExpressions($sAttClassAlias) as $sSQLExpression)
|
||||
{
|
||||
$aOrderSpec[$sSQLExpression] = $bAscending;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aOrderSpec['`'.$sAttClassAlias.$sAttCode.'`'] = $bAscending;
|
||||
}
|
||||
|
||||
// Make sure that the columns used for sorting are present in the loaded columns
|
||||
if (!is_null($aAttToLoad) && !isset($aAttToLoad[$sAttClassAlias][$sAttCode]))
|
||||
{
|
||||
$aAttToLoad[$sAttClassAlias][$sAttCode] = MetaModel::GetAttributeDef($sAttClass, $sAttCode);
|
||||
}
|
||||
}
|
||||
/*******START difference with MakeSelectQuery **************/
|
||||
$sClass = key($aAttToLoad);
|
||||
$sKey = $aAttToLoad[$sClass][0];
|
||||
$oObjId = new FieldExpression($sKey, $sClass);
|
||||
|
||||
$oSQLQuery = $this->GetSQLQuery($aOrderBy, $aArgs, [], $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, null, [$oObjId] );
|
||||
/********END difference with MakeSelectQuery*************/
|
||||
|
||||
if ($this->m_bNoContextParameters)
|
||||
{
|
||||
// Only internal parameters
|
||||
$aScalarArgs = $this->GetInternalParams();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The complete list of arguments will include magic arguments (e.g. current_user->attcode)
|
||||
$aScalarArgs = MetaModel::PrepareQueryArguments($aArgs, $this->GetInternalParams(), $this->GetExpectedArguments());
|
||||
}
|
||||
try
|
||||
{
|
||||
$sRes = $oSQLQuery->RenderSelect($aOrderSpec, $aScalarArgs, $iLimitCount, $iLimitStart, $bGetCount, $bBeautifulSQL);
|
||||
if ($sClassAlias == '_itop_')
|
||||
{
|
||||
IssueLog::Info('SQL Query (_itop_): '.$sRes);
|
||||
}
|
||||
}
|
||||
catch (MissingQueryArgument $e)
|
||||
{
|
||||
// Add some information...
|
||||
$e->addInfo('OQL', $this->ToOQL());
|
||||
throw $e;
|
||||
}
|
||||
$this->AddQueryTraceSelect($oSQLQuery->GetSourceOQL(), $aOrderBy, $aScalarArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $sRes);
|
||||
return $sRes;
|
||||
}
|
||||
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null)
|
||||
{
|
||||
$oSQLQuery = parent::GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr, $aSelectExpr);
|
||||
|
||||
$oSQLQuery->SetSelect($aSelectExpr);
|
||||
return $oSQLQuery;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* A search over a DBObject
|
||||
*
|
||||
@@ -1004,15 +909,15 @@ class DBObjectSearch extends DBSearch
|
||||
*/
|
||||
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
|
||||
{
|
||||
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
|
||||
if (!MetaModel::IsValidKeyAttCode($this->GetClass(), $sExtKeyAttCode))
|
||||
{
|
||||
throw new CoreWarning("The attribute code '$sExtKeyAttCode' is not an external key of the class '{$this->GetClass()}'");
|
||||
}
|
||||
$oAttExtKey = MetaModel::GetAttributeDef($this->GetClass(), $sExtKeyAttCode);
|
||||
if(!MetaModel::IsSameFamilyBranch($oFilter->GetClass(), $oAttExtKey->GetTargetClass()))
|
||||
{
|
||||
throw new CoreException("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
|
||||
}
|
||||
throw new CoreException("The specified filter (pointing to {$oFilter->GetClass()}) is not compatible with the key '{$this->GetClass()}::$sExtKeyAttCode', which is pointing to {$oAttExtKey->GetTargetClass()}");
|
||||
}
|
||||
if(($iOperatorCode != TREE_OPERATOR_EQUALS) && !($oAttExtKey instanceof AttributeHierarchicalKey))
|
||||
{
|
||||
throw new CoreException("The specified tree operator $iOperatorCode is not applicable to the key '{$this->GetClass()}::$sExtKeyAttCode', which is not a HierarchicalKey");
|
||||
@@ -1711,10 +1616,6 @@ class DBObjectSearch extends DBSearch
|
||||
{
|
||||
return NestedQueryExpression::FromOQLObjectQuery($oExpression->GetOQLObjectQuery());
|
||||
}
|
||||
elseif ($oExpression instanceof SharedQueryExpression)
|
||||
{
|
||||
return SharedQueryExpression::FromOQLObjectQuery($oExpression->GetOQLObjectQuery());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CoreException('Unknown expression type', array('class'=>get_class($oExpression), 'query'=>$sQuery));
|
||||
|
||||
@@ -28,8 +28,13 @@ namespace Combodo\iTop;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMFormatException;
|
||||
use DOMNode;
|
||||
use DOMNodeList;
|
||||
use DOMXPath;
|
||||
use Exception;
|
||||
use IssueLog;
|
||||
use LogAPI;
|
||||
use MFElement;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
@@ -41,6 +46,11 @@ use utils;
|
||||
*/
|
||||
class DesignDocument extends DOMDocument
|
||||
{
|
||||
|
||||
/** To fix DOMNode::getLineNo() ref https://www.php.net/manual/en/domnode.getlineno.php */
|
||||
public const XML_PARSE_BIG_LINES = 4194304;
|
||||
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
@@ -71,12 +81,12 @@ class DesignDocument extends DOMDocument
|
||||
*/
|
||||
public function load(string $filename, int $options = 0): bool
|
||||
{
|
||||
libxml_clear_errors();
|
||||
if (parent::load($filename, LIBXML_NOBLANKS) === false) {
|
||||
$aErrors = libxml_get_errors();
|
||||
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
|
||||
|
||||
return false;
|
||||
if (is_file($filename)) {
|
||||
libxml_clear_errors();
|
||||
if (parent::load($filename, LIBXML_NOBLANKS | LIBXML_BIGLINES | LIBXML_PARSEHUGE | self::XML_PARSE_BIG_LINES) === false) {
|
||||
$aErrors = libxml_get_errors();
|
||||
IssueLog::Error("Error loading $filename", LogAPI::CHANNEL_DEFAULT, $aErrors);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -233,6 +243,56 @@ class DesignElement extends \DOMElement
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility with PHP8.0
|
||||
*
|
||||
* @return \DOMElement|null
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public function GetFirstElementChild()
|
||||
{
|
||||
if (property_exists($this, 'firstElementChild')) {
|
||||
return $this->firstElementChild;
|
||||
}
|
||||
|
||||
$oChildNode = $this->firstChild;
|
||||
while (!is_null($oChildNode)) {
|
||||
if ($oChildNode instanceof \DOMElement) {
|
||||
return $oChildNode;
|
||||
}
|
||||
$oChildNode = $oChildNode->nextSibling;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility with PHP8.0
|
||||
*
|
||||
* @return \DOMElement|null
|
||||
*
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public function GetNextElementSibling()
|
||||
{
|
||||
if (property_exists($this, 'nextElementSibling')) {
|
||||
return $this->nextElementSibling;
|
||||
}
|
||||
|
||||
$oSibling = $this->nextSibling;
|
||||
while (!is_null($oSibling)) {
|
||||
if ($oSibling instanceof \DOMElement) {
|
||||
return $oSibling;
|
||||
}
|
||||
$oSibling = $oSibling->nextSibling;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node directly under the given node
|
||||
* @param $sTagName
|
||||
@@ -313,4 +373,146 @@ class DesignElement extends \DOMElement
|
||||
}
|
||||
return $sRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the current node is actually a class node, under classes
|
||||
* @since 3.1.2 3.2.0 N°6974
|
||||
*/
|
||||
public function IsClassNode(): bool
|
||||
{
|
||||
if ($this->tagName == 'class') {
|
||||
// Beware: classes/class also exists in the group definition
|
||||
if (($this->parentNode->tagName == 'classes') && ($this->parentNode->parentNode->tagName == 'itop_design')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the node is contained in a _delta="merge" tree
|
||||
* @return bool
|
||||
*/
|
||||
public function IsInSpecifiedMerge(): bool
|
||||
{
|
||||
// Iterate through the parents: reset the flag if any of them has a flag set
|
||||
for ($oParent = $this; $oParent instanceof MFElement; $oParent = $oParent->parentNode) {
|
||||
$sDeltaSpec = $oParent->getAttribute('_delta');
|
||||
if ($sDeltaSpec === 'merge') {
|
||||
return true;
|
||||
}
|
||||
if (in_array($sDeltaSpec, ['define', 'define_if_not_exists', 'force', 'redefine'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the child node matching the given node.
|
||||
* UNSAFE: may return nodes marked as _alteration="removed"
|
||||
* A method with the same signature MUST exist in MFDocument for the recursion to work fine
|
||||
*
|
||||
* @param DesignElement $oRefNode The node to search for
|
||||
* @param null|string $sSearchId substitutes to the value of the 'id' attribute
|
||||
*
|
||||
* @return DesignElement|null
|
||||
* @throws \Exception
|
||||
* @since 3.1.2 3.2.0 N°6974
|
||||
*/
|
||||
public function _FindChildNode(DesignElement $oRefNode, $sSearchId = null): ?DesignElement
|
||||
{
|
||||
return self::_FindNode($this, $oRefNode, $sSearchId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the child node matching the given node.
|
||||
* UNSAFE: may return nodes marked as _alteration="removed"
|
||||
* A method with the same signature MUST exist in MFDocument for the recursion to work fine
|
||||
*
|
||||
* @param DesignElement $oRefNode The node to search for
|
||||
*
|
||||
* @return DesignElement|null
|
||||
* @throws \Exception
|
||||
* @since 3.1.2 3.2.0 N°6974
|
||||
*/
|
||||
public function _FindChildNodes(DesignElement $oRefNode): ?DesignElement
|
||||
{
|
||||
return self::_FindNodes($this, $oRefNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the child node matching the given node under the specified parent.
|
||||
* UNSAFE: may return nodes marked as _alteration="removed"
|
||||
*
|
||||
* @param \DOMNode $oParent
|
||||
* @param DesignElement $oRefNode
|
||||
* @param string|null $sSearchId
|
||||
*
|
||||
* @return DesignElement|null
|
||||
* @throws Exception
|
||||
* @since 3.1.2 3.2.0 N°6974
|
||||
*/
|
||||
public static function _FindNode(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null): ?DesignElement
|
||||
{
|
||||
$oNodes = self::_FindNodes($oParent, $oRefNode, $sSearchId);
|
||||
if ($oNodes instanceof DOMNodeList) {
|
||||
/** @var DesignElement $oNode */
|
||||
$oNode = $oNodes->item(0);
|
||||
|
||||
return $oNode;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the child node matching the given node under the specified parent.
|
||||
* UNSAFE: may return nodes marked as _alteration="removed"
|
||||
*
|
||||
* @param \DOMNode $oParent
|
||||
* @param DesignElement $oRefNode
|
||||
* @param string|null $sSearchId
|
||||
*
|
||||
* @return \DOMNodeList|false|mixed
|
||||
* @since 3.1.2 3.2.0 N°6974
|
||||
*/
|
||||
public static function _FindNodes(DOMNode $oParent, DesignElement $oRefNode, string $sSearchId = null)
|
||||
{
|
||||
if ($oParent instanceof DOMDocument)
|
||||
{
|
||||
$oDoc = $oParent->firstChild->ownerDocument;
|
||||
$oRoot = $oParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDoc = $oParent->ownerDocument;
|
||||
$oRoot = $oParent;
|
||||
}
|
||||
|
||||
$oXPath = new DOMXPath($oDoc);
|
||||
if ($oRefNode->hasAttribute('id'))
|
||||
{
|
||||
// Find the elements having the same tag name and id
|
||||
if (!$sSearchId)
|
||||
{
|
||||
$sSearchId = $oRefNode->getAttribute('id');
|
||||
}
|
||||
$sXPath = './'.$oRefNode->tagName."[@id='$sSearchId']";
|
||||
|
||||
$oRes = $oXPath->query($sXPath, $oRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the elements having the same tag name
|
||||
$sXPath = './'.$oRefNode->tagName;
|
||||
|
||||
$oRes = $oXPath->query($sXPath, $oRoot);
|
||||
}
|
||||
|
||||
return $oRes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Masterminds\HTML5;
|
||||
|
||||
/**
|
||||
* Base class for all possible implementations of HTML Sanitization
|
||||
*/
|
||||
@@ -287,7 +289,7 @@ class HTMLDOMSanitizer extends DOMSanitizer
|
||||
'u' => array(),
|
||||
'em' => array(),
|
||||
'strong' => array(),
|
||||
'img' => array('src', 'style', 'alt', 'title'),
|
||||
'img' => array('src', 'style', 'alt', 'title', 'width', 'height'),
|
||||
'ul' => array('style'),
|
||||
'ol' => array('reversed', 'start', 'style', 'type'),
|
||||
'li' => array('style', 'value'),
|
||||
@@ -321,6 +323,8 @@ class HTMLDOMSanitizer extends DOMSanitizer
|
||||
'hr' => array('style'),
|
||||
'pre' => array(),
|
||||
'center' => array(),
|
||||
'figure' => array('class'), // Ckeditor 5 puts images in figures
|
||||
'mark' => array('class')
|
||||
);
|
||||
|
||||
protected static $aAttrsWhiteList = array(
|
||||
@@ -332,6 +336,7 @@ class HTMLDOMSanitizer extends DOMSanitizer
|
||||
* @see https://www.itophub.io/wiki/page?id=2_6_0%3Aadmin%3Arich_text_limitations
|
||||
*/
|
||||
protected static $aStylesWhiteList = array(
|
||||
'aspect-ratio',
|
||||
'background-color',
|
||||
'border',
|
||||
'border-collapse',
|
||||
|
||||
@@ -536,6 +536,11 @@ JS
|
||||
|
||||
$sAbsoluteUrlAppRoot = utils::GetAbsoluteUrlAppRoot();
|
||||
$sToggleFullScreen = utils::EscapeHtml(Dict::S('UI:ToggleFullScreen'));
|
||||
return <<<JS
|
||||
$('.htmlEditor').each(function() {
|
||||
CombodoCKEditorHandler.EnableImageUpload('#' + $(this).attr('id'), '$sAbsoluteUrlAppRoot'+'pages/ajax.render.php?operation=cke_img_upload&temp_id=$sTempId&obj_class=$sObjClass&obj_key=$iObjKey');
|
||||
});
|
||||
JS;
|
||||
|
||||
return
|
||||
<<<JS
|
||||
@@ -605,6 +610,13 @@ JS
|
||||
JS
|
||||
;
|
||||
}
|
||||
public static function EnableCKEditor5ImageUpload(DBObject $oObject, $sTempId){
|
||||
return <<<JS
|
||||
// Hook the file upload of all CKEditor instances
|
||||
JS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
|
||||
@@ -575,6 +575,12 @@ class LogChannels
|
||||
*/
|
||||
public const DATATABLE = 'Datatable';
|
||||
|
||||
/**
|
||||
* @var string Everything related to the data integrity
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public const DATA_INTEGRITY = 'DataIntegrity';
|
||||
|
||||
public const DEADLOCK = 'DeadLock';
|
||||
/**
|
||||
* @var string Everything related to PHP sessions tracking
|
||||
@@ -1335,19 +1341,7 @@ class DeprecatedCallsLog extends LogAPI
|
||||
}
|
||||
|
||||
$aStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
$iStackDeprecatedMethodLevel = 1; // level 0 = current method, level 1 = method containing the `NotifyDeprecatedPhpMethod` call
|
||||
$sDeprecatedObject = $aStack[$iStackDeprecatedMethodLevel]['class'];
|
||||
$sDeprecatedMethod = $aStack[$iStackDeprecatedMethodLevel]['function'];
|
||||
$sCallerFile = $aStack[$iStackDeprecatedMethodLevel]['file'];
|
||||
$sCallerLine = $aStack[$iStackDeprecatedMethodLevel]['line'];
|
||||
$sMessage = "Call to {$sDeprecatedObject}::{$sDeprecatedMethod} in {$sCallerFile}#L{$sCallerLine}";
|
||||
|
||||
$iStackCallerMethodLevel = $iStackDeprecatedMethodLevel + 1; // level 2 = caller of the deprecated method
|
||||
if (array_key_exists($iStackCallerMethodLevel, $aStack)) {
|
||||
$sCallerObject = $aStack[$iStackCallerMethodLevel]['class'];
|
||||
$sCallerMethod = $aStack[$iStackCallerMethodLevel]['function'];
|
||||
$sMessage .= " ({$sCallerObject}::{$sCallerMethod})";
|
||||
}
|
||||
$sMessage = self::GetMessageFromStack($aStack);
|
||||
|
||||
if (!is_null($sAdditionalMessage)) {
|
||||
$sMessage .= ' : '.$sAdditionalMessage;
|
||||
@@ -1356,6 +1350,45 @@ class DeprecatedCallsLog extends LogAPI
|
||||
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aDebugBacktrace data from {@see debug_backtrace()}
|
||||
*
|
||||
* @return string message to print to the log
|
||||
*/
|
||||
private static function GetMessageFromStack(array $aDebugBacktrace): string
|
||||
{
|
||||
// level 0 = current method
|
||||
// level 1 = deprecated method, containing the `NotifyDeprecatedPhpMethod` call
|
||||
$sMessage = 'Call'.self::GetMessageForCurrentStackLevel($aDebugBacktrace[1], " to ");
|
||||
|
||||
// level 2 = caller of the deprecated method
|
||||
if (array_key_exists(2, $aDebugBacktrace)) {
|
||||
$sMessage .= ' (from ';
|
||||
$sMessage .= self::GetMessageForCurrentStackLevel($aDebugBacktrace[2]);
|
||||
$sMessage .= ')';
|
||||
}
|
||||
|
||||
return $sMessage;
|
||||
}
|
||||
|
||||
private static function GetMessageForCurrentStackLevel(array $aCurrentLevelDebugTrace, ?string $sPrefix = ""): string
|
||||
{
|
||||
$sMessage = "";
|
||||
if (array_key_exists('class', $aCurrentLevelDebugTrace)) {
|
||||
$sDeprecatedObject = $aCurrentLevelDebugTrace['class'];
|
||||
$sDeprecatedMethod = $aCurrentLevelDebugTrace['function'] ?? "";
|
||||
$sMessage = "{$sPrefix}{$sDeprecatedObject}::{$sDeprecatedMethod} in ";
|
||||
}
|
||||
|
||||
if (array_key_exists('file', $aCurrentLevelDebugTrace)) {
|
||||
$sCallerFile = $aCurrentLevelDebugTrace['file'];
|
||||
$sCallerLine = $aCurrentLevelDebugTrace['line'] ?? "";
|
||||
$sMessage .= "{$sCallerFile}#L{$sCallerLine}";
|
||||
}
|
||||
|
||||
return $sMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sAdditionalMessage
|
||||
* @since 3.1.0
|
||||
|
||||
@@ -516,7 +516,7 @@ class ormCaseLog {
|
||||
$sScript = '<script src="'.$sFileAbsUrl.'"></></script>';
|
||||
$sHtml .= $sScript;
|
||||
} else {
|
||||
$oP->add_linked_script($sFileAbsUrl);
|
||||
$oP->LinkScriptFromURI($sFileAbsUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ class ormStopWatch
|
||||
}
|
||||
else
|
||||
{
|
||||
$aProperties['Elapsed'] = 'running <img src="../images/indicator.gif">';
|
||||
$aProperties['Elapsed'] = 'running <img src="' . utils::GetAbsoluteUrlAppRoot() . 'images/indicator.gif">';
|
||||
}
|
||||
|
||||
$aProperties['Started'] = $oAttDef->SecondsToDate($this->iStarted);
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class Trigger extends cmdbAbstractObject
|
||||
MetaModel::Init_AddAttribute(new AttributeEnumSet("context", array("allowed_values" => null, "possible_values" => new ValueSetEnumPadded($aTags, true), "sql" => "context", "depends_on" => array(), "is_null_allowed" => true, "max_items" => 12)));
|
||||
// "complement" is a computed field, fed by Trigger sub-classes, in general in ComputeValues method, for eg. the TriggerOnObject fed it with target_class info
|
||||
MetaModel::Init_AddAttribute(new AttributeString("complement", array("allowed_values" => null, "sql" => "complement", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("subscription_policy", array("allowed_values" => new ValueSetEnum('allow_no_channel,force_at_least_one_channel,force_all_channels'), "sql" => "subscription_policy", "default_value" => 'allow_no_channel', "is_null_allowed" => false, "depends_on" => array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeEnum("subscription_policy", array("allowed_values" => new ValueSetEnum(Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::cases()), "sql" => "subscription_policy", "default_value" => \Combodo\iTop\Core\Trigger\Enum\SubscriptionPolicy::AllowNoChannel->value, "is_null_allowed" => false, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('finalclass', 'description', 'context', 'subscription_policy', 'action_list', 'complement')); // Attributes to be displayed for the complete details
|
||||
@@ -185,7 +185,7 @@ abstract class TriggerOnObject extends Trigger
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("filter", array("allowed_values" => null, "sql" => "filter", "default_value" => null, "is_null_allowed" => true, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('default_search', array('description', 'target_class')); // Default criteria of the search banner
|
||||
@@ -385,7 +385,7 @@ class TriggerOnPortalUpdate extends TriggerOnObject
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
}
|
||||
@@ -418,7 +418,7 @@ abstract class TriggerOnStateChange extends TriggerOnObject
|
||||
MetaModel::Init_AddAttribute(new AttributeClassState("state", array("class_field" => 'target_class', "allowed_values" => null, "sql" => "state", "default_value" => null, "is_null_allowed" => false, "depends_on" => array('target_class'))));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'filter', 'state', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'state')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class', 'state')); // Criteria of the std search form
|
||||
@@ -840,7 +840,7 @@ class TriggerOnThresholdReached extends TriggerOnObject
|
||||
MetaModel::Init_AddAttribute(new AttributeString("threshold_index", array("allowed_values" => null, "sql" => "threshold_index", "default_value" => null, "is_null_allowed" => false, "depends_on" => array())));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'context', 'target_class', 'stop_watch_code', 'threshold_index', 'filter', 'subscription_policy', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('target_class', 'threshold_index', 'threshold_index')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', array('description', 'target_class')); // Criteria of the std search form
|
||||
|
||||
@@ -180,17 +180,23 @@ abstract class UserRightsAddOnAPI
|
||||
$sShareClass = $aShareProperties['share_class'];
|
||||
$sShareAttCode = $aShareProperties['attcode'];
|
||||
|
||||
$oSearchShares = new DBSharedSearch($sShareClass);
|
||||
$oSearchShares->AllowAllData();
|
||||
$oSearchShares = new DBObjectSearch($sShareClass);
|
||||
$oSearchShares->AllowAllData();
|
||||
|
||||
$sHierarchicalKeyCode = MetaModel::IsHierarchicalClass('Organization');
|
||||
$oOrgField = new FieldExpression('org_id', $sShareClass);
|
||||
$oSearchShares->AddConditionExpression(new BinaryExpression($oOrgField, 'IN', $oListExpr));
|
||||
|
||||
$oNested = SharedQueryExpression::FromOQLObjectQuery($oSearchShares, [$sShareClass =>[$sShareAttCode]]);
|
||||
$oObjId = new FieldExpression('id', $sClass);
|
||||
$oFilter->MergeConditionExpression(new BinaryExpression($oObjId, 'IN', $oNested));
|
||||
|
||||
$aShared = array();
|
||||
foreach($oSearchShares->SelectAttributeToArray($sShareAttCode) as $aRow)
|
||||
{
|
||||
$aShared[] = $aRow[$sShareAttCode];
|
||||
}
|
||||
if (count($aShared) > 0)
|
||||
{
|
||||
$oObjId = new FieldExpression('id', $sClass);
|
||||
$oSharedIdList = ListExpression::FromScalars($aShared);
|
||||
$oFilter->MergeConditionExpression(new BinaryExpression($oObjId, 'IN', $oSharedIdList));
|
||||
}
|
||||
}
|
||||
} // if HasSharing
|
||||
|
||||
|
||||
@@ -476,6 +476,7 @@ class ValueSetEnum extends ValueSetDefinition
|
||||
* @param bool $bLocalizedSort
|
||||
*
|
||||
* @since 3.1.0 N°1646 Add $bLocalizedSort parameter
|
||||
* @since 3.2.0 N°7157 $Values can be an array of backed-enum cases
|
||||
*/
|
||||
public function __construct($Values, bool $bSortByValues = false)
|
||||
{
|
||||
@@ -523,13 +524,21 @@ class ValueSetEnum extends ValueSetDefinition
|
||||
*/
|
||||
protected function LoadValues($aArgs)
|
||||
{
|
||||
$aValues = [];
|
||||
if (is_array($this->m_values))
|
||||
{
|
||||
$aValues = $this->m_values;
|
||||
foreach ($this->m_values as $key => $value) {
|
||||
// Handle backed-enum case
|
||||
if (is_object($value) && enum_exists(get_class($value))) {
|
||||
$aValues[$value->value] = $value->value;
|
||||
continue;
|
||||
}
|
||||
|
||||
$aValues[$key] = $value;
|
||||
}
|
||||
}
|
||||
elseif (is_string($this->m_values) && strlen($this->m_values) > 0)
|
||||
{
|
||||
$aValues = array();
|
||||
foreach (explode(",", $this->m_values) as $sVal)
|
||||
{
|
||||
$sVal = trim($sVal);
|
||||
@@ -539,7 +548,7 @@ class ValueSetEnum extends ValueSetDefinition
|
||||
}
|
||||
else
|
||||
{
|
||||
$aValues = array();
|
||||
$aValues = [];
|
||||
}
|
||||
$this->m_aValues = $aValues;
|
||||
return true;
|
||||
|
||||
@@ -19,9 +19,19 @@ $ibo-navigation-menu--notifications--item--content--padding-x: 14px !default;
|
||||
$ibo-navigation-menu--notifications--item--content--img--max-height: 100px !default;
|
||||
$ibo-navigation-menu--notifications--item--content--img--padding: 5px !default;
|
||||
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--width: 10px !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--height: 10px !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-blue-500 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--width: 13px !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--height: 13px !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-red-100 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-red-500 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-orange-100 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-orange-500 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-blue-100 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-blue-500 !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--background-color !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--border: $ibo-navigation-menu--notifications--item--new-message-indicator--border !default;
|
||||
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--border-radius: $ibo-border-radius-full !default;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--margin-top: $ibo-spacing-200 !default;
|
||||
|
||||
@@ -87,8 +97,25 @@ $ibo-popover-menu--item--no-message--image--svg--padding : 15px !default;
|
||||
width: $ibo-navigation-menu--notifications--item--new-message-indicator--width;
|
||||
height: $ibo-navigation-menu--notifications--item--new-message-indicator--height;
|
||||
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--background-color;
|
||||
border: $ibo-navigation-menu--notifications--item--new-message-indicator--border;
|
||||
border-radius: $ibo-navigation-menu--notifications--item--new-message-indicator--border-radius;
|
||||
margin-top: $ibo-navigation-menu--notifications--item--new-message-indicator--margin-top;
|
||||
&.ibo-is-priority-1{
|
||||
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color;
|
||||
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border;
|
||||
}
|
||||
&.ibo-is-priority-2{
|
||||
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color;
|
||||
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border;
|
||||
}
|
||||
&.ibo-is-priority-3{
|
||||
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color;
|
||||
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border;
|
||||
}
|
||||
&.ibo-is-priority-4{
|
||||
background-color: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--background-color;
|
||||
border: $ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-4--border;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--notifications-show-all-multiple ~ .ibo-popover-menu {
|
||||
|
||||
@@ -49,10 +49,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
.ibo-input-select {
|
||||
display: inline-flex;
|
||||
min-width: $ibo-input-select--value--min-midth;
|
||||
|
||||
&:not(.ibo-input-select-autocomplete):not(.ibo-input-selectize) {
|
||||
appearance: none;
|
||||
}
|
||||
appearance: none;
|
||||
|
||||
&.ibo-input-selectize {
|
||||
padding-right: 0;
|
||||
@@ -108,7 +105,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
outline: none !important; /* Overwrite browsers default focus outline */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.input-active{
|
||||
border: 1px solid $ibo-input--focus--border-color;
|
||||
}
|
||||
@@ -123,15 +120,16 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
}
|
||||
.ibo-input-select-wrapper::after{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
content: "\f0d7";
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-weight: 600;
|
||||
|
||||
|
||||
height: $ibo-input-select-wrapper--after--height;
|
||||
margin-left: $ibo-input-select-wrapper--after--margin-left;
|
||||
margin-top: $ibo-input-select-wrapper--after--margin-top;
|
||||
padding-top: $ibo-input-select-wrapper--after--padding-top;
|
||||
|
||||
|
||||
background-color: $ibo-input-select-wrapper--after--background-color;
|
||||
color: $ibo-input-select-wrapper--after--color;
|
||||
pointer-events: none;
|
||||
@@ -146,6 +144,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
|
||||
.ibo-input-select-wrapper--with-buttons:not(.ibo-input-select-autocomplete-wrapper)::after {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
content: "\f0d7";
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-weight: 600;
|
||||
@@ -163,6 +162,7 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
|
||||
}
|
||||
.ibo-input-select--action-buttons{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
height: $ibo-input-select--action-button--height;
|
||||
margin-top: $ibo-input-select--action-button--margin-top;
|
||||
|
||||
@@ -8,7 +8,11 @@ $ibo-input--width: 100% !default;
|
||||
|
||||
$ibo-input--color: $ibo-color-grey-900 !default;
|
||||
$ibo-input--background-color: $ibo-color-white-100 !default;
|
||||
|
||||
$ibo-input--border-color: $ibo-color-grey-500 !default;
|
||||
$ibo-input--border-size: 1px !default;
|
||||
$ibo-input--border-style: solid !default;
|
||||
$ibo-input--border: $ibo-input--border-size $ibo-input--border-style $ibo-input--border-color !default;
|
||||
|
||||
$ibo-input--padding-x: 10px !default;
|
||||
$ibo-input--padding-y: $ibo-spacing-0 !default;
|
||||
@@ -34,13 +38,13 @@ $ibo-input--margin-x: $ibo-spacing-200 !default;
|
||||
background-color: $ibo-input--background-color;
|
||||
color: $ibo-input--color;
|
||||
padding: $ibo-input--padding-y $ibo-input--padding-x;
|
||||
border: 1px solid $ibo-input--border-color;
|
||||
border: $ibo-input--border;
|
||||
border-radius: $ibo-input--border-radius;
|
||||
|
||||
@extend %ibo-font-ral-nor-150;
|
||||
|
||||
&:focus{
|
||||
border: 1px solid $ibo-input--focus--border-color;
|
||||
border-color: $ibo-input--focus--border-color;
|
||||
}
|
||||
&:disabled{
|
||||
background-color: $ibo-input--disabled--background-color;
|
||||
@@ -54,8 +58,8 @@ textarea.ibo-input{
|
||||
height:unset;
|
||||
}
|
||||
.ibo-input-wrapper.is-error, .ibo-input-field-wrapper.is-error {
|
||||
.ibo-input, .ibo-input-vanilla, .cke, textarea {
|
||||
border: 1px solid $ibo-input-wrapper--is-error--border-color;
|
||||
.ibo-input, .ibo-input-vanilla, .ck-editor, textarea {
|
||||
border-color: $ibo-input-wrapper--is-error--border-color;
|
||||
}
|
||||
.ibo-input-vanilla input{
|
||||
border: 0;
|
||||
|
||||
@@ -83,6 +83,7 @@ $ibo-object-details--header-right--padding-right--is-sticking: $ibo-spacing-300
|
||||
|
||||
.ibo-object-details--status + .ibo-object-details--object-class {
|
||||
margin-left: 0.5rem;
|
||||
display: inline-flex; /* To avoid having spaces around the class name due to the indentation */
|
||||
|
||||
&::before {
|
||||
content: "(";
|
||||
|
||||
@@ -21,6 +21,9 @@ $ibo-notifications--view-all--empty--svg--max-width: 30% !default;
|
||||
grid-gap: $ibo-notifications--view-all--container--grid-gap;
|
||||
.ibo-object-summary .ibo-panel--title{
|
||||
font-size: $ibo-font-size-250;
|
||||
}
|
||||
.ibo-object-summary .ibo-panel--toolbar{
|
||||
min-width: 102px;
|
||||
}
|
||||
.ibo-object-summary > .ibo-panel--body{
|
||||
box-shadow: none;
|
||||
@@ -53,7 +56,20 @@ $ibo-notifications--view-all--empty--svg--max-width: 30% !default;
|
||||
.ibo-notifications--view-all--item--unread .ibo-panel--body::before{
|
||||
background-color: $ibo-notifications--view-all--item--unread--highlight--background-color;
|
||||
}
|
||||
|
||||
.ibo-notifications--view-all--container {
|
||||
.ibo-notifications--view-all--read-action, .ibo-notifications--view-all--unread-action {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-notifications--view-all--item--read .ibo-notifications--view-all--read-action {
|
||||
display: none;
|
||||
}
|
||||
.ibo-notifications--view-all--item--unread .ibo-notifications--view-all--unread-action {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ibo-notifications--view-all--empty {
|
||||
@extend %ibo-fully-centered-content;
|
||||
flex-direction: column;
|
||||
|
||||
4
css/backoffice/vendors/_ckeditor.scss
vendored
4
css/backoffice/vendors/_ckeditor.scss
vendored
@@ -22,6 +22,10 @@ $ibo-vendors-ckeditor--autocomplete-item-image--border: 1px solid $ibo-color-gre
|
||||
|
||||
$ibo-vendors-ckeditor--autocomplete-item-title--text-color: #3A3A3A !default;
|
||||
|
||||
.ck-editor__editable_inline:not(.ck-comment__input *) {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
/* Fullscreen button (Combodo custom) */
|
||||
.ibo-vendors-ckeditor--toolbar-fullscreen-button {
|
||||
display: none;
|
||||
|
||||
109
css/backoffice/vendors/_selectize.scss
vendored
109
css/backoffice/vendors/_selectize.scss
vendored
@@ -21,82 +21,87 @@ $ibo-vendors-selectize--item--ignore-partial--background-color: $ibo-color-grey-
|
||||
|
||||
$ibo-vendors-selectize--input-error--border: 1px solid $ibo-color-red-600 !default;
|
||||
|
||||
.selectize-dropdown-content {
|
||||
max-height: unset; /* Overloaded as it will be handled by the _input-select.scss partial */
|
||||
}
|
||||
.selectize-input input{
|
||||
color: $ibo-vendors-selectize-input--color;
|
||||
.selectize-control.single .selectize-input {
|
||||
box-shadow: unset;
|
||||
background-color: unset;
|
||||
background-image: unset;
|
||||
background-repeat: unset;
|
||||
}
|
||||
|
||||
.selectize-input,
|
||||
.selectize-control.single .selectize-input.input-active {
|
||||
background: unset;
|
||||
cursor: text;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.selectize-control.plugin-combodo_add_button{
|
||||
display: flex;
|
||||
.selectize-control.single .selectize-input.dropdown-active:after {
|
||||
margin-top: unset;
|
||||
border-width: unset;
|
||||
border-color: unset;
|
||||
}
|
||||
.selectize-control.single .selectize-input:after {
|
||||
content: unset;
|
||||
}
|
||||
.selectize-input::after {
|
||||
content: unset;
|
||||
}
|
||||
|
||||
.selectize-add-option {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
position: absolute;
|
||||
right: $ibo-vendors-selectize-control--plugin-add-button--add-option--right;
|
||||
|
||||
height: $ibo-vendors-selectize-control--plugin-add-button--add-option--height;
|
||||
width: $ibo-vendors-selectize-control--plugin-add-button--add-option--width;
|
||||
z-index: 1;
|
||||
|
||||
color: $ibo-vendors-selectize-control--plugin-add-button--add-option--color;
|
||||
@extend %ibo-font-size-100;
|
||||
.selectize-input>* {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.selectize-control.single .selectize-input, .selectize-dropdown.single {
|
||||
border-color: $ibo-color-grey-500;
|
||||
}
|
||||
|
||||
.selectize-dropdown {
|
||||
.selected,
|
||||
.active,
|
||||
.active:not(.selected){
|
||||
background: #f5fafd;
|
||||
color: #495c68;
|
||||
}
|
||||
|
||||
[data-selectable],
|
||||
.optgroup-header {
|
||||
padding: 5px 8px;
|
||||
}
|
||||
|
||||
.option {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Simple options renderer
|
||||
|
||||
.simple-option-renderer--container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.simple-option-renderer--container--icon {
|
||||
width: 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.simple-option-renderer--container--label {
|
||||
margin-left: 3px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.selectize-input{
|
||||
.attribute-set-item{
|
||||
>* {
|
||||
// Bulk modification: add / remove / partial items states
|
||||
.selectize-input {
|
||||
.attribute-set-item {
|
||||
> * {
|
||||
display: inline;
|
||||
}
|
||||
&.item-add::before,&.item-remove::before{
|
||||
&.item-add::before,&.item-remove::before {
|
||||
@extend %fa-solid-base;
|
||||
margin-right: $ibo-vendors-selectize--item--icon--margin-right;
|
||||
}
|
||||
&.item-add{
|
||||
&.item-add {
|
||||
background-color: $ibo-vendors-selectize--item--add--background-color !important;
|
||||
&::before{
|
||||
&::before {
|
||||
color: $ibo-vendors-selectize--item--add--icon--color;
|
||||
content: '\f067';
|
||||
}
|
||||
}
|
||||
&.item-remove{
|
||||
&.item-remove {
|
||||
background-color: $ibo-vendors-selectize--item--remove--background-color !important;
|
||||
&::before{
|
||||
&::before {
|
||||
color: $ibo-vendors-selectize--item--remove--icon--color;
|
||||
content: '\f1f8';
|
||||
}
|
||||
}
|
||||
&.item-ignore-partial{
|
||||
&.item-ignore-partial {
|
||||
background-color: $ibo-vendors-selectize--item--ignore-partial--background-color !important;
|
||||
}
|
||||
}
|
||||
&.selectize-input-error{
|
||||
&.selectize-input-error {
|
||||
border: $ibo-vendors-selectize--input-error--border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
css/c3.min.css
vendored
4
css/c3.min.css
vendored
@@ -1 +1,5 @@
|
||||
/*
|
||||
* @deprecated 3.2.0 N°5621 Moved to NPM
|
||||
*/
|
||||
|
||||
.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}
|
||||
@@ -3,18 +3,32 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
/* These rules should be the same as those in css/backoffice/vendors/ckeditor.css */
|
||||
body{
|
||||
margin: 5px 10px;
|
||||
.ibo-mention-item{
|
||||
line-height: 1.6rem;
|
||||
}
|
||||
.cke_editable{
|
||||
line-height: 1.4;
|
||||
|
||||
[data-role="object-mention"]{
|
||||
color: #0782C1;
|
||||
}
|
||||
figure{
|
||||
border: solid 1px #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
p{
|
||||
margin-top: 0.25em;
|
||||
margin-bottom: 0.25em;
|
||||
[data-role="object-mention"]:hover{
|
||||
color: #2b6bb0;
|
||||
}
|
||||
|
||||
.ck.ck-editor.cke-maximized{
|
||||
position: fixed;
|
||||
left: 0px;
|
||||
top:0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ck.ck-editor.cke-maximized .ck.ck-editor__main{
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.ck.ck-editor.cke-maximized .ck-editor__editable_inline:not(.ck-comment__input *){
|
||||
height: 100%;
|
||||
}
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
/* Shortened version style */
|
||||
.ui-timepicker-div.ui-timepicker-oneLine { padding-right: 2px; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dt { display: none; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { display: block; padding-top: 2px; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl { text-align: right; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { display:inline-block; margin:0; }
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before,
|
||||
.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { content:':'; display:inline-block; }
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* @deprecated 3.2.0 N°5621 Moved to NPM
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery contextMenu - Plugin for simple contextMenu handling
|
||||
*
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* @deprecated 3.2.0 N°5621 Moved to NPM
|
||||
*/
|
||||
|
||||
/* Magnific Popup CSS */
|
||||
.mfp-bg {
|
||||
top: 0;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -58,6 +58,9 @@ $progress-bar-error-bg-color: #F56565 !default;
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes progress_bar_color_ongoing {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="fullmoon-high-contrast" _delta="define">
|
||||
<variables>
|
||||
</variables>
|
||||
<imports>
|
||||
<import id="fullmoon-high-contrast-scss-variables" xsi:type="variables">combodo-backoffice-fullmoon-high-contrast-theme/scss/scss-variables.scss</import>
|
||||
</imports>
|
||||
<stylesheets>
|
||||
<stylesheet id="fullmoon">../css/backoffice/main.scss</stylesheet>
|
||||
<stylesheet id="high-contrast-stylesheet">combodo-backoffice-fullmoon-high-contrast-theme/scss/stylesheet.scss</stylesheet>
|
||||
</stylesheets>
|
||||
<precompiled_stylesheet>combodo-backoffice-fullmoon-high-contrast-theme/precompiled-themes/main.css</precompiled_stylesheet>
|
||||
</theme>
|
||||
</themes>
|
||||
</branding>
|
||||
</itop_design>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'theme:fullmoon-high-contrast' => 'Fullmoon (High contrast)',
|
||||
));
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'theme:fullmoon-high-contrast' => 'Fullmoon (Contraste élevé)',
|
||||
));
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
//
|
||||
// iTop module definition file
|
||||
//
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Backoffice: Fullmoon with high contrast accessibility theme',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
),
|
||||
'data.struct' => array(
|
||||
// add your 'structure' definition XML files here,
|
||||
),
|
||||
'data.sample' => array(
|
||||
// add your sample data XML files here,
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
// Module specific settings go here, if any
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,145 @@
|
||||
$ibo-high-contrast--thin-border: solid 1px $ibo-color-grey-900 !default;
|
||||
$ibo-high-contrast--medium-border: solid 2px $ibo-color-grey-900 !default;
|
||||
|
||||
$ibo-alert--icon--font-size: 3rem !default;
|
||||
$ibo-alert--icon--top: calc(50% - #{$ibo-alert--icon--font-size} / 2) !default;
|
||||
$ibo-alert--icon--left: $ibo-spacing-500 !default;
|
||||
$ibo-alert--icon--opacity: 0.8 !default;
|
||||
$ibo-alert--icons: (
|
||||
'success': '\f00c',
|
||||
'information': '\f129',
|
||||
'warning': '\f12a',
|
||||
'danger': '\f071',
|
||||
'failure': '\f071',
|
||||
'error': '\f071',
|
||||
) !default;
|
||||
|
||||
$ibo-toast--icon--font-size: 2rem !default;
|
||||
$ibo-toast--icon--top: calc(50% - #{$ibo-toast--icon--font-size} / 2) !default;
|
||||
$ibo-toast--icon--left: $ibo-spacing-400 !default;
|
||||
|
||||
|
||||
@each $sName, $sIcon in $ibo-alert--icons {
|
||||
%ibo-alert-#{$sName}, .ibo-alert.ibo-is-#{$sName} {
|
||||
&::after {
|
||||
content: $sIcon;
|
||||
@extend %fa-solid-base;
|
||||
position: absolute;
|
||||
top: $ibo-alert--icon--top;
|
||||
left: $ibo-alert--icon--left;
|
||||
opacity: $ibo-alert--icon--opacity;
|
||||
font-size: $ibo-alert--icon--font-size;
|
||||
width: $ibo-alert--icon--font-size;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ibo-alert--body, .ibo-alert--title {
|
||||
padding-left: calc(#{$ibo-alert--icon--left} + #{$ibo-alert--icon--font-size});
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-toast.ibo-is-#{$sName} {
|
||||
&::after{
|
||||
font-size: $ibo-toast--icon--font-size !important;
|
||||
top: $ibo-toast--icon--top !important;
|
||||
left: $ibo-toast--icon--left !important;
|
||||
width: $ibo-toast--icon--font-size !important;
|
||||
}
|
||||
padding-left: calc(#{$ibo-toast--padding-left} / 2 + #{$ibo-toast--icon--left} + #{$ibo-toast--icon--font-size});
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator{
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
&.ibo-is-priority-1::before{
|
||||
content: "\f12a \f12a \f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-danger-900;
|
||||
}
|
||||
&.ibo-is-priority-2::before{
|
||||
content: "\f12a \f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-warning-900;
|
||||
}
|
||||
&.ibo-is-priority-3::before{
|
||||
content: "\f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-success-900;
|
||||
}
|
||||
&.ibo-is-priority-4::before{
|
||||
content: "\f129";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-information-900;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--menu-nodes ul li > a:hover, .ibo-navigation-menu--menu-node-counter{
|
||||
border: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
|
||||
.ibo-top-bar{
|
||||
box-shadow: none;
|
||||
border-bottom: $ibo-high-contrast--medium-border;
|
||||
}
|
||||
.ibo-breadcrumbs--item-icon > span, .ibo-breadcrumbs--item-icon > img{
|
||||
opacity: 1 !important;
|
||||
}
|
||||
.ibo-tab-container--tabs-list{
|
||||
border-bottom: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
.ibo-tab-container--extra-tabs-list{
|
||||
border: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
.ibo-datatable tbody > tr {
|
||||
border-bottom: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
|
||||
.ibo-activity-panel--tab-toolbar{
|
||||
border-bottom: $ibo-high-contrast--thin-border;
|
||||
border-top: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
.ibo-activity-entry--main-information{
|
||||
border: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
.ibo-activity-entry--medallion.ibo-has-image{
|
||||
box-shadow: none;
|
||||
border: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
.ibo-activity-panel--tab-toggler.ibo-is-active .ibo-activity-panel--tab-title{
|
||||
border-left: $ibo-high-contrast--thin-border;
|
||||
border-right: $ibo-high-contrast--thin-border;
|
||||
font-weight: 800;
|
||||
}
|
||||
.ibo-button{
|
||||
border: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
@each $sColor, $aColorValues in $ibo-alert-colors {
|
||||
$highlight-color: nth($aColorValues, 2);
|
||||
%ibo-alert-#{$sColor}, .ibo-alert.ibo-is-#{$sColor} {
|
||||
border: 1px solid $highlight-color;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-pill{
|
||||
border: 1px solid var(--ibo-main-color--900);
|
||||
}
|
||||
|
||||
@each $sType, $aColors in $ibo-pill-states-colors {
|
||||
.ibo-pill.ibo-is-#{$sType} {
|
||||
border: 1px solid map-get($aColors, 'secondary-color');
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-quick-create, .ibo-global-search{
|
||||
border-left: $ibo-high-contrast--thin-border;
|
||||
border-right: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
|
||||
.ibo-popover-menu{
|
||||
border: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
|
||||
.ibo-popover-menu--item:not(:last-child){
|
||||
border-bottom: $ibo-high-contrast--thin-border;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="fullmoon-protanopia-deuteranopia" _delta="define">
|
||||
<variables>
|
||||
</variables>
|
||||
<imports>
|
||||
<import id="fullmoon-prota-deutera-scss-variables" xsi:type="variables">combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/scss/scss-variables.scss</import>
|
||||
</imports>
|
||||
<stylesheets>
|
||||
<stylesheet id="fullmoon">../css/backoffice/main.scss</stylesheet>
|
||||
<stylesheet id="stylesheet">combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/scss/stylesheet.scss</stylesheet>
|
||||
</stylesheets>
|
||||
<precompiled_stylesheet>combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/precompiled-themes/main.css</precompiled_stylesheet>
|
||||
</theme>
|
||||
</themes>
|
||||
</branding>
|
||||
</itop_design>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (Protanopia & Deuteranopia)'
|
||||
));
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'theme:fullmoon-protanopia-deuteranopia' => 'Fullmoon (Protanopie et Deuteranopie)'
|
||||
));
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
//
|
||||
// iTop module definition file
|
||||
//
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Backoffice: Fullmoon with protonopia & deuteranopia accessibility theme',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
),
|
||||
'data.struct' => array(
|
||||
// add your 'structure' definition XML files here,
|
||||
),
|
||||
'data.sample' => array(
|
||||
// add your sample data XML files here,
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
// Module specific settings go here, if any
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,114 @@
|
||||
$ibo-color-primary-100: $ibo-color-blue-100;
|
||||
$ibo-color-primary-200: $ibo-color-blue-200;
|
||||
$ibo-color-primary-300: $ibo-color-blue-300;
|
||||
$ibo-color-primary-400: $ibo-color-blue-400;
|
||||
$ibo-color-primary-500: $ibo-color-blue-500;
|
||||
$ibo-color-primary-600: $ibo-color-blue-600;
|
||||
$ibo-color-primary-700: $ibo-color-blue-700;
|
||||
$ibo-color-primary-800: $ibo-color-blue-800;
|
||||
$ibo-color-primary-900: $ibo-color-blue-900;
|
||||
$ibo-color-primary-950: $ibo-color-blue-950;
|
||||
|
||||
|
||||
$ibo-color-danger-100: $ibo-color-orange-100;
|
||||
$ibo-color-danger-200: $ibo-color-orange-200;
|
||||
$ibo-color-danger-300: $ibo-color-orange-300;
|
||||
$ibo-color-danger-400: $ibo-color-orange-400;
|
||||
$ibo-color-danger-500: $ibo-color-orange-500;
|
||||
$ibo-color-danger-600: $ibo-color-orange-600;
|
||||
$ibo-color-danger-700: $ibo-color-orange-700;
|
||||
$ibo-color-danger-800: $ibo-color-orange-800;
|
||||
$ibo-color-danger-900: $ibo-color-orange-900;
|
||||
$ibo-color-danger-950: $ibo-color-orange-950;
|
||||
|
||||
|
||||
$ibo-color-yellow-100: #fefce8;
|
||||
$ibo-color-yellow-200: #fef9c3;
|
||||
$ibo-color-yellow-300: #fef08a;
|
||||
$ibo-color-yellow-400: #fde047;
|
||||
$ibo-color-yellow-500: #facc15;
|
||||
$ibo-color-yellow-600: #eab308;
|
||||
$ibo-color-yellow-700: #ca8a04;
|
||||
$ibo-color-yellow-800: #a16207;
|
||||
$ibo-color-yellow-900: #854d0e;
|
||||
$ibo-color-yellow-950: #713f12;
|
||||
|
||||
$ibo-color-warning-100: $ibo-color-yellow-100;
|
||||
$ibo-color-warning-200: $ibo-color-yellow-200;
|
||||
$ibo-color-warning-300: $ibo-color-yellow-300;
|
||||
$ibo-color-warning-400: $ibo-color-yellow-400;
|
||||
$ibo-color-warning-500: $ibo-color-yellow-500;
|
||||
$ibo-color-warning-600: $ibo-color-yellow-600;
|
||||
$ibo-color-warning-700: $ibo-color-yellow-700;
|
||||
$ibo-color-warning-800: $ibo-color-yellow-800;
|
||||
$ibo-color-warning-900: $ibo-color-yellow-900;
|
||||
$ibo-color-warning-950: $ibo-color-yellow-950;
|
||||
|
||||
|
||||
$ibo-color-success-100: $ibo-color-blue-100;
|
||||
$ibo-color-success-200: $ibo-color-blue-200;
|
||||
$ibo-color-success-300: $ibo-color-blue-300;
|
||||
$ibo-color-success-400: $ibo-color-blue-400;
|
||||
$ibo-color-success-500: $ibo-color-blue-500;
|
||||
$ibo-color-success-600: $ibo-color-blue-600;
|
||||
$ibo-color-success-700: $ibo-color-blue-700;
|
||||
$ibo-color-success-800: $ibo-color-blue-800;
|
||||
$ibo-color-success-900: $ibo-color-blue-900;
|
||||
$ibo-color-success-950: $ibo-color-blue-950;
|
||||
|
||||
$ibo-color-information-100: #f1f5f9;
|
||||
$ibo-color-information-200: #e2e8f0;
|
||||
$ibo-color-information-300: #cbd5e1;
|
||||
$ibo-color-information-400: #94a3b8;
|
||||
$ibo-color-information-500: #64748b;
|
||||
$ibo-color-information-600: #475569;
|
||||
$ibo-color-information-700: #334155;
|
||||
$ibo-color-information-800: #1e293b;
|
||||
$ibo-color-information-900: #0f172a;
|
||||
$ibo-color-information-950: #020617;
|
||||
|
||||
|
||||
$ibo-lifecycle-new-state-primary-color: $ibo-color-information-600;
|
||||
$ibo-lifecycle-new-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-neutral-state-primary-color: $ibo-color-information-600;
|
||||
$ibo-lifecycle-neutral-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-waiting-state-primary-color: $ibo-color-yellow-700;
|
||||
$ibo-lifecycle-waiting-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-success-state-primary-color: $ibo-color-blue-700;
|
||||
$ibo-lifecycle-success-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-failure-state-primary-color: $ibo-color-orange-800;
|
||||
$ibo-lifecycle-failure-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-frozen-state-primary-color: $ibo-color-information-200;
|
||||
$ibo-lifecycle-frozen-state-secondary-color: $ibo-color-information-700;
|
||||
|
||||
$ibo-lifecycle-active-state-primary-color: $ibo-color-blue-700;
|
||||
$ibo-lifecycle-active-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-inactive-state-primary-color: $ibo-color-yellow-700;
|
||||
$ibo-lifecycle-inactive-state-secondary-color: $ibo-color-white-100;
|
||||
|
||||
$ibo-caselog-highlight-color-1: $ibo-color-blue-700;
|
||||
$ibo-caselog-highlight-color-2: $ibo-color-yellow-700;
|
||||
$ibo-caselog-highlight-color-3: $ibo-color-information-600;
|
||||
$ibo-caselog-highlight-color-4: $ibo-color-yellow-500;
|
||||
$ibo-caselog-highlight-color-5: $ibo-color-blue-500;
|
||||
$ibo-caselog-highlight-color-6: $ibo-color-yellow-300;
|
||||
$ibo-caselog-highlight-color-7: $ibo-color-blue-300;
|
||||
|
||||
$ibo-input-wrapper--is-error--border-color: $ibo-color-warning-700;
|
||||
$ibo-field-validation: $ibo-color-warning-800;
|
||||
|
||||
$ibo-navigation-menu--visual-hint--background-color: $ibo-color-blue-400;
|
||||
|
||||
$ibo-wizard-container--background-color: $ibo-color-information-200;
|
||||
$ibo-wizard-container--border-color: $ibo-color-information-600;
|
||||
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-danger-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-danger-500;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-warning-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-warning-500;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-success-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-success-500;
|
||||
|
||||
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-blue-600;
|
||||
@@ -0,0 +1,73 @@
|
||||
$ibo-alert--icon--font-size: 3rem !default;
|
||||
$ibo-alert--icon--top: calc(50% - #{$ibo-alert--icon--font-size} / 2) !default;
|
||||
$ibo-alert--icon--left: $ibo-spacing-500 !default;
|
||||
$ibo-alert--icon--opacity: 0.3 !default;
|
||||
$ibo-alert--icons: (
|
||||
'success': '\f00c',
|
||||
'information': '\f129',
|
||||
'warning': '\f12a',
|
||||
'danger': '\f071',
|
||||
'failure': '\f071',
|
||||
'error': '\f071',
|
||||
) !default;
|
||||
|
||||
$ibo-toast--icon--font-size: 2rem !default;
|
||||
$ibo-toast--icon--top: calc(50% - #{$ibo-toast--icon--font-size} / 2) !default;
|
||||
$ibo-toast--icon--left: $ibo-spacing-400 !default;
|
||||
|
||||
|
||||
@each $sName, $sIcon in $ibo-alert--icons {
|
||||
%ibo-alert-#{$sName}, .ibo-alert.ibo-is-#{$sName} {
|
||||
&::after {
|
||||
content: $sIcon;
|
||||
@extend %fa-solid-base;
|
||||
position: absolute;
|
||||
top: $ibo-alert--icon--top;
|
||||
left: $ibo-alert--icon--left;
|
||||
opacity: $ibo-alert--icon--opacity;
|
||||
font-size: $ibo-alert--icon--font-size;
|
||||
width: $ibo-alert--icon--font-size;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ibo-alert--body, .ibo-alert--title {
|
||||
padding-left: calc(#{$ibo-alert--icon--left} + #{$ibo-alert--icon--font-size});
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-toast.ibo-is-#{$sName} {
|
||||
&::after{
|
||||
font-size: $ibo-toast--icon--font-size !important;
|
||||
top: $ibo-toast--icon--top !important;
|
||||
left: $ibo-toast--icon--left !important;
|
||||
width: $ibo-toast--icon--font-size !important;
|
||||
}
|
||||
padding-left: calc(#{$ibo-toast--padding-left} / 2 + #{$ibo-toast--icon--left} + #{$ibo-toast--icon--font-size});
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator{
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
&.ibo-is-priority-1::before{
|
||||
content: "\f12a \f12a \f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-danger-700;
|
||||
}
|
||||
&.ibo-is-priority-2::before{
|
||||
content: "\f12a \f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-warning-700;
|
||||
}
|
||||
&.ibo-is-priority-3::before{
|
||||
content: "\f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-success-700;
|
||||
}
|
||||
&.ibo-is-priority-4::before{
|
||||
content: "\f129";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-information-700;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.2">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="fullmoon-tritanopia" _delta="define">
|
||||
<variables>
|
||||
</variables>
|
||||
<imports>
|
||||
<import id="fullmoon-trita-scss-variables" xsi:type="variables">combodo-backoffice-fullmoon-tritanopia-theme/scss/scss-variables.scss</import>
|
||||
</imports>
|
||||
<stylesheets>
|
||||
<stylesheet id="fullmoon">../css/backoffice/main.scss</stylesheet>
|
||||
<stylesheet id="stylesheet">combodo-backoffice-fullmoon-tritanopia-theme/scss/stylesheet.scss</stylesheet>
|
||||
</stylesheets>
|
||||
<precompiled_stylesheet>combodo-backoffice-fullmoon-tritanopia-theme/precompiled-themes/main.css</precompiled_stylesheet>
|
||||
</theme>
|
||||
</themes>
|
||||
</branding>
|
||||
</itop_design>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'theme:fullmoon-tritanopia' => 'Fullmoon (Tritanopia)',
|
||||
));
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Localized data
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2023 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
* This file is part of iTop.
|
||||
*
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'theme:fullmoon-tritanopia' => 'Fullmoon (Tritanopie)',
|
||||
));
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
//
|
||||
// iTop module definition file
|
||||
//
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.2.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
'label' => 'Backoffice: Fullmoon with tritanopia accessibility theme',
|
||||
'category' => 'business',
|
||||
|
||||
// Setup
|
||||
//
|
||||
'dependencies' => array(
|
||||
|
||||
),
|
||||
'mandatory' => true,
|
||||
'visible' => false,
|
||||
|
||||
// Components
|
||||
//
|
||||
'datamodel' => array(
|
||||
),
|
||||
'webservice' => array(
|
||||
|
||||
),
|
||||
'data.struct' => array(
|
||||
// add your 'structure' definition XML files here,
|
||||
),
|
||||
'data.sample' => array(
|
||||
// add your sample data XML files here,
|
||||
),
|
||||
|
||||
// Documentation
|
||||
//
|
||||
'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any
|
||||
'doc.more_information' => '', // hyperlink to more information, if any
|
||||
|
||||
// Default settings
|
||||
//
|
||||
'settings' => array(
|
||||
// Module specific settings go here, if any
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,78 @@
|
||||
$ibo-color-yellow-100: #fefce8;
|
||||
$ibo-color-yellow-200: #fef9c3;
|
||||
$ibo-color-yellow-300: #fef08a;
|
||||
$ibo-color-yellow-400: #fde047;
|
||||
$ibo-color-yellow-500: #facc15;
|
||||
$ibo-color-yellow-600: #eab308;
|
||||
$ibo-color-yellow-700: #ca8a04;
|
||||
$ibo-color-yellow-800: #a16207;
|
||||
$ibo-color-yellow-900: #854d0e;
|
||||
$ibo-color-yellow-950: #713f12;
|
||||
|
||||
$ibo-color-success-100: $ibo-color-blue-100;
|
||||
$ibo-color-success-200: $ibo-color-blue-200;
|
||||
$ibo-color-success-300: $ibo-color-blue-300;
|
||||
$ibo-color-success-400: $ibo-color-blue-400;
|
||||
$ibo-color-success-500: $ibo-color-blue-500;
|
||||
$ibo-color-success-600: $ibo-color-blue-600;
|
||||
$ibo-color-success-700: $ibo-color-blue-700;
|
||||
$ibo-color-success-800: $ibo-color-blue-800;
|
||||
$ibo-color-success-900: $ibo-color-blue-900;
|
||||
$ibo-color-success-950: $ibo-color-blue-950;
|
||||
|
||||
$ibo-color-information-100: #f1f5f9;
|
||||
$ibo-color-information-200: #e2e8f0;
|
||||
$ibo-color-information-300: #cbd5e1;
|
||||
$ibo-color-information-400: #94a3b8;
|
||||
$ibo-color-information-500: #64748b;
|
||||
$ibo-color-information-600: #475569;
|
||||
$ibo-color-information-700: #334155;
|
||||
$ibo-color-information-800: #1e293b;
|
||||
$ibo-color-information-900: #0f172a;
|
||||
$ibo-color-information-950: #020617;
|
||||
|
||||
|
||||
$ibo-lifecycle-new-state-primary-color: $ibo-color-information-600;
|
||||
$ibo-lifecycle-new-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-neutral-state-primary-color: $ibo-color-information-600;
|
||||
$ibo-lifecycle-neutral-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-waiting-state-primary-color: $ibo-color-red-200;
|
||||
$ibo-lifecycle-waiting-state-secondary-color: $ibo-color-red-800;
|
||||
$ibo-lifecycle-success-state-primary-color: $ibo-color-blue-700;
|
||||
$ibo-lifecycle-success-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-failure-state-primary-color: $ibo-color-red-800;
|
||||
$ibo-lifecycle-failure-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-frozen-state-primary-color: $ibo-color-information-200;
|
||||
$ibo-lifecycle-frozen-state-secondary-color: $ibo-color-information-700;
|
||||
|
||||
$ibo-lifecycle-active-state-primary-color: $ibo-color-blue-700;
|
||||
$ibo-lifecycle-active-state-secondary-color: $ibo-color-white-100;
|
||||
$ibo-lifecycle-inactive-state-primary-color: $ibo-color-red-700;
|
||||
$ibo-lifecycle-inactive-state-secondary-color: $ibo-color-white-100;
|
||||
|
||||
$ibo-caselog-highlight-color-1: $ibo-color-blue-700;
|
||||
$ibo-caselog-highlight-color-2: $ibo-color-red-700;
|
||||
$ibo-caselog-highlight-color-3: $ibo-color-information-600;
|
||||
$ibo-caselog-highlight-color-4: $ibo-color-red-500;
|
||||
$ibo-caselog-highlight-color-5: $ibo-color-blue-500;
|
||||
$ibo-caselog-highlight-color-6: $ibo-color-red-300;
|
||||
$ibo-caselog-highlight-color-7: $ibo-color-blue-300;
|
||||
|
||||
$ibo-input-wrapper--is-error--border-color: $ibo-color-pink-700;
|
||||
$ibo-field-validation: $ibo-color-pink-800;
|
||||
|
||||
$ibo-navigation-menu--visual-hint--background-color: $ibo-color-pink-600;
|
||||
|
||||
$ibo-wizard-container--background-color: $ibo-color-information-200;
|
||||
$ibo-wizard-container--border-color: $ibo-color-information-600;
|
||||
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--background-color: $ibo-color-white-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--border: solid 2px $ibo-color-grey-500;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--background-color: $ibo-color-pink-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-1--border: solid 2px $ibo-color-pink-600;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--background-color: $ibo-color-warning-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-2--border: solid 2px $ibo-color-warning-400;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--background-color: $ibo-color-success-100;
|
||||
$ibo-navigation-menu--notifications--item--new-message-indicator--is-priority-3--border: solid 2px $ibo-color-success-500;
|
||||
|
||||
$ibo-notifications--view-all--item--unread--highlight--background-color: $ibo-color-pink-500;
|
||||
@@ -0,0 +1,73 @@
|
||||
$ibo-alert--icon--font-size: 3rem !default;
|
||||
$ibo-alert--icon--top: calc(50% - #{$ibo-alert--icon--font-size} / 2) !default;
|
||||
$ibo-alert--icon--left: $ibo-spacing-500 !default;
|
||||
$ibo-alert--icon--opacity: 0.3 !default;
|
||||
$ibo-alert--icons: (
|
||||
'success': '\f00c',
|
||||
'information': '\f129',
|
||||
'warning': '\f12a',
|
||||
'danger': '\f071',
|
||||
'failure': '\f071',
|
||||
'error': '\f071',
|
||||
) !default;
|
||||
|
||||
$ibo-toast--icon--font-size: 2rem !default;
|
||||
$ibo-toast--icon--top: calc(50% - #{$ibo-toast--icon--font-size} / 2) !default;
|
||||
$ibo-toast--icon--left: $ibo-spacing-400 !default;
|
||||
|
||||
|
||||
@each $sName, $sIcon in $ibo-alert--icons {
|
||||
%ibo-alert-#{$sName}, .ibo-alert.ibo-is-#{$sName} {
|
||||
&::after {
|
||||
content: $sIcon;
|
||||
@extend %fa-solid-base;
|
||||
position: absolute;
|
||||
top: $ibo-alert--icon--top;
|
||||
left: $ibo-alert--icon--left;
|
||||
opacity: $ibo-alert--icon--opacity;
|
||||
font-size: $ibo-alert--icon--font-size;
|
||||
width: $ibo-alert--icon--font-size;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ibo-alert--body, .ibo-alert--title {
|
||||
padding-left: calc(#{$ibo-alert--icon--left} + #{$ibo-alert--icon--font-size});
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-toast.ibo-is-#{$sName} {
|
||||
&::after{
|
||||
font-size: $ibo-toast--icon--font-size !important;
|
||||
top: $ibo-toast--icon--top !important;
|
||||
left: $ibo-toast--icon--left !important;
|
||||
width: $ibo-toast--icon--font-size !important;
|
||||
}
|
||||
padding-left: calc(#{$ibo-toast--padding-left} / 2 + #{$ibo-toast--icon--left} + #{$ibo-toast--icon--font-size});
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-navigation-menu--notifications--item--new-message-indicator{
|
||||
border: none !important;
|
||||
background-color: transparent !important;
|
||||
&.ibo-is-priority-1::before{
|
||||
content: "\f12a \f12a \f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-danger-700;
|
||||
}
|
||||
&.ibo-is-priority-2::before{
|
||||
content: "\f12a \f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-warning-700;
|
||||
}
|
||||
&.ibo-is-priority-3::before{
|
||||
content: "\f12a";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-success-700;
|
||||
}
|
||||
&.ibo-is-priority-4::before{
|
||||
content: "\f129";
|
||||
@extend %fa-solid-base;
|
||||
color: $ibo-color-information-700;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
<module>itop-hub-connector</module>
|
||||
<module>itop-oauth-client</module>
|
||||
<module>combodo-backoffice-darkmoon-theme</module>
|
||||
<module>combodo-backoffice-fullmoon-high-contrast-theme</module>
|
||||
<module>combodo-backoffice-fullmoon-protanopia-deuteranopia-theme</module>
|
||||
<module>combodo-backoffice-fullmoon-tritanopia-theme</module>
|
||||
<module>itop-themes-compat</module>
|
||||
</modules>
|
||||
<mandatory>true</mandatory>
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
$this->SetIfNull('user_id', $iUserId);
|
||||
|
||||
// Get Contact from user
|
||||
$oUser = MetaModel::GetObject('User', $iUserId);
|
||||
$oUser = MetaModel::GetObject('User', $iUserId, true, true);
|
||||
$this->SetIfNull('contact_id', $oUser->Get('contactid'));
|
||||
}
|
||||
return parent::DBInsertNoReload();
|
||||
@@ -266,7 +266,8 @@
|
||||
</classes>
|
||||
<events>
|
||||
<event id="EVENT_ADD_ATTACHMENT_TO_OBJECT" _delta="define">
|
||||
<description>An attachment has been added to an object</description>
|
||||
<name>Attachment added</name>
|
||||
<description><![CDATA[An attachment has been added to an object]]></description>
|
||||
<replaces>Attachment::AfterUpdate</replaces>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
@@ -287,7 +288,8 @@
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_REMOVE_ATTACHMENT_FROM_OBJECT" _delta="define">
|
||||
<description>An attachment has been removed from an object</description>
|
||||
<name>Attachment removed</name>
|
||||
<description><![CDATA[An attachment has been removed from an object]]></description>
|
||||
<replaces>Attachment::AfterUpdate</replaces>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
|
||||
@@ -267,6 +267,23 @@ class AttachmentPlugIn implements iApplicationUIExtension, iApplicationObjectExt
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @see ObjectFormManager::FinalizeAttachments() for the portal version
|
||||
*
|
||||
* @param $oObject
|
||||
* @param $oChange
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DeleteException
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
protected static function UpdateAttachments($oObject, $oChange = null)
|
||||
{
|
||||
self::$m_bIsModified = false;
|
||||
|
||||
@@ -185,6 +185,7 @@ abstract class AbstractAttachmentsRenderer
|
||||
{
|
||||
$sClass = $this->sObjClass;
|
||||
$sId = $this->iObjKey;
|
||||
$sAppRootUrl = utils::GetAbsoluteUrlAppRoot();
|
||||
$iMaxUploadInBytes = AttachmentPlugIn::GetMaxUploadSize();
|
||||
$sMaxUploadLabel = AttachmentPlugIn::GetMaxUpload();
|
||||
$sFileTooBigLabel = Dict::Format('Attachments:Error:FileTooLarge', $sMaxUploadLabel);
|
||||
@@ -195,15 +196,15 @@ abstract class AbstractAttachmentsRenderer
|
||||
$oAddButton = FileSelectUIBlockFactory::MakeStandard('file', 'file');
|
||||
$oAddButton->SetShowFilename(false);
|
||||
$this->oPage->AddUiBlock($oAddButton);
|
||||
$this->oPage->add('<span style="display:none;" id="attachment_loading"><img src="../images/indicator.gif"></span> '.$sMaxUploadLabel);
|
||||
$this->oPage->add('<span style="display:none;" id="attachment_loading"><img src="' . $sAppRootUrl . 'images/indicator.gif"></span> ' . $sMaxUploadLabel);
|
||||
$this->oPage->add('</div>');
|
||||
$this->oPage->add('<div class="ibo-attachment--upload-file--drop-zone-hint ibo-svg-illustration--container">');
|
||||
$this->oPage->add(file_get_contents(APPROOT.'images/illustrations/undraw_upload.svg'));
|
||||
$this->oPage->add(Dict::S('UI:Attachments:DropYourFileHint').'</div>');
|
||||
|
||||
|
||||
$this->oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.iframe-transport.js');
|
||||
$this->oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.fileupload.js');
|
||||
$this->oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.iframe-transport.js');
|
||||
$this->oPage->LinkScriptFromAppRoot('node_modules/blueimp-file-upload/js/jquery.fileupload.js');
|
||||
|
||||
$this->oPage->add_ready_script(
|
||||
<<<JS
|
||||
@@ -275,7 +276,7 @@ abstract class AbstractAttachmentsRenderer
|
||||
e.stopPropagation();
|
||||
})
|
||||
|
||||
$(document).bind('dragover', function (e) {
|
||||
$(document).on('dragover', function (e) {
|
||||
var bFiles = false;
|
||||
if (e.dataTransfer && e.dataTransfer.types)
|
||||
{
|
||||
@@ -316,7 +317,7 @@ abstract class AbstractAttachmentsRenderer
|
||||
window.dropZoneCnt++;
|
||||
});
|
||||
|
||||
$(document).bind('dragend dragleave drop', function(event){
|
||||
$(document).on('dragend dragleave drop', function(event){
|
||||
window.dropZoneCnt--;
|
||||
if(window.dropZone && window.dropZoneCnt === 0){
|
||||
window.dropZone.removeClass('ibo-drag-in');
|
||||
@@ -333,16 +334,16 @@ abstract class AbstractAttachmentsRenderer
|
||||
$(this).addClass('image-in-use').find('img').wrap('<div class="image-in-use-wrapper" style="position:relative;display:inline-block;"></div>');
|
||||
}
|
||||
});
|
||||
$('.htmlEditor').each(function() {
|
||||
var oEditor = $(this).ckeditorGet();
|
||||
var sHtml = oEditor.getData();
|
||||
var jElement = $('<div/>').html(sHtml).contents();
|
||||
jElement.find('img').each(function() {
|
||||
var sSrc = $(this).attr('src');
|
||||
$('.attachment a[href="'+sSrc+'"]').parent().addClass('image-in-use').find('img').wrap('<div class="image-in-use-wrapper" style="position:relative;display:inline-block;"></div>');
|
||||
});
|
||||
});
|
||||
$('.image-in-use-wrapper').append('<div style="position:absolute;top:0;left:0;"><img src="../images/transp-lock.png"></div>');
|
||||
// $('.htmlEditor').each(function() {
|
||||
// var oEditor = $(this).ckeditorGet();
|
||||
// var sHtml = oEditor.getData();
|
||||
// var jElement = $('<div/>').html(sHtml).contents();
|
||||
// jElement.find('img').each(function() {
|
||||
// var sSrc = $(this).attr('src');
|
||||
// $('.attachment a[href="'+sSrc+'"]').parent().addClass('image-in-use').find('img').wrap('<div class="image-in-use-wrapper" style="position:relative;display:inline-block;"></div>');
|
||||
// });
|
||||
// });
|
||||
$('.image-in-use-wrapper').append('<div style="position:absolute;top:0;left:0;"><img src="' + GetAbsoluteUrlModulesRoot() + 'images/transp-lock.png"></div>');
|
||||
}, 200 );
|
||||
JS
|
||||
);
|
||||
|
||||
@@ -993,34 +993,6 @@
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="SetClosureDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>StimulusUserAction</type>
|
||||
<code><![CDATA[ public function SetClosureDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('close_date', time());
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ResetRejectReason">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function ResetRejectReason($sStimulusCode)
|
||||
{
|
||||
$this->Set('reason', '');
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="OnInsert">
|
||||
<static>false</static>
|
||||
<access>protected</access>
|
||||
|
||||
@@ -535,48 +535,6 @@
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="SetApprovalDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function SetApprovalDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('approval_date', time());
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ResetRejectReason">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function ResetRejectReason($sStimulusCode)
|
||||
{
|
||||
$this->Set('reject_reason', '');
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="SetClosureDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function SetClosureDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('close_date', time());
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="OnInsert">
|
||||
<static>false</static>
|
||||
<access>protected</access>
|
||||
|
||||
@@ -80,7 +80,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
//
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:lnkContactToFunctionalCI' => 'Lien Contact / CI Fonctionel',
|
||||
'Class:lnkContactToFunctionalCI' => 'Lien Contact / CI Fonctionnel',
|
||||
'Class:lnkContactToFunctionalCI+' => '',
|
||||
'Class:lnkContactToFunctionalCI/Name' => '%1$s / %2$s',
|
||||
'Class:lnkContactToFunctionalCI/Attribute:functionalci_id' => 'CI',
|
||||
@@ -98,7 +98,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
//
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:FunctionalCI' => 'CI fonctionnel',
|
||||
'Class:FunctionalCI' => 'CI Fonctionnel',
|
||||
'Class:FunctionalCI+' => '',
|
||||
'Class:FunctionalCI/Attribute:name' => 'Nom',
|
||||
'Class:FunctionalCI/Attribute:name+' => '',
|
||||
@@ -1214,7 +1214,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
//
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:lnkFunctionalCIToOSPatch' => 'Lien CI Fonctionel / Patch OS',
|
||||
'Class:lnkFunctionalCIToOSPatch' => 'Lien CI Fonctionnel / Patch OS',
|
||||
'Class:lnkFunctionalCIToOSPatch+' => '',
|
||||
'Class:lnkFunctionalCIToOSPatch/Name' => '%1$s / %2$s',
|
||||
'Class:lnkFunctionalCIToOSPatch/Attribute:ospatch_id' => 'Patch OS',
|
||||
@@ -1449,7 +1449,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
//
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:lnkApplicationSolutionToFunctionalCI' => 'Lien Solution Applicative / CI Fonctionel',
|
||||
'Class:lnkApplicationSolutionToFunctionalCI' => 'Lien Solution Applicative / CI Fonctionnel',
|
||||
'Class:lnkApplicationSolutionToFunctionalCI+' => '',
|
||||
'Class:lnkApplicationSolutionToFunctionalCI/Name' => '%1$s / %2$s',
|
||||
'Class:lnkApplicationSolutionToFunctionalCI/Attribute:applicationsolution_id' => 'Solution applicative',
|
||||
@@ -1559,7 +1559,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
//
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:lnkDocumentToFunctionalCI' => 'Lien Document / CI Fonctionel',
|
||||
'Class:lnkDocumentToFunctionalCI' => 'Lien Document / CI Fonctionnel',
|
||||
'Class:lnkDocumentToFunctionalCI+' => '',
|
||||
'Class:lnkDocumentToFunctionalCI/Name' => '%1$s / %2$s',
|
||||
'Class:lnkDocumentToFunctionalCI/Attribute:functionalci_id' => 'CI',
|
||||
|
||||
@@ -109,10 +109,11 @@ ApplicationMenu::CheckMenuIdEnabled('ConfigEditor');
|
||||
|
||||
$oP = new iTopWebPage(Dict::S('config-edit-title'));
|
||||
$oP->set_base(utils::GetAbsoluteUrlAppRoot().'pages/');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/ace.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/mode-php.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/theme-eclipse.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'/js/ace/ext-searchbox.js');
|
||||
$sAceDir = 'node_modules/ace-builds/src-min/';
|
||||
$oP->LinkScriptFromAppRoot($sAceDir.'ace.js');
|
||||
$oP->LinkScriptFromAppRoot($sAceDir.'mode-php.js');
|
||||
$oP->LinkScriptFromAppRoot($sAceDir.'theme-eclipse.js');
|
||||
$oP->LinkScriptFromAppRoot($sAceDir.'ext-searchbox.js');
|
||||
|
||||
try {
|
||||
$sOperation = utils::ReadParam('operation', '');
|
||||
|
||||
@@ -45,6 +45,7 @@ class UpdateController extends Controller
|
||||
$aParams['sFileUploadMaxSize'] = utils::BytesToFriendlyFormat($aParams['iFileUploadMaxSize']);
|
||||
$aParams['sPostMaxSize'] = ini_get('post_max_size');
|
||||
$aParams['sUploadMaxSize'] = ini_get('upload_max_filesize');
|
||||
$aParams['bDontUpgradeIfIntegrityFailed'] = !utils::IsDevelopmentEnvironment();
|
||||
$oFilter = DBObjectSearch::FromOQL('SELECT ModuleInstallation WHERE parent_id=0 AND name!="datamodel"');
|
||||
$oSet = new DBObjectSet($oFilter, ['installed' => false]); // Most recent first
|
||||
$aParams['oSet'] = $oSet;
|
||||
@@ -129,7 +130,6 @@ class UpdateController extends Controller
|
||||
$sTransactionId = utils::GetNewTransactionId();
|
||||
$aParams['sTransactionId'] = $sTransactionId;
|
||||
|
||||
$this->AddSaas('css/backoffice/main.scss');
|
||||
$this->m_sOperation = 'ConfirmUpdate';
|
||||
$this->DisplaySetupPage($aParams);
|
||||
}
|
||||
@@ -158,7 +158,6 @@ class UpdateController extends Controller
|
||||
'sAjaxURL' => utils::GetAbsoluteUrlAppRoot().'/pages/UI.php',
|
||||
];
|
||||
$this->AddLinkedScript(utils::GetAbsoluteUrlAppRoot().'setup/jquery.progression.js');
|
||||
$this->AddSaas('css/backoffice/main.scss');
|
||||
$this->AddSaas('env-'.utils::GetCurrentEnvironment().'/itop-core-update/css/itop-core-update.scss');
|
||||
$this->m_sOperation = 'UpdateCoreFiles';
|
||||
$this->DisplaySetupPage($aParams);
|
||||
|
||||
@@ -28,10 +28,17 @@ $.ajax({
|
||||
$("#file-container").removeClass("ibo-is-hidden");
|
||||
$("#check-in-progress").addClass("ibo-is-hidden");
|
||||
} else {
|
||||
$("#check-update").prop("disabled", true);
|
||||
$("#file").prop("disabled", true);
|
||||
$('#form-update-outer').slideUp(600);
|
||||
oRequirements.addClass("ibo-is-failure");
|
||||
{% if bDontUpgradeIfIntegrityFailed %}
|
||||
$("#check-update").prop("disabled", true);
|
||||
$("#file").prop("disabled", true);
|
||||
$('#form-update-outer').slideUp(600);
|
||||
{% else %}
|
||||
$("#check-update").prop("disabled", false);
|
||||
$("#file").prop("disabled", false);
|
||||
$("#file-container").removeClass("ibo-is-hidden");
|
||||
$("#check-in-progress").addClass("ibo-is-hidden");
|
||||
{% endif %}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -55,7 +62,7 @@ var oGetDBDiskSpace = $.ajax({
|
||||
method: "POST",
|
||||
url: "{{ sAjaxURL|raw }}",
|
||||
data: {
|
||||
route: "core_update_ajax.get_d_b_disk_space",
|
||||
route: "core_update_ajax.get_db_disk_space",
|
||||
maintenance: true
|
||||
},
|
||||
dataType: "json",
|
||||
|
||||
@@ -17,7 +17,7 @@ class HubConnectorPage extends NiceWebPage
|
||||
$sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images';
|
||||
|
||||
$sUserPrefs = appUserPreferences::GetAsJSON();
|
||||
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
|
||||
$this->LinkScriptFromAppRoot('js/utils.js');
|
||||
$this->add_script(<<<JS
|
||||
var oUserPreferences = $sUserPrefs;
|
||||
JS
|
||||
|
||||
@@ -57,7 +57,7 @@ function DisplayStatus(WebPage $oPage)
|
||||
|
||||
function DoLanding(WebPage $oPage)
|
||||
{
|
||||
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css');
|
||||
$oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
|
||||
$oPage->add('<table class="module-selection-banner"><tr>');
|
||||
$sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png';
|
||||
$oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>');
|
||||
@@ -138,7 +138,7 @@ function DoInstall(WebPage $oPage)
|
||||
$sUID = hash('sha256', rand());
|
||||
file_put_contents(APPROOT.'data/hub/compile_authent', $sUID);
|
||||
|
||||
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css');
|
||||
$oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
|
||||
$oPage->add('<table class="module-selection-banner"><tr>');
|
||||
$sBannerUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/landing-extension.png';
|
||||
$oPage->add('<td><img style="max-height:72px; margin-right: 10px;" src="'.$sBannerUrl.'"/><td>');
|
||||
@@ -214,7 +214,7 @@ function DoInstall(WebPage $oPage)
|
||||
$oPage->add('</div>'); // module-selection-body
|
||||
|
||||
|
||||
$oPage->add_linked_stylesheet('../css/font-awesome/css/all.min.css');
|
||||
$oPage->LinkStylesheetFromAppRoot('css/font-awesome/css/all.min.css');
|
||||
|
||||
|
||||
$oPage->add('<div id="hub_installation_widget"></div>');
|
||||
@@ -263,8 +263,8 @@ try {
|
||||
}
|
||||
|
||||
$oPage = new SetupPage(''); // Title will be set later, depending on $sOperation
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js');
|
||||
$oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css');
|
||||
$oPage->LinkScriptFromModule('itop-hub-connector/js/hub.js');
|
||||
$oPage->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
|
||||
|
||||
$oPage->add_style(<<<CSS
|
||||
div.choice { margin: 0.5em;}
|
||||
|
||||
@@ -305,9 +305,9 @@ try {
|
||||
$sCloseUrl = utils::GetAbsoluteUrlModulesRoot().'/itop-hub-connector/images/black-close.svg';
|
||||
|
||||
$oPage = new HubConnectorPage(Dict::S('iTopHub:Connect'));
|
||||
$oPage->add_linked_script(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/js/hub.js');
|
||||
$oPage->add_linked_stylesheet('../css/font-combodo/font-combodo.css');
|
||||
$oPage->add_linked_stylesheet(utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/css/hub.css');
|
||||
$oPage->LinkScriptFromModule('itop-hub-connector/js/hub.js');
|
||||
$oPage->LinkStylesheetFromAppRoot('css/font-combodo/font-combodo.css');
|
||||
$oPage->LinkStylesheetFromModule('itop-hub-connector/css/hub.css');
|
||||
|
||||
$aDataToPost = MakeDataToPost($sTargetRoute);
|
||||
|
||||
|
||||
@@ -1083,64 +1083,6 @@
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
<method id="SetAssignedDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function SetAssignedDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('assignment_date', time());
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="SetLastPendingDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function SetLastPendingDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('last_pending_date', time());
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="SetResolveDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() and SetElapsedTime() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function SetResolveDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('resolution_date', time());
|
||||
$iTimeSpent = time() - AttributeDateTime::GetAsUnixSeconds($this->Get('start_date'));
|
||||
$this->Set('time_spent', $iTimeSpent);
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="SetClosureDate">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use SetCurrentDate() instead
|
||||
* @return void
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function SetClosureDate($sStimulusCode)
|
||||
{
|
||||
$this->Set('close_date', time());
|
||||
return true;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="DoCheckToWrite">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
@@ -1238,67 +1180,6 @@
|
||||
}
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="resolveChilds">
|
||||
<comment><![CDATA[/**
|
||||
* To be deprecated: use ResolveChildTickets() instead
|
||||
*/]]></comment>
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function resolveChilds($sStimulusCode)
|
||||
{
|
||||
if (MetaModel::IsValidClass('UserRequest'))
|
||||
{
|
||||
$sOQL = "SELECT UserRequest WHERE parent_incident_id=:ticket";
|
||||
$oChildRequestSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'ticket' => $this->GetKey(),
|
||||
)
|
||||
);
|
||||
//automatically resolve child requests
|
||||
while($oRequest = $oChildRequestSet->Fetch())
|
||||
{
|
||||
if ( $oRequest->Get('status') != 'resolved')
|
||||
{
|
||||
$oRequest->set('servicesubcategory_id',$this->Get('servicesubcategory_id'));
|
||||
$oRequest->set('service_id',$this->Get('service_id'));
|
||||
$oRequest->set('team_id',$this->Get('team_id'));
|
||||
$oRequest->set('agent_id',$this->Get('agent_id'));
|
||||
$oRequest->set('resolution_code',$this->Get('resolution_code'));
|
||||
$oRequest->set('solution','Automatically resolved by incident:[[Incident:'.$this->Get('ref').']]');
|
||||
$oRequest->ApplyStimulus('ev_autoresolve');
|
||||
$oRequest->DBUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//automatically resolve child incidents
|
||||
$sOQL = "SELECT Incident WHERE parent_incident_id=:ticket";
|
||||
$oChildIncidentSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'ticket' => $this->GetKey(),
|
||||
)
|
||||
);
|
||||
while($oIncident = $oChildIncidentSet->Fetch())
|
||||
{
|
||||
if ( $oIncident->Get('status') != 'resolved')
|
||||
{
|
||||
$oIncident->set('servicesubcategory_id',$this->Get('servicesubcategory_id'));
|
||||
$oIncident->set('service_id',$this->Get('service_id'));
|
||||
$oIncident->set('team_id',$this->Get('team_id'));
|
||||
$oIncident->set('agent_id',$this->Get('agent_id'));
|
||||
$oIncident->set('resolution_code',$this->Get('resolution_code'));
|
||||
$oIncident->set('solution','Automatically resolved by incident:[[Incident:'.$this->Get('ref').']]');
|
||||
$oIncident->ApplyStimulus('ev_autoresolve');
|
||||
$oIncident->DBUpdate();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ResolveChildTickets">
|
||||
<comment><![CDATA[/**
|
||||
* Cascade the resolution to child User Request and Incidents
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
<itop_design version="3.2">
|
||||
<events>
|
||||
<event id="EVENT_DISPLAY_OBJECT_DETAILS" _delta="define">
|
||||
<description>An object details is about to be displayed to a user</description>
|
||||
<name>Portal object displayed</name>
|
||||
<description><![CDATA[An object details is about to be displayed to a user on a portal]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
|
||||
@@ -29,6 +29,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use UserRights;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* Class UserProvider
|
||||
@@ -44,6 +45,8 @@ class UserProvider
|
||||
private $sPortalId;
|
||||
/** @var \User $oUser */
|
||||
private $oUser;
|
||||
/** @var bool $bUserCanLogOff Whether the current user can log off or not */
|
||||
private $bUserCanLogOff;
|
||||
/** @var array $aAllowedPortals */
|
||||
private $aAllowedPortals;
|
||||
|
||||
@@ -89,6 +92,9 @@ class UserProvider
|
||||
throw new Exception('Could not load connected user.');
|
||||
}
|
||||
|
||||
// User allowed to log off or not
|
||||
$this->bUserCanLogOff = utils::CanLogOff();
|
||||
|
||||
// Allowed portals
|
||||
$aAllowedPortals = UserRights::GetAllowedPortals();
|
||||
|
||||
@@ -119,6 +125,15 @@ class UserProvider
|
||||
return $this->oUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool {@see static::$bUserCanLogOff}
|
||||
* @since 3.1.2 3.2.0
|
||||
*/
|
||||
public function getCurrentUserCanLogOff(): bool
|
||||
{
|
||||
return $this->bUserCanLogOff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get allowed portals.
|
||||
*
|
||||
|
||||
@@ -1463,6 +1463,8 @@ class ObjectFormManager extends FormManager
|
||||
// Remove attachments that are no longer attached to the current object
|
||||
if (in_array($oAttachment->GetKey(), $aRemovedAttachmentsIds))
|
||||
{
|
||||
$aData = ['attachment' => $oAttachment];
|
||||
$this->oObject->FireEvent(EVENT_REMOVE_ATTACHMENT_FROM_OBJECT, $aData);
|
||||
$oAttachment->DBDelete();
|
||||
$aActions[] = self::GetAttachmentActionChangeOp($oAttachment, false);
|
||||
}
|
||||
@@ -1487,6 +1489,8 @@ class ObjectFormManager extends FormManager
|
||||
$oAttachment->Set('temp_id', '');
|
||||
$oAttachment->DBUpdate();
|
||||
$aActions[] = self::GetAttachmentActionChangeOp($oAttachment, true);
|
||||
$aData = ['attachment' => $oAttachment];
|
||||
$this->oObject->FireEvent(EVENT_ADD_ATTACHMENT_TO_OBJECT, $aData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user