diff --git a/js/.eslintrc.js b/js/.eslintrc.js index ac692e5ee..d29e98c47 100644 --- a/js/.eslintrc.js +++ b/js/.eslintrc.js @@ -48,6 +48,8 @@ module.exports = { "import/prefer-default-export": "off", "import/extensions": "off", "import/no-unresolved": "off", + "no-shadow": "off", + "@typescript-eslint/no-shadow": ["error"], }, ignorePatterns: ["src/typings/*.d.ts", "vue.config.js"], diff --git a/js/src/@types/dom.d.ts b/js/src/@types/dom.d.ts new file mode 100644 index 000000000..59a3a0781 --- /dev/null +++ b/js/src/@types/dom.d.ts @@ -0,0 +1,18 @@ +declare global { + interface GeolocationCoordinates { + readonly accuracy: number; + readonly altitude: number | null; + readonly altitudeAccuracy: number | null; + readonly heading: number | null; + readonly latitude: number; + readonly longitude: number; + readonly speed: number | null; + } + + interface GeolocationPosition { + readonly coords: GeolocationCoordinates; + readonly timestamp: number; + } +} + +export {}; diff --git a/js/src/apollo/user.ts b/js/src/apollo/user.ts index 5abd70fcf..824df6f73 100644 --- a/js/src/apollo/user.ts +++ b/js/src/apollo/user.ts @@ -1,8 +1,11 @@ +import { ICurrentUserRole } from "@/types/enums"; import { ApolloCache } from "apollo-cache"; import { NormalizedCacheObject } from "apollo-cache-inmemory"; -import { ICurrentUserRole } from "@/types/current-user.model"; +import { Resolvers } from "apollo-client/core/types"; -export default function buildCurrentUserResolver(cache: ApolloCache<NormalizedCacheObject>) { +export default function buildCurrentUserResolver( + cache: ApolloCache<NormalizedCacheObject> +): Resolvers { cache.writeData({ data: { currentUser: { diff --git a/js/src/components/Account/Identities.vue b/js/src/components/Account/Identities.vue index 81c08e66a..6dea19a45 100644 --- a/js/src/components/Account/Identities.vue +++ b/js/src/components/Account/Identities.vue @@ -53,7 +53,7 @@ export default class Identities extends Vue { errors: string[] = []; - isCurrentIdentity(identity: IPerson) { + isCurrentIdentity(identity: IPerson): boolean { return identity.preferredUsername === this.currentIdentityName; } } diff --git a/js/src/components/Account/ParticipantCard.vue b/js/src/components/Account/ParticipantCard.vue deleted file mode 100644 index 807e2f3a5..000000000 --- a/js/src/components/Account/ParticipantCard.vue +++ /dev/null @@ -1,94 +0,0 @@ -<docs> -```vue -<participant-card :participant="{ actor: { preferredUsername: 'user1', name: 'someoneIDontLike' }, role: 'REJECTED' }" /> -``` - -```vue -<participant-card :participant="{ actor: { preferredUsername: 'user2', name: 'someoneWhoWillWait' }, role: 'NOT_APPROVED' }" /> -``` - -```vue -<participant-card :participant="{ actor: { preferredUsername: 'user3', name: 'a_participant' }, role: 'PARTICIPANT' }" /> -``` - -```vue -<participant-card :participant="{ actor: { preferredUsername: 'me', name: 'myself' }, role: 'CREATOR' }" /> -``` -</docs> -<template> - <article class="card"> - <div class="card-content"> - <div class="media"> - <div class="media-left" v-if="participant.actor.avatar"> - <figure class="image is-48x48"> - <img :src="participant.actor.avatar.url" /> - </figure> - </div> - <div class="media-content"> - <span ref="title">{{ actorDisplayName }}</span - ><br /> - <small class="has-text-grey" v-if="participant.actor.domain" - >@{{ participant.actor.preferredUsername }}@{{ participant.actor.domain }}</small - > - <small class="has-text-grey" v-else>@{{ participant.actor.preferredUsername }}</small> - </div> - </div> - </div> - <footer class="card-footer"> - <b-button - v-if="[ParticipantRole.NOT_APPROVED, ParticipantRole.REJECTED].includes(participant.role)" - @click="accept(participant)" - type="is-success" - class="card-footer-item" - >{{ $t("Approve") }}</b-button - > - <b-button - v-if="participant.role === ParticipantRole.NOT_APPROVED" - @click="reject(participant)" - type="is-danger" - class="card-footer-item" - >{{ $t("Reject") }}</b-button - > - <b-button - v-if="participant.role === ParticipantRole.PARTICIPANT" - @click="exclude(participant)" - type="is-danger" - class="card-footer-item" - >{{ $t("Exclude") }}</b-button - > - <span v-if="participant.role === ParticipantRole.CREATOR" class="card-footer-item">{{ - $t("Creator") - }}</span> - </footer> - </article> -</template> - -<script lang="ts"> -import { Component, Prop, Vue } from "vue-property-decorator"; -import { IParticipant, ParticipantRole } from "../../types/participant.model"; -import { IPerson, Person } from "../../types/actor"; - -@Component -export default class ParticipantCard extends Vue { - @Prop({ required: true }) participant!: IParticipant; - - @Prop({ type: Function }) accept!: Function; - - @Prop({ type: Function }) reject!: Function; - - @Prop({ type: Function }) exclude!: Function; - - ParticipantRole = ParticipantRole; - - get actorDisplayName(): string { - const actor = new Person(this.participant.actor as IPerson); - return actor.displayName(); - } -} -</script> - -<style lang="scss"> -.card-footer-item { - height: $control-height; -} -</style> diff --git a/js/src/components/Account/PopoverActorCard.vue b/js/src/components/Account/PopoverActorCard.vue index a61d08880..7374376c5 100644 --- a/js/src/components/Account/PopoverActorCard.vue +++ b/js/src/components/Account/PopoverActorCard.vue @@ -12,8 +12,9 @@ </v-popover> </template> <script lang="ts"> +import { ActorType } from "@/types/enums"; import { Component, Vue, Prop } from "vue-property-decorator"; -import { IActor, ActorType } from "../../types/actor"; +import { IActor } from "../../types/actor"; import ActorCard from "./ActorCard.vue"; @Component({ diff --git a/js/src/components/Admin/Followings.vue b/js/src/components/Admin/Followings.vue index d39a8c746..f3531d931 100644 --- a/js/src/components/Admin/Followings.vue +++ b/js/src/components/Admin/Followings.vue @@ -103,7 +103,6 @@ import { SnackbarProgrammatic as Snackbar } from "buefy"; import { formatDistanceToNow } from "date-fns"; import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin"; import { IFollower } from "../../types/actor/follower.model"; -import { Paginate } from "../../types/paginate"; import RelayMixin from "../../mixins/relay"; @Component({ diff --git a/js/src/components/Comment/Comment.vue b/js/src/components/Comment/Comment.vue index 825c81628..9f9d3b304 100644 --- a/js/src/components/Comment/Comment.vue +++ b/js/src/components/Comment/Comment.vue @@ -137,7 +137,7 @@ import { Component, Prop, Vue, Ref } from "vue-property-decorator"; import EditorComponent from "@/components/Editor.vue"; import { SnackbarProgrammatic as Snackbar } from "buefy"; import { formatDistanceToNow } from "date-fns"; -import { CommentModeration } from "../../types/event-options.model"; +import { CommentModeration } from "@/types/enums"; import { CommentModel, IComment } from "../../types/comment.model"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import { IPerson, usernameWithDomain } from "../../types/actor"; diff --git a/js/src/components/Comment/CommentTree.vue b/js/src/components/Comment/CommentTree.vue index ab6ce3286..06b61a31c 100644 --- a/js/src/components/Comment/CommentTree.vue +++ b/js/src/components/Comment/CommentTree.vue @@ -51,7 +51,7 @@ import { Prop, Vue, Component, Watch } from "vue-property-decorator"; import Comment from "@/components/Comment/Comment.vue"; import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue"; -import { CommentModeration } from "../../types/event-options.model"; +import { CommentModeration } from "@/types/enums"; import { CommentModel, IComment } from "../../types/comment.model"; import { CREATE_COMMENT_FROM_EVENT, diff --git a/js/src/components/Editor.vue b/js/src/components/Editor.vue index 8117e5526..7223d4ba3 100644 --- a/js/src/components/Editor.vue +++ b/js/src/components/Editor.vue @@ -395,15 +395,7 @@ export default class EditorComponent extends Vue { new Image(), new MaxSize({ maxSize: this.maxSize }), ], - onUpdate: ({ - getHTML, - transaction, - getJSON, - }: { - getHTML: Function; - getJSON: Function; - transaction: unknown; - }) => { + onUpdate: ({ getHTML }: { getHTML: Function }) => { this.$emit("input", getHTML()); }, }); diff --git a/js/src/components/Editor/MaxSize.ts b/js/src/components/Editor/MaxSize.ts index a1d113704..3205263f6 100644 --- a/js/src/components/Editor/MaxSize.ts +++ b/js/src/components/Editor/MaxSize.ts @@ -1,11 +1,14 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck import { Extension, Plugin } from "tiptap"; export default class MaxSize extends Extension { + // eslint-disable-next-line class-methods-use-this get name() { return "maxSize"; } + // eslint-disable-next-line class-methods-use-this get defaultOptions() { return { maxSize: null, @@ -21,7 +24,7 @@ export default class MaxSize extends Extension { const newLength = newState.doc.content.size; if (newLength > max && newLength > oldLength) { - let newTr = newState.tr; + const newTr = newState.tr; newTr.insertText("", max + 1, newLength); return newTr; diff --git a/js/src/components/Event/AddressAutoComplete.vue b/js/src/components/Event/AddressAutoComplete.vue index 49a93b9e7..17e6c139d 100644 --- a/js/src/components/Event/AddressAutoComplete.vue +++ b/js/src/components/Event/AddressAutoComplete.vue @@ -50,7 +50,7 @@ <script lang="ts"> import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import { LatLng } from "leaflet"; -import { debounce } from "lodash"; +import { debounce, DebouncedFunc } from "lodash"; import { Address, IAddress } from "../../types/address.model"; import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address"; import { CONFIG } from "../../graphql/config"; @@ -81,7 +81,7 @@ export default class AddressAutoComplete extends Vue { private gettingLocation = false; - private location!: Position; + private location!: GeolocationPosition; private gettingLocationError: any; @@ -89,7 +89,7 @@ export default class AddressAutoComplete extends Vue { config!: IConfig; - fetchAsyncData!: Function; + fetchAsyncData!: DebouncedFunc<(query: string) => Promise<void>>; // We put this in data because of issues like // https://github.com/vuejs/vue-class-component/issues/263 @@ -207,7 +207,7 @@ export default class AddressAutoComplete extends Vue { this.gettingLocation = false; } - static async getLocation(): Promise<Position> { + static async getLocation(): Promise<GeolocationPosition> { return new Promise((resolve, reject) => { if (!("geolocation" in navigator)) { reject(new Error("Geolocation is not available.")); diff --git a/js/src/components/Event/EventCard.vue b/js/src/components/Event/EventCard.vue index a399a5021..31d95b799 100644 --- a/js/src/components/Event/EventCard.vue +++ b/js/src/components/Event/EventCard.vue @@ -77,7 +77,7 @@ import { IEvent, IEventCardOptions } from "@/types/event.model"; import { Component, Prop, Vue } from "vue-property-decorator"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import { Actor, Person } from "@/types/actor"; -import { ParticipantRole } from "../../types/participant.model"; +import { ParticipantRole } from "@/types/enums"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/components/Event/EventListCard.vue b/js/src/components/Event/EventListCard.vue index 780bd96f0..6f2953e74 100644 --- a/js/src/components/Event/EventListCard.vue +++ b/js/src/components/Event/EventListCard.vue @@ -187,8 +187,9 @@ import { Component, Prop } from "vue-property-decorator"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import { mixins } from "vue-class-component"; import { RawLocation, Route } from "vue-router"; -import { IParticipant, ParticipantRole } from "../../types/participant.model"; -import { EventVisibility, IEventCardOptions } from "../../types/event.model"; +import { EventVisibility, ParticipantRole } from "@/types/enums"; +import { IParticipant } from "../../types/participant.model"; +import { IEventCardOptions } from "../../types/event.model"; import { IPerson } from "../../types/actor"; import ActorMixin from "../../mixins/actor"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; diff --git a/js/src/components/Event/EventListViewCard.vue b/js/src/components/Event/EventListViewCard.vue index 895637dbc..99113f40d 100644 --- a/js/src/components/Event/EventListViewCard.vue +++ b/js/src/components/Event/EventListViewCard.vue @@ -51,7 +51,7 @@ </template> <script lang="ts"> -import { EventVisibility, IEventCardOptions, IEvent } from "@/types/event.model"; +import { IEventCardOptions, IEvent } from "@/types/event.model"; import { Component, Prop } from "vue-property-decorator"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import { IPerson, usernameWithDomain } from "@/types/actor"; @@ -59,7 +59,7 @@ import { mixins } from "vue-class-component"; import ActorMixin from "@/mixins/actor"; import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import EventMixin from "@/mixins/event"; -import { ParticipantRole } from "../../types/participant.model"; +import { EventVisibility, ParticipantRole } from "@/types/enums"; import RouteName from "../../router/name"; const defaultOptions: IEventCardOptions = { diff --git a/js/src/components/Event/EventMinimalistCard.vue b/js/src/components/Event/EventMinimalistCard.vue index 7d8455263..2f7db05a4 100644 --- a/js/src/components/Event/EventMinimalistCard.vue +++ b/js/src/components/Event/EventMinimalistCard.vue @@ -56,7 +56,7 @@ import { Component, Prop, Vue } from "vue-property-decorator"; import { IEvent } from "@/types/event.model"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; -import { ParticipantRole } from "../../types/participant.model"; +import { ParticipantRole } from "@/types/enums"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/components/Event/FullAddressAutoComplete.vue b/js/src/components/Event/FullAddressAutoComplete.vue index 00acbaa4a..14b96533d 100644 --- a/js/src/components/Event/FullAddressAutoComplete.vue +++ b/js/src/components/Event/FullAddressAutoComplete.vue @@ -102,7 +102,7 @@ <script lang="ts"> import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import { LatLng } from "leaflet"; -import { debounce } from "lodash"; +import { debounce, DebouncedFunc } from "lodash"; import { Address, IAddress } from "../../types/address.model"; import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address"; import { CONFIG } from "../../graphql/config"; @@ -133,7 +133,7 @@ export default class FullAddressAutoComplete extends Vue { private gettingLocation = false; - private location!: Position; + private location!: GeolocationPosition; private gettingLocationError: any; @@ -141,11 +141,11 @@ export default class FullAddressAutoComplete extends Vue { config!: IConfig; - fetchAsyncData!: Function; + fetchAsyncData!: DebouncedFunc<(query: string) => Promise<void>>; // We put this in data because of issues like // https://github.com/vuejs/vue-class-component/issues/263 - data() { + data(): Record<string, unknown> { return { fetchAsyncData: debounce(this.asyncData, 200), }; @@ -266,7 +266,7 @@ export default class FullAddressAutoComplete extends Vue { return window.isSecureContext; } - static async getLocation(): Promise<Position> { + static async getLocation(): Promise<GeolocationPosition> { return new Promise((resolve, reject) => { if (!("geolocation" in navigator)) { reject(new Error("Geolocation is not available.")); diff --git a/js/src/components/Event/OrganizerPicker.vue b/js/src/components/Event/OrganizerPicker.vue index 7eb58814b..dcc455789 100644 --- a/js/src/components/Event/OrganizerPicker.vue +++ b/js/src/components/Event/OrganizerPicker.vue @@ -23,9 +23,11 @@ </template> <script lang="ts"> import { Component, Prop, Vue, Watch } from "vue-property-decorator"; -import { IMember, IPerson, MemberRole, IActor, Actor } from "@/types/actor"; +import { IPerson, IActor, Actor } from "@/types/actor"; import { PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { Paginate } from "@/types/paginate"; +import { IMember } from "@/types/actor/member.model"; +import { MemberRole } from "@/types/enums"; @Component({ apollo: { diff --git a/js/src/components/Event/OrganizerPickerWrapper.vue b/js/src/components/Event/OrganizerPickerWrapper.vue index abc94ea66..ff76936aa 100644 --- a/js/src/components/Event/OrganizerPickerWrapper.vue +++ b/js/src/components/Event/OrganizerPickerWrapper.vue @@ -115,7 +115,8 @@ </template> <script lang="ts"> import { Component, Prop, Vue, Watch } from "vue-property-decorator"; -import { IActor, IGroup, IMember, IPerson } from "../../types/actor"; +import { IMember } from "@/types/actor/member.model"; +import { IActor, IGroup, IPerson } from "../../types/actor"; import OrganizerPicker from "./OrganizerPicker.vue"; import { PERSON_MEMBERSHIPS_WITH_MEMBERS } from "../../graphql/actor"; import { Paginate } from "../../types/paginate"; @@ -182,7 +183,7 @@ export default class OrganizerPickerWrapper extends Vue { ({ parent: { id } }) => id === this.currentActor.id ); if (currentMembership) { - return currentMembership.parent.members.elements.map(({ actor }) => actor); + return currentMembership.parent.members.elements.map(({ actor }: { actor: IActor }) => actor); } return []; } diff --git a/js/src/components/Event/ParticipationButton.vue b/js/src/components/Event/ParticipationButton.vue index f77a342af..27a02da95 100644 --- a/js/src/components/Event/ParticipationButton.vue +++ b/js/src/components/Event/ParticipationButton.vue @@ -142,8 +142,9 @@ A button to set your participation <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { IParticipant, ParticipantRole } from "../../types/participant.model"; -import { EventJoinOptions, IEvent } from "../../types/event.model"; +import { EventJoinOptions, ParticipantRole } from "@/types/enums"; +import { IParticipant } from "../../types/participant.model"; +import { IEvent } from "../../types/event.model"; import { IPerson, Person } from "../../types/actor"; import { CURRENT_ACTOR_CLIENT, IDENTITIES } from "../../graphql/actor"; import { CURRENT_USER_CLIENT } from "../../graphql/user"; diff --git a/js/src/components/Event/ShareEventModal.vue b/js/src/components/Event/ShareEventModal.vue index f98056a51..56e1b341a 100644 --- a/js/src/components/Event/ShareEventModal.vue +++ b/js/src/components/Event/ShareEventModal.vue @@ -76,7 +76,9 @@ <script lang="ts"> import { Component, Prop, Vue, Ref } from "vue-property-decorator"; -import { IEvent, EventVisibility, EventStatus } from "../../types/event.model"; +import { EventStatus, EventVisibility } from "@/types/enums"; +import { IEvent } from "../../types/event.model"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore import DiasporaLogo from "../../assets/diaspora-icon.svg?inline"; @@ -124,7 +126,7 @@ export default class ShareEventModal extends Vue { )}&url=${encodeURIComponent(this.event.url)}`; } - copyURL() { + copyURL(): void { this.eventURLInput.$refs.input.select(); document.execCommand("copy"); this.showCopiedTooltip = true; diff --git a/js/src/components/Event/TagInput.vue b/js/src/components/Event/TagInput.vue index bade41cf8..0a0e82ebe 100644 --- a/js/src/components/Event/TagInput.vue +++ b/js/src/components/Event/TagInput.vue @@ -40,7 +40,6 @@ import { ITag } from "../../types/tag.model"; if (typeof tag !== "string") { return tag; } - // @ts-ignore return { title: tag, slug: tag } as ITag; }); this.$emit("input", tagEntities); @@ -57,14 +56,10 @@ export default class TagInput extends Vue { filteredTags: ITag[] = []; - getFilteredTags(text: string) { + getFilteredTags(text: string): void { this.filteredTags = differenceBy(this.data, this.value, "id").filter( (option) => get(option, this.path).toString().toLowerCase().indexOf(text.toLowerCase()) >= 0 ); } - - static isTag(x: any): x is ITag { - return x.slug !== undefined; - } } </script> diff --git a/js/src/components/Group/GroupMemberCard.vue b/js/src/components/Group/GroupMemberCard.vue index f00689077..0b94eacdd 100644 --- a/js/src/components/Group/GroupMemberCard.vue +++ b/js/src/components/Group/GroupMemberCard.vue @@ -54,7 +54,9 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { IMember, MemberRole, usernameWithDomain } from "@/types/actor"; +import { usernameWithDomain } from "@/types/actor"; +import { IMember } from "@/types/actor/member.model"; +import { MemberRole } from "@/types/enums"; import RouteName from "../../router/name"; @Component diff --git a/js/src/components/Group/GroupPicker.vue b/js/src/components/Group/GroupPicker.vue index 071aa5b3a..12211563d 100644 --- a/js/src/components/Group/GroupPicker.vue +++ b/js/src/components/Group/GroupPicker.vue @@ -36,9 +36,11 @@ </template> <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { IGroup, IMember, IPerson, Group, MemberRole } from "@/types/actor"; +import { IGroup, IPerson, Group } from "@/types/actor"; import { PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { Paginate } from "@/types/paginate"; +import { IMember } from "@/types/actor/member.model"; +import { MemberRole } from "@/types/enums"; @Component({ apollo: { diff --git a/js/src/components/Group/GroupPickerWrapper.vue b/js/src/components/Group/GroupPickerWrapper.vue index c2c0a5764..61c009a32 100644 --- a/js/src/components/Group/GroupPickerWrapper.vue +++ b/js/src/components/Group/GroupPickerWrapper.vue @@ -61,7 +61,8 @@ </template> <script lang="ts"> import { Component, Prop, Vue, Watch } from "vue-property-decorator"; -import { IGroup, IMember, IPerson } from "../../types/actor"; +import { IMember } from "@/types/actor/member.model"; +import { IGroup, IPerson } from "../../types/actor"; import GroupPicker from "./GroupPicker.vue"; import { PERSON_MEMBERSHIPS } from "../../graphql/actor"; import { Paginate } from "../../types/paginate"; diff --git a/js/src/components/Group/InvitationCard.vue b/js/src/components/Group/InvitationCard.vue index 9292bb264..8d02ddb51 100644 --- a/js/src/components/Group/InvitationCard.vue +++ b/js/src/components/Group/InvitationCard.vue @@ -54,7 +54,8 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { IMember, usernameWithDomain } from "@/types/actor"; +import { usernameWithDomain } from "@/types/actor"; +import { IMember } from "@/types/actor/member.model"; import RouteName from "../../router/name"; @Component diff --git a/js/src/components/Group/Invitations.vue b/js/src/components/Group/Invitations.vue index d999a737b..c7ce08b3d 100644 --- a/js/src/components/Group/Invitations.vue +++ b/js/src/components/Group/Invitations.vue @@ -11,10 +11,10 @@ </template> <script lang="ts"> import { ACCEPT_INVITATION, REJECT_INVITATION } from "@/graphql/member"; -import { IMember } from "@/types/actor"; import { Component, Prop, Vue } from "vue-property-decorator"; import InvitationCard from "@/components/Group/InvitationCard.vue"; import { LOGGED_USER_MEMBERSHIPS } from "@/graphql/actor"; +import { IMember } from "@/types/actor/member.model"; @Component({ components: { diff --git a/js/src/components/Map.vue b/js/src/components/Map.vue index ab05c5248..00ebaa3a3 100644 --- a/js/src/components/Map.vue +++ b/js/src/components/Map.vue @@ -53,10 +53,10 @@ export default class Map extends Vue { @Prop({ type: Object, required: false }) marker!: { text: string | string[]; icon: string }; - @Prop({ type: Object, required: false }) options!: object; + @Prop({ type: Object, required: false }) options!: Record<string, unknown>; @Prop({ type: Function, required: false }) - updateDraggableMarkerCallback!: Function; + updateDraggableMarkerCallback!: (latlng: LatLng, zoom: number) => void; defaultOptions: { zoom: number; @@ -86,45 +86,47 @@ export default class Map extends Vue { } /* eslint-enable */ - openPopup(event: LeafletEvent) { + openPopup(event: LeafletEvent): void { this.$nextTick(() => { event.target.openPopup(); }); } - get mergedOptions(): object { + get mergedOptions(): Record<string, unknown> { return { ...this.defaultOptions, ...this.options }; } - get lat() { + get lat(): number { return this.$props.coords.split(";")[1]; } - get lon() { + get lon(): number { return this.$props.coords.split(";")[0]; } - get popupMultiLine() { + get popupMultiLine(): Array<string> { if (Array.isArray(this.marker.text)) { return this.marker.text; } return [this.marker.text]; } - clickMap(event: LeafletMouseEvent) { + clickMap(event: LeafletMouseEvent): void { this.updateDraggableMarkerPosition(event.latlng); } - updateDraggableMarkerPosition(e: LatLng) { + updateDraggableMarkerPosition(e: LatLng): void { this.updateDraggableMarkerCallback(e, this.zoom); } - updateZoom(zoom: number) { + updateZoom(zoom: number): void { this.zoom = zoom; } - get attribution() { - return this.config.maps.tiles.attribution || this.$t("© The OpenStreetMap Contributors"); + get attribution(): string { + return ( + this.config.maps.tiles.attribution || (this.$t("© The OpenStreetMap Contributors") as string) + ); } } </script> diff --git a/js/src/components/Map/Vue2LeafletLocateControl.vue b/js/src/components/Map/Vue2LeafletLocateControl.vue index 9a69db9f0..df2de381e 100644 --- a/js/src/components/Map/Vue2LeafletLocateControl.vue +++ b/js/src/components/Map/Vue2LeafletLocateControl.vue @@ -17,13 +17,13 @@ import { Component, Prop, Vue } from "vue-property-decorator"; @Component({ beforeDestroy() { - // eslint-disable-next-line @typescript-eslint/ban-ts-ignore + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this.parentContainer.removeLayer(this); }, }) export default class Vue2LeafletLocateControl extends Vue { - @Prop({ type: Object, default: () => ({}) }) options!: object; + @Prop({ type: Object, default: () => ({}) }) options!: Record<string, unknown>; @Prop({ type: Boolean, default: true }) visible = true; @@ -33,7 +33,7 @@ export default class Vue2LeafletLocateControl extends Vue { parentContainer: any; - mounted() { + mounted(): void { this.mapObject = L.control.locate(this.options); DomEvent.on(this.mapObject, this.$listeners as any); propsBinder(this, this.mapObject, this.$props); @@ -42,7 +42,7 @@ export default class Vue2LeafletLocateControl extends Vue { this.mapObject.addTo(this.parentContainer.mapObject, !this.visible); } - public locate() { + public locate(): void { this.mapObject.start(); } } diff --git a/js/src/components/NavBar.vue b/js/src/components/NavBar.vue index 5af8b3f00..6846f78eb 100644 --- a/js/src/components/NavBar.vue +++ b/js/src/components/NavBar.vue @@ -109,13 +109,14 @@ import { Component, Vue, Watch } from "vue-property-decorator"; import Logo from "@/components/Logo.vue"; import { GraphQLError } from "graphql"; import { loadLanguageAsync } from "@/utils/i18n"; +import { ICurrentUserRole } from "@/types/enums"; import { CURRENT_USER_CLIENT, USER_SETTINGS } from "../graphql/user"; import { changeIdentity, logout } from "../utils/auth"; import { CURRENT_ACTOR_CLIENT, IDENTITIES, UPDATE_DEFAULT_ACTOR } from "../graphql/actor"; import { IPerson, Person } from "../types/actor"; import { CONFIG } from "../graphql/config"; import { IConfig } from "../types/config.model"; -import { ICurrentUser, ICurrentUserRole, IUser } from "../types/current-user.model"; +import { ICurrentUser, IUser } from "../types/current-user.model"; import SearchField from "./SearchField.vue"; import RouteName from "../router/name"; diff --git a/js/src/components/Participation/ConfirmParticipation.vue b/js/src/components/Participation/ConfirmParticipation.vue index 8630e0362..a72c8d4d6 100644 --- a/js/src/components/Participation/ConfirmParticipation.vue +++ b/js/src/components/Participation/ConfirmParticipation.vue @@ -38,9 +38,9 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; import { confirmLocalAnonymousParticipation } from "@/services/AnonymousParticipationStorage"; +import { EventJoinOptions } from "@/types/enums"; import { IParticipant } from "../../types/participant.model"; import RouteName from "../../router/name"; -import { EventJoinOptions } from "../../types/event.model"; import { CONFIRM_PARTICIPATION } from "../../graphql/event"; @Component diff --git a/js/src/components/Participation/ParticipationWithoutAccount.vue b/js/src/components/Participation/ParticipationWithoutAccount.vue index 3f6c67830..980f2432e 100644 --- a/js/src/components/Participation/ParticipationWithoutAccount.vue +++ b/js/src/components/Participation/ParticipationWithoutAccount.vue @@ -74,12 +74,13 @@ </template> <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { EventModel, IEvent, EventJoinOptions } from "@/types/event.model"; +import { EventModel, IEvent } from "@/types/event.model"; import { FETCH_EVENT, JOIN_EVENT } from "@/graphql/event"; import { IConfig } from "@/types/config.model"; import { CONFIG } from "@/graphql/config"; import { addLocalUnconfirmedAnonymousParticipation } from "@/services/AnonymousParticipationStorage"; -import { IParticipant, ParticipantRole } from "../../types/participant.model"; +import { EventJoinOptions, ParticipantRole } from "@/types/enums"; +import { IParticipant } from "../../types/participant.model"; @Component({ apollo: { diff --git a/js/src/components/Post/PostElementItem.vue b/js/src/components/Post/PostElementItem.vue index 1e1f8b3e1..f377c8aae 100644 --- a/js/src/components/Post/PostElementItem.vue +++ b/js/src/components/Post/PostElementItem.vue @@ -43,9 +43,10 @@ </template> <script lang="ts"> import { usernameWithDomain } from "@/types/actor"; +import { PostVisibility } from "@/types/enums"; import { Component, Prop, Vue } from "vue-property-decorator"; import RouteName from "../../router/name"; -import { IPost, PostVisibility } from "../../types/post.model"; +import { IPost } from "../../types/post.model"; @Component export default class PostElementItem extends Vue { diff --git a/js/src/components/Report/ReportCard.vue b/js/src/components/Report/ReportCard.vue index 1f305f30c..0ae5a991b 100644 --- a/js/src/components/Report/ReportCard.vue +++ b/js/src/components/Report/ReportCard.vue @@ -36,7 +36,7 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; import { IReport } from "@/types/report.model"; -import { ActorType } from "@/types/actor"; +import { ActorType } from "@/types/enums"; @Component export default class ReportCard extends Vue { diff --git a/js/src/components/Report/ReportModal.vue b/js/src/components/Report/ReportModal.vue index 020725eb7..57eed0e97 100644 --- a/js/src/components/Report/ReportModal.vue +++ b/js/src/components/Report/ReportModal.vue @@ -82,7 +82,7 @@ import { IComment } from "../../types/comment.model"; }, }) export default class ReportModal extends Vue { - @Prop({ type: Function }) onConfirm!: Function; + @Prop({ type: Function }) onConfirm!: (content: string, forward: boolean) => void; @Prop({ type: String }) title!: string; diff --git a/js/src/components/Resource/ResourceDropdown.vue b/js/src/components/Resource/ResourceDropdown.vue index d1a2e566c..3546381be 100644 --- a/js/src/components/Resource/ResourceDropdown.vue +++ b/js/src/components/Resource/ResourceDropdown.vue @@ -17,7 +17,7 @@ </b-dropdown> </template> <script lang="ts"> -import { Component, Vue, Prop } from "vue-property-decorator"; +import { Component, Vue } from "vue-property-decorator"; @Component export default class ResourceDropdown extends Vue {} diff --git a/js/src/components/Resource/ResourceSelector.vue b/js/src/components/Resource/ResourceSelector.vue index 755604055..2b1fb874b 100644 --- a/js/src/components/Resource/ResourceSelector.vue +++ b/js/src/components/Resource/ResourceSelector.vue @@ -47,7 +47,7 @@ <b-button type="is-primary" @click="updateResource" :disabled="moveDisabled">{{ $t("Move resource to {folder}", { folder: resource.title }) }}</b-button> - <b-button type="is-text" @click="$emit('closeMoveModal')">{{ $t("Cancel") }}</b-button> + <b-button type="is-text" @click="$emit('close-move-modal')">{{ $t("Cancel") }}</b-button> </div> </template> <script lang="ts"> @@ -81,15 +81,15 @@ export default class ResourceSelector extends Vue { resource: IResource | undefined = this.initialResource.parent; - goDown(element: IResource) { + goDown(element: IResource): void { if (element.type === "folder" && element.id !== this.initialResource.id) { this.resource = element; } } - updateResource() { + updateResource(): void { this.$emit( - "updateResource", + "update-resource", { id: this.initialResource.id, title: this.initialResource.title, @@ -100,12 +100,12 @@ export default class ResourceSelector extends Vue { ); } - get moveDisabled() { + get moveDisabled(): boolean | undefined { return ( (this.initialResource.parent && this.resource && this.initialResource.parent.path === this.resource.path) || - (this.initialResource.parent == undefined && this.resource && this.resource.path === "/") + (this.initialResource.parent === undefined && this.resource && this.resource.path === "/") ); } } diff --git a/js/src/components/SearchField.vue b/js/src/components/SearchField.vue index 1e2a27a86..9261059a3 100644 --- a/js/src/components/SearchField.vue +++ b/js/src/components/SearchField.vue @@ -23,9 +23,9 @@ export default class SearchField extends Vue { search = ""; - enter() { + async enter(): Promise<void> { this.$emit("navbar-search"); - this.$router.push({ + await this.$router.push({ name: RouteName.SEARCH, query: { term: this.search }, }); diff --git a/js/src/components/Settings/SettingMenuItem.vue b/js/src/components/Settings/SettingMenuItem.vue index 2f201ae94..5c9103491 100644 --- a/js/src/components/Settings/SettingMenuItem.vue +++ b/js/src/components/Settings/SettingMenuItem.vue @@ -16,7 +16,7 @@ export default class SettingMenuItem extends Vue { @Prop({ required: true, type: Object }) to!: Route; - get isActive() { + get isActive(): boolean { if (!this.to) return false; if (this.to.name === this.$route.name) { if (this.to.params) { diff --git a/js/src/components/Settings/SettingMenuSection.vue b/js/src/components/Settings/SettingMenuSection.vue index cc2d1953a..264eb19b1 100644 --- a/js/src/components/Settings/SettingMenuSection.vue +++ b/js/src/components/Settings/SettingMenuSection.vue @@ -20,11 +20,12 @@ export default class SettingMenuSection extends Vue { @Prop({ required: true, type: Object }) to!: Route; - get sectionActive() { + get sectionActive(): boolean { if (this.$slots.default) { return this.$slots.default.some( ({ componentOptions: { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore propsData: { to }, }, diff --git a/js/src/components/Settings/SettingsMenu.vue b/js/src/components/Settings/SettingsMenu.vue index d64ec2d5c..09f713c1c 100644 --- a/js/src/components/Settings/SettingsMenu.vue +++ b/js/src/components/Settings/SettingsMenu.vue @@ -55,13 +55,14 @@ </aside> </template> <script lang="ts"> -import { Component, Prop, Vue } from "vue-property-decorator"; +import { Component, Vue } from "vue-property-decorator"; +import { ICurrentUserRole } from "@/types/enums"; import SettingMenuSection from "./SettingMenuSection.vue"; import SettingMenuItem from "./SettingMenuItem.vue"; import { IDENTITIES } from "../../graphql/actor"; import { IPerson, Person } from "../../types/actor"; import { CURRENT_USER_CLIENT } from "../../graphql/user"; -import { ICurrentUser, ICurrentUserRole } from "../../types/current-user.model"; +import { ICurrentUser } from "../../types/current-user.model"; import RouteName from "../../router/name"; diff --git a/js/src/components/Todo/FullTodo.vue b/js/src/components/Todo/FullTodo.vue index 3ba34e7e3..9ccf2e9b7 100644 --- a/js/src/components/Todo/FullTodo.vue +++ b/js/src/components/Todo/FullTodo.vue @@ -18,7 +18,7 @@ </template> <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { debounce } from "lodash"; +import { debounce, DebouncedFunc } from "lodash"; import { SnackbarProgrammatic as Snackbar } from "buefy"; import { ITodo } from "../../types/todos"; import RouteName from "../../router/name"; @@ -36,7 +36,7 @@ export default class Todo extends Vue { editMode = false; - debounceUpdateTodo!: Function; + debounceUpdateTodo!: DebouncedFunc<(obj: Record<string, unknown>) => Promise<void>>; // We put this in data because of issues like // https://github.com/vuejs/vue-class-component/issues/263 diff --git a/js/src/components/Utils/RedirectWithAccount.vue b/js/src/components/Utils/RedirectWithAccount.vue index 52c2fb8f1..bd1fa1c17 100644 --- a/js/src/components/Utils/RedirectWithAccount.vue +++ b/js/src/components/Utils/RedirectWithAccount.vue @@ -54,7 +54,7 @@ import { Component, Prop, Vue } from "vue-property-decorator"; import VerticalDivider from "@/components/Utils/VerticalDivider.vue"; import Subtitle from "@/components/Utils/Subtitle.vue"; -import { LoginErrorCode } from "@/types/login-error-code.model"; +import { LoginErrorCode } from "@/types/enums"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/mixins/actor.ts b/js/src/mixins/actor.ts index 9954edf5a..779eae0a7 100644 --- a/js/src/mixins/actor.ts +++ b/js/src/mixins/actor.ts @@ -4,9 +4,9 @@ import { Component, Vue } from "vue-property-decorator"; @Component export default class ActorMixin extends Vue { - static actorIsOrganizer(actor: IActor, event: IEvent) { + static actorIsOrganizer(actor: IActor, event: IEvent): boolean { console.log("actorIsOrganizer actor", actor.id); console.log("actorIsOrganizer event", event); - return event.organizerActor && actor.id === event.organizerActor.id; + return event.organizerActor !== undefined && actor.id === event.organizerActor.id; } } diff --git a/js/src/mixins/event.ts b/js/src/mixins/event.ts index 8bcf9d659..ef672c7c5 100644 --- a/js/src/mixins/event.ts +++ b/js/src/mixins/event.ts @@ -1,7 +1,8 @@ import { mixins } from "vue-class-component"; import { Component, Vue } from "vue-property-decorator"; import { SnackbarProgrammatic as Snackbar } from "buefy"; -import { IParticipant, ParticipantRole } from "../types/participant.model"; +import { ParticipantRole } from "@/types/enums"; +import { IParticipant } from "../types/participant.model"; import { IEvent } from "../types/event.model"; import { DELETE_EVENT, diff --git a/js/src/mixins/group.ts b/js/src/mixins/group.ts index d39e593b4..db47fb957 100644 --- a/js/src/mixins/group.ts +++ b/js/src/mixins/group.ts @@ -2,7 +2,8 @@ import { PERSON_MEMBERSHIPS, CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import { GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED } from "@/graphql/event"; import { FETCH_GROUP } from "@/graphql/group"; import RouteName from "@/router/name"; -import { Group, IActor, IGroup, IPerson, MemberRole } from "@/types/actor"; +import { Group, IActor, IGroup, IPerson } from "@/types/actor"; +import { MemberRole } from "@/types/enums"; import { Component, Vue } from "vue-property-decorator"; @Component({ diff --git a/js/src/mixins/relay.ts b/js/src/mixins/relay.ts index 3b754a5fd..20d3238d6 100644 --- a/js/src/mixins/relay.ts +++ b/js/src/mixins/relay.ts @@ -1,8 +1,9 @@ import { Component, Vue, Ref } from "vue-property-decorator"; -import { ActorType, IActor } from "@/types/actor"; +import { IActor } from "@/types/actor"; import { IFollower } from "@/types/actor/follower.model"; import { RELAY_FOLLOWERS, RELAY_FOLLOWINGS } from "@/graphql/admin"; import { Paginate } from "@/types/paginate"; +import { ActorType } from "@/types/enums"; @Component({ apollo: { diff --git a/js/src/router/event.ts b/js/src/router/event.ts index 6dbc6addb..f443235f4 100644 --- a/js/src/router/event.ts +++ b/js/src/router/event.ts @@ -18,7 +18,6 @@ export enum EventRouteName { EVENT_PARTICIPATE_WITHOUT_ACCOUNT = "EVENT_PARTICIPATE_WITHOUT_ACCOUNT", EVENT_PARTICIPATE_LOGGED_OUT = "EVENT_PARTICIPATE_LOGGED_OUT", EVENT_PARTICIPATE_CONFIRM = "EVENT_PARTICIPATE_CONFIRM", - LOCATION = "Location", TAG = "Tag", } @@ -46,14 +45,17 @@ export const eventRoutes: RouteConfig[] = [ name: EventRouteName.EDIT_EVENT, component: editEvent, meta: { requiredAuth: true }, - props: (route: Route) => ({ ...route.params, ...{ isUpdate: true } }), + props: (route: Route): Record<string, unknown> => ({ ...route.params, ...{ isUpdate: true } }), }, { path: "/events/duplicate/:eventId", name: EventRouteName.DUPLICATE_EVENT, component: editEvent, meta: { requiredAuth: true }, - props: (route: Route) => ({ ...route.params, ...{ isDuplicate: true } }), + props: (route: Route): Record<string, unknown> => ({ + ...route.params, + ...{ isDuplicate: true }, + }), }, { path: "/events/:eventId/participations", @@ -62,12 +64,6 @@ export const eventRoutes: RouteConfig[] = [ meta: { requiredAuth: true }, props: true, }, - { - path: "/location/new", - name: EventRouteName.LOCATION, - component: () => import(/* webpackChunkName: "Location" */ "@/views/Location.vue"), - meta: { requiredAuth: true }, - }, { path: "/events/:uuid", name: EventRouteName.EVENT, diff --git a/js/src/router/guards/auth-guard.ts b/js/src/router/guards/auth-guard.ts index 15b8566b3..4dfa635e1 100644 --- a/js/src/router/guards/auth-guard.ts +++ b/js/src/router/guards/auth-guard.ts @@ -1,7 +1,7 @@ import { NavigationGuard } from "vue-router"; import { UserRouteName } from "@/router/user"; -import { LoginErrorCode } from "@/types/login-error-code.model"; import { AUTH_ACCESS_TOKEN } from "@/constants"; +import { LoginErrorCode } from "@/types/enums"; // eslint-disable-next-line import/prefer-default-export export const authGuardIfNeeded: NavigationGuard = async (to, from, next) => { diff --git a/js/src/router/guards/register-guard.ts b/js/src/router/guards/register-guard.ts index b78acb63e..879d67f83 100644 --- a/js/src/router/guards/register-guard.ts +++ b/js/src/router/guards/register-guard.ts @@ -1,6 +1,6 @@ +import { ErrorCode } from "@/types/enums"; import { NavigationGuard } from "vue-router"; import { CONFIG } from "../../graphql/config"; -import { ErrorCode } from "../../types/error-code.model"; import apolloProvider from "../../vue-apollo"; // eslint-disable-next-line import/prefer-default-export diff --git a/js/src/router/settings.ts b/js/src/router/settings.ts index 67fcabdae..c4ddacf0c 100644 --- a/js/src/router/settings.ts +++ b/js/src/router/settings.ts @@ -1,4 +1,4 @@ -import { RouteConfig } from "vue-router"; +import { Route, RouteConfig } from "vue-router"; export enum SettingsRouteName { SETTINGS = "SETTINGS", @@ -199,7 +199,10 @@ export const settingsRoutes: RouteConfig[] = [ import( /* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue" ), - props: (route) => ({ identityName: route.params.identityName, isUpdate: false }), + props: (route: Route): Record<string, unknown> => ({ + identityName: route.params.identityName, + isUpdate: false, + }), meta: { requiredAuth: true }, }, { @@ -209,7 +212,10 @@ export const settingsRoutes: RouteConfig[] = [ import( /* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue" ), - props: (route) => ({ identityName: route.params.identityName, isUpdate: true }), + props: (route: Route): Record<string, unknown> => ({ + identityName: route.params.identityName, + isUpdate: true, + }), meta: { requiredAuth: true }, }, ], diff --git a/js/src/router/user.ts b/js/src/router/user.ts index 96989b5af..fd7ce296a 100644 --- a/js/src/router/user.ts +++ b/js/src/router/user.ts @@ -1,5 +1,5 @@ import { beforeRegisterGuard } from "@/router/guards/register-guard"; -import { RouteConfig } from "vue-router"; +import { Route, RouteConfig } from "vue-router"; export enum UserRouteName { REGISTER = "Register", @@ -27,7 +27,7 @@ export const userRoutes: RouteConfig[] = [ component: () => import(/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"), // We can only pass string values through params, therefore - props: (route) => ({ + props: (route: Route): Record<string, unknown> => ({ email: route.params.email, userAlreadyActivated: route.params.userAlreadyActivated === "true", }), diff --git a/js/src/services/AnonymousParticipationStorage.ts b/js/src/services/AnonymousParticipationStorage.ts index 43eb9fbe2..a8f376d3c 100644 --- a/js/src/services/AnonymousParticipationStorage.ts +++ b/js/src/services/AnonymousParticipationStorage.ts @@ -16,6 +16,14 @@ class AnonymousParticipationNotFoundError extends Error { } } +function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> { + return new Map(JSON.parse(jsonStr)); +} + +function mapToJson(map: Map<any, any>): string { + return JSON.stringify([...map]); +} + /** * Fetch existing anonymous participations saved inside this browser */ @@ -25,13 +33,6 @@ function getLocalAnonymousParticipations(): Map<string, IAnonymousParticipation> ); } -function mapToJson(map: Map<any, any>): string { - return JSON.stringify([...map]); -} -function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> { - return new Map(JSON.parse(jsonStr)); -} - /** * Purge participations which expiration has been reached * @param participations Map @@ -39,6 +40,7 @@ function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> { function purgeOldParticipations( participations: Map<string, IAnonymousParticipation> ): Map<string, IAnonymousParticipation> { + // eslint-disable-next-line no-restricted-syntax for (const [hashedUUID, { expiration }] of participations) { if (expiration < new Date()) { participations.delete(hashedUUID); @@ -67,7 +69,18 @@ function buildExpiration(event: IEvent): Date { return expiration; } -async function addLocalUnconfirmedAnonymousParticipation(event: IEvent, cancellationToken: string) { +async function digestMessage(message: string): Promise<string> { + const encoder = new TextEncoder(); + const data = encoder.encode(message); + const hashBuffer = await crypto.subtle.digest("SHA-256", data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); +} + +async function addLocalUnconfirmedAnonymousParticipation( + event: IEvent, + cancellationToken: string +): Promise<void> { /** * We hash the event UUID so that we can't know which events an anonymous user goes by looking up it's localstorage */ @@ -84,7 +97,7 @@ async function addLocalUnconfirmedAnonymousParticipation(event: IEvent, cancella }); } -async function confirmLocalAnonymousParticipation(uuid: string) { +async function confirmLocalAnonymousParticipation(uuid: string): Promise<void> { const participations = purgeOldParticipations(getLocalAnonymousParticipations()); const hashedUUID = await digestMessage(uuid); const participation = participations.get(hashedUUID); @@ -95,11 +108,6 @@ async function confirmLocalAnonymousParticipation(uuid: string) { } } -async function isParticipatingInThisEvent(eventUUID: string): Promise<boolean> { - const participation = await getParticipation(eventUUID); - return participation !== undefined && participation.confirmed; -} - async function getParticipation(eventUUID: string): Promise<IAnonymousParticipation> { const hashedUUID = await digestMessage(eventUUID); const participation = purgeOldParticipations(getLocalAnonymousParticipations()).get(hashedUUID); @@ -109,6 +117,11 @@ async function getParticipation(eventUUID: string): Promise<IAnonymousParticipat throw new AnonymousParticipationNotFoundError("Participation not found"); } +async function isParticipatingInThisEvent(eventUUID: string): Promise<boolean> { + const participation = await getParticipation(eventUUID); + return participation !== undefined && participation.confirmed; +} + async function getLeaveTokenForParticipation(eventUUID: string): Promise<string> { return (await getParticipation(eventUUID)).token; } @@ -120,14 +133,6 @@ async function removeAnonymousParticipation(eventUUID: string): Promise<void> { localStorage.setItem(ANONYMOUS_PARTICIPATIONS_LOCALSTORAGE_KEY, mapToJson(participations)); } -async function digestMessage(message: string): Promise<string> { - const encoder = new TextEncoder(); - const data = encoder.encode(message); - const hashBuffer = await crypto.subtle.digest("SHA-256", data); - const hashArray = Array.from(new Uint8Array(hashBuffer)); - return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); -} - export { addLocalUnconfirmedAnonymousParticipation, confirmLocalAnonymousParticipation, diff --git a/js/src/types/actor/actor.model.ts b/js/src/types/actor/actor.model.ts index d74db12ed..b4f86e078 100644 --- a/js/src/types/actor/actor.model.ts +++ b/js/src/types/actor/actor.model.ts @@ -1,12 +1,5 @@ -import { IMedia } from "@/types/media.model"; - -export enum ActorType { - PERSON = "PERSON", - APPLICATION = "APPLICATION", - GROUP = "GROUP", - ORGANISATION = "ORGANISATION", - SERVICE = "SERVICE", -} +import type { IMedia } from "@/types/media.model"; +import { ActorType } from "../enums"; export interface IActor { id?: string; diff --git a/js/src/types/actor/follower.model.ts b/js/src/types/actor/follower.model.ts index 21f51ec16..9c96b7ec0 100644 --- a/js/src/types/actor/follower.model.ts +++ b/js/src/types/actor/follower.model.ts @@ -1,4 +1,4 @@ -import { IActor } from "@/types/actor/actor.model"; +import type { IActor } from "@/types/actor/actor.model"; export interface IFollower { id?: string; diff --git a/js/src/types/actor/group.model.ts b/js/src/types/actor/group.model.ts index 41cb6f877..f3966c122 100644 --- a/js/src/types/actor/group.model.ts +++ b/js/src/types/actor/group.model.ts @@ -1,38 +1,15 @@ -import { Actor, ActorType, IActor } from "./actor.model"; -import { Paginate } from "../paginate"; -import { IResource } from "../resource"; -import { ITodoList } from "../todos"; -import { IEvent } from "../event.model"; -import { IDiscussion } from "../discussions"; -import { IPerson } from "./person.model"; -import { IPost } from "../post.model"; -import { IAddress, Address } from "../address.model"; - -export enum MemberRole { - NOT_APPROVED = "NOT_APPROVED", - INVITED = "INVITED", - MEMBER = "MEMBER", - MODERATOR = "MODERATOR", - ADMINISTRATOR = "ADMINISTRATOR", - CREATOR = "CREATOR", - REJECTED = "REJECTED", -} - -export enum Openness { - INVITE_ONLY = "INVITE_ONLY", - MODERATED = "MODERATED", - OPEN = "OPEN", -} - -export interface IMember { - id?: string; - role: MemberRole; - parent: IGroup; - actor: IActor; - invitedBy?: IPerson; - insertedAt: string; - updatedAt: string; -} +import type { IActor } from "./actor.model"; +import { Actor } from "./actor.model"; +import type { Paginate } from "../paginate"; +import type { IResource } from "../resource"; +import type { IEvent } from "../event.model"; +import type { IDiscussion } from "../discussions"; +import type { IPost } from "../post.model"; +import type { IAddress } from "../address.model"; +import { Address } from "../address.model"; +import { ActorType, Openness } from "../enums"; +import type { IMember } from "./member.model"; +import type { ITodoList } from "../todolist"; export interface IGroup extends IActor { members: Paginate<IMember>; diff --git a/js/src/types/actor/member.model.ts b/js/src/types/actor/member.model.ts new file mode 100644 index 000000000..24f1c3756 --- /dev/null +++ b/js/src/types/actor/member.model.ts @@ -0,0 +1,12 @@ +import type { IActor, IGroup, IPerson } from "."; +import { MemberRole } from "../enums"; + +export interface IMember { + id?: string; + role: MemberRole; + parent: IGroup; + actor: IActor; + invitedBy?: IPerson; + insertedAt: string; + updatedAt: string; +} diff --git a/js/src/types/actor/person.model.ts b/js/src/types/actor/person.model.ts index 928854e71..699f8a72d 100644 --- a/js/src/types/actor/person.model.ts +++ b/js/src/types/actor/person.model.ts @@ -1,15 +1,11 @@ -import { ICurrentUser } from "../current-user.model"; -import { IEvent } from "../event.model"; -import { Actor, IActor } from "./actor.model"; -import { Paginate } from "../paginate"; -import { IMember } from "./group.model"; -import { IParticipant } from "../participant.model"; - -export interface IFeedToken { - token: string; - actor?: IPerson; - user: ICurrentUser; -} +import type { ICurrentUser } from "../current-user.model"; +import type { IEvent } from "../event.model"; +import { Actor } from "./actor.model"; +import type { IActor } from "./actor.model"; +import type { Paginate } from "../paginate"; +import type { IParticipant } from "../participant.model"; +import type { IMember } from "./member.model"; +import type { IFeedToken } from "../feedtoken.model"; export interface IPerson extends IActor { feedTokens: IFeedToken[]; diff --git a/js/src/types/address.model.ts b/js/src/types/address.model.ts index e320f59a9..a306a6f1c 100644 --- a/js/src/types/address.model.ts +++ b/js/src/types/address.model.ts @@ -1,4 +1,5 @@ -import { poiIcons, IPOIIcon } from "@/utils/poiIcons"; +import { poiIcons } from "@/utils/poiIcons"; +import type { IPOIIcon } from "@/utils/poiIcons"; export interface IAddress { id?: string; @@ -53,7 +54,7 @@ export class Address implements IAddress { this.originId = hash.originId; } - get poiInfos() { + get poiInfos(): { name: string; alternativeName: string; poiIcon: IPOIIcon } { /* generate name corresponding to poi type */ let name = ""; let alternativeName = ""; diff --git a/js/src/types/admin.model.ts b/js/src/types/admin.model.ts index 9872e5aca..00d165428 100644 --- a/js/src/types/admin.model.ts +++ b/js/src/types/admin.model.ts @@ -1,5 +1,6 @@ -import { IEvent } from "@/types/event.model"; -import { IGroup } from "./actor"; +import type { IEvent } from "@/types/event.model"; +import type { IGroup } from "./actor"; +import { InstanceTermsType } from "./enums"; export interface IDashboard { lastPublicEventPublished: IEvent; @@ -14,23 +15,10 @@ export interface IDashboard { numberOfConfirmedParticipationsToLocalEvents: number; } -export enum InstanceTermsType { - DEFAULT = "DEFAULT", - URL = "URL", - CUSTOM = "CUSTOM", -} - -export enum InstancePrivacyType { - DEFAULT = "DEFAULT", - URL = "URL", - CUSTOM = "CUSTOM", -} - export interface ILanguage { code: string; name: string; } - export interface IAdminSettings { instanceName: string; instanceDescription: string; diff --git a/js/src/types/comment.model.ts b/js/src/types/comment.model.ts index 5f45f4bd7..95de6f3af 100644 --- a/js/src/types/comment.model.ts +++ b/js/src/types/comment.model.ts @@ -1,5 +1,7 @@ -import { Actor, IActor } from "@/types/actor"; -import { EventModel, IEvent } from "@/types/event.model"; +import { Actor } from "@/types/actor"; +import type { IActor } from "@/types/actor"; +import type { IEvent } from "@/types/event.model"; +import { EventModel } from "@/types/event.model"; export interface IComment { id?: string; diff --git a/js/src/types/config.model.ts b/js/src/types/config.model.ts index 3c314b387..af43f666e 100644 --- a/js/src/types/config.model.ts +++ b/js/src/types/config.model.ts @@ -1,5 +1,5 @@ -import { InstanceTermsType, InstancePrivacyType } from "./admin.model"; -import { IProvider } from "./resource"; +import { InstancePrivacyType, InstanceTermsType } from "./enums"; +import type { IProvider } from "./resource"; export interface IOAuthProvider { id: string; diff --git a/js/src/types/current-user.model.ts b/js/src/types/current-user.model.ts index 3b2a29ea0..2c834c552 100644 --- a/js/src/types/current-user.model.ts +++ b/js/src/types/current-user.model.ts @@ -1,13 +1,8 @@ -import { IEvent } from "@/types/event.model"; -import { IPerson } from "@/types/actor/person.model"; -import { Paginate } from "./paginate"; -import { IParticipant } from "./participant.model"; - -export enum ICurrentUserRole { - USER = "USER", - MODERATOR = "MODERATOR", - ADMINISTRATOR = "ADMINISTRATOR", -} +import type { IEvent } from "@/types/event.model"; +import type { IPerson } from "@/types/actor/person.model"; +import type { Paginate } from "./paginate"; +import type { IParticipant } from "./participant.model"; +import { ICurrentUserRole, INotificationPendingEnum } from "./enums"; export interface ICurrentUser { id: string; @@ -17,13 +12,6 @@ export interface ICurrentUser { defaultActor?: IPerson; } -export enum INotificationPendingEnum { - NONE = "NONE", - DIRECT = "DIRECT", - ONE_DAY = "ONE_DAY", - ONE_HOUR = "ONE_HOUR", -} - export interface IUserSettings { timezone: string; notificationOnDay: boolean; @@ -49,14 +37,3 @@ export interface IUser extends ICurrentUser { currentSignInIp: string; currentSignInAt: string; } - -export enum IAuthProvider { - LDAP = "ldap", - GOOGLE = "google", - DISCORD = "discord", - GITHUB = "github", - KEYCLOAK = "keycloak", - FACEBOOK = "facebook", - GITLAB = "gitlab", - TWITTER = "twitter", -} diff --git a/js/src/types/discussions.ts b/js/src/types/discussions.ts index 11ced50ad..d3b483b9b 100644 --- a/js/src/types/discussions.ts +++ b/js/src/types/discussions.ts @@ -1,6 +1,7 @@ -import { IActor, IPerson } from "@/types/actor"; -import { IComment, CommentModel } from "@/types/comment.model"; -import { Paginate } from "@/types/paginate"; +import type { IActor, IPerson } from "@/types/actor"; +import type { IComment } from "@/types/comment.model"; +import { CommentModel } from "@/types/comment.model"; +import type { Paginate } from "@/types/paginate"; export interface IDiscussion { id?: string; diff --git a/js/src/types/enums.ts b/js/src/types/enums.ts new file mode 100644 index 000000000..1fce2d6c4 --- /dev/null +++ b/js/src/types/enums.ts @@ -0,0 +1,161 @@ +export enum InstanceTermsType { + DEFAULT = "DEFAULT", + URL = "URL", + CUSTOM = "CUSTOM", +} + +export enum InstancePrivacyType { + DEFAULT = "DEFAULT", + URL = "URL", + CUSTOM = "CUSTOM", +} + +export enum ICurrentUserRole { + USER = "USER", + MODERATOR = "MODERATOR", + ADMINISTRATOR = "ADMINISTRATOR", +} + +export enum INotificationPendingEnum { + NONE = "NONE", + DIRECT = "DIRECT", + ONE_DAY = "ONE_DAY", + ONE_HOUR = "ONE_HOUR", +} + +export enum IAuthProvider { + LDAP = "ldap", + GOOGLE = "google", + DISCORD = "discord", + GITHUB = "github", + KEYCLOAK = "keycloak", + FACEBOOK = "facebook", + GITLAB = "gitlab", + TWITTER = "twitter", +} + +export enum ErrorCode { + UNKNOWN = "unknown", + REGISTRATION_CLOSED = "registration_closed", +} + +export enum CommentModeration { + ALLOW_ALL = "ALLOW_ALL", + MODERATED = "MODERATED", + CLOSED = "CLOSED", +} + +export enum EventStatus { + TENTATIVE = "TENTATIVE", + CONFIRMED = "CONFIRMED", + CANCELLED = "CANCELLED", +} + +export enum EventVisibility { + PUBLIC = "PUBLIC", + UNLISTED = "UNLISTED", + RESTRICTED = "RESTRICTED", + PRIVATE = "PRIVATE", +} + +export enum EventJoinOptions { + FREE = "FREE", + RESTRICTED = "RESTRICTED", + INVITE = "INVITE", +} + +export enum EventVisibilityJoinOptions { + PUBLIC = "PUBLIC", + LINK = "LINK", + LIMITED = "LIMITED", +} + +export enum Category { + BUSINESS = "business", + CONFERENCE = "conference", + BIRTHDAY = "birthday", + DEMONSTRATION = "demonstration", + MEETING = "meeting", +} + +export enum LoginErrorCode { + NEED_TO_LOGIN = "need_to_login", +} + +export enum LoginError { + USER_NOT_CONFIRMED = "User account not confirmed", + USER_DOES_NOT_EXIST = "No user with this email was found", + USER_EMAIL_PASSWORD_INVALID = "Impossible to authenticate, either your email or password are invalid.", + LOGIN_PROVIDER_ERROR = "Error with Login Provider", + LOGIN_PROVIDER_NOT_FOUND = "Login Provider not found", + USER_DISABLED = "This user has been disabled", +} + +export enum ResetError { + USER_IMPOSSIBLE_TO_RESET = "This user can't reset their password", +} + +export enum ParticipantRole { + NOT_APPROVED = "NOT_APPROVED", + NOT_CONFIRMED = "NOT_CONFIRMED", + REJECTED = "REJECTED", + PARTICIPANT = "PARTICIPANT", + MODERATOR = "MODERATOR", + ADMINISTRATOR = "ADMINISTRATOR", + CREATOR = "CREATOR", +} + +export enum PostVisibility { + PUBLIC = "PUBLIC", + UNLISTED = "UNLISTED", + RESTRICTED = "RESTRICTED", + PRIVATE = "PRIVATE", +} + +export enum ReportStatusEnum { + OPEN = "OPEN", + CLOSED = "CLOSED", + RESOLVED = "RESOLVED", +} + +export enum ActionLogAction { + NOTE_CREATION = "NOTE_CREATION", + NOTE_DELETION = "NOTE_DELETION", + REPORT_UPDATE_CLOSED = "REPORT_UPDATE_CLOSED", + REPORT_UPDATE_OPENED = "REPORT_UPDATE_OPENED", + REPORT_UPDATE_RESOLVED = "REPORT_UPDATE_RESOLVED", + EVENT_DELETION = "EVENT_DELETION", + COMMENT_DELETION = "COMMENT_DELETION", + ACTOR_SUSPENSION = "ACTOR_SUSPENSION", + ACTOR_UNSUSPENSION = "ACTOR_UNSUSPENSION", + USER_DELETION = "USER_DELETION", +} + +export enum SearchTabs { + EVENTS = 0, + GROUPS = 1, +} + +export enum ActorType { + PERSON = "PERSON", + APPLICATION = "APPLICATION", + GROUP = "GROUP", + ORGANISATION = "ORGANISATION", + SERVICE = "SERVICE", +} + +export enum MemberRole { + NOT_APPROVED = "NOT_APPROVED", + INVITED = "INVITED", + MEMBER = "MEMBER", + MODERATOR = "MODERATOR", + ADMINISTRATOR = "ADMINISTRATOR", + CREATOR = "CREATOR", + REJECTED = "REJECTED", +} + +export enum Openness { + INVITE_ONLY = "INVITE_ONLY", + MODERATED = "MODERATED", + OPEN = "OPEN", +} diff --git a/js/src/types/error-code.model.ts b/js/src/types/error-code.model.ts deleted file mode 100644 index 03346340d..000000000 --- a/js/src/types/error-code.model.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum ErrorCode { - UNKNOWN = "unknown", - REGISTRATION_CLOSED = "registration_closed", -} diff --git a/js/src/types/event-options.model.ts b/js/src/types/event-options.model.ts index 95e9ec405..f045d7f55 100644 --- a/js/src/types/event-options.model.ts +++ b/js/src/types/event-options.model.ts @@ -1,3 +1,5 @@ +import { CommentModeration } from "./enums"; + export interface IParticipationCondition { title: string; content: string; @@ -10,12 +12,6 @@ export interface IOffer { url: string; } -export enum CommentModeration { - ALLOW_ALL = "ALLOW_ALL", - MODERATED = "MODERATED", - CLOSED = "CLOSED", -} - export interface IEventOptions { maximumAttendeeCapacity: number; remainingAttendeeCapacity: number; diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts index 9c47d894f..f00d11501 100644 --- a/js/src/types/event.model.ts +++ b/js/src/types/event.model.ts @@ -1,44 +1,15 @@ -import { Address, IAddress } from "@/types/address.model"; -import { ITag } from "@/types/tag.model"; -import { IMedia } from "@/types/media.model"; -import { IComment } from "@/types/comment.model"; -import { Paginate } from "@/types/paginate"; -import { Actor, Group, IActor, IGroup, IPerson } from "./actor"; -import { IParticipant } from "./participant.model"; -import { EventOptions, IEventOptions } from "./event-options.model"; - -export enum EventStatus { - TENTATIVE = "TENTATIVE", - CONFIRMED = "CONFIRMED", - CANCELLED = "CANCELLED", -} - -export enum EventVisibility { - PUBLIC = "PUBLIC", - UNLISTED = "UNLISTED", - RESTRICTED = "RESTRICTED", - PRIVATE = "PRIVATE", -} - -export enum EventJoinOptions { - FREE = "FREE", - RESTRICTED = "RESTRICTED", - INVITE = "INVITE", -} - -export enum EventVisibilityJoinOptions { - PUBLIC = "PUBLIC", - LINK = "LINK", - LIMITED = "LIMITED", -} - -export enum Category { - BUSINESS = "business", - CONFERENCE = "conference", - BIRTHDAY = "birthday", - DEMONSTRATION = "demonstration", - MEETING = "meeting", -} +import { Address } from "@/types/address.model"; +import type { IAddress } from "@/types/address.model"; +import type { ITag } from "@/types/tag.model"; +import type { IMedia } from "@/types/media.model"; +import type { IComment } from "@/types/comment.model"; +import type { Paginate } from "@/types/paginate"; +import { Actor, Group } from "./actor"; +import type { IActor, IGroup, IPerson } from "./actor"; +import type { IParticipant } from "./participant.model"; +import { EventOptions } from "./event-options.model"; +import type { IEventOptions } from "./event-options.model"; +import { EventJoinOptions, EventStatus, EventVisibility } from "./enums"; export interface IEventCardOptions { hideDate: boolean; diff --git a/js/src/types/feedtoken.model.ts b/js/src/types/feedtoken.model.ts new file mode 100644 index 000000000..1d08b5e14 --- /dev/null +++ b/js/src/types/feedtoken.model.ts @@ -0,0 +1,8 @@ +import type { IPerson } from "./actor"; +import type { ICurrentUser } from "./current-user.model"; + +export interface IFeedToken { + token: string; + actor?: IPerson; + user: ICurrentUser; +} diff --git a/js/src/types/login-error-code.model.ts b/js/src/types/login-error-code.model.ts deleted file mode 100644 index e691534a7..000000000 --- a/js/src/types/login-error-code.model.ts +++ /dev/null @@ -1,16 +0,0 @@ -export enum LoginErrorCode { - NEED_TO_LOGIN = "need_to_login", -} - -export enum LoginError { - USER_NOT_CONFIRMED = "User account not confirmed", - USER_DOES_NOT_EXIST = "No user with this email was found", - USER_EMAIL_PASSWORD_INVALID = "Impossible to authenticate, either your email or password are invalid.", - LOGIN_PROVIDER_ERROR = "Error with Login Provider", - LOGIN_PROVIDER_NOT_FOUND = "Login Provider not found", - USER_DISABLED = "This user has been disabled", -} - -export enum ResetError { - USER_IMPOSSIBLE_TO_RESET = "This user can't reset their password", -} diff --git a/js/src/types/login.model.ts b/js/src/types/login.model.ts index a1798b040..b4750c6e9 100644 --- a/js/src/types/login.model.ts +++ b/js/src/types/login.model.ts @@ -1,4 +1,4 @@ -import { ICurrentUser } from "@/types/current-user.model"; +import type { ICurrentUser } from "@/types/current-user.model"; export interface IToken { accessToken: string; diff --git a/js/src/types/participant.model.ts b/js/src/types/participant.model.ts index f74c71cd4..2cb516d95 100644 --- a/js/src/types/participant.model.ts +++ b/js/src/types/participant.model.ts @@ -1,15 +1,8 @@ -import { Actor, IActor } from "./actor"; -import { EventModel, IEvent } from "./event.model"; - -export enum ParticipantRole { - NOT_APPROVED = "NOT_APPROVED", - NOT_CONFIRMED = "NOT_CONFIRMED", - REJECTED = "REJECTED", - PARTICIPANT = "PARTICIPANT", - MODERATOR = "MODERATOR", - ADMINISTRATOR = "ADMINISTRATOR", - CREATOR = "CREATOR", -} +import { Actor } from "./actor"; +import type { IActor } from "./actor"; +import { EventModel } from "./event.model"; +import type { IEvent } from "./event.model"; +import { ParticipantRole } from "./enums"; export interface IParticipant { id?: string; diff --git a/js/src/types/post.model.ts b/js/src/types/post.model.ts index 3a5537961..c73af5b56 100644 --- a/js/src/types/post.model.ts +++ b/js/src/types/post.model.ts @@ -1,13 +1,7 @@ -import { ITag } from "./tag.model"; -import { IMedia } from "./media.model"; -import { IActor } from "./actor"; - -export enum PostVisibility { - PUBLIC = "PUBLIC", - UNLISTED = "UNLISTED", - RESTRICTED = "RESTRICTED", - PRIVATE = "PRIVATE", -} +import type { ITag } from "./tag.model"; +import type { IMedia } from "./media.model"; +import type { IActor } from "./actor"; +import type { PostVisibility } from "./enums"; export interface IPost { id?: string; diff --git a/js/src/types/report.model.ts b/js/src/types/report.model.ts index 6abfdf3ac..b7a79bdd9 100644 --- a/js/src/types/report.model.ts +++ b/js/src/types/report.model.ts @@ -1,13 +1,16 @@ -import { IActor, IPerson } from "@/types/actor"; -import { IEvent } from "@/types/event.model"; -import { IComment } from "@/types/comment.model"; +import type { IActor, IPerson } from "@/types/actor"; +import type { IEvent } from "@/types/event.model"; +import type { IComment } from "@/types/comment.model"; +import { ActionLogAction, ReportStatusEnum } from "./enums"; -export enum ReportStatusEnum { - OPEN = "OPEN", - CLOSED = "CLOSED", - RESOLVED = "RESOLVED", +export interface IActionLogObject { + id: string; +} +export interface IReportNote extends IActionLogObject { + id: string; + content: string; + moderator: IActor; } - export interface IReport extends IActionLogObject { id: string; reported: IActor; @@ -21,29 +24,6 @@ export interface IReport extends IActionLogObject { status: ReportStatusEnum; } -export interface IReportNote extends IActionLogObject { - id: string; - content: string; - moderator: IActor; -} - -export interface IActionLogObject { - id: string; -} - -export enum ActionLogAction { - NOTE_CREATION = "NOTE_CREATION", - NOTE_DELETION = "NOTE_DELETION", - REPORT_UPDATE_CLOSED = "REPORT_UPDATE_CLOSED", - REPORT_UPDATE_OPENED = "REPORT_UPDATE_OPENED", - REPORT_UPDATE_RESOLVED = "REPORT_UPDATE_RESOLVED", - EVENT_DELETION = "EVENT_DELETION", - COMMENT_DELETION = "COMMENT_DELETION", - ACTOR_SUSPENSION = "ACTOR_SUSPENSION", - ACTOR_UNSUSPENSION = "ACTOR_UNSUSPENSION", - USER_DELETION = "USER_DELETION", -} - export interface IActionLog { id: string; object: IReport | IReportNote | IEvent | IComment | IActor; diff --git a/js/src/types/resource.ts b/js/src/types/resource.ts index 85024bffe..2fa2dff7a 100644 --- a/js/src/types/resource.ts +++ b/js/src/types/resource.ts @@ -1,6 +1,20 @@ -import { Paginate } from "@/types/paginate"; -import { IActor } from "@/types/actor"; +import type { Paginate } from "@/types/paginate"; +import type { IActor } from "@/types/actor"; +export interface IResourceMetadata { + title?: string; + description?: string; + imageRemoteUrl?: string; + height?: number; + width?: number; + type?: string; + authorName?: string; + authorUrl?: string; + providerName?: string; + providerUrl?: string; + html?: string; + faviconUrl?: string; +} export interface IResource { id?: string; title: string; @@ -18,22 +32,7 @@ export interface IResource { type?: string; } -export interface IResourceMetadata { - title?: string; - description?: string; - imageRemoteUrl?: string; - height?: number; - width?: number; - type?: string; - authorName?: string; - authorUrl?: string; - providerName?: string; - providerUrl?: string; - html?: string; - faviconUrl?: string; -} - -export const mapServiceTypeToIcon: object = { +export const mapServiceTypeToIcon: Record<string, string> = { pad: "file-document-outline", calc: "google-spreadsheet", visio: "webcam", diff --git a/js/src/types/search.model.ts b/js/src/types/search.model.ts index 4d4ddaf9c..e60b71c26 100644 --- a/js/src/types/search.model.ts +++ b/js/src/types/search.model.ts @@ -1,5 +1,5 @@ -import { IGroup, IPerson } from "@/types/actor"; -import { IEvent } from "@/types/event.model"; +import type { IGroup, IPerson } from "@/types/actor"; +import type { IEvent } from "@/types/event.model"; export interface SearchEvent { total: number; @@ -15,8 +15,3 @@ export interface SearchPerson { total: number; elements: IPerson[]; } - -export enum SearchTabs { - EVENTS = 0, - GROUPS = 1, -} diff --git a/js/src/types/todolist.ts b/js/src/types/todolist.ts new file mode 100644 index 000000000..fb5795818 --- /dev/null +++ b/js/src/types/todolist.ts @@ -0,0 +1,10 @@ +import type { IActor } from "./actor"; +import type { Paginate } from "./paginate"; +import type { ITodo } from "./todos"; + +export interface ITodoList { + id: string; + title: string; + todos: Paginate<ITodo>; + actor?: IActor; +} diff --git a/js/src/types/todos.ts b/js/src/types/todos.ts index 060443c56..ad3dd8a5c 100644 --- a/js/src/types/todos.ts +++ b/js/src/types/todos.ts @@ -1,12 +1,5 @@ -import { Paginate } from "@/types/paginate"; -import { IActor, IPerson } from "@/types/actor"; - -export interface ITodoList { - id: string; - title: string; - todos: Paginate<ITodo>; - actor?: IActor; -} +import type { IActor, IPerson } from "@/types/actor"; +import { ITodoList } from "./todolist"; export interface ITodo { id?: string; diff --git a/js/src/utils/.editorconfig b/js/src/utils/.editorconfig deleted file mode 100644 index b6b82f05c..000000000 --- a/js/src/utils/.editorconfig +++ /dev/null @@ -1,22 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 4 -indent_style = space -insert_final_newline = true -max_line_length = 120 -tab_width = 4 -trim_trailing_whitespace = true - -[*.ex] -indent_size = 2 -tab_width = 2 - -[*.scss] -indent_size = 2 - -[*.ts] -indent_size = 2 -tab_width = 2 diff --git a/js/src/utils/asyncForEach.ts b/js/src/utils/asyncForEach.ts index 5d6dc549e..ec4bb1cd6 100644 --- a/js/src/utils/asyncForEach.ts +++ b/js/src/utils/asyncForEach.ts @@ -1,5 +1,9 @@ -async function asyncForEach(array: Array<any>, callback: Function) { +async function asyncForEach( + array: Array<any>, + callback: (arg0: any, arg1: number, arg2: Array<any>) => any +): Promise<void> { for (let index = 0; index < array.length; index += 1) { + // eslint-disable-next-line no-await-in-loop await callback(array[index], index, array); } } diff --git a/js/src/utils/auth.ts b/js/src/utils/auth.ts index dbf56b057..abd073437 100644 --- a/js/src/utils/auth.ts +++ b/js/src/utils/auth.ts @@ -10,10 +10,10 @@ import { import { ILogin, IToken } from "@/types/login.model"; import { UPDATE_CURRENT_USER_CLIENT } from "@/graphql/user"; import ApolloClient from "apollo-client"; -import { ICurrentUserRole } from "@/types/current-user.model"; import { IPerson } from "@/types/actor"; import { IDENTITIES, UPDATE_CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import { NormalizedCacheObject } from "apollo-cache-inmemory"; +import { ICurrentUserRole } from "@/types/enums"; export function saveTokenData(obj: IToken): void { localStorage.setItem(AUTH_ACCESS_TOKEN, obj.accessToken); @@ -37,14 +37,19 @@ export function saveActorData(obj: IPerson): void { } export function deleteUserData(): void { - [AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN, AUTH_USER_ROLE].forEach((key) => { - localStorage.removeItem(key); - }); + [AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN, AUTH_USER_ROLE].forEach( + (key) => { + localStorage.removeItem(key); + } + ); } export class NoIdentitiesException extends Error {} -export async function changeIdentity(apollo: ApolloClient<NormalizedCacheObject>, identity: IPerson): Promise<void> { +export async function changeIdentity( + apollo: ApolloClient<NormalizedCacheObject>, + identity: IPerson +): Promise<void> { await apollo.mutate({ mutation: UPDATE_CURRENT_ACTOR_CLIENT, variables: identity, @@ -69,7 +74,8 @@ export async function initializeCurrentActor(apollo: ApolloClient<any>): Promise console.warn("Logged user has no identities!"); throw new NoIdentitiesException(); } - const activeIdentity = identities.find((identity: IPerson) => identity.id === actorId) || (identities[0] as IPerson); + const activeIdentity = + identities.find((identity: IPerson) => identity.id === actorId) || (identities[0] as IPerson); if (activeIdentity) { await changeIdentity(apollo, activeIdentity); diff --git a/js/src/utils/html.ts b/js/src/utils/html.ts index 65ff595dd..ee6cea891 100644 --- a/js/src/utils/html.ts +++ b/js/src/utils/html.ts @@ -1,3 +1,3 @@ -export function nl2br(text: string) { +export function nl2br(text: string): string { return text.replace(/(?:\r\n|\r|\n)/g, "<br>"); } diff --git a/js/src/utils/i18n.ts b/js/src/utils/i18n.ts index a5605ab4a..30e2b06c7 100644 --- a/js/src/utils/i18n.ts +++ b/js/src/utils/i18n.ts @@ -7,10 +7,15 @@ import langs from "../i18n/langs.json"; const DEFAULT_LOCALE = "en_US"; -let language = localStorage.getItem(USER_LOCALE) || (document.documentElement.getAttribute("lang") as string); -language = language || ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_"); +let language = + localStorage.getItem(USER_LOCALE) || (document.documentElement.getAttribute("lang") as string); +language = + language || + ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_"); export const locale = - language && Object.prototype.hasOwnProperty.call(langs, language) ? language : language.split("-")[0]; + language && Object.prototype.hasOwnProperty.call(langs, language) + ? language + : language.split("-")[0]; Vue.use(VueI18n); diff --git a/js/src/utils/image.ts b/js/src/utils/image.ts index 8a32e6a67..996f8bcf3 100644 --- a/js/src/utils/image.ts +++ b/js/src/utils/image.ts @@ -9,7 +9,11 @@ export async function buildFileFromIMedia(obj: IMedia | null | undefined): Promi return new File([blob], obj.name); } -export function buildFileVariable(file: File | null, name: string, alt?: string): Record<string, unknown> { +export function buildFileVariable( + file: File | null, + name: string, + alt?: string +): Record<string, unknown> { if (!file) return {}; return { diff --git a/js/src/utils/object.ts b/js/src/utils/object.ts deleted file mode 100644 index 0946c7186..000000000 --- a/js/src/utils/object.ts +++ /dev/null @@ -1,5 +0,0 @@ -export function buildObjectCollection<T, U>(collection: T[] | undefined, builder: new (p: T) => U) { - if (!collection || Array.isArray(collection) === false) return []; - - return collection.map((v) => new builder(v)); -} diff --git a/js/src/utils/username.ts b/js/src/utils/username.ts index c565f7890..91fa7dae4 100644 --- a/js/src/utils/username.ts +++ b/js/src/utils/username.ts @@ -1,15 +1,5 @@ import { IActor } from "@/types/actor"; -function autoUpdateUsername(actor: IActor, newDisplayName: string | null): IActor { - const oldUsername = convertToUsername(actor.name); - - if (actor.preferredUsername === oldUsername) { - actor.preferredUsername = convertToUsername(newDisplayName); - } - - return actor; -} - function convertToUsername(value: string | null): string { if (!value) return ""; @@ -22,6 +12,17 @@ function convertToUsername(value: string | null): string { .replace(/[^a-z0-9_]/g, ""); } +function autoUpdateUsername(actor: IActor, newDisplayName: string | null): IActor { + const actor2 = { ...actor }; + const oldUsername = convertToUsername(actor.name); + + if (actor.preferredUsername === oldUsername) { + actor2.preferredUsername = convertToUsername(newDisplayName); + } + + return actor2; +} + function validateUsername(actor: IActor): boolean { return actor.preferredUsername === convertToUsername(actor.preferredUsername); } diff --git a/js/src/utils/validators.ts b/js/src/utils/validators.ts index a137d8d20..9270f0b61 100644 --- a/js/src/utils/validators.ts +++ b/js/src/utils/validators.ts @@ -1,7 +1,7 @@ -export function validateEmailField(value: string) { +export function validateEmailField(value: string): boolean | string { return value.includes("@") || "Invalid e-mail."; } -export function validateRequiredField(value: any) { +export function validateRequiredField(value: unknown): boolean | string { return !!value || "Required."; } diff --git a/js/src/views/About/Privacy.vue b/js/src/views/About/Privacy.vue index 4d9da6174..80a36581d 100644 --- a/js/src/views/About/Privacy.vue +++ b/js/src/views/About/Privacy.vue @@ -9,7 +9,7 @@ import { Component, Vue, Watch } from "vue-property-decorator"; import { PRIVACY } from "@/graphql/config"; import { IConfig } from "@/types/config.model"; -import { InstancePrivacyType } from "@/types/admin.model"; +import { InstancePrivacyType } from "@/types/enums"; @Component({ apollo: { @@ -31,19 +31,18 @@ export default class Privacy extends Vue { locale: string | null = null; - created() { + created(): void { this.locale = this.$i18n.locale; } @Watch("config", { deep: true }) - watchConfig(config: IConfig) { + watchConfig(config: IConfig): void { if (config.privacy.type) { - console.log(this.config.privacy); this.redirectToUrl(); } } - redirectToUrl() { + redirectToUrl(): void { if (this.config.privacy.type === InstancePrivacyType.URL) { window.location.replace(this.config.privacy.url); } diff --git a/js/src/views/About/Rules.vue b/js/src/views/About/Rules.vue index b2b5651e1..2dd0059f3 100644 --- a/js/src/views/About/Rules.vue +++ b/js/src/views/About/Rules.vue @@ -7,10 +7,9 @@ </template> <script lang="ts"> -import { Component, Vue, Watch } from "vue-property-decorator"; +import { Component, Vue } from "vue-property-decorator"; import { RULES } from "@/graphql/config"; import { IConfig } from "@/types/config.model"; -import { InstanceTermsType } from "@/types/admin.model"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/About/Terms.vue b/js/src/views/About/Terms.vue index 5e55d78c1..7d60e8f7e 100644 --- a/js/src/views/About/Terms.vue +++ b/js/src/views/About/Terms.vue @@ -9,7 +9,7 @@ import { Component, Vue, Watch } from "vue-property-decorator"; import { TERMS } from "@/graphql/config"; import { IConfig } from "@/types/config.model"; -import { InstanceTermsType } from "@/types/admin.model"; +import { InstanceTermsType } from "@/types/enums"; @Component({ apollo: { @@ -31,19 +31,18 @@ export default class Terms extends Vue { locale: string | null = null; - created() { + created(): void { this.locale = this.$i18n.locale; } @Watch("config", { deep: true }) - watchConfig(config: IConfig) { + watchConfig(config: IConfig): void { if (config.terms.type) { - console.log(this.config.terms); this.redirectToUrl(); } } - redirectToUrl() { + redirectToUrl(): void { if (this.config.terms.type === InstanceTermsType.URL) { window.location.replace(this.config.terms.url); } diff --git a/js/src/views/Admin/AdminGroupProfile.vue b/js/src/views/Admin/AdminGroupProfile.vue index 6b7cb9279..85407e5f1 100644 --- a/js/src/views/Admin/AdminGroupProfile.vue +++ b/js/src/views/Admin/AdminGroupProfile.vue @@ -199,8 +199,9 @@ import { Component, Vue, Prop } from "vue-property-decorator"; import { GET_GROUP, REFRESH_PROFILE } from "@/graphql/group"; import { formatBytes } from "@/utils/datetime"; +import { MemberRole } from "@/types/enums"; import { SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor"; -import { IGroup, MemberRole } from "../../types/actor"; +import { IGroup } from "../../types/actor"; import { usernameWithDomain, IActor } from "../../types/actor/actor.model"; import RouteName from "../../router/name"; import ActorCard from "../../components/Account/ActorCard.vue"; diff --git a/js/src/views/Admin/AdminUserProfile.vue b/js/src/views/Admin/AdminUserProfile.vue index fa0c43084..5a6ad751f 100644 --- a/js/src/views/Admin/AdminUserProfile.vue +++ b/js/src/views/Admin/AdminUserProfile.vue @@ -64,10 +64,11 @@ import { Component, Vue, Prop } from "vue-property-decorator"; import { Route } from "vue-router"; import { formatBytes } from "@/utils/datetime"; +import { ICurrentUserRole } from "@/types/enums"; import { GET_USER, SUSPEND_USER } from "../../graphql/user"; import { usernameWithDomain } from "../../types/actor/actor.model"; import RouteName from "../../router/name"; -import { IUser, ICurrentUserRole } from "../../types/current-user.model"; +import { IUser } from "../../types/current-user.model"; import { IPerson } from "../../types/actor"; @Component({ diff --git a/js/src/views/Admin/GroupProfiles.vue b/js/src/views/Admin/GroupProfiles.vue index 5a99ae7a9..ae0f9dc46 100644 --- a/js/src/views/Admin/GroupProfiles.vue +++ b/js/src/views/Admin/GroupProfiles.vue @@ -83,7 +83,6 @@ <script lang="ts"> import { Component, Vue, Watch } from "vue-property-decorator"; import { LIST_GROUPS } from "@/graphql/group"; -import { LIST_PROFILES } from "../../graphql/actor"; import RouteName from "../../router/name"; const PROFILES_PER_PAGE = 10; @@ -124,7 +123,7 @@ export default class GroupProfiles extends Vue { RouteName = RouteName; - async onPageChange(page: number) { + async onPageChange(page: number): Promise<void> { this.page = page; await this.$apollo.queries.groups.fetchMore({ variables: { @@ -150,13 +149,19 @@ export default class GroupProfiles extends Vue { }); } - onFiltersChange({ preferredUsername, domain }: { preferredUsername: string; domain: string }) { + onFiltersChange({ + preferredUsername, + domain, + }: { + preferredUsername: string; + domain: string; + }): void { this.preferredUsername = preferredUsername; this.domain = domain; } @Watch("domain") - domainNotLocal() { + domainNotLocal(): void { this.local = this.domain === ""; } } diff --git a/js/src/views/Admin/Profiles.vue b/js/src/views/Admin/Profiles.vue index eb96a0536..8ca74cc71 100644 --- a/js/src/views/Admin/Profiles.vue +++ b/js/src/views/Admin/Profiles.vue @@ -123,7 +123,7 @@ export default class Profiles extends Vue { RouteName = RouteName; - async onPageChange(page: number) { + async onPageChange(page: number): Promise<void> { this.page = page; await this.$apollo.queries.persons.fetchMore({ variables: { @@ -149,13 +149,19 @@ export default class Profiles extends Vue { }); } - onFiltersChange({ preferredUsername, domain }: { preferredUsername: string; domain: string }) { + onFiltersChange({ + preferredUsername, + domain, + }: { + preferredUsername: string; + domain: string; + }): void { this.preferredUsername = preferredUsername; this.domain = domain; } @Watch("domain") - domainNotLocal() { + domainNotLocal(): void { this.local = this.domain === ""; } } diff --git a/js/src/views/Admin/Settings.vue b/js/src/views/Admin/Settings.vue index 417645690..a38b75474 100644 --- a/js/src/views/Admin/Settings.vue +++ b/js/src/views/Admin/Settings.vue @@ -290,12 +290,8 @@ <script lang="ts"> import { Component, Vue, Watch } from "vue-property-decorator"; import { ADMIN_SETTINGS, SAVE_ADMIN_SETTINGS, LANGUAGES } from "@/graphql/admin"; -import { - IAdminSettings, - InstanceTermsType, - InstancePrivacyType, - ILanguage, -} from "../../types/admin.model"; +import { InstancePrivacyType, InstanceTermsType } from "@/types/enums"; +import { IAdminSettings, ILanguage } from "../../types/admin.model"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/Admin/Users.vue b/js/src/views/Admin/Users.vue index b554328bb..b9f7a225f 100644 --- a/js/src/views/Admin/Users.vue +++ b/js/src/views/Admin/Users.vue @@ -123,7 +123,7 @@ export default class Users extends Vue { RouteName = RouteName; - async onPageChange(page: number) { + async onPageChange(page: number): Promise<void> { this.page = page; await this.$apollo.queries.users.fetchMore({ variables: { diff --git a/js/src/views/Discussions/Discussion.vue b/js/src/views/Discussions/Discussion.vue index 4faaba3f1..fa50209d2 100644 --- a/js/src/views/Discussions/Discussion.vue +++ b/js/src/views/Discussions/Discussion.vue @@ -222,23 +222,24 @@ export default class discussion extends mixins(GroupMixin) { }, }); if (!discussionData) return; - const { discussion } = discussionData; - discussion.lastComment = replyToDiscussion.lastComment; - discussion.comments.elements.push(replyToDiscussion.lastComment); - discussion.comments.total += 1; + const { discussion: discussionCached } = discussionData; + discussionCached.lastComment = replyToDiscussion.lastComment; + discussionCached.comments.elements.push(replyToDiscussion.lastComment); + discussionCached.comments.total += 1; store.writeQuery({ query: GET_DISCUSSION, variables: { slug: this.slug, page: this.page }, - data: { discussion }, + data: { discussion: discussionCached }, }); }, - // We don't need to handle cache update since there's the subscription that handles this for us + // We don't need to handle cache update since + // there's the subscription that handles this for us }); this.newComment = ""; } async updateComment(comment: IComment): Promise<void> { - const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({ + await this.$apollo.mutate<{ deleteComment: IComment }>({ mutation: UPDATE_COMMENT, variables: { commentId: comment.id, @@ -256,25 +257,25 @@ export default class discussion extends mixins(GroupMixin) { }, }); if (!discussionData) return; - const { discussion } = discussionData; - const index = discussion.comments.elements.findIndex( + const { discussion: discussionCached } = discussionData; + const index = discussionCached.comments.elements.findIndex( ({ id }) => id === data.deleteComment.id ); if (index > -1) { - discussion.comments.elements.splice(index, 1); - discussion.comments.total -= 1; + discussionCached.comments.elements.splice(index, 1); + discussionCached.comments.total -= 1; } store.writeQuery({ query: GET_DISCUSSION, variables: { slug: this.slug, page: this.page }, - data: { discussion }, + data: { discussion: discussionCached }, }); }, }); } async deleteComment(comment: IComment): Promise<void> { - const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({ + await this.$apollo.mutate<{ deleteComment: IComment }>({ mutation: DELETE_COMMENT, variables: { commentId: comment.id, @@ -291,21 +292,21 @@ export default class discussion extends mixins(GroupMixin) { }, }); if (!discussionData) return; - const { discussion } = discussionData; - const index = discussion.comments.elements.findIndex( + const { discussion: discussionCached } = discussionData; + const index = discussionCached.comments.elements.findIndex( ({ id }) => id === data.deleteComment.id ); if (index > -1) { - const updatedComment = discussion.comments.elements[index]; + const updatedComment = discussionCached.comments.elements[index]; updatedComment.deletedAt = new Date(); updatedComment.actor = null; updatedComment.text = ""; - discussion.comments.elements.splice(index, 1, updatedComment); + discussionCached.comments.elements.splice(index, 1, updatedComment); } store.writeQuery({ query: GET_DISCUSSION, variables: { slug: this.slug, page: this.page }, - data: { discussion }, + data: { discussion: discussionCached }, }); }, }); @@ -327,13 +328,13 @@ export default class discussion extends mixins(GroupMixin) { if (!fetchMoreResult) return previousResult; const newComments = fetchMoreResult.discussion.comments.elements; this.hasMoreComments = newComments.length === 1; - const { discussion } = previousResult; - discussion.comments.elements = [ + const { discussion: discussionCached } = previousResult; + discussionCached.comments.elements = [ ...previousResult.discussion.comments.elements, ...newComments, ]; - return { discussion }; + return { discussion: discussionCached }; }, }); } catch (e) { @@ -359,12 +360,12 @@ export default class discussion extends mixins(GroupMixin) { }, }); if (!discussionData) return; - const { discussion } = discussionData; - discussion.title = updateDiscussion.title; + const { discussion: discussionCached } = discussionData; + discussionCached.title = updateDiscussion.title; store.writeQuery({ query: GET_DISCUSSION, variables: { slug: this.slug, page: this.page }, - data: { discussion }, + data: { discussion: discussionCached }, }); }, }); diff --git a/js/src/views/Error.vue b/js/src/views/Error.vue index e1e758843..e68e246e7 100644 --- a/js/src/views/Error.vue +++ b/js/src/views/Error.vue @@ -11,8 +11,8 @@ </template> <script lang="ts"> +import { ErrorCode } from "@/types/enums"; import { Component, Vue } from "vue-property-decorator"; -import { ErrorCode } from "@/types/error-code.model"; @Component export default class ErrorPage extends Vue { @@ -20,7 +20,7 @@ export default class ErrorPage extends Vue { ErrorCode = ErrorCode; - mounted() { + mounted(): void { this.code = this.$route.query.code as ErrorCode; } } diff --git a/js/src/views/Event/Edit.vue b/js/src/views/Event/Edit.vue index e14f7dcf5..bd87b7fff 100644 --- a/js/src/views/Event/Edit.vue +++ b/js/src/views/Event/Edit.vue @@ -353,8 +353,13 @@ import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue"; import Subtitle from "@/components/Utils/Subtitle.vue"; import { Route } from "vue-router"; import { formatList } from "@/utils/i18n"; -import { CommentModeration } from "../../types/event-options.model"; -import { ParticipantRole } from "../../types/participant.model"; +import { + CommentModeration, + EventJoinOptions, + EventStatus, + EventVisibility, + ParticipantRole, +} from "@/types/enums"; import OrganizerPickerWrapper from "../../components/Event/OrganizerPickerWrapper.vue"; import { CREATE_EVENT, @@ -362,13 +367,7 @@ import { EVENT_PERSON_PARTICIPATION, FETCH_EVENT, } from "../../graphql/event"; -import { - EventJoinOptions, - EventModel, - EventStatus, - EventVisibility, - IEvent, -} from "../../types/event.model"; +import { EventModel, IEvent } from "../../types/event.model"; import { CURRENT_ACTOR_CLIENT, LOGGED_USER_DRAFTS, @@ -837,9 +836,9 @@ export default class EditEvent extends Vue { /** * Confirm cancel */ - confirmGoElsewhere(callback: (value?: string) => any): void | Function { + confirmGoElsewhere(callback: (value?: string) => any): void { if (!this.isEventModified) { - return callback(); + callback(); } const title: string = this.isUpdate ? (this.$t("Cancel edition") as string) @@ -872,7 +871,8 @@ export default class EditEvent extends Vue { this.confirmGoElsewhere(() => this.$router.go(-1)); } - beforeRouteLeave(to: Route, from: Route, next: Function): void { + // eslint-disable-next-line consistent-return + beforeRouteLeave(to: Route, from: Route, next: () => void): void { if (to.name === RouteName.EVENT) return next(); this.confirmGoElsewhere(() => next()); } diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue index 8e7f63592..21adf746b 100644 --- a/js/src/views/Event/Event.vue +++ b/js/src/views/Event/Event.vue @@ -504,6 +504,7 @@ <script lang="ts"> import { Component, Prop, Watch } from "vue-property-decorator"; import BIcon from "buefy/src/components/icon/Icon.vue"; +import { EventJoinOptions, EventStatus, EventVisibility, ParticipantRole } from "@/types/enums"; import { EVENT_PERSON_PARTICIPATION, EVENT_PERSON_PARTICIPATION_SUBSCRIPTION_CHANGED, @@ -511,13 +512,7 @@ import { JOIN_EVENT, } from "../../graphql/event"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; -import { - EventModel, - EventStatus, - EventVisibility, - IEvent, - EventJoinOptions, -} from "../../types/event.model"; +import { EventModel, IEvent } from "../../types/event.model"; import { IActor, IPerson, Person, usernameWithDomain } from "../../types/actor"; import { GRAPHQL_API_ENDPOINT } from "../../api/_entrypoint"; import DateCalendarIcon from "../../components/Event/DateCalendarIcon.vue"; @@ -546,7 +541,7 @@ import Tag from "../../components/Tag.vue"; import EventMetadataBlock from "../../components/Event/EventMetadataBlock.vue"; import ActorCard from "../../components/Account/ActorCard.vue"; import PopoverActorCard from "../../components/Account/PopoverActorCard.vue"; -import { IParticipant, ParticipantRole } from "../../types/participant.model"; +import { IParticipant } from "../../types/participant.model"; @Component({ components: { diff --git a/js/src/views/Event/GroupEvents.vue b/js/src/views/Event/GroupEvents.vue index a839b6252..07b1b6e73 100644 --- a/js/src/views/Event/GroupEvents.vue +++ b/js/src/views/Event/GroupEvents.vue @@ -74,7 +74,8 @@ import Subtitle from "@/components/Utils/Subtitle.vue"; import EventListViewCard from "@/components/Event/EventListViewCard.vue"; import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor"; import GroupMixin from "@/mixins/group"; -import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor"; +import { IMember } from "@/types/actor/member.model"; +import { IGroup, IPerson, usernameWithDomain } from "../../types/actor"; @Component({ apollo: { diff --git a/js/src/views/Event/MyEvents.vue b/js/src/views/Event/MyEvents.vue index 99caf50bb..2640e5de1 100644 --- a/js/src/views/Event/MyEvents.vue +++ b/js/src/views/Event/MyEvents.vue @@ -88,7 +88,8 @@ <script lang="ts"> import { Component, Vue } from "vue-property-decorator"; -import { IParticipant, Participant, ParticipantRole } from "../../types/participant.model"; +import { ParticipantRole } from "@/types/enums"; +import { IParticipant, Participant } from "../../types/participant.model"; import { LOGGED_USER_PARTICIPATIONS, LOGGED_USER_DRAFTS } from "../../graphql/actor"; import { EventModel, IEvent } from "../../types/event.model"; import EventListCard from "../../components/Event/EventListCard.vue"; diff --git a/js/src/views/Event/Participants.vue b/js/src/views/Event/Participants.vue index 2bd7dcddf..7f604538d 100644 --- a/js/src/views/Event/Participants.vue +++ b/js/src/views/Event/Participants.vue @@ -185,7 +185,8 @@ <script lang="ts"> import { Component, Prop, Vue, Watch, Ref } from "vue-property-decorator"; -import { IParticipant, ParticipantRole } from "../../types/participant.model"; +import { ParticipantRole } from "@/types/enums"; +import { IParticipant } from "../../types/participant.model"; import { IEvent, IEventParticipantStats } from "../../types/event.model"; import { PARTICIPANTS, UPDATE_PARTICIPANT } from "../../graphql/event"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; diff --git a/js/src/views/Group/Create.vue b/js/src/views/Group/Create.vue index 4acdacdac..1401ee85e 100644 --- a/js/src/views/Group/Create.vue +++ b/js/src/views/Group/Create.vue @@ -67,14 +67,15 @@ <script lang="ts"> import { Component, Watch } from "vue-property-decorator"; -import { Group, IPerson, usernameWithDomain, MemberRole } from "@/types/actor"; +import { Group, IPerson, usernameWithDomain } from "@/types/actor"; import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { CREATE_GROUP } from "@/graphql/group"; -import PictureUpload from "@/components/PictureUpload.vue"; import { mixins } from "vue-class-component"; import IdentityEditionMixin from "@/mixins/identityEdition"; +import { MemberRole } from "@/types/enums"; import RouteName from "../../router/name"; import { convertToUsername } from "../../utils/username"; +import PictureUpload from "../../components/PictureUpload.vue"; @Component({ components: { diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue index ddf687f55..858ef5827 100644 --- a/js/src/views/Group/Group.vue +++ b/js/src/views/Group/Group.vue @@ -362,7 +362,7 @@ <script lang="ts"> import { Component, Prop, Watch } from "vue-property-decorator"; import EventCard from "@/components/Event/EventCard.vue"; -import { IActor, usernameWithDomain, MemberRole, IMember, Openness } from "@/types/actor"; +import { IActor, usernameWithDomain } from "@/types/actor"; import Subtitle from "@/components/Utils/Subtitle.vue"; import CompactTodo from "@/components/Todo/CompactTodo.vue"; import EventMinimalistCard from "@/components/Event/EventMinimalistCard.vue"; @@ -380,6 +380,8 @@ import { IConfig } from "@/types/config.model"; import GroupMixin from "@/mixins/group"; import { mixins } from "vue-class-component"; import { JOIN_GROUP } from "@/graphql/member"; +import { MemberRole, Openness } from "@/types/enums"; +import { IMember } from "@/types/actor/member.model"; import RouteName from "../../router/name"; import GroupSection from "../../components/Group/GroupSection.vue"; import ReportModal from "../../components/Report/ReportModal.vue"; diff --git a/js/src/views/Group/GroupMembers.vue b/js/src/views/Group/GroupMembers.vue index 72e6e19ac..ec1974313 100644 --- a/js/src/views/Group/GroupMembers.vue +++ b/js/src/views/Group/GroupMembers.vue @@ -184,10 +184,11 @@ import { Component, Watch } from "vue-property-decorator"; import GroupMixin from "@/mixins/group"; import { mixins } from "vue-class-component"; import { FETCH_GROUP } from "@/graphql/group"; +import { MemberRole } from "@/types/enums"; +import { IMember } from "@/types/actor/member.model"; import RouteName from "../../router/name"; import { INVITE_MEMBER, GROUP_MEMBERS, REMOVE_MEMBER, UPDATE_MEMBER } from "../../graphql/member"; import { usernameWithDomain } from "../../types/actor"; -import { IMember, MemberRole } from "../../types/actor/group.model"; @Component({ apollo: { diff --git a/js/src/views/Group/GroupSettings.vue b/js/src/views/Group/GroupSettings.vue index 2e82c0e43..837001bcf 100644 --- a/js/src/views/Group/GroupSettings.vue +++ b/js/src/views/Group/GroupSettings.vue @@ -152,9 +152,10 @@ import { Route } from "vue-router"; import PictureUpload from "@/components/PictureUpload.vue"; import { mixins } from "vue-class-component"; import GroupMixin from "@/mixins/group"; +import { Openness } from "@/types/enums"; import RouteName from "../../router/name"; import { UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group"; -import { IGroup, usernameWithDomain, Openness } from "../../types/actor"; +import { IGroup, usernameWithDomain } from "../../types/actor"; import { Address, IAddress } from "../../types/address.model"; @Component({ diff --git a/js/src/views/Group/MyGroups.vue b/js/src/views/Group/MyGroups.vue index e8051adaf..1cdf67b97 100644 --- a/js/src/views/Group/MyGroups.vue +++ b/js/src/views/Group/MyGroups.vue @@ -51,8 +51,10 @@ import { LEAVE_GROUP } from "@/graphql/group"; import GroupMemberCard from "@/components/Group/GroupMemberCard.vue"; import Invitations from "@/components/Group/Invitations.vue"; import { Paginate } from "@/types/paginate"; -import { IGroup, IMember, MemberRole, usernameWithDomain } from "@/types/actor"; +import { IGroup, usernameWithDomain } from "@/types/actor"; import { Route } from "vue-router"; +import { IMember } from "@/types/actor/member.model"; +import { MemberRole } from "@/types/enums"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/Home.vue b/js/src/views/Home.vue index dd1a84e23..d27d09587 100644 --- a/js/src/views/Home.vue +++ b/js/src/views/Home.vue @@ -126,8 +126,7 @@ </span> <div> <EventListCard - v-for="participation in row[1]" - v-if="isInLessThanSevenDays(row[0])" + v-for="participation in thisWeek(row)" @event-deleted="eventDeleted" :key="participation[1].id" :participation="participation[1]" @@ -173,7 +172,8 @@ <script lang="ts"> import { Component, Vue, Watch } from "vue-property-decorator"; -import { IParticipant, Participant, ParticipantRole } from "../types/participant.model"; +import { ParticipantRole } from "@/types/enums"; +import { IParticipant, Participant } from "../types/participant.model"; import { FETCH_EVENTS } from "../graphql/event"; import EventListCard from "../components/Event/EventListCard.vue"; import EventCard from "../components/Event/EventCard.vue"; @@ -286,6 +286,13 @@ export default class Home extends Vue { return window.localStorage.getItem("new-registered-user") === "yes"; } + thisWeek(row: [string, Map<string, IParticipant>]): Map<string, IParticipant> { + if (this.isInLessThanSevenDays(row[0])) { + return row[1]; + } + return new Map(); + } + // eslint-disable-next-line class-methods-use-this mounted(): void { if (window.localStorage.getItem("welcome-back")) { diff --git a/js/src/views/Location.vue b/js/src/views/Location.vue deleted file mode 100644 index 608d5eb89..000000000 --- a/js/src/views/Location.vue +++ /dev/null @@ -1,32 +0,0 @@ -<template> - <div>{{ center.lat }} - {{ center.lng }}</div> -</template> - -<script lang="ts"> -import { Component, Prop, Vue } from "vue-property-decorator"; - -@Component -export default class Location extends Vue { - @Prop(String) address!: string; - - description = "Paris, France"; - - center = { lat: 48.85, lng: 2.35 }; - - markers: any[] = []; - - setPlace(place: any) { - this.center = { - lat: place.geometry.location.lat(), - lng: place.geometry.location.lng(), - }; - this.markers = [ - { - position: { lat: this.center.lat, lng: this.center.lng }, - }, - ]; - - this.$emit("input", place.formatted_address); - } -} -</script> diff --git a/js/src/views/Moderation/Logs.vue b/js/src/views/Moderation/Logs.vue index c5369f9ec..b0cc89c6f 100644 --- a/js/src/views/Moderation/Logs.vue +++ b/js/src/views/Moderation/Logs.vue @@ -158,9 +158,10 @@ </template> <script lang="ts"> import { Component, Vue } from "vue-property-decorator"; -import { IActionLog, ActionLogAction } from "@/types/report.model"; +import { IActionLog } from "@/types/report.model"; import { LOGS } from "@/graphql/report"; import ReportCard from "@/components/Report/ReportCard.vue"; +import { ActionLogAction } from "@/types/enums"; import RouteName from "../../router/name"; import { displayNameAndUsername } from "../../types/actor"; diff --git a/js/src/views/Moderation/Report.vue b/js/src/views/Moderation/Report.vue index c2dacf34e..2534bb6a7 100644 --- a/js/src/views/Moderation/Report.vue +++ b/js/src/views/Moderation/Report.vue @@ -241,14 +241,15 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; import { CREATE_REPORT_NOTE, REPORT, UPDATE_REPORT } from "@/graphql/report"; -import { IReport, IReportNote, ReportStatusEnum } from "@/types/report.model"; +import { IReport, IReportNote } from "@/types/report.model"; import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; -import { IPerson, ActorType, displayNameAndUsername } from "@/types/actor"; +import { IPerson, displayNameAndUsername } from "@/types/actor"; import { DELETE_EVENT } from "@/graphql/event"; import { uniq } from "lodash"; import { nl2br } from "@/utils/html"; import { DELETE_COMMENT } from "@/graphql/comment"; import { IComment } from "@/types/comment.model"; +import { ActorType, ReportStatusEnum } from "@/types/enums"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/Moderation/ReportList.vue b/js/src/views/Moderation/ReportList.vue index c8ea560a5..4a134d518 100644 --- a/js/src/views/Moderation/ReportList.vue +++ b/js/src/views/Moderation/ReportList.vue @@ -45,9 +45,10 @@ </template> <script lang="ts"> import { Component, Vue, Watch } from "vue-property-decorator"; -import { IReport, ReportStatusEnum } from "@/types/report.model"; +import { IReport } from "@/types/report.model"; import { REPORTS } from "@/graphql/report"; import ReportCard from "@/components/Report/ReportCard.vue"; +import { ReportStatusEnum } from "@/types/enums"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/PageNotFound.vue b/js/src/views/PageNotFound.vue index dcbde73e6..d2cb39aea 100644 --- a/js/src/views/PageNotFound.vue +++ b/js/src/views/PageNotFound.vue @@ -46,8 +46,8 @@ export default class PageNotFound extends Vue { return this.$t("Search events, groups, etc.") as string; } - enter() { - this.$router.push({ + async enter(): Promise<void> { + await this.$router.push({ name: RouteName.SEARCH, query: { term: this.searchText }, }); diff --git a/js/src/views/Posts/Edit.vue b/js/src/views/Posts/Edit.vue index 9af397afc..fe30780ba 100644 --- a/js/src/views/Posts/Edit.vue +++ b/js/src/views/Posts/Edit.vue @@ -105,11 +105,12 @@ import { mixins } from "vue-class-component"; import { FETCH_GROUP } from "@/graphql/group"; import { buildFileFromIMedia, readFileAsync } from "@/utils/image"; import GroupMixin from "@/mixins/group"; +import { PostVisibility } from "@/types/enums"; import { TAGS } from "../../graphql/tags"; import { CONFIG } from "../../graphql/config"; import { FETCH_POST, CREATE_POST, UPDATE_POST, DELETE_POST } from "../../graphql/post"; -import { IPost, PostVisibility } from "../../types/post.model"; +import { IPost } from "../../types/post.model"; import Editor from "../../components/Editor.vue"; import { IActor, IGroup, usernameWithDomain } from "../../types/actor"; import TagInput from "../../components/Event/TagInput.vue"; diff --git a/js/src/views/Posts/List.vue b/js/src/views/Posts/List.vue index f8c89bd4f..5ddb22c22 100644 --- a/js/src/views/Posts/List.vue +++ b/js/src/views/Posts/List.vue @@ -82,10 +82,11 @@ import { Component, Prop } from "vue-property-decorator"; import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "@/graphql/actor"; import { mixins } from "vue-class-component"; import GroupMixin from "@/mixins/group"; +import { IMember } from "@/types/actor/member.model"; import { FETCH_GROUP_POSTS } from "../../graphql/post"; import { Paginate } from "../../types/paginate"; import { IPost } from "../../types/post.model"; -import { IGroup, IMember, IPerson, usernameWithDomain } from "../../types/actor"; +import { IGroup, IPerson, usernameWithDomain } from "../../types/actor"; import RouteName from "../../router/name"; import PostElementItem from "../../components/Post/PostElementItem.vue"; diff --git a/js/src/views/Posts/Post.vue b/js/src/views/Posts/Post.vue index 197f2b375..77d9f6b05 100644 --- a/js/src/views/Posts/Post.vue +++ b/js/src/views/Posts/Post.vue @@ -47,13 +47,14 @@ <script lang="ts"> import { Component, Prop } from "vue-property-decorator"; import { mixins } from "vue-class-component"; -import Editor from "@/components/Editor.vue"; import GroupMixin from "@/mixins/group"; +import { PostVisibility } from "@/types/enums"; +import { IMember } from "@/types/actor/member.model"; import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "../../graphql/actor"; import { FETCH_POST } from "../../graphql/post"; -import { IPost, PostVisibility } from "../../types/post.model"; -import { IMember, IPerson, usernameWithDomain } from "../../types/actor"; +import { IPost } from "../../types/post.model"; +import { IPerson, usernameWithDomain } from "../../types/actor"; import RouteName from "../../router/name"; import Tag from "../../components/Tag.vue"; diff --git a/js/src/views/Resources/ResourceFolder.vue b/js/src/views/Resources/ResourceFolder.vue index 3c3b3972d..7e7188cec 100644 --- a/js/src/views/Resources/ResourceFolder.vue +++ b/js/src/views/Resources/ResourceFolder.vue @@ -21,9 +21,8 @@ > </li> <li - v-if="resource.path !== '/'" :class="{ 'is-active': index + 1 === ResourceMixin.resourcePathArray(resource).length }" - v-for="(pathFragment, index) in ResourceMixin.resourcePathArray(resource)" + v-for="(pathFragment, index) in filteredPath" :key="pathFragment" > <router-link @@ -145,8 +144,8 @@ <resource-selector :initialResource="updatedResource" :username="usernameWithDomain(resource.actor)" - @updateResource="moveResource" - @closeMoveModal="moveModal = false" + @update-resource="moveResource" + @close-move-modal="moveModal = false" /> </section> </div> @@ -303,6 +302,13 @@ export default class Resources extends Mixins(ResourceMixin) { return path[0] !== "/" ? `/${path}` : path; } + get filteredPath(): string[] { + if (this.resource && this.resource.path !== "/") { + return ResourceMixin.resourcePathArray(this.resource); + } + return []; + } + async createResource(): Promise<void> { if (!this.resource.actor) return; try { diff --git a/js/src/views/Search.vue b/js/src/views/Search.vue index b175ff0d2..54ec306af 100644 --- a/js/src/views/Search.vue +++ b/js/src/views/Search.vue @@ -152,6 +152,7 @@ import { startOfMonth, eachWeekendOfInterval, } from "date-fns"; +import { SearchTabs } from "@/types/enums"; import EventCard from "../components/Event/EventCard.vue"; import { FETCH_EVENTS } from "../graphql/event"; import { IEvent } from "../types/event.model"; @@ -160,7 +161,6 @@ import { IAddress, Address } from "../types/address.model"; import AddressAutoComplete from "../components/Event/AddressAutoComplete.vue"; import { SEARCH_EVENTS, SEARCH_GROUPS } from "../graphql/search"; import { Paginate } from "../types/paginate"; -import { SearchTabs } from "../types/search.model"; import { IGroup } from "../types/actor"; import GroupCard from "../components/Group/GroupCard.vue"; import { CONFIG } from "../graphql/config"; diff --git a/js/src/views/Settings.vue b/js/src/views/Settings.vue index 50222d26b..6d51de272 100644 --- a/js/src/views/Settings.vue +++ b/js/src/views/Settings.vue @@ -10,14 +10,13 @@ </div> </template> <script lang="ts"> -import { Component, Vue, Watch } from "vue-property-decorator"; -import { Route } from "vue-router"; +import { Component, Vue } from "vue-property-decorator"; import SettingsMenu from "../components/Settings/SettingsMenu.vue"; import RouteName from "../router/name"; import { IPerson, Person } from "../types/actor"; import { IDENTITIES } from "../graphql/actor"; import { CURRENT_USER_CLIENT } from "../graphql/user"; -import { ICurrentUser, ICurrentUserRole } from "../types/current-user.model"; +import { ICurrentUser } from "../types/current-user.model"; @Component({ components: { SettingsMenu }, diff --git a/js/src/views/Settings/AccountSettings.vue b/js/src/views/Settings/AccountSettings.vue index d9e195013..1402e4f97 100644 --- a/js/src/views/Settings/AccountSettings.vue +++ b/js/src/views/Settings/AccountSettings.vue @@ -176,11 +176,12 @@ </template> <script lang="ts"> +import { IAuthProvider } from "@/types/enums"; import { Component, Vue, Ref } from "vue-property-decorator"; import { Route } from "vue-router"; import { CHANGE_EMAIL, CHANGE_PASSWORD, DELETE_ACCOUNT, LOGGED_USER } from "../../graphql/user"; import RouteName from "../../router/name"; -import { IUser, IAuthProvider } from "../../types/current-user.model"; +import { IUser } from "../../types/current-user.model"; import { logout, SELECTED_PROVIDERS } from "../../utils/auth"; @Component({ @@ -299,7 +300,7 @@ export default class AccountSettings extends Vue { get hasUserGotAPassword(): boolean { return ( this.loggedUser && - (this.loggedUser.provider == null || this.loggedUser.provider == IAuthProvider.LDAP) + (this.loggedUser.provider == null || this.loggedUser.provider === IAuthProvider.LDAP) ); } diff --git a/js/src/views/Settings/Notifications.vue b/js/src/views/Settings/Notifications.vue index 718569056..82e76d9bd 100644 --- a/js/src/views/Settings/Notifications.vue +++ b/js/src/views/Settings/Notifications.vue @@ -102,8 +102,9 @@ </template> <script lang="ts"> import { Component, Vue, Watch } from "vue-property-decorator"; +import { INotificationPendingEnum } from "@/types/enums"; import { USER_SETTINGS, SET_USER_SETTINGS } from "../../graphql/user"; -import { IUser, INotificationPendingEnum } from "../../types/current-user.model"; +import { IUser } from "../../types/current-user.model"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/Todos/TodoList.vue b/js/src/views/Todos/TodoList.vue index c32938198..c8bdc1228 100644 --- a/js/src/views/Todos/TodoList.vue +++ b/js/src/views/Todos/TodoList.vue @@ -42,11 +42,12 @@ </template> <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { ITodo, ITodoList } from "@/types/todos"; +import { ITodo } from "@/types/todos"; import { CREATE_TODO, FETCH_TODO_LIST } from "@/graphql/todos"; import CompactTodo from "@/components/Todo/CompactTodo.vue"; import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import { IActor } from "@/types/actor"; +import { ITodoList } from "@/types/todolist"; import RouteName from "../../router/name"; @Component({ @@ -77,7 +78,7 @@ export default class TodoList extends Vue { RouteName = RouteName; - async createNewTodo() { + async createNewTodo(): Promise<void> { await this.$apollo.mutate({ mutation: CREATE_TODO, variables: { diff --git a/js/src/views/Todos/TodoLists.vue b/js/src/views/Todos/TodoLists.vue index 537bffdee..8886b455b 100644 --- a/js/src/views/Todos/TodoLists.vue +++ b/js/src/views/Todos/TodoLists.vue @@ -54,9 +54,9 @@ import { Component, Prop, Vue } from "vue-property-decorator"; import { FETCH_GROUP } from "@/graphql/group"; import { IGroup, usernameWithDomain } from "@/types/actor"; -import { ITodoList } from "@/types/todos"; import { CREATE_TODO_LIST } from "@/graphql/todos"; import CompactTodo from "@/components/Todo/CompactTodo.vue"; +import { ITodoList } from "@/types/todolist"; import RouteName from "../../router/name"; @Component({ diff --git a/js/src/views/User/Login.vue b/js/src/views/User/Login.vue index ce4370831..0531acacd 100644 --- a/js/src/views/User/Login.vue +++ b/js/src/views/User/Login.vue @@ -98,14 +98,14 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; import { Route } from "vue-router"; +import { ICurrentUser } from "@/types/current-user.model"; +import { LoginError, LoginErrorCode } from "@/types/enums"; import { LOGIN } from "../../graphql/auth"; import { validateEmailField, validateRequiredField } from "../../utils/validators"; import { initializeCurrentActor, NoIdentitiesException, saveUserData } from "../../utils/auth"; import { ILogin } from "../../types/login.model"; import { CURRENT_USER_CLIENT, UPDATE_CURRENT_USER_CLIENT } from "../../graphql/user"; import RouteName from "../../router/name"; -import { LoginErrorCode, LoginError } from "../../types/login-error-code.model"; -import { ICurrentUser } from "../../types/current-user.model"; import { CONFIG } from "../../graphql/config"; import { IConfig } from "../../types/config.model"; import AuthProviders from "../../components/User/AuthProviders.vue"; diff --git a/js/src/views/User/PasswordReset.vue b/js/src/views/User/PasswordReset.vue index b9a407c87..e36cfe9a6 100644 --- a/js/src/views/User/PasswordReset.vue +++ b/js/src/views/User/PasswordReset.vue @@ -52,21 +52,21 @@ export default class PasswordReset extends Vue { errors: string[] = []; rules = { - passwordLength: (value: string) => + passwordLength: (value: string): boolean | string => value.length > 6 || "Password must be at least 6 characters long", required: validateRequiredField, - passwordEqual: (value: string) => + passwordEqual: (value: string): boolean | string => value === this.credentials.password || "Passwords must be the same", }; - get samePasswords() { + get samePasswords(): boolean { return ( this.rules.passwordLength(this.credentials.password) === true && this.credentials.password === this.credentials.passwordConfirmation ); } - async resetAction(e: Event) { + async resetAction(e: Event): Promise<void> { e.preventDefault(); this.errors.splice(0); diff --git a/js/src/views/User/ProviderValidation.vue b/js/src/views/User/ProviderValidation.vue index f62dd62c4..83cbf605a 100644 --- a/js/src/views/User/ProviderValidation.vue +++ b/js/src/views/User/ProviderValidation.vue @@ -1,59 +1,58 @@ -<template></template> <script lang="ts"> -import { Component, Prop, Vue } from "vue-property-decorator"; -import { VALIDATE_USER, UPDATE_CURRENT_USER_CLIENT, LOGGED_USER } from "../../graphql/user"; +import { Component, Vue } from "vue-property-decorator"; +import { ICurrentUserRole } from "@/types/enums"; +import { UPDATE_CURRENT_USER_CLIENT, LOGGED_USER } from "../../graphql/user"; import RouteName from "../../router/name"; import { saveUserData, changeIdentity } from "../../utils/auth"; -import { ILogin } from "../../types/login.model"; -import { ICurrentUserRole, ICurrentUser, IUser } from "../../types/current-user.model"; -import { IDENTITIES } from "../../graphql/actor"; +import { IUser } from "../../types/current-user.model"; @Component export default class ProviderValidate extends Vue { - async mounted() { + async mounted(): Promise<void> { const accessToken = this.getValueFromMeta("auth-access-token"); const refreshToken = this.getValueFromMeta("auth-refresh-token"); const userId = this.getValueFromMeta("auth-user-id"); const userEmail = this.getValueFromMeta("auth-user-email"); const userRole = this.getValueFromMeta("auth-user-role") as ICurrentUserRole; - const userActorId = this.getValueFromMeta("auth-user-actor-id"); if (!(userId && userEmail && userRole && accessToken && refreshToken)) { - return this.$router.push("/"); - } - const login = { - user: { id: userId, email: userEmail, role: userRole, isLoggedIn: true }, - accessToken, - refreshToken, - }; - saveUserData(login); - await this.$apollo.mutate({ - mutation: UPDATE_CURRENT_USER_CLIENT, - variables: { - id: userId, - email: userEmail, - isLoggedIn: true, - role: ICurrentUserRole.USER, - }, - }); - const { data } = await this.$apollo.query<{ loggedUser: IUser }>({ - query: LOGGED_USER, - }); - const { loggedUser } = data; - - if (loggedUser.defaultActor) { - await changeIdentity(this.$apollo.provider.defaultClient, loggedUser.defaultActor); - await this.$router.push({ name: RouteName.HOME }); + await this.$router.push("/"); } else { - // If the user didn't register any profile yet, let's create one for them - await this.$router.push({ - name: RouteName.REGISTER_PROFILE, - params: { email: loggedUser.email, userAlreadyActivated: "true" }, + const login = { + user: { id: userId, email: userEmail, role: userRole, isLoggedIn: true }, + accessToken, + refreshToken, + }; + saveUserData(login); + await this.$apollo.mutate({ + mutation: UPDATE_CURRENT_USER_CLIENT, + variables: { + id: userId, + email: userEmail, + isLoggedIn: true, + role: ICurrentUserRole.USER, + }, }); + const { data } = await this.$apollo.query<{ loggedUser: IUser }>({ + query: LOGGED_USER, + }); + const { loggedUser } = data; + + if (loggedUser.defaultActor) { + await changeIdentity(this.$apollo.provider.defaultClient, loggedUser.defaultActor); + await this.$router.push({ name: RouteName.HOME }); + } else { + // If the user didn't register any profile yet, let's create one for them + await this.$router.push({ + name: RouteName.REGISTER_PROFILE, + params: { email: loggedUser.email, userAlreadyActivated: "true" }, + }); + } } } - getValueFromMeta(name: string) { + // eslint-disable-next-line class-methods-use-this + getValueFromMeta(name: string): string | null { const element = document.querySelector(`meta[name="${name}"]`); if (element && element.getAttribute("content")) { return element.getAttribute("content"); diff --git a/js/src/views/User/Register.vue b/js/src/views/User/Register.vue index 63da0155d..9b112b692 100644 --- a/js/src/views/User/Register.vue +++ b/js/src/views/User/Register.vue @@ -143,7 +143,6 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; -import { Route } from "vue-router"; import { CREATE_USER } from "../../graphql/user"; import RouteName from "../../router/name"; import { IConfig } from "../../types/config.model"; diff --git a/js/src/views/User/ResendConfirmation.vue b/js/src/views/User/ResendConfirmation.vue index 24b5dd54b..292f72331 100644 --- a/js/src/views/User/ResendConfirmation.vue +++ b/js/src/views/User/ResendConfirmation.vue @@ -68,11 +68,11 @@ export default class ResendConfirmation extends Vue { email: validateEmailField, }; - mounted() { + mounted(): void { this.credentials.email = this.email; } - async resendConfirmationAction(e: Event) { + async resendConfirmationAction(e: Event): Promise<void> { e.preventDefault(); this.error = false; diff --git a/js/src/views/User/Validate.vue b/js/src/views/User/Validate.vue index f6df0fe0f..0eb980fd1 100644 --- a/js/src/views/User/Validate.vue +++ b/js/src/views/User/Validate.vue @@ -16,11 +16,11 @@ <script lang="ts"> import { Component, Prop, Vue } from "vue-property-decorator"; +import { ICurrentUserRole } from "@/types/enums"; import { VALIDATE_USER, UPDATE_CURRENT_USER_CLIENT } from "../../graphql/user"; import RouteName from "../../router/name"; import { saveUserData, saveTokenData, changeIdentity } from "../../utils/auth"; import { ILogin } from "../../types/login.model"; -import { ICurrentUserRole } from "../../types/current-user.model"; @Component export default class Validate extends Vue { @@ -30,11 +30,11 @@ export default class Validate extends Vue { failed = false; - async created() { + async created(): Promise<void> { await this.validateAction(); } - async validateAction() { + async validateAction(): Promise<void> { try { const { data } = await this.$apollo.mutate<{ validateUser: ILogin }>({ mutation: VALIDATE_USER,