diff --git a/ajax/form/form_tags.php b/ajax/form/form_tags.php new file mode 100644 index 00000000000..b3d556a78bb --- /dev/null +++ b/ajax/form/form_tags.php @@ -0,0 +1,56 @@ +. + * + * --------------------------------------------------------------------- + */ + +use Glpi\Form\Form; + +include('../../inc/includes.php'); + +// The user must be able to respond to forms. +Session::checkRight(Form::$rightname, UPDATE); + +// Get tags +$tags = [ + [ + 'label' => 'Exemple tag 1', + ], + [ + 'label' => 'Exemple tag 2', + ], + [ + 'label' => 'Exemple tag 3', + ], +]; +header('Content-Type: application/json'); +echo json_encode($tags); diff --git a/css/includes/components/_richtext.scss b/css/includes/components/_richtext.scss index 6e571d96b68..1897ccbe779 100644 --- a/css/includes/components/_richtext.scss +++ b/css/includes/components/_richtext.scss @@ -39,6 +39,7 @@ body.mce-content-body { margin: 15px 10px; + [data-form-tag="true"], [data-user-mention="true"] { cursor: default !important; // Overrides "not-allowed" cursor on noneditable content } @@ -100,3 +101,9 @@ body.mce-content-body { border-radius: 3px; padding: 5px; } + +[data-form-tag="true"] { + background: rgba(0, 0, 0, 20%); + border-radius: 3px; + padding: 5px; +} diff --git a/js/RichText/FormTags.js b/js/RichText/FormTags.js new file mode 100644 index 00000000000..f4cd219d5b6 --- /dev/null +++ b/js/RichText/FormTags.js @@ -0,0 +1,106 @@ +/** + * --------------------------------------------------------------------- + * + * 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 . + * + * --------------------------------------------------------------------- + */ + +/* global tinymce */ + +var GLPI = GLPI || {}; +GLPI.RichText = GLPI.RichText || {}; + +/** + * Form tags rich text autocompleter. + * + * @since 11.0.0 + */ +GLPI.RichText.FormTags = class +{ + /** + * Target tinymce editor. + * @type {TinyMCE.Editor} + */ + #editor; + + /** + * @param {Editor} editor + */ + constructor(editor) { + this.#editor = editor; + } + + /** + * Register as autocompleter to editor. + * + * @returns {void} + */ + register() { + // Register autocompleter + this.#editor.ui.registry.addAutocompleter( + 'form_tags', + { + trigger: '#', + minChars: 0, + fetch: () => this.#fetchItems(), + onAction: (autocompleteApi, range, value) => { + this.#insertTag(autocompleteApi, range, value); + } + } + ); + } + + async #fetchItems() { + const url = CFG_GLPI.root_doc + '/ajax/form/form_tags.php'; + const data = await $.get(url); + + return data.map((tag) => ({ + type: 'autocompleteitem', + value: JSON.stringify(tag), + text: tag.label, + })); + } + + #insertTag(autocompleteApi, range, value) { + this.#editor.selection.setRng(range); + this.#editor.insertContent(this.#generateTagHtml(value)); + + autocompleteApi.hide(); + } + + #generateTagHtml(value) { + const tag = JSON.parse(value); + return ` + ${tag.label}  + `; + } +}; diff --git a/src/Form/Destination/CommonITILField/ContentField.php b/src/Form/Destination/CommonITILField/ContentField.php index c3834f3fbb0..8aeccf57e6b 100644 --- a/src/Form/Destination/CommonITILField/ContentField.php +++ b/src/Form/Destination/CommonITILField/ContentField.php @@ -69,6 +69,7 @@ public function renderConfigForm( options|merge({ 'enable_richtext': true, 'enable_images': false, + 'enable_form_tags': true, }) ) }} TWIG; diff --git a/src/Html.php b/src/Html.php index 79c877d9f6e..81b8cbb30d0 100644 --- a/src/Html.php +++ b/src/Html.php @@ -5876,6 +5876,7 @@ public static function requireJs($name) break; case 'tinymce': $_SESSION['glpi_js_toload'][$name][] = 'public/lib/tinymce.js'; + $_SESSION['glpi_js_toload'][$name][] = 'js/RichText/FormTags.js'; $_SESSION['glpi_js_toload'][$name][] = 'js/RichText/UserMention.js'; $_SESSION['glpi_js_toload'][$name][] = 'js/RichText/ContentTemplatesParameters.js'; break; diff --git a/src/RichText/RichText.php b/src/RichText/RichText.php index a7c62b38fc5..19e152979f8 100644 --- a/src/RichText/RichText.php +++ b/src/RichText/RichText.php @@ -591,6 +591,7 @@ private static function getHtmlSanitizer(): HtmlSanitizer // required for user mentions 'data-user-mention', 'data-user-id', + 'data-form-tag', ]; foreach ($rich_text_completion_attributes as $attribute) { $config = $config->allowAttribute($attribute, 'span'); diff --git a/templates/components/form/basic_inputs_macros.html.twig b/templates/components/form/basic_inputs_macros.html.twig index 7933c0b9e98..9e4cb47c178 100644 --- a/templates/components/form/basic_inputs_macros.html.twig +++ b/templates/components/form/basic_inputs_macros.html.twig @@ -308,6 +308,7 @@ 'toolbar_location': 'top', 'init': true, 'placeholder': "", + 'enable_form_tags': false, }|merge(options) %} {% if options.fields_template.isMandatoryField(name) %} @@ -340,6 +341,17 @@ ]) %} {% endif %} + {% if options.enable_form_tags %} + + {% endif %} + {% if options.enable_mentions and config('use_notifications') %}