From eba3c70c9bef683382a092ec4cf0164a36a08617 Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Sun, 10 Oct 2021 16:24:12 +0200 Subject: [PATCH 1/9] Various accessibility improvements * Add announcement element with `aria-live` * Add skip to main content element Signed-off-by: Thomas Citharel --- js/package.json | 2 + js/src/App.vue | 48 ++++++- js/src/common.scss | 20 +++ .../components/Account/ProfileOnboarding.vue | 4 +- js/src/components/Comment/Comment.vue | 1 + js/src/components/Comment/CommentTree.vue | 9 +- .../Discussion/DiscussionComment.vue | 2 +- js/src/components/Editor.vue | 9 ++ js/src/components/Error.vue | 8 +- .../components/Event/AddressAutoComplete.vue | 1 + .../components/Event/EventMetadataSidebar.vue | 20 +-- .../components/Event/ParticipationButton.vue | 36 ++++-- js/src/components/Footer.vue | 21 +++- js/src/components/NavBar.vue | 22 +++- .../Participation/ConfirmParticipation.vue | 8 +- .../ParticipationWithAccount.vue | 5 + .../ParticipationWithoutAccount.vue | 5 + .../Participation/UnloggedParticipation.vue | 5 + js/src/components/PictureUpload.vue | 7 +- js/src/main.ts | 4 + js/src/router/actor.ts | 13 +- js/src/router/discussion.ts | 17 ++- js/src/router/error.ts | 4 + js/src/router/event.ts | 50 ++++++-- js/src/router/groups.ts | 27 ++-- js/src/router/index.ts | 56 +++++++-- js/src/router/settings.ts | 117 ++++++++++++++---- js/src/router/user.ts | 47 +++++-- js/src/types/event.model.ts | 6 +- js/src/views/About.vue | 49 ++++---- js/src/views/About/AboutInstance.vue | 14 +-- js/src/views/Admin/AdminProfile.vue | 8 ++ js/src/views/Admin/AdminUserProfile.vue | 8 ++ js/src/views/Admin/Follows.vue | 5 + js/src/views/Discussions/Create.vue | 2 +- js/src/views/Discussions/Discussion.vue | 2 +- js/src/views/Event/Edit.vue | 5 +- js/src/views/Event/Event.vue | 12 ++ js/src/views/Event/Participants.vue | 27 +++- js/src/views/Group/Group.vue | 3 +- js/src/views/Group/GroupSettings.vue | 6 +- js/src/views/Group/Settings.vue | 5 + js/src/views/Home.vue | 3 + js/src/views/Moderation/Logs.vue | 5 + js/src/views/Moderation/ReportList.vue | 5 + js/src/views/Posts/Edit.vue | 2 +- js/src/views/Posts/List.vue | 10 +- js/src/views/Resources/ResourceFolder.vue | 1 + js/src/views/Settings/Notifications.vue | 20 ++- js/src/views/Settings/Preferences.vue | 3 +- js/src/views/Todos/Todo.vue | 8 ++ js/src/views/Todos/TodoList.vue | 8 ++ js/src/views/Todos/TodoLists.vue | 10 ++ js/src/views/User/EmailValidate.vue | 8 +- js/src/views/User/PasswordReset.vue | 8 +- js/src/views/User/ProviderValidation.vue | 8 +- js/src/views/User/Register.vue | 4 +- js/src/views/User/ResendConfirmation.vue | 8 +- js/src/views/User/SendPasswordReset.vue | 8 +- js/src/views/User/SettingsOnboard.vue | 5 + js/src/views/User/Validate.vue | 8 +- js/yarn.lock | 10 ++ 62 files changed, 687 insertions(+), 175 deletions(-) diff --git a/js/package.json b/js/package.json index 7b3fc2b9..9e38573e 100644 --- a/js/package.json +++ b/js/package.json @@ -29,6 +29,8 @@ "@tiptap/extension-underline": "^2.0.0-beta.7", "@tiptap/starter-kit": "^2.0.0-beta.37", "@tiptap/vue-2": "^2.0.0-beta.21", + "@vue-a11y/announcer": "^2.1.0", + "@vue-a11y/skip-to": "^2.1.2", "@vue/apollo-option": "4.0.0-alpha.11", "apollo-absinthe-upload-link": "^1.5.0", "blurhash": "^1.1.3", diff --git a/js/src/App.vue b/js/src/App.vue index f9818269..bcda0491 100644 --- a/js/src/App.vue +++ b/js/src/App.vue @@ -1,5 +1,7 @@ @@ -218,4 +256,8 @@ $mdi-font-path: "~@mdi/font/fonts"; flex-grow: 1; } } + +.vue-skip-to { + z-index: 40; +} diff --git a/js/src/common.scss b/js/src/common.scss index 004ddb1b..66979923 100644 --- a/js/src/common.scss +++ b/js/src/common.scss @@ -135,3 +135,23 @@ a.list-item { font-size: 1.25rem; } } + +@mixin focus() { + &:focus { + border: 2px solid black; + border-radius: 5px; + } +} + +ul.menu-list > li, +p { + @include focus; +} +.navbar-item { + @include focus; +} + +.navbar-dropdown span.navbar-item:hover { + background-color: whitesmoke; + color: #0a0a0a; +} diff --git a/js/src/components/Account/ProfileOnboarding.vue b/js/src/components/Account/ProfileOnboarding.vue index 43448fc1..bba07338 100644 --- a/js/src/components/Account/ProfileOnboarding.vue +++ b/js/src/components/Account/ProfileOnboarding.vue @@ -11,7 +11,7 @@ ) }}

-
+

{{ @@ -33,7 +33,7 @@ " />

-
+

{{ $t( diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue index 14d0a9be..33fd0cc9 100644 --- a/js/src/components/Comment/Comment.vue +++ b/js/src/components/Comment/Comment.vue @@ -137,6 +137,7 @@ ref="commentEditor" v-model="newComment.text" mode="comment" + :aria-label="$t('Comment body')" />

@@ -30,9 +31,11 @@

- {{ - $t("Notify participants") - }} + {{ $t("Notify participants") }}
diff --git a/js/src/components/Discussion/DiscussionComment.vue b/js/src/components/Discussion/DiscussionComment.vue index c3d27c96..3dd5706e 100644 --- a/js/src/components/Discussion/DiscussionComment.vue +++ b/js/src/components/Discussion/DiscussionComment.vue @@ -88,7 +88,7 @@ {{ $t("[This comment has been deleted by it's author]") }}
- +
- {{ - $t("Copy details to clipboard") - }} + {{ $t("Copy details to clipboard") }}
diff --git a/js/src/components/Event/AddressAutoComplete.vue b/js/src/components/Event/AddressAutoComplete.vue index a3c80680..886c3fa1 100644 --- a/js/src/components/Event/AddressAutoComplete.vue +++ b/js/src/components/Event/AddressAutoComplete.vue @@ -31,6 +31,7 @@ v-if="!gettingLocation" icon-right="target" @click="locateMe" + @keyup.enter="locateMe" >{{ $t("Use my location") }} {{ $t("Getting location") }} diff --git a/js/src/components/Event/EventMetadataSidebar.vue b/js/src/components/Event/EventMetadataSidebar.vue index af567ee7..912038d6 100644 --- a/js/src/components/Event/EventMetadataSidebar.vue +++ b/js/src/components/Event/EventMetadataSidebar.vue @@ -7,25 +7,15 @@
{{ $t("No address defined") }}
-
-
-

- {{ physicalAddress.poiInfos.name }} -

-

- {{ physicalAddress.poiInfos.alternativeName }} -

-
-
- + {{ $t("Show map") }} + {{ $t("Show map") }} +
diff --git a/js/src/components/Event/ParticipationButton.vue b/js/src/components/Event/ParticipationButton.vue index c19a30cc..65c44041 100644 --- a/js/src/components/Event/ParticipationButton.vue +++ b/js/src/components/Event/ParticipationButton.vue @@ -30,18 +30,22 @@ A button to set your participation position="is-bottom-left" v-if="participation && participation.role === ParticipantRole.PARTICIPANT" > - + {{ $t("Cancel my participation…") }} @@ -73,6 +77,7 @@ A button to set your participation :value="false" aria-role="listitem" @click="confirmLeave" + @keyup.enter="confirmLeave" class="has-text-danger" >{{ $t("Cancel my participation request…") }} @@ -101,17 +106,21 @@ A button to set your participation position="is-bottom-left" v-else-if="!participation && currentActor.id" > - +
@@ -136,6 +145,7 @@ A button to set your participation :value="false" aria-role="listitem" @click="joinModal" + @keyup.enter="joinModal" v-if="identities.length > 1" >{{ $t("with another identity…") }} diff --git a/js/src/components/Footer.vue b/js/src/components/Footer.vue index b6454656..a38792db 100644 --- a/js/src/components/Footer.vue +++ b/js/src/components/Footer.vue @@ -25,7 +25,12 @@ v-model="locale" :placeholder="$t('Select a language')" > - @@ -48,6 +53,9 @@ {{ $t("License") }} +
  • + {{ $t("Back to top") }} +
  • diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue index 8a867ca1..2cde993c 100644 --- a/js/src/views/Group/Group.vue +++ b/js/src/views/Group/Group.vue @@ -203,6 +203,7 @@ @@ -224,7 +225,7 @@ {{ $t("ICS/WebCal Feed") }} - + - @@ -259,6 +260,7 @@
    @@ -297,6 +299,7 @@
    = { total: 0, elements: [] }; diff --git a/js/src/views/Moderation/ReportList.vue b/js/src/views/Moderation/ReportList.vue index 928e19c3..bce76169 100644 --- a/js/src/views/Moderation/ReportList.vue +++ b/js/src/views/Moderation/ReportList.vue @@ -111,6 +111,11 @@ const REPORT_PAGE_LIMIT = 10; pollInterval: 120000, // 2 minutes }, }, + metaInfo() { + return { + title: this.$t("Reports") as string, + }; + }, }) export default class ReportList extends Vue { reports?: Paginate = { elements: [], total: 0 }; diff --git a/js/src/views/Posts/Edit.vue b/js/src/views/Posts/Edit.vue index 899dc3d7..91bf702b 100644 --- a/js/src/views/Posts/Edit.vue +++ b/js/src/views/Posts/Edit.vue @@ -72,7 +72,7 @@

    {{ errors.body }}

    - +
    {{ $t("Who can view this post") }}
    diff --git a/js/src/views/Posts/List.vue b/js/src/views/Posts/List.vue index 85288374..14d87b78 100644 --- a/js/src/views/Posts/List.vue +++ b/js/src/views/Posts/List.vue @@ -127,11 +127,13 @@ const POSTS_PAGE_LIMIT = 10; PostElementItem, }, metaInfo() { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const { group } = this; return { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - title: this.$t("My groups") as string, - titleTemplate: "%s | Mobilizon", + title: this.$t("{group} posts", { + group: group.name || usernameWithDomain(group), + }) as string, }; }, }) diff --git a/js/src/views/Resources/ResourceFolder.vue b/js/src/views/Resources/ResourceFolder.vue index 360c8589..c830327b 100644 --- a/js/src/views/Resources/ResourceFolder.vue +++ b/js/src/views/Resources/ResourceFolder.vue @@ -58,6 +58,7 @@ {{ $t("New link") }} diff --git a/js/src/views/Settings/Notifications.vue b/js/src/views/Settings/Notifications.vue index adb60576..cf3abb3a 100644 --- a/js/src/views/Settings/Notifications.vue +++ b/js/src/views/Settings/Notifications.vue @@ -18,12 +18,16 @@

    {{ $t("Browser notifications") }}

    - {{ - $t("Unsubscribe to browser push notifications") - }} + {{ $t("Unsubscribe to browser push notifications") }} {{ $t("Activate browser push notifications") }} @@ -247,6 +251,9 @@ @click=" (e) => copyURL(e, tokenToURL(feedToken.token, 'atom'), 'atom') " + @keyup.enter=" + (e) => copyURL(e, tokenToURL(feedToken.token, 'atom'), 'atom') + " :href="tokenToURL(feedToken.token, 'atom')" target="_blank" >{{ $t("RSS/Atom Feed") }}{{ $t("Regenerate new links") }}
    @@ -283,6 +294,7 @@ icon-left="refresh" type="is-text" @click="generateFeedTokens" + @keyup.enter="generateFeedTokens" >{{ $t("Create new links") }} @@ -333,7 +345,7 @@ type NotificationType = { label: string; subtypes: NotificationSubType[] }; }, metaInfo() { return { - title: this.$t("Notifications") as string, + title: this.$t("Notification settings") as string, }; }, }) diff --git a/js/src/views/Settings/Preferences.vue b/js/src/views/Settings/Preferences.vue index 521ed247..95543b86 100644 --- a/js/src/views/Settings/Preferences.vue +++ b/js/src/views/Settings/Preferences.vue @@ -61,7 +61,7 @@ {{ $t("Unable to detect timezone.") }} -
    +
    { const accessToken = this.getValueFromMeta("auth-access-token"); diff --git a/js/src/views/User/Register.vue b/js/src/views/User/Register.vue index 8d8b10cc..a1638a75 100644 --- a/js/src/views/User/Register.vue +++ b/js/src/views/User/Register.vue @@ -59,7 +59,7 @@ {{ $t("Learn more") }} -
    +
    {{ $t("About {instance}", { instance: config.name }) @@ -170,7 +170,7 @@ >

    -
    +
    Date: Sun, 10 Oct 2021 16:25:50 +0200 Subject: [PATCH 2/9] Add timezone handling Signed-off-by: Thomas Citharel --- js/package.json | 1 + js/src/components/Address/AddressInfo.vue | 124 +++++++++++ js/src/components/Event/EventFullDate.vue | 186 ++++++++++++---- js/src/components/Event/EventMap.vue | 175 +++++++++++++++ .../components/Event/EventMetadataSidebar.vue | 201 ++---------------- .../Event/FullAddressAutoComplete.vue | 152 +++++++------ js/src/components/NavBar.vue | 9 +- js/src/filters/datetime.ts | 5 +- js/src/graphql/address.ts | 1 + js/src/graphql/config.ts | 25 +++ js/src/graphql/event.ts | 1 + js/src/graphql/user.ts | 11 + js/src/i18n/en_US.json | 46 +++- js/src/i18n/fr_FR.json | 46 +++- js/src/types/address.model.ts | 16 +- js/src/types/event-options.model.ts | 3 + js/src/types/event.model.ts | 21 +- js/src/views/Event/Edit.vue | 199 ++++++++++++++--- js/src/views/Event/Event.vue | 35 ++- .../components/Post/PostElementItem.spec.ts | 2 +- js/tsconfig.json | 2 +- js/yarn.lock | 5 + lib/federation/activity_pub/actor.ex | 4 +- lib/federation/activity_pub/permission.ex | 2 +- lib/federation/activity_pub/types/events.ex | 2 +- lib/graphql/api/events.ex | 6 +- .../middleware/current_actor_provider.ex | 4 +- lib/graphql/resolvers/address.ex | 2 +- lib/graphql/resolvers/event.ex | 99 +++++++-- lib/graphql/schema/address.ex | 2 + lib/graphql/schema/event.ex | 6 +- lib/mobilizon.ex | 1 + lib/mobilizon/addresses/address.ex | 51 ++++- lib/mobilizon/events/event_options.ex | 3 + lib/mobilizon/events/events.ex | 19 +- lib/service/geospatial/addok.ex | 5 +- lib/service/geospatial/google_maps.ex | 5 +- lib/service/geospatial/map_quest.ex | 5 +- lib/service/geospatial/mimirsbrunn.ex | 3 +- lib/service/geospatial/nominatim.ex | 3 +- lib/service/geospatial/pelias.ex | 3 +- lib/service/geospatial/photon.ex | 5 +- lib/service/geospatial/provider.ex | 13 ++ lib/service/metadata/event.ex | 54 ++++- lib/service/timezone_detector.ex | 40 ++++ lib/web/auth/context.ex | 33 +-- mix.exs | 1 + mix.lock | 1 + ...211008084901_add_timezone_to_addresses.exs | 9 + 49 files changed, 1218 insertions(+), 429 deletions(-) create mode 100644 js/src/components/Address/AddressInfo.vue create mode 100644 js/src/components/Event/EventMap.vue create mode 100644 lib/service/timezone_detector.ex create mode 100644 priv/repo/migrations/20211008084901_add_timezone_to_addresses.exs diff --git a/js/package.json b/js/package.json index 9e38573e..a3d4ca10 100644 --- a/js/package.json +++ b/js/package.json @@ -38,6 +38,7 @@ "bulma-divider": "^0.2.0", "core-js": "^3.6.4", "date-fns": "^2.16.0", + "date-fns-tz": "^1.1.6", "graphql": "^15.0.0", "graphql-tag": "^2.10.3", "intersection-observer": "^0.12.0", diff --git a/js/src/components/Address/AddressInfo.vue b/js/src/components/Address/AddressInfo.vue new file mode 100644 index 00000000..a0ef9ead --- /dev/null +++ b/js/src/components/Address/AddressInfo.vue @@ -0,0 +1,124 @@ + + + diff --git a/js/src/components/Event/EventFullDate.vue b/js/src/components/Event/EventFullDate.vue index 454a3949..33c1d617 100644 --- a/js/src/components/Event/EventFullDate.vue +++ b/js/src/components/Event/EventFullDate.vue @@ -18,64 +18,97 @@ diff --git a/js/src/components/Event/EventMap.vue b/js/src/components/Event/EventMap.vue new file mode 100644 index 00000000..7ed79b3f --- /dev/null +++ b/js/src/components/Event/EventMap.vue @@ -0,0 +1,175 @@ + + + diff --git a/js/src/components/Event/EventMetadataSidebar.vue b/js/src/components/Event/EventMetadataSidebar.vue index 912038d6..1f94d5d0 100644 --- a/js/src/components/Event/EventMetadataSidebar.vue +++ b/js/src/components/Event/EventMetadataSidebar.vue @@ -11,7 +11,7 @@ {{ $t("Show map") }} @@ -24,6 +24,8 @@ :beginsOn="event.beginsOn" :show-start-time="event.options.showStartTime" :show-end-time="event.options.showEndTime" + :timezone="event.options.timezone" + :userTimezone="userTimezone" :endsOn="event.endsOn" /> @@ -130,91 +132,12 @@ > {{ extra.value }} - - -
    diff --git a/js/src/components/Event/FullAddressAutoComplete.vue b/js/src/components/Event/FullAddressAutoComplete.vue index b1af7d7a..48f16ead 100644 --- a/js/src/components/Event/FullAddressAutoComplete.vue +++ b/js/src/components/Event/FullAddressAutoComplete.vue @@ -1,72 +1,89 @@