Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .phpstan-baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -4972,13 +4972,13 @@
$ignoreErrors[] = [
'message' => '#^Function json_decode is unsafe to use\\. It can return FALSE instead of throwing an exception\\. Please add \'use function Safe\\\\json_decode;\' at the beginning of the file to use the variant provided by the \'thecodingmachine/safe\' library\\.$#',
'identifier' => 'theCodingMachineSafe.function',
'count' => 4,
'count' => 5,
'path' => __DIR__ . '/src/Glpi/Form/Question.php',
];
$ignoreErrors[] = [
'message' => '#^Function json_encode is unsafe to use\\. It can return FALSE instead of throwing an exception\\. Please add \'use function Safe\\\\json_encode;\' at the beginning of the file to use the variant provided by the \'thecodingmachine/safe\' library\\.$#',
'identifier' => 'theCodingMachineSafe.function',
'count' => 3,
'count' => 5,
'path' => __DIR__ . '/src/Glpi/Form/Question.php',
];
$ignoreErrors[] = [
Expand Down
2 changes: 1 addition & 1 deletion css/includes/components/form/_form-editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ input.value-selector {
}
}

.visibility-dropdown-card {
.visibility-dropdown-card, .validation-dropdown-card {
min-width: 700px;
width: fit-content;

Expand Down
22 changes: 22 additions & 0 deletions install/migrations/update_10.0.x_to_11.0.0/form.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,28 @@
);
}

if (!$DB->fieldExists('glpi_forms_questions', 'validation_strategy')) {
$migration->addField(
'glpi_forms_questions',
'validation_strategy',
"varchar(30) NOT NULL DEFAULT ''",
[
'after' => 'conditions',
]
);
}

if (!$DB->fieldExists('glpi_forms_questions', 'validation_conditions')) {
$migration->addField(
'glpi_forms_questions',
'validation_conditions',
"JSON NOT NULL",
[
'after' => 'validation_strategy',
]
);
}

// Add rights for the forms object
$migration->addRight("form", ALLSTANDARDRIGHT, ['config' => UPDATE]);

Expand Down
2 changes: 2 additions & 0 deletions install/mysql/glpi-empty.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9555,6 +9555,8 @@ CREATE TABLE `glpi_forms_questions` (
`extra_data` text COMMENT 'JSON - Extra configuration field(s) depending on the questions type',
`visibility_strategy` varchar(30) NOT NULL DEFAULT '',
`conditions` JSON NOT NULL,
`validation_strategy` varchar(30) NOT NULL DEFAULT '',
`validation_conditions` JSON NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uuid` (`uuid`),
KEY `name` (`name`),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@
* ---------------------------------------------------------------------
*/


export class GlpiFormConditionEditorController
{
export class BaseConditionEditorController {
/**
* Target containerthat will display the condition editor
* Target container that will display the condition editor
* @type {HTMLElement}
*/
#container;
Expand Down Expand Up @@ -63,8 +61,10 @@ export class GlpiFormConditionEditorController
/** @type {?string} */
#item_type;

constructor(container, item_uuid, item_type, forms_sections, form_questions, form_comments)
{
/** @type {string} */
#editorEndpoint;

constructor(container, item_uuid, item_type, forms_sections, form_questions, form_comments, editorEndpoint) {
this.#container = container;
if (this.#container.dataset.glpiConditionsEditorContainer === undefined) {
console.error(this.#container); // Help debugging by printing the node.
Expand All @@ -75,6 +75,9 @@ export class GlpiFormConditionEditorController
this.#item_uuid = item_uuid;
this.#item_type = item_type;

// Set the editor endpoint URL
this.#editorEndpoint = editorEndpoint;

// Load form sections
this.#form_sections = forms_sections;

Expand All @@ -94,8 +97,7 @@ export class GlpiFormConditionEditorController
}
}

async renderEditor()
{
async renderEditor() {
const data = this.#computeData();
await this.#doRenderEditor(data);
}
Expand All @@ -104,32 +106,28 @@ export class GlpiFormConditionEditorController
* In a dynamic environement such as the form editor, it might be necessary
* to redefine the known list of available sections.
*/
setFormSections(form_sections)
{
setFormSections(form_sections) {
this.#form_sections = form_sections;
}

/**
* In a dynamic environement such as the form editor, it might be necessary
* to redefine the known list of available questions.
*/
setFormQuestions(form_questions)
{
setFormQuestions(form_questions) {
this.#form_questions = form_questions;
}

/**
* In a dynamic environement such as the form editor, it might be necessary
* to redefine the known list of available comments.
*/
setFormComments(form_comments)
{
setFormComments(form_comments) {
this.#form_comments = form_comments;
}

async #doRenderEditor(data)
{
const url = `${CFG_GLPI.root_doc}/Form/Condition/Editor`;
async #doRenderEditor(data) {
const url = this.#editorEndpoint;
const content = await $.post(url, {
form_data: data,
});
Expand All @@ -138,8 +136,7 @@ export class GlpiFormConditionEditorController
$(this.#container.querySelector('[data-glpi-conditions-editor]')).html(content);
}

#initEventHandlers()
{
#initEventHandlers() {
// Handle add and delete conditions
this.#container.addEventListener('click', (e) => {
const target = e.target;
Expand Down Expand Up @@ -195,24 +192,21 @@ export class GlpiFormConditionEditorController
}
}

async #addNewEmptyCondition()
{
async #addNewEmptyCondition() {
const data = this.#computeData();
data.conditions.push({'item': ''});
await this.#doRenderEditor(data);
}

async #deleteCondition(condition_index)
{
async #deleteCondition(condition_index) {
const data = this.#computeData();
data.conditions = data.conditions.filter((_condition, index) => {
return index != condition_index;
});
await this.#doRenderEditor(data);
}

#computeData()
{
#computeData() {
return {
sections: this.#form_sections,
questions: this.#form_questions,
Expand All @@ -223,8 +217,7 @@ export class GlpiFormConditionEditorController
};
}

#computeDefinedConditions()
{
#computeDefinedConditions() {
const conditions_data = [];
const conditions = this.#container.querySelectorAll(
'[data-glpi-conditions-editor-condition]'
Expand Down
47 changes: 47 additions & 0 deletions js/modules/Forms/ConditionValidationEditorController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2025 Teclib' and contributors.
* @licence https://www.gnu.org/licenses/gpl-3.0.html
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*/

import { BaseConditionEditorController } from './BaseConditionEditorController.js';

export class GlpiFormConditionValidationEditorController extends BaseConditionEditorController {
constructor(container, item_uuid, item_type, forms_sections, form_questions, form_comments) {
super(
container,
item_uuid,
item_type,
forms_sections,
form_questions,
form_comments,
`${CFG_GLPI.root_doc}/Form/Condition/Validation/Editor`
);
}
}
47 changes: 47 additions & 0 deletions js/modules/Forms/ConditionVisibilityEditorController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2025 Teclib' and contributors.
* @licence https://www.gnu.org/licenses/gpl-3.0.html
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*/

import { BaseConditionEditorController } from './BaseConditionEditorController.js';

export class GlpiFormConditionVisibilityEditorController extends BaseConditionEditorController {
constructor(container, item_uuid, item_type, forms_sections, form_questions, form_comments) {
super(
container,
item_uuid,
item_type,
forms_sections,
form_questions,
form_comments,
`${CFG_GLPI.root_doc}/Form/Condition/Visibility/Editor`
);
}
}
Loading