diff --git a/.eslintrc.js b/.eslintrc.js
index 695779d..cf34169 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,3 +1,30 @@
+/**
+ * -------------------------------------------------------------------------
+ * Deploy plugin for GLPI
+ * -------------------------------------------------------------------------
+ *
+ * LICENSE
+ *
+ * This file is part of Deploy.
+ *
+ * Deploy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Deploy 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Deploy. If not, see .
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
module.exports = {
"root": true,
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index f21cdb7..9254f2e 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -14,13 +14,12 @@ on:
concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true
-
jobs:
generate-ci-matrix:
name: "Generate CI matrix"
uses: "glpi-project/plugin-ci-workflows/.github/workflows/generate-ci-matrix.yml@v1"
with:
- glpi-version: "10.1.x"
+ glpi-version: "11.0.x"
ci:
name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}"
needs: "generate-ci-matrix"
diff --git a/.gitignore b/.gitignore
index f6254b8..02bf194 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,4 @@ vendor/
.gh_token
composer.lock
*.min.*
-
+lib/
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..b6f27f1
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/.stylelintrc.js b/.stylelintrc.js
index 1116459..4573782 100644
--- a/.stylelintrc.js
+++ b/.stylelintrc.js
@@ -1,3 +1,30 @@
+/**
+ * -------------------------------------------------------------------------
+ * Deploy plugin for GLPI
+ * -------------------------------------------------------------------------
+ *
+ * LICENSE
+ *
+ * This file is part of Deploy.
+ *
+ * Deploy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Deploy 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Deploy. If not, see .
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
module.exports = {
"extends": "stylelint-config-standard",
diff --git a/ajax/timeslot.php b/ajax/timeslot.php
new file mode 100644
index 0000000..80a52d8
--- /dev/null
+++ b/ajax/timeslot.php
@@ -0,0 +1,55 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Deploy;
+
+use Glpi\Application\View\TemplateRenderer;
+
+include("../../../inc/includes.php");
+
+\Session::checkLoginUser();
+$trange = new TimeslotRange();
+$id = $_POST['plugin_deploy_timeslots_id'];
+TimeslotRange::cleanOldData($_POST);
+$_POST = TimeslotRange::cleanInput($_POST);
+foreach ($_POST as $timeslot) {
+ foreach ($timeslot as $range) {
+ if ((bool)$range['is_enable'] == true) {
+ $trange->add($range);
+ }
+ }
+}
+$timeslots_data = TimeslotRange::getForTimeslot(Timeslot::getById($id));
+echo TemplateRenderer::getInstance()->render('@deploy/timeslot/timeslotrange.html.twig', [
+ 'rand' => mt_rand(),
+ 'timeslot_id' => $id,
+ 'days_list' => TimeslotRange ::getDayList(),
+ 'timeslots_data' => $timeslots_data
+]);
diff --git a/front/package.form.php b/front/package.form.php
index 3aab27d..358977d 100644
--- a/front/package.form.php
+++ b/front/package.form.php
@@ -112,7 +112,7 @@
$action->delete($_POST);
Html::back();
} else if (isset($_POST["add_target"])) {
- if ($_POST['plugin_deploy_computers_groups_id'] > 0) {
+ if ($_POST['plugin_deploy_computers_groups_id'] > 0 && $_POST['plugin_deploy_timeslots_id'] > 0) {
$package_target = new PackageTarget();
$package_target->add($_POST);
}
diff --git a/front/timeslot.form.php b/front/timeslot.form.php
new file mode 100644
index 0000000..d04f1f9
--- /dev/null
+++ b/front/timeslot.form.php
@@ -0,0 +1,40 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Deploy;
+
+use Html;
+use Session;
+
+include('../../../inc/includes.php');
+
+Session::checkRight("entity", UPDATE);
+$dropdown = new Timeslot();
+include(GLPI_ROOT . "/front/dropdown.common.form.php");
diff --git a/front/timeslot.php b/front/timeslot.php
new file mode 100644
index 0000000..2d49c65
--- /dev/null
+++ b/front/timeslot.php
@@ -0,0 +1,41 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Deploy;
+
+use Html;
+use Search;
+use Session;
+
+include('../../../inc/includes.php');
+
+Session::checkRight("entity", UPDATE);
+$dropdown = new Timeslot();
+include(GLPI_ROOT . "/front/dropdown.common.php");
diff --git a/front/timeslotrange.form.php b/front/timeslotrange.form.php
new file mode 100644
index 0000000..a2d57fb
--- /dev/null
+++ b/front/timeslotrange.form.php
@@ -0,0 +1,59 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Deploy;
+
+use Html;
+use Session;
+
+include('../../../inc/includes.php');
+
+Session::checkRight("entity", UPDATE);
+
+if (!isset($_GET["id"])) {
+ $_GET["id"] = "";
+}
+
+$trange = new TimeslotRange();
+
+if (isset($_POST['timeslot']) && !empty($_POST['timeslot'])) {
+ $_POST['timeslot'] = json_decode($_POST['timeslot'], true);
+ TimeslotRange::cleanOldData($_POST);
+ $_POST = TimeslotRange::cleanInput($_POST);
+ foreach ($_POST as $timeslot) {
+ foreach ($timeslot as $range) {
+ if ($range['is_enable'] == true) {
+ $trange->add($range);
+ }
+ }
+ }
+ Session::addMessageAfterRedirect(__('Range options saved', 'deploy'), true, INFO);
+}
+Html::back();
diff --git a/hook.php b/hook.php
index a472ddc..97ca5f4 100644
--- a/hook.php
+++ b/hook.php
@@ -38,7 +38,10 @@
use GlpiPlugin\Deploy\PackageFile;
use GlpiPlugin\Deploy\PackageTarget;
use GlpiPlugin\Deploy\Profile;
+use GlpiPlugin\Deploy\PackageTimeslot;
use GlpiPlugin\Deploy\Repository;
+use GlpiPlugin\Deploy\Timeslot;
+use GlpiPlugin\Deploy\TimeslotRange;
/**
* -------------------------------------------------------------------------
@@ -68,6 +71,13 @@
* -------------------------------------------------------------------------
*/
+ // Define Dropdown tables to be manage in GLPI :
+function plugin_deploy_getDropdown()
+{
+ $dropdowns = [Timeslot::class => Timeslot::getTypeName(2)];
+ return $dropdowns;
+}
+
function plugin_deploy_install()
{
$version = plugin_version_deploy();
@@ -84,6 +94,8 @@ function plugin_deploy_install()
Group::install($migration);
GroupDynamic::install($migration);
GroupStatic::install($migration);
+ Timeslot::install($migration);
+ TimeslotRange::install($migration);
return true;
}
@@ -106,6 +118,8 @@ function plugin_deploy_uninstall()
Group::uninstall($migration);
GroupDynamic::uninstall($migration);
GroupStatic::uninstall($migration);
+ Timeslot::uninstall($migration);
+ TimeslotRange::uninstall($migration);
return true;
}
diff --git a/javascript/timeslot.js b/javascript/timeslot.js
new file mode 100644
index 0000000..32bc747
--- /dev/null
+++ b/javascript/timeslot.js
@@ -0,0 +1,172 @@
+/**
+ * -------------------------------------------------------------------------
+ * Deploy plugin for GLPI
+ * -------------------------------------------------------------------------
+ *
+ * LICENSE
+ *
+ * This file is part of Deploy.
+ *
+ * Deploy is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Deploy 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Deploy. If not, see .
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+var AJAX_URL = CFG_GLPI.root_doc + '/' + GLPI_PLUGINS_PATH.deploy + '/ajax/timeslot.php';
+
+var timeslot = {};
+var timeslotsData = JSON.parse(document.getElementById('timeslotsData').dataset.value);
+
+var everydayButton = document.getElementById('everyday');
+var daysLength = parseInt(document.getElementById('daysLength').dataset.value);
+var timeslot_id = parseInt(document.getElementById('timeslotId').dataset.value);
+
+function setSliderValues(slider, values) {
+ slider.noUiSlider.set(values);
+}
+
+function toggleSlider(slider, checkbox, addRangeButton, delRangeButton, i) {
+ if (checkbox.checked) {
+ addRangeButton.removeAttribute('disabled');
+ delRangeButton.removeAttribute('disabled');
+ setSliderValues(slider, timeslotsData[i] ? timeslotsData[i].map(slot => [slot.starttime, slot.endtime]).flat() : [8, 12, 14, 18]);
+ slider.style.display = 'block';
+ } else {
+ addRangeButton.setAttribute('disabled', true);
+ delRangeButton.setAttribute('disabled', true);
+ slider.style.display = 'none';
+ }
+ timeslot[i]['is_enable'] = +checkbox.checked;
+ document.getElementById('timeslot').value = JSON.stringify(timeslot);
+}
+
+function sendAjaxRequest(action, timeslot, timeslot_id) {
+ $.ajax({
+ method: 'POST',
+ url: AJAX_URL,
+ data: {
+ action: action,
+ timeslot: timeslot,
+ plugin_deploy_timeslots_id: timeslot_id
+ }
+ }).done(function(response) {
+ $('#tr_countainer').html(response);
+ });
+}
+
+for (let i = 1; i <= daysLength; i++) {
+ const slider = document.getElementById('slider' + i);
+ const checkbox = document.getElementById('notimeslot' + i);
+ const alldayButton = document.getElementById('allday' + i);
+ const addRangeButton = document.getElementById('addrange' + i);
+ const delRangeButton = document.getElementById('delrange' + i);
+
+ timeslot[i] = {
+ is_enable: +checkbox.checked
+ };
+
+ noUiSlider.create(slider, {
+ start: timeslotsData[i] ? timeslotsData[i].map(slot => [slot.starttime, slot.endtime]).flat() : [0, 0, 0, 0],
+ connect: [false, ...Array(timeslotsData[i].length * 2).fill().flatMap((_, idx) => idx % 2 === 0 ? [true, false] : [])],
+ behaviour: 'drag',
+ step: 1,
+ range: {
+ 'min': 0,
+ 'max': 24
+ },
+ margin: 1,
+ });
+
+ slider.noUiSlider.on('update', function(values, handle) {
+ timeslot[i]['is_enable'] = +checkbox.checked;
+ const order = Math.floor(handle / 2);
+ const start = document.getElementById('value' + order + '_start' + i);
+ const end = document.getElementById('value' + order + '_end' + i);
+ if (handle % 2 === 1) {
+ end.value = values[handle];
+ } else {
+ start.value = values[handle];
+ }
+ timeslot[i][order] = {
+ starttime: start.value,
+ endtime: end.value
+ };
+ document.getElementById('timeslot').value = JSON.stringify(timeslot);
+ });
+
+ // Disable slider if checkbox is not checked
+ toggleSlider(slider, checkbox, addRangeButton, delRangeButton, i);
+
+ // Enable or disable slider on checkbox change
+ checkbox.addEventListener('change', function() {
+ toggleSlider(slider, this, addRangeButton, delRangeButton, i);
+ });
+
+ alldayButton.addEventListener('click', function(event) {
+ timeslot[i] = {
+ 0: {
+ starttime: '0.00',
+ endtime: '24.00'
+ },
+ is_enable: 1
+ };
+ document.getElementById('timeslot').value = JSON.stringify(timeslot);
+ sendAjaxRequest('add', timeslot, timeslot_id);
+ });
+
+ // Disable add button if there are already 12 ranges
+ if (Object.keys(timeslot[i]).length - 1 >= 12) {
+ addRangeButton.setAttribute('disabled', true);
+ }
+
+ addRangeButton.addEventListener('click', function(event) {
+ const lastKey = Object.keys(timeslot[i]).length - 1;
+ timeslot[i][lastKey + 1] = {
+ starttime: '23.00',
+ endtime: '24.00'
+ };
+ document.getElementById('timeslot').value = JSON.stringify(timeslot);
+ sendAjaxRequest('add', timeslot, timeslot_id);
+ });
+
+ // Disable delete button if there is only 1 range
+ if (Object.keys(timeslot[i]).length - 1 === 1) {
+ delRangeButton.setAttribute('disabled', true);
+ }
+
+ delRangeButton.addEventListener('click', function(event) {
+ const lastKey = Object.keys(timeslot[i]).length - 1;
+ delete timeslot[i][lastKey - 1];
+ document.getElementById('timeslot').value = JSON.stringify(timeslot);
+ sendAjaxRequest('add', timeslot, timeslot_id);
+ });
+
+}
+
+everydayButton.addEventListener('click', function(event) {
+ for (let i = 1; i <= daysLength; i++) {
+ timeslot[i] = {
+ 0: {
+ starttime: '0.00',
+ endtime: '24.00'
+ },
+ is_enable: 1
+ };
+ document.getElementById('timeslot').value = JSON.stringify(timeslot);
+ document.getElementById("rangeform").submit();
+ }
+});
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..701e652
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,20 @@
+{
+ "name": "@glpi-plugins/deploy",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@glpi-plugins/deploy",
+ "hasInstallScript": true,
+ "license": "GPL-3.0",
+ "dependencies": {
+ "nouislider": "^15.7.1"
+ }
+ },
+ "node_modules/nouislider": {
+ "version": "15.7.1",
+ "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.7.1.tgz",
+ "integrity": "sha512-5N7C1ru/i8y3dg9+Z6ilj6+m1EfabvOoaRa7ztpxBSKKRZso4vA52DGSbBJjw5XLtFr/LZ9SgGAXqyVtlVHO5w=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0605f51
--- /dev/null
+++ b/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "@glpi-plugins/deploy",
+ "description": "GLPI Deploy plugin",
+ "private": true,
+ "license": "GPL-3.0",
+ "dependencies": {
+ "nouislider": "^15.7.1"
+ },
+ "scripts": {
+ "postinstall": "mv node_modules lib"
+ }
+ }
diff --git a/setup.php b/setup.php
index ea0f365..72445e0 100644
--- a/setup.php
+++ b/setup.php
@@ -28,12 +28,14 @@
* -------------------------------------------------------------------------
*/
+use Glpi\Plugin\Hooks;
+
define('PLUGIN_DEPLOY_VERSION', '0.0.5');
define('PLUGIN_DEPLOY_REPOSITORY_PATH', GLPI_PLUGIN_DOC_DIR . "/deploy/repository");
define('PLUGIN_DEPLOY_MANIFESTS_PATH', PLUGIN_DEPLOY_REPOSITORY_PATH . "/manifests");
define('PLUGIN_DEPLOY_PARTS_PATH', PLUGIN_DEPLOY_REPOSITORY_PATH . "/parts");
-define("PLUGIN_DEPLOY_MIN_GLPI", "10.1.0");
-define("PLUGIN_DEPLOY_MAX_GLPI", "10.1.99");
+define("PLUGIN_DEPLOY_MIN_GLPI", "11.0.0");
+define("PLUGIN_DEPLOY_MAX_GLPI", "11.0.99");
/**
* Init hooks of the plugin.
@@ -63,6 +65,9 @@ function plugin_init_deploy()
];
$PLUGIN_HOOKS['config_page']['deploy'] = 'front/package.php';
+ $PLUGIN_HOOKS[Hooks::ADD_CSS]['deploy'][] = 'lib/nouislider/dist/nouislider.css';
+ $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT]['deploy'][] = 'lib/nouislider/dist/nouislider.min.js';
+
Plugin::registerClass('GlpiPlugin\Deploy\Profile', ['addtabon' => ['Profile']]);
}
@@ -98,8 +103,13 @@ function plugin_version_deploy()
*/
function plugin_deploy_check_prerequisites()
{
+ $prerequisitesSuccess = true;
+ if (!is_dir(__DIR__ . '/lib/') || !is_readable(__DIR__ . '/lib/.package-lock.json')) {
+ echo "Run `npm install` in the plugin directory ";
+ $prerequisitesSuccess = false;
+ }
- return true;
+ return $prerequisitesSuccess;
}
/**
diff --git a/src/Computer/Group.php b/src/Computer/Group.php
index 656bd6a..b04172c 100644
--- a/src/Computer/Group.php
+++ b/src/Computer/Group.php
@@ -34,6 +34,8 @@
use Computer;
use DisplayPreference;
use Glpi\Application\View\TemplateRenderer;
+use GlpiPlugin\Deploy\PackageTarget;
+use GlpiPlugin\Deploy\Timeslot;
use Migration;
use Search;
use Session;
@@ -148,6 +150,24 @@ public function rawSearchOptions()
]
];
+ $tab[] = [
+ 'id' => '9',
+ 'table' => Timeslot::getTable(),
+ 'field' => 'name',
+ 'datatype' => 'itemlink',
+ 'name' => __('Timeslot', 'deploy'),
+ 'forcegroupby' => true,
+ 'massiveaction' => false,
+ 'joinparams' => [
+ 'beforejoin' => [
+ 'table' => PackageTarget::getTable(),
+ 'joinparams' => [
+ 'jointype' => 'child',
+ ]
+ ]
+ ]
+ ];
+
return $tab;
}
@@ -202,6 +222,27 @@ public function countStaticItem()
return $count;
}
+ public function getTimeslotLink()
+ {
+ /** @var object $DB */
+ global $DB;
+
+ $params = [
+ 'SELECT' => 'plugin_deploy_timeslots_id',
+ 'FROM' => PackageTarget::getTable(),
+ 'WHERE' => ['plugin_deploy_computers_groups_id' => $this->fields['id']],
+ ];
+ $iterator = $DB->request($params);
+ $plugin_deploy_timeslots_id = 0;
+ foreach ($iterator as $data) {
+ $plugin_deploy_timeslots_id = $data['plugin_deploy_timeslots_id'];
+ }
+
+ $timeslot = new Timeslot();
+ $timeslot->getFromDB($plugin_deploy_timeslots_id);
+ return $timeslot->getLink();
+ }
+
public static function install(Migration $migration)
{
diff --git a/src/PackageTarget.php b/src/PackageTarget.php
index 3149653..801b197 100644
--- a/src/PackageTarget.php
+++ b/src/PackageTarget.php
@@ -134,11 +134,13 @@ public static function install(Migration $migration)
$package_fk = getForeignKeyFieldForItemType(Package::class);
$computer_group_fk = getForeignKeyFieldForItemType(Group::class);
+ $timeslot_fk = getForeignKeyFieldForItemType(Timeslot::class);
$query = "CREATE TABLE IF NOT EXISTS `$table` (
`id` int $sign NOT NULL AUTO_INCREMENT,
`$package_fk` int $sign NOT NULL DEFAULT '0',
`$computer_group_fk` int $sign NOT NULL DEFAULT '0',
+ `$timeslot_fk` int $sign NOT NULL DEFAULT '0',
`date_creation` timestamp NULL DEFAULT NULL,
`date_mod` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
@@ -152,7 +154,6 @@ public static function install(Migration $migration)
}
}
-
public static function uninstall(Migration $migration)
{
$table = self::getTable();
diff --git a/src/Timeslot.php b/src/Timeslot.php
new file mode 100644
index 0000000..da98f76
--- /dev/null
+++ b/src/Timeslot.php
@@ -0,0 +1,92 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Deploy;
+
+use CommonDropdown;
+use DBConnection;
+use Migration;
+
+class Timeslot extends CommonDropdown
+{
+ public static function getTypeName($nb = 0)
+ {
+ return __('Timeslot', 'deploy');
+ }
+
+ public static function getIcon()
+ {
+ return 'ti ti-calendar';
+ }
+
+ public function defineTabs($options = [])
+ {
+
+ $ong = [];
+ $this->addDefaultFormTab($ong)
+ ->addStandardTab(TimeslotRange::getType(), $ong, $options)
+ ->addStandardTab(__CLASS__, $ong, $options);
+
+ return $ong;
+ }
+
+ public static function install(Migration $migration)
+ {
+ /** @var object $DB */
+ global $DB;
+
+ $table = self::getTable();
+ if (!$DB->tableExists($table)) {
+ $migration->displayMessage("Installing $table");
+
+ $default_charset = DBConnection::getDefaultCharset();
+ $default_collation = DBConnection::getDefaultCollation();
+
+ $query = "CREATE TABLE {$table} (
+ `id` int unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) DEFAULT NULL,
+ `date_creation` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `date_mod` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ KEY `name` (`name`),
+ KEY `date_creation` (`date_creation`),
+ KEY `date_mod` (`date_mod`)
+ ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
+ $DB->request($query);
+ }
+ }
+
+ public static function uninstall(Migration $migration)
+ {
+ $table = self::getTable();
+ $migration->displayMessage("Uninstalling $table");
+ $migration->dropTable($table);
+ }
+}
diff --git a/src/TimeslotRange.php b/src/TimeslotRange.php
new file mode 100644
index 0000000..3c5a39a
--- /dev/null
+++ b/src/TimeslotRange.php
@@ -0,0 +1,203 @@
+.
+ * -------------------------------------------------------------------------
+ * @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ * @link https://github.com/pluginsGLPI/deploy
+ * -------------------------------------------------------------------------
+ */
+
+namespace GlpiPlugin\Deploy;
+
+use CommonDBTM;
+use CommonGLPI;
+use DBConnection;
+use Glpi\Application\View\TemplateRenderer;
+use Migration;
+
+class TimeslotRange extends CommonDBTM
+{
+ public static function getTypeName($nb = 0)
+ {
+ return __('Range', 'deploy');
+ }
+
+ public static function getIcon()
+ {
+ return 'ti ti-calendar-event';
+ }
+
+ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
+ {
+ if ($item->getType() == Timeslot::class) {
+ return self::createTabEntry(self::getTypeName(1), 0);
+ }
+ return '';
+ }
+
+ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0)
+ {
+ if ($item->getType() == Timeslot::class) {
+ self::showForTimeslot($item);
+ }
+ return true;
+ }
+
+ public static function getForTimeslot(Timeslot $timeslot)
+ {
+ $timeslots = new self();
+ $timeslots = $timeslots->find([
+ 'plugin_deploy_timeslots_id' => $timeslot->fields['id'],
+ ]);
+ $timeslots_data = [];
+ foreach ($timeslots as $timeslot) {
+ $timeslots_data[$timeslot['weekday']][] = [
+ 'checked' => 'checked',
+ 'starttime' => intval(substr($timeslot['time_start'], 0, 2)),
+ 'endtime' => intval(substr($timeslot['time_end'], 0, 2)),
+ ];
+ $timeslots_data['as_data'] = true;
+ }
+ for ($i = 1; $i <= 7; $i++) {
+ if (!isset($timeslots_data[$i])) {
+ $timeslots_data[$i] = [
+ [
+ 'checked' => '',
+ 'starttime' => 8,
+ 'endtime' => 12,
+ ],
+ [
+ 'checked' => '',
+ 'starttime' => 14,
+ 'endtime' => 18,
+ ]
+ ];
+ }
+ }
+ return $timeslots_data;
+ }
+
+ public static function showForTimeslot(Timeslot $timeslot)
+ {
+ $timeslots_data = self::getForTimeslot($timeslot);
+ TemplateRenderer::getInstance()->display('@deploy/timeslot/timeslotrange.html.twig', [
+ 'rand' => mt_rand(),
+ 'timeslot_id' => $timeslot->fields['id'],
+ 'days_list' => self::getDayList(),
+ 'timeslots_data' => $timeslots_data
+ ]);
+ }
+
+ public static function getDayList()
+ {
+ return [
+ 1 => __('Monday'),
+ 2 => __('Tuesday'),
+ 3 => __('Wednesday'),
+ 4 => __('Thursday'),
+ 5 => __('Friday'),
+ 6 => __('Saturday'),
+ 7 => __('Sunday'),
+ ];
+ }
+
+ public static function cleanOldData(array $input)
+ {
+ $timeslot = new self();
+ $olddata = $timeslot->find(
+ [
+ 'plugin_deploy_timeslots_id' => $input['plugin_deploy_timeslots_id'],
+ ]
+ );
+ foreach ($olddata as $data) {
+ $timeslot->delete(
+ [
+ 'id' => $data['id']
+ ]
+ );
+ }
+ }
+
+ public static function cleanInput(array $input)
+ {
+ $output = [];
+ foreach ($input['timeslot'] as $key => $value) {
+ foreach ($value as $k => $v) {
+ if ($k == 'is_enable') {
+ continue;
+ }
+ $start_time = sprintf('%02d:00:00', $v['starttime']);
+ $end_time = sprintf('%02d:00:00', $v['endtime']);
+ $output[$key][$k] = [
+ 'plugin_deploy_timeslots_id' => $input['plugin_deploy_timeslots_id'],
+ 'weekday' => $key,
+ 'time_start' => $start_time,
+ 'time_end' => $end_time,
+ 'is_enable' => (bool)$value['is_enable'],
+ ];
+ }
+ }
+
+ return $output;
+ }
+
+ public static function install(Migration $migration)
+ {
+ /** @var object $DB */
+ global $DB;
+
+ $table = self::getTable();
+ if (!$DB->tableExists($table)) {
+ $migration->displayMessage("Installing $table");
+
+ $default_charset = DBConnection::getDefaultCharset();
+ $default_collation = DBConnection::getDefaultCollation();
+
+ $query = "CREATE TABLE {$table} (
+ `id` int unsigned NOT NULL AUTO_INCREMENT,
+ `plugin_deploy_timeslots_id` int unsigned NOT NULL DEFAULT '0',
+ `weekday` tinyint NOT NULL DEFAULT '1',
+ `time_start` time NULL DEFAULT NULL,
+ `time_end` time NULL DEFAULT NULL,
+ `entities_id` int unsigned NOT NULL DEFAULT '0',
+ `is_active` tinyint(1) NOT NULL DEFAULT '1',
+ `is_recursive` tinyint(1) NOT NULL DEFAULT '0',
+ `date_mod` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ KEY `entities_id` (`entities_id`),
+ KEY `is_active` (`is_active`),
+ KEY `is_recursive` (`is_recursive`),
+ KEY `date_mod` (`date_mod`)
+ ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;";
+ $DB->request($query);
+ }
+ }
+
+ public static function uninstall(Migration $migration)
+ {
+ $table = self::getTable();
+ $migration->displayMessage("Uninstalling $table");
+ $migration->dropTable($table);
+ }
+}
diff --git a/templates/package/subitemtarget.list.html.twig b/templates/package/subitemtarget.list.html.twig
index 8d062cc..1fdf821 100644
--- a/templates/package/subitemtarget.list.html.twig
+++ b/templates/package/subitemtarget.list.html.twig
@@ -87,6 +87,9 @@
{{ __('Number of statics items', 'deploy') }}
+
+ {{ __('Timeslot', 'deploy') }}
+
@@ -118,6 +121,9 @@
{{ subitem.countStaticItem() }}
+
+ {{ subitem.getTimeslotLink()|raw }}
+
{% endfor %}
diff --git a/templates/package/target.list.html.twig b/templates/package/target.list.html.twig
index 6ed6406..d4fc4af 100644
--- a/templates/package/target.list.html.twig
+++ b/templates/package/target.list.html.twig
@@ -29,28 +29,44 @@
{% import 'components/form/fields_macros.html.twig' as fields %}
{% extends "@deploy/package/subitemtarget.list.html.twig" %}
-
{% block subitem_form %}
- {{ fields.dropdownField(
- "GlpiPlugin\\Deploy\\Computer\\Group",
- 'plugin_deploy_computers_groups_id',
- '0',
- call('GlpiPlugin\\Deploy\\Computer\\Group::getTypeName', [0]),
- {
- 'used': used_item,
- }
- ) }}
+
+
+ {{ fields.dropdownField(
+ "GlpiPlugin\\Deploy\\Computer\\Group",
+ 'plugin_deploy_computers_groups_id',
+ '0',
+ call('GlpiPlugin\\Deploy\\Computer\\Group::getTypeName', [0]),
+ {
+ 'used': used_item,
+ 'required': true,
+ 'field_class': 'col-12 col-sm-3',
+ }
+ ) }}
+
+ {{ fields.dropdownField(
+ "GlpiPlugin\\Deploy\\Timeslot",
+ 'plugin_deploy_timeslots_id',
+ '0',
+ __("Choose a timeslot", 'deploy'),
+ {
+ 'required': true,
+ 'field_class': 'col-12 col-sm-3',
+ }
+ ) }}
- {% set btn_add %}
-
-
- {{ __("Add a new target", 'deploy') }}
-
- {% endset %}
+ {% set btn_add %}
+
+
+ {{ __("Add a new target", 'deploy') }}
+
+ {% endset %}
- {{ fields.htmlField(
- '',
- btn_add,
- ''
- ) }}
+ {{ fields.htmlField(
+ '',
+ btn_add,
+ ''
+ ) }}
+
+
{% endblock %}
diff --git a/templates/package/task.list.html.twig b/templates/package/task.list.html.twig
index 850609e..2207061 100644
--- a/templates/package/task.list.html.twig
+++ b/templates/package/task.list.html.twig
@@ -25,7 +25,6 @@
# @link https://github.com/pluginsGLPI/deploy
# -------------------------------------------------------------------------
#}
-
{% if tasks|length == 0 %}
diff --git a/templates/package/timeslot.html.twig b/templates/package/timeslot.html.twig
new file mode 100644
index 0000000..6f4277b
--- /dev/null
+++ b/templates/package/timeslot.html.twig
@@ -0,0 +1,43 @@
+{#
+ # -------------------------------------------------------------------------
+ # Deploy plugin for GLPI
+ # -------------------------------------------------------------------------
+ #
+ # LICENSE
+ #
+ # This file is part of Deploy.
+ #
+ # Deploy is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # Deploy 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 General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with Deploy. If not, see
.
+ # -------------------------------------------------------------------------
+ # @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ # @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ # @link https://github.com/pluginsGLPI/deploy
+ # -------------------------------------------------------------------------
+ #}
+
+
+
+
diff --git a/templates/timeslot/timeslotrange.html.twig b/templates/timeslot/timeslotrange.html.twig
new file mode 100644
index 0000000..584c5c9
--- /dev/null
+++ b/templates/timeslot/timeslotrange.html.twig
@@ -0,0 +1,108 @@
+{#
+ # -------------------------------------------------------------------------
+ # Deploy plugin for GLPI
+ # -------------------------------------------------------------------------
+ #
+ # LICENSE
+ #
+ # This file is part of Deploy.
+ #
+ # Deploy is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+ #
+ # Deploy 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 General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License
+ # along with Deploy. If not, see
.
+ # -------------------------------------------------------------------------
+ # @copyright Copyright (C) 2022-2024 by Deploy plugin team.
+ # @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
+ # @link https://github.com/pluginsGLPI/deploy
+ # -------------------------------------------------------------------------
+ #}
+
+{% set header %}
+
+
+
+ {{ __('Day')}}
+
+
+ {{ __('Timeslot', 'deploy')}}
+
+
+ {{ __('All Day', 'deploy')}}
+
+ {% for i in 0..24 %}
+
+ {{ '%02d'|format(i) }}
+
+ {% endfor %}
+
+ {{ __('Add', 'deploy')}}
+
+
+ {{ __('Delete', 'deploy')}}
+
+
+
+{% endset %}
+