From 411e3dcd5be3ce0e9adf33fa185db5711522f844 Mon Sep 17 00:00:00 2001 From: Felix Ruf Date: Thu, 19 Oct 2023 11:58:59 +0200 Subject: [PATCH] removed ununsed files --- .../Resources/translations/messages.de.yml | 10 - .../Resources/translations/messages.en.yml | 10 - .../Resources/translations/actions.de.yml | 19 - .../Resources/translations/actions.en.yml | 19 - .../Resources/translations/date.de.yml | 12 - .../Resources/translations/general.de.yml | 89 ---- .../Resources/translations/general.en.yml | 89 ---- .../Resources/translations/messages.de.yml | 45 -- .../Resources/translations/messages.en.yml | 56 --- src/Resources/js/controller.js | 14 - src/Resources/js/init.js | 167 ------- src/Resources/js/modules/add-participant.js | 113 ----- .../js/modules/ajax-error-handler.ts | 16 - src/Resources/js/modules/ajax-forms.js | 155 ------ src/Resources/js/modules/base-dialog.ts | 18 - .../js/modules/combined-meal-dialog.ts | 134 ----- .../js/modules/combined-meal-offers-dialog.ts | 131 ----- .../modules/combined-meal-offers-service.ts | 39 -- .../js/modules/combined-meal-service.ts | 189 -------- src/Resources/js/modules/confirm-action.js | 21 - .../js/modules/confirm-swap-dialog.ts | 39 -- src/Resources/js/modules/custom-functions.js | 81 ---- src/Resources/js/modules/dish-selection.js | 330 ------------- src/Resources/js/modules/labels.ts | 18 - src/Resources/js/modules/lightbox.js | 13 - .../js/modules/meal-offer-update-handler.ts | 85 ---- src/Resources/js/modules/meal-service.ts | 33 -- .../js/modules/mercure-subscribe-handler.ts | 15 - .../js/modules/participant-counter.ts | 42 -- .../participation-pre-toggle-handler.ts | 143 ------ .../modules/participation-request-handler.ts | 68 --- .../modules/participation-response-handler.ts | 54 --- .../modules/participation-toggle-handler.ts | 150 ------ .../modules/participation-update-handler.ts | 459 ------------------ src/Resources/js/modules/paypal.js | 155 ------ .../modules/slot-allocation-update-handler.ts | 36 -- .../js/modules/style-form-elements.js | 96 ---- src/Resources/js/modules/tables.js | 24 - .../js/modules/toggle-hidden-users.js | 43 -- .../js/modules/transactions-export.js | 16 - src/Resources/js/types/index.d.ts | 1 - .../js/views/adminParticipationEdit.ts | 363 -------------- src/Resources/js/views/dishIndex.ts | 40 -- src/Resources/js/views/mealGuest.ts | 33 -- src/Resources/js/views/mealIndex.ts | 155 ------ src/Resources/js/views/slotIndex.ts | 73 --- 46 files changed, 3911 deletions(-) delete mode 100644 src/Mealz/MealBundle/Resources/translations/actions.de.yml delete mode 100644 src/Mealz/MealBundle/Resources/translations/actions.en.yml delete mode 100644 src/Mealz/MealBundle/Resources/translations/date.de.yml delete mode 100644 src/Mealz/MealBundle/Resources/translations/general.de.yml delete mode 100644 src/Mealz/MealBundle/Resources/translations/general.en.yml delete mode 100644 src/Mealz/MealBundle/Resources/translations/messages.de.yml delete mode 100644 src/Mealz/MealBundle/Resources/translations/messages.en.yml delete mode 100644 src/Resources/js/controller.js delete mode 100644 src/Resources/js/init.js delete mode 100644 src/Resources/js/modules/add-participant.js delete mode 100644 src/Resources/js/modules/ajax-error-handler.ts delete mode 100644 src/Resources/js/modules/ajax-forms.js delete mode 100644 src/Resources/js/modules/base-dialog.ts delete mode 100644 src/Resources/js/modules/combined-meal-dialog.ts delete mode 100644 src/Resources/js/modules/combined-meal-offers-dialog.ts delete mode 100644 src/Resources/js/modules/combined-meal-offers-service.ts delete mode 100644 src/Resources/js/modules/combined-meal-service.ts delete mode 100644 src/Resources/js/modules/confirm-action.js delete mode 100644 src/Resources/js/modules/confirm-swap-dialog.ts delete mode 100644 src/Resources/js/modules/custom-functions.js delete mode 100644 src/Resources/js/modules/dish-selection.js delete mode 100644 src/Resources/js/modules/labels.ts delete mode 100644 src/Resources/js/modules/lightbox.js delete mode 100644 src/Resources/js/modules/meal-offer-update-handler.ts delete mode 100644 src/Resources/js/modules/meal-service.ts delete mode 100644 src/Resources/js/modules/mercure-subscribe-handler.ts delete mode 100644 src/Resources/js/modules/participant-counter.ts delete mode 100644 src/Resources/js/modules/participation-pre-toggle-handler.ts delete mode 100644 src/Resources/js/modules/participation-request-handler.ts delete mode 100644 src/Resources/js/modules/participation-response-handler.ts delete mode 100644 src/Resources/js/modules/participation-toggle-handler.ts delete mode 100644 src/Resources/js/modules/participation-update-handler.ts delete mode 100644 src/Resources/js/modules/paypal.js delete mode 100644 src/Resources/js/modules/slot-allocation-update-handler.ts delete mode 100644 src/Resources/js/modules/style-form-elements.js delete mode 100644 src/Resources/js/modules/tables.js delete mode 100644 src/Resources/js/modules/toggle-hidden-users.js delete mode 100644 src/Resources/js/modules/transactions-export.js delete mode 100644 src/Resources/js/types/index.d.ts delete mode 100644 src/Resources/js/views/adminParticipationEdit.ts delete mode 100644 src/Resources/js/views/dishIndex.ts delete mode 100644 src/Resources/js/views/mealGuest.ts delete mode 100644 src/Resources/js/views/mealIndex.ts delete mode 100644 src/Resources/js/views/slotIndex.ts diff --git a/src/Mealz/AccountingBundle/Resources/translations/messages.de.yml b/src/Mealz/AccountingBundle/Resources/translations/messages.de.yml index 77ccf4b41..1f531da2d 100644 --- a/src/Mealz/AccountingBundle/Resources/translations/messages.de.yml +++ b/src/Mealz/AccountingBundle/Resources/translations/messages.de.yml @@ -1,14 +1,4 @@ payment: - separator: - decimals: "," - thousands: "." - cash: - success: Einzahlung für %name% in Höhe von %amount% € wurde verbucht. - failure: Einzahlung wurde nicht verbucht. Bitte nur Positive Werte eintragen. - acknowledge_debts: - text: Ich weiß, dass ich einen Kontostand von %amount% € habe und werde meine Schulden umgehend begleichen. - button: OK, kapiert! - pay_now: Jetzt bezahlen costsheet: mail: subject: Anfrage auf Kontoausgleich diff --git a/src/Mealz/AccountingBundle/Resources/translations/messages.en.yml b/src/Mealz/AccountingBundle/Resources/translations/messages.en.yml index 5fd84775e..997e3c8c9 100644 --- a/src/Mealz/AccountingBundle/Resources/translations/messages.en.yml +++ b/src/Mealz/AccountingBundle/Resources/translations/messages.en.yml @@ -1,14 +1,4 @@ payment: - separator: - decimals: "." - thousands: "," - cash: - success: Booked cash payment of %amount% € for %name% - failure: The payment was not booked. Negative values are invalid.s - acknowledge_debts: - text: I know that my account balance is %amount% € in the red and I will pay my debt very soon. - button: Understood! - pay_now: Pay now costsheet: mail: subject: Request for account settlement diff --git a/src/Mealz/MealBundle/Resources/translations/actions.de.yml b/src/Mealz/MealBundle/Resources/translations/actions.de.yml deleted file mode 100644 index d087dd498..000000000 --- a/src/Mealz/MealBundle/Resources/translations/actions.de.yml +++ /dev/null @@ -1,19 +0,0 @@ -button: - ok: OK - save: Speichern - cancel: Abbrechen - edit: Editieren - delete: Löschen - add_variation: Variation hinzufügen - -dish: - create: Gericht erstellen - -category: - create: Kategorie erstellen - -slot: - create: Slot erstellen - -costs: - cash_register: Kasse diff --git a/src/Mealz/MealBundle/Resources/translations/actions.en.yml b/src/Mealz/MealBundle/Resources/translations/actions.en.yml deleted file mode 100644 index de1520a42..000000000 --- a/src/Mealz/MealBundle/Resources/translations/actions.en.yml +++ /dev/null @@ -1,19 +0,0 @@ -button: - ok: OK - save: Save - cancel: Cancel - edit: Edit - delete: Delete - add_variation: Add variation - -dish: - create: Create Dish - -category: - create: Create Category - -slot: - create: Create Slot - -costs: - cash_register: Cash Register diff --git a/src/Mealz/MealBundle/Resources/translations/date.de.yml b/src/Mealz/MealBundle/Resources/translations/date.de.yml deleted file mode 100644 index 4d76d2939..000000000 --- a/src/Mealz/MealBundle/Resources/translations/date.de.yml +++ /dev/null @@ -1,12 +0,0 @@ -Mon: Mo. -Tue: Di. -Wed: Mi. -Thu: Do. -Fri: Fr. -Monday: Montag -Tuesday: Dienstag -Wednesday: Mittwoch -Thursday: Donnerstag -Friday: Freitag -Saturday: Samstag -Sunday: Sonntag diff --git a/src/Mealz/MealBundle/Resources/translations/general.de.yml b/src/Mealz/MealBundle/Resources/translations/general.de.yml deleted file mode 100644 index 3dfd89db1..000000000 --- a/src/Mealz/MealBundle/Resources/translations/general.de.yml +++ /dev/null @@ -1,89 +0,0 @@ -header: - navigation: - menu: Mahlzeiten - dishes: Gerichte - categories: Kategorien - slots: Zeitslot - costs: Kosten - finance: Finanzen - logged_in_text: Eingeloggt als - balance: Kontostand - -headings: - week: - list: Liste der Wochen - create: Erstelle Woche - edit: Editiere Woche - participations: Teilnahmen - participationsprint: Teilnahmen am - dishes: - list: Liste der Gerichte - categories: - list: Liste der Kategorien - slots: - list: Liste der Slots - costs: - list: Liste der Kosten - guest_enrollment: Mittagessen bei AOE - -table: - title: Titel - actions: Aktionen - name: Name - category: Kategorie - total: Gesamt - -content: - participation: - week: - current: Diese Woche - next: Nächste Woche - disabled: Kein Angebot für diese Woche! - no_meals: | - Gedulde dich - noch haben wir kein Essen - für Dich, aber wir arbeiten daran! - participant.none: Bisher gibt es keine Teilnahmen für diese Woche. - day: - disabled: Kein Angebot für diesen Tag! - meal: - clipboard: In die Zwischenablage kopiert! - no_service: Kein Angebot! - select_slot: Autoselektion nächster freier Slot - dish: - new: Neu! - legend: - available: Verfügbar - unavailable: Nicht bestellbar - tradeable: Deine Bestellung wird anderen zum Tausch angeboten - no_service: Kein Service - menu: - week: Woche - no_service: Kein Service - print: - costs: - no_data: Keine Kosten vorhanden. - guest_enrollment: - message_body: Als Gast in unserem Haus laden wir Sie gerne zu einem Mittagessen in der AOE Eatery ein. Für Ihre Bestellung tragen Sie sich bitte bis spätestens einen Tag vorher mit Ihren Daten ein und wählen das gewünschte Gericht aus, das dann an unsere Köche weitergeleitet wird. - message_ending: Guten Appetit wünscht Ihnen, - message_signature: AOE - -form: - placeholder: - title: Titel - description: Beschreibung - category: Keine Kategorie - name: Nachname - first_name: Vorname - company: Firma - - create_edit_dish: - category: Kategorie - one_serving_size: Dieses Gericht ist nicht teilbar - - create-slot: - title: Titel - limit: Limit - order: Sortierung - - week: - notification: Menü in Mattermost bekanntgeben diff --git a/src/Mealz/MealBundle/Resources/translations/general.en.yml b/src/Mealz/MealBundle/Resources/translations/general.en.yml deleted file mode 100644 index 38dc00c18..000000000 --- a/src/Mealz/MealBundle/Resources/translations/general.en.yml +++ /dev/null @@ -1,89 +0,0 @@ -header: - navigation: - menu: Menu - dishes: Dishes - categories: Categories - slots: Time Slots - costs: Costs - finance: Finance - logged_in_text: You are logged in as - balance: Balance - -headings: - week: - list: List of weeks - create: Create week - edit: Edit week - participations: Participations - participationsprint: Participations on - dishes: - list: List of dishes - categories: - list: List of categories - slots: - list: Meal Slots - costs: - list: Cost listing - guest_enrollment: Lunch at AOE - -table: - title: Title - actions: Actions - name: Name - category: Category - total: Total - -content: - participation: - week: - current: Current week - next: Next week - disabled: No service this week! - no_meals: | - Be patient - we don't have - a menu yet but we're working on it! - participant.none: There are no participations for this week so far. - day: - disabled: No service this day! - meal: - clipboard: Copied to clipboard! - no_service: No service! - select_slot: Autoselect next free slot - dish: - new: New! - legend: - available: Available - unavailable: Unavailable for order - tradeable: Your order is being offered to others - no_service: No service - menu: - week: Week - no_service: No Service - print: - costs: - no_data: There exist no costs. - guest_enrollment: - message_body: As our guest, we would like to invite you to lunch in the AOE Eatery. To order a meal, register no later than one day before your visit to AOE with your personal information and choose the desired dish. Your order will be forwarded to our cooks. - message_ending: We hope that you enjoy your lunch - message_signature: AOE - -form: - placeholder: - title: Title - description: Description - category: No category - name: Last name - first_name: First name - company: Company - - create_edit_dish: - category: Category - one_serving_size: This dish has only one serving size - - create-slot: - title: Title - limit: Limit - order: Sort Order - - week: - notification: Announce menu via Mattermost diff --git a/src/Mealz/MealBundle/Resources/translations/messages.de.yml b/src/Mealz/MealBundle/Resources/translations/messages.de.yml deleted file mode 100644 index c2f394800..000000000 --- a/src/Mealz/MealBundle/Resources/translations/messages.de.yml +++ /dev/null @@ -1,45 +0,0 @@ -week: - created: Woche wurde angelegt. - modified: Woche wurde geändert. - -entity: - added: '%entityName% wurde hinzugefügt.' - modified: '%entityName% wurde geändert.' - deleted: '%entityName% "%entity%" wurde gelöscht.' - Dish: Gericht - Category: Kategorie - Slot: Slot -dish: - hidden: Gericht "%dish%" wurde verborgen. - deleted: Gericht "%dish%" wurde gelöscht. - delete_error: Gericht "%dish%" kann nicht gelöscht werden. Wir kümmern uns darum. Bitte versuchen Sie es später noch einmal. -dish_variation: - hidden: Gericht variation "%dishVariation%" wurde verborgen. - deleted: Gericht variation "%dishVariation%" wurde gelöscht. - delete_error: Gericht variation "%dishVariation%" kann nicht gelöscht werden. Wir kümmern uns darum. Bitte versuchen Sie es später noch einmal. -error: - unknown: Ein unbekannter Fehler ist aufgetreten. - all_days_disabled: Es kann keine Liste angezeigt werden, da alle Tage der Woche vom %startDate% - %endDate% deaktiviert sind. - profile: - already_exists: Es existiert bereits ein Profil mit diesem Namen. - participation: - no_meal_selected: Es muss mindestens ein Gericht ausgewählt werden - not_unique: Eine Essensbuchung mit diesen Eingaben existiert bereits. - meal: - has_participants: Es gibt bereits Teilnehmer für "%dish%" am %day%. - join_not_allowed: Es ist leider nicht mehr möglich, "%dish%" zu buchen. - update_not_allowed: Es ist leider nicht mehr möglich, dieses Gericht zu ändern. - variation_required: Bitte wähle eine Variation aus! -participation: - successful: Essensbuchung erfolgreich! -notification: - confirm_swap: Leider ist es schon zu spät, um dein Essen zu stornieren. Du hast aber die Möglichkeit, es jemand anderem zu überlassen. -tooltip: - offered_meal: Jemand anderes kann jetzt dein Essen übernehmen. - available_meal: Es ist Essen verfügbar. -offer_dialog: - title: "Zum Tausch angeboten:" -mail: - domain: '@aoe.com' - subject: 'Your offered food has been taken' - message: "Hi %firstname%,\nI would like to inform you that the \"%takenOffer%\" you offered has just been taken by someone.\nNo further action is required on your side.\n\nCheers, Your Chef Bot." diff --git a/src/Mealz/MealBundle/Resources/translations/messages.en.yml b/src/Mealz/MealBundle/Resources/translations/messages.en.yml deleted file mode 100644 index ef084924c..000000000 --- a/src/Mealz/MealBundle/Resources/translations/messages.en.yml +++ /dev/null @@ -1,56 +0,0 @@ -week: - created: Week has been created. - modified: Week has been modified. - notification: - header: - default: 'We are happy to offer the menu for the week %weekStart%-%weekEnd%' - no_week: 'In the week of %weekStart%-%weekEnd% we will not offer a menu' - footer: - default: Log into your account at https://meals.aoe.com/ to get it! - content: - no_meals: No offers for this day - -entity: - added: '%entityName% has been added.' - modified: '%entityName% has been modified.' - deleted: '%entityName% "%entity%" has been deleted.' - Dish: Dish - Category: Category - Slot: Slot -dish: - hidden: Dish "%dish%" has been marked as hidden. - deleted: Dish "%dish%" has been successfully deleted. - delete_error: Unable to delete "%dish%". We are looking into it. Please try again later. -dish_variation: - hidden: Dish variation "%dishVariation%" has been marked as hidden. - deleted: Dish variation "%dishVariation%" has been successfully deleted. - delete_error: Unable to delete dish variation "%dishVariation%". We are looking into it. Please try again later. -error: - unknown: An unknown error occured. - all_days_disabled: No list can be shown because all days for the week of %startDate% - %endDate% are deactivated. - profile: - already_exists: A profile with this name already exists. - participation: - no_meal_selected: Please select at least one Meal from options - not_unique: This participation already exists. - meal: - has_participants: There are already participants for "%dish%" on %day%. - join_not_allowed: Sorry, it's not possible to book "%dish%" anymore. - update_not_allowed: Sorry, making changes to this meal in no longer possible. - variation_required: Please select a variation! -participation: - successful: Meal participation successful -notification: - confirm_swap: Unfortunately it's already too late to cancel your order, but you have the possibility to offer it to someone else. -tooltip: - offered_meal: Someone else can take your meal now. - available_meal: There is food available. -offer_dialog: - title: "Offered for exchange:" -mattermost: - offered: '{1}:meal: One meal has just been offered: "%dish%". Log into your account at https://meals.aoe.com/ to get it!|[2, Inf[ :meal: One meal has just been offered: "%dish%". A total of %count% meals are currently being offered. Log into your account at https://meals.aoe.com/ to get it!' - offer_taken: '{0}:nomeal: One "%takenOffer%" has been taken. All offers are gone now.|{1}:meal: One "%takenOffer%" has been taken. Still one other meal is being offered.|[2, Inf[ :meal: One "%takenOffer%" has been taken. Still %count% other meals are being offered.' -mail: - domain: '@aoe.com' - subject: 'Your offered food has been taken' - message: "Hi %firstname%,\nI would like to inform you that the \"%takenOffer%\" you offered has just been taken by someone.\nNo further action is required on your side.\n\nCheers, Your Chef Bot." diff --git a/src/Resources/js/controller.js b/src/Resources/js/controller.js deleted file mode 100644 index 623ab05c9..000000000 --- a/src/Resources/js/controller.js +++ /dev/null @@ -1,14 +0,0 @@ -let Controller = function (view) { - if (typeof view == 'string' && view !== '') { - this.getView(view); - } -}; - -Controller.prototype.getView = function (viewName) { - const viewFile = './'+viewName+'.ts'; - const context = require.context('./views', false, /.*\.ts$/); - const viewObj = context(viewFile); - new viewObj.default(); -}; - -export { Controller }; diff --git a/src/Resources/js/init.js b/src/Resources/js/init.js deleted file mode 100644 index 1c39bedb2..000000000 --- a/src/Resources/js/init.js +++ /dev/null @@ -1,167 +0,0 @@ -// include CSS -import 'daterangepicker/daterangepicker.css' -import 'jquery-datetimepicker/build/jquery.datetimepicker.min.css' -import 'jquery-ui/themes/base/all.css' -import '@fancyapps/fancybox/dist/jquery.fancybox.css' -import '../sass/mealz.scss' - -// include vendors -import 'jquery'; -import 'jquery-datetimepicker/build/jquery.datetimepicker.full'; -import '@fancyapps/fancybox'; -import 'easy-autocomplete'; -import 'daterangepicker'; -import {Controller} from './controller'; -import { createApp } from 'vue' -import App from '../vue/App.vue' - -const vueApp = createApp(App); -vueApp.mount('#app'); - -if (process.env.MODE !== 'production' && import.meta.webpackHot) { - import.meta.webpackHot.accept(); -} - -function importAll(r) { - r.keys().forEach(r); -} - -window.Mealz = function () { - this.prototypeFormId = undefined; - this.checkboxWrapperClass = 'checkbox-wrapper'; - this.hiddenClass = 'hidden'; - this.weekCheckbox = $('.meal-form .week-disable input[type="checkbox"]')[0]; - this.$weekDayCheckboxes = $('.meal-form .week-day-action input[type="checkbox"]'); - this.notifyCheckbox = $('.meal-form .week-notify-action input[type="checkbox"]')[0]; - this.$participationCheckboxes = $('.meals-list input.checkbox, .meals-list input[type = "checkbox"]'); - this.$guestParticipationCheckboxes = $('.meal-guests input.checkbox, .meal-guests input[type = "checkbox"]'); - this.$iconCells = $('.icon-cell'); - this.selectWrapperClass = 'select-wrapper'; - this.mealRowsWrapperClassSelector = '.meal-rows-wrapper'; - this.$selects = $('select'); - this.$body = $('body'); - this.$editParticipationEventListener = undefined; - this.$profileAdd = $('.profile-list a[class="button small"]'); -}; - -importAll(require.context('./modules/', true, /\.js$/)); - -$(function () { - const view = $('body').data('view'); - new Controller(view); - - var mealz = new Mealz(); - mealz.styleCheckboxes(); - mealz.styleSelects(); - mealz.initButtonHandling(); - mealz.copyToClipboard(); - - mealz.confirmAction( - '.hide-user-action', - 'data-hide-user-confirmation', - '#hide-user-confirmation-continue' - ); - mealz.initHiddenUsersToggler(); - - /** - * See: https://stackoverflow.com/questions/1537032/how-do-i-stop-jquery-appending-a-unique-id-to-scripts-called-via-ajax - * http://api.jquery.com/jQuery.ajaxPrefilter/ - */ - $.ajaxPrefilter('script', function (options) { - options.cache = true; - }); - - /** - * Week creation, dish and variations selection - */ - mealz.initDishSelection(); - - /** - * Mobile navigation button - */ - $('.hamburger').on('click', function () { - $(this).toggleClass('is-active'); - $('.header-content').toggleClass('is-open'); - }); - - /** - * Ajax form handling - */ - mealz.initAjaxForms(); - - /** - * Enable table sorting - */ - mealz.enableSortableTables(); - - /** - * Lightbox - */ - mealz.enableLightbox(); - - if ($('.edit-participation').length > 0) { - /** - * Profile Selection on Participants View - */ - mealz.initAutocomplete(); - mealz.showProfiles(); - } - - mealz.exportTransactions(); - - /** - * if meals is limited it should be displayed - */ - $('.participation-limit').each(function () { - if ($(this).val().length > 0 && $(this).val() > 0) { - $(this).closest('.day').children('.limit-icon').addClass('modified'); - } - }); - - /** - * datetimepicker - */ - $('.calendar-icon').each(function (i) { - var thisDay = $('#week_form_days_' + i + '_lockParticipationDateTime'); - $(this).datetimepicker({ - format: 'Y-m-d H:i:s', - inline: false, - defaultTime: new Date(thisDay.val()), - defaultDate: new Date(thisDay.val()), - onClose: function (dp, $input) { - if ($input.val().length > 0) { - thisDay.val($input.val()); - } - } - }); - }); - if ($('.language-switch > span').text() == 'de') { - $.datetimepicker.setLocale('de'); - } - - /* - * MouseOver hack - */ - (function ($) { - $.mlp = {x: 0, y: 0}; // Mouse Last Position - function documentHandler() { - var $current = this === document ? $(this) : $(this).contents(); - $current.on('mousemove', function (e) { - jQuery.mlp = {x: e.pageX, y: e.pageY}; - }); - $current.find('iframe').on('load', documentHandler); - } - - $(documentHandler); - $.fn.ismouseover = function (overThis) { - var result = false; - this.eq(0).each(function () { - var $current = $(this).is('iframe') ? $(this).contents().find('body') : $(this); - var offset = $current.offset(); - result = offset.left <= $.mlp.x && offset.left + $current.outerWidth() > $.mlp.x && - offset.top <= $.mlp.y && offset.top + $current.outerHeight() > $.mlp.y; - }); - return result; - }; - })(jQuery); -}); diff --git a/src/Resources/js/modules/add-participant.js b/src/Resources/js/modules/add-participant.js deleted file mode 100644 index 714fea235..000000000 --- a/src/Resources/js/modules/add-participant.js +++ /dev/null @@ -1,113 +0,0 @@ - -/** - * Initialize and configurate plugin easyautocomplete - */ -Mealz.prototype.initAutocomplete = function () { - var profile = $('.profile'); - var profiles = { - data: JSON.parse($('.profile-list').attr('data-attribute-profiles')), - getValue: 'label', - list: { - match: { - enabled: true - }, - onSelectItemEvent: function () { - var value = profile.getSelectedItemData().value; - var selected = $('.easy-autocomplete-container li')[profile.getSelectedItemIndex()]; - $(selected).attr({'data-attribute-value': value}); - } - } - }; - profile.easyAutocomplete(profiles); -}; - -/** - * Add new profil into participation list - */ -Mealz.prototype.addProfile = function () { - var profileList = JSON.parse($('.profile-list').attr('data-attribute-profiles')); - var prototype = $('.table-content').data('prototype'); - var selectedProfile = $('.easy-autocomplete-container li[class="selected"]'); - - // if a profil is selected add profil to table - if(selectedProfile.length > 0) { - var name = $(selectedProfile)[0].innerText; - var userName = $(selectedProfile).data('attribute-value'); - buildPrototype(name, userName); - addToTable(prototype, selectedProfile); - buildNewProfileList(profileList, userName); - } - - // add name and username in prototype variable - function buildPrototype(name, userName) { - prototype = prototype.replace(/__name__/g, name); - prototype = prototype.replace(/__username__/g, userName); - } - - // remove input value and add new profil into the profil table - function addToTable(prototype, selectedProfile) { - $(prototype).prependTo('.edit-participation .table > tbody'); - selectedProfile.remove(); - $('.profile').val(''); - $('.table').removeAttr('style'); - $('.empty-table').remove(); - } - - // build and show new profil list and intialize autocomplete - function buildNewProfileList(profileList, userName) { - var newProfileList = $.grep(profileList, function(e) { return e.value != userName; }); - $('.profile-list').attr('data-attribute-profiles', JSON.stringify(newProfileList)); - reinitialize(); - } - - // after adding a profile it is necessary to reinitialize to get new context - function reinitialize() { - Mealz.prototype.initAutocomplete(); - Mealz.prototype.showProfiles(); - } -}; - -/** - * Show participation list - */ -Mealz.prototype.showProfiles = function () { - var input = $('.profile'); - var profileListContainer = $('.easy-autocomplete-container ul'); - fillContainer(JSON.parse($('.profile-list').attr('data-attribute-profiles'))); - - // close profil list select field if click next to list - $(document).on('click', function () { - profileListContainer.hide(); - }); - - // if click on hamburger-menu show profile list - $('.toggle-profiles').on('click', function (event) { - input.val(''); - fillContainer(JSON.parse($('.profile-list').attr('data-attribute-profiles'))); - profileListContainer.toggle(); - event.preventDefault(); - event.stopPropagation(); - }); - - // show all profiles in list - function fillContainer(profileList) { - profileListContainer.empty(); - $.each(profileList, function( key ) { - profileListContainer.append('
  • ' + profileList[key].label + '
  • '); - }); - selectProfile(); - } - - function selectProfile() { - // if click li add class selected - $('.easy-autocomplete-container li').on('click', function () { - $(this).toggleClass('selected'); - }); - - // if click on profil, add profil into input value - $('.easy-autocomplete-container li div').on('click', function () { - var selectedItem = $(this)[0].innerHTML; - $('.profile').val(selectedItem); - }); - } -}; diff --git a/src/Resources/js/modules/ajax-error-handler.ts b/src/Resources/js/modules/ajax-error-handler.ts deleted file mode 100644 index 4c59a6632..000000000 --- a/src/Resources/js/modules/ajax-error-handler.ts +++ /dev/null @@ -1,16 +0,0 @@ -export default class AjaxErrorHandler { - public static handleError(jqXHR: JQueryXHR, customFn?: () => void){ - if (401 === jqXHR.status) { - location.reload(); - return; - } - - if (undefined !== customFn) { - customFn(); - return; - } - - console.log(jqXHR.status + ': ' + jqXHR.statusText); - alert('An unknown error occurred'); - } -} diff --git a/src/Resources/js/modules/ajax-forms.js b/src/Resources/js/modules/ajax-forms.js deleted file mode 100644 index 84249adb1..000000000 --- a/src/Resources/js/modules/ajax-forms.js +++ /dev/null @@ -1,155 +0,0 @@ -import AjaxErrorHandler from './ajax-error-handler'; - -Mealz.prototype.initAjaxForms = function () { - var that = this; - $('.load-ajax-form').on('click', function (e) { - e.preventDefault(); - that.loadAjaxForm($(this)); - }); - - $('.print-participations .meal-participation a').on('click', function (e) { - e.preventDefault(); - that.toggleParticipationAdmin($(this)); - }); - - $('.load-payment-form').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - - that.loadAjaxFormPayment($(this)); - }); -}; - -Mealz.prototype.loadAjaxForm = function ($element) { - var that = this; - - var url = $element.attr('href'); - var animationDuration = 150; - - var $createForm = $('.create-form'); - var $editFormWrapper = $('.edit-form:visible'); - var $elementParentRow = $element.closest('.table-row'); - var $ajaxRow; - - if ($createForm.is(':visible')) { - $createForm.slideUp(animationDuration); - if ($element.hasClass('load-create-form')) { - return; - } - } else if ($element.hasClass('load-create-form') && $element.hasClass('loaded')) { - $createForm.slideDown(animationDuration); - $editFormWrapper.find('form').slideUp(animationDuration, function () { - $editFormWrapper.hide(); - }); - return; - } - - if ($editFormWrapper.length > 0) { - $ajaxRow = $elementParentRow.next('.table-row-form'); - - var ajaxRowVisible = $ajaxRow.length > 0 && $ajaxRow.is(':visible'); - - $editFormWrapper.find('form').slideUp(animationDuration, function () { - $editFormWrapper.hide(); - }); - - if (!ajaxRowVisible && $element.hasClass('load-edit-form') && $element.hasClass('loaded')) { - $ajaxRow.show(); - $ajaxRow.find('form').slideDown(animationDuration); - return; - } else if (ajaxRowVisible) { - return; - } - } else if ($element.hasClass('load-edit-form') && $element.hasClass('loaded')) { - $ajaxRow = $elementParentRow.next('.table-row-form'); - $ajaxRow.show(); - $ajaxRow.find('form').slideDown(animationDuration); - return; - } - - $.ajax({ - method: 'GET', - url: url, - dataType: 'text', - success: function (data) { - var $wrapperForm; - - if ($element.hasClass('load-create-form')) { - $createForm.html(data); - $createForm.slideDown(animationDuration); - $wrapperForm = $createForm; - } else { - $wrapperForm = $(data).insertAfter($elementParentRow); - $wrapperForm.find('form').slideDown(animationDuration); - } - - // Style selects - $wrapperForm.find('select') - .wrap('
    ') - .parent().append(''); - - $element.addClass('loaded'); - }, - error: function (jqXHR) { - AjaxErrorHandler.handleError(jqXHR); - } - }); -}; - -Mealz.prototype.loadAjaxFormPayment = function ($element) { - var that = this; - var url = $element.attr('href'); - var $elementParent = $element.parent(); - var $form = $elementParent.find('form'); - - if ($form.length !== 0) { - that.$iconCells.find('form').addClass(that.hiddenClass); - $form.toggleClass(this.hiddenClass); - if (!$form.hasClass(this.hiddenClass)) { - $form.find('input[type=text]').focus(); - } - return; - } - - $.ajax({ - method: 'GET', - url: url, - dataType: 'text', - success: function (data) { - that.$iconCells.find('form').addClass(that.hiddenClass); - $element.after(data); - $form = $elementParent.find('form'); - $form.find('input[type=text]').focus(); - $form.on('click', function (e) { - e.stopPropagation(); - }); - - // remove other Payment Forms opened - if($form.length > 0) { - $(document).on('mouseup', function(e){ - // if the target of the click isn't the container - // nor a descendant of the container - if ($form.is(e.target) === false && - $elementParent.has(e.target).length === 0) { - $form.remove(); - } - }); - } - - if ($('form[name="settleform"]').length >= 1) { - Mealz.prototype.confirmAction( - 'a#settle-account', - 'data-account-settlement-confirmation', - '#account-settlement-confirmation-continue' - ); - } - - if ($('.load-payment-form').is('#ecash') === true && $('.paypal-button-container').length >= 1) { - that.enablePaypal(); - } - }, - error: function (jqXHR) { - AjaxErrorHandler.handleError(jqXHR); - } - }); -}; diff --git a/src/Resources/js/modules/base-dialog.ts b/src/Resources/js/modules/base-dialog.ts deleted file mode 100644 index fed597244..000000000 --- a/src/Resources/js/modules/base-dialog.ts +++ /dev/null @@ -1,18 +0,0 @@ -import 'jquery-ui/ui/widgets/dialog'; - -export abstract class BaseDialog { - protected $dialog: JQuery; - - public abstract open(): void; - - protected handleCancel(): void { - this.$dialog.dialog('close'); - } - - protected handleCreate(): void { - let $widget = $(this).dialog('widget'); - $widget.removeClass('ui-corner-all'); - $widget.find('.ui-dialog-titlebar-close').remove(); - $widget.find('.ui-button').removeClass('ui-corner-all'); - } -} \ No newline at end of file diff --git a/src/Resources/js/modules/combined-meal-dialog.ts b/src/Resources/js/modules/combined-meal-dialog.ts deleted file mode 100644 index e1227ee28..000000000 --- a/src/Resources/js/modules/combined-meal-dialog.ts +++ /dev/null @@ -1,134 +0,0 @@ -import 'jquery-ui/ui/widgets/dialog'; -import {BaseDialog} from './base-dialog'; -import {Dish} from './combined-meal-service'; - -export class CombinedMealDialog extends BaseDialog { - private readonly containerID: string = '#combined-meal-selector'; - private readonly title: string; - private readonly slotSlug: string; - private opts: CombinedMealDialogOptions; - - private $form: JQuery; - - constructor( - title: string, - dishes: Dish[], - selectedDishIDs: string[], - slotSlug: string, - opts: CombinedMealDialogOptions - ) { - super(); - this.title = title; - this.slotSlug = slotSlug; - this.$form = this.buildForm(dishes, selectedDishIDs, this.slotSlug); - this.opts = opts; - } - - public open(): void { - this.$dialog = $(this.containerID).empty().append(this.$form).dialog({ - modal: true, - width: 400, - maxWidth: 500, - title: this.title, - draggable: false, - buttons: [ - { - 'text': 'OK', - 'data-qa': 'ok', - 'click': this.handleOk.bind(this) - }, - { - 'text': 'Cancel', - 'data-qa': 'cancel', - 'click': this.handleCancel.bind(this) - } - ], - create: this.handleCreate - }); - } - - private buildForm(dishes: Dish[], selectedDishIDs: string[], slotSlug: string): JQuery { - let $form = $('
    '); - let $formFields = this.getFormFields(dishes, selectedDishIDs); - $form.prepend($formFields); - let $slotSlugField = ''; - $form.prepend($slotSlugField); - - return $form; - } - - private getFormFields(dishes: Dish[], selectedDishIDs: string[]): JQuery { - let $dishes = $('
    '); - - dishes.forEach((dish, index) => { - if (dish.isCombined) { - return; - } - let $dishField = this.getDishField(dish, index, selectedDishIDs); - $dishes.append($dishField); - }); - - return $dishes; - } - - private getDishField(d: Dish, index: number, selectedDishIDs: string[]): JQuery { - const fieldName = `dishes[${index}]`; - - if (0 === d.variations.length) { - return this.getRadioButton(fieldName, d.slug, true, d.title, {wrapper: {'class': 'dish', 'data-qa': 'dish'}}); - } - - let $dish = $('
    ' + d.title + '
    '); - d.variations.forEach((dv, index) => { - const selected = selectedDishIDs.includes(dv.slug) || (0 === index); - let $dishVariation = this.getRadioButton(fieldName, dv.slug, selected, dv.title, { - wrapper: { - 'class': 'dish-variation', - 'data-qa': 'dish-variation' - } - }); - $dish.append($dishVariation); - }); - - return $dish; - } - - private getRadioButton(name: string, value: string, selected: boolean, label: string, opts?: RadioElementOptions): JQuery { - let wrapperExtraAttrs = ''; - if (typeof opts !== 'undefined' && typeof opts.wrapper !== 'undefined') { - for (const [k, v] of Object.entries(opts.wrapper)) { - wrapperExtraAttrs += ` ${k}="${v}"`; - } - } - - return $(` - - - - - `); - } - - private handleOk(): void { - const $form = this.$dialog.find('form:first'); - this.opts.ok($form.serializeArray()); - this.$dialog.dialog('close'); - } -} - -interface CombinedMealDialogOptions { - ok: (data: any) => void -} - -export interface SerializedFormData { - name: string; - value: string; -} - -interface RadioElementOptions { - wrapper?: ElementAttributes; -} - -interface ElementAttributes { - [index: string]: string; -} diff --git a/src/Resources/js/modules/combined-meal-offers-dialog.ts b/src/Resources/js/modules/combined-meal-offers-dialog.ts deleted file mode 100644 index 51840acef..000000000 --- a/src/Resources/js/modules/combined-meal-offers-dialog.ts +++ /dev/null @@ -1,131 +0,0 @@ -import 'jquery-ui/ui/widgets/dialog'; -import {BaseDialog} from './base-dialog'; - -export class CombinedMealOffersDialog extends BaseDialog { - private readonly containerID: string = '#combined-meal-selector'; - private readonly title: string; - private readonly offers: Array; - private opts: CombinedMealDialogOffersOptions; - - private $form: JQuery; - - constructor(title: string, offers: Array, opts: CombinedMealDialogOffersOptions) { - super(); - this.title = title; - this.offers = offers; - this.$form = this.buildForm(offers); - this.opts = opts; - } - - public open(): void { - this.$dialog = $(this.containerID).empty().append(this.$form).dialog({ - modal: true, - width: 500, - maxWidth: 500, - title: this.title, - draggable: false, - buttons: { - 'OK': this.handleOk.bind(this), - 'Cancel': this.handleCancel.bind(this) - }, - create: this.handleCreate - }); - } - - private buildForm(offers: Array): JQuery { - let $form = $('
    '); - let $formFields = this.getFormFields(offers); - $form.prepend($formFields); - return $form; - } - - private getFormFields(offers: Array): JQuery { - let $offers = $('
    '); - - let selected = true; - for (let offer of offers) { - let $offerField = this.getOfferField(offer, selected); - $offers.append($offerField); - selected = false; - } - - return $offers; - } - - private getOfferField(offer: Offer, selected: boolean): JQuery { - const fieldName = 'offer'; - let dishTitles = []; - for (let dishInfo of offer.dishes) { - dishTitles.push(dishInfo.title); - } - let title = dishTitles.join(', ') + ' (' + offer.count + ')'; - - return this.getRadioButton(fieldName, offer.id, selected, title, {wrapperClass: 'offer'}); - } - - private getRadioButton(name: string, value: string, selected: boolean, label: string, attrs?: ElementAttributes): JQuery { - let attributes = Object.assign({ - wrapperClass: 'wrapper' - }, attrs || {}); - - return $(` -
    - - -
    - `); - } - - private handleOk(): void { - const $form = this.$dialog.find('form:first'); - let formData = $form.serializeArray(); - if (formData.length > 0) { - let offerChoice; - formData.forEach(formEntry => { - if ('offer' === formEntry.name) { - offerChoice = formEntry.value; - return; - } - }); - - let dishSlugs = []; - for (let offer of this.offers) { - if (offer.id === offerChoice) { - let index = 0; - for (let dish of offer.dishes) { - dishSlugs.push({ - name: 'dishes[' + index + ']', - value: dish.slug - }); - index++; - } - break; - } - } - this.opts.ok(dishSlugs); - } else { - console.log("Error: Form is empty"); - } - - this.$dialog.dialog('close'); - } -} - -export interface DishInfo { - slug: string - title: string -} - -export interface Offer { - id: string - count: number - dishes: Array -} - -interface CombinedMealDialogOffersOptions { - ok: (data: any) => void -} - -interface ElementAttributes { - wrapperClass: string -} diff --git a/src/Resources/js/modules/combined-meal-offers-service.ts b/src/Resources/js/modules/combined-meal-offers-service.ts deleted file mode 100644 index c41a43543..000000000 --- a/src/Resources/js/modules/combined-meal-offers-service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import 'jquery-ui/ui/widgets/dialog'; -import {CombinedMealOffersDialog, Offer} from './combined-meal-offers-dialog'; -import {AbstractParticipationToggleHandler} from './participation-toggle-handler'; -import {ParticipantCounter} from './participant-counter'; - -export class CombinedMealOffersService { - public static execute($checkbox: JQuery, participationToggleHandler: AbstractParticipationToggleHandler) { - this.getOffers($checkbox, participationToggleHandler); - } - - private static getOffers($checkbox: JQuery, participationToggleHandler: AbstractParticipationToggleHandler) { - let self = this - let participantCounter: ParticipantCounter = $checkbox.data(ParticipantCounter.NAME); - let date = participantCounter.getDay(); - let dish = participantCounter.getDishSlug(); - $.getJSON('/menu/' + date + '/' + dish + '/offers') - .done(function (offers: Offers) { - self.openDialog(offers.title, $checkbox, offers.offers, participationToggleHandler); - }); - } - - private static openDialog(title: string, $checkbox: JQuery, offers: Array, participationToggleHandler: AbstractParticipationToggleHandler) { - let cmd = new CombinedMealOffersDialog( - title, - offers, - { - ok: function (data) { - participationToggleHandler.toggle($checkbox, data); - } - } - ); - cmd.open(); - } -} - -interface Offers { - title: string, - offers: Array -} diff --git a/src/Resources/js/modules/combined-meal-service.ts b/src/Resources/js/modules/combined-meal-service.ts deleted file mode 100644 index 0752347ce..000000000 --- a/src/Resources/js/modules/combined-meal-service.ts +++ /dev/null @@ -1,189 +0,0 @@ -import {MealService} from './meal-service'; - -export class CombinedMealService { - - /** - * No. of dish items in a combined dish. - */ - private static readonly DISH_COUNT = 2; - - /** - * Gets the available dishes for the combined dish. - */ - public static getDishes($dayMealsContainer: JQuery): Dish[] { - let dishes = CombinedMealService.getAllDishes($dayMealsContainer); - let availableDishSlugs = CombinedMealService.getAvailableDishSlugs($dayMealsContainer); - - if (0 === availableDishSlugs.length) { - return dishes; - } - - let availableDishes: Dish[] = []; - dishes.forEach((dish) => { - if (dish.slug === undefined) { - let dv = dish.variations.filter(dv => availableDishSlugs.includes(dv.slug)); - if (0 < dv.length) { - dish.variations = dv; - availableDishes.push(dish); - } - } else if (availableDishSlugs.includes(dish.slug)) { - availableDishes.push(dish); - } - }); - - return availableDishes; - } - - /** - * @param $checkbox Combined Dish Checkbox - * @param participantID Participant's ID for the booked combined meal - * @param bookedDishSlugs Dish IDs in booked combined meal - */ - public static updateDishes($checkbox: JQuery, participantID: number, bookedDishSlugs: string[]) { - let $dishContainer = $checkbox.closest('.meal-row'); - if (!CombinedMealService.isCombinedDish($dishContainer)) { - return; - } - if (typeof participantID === 'undefined' || !Array.isArray(bookedDishSlugs) || 0 === bookedDishSlugs.length) { - CombinedMealService.resetDish($dishContainer); - return; - } - - let $mealContainer = $dishContainer.closest('.meal'); - const dishes = CombinedMealService.getDishes($mealContainer); - const success = CombinedMealService.updateBookedDishes($checkbox, dishes, bookedDishSlugs); - - if (success) { - MealService.setParticipantId($checkbox, participantID); - if (CombinedMealService.mealHasDishVariations($mealContainer) - && !CombinedMealService.isLockedMeal($mealContainer)) { - $dishContainer.find('.title').addClass('edit'); - } - } - } - - /** - * @param $checkbox Combined Dish Checkbox - * @param $dishes Available meal dishes on a given day - * @param bookedDishSlugs Dish Slugs in booked combined meal - */ - public static updateBookedDishes($checkbox: JQuery, $dishes: Dish[], bookedDishSlugs: string[]): boolean { - let $dishContainer = $checkbox.closest('.meal-row'); - if (!CombinedMealService.isCombinedDish($dishContainer) || - !Array.isArray(bookedDishSlugs) || - 0 === bookedDishSlugs.length) { - return false; - } - - let bdt = CombinedMealService.getBookedDishTitles(bookedDishSlugs, $dishes); - - if (CombinedMealService.DISH_COUNT === bdt.length) { - // update dish description with titles of booked dishes - const bookedDishTitles = bdt.map(dishTitle => $(`
    ${dishTitle}
    `)); - $dishContainer.find('.description .dish-combination').empty().append(...bookedDishTitles); - $dishContainer.find('.title').removeClass('no-description'); - // update booked dish IDs in data attribute - $dishContainer.attr('data-booked-dishes', bookedDishSlugs.join(',')); - - return true; - } - - return false; - } - - public static isCombinedDish($dishContainer: JQuery): boolean { - return $dishContainer.hasClass('combined-meal'); - } - - private static getAllDishes($mealContainer: JQuery): Dish[] { - let dishes: Dish[] = []; - - $mealContainer.find('.meal-row').each(function () { - const $dishContainer = $(this); - if (CombinedMealService.isCombinedDish($dishContainer)) { - return; - } - - let dish: Dish = { - title: $dishContainer.find('.title').contents().get(0).nodeValue.trim(), - slug: $dishContainer.data('slug'), - variations: [], - isCombined: false - }; - $dishContainer.find('.variation-row').each(function () { - const $dishVarRow = $(this); - let dishVariation: DishVariation = { - title: $dishVarRow.find('.text-variation').text().trim(), - slug: $dishVarRow.data('slug'), - }; - dish.variations.push(dishVariation); - }); - dishes.push(dish); - }); - - return dishes; - } - - private static getAvailableDishSlugs($dayMealsContainer: JQuery): string[] { - let $combinedMeal = $dayMealsContainer.find('.combined-meal'); - if (0 === $combinedMeal.length) { - console.log(`error: combined meal not found, date: ${$dayMealsContainer.data('date')}`); - return; - } - - let availableDishes = $combinedMeal.attr('data-available-dishes'); - - return availableDishes === undefined || availableDishes === '' ? [] : availableDishes.split(','); - } - - private static getBookedDishTitles(dishIDs: string[], dishes: Dish[] | DishVariation[]) { - let dishTitles: string[] = []; - dishes.forEach(function (dish) { - let idx = dishIDs.indexOf(dish.slug); - if (-1 < idx) { - dishTitles.push(dish.title); - dishIDs.slice(idx, 1); - } else if (Array.isArray(dish.variations) && 0 < dish.variations.length) { - let dvt = CombinedMealService.getBookedDishTitles(dishIDs, dish.variations); - dishTitles.push(...dvt); - } - }); - - return dishTitles; - } - - private static resetDish($dishContainer: JQuery): void { - const $checkbox = $dishContainer.find('input[type=checkbox]'); - MealService.setParticipantId($checkbox, null); - - let desc = $dishContainer.data('description'); - $dishContainer.find('.description .dish-combination').empty().text(desc); - $dishContainer.find('.title').removeClass('edit'); - if (CombinedMealService.isCombinedDish($dishContainer)) { - $dishContainer.find('.title').addClass('no-description'); - } - $dishContainer.attr('data-id', ''); - $dishContainer.attr('data-booked-dishes', ''); - } - - private static isLockedMeal($mealContainer: JQuery): boolean { - let lockDateTime = $mealContainer.data('lockDateTime'); - const mealLockDateTime = Date.parse(lockDateTime); - - return mealLockDateTime <= Date.now(); - } - - private static mealHasDishVariations($mealContainer: JQuery): boolean { - return 0 < $mealContainer.find('.meal-row .variation-row').length; - } -} - -export interface Dish extends DishVariation { - variations: DishVariation[]; - 'isCombined': boolean; -} - -export interface DishVariation { - title: string; - slug: string; -} diff --git a/src/Resources/js/modules/confirm-action.js b/src/Resources/js/modules/confirm-action.js deleted file mode 100644 index baeb84087..000000000 --- a/src/Resources/js/modules/confirm-action.js +++ /dev/null @@ -1,21 +0,0 @@ -Mealz.prototype.confirmAction = function (linkSelector, hiddenContainer, continueButtonSelector) { - $(linkSelector).on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - - let $container = $('['+hiddenContainer+']'); - let $profile = $(this).data('profile'); - let $continueButton = $(continueButtonSelector); - - $continueButton.attr('href', $continueButton.attr('href').replace('_', $profile)); - - let options = { - closeClickOutside: false, - smallBtn: false, - infobar: false, - buttons: false, - }; - - $.fancybox.open($container, options); - }); -} \ No newline at end of file diff --git a/src/Resources/js/modules/confirm-swap-dialog.ts b/src/Resources/js/modules/confirm-swap-dialog.ts deleted file mode 100644 index 891d236e0..000000000 --- a/src/Resources/js/modules/confirm-swap-dialog.ts +++ /dev/null @@ -1,39 +0,0 @@ -import 'jquery-ui/ui/widgets/dialog'; -import {ParticipationRequest, ParticipationRequestHandler} from './participation-request-handler'; -import {ActionResponse} from './participation-response-handler'; -import {BaseDialog} from './base-dialog'; - -export class ConfirmSwapDialog extends BaseDialog { - private readonly containerID: string = '#confirm-swapbox'; - private opts: ConfirmSwapDialogOptions; - - constructor(opts: ConfirmSwapDialogOptions) { - super(); - this.opts = opts; - } - - public open(): void { - this.$dialog = $(this.containerID).dialog({ - modal: true, - width: 500, - maxWidth: 500, - draggable: false, - buttons: { - 'OK': this.handleOk.bind(this), - 'Cancel': this.handleCancel.bind(this) - }, - create: this.handleCreate - }); - } - - private handleOk(): void { - ParticipationRequestHandler.sendRequest(this.opts.participationRequest, this.opts.$checkbox, this.opts.handlerMethod); - this.$dialog.dialog('close'); - } -} - -interface ConfirmSwapDialogOptions { - participationRequest: ParticipationRequest, - $checkbox: JQuery, - handlerMethod: ($checkbox: JQuery, response: ActionResponse) => void -} diff --git a/src/Resources/js/modules/custom-functions.js b/src/Resources/js/modules/custom-functions.js deleted file mode 100644 index 377481f00..000000000 --- a/src/Resources/js/modules/custom-functions.js +++ /dev/null @@ -1,81 +0,0 @@ -import AjaxErrorHandler from './ajax-error-handler'; - -Mealz.prototype.toggleArrayItem = function (a, v) { - var i = a.indexOf(v); - if (i === -1) - a.push(v); - else - a.splice(i,1); -} - -Mealz.prototype.copyToClipboard = function() { - 'use strict'; - - var that = this; - - // click events - $('.guest-menu').on('click', function () { - var $that = $(this); - - // Close all open overlays - $('.guest-menu-link').removeClass('open'); - - var dayId = $that.attr('data-copytarget').split('-').pop(); - var guestMenuLinkInput = $that.parent().find('.guest-menu-link textarea'); - - $.ajax({ - method: 'GET', - url: '/menu/' + dayId + '/new-guest-invitation', - success: function (result) { - if (that.isUrl(result)) { - guestMenuLinkInput.val(result); - $that.next().addClass('open'); - if (navigator.userAgent.match(/ipad|ipod|iphone/i)) { - var el = guestMenuLinkInput.get(0); - var editable = el.contentEditable; - var readOnly = el.readOnly; - el.contentEditable = true; - el.readOnly = false; - var range = document.createRange(); - range.selectNodeContents(el); - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - el.setSelectionRange(0, 999999); - el.contentEditable = editable; - el.readOnly = readOnly; - } else { - guestMenuLinkInput.trigger('select'); - } - // Clipboard copy only works in secure context, redirect http -> https - if (window.location.protocol === 'https:') { - navigator.clipboard.writeText(result); - } else { - console.warn('Clipboard access from insecure (HTTP) context is prohibited. Reload page with HTTPS and try again.'); - } - guestMenuLinkInput.trigger('blur'); - } else { - var $html = $(result); - if ($html.length && $html.find('.login-form').length) { - window.location.reload(); - } - } - return false; - }, - error: function(jqXHR){ - AjaxErrorHandler.handleError(jqXHR); - } - }); - }); - - $(document).on('click', function (event) { - if (!$(event.target).closest('.guest-menu-link').length) { - $('.guest-menu-link').removeClass('open'); - } - }); -}; - -Mealz.prototype.isUrl = function(s) { - var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; - return regexp.test(s); -}; diff --git a/src/Resources/js/modules/dish-selection.js b/src/Resources/js/modules/dish-selection.js deleted file mode 100644 index 021bc82f4..000000000 --- a/src/Resources/js/modules/dish-selection.js +++ /dev/null @@ -1,330 +0,0 @@ -Mealz.prototype.initDishSelection = function () { - var that = this; - - - $('.day .limit-icon').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - var $this = $(this); - if($this.next('.limit-box').is(':visible')) { - limitBoxSaveClick(); - return; - } else { - $this.parent('.day').siblings().find('.limit-box').each(function () { - limitBoxSaveClick(); - }); - } - var selectedDay = $(this).parent(); - var limitBoxSelectedDay= selectedDay.children('.limit-box'); - // start to build my limit-box - limitBoxSelectedDay.append('

    Limit

    '); - // for each meal selected a day we need a new input row - selectedDay.children('.meal-rows-wrapper').children('.meal-row').each(function(){ - // but we have to distinguish between Meal and Variation - var thisMealRow = $(this); - if(thisMealRow.is('[data-attribute-selected-dish]') && thisMealRow.is('[data-attribute-selected-variations]') && - thisMealRow.attr('data-attribute-selected-variations').length > 0){ - // if a variation is set, we need to find out the name for all variations selected - var mainDishId = parseInt(thisMealRow.attr('data-attribute-selected-dish')); - var mainDishTitle = thisMealRow.find('.dishes[data-attribute-id="'+mainDishId+'"] span.dish-title').text(); - $.each(JSON.parse(thisMealRow.attr('data-attribute-selected-variations')), function(key, value){ - var mealName = thisMealRow.find('.variation').filter('[data-attribute-id='+parseInt(value)+']').find('span').text(); - limitBoxSelectedDay.append('
    '); - }); - } else { - // if it's just a meal, we just need to find the meal Name once - var mealName = ''; - // if the meal is not selected now, we have do catch error cases - if(thisMealRow.attr('data-attribute-selected-dish') !== ''){ - mealName = thisMealRow.find('.dishes').filter('[data-attribute-id=' + thisMealRow.attr('data-attribute-selected-dish') + ']').children('span').text(); - } - // if the mealname is not set hard in form (if you select it the first time) - // we have to take it from the meal-select span - if (mealName.length === 0){ - mealName = thisMealRow.children('.meal-select').children('span').text(); - } - - limitBoxSelectedDay.append('
    '); - } - }); - - // prefill all LimitValues - selectedDay.find('.participation-limit').each(function(i){ - // but only if there is some value - if($(this).val() !== ''){ - $('.limit-input').eq(i).text(parseInt($(this).val())); - } else { - $(selectedDay).children('.limit-icon').removeClass('modified'); - } - }); - - // add Save Button - limitBoxSelectedDay.append('save'); - limitBoxSelectedDay.show('fast'); - }); - - $('.meal-select').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - $('.variation-checkbox.checked', this.prev).closest('li.dishes').find('.variation-button:first').click(); - $(this).prev().toggle(); - }); - - $('.meal-select .remove-meal').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - that.clearDishSelection($(this)); - // disable remove icon - $(this).attr('style', 'display: none;'); - }); - - $('.meal-select-box .dishes').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - that.selectDish($(this), e); - }); - - // Click on 'variations' button to open up variations selection - $('.meal-select-box .dishes .variation-button').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - - var $mealSelectVariations = $(this).next(); - var $dish = $mealSelectVariations.parent('.dishes'); - - if ($mealSelectVariations.is(':visible')) { - that.hideVariationSelectBox(); - } else { - that.hideVariationSelectBox(); - $mealSelectVariations.show(); - $dish.addClass('active'); - } - }); - - $('.meal-select-box .dishes .meal-select-variations .variation-checkbox').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - that.selectVariation($(this)); - }); - - // Click on save button in variations selection - $('.meal-select-variations .button').on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - that.hideSelectBox(); - }); - - // Hiding meal-select-box and limit-box if click anywhere else - $('.meal-form').on('click', function (e) { - e.stopPropagation(); - that.hideSelectBox(); - var isOnSomeBox = false; - var limitBox = $('.limit-box'); - limitBox.each(function(){ - if(!isOnSomeBox){ - isOnSomeBox = $(this).ismouseover(); - } - }); - if(!isOnSomeBox){ - limitBox.hide(); - limitBox.children().remove(); - } - }); -}; - -window.limitBoxSaveClick = function(){ - var thisDay = $('.limit-box').filter(':visible').parent(); - var isOkayToClose = true; - thisDay.find('.limit-input').each(function(i){ - if(Number.isInteger(parseInt($(this).text()))){ - thisDay.find('.participation-limit').eq(i).val(parseInt($(this).text())); - } else if($(this).text() === "") { - - } else { - $(this).css('border-color', 'red'); - isOkayToClose = false; - } - }); - if (isOkayToClose){ - $('.limit-box').hide('fast'); - $('.limit-box').children().remove(); - } -}; - -Mealz.prototype.selectDish = function ($element, e) { - var $mealRow = $element.closest('.meal-row'); - var dishId = $element.data('attribute-id'); - - // If it's a dish without variations - if ($element.attr('data-attribute-parent') !== 'true') { - // add remove icon - $mealRow.find('.remove-meal').attr('style', 'display: block;'); - $mealRow.data('attribute-selected-dish', dishId); - $mealRow.find('.meal-label').text($element.find('.dish-title').html()); - $mealRow.attr('data-attribute-selected-variations', ''); - $mealRow.find('.variation-checkbox').removeClass('checked'); - this.clearAllFormElements($mealRow); - this.createMealFormElement($mealRow, dishId); - this.hideSelectBox(); - } - - // Initialize the participation limit with 0 - if($mealRow.find('.participation-limit').val() === "" ){ - $mealRow.find('.participation-limit').val(0); - } -}; - -Mealz.prototype.selectVariation = function ($element) { - var parentId = $element.closest('.dishes').attr('data-attribute-id'); - var variationId = $element.parent('.variation').data('attribute-id'); - - var $mealRow = $element.closest('.meal-row'); - var variations = []; - var that = this; - - // If data-attribute-selected-dish change, delete variations - if ($mealRow.attr('data-attribute-selected-dish') !== parentId) { - $mealRow.attr('data-attribute-selected-variations', ''); - $mealRow.find('.variation-checkbox.checked').removeClass('checked'); - } - - var previousSelectedVariations = $mealRow.attr('data-attribute-selected-variations'); - - // If data-attribute selected-variations is defined and not empty - if (previousSelectedVariations.length > 0) { - previousSelectedVariations = JSON.parse(previousSelectedVariations); - variations = previousSelectedVariations; - } - - this.toggleArrayItem(variations, variationId); - - // Set meal row data attributes and dropdown label - $mealRow.attr('data-attribute-selected-variations', JSON.stringify(variations)); - this.setDropdownLabelForSelectedVariations($mealRow, parentId, variations); - - $mealRow.attr('data-attribute-selected-dish', parentId); - - // add remove icon - $mealRow.find('.remove-meal').attr('style', 'display: block;'); - - // If checkbox wasn't checked before - if ($element.hasClass('checked') === false) { - // If this is the first selected variation - if (variations.length === 1) { - that.clearAllFormElements($mealRow); - that.createMealFormElement($mealRow, variationId); - // Else (If other variations were selected before) - } else { - // add remove icon - $mealRow.find('.remove-meal').attr('style', 'display: block;'); - that.createMealFormElement($mealRow, variationId); - } - } else { - // If there are still variations selected - if (variations.length > 0) { - // Find and remove input field with the same value like the id of clicked variation - $mealRow.find('.meal-selected').each(function () { - if ($(this).find('input:first').val() == variationId) { - that.deleteSingleSelection($(this)); - } - }); - // Else (If no variation, and therefore no dish, is selected anymore) - } else { - // disable remove icon - $mealRow.find('.remove-meal').attr('style', 'display: none;'); - - // Remove every other input except first - $mealRow.attr('data-attribute-selected-dish', ''); - that.clearAllFormElements($mealRow); - } - } - $element.toggleClass('checked'); -}; - -Mealz.prototype.clearDishSelection = function ($element) { - var $mealRow = $element.closest('.meal-row'); - - // Remove data attribute values from meal-row - $mealRow.attr('data-attribute-selected-dish', ''); - $mealRow.attr('data-attribute-selected-variations', ''); - - // Clear dropdown text - $element.prev('.meal-label').empty(); - - // Remove value (dish id) from default input field and remove others - this.clearAllFormElements($mealRow); - - //Remove tick from variation checkboxes - $mealRow.find('.variation-checkbox.checked').removeClass('checked'); -}; - -Mealz.prototype.setDropdownLabelForSelectedVariations = function (mealRow, parentId, variations) { - var mealRowLabel = mealRow.find('.meal-label'); - if (variations.length > 0) { - var $parentDish = $('li.dishes[data-attribute-id=' + parentId + ']'); - var parentLabel = $parentDish.find('.dish-title').html(); - var variationsLabel = ''; - - for (var i = 0; i < variations.length; i++) { - variationsLabel += (i > 0) ? ', ' : ''; - variationsLabel += $parentDish.find('.variation[data-attribute-id=' + variations[i] + '] span').html(); - } - mealRowLabel.text(parentLabel + ' - ' + variationsLabel); - } else { - mealRowLabel.empty(); - } -}; - -Mealz.prototype.hideSelectBox = function () { - var $activeSelectBox = $('.meal-select-box:visible'); - this.hideVariationSelectBox($activeSelectBox); - $activeSelectBox.hide(); -}; - -Mealz.prototype.hideVariationSelectBox = function ($activeSelectBox) { - if (typeof $activeSelectBox === 'undefined') { - $activeSelectBox = $('.meal-select-box:visible'); - } - - var $activeDish = $activeSelectBox.find('.dishes.active'); - if ($activeDish.length !== 0) { - $activeDish.children('.meal-select-variations:visible').hide(); - $activeDish.removeClass('active'); - } -}; - -Mealz.prototype.createMealFormElement = function ($mealRow, dishId) { - // Get prototype and day id and retrieve prototype form from data-prototype attribute - if (this.prototypeFormId === undefined) { - this.prototypeFormId = $mealRow.closest('.day').find('.meal-selected').length; - } - this.prototypeFormId += 1; - var day = $mealRow.children('.meal-selected:first').find('input:last').val(); - var prototypeForm = $mealRow.parent('.meal-rows-wrapper').data('prototype'); - - // Set prototype, day and dish id in prototype form and append form element to related meal row - prototypeForm = prototypeForm.replace(/__name__/g, this.prototypeFormId); - var $prototypeFormElement = $(prototypeForm).appendTo($mealRow); - $prototypeFormElement.addClass('meal-selected'); - var $prototypeFormElementInputs = $prototypeFormElement.find('input'); - $prototypeFormElementInputs.last().val(day); - $prototypeFormElementInputs.first().val(dishId); - if($mealRow.find('.participation-limit').val() === '') { - $mealRow.find('.participation-limit').val(0); - } -}; - -Mealz.prototype.clearAllFormElements = function ($mealRow) { - var that = this; - $mealRow.find('.meal-selected').each(function () { - that.deleteSingleSelection($(this)); - }); -}; - -Mealz.prototype.deleteSingleSelection = function ($element) { - if ($element.hasClass('meal-persisted') === true) { - $element.find('input:first').val(''); - } else { - $element.remove(); - } -}; diff --git a/src/Resources/js/modules/labels.ts b/src/Resources/js/modules/labels.ts deleted file mode 100644 index 5c6330d22..000000000 --- a/src/Resources/js/modules/labels.ts +++ /dev/null @@ -1,18 +0,0 @@ -export enum TooltipLabel { - OFFERED_MEAL = "offeredMeal", - AVAILABLE_MEAL = "availableMeal" -} - -export interface Tooltip { - offeredMeal: string - availableMeal: string -} - -export interface LocalizedLabels { - tooltip: Tooltip -} - -export interface Labels { - en: LocalizedLabels, - de: LocalizedLabels -} \ No newline at end of file diff --git a/src/Resources/js/modules/lightbox.js b/src/Resources/js/modules/lightbox.js deleted file mode 100644 index b2a175888..000000000 --- a/src/Resources/js/modules/lightbox.js +++ /dev/null @@ -1,13 +0,0 @@ -Mealz.prototype.enableLightbox = function () { - var $container = $('[data-fancybox]'); - - var $options = { - closeClickOutside: false, - smallBtn : false, - infobar : false, - buttons : false, - }; - - $.fancybox.open($container, $options); - -}; diff --git a/src/Resources/js/modules/meal-offer-update-handler.ts b/src/Resources/js/modules/meal-offer-update-handler.ts deleted file mode 100644 index dbc193804..000000000 --- a/src/Resources/js/modules/meal-offer-update-handler.ts +++ /dev/null @@ -1,85 +0,0 @@ -import {ParticipationUpdateHandler} from './participation-update-handler'; -import {MealService} from './meal-service'; - -export enum MealOfferStates { - New = 'new', - Accepted = 'accepted', - Gone = 'gone' -} - -export interface MealOfferUpdate { - state: MealOfferStates; - mealId: number; - participantId?: number; // Updated participant's ID - available?: boolean; // Flag to specify if the meal is still available or not -} - -export class MealOfferUpdateHandler { - - static handleUpdate($checkbox: JQuery, data: MealOfferUpdate): void { - switch (data.state) { - case MealOfferStates.New: - let dishSlug = $checkbox.closest('[data-slug]').data('slug'); - let date = $checkbox.closest('.meal').data('date'); - MealOfferUpdateHandler.handleNewMealOffer($checkbox, date, dishSlug); - - break; - case MealOfferStates.Accepted: - if (data.participantId === undefined) { - console.log('error: invalid meal-offer update; property "offerer-id" not found'); - return; - } - if (data.available === undefined) { - console.log('error: invalid meal-offer update; property "available" not found'); - return; - } - - MealOfferUpdateHandler.handleMealOfferAccepted($checkbox, data.participantId, data.available); - - break; - case MealOfferStates.Gone: - ParticipationUpdateHandler.changeToOfferIsGone($checkbox); - - break; - } - } - - /** - * Handles event when a meal is offered. - */ - static handleNewMealOffer($checkbox: JQuery, date: string, dishSlug: string): void { - if ($checkbox.is(':checked')) { - return; // user already has the meal booked - } - - const nextAction = $checkbox.attr('data-action'); - if (undefined !== nextAction && '' !== nextAction) { - return; // Meal is open to overtake, i.e. accept offered meal - } - - ParticipationUpdateHandler.changeToOfferIsAvailable( - $checkbox, - `/menu/${date}/${dishSlug}/accept-offer` - ); - } - - /** - * Handles event when an offered meals is accepted by some user. - * - * @param $checkbox Meal Checkbox - * @param offererId Participant-ID of the accepted meal - * @param available Is the accepted/taken meal is still available, i.e. still being offered - */ - static handleMealOfferAccepted($checkbox: JQuery, offererId: number, available: boolean): void { - if (isNaN(offererId)) { - console.log('Error: Participant-ID is not a number'); - return; - } - // change participation state for - // - offerer whose meal has been taken, or - // - everyone if meal is no longer available - if (offererId === MealService.getParticipantId($checkbox) || !available) { - ParticipationUpdateHandler.offerAccepted($checkbox, offererId, available); - } - } -} diff --git a/src/Resources/js/modules/meal-service.ts b/src/Resources/js/modules/meal-service.ts deleted file mode 100644 index 7bb0252cf..000000000 --- a/src/Resources/js/modules/meal-service.ts +++ /dev/null @@ -1,33 +0,0 @@ -export class MealService { - static getDate($checkbox: JQuery): string { - const date = $checkbox.closest('[data-date]').data('date'); - if (undefined === date) { - return null; - } - return date; - } - - static getDishSlug($checkbox: JQuery): string { - const slug = $checkbox.closest('[data-slug]').data('slug'); - if (undefined === slug) { - return null; - } - return slug; - } - - static getParticipantId($checkbox: JQuery): number { - let strID = $checkbox.closest('[data-participant-id]').attr('data-participant-id'); - if (undefined === strID) { - return null; - } - - const id = Number(strID); - return isNaN(id) ? null : id; - } - - static setParticipantId($checkbox: JQuery, participantId: number): void { - $checkbox - .closest('[data-participant-id]') - .attr('data-participant-id', participantId ?? ''); - } -} diff --git a/src/Resources/js/modules/mercure-subscribe-handler.ts b/src/Resources/js/modules/mercure-subscribe-handler.ts deleted file mode 100644 index 5ba23c703..000000000 --- a/src/Resources/js/modules/mercure-subscribe-handler.ts +++ /dev/null @@ -1,15 +0,0 @@ -export class MercureSubscribeHandler { - - private eventSource: EventSource; - - constructor(topics: Array, onRecieve: Function) { - - let url = new URL('https://meals.test:8081/.well-known/mercure'); - topics.forEach(topic => { - url.searchParams.append('topic', topic); - }); - - this.eventSource = new EventSource(url); - this.eventSource.onmessage = ({data}) => onRecieve(JSON.parse(data)); - } -} diff --git a/src/Resources/js/modules/participant-counter.ts b/src/Resources/js/modules/participant-counter.ts deleted file mode 100644 index 549000bb1..000000000 --- a/src/Resources/js/modules/participant-counter.ts +++ /dev/null @@ -1,42 +0,0 @@ -export class ParticipantCounter { - public static readonly NAME = 'participant-counter'; - - private readonly mealId: number; - private readonly dishSlug: string; - private readonly day: string; - private readonly dayEnabled: boolean; - private readonly lockDateTime: Date; - - private $participantsCountWrapper: JQuery; - - constructor($participantsActionsWrapper: JQuery) { - this.$participantsCountWrapper = $participantsActionsWrapper.find('.participants-count'); - - this.mealId = $participantsActionsWrapper.data('id'); - this.dishSlug = $participantsActionsWrapper.closest('.meal-row').data('slug'); - if (undefined === this.dishSlug) { - this.dishSlug = $participantsActionsWrapper.closest('.variation-row').data('slug'); - } - - let $meal = this.$participantsCountWrapper.closest('.meal'); - this.day = $meal.data('date'); - this.lockDateTime = new Date(Date.parse($meal.data('lock-date-time'))); - this.dayEnabled = $meal.data('day-enabled') === 1; - } - - getMealId(): number { - return this.mealId; - } - - getDishSlug(): string { - return this.dishSlug; - } - - getDay(): string { - return this.day; - } - - isAvailable(): boolean { - return this.dayEnabled && this.lockDateTime.getTime() > Date.now(); - } -} diff --git a/src/Resources/js/modules/participation-pre-toggle-handler.ts b/src/Resources/js/modules/participation-pre-toggle-handler.ts deleted file mode 100644 index 5d4479761..000000000 --- a/src/Resources/js/modules/participation-pre-toggle-handler.ts +++ /dev/null @@ -1,143 +0,0 @@ -import {CombinedMealDialog, SerializedFormData} from './combined-meal-dialog'; -import Event = JQuery.Event; -import {AbstractParticipationToggleHandler} from './participation-toggle-handler'; -import {ParticipantCounter} from './participant-counter'; -import {CombinedMealOffersService} from './combined-meal-offers-service'; -import {CombinedMealService} from './combined-meal-service'; - -export class ParticipationPreToggleHandler { - private readonly participationToggleHandler: AbstractParticipationToggleHandler; - - constructor(participationToggleHandler: AbstractParticipationToggleHandler) { - this.participationToggleHandler = participationToggleHandler; - this.initEvents(); - } - - private initEvents(): void { - let self = this - $('.checkbox-wrapper').on('click', function (e: Event) { - let $checkboxWrapper = $(this); - if ($checkboxWrapper.hasClass('disabled') || $checkboxWrapper.hasClass('submitting')) { - return; - } - - let $checkbox = $checkboxWrapper.find('input'); - if (undefined === $checkbox) { - console.log('Error: No checkbox found'); - return; - } - - if (self.isUnbookedCombinedDish($checkbox)) { - self.processCombinedMealJoin($checkbox); - } else { - self.participationToggleHandler.toggle($checkbox); - } - }); - } - - private processCombinedMealJoin($checkbox: JQuery): void { - if (this.existDishVariations($checkbox)) { - this.joinCombinedMealWithVariations($checkbox); - } else { - this.joinCombinedMealWithoutVariations($checkbox); - } - } - - private joinCombinedMealWithVariations($checkbox: JQuery) { - let participantCounter: ParticipantCounter = $checkbox.data(ParticipantCounter.NAME); - if (participantCounter.isAvailable()) { - this.executeBeforeToggle($checkbox); - } else { - CombinedMealOffersService.execute($checkbox, this.participationToggleHandler); - } - } - - private joinCombinedMealWithoutVariations($checkbox: JQuery) { - let $mealContainer = $checkbox.closest('.meal'); - let simpleDishSlugs = this.getSimpleDishSlugs($mealContainer); - - if (0 === simpleDishSlugs.length) { - console.log('combined-meal dishes not found'); - return; - } - - let data: SerializedFormData[] = []; - - if (0 !== $mealContainer.find('.slot-selector').length) { - const slotSlug: string = $mealContainer.find('.slot-selector').val().toString(); - data.push({ - 'name': 'slot', - 'value': slotSlug - }); - } - simpleDishSlugs.forEach(function (slug, i) { - data.push({ - 'name': `dishes[${i}]`, - 'value': slug - }); - }); - - this.participationToggleHandler.toggle($checkbox, data); - } - - private existDishVariations($checkbox: JQuery): boolean { - return 0 < $checkbox.closest('.meal').find('.variation-row .text-variation').length; - } - - private isBookedDish($checkbox: JQuery): boolean { - return $checkbox.is(':checked'); - } - - private isCombinedDish($checkbox: JQuery): boolean { - return 0 < $checkbox.closest('.meal-row.combined-meal').length; - } - - private isUnbookedCombinedDish($checkbox: JQuery): boolean { - return this.isCombinedDish($checkbox) && !this.isBookedDish($checkbox); - } - - private getSimpleDishSlugs($mealContainer: JQuery): string[] - { - let dishes: string[] = []; - $mealContainer - .find('.meal-row:not(.combined-meal)') - .each(function() { - dishes.push($(this).data('slug')); - }); - - return dishes; - } - - private executeBeforeToggle($checkbox: JQuery): void { - let self = this; - let $dishContainer = $checkbox.closest('.meal-row'); - let $mealContainer = $dishContainer.closest('.meal'); - - const slotSlug: string = $mealContainer.find('.slot-selector').val().toString(); - const title = $dishContainer.find('.title').text(); - const dishes = CombinedMealService.getDishes($mealContainer); - const $bookedDishIDs = this.getBookedDishSlugs($dishContainer); - let cmd = new CombinedMealDialog( - title, - dishes, - $bookedDishIDs, - slotSlug, - { - ok: function (data) { - self.participationToggleHandler.toggle($checkbox, data); - } - } - ); - cmd.open(); - } - - private getBookedDishSlugs($dishContainer: JQuery): string[] - { - let bookedDishSlugs = $dishContainer.data('bookedDishes') || ''; - if (bookedDishSlugs === '') { - return []; - } - - return bookedDishSlugs.split(',').map((id: string) => id.trim()); - } -} diff --git a/src/Resources/js/modules/participation-request-handler.ts b/src/Resources/js/modules/participation-request-handler.ts deleted file mode 100644 index c90594191..000000000 --- a/src/Resources/js/modules/participation-request-handler.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {ParticipationResponse} from './participation-response-handler'; -import AjaxErrorHandler from './ajax-error-handler'; - -export class ParticipationRequest { - readonly url: string; - readonly data: {}; - readonly method: string; - - constructor(url: string, data?: {}) { - this.url = url; - this.method = 'GET'; - if (data) { - this.data = data - this.method = 'POST' - } - } -} - -type ParticipationResponseHandlerMethod = ($checkbox: JQuery, response: ParticipationResponse) => void; - -export class ParticipationRequestHandler { - public static sendRequest(participationRequest: ParticipationRequest, $checkbox: JQuery, handle: ParticipationResponseHandlerMethod) { - if (undefined === $checkbox) { - console.log('Error: No checkbox found'); - return; - } - - if (undefined === participationRequest.url || '' === participationRequest.url) { - console.log('Error: URL is missing'); - return; - } - - $.ajax({ - method: participationRequest.method, - url: participationRequest.url, - data: participationRequest.data, - dataType: 'json', - beforeSend: function () { - $checkbox.closest('.checkbox-wrapper').toggleClass('submitting'); - }, - success: function (data) { - handle($checkbox, data); - }, - error: function (jqXHR) { - AjaxErrorHandler.handleError(jqXHR, function (){ - if (true === ParticipationRequestHandler.isJoinRequest(participationRequest.url)) { - let mealTitle = $checkbox.closest('.meal-row').children('.title').text(); - let errMsg = $('.weeks').data('errJoinNotPossible').replace('%dish%', mealTitle); - ParticipationRequestHandler.sendAlert(errMsg); - } - }); - }, - complete: function () { - $checkbox.closest('.checkbox-wrapper').toggleClass('submitting'); - } - }); - } - - private static isJoinRequest(url: string): boolean { - return (url.indexOf('join') !== -1); - } - - private static sendAlert(message: string):void { - if (message.length > 0) { - alert(message); - } - } -} diff --git a/src/Resources/js/modules/participation-response-handler.ts b/src/Resources/js/modules/participation-response-handler.ts deleted file mode 100644 index 87895ffdd..000000000 --- a/src/Resources/js/modules/participation-response-handler.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {AcceptOfferData, ParticipationUpdateHandler, ToggleData} from './participation-update-handler'; - -export interface ParticipationResponse { - actionText: string; -} - -export interface ActionResponse extends ParticipationResponse { - url: string; -} - -interface SwapResponse extends ActionResponse { - id: number; // Participant ID -} - -export interface ToggleResponse extends SwapResponse { - participantsCount: number; - bookedDishSlugs: string[]; - slot: string; - available: boolean; -} - - -export class ParticipationResponseHandler { - public static onToggle($checkbox: JQuery, response: ToggleResponse) { - const data: ToggleData = { - participantID: response.id, - actionText: response.actionText, - url: response.url, - participantsCount: response.participantsCount, - bookedDishSlugs: response.bookedDishSlugs, - slot: response.slot, - available: response.available - }; - ParticipationUpdateHandler.toggle($checkbox, data); - } - - public static onAcceptOffer($checkbox: JQuery, response: ToggleResponse) { - const data: AcceptOfferData = { - participantID: response.id, - url: response.url, - participantsCount: response.participantsCount, - bookedDishSlugs: response.bookedDishSlugs, - }; - ParticipationUpdateHandler.acceptOffer($checkbox, data); - } - - public static onOffer($checkbox: JQuery, response: SwapResponse) { - ParticipationUpdateHandler.setOffered($checkbox, response.url, response.id); - } - - public static onRollbackOffer($checkbox: JQuery, response: SwapResponse) { - ParticipationUpdateHandler.rollbackOffer($checkbox, response.url); - } -} diff --git a/src/Resources/js/modules/participation-toggle-handler.ts b/src/Resources/js/modules/participation-toggle-handler.ts deleted file mode 100644 index 783e1176e..000000000 --- a/src/Resources/js/modules/participation-toggle-handler.ts +++ /dev/null @@ -1,150 +0,0 @@ -import {ParticipantCounter} from './participant-counter'; -import {ParticipationResponseHandler} from './participation-response-handler'; -import { - ParticipationRequest, - ParticipationRequestHandler -} from './participation-request-handler'; -import {ConfirmSwapDialog} from './confirm-swap-dialog'; -import {CombinedMealService} from './combined-meal-service'; - -export abstract class AbstractParticipationToggleHandler { - constructor($checkboxes: JQuery) { - this.prepare($checkboxes); - this.initEvents($checkboxes); - } - - public abstract toggle($checkbox: JQuery, data?: {}): void; - - protected initCheckboxState($checkbox: JQuery): void { - let $checkboxWrapper = $checkbox.closest('.checkbox-wrapper'); - $checkboxWrapper.toggleClass('checked', $checkbox.is(':checked')); - } - - private prepare($checkboxes: JQuery): void { - let self = this; - $checkboxes.each(function (idx, checkbox) { - let $checkbox = $(checkbox); - let $actionsWrapper = $checkbox.closest('.wrapper-meal-actions'); - $checkbox.data(ParticipantCounter.NAME, new ParticipantCounter($actionsWrapper)); - self.initCheckboxState($checkbox); - }); - } - - private initEvents($checkboxes: JQuery): void { - $checkboxes.on('click', function (e) { - e.preventDefault(); - e.stopPropagation(); - }); - } -} - -export class ParticipationToggleHandler extends AbstractParticipationToggleHandler { - public toggle($checkbox: JQuery, data?: {}) { - const action = $checkbox.attr('data-action'); - if ('join' === action && undefined === data && $checkbox.closest('.meal').find('.slot-selector').length !== 0) { - let slotSlug: string = $checkbox.closest('.meal').find('.slot-selector').val().toString(); - data = { 'slot': slotSlug } - } else if ('join' === action && undefined === data) { - data = {} - } - - const url = $checkbox.attr('value'); - let request = new ParticipationRequest(url, data); - - switch (action) { - case 'join': - case 'delete': - ParticipationRequestHandler.sendRequest(request, $checkbox, ParticipationResponseHandler.onToggle); - break; - case 'acceptOffer': - ParticipationRequestHandler.sendRequest(request, $checkbox, ParticipationResponseHandler.onAcceptOffer); - break; - case 'rollbackOffer': - ParticipationRequestHandler.sendRequest(request, $checkbox, ParticipationResponseHandler.onRollbackOffer); - break; - case 'offer': - let dialog = new ConfirmSwapDialog({ - participationRequest: request, - $checkbox: $checkbox, - handlerMethod: ParticipationResponseHandler.onOffer, - }); - dialog.open(); - break; - } - } - - protected initCheckboxState($checkbox: JQuery): void { - let $checkboxWrapper = $checkbox.closest('.checkbox-wrapper'); - $checkboxWrapper.toggleClass('checked', $checkbox.is(':checked')); - $checkboxWrapper.toggleClass('disabled', $checkbox.is(':disabled')); - } -} - -export class ParticipationGuestToggleHandler extends AbstractParticipationToggleHandler { - public toggle($checkbox: JQuery, data?: any) { - let $dishContainer = $checkbox.closest('.meal-row'); - if (CombinedMealService.isCombinedDish($dishContainer)) { - this.updateDishSelection($checkbox, data); - } - - $checkbox.prop('checked', !$checkbox.is(':checked')); - let $checkboxWrapper = $checkbox.closest('.checkbox-wrapper'); - $checkboxWrapper.toggleClass('checked', $checkbox.is(':checked')); - } - - private updateDishSelection($checkbox: JQuery, data?: Array) { - let dishSelectionWrapperSelector = 'dish-selection-wrapper'; - let $meal = $checkbox.closest('.meal'); - let $dishContainer = $checkbox.closest('.meal-row'); - let $dishSelectionWrapper = $dishContainer.find('#' + dishSelectionWrapperSelector); - if (0 === $dishSelectionWrapper.length) { - $dishSelectionWrapper = $('
    '); - $dishContainer.append($dishSelectionWrapper); - } else { - this.updateCombinedDishDesc($dishContainer, []); - $dishSelectionWrapper.empty(); - } - - if (undefined === data) { - return; - } - - let selectedDishes: Array = new Array(); - data.filter(entry => entry.name.startsWith('dishes')).forEach(entry => { - let $dishSelectionField = ''; - $dishSelectionWrapper.append($dishSelectionField); - - let $mealWrapper = $meal.find('[data-slug="' + entry.value + '"]'); - let $dishTitle; - if ($mealWrapper.hasClass('meal-row')) { - $dishTitle = $mealWrapper.find('.title'); - } else if ($mealWrapper.hasClass('variation-row')) { - $dishTitle = $mealWrapper.find('.text-variation'); - } - selectedDishes.push($dishTitle.text()); - }); - - this.updateCombinedDishDesc($dishContainer, selectedDishes); - } - - private updateCombinedDishDesc($dishContainer: JQuery, dishSlugs: string[]): void { - let $dishDesc = $dishContainer.find('.description').empty(); - if (0 === dishSlugs.length) { - $dishDesc.text($dishContainer.data('description')); - $dishContainer.find('.title').addClass('no-description'); - return; - } - - let $dishList = $('
    '); - dishSlugs.forEach(function (dishSlug: string) { - $dishList.append(`
    ${dishSlug}
    `) - }); - $dishDesc.append($dishList); - $dishContainer.find('.title').removeClass('no-description'); - } -} - -class Entry { - name: string; - value: string; -} diff --git a/src/Resources/js/modules/participation-update-handler.ts b/src/Resources/js/modules/participation-update-handler.ts deleted file mode 100644 index 6bf9ca434..000000000 --- a/src/Resources/js/modules/participation-update-handler.ts +++ /dev/null @@ -1,459 +0,0 @@ -import {Labels, TooltipLabel} from './labels'; -import {CombinedMealService} from './combined-meal-service'; -import {MealService} from './meal-service'; - -/** - * Meal States - */ -export enum State { - OPEN = 1, // Open for participation - CLOSED, // Closed for participation - BOOKED, // Booked; further participation is possible - BOOKED_AND_CLOSED, // Booked; further participation is not possible - OFFERED, // Booked and offered; further participation is not possible -} - -export interface AcceptOfferData { - participantID: number - url: string; - participantsCount: number; - bookedDishSlugs: string[]; -} - -export interface ToggleData extends AcceptOfferData { - actionText: string; - slot: string; - available: boolean -} - -export interface ParticipationUpdateData { - mealId: number; - count: number; - available: boolean; - availableWith?: string[]; - locked: boolean; -} - -interface CheckboxAttributes { - value: string; - checked: boolean; - disabled: boolean; - action: string; -} - -interface Status { - state: State; - action?: string; - actionURL?: string; - count?: number; - participantID?: number; -} - -export class ParticipationUpdateHandler { - /** - * Handles event when a user successfully accepts an offered meal. - * - * @param $checkbox Meal Checkbox - * @param data Server response - */ - public static acceptOffer($checkbox: JQuery, data: AcceptOfferData): void { - this.updateStatus($checkbox, { - state: State.BOOKED_AND_CLOSED, - action: 'offer', - actionURL: data.url - }); - this.toggleTooltip($checkbox); - - let $dishContainer = $checkbox.closest('.meal-row'); - if (1 > $dishContainer.length) { - return; - } - - if (CombinedMealService.isCombinedDish($dishContainer)) { - CombinedMealService.updateDishes($checkbox, data.participantID, data.bookedDishSlugs); - } - } - - public static updateParticipation(data: ParticipationUpdateData[]) { - for (const [mealId, update] of Object.entries(data)) { - let $checkbox = $(`div[data-id=${mealId}] input[type=checkbox]`); - if (1 > $checkbox.length) { - console.error(`checkbox not found, mealId: ${mealId}`); - continue; - } - - const state = ParticipationUpdateHandler.getNextState( - $checkbox, - $checkbox.prop('checked'), - update.available, - update.locked - ); - const [action, url] = ParticipationUpdateHandler.stateToAction($checkbox, state); - ParticipationUpdateHandler.updateStatus($checkbox, { - state: state, - count: update.count, - action: action, - actionURL: url - }); - - let $mealContainer = $checkbox.closest('.meal-row'); - if (1 > $mealContainer.length) { - continue; - } - - if (update.availableWith === undefined) { - $mealContainer.attr('data-available-dishes', ''); - } else { - $mealContainer.attr('data-available-dishes', update.availableWith.join(',')) - } - } - } - - public static changeToAssignedSlot($checkbox: JQuery, slot: string){ - $checkbox - .closest('.meal') - .find('[value='+ slot +']') - .prop('selected', 'selected'); - } - - /** - * Handles event when a meal is offered to be taken over by other users. - * - * @param $checkbox Meal Checkbox - * @param url URL to send the accept-meal request - */ - public static changeToOfferIsAvailable($checkbox: JQuery, url: string) { - this.updateStatus($checkbox, { - state: State.OPEN, - action: 'acceptOffer', - actionURL: url - }); - this.toggleTooltip($checkbox, TooltipLabel.AVAILABLE_MEAL); - } - - /** - * Handles event when an offered meal is accepted by some user. - * - * @param $checkbox Meal Checkbox - * @param offererId Participant-ID of the accepted meal - * @param available Weather or not the accepted/taken meal is still available, i.e. still being offered - */ - public static offerAccepted($checkbox: JQuery, offererId: number, available: boolean = false) { - let $dishContainer = $checkbox.closest('.meal-row'); - if (1 > $dishContainer.length) { - console.error('dish container not found'); - return; - } - - // unset OFFERED state if participant-ID and offerer-ID are same, i.e. current user's meal got accepted - if (offererId === MealService.getParticipantId($checkbox)) { - if (available) { - ParticipationUpdateHandler.updateStatus($checkbox, { - state: State.OPEN, - action: 'acceptOffer', - actionURL: ParticipationUpdateHandler.getURL($checkbox, 'acceptOffer'), - participantID: null - }); - } else { - ParticipationUpdateHandler.updateStatus($checkbox, { state: State.CLOSED }); - } - - if (CombinedMealService.isCombinedDish($dishContainer)) { - CombinedMealService.updateDishes($checkbox, undefined, []); - } - - this.toggleTooltip($checkbox, available ? TooltipLabel.AVAILABLE_MEAL : undefined); - return; - } - - // set participation state for other users - const nextState = ParticipationUpdateHandler.getNextState( - $checkbox, - $checkbox.prop('checked'), - available, - true - ); - this.updateStatus($checkbox, {state: nextState}); - - if (nextState === State.CLOSED || nextState === State.BOOKED_AND_CLOSED) { - this.toggleTooltip($checkbox); - } - } - - public static changeToOfferIsGone($checkbox: JQuery) { - const nextState = ParticipationUpdateHandler.getNextState( - $checkbox, - $checkbox.prop('checked'), - false, - true - ); - this.updateStatus($checkbox, {state: nextState}); - } - - public static rollbackOffer($checkbox: JQuery, url: string) { - this.updateStatus($checkbox, { - state: State.BOOKED_AND_CLOSED, - action: 'offer', - actionURL: url - }); - this.toggleTooltip($checkbox); - } - - /** - * Mark meal as offered. - * - * @param $checkbox Meal Checkbox - * @param url Offer Rollback URL - * @param participantId Meal participant ID - */ - public static setOffered($checkbox: JQuery, url: string, participantId: number) { - this.updateStatus($checkbox, { - state: State.OFFERED, - action: 'rollbackOffer', - actionURL: url, - participantID: participantId - }); - this.toggleTooltip($checkbox, TooltipLabel.OFFERED_MEAL); - } - - public static toggle($checkbox: JQuery, data: ToggleData): void { - const state = ParticipationUpdateHandler.getNextState( - $checkbox, - !$checkbox.prop('checked'), - data.available, - false - ); - - let nextAction, participantId; - if ('deleted' === data.actionText) { - nextAction = 'join'; - participantId = null; - } else { - nextAction = 'delete'; - participantId = data.participantID; - } - - ParticipationUpdateHandler.updateStatus($checkbox, { - state: state, - count: data.participantsCount, - action: nextAction, - actionURL: data.url, - participantID: participantId - }); - - if ('added' === data.actionText && data.slot !== '') { - ParticipationUpdateHandler.changeToAssignedSlot($checkbox, data.slot); - } - - let $dishContainer = $checkbox.closest('.meal-row'); - if (1 > $dishContainer.length) { - return; - } - - if (CombinedMealService.isCombinedDish($dishContainer)) { - CombinedMealService.updateDishes($checkbox, data.participantID, data.bookedDishSlugs); - } - } - - private static getURL($checkbox: JQuery, action: string): string { - if ('join' === action || 'acceptOffer' === action) { - const date = MealService.getDate($checkbox); - if (null === date) { - return ''; - } - - const dishSlug = MealService.getDishSlug($checkbox); - if (null === dishSlug) { - return ''; - } - - if ('join' === action) { - return `/menu/${date}/${dishSlug}/join`; - } - - return `/menu/${date}/${dishSlug}/accept-offer`; - } - - const participantId = MealService.getParticipantId($checkbox); - if (null === participantId) { - return ''; - } - - switch (action) { - case 'delete': - return `/menu/meal/${participantId}/delete`; - case 'offer': - return `/menu/meal/${participantId}/offer-meal`; - case 'rollbackOffer': - return `/menu/meal/${participantId}/cancel-offered-meal`; - } - - return ''; - } - - /** - * @param $checkbox Meal Checkbox - * @param check Weather or not the meal checkbox be checked - * @param available Weather or not the meal is available - * @param locked Weather or not the meal is locked - * @private - */ - private static getNextState($checkbox: JQuery, check: boolean, available: boolean, locked: boolean): State { - if (available) { - // no participation, and meal is not locked - if (!check && !locked) { - return State.OPEN; - } - // no participation, and meal is locked - if (!check && locked) { - return State.CLOSED; - } - // participation, and meal is locked - if (check && locked) { - return ('rollbackOffer' === $checkbox.attr('data-action')) ? State.OFFERED : State.BOOKED_AND_CLOSED; - } - if (check && !locked) { - return State.BOOKED; - } - } - - // no participation, and meal is not available - if (!check) { - return State.CLOSED; - } - - // participation, and meal is not available - return State.BOOKED_AND_CLOSED; - } - - private static updateStatus($checkbox: JQuery, status: Status): void { - const state = status.state; - const checked = state === State.BOOKED || state === State.BOOKED_AND_CLOSED || state === State.OFFERED; - const disabled = state === State.CLOSED; - - let attrs: Partial = { - checked: checked, - disabled: disabled, - }; - - if (State.CLOSED === state) { - attrs.action = null; - attrs.value = ''; - } else { - attrs.action = status.action; - attrs.value = status.actionURL; - } - - ParticipationUpdateHandler.updateCheckboxAttributes($checkbox, attrs); - ParticipationUpdateHandler.updateCheckboxWrapper($checkbox); - - if (undefined !== status.participantID) { - MealService.setParticipantId($checkbox, status.participantID); - } - - ParticipationUpdateHandler.setCount($checkbox, state, status.count); - } - - private static setCount($checkbox: JQuery, state: State, count?: number): void { - let $countContainer = $checkbox.closest('.wrapper-meal-actions').find('.participants-count'); - if (1 > $countContainer.length) { - return; - } - - $countContainer.removeClass().addClass('participants-count'); - - switch (state) { - case State.OPEN: - if ('acceptOffer' === $checkbox.attr('data-action')) { - $countContainer.addClass('offer-available'); - } - case State.BOOKED: - $countContainer.addClass('participation-allowed'); - break; - case State.OFFERED: - $countContainer.addClass('participation-pending'); - break; - } - - if (undefined === count) { - return; - } - - let partCount = $countContainer.find('.count'); - if (0 < partCount.length) { - partCount.text(count); - } - } - - private static toggleTooltip($checkbox: JQuery, label?: TooltipLabel) { - let $tooltip = $checkbox.closest('.wrapper-meal-actions').find('.tooltiptext'); - if (undefined !== label) { - $.getJSON('/labels.json') - .done(function (labels: Labels) { - if ('de' === $('.language-switch').find('span').text()) { - $tooltip.text(labels.de.tooltip[label]); - } else { - $tooltip.text(labels.en.tooltip[label]); - } - $tooltip.addClass('active'); - }); - } else { - $tooltip.removeClass('active'); - } - } - - private static updateCheckboxWrapper($checkbox: JQuery) { - $checkbox - .closest('.checkbox-wrapper') - .toggleClass('checked', $checkbox.is(':checked')) - .toggleClass('disabled', $checkbox.is(':disabled')); - } - - /** - * @param $checkbox Meal Checkbox - * @param attrs Checkbox attributes - * @private - */ - private static updateCheckboxAttributes($checkbox: JQuery, attrs: Partial) { - if (undefined !== attrs.checked) { - $checkbox.prop('checked', attrs.checked).trigger('change'); - if (false === attrs.checked) { - $checkbox.removeAttr('checked'); - } - } - if (undefined !== attrs.disabled) { - $checkbox.prop('disabled', attrs.disabled); - if (false === attrs.disabled) { - $checkbox.removeAttr('disabled'); - } - } - if (undefined !== attrs.action) { - if (null === attrs.action) { - $checkbox.removeAttr('data-action'); - } else { - $checkbox.attr('data-action', attrs.action); - } - } - if (undefined !== attrs.value) { - $checkbox.attr('value', attrs.value); - } - } - - /** - * Returns the (next) action and corresponding request URL to the given meal state. - */ - private static stateToAction($checkbox: JQuery, state: State): string[] { - switch (state) { - case State.OPEN: - return ['join', ParticipationUpdateHandler.getURL($checkbox, 'join')]; - case State.CLOSED: - return [null, '']; - case State.BOOKED: - return ['delete', ParticipationUpdateHandler.getURL($checkbox, 'delete')]; - case State.OFFERED: - return ['rollbackOffer', ParticipationUpdateHandler.getURL($checkbox, 'rollbackOffer')]; - case State.BOOKED_AND_CLOSED: - return ['offer', ParticipationUpdateHandler.getURL($checkbox, 'offer')]; - } - } -} diff --git a/src/Resources/js/modules/paypal.js b/src/Resources/js/modules/paypal.js deleted file mode 100644 index 78fd4a309..000000000 --- a/src/Resources/js/modules/paypal.js +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Logic for payment method "PayPal" - */ -Mealz.prototype.enablePaypal = function () { - var amountField = $('#ecash_amount'); - - // Disable usage of "Enter" button in the input field to avoid POST request of form - amountField.on('keypress', function (e) { - if (e.key === 'Enter') { - e.preventDefault(); - } - }); - - // Render PayPal buttons initially - renderPaypalButtons(); - - // Only show PayPal buttons when the according radio button is chosen - $('#ecash_paymethod input').on('click', function (event) { - if (event.target.id === 'ecash_paymethod_0') { - renderPaypalButtons(); - } else { - $('.paypal-buttons').remove(); - } - }); - - /* - * Render PayPal buttons and handle user input and requests - */ - function renderPaypalButtons() { - if ($('.paypal-buttons').length === 0) { - var invalidAmountMessage = $('.invalid-amount'); - - paypal.Buttons({ - - // Form validation - onInit: function (data, actions) { - if (amountField[0].checkValidity() === true && parseFloat(amountField.val().replace(/,/g, '.')) > 0.00) { - actions.enable(); - } else { - actions.disable(); - } - - amountField.change(function () { - // Replace a comma with a point and parse the input string to a float - var amountFieldValue = parseFloat(amountField.val().replace(/,/g, '.')); - - amountField[0].setCustomValidity(''); - - // If the input is valid (matches the HTML pattern: "\d*([.,]?\d{0,2})") and the value is above 0.00.. - if (amountField[0].checkValidity() === true && amountFieldValue > 0.00) { - - // ..and the language is set to German.. - if ($('.language-switch').find('span').text() === 'de') { - - // ..add missing decimal places and render the amount in the comma format. - amountField.val(amountFieldValue.toFixed(2).replace(/\./g, ',')); - - // If the language is set to English.. - } else { - - // ..add missing decimal places and render the amount in the point format. - amountField.val(amountFieldValue.toFixed(2)); - } - - // Enable PayPal buttons and remove the warning message. - actions.enable(); - invalidAmountMessage.hide(); - } else { - actions.disable(); - invalidAmountMessage.show(); - amountField[0].setCustomValidity('Invalid field'); - } - }); - - }, - - onClick: function () { - if (amountField[0].checkValidity() === false || parseFloat(amountField[0].value.replace(/,/g, '.')) <= 0.00) { - invalidAmountMessage.show(); - amountField[0].setCustomValidity('Invalid field'); - } - }, - - onCancel: function (data, actions) { - window.location.reload(); - }, - - onError: function (err) { - // if its the "Window navigated away" Error which always happens caused by redirect - ignore it - if (err.text() !== 'Window navigated away') { - return fetch('/payment/ecash/form/submit', { - method: 'post', - headers: { - 'content-type': 'application/json' - }, - }).then(function (redirect) { - if (redirect.status === 200 && redirect.redirected === false) { - return (redirect.text()); - } - }).then(function (redirect) { - actions.redirect(window.location.origin + redirect); - }); - } - }, - - // Set up the transaction - createOrder: function (data, actions) { - $('.form-header').hide(); - return actions.order.create({ - purchase_units: [{ - amount: { - value: formatCurrency(amountField.val()) - } - }] - }); - }, - onApprove: function (data, actions) { - return actions.order.capture().then(function (details) { - $('#ecash_orderid').val(data.orderID); - return fetch('/payment/ecash/form/submit', { - method: 'post', - headers: { - 'content-type': 'application/json' - }, - body: JSON.stringify( - $('form[name="ecash"]').serializeArray() - ) - }).then(function (response) { - if (response.status !== 200) { - return '/payment/ecash/transaction/failure'; - } - if (response.status === 200 && response.redirected === false) { - return (response.text()); - } - }).then(function (redirectPath) { - return actions.redirect(window.location.origin + redirectPath); - }); - }); - } - }).render('.paypal-button-container'); - } - } - - /* - * Format amount input field - */ - function formatCurrency(total) { - var neg = false; - if (total < 0) { - neg = true; - total = Math.abs(total); - } - return (neg ? '-' : '') + parseFloat(total.replace(/,/g, '.')).toFixed(2).toString(); - } -}; diff --git a/src/Resources/js/modules/slot-allocation-update-handler.ts b/src/Resources/js/modules/slot-allocation-update-handler.ts deleted file mode 100644 index aa5ee2bbf..000000000 --- a/src/Resources/js/modules/slot-allocation-update-handler.ts +++ /dev/null @@ -1,36 +0,0 @@ -interface SlotAllocationUpdate { - date: Date; - slotAllocation: { - // key: slot, value: allocation count - [key: string]: number; - }; -} - -export class SlotAllocationUpdateHandler { - static handleUpdate(data: SlotAllocationUpdate): void { - let $slotSelector = $(`#day-${data.date}-slots`); - if (1 !== $slotSelector.length) { - return; - } - - for (const [slot, count] of Object.entries(data.slotAllocation)) { - let $slotOption = $slotSelector.find(`option[value="${slot}"]`); - if (1 !== $slotOption.length) { - continue; - } - - const slotLimit = $slotOption.data('limit'); - if (slotLimit > 0) { - const slotTitle = $slotOption.data('title'); - const slotText = `${slotTitle} (${count}/${slotLimit})`; - $slotOption - .text(slotText) - .prop('disabled', slotLimit <= count); // disable slot-option if no. of booked slots reach the slot limit - } - - if ('' !== $slotSelector.val()) { - $slotSelector.find('option[value=""]').hide(); - } - } - } -} diff --git a/src/Resources/js/modules/style-form-elements.js b/src/Resources/js/modules/style-form-elements.js deleted file mode 100644 index f790b554b..000000000 --- a/src/Resources/js/modules/style-form-elements.js +++ /dev/null @@ -1,96 +0,0 @@ -import Switchery from 'switchery.js'; - -Mealz.prototype.styleCheckboxes = function () { - var that = this; - - // Week detail view - if (this.weekCheckbox && this.$weekDayCheckboxes && this.notifyCheckbox) { - // Enable switchery for week days - this.weekDaySwitchery = []; - this.$weekDayCheckboxes.each(function (idx, checkbox) { - that.weekDaySwitchery.push(new Switchery(checkbox)); - }); - - // Enable switchery for week - var weekSwitchery = new Switchery(this.weekCheckbox); - $(weekSwitchery.switcher) - .detach() - .appendTo('.meal-form .headline-tool .switchery-placeholder'); - - // Enable switchery for notifyCheckbox - var notifySwitchery = new Switchery(this.notifyCheckbox); - $(notifySwitchery.switcher) - .detach() - .appendTo('.meal-form .week-notify-action'); - - // Toggle day switcher and dropdown state on changed week state - this.weekCheckbox.onchange = function () { - that.applySwitcheryStates(); - that.applyDropdownStatesByWeekState(); - }; - - // Toggle dropdown state on changed day state - this.$weekDayCheckboxes.on('change', function () { - that.applyDropdownStates(this); - }); - - // Enable checkboxes before submit, otherwise they will be set to false - $('.meal-form .week-form > form').on('submit', function () { - for (var i = 0; i < that.weekDaySwitchery.length; i++) { - var current = that.weekDaySwitchery[i]; - if (current.isDisabled()) { - current.enable(); - current.switcher.style.opacity = 0.5; - } - } - }); - } -}; - -Mealz.prototype.styleSelects = function () { - this.$selects - .wrap('
    ') - .parent().append(''); -}; - -Mealz.prototype.applySwitcheryStates = function () { - - // disable all day checkboxes in disabled week - for (var i = 0; i < this.weekDaySwitchery.length; i++) { - - // if enable is called on a already enabled switchery element, you can't switch - // its status anymore by clicking (see https://github.com/abpetkov/switchery/issues/103) - var weekDayDisabled = this.weekDaySwitchery[i].isDisabled(); - - if (weekDayDisabled === true) { - this.weekDaySwitchery[i].enable(); - } else if (weekDayDisabled === false) { - this.weekDaySwitchery[i].disable(); - } else { - this.weekDaySwitchery[i].disable(); - } - } -}; - -Mealz.prototype.applyDropdownStatesByWeekState = function () { - var that = this; - - $.each(this.$weekDayCheckboxes, function (i, e) { - if ($(e).parent().parent().find('.week-day-action .js-switch').prop('checked') === true) { - that.applyDropdownStates(e); - } - }); -}; - -Mealz.prototype.applyDropdownStates = function (e) { - $(e).parent().siblings(this.mealRowsWrapperClassSelector).toggleClass('disabled'); -}; - -Mealz.prototype.initButtonHandling = function () { - var that = this; - - // click handling for add button - this.$profileAdd.on('click', function() { - that.addProfile($(this)); - }); -}; diff --git a/src/Resources/js/modules/tables.js b/src/Resources/js/modules/tables.js deleted file mode 100644 index 2648345e4..000000000 --- a/src/Resources/js/modules/tables.js +++ /dev/null @@ -1,24 +0,0 @@ -const DataTable = require( 'datatables.net/js/jquery.dataTables' ); -$.fn.dataTable = DataTable; - -// Provide access to the host jQuery object (circular reference) -DataTable.$ = $; - -// With a capital `D` we return a DataTables API instance rather than a -// jQuery object -$.fn.DataTable = function ( opts ) { - return $(this).dataTable( opts ).api(); -}; - -Mealz.prototype.enableSortableTables = function () { - $('.table-sortable').DataTable({ - 'aaSorting': [], // Disable initial sort - paging: false, - searching: false, - info: false, - columnDefs: [{ - targets: 'no-sort', - orderable: false - }] - }); -}; diff --git a/src/Resources/js/modules/toggle-hidden-users.js b/src/Resources/js/modules/toggle-hidden-users.js deleted file mode 100644 index e24e948fc..000000000 --- a/src/Resources/js/modules/toggle-hidden-users.js +++ /dev/null @@ -1,43 +0,0 @@ -import Switchery from 'switchery.js'; - -Mealz.prototype.initHiddenUsersToggler = function () { - const self = this; - let checkbox = document.querySelector('#toggle-hidden-users') - if (checkbox === null) - return - - let state = checkbox.checked - - // reload cached state - let showHiddenUsers = localStorage.getItem('showHiddenUsers') - if (showHiddenUsers !== null) { - let cachedState = showHiddenUsers === 'true' - if (state !== cachedState) { - state = cachedState - if (cachedState) { - checkbox.setAttribute('checked', 'checked') - } - else { - checkbox.removeAttribute('checked') - } - } - } - - self.toggleHiddenUsers(state) - - new Switchery(checkbox, { - onChange: function (state) { - self.toggleHiddenUsersChangeHandler(state); - } - }); -}; - -Mealz.prototype.toggleHiddenUsersChangeHandler = function (state) { - Mealz.prototype.toggleHiddenUsers(state) - localStorage.setItem('showHiddenUsers', state) -}; - -Mealz.prototype.toggleHiddenUsers = function(state) { - let userRow = $('.user-hidden') - state ? userRow.show() : userRow.hide() -} \ No newline at end of file diff --git a/src/Resources/js/modules/transactions-export.js b/src/Resources/js/modules/transactions-export.js deleted file mode 100644 index b13df2210..000000000 --- a/src/Resources/js/modules/transactions-export.js +++ /dev/null @@ -1,16 +0,0 @@ -Mealz.prototype.exportTransactions = function () { - - $(function () { - $('.date-range-picker').daterangepicker({ - startDate: $('input[name="min-date"]').val(), - endDate: $('input[name="max-date"]').val() - }, function (start, end, label) { - window.location.replace($('input[name="page-url"]').val() + '/' + start.format('YYYY-MM-DD') + '&' + end.format('YYYY-MM-DD')); - }); - }); - - $('.pdf-export').on('click', function (e) { - var url = $('input[name="export-url"]').val() + '/' + $('input[name="min-date"]').val().replace(/\//g, '-') + '&' + $('input[name="max-date"]').val().replace(/\//g, '-'); - window.open(url); - }); -}; diff --git a/src/Resources/js/types/index.d.ts b/src/Resources/js/types/index.d.ts deleted file mode 100644 index 60f8197c4..000000000 --- a/src/Resources/js/types/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'switchery.js'; diff --git a/src/Resources/js/views/adminParticipationEdit.ts b/src/Resources/js/views/adminParticipationEdit.ts deleted file mode 100644 index d6252993d..000000000 --- a/src/Resources/js/views/adminParticipationEdit.ts +++ /dev/null @@ -1,363 +0,0 @@ -import {CombinedMealDialog, SerializedFormData} from '../modules/combined-meal-dialog'; -import {Dish, DishVariation} from '../modules/combined-meal-service'; -import AjaxErrorHandler from '../modules/ajax-error-handler'; - -interface DeleteResponseData { - participantsCount: number; - url: string; -} - -interface JoinResponseData { - id: number, - participantsCount: number; - url: string; - bookedDishSlugs: string[]; -} - -// function type for request success/failure handlers -type ReqFailureFn = (error: string) => void; -type ReqSuccessFn = (data: unknown) => void; - -enum MealToggleAction { - Join = 'join', - Cancel = 'delete' -} - -export default class AdminParticipationEditView { - constructor() { - this.initEvents(); - } - - private initEvents(): void { - $('.table-content') - // edit meal participation - .on( - 'click', - '.table-row .table-data.text', - this.handleEditMealParticipation - ) - // toggle simple meal participation - .on( - 'click', - '.table-row.editing .meal-participation[data-combined=0]', - this.handleToggleSimpleMealParticipation.bind(this) - ) - // toggle combined meal participation - .on( - 'click', - '.table-row.editing .meal-participation[data-combined=1]', - this.handleToggleCombinedMealParticipation.bind(this) - ); - } - - private handleEditMealParticipation(event: JQuery.TriggeredEvent): void { - let $participantRow = $(event.target).closest('.table-row'); - const $isParticipantRowEditable = $participantRow.hasClass('editing'); - - // reset previous editable user row (if any) - $participantRow.closest('.table').find('.table-row.editing').each(function(idx, participantRow){ - $(participantRow) - .removeClass('editing') - .find('.table-data').each(function(idx, mealContainer){ - let $mealContainer = $(mealContainer); - let iconClass = 'glyphicon'; - if ($mealContainer.hasClass('participating')) { - iconClass += ' glyphicon-ok'; - } - $mealContainer.find('i:first').attr('class', iconClass); - }); - }); - - // selected user row was in edit mode, and now has been reset; do nothing - if ($isParticipantRowEditable) { - return; - } - - // make current participant row editable - $participantRow.addClass('editing') - $participantRow.find('.table-data').each(function(idx, mealContainer){ - let $mealContainer = $(mealContainer); - const participationStatusIconClass = $mealContainer.hasClass('participating') ? 'glyphicon-check' : 'glyphicon-unchecked'; - $mealContainer.find('i:first').addClass(participationStatusIconClass); - }); - } - - private handleToggleSimpleMealParticipation(event: JQuery.TriggeredEvent): void { - let $mealContainer = $(event.target).closest('[data-combined]'); - const action = $mealContainer.attr('data-action') as MealToggleAction; - if (action === MealToggleAction.Join) { - this.joinSimpleMeal($mealContainer); - } else { - this.cancelSimpleMeal($mealContainer); - } - } - - private joinSimpleMeal($mealContainer: JQuery): void { - const url = $mealContainer.attr('data-action-url'); - this.sendRequest( - url, - null, - (data: JoinResponseData) => AdminParticipationEditView.simpleMealJoinSuccess($mealContainer, data), - (error: string) => AdminParticipationEditView.toggleFailure(error, MealToggleAction.Join, url) - ); - } - - private static simpleMealJoinSuccess($mealContainer: JQuery, data: JoinResponseData): void { - $mealContainer - .attr('data-action-url', data.url) - .attr('data-action', MealToggleAction.Cancel) - .toggleClass('participating') - .find('i:first') - .removeClass('glyphicon-unchecked') - .addClass('glyphicon-check'); - - const dishSlug = $mealContainer.data('dishSlug'); - const day = $mealContainer.data('date'); - AdminParticipationEditView.updateParticipantCount(dishSlug, day, data.participantsCount); - } - - private cancelSimpleMeal($mealContainer: JQuery): void { - const url = $mealContainer.attr('data-action-url'); - this.sendRequest( - url, - null, - (data: DeleteResponseData) => AdminParticipationEditView.simpleMealCancelSuccess($mealContainer, data), - (error: string) => AdminParticipationEditView.toggleFailure(error, MealToggleAction.Cancel, url) - ); - } - - private static simpleMealCancelSuccess($mealContainer: JQuery, data: DeleteResponseData): void { - $mealContainer - .attr('data-action-url', data.url) - .attr('data-action', MealToggleAction.Join) - .toggleClass('participating') - .find('i:first') - .removeClass('glyphicon-check') - .addClass('glyphicon-unchecked'); - - const dishSlug = $mealContainer.data('dishSlug'); - const day = $mealContainer.data('date'); - AdminParticipationEditView.updateParticipantCount(dishSlug, day, data.participantsCount); - } - - private handleToggleCombinedMealParticipation(event: JQuery.TriggeredEvent): void { - let $mealContainer = $(event.target).closest('[data-combined]'); - const action = $mealContainer.attr('data-action'); - - if (MealToggleAction.Cancel === action) { - this.cancelCombinedMeal($mealContainer); - return; - } - - this.joinCombinedMeal($mealContainer); - } - - private joinCombinedMeal($mealContainer: JQuery): void { - const day = $mealContainer.data('date'); - let dishes = AdminParticipationEditView.getDishesOn(day); - const dishSlug = $mealContainer.data('dishSlug'); - const dish = AdminParticipationEditView.findDish(dishSlug, dishes); - - if (null === dish) { - console.log(`dish not found, slug: ${dishSlug}`); - return; - } - - if (AdminParticipationEditView.dishesContainVariation(dishes)) { - this.joinCombinedMealWithVariations($mealContainer); - } else { - this.joinCombinedMealWithoutVariations($mealContainer); - } - } - - private joinCombinedMealWithVariations($mealContainer: JQuery): void { - let self = this; - const day = $mealContainer.data('date'); - const dishes = AdminParticipationEditView.getDishesOn(day); - const dishSlug = $mealContainer.data('dishSlug'); - const dish = AdminParticipationEditView.findDish(dishSlug, dishes); - let cmd = new CombinedMealDialog( - dish.title, - dishes, - [], - null, - { - ok: function (payload: SerializedFormData[]) { - const url = $mealContainer.attr('data-action-url'); - self.sendRequest( - url, - payload, - (data: JoinResponseData) => AdminParticipationEditView.combinedMealJoinSuccess($mealContainer, data), - (error: string) => AdminParticipationEditView.toggleFailure(error, MealToggleAction.Join, url) - ); - } - } - ); - cmd.open(); - } - - private joinCombinedMealWithoutVariations($mealContainer: JQuery): void { - const day = $mealContainer.data('date'); - const dishes = AdminParticipationEditView.getDishesOn(day); - const dishSlugs = AdminParticipationEditView.getSimpleDishSlugs(dishes); - - let payload: SerializedFormData[] = []; - dishSlugs.forEach(function (slug, i) { - payload.push({ - 'name': `dishes[${i}]`, - 'value': slug - }); - }); - - const url = $mealContainer.attr('data-action-url'); - this.sendRequest( - url, - payload, - (data: JoinResponseData) => AdminParticipationEditView.combinedMealJoinSuccess($mealContainer, data), - (error: string) => AdminParticipationEditView.toggleFailure(error, MealToggleAction.Join, url) - ); - } - - private static combinedMealJoinSuccess($mealContainer: JQuery, data: JoinResponseData): void { - $mealContainer - .addClass('participating') - .attr('data-action', MealToggleAction.Cancel) - .attr('data-action-url', data.url) - .find('.glyphicon') - .removeClass('glyphicon-unchecked') - .addClass('glyphicon-check glyphicon-ok'); - - const day = $mealContainer.data('date'); - $(`.table-row.editing .meal-participation[data-date='${day}'][data-combined='0']`).each(function(){ - if (data.bookedDishSlugs.includes($(this).data('dishSlug'))) { - $(this).append(''); - } - }); - - const dishSlug = $mealContainer.data('dishSlug'); - AdminParticipationEditView.updateParticipantCount(dishSlug, day, data.participantsCount); - } - - /** - * Cancels a booked combined meal. - */ - private cancelCombinedMeal($mealContainer: JQuery): void { - const url = $mealContainer.attr('data-action-url'); - this.sendRequest( - url, - null, - (data: DeleteResponseData) => AdminParticipationEditView.combinedMealCancelSuccess($mealContainer, data), - (error: string) => AdminParticipationEditView.toggleFailure(error, MealToggleAction.Cancel, url) - ); - } - - private static combinedMealCancelSuccess($mealContainer: JQuery, data: DeleteResponseData): void { - const day = $mealContainer.data('date'); - $(`.table-row.editing .meal-participation[data-date=${day}][data-combined='0'] .glyphicon-adjust`).remove(); - $(`.table-row.editing .meal-participation[data-date=${day}][data-combined='1'] .glyphicon-check`) - .removeClass('glyphicon-check glyphicon-ok') - .addClass('glyphicon-unchecked'); - $(`.table-row.editing .meal-participation[data-date=${day}][data-combined='1']`) - .removeClass('participating') - .attr('data-action', MealToggleAction.Join) - .attr('data-action-url', data.url); - - const dishSlug = $mealContainer.data('dishSlug'); - AdminParticipationEditView.updateParticipantCount(dishSlug, day, data.participantsCount); - } - - /** - * Error response handler for join and cancel operations on both simple and combined meals. - */ - private static toggleFailure(error: string, action: MealToggleAction, url: string, payload?: SerializedFormData[]): void { - let logMsg = `toggle failure, error: ${error}, action: ${action}, url: ${url}, payload: ${payload}`; - console.log(logMsg); - } - - /** - * @param day Date in YYYY-MM-DD format. - */ - private static getDishesOn(day: string): Dish[]|null { - let dishes = $('[data-weekly-menu]').data('weeklyMenu'); - - if (undefined === dishes[day]) { - return null; - } - - return dishes[day] - } - - /** - * Extracts simple dish slugs from a given dish collection. - * - * @return List of simple dish slugs. - */ - private static getSimpleDishSlugs(dishes: Dish[]): string[] { - let slugs: string[] = []; - for (const dish of dishes) { - if (dish.isCombined) { - continue; - } - slugs.push(dish.slug); - } - - return slugs; - } - - /** - * Checks weather or not a dish collection contains a dish variation. - */ - private static dishesContainVariation(dishes: Dish[]): boolean { - for (const dish of dishes) { - if (0 < dish.variations.length) { - return true; - } - } - - return false; - } - - /** - * Finds a dish, or a dish variation with given slug in a dish collection. - */ - private static findDish(slug: string, dishes: Dish[]): Dish|DishVariation|null { - for (const dish of dishes) { - if (slug === dish.slug) { - return dish; - } - if (0 === dish.variations.length) { - continue; - } - for (const dv of dish.variations) { - if (slug === dv.slug) { - return dv; - } - } - } - } - - private static updateParticipantCount(dishSlug: string, day: string, count: number): void { - $(`.meal-count[data-dish-slug=${dishSlug}][data-day=${day}] .count`).text(count); - } - - private sendRequest(url: string, payload?: SerializedFormData[], successFn?: ReqSuccessFn, failureFn?: ReqFailureFn) { - $.ajax({ - method: 'POST', - url: url, - data: payload, - dataType: 'json', - success: successFn, - error: function (jqXHR, status, error) { - AjaxErrorHandler.handleError(jqXHR, function(){ - if (failureFn) { - let errMsg = status; - if ('' !== error) { - errMsg += `, ${error}`; - } - failureFn(errMsg); - } - }); - } - }); - } -}; diff --git a/src/Resources/js/views/dishIndex.ts b/src/Resources/js/views/dishIndex.ts deleted file mode 100644 index 67b0ee8c3..000000000 --- a/src/Resources/js/views/dishIndex.ts +++ /dev/null @@ -1,40 +0,0 @@ -import Switchery from 'switchery.js'; - -export default class DishIndex { - constructor() { - DishIndex.initObservers(); - } - - private static initObservers(): void { - let createDishContainer = document.querySelector('.dish-list .create-form'); - if (null === createDishContainer) { - console.error('element not found, selector: .dish-list .create-form'); - return; - } - let dishTable = document.querySelector('#dish-table tbody'); - if (null === dishTable) { - console.error('element not found, selector: #dish-table tbody'); - return; - } - - let observerConfig = {childList: true}; - const observer = new MutationObserver((mutations) => { - for (const mutation of mutations) { - mutation.addedNodes.forEach((node) => { - if (!(node instanceof HTMLElement)) { - return; - } - let oneServingSizeCheckbox = node.querySelector('form[name=dish] input[type=checkbox]'); - if (null !== oneServingSizeCheckbox) { - new Switchery(oneServingSizeCheckbox, { - size: 'small' - }); - } - }); - } - }); - - observer.observe(createDishContainer, observerConfig); - observer.observe(dishTable, observerConfig); - } -} diff --git a/src/Resources/js/views/mealGuest.ts b/src/Resources/js/views/mealGuest.ts deleted file mode 100644 index 1e0542698..000000000 --- a/src/Resources/js/views/mealGuest.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {ParticipationGuestToggleHandler} from '../modules/participation-toggle-handler'; -import {ParticipationPreToggleHandler} from '../modules/participation-pre-toggle-handler'; -import {ParticipationUpdateHandler} from '../modules/participation-update-handler'; -import {SlotAllocationUpdateHandler} from '../modules/slot-allocation-update-handler'; - -export default class MealGuestView { - $participationCheckboxes: JQuery; - - constructor() { - this.$participationCheckboxes = $('.meal-guest input[type="checkbox"]'); - if (1 > this.$participationCheckboxes.length) { - return; - } - - let participationToggleHandler = new ParticipationGuestToggleHandler(this.$participationCheckboxes); - new ParticipationPreToggleHandler(participationToggleHandler); - - this.configureMealUpdateHandlers(); - } - - /** - * Configure handlers to process meal push notifications. - */ - private configureMealUpdateHandlers(): void { - const event = new EventSource($('.weeks').data('msgSubscribeUrl'), { withCredentials: true }); - event.addEventListener('participationUpdate', (event: MessageEvent) => { - ParticipationUpdateHandler.updateParticipation(JSON.parse(event.data)); - }); - event.addEventListener('slotAllocationUpdate', (event: MessageEvent) => { - SlotAllocationUpdateHandler.handleUpdate(JSON.parse(event.data)); - }); - } -}; diff --git a/src/Resources/js/views/mealIndex.ts b/src/Resources/js/views/mealIndex.ts deleted file mode 100644 index 5018b7fc3..000000000 --- a/src/Resources/js/views/mealIndex.ts +++ /dev/null @@ -1,155 +0,0 @@ -import {ParticipationPreToggleHandler} from '../modules/participation-pre-toggle-handler'; -import {ParticipationToggleHandler} from '../modules/participation-toggle-handler'; -import {CombinedMealDialog, SerializedFormData} from '../modules/combined-meal-dialog'; -import {ParticipationRequest, ParticipationRequestHandler} from '../modules/participation-request-handler'; -import {ParticipationResponse} from '../modules/participation-response-handler'; -import {CombinedMealService} from '../modules/combined-meal-service'; -import {MealOfferUpdate, MealOfferUpdateHandler} from '../modules/meal-offer-update-handler'; -import {ParticipationUpdateHandler} from '../modules/participation-update-handler'; -import {SlotAllocationUpdateHandler} from '../modules/slot-allocation-update-handler'; -import {MealService} from '../modules/meal-service'; -import AjaxErrorHandler from '../modules/ajax-error-handler'; - -interface UpdateResponse extends ParticipationResponse { - bookedDishSlugs: string[]; -} - -export default class MealIndexView { - participationPreToggleHandler: ParticipationPreToggleHandler; - $participationCheckboxes: JQuery; - - constructor() { - this.$participationCheckboxes = $('.meals-list .meal .participation-checkbox'); - this.initEvents(); - this.configureMealUpdateHandlers(); - - if (this.$participationCheckboxes.length > 0) { - let participationToggleHandler = new ParticipationToggleHandler(this.$participationCheckboxes); - this.participationPreToggleHandler = new ParticipationPreToggleHandler(participationToggleHandler); - } - } - - /** - * Configure handlers to process meal push notifications. - */ - private configureMealUpdateHandlers(): void { - const event = new EventSource($('.weeks').data('msgSubscribeUrl'), { withCredentials: true }); - event.addEventListener('participationUpdate', (event: MessageEvent) => { - ParticipationUpdateHandler.updateParticipation(JSON.parse(event.data)); - }); - event.addEventListener('mealOfferUpdate', (event: MessageEvent) => { - MealIndexView.handleMealOfferUpdate(JSON.parse(event.data)); - }); - event.addEventListener('slotAllocationUpdate', (event: MessageEvent) => { - SlotAllocationUpdateHandler.handleUpdate(JSON.parse(event.data)); - }); - } - - private initEvents(): void { - // set handler for slot change event - $('.meals-list .meal .slot-selector').on('change', this.handleChangeSlot); - this.$participationCheckboxes.on('change', MealIndexView.postToggleParticipation); - $('.meals-list .meal .meal-row').on('click', ' .title.edit', this.handleCombinedMealEdit.bind(this)); - } - - private static handleMealOfferUpdate(data: MealOfferUpdate) { - let $checkbox = $(`[data-id=${data.mealId}] input[type=checkbox]`); - if (1 > $checkbox.length) { - console.log(`error: meal not found, mealId: ${data.mealId}, method: MealIndexView.handleMealOfferUpdate`); - return; - } - - MealOfferUpdateHandler.handleUpdate($checkbox, data); - } - - private handleChangeSlot(event: JQuery.TriggeredEvent) { - const $slotSelector = $(event.target); - const $mealContainer = $slotSelector.closest('.meal'); - const mealIsBooked = $mealContainer.find('input[type="checkbox"]').is(':checked'); - - if (mealIsBooked) { - const $mealDate = $mealContainer.data('date'); - const slot = $slotSelector.val(); - $.ajax({ - method: 'POST', - url: '/menu/meal/'+$mealDate+'/update-slot', - data: { 'slot': slot }, - dataType: 'json', - success: function () { - // hide default option to auto-select slot [TP##250006] - $slotSelector.find('option[value=""]').hide() - }, - error: function (jqXHR) { - AjaxErrorHandler.handleError(jqXHR); - } - }); - } - } - - private static postToggleParticipation(event: JQuery.TriggeredEvent) { - const $updatedDishCheckbox = $(event.target); - const $mealContainer = $updatedDishCheckbox.closest('.meal'); - let $slotSelector = $mealContainer.find('.slot-selector'); - - // hide default slot option (autoselect) if user joined a meal - if ($updatedDishCheckbox.is(':checked')) { - $slotSelector.find('option[value=""]').hide(); - return; - } - - const bookedMealCount = $mealContainer.find('input.participation-checkbox:checked').length - - // reset slot selector if user cancelled all booked meals - if (1 > bookedMealCount) { - $slotSelector.find('option[value=""]').show(); - $slotSelector.val(''); - } - } - - private handleCombinedMealEdit(event: JQuery.TriggeredEvent): void { - let mealTitle = $(event.target); - let mealContainer = mealTitle.closest('.meal'); - const mealLockDateTime = Date.parse(mealContainer.data('lockDateTime')); - if (mealLockDateTime <= Date.now()) { - const errMsg = mealContainer.closest('.weeks').data('errUpdateNotPossible'); - if (errMsg.length > 0) { - alert(errMsg); - } - mealTitle.removeClass('edit'); - return; - } - - const $dishContainer = mealContainer.find('.meal-row.combined-meal'); - this.showMealConfigurator($dishContainer); - } - - private showMealConfigurator($dishContainer: JQuery): void { - let self = this; - let $mealContainer = $dishContainer.closest('.meal'); - const slotSlug: string = $mealContainer.find('.slot-selector').val().toString(); - const title = $dishContainer.find('.title').text(); - const dishes = CombinedMealService.getDishes($mealContainer); - const $bookedDishIDs = $dishContainer.attr('data-booked-dishes').split(',').map((id: string) => id.trim()); - let cmd = new CombinedMealDialog( - title, - dishes, - $bookedDishIDs, - slotSlug, - { - ok: function (reqPayload: SerializedFormData) { - let $mealCheckbox = $dishContainer.find('input[type=checkbox]'); - - const participationID = MealService.getParticipantId($mealCheckbox); - const url = `/meal/participation/${participationID}/update`; - let req = new ParticipationRequest(url, reqPayload); - ParticipationRequestHandler.sendRequest(req, $mealCheckbox, function($checkbox, data: UpdateResponse) { - if (0 < data.bookedDishSlugs.length) { - CombinedMealService.updateBookedDishes($checkbox, dishes, data.bookedDishSlugs); - } - }); - }.bind(self) - } - ); - cmd.open(); - } -} diff --git a/src/Resources/js/views/slotIndex.ts b/src/Resources/js/views/slotIndex.ts deleted file mode 100644 index 135790b83..000000000 --- a/src/Resources/js/views/slotIndex.ts +++ /dev/null @@ -1,73 +0,0 @@ -import Switchery from 'switchery.js'; -import AjaxErrorHandler from '../modules/ajax-error-handler'; - -export default class SlotIndexView { - constructor() { - this.init(); - } - - private init() { - this.initSlotStateToggler(); - $('#slot-table .table-data.slot-actions a.delete').on('click', this.handleDeleteSlot.bind(this)); - } - - private initSlotStateToggler() { - const self = this; - $('#slot-table .table-data.slot-actions input[type="checkbox"]').each(function (idx, checkbox) { - new Switchery(checkbox, { - size: 'small', - onChange: function (state: boolean) { - const id = $(checkbox).data('id'); - self.handleToggleSlotState(id, state); - } - }); - }); - }; - - private handleToggleSlotState(slotSlug: string, state: boolean) { - const url = '/meal/slot/' + slotSlug + '/update-state'; - $.post(url, {'disabled': (false === state ? '1' : '0')}) - .fail(function () { - $('.alert').show(); - }); - }; - - private handleDeleteSlot(event: JQuery.TriggeredEvent) { - let self = this; // SlotIndexView - - const $delLink = $(event.target); - const slotSlug = $delLink.data('id'); - const url = '/meal/slot/' + slotSlug + '/delete'; - - let $flashContainer = $('#flash-msg'); - let msg = ''; - - $.ajax({url: url, method: 'DELETE'}) - .done(function () { - const $slotRow = $delLink.closest('.table-row'); - const slotTitle = $slotRow.find('.slot-title').text(); - - $slotRow.remove(); - msg = $flashContainer.data('del-success-msg').replace('_', slotTitle); - self.showFlashMsg(msg, 'success'); - }) - .fail(function (jqXHR) { - AjaxErrorHandler.handleError(jqXHR, function(){ - msg = $flashContainer.data('err-msg'); - if (0 < msg.length) { - self.showFlashMsg(msg, 'error'); - } - }); - }); - } - - private showFlashMsg(msg: string, type: string) { - const msgClass = ('error' === type) ? 'alert-danger' : 'alert-success'; - let $flashContainer = $('#flash-msg'); - - $flashContainer.addClass(msgClass).text(msg).slideToggle('slow'); - setTimeout( function () { - $flashContainer.slideToggle('slow', () => $flashContainer.text('').removeClass(msgClass)); - }, 3000); - } -};