From 9548ad6e313f547e93778bf78e880d2527ec1f49 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Sat, 21 Feb 2026 08:47:14 +0100 Subject: [PATCH] fix(webapp): add responsive mobile menu with locale switching and filter support (#9281) --- backend/src/graphql/queries/UpdateUser.ts | 37 +- .../I_select_{string}_in_the_language_menu.js | 3 +- ...cation_menu_and_click_on_the_first_item.js | 3 +- ...t}_unread_notifications_in_the_top_menu.js | 3 +- ...ton_links_to_the_all_notifications_page.js | 3 +- .../ui/src/ocelot/icons/svgs/language.svg | 5 + webapp/assets/_new/styles/tokens.scss | 1 + .../components/DonationInfo/DonationInfo.vue | 14 +- webapp/components/FilterMenu/FilterMenu.vue | 8 +- .../FilterMenu/FilterMenuSection.vue | 1 + webapp/components/HeaderMenu/HeaderMenu.vue | 1091 +++++++++++++---- .../LocaleSwitch/LocaleSwitch.spec.js | 48 +- .../components/LocaleSwitch/LocaleSwitch.vue | 89 +- webapp/components/ProgressBar/ProgressBar.vue | 4 + webapp/graphql/User.js | 2 + webapp/layouts/default.vue | 10 +- webapp/locales/de.json | 1 + webapp/locales/en.json | 1 + webapp/locales/es.json | 1 + webapp/locales/fr.json | 1 + webapp/locales/index.js | 9 + webapp/locales/it.json | 1 + webapp/locales/nl.json | 1 + webapp/locales/pl.json | 1 + webapp/locales/pt.json | 1 + webapp/locales/ru.json | 1 + webapp/mixins/localeUpdate.js | 36 + webapp/pages/index.vue | 239 ++-- 28 files changed, 1153 insertions(+), 462 deletions(-) create mode 100644 packages/ui/src/ocelot/icons/svgs/language.svg create mode 100644 webapp/mixins/localeUpdate.js diff --git a/backend/src/graphql/queries/UpdateUser.ts b/backend/src/graphql/queries/UpdateUser.ts index d58cf68a1..612feec21 100644 --- a/backend/src/graphql/queries/UpdateUser.ts +++ b/backend/src/graphql/queries/UpdateUser.ts @@ -3,23 +3,40 @@ import gql from 'graphql-tag' export const UpdateUser = gql` mutation ( $id: ID! + $slug: String $name: String - $termsAndConditionsAgreedVersion: String - $locationName: String # empty string '' sets it to null + $about: String + $allowEmbedIframes: Boolean + $showShoutsPublicly: Boolean $emailNotificationSettings: [EmailNotificationSettingsInput] + $termsAndConditionsAgreedVersion: String + $avatar: ImageInput + $locationName: String # empty string '' sets it to null + $locale: String ) { UpdateUser( id: $id + slug: $slug name: $name - termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion - locationName: $locationName + about: $about + allowEmbedIframes: $allowEmbedIframes + showShoutsPublicly: $showShoutsPublicly emailNotificationSettings: $emailNotificationSettings + termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion + avatar: $avatar + locationName: $locationName + locale: $locale ) { id + slug name + about + allowEmbedIframes + showShoutsPublicly termsAndConditionsAgreedVersion termsAndConditionsAgreedAt locationName + locale location { name nameDE @@ -33,6 +50,18 @@ export const UpdateUser = gql` value } } + avatar { + url + alt + sensitive + aspectRatio + type + } + badgeVerification { + id + description + icon + } } } ` diff --git a/cypress/support/step_definitions/Internationalization/I_select_{string}_in_the_language_menu.js b/cypress/support/step_definitions/Internationalization/I_select_{string}_in_the_language_menu.js index 48e1d4b59..450ac2673 100644 --- a/cypress/support/step_definitions/Internationalization/I_select_{string}_in_the_language_menu.js +++ b/cypress/support/step_definitions/Internationalization/I_select_{string}_in_the_language_menu.js @@ -1,7 +1,8 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('I select {string} in the language menu', language => { - cy.get('.locale-menu') + cy.get('.locale-menu:visible') + .first() .click() cy.contains('.locale-menu-popover a', language) .click() diff --git a/cypress/support/step_definitions/Notification.Mention/open_the_notification_menu_and_click_on_the_first_item.js b/cypress/support/step_definitions/Notification.Mention/open_the_notification_menu_and_click_on_the_first_item.js index 534db2a56..d8d898559 100644 --- a/cypress/support/step_definitions/Notification.Mention/open_the_notification_menu_and_click_on_the_first_item.js +++ b/cypress/support/step_definitions/Notification.Mention/open_the_notification_menu_and_click_on_the_first_item.js @@ -1,7 +1,8 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('open the notification menu and click on the first item', () => { - cy.get('.notifications-menu') + cy.get('.notifications-menu:visible') + .first() .invoke('show') .click() // 'invoke('show')' because of the delay for show the menu cy.get('.notification-content a') diff --git a/cypress/support/step_definitions/Notification.Mention/see_{int}_unread_notifications_in_the_top_menu.js b/cypress/support/step_definitions/Notification.Mention/see_{int}_unread_notifications_in_the_top_menu.js index eebb5b877..67ef47674 100644 --- a/cypress/support/step_definitions/Notification.Mention/see_{int}_unread_notifications_in_the_top_menu.js +++ b/cypress/support/step_definitions/Notification.Mention/see_{int}_unread_notifications_in_the_top_menu.js @@ -1,6 +1,7 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('see {int} unread notifications in the top menu', count => { - cy.get('.notifications-menu') + cy.get('.notifications-menu:visible') + .first() .should('contain', count) }) diff --git a/cypress/support/step_definitions/Notification.Mention/the_notification_menu_button_links_to_the_all_notifications_page.js b/cypress/support/step_definitions/Notification.Mention/the_notification_menu_button_links_to_the_all_notifications_page.js index 3cdbeb305..fd9090e8f 100644 --- a/cypress/support/step_definitions/Notification.Mention/the_notification_menu_button_links_to_the_all_notifications_page.js +++ b/cypress/support/step_definitions/Notification.Mention/the_notification_menu_button_links_to_the_all_notifications_page.js @@ -1,7 +1,8 @@ import { defineStep } from '@badeball/cypress-cucumber-preprocessor' defineStep('the notification menu button links to the all notifications page', () => { - cy.get('.notifications-menu') + cy.get('.notifications-menu:visible') + .first() .click() cy.location('pathname') .should('contain', '/notifications') diff --git a/packages/ui/src/ocelot/icons/svgs/language.svg b/packages/ui/src/ocelot/icons/svgs/language.svg new file mode 100644 index 000000000..30af3ee58 --- /dev/null +++ b/packages/ui/src/ocelot/icons/svgs/language.svg @@ -0,0 +1,5 @@ + + +language + + diff --git a/webapp/assets/_new/styles/tokens.scss b/webapp/assets/_new/styles/tokens.scss index f4ac15b3f..69c269f9e 100644 --- a/webapp/assets/_new/styles/tokens.scss +++ b/webapp/assets/_new/styles/tokens.scss @@ -359,6 +359,7 @@ $media-query-small: "(min-width: 600px)"; $media-query-medium: "(min-width: 768px)"; $media-query-large: "(min-width: 1024px)"; $media-query-x-large: "(min-width: 1200px)"; +$container-max-width-x-large: 1200px; /** * @tokens Background Images diff --git a/webapp/components/DonationInfo/DonationInfo.vue b/webapp/components/DonationInfo/DonationInfo.vue index 0e935271a..b99a30993 100644 --- a/webapp/components/DonationInfo/DonationInfo.vue +++ b/webapp/components/DonationInfo/DonationInfo.vue @@ -1,26 +1,28 @@ @@ -58,5 +55,6 @@ export default { flex: 1; margin-bottom: $space-x-small; margin-top: 16px; + cursor: pointer; } diff --git a/webapp/components/FilterMenu/FilterMenu.vue b/webapp/components/FilterMenu/FilterMenu.vue index 67f7b0dc9..100cf964f 100644 --- a/webapp/components/FilterMenu/FilterMenu.vue +++ b/webapp/components/FilterMenu/FilterMenu.vue @@ -1,16 +1,16 @@