diff --git a/js/package.json b/js/package.json index 13ad2a811..06c8c2d30 100644 --- a/js/package.json +++ b/js/package.json @@ -29,6 +29,7 @@ "@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/apollo-option": "^4.0.0-alpha.11", "apollo-absinthe-upload-link": "^1.5.0", "blurhash": "^1.1.3", "buefy": "^0.9.0", @@ -50,7 +51,6 @@ "unfetch": "^4.2.0", "v-tooltip": "^2.1.3", "vue": "^2.6.11", - "vue-apollo": "^3.0.3", "vue-class-component": "^7.2.3", "vue-i18n": "^8.14.0", "vue-meta": "^2.3.1", diff --git a/js/src/apollo/utils.ts b/js/src/apollo/utils.ts index 838ff718d..e7dbd2d1f 100644 --- a/js/src/apollo/utils.ts +++ b/js/src/apollo/utils.ts @@ -37,7 +37,7 @@ export const possibleTypes = types.reduce((acc, type) => { export const typePolicies: TypePolicies = { Discussion: { fields: { - comments: paginatedLimitPagination(), + comments: paginatedLimitPagination(), }, }, Group: { diff --git a/js/src/common.scss b/js/src/common.scss index e1a5012bd..004ddb1b4 100644 --- a/js/src/common.scss +++ b/js/src/common.scss @@ -32,7 +32,6 @@ $color-black: #000; .mention { background: rgba($color-black, 0.1); - color: rgba($color-black, 0.6); font-size: 0.9rem; font-weight: bold; border-radius: 5px; diff --git a/js/src/components/Account/ActorCard.vue b/js/src/components/Account/ActorCard.vue index a6b7aebad..a57c2692a 100644 --- a/js/src/components/Account/ActorCard.vue +++ b/js/src/components/Account/ActorCard.vue @@ -12,7 +12,7 @@

{{ actor.name || `@${usernameWithDomain(actor)}` }}

-

+

@{{ usernameWithDomain(actor) }}

, { data }: FetchResult) { + update( + cache: ApolloCache<{ relayFollowings: Paginate }>, + { data }: FetchResult + ) { cache.modify({ fields: { relayFollowings( @@ -274,12 +272,12 @@ export default class Followings extends Mixins(RelayMixin) { async removeRelay(follower: IFollower): Promise { const address = `${follower.targetActor.preferredUsername}@${follower.targetActor.domain}`; try { - await this.$apollo.mutate({ + await this.$apollo.mutate<{ removeRelay: IFollower }>({ mutation: REMOVE_RELAY, variables: { address, }, - update(cache: ApolloCache) { + update(cache: ApolloCache<{ removeRelay: IFollower }>) { cache.modify({ fields: { relayFollowings(existingFollowingRefs, { readField }) { diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue index 6a85c3358..00994462c 100644 --- a/js/src/components/Comment/Comment.vue +++ b/js/src/components/Comment/Comment.vue @@ -67,7 +67,8 @@
{{ $t("[This comment has been deleted]") }}

- {{ + + {{ $tc("View a reply", comment.totalReplies, { totalReplies: comment.totalReplies, }) @@ -77,8 +78,8 @@ v-else-if="comment.totalReplies && showReplies" @click="showReplies = false" > - - {{ $t("Hide replies") }} + + {{ $t("Hide replies") }}

@@ -465,7 +466,7 @@ a.comment-link { & > p > span { font-weight: bold; - color: $primary; + color: $violet-2; } } diff --git a/js/src/components/Comment/CommentTree.vue b/js/src/components/Comment/CommentTree.vue index 70a08c0b2..816e4073e 100644 --- a/js/src/components/Comment/CommentTree.vue +++ b/js/src/components/Comment/CommentTree.vue @@ -107,11 +107,7 @@ import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; eventUUID: this.event.uuid, }; }, - update(data) { - return data.event.comments.map( - (comment: IComment) => new CommentModel(comment) - ); - }, + update: (data) => data.event.comments, skip() { return !this.event.uuid; }, diff --git a/js/src/components/Discussion/DiscussionComment.vue b/js/src/components/Discussion/DiscussionComment.vue index 2cb6bc3b7..f4b990407 100644 --- a/js/src/components/Discussion/DiscussionComment.vue +++ b/js/src/components/Discussion/DiscussionComment.vue @@ -57,7 +57,12 @@

{{ diff --git a/js/src/components/Event/EventListCard.vue b/js/src/components/Event/EventListCard.vue index 26f92609a..7d3dc515e 100644 --- a/js/src/components/Event/EventListCard.vue +++ b/js/src/components/Event/EventListCard.vue @@ -13,206 +13,208 @@ :small="true" />

-
-
- -

{{ participation.event.title }}

-
-
-
- - - - - - {{ participation.event.physicalAddress.locality }} - - - - {{ organizerActor.displayName() }} - - - {{ $t("Organized by you") }} -
-
- - - {{ - $tc( - "{available}/{capacity} available places", - participation.event.options.maximumAttendeeCapacity - - participation.event.participantStats.participant, - { - available: - participation.event.options.maximumAttendeeCapacity - - participation.event.participantStats.participant, - capacity: - participation.event.options.maximumAttendeeCapacity, - } - ) - }} - - - {{ - $tc( - "{count} participants", - participation.event.participantStats.participant, - { - count: participation.event.participantStats.participant, - } - ) - }} - - - - {{ - $tc( - "{count} requests waiting", - participation.event.participantStats.notApproved, - { - count: participation.event.participantStats.notApproved, - } - ) - }} - - - -
-
-
- - - {{ $t("Actions") }} - - - - - {{ $t("Edit") }} - - - - - {{ $t("Duplicate") }} - - - - - {{ $t("Delete") }} - - - - - {{ $t("Manage participations") }} - - - +
+
+
- - {{ $t("View event page") }} +

{{ participation.event.title }}

- - +
+
+ + + + + + {{ participation.event.physicalAddress.locality }} - + + + {{ organizerActor.displayName() }} + + + {{ $t("Organized by you") }} +
+
+ + + {{ + $tc( + "{available}/{capacity} available places", + participation.event.options.maximumAttendeeCapacity - + participation.event.participantStats.participant, + { + available: + participation.event.options.maximumAttendeeCapacity - + participation.event.participantStats.participant, + capacity: + participation.event.options.maximumAttendeeCapacity, + } + ) + }} + + + {{ + $tc( + "{count} participants", + participation.event.participantStats.participant, + { + count: participation.event.participantStats.participant, + } + ) + }} + + + + {{ + $tc( + "{count} requests waiting", + participation.event.participantStats.notApproved, + { + count: participation.event.participantStats.notApproved, + } + ) + }} + + + +
+
+
+ + + {{ $t("Actions") }} + + + + + {{ $t("Edit") }} + + + + + {{ $t("Duplicate") }} + + + + + {{ $t("Delete") }} + + + + + {{ $t("Manage participations") }} + + + + + + {{ $t("View event page") }} + + + +
@@ -351,51 +353,72 @@ article.box { .list-card { display: flex; - align-items: center; padding: 0 6px; + position: relative; + flex-direction: column; - .actions { - padding-right: 7.5px; - cursor: pointer; + div.date-component { + align-self: flex-start; + padding: 5px; + position: absolute; + top: 0; + left: 0; + margin-top: 1px; + height: 0; + display: flex; + align-items: flex-end; + margin-bottom: 15px; + margin-left: 0rem; } - div.content { - flex: 1; - padding: 5px; + .content-and-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; + padding-bottom: 1rem; - .participation-actor span, - .participant-stats span { - padding: 0 5px; - - button { - height: auto; - padding-top: 0; - } + .actions { + padding-right: 7.5px; + cursor: pointer; } - div.title-wrapper { - display: flex; - align-items: center; + div.list-card-content { + flex: 1; + padding: 5px; + min-width: 350px; - div.date-component { - flex: 0; - margin-right: 16px; + .participation-actor span, + .participant-stats span { + padding: 0 5px; + + button { + height: auto; + padding-top: 0; + } } - a { - text-decoration: none; - } + div.title-wrapper { + display: flex; + align-items: center; + padding-top: 5px; - .title { - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - font-weight: 400; - line-height: 1em; - font-size: 1.6em; - padding-bottom: 5px; - margin: auto 0; + a { + text-decoration: none; + padding-bottom: 5px; + } + + .title { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + font-weight: 400; + line-height: 1em; + font-size: 1.4em; + padding-bottom: 5px; + margin: auto 0; + } } } } @@ -405,6 +428,7 @@ article.box { background: $yellow-2; display: flex; padding: 5px; + padding-left: calc(48px + 15px); figure { padding-right: 3px; diff --git a/js/src/components/Group/GroupMemberCard.vue b/js/src/components/Group/GroupMemberCard.vue index 69bd79004..784f6fc11 100644 --- a/js/src/components/Group/GroupMemberCard.vue +++ b/js/src/components/Group/GroupMemberCard.vue @@ -97,6 +97,10 @@ export default class GroupMemberCard extends Vue { & > div:last-child { cursor: pointer; } + + .media-content { + overflow: hidden; + } } .identity-header { diff --git a/js/src/components/NavBar.vue b/js/src/components/NavBar.vue index c2be785cf..1d6cda137 100644 --- a/js/src/components/NavBar.vue +++ b/js/src/components/NavBar.vue @@ -56,6 +56,7 @@ tag="a" href="https://mediation.koena.net/framasoft/mobilizon/" target="_blank" + rel="noopener" > - + @@ -103,8 +118,8 @@
- {{ identity.displayName() }} - {{ displayName(identity) }} + @{{ identity.preferredUsername }}
@@ -169,7 +184,7 @@ import { IDENTITIES, UPDATE_DEFAULT_ACTOR, } from "../graphql/actor"; -import { IPerson, Person } from "../types/actor"; +import { displayName, IPerson, Person } from "../types/actor"; import { CONFIG } from "../graphql/config"; import { IConfig } from "../types/config.model"; import { ICurrentUser, IUser } from "../types/current-user.model"; @@ -227,6 +242,8 @@ export default class NavBar extends Vue { mobileNavbarActive = false; + displayName = displayName; + @Watch("currentActor") async initializeListOfIdentities(): Promise { if (!this.currentUser.isLoggedIn) return; @@ -309,7 +326,7 @@ nav { cursor: pointer; span { - display: inherit; + display: flex; } &.is-active { @@ -343,5 +360,14 @@ nav { padding-top: 0.2rem; } } + + .identity-wrapper { + display: flex; + + .media-content span { + display: flex; + color: $violet-2; + } + } } diff --git a/js/src/components/Participation/ParticipationWithoutAccount.vue b/js/src/components/Participation/ParticipationWithoutAccount.vue index e7ec23932..0a6410be9 100644 --- a/js/src/components/Participation/ParticipationWithoutAccount.vue +++ b/js/src/components/Participation/ParticipationWithoutAccount.vue @@ -134,7 +134,7 @@ import { addLocalUnconfirmedAnonymousParticipation } from "@/services/AnonymousP import { EventJoinOptions, ParticipantRole } from "@/types/enums"; import RouteName from "@/router/name"; import { IParticipant } from "../../types/participant.model"; -import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; +import { ApolloCache, FetchResult } from "@apollo/client/core"; @Component({ apollo: { @@ -197,7 +197,7 @@ export default class ParticipationWithoutAccount extends Vue { locale: this.$i18n.locale, }, update: ( - store: ApolloCache, + store: ApolloCache<{ joinEvent: IParticipant }>, { data: updateData }: FetchResult ) => { if (updateData == null) { diff --git a/js/src/graphql/group.ts b/js/src/graphql/group.ts index a60108b4c..1217c5fe8 100644 --- a/js/src/graphql/group.ts +++ b/js/src/graphql/group.ts @@ -188,7 +188,7 @@ export const GROUP_FIELDS_FRAGMENTS = gql` `; export const FETCH_GROUP = gql` - query ( + query FetchGroup( $name: String! $afterDateTime: DateTime $beforeDateTime: DateTime @@ -212,7 +212,7 @@ export const FETCH_GROUP = gql` `; export const GET_GROUP = gql` - query ( + query GetGroup( $id: ID! $afterDateTime: DateTime $beforeDateTime: DateTime diff --git a/js/src/mixins/event.ts b/js/src/mixins/event.ts index b0a742855..213db15e3 100644 --- a/js/src/mixins/event.ts +++ b/js/src/mixins/event.ts @@ -31,7 +31,12 @@ export default class EventMixin extends mixins(Vue) { actorId, token, }, - update: (store: ApolloCache, { data }: FetchResult) => { + update: ( + store: ApolloCache<{ + leaveEvent: IParticipant; + }>, + { data }: FetchResult + ) => { if (data == null) return; let participation; diff --git a/js/src/mixins/group.ts b/js/src/mixins/group.ts index 26be0c3e2..c6e9f6024 100644 --- a/js/src/mixins/group.ts +++ b/js/src/mixins/group.ts @@ -15,6 +15,8 @@ import { import { MemberRole } from "@/types/enums"; import { Component, Vue } from "vue-property-decorator"; +const now = new Date(); + @Component({ apollo: { group: { @@ -24,7 +26,7 @@ import { Component, Vue } from "vue-property-decorator"; return { name: this.$route.params.preferredUsername, beforeDateTime: null, - afterDateTime: new Date(), + afterDateTime: now, }; }, skip() { diff --git a/js/src/views/Account/Register.vue b/js/src/views/Account/Register.vue index c6477c653..8dc97b895 100644 --- a/js/src/views/Account/Register.vue +++ b/js/src/views/Account/Register.vue @@ -128,7 +128,7 @@ import { MOBILIZON_INSTANCE_HOST } from "../../api/_entrypoint"; import RouteName from "../../router/name"; import { changeIdentity } from "../../utils/auth"; import identityEditionMixin from "../../mixins/identityEdition"; -import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; +import { ApolloCache, FetchResult } from "@apollo/client/core"; @Component({ apollo: { @@ -171,7 +171,7 @@ export default class Register extends mixins(identityEditionMixin) { mutation: REGISTER_PERSON, variables: { email: this.email, ...this.identity }, update: ( - store: ApolloCache, + store: ApolloCache<{ registerPerson: IPerson }>, { data: localData }: FetchResult ) => { if (this.userAlreadyActivated) { diff --git a/js/src/views/Admin/AdminGroupProfile.vue b/js/src/views/Admin/AdminGroupProfile.vue index e4bae72db..9a8e8a18b 100644 --- a/js/src/views/Admin/AdminGroupProfile.vue +++ b/js/src/views/Admin/AdminGroupProfile.vue @@ -289,7 +289,7 @@ import { usernameWithDomain, IActor } from "../../types/actor/actor.model"; import RouteName from "../../router/name"; import ActorCard from "../../components/Account/ActorCard.vue"; import EmptyContent from "../../components/Utils/EmptyContent.vue"; -import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; +import { ApolloCache, FetchResult } from "@apollo/client/core"; import VueRouter from "vue-router"; const { isNavigationFailure, NavigationFailureType } = VueRouter; @@ -427,7 +427,10 @@ export default class AdminGroupProfile extends Vue { variables: { id: this.id, }, - update: (store: ApolloCache, { data }: FetchResult) => { + update: ( + store: ApolloCache<{ suspendProfile: { id: string } }>, + { data }: FetchResult + ) => { if (data == null) return; const profileId = this.id; diff --git a/js/src/views/Admin/AdminProfile.vue b/js/src/views/Admin/AdminProfile.vue index 84e909ffb..8f30cfa36 100644 --- a/js/src/views/Admin/AdminProfile.vue +++ b/js/src/views/Admin/AdminProfile.vue @@ -272,7 +272,7 @@ import { usernameWithDomain } from "../../types/actor/actor.model"; import RouteName from "../../router/name"; import ActorCard from "../../components/Account/ActorCard.vue"; import EmptyContent from "../../components/Utils/EmptyContent.vue"; -import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core"; +import { ApolloCache, FetchResult } from "@apollo/client/core"; import VueRouter from "vue-router"; import { MemberRole } from "@/types/enums"; const { isNavigationFailure, NavigationFailureType } = VueRouter; @@ -389,7 +389,10 @@ export default class AdminProfile extends Vue { variables: { id: this.id, }, - update: (store: ApolloCache, { data }: FetchResult) => { + update: ( + store: ApolloCache<{ suspendProfile: { id: string } }>, + { data }: FetchResult + ) => { if (data == null) return; const profileId = this.id; diff --git a/js/src/views/Discussions/Discussion.vue b/js/src/views/Discussions/Discussion.vue index eeff5c07d..aa4999b6e 100644 --- a/js/src/views/Discussions/Discussion.vue +++ b/js/src/views/Discussions/Discussion.vue @@ -127,7 +127,6 @@