Skip to content

Commit

Permalink
feat(forms): Adding actors category and related sub question types
Browse files Browse the repository at this point in the history
  • Loading branch information
ccailly committed Apr 11, 2024
1 parent e680b33 commit a878926
Show file tree
Hide file tree
Showing 20 changed files with 1,001 additions and 114 deletions.
62 changes: 62 additions & 0 deletions ajax/getFormQuestionActorsDropdownValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/**
* ---------------------------------------------------------------------
*
* GLPI - Gestionnaire Libre de Parc Informatique
*
* http://glpi-project.org
*
* @copyright 2015-2024 Teclib' and contributors.
* @copyright 2003-2014 by the INDEPNET Development Team.
* @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/>.
*
* ---------------------------------------------------------------------
*/

use Glpi\Form\Dropdown\FormActorsDropdown;
use Glpi\Form\Question;
use Glpi\Form\QuestionType\QuestionTypeAssignee;
use Glpi\Form\QuestionType\QuestionTypeObserver;
use Glpi\Form\QuestionType\QuestionTypeRequester;

include(__DIR__ . '/getAbstractRightDropdownValue.php');

Session::checkLoginUser();

if (Session::getCurrentInterface() !== 'central') {
$questions = (new Question())->find([
'type' => [
QuestionTypeAssignee::class,
QuestionTypeObserver::class,
QuestionTypeRequester::class
]
]);

// Check if the user can view at least one question
if (array_reduce($questions, fn($acc, $question) => $acc || $question->canViewItem(), false) === false) {
http_response_code(403);
exit();
}
}

show_rights_dropdown(FormActorsDropdown::class);
102 changes: 102 additions & 0 deletions js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ var timeoutglobalvar;
// api does not provide any method to get the current configuration
var tinymce_editor_configs = {};

// Store select2 configurations
// This is needed if a select2 need to be destroyed and recreated as select2
// api does not provide any method to get the current configuration
var select2_configs = {};

/**
* modifier la propriete display d'un element
*
Expand Down Expand Up @@ -1760,3 +1765,100 @@ function getUUID() {
if (typeof GlpiCommonAjaxController == "function") {
new GlpiCommonAjaxController();
}

function setupAjaxDropdown(config) {
// Field ID is used as a selector, so we need to escape special characters
// to avoid issues with jQuery.
const field_id = $.escapeSelector(config.field_id);

const select2_el = $('#' + field_id).select2({
width: config.width,
multiple: config.multiple,
placeholder: config.placeholder,
allowClear: config.allowclear,
minimumInputLength: 0,
quietMillis: 100,
dropdownAutoWidth: true,
dropdownParent: $('#' + field_id).closest('div.modal, div.dropdown-menu, body'),
minimumResultsForSearch: config.ajax_limit_count,
ajax: {
url: config.url,
dataType: 'json',
type: 'POST',
data: function (params) {
query = params;
var data = $.extend({}, config.params, {
searchText: params.term,
});

if (config.parent_id_field !== '') {
data.parent_id = document.getElementById(config.parent_id_field).value;
}

data.page_limit = config.dropdown_max; // page size
data.page = params.page || 1; // page number

return data;
},
processResults: function (data, params) {
params.page = params.page || 1;
var more = (data.count >= config.dropdown_max);

return {
results: data.results,
pagination: {
more: more
}
};
}
},
templateResult: config.templateResult,
templateSelection: config.templateSelection
})
.bind('setValue', function (e, value) {
$.ajax(config.url, {
data: $.extend({}, config.params, {
_one_id: value,
}),
dataType: 'json',
type: 'POST',
}).done(function (data) {

var iterate_options = function (options, value) {
var to_return = false;
$.each(options, function (index, option) {
if (Object.prototype.hasOwnProperty.call(option, 'id') && option.id == value) {
to_return = option;
return false; // act as break;
}

if (Object.prototype.hasOwnProperty.call(option, 'children')) {
to_return = iterate_options(option.children, value);
}
});

return to_return;
};

var option = iterate_options(data.results, value);
if (option !== false) {
var newOption = new Option(option.text, option.id, true, true);
$('#' + field_id).append(newOption).trigger('change');
}
});
});

if (config.on_change !== '') {
$('#' + field_id).on('change', function () { eval(config.on_change); });
}

$('label[for=' + field_id + ']').on('click', function () { $('#' + field_id).select2('open'); });
$('#' + field_id).on('select2:open', function (e) {
const search_input = document.querySelector(`.select2-search__field[aria-controls='select2-${e.target.id}-results']`);
if (search_input) {
search_input.focus();
}
});

return select2_el;
}
33 changes: 30 additions & 3 deletions js/form_editor_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
* ---------------------------------------------------------------------
*/

/* global _, tinymce_editor_configs, getUUID, getRealInputWidth, sortable, tinymce, glpi_toast_error, bootstrap */
/* global _, tinymce_editor_configs, getUUID, getRealInputWidth, sortable, tinymce, glpi_toast_error, bootstrap, setupAjaxDropdown */

/**
* Client code to handle users actions on the form_editor template
Expand Down Expand Up @@ -430,7 +430,7 @@ class GlpiFormEditorController
}

// Format input name
const field = $(input).data("glpi-form-editor-original-name");
let field = $(input).data("glpi-form-editor-original-name");
let base_input_index = "";
if (type === "section") {
// The input is for the section itself
Expand All @@ -450,9 +450,15 @@ class GlpiFormEditorController
}

// Update input name
let postfix = "";
if (field.endsWith("[]")) {
field = field.slice(0, -2);
postfix = "[]";
}

$(input).attr(
"name",
base_input_index + `[${field}]`
base_input_index + `[${field}]${postfix}`
);
});
}
Expand Down Expand Up @@ -773,6 +779,9 @@ class GlpiFormEditorController
// Keep track of rich text editors that will need to be initialized
const tiny_mce_to_init = [];

// Keep track of select2 that will need to be initialized
const select2_to_init = [];

// Look for tiynmce editor to init
copy.find("textarea").each(function() {
// Get editor config for this field
Expand All @@ -798,6 +807,21 @@ class GlpiFormEditorController
window.tinymce_editor_configs[id] = config;
});

// Look for select2 to init
copy.find("select").each(function() {
const id = $(this).attr("id");
const config = window.select2_configs[id];

// Check if a select2 isn't already initialized
// and if a configuration is available
if (
$(this).hasClass("select2-hidden-accessible") === false
&& config !== undefined
) {
select2_to_init.push(config);
}
});

// Insert the new question
switch (action) {
case "append":
Expand All @@ -819,6 +843,9 @@ class GlpiFormEditorController
// Init the editors
tiny_mce_to_init.forEach((config) => tinyMCE.init(config));

// Init the select2
select2_to_init.forEach((config) => setupAjaxDropdown(config));

// Init tooltips
const tooltip_trigger_list = copy.find('[data-bs-toggle="tooltip"]');
[...tooltip_trigger_list].map(
Expand Down
16 changes: 11 additions & 5 deletions src/AbstractRightsDropdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ protected static function isTypeEnabled(string $type): bool
*
* @return string
*/
public static function show(string $name, array $values): string
public static function show(string $name, array $values, array $params = []): string
{
// Flatten values
$dropdown_values = [];
Expand All @@ -92,12 +92,18 @@ public static function show(string $name, array $values): string
$url = static::getAjaxUrl();

// Build params
$params = [
$params = array_merge([
'name' => $name . "[]",
'values' => $dropdown_values,
'valuesnames' => self::getValueNames($dropdown_values),
'multiple' => true,
];
], $params);

if ($params['multiple']) {
$params['values'] = $dropdown_values;
$params['valuesnames'] = self::getValueNames($dropdown_values);
} elseif (count($dropdown_values) > 0) {
$params['value'] = $dropdown_values[0];
$params['valuename'] = self::getValueNames($dropdown_values)[0];
}
return Html::jsAjaxDropdown($params['name'], $field_id, $url, $params);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Dropdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public static function show($itemtype, $options = [])
$params['readonly'] = false;
$params['parent_id_field'] = null;
$params['multiple'] = false;
$params['init'] = true;

if (is_array($options) && count($options)) {
foreach ($options as $key => $val) {
Expand Down Expand Up @@ -258,6 +259,7 @@ public static function show($itemtype, $options = [])
'order' => $params['order'] ?? null,
'parent_id_field' => $params['parent_id_field'],
'multiple' => $params['multiple'] ?? false,
'init' => $params['init'] ?? true,
];

if ($params['multiple']) {
Expand Down

0 comments on commit a878926

Please sign in to comment.