Fix lint issues

And disable eslint when building in prod mode

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2020-11-30 10:24:11 +01:00
parent da42522073
commit 2d541f2e32
No known key found for this signature in database
GPG Key ID: A061B9DDE0CA0773
161 changed files with 3869 additions and 1236 deletions

View File

@ -4,4 +4,4 @@ indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 100
max_line_length = 80

View File

@ -38,8 +38,11 @@ module.exports = {
"error",
{
ignoreStrings: true,
ignoreHTMLTextContents: true,
ignoreTemplateLiterals: true,
ignoreComments: true,
template: 170,
code: 100,
code: 80,
},
],
"prettier/prettier": "error",
@ -56,7 +59,10 @@ module.exports = {
overrides: [
{
files: ["**/__tests__/*.{j,t}s?(x)", "**/tests/unit/**/*.spec.{j,t}s?(x)"],
files: [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)",
],
env: {
mocha: true,
},

View File

@ -24,7 +24,9 @@ fetch(`http://localhost:4000/api`, {
.then((result) => result.json())
.then((result) => {
// here we're filtering out any type information unrelated to unions or interfaces
const filteredData = result.data.__schema.types.filter((type) => type.possibleTypes !== null);
const filteredData = result.data.__schema.types.filter(
(type) => type.possibleTypes !== null
);
result.data.__schema.types = filteredData;
fs.writeFile("./fragmentTypes.json", JSON.stringify(result.data), (err) => {
if (err) {

View File

@ -32,8 +32,16 @@
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import NavBar from "./components/NavBar.vue";
import { AUTH_ACCESS_TOKEN, AUTH_USER_EMAIL, AUTH_USER_ID, AUTH_USER_ROLE } from "./constants";
import { CURRENT_USER_CLIENT, UPDATE_CURRENT_USER_CLIENT } from "./graphql/user";
import {
AUTH_ACCESS_TOKEN,
AUTH_USER_EMAIL,
AUTH_USER_ID,
AUTH_USER_ROLE,
} from "./constants";
import {
CURRENT_USER_CLIENT,
UPDATE_CURRENT_USER_CLIENT,
} from "./graphql/user";
import Footer from "./components/Footer.vue";
import Logo from "./components/Logo.vue";
import { initializeCurrentActor } from "./utils/auth";

View File

@ -56,7 +56,12 @@ export default function buildCurrentUserResolver(
preferredUsername,
avatar,
name,
}: { id: string; preferredUsername: string; avatar: string; name: string },
}: {
id: string;
preferredUsername: string;
avatar: string;
name: string;
},
{ cache: localCache }: { cache: ApolloCache<NormalizedCacheObject> }
) => {
const data = {

View File

@ -1,4 +1,7 @@
import { IntrospectionFragmentMatcher, NormalizedCacheObject } from "apollo-cache-inmemory";
import {
IntrospectionFragmentMatcher,
NormalizedCacheObject,
} from "apollo-cache-inmemory";
import { AUTH_ACCESS_TOKEN, AUTH_REFRESH_TOKEN } from "@/constants";
import { REFRESH_TOKEN } from "@/graphql/auth";
import { saveTokenData } from "@/utils/auth";
@ -11,7 +14,11 @@ export const fragmentMatcher = new IntrospectionFragmentMatcher({
{
kind: "UNION",
name: "SearchResult",
possibleTypes: [{ name: "Event" }, { name: "Person" }, { name: "Group" }],
possibleTypes: [
{ name: "Event" },
{ name: "Person" },
{ name: "Group" },
],
},
{
kind: "INTERFACE",

View File

@ -13,7 +13,12 @@
<template slot-scope="props">
<div class="media">
<div class="media-left">
<img width="32" :src="props.option.avatar.url" v-if="props.option.avatar" alt="" />
<img
width="32"
:src="props.option.avatar.url"
v-if="props.option.avatar"
alt=""
/>
<b-icon v-else icon="account-circle" />
</div>
<div class="media-content">
@ -21,7 +26,9 @@
{{ props.option.name }}
<br />
<small>{{ `@${props.option.preferredUsername}` }}</small>
<small v-if="props.option.domain">{{ `@${props.option.domain}` }}</small>
<small v-if="props.option.domain">{{
`@${props.option.domain}`
}}</small>
</span>
<span v-else>
{{ `@${props.option.preferredUsername}` }}
@ -53,7 +60,9 @@ export default class ActorAutoComplete extends Vue {
selected: IPerson | null = this.defaultSelected;
name: string = this.defaultSelected ? this.defaultSelected.preferredUsername : "";
name: string = this.defaultSelected
? this.defaultSelected.preferredUsername
: "";
page = 1;

View File

@ -12,8 +12,15 @@
<p>
{{ actor.name || `@${usernameWithDomain(actor)}` }}
</p>
<p class="has-text-grey" v-if="actor.name">@{{ usernameWithDomain(actor) }}</p>
<div v-if="full" class="summary" :class="{ limit: limit }" v-html="actor.summary" />
<p class="has-text-grey" v-if="actor.name">
@{{ usernameWithDomain(actor) }}
</p>
<div
v-if="full"
class="summary"
:class="{ limit: limit }"
v-html="actor.summary"
/>
</div>
</div>
</div>

View File

@ -7,7 +7,10 @@
<ul class="identities">
<li v-for="identity in identities" :key="identity.id">
<router-link
:to="{ name: 'UpdateIdentity', params: { identityName: identity.preferredUsername } }"
:to="{
name: 'UpdateIdentity',
params: { identityName: identity.preferredUsername },
}"
class="media identity"
v-bind:class="{ 'is-current-identity': isCurrentIdentity(identity) }"
>
@ -24,7 +27,10 @@
</li>
</ul>
<router-link :to="{ name: 'CreateIdentity' }" class="button create-identity is-primary">
<router-link
:to="{ name: 'CreateIdentity' }"
class="button create-identity is-primary"
>
{{ $t("Create a new identity") }}
</router-link>
</section>

View File

@ -16,11 +16,21 @@
checkable
checkbox-position="left"
>
<b-table-column field="actor.id" label="ID" width="40" numeric v-slot="props">{{
props.row.actor.id
}}</b-table-column>
<b-table-column
field="actor.id"
label="ID"
width="40"
numeric
v-slot="props"
>{{ props.row.actor.id }}</b-table-column
>
<b-table-column field="actor.type" :label="$t('Type')" width="80" v-slot="props">
<b-table-column
field="actor.type"
:label="$t('Type')"
width="80"
v-slot="props"
>
<b-icon icon="lan" v-if="RelayMixin.isInstance(props.row.actor)" />
<b-icon icon="account-circle" v-else />
</b-table-column>
@ -33,26 +43,39 @@
centered
v-slot="props"
>
<span :class="`tag ${props.row.approved ? 'is-success' : 'is-danger'}`">{{
props.row.approved ? $t("Accepted") : $t("Pending")
}}</span>
<span
:class="`tag ${props.row.approved ? 'is-success' : 'is-danger'}`"
>{{ props.row.approved ? $t("Accepted") : $t("Pending") }}</span
>
</b-table-column>
<b-table-column field="actor.domain" :label="$t('Domain')" sortable>
<template v-slot:default="props">
<a @click="toggle(props.row)" v-if="RelayMixin.isInstance(props.row.actor)">{{
props.row.actor.domain
}}</a>
<a
@click="toggle(props.row)"
v-if="RelayMixin.isInstance(props.row.actor)"
>{{ props.row.actor.domain }}</a
>
<a @click="toggle(props.row)" v-else>{{
`${props.row.actor.preferredUsername}@${props.row.actor.domain}`
}}</a>
</template>
</b-table-column>
<b-table-column field="targetActor.updatedAt" :label="$t('Date')" sortable v-slot="props">
<span :title="$options.filters.formatDateTimeString(props.row.updatedAt)">{{
formatDistanceToNow(new Date(props.row.updatedAt), { locale: $dateFnsLocale })
}}</span></b-table-column
<b-table-column
field="targetActor.updatedAt"
:label="$t('Date')"
sortable
v-slot="props"
>
<span
:title="$options.filters.formatDateTimeString(props.row.updatedAt)"
>{{
formatDistanceToNow(new Date(props.row.updatedAt), {
locale: $dateFnsLocale,
})
}}</span
></b-table-column
>
<template slot="detail" slot-scope="props">
@ -143,7 +166,11 @@ export default class Followers extends Mixins(RelayMixin) {
await this.$apollo.queries.relayFollowers.refetch();
this.checkedRows = [];
} catch (e) {
Snackbar.open({ message: e.message, type: "is-danger", position: "is-bottom" });
Snackbar.open({
message: e.message,
type: "is-danger",
position: "is-bottom",
});
}
}
@ -158,7 +185,11 @@ export default class Followers extends Mixins(RelayMixin) {
await this.$apollo.queries.relayFollowers.refetch();
this.checkedRows = [];
} catch (e) {
Snackbar.open({ message: e.message, type: "is-danger", position: "is-bottom" });
Snackbar.open({
message: e.message,
type: "is-danger",
position: "is-bottom",
});
}
}

View File

@ -1,13 +1,22 @@
<template>
<div>
<form @submit="followRelay">
<b-field :label="$t('Add an instance')" custom-class="add-relay" horizontal>
<b-field
:label="$t('Add an instance')"
custom-class="add-relay"
horizontal
>
<b-field grouped expanded size="is-large">
<p class="control">
<b-input v-model="newRelayAddress" :placeholder="$t('Ex: mobilizon.fr')" />
<b-input
v-model="newRelayAddress"
:placeholder="$t('Ex: mobilizon.fr')"
/>
</p>
<p class="control">
<b-button type="is-primary" native-type="submit">{{ $t("Add an instance") }}</b-button>
<b-button type="is-primary" native-type="submit">{{
$t("Add an instance")
}}</b-button>
</p>
</b-field>
</b-field>
@ -29,12 +38,25 @@
checkable
checkbox-position="left"
>
<b-table-column field="targetActor.id" label="ID" width="40" numeric v-slot="props">{{
props.row.targetActor.id
}}</b-table-column>
<b-table-column
field="targetActor.id"
label="ID"
width="40"
numeric
v-slot="props"
>{{ props.row.targetActor.id }}</b-table-column
>
<b-table-column field="targetActor.type" :label="$t('Type')" width="80" v-slot="props">
<b-icon icon="lan" v-if="RelayMixin.isInstance(props.row.targetActor)" />
<b-table-column
field="targetActor.type"
:label="$t('Type')"
width="80"
v-slot="props"
>
<b-icon
icon="lan"
v-if="RelayMixin.isInstance(props.row.targetActor)"
/>
<b-icon icon="account-circle" v-else />
</b-table-column>
@ -46,26 +68,39 @@
centered
v-slot="props"
>
<span :class="`tag ${props.row.approved ? 'is-success' : 'is-danger'}`">{{
props.row.approved ? $t("Accepted") : $t("Pending")
}}</span>
<span
:class="`tag ${props.row.approved ? 'is-success' : 'is-danger'}`"
>{{ props.row.approved ? $t("Accepted") : $t("Pending") }}</span
>
</b-table-column>
<b-table-column field="targetActor.domain" :label="$t('Domain')" sortable>
<template v-slot:default="props">
<a @click="toggle(props.row)" v-if="RelayMixin.isInstance(props.row.targetActor)">{{
props.row.targetActor.domain
}}</a>
<a
@click="toggle(props.row)"
v-if="RelayMixin.isInstance(props.row.targetActor)"
>{{ props.row.targetActor.domain }}</a
>
<a @click="toggle(props.row)" v-else>{{
`${props.row.targetActor.preferredUsername}@${props.row.targetActor.domain}`
}}</a>
</template>
</b-table-column>
<b-table-column field="targetActor.updatedAt" :label="$t('Date')" sortable v-slot="props">
<span :title="$options.filters.formatDateTimeString(props.row.updatedAt)">{{
formatDistanceToNow(new Date(props.row.updatedAt), { locale: $dateFnsLocale })
}}</span></b-table-column
<b-table-column
field="targetActor.updatedAt"
:label="$t('Date')"
sortable
v-slot="props"
>
<span
:title="$options.filters.formatDateTimeString(props.row.updatedAt)"
>{{
formatDistanceToNow(new Date(props.row.updatedAt), {
locale: $dateFnsLocale,
})
}}</span
></b-table-column
>
<template slot="detail" slot-scope="props">
@ -132,13 +167,19 @@ export default class Followings extends Mixins(RelayMixin) {
await this.$apollo.queries.relayFollowings.refetch();
this.newRelayAddress = "";
} catch (err) {
Snackbar.open({ message: err.message, type: "is-danger", position: "is-bottom" });
Snackbar.open({
message: err.message,
type: "is-danger",
position: "is-bottom",
});
}
}
async removeRelays(): Promise<void> {
await this.checkedRows.forEach((row: IFollower) => {
this.removeRelay(`${row.targetActor.preferredUsername}@${row.targetActor.domain}`);
this.removeRelay(
`${row.targetActor.preferredUsername}@${row.targetActor.domain}`
);
});
}
@ -153,7 +194,11 @@ export default class Followings extends Mixins(RelayMixin) {
await this.$apollo.queries.relayFollowings.refetch();
this.checkedRows = [];
} catch (e) {
Snackbar.open({ message: e.message, type: "is-danger", position: "is-bottom" });
Snackbar.open({
message: e.message,
type: "is-danger",
position: "is-bottom",
});
}
}
}

View File

@ -1,19 +1,34 @@
<template>
<li :class="{ reply: comment.inReplyToComment }">
<article class="media" :class="{ selected: commentSelected }" :id="commentId">
<article
class="media"
:class="{ selected: commentSelected }"
:id="commentId"
>
<popover-actor-card
class="media-left"
:actor="comment.actor"
:inline="true"
v-if="comment.actor"
>
<figure class="image is-48x48" v-if="!comment.deletedAt && comment.actor.avatar">
<figure
class="image is-48x48"
v-if="!comment.deletedAt && comment.actor.avatar"
>
<img class="is-rounded" :src="comment.actor.avatar.url" alt="" />
</figure>
<b-icon class="media-left" v-else size="is-large" icon="account-circle" />
<b-icon
class="media-left"
v-else
size="is-large"
icon="account-circle"
/>
</popover-actor-card>
<div v-else class="media-left">
<figure class="image is-48x48" v-if="!comment.deletedAt && comment.actor.avatar">
<figure
class="image is-48x48"
v-if="!comment.deletedAt && comment.actor.avatar"
>
<img class="is-rounded" :src="comment.actor.avatar.url" alt="" />
</figure>
<b-icon v-else size="is-large" icon="account-circle" />
@ -21,7 +36,9 @@
<div class="media-content">
<div class="content">
<span class="first-line" v-if="!comment.deletedAt">
<strong :class="{ organizer: commentFromOrganizer }">{{ comment.actor.name }}</strong>
<strong :class="{ organizer: commentFromOrganizer }">{{
comment.actor.name
}}</strong>
<small>@{{ usernameWithDomain(comment.actor) }}</small>
<a class="comment-link has-text-grey" :href="commentURL">
<small>{{
@ -54,10 +71,15 @@
<div class="load-replies" v-if="comment.totalReplies">
<p v-if="!showReplies" @click="fetchReplies">
<b-icon icon="chevron-down" /><span>{{
$tc("View a reply", comment.totalReplies, { totalReplies: comment.totalReplies })
$tc("View a reply", comment.totalReplies, {
totalReplies: comment.totalReplies,
})
}}</span>
</p>
<p v-else-if="comment.totalReplies && showReplies" @click="showReplies = false">
<p
v-else-if="comment.totalReplies && showReplies"
@click="showReplies = false"
>
<b-icon icon="chevron-up" />
<span>{{ $t("Hide replies") }}</span>
</p>
@ -86,14 +108,24 @@
</nav>
</div>
</article>
<form class="reply" @submit.prevent="replyToComment" v-if="currentActor.id" v-show="replyTo">
<form
class="reply"
@submit.prevent="replyToComment"
v-if="currentActor.id"
v-show="replyTo"
>
<article class="media reply">
<figure class="media-left" v-if="currentActor.avatar">
<p class="image is-48x48">
<img :src="currentActor.avatar.url" alt="" />
</p>
</figure>
<b-icon class="media-left" v-else size="is-large" icon="account-circle" />
<b-icon
class="media-left"
v-else
size="is-large"
icon="account-circle"
/>
<div class="media-content">
<div class="content">
<span class="first-line">
@ -102,7 +134,12 @@
</span>
<br />
<span class="editor-line">
<editor class="editor" ref="commentEditor" v-model="newComment.text" mode="comment" />
<editor
class="editor"
ref="commentEditor"
v-model="newComment.text"
mode="comment"
/>
<b-button
:disabled="newComment.text.trim().length === 0"
native-type="submit"
@ -118,7 +155,12 @@
<div class="left">
<div class="vertical-border" @click="showReplies = false" />
</div>
<transition-group name="comment-replies" v-if="showReplies" class="comment-replies" tag="ul">
<transition-group
name="comment-replies"
v-if="showReplies"
class="comment-replies"
tag="ul"
>
<comment
class="reply"
v-for="reply in comment.replies"
@ -155,7 +197,8 @@ import PopoverActorCard from "../Account/PopoverActorCard.vue";
},
},
components: {
editor: () => import(/* webpackChunkName: "editor" */ "@/components/Editor.vue"),
editor: () =>
import(/* webpackChunkName: "editor" */ "@/components/Editor.vue"),
comment: () => import(/* webpackChunkName: "comment" */ "./Comment.vue"),
PopoverActorCard,
},
@ -167,7 +210,9 @@ export default class Comment extends Vue {
// Hack because Vue only exports it's own interface.
// See https://github.com/kaorun343/vue-property-decorator/issues/257
@Ref() readonly commentEditor!: EditorComponent & { replyToComment: (comment: IComment) => void };
@Ref() readonly commentEditor!: EditorComponent & {
replyToComment: (comment: IComment) => void;
};
currentActor!: IPerson;
@ -231,7 +276,9 @@ export default class Comment extends Vue {
if (!eventData) return;
const { event } = eventData;
const { comments } = event;
const parentCommentIndex = comments.findIndex((oldComment) => oldComment.id === parentId);
const parentCommentIndex = comments.findIndex(
(oldComment) => oldComment.id === parentId
);
const parentComment = comments[parentCommentIndex];
if (!parentComment) return;
parentComment.replies = thread;
@ -303,7 +350,11 @@ export default class Comment extends Vue {
duration: 5000,
});
} catch (e) {
Snackbar.open({ message: e.message, type: "is-danger", position: "is-bottom" });
Snackbar.open({
message: e.message,
type: "is-danger",
position: "is-bottom",
});
}
}
}

View File

@ -6,9 +6,11 @@
@submit.prevent="createCommentForEvent(newComment)"
@keyup.ctrl.enter="createCommentForEvent(newComment)"
>
<b-notification v-if="isEventOrganiser && !areCommentsClosed" :closable="false">{{
$t("Comments are closed for everybody else.")
}}</b-notification>
<b-notification
v-if="isEventOrganiser && !areCommentsClosed"
:closable="false"
>{{ $t("Comments are closed for everybody else.") }}</b-notification
>
<article class="media">
<figure class="media-left">
<identity-picker-wrapper :inline="false" v-model="newComment.actor" />
@ -16,11 +18,17 @@
<div class="media-content">
<div class="field">
<p class="control">
<editor ref="commenteditor" mode="comment" v-model="newComment.text" />
<editor
ref="commenteditor"
mode="comment"
v-model="newComment.text"
/>
</p>
</div>
<div class="send-comment">
<b-button native-type="submit" type="is-primary">{{ $t("Post a comment") }}</b-button>
<b-button native-type="submit" type="is-primary">{{
$t("Post a comment")
}}</b-button>
</div>
</div>
</article>
@ -29,7 +37,12 @@
$t("The organiser has chosen to close comments.")
}}</b-notification>
<transition name="comment-empty-list" mode="out-in">
<transition-group name="comment-list" v-if="comments.length" class="comment-list" tag="ul">
<transition-group
name="comment-list"
v-if="comments.length"
class="comment-list"
tag="ul"
>
<comment
class="root-comment"
:comment="comment"
@ -76,7 +89,9 @@ import { IEvent } from "../../types/event.model";
};
},
update(data) {
return data.event.comments.map((comment: IComment) => new CommentModel(comment));
return data.event.comments.map(
(comment: IComment) => new CommentModel(comment)
);
},
skip() {
return !this.event.uuid;
@ -86,7 +101,8 @@ import { IEvent } from "../../types/event.model";
components: {
Comment,
IdentityPickerWrapper,
editor: () => import(/* webpackChunkName: "editor" */ "@/components/Editor.vue"),
editor: () =>
import(/* webpackChunkName: "editor" */ "@/components/Editor.vue"),
},
})
export default class CommentTree extends Vue {
@ -113,7 +129,9 @@ export default class CommentTree extends Vue {
variables: {
eventId: this.event.id,
text: comment.text,
inReplyToCommentId: comment.inReplyToComment ? comment.inReplyToComment.id : null,
inReplyToCommentId: comment.inReplyToComment
? comment.inReplyToComment.id
: null,
},
update: (store, { data }) => {
if (data == null) return;
@ -228,7 +246,9 @@ export default class CommentTree extends Vue {
});
if (!localData) return;
const { thread: oldReplyList } = localData;
const replies = oldReplyList.filter((reply) => reply.id !== deletedCommentId);
const replies = oldReplyList.filter(
(reply) => reply.id !== deletedCommentId
);
store.writeQuery({
query: FETCH_THREAD_REPLIES,
variables: {
@ -249,7 +269,9 @@ export default class CommentTree extends Vue {
event.comments = oldComments;
} else {
// we have deleted a thread itself
event.comments = oldComments.filter((reply) => reply.id !== deletedCommentId);
event.comments = oldComments.filter(
(reply) => reply.id !== deletedCommentId
);
}
store.writeQuery({
query: COMMENTS_THREADS,
@ -274,14 +296,18 @@ export default class CommentTree extends Vue {
.filter((comment) => comment.inReplyToComment == null)
.sort((a, b) => {
if (a.updatedAt && b.updatedAt) {
return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
return (
new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
);
}
return 0;
});
}
get filteredOrderedComments(): IComment[] {
return this.orderedComments.filter((comment) => !comment.deletedAt || comment.totalReplies > 0);
return this.orderedComments.filter(
(comment) => !comment.deletedAt || comment.totalReplies > 0
);
}
get isEventOrganiser(): boolean {

View File

@ -15,7 +15,10 @@
<span v-else class="name comment-link has-text-grey">
{{ $t("[deleted]") }}
</span>
<span class="icons" v-if="!comment.deletedAt && comment.actor.id === currentActor.id">
<span
class="icons"
v-if="!comment.deletedAt && comment.actor.id === currentActor.id"
>
<b-dropdown aria-role="list">
<b-icon slot="trigger" role="button" icon="dots-horizontal" />
@ -44,8 +47,9 @@
<div class="post-infos">
<span :title="comment.insertedAt | formatDateTimeString">
{{
formatDistanceToNow(new Date(comment.updatedAt), { locale: $dateFnsLocale }) ||
$t("Right now")
formatDistanceToNow(new Date(comment.updatedAt), {
locale: $dateFnsLocale,
}) || $t("Right now")
}}</span
>
</div>
@ -77,7 +81,9 @@
type="is-primary"
>{{ $t("Update") }}</b-button
>
<b-button native-type="button" @click="toggleEditMode">{{ $t("Cancel") }}</b-button>
<b-button native-type="button" @click="toggleEditMode">{{
$t("Cancel")
}}</b-button>
</div>
</form>
</div>
@ -95,7 +101,8 @@ import { CURRENT_ACTOR_CLIENT } from "../../graphql/actor";
currentActor: CURRENT_ACTOR_CLIENT,
},
components: {
editor: () => import(/* webpackChunkName: "editor" */ "@/components/Editor.vue"),
editor: () =>
import(/* webpackChunkName: "editor" */ "@/components/Editor.vue"),
},
})
export default class DiscussionComment extends Vue {

View File

@ -1,14 +1,23 @@
<template>
<router-link
class="discussion-minimalist-card-wrapper"
:to="{ name: RouteName.DISCUSSION, params: { slug: discussion.slug, id: discussion.id } }"
:to="{
name: RouteName.DISCUSSION,
params: { slug: discussion.slug, id: discussion.id },
}"
>
<div class="media-left">
<figure
class="image is-32x32"
v-if="discussion.lastComment.actor && discussion.lastComment.actor.avatar"
v-if="
discussion.lastComment.actor && discussion.lastComment.actor.avatar
"
>
<img class="is-rounded" :src="discussion.lastComment.actor.avatar.url" alt />
<img
class="is-rounded"
:src="discussion.lastComment.actor.avatar.url"
alt
/>
</figure>
<b-icon v-else size="is-medium" icon="account-circle" />
</div>
@ -17,15 +26,18 @@
<p class="discussion-minimalist-title">{{ discussion.title }}</p>
<span :title="actualDate | formatDateTimeString">
{{
formatDistanceToNowStrict(new Date(actualDate), { locale: $dateFnsLocale }) ||
$t("Right now")
formatDistanceToNowStrict(new Date(actualDate), {
locale: $dateFnsLocale,
}) || $t("Right now")
}}</span
>
</div>
<div class="has-text-grey" v-if="!discussion.lastComment.deletedAt">
{{ htmlTextEllipsis }}
</div>
<div v-else class="has-text-grey">{{ $t("[This comment has been deleted]") }}</div>
<div v-else class="has-text-grey">
{{ $t("[This comment has been deleted]") }}
</div>
</div>
</router-link>
</template>
@ -54,7 +66,10 @@ export default class DiscussionListItem extends Vue {
}
get actualDate(): string | Date | undefined {
if (this.discussion.updatedAt === this.discussion.insertedAt && this.discussion.lastComment) {
if (
this.discussion.updatedAt === this.discussion.insertedAt &&
this.discussion.lastComment
) {
return this.discussion.lastComment.publishedAt;
}
return this.discussion.updatedAt;
@ -83,7 +98,8 @@ export default class DiscussionListItem extends Vue {
.discussion-minimalist-title {
color: #3c376e;
font-family: "Liberation Sans", "Helvetica Neue", Roboto, Helvetica, Arial, serif;
font-family: "Liberation Sans", "Helvetica Neue", Roboto, Helvetica,
Arial, serif;
font-size: 1.25rem;
font-weight: 700;
flex: 1;

View File

@ -117,11 +117,21 @@
<b-icon icon="format-quote-close" />
</button>
<button v-if="!isBasicMode" class="menubar__button" @click="commands.undo" type="button">
<button
v-if="!isBasicMode"
class="menubar__button"
@click="commands.undo"
type="button"
>
<b-icon icon="undo" />
</button>
<button v-if="!isBasicMode" class="menubar__button" @click="commands.redo" type="button">
<button
v-if="!isBasicMode"
class="menubar__button"
@click="commands.redo"
type="button"
>
<b-icon icon="redo" />
</button>
</div>
@ -181,7 +191,9 @@
</div>
</div>
</template>
<div v-else class="suggestion-list__item is-empty">{{ $t("No profiles found") }}</div>
<div v-else class="suggestion-list__item is-empty">
{{ $t("No profiles found") }}
</div>
</div>
</div>
</template>
@ -430,7 +442,8 @@ export default class EditorComponent extends Vue {
upHandler(): void {
this.navigatedActorIndex =
(this.navigatedActorIndex + this.filteredActors.length - 1) % this.filteredActors.length;
(this.navigatedActorIndex + this.filteredActors.length - 1) %
this.filteredActors.length;
}
/**
@ -438,7 +451,8 @@ export default class EditorComponent extends Vue {
* if it's the last item, navigate to the first one
*/
downHandler(): void {
this.navigatedActorIndex = (this.navigatedActorIndex + 1) % this.filteredActors.length;
this.navigatedActorIndex =
(this.navigatedActorIndex + 1) % this.filteredActors.length;
}
enterHandler(): void {
@ -533,7 +547,10 @@ export default class EditorComponent extends Vue {
},
});
if (data.uploadMedia && data.uploadMedia.url) {
command({ src: data.uploadMedia.url, "data-media-id": data.uploadMedia.id });
command({
src: data.uploadMedia.url,
"data-media-id": data.uploadMedia.id,
});
}
} catch (error) {
console.error(error);

View File

@ -48,9 +48,14 @@ export default class Image extends Node {
}
commands({ type }: { type: NodeType }): any {
return (attrs: { [key: string]: string }) => (state: EditorState, dispatch: DispatchFn) => {
return (attrs: { [key: string]: string }) => (
state: EditorState,
dispatch: DispatchFn
) => {
const { selection }: { selection: TextSelection } = state;
const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos;
const position = selection.$cursor
? selection.$cursor.pos
: selection.$to.pos;
const node = type.create(attrs);
const transaction = state.tr.insert(position, node);
dispatch(transaction);
@ -75,7 +80,8 @@ export default class Image extends Node {
}
const images = Array.from(realEvent.dataTransfer.files).filter(
(file: any) => /image/i.test(file.type) && !/svg/i.test(file.type)
(file: any) =>
/image/i.test(file.type) && !/svg/i.test(file.type)
);
if (images.length === 0) {
@ -105,7 +111,10 @@ export default class Image extends Node {
src: data.uploadMedia.url,
"data-media-id": data.uploadMedia.id,
});
const transaction = view.state.tr.insert(coordinates.pos, node);
const transaction = view.state.tr.insert(
coordinates.pos,
node
);
view.dispatch(transaction);
});
return true;

View File

@ -21,9 +21,13 @@
</b-autocomplete>
</b-field>
<b-field v-if="isSecureContext()">
<b-button type="is-text" v-if="!gettingLocation" icon-right="target" @click="locateMe">{{
$t("Use my location")
}}</b-button>
<b-button
type="is-text"
v-if="!gettingLocation"
icon-right="target"
@click="locateMe"
>{{ $t("Use my location") }}</b-button
>
<span v-else>{{ $t("Getting location") }}</span>
</b-field>
<!--
@ -58,7 +62,8 @@ import { IConfig } from "../../types/config.model";
@Component({
components: {
"map-leaflet": () => import(/* webpackChunkName: "map" */ "@/components/Map.vue"),
"map-leaflet": () =>
import(/* webpackChunkName: "map" */ "@/components/Map.vue"),
},
apollo: {
config: CONFIG,
@ -121,7 +126,9 @@ export default class AddressAutoComplete extends Vue {
},
});
this.addressData = result.data.searchAddress.map((address: IAddress) => new Address(address));
this.addressData = result.data.searchAddress.map(
(address: IAddress) => new Address(address)
);
this.isFetching = false;
}
@ -174,7 +181,9 @@ export default class AddressAutoComplete extends Vue {
},
});
this.addressData = result.data.reverseGeocode.map((address: IAddress) => new Address(address));
this.addressData = result.data.reverseGeocode.map(
(address: IAddress) => new Address(address)
);
if (this.addressData.length > 0) {
const defaultAddress = new Address(this.addressData[0]);
this.selected = defaultAddress;
@ -197,7 +206,10 @@ export default class AddressAutoComplete extends Vue {
this.location = await AddressAutoComplete.getLocation();
this.mapDefaultZoom = 12;
this.reverseGeoCode(
new LatLng(this.location.coords.latitude, this.location.coords.longitude),
new LatLng(
this.location.coords.latitude,
this.location.coords.longitude
),
12
);
} catch (e) {

View File

@ -102,14 +102,20 @@ export default class DateTimePicker extends Vue {
}
get minTime(): Date | null {
if (this.minDatetime && this.datesAreOnSameDay(this.dateWithTime, this.minDatetime)) {
if (
this.minDatetime &&
this.datesAreOnSameDay(this.dateWithTime, this.minDatetime)
) {
return this.minDatetime;
}
return null;
}
get maxTime(): Date | null {
if (this.maxDatetime && this.datesAreOnSameDay(this.dateWithTime, this.maxDatetime)) {
if (
this.maxDatetime &&
this.datesAreOnSameDay(this.dateWithTime, this.maxDatetime)
) {
return this.maxDatetime;
}
return null;

View File

@ -1,5 +1,8 @@
<template>
<router-link class="card" :to="{ name: 'Event', params: { uuid: event.uuid } }">
<router-link
class="card"
:to="{ name: 'Event', params: { uuid: event.uuid } }"
>
<div class="card-image">
<figure
class="image is-16by9"
@ -21,14 +24,18 @@
<div class="card-content">
<div class="media">
<div class="media-left">
<date-calendar-icon v-if="!mergedOptions.hideDate" :date="event.beginsOn" />
<date-calendar-icon
v-if="!mergedOptions.hideDate"
:date="event.beginsOn"
/>
</div>
<div class="media-content">
<p class="event-title">{{ event.title }}</p>
<div class="event-subtitle" v-if="event.physicalAddress">
<!-- <p>{{ $t('By @{username}', { username: actor.preferredUsername }) }}</p>-->
<span>
{{ event.physicalAddress.description }}, {{ event.physicalAddress.locality }}
{{ event.physicalAddress.description }},
{{ event.physicalAddress.locality }}
</span>
</div>
</div>

View File

@ -18,7 +18,9 @@
</docs>
<template>
<span v-if="!endsOn">{{ beginsOn | formatDateTimeString(showStartTime) }}</span>
<span v-if="!endsOn">{{
beginsOn | formatDateTimeString(showStartTime)
}}</span>
<span v-else-if="isSameDay() && showStartTime && showEndTime">
{{
$t("On {date} from {startTime} to {endTime}", {
@ -44,7 +46,9 @@
})
}}
</span>
<span v-else-if="isSameDay()">{{ $t("On {date}", { date: formatDate(beginsOn) }) }}</span>
<span v-else-if="isSameDay()">{{
$t("On {date}", { date: formatDate(beginsOn) })
}}</span>
<span v-else-if="endsOn && showStartTime && showEndTime">
{{
$t("From the {startDate} at {startTime} to the {endDate} at {endTime}", {
@ -97,7 +101,9 @@ export default class EventFullDate extends Vue {
}
isSameDay(): boolean {
const sameDay = new Date(this.beginsOn).toDateString() === new Date(this.endsOn).toDateString();
const sameDay =
new Date(this.beginsOn).toDateString() ===
new Date(this.endsOn).toDateString();
return this.endsOn !== undefined && sameDay;
}
}

View File

@ -6,25 +6,38 @@
<div class="date-component">
<date-calendar-icon :date="participation.event.beginsOn" />
</div>
<router-link :to="{ name: RouteName.EVENT, params: { uuid: participation.event.uuid } }">
<router-link
:to="{
name: RouteName.EVENT,
params: { uuid: participation.event.uuid },
}"
>
<h3 class="title">{{ participation.event.title }}</h3>
</router-link>
</div>
<div class="participation-actor has-text-grey">
<span>
<b-icon icon="earth" v-if="participation.event.visibility === EventVisibility.PUBLIC" />
<b-icon
icon="earth"
v-if="participation.event.visibility === EventVisibility.PUBLIC"
/>
<b-icon
icon="link"
v-else-if="participation.event.visibility === EventVisibility.UNLISTED"
v-else-if="
participation.event.visibility === EventVisibility.UNLISTED
"
/>
<b-icon
icon="lock"
v-else-if="participation.event.visibility === EventVisibility.PRIVATE"
v-else-if="
participation.event.visibility === EventVisibility.PRIVATE
"
/>
</span>
<span
v-if="
participation.event.physicalAddress && participation.event.physicalAddress.locality
participation.event.physicalAddress &&
participation.event.physicalAddress.locality
"
>{{ participation.event.physicalAddress.locality }} -</span
>
@ -43,7 +56,11 @@
path="Going as {name}"
tag="span"
>
<popover-actor-card slot="name" :actor="participation.actor" :inline="true">
<popover-actor-card
slot="name"
:actor="participation.actor"
:inline="true"
>
{{ participation.actor.displayName() }}
</popover-actor-card>
<