From 5429efe64209b7cf85c4097ac2ce2077d6f6d978 Mon Sep 17 00:00:00 2001 From: Mathieu De Keyzer Date: Tue, 20 Feb 2024 09:43:24 +0100 Subject: [PATCH] refactor(bootstrap 5): date field types, textareas and some fixes (#772) --- EMS/admin-ui-bundle/_to_be_ref/js/core.js | 7 - .../js/editRevisionEventListeners.js | 112 -------------- EMS/admin-ui-bundle/_to_be_ref/js/initEms.js | 88 ----------- .../assets/css/core/components/form.scss | 7 + .../assets/js/core/components/modal.js | 30 +++- .../js/core/components/notifications.js | 11 +- EMS/admin-ui-bundle/assets/js/core/core.js | 8 +- .../assets/js/core/events/addedDomEvent.js | 6 +- .../assets/js/core/helpers/ajaxModal.js | 3 +- .../assets/js/core/plugins/button.js | 20 ++- .../js/core/plugins/collapsibleCollection.js | 28 ---- .../assets/js/core/plugins/collection.js | 88 +++++++++++ .../assets/js/core/plugins/datetime.js | 142 +++++++++++++++--- .../assets/js/core/plugins/form.js | 1 + .../assets/js/core/plugins/mediaLibrary.js | 6 +- .../assets/js/core/plugins/searchForm.js | 36 +++++ .../assets/js/edit-revision.js | 54 +++---- .../bootstrap5/data/edit-revision.html.twig | 10 +- .../bootstrap5/data/revisions-data.html.twig | 2 +- .../bootstrap5/elasticsearch/search.html.twig | 2 +- .../elements/object-views-button.html.twig | 16 +- .../bootstrap5/elements/post-button.html.twig | 2 +- .../elements/revision-toolbar.html.twig | 24 +-- .../bootstrap5/elements/toasts.html.twig | 8 +- .../views/bootstrap5/form/fields.html.twig | 33 ++-- .../macros/data-field-type.html.twig | 8 +- .../src/Form/DataField/DateFieldType.php | 10 +- .../src/Form/DataField/DateRangeFieldType.php | 20 ++- .../src/Form/DataField/DateTimeFieldType.php | 17 ++- .../src/Form/DataField/TimeFieldType.php | 6 +- .../src/Form/Form/RevisionType.php | 4 +- EMS/core-bundle/src/Twig/AppExtension.php | 21 ++- 32 files changed, 432 insertions(+), 398 deletions(-) delete mode 100644 EMS/admin-ui-bundle/_to_be_ref/js/initEms.js create mode 100644 EMS/admin-ui-bundle/assets/css/core/components/form.scss delete mode 100644 EMS/admin-ui-bundle/assets/js/core/plugins/collapsibleCollection.js create mode 100644 EMS/admin-ui-bundle/assets/js/core/plugins/collection.js create mode 100644 EMS/admin-ui-bundle/assets/js/core/plugins/searchForm.js diff --git a/EMS/admin-ui-bundle/_to_be_ref/js/core.js b/EMS/admin-ui-bundle/_to_be_ref/js/core.js index 553f32b9d..4f1383c75 100644 --- a/EMS/admin-ui-bundle/_to_be_ref/js/core.js +++ b/EMS/admin-ui-bundle/_to_be_ref/js/core.js @@ -1,6 +1,5 @@ window.ems_wysiwyg_type_filters = JSON.parse(document.querySelector("BODY").getAttribute('data-wysiwyg-type-filters')); -require('admin-lte/plugins/timepicker/bootstrap-timepicker'); require('chart.js'); require('fastclick'); require('flot'); @@ -11,12 +10,8 @@ require('jquery-sparkline'); require('moment'); require('pace'); require('raphael'); -require('select2/dist/js/select2.full'); require('slimscroll'); -require('bootstrap-datepicker'); -require('daterangepicker'); require('fullcalendar'); -require('jquery-match-height'); //Fix issue CK editor in bootstrap model //https://ckeditor.com/old/forums/Support/Issue-with-Twitter-Bootstrap#comment-127719 @@ -31,5 +26,3 @@ $.fn.modal.Constructor.prototype.enforceFocus = function() { }) }; -require('./initEms'); - diff --git a/EMS/admin-ui-bundle/_to_be_ref/js/editRevisionEventListeners.js b/EMS/admin-ui-bundle/_to_be_ref/js/editRevisionEventListeners.js index 274111039..5c3d8ceb2 100644 --- a/EMS/admin-ui-bundle/_to_be_ref/js/editRevisionEventListeners.js +++ b/EMS/admin-ui-bundle/_to_be_ref/js/editRevisionEventListeners.js @@ -1,57 +1,4 @@ -import EmsListeners from "./EmsListeners"; -import {CKEditorConfig} from "./CKEditorConfig"; - -let ckconfig = false; - function editRevisionEventListeners(target, onChangeCallback = null){ - new EmsListeners(target.get(0), onChangeCallback); - - if (false === ckconfig) { - ckconfig = new CKEditorConfig().getConfig() - } - - target.find('.remove-content-button').on('click', function(e) { - // prevent the link from creating a "#" on the URL - e.preventDefault(); - - const panel = $(this).closest('.collection-item-panel'); - panel.find('input._ems_internal_deleted').val('deleted'); - panel.hide(); - - if (onChangeCallback) { - onChangeCallback(); - } - }); - - target.find('.add-content-button').on('click', function(e) { - // prevent the link from creating a "#" on the URL - e.preventDefault(); - - const panel = $(this).closest('.collection-panel'); - const index = panel.data('index'); - const prototype = panel.data('prototype'); - const prototypeName = new RegExp(panel.data('prototype-name'), "g"); - const prototypeLabel = new RegExp(panel.data('prototype-label'), "g"); - - // Replace '__label__name__$fieldId__' in the prototype's HTML to - // Replace '__name__$fieldId__' in the prototype's HTML to - // instead be a number based on how many items we have - const newForm = $(prototype.replace(prototypeLabel, (index+1)).replace(prototypeName, index)); - // increase the index with one for the next item - panel.data('index', (index + 1)); - - editRevisionEventListeners(newForm); - - panel.children('.panel-body').children('.collection-panel-container').append(newForm); - - if (onChangeCallback) { - onChangeCallback(); - } - }); - - target.find('.ems-sortable > div').sortable({ - handle: ".ems-handle" - }); target.find(".ckeditor_ems").each(function(){ @@ -177,65 +124,6 @@ function editRevisionEventListeners(target, onChangeCallback = null){ }); } }); - - target.find(".timepicker").each(function(){ - - const settings = { - showMeridian: $( this ).data('show-meridian'), - explicitMode: $( this ).data('explicit-mode'), - minuteStep: $( this ).data('minute-step'), - disableMousewheel: true, - defaultTime: false - }; - - $( this ).unbind( "change" ); - - if ($(this).not('.ignore-ems-update')) { - if (onChangeCallback) { - $( this ).timepicker(settings).on('changeTime.timepicker', onChangeCallback); - } - } else { - $( this ).timepicker(settings); - } - }); - - - target.find('.datepicker').each(function( ) { - - $(this).unbind('change'); - const params = { - format: $(this).attr('data-date-format'), - todayBtn: true, - weekStart: $(this).attr('data-week-start'), - daysOfWeekHighlighted: $(this).attr('data-days-of-week-highlighted'), - daysOfWeekDisabled: $(this).attr('data-days-of-week-disabled'), - todayHighlight: $(this).attr('data-today-highlight') - }; - - if($(this).attr('data-multidate') && $(this).attr('data-multidate') !== 'false'){ - params.multidate = true; - } - - $(this).datepicker(params); - - if (onChangeCallback) { - $(this).not(".ignore-ems-update").on('dp.change', onChangeCallback); - } - }); - - target.find('.ems_daterangepicker').each(function( ) { - - const options = $(this).data('display-option'); - $(this).unbind('change'); - - if ($(this).not('.ignore-ems-update')) { - if (onChangeCallback) { - $(this).daterangepicker(options, function() { onChangeCallback(); }); - } - } else { - $(this).daterangepicker(options); - } - }); } export {editRevisionEventListeners}; diff --git a/EMS/admin-ui-bundle/_to_be_ref/js/initEms.js b/EMS/admin-ui-bundle/_to_be_ref/js/initEms.js deleted file mode 100644 index 029f21f19..000000000 --- a/EMS/admin-ui-bundle/_to_be_ref/js/initEms.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict'; - -/* - * This function initialized the elasticms admin interface - * - */ -import EmsListeners from "./EmsListeners"; -import ajaxModal from "../../js/core/helpers/ajaxModal"; - -(function(factory) { - "use strict"; - - if ( typeof define === "function" && define.amd ) { - // AMD. Register as an anonymous module. - define([ - "jquery", - ], factory ); - } else { - // Browser globals - factory( window.jQuery ); - } - -}(function($) { - - function closeModalNotification() { - $('#modal-notification-close-button').on('click', function(){ - $('#modal-notifications .modal-body').empty(); - $('#modal-notifications').modal('hide'); - }); - } - - function toggleMenu() { - $('.toggle-button').on('click', function(){ - const toggleTex = $(this).data('toggle-contain'); - const text=$(this).html(); - $(this).html(toggleTex); - $(this).data('toggle-contain', text); - }); - } - - function initSearchForm() { - - $('#add-search-filter-button').on('click', function(e) { - // prevent the link to scroll to the top ("#" anchor) - e.preventDefault(); - - const $listFilters = $('#list-of-search-filters'); - const prototype = $listFilters.data('prototype'); - const index = $listFilters.data('index'); - // Replace '__name__' in the prototype's HTML to - // instead be a number based on how many items we have - const newForm = $(prototype.replace(/__name__/g, index)); - - // increase the index with one for the next item - $listFilters.data('index', index + 1); - - //attach listeners to the new DOM element - new EmsListeners(newForm.get(0)); - $listFilters.append(newForm); - - }); - } - - function intAjaxModalLinks() { - let ajaxModalLinks = document.querySelectorAll('a[data-ajax-modal-url]'); - [].forEach.call(ajaxModalLinks, function (link) { - link.onclick = (event) => { - ajaxModal.load({ - url: event.target.dataset.ajaxModalUrl, - size: event.target.dataset.ajaxModalSize - }, (json) => { - if (json.hasOwnProperty('success') && json.success === true) { - location.reload(); - } - }); - } - }); - } - - - $(document).ready(function() { - closeModalNotification(); - toggleMenu(); - initSearchForm(); - intAjaxModalLinks(); - }); - -})); diff --git a/EMS/admin-ui-bundle/assets/css/core/components/form.scss b/EMS/admin-ui-bundle/assets/css/core/components/form.scss new file mode 100644 index 000000000..1ad3f590a --- /dev/null +++ b/EMS/admin-ui-bundle/assets/css/core/components/form.scss @@ -0,0 +1,7 @@ +form { + div.has-error { + border-color: var(--bs-form-invalid-border-color); + border-style: solid; + border-width: 1px; + } +} diff --git a/EMS/admin-ui-bundle/assets/js/core/components/modal.js b/EMS/admin-ui-bundle/assets/js/core/components/modal.js index e8ccecedf..412953d41 100644 --- a/EMS/admin-ui-bundle/assets/js/core/components/modal.js +++ b/EMS/admin-ui-bundle/assets/js/core/components/modal.js @@ -1,18 +1,44 @@ 'use strict' +import $ from 'jquery' import queryString from '../helpers/queryString' -import { Modal as BSModal } from 'bootstrap' +import ajaxModal from '../../../js/core/helpers/ajaxModal' export default class Modal { constructor () { this.autoOpenModal() + this.closeModalNotification() + this.intAjaxModalLinks() } autoOpenModal () { const queryStringObject = queryString() if (queryStringObject.open) { const modalElement = document.getElementById(`content_type_structure_fieldType${queryStringObject.open}`) - const modal = BSModal.getOrCreateInstance(modalElement) + const modal = window.bootstrap.Modal.getOrCreateInstance(modalElement) modal.show() } } + + closeModalNotification () { + $('#modal-notification-close-button').on('click', function () { + $('#modal-notifications .modal-body').empty() + $('#modal-notifications').modal('hide') + }) + } + + intAjaxModalLinks () { + const ajaxModalLinks = document.querySelectorAll('a[data-ajax-modal-url]'); + [].forEach.call(ajaxModalLinks, function (link) { + link.onclick = (event) => { + ajaxModal.load({ + url: event.target.dataset.ajaxModalUrl, + size: event.target.dataset.ajaxModalSize + }, (json) => { + if (Object.prototype.hasOwnProperty.call(json, 'success') && json.success === true) { + location.reload() + } + }) + } + }) + } } diff --git a/EMS/admin-ui-bundle/assets/js/core/components/notifications.js b/EMS/admin-ui-bundle/assets/js/core/components/notifications.js index 1723e949c..9cd2733ec 100644 --- a/EMS/admin-ui-bundle/assets/js/core/components/notifications.js +++ b/EMS/admin-ui-bundle/assets/js/core/components/notifications.js @@ -1,8 +1,11 @@ -import { Toast, Modal } from 'bootstrap' - class Notifications { constructor () { this.counter = 0 + const toasts = document.querySelectorAll('.toast') + for (let i = 0; i < toasts.length; ++i) { + const toast = new window.bootstrap.Toast(toasts[i]) + toast.show() + } } startActivity () { @@ -75,7 +78,7 @@ class Notifications { const toaster = document.getElementById('toaster') toaster.insertAdjacentElement('beforeend', div) - const toast = new Toast(div, { + const toast = new window.bootstrap.Toast(div, { animation: true, autohide: autoHide, delay: 5000 @@ -85,7 +88,7 @@ class Notifications { outOfSync () { const outOfSync = document.getElementById('data-out-of-sync') - const modal = new Modal(outOfSync, { + const modal = new window.bootstrap.Modal(outOfSync, { keyboard: false, backdrop: 'static' }) diff --git a/EMS/admin-ui-bundle/assets/js/core/core.js b/EMS/admin-ui-bundle/assets/js/core/core.js index 6f56d5edd..19ed7a60f 100644 --- a/EMS/admin-ui-bundle/assets/js/core/core.js +++ b/EMS/admin-ui-bundle/assets/js/core/core.js @@ -1,7 +1,7 @@ import Button from './plugins/button' import Choice from './plugins/choice' import CodeEditor from './plugins/codeEditor' -import CollapsibleCollection from './plugins/collapsibleCollection' +import Collection from './plugins/Collection' import Datatable from './plugins/datatable' import Datetime from './plugins/datetime' import File from './plugins/file' @@ -14,6 +14,7 @@ import JsonMenuNested from './plugins/jsonMenuNested' import MediaLibrary from './plugins/mediaLibrary' import NestedSortable from './plugins/nestedSortable' import ObjectPicker from './plugins/objectPicker' +import SearchForm from './plugins/searchForm' import Select from './plugins/select' import SortableList from './plugins/sortableList' import SymfonyCollection from './plugins/symfonyCollection' @@ -36,7 +37,7 @@ class Core { new Button(), new Choice(), new CodeEditor(), - new CollapsibleCollection(), + new Collection(), new Datatable(), new Datetime(), new File(), @@ -49,6 +50,7 @@ class Core { new MediaLibrary(), new NestedSortable(), new ObjectPicker(), + new SearchForm(), new Select(), new SortableList(), new SymfonyCollection(), @@ -56,7 +58,7 @@ class Core { new Tooltip(), new WYSIWYG() ] - document.addEventListener(EMS_ADDED_DOM_EVENT, (event) => this.load(event.target)) + document.addEventListener(EMS_ADDED_DOM_EVENT, (event) => this.load(event.detail.target)) this.coreReady() } diff --git a/EMS/admin-ui-bundle/assets/js/core/events/addedDomEvent.js b/EMS/admin-ui-bundle/assets/js/core/events/addedDomEvent.js index 14172191d..d5ed3cece 100644 --- a/EMS/admin-ui-bundle/assets/js/core/events/addedDomEvent.js +++ b/EMS/admin-ui-bundle/assets/js/core/events/addedDomEvent.js @@ -1,7 +1,11 @@ export const EMS_ADDED_DOM_EVENT = 'emsAddedDomEvent' export class AddedDomEvent { constructor (target) { - this._event = new CustomEvent(EMS_ADDED_DOM_EVENT, { target }) + this._event = new CustomEvent(EMS_ADDED_DOM_EVENT, { + detail: { + target + } + }) this._target = target } diff --git a/EMS/admin-ui-bundle/assets/js/core/helpers/ajaxModal.js b/EMS/admin-ui-bundle/assets/js/core/helpers/ajaxModal.js index 27182e254..cc9a02272 100644 --- a/EMS/admin-ui-bundle/assets/js/core/helpers/ajaxModal.js +++ b/EMS/admin-ui-bundle/assets/js/core/helpers/ajaxModal.js @@ -1,13 +1,12 @@ import $ from 'jquery' import { AddedDomEvent } from '../events/addedDomEvent' import { tooltipDataLinks } from './tooltip' -import { Modal } from 'bootstrap' class AjaxModal { constructor (selector) { this.selector = selector this.$modal = $(selector) - this.bsModal = new Modal(document.querySelector(selector)) + this.bsModal = new window.bootstrap.Modal(document.querySelector(selector)) this.modal = document.querySelector(this.selector) if (this.modal) { diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/button.js b/EMS/admin-ui-bundle/assets/js/core/plugins/button.js index 67211fe78..300098056 100644 --- a/EMS/admin-ui-bundle/assets/js/core/plugins/button.js +++ b/EMS/admin-ui-bundle/assets/js/core/plugins/button.js @@ -7,6 +7,7 @@ export default class Button { this.addDisabledButtonTreatListeners(target) this.addRequestNotificationListeners(target) this.addPostButtonListeners(target) + this.addToggleButtonListeners(target) } addRemoveButtonListeners (target) { @@ -15,12 +16,6 @@ export default class Button { event.preventDefault() $(this).closest('li').remove() }) - - $(target).find('.remove-filter') - .on('click', function (event) { - event.preventDefault() - $(this).closest('.filter-container').remove() - }) } addDisabledButtonTreatListeners (target) { @@ -94,4 +89,17 @@ export default class Button { }) } } + + addToggleButtonListeners (target) { + const buttons = target.querySelectorAll('[data-bs-toggle-contain].toggle-button') + for (let i = 0; i < buttons.length; ++i) { + const button = buttons[i] + button.addEventListener('click', function () { + const toggleText = button.dataset.bsToggleContain + const previousText = button.innerHTML + button.innerHTML = toggleText + button.dataset.bsToggleContain = previousText + }) + } + } } diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/collapsibleCollection.js b/EMS/admin-ui-bundle/assets/js/core/plugins/collapsibleCollection.js deleted file mode 100644 index aef7638bb..000000000 --- a/EMS/admin-ui-bundle/assets/js/core/plugins/collapsibleCollection.js +++ /dev/null @@ -1,28 +0,0 @@ -import $ from 'jquery' - -export default class CollapsibleCollection { - load (target) { - $(target).find('.collapsible-collection') - .on('click', '.button-collapse', function () { - const $isExpanded = ($(this).attr('aria-expanded') === 'true') - $(this).parent().find('button').attr('aria-expanded', !$isExpanded) - - const panel = $(this).closest('.panel') - panel.find('.collapse').first().collapse('toggle') - }) - .on('click', '.button-collapse-all', function () { - const $isExpanded = ($(this).attr('aria-expanded') === 'true') - $(this).parent().find('button').attr('aria-expanded', !$isExpanded) - - const panel = $(this).closest('.panel') - panel.find('.button-collapse').attr('aria-expanded', !$isExpanded) - panel.find('.button-collapse-all').attr('aria-expanded', !$isExpanded) - - if (!$isExpanded) { - panel.find('.collapse').collapse('show') - } else { - panel.find('.collapse').collapse('hide') - } - }) - } -} diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/collection.js b/EMS/admin-ui-bundle/assets/js/core/plugins/collection.js new file mode 100644 index 000000000..a39c6193f --- /dev/null +++ b/EMS/admin-ui-bundle/assets/js/core/plugins/collection.js @@ -0,0 +1,88 @@ +import $ from 'jquery' +import { AddedDomEvent } from '../events/addedDomEvent' +import { ChangeEvent } from '../events/changeEvent' +require('jquery-ui') +require('jquery-ui/ui/widgets/sortable') + +class Collection { + load (target) { + this.initSortable(target) + this.addAddButtonListeners(target) + this.addRemoveButtonListeners(target) + this.addCollapsibleListeners(target) + } + + initSortable (target) { + $(target).find('.ems-sortable > div').sortable({ + handle: '.ems-handle' + }) + } + + addAddButtonListeners (target) { + $(target).find('.add-content-button').on('click', function (e) { + // prevent the link from creating a "#" on the URL + e.preventDefault() + + const panel = $(this).closest('.collection-panel') + const index = panel.data('index') + const prototype = panel.data('prototype') + const prototypeName = new RegExp(panel.data('prototype-name'), 'g') + const prototypeLabel = new RegExp(panel.data('prototype-label'), 'g') + + // Replace '__label__name__$fieldId__' in the prototype's HTML to + // Replace '__name__$fieldId__' in the prototype's HTML to + // instead be a number based on how many items we have + const newForm = $(prototype.replace(prototypeLabel, (index + 1)).replace(prototypeName, index)) + // increase the index with one for the next item + panel.data('index', (index + 1)) + + panel.children('.panel-body').children('.collection-panel-container').append(newForm) + const addedDomEvent = new AddedDomEvent(newForm.get(0)) + addedDomEvent.dispatch() + + const changeEvent = new ChangeEvent(this) + changeEvent.dispatch() + }) + } + + addRemoveButtonListeners (target) { + $(target).find('.remove-content-button').on('click', function (e) { + // prevent the link from creating a "#" on the URL + e.preventDefault() + + const panel = $(this).closest('.collection-item-panel') + panel.find('input._ems_internal_deleted').val('deleted') + panel.hide() + + const event = new ChangeEvent(this) + event.dispatch() + }) + } + + addCollapsibleListeners (target) { + $(target).find('.collapsible-collection') + .on('click', '.button-collapse', function () { + const $isExpanded = ($(this).attr('aria-expanded') === 'true') + $(this).parent().find('button').attr('aria-expanded', !$isExpanded) + + const panel = $(this).closest('.panel') + panel.find('.collapse').first().collapse('toggle') + }) + .on('click', '.button-collapse-all', function () { + const $isExpanded = ($(this).attr('aria-expanded') === 'true') + $(this).parent().find('button').attr('aria-expanded', !$isExpanded) + + const panel = $(this).closest('.panel') + panel.find('.button-collapse').attr('aria-expanded', !$isExpanded) + panel.find('.button-collapse-all').attr('aria-expanded', !$isExpanded) + + if (!$isExpanded) { + panel.find('.collapse').collapse('show') + } else { + panel.find('.collapse').collapse('hide') + } + }) + } +} + +export default Collection diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/datetime.js b/EMS/admin-ui-bundle/assets/js/core/plugins/datetime.js index bcee14682..c3fbf7e8f 100644 --- a/EMS/admin-ui-bundle/assets/js/core/plugins/datetime.js +++ b/EMS/admin-ui-bundle/assets/js/core/plugins/datetime.js @@ -6,37 +6,133 @@ class Datetime { #iframes = [] load (target) { - const datetimePickers = target.querySelectorAll('.datetime-picker') - for (let i = 0; i < datetimePickers.length; i++) { - const picker = new TempusDominus(datetimePickers[i], { - display: { - buttons: { - today: true, - clear: true, - close: true - } - }, - localization: { - format: datetimePickers[i].dataset.dateFormat, - startOfTheWeek: 1 - }, - restrictions: { - daysOfWeekDisabled: JSON.parse(datetimePickers[i].dataset.dateDaysOfWeekDisabled), - disabledHours: JSON.parse(datetimePickers[i].dataset.dateDisabledHours) + this.loadDatetime(target) + this.loadDate(target) + this.loadDateRange(target) + this.loadTime(target) + } + + loadTime (target) { + const options = this.defaultOptions() + options.display.components.calendar = false + this.loadPicker(target, '.timepicker', options) + } + + loadDateRange (target) { + const options = this.defaultOptions() + options.dateRange = true + options.multipleDatesSeparator = ' - ' + this.loadPicker(target, '.ems_daterangepicker', options) + } + + loadDate (target) { + const options = this.defaultOptions() + options.display.components.clock = false + options.multipleDatesSeparator = ',' + this.loadPicker(target, '.datepicker', options) + } + + loadDatetime (target) { + const options = this.defaultOptions() + this.loadPicker(target, '.datetime-picker', options) + } + + loadPicker (target, query, options) { + const pickers = target.querySelectorAll(query) + for (let i = 0; i < pickers.length; i++) { + if (pickers[i].dataset.multidate) { + options.multipleDates = pickers[i].dataset.multidate + } + if (pickers[i].dataset.weekStart) { + options.localization.startOfTheWeek = pickers[i].dataset.weekStart + } + if (pickers[i].dataset.dateFormat) { + options.localization.format = pickers[i].dataset.dateFormat + } + if (pickers[i].dataset.daysOfWeekDisabled) { + options.restrictions.daysOfWeekDisabled = JSON.parse(pickers[i].dataset.daysOfWeekDisabled) + } + if (pickers[i].dataset.dateDaysOfWeekDisabled) { + options.restrictions.daysOfWeekDisabled = JSON.parse(pickers[i].dataset.dateDaysOfWeekDisabled) + } + if (pickers[i].dataset.dateDisabledHours) { + options.restrictions.disabledHours = JSON.parse(pickers[i].dataset.dateDisabledHours) + } + if (undefined !== pickers[i].dataset.showMeridian) { + let format + if (pickers[i].dataset.showMeridian === 'true') { + format = 'h:mm' + options.localization.hourCycle = 'h12' + } else { + format = 'H:mm' + options.localization.hourCycle = 'h23' } - }) - if (datetimePickers[i].dataset.dateLocale) { - picker.locale(datetimePickers[i].dataset.dateLocale) + if (pickers[i].dataset.showSeconds) { + format += ':ss' + options.display.components.seconds = true + } + if (pickers[i].dataset.showMeridian === 'true') { + format += ' T' + } + options.localization.format = format } - datetimePickers[i].addEventListener('change.td', function () { - if (datetimePickers[i].classList.contains('ignore-ems-update')) { + if (pickers[i].dataset.displayOption) { + const displayOptions = JSON.parse(pickers[i].dataset.displayOption) + if (undefined !== displayOptions.locale.firstDay) { + options.localization.startOfTheWeek = displayOptions.locale.firstDay + } + if (undefined !== displayOptions.locale.format) { + options.localization.format = displayOptions.locale.format + } + if (undefined !== displayOptions.timePicker) { + options.display.components.clock = displayOptions.timePicker + } + if (undefined !== displayOptions.timePicker24Hour && displayOptions.timePicker24Hour) { + options.localization.hourCycle = 'h23' + } else { + options.localization.hourCycle = 'h12' + } + if (undefined !== displayOptions.showWeekNumbers && displayOptions.showWeekNumbers) { + options.display.calendarWeeks = true + } + if (undefined !== displayOptions.timePickerIncrement) { + options.stepping = displayOptions.timePickerIncrement + } + } + if (pickers[i].dataset.minuteStep) { + options.stepping = JSON.parse(pickers[i].dataset.minuteStep) + } + const picker = new TempusDominus(pickers[i], options) + if (pickers[i].dataset.dateLocale) { + picker.locale(pickers[i].dataset.dateLocale) + } + pickers[i].addEventListener('change.td', function () { + if (pickers[i].classList.contains('ignore-ems-update')) { return } - const event = new ChangeEvent(datetimePickers[i]) + const event = new ChangeEvent(pickers[i]) event.dispatch() }) } } + + defaultOptions () { + return { + display: { + buttons: { + today: true, + clear: true, + close: true + }, + components: { + } + }, + localization: { + startOfTheWeek: 1 + }, + restrictions: {} + } + } } export default Datetime diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/form.js b/EMS/admin-ui-bundle/assets/js/core/plugins/form.js index fd7362861..2add961b8 100644 --- a/EMS/admin-ui-bundle/assets/js/core/plugins/form.js +++ b/EMS/admin-ui-bundle/assets/js/core/plugins/form.js @@ -2,6 +2,7 @@ import $ from 'jquery' import ajaxRequest from '../components/ajaxRequest' import ChangeEvent from '../events/changeEvent' import { EMS_CTRL_SAVE_EVENT } from '../events/ctrlSaveEvent' +import '../../../css/core/components/form.scss' class Form { load (target) { diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/mediaLibrary.js b/EMS/admin-ui-bundle/assets/js/core/plugins/mediaLibrary.js index 9313dffdc..ce1dd28b4 100644 --- a/EMS/admin-ui-bundle/assets/js/core/plugins/mediaLibrary.js +++ b/EMS/admin-ui-bundle/assets/js/core/plugins/mediaLibrary.js @@ -3,18 +3,18 @@ import Component from '../components/mediaLibrary' class MediaLibrary { constructor () { this.components = [] + this.bodyData = document.querySelector('body').dataset } load (target) { const elements = target.getElementsByClassName('media-lib') - const bodyData = target.querySelector('body').dataset const self = this; [].forEach.call(elements, function (el) { self.components.push(new Component(el, { urlMediaLib: '/component/media-lib', - urlInitUpload: bodyData.initUpload, - hashAlgo: bodyData.hashAlgo + urlInitUpload: this.bodyData.initUpload, + hashAlgo: this.bodyData.hashAlgo })) }) } diff --git a/EMS/admin-ui-bundle/assets/js/core/plugins/searchForm.js b/EMS/admin-ui-bundle/assets/js/core/plugins/searchForm.js new file mode 100644 index 000000000..4513ec8eb --- /dev/null +++ b/EMS/admin-ui-bundle/assets/js/core/plugins/searchForm.js @@ -0,0 +1,36 @@ +import $ from 'jquery' +import { AddedDomEvent } from '../events/addedDomEvent' + +class SearchForm { + constructor () { + $('#add-search-filter-button').on('click', function (e) { + // prevent the link to scroll to the top ("#" anchor) + e.preventDefault() + + const $listFilters = $('#list-of-search-filters') + const prototype = $listFilters.data('prototype') + const index = $listFilters.data('index') + // Replace '__name__' in the prototype's HTML to + // instead be a number based on how many items we have + const newForm = $(prototype.replace(/__name__/g, index)) + + // increase the index with one for the next item + $listFilters.data('index', index + 1) + + console.log(newForm.get(0)) + const addedDomEvent = new AddedDomEvent(newForm.get(0)) + addedDomEvent.dispatch() + $listFilters.append(newForm) + }) + } + + load (target) { + $(target).find('.remove-filter') + .on('click', function (event) { + event.preventDefault() + $(this).closest('.filter-container').remove() + }) + } +} + +export default SearchForm diff --git a/EMS/admin-ui-bundle/assets/js/edit-revision.js b/EMS/admin-ui-bundle/assets/js/edit-revision.js index 9135739ac..2a92ff3e1 100644 --- a/EMS/admin-ui-bundle/assets/js/edit-revision.js +++ b/EMS/admin-ui-bundle/assets/js/edit-revision.js @@ -91,6 +91,14 @@ function updateChoiceFieldTypes () { }) } +function createInvalidFeedback (message) { + const invalidFeedback = document.createElement('DIV') + invalidFeedback.textContent = message + invalidFeedback.classList.add('d-block') + invalidFeedback.classList.add('invalid-feedback') + return invalidFeedback +} + function onChange (allowAutoPublish = false) { if (updateMode === 'disabled') { // console.log('No way to save a finalized revision!'); @@ -126,12 +134,11 @@ function onChange (allowAutoPublish = false) { $('.invalid-feedback').html('') $(response.formErrors).each(function (index, item) { let target = item.propertyPath - let targetElement = document.getElementById(target) + let targetElement = document.getElementById(`${target}_value`) if (targetElement === null) { - targetElement = document.getElementById(`${target}_value`) - if (targetElement !== null) { - target = `${target}_value` - } + targetElement = document.getElementById(target) + } else { + target = `${target}_value` } if (targetElement !== null) { switch (targetElement.nodeName) { @@ -141,10 +148,12 @@ function onChange (allowAutoPublish = false) { if (previousElement !== null && previousElement.classList.contains('invalid-feedback') && item.message) { $(previousElement).html(item.message) } else { - console.log(targetElement) + const invalidFeedback = createInvalidFeedback(item.message) + targetElement.parentNode.insertBefore(invalidFeedback, targetElement) } break } + case 'TEXTAREA': case 'INPUT': { targetElement.classList.add('is-invalid') const label = document.querySelector(`label[for=${target}]`) @@ -157,7 +166,8 @@ function onChange (allowAutoPublish = false) { if (invalidFeedback !== null) { invalidFeedback.textContent = item.message } else { - console.log(targetElement) + const invalidFeedback = createInvalidFeedback(item.message) + parent.appendChild(invalidFeedback) } } else { console.log(targetElement) @@ -172,36 +182,6 @@ function onChange (allowAutoPublish = false) { } else { console.log(item) } - - // const targetLabel = $('#' + target + '__label') - // const targetError = $('#' + target + '__error') - // - // const propPath = $('#' + item.propertyPath + '_value') - // if (propPath.length && propPath.prop('nodeName') === 'TEXTAREA') { - // target = item.propertyPath + '_value' - // } - - // const targetParent = $('#' + target) - // if (targetLabel.length) { - // targetLabel.closest('div.form-group').addClass('has-error') - // if (item.message && targetError.length > 0) { - // targetError.addClass('has-error') - // if ($('#' + target + '__error span.help-block').length === 0) { - // targetError.append('') - // } - // $('#' + target + '__error' + ' span.help-block ul.list-unstyled').append('
  • ' + item.message + '
  • ') - // } - // } else { - // $('#' + target).closest('div.form-group').addClass('has-error') - // targetParent.parents('.form-group').addClass('has-error') - // if (item.message) { - // if (targetParent.parents('.form-group').find(' span.help-block').length === 0) { - // targetParent.parent('.form-group').append('') - // } else { - // targetParent.parents('.form-group').find(' span.help-block ul.list-unstyled').append('
  • ' + item.message + '
  • ') - // } - // } - // } }) }) .always(function () { diff --git a/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/data/edit-revision.html.twig b/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/data/edit-revision.html.twig index d9ccc79a8..afff8ee92 100644 --- a/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/data/edit-revision.html.twig +++ b/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/data/edit-revision.html.twig @@ -38,15 +38,19 @@ diff --git a/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/revision-toolbar.html.twig b/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/revision-toolbar.html.twig index e3b109b34..8769daf5e 100644 --- a/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/revision-toolbar.html.twig +++ b/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/revision-toolbar.html.twig @@ -35,7 +35,7 @@ @@ -94,13 +94,13 @@ {% if draft %}
  • {% include '@EMSAdminUI/bootstrap5/elements/get-button.html.twig' with { 'url': path('emsco_edit_revision', {'revisionId': revisionId}), - 'btnClass': '', + 'btnClass': 'dropdown-item', 'label': 'views.elements.revision-toolbar-html.edit-draft-label'|trans, 'icon': 'pencil' }%}
  • {% if autoSave %}
  • {% include '@EMSAdminUI/bootstrap5/elements/post-button.html.twig' with { 'url': path('revision.cancel', {'revision': revisionId}), - 'btnClass': '', + 'btnClass': 'dropdown-item', 'label': 'views.elements.revision-toolbar-html.cancel-last-updates-label'|trans, 'icon': 'remove' }%}
  • @@ -109,21 +109,21 @@ {% if is_granted('ROLE_PUBLISHER') and revision.id|default(false) %}
  • {% include '@EMSAdminUI/bootstrap5/elements/get-button.html.twig' with { 'url': path('emsco_pick_a_release', {revision: revision.id}), - 'btnClass': '', + 'btnClass': 'dropdown-item', 'label': 'views.elements.revision-toolbar-html.add-to-release'|trans(), - 'icon': 'glyphicon glyphicon-pushpin' }%}
  • + 'icon': 'fa fa-map-pin' }%} {% endif %} {% if is_granted('ROLE_SUPER') and instance.contentType.environment not in environmentsRevision.environments %}
  • {% include '@EMSAdminUI/bootstrap5/elements/get-button.html.twig' with { 'url': path('emsco_edit_revision', {'revisionId': revisionId}), - 'btnClass': ' ', + 'btnClass': 'dropdown-item', 'label': 'views.elements.revision-toolbar-html.edit-revision-label'|trans, 'icon': 'pencil' }%}
  • {% endif %} {% if autoSave %}
  • {% include '@EMSAdminUI/bootstrap5/elements/post-button.html.twig' with { 'url': path('revision.cancel', {'revision': revisionId}), - 'btnClass': '', + 'btnClass': 'dropdown-item', 'message': 'views.elements.revision-toolbar-html.cancel-last-updates-message'|trans, 'label': 'views.elements.revision-toolbar-html.cancel-last-updates-label'|trans, 'icon': 'remove' @@ -131,7 +131,7 @@ {% endif %}
  • {% include '@EMSAdminUI/bootstrap5/elements/post-button.html.twig' with { 'url': path('revision.revert', {'id': revisionId}), - 'btnClass': '', + 'btnClass': 'dropdown-item', 'label': 'views.elements.revision-toolbar-html.revert-revision-label'|trans, 'icon': 'undo' }%}
  • {% endif %} @@ -144,7 +144,7 @@ 'compareId': rev.id < revision.id ? rev.id :revision.id, 'page': page }), - 'btnClass': '', + 'btnClass': 'dropdown-item', 'label': 'views.elements.revision-toolbar-html.compare-label'|trans, 'icon': 'compress' }%} {% endif %} @@ -164,7 +164,7 @@ @@ -179,7 +179,7 @@ @@ -194,7 +194,7 @@ diff --git a/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/toasts.html.twig b/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/toasts.html.twig index 281cdb79b..1b914cdf0 100644 --- a/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/toasts.html.twig +++ b/EMS/admin-ui-bundle/src/Resources/views/bootstrap5/elements/toasts.html.twig @@ -3,15 +3,15 @@
    {%- set types = { - 'error' : { 'class': 'bg-danger', 'icon': 'fa-ban' }, - 'warning' : { 'class': 'bg-warning', 'icon': 'fa-warning' }, - 'notice' : { 'class': 'bg-info', 'icon': 'fa-info' }, + 'error' : { 'class': 'bg-danger', 'icon': 'fa-ban', 'delay': 99999, 'autohide': false }, + 'warning' : { 'class': 'bg-warning', 'icon': 'fa-warning', 'delay': 10000, 'autohide': true }, + 'notice' : { 'class': 'bg-info', 'icon': 'fa-info', 'delay': 5000, 'autohide': true }, } -%} {%- for type, config in types -%} {% set alerts = app.session.flashbag.get(type) %} {% if alerts|length > 0 %} -