Fix eslint warnings

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2020-11-27 19:27:44 +01:00
parent 487ac56b4c
commit da42522073
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
130 changed files with 702 additions and 734 deletions

View file

@ -48,6 +48,8 @@ module.exports = {
"import/prefer-default-export": "off", "import/prefer-default-export": "off",
"import/extensions": "off", "import/extensions": "off",
"import/no-unresolved": "off", "import/no-unresolved": "off",
"no-shadow": "off",
"@typescript-eslint/no-shadow": ["error"],
}, },
ignorePatterns: ["src/typings/*.d.ts", "vue.config.js"], ignorePatterns: ["src/typings/*.d.ts", "vue.config.js"],

18
js/src/@types/dom.d.ts vendored Normal file
View file

@ -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 {};

View file

@ -1,8 +1,11 @@
import { ICurrentUserRole } from "@/types/enums";
import { ApolloCache } from "apollo-cache"; import { ApolloCache } from "apollo-cache";
import { NormalizedCacheObject } from "apollo-cache-inmemory"; 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({ cache.writeData({
data: { data: {
currentUser: { currentUser: {

View file

@ -53,7 +53,7 @@ export default class Identities extends Vue {
errors: string[] = []; errors: string[] = [];
isCurrentIdentity(identity: IPerson) { isCurrentIdentity(identity: IPerson): boolean {
return identity.preferredUsername === this.currentIdentityName; return identity.preferredUsername === this.currentIdentityName;
} }
} }

View file

@ -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>

View file

@ -12,8 +12,9 @@
</v-popover> </v-popover>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ActorType } from "@/types/enums";
import { Component, Vue, Prop } from "vue-property-decorator"; import { Component, Vue, Prop } from "vue-property-decorator";
import { IActor, ActorType } from "../../types/actor"; import { IActor } from "../../types/actor";
import ActorCard from "./ActorCard.vue"; import ActorCard from "./ActorCard.vue";
@Component({ @Component({

View file

@ -103,7 +103,6 @@ import { SnackbarProgrammatic as Snackbar } from "buefy";
import { formatDistanceToNow } from "date-fns"; import { formatDistanceToNow } from "date-fns";
import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin"; import { ADD_RELAY, REMOVE_RELAY } from "../../graphql/admin";
import { IFollower } from "../../types/actor/follower.model"; import { IFollower } from "../../types/actor/follower.model";
import { Paginate } from "../../types/paginate";
import RelayMixin from "../../mixins/relay"; import RelayMixin from "../../mixins/relay";
@Component({ @Component({

View file

@ -137,7 +137,7 @@ import { Component, Prop, Vue, Ref } from "vue-property-decorator";
import EditorComponent from "@/components/Editor.vue"; import EditorComponent from "@/components/Editor.vue";
import { SnackbarProgrammatic as Snackbar } from "buefy"; import { SnackbarProgrammatic as Snackbar } from "buefy";
import { formatDistanceToNow } from "date-fns"; 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 { CommentModel, IComment } from "../../types/comment.model";
import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
import { IPerson, usernameWithDomain } from "../../types/actor"; import { IPerson, usernameWithDomain } from "../../types/actor";

View file

@ -51,7 +51,7 @@
import { Prop, Vue, Component, Watch } from "vue-property-decorator"; import { Prop, Vue, Component, Watch } from "vue-property-decorator";
import Comment from "@/components/Comment/Comment.vue"; import Comment from "@/components/Comment/Comment.vue";
import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.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 { CommentModel, IComment } from "../../types/comment.model";
import { import {
CREATE_COMMENT_FROM_EVENT, CREATE_COMMENT_FROM_EVENT,

View file

@ -395,15 +395,7 @@ export default class EditorComponent extends Vue {
new Image(), new Image(),
new MaxSize({ maxSize: this.maxSize }), new MaxSize({ maxSize: this.maxSize }),
], ],
onUpdate: ({ onUpdate: ({ getHTML }: { getHTML: Function }) => {
getHTML,
transaction,
getJSON,
}: {
getHTML: Function;
getJSON: Function;
transaction: unknown;
}) => {
this.$emit("input", getHTML()); this.$emit("input", getHTML());
}, },
}); });

View file

@ -1,11 +1,14 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import { Extension, Plugin } from "tiptap"; import { Extension, Plugin } from "tiptap";
export default class MaxSize extends Extension { export default class MaxSize extends Extension {
// eslint-disable-next-line class-methods-use-this
get name() { get name() {
return "maxSize"; return "maxSize";
} }
// eslint-disable-next-line class-methods-use-this
get defaultOptions() { get defaultOptions() {
return { return {
maxSize: null, maxSize: null,
@ -21,7 +24,7 @@ export default class MaxSize extends Extension {
const newLength = newState.doc.content.size; const newLength = newState.doc.content.size;
if (newLength > max && newLength > oldLength) { if (newLength > max && newLength > oldLength) {
let newTr = newState.tr; const newTr = newState.tr;
newTr.insertText("", max + 1, newLength); newTr.insertText("", max + 1, newLength);
return newTr; return newTr;

View file

@ -50,7 +50,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import { LatLng } from "leaflet"; import { LatLng } from "leaflet";
import { debounce } from "lodash"; import { debounce, DebouncedFunc } from "lodash";
import { Address, IAddress } from "../../types/address.model"; import { Address, IAddress } from "../../types/address.model";
import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address"; import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address";
import { CONFIG } from "../../graphql/config"; import { CONFIG } from "../../graphql/config";
@ -81,7 +81,7 @@ export default class AddressAutoComplete extends Vue {
private gettingLocation = false; private gettingLocation = false;
private location!: Position; private location!: GeolocationPosition;
private gettingLocationError: any; private gettingLocationError: any;
@ -89,7 +89,7 @@ export default class AddressAutoComplete extends Vue {
config!: IConfig; config!: IConfig;
fetchAsyncData!: Function; fetchAsyncData!: DebouncedFunc<(query: string) => Promise<void>>;
// We put this in data because of issues like // We put this in data because of issues like
// https://github.com/vuejs/vue-class-component/issues/263 // https://github.com/vuejs/vue-class-component/issues/263
@ -207,7 +207,7 @@ export default class AddressAutoComplete extends Vue {
this.gettingLocation = false; this.gettingLocation = false;
} }
static async getLocation(): Promise<Position> { static async getLocation(): Promise<GeolocationPosition> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!("geolocation" in navigator)) { if (!("geolocation" in navigator)) {
reject(new Error("Geolocation is not available.")); reject(new Error("Geolocation is not available."));

View file

@ -77,7 +77,7 @@ import { IEvent, IEventCardOptions } from "@/types/event.model";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { Actor, Person } from "@/types/actor"; import { Actor, Person } from "@/types/actor";
import { ParticipantRole } from "../../types/participant.model"; import { ParticipantRole } from "@/types/enums";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component({ @Component({

View file

@ -187,8 +187,9 @@ import { Component, Prop } from "vue-property-decorator";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
import { RawLocation, Route } from "vue-router"; import { RawLocation, Route } from "vue-router";
import { IParticipant, ParticipantRole } from "../../types/participant.model"; import { EventVisibility, ParticipantRole } from "@/types/enums";
import { EventVisibility, IEventCardOptions } from "../../types/event.model"; import { IParticipant } from "../../types/participant.model";
import { IEventCardOptions } from "../../types/event.model";
import { IPerson } from "../../types/actor"; import { IPerson } from "../../types/actor";
import ActorMixin from "../../mixins/actor"; import ActorMixin from "../../mixins/actor";
import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";

View file

@ -51,7 +51,7 @@
</template> </template>
<script lang="ts"> <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 { Component, Prop } from "vue-property-decorator";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { IPerson, usernameWithDomain } from "@/types/actor"; import { IPerson, usernameWithDomain } from "@/types/actor";
@ -59,7 +59,7 @@ import { mixins } from "vue-class-component";
import ActorMixin from "@/mixins/actor"; import ActorMixin from "@/mixins/actor";
import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import { CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import EventMixin from "@/mixins/event"; import EventMixin from "@/mixins/event";
import { ParticipantRole } from "../../types/participant.model"; import { EventVisibility, ParticipantRole } from "@/types/enums";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
const defaultOptions: IEventCardOptions = { const defaultOptions: IEventCardOptions = {

View file

@ -56,7 +56,7 @@
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import { IEvent } from "@/types/event.model"; import { IEvent } from "@/types/event.model";
import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue"; import DateCalendarIcon from "@/components/Event/DateCalendarIcon.vue";
import { ParticipantRole } from "../../types/participant.model"; import { ParticipantRole } from "@/types/enums";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component({ @Component({

View file

@ -102,7 +102,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; import { Component, Prop, Vue, Watch } from "vue-property-decorator";
import { LatLng } from "leaflet"; import { LatLng } from "leaflet";
import { debounce } from "lodash"; import { debounce, DebouncedFunc } from "lodash";
import { Address, IAddress } from "../../types/address.model"; import { Address, IAddress } from "../../types/address.model";
import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address"; import { ADDRESS, REVERSE_GEOCODE } from "../../graphql/address";
import { CONFIG } from "../../graphql/config"; import { CONFIG } from "../../graphql/config";
@ -133,7 +133,7 @@ export default class FullAddressAutoComplete extends Vue {
private gettingLocation = false; private gettingLocation = false;
private location!: Position; private location!: GeolocationPosition;
private gettingLocationError: any; private gettingLocationError: any;
@ -141,11 +141,11 @@ export default class FullAddressAutoComplete extends Vue {
config!: IConfig; config!: IConfig;
fetchAsyncData!: Function; fetchAsyncData!: DebouncedFunc<(query: string) => Promise<void>>;
// We put this in data because of issues like // We put this in data because of issues like
// https://github.com/vuejs/vue-class-component/issues/263 // https://github.com/vuejs/vue-class-component/issues/263
data() { data(): Record<string, unknown> {
return { return {
fetchAsyncData: debounce(this.asyncData, 200), fetchAsyncData: debounce(this.asyncData, 200),
}; };
@ -266,7 +266,7 @@ export default class FullAddressAutoComplete extends Vue {
return window.isSecureContext; return window.isSecureContext;
} }
static async getLocation(): Promise<Position> { static async getLocation(): Promise<GeolocationPosition> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!("geolocation" in navigator)) { if (!("geolocation" in navigator)) {
reject(new Error("Geolocation is not available.")); reject(new Error("Geolocation is not available."));

View file

@ -23,9 +23,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; 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 { PERSON_MEMBERSHIPS } from "@/graphql/actor";
import { Paginate } from "@/types/paginate"; import { Paginate } from "@/types/paginate";
import { IMember } from "@/types/actor/member.model";
import { MemberRole } from "@/types/enums";
@Component({ @Component({
apollo: { apollo: {

View file

@ -115,7 +115,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; 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 OrganizerPicker from "./OrganizerPicker.vue";
import { PERSON_MEMBERSHIPS_WITH_MEMBERS } from "../../graphql/actor"; import { PERSON_MEMBERSHIPS_WITH_MEMBERS } from "../../graphql/actor";
import { Paginate } from "../../types/paginate"; import { Paginate } from "../../types/paginate";
@ -182,7 +183,7 @@ export default class OrganizerPickerWrapper extends Vue {
({ parent: { id } }) => id === this.currentActor.id ({ parent: { id } }) => id === this.currentActor.id
); );
if (currentMembership) { if (currentMembership) {
return currentMembership.parent.members.elements.map(({ actor }) => actor); return currentMembership.parent.members.elements.map(({ actor }: { actor: IActor }) => actor);
} }
return []; return [];
} }

View file

@ -142,8 +142,9 @@ A button to set your participation
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import { IParticipant, ParticipantRole } from "../../types/participant.model"; import { EventJoinOptions, ParticipantRole } from "@/types/enums";
import { EventJoinOptions, IEvent } from "../../types/event.model"; import { IParticipant } from "../../types/participant.model";
import { IEvent } from "../../types/event.model";
import { IPerson, Person } from "../../types/actor"; import { IPerson, Person } from "../../types/actor";
import { CURRENT_ACTOR_CLIENT, IDENTITIES } from "../../graphql/actor"; import { CURRENT_ACTOR_CLIENT, IDENTITIES } from "../../graphql/actor";
import { CURRENT_USER_CLIENT } from "../../graphql/user"; import { CURRENT_USER_CLIENT } from "../../graphql/user";

View file

@ -76,7 +76,9 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Ref } from "vue-property-decorator"; 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 // @ts-ignore
import DiasporaLogo from "../../assets/diaspora-icon.svg?inline"; import DiasporaLogo from "../../assets/diaspora-icon.svg?inline";
@ -124,7 +126,7 @@ export default class ShareEventModal extends Vue {
)}&url=${encodeURIComponent(this.event.url)}`; )}&url=${encodeURIComponent(this.event.url)}`;
} }
copyURL() { copyURL(): void {
this.eventURLInput.$refs.input.select(); this.eventURLInput.$refs.input.select();
document.execCommand("copy"); document.execCommand("copy");
this.showCopiedTooltip = true; this.showCopiedTooltip = true;

View file

@ -40,7 +40,6 @@ import { ITag } from "../../types/tag.model";
if (typeof tag !== "string") { if (typeof tag !== "string") {
return tag; return tag;
} }
// @ts-ignore
return { title: tag, slug: tag } as ITag; return { title: tag, slug: tag } as ITag;
}); });
this.$emit("input", tagEntities); this.$emit("input", tagEntities);
@ -57,14 +56,10 @@ export default class TagInput extends Vue {
filteredTags: ITag[] = []; filteredTags: ITag[] = [];
getFilteredTags(text: string) { getFilteredTags(text: string): void {
this.filteredTags = differenceBy(this.data, this.value, "id").filter( this.filteredTags = differenceBy(this.data, this.value, "id").filter(
(option) => get(option, this.path).toString().toLowerCase().indexOf(text.toLowerCase()) >= 0 (option) => get(option, this.path).toString().toLowerCase().indexOf(text.toLowerCase()) >= 0
); );
} }
static isTag(x: any): x is ITag {
return x.slug !== undefined;
}
} }
</script> </script>

View file

@ -54,7 +54,9 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; 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"; import RouteName from "../../router/name";
@Component @Component

View file

@ -36,9 +36,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; 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 { PERSON_MEMBERSHIPS } from "@/graphql/actor";
import { Paginate } from "@/types/paginate"; import { Paginate } from "@/types/paginate";
import { IMember } from "@/types/actor/member.model";
import { MemberRole } from "@/types/enums";
@Component({ @Component({
apollo: { apollo: {

View file

@ -61,7 +61,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue, Watch } from "vue-property-decorator"; 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 GroupPicker from "./GroupPicker.vue";
import { PERSON_MEMBERSHIPS } from "../../graphql/actor"; import { PERSON_MEMBERSHIPS } from "../../graphql/actor";
import { Paginate } from "../../types/paginate"; import { Paginate } from "../../types/paginate";

View file

@ -54,7 +54,8 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; 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"; import RouteName from "../../router/name";
@Component @Component

View file

@ -11,10 +11,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ACCEPT_INVITATION, REJECT_INVITATION } from "@/graphql/member"; import { ACCEPT_INVITATION, REJECT_INVITATION } from "@/graphql/member";
import { IMember } from "@/types/actor";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import InvitationCard from "@/components/Group/InvitationCard.vue"; import InvitationCard from "@/components/Group/InvitationCard.vue";
import { LOGGED_USER_MEMBERSHIPS } from "@/graphql/actor"; import { LOGGED_USER_MEMBERSHIPS } from "@/graphql/actor";
import { IMember } from "@/types/actor/member.model";
@Component({ @Component({
components: { components: {

View file

@ -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 }) 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 }) @Prop({ type: Function, required: false })
updateDraggableMarkerCallback!: Function; updateDraggableMarkerCallback!: (latlng: LatLng, zoom: number) => void;
defaultOptions: { defaultOptions: {
zoom: number; zoom: number;
@ -86,45 +86,47 @@ export default class Map extends Vue {
} }
/* eslint-enable */ /* eslint-enable */
openPopup(event: LeafletEvent) { openPopup(event: LeafletEvent): void {
this.$nextTick(() => { this.$nextTick(() => {
event.target.openPopup(); event.target.openPopup();
}); });
} }
get mergedOptions(): object { get mergedOptions(): Record<string, unknown> {
return { ...this.defaultOptions, ...this.options }; return { ...this.defaultOptions, ...this.options };
} }
get lat() { get lat(): number {
return this.$props.coords.split(";")[1]; return this.$props.coords.split(";")[1];
} }
get lon() { get lon(): number {
return this.$props.coords.split(";")[0]; return this.$props.coords.split(";")[0];
} }
get popupMultiLine() { get popupMultiLine(): Array<string> {
if (Array.isArray(this.marker.text)) { if (Array.isArray(this.marker.text)) {
return this.marker.text; return this.marker.text;
} }
return [this.marker.text]; return [this.marker.text];
} }
clickMap(event: LeafletMouseEvent) { clickMap(event: LeafletMouseEvent): void {
this.updateDraggableMarkerPosition(event.latlng); this.updateDraggableMarkerPosition(event.latlng);
} }
updateDraggableMarkerPosition(e: LatLng) { updateDraggableMarkerPosition(e: LatLng): void {
this.updateDraggableMarkerCallback(e, this.zoom); this.updateDraggableMarkerCallback(e, this.zoom);
} }
updateZoom(zoom: number) { updateZoom(zoom: number): void {
this.zoom = zoom; this.zoom = zoom;
} }
get attribution() { get attribution(): string {
return this.config.maps.tiles.attribution || this.$t("© The OpenStreetMap Contributors"); return (
this.config.maps.tiles.attribution || (this.$t("© The OpenStreetMap Contributors") as string)
);
} }
} }
</script> </script>

View file

@ -17,13 +17,13 @@ import { Component, Prop, Vue } from "vue-property-decorator";
@Component({ @Component({
beforeDestroy() { beforeDestroy() {
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
this.parentContainer.removeLayer(this); this.parentContainer.removeLayer(this);
}, },
}) })
export default class Vue2LeafletLocateControl extends Vue { 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; @Prop({ type: Boolean, default: true }) visible = true;
@ -33,7 +33,7 @@ export default class Vue2LeafletLocateControl extends Vue {
parentContainer: any; parentContainer: any;
mounted() { mounted(): void {
this.mapObject = L.control.locate(this.options); this.mapObject = L.control.locate(this.options);
DomEvent.on(this.mapObject, this.$listeners as any); DomEvent.on(this.mapObject, this.$listeners as any);
propsBinder(this, this.mapObject, this.$props); propsBinder(this, this.mapObject, this.$props);
@ -42,7 +42,7 @@ export default class Vue2LeafletLocateControl extends Vue {
this.mapObject.addTo(this.parentContainer.mapObject, !this.visible); this.mapObject.addTo(this.parentContainer.mapObject, !this.visible);
} }
public locate() { public locate(): void {
this.mapObject.start(); this.mapObject.start();
} }
} }

View file

@ -109,13 +109,14 @@ import { Component, Vue, Watch } from "vue-property-decorator";
import Logo from "@/components/Logo.vue"; import Logo from "@/components/Logo.vue";
import { GraphQLError } from "graphql"; import { GraphQLError } from "graphql";
import { loadLanguageAsync } from "@/utils/i18n"; import { loadLanguageAsync } from "@/utils/i18n";
import { ICurrentUserRole } from "@/types/enums";
import { CURRENT_USER_CLIENT, USER_SETTINGS } from "../graphql/user"; import { CURRENT_USER_CLIENT, USER_SETTINGS } from "../graphql/user";
import { changeIdentity, logout } from "../utils/auth"; import { changeIdentity, logout } from "../utils/auth";
import { CURRENT_ACTOR_CLIENT, IDENTITIES, UPDATE_DEFAULT_ACTOR } from "../graphql/actor"; import { CURRENT_ACTOR_CLIENT, IDENTITIES, UPDATE_DEFAULT_ACTOR } from "../graphql/actor";
import { IPerson, Person } from "../types/actor"; import { IPerson, Person } from "../types/actor";
import { CONFIG } from "../graphql/config"; import { CONFIG } from "../graphql/config";
import { IConfig } from "../types/config.model"; 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 SearchField from "./SearchField.vue";
import RouteName from "../router/name"; import RouteName from "../router/name";

View file

@ -38,9 +38,9 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import { confirmLocalAnonymousParticipation } from "@/services/AnonymousParticipationStorage"; import { confirmLocalAnonymousParticipation } from "@/services/AnonymousParticipationStorage";
import { EventJoinOptions } from "@/types/enums";
import { IParticipant } from "../../types/participant.model"; import { IParticipant } from "../../types/participant.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import { EventJoinOptions } from "../../types/event.model";
import { CONFIRM_PARTICIPATION } from "../../graphql/event"; import { CONFIRM_PARTICIPATION } from "../../graphql/event";
@Component @Component

View file

@ -74,12 +74,13 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; 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 { FETCH_EVENT, JOIN_EVENT } from "@/graphql/event";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
import { CONFIG } from "@/graphql/config"; import { CONFIG } from "@/graphql/config";
import { addLocalUnconfirmedAnonymousParticipation } from "@/services/AnonymousParticipationStorage"; 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({ @Component({
apollo: { apollo: {

View file

@ -43,9 +43,10 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { usernameWithDomain } from "@/types/actor"; import { usernameWithDomain } from "@/types/actor";
import { PostVisibility } from "@/types/enums";
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import { IPost, PostVisibility } from "../../types/post.model"; import { IPost } from "../../types/post.model";
@Component @Component
export default class PostElementItem extends Vue { export default class PostElementItem extends Vue {

View file

@ -36,7 +36,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import { IReport } from "@/types/report.model"; import { IReport } from "@/types/report.model";
import { ActorType } from "@/types/actor"; import { ActorType } from "@/types/enums";
@Component @Component
export default class ReportCard extends Vue { export default class ReportCard extends Vue {

View file

@ -82,7 +82,7 @@ import { IComment } from "../../types/comment.model";
}, },
}) })
export default class ReportModal extends Vue { 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; @Prop({ type: String }) title!: string;

View file

@ -17,7 +17,7 @@
</b-dropdown> </b-dropdown>
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"; import { Component, Vue } from "vue-property-decorator";
@Component @Component
export default class ResourceDropdown extends Vue {} export default class ResourceDropdown extends Vue {}

View file

@ -47,7 +47,7 @@
<b-button type="is-primary" @click="updateResource" :disabled="moveDisabled">{{ <b-button type="is-primary" @click="updateResource" :disabled="moveDisabled">{{
$t("Move resource to {folder}", { folder: resource.title }) $t("Move resource to {folder}", { folder: resource.title })
}}</b-button> }}</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> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -81,15 +81,15 @@ export default class ResourceSelector extends Vue {
resource: IResource | undefined = this.initialResource.parent; resource: IResource | undefined = this.initialResource.parent;
goDown(element: IResource) { goDown(element: IResource): void {
if (element.type === "folder" && element.id !== this.initialResource.id) { if (element.type === "folder" && element.id !== this.initialResource.id) {
this.resource = element; this.resource = element;
} }
} }
updateResource() { updateResource(): void {
this.$emit( this.$emit(
"updateResource", "update-resource",
{ {
id: this.initialResource.id, id: this.initialResource.id,
title: this.initialResource.title, title: this.initialResource.title,
@ -100,12 +100,12 @@ export default class ResourceSelector extends Vue {
); );
} }
get moveDisabled() { get moveDisabled(): boolean | undefined {
return ( return (
(this.initialResource.parent && (this.initialResource.parent &&
this.resource && this.resource &&
this.initialResource.parent.path === this.resource.path) || 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 === "/")
); );
} }
} }

View file

@ -23,9 +23,9 @@ export default class SearchField extends Vue {
search = ""; search = "";
enter() { async enter(): Promise<void> {
this.$emit("navbar-search"); this.$emit("navbar-search");
this.$router.push({ await this.$router.push({
name: RouteName.SEARCH, name: RouteName.SEARCH,
query: { term: this.search }, query: { term: this.search },
}); });

View file

@ -16,7 +16,7 @@ export default class SettingMenuItem extends Vue {
@Prop({ required: true, type: Object }) to!: Route; @Prop({ required: true, type: Object }) to!: Route;
get isActive() { get isActive(): boolean {
if (!this.to) return false; if (!this.to) return false;
if (this.to.name === this.$route.name) { if (this.to.name === this.$route.name) {
if (this.to.params) { if (this.to.params) {

View file

@ -20,11 +20,12 @@ export default class SettingMenuSection extends Vue {
@Prop({ required: true, type: Object }) to!: Route; @Prop({ required: true, type: Object }) to!: Route;
get sectionActive() { get sectionActive(): boolean {
if (this.$slots.default) { if (this.$slots.default) {
return this.$slots.default.some( return this.$slots.default.some(
({ ({
componentOptions: { componentOptions: {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
propsData: { to }, propsData: { to },
}, },

View file

@ -55,13 +55,14 @@
</aside> </aside>
</template> </template>
<script lang="ts"> <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 SettingMenuSection from "./SettingMenuSection.vue";
import SettingMenuItem from "./SettingMenuItem.vue"; import SettingMenuItem from "./SettingMenuItem.vue";
import { IDENTITIES } from "../../graphql/actor"; import { IDENTITIES } from "../../graphql/actor";
import { IPerson, Person } from "../../types/actor"; import { IPerson, Person } from "../../types/actor";
import { CURRENT_USER_CLIENT } from "../../graphql/user"; 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"; import RouteName from "../../router/name";

View file

@ -18,7 +18,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import { debounce } from "lodash"; import { debounce, DebouncedFunc } from "lodash";
import { SnackbarProgrammatic as Snackbar } from "buefy"; import { SnackbarProgrammatic as Snackbar } from "buefy";
import { ITodo } from "../../types/todos"; import { ITodo } from "../../types/todos";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@ -36,7 +36,7 @@ export default class Todo extends Vue {
editMode = false; editMode = false;
debounceUpdateTodo!: Function; debounceUpdateTodo!: DebouncedFunc<(obj: Record<string, unknown>) => Promise<void>>;
// We put this in data because of issues like // We put this in data because of issues like
// https://github.com/vuejs/vue-class-component/issues/263 // https://github.com/vuejs/vue-class-component/issues/263

View file

@ -54,7 +54,7 @@
import { Component, Prop, Vue } from "vue-property-decorator"; import { Component, Prop, Vue } from "vue-property-decorator";
import VerticalDivider from "@/components/Utils/VerticalDivider.vue"; import VerticalDivider from "@/components/Utils/VerticalDivider.vue";
import Subtitle from "@/components/Utils/Subtitle.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"; import RouteName from "../../router/name";
@Component({ @Component({

View file

@ -4,9 +4,9 @@ import { Component, Vue } from "vue-property-decorator";
@Component @Component
export default class ActorMixin extends Vue { 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 actor", actor.id);
console.log("actorIsOrganizer event", event); console.log("actorIsOrganizer event", event);
return event.organizerActor && actor.id === event.organizerActor.id; return event.organizerActor !== undefined && actor.id === event.organizerActor.id;
} }
} }

View file

@ -1,7 +1,8 @@
import { mixins } from "vue-class-component"; import { mixins } from "vue-class-component";
import { Component, Vue } from "vue-property-decorator"; import { Component, Vue } from "vue-property-decorator";
import { SnackbarProgrammatic as Snackbar } from "buefy"; 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 { IEvent } from "../types/event.model";
import { import {
DELETE_EVENT, DELETE_EVENT,

View file

@ -2,7 +2,8 @@ import { PERSON_MEMBERSHIPS, CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import { GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED } from "@/graphql/event"; import { GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED } from "@/graphql/event";
import { FETCH_GROUP } from "@/graphql/group"; import { FETCH_GROUP } from "@/graphql/group";
import RouteName from "@/router/name"; 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"; import { Component, Vue } from "vue-property-decorator";
@Component({ @Component({

View file

@ -1,8 +1,9 @@
import { Component, Vue, Ref } from "vue-property-decorator"; 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 { IFollower } from "@/types/actor/follower.model";
import { RELAY_FOLLOWERS, RELAY_FOLLOWINGS } from "@/graphql/admin"; import { RELAY_FOLLOWERS, RELAY_FOLLOWINGS } from "@/graphql/admin";
import { Paginate } from "@/types/paginate"; import { Paginate } from "@/types/paginate";
import { ActorType } from "@/types/enums";
@Component({ @Component({
apollo: { apollo: {

View file

@ -18,7 +18,6 @@ export enum EventRouteName {
EVENT_PARTICIPATE_WITHOUT_ACCOUNT = "EVENT_PARTICIPATE_WITHOUT_ACCOUNT", EVENT_PARTICIPATE_WITHOUT_ACCOUNT = "EVENT_PARTICIPATE_WITHOUT_ACCOUNT",
EVENT_PARTICIPATE_LOGGED_OUT = "EVENT_PARTICIPATE_LOGGED_OUT", EVENT_PARTICIPATE_LOGGED_OUT = "EVENT_PARTICIPATE_LOGGED_OUT",
EVENT_PARTICIPATE_CONFIRM = "EVENT_PARTICIPATE_CONFIRM", EVENT_PARTICIPATE_CONFIRM = "EVENT_PARTICIPATE_CONFIRM",
LOCATION = "Location",
TAG = "Tag", TAG = "Tag",
} }
@ -46,14 +45,17 @@ export const eventRoutes: RouteConfig[] = [
name: EventRouteName.EDIT_EVENT, name: EventRouteName.EDIT_EVENT,
component: editEvent, component: editEvent,
meta: { requiredAuth: true }, meta: { requiredAuth: true },
props: (route: Route) => ({ ...route.params, ...{ isUpdate: true } }), props: (route: Route): Record<string, unknown> => ({ ...route.params, ...{ isUpdate: true } }),
}, },
{ {
path: "/events/duplicate/:eventId", path: "/events/duplicate/:eventId",
name: EventRouteName.DUPLICATE_EVENT, name: EventRouteName.DUPLICATE_EVENT,
component: editEvent, component: editEvent,
meta: { requiredAuth: true }, meta: { requiredAuth: true },
props: (route: Route) => ({ ...route.params, ...{ isDuplicate: true } }), props: (route: Route): Record<string, unknown> => ({
...route.params,
...{ isDuplicate: true },
}),
}, },
{ {
path: "/events/:eventId/participations", path: "/events/:eventId/participations",
@ -62,12 +64,6 @@ export const eventRoutes: RouteConfig[] = [
meta: { requiredAuth: true }, meta: { requiredAuth: true },
props: true, props: true,
}, },
{
path: "/location/new",
name: EventRouteName.LOCATION,
component: () => import(/* webpackChunkName: "Location" */ "@/views/Location.vue"),
meta: { requiredAuth: true },
},
{ {
path: "/events/:uuid", path: "/events/:uuid",
name: EventRouteName.EVENT, name: EventRouteName.EVENT,

View file

@ -1,7 +1,7 @@
import { NavigationGuard } from "vue-router"; import { NavigationGuard } from "vue-router";
import { UserRouteName } from "@/router/user"; import { UserRouteName } from "@/router/user";
import { LoginErrorCode } from "@/types/login-error-code.model";
import { AUTH_ACCESS_TOKEN } from "@/constants"; import { AUTH_ACCESS_TOKEN } from "@/constants";
import { LoginErrorCode } from "@/types/enums";
// eslint-disable-next-line import/prefer-default-export // eslint-disable-next-line import/prefer-default-export
export const authGuardIfNeeded: NavigationGuard = async (to, from, next) => { export const authGuardIfNeeded: NavigationGuard = async (to, from, next) => {

View file

@ -1,6 +1,6 @@
import { ErrorCode } from "@/types/enums";
import { NavigationGuard } from "vue-router"; import { NavigationGuard } from "vue-router";
import { CONFIG } from "../../graphql/config"; import { CONFIG } from "../../graphql/config";
import { ErrorCode } from "../../types/error-code.model";
import apolloProvider from "../../vue-apollo"; import apolloProvider from "../../vue-apollo";
// eslint-disable-next-line import/prefer-default-export // eslint-disable-next-line import/prefer-default-export

View file

@ -1,4 +1,4 @@
import { RouteConfig } from "vue-router"; import { Route, RouteConfig } from "vue-router";
export enum SettingsRouteName { export enum SettingsRouteName {
SETTINGS = "SETTINGS", SETTINGS = "SETTINGS",
@ -199,7 +199,10 @@ export const settingsRoutes: RouteConfig[] = [
import( import(
/* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue" /* 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 }, meta: { requiredAuth: true },
}, },
{ {
@ -209,7 +212,10 @@ export const settingsRoutes: RouteConfig[] = [
import( import(
/* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue" /* 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 }, meta: { requiredAuth: true },
}, },
], ],

View file

@ -1,5 +1,5 @@
import { beforeRegisterGuard } from "@/router/guards/register-guard"; import { beforeRegisterGuard } from "@/router/guards/register-guard";
import { RouteConfig } from "vue-router"; import { Route, RouteConfig } from "vue-router";
export enum UserRouteName { export enum UserRouteName {
REGISTER = "Register", REGISTER = "Register",
@ -27,7 +27,7 @@ export const userRoutes: RouteConfig[] = [
component: () => component: () =>
import(/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"), import(/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"),
// We can only pass string values through params, therefore // We can only pass string values through params, therefore
props: (route) => ({ props: (route: Route): Record<string, unknown> => ({
email: route.params.email, email: route.params.email,
userAlreadyActivated: route.params.userAlreadyActivated === "true", userAlreadyActivated: route.params.userAlreadyActivated === "true",
}), }),

View file

@ -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 * 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 * Purge participations which expiration has been reached
* @param participations Map * @param participations Map
@ -39,6 +40,7 @@ function jsonToMap(jsonStr: string): Map<string, IAnonymousParticipation> {
function purgeOldParticipations( function purgeOldParticipations(
participations: Map<string, IAnonymousParticipation> participations: Map<string, IAnonymousParticipation>
): Map<string, IAnonymousParticipation> { ): Map<string, IAnonymousParticipation> {
// eslint-disable-next-line no-restricted-syntax
for (const [hashedUUID, { expiration }] of participations) { for (const [hashedUUID, { expiration }] of participations) {
if (expiration < new Date()) { if (expiration < new Date()) {
participations.delete(hashedUUID); participations.delete(hashedUUID);
@ -67,7 +69,18 @@ function buildExpiration(event: IEvent): Date {
return expiration; 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 * 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 participations = purgeOldParticipations(getLocalAnonymousParticipations());
const hashedUUID = await digestMessage(uuid); const hashedUUID = await digestMessage(uuid);
const participation = participations.get(hashedUUID); 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> { async function getParticipation(eventUUID: string): Promise<IAnonymousParticipation> {
const hashedUUID = await digestMessage(eventUUID); const hashedUUID = await digestMessage(eventUUID);
const participation = purgeOldParticipations(getLocalAnonymousParticipations()).get(hashedUUID); const participation = purgeOldParticipations(getLocalAnonymousParticipations()).get(hashedUUID);
@ -109,6 +117,11 @@ async function getParticipation(eventUUID: string): Promise<IAnonymousParticipat
throw new AnonymousParticipationNotFoundError("Participation not found"); 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> { async function getLeaveTokenForParticipation(eventUUID: string): Promise<string> {
return (await getParticipation(eventUUID)).token; return (await getParticipation(eventUUID)).token;
} }
@ -120,14 +133,6 @@ async function removeAnonymousParticipation(eventUUID: string): Promise<void> {
localStorage.setItem(ANONYMOUS_PARTICIPATIONS_LOCALSTORAGE_KEY, mapToJson(participations)); 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 { export {
addLocalUnconfirmedAnonymousParticipation, addLocalUnconfirmedAnonymousParticipation,
confirmLocalAnonymousParticipation, confirmLocalAnonymousParticipation,

View file

@ -1,12 +1,5 @@
import { IMedia } from "@/types/media.model"; import type { IMedia } from "@/types/media.model";
import { ActorType } from "../enums";
export enum ActorType {
PERSON = "PERSON",
APPLICATION = "APPLICATION",
GROUP = "GROUP",
ORGANISATION = "ORGANISATION",
SERVICE = "SERVICE",
}
export interface IActor { export interface IActor {
id?: string; id?: string;

View file

@ -1,4 +1,4 @@
import { IActor } from "@/types/actor/actor.model"; import type { IActor } from "@/types/actor/actor.model";
export interface IFollower { export interface IFollower {
id?: string; id?: string;

View file

@ -1,38 +1,15 @@
import { Actor, ActorType, IActor } from "./actor.model"; import type { IActor } from "./actor.model";
import { Paginate } from "../paginate"; import { Actor } from "./actor.model";
import { IResource } from "../resource"; import type { Paginate } from "../paginate";
import { ITodoList } from "../todos"; import type { IResource } from "../resource";
import { IEvent } from "../event.model"; import type { IEvent } from "../event.model";
import { IDiscussion } from "../discussions"; import type { IDiscussion } from "../discussions";
import { IPerson } from "./person.model"; import type { IPost } from "../post.model";
import { IPost } from "../post.model"; import type { IAddress } from "../address.model";
import { IAddress, Address } from "../address.model"; import { Address } from "../address.model";
import { ActorType, Openness } from "../enums";
export enum MemberRole { import type { IMember } from "./member.model";
NOT_APPROVED = "NOT_APPROVED", import type { ITodoList } from "../todolist";
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;
}
export interface IGroup extends IActor { export interface IGroup extends IActor {
members: Paginate<IMember>; members: Paginate<IMember>;

View file

@ -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;
}

View file

@ -1,15 +1,11 @@
import { ICurrentUser } from "../current-user.model"; import type { ICurrentUser } from "../current-user.model";
import { IEvent } from "../event.model"; import type { IEvent } from "../event.model";
import { Actor, IActor } from "./actor.model"; import { Actor } from "./actor.model";
import { Paginate } from "../paginate"; import type { IActor } from "./actor.model";
import { IMember } from "./group.model"; import type { Paginate } from "../paginate";
import { IParticipant } from "../participant.model"; import type { IParticipant } from "../participant.model";
import type { IMember } from "./member.model";
export interface IFeedToken { import type { IFeedToken } from "../feedtoken.model";
token: string;
actor?: IPerson;
user: ICurrentUser;
}
export interface IPerson extends IActor { export interface IPerson extends IActor {
feedTokens: IFeedToken[]; feedTokens: IFeedToken[];

View file

@ -1,4 +1,5 @@
import { poiIcons, IPOIIcon } from "@/utils/poiIcons"; import { poiIcons } from "@/utils/poiIcons";
import type { IPOIIcon } from "@/utils/poiIcons";
export interface IAddress { export interface IAddress {
id?: string; id?: string;
@ -53,7 +54,7 @@ export class Address implements IAddress {
this.originId = hash.originId; this.originId = hash.originId;
} }
get poiInfos() { get poiInfos(): { name: string; alternativeName: string; poiIcon: IPOIIcon } {
/* generate name corresponding to poi type */ /* generate name corresponding to poi type */
let name = ""; let name = "";
let alternativeName = ""; let alternativeName = "";

View file

@ -1,5 +1,6 @@
import { IEvent } from "@/types/event.model"; import type { IEvent } from "@/types/event.model";
import { IGroup } from "./actor"; import type { IGroup } from "./actor";
import { InstanceTermsType } from "./enums";
export interface IDashboard { export interface IDashboard {
lastPublicEventPublished: IEvent; lastPublicEventPublished: IEvent;
@ -14,23 +15,10 @@ export interface IDashboard {
numberOfConfirmedParticipationsToLocalEvents: number; numberOfConfirmedParticipationsToLocalEvents: number;
} }
export enum InstanceTermsType {
DEFAULT = "DEFAULT",
URL = "URL",
CUSTOM = "CUSTOM",
}
export enum InstancePrivacyType {
DEFAULT = "DEFAULT",
URL = "URL",
CUSTOM = "CUSTOM",
}
export interface ILanguage { export interface ILanguage {
code: string; code: string;
name: string; name: string;
} }
export interface IAdminSettings { export interface IAdminSettings {
instanceName: string; instanceName: string;
instanceDescription: string; instanceDescription: string;

View file

@ -1,5 +1,7 @@
import { Actor, IActor } from "@/types/actor"; import { Actor } from "@/types/actor";
import { EventModel, IEvent } from "@/types/event.model"; import type { IActor } from "@/types/actor";
import type { IEvent } from "@/types/event.model";
import { EventModel } from "@/types/event.model";
export interface IComment { export interface IComment {
id?: string; id?: string;

View file

@ -1,5 +1,5 @@
import { InstanceTermsType, InstancePrivacyType } from "./admin.model"; import { InstancePrivacyType, InstanceTermsType } from "./enums";
import { IProvider } from "./resource"; import type { IProvider } from "./resource";
export interface IOAuthProvider { export interface IOAuthProvider {
id: string; id: string;

View file

@ -1,13 +1,8 @@
import { IEvent } from "@/types/event.model"; import type { IEvent } from "@/types/event.model";
import { IPerson } from "@/types/actor/person.model"; import type { IPerson } from "@/types/actor/person.model";
import { Paginate } from "./paginate"; import type { Paginate } from "./paginate";
import { IParticipant } from "./participant.model"; import type { IParticipant } from "./participant.model";
import { ICurrentUserRole, INotificationPendingEnum } from "./enums";
export enum ICurrentUserRole {
USER = "USER",
MODERATOR = "MODERATOR",
ADMINISTRATOR = "ADMINISTRATOR",
}
export interface ICurrentUser { export interface ICurrentUser {
id: string; id: string;
@ -17,13 +12,6 @@ export interface ICurrentUser {
defaultActor?: IPerson; defaultActor?: IPerson;
} }
export enum INotificationPendingEnum {
NONE = "NONE",
DIRECT = "DIRECT",
ONE_DAY = "ONE_DAY",
ONE_HOUR = "ONE_HOUR",
}
export interface IUserSettings { export interface IUserSettings {
timezone: string; timezone: string;
notificationOnDay: boolean; notificationOnDay: boolean;
@ -49,14 +37,3 @@ export interface IUser extends ICurrentUser {
currentSignInIp: string; currentSignInIp: string;
currentSignInAt: string; currentSignInAt: string;
} }
export enum IAuthProvider {
LDAP = "ldap",
GOOGLE = "google",
DISCORD = "discord",
GITHUB = "github",
KEYCLOAK = "keycloak",
FACEBOOK = "facebook",
GITLAB = "gitlab",
TWITTER = "twitter",
}

View file

@ -1,6 +1,7 @@
import { IActor, IPerson } from "@/types/actor"; import type { IActor, IPerson } from "@/types/actor";
import { IComment, CommentModel } from "@/types/comment.model"; import type { IComment } from "@/types/comment.model";
import { Paginate } from "@/types/paginate"; import { CommentModel } from "@/types/comment.model";
import type { Paginate } from "@/types/paginate";
export interface IDiscussion { export interface IDiscussion {
id?: string; id?: string;

161
js/src/types/enums.ts Normal file
View file

@ -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",
}

View file

@ -1,4 +0,0 @@
export enum ErrorCode {
UNKNOWN = "unknown",
REGISTRATION_CLOSED = "registration_closed",
}

View file

@ -1,3 +1,5 @@
import { CommentModeration } from "./enums";
export interface IParticipationCondition { export interface IParticipationCondition {
title: string; title: string;
content: string; content: string;
@ -10,12 +12,6 @@ export interface IOffer {
url: string; url: string;
} }
export enum CommentModeration {
ALLOW_ALL = "ALLOW_ALL",
MODERATED = "MODERATED",
CLOSED = "CLOSED",
}
export interface IEventOptions { export interface IEventOptions {
maximumAttendeeCapacity: number; maximumAttendeeCapacity: number;
remainingAttendeeCapacity: number; remainingAttendeeCapacity: number;

View file

@ -1,44 +1,15 @@
import { Address, IAddress } from "@/types/address.model"; import { Address } from "@/types/address.model";
import { ITag } from "@/types/tag.model"; import type { IAddress } from "@/types/address.model";
import { IMedia } from "@/types/media.model"; import type { ITag } from "@/types/tag.model";
import { IComment } from "@/types/comment.model"; import type { IMedia } from "@/types/media.model";
import { Paginate } from "@/types/paginate"; import type { IComment } from "@/types/comment.model";
import { Actor, Group, IActor, IGroup, IPerson } from "./actor"; import type { Paginate } from "@/types/paginate";
import { IParticipant } from "./participant.model"; import { Actor, Group } from "./actor";
import { EventOptions, IEventOptions } from "./event-options.model"; import type { IActor, IGroup, IPerson } from "./actor";
import type { IParticipant } from "./participant.model";
export enum EventStatus { import { EventOptions } from "./event-options.model";
TENTATIVE = "TENTATIVE", import type { IEventOptions } from "./event-options.model";
CONFIRMED = "CONFIRMED", import { EventJoinOptions, EventStatus, EventVisibility } from "./enums";
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 interface IEventCardOptions { export interface IEventCardOptions {
hideDate: boolean; hideDate: boolean;

View file

@ -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;
}

View file

@ -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",
}

View file

@ -1,4 +1,4 @@
import { ICurrentUser } from "@/types/current-user.model"; import type { ICurrentUser } from "@/types/current-user.model";
export interface IToken { export interface IToken {
accessToken: string; accessToken: string;

View file

@ -1,15 +1,8 @@
import { Actor, IActor } from "./actor"; import { Actor } from "./actor";
import { EventModel, IEvent } from "./event.model"; import type { IActor } from "./actor";
import { EventModel } from "./event.model";
export enum ParticipantRole { import type { IEvent } from "./event.model";
NOT_APPROVED = "NOT_APPROVED", import { ParticipantRole } from "./enums";
NOT_CONFIRMED = "NOT_CONFIRMED",
REJECTED = "REJECTED",
PARTICIPANT = "PARTICIPANT",
MODERATOR = "MODERATOR",
ADMINISTRATOR = "ADMINISTRATOR",
CREATOR = "CREATOR",
}
export interface IParticipant { export interface IParticipant {
id?: string; id?: string;

View file

@ -1,13 +1,7 @@
import { ITag } from "./tag.model"; import type { ITag } from "./tag.model";
import { IMedia } from "./media.model"; import type { IMedia } from "./media.model";
import { IActor } from "./actor"; import type { IActor } from "./actor";
import type { PostVisibility } from "./enums";
export enum PostVisibility {
PUBLIC = "PUBLIC",
UNLISTED = "UNLISTED",
RESTRICTED = "RESTRICTED",
PRIVATE = "PRIVATE",
}
export interface IPost { export interface IPost {
id?: string; id?: string;

View file

@ -1,13 +1,16 @@
import { IActor, IPerson } from "@/types/actor"; import type { IActor, IPerson } from "@/types/actor";
import { IEvent } from "@/types/event.model"; import type { IEvent } from "@/types/event.model";
import { IComment } from "@/types/comment.model"; import type { IComment } from "@/types/comment.model";
import { ActionLogAction, ReportStatusEnum } from "./enums";
export enum ReportStatusEnum { export interface IActionLogObject {
OPEN = "OPEN", id: string;
CLOSED = "CLOSED", }
RESOLVED = "RESOLVED", export interface IReportNote extends IActionLogObject {
id: string;
content: string;
moderator: IActor;
} }
export interface IReport extends IActionLogObject { export interface IReport extends IActionLogObject {
id: string; id: string;
reported: IActor; reported: IActor;
@ -21,29 +24,6 @@ export interface IReport extends IActionLogObject {
status: ReportStatusEnum; 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 { export interface IActionLog {
id: string; id: string;
object: IReport | IReportNote | IEvent | IComment | IActor; object: IReport | IReportNote | IEvent | IComment | IActor;

View file

@ -1,6 +1,20 @@
import { Paginate } from "@/types/paginate"; import type { Paginate } from "@/types/paginate";
import { IActor } from "@/types/actor"; 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 { export interface IResource {
id?: string; id?: string;
title: string; title: string;
@ -18,22 +32,7 @@ export interface IResource {
type?: string; type?: string;
} }
export interface IResourceMetadata { export const mapServiceTypeToIcon: Record<string, string> = {
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 = {
pad: "file-document-outline", pad: "file-document-outline",
calc: "google-spreadsheet", calc: "google-spreadsheet",
visio: "webcam", visio: "webcam",

View file

@ -1,5 +1,5 @@
import { IGroup, IPerson } from "@/types/actor"; import type { IGroup, IPerson } from "@/types/actor";
import { IEvent } from "@/types/event.model"; import type { IEvent } from "@/types/event.model";
export interface SearchEvent { export interface SearchEvent {
total: number; total: number;
@ -15,8 +15,3 @@ export interface SearchPerson {
total: number; total: number;
elements: IPerson[]; elements: IPerson[];
} }
export enum SearchTabs {
EVENTS = 0,
GROUPS = 1,
}

10
js/src/types/todolist.ts Normal file
View file

@ -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;
}

View file

@ -1,12 +1,5 @@
import { Paginate } from "@/types/paginate"; import type { IActor, IPerson } from "@/types/actor";
import { IActor, IPerson } from "@/types/actor"; import { ITodoList } from "./todolist";
export interface ITodoList {
id: string;
title: string;
todos: Paginate<ITodo>;
actor?: IActor;
}
export interface ITodo { export interface ITodo {
id?: string; id?: string;

View file

@ -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

View file

@ -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) { for (let index = 0; index < array.length; index += 1) {
// eslint-disable-next-line no-await-in-loop
await callback(array[index], index, array); await callback(array[index], index, array);
} }
} }

View file

@ -10,10 +10,10 @@ import {
import { ILogin, IToken } from "@/types/login.model"; import { ILogin, IToken } from "@/types/login.model";
import { UPDATE_CURRENT_USER_CLIENT } from "@/graphql/user"; import { UPDATE_CURRENT_USER_CLIENT } from "@/graphql/user";
import ApolloClient from "apollo-client"; import ApolloClient from "apollo-client";
import { ICurrentUserRole } from "@/types/current-user.model";
import { IPerson } from "@/types/actor"; import { IPerson } from "@/types/actor";
import { IDENTITIES, UPDATE_CURRENT_ACTOR_CLIENT } from "@/graphql/actor"; import { IDENTITIES, UPDATE_CURRENT_ACTOR_CLIENT } from "@/graphql/actor";
import { NormalizedCacheObject } from "apollo-cache-inmemory"; import { NormalizedCacheObject } from "apollo-cache-inmemory";
import { ICurrentUserRole } from "@/types/enums";
export function saveTokenData(obj: IToken): void { export function saveTokenData(obj: IToken): void {
localStorage.setItem(AUTH_ACCESS_TOKEN, obj.accessToken); localStorage.setItem(AUTH_ACCESS_TOKEN, obj.accessToken);
@ -37,14 +37,19 @@ export function saveActorData(obj: IPerson): void {
} }
export function deleteUserData(): void { export function deleteUserData(): void {
[AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN, AUTH_USER_ROLE].forEach((key) => { [AUTH_USER_ID, AUTH_USER_EMAIL, AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN, AUTH_USER_ROLE].forEach(
localStorage.removeItem(key); (key) => {
}); localStorage.removeItem(key);
}
);
} }
export class NoIdentitiesException extends Error {} 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({ await apollo.mutate({
mutation: UPDATE_CURRENT_ACTOR_CLIENT, mutation: UPDATE_CURRENT_ACTOR_CLIENT,
variables: identity, variables: identity,
@ -69,7 +74,8 @@ export async function initializeCurrentActor(apollo: ApolloClient<any>): Promise
console.warn("Logged user has no identities!"); console.warn("Logged user has no identities!");
throw new NoIdentitiesException(); 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) { if (activeIdentity) {
await changeIdentity(apollo, activeIdentity); await changeIdentity(apollo, activeIdentity);

View file

@ -1,3 +1,3 @@
export function nl2br(text: string) { export function nl2br(text: string): string {
return text.replace(/(?:\r\n|\r|\n)/g, "<br>"); return text.replace(/(?:\r\n|\r|\n)/g, "<br>");
} }

View file

@ -7,10 +7,15 @@ import langs from "../i18n/langs.json";
const DEFAULT_LOCALE = "en_US"; const DEFAULT_LOCALE = "en_US";
let language = localStorage.getItem(USER_LOCALE) || (document.documentElement.getAttribute("lang") as string); let language =
language = language || ((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_"); localStorage.getItem(USER_LOCALE) || (document.documentElement.getAttribute("lang") as string);
language =
language ||
((window.navigator as any).userLanguage || window.navigator.language).replace(/-/, "_");
export const locale = 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); Vue.use(VueI18n);

View file

@ -9,7 +9,11 @@ export async function buildFileFromIMedia(obj: IMedia | null | undefined): Promi
return new File([blob], obj.name); 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 {}; if (!file) return {};
return { return {

View file

@ -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));
}

View file

@ -1,15 +1,5 @@
import { IActor } from "@/types/actor"; 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 { function convertToUsername(value: string | null): string {
if (!value) return ""; if (!value) return "";
@ -22,6 +12,17 @@ function convertToUsername(value: string | null): string {
.replace(/[^a-z0-9_]/g, ""); .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 { function validateUsername(actor: IActor): boolean {
return actor.preferredUsername === convertToUsername(actor.preferredUsername); return actor.preferredUsername === convertToUsername(actor.preferredUsername);
} }

View file

@ -1,7 +1,7 @@
export function validateEmailField(value: string) { export function validateEmailField(value: string): boolean | string {
return value.includes("@") || "Invalid e-mail."; return value.includes("@") || "Invalid e-mail.";
} }
export function validateRequiredField(value: any) { export function validateRequiredField(value: unknown): boolean | string {
return !!value || "Required."; return !!value || "Required.";
} }

View file

@ -9,7 +9,7 @@
import { Component, Vue, Watch } from "vue-property-decorator"; import { Component, Vue, Watch } from "vue-property-decorator";
import { PRIVACY } from "@/graphql/config"; import { PRIVACY } from "@/graphql/config";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
import { InstancePrivacyType } from "@/types/admin.model"; import { InstancePrivacyType } from "@/types/enums";
@Component({ @Component({
apollo: { apollo: {
@ -31,19 +31,18 @@ export default class Privacy extends Vue {
locale: string | null = null; locale: string | null = null;
created() { created(): void {
this.locale = this.$i18n.locale; this.locale = this.$i18n.locale;
} }
@Watch("config", { deep: true }) @Watch("config", { deep: true })
watchConfig(config: IConfig) { watchConfig(config: IConfig): void {
if (config.privacy.type) { if (config.privacy.type) {
console.log(this.config.privacy);
this.redirectToUrl(); this.redirectToUrl();
} }
} }
redirectToUrl() { redirectToUrl(): void {
if (this.config.privacy.type === InstancePrivacyType.URL) { if (this.config.privacy.type === InstancePrivacyType.URL) {
window.location.replace(this.config.privacy.url); window.location.replace(this.config.privacy.url);
} }

View file

@ -7,10 +7,9 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator"; import { Component, Vue } from "vue-property-decorator";
import { RULES } from "@/graphql/config"; import { RULES } from "@/graphql/config";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
import { InstanceTermsType } from "@/types/admin.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component({ @Component({

View file

@ -9,7 +9,7 @@
import { Component, Vue, Watch } from "vue-property-decorator"; import { Component, Vue, Watch } from "vue-property-decorator";
import { TERMS } from "@/graphql/config"; import { TERMS } from "@/graphql/config";
import { IConfig } from "@/types/config.model"; import { IConfig } from "@/types/config.model";
import { InstanceTermsType } from "@/types/admin.model"; import { InstanceTermsType } from "@/types/enums";
@Component({ @Component({
apollo: { apollo: {
@ -31,19 +31,18 @@ export default class Terms extends Vue {
locale: string | null = null; locale: string | null = null;
created() { created(): void {
this.locale = this.$i18n.locale; this.locale = this.$i18n.locale;
} }
@Watch("config", { deep: true }) @Watch("config", { deep: true })
watchConfig(config: IConfig) { watchConfig(config: IConfig): void {
if (config.terms.type) { if (config.terms.type) {
console.log(this.config.terms);
this.redirectToUrl(); this.redirectToUrl();
} }
} }
redirectToUrl() { redirectToUrl(): void {
if (this.config.terms.type === InstanceTermsType.URL) { if (this.config.terms.type === InstanceTermsType.URL) {
window.location.replace(this.config.terms.url); window.location.replace(this.config.terms.url);
} }

View file

@ -199,8 +199,9 @@
import { Component, Vue, Prop } from "vue-property-decorator"; import { Component, Vue, Prop } from "vue-property-decorator";
import { GET_GROUP, REFRESH_PROFILE } from "@/graphql/group"; import { GET_GROUP, REFRESH_PROFILE } from "@/graphql/group";
import { formatBytes } from "@/utils/datetime"; import { formatBytes } from "@/utils/datetime";
import { MemberRole } from "@/types/enums";
import { SUSPEND_PROFILE, UNSUSPEND_PROFILE } from "../../graphql/actor"; 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 { usernameWithDomain, IActor } from "../../types/actor/actor.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
import ActorCard from "../../components/Account/ActorCard.vue"; import ActorCard from "../../components/Account/ActorCard.vue";

View file

@ -64,10 +64,11 @@
import { Component, Vue, Prop } from "vue-property-decorator"; import { Component, Vue, Prop } from "vue-property-decorator";
import { Route } from "vue-router"; import { Route } from "vue-router";
import { formatBytes } from "@/utils/datetime"; import { formatBytes } from "@/utils/datetime";
import { ICurrentUserRole } from "@/types/enums";
import { GET_USER, SUSPEND_USER } from "../../graphql/user"; import { GET_USER, SUSPEND_USER } from "../../graphql/user";
import { usernameWithDomain } from "../../types/actor/actor.model"; import { usernameWithDomain } from "../../types/actor/actor.model";
import RouteName from "../../router/name"; 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"; import { IPerson } from "../../types/actor";
@Component({ @Component({

View file

@ -83,7 +83,6 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator"; import { Component, Vue, Watch } from "vue-property-decorator";
import { LIST_GROUPS } from "@/graphql/group"; import { LIST_GROUPS } from "@/graphql/group";
import { LIST_PROFILES } from "../../graphql/actor";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
const PROFILES_PER_PAGE = 10; const PROFILES_PER_PAGE = 10;
@ -124,7 +123,7 @@ export default class GroupProfiles extends Vue {
RouteName = RouteName; RouteName = RouteName;
async onPageChange(page: number) { async onPageChange(page: number): Promise<void> {
this.page = page; this.page = page;
await this.$apollo.queries.groups.fetchMore({ await this.$apollo.queries.groups.fetchMore({
variables: { 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.preferredUsername = preferredUsername;
this.domain = domain; this.domain = domain;
} }
@Watch("domain") @Watch("domain")
domainNotLocal() { domainNotLocal(): void {
this.local = this.domain === ""; this.local = this.domain === "";
} }
} }

View file

@ -123,7 +123,7 @@ export default class Profiles extends Vue {
RouteName = RouteName; RouteName = RouteName;
async onPageChange(page: number) { async onPageChange(page: number): Promise<void> {
this.page = page; this.page = page;
await this.$apollo.queries.persons.fetchMore({ await this.$apollo.queries.persons.fetchMore({
variables: { 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.preferredUsername = preferredUsername;
this.domain = domain; this.domain = domain;
} }
@Watch("domain") @Watch("domain")
domainNotLocal() { domainNotLocal(): void {
this.local = this.domain === ""; this.local = this.domain === "";
} }
} }

View file

@ -290,12 +290,8 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator"; import { Component, Vue, Watch } from "vue-property-decorator";
import { ADMIN_SETTINGS, SAVE_ADMIN_SETTINGS, LANGUAGES } from "@/graphql/admin"; import { ADMIN_SETTINGS, SAVE_ADMIN_SETTINGS, LANGUAGES } from "@/graphql/admin";
import { import { InstancePrivacyType, InstanceTermsType } from "@/types/enums";
IAdminSettings, import { IAdminSettings, ILanguage } from "../../types/admin.model";
InstanceTermsType,
InstancePrivacyType,
ILanguage,
} from "../../types/admin.model";
import RouteName from "../../router/name"; import RouteName from "../../router/name";
@Component({ @Component({

View file

@ -123,7 +123,7 @@ export default class Users extends Vue {
RouteName = RouteName; RouteName = RouteName;
async onPageChange(page: number) { async onPageChange(page: number): Promise<void> {
this.page = page; this.page = page;
await this.$apollo.queries.users.fetchMore({ await this.$apollo.queries.users.fetchMore({
variables: { variables: {

View file

@ -222,23 +222,24 @@ export default class discussion extends mixins(GroupMixin) {
}, },
}); });
if (!discussionData) return; if (!discussionData) return;
const { discussion } = discussionData; const { discussion: discussionCached } = discussionData;
discussion.lastComment = replyToDiscussion.lastComment; discussionCached.lastComment = replyToDiscussion.lastComment;
discussion.comments.elements.push(replyToDiscussion.lastComment); discussionCached.comments.elements.push(replyToDiscussion.lastComment);
discussion.comments.total += 1; discussionCached.comments.total += 1;
store.writeQuery({ store.writeQuery({
query: GET_DISCUSSION, query: GET_DISCUSSION,
variables: { slug: this.slug, page: this.page }, 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 = ""; this.newComment = "";
} }
async updateComment(comment: IComment): Promise<void> { async updateComment(comment: IComment): Promise<void> {
const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({ await this.$apollo.mutate<{ deleteComment: IComment }>({
mutation: UPDATE_COMMENT, mutation: UPDATE_COMMENT,
variables: { variables: {
commentId: comment.id, commentId: comment.id,
@ -256,25 +257,25 @@ export default class discussion extends mixins(GroupMixin) {
}, },
}); });
if (!discussionData) return; if (!discussionData) return;
const { discussion } = discussionData; const { discussion: discussionCached } = discussionData;
const index = discussion.comments.elements.findIndex( const index = discussionCached.comments.elements.findIndex(
({ id }) => id === data.deleteComment.id ({ id }) => id === data.deleteComment.id
); );
if (index > -1) { if (index > -1) {
discussion.comments.elements.splice(index, 1); discussionCached.comments.elements.splice(index, 1);
discussion.comments.total -= 1; discussionCached.comments.total -= 1;
} }
store.writeQuery({ store.writeQuery({
query: GET_DISCUSSION, query: GET_DISCUSSION,
variables: { slug: this.slug, page: this.page }, variables: { slug: this.slug, page: this.page },
data: { discussion }, data: { discussion: discussionCached },
}); });
}, },
}); });
} }
async deleteComment(comment: IComment): Promise<void> { async deleteComment(comment: IComment): Promise<void> {
const { data } = await this.$apollo.mutate<{ deleteComment: IComment }>({ await this.$apollo.mutate<{ deleteComment: IComment }>({
mutation: DELETE_COMMENT, mutation: DELETE_COMMENT,
variables: { variables: {
commentId: comment.id, commentId: comment.id,
@ -291,21 +292,21 @@ export default class discussion extends mixins(GroupMixin) {
}, },
}); });
if (!discussionData) return; if (!discussionData) return;
const { discussion } = discussionData; const { discussion: discussionCached } = discussionData;
const index = discussion.comments.elements.findIndex( const index = discussionCached.comments.elements.findIndex(
({ id }) => id === data.deleteComment.id ({ id }) => id === data.deleteComment.id
); );
if (index > -1) { if (index > -1) {
const updatedComment = discussion.comments.elements[index]; const updatedComment = discussionCached.comments.elements[index];
updatedComment.deletedAt = new Date(); updatedComment.deletedAt = new Date();
updatedComment.actor = null; updatedComment.actor = null;
updatedComment.text = ""; updatedComment.text = "";
discussion.comments.elements.splice(index, 1, updatedComment); discussionCached.comments.elements.splice(index, 1, updatedComment);
} }
store.writeQuery({ store.writeQuery({
query: GET_DISCUSSION, query: GET_DISCUSSION,
variables: { slug: this.slug, page: this.page }, 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; if (!fetchMoreResult) return previousResult;
const newComments = fetchMoreResult.discussion.comments.elements; const newComments = fetchMoreResult.discussion.comments.elements;
this.hasMoreComments = newComments.length === 1; this.hasMoreComments = newComments.length === 1;
const { discussion } = previousResult; const { discussion: discussionCached } = previousResult;
discussion.comments.elements = [ discussionCached.comments.elements = [
...previousResult.discussion.comments.elements, ...previousResult.discussion.comments.elements,
...newComments, ...newComments,
]; ];
return { discussion }; return { discussion: discussionCached };
}, },
}); });
} catch (e) { } catch (e) {
@ -359,12 +360,12 @@ export default class discussion extends mixins(GroupMixin) {
}, },
}); });
if (!discussionData) return; if (!discussionData) return;
const { discussion } = discussionData; const { discussion: discussionCached } = discussionData;
discussion.title = updateDiscussion.title; discussionCached.title = updateDiscussion.title;
store.writeQuery({ store.writeQuery({
query: GET_DISCUSSION, query: GET_DISCUSSION,
variables: { slug: this.slug, page: this.page }, variables: { slug: this.slug, page: this.page },
data: { discussion }, data: { discussion: discussionCached },
}); });
}, },
}); });

View file

@ -11,8 +11,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ErrorCode } from "@/types/enums";
import { Component, Vue } from "vue-property-decorator"; import { Component, Vue } from "vue-property-decorator";
import { ErrorCode } from "@/types/error-code.model";
@Component @Component
export default class ErrorPage extends Vue { export default class ErrorPage extends Vue {
@ -20,7 +20,7 @@ export default class ErrorPage extends Vue {
ErrorCode = ErrorCode; ErrorCode = ErrorCode;
mounted() { mounted(): void {
this.code = this.$route.query.code as ErrorCode; this.code = this.$route.query.code as ErrorCode;
} }
} }

View file

@ -353,8 +353,13 @@ import IdentityPickerWrapper from "@/views/Account/IdentityPickerWrapper.vue";
import Subtitle from "@/components/Utils/Subtitle.vue"; import Subtitle from "@/components/Utils/Subtitle.vue";
import { Route } from "vue-router"; import { Route } from "vue-router";
import { formatList } from "@/utils/i18n"; import { formatList } from "@/utils/i18n";
import { CommentModeration } from "../../types/event-options.model"; import {
import { ParticipantRole } from "../../types/participant.model"; CommentModeration,
EventJoinOptions,
EventStatus,
EventVisibility,
ParticipantRole,
} from "@/types/enums";
import OrganizerPickerWrapper from "../../components/Event/OrganizerPickerWrapper.vue"; import OrganizerPickerWrapper from "../../components/Event/OrganizerPickerWrapper.vue";
import { import {
CREATE_EVENT, CREATE_EVENT,
@ -362,13 +367,7 @@ import {
EVENT_PERSON_PARTICIPATION, EVENT_PERSON_PARTICIPATION,
FETCH_EVENT, FETCH_EVENT,
} from "../../graphql/event"; } from "../../graphql/event";
import { import { EventModel, IEvent } from "../../types/event.model";
EventJoinOptions,
EventModel,
EventStatus,
EventVisibility,
IEvent,
} from "../../types/event.model";
import { import {
CURRENT_ACTOR_CLIENT, CURRENT_ACTOR_CLIENT,
LOGGED_USER_DRAFTS, LOGGED_USER_DRAFTS,
@ -837,9 +836,9 @@ export default class EditEvent extends Vue {
/** /**
* Confirm cancel * Confirm cancel
*/ */
confirmGoElsewhere(callback: (value?: string) => any): void | Function { confirmGoElsewhere(callback: (value?: string) => any): void {
if (!this.isEventModified) { if (!this.isEventModified) {
return callback(); callback();
} }
const title: string = this.isUpdate const title: string = this.isUpdate
? (this.$t("Cancel edition") as string) ? (this.$t("Cancel edition") as string)
@ -872,7 +871,8 @@ export default class EditEvent extends Vue {
this.confirmGoElsewhere(() => this.$router.go(-1)); 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(); if (to.name === RouteName.EVENT) return next();
this.confirmGoElsewhere(() => next()); this.confirmGoElsewhere(() => next());
} }

View file

@ -504,6 +504,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Prop, Watch } from "vue-property-decorator"; import { Component, Prop, Watch } from "vue-property-decorator";
import BIcon from "buefy/src/components/icon/Icon.vue"; import BIcon from "buefy/src/components/icon/Icon.vue";
import { EventJoinOptions, EventStatus, EventVisibility, ParticipantRole } from "@/types/enums";
import { import {
EVENT_PERSON_PARTICIPATION, EVENT_PERSON_PARTICIPATION,
EVENT_PERSON_PARTICIPATION_SUBSCRIPTION_CHANGED, EVENT_PERSON_PARTICIPATION_SUBSCRIPTION_CHANGED,
@ -511,13 +512,7 @@ import {
JOIN_EVENT, JOIN_EVENT,
} from "../../graphql/event"; } from "../../graphql/event";
import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor"; import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
import { import { EventModel, IEvent } from "../../types/event.model";
EventModel,
EventStatus,
EventVisibility,
IEvent,
EventJoinOptions,
} from "../../types/event.model";
import { IActor, IPerson, Person, usernameWithDomain } from "../../types/actor"; import { IActor, IPerson, Person, usernameWithDomain } from "../../types/actor";
import { GRAPHQL_API_ENDPOINT } from "../../api/_entrypoint"; import { GRAPHQL_API_ENDPOINT } from "../../api/_entrypoint";
import DateCalendarIcon from "../../components/Event/DateCalendarIcon.vue"; 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 EventMetadataBlock from "../../components/Event/EventMetadataBlock.vue";
import ActorCard from "../../components/Account/ActorCard.vue"; import ActorCard from "../../components/Account/ActorCard.vue";
import PopoverActorCard from "../../components/Account/PopoverActorCard.vue"; import PopoverActorCard from "../../components/Account/PopoverActorCard.vue";
import { IParticipant, ParticipantRole } from "../../types/participant.model"; import { IParticipant } from "../../types/participant.model";
@Component({ @Component({
components: { components: {

Some files were not shown because too many files have changed in this diff Show more