Merge branch 'fixes' into 'master'
Fix overflow on group membership cards See merge request framasoft/mobilizon!940
This commit is contained in:
commit
5eea5e2c81
@ -2,8 +2,9 @@
|
|||||||
FROM node:16-alpine as assets
|
FROM node:16-alpine as assets
|
||||||
|
|
||||||
RUN apk add --no-cache python3 build-base libwebp-tools bash imagemagick ncurses
|
RUN apk add --no-cache python3 build-base libwebp-tools bash imagemagick ncurses
|
||||||
|
WORKDIR /build
|
||||||
COPY js .
|
COPY js .
|
||||||
|
RUN ls -a
|
||||||
RUN yarn install \
|
RUN yarn install \
|
||||||
&& yarn run build
|
&& yarn run build
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ COPY config/config.exs config/prod.exs ./config/
|
|||||||
COPY config/docker.exs ./config/runtime.exs
|
COPY config/docker.exs ./config/runtime.exs
|
||||||
COPY rel ./rel
|
COPY rel ./rel
|
||||||
COPY support ./support
|
COPY support ./support
|
||||||
COPY --from=assets ./priv/static ./priv/static
|
COPY --from=assets ./build/priv/static ./priv/static
|
||||||
|
|
||||||
RUN mix phx.digest \
|
RUN mix phx.digest \
|
||||||
&& mix release
|
&& mix release
|
||||||
|
@ -73,14 +73,14 @@
|
|||||||
"@types/vuedraggable": "^2.23.0",
|
"@types/vuedraggable": "^2.23.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
||||||
"@typescript-eslint/parser": "^4.18.0",
|
"@typescript-eslint/parser": "^4.18.0",
|
||||||
"@vue/cli-plugin-babel": "~5.0.0-beta.0",
|
"@vue/cli-plugin-babel": "~5.0.0-beta.2",
|
||||||
"@vue/cli-plugin-e2e-cypress": "~5.0.0-beta.0",
|
"@vue/cli-plugin-e2e-cypress": "~5.0.0-beta.2",
|
||||||
"@vue/cli-plugin-eslint": "~5.0.0-beta.0",
|
"@vue/cli-plugin-eslint": "~5.0.0-beta.2",
|
||||||
"@vue/cli-plugin-pwa": "~5.0.0-beta.0",
|
"@vue/cli-plugin-pwa": "~5.0.0-beta.2",
|
||||||
"@vue/cli-plugin-router": "~5.0.0-beta.0",
|
"@vue/cli-plugin-router": "~5.0.0-beta.2",
|
||||||
"@vue/cli-plugin-typescript": "~5.0.0-beta.0",
|
"@vue/cli-plugin-typescript": "~5.0.0-beta.2",
|
||||||
"@vue/cli-plugin-unit-jest": "~5.0.0-beta.0",
|
"@vue/cli-plugin-unit-jest": "~5.0.0-beta.2",
|
||||||
"@vue/cli-service": "~5.0.0-beta.0",
|
"@vue/cli-service": "~5.0.0-beta.2",
|
||||||
"@vue/eslint-config-prettier": "^6.0.0",
|
"@vue/eslint-config-prettier": "^6.0.0",
|
||||||
"@vue/eslint-config-typescript": "^7.0.0",
|
"@vue/eslint-config-typescript": "^7.0.0",
|
||||||
"@vue/test-utils": "^1.1.0",
|
"@vue/test-utils": "^1.1.0",
|
||||||
|
48
js/src/components/Account/ActorInline.vue
Normal file
48
js/src/components/Account/ActorInline.vue
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<div class="actor-inline">
|
||||||
|
<div class="actor-avatar">
|
||||||
|
<figure class="image is-24x24" v-if="actor.avatar">
|
||||||
|
<img class="is-rounded" :src="actor.avatar.url" alt="" />
|
||||||
|
</figure>
|
||||||
|
<b-icon v-else size="is-medium" icon="account-circle" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="actor-name">
|
||||||
|
<p>
|
||||||
|
{{ actor.name || `@${usernameWithDomain(actor)}` }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue, Prop } from "vue-property-decorator";
|
||||||
|
import { IActor, usernameWithDomain } from "../../types/actor";
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class ActorInline extends Vue {
|
||||||
|
@Prop({ required: true, type: Object }) actor!: IActor;
|
||||||
|
|
||||||
|
usernameWithDomain = usernameWithDomain;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
div.actor-inline {
|
||||||
|
align-items: flex-start;
|
||||||
|
display: inline-flex;
|
||||||
|
text-align: inherit;
|
||||||
|
align-items: top;
|
||||||
|
|
||||||
|
div.actor-avatar {
|
||||||
|
flex-basis: auto;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
div.actor-name {
|
||||||
|
flex-basis: auto;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -41,7 +41,7 @@
|
|||||||
></popover-actor-card
|
></popover-actor-card
|
||||||
></i18n
|
></i18n
|
||||||
>
|
>
|
||||||
<small class="has-text-grey activity-date">{{
|
<small class="has-text-grey-dark activity-date">{{
|
||||||
activity.insertedAt | formatTimeString
|
activity.insertedAt | formatTimeString
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
></popover-actor-card
|
></popover-actor-card
|
||||||
></i18n
|
></i18n
|
||||||
>
|
>
|
||||||
<small class="has-text-grey activity-date">{{
|
<small class="has-text-grey-dark activity-date">{{
|
||||||
activity.insertedAt | formatTimeString
|
activity.insertedAt | formatTimeString
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
v-for="detail in details"
|
v-for="detail in details"
|
||||||
:key="detail"
|
:key="detail"
|
||||||
tag="p"
|
tag="p"
|
||||||
class="has-text-grey"
|
class="has-text-grey-dark"
|
||||||
>
|
>
|
||||||
<popover-actor-card
|
<popover-actor-card
|
||||||
:actor="activity.author"
|
:actor="activity.author"
|
||||||
@ -63,7 +63,7 @@
|
|||||||
subjectParams.old_group_name
|
subjectParams.old_group_name
|
||||||
}}</b>
|
}}</b>
|
||||||
</i18n>
|
</i18n>
|
||||||
<small class="has-text-grey activity-date">{{
|
<small class="has-text-grey-dark activity-date">{{
|
||||||
activity.insertedAt | formatTimeString
|
activity.insertedAt | formatTimeString
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
></popover-actor-card
|
></popover-actor-card
|
||||||
></i18n
|
></i18n
|
||||||
>
|
>
|
||||||
<small class="has-text-grey activity-date">{{
|
<small class="has-text-grey-dark activity-date">{{
|
||||||
activity.insertedAt | formatTimeString
|
activity.insertedAt | formatTimeString
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
></popover-actor-card
|
></popover-actor-card
|
||||||
></i18n
|
></i18n
|
||||||
>
|
>
|
||||||
<small class="has-text-grey activity-date">{{
|
<small class="has-text-grey-dark activity-date">{{
|
||||||
activity.insertedAt | formatTimeString
|
activity.insertedAt | formatTimeString
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
></popover-actor-card
|
></popover-actor-card
|
||||||
></i18n
|
></i18n
|
||||||
>
|
>
|
||||||
<small class="has-text-grey activity-date">{{
|
<small class="has-text-grey-dark activity-date">{{
|
||||||
activity.insertedAt | formatTimeString
|
activity.insertedAt | formatTimeString
|
||||||
}}</small>
|
}}</small>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
}}</span
|
}}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="has-text-grey" v-if="!discussion.lastComment.deletedAt">
|
<div class="has-text-grey-dark" v-if="!discussion.lastComment.deletedAt">
|
||||||
{{ htmlTextEllipsis }}
|
{{ htmlTextEllipsis }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="has-text-grey">
|
<div v-else class="has-text-grey-dark">
|
||||||
{{ $t("[This comment has been deleted]") }}
|
{{ $t("[This comment has been deleted]") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -98,10 +98,9 @@ export default class DiscussionListItem extends Vue {
|
|||||||
|
|
||||||
.discussion-minimalist-title {
|
.discussion-minimalist-title {
|
||||||
color: #3c376e;
|
color: #3c376e;
|
||||||
font-family: "Liberation Sans", "Helvetica Neue", Roboto, Helvetica,
|
font-family: Roboto, Helvetica, Arial, serif;
|
||||||
Arial, serif;
|
font-size: 16px;
|
||||||
font-size: 1.25rem;
|
font-weight: 500;
|
||||||
font-weight: 700;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,9 @@ export default class GroupMemberCard extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.media-content {
|
.media-content {
|
||||||
overflow: hidden;
|
::v-deep .tags {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,20 +55,21 @@ section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.group-section-title {
|
div.group-section-title {
|
||||||
|
--title-color: $violet-2;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
background: $secondary;
|
background: $secondary;
|
||||||
color: #3a384c;
|
color: var(--title-color);
|
||||||
|
|
||||||
&.privateSection {
|
&.privateSection {
|
||||||
color: $violet-2;
|
color: $purple-3;
|
||||||
background: $purple-2;
|
background: $violet-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep & > a {
|
::v-deep & > a {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
color: $orange-3;
|
color: var(--title-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
|
@ -30,6 +30,17 @@ import { IGroup } from "@/types/actor";
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
metaInfo() {
|
||||||
|
return {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
title: this.$t("Join group {group}", {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
group: this.groupTitle,
|
||||||
|
}) as string,
|
||||||
|
};
|
||||||
|
},
|
||||||
})
|
})
|
||||||
export default class JoinGroupWithAccount extends Vue {
|
export default class JoinGroupWithAccount extends Vue {
|
||||||
@Prop({ type: String, required: true }) preferredUsername!: string;
|
@Prop({ type: String, required: true }) preferredUsername!: string;
|
||||||
@ -40,6 +51,10 @@ export default class JoinGroupWithAccount extends Vue {
|
|||||||
return this.group?.url;
|
return this.group?.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get groupTitle(): undefined | string {
|
||||||
|
return this.group?.name || this.group?.preferredUsername;
|
||||||
|
}
|
||||||
|
|
||||||
sentence = this.$t(
|
sentence = this.$t(
|
||||||
"We will redirect you to your instance in order to interact with this group"
|
"We will redirect you to your instance in order to interact with this group"
|
||||||
);
|
);
|
||||||
|
138
js/src/components/Group/ShareGroupModal.vue
Normal file
138
js/src/components/Group/ShareGroupModal.vue
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<template>
|
||||||
|
<div class="modal-card">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">{{ $t("Share this group") }}</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="modal-card-body is-flex" v-if="group">
|
||||||
|
<div class="container has-text-centered">
|
||||||
|
<b-notification
|
||||||
|
type="is-warning"
|
||||||
|
v-if="group.visibility !== GroupVisibility.PUBLIC"
|
||||||
|
:closable="false"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"This group is accessible only through it's link. Be careful where you post this link."
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</b-notification>
|
||||||
|
<b-field>
|
||||||
|
<b-input ref="groupURLInput" :value="group.url" expanded />
|
||||||
|
<p class="control">
|
||||||
|
<b-tooltip
|
||||||
|
:label="$t('URL copied to clipboard')"
|
||||||
|
:active="showCopiedTooltip"
|
||||||
|
always
|
||||||
|
type="is-success"
|
||||||
|
position="is-left"
|
||||||
|
>
|
||||||
|
<b-button
|
||||||
|
type="is-primary"
|
||||||
|
icon-right="content-paste"
|
||||||
|
native-type="button"
|
||||||
|
@click="copyURL"
|
||||||
|
@keyup.enter="copyURL"
|
||||||
|
/>
|
||||||
|
</b-tooltip>
|
||||||
|
</p>
|
||||||
|
</b-field>
|
||||||
|
<div>
|
||||||
|
<!-- <b-icon icon="mastodon" size="is-large" type="is-primary" />-->
|
||||||
|
|
||||||
|
<a :href="twitterShareUrl" target="_blank" rel="nofollow noopener"
|
||||||
|
><b-icon icon="twitter" size="is-large" type="is-primary"
|
||||||
|
/></a>
|
||||||
|
<a :href="facebookShareUrl" target="_blank" rel="nofollow noopener"
|
||||||
|
><b-icon icon="facebook" size="is-large" type="is-primary"
|
||||||
|
/></a>
|
||||||
|
<a :href="linkedInShareUrl" target="_blank" rel="nofollow noopener"
|
||||||
|
><b-icon icon="linkedin" size="is-large" type="is-primary"
|
||||||
|
/></a>
|
||||||
|
<a
|
||||||
|
:href="diasporaShareUrl"
|
||||||
|
class="diaspora"
|
||||||
|
target="_blank"
|
||||||
|
rel="nofollow noopener"
|
||||||
|
>
|
||||||
|
<span data-v-5e15e80a="" class="icon has-text-primary is-large">
|
||||||
|
<DiasporaLogo alt="diaspora-logo" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a :href="emailShareUrl" target="_blank" rel="nofollow noopener"
|
||||||
|
><b-icon icon="email" size="is-large" type="is-primary"
|
||||||
|
/></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Prop, Vue, Ref } from "vue-property-decorator";
|
||||||
|
import { GroupVisibility } from "@/types/enums";
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
import DiasporaLogo from "../../assets/diaspora-icon.svg?inline";
|
||||||
|
import { displayName, IGroup } from "@/types/actor";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
DiasporaLogo,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class ShareGroupModal extends Vue {
|
||||||
|
@Prop({ type: Object, required: true }) group!: IGroup;
|
||||||
|
|
||||||
|
@Ref("groupURLInput") readonly groupURLInput!: any;
|
||||||
|
|
||||||
|
GroupVisibility = GroupVisibility;
|
||||||
|
|
||||||
|
showCopiedTooltip = false;
|
||||||
|
|
||||||
|
get twitterShareUrl(): string {
|
||||||
|
return `https://twitter.com/intent/tweet?url=${encodeURIComponent(
|
||||||
|
this.group.url
|
||||||
|
)}&text=${displayName(this.group)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get facebookShareUrl(): string {
|
||||||
|
return `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(
|
||||||
|
this.group.url
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get linkedInShareUrl(): string {
|
||||||
|
return `https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(
|
||||||
|
this.group.url
|
||||||
|
)}&title=${displayName(this.group)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get emailShareUrl(): string {
|
||||||
|
return `mailto:?to=&body=${this.group.url}&subject=${displayName(
|
||||||
|
this.group
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get diasporaShareUrl(): string {
|
||||||
|
return `https://share.diasporafoundation.org/?title=${encodeURIComponent(
|
||||||
|
displayName(this.group)
|
||||||
|
)}&url=${encodeURIComponent(this.group.url)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
copyURL(): void {
|
||||||
|
this.groupURLInput.$refs.input.select();
|
||||||
|
document.execCommand("copy");
|
||||||
|
this.showCopiedTooltip = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showCopiedTooltip = false;
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.diaspora span svg {
|
||||||
|
height: 2rem;
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
@ -12,27 +12,38 @@ import { IMedia } from "@/types/media.model";
|
|||||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||||
import LazyImage from "../Image/LazyImage.vue";
|
import LazyImage from "../Image/LazyImage.vue";
|
||||||
|
|
||||||
|
const DEFAULT_CARD_URL = "/img/mobilizon_default_card.png";
|
||||||
|
const DEFAULT_BLURHASH = "MCHKI4El-P-U}+={R-WWoes,Iu-P=?R,xD";
|
||||||
|
const DEFAULT_WIDTH = 630;
|
||||||
|
const DEFAULT_HEIGHT = 350;
|
||||||
|
const DEFAULT_PICTURE = {
|
||||||
|
url: DEFAULT_CARD_URL,
|
||||||
|
metadata: {
|
||||||
|
width: DEFAULT_WIDTH,
|
||||||
|
height: DEFAULT_HEIGHT,
|
||||||
|
blurhash: DEFAULT_BLURHASH,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
LazyImage,
|
LazyImage,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class LazyImageWrapper extends Vue {
|
export default class LazyImageWrapper extends Vue {
|
||||||
@Prop({ required: true, default: null })
|
@Prop({ required: true })
|
||||||
picture!: IMedia | null;
|
picture!: IMedia;
|
||||||
|
|
||||||
get pictureOrDefault(): Partial<IMedia> {
|
get pictureOrDefault(): Partial<IMedia> {
|
||||||
|
if (this.picture === null) {
|
||||||
|
return DEFAULT_PICTURE;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
url:
|
url: this?.picture?.url,
|
||||||
this?.picture === null
|
|
||||||
? "/img/mobilizon_default_card.png"
|
|
||||||
: this?.picture?.url,
|
|
||||||
metadata: {
|
metadata: {
|
||||||
width: this?.picture?.metadata?.width || 630,
|
width: this?.picture?.metadata?.width,
|
||||||
height: this?.picture?.metadata?.height || 350,
|
height: this?.picture?.metadata?.height,
|
||||||
blurhash:
|
blurhash: this?.picture?.metadata?.blurhash,
|
||||||
this?.picture?.metadata?.blurhash ||
|
|
||||||
"MCHKI4El-P-U}+={R-WWoes,Iu-P=?R,xD",
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,12 @@
|
|||||||
<span @click="setIdentity(identity)">
|
<span @click="setIdentity(identity)">
|
||||||
<div class="media-left">
|
<div class="media-left">
|
||||||
<figure class="image is-32x32" v-if="identity.avatar">
|
<figure class="image is-32x32" v-if="identity.avatar">
|
||||||
<img class="is-rounded" :src="identity.avatar.url" alt />
|
<img
|
||||||
|
class="is-rounded"
|
||||||
|
loading="lazy"
|
||||||
|
:src="identity.avatar.url"
|
||||||
|
alt
|
||||||
|
/>
|
||||||
</figure>
|
</figure>
|
||||||
<b-icon v-else size="is-medium" icon="account-circle" />
|
<b-icon v-else size="is-medium" icon="account-circle" />
|
||||||
</div>
|
</div>
|
||||||
@ -133,11 +138,6 @@
|
|||||||
:to="{ name: RouteName.UPDATE_IDENTITY }"
|
:to="{ name: RouteName.UPDATE_IDENTITY }"
|
||||||
>{{ $t("My account") }}</b-navbar-item
|
>{{ $t("My account") }}</b-navbar-item
|
||||||
>
|
>
|
||||||
|
|
||||||
<!-- <b-navbar-item tag="router-link" :to="{ name: RouteName.CREATE_GROUP }">-->
|
|
||||||
<!-- {{ $t('Create group') }}-->
|
|
||||||
<!-- </b-navbar-item>-->
|
|
||||||
|
|
||||||
<b-navbar-item
|
<b-navbar-item
|
||||||
v-if="currentUser.role === ICurrentUserRole.ADMINISTRATOR"
|
v-if="currentUser.role === ICurrentUserRole.ADMINISTRATOR"
|
||||||
tag="router-link"
|
tag="router-link"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
>
|
>
|
||||||
<div class="title-info-wrapper">
|
<div class="title-info-wrapper">
|
||||||
<p class="post-minimalist-title">{{ post.title }}</p>
|
<p class="post-minimalist-title">{{ post.title }}</p>
|
||||||
<small class="has-text-grey">{{
|
<small class="has-text-grey-dark">{{
|
||||||
formatDistanceToNow(new Date(post.publishAt || post.insertedAt), {
|
formatDistanceToNow(new Date(post.publishAt || post.insertedAt), {
|
||||||
locale: $dateFnsLocale,
|
locale: $dateFnsLocale,
|
||||||
addSuffix: true,
|
addSuffix: true,
|
||||||
@ -43,10 +43,9 @@ export default class PostListItem extends Vue {
|
|||||||
|
|
||||||
.post-minimalist-title {
|
.post-minimalist-title {
|
||||||
color: #3c376e;
|
color: #3c376e;
|
||||||
font-family: "Liberation Sans", "Helvetica Neue", Roboto, Helvetica, Arial,
|
font-family: Roboto, Helvetica, Arial, serif;
|
||||||
serif;
|
font-size: 16px;
|
||||||
font-size: 1rem;
|
font-weight: 500;
|
||||||
font-weight: 700;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
<div class="title-wrapper">
|
<div class="title-wrapper">
|
||||||
<img
|
<img
|
||||||
class="favicon"
|
class="favicon"
|
||||||
|
alt=""
|
||||||
v-if="resource.metadata && resource.metadata.faviconUrl"
|
v-if="resource.metadata && resource.metadata.faviconUrl"
|
||||||
:src="resource.metadata.faviconUrl"
|
:src="resource.metadata.faviconUrl"
|
||||||
/>
|
/>
|
||||||
@ -31,7 +32,8 @@
|
|||||||
<div class="metadata-wrapper">
|
<div class="metadata-wrapper">
|
||||||
<span class="host" v-if="!inline || preview">{{ urlHostname }}</span>
|
<span class="host" v-if="!inline || preview">{{ urlHostname }}</span>
|
||||||
<span
|
<span
|
||||||
class="published-at is-hidden-mobile"
|
class="published-at"
|
||||||
|
:class="{ 'is-hidden-mobile': !inline }"
|
||||||
v-if="resource.updatedAt || resource.publishedAt"
|
v-if="resource.updatedAt || resource.publishedAt"
|
||||||
>{{
|
>{{
|
||||||
(resource.updatedAt || resource.publishedAt)
|
(resource.updatedAt || resource.publishedAt)
|
||||||
|
@ -369,10 +369,10 @@ export const JOIN_EVENT = gql`
|
|||||||
message: $message
|
message: $message
|
||||||
locale: $locale
|
locale: $locale
|
||||||
) {
|
) {
|
||||||
...ParticipantsQuery
|
...ParticipantQuery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${PARTICIPANTS_QUERY_FRAGMENT}
|
${PARTICIPANT_QUERY_FRAGMENT}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LEAVE_EVENT = gql`
|
export const LEAVE_EVENT = gql`
|
||||||
|
@ -80,10 +80,22 @@ export const GROUP_FIELDS_FRAGMENTS = gql`
|
|||||||
avatar {
|
avatar {
|
||||||
id
|
id
|
||||||
url
|
url
|
||||||
|
name
|
||||||
|
metadata {
|
||||||
|
width
|
||||||
|
height
|
||||||
|
blurhash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
banner {
|
banner {
|
||||||
id
|
id
|
||||||
url
|
url
|
||||||
|
name
|
||||||
|
metadata {
|
||||||
|
width
|
||||||
|
height
|
||||||
|
blurhash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
organizedEvents(
|
organizedEvents(
|
||||||
afterDatetime: $afterDateTime
|
afterDatetime: $afterDateTime
|
||||||
|
@ -41,6 +41,11 @@ export const POST_FRAGMENT = gql`
|
|||||||
id
|
id
|
||||||
url
|
url
|
||||||
name
|
name
|
||||||
|
metadata {
|
||||||
|
height
|
||||||
|
width
|
||||||
|
blurhash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${TAG_FRAGMENT}
|
${TAG_FRAGMENT}
|
||||||
|
@ -1043,5 +1043,9 @@
|
|||||||
"User settings": "User settings",
|
"User settings": "User settings",
|
||||||
"You changed your email or password": "You changed your email or password",
|
"You changed your email or password": "You changed your email or password",
|
||||||
"Organized by you": "Organized by you",
|
"Organized by you": "Organized by you",
|
||||||
"Move resource to the root folder": "Move resource to the root folder"
|
"Move resource to the root folder": "Move resource to the root folder",
|
||||||
|
"Share this group": "Share this group",
|
||||||
|
"This group is accessible only through it's link. Be careful where you post this link.": "This group is accessible only through it's link. Be careful where you post this link.",
|
||||||
|
"{count} members": "No members|One member|{count} members",
|
||||||
|
"Share": "Share"
|
||||||
}
|
}
|
||||||
|
@ -1134,5 +1134,9 @@
|
|||||||
"{username} was invited to {group}": "{username} a été invité à {group}",
|
"{username} was invited to {group}": "{username} a été invité à {group}",
|
||||||
"© The OpenStreetMap Contributors": "© Les Contributeur⋅ices OpenStreetMap",
|
"© The OpenStreetMap Contributors": "© Les Contributeur⋅ices OpenStreetMap",
|
||||||
"Organized by you": "Organisé par vous",
|
"Organized by you": "Organisé par vous",
|
||||||
"Move resource to the root folder": "Déplacer la resource dans le dossier racine"
|
"Move resource to the root folder": "Déplacer la resource dans le dossier racine",
|
||||||
|
"Share this group": "Partager ce groupe",
|
||||||
|
"This group is accessible only through it's link. Be careful where you post this link.": "Ce groupe est accessible uniquement à travers son lien. Faites attention où vous le diffusez.",
|
||||||
|
"{count} members": "Aucun membre|Un⋅e membre|{count} membres",
|
||||||
|
"Share": "Partager"
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,7 @@ import {
|
|||||||
} from "@/graphql/actor";
|
} from "@/graphql/actor";
|
||||||
import { FETCH_GROUP } from "@/graphql/group";
|
import { FETCH_GROUP } from "@/graphql/group";
|
||||||
import RouteName from "@/router/name";
|
import RouteName from "@/router/name";
|
||||||
import {
|
import { IActor, IGroup, IPerson, usernameWithDomain } from "@/types/actor";
|
||||||
Group,
|
|
||||||
IActor,
|
|
||||||
IGroup,
|
|
||||||
IPerson,
|
|
||||||
usernameWithDomain,
|
|
||||||
} from "@/types/actor";
|
|
||||||
import { MemberRole } from "@/types/enums";
|
import { MemberRole } from "@/types/enums";
|
||||||
import { Component, Vue } from "vue-property-decorator";
|
import { Component, Vue } from "vue-property-decorator";
|
||||||
|
|
||||||
@ -50,14 +44,14 @@ const now = new Date();
|
|||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
actorId: this.currentActor.id,
|
actorId: this.currentActor.id,
|
||||||
group: this.group.preferredUsername,
|
group: this.group?.preferredUsername,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
skip() {
|
skip() {
|
||||||
return (
|
return (
|
||||||
!this.currentActor ||
|
!this.currentActor ||
|
||||||
!this.currentActor.id ||
|
!this.currentActor.id ||
|
||||||
!this.group.preferredUsername
|
!this.group?.preferredUsername
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -65,7 +59,7 @@ const now = new Date();
|
|||||||
return (
|
return (
|
||||||
!this.currentActor ||
|
!this.currentActor ||
|
||||||
!this.currentActor.id ||
|
!this.currentActor.id ||
|
||||||
!this.group.preferredUsername
|
!this.group?.preferredUsername
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -73,7 +67,7 @@ const now = new Date();
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class GroupMixin extends Vue {
|
export default class GroupMixin extends Vue {
|
||||||
group: IGroup = new Group();
|
group!: IGroup;
|
||||||
|
|
||||||
currentActor!: IActor;
|
currentActor!: IActor;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { RouteConfig } from "vue-router";
|
import { RouteConfig } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
export enum ActorRouteName {
|
export enum ActorRouteName {
|
||||||
GROUP = "Group",
|
GROUP = "Group",
|
||||||
@ -12,14 +12,14 @@ export const actorRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/groups/create",
|
path: "/groups/create",
|
||||||
name: ActorRouteName.CREATE_GROUP,
|
name: ActorRouteName.CREATE_GROUP,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "CreateGroup" */ "@/views/Group/Create.vue"),
|
import(/* webpackChunkName: "CreateGroup" */ "@/views/Group/Create.vue"),
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/@:preferredUsername",
|
path: "/@:preferredUsername",
|
||||||
name: ActorRouteName.GROUP,
|
name: ActorRouteName.GROUP,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Group" */ "@/views/Group/Group.vue"),
|
import(/* webpackChunkName: "Group" */ "@/views/Group/Group.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
@ -27,7 +27,7 @@ export const actorRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/groups/me",
|
path: "/groups/me",
|
||||||
name: ActorRouteName.MY_GROUPS,
|
name: ActorRouteName.MY_GROUPS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "MyGroups" */ "@/views/Group/MyGroups.vue"),
|
import(/* webpackChunkName: "MyGroups" */ "@/views/Group/MyGroups.vue"),
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { RouteConfig } from "vue-router";
|
import { RouteConfig } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
export enum DiscussionRouteName {
|
export enum DiscussionRouteName {
|
||||||
DISCUSSION_LIST = "DISCUSSION_LIST",
|
DISCUSSION_LIST = "DISCUSSION_LIST",
|
||||||
@ -11,7 +11,7 @@ export const discussionRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/@:preferredUsername/discussions",
|
path: "/@:preferredUsername/discussions",
|
||||||
name: DiscussionRouteName.DISCUSSION_LIST,
|
name: DiscussionRouteName.DISCUSSION_LIST,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "DiscussionsList" */ "@/views/Discussions/DiscussionsList.vue"
|
/* webpackChunkName: "DiscussionsList" */ "@/views/Discussions/DiscussionsList.vue"
|
||||||
),
|
),
|
||||||
@ -21,7 +21,7 @@ export const discussionRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/@:preferredUsername/discussions/new",
|
path: "/@:preferredUsername/discussions/new",
|
||||||
name: DiscussionRouteName.CREATE_DISCUSSION,
|
name: DiscussionRouteName.CREATE_DISCUSSION,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "CreateDiscussion" */ "@/views/Discussions/Create.vue"
|
/* webpackChunkName: "CreateDiscussion" */ "@/views/Discussions/Create.vue"
|
||||||
),
|
),
|
||||||
@ -31,7 +31,7 @@ export const discussionRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/@:preferredUsername/c/:slug/:comment_id?",
|
path: "/@:preferredUsername/c/:slug/:comment_id?",
|
||||||
name: DiscussionRouteName.DISCUSSION,
|
name: DiscussionRouteName.DISCUSSION,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Discussion" */ "@/views/Discussions/Discussion.vue"
|
/* webpackChunkName: "Discussion" */ "@/views/Discussions/Discussion.vue"
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { RouteConfig } from "vue-router";
|
import { RouteConfig } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
export enum ErrorRouteName {
|
export enum ErrorRouteName {
|
||||||
ERROR = "Error",
|
ERROR = "Error",
|
||||||
@ -9,7 +9,7 @@ export const errorRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/error",
|
path: "/error",
|
||||||
name: ErrorRouteName.ERROR,
|
name: ErrorRouteName.ERROR,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Error" */ "../views/Error.vue"),
|
import(/* webpackChunkName: "Error" */ "../views/Error.vue"),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { RouteConfig, Route } from "vue-router";
|
import { RouteConfig, Route } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
const participations = (): Promise<EsModuleComponent> =>
|
const participations = (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "participations" */ "@/views/Event/Participants.vue"
|
/* webpackChunkName: "participations" */ "@/views/Event/Participants.vue"
|
||||||
);
|
);
|
||||||
const editEvent = (): Promise<EsModuleComponent> =>
|
const editEvent = (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "edit-event" */ "@/views/Event/Edit.vue");
|
import(/* webpackChunkName: "edit-event" */ "@/views/Event/Edit.vue");
|
||||||
const event = (): Promise<EsModuleComponent> =>
|
const event = (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "event" */ "@/views/Event/Event.vue");
|
import(/* webpackChunkName: "event" */ "@/views/Event/Event.vue");
|
||||||
const myEvents = (): Promise<EsModuleComponent> =>
|
const myEvents = (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "my-events" */ "@/views/Event/MyEvents.vue");
|
import(/* webpackChunkName: "my-events" */ "@/views/Event/MyEvents.vue");
|
||||||
|
|
||||||
export enum EventRouteName {
|
export enum EventRouteName {
|
||||||
@ -31,7 +31,7 @@ export const eventRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/events/list/:location?",
|
path: "/events/list/:location?",
|
||||||
name: EventRouteName.EVENT_LIST,
|
name: EventRouteName.EVENT_LIST,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "EventList" */ "@/views/Event/EventList.vue"),
|
import(/* webpackChunkName: "EventList" */ "@/views/Event/EventList.vue"),
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
},
|
},
|
||||||
@ -83,35 +83,35 @@ export const eventRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/events/:uuid/participate",
|
path: "/events/:uuid/participate",
|
||||||
name: EventRouteName.EVENT_PARTICIPATE_LOGGED_OUT,
|
name: EventRouteName.EVENT_PARTICIPATE_LOGGED_OUT,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../components/Participation/UnloggedParticipation.vue"),
|
import("../components/Participation/UnloggedParticipation.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/events/:uuid/participate/with-account",
|
path: "/events/:uuid/participate/with-account",
|
||||||
name: EventRouteName.EVENT_PARTICIPATE_WITH_ACCOUNT,
|
name: EventRouteName.EVENT_PARTICIPATE_WITH_ACCOUNT,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../components/Participation/ParticipationWithAccount.vue"),
|
import("../components/Participation/ParticipationWithAccount.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/events/:uuid/participate/without-account",
|
path: "/events/:uuid/participate/without-account",
|
||||||
name: EventRouteName.EVENT_PARTICIPATE_WITHOUT_ACCOUNT,
|
name: EventRouteName.EVENT_PARTICIPATE_WITHOUT_ACCOUNT,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../components/Participation/ParticipationWithoutAccount.vue"),
|
import("../components/Participation/ParticipationWithoutAccount.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/participation/email/confirm/:token",
|
path: "/participation/email/confirm/:token",
|
||||||
name: EventRouteName.EVENT_PARTICIPATE_CONFIRM,
|
name: EventRouteName.EVENT_PARTICIPATE_CONFIRM,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../components/Participation/ConfirmParticipation.vue"),
|
import("../components/Participation/ConfirmParticipation.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/tag/:tag",
|
path: "/tag/:tag",
|
||||||
name: EventRouteName.TAG,
|
name: EventRouteName.TAG,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Search" */ "@/views/Search.vue"),
|
import(/* webpackChunkName: "Search" */ "@/views/Search.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { RouteConfig, Route } from "vue-router";
|
import { RouteConfig, Route } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
export enum GroupsRouteName {
|
export enum GroupsRouteName {
|
||||||
TODO_LISTS = "TODO_LISTS",
|
TODO_LISTS = "TODO_LISTS",
|
||||||
@ -21,16 +21,16 @@ export enum GroupsRouteName {
|
|||||||
TIMELINE = "TIMELINE",
|
TIMELINE = "TIMELINE",
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceFolder = (): Promise<EsModuleComponent> =>
|
const resourceFolder = (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Resources/ResourceFolder.vue");
|
import("@/views/Resources/ResourceFolder.vue");
|
||||||
const groupEvents = (): Promise<EsModuleComponent> =>
|
const groupEvents = (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "groupEvents" */ "@/views/Event/GroupEvents.vue");
|
import(/* webpackChunkName: "groupEvents" */ "@/views/Event/GroupEvents.vue");
|
||||||
|
|
||||||
export const groupsRoutes: RouteConfig[] = [
|
export const groupsRoutes: RouteConfig[] = [
|
||||||
{
|
{
|
||||||
path: "/@:preferredUsername/todo-lists",
|
path: "/@:preferredUsername/todo-lists",
|
||||||
name: GroupsRouteName.TODO_LISTS,
|
name: GroupsRouteName.TODO_LISTS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Todos/TodoLists.vue"),
|
import("@/views/Todos/TodoLists.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
@ -38,7 +38,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/todo-lists/:id",
|
path: "/todo-lists/:id",
|
||||||
name: GroupsRouteName.TODO_LIST,
|
name: GroupsRouteName.TODO_LIST,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Todos/TodoList.vue"),
|
import("@/views/Todos/TodoList.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
@ -46,7 +46,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/todo/:todoId",
|
path: "/todo/:todoId",
|
||||||
name: GroupsRouteName.TODO,
|
name: GroupsRouteName.TODO,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Todos/Todo.vue"),
|
import("@/views/Todos/Todo.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
@ -67,7 +67,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/@:preferredUsername/settings",
|
path: "/@:preferredUsername/settings",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Group/Settings.vue"),
|
import("@/views/Group/Settings.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
@ -77,20 +77,20 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "public",
|
path: "public",
|
||||||
name: GroupsRouteName.GROUP_PUBLIC_SETTINGS,
|
name: GroupsRouteName.GROUP_PUBLIC_SETTINGS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../views/Group/GroupSettings.vue"),
|
import("../views/Group/GroupSettings.vue"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "members",
|
path: "members",
|
||||||
name: GroupsRouteName.GROUP_MEMBERS_SETTINGS,
|
name: GroupsRouteName.GROUP_MEMBERS_SETTINGS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../views/Group/GroupMembers.vue"),
|
import("../views/Group/GroupMembers.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "followers",
|
path: "followers",
|
||||||
name: GroupsRouteName.GROUP_FOLLOWERS_SETTINGS,
|
name: GroupsRouteName.GROUP_FOLLOWERS_SETTINGS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("../views/Group/GroupFollowers.vue"),
|
import("../views/Group/GroupFollowers.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
},
|
},
|
||||||
@ -98,7 +98,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/@:preferredUsername/p/new",
|
path: "/@:preferredUsername/p/new",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Posts/Edit.vue"),
|
import("@/views/Posts/Edit.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
name: GroupsRouteName.POST_CREATE,
|
name: GroupsRouteName.POST_CREATE,
|
||||||
@ -106,7 +106,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/p/:slug/edit",
|
path: "/p/:slug/edit",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Posts/Edit.vue"),
|
import("@/views/Posts/Edit.vue"),
|
||||||
props: (route: Route): Record<string, unknown> => ({
|
props: (route: Route): Record<string, unknown> => ({
|
||||||
...route.params,
|
...route.params,
|
||||||
@ -117,7 +117,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/p/:slug",
|
path: "/p/:slug",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Posts/Post.vue"),
|
import("@/views/Posts/Post.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
name: GroupsRouteName.POST,
|
name: GroupsRouteName.POST,
|
||||||
@ -125,7 +125,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/@:preferredUsername/p",
|
path: "/@:preferredUsername/p",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Posts/List.vue"),
|
import("@/views/Posts/List.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
name: GroupsRouteName.POSTS,
|
name: GroupsRouteName.POSTS,
|
||||||
@ -140,7 +140,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/@:preferredUsername/join",
|
path: "/@:preferredUsername/join",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/components/Group/JoinGroupWithAccount.vue"),
|
import("@/components/Group/JoinGroupWithAccount.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
name: GroupsRouteName.GROUP_JOIN,
|
name: GroupsRouteName.GROUP_JOIN,
|
||||||
@ -149,7 +149,7 @@ export const groupsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/@:preferredUsername/timeline",
|
path: "/@:preferredUsername/timeline",
|
||||||
name: GroupsRouteName.TIMELINE,
|
name: GroupsRouteName.TIMELINE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import("@/views/Group/Timeline.vue"),
|
import("@/views/Group/Timeline.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
|
@ -2,7 +2,7 @@ import Vue from "vue";
|
|||||||
import Router, { Route } from "vue-router";
|
import Router, { Route } from "vue-router";
|
||||||
import VueScrollTo from "vue-scrollto";
|
import VueScrollTo from "vue-scrollto";
|
||||||
import { PositionResult } from "vue-router/types/router.d";
|
import { PositionResult } from "vue-router/types/router.d";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
import Home from "../views/Home.vue";
|
import Home from "../views/Home.vue";
|
||||||
import { eventRoutes } from "./event";
|
import { eventRoutes } from "./event";
|
||||||
import { actorRoutes } from "./actor";
|
import { actorRoutes } from "./actor";
|
||||||
@ -46,7 +46,7 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "/search",
|
path: "/search",
|
||||||
name: RouteName.SEARCH,
|
name: RouteName.SEARCH,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Search" */ "@/views/Search.vue"),
|
import(/* webpackChunkName: "Search" */ "@/views/Search.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
@ -60,7 +60,7 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "/about",
|
path: "/about",
|
||||||
name: RouteName.ABOUT,
|
name: RouteName.ABOUT,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "about" */ "@/views/About.vue"),
|
import(/* webpackChunkName: "about" */ "@/views/About.vue"),
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
redirect: { name: RouteName.ABOUT_INSTANCE },
|
redirect: { name: RouteName.ABOUT_INSTANCE },
|
||||||
@ -68,7 +68,7 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "instance",
|
path: "instance",
|
||||||
name: RouteName.ABOUT_INSTANCE,
|
name: RouteName.ABOUT_INSTANCE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "about" */ "@/views/About/AboutInstance.vue"
|
/* webpackChunkName: "about" */ "@/views/About/AboutInstance.vue"
|
||||||
),
|
),
|
||||||
@ -76,28 +76,28 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "/terms",
|
path: "/terms",
|
||||||
name: RouteName.TERMS,
|
name: RouteName.TERMS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "cookies" */ "@/views/About/Terms.vue"),
|
import(/* webpackChunkName: "cookies" */ "@/views/About/Terms.vue"),
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/privacy",
|
path: "/privacy",
|
||||||
name: RouteName.PRIVACY,
|
name: RouteName.PRIVACY,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "cookies" */ "@/views/About/Privacy.vue"),
|
import(/* webpackChunkName: "cookies" */ "@/views/About/Privacy.vue"),
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/rules",
|
path: "/rules",
|
||||||
name: RouteName.RULES,
|
name: RouteName.RULES,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "cookies" */ "@/views/About/Rules.vue"),
|
import(/* webpackChunkName: "cookies" */ "@/views/About/Rules.vue"),
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/glossary",
|
path: "/glossary",
|
||||||
name: RouteName.GLOSSARY,
|
name: RouteName.GLOSSARY,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "cookies" */ "@/views/About/Glossary.vue"
|
/* webpackChunkName: "cookies" */ "@/views/About/Glossary.vue"
|
||||||
),
|
),
|
||||||
@ -108,14 +108,14 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "/interact",
|
path: "/interact",
|
||||||
name: RouteName.INTERACT,
|
name: RouteName.INTERACT,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "interact" */ "@/views/Interact.vue"),
|
import(/* webpackChunkName: "interact" */ "@/views/Interact.vue"),
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/auth/:provider/callback",
|
path: "/auth/:provider/callback",
|
||||||
name: "auth-callback",
|
name: "auth-callback",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "ProviderValidation" */ "@/views/User/ProviderValidation.vue"
|
/* webpackChunkName: "ProviderValidation" */ "@/views/User/ProviderValidation.vue"
|
||||||
),
|
),
|
||||||
@ -123,7 +123,7 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "/welcome/:step?",
|
path: "/welcome/:step?",
|
||||||
name: RouteName.WELCOME_SCREEN,
|
name: RouteName.WELCOME_SCREEN,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "WelcomeScreen" */ "@/views/User/SettingsOnboard.vue"
|
/* webpackChunkName: "WelcomeScreen" */ "@/views/User/SettingsOnboard.vue"
|
||||||
),
|
),
|
||||||
@ -139,7 +139,7 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: "/404",
|
path: "/404",
|
||||||
name: RouteName.PAGE_NOT_FOUND,
|
name: RouteName.PAGE_NOT_FOUND,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "PageNotFound" */ "../views/PageNotFound.vue"
|
/* webpackChunkName: "PageNotFound" */ "../views/PageNotFound.vue"
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Route, RouteConfig } from "vue-router";
|
import { Route, RouteConfig } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
export enum SettingsRouteName {
|
export enum SettingsRouteName {
|
||||||
SETTINGS = "SETTINGS",
|
SETTINGS = "SETTINGS",
|
||||||
@ -31,7 +31,7 @@ export enum SettingsRouteName {
|
|||||||
export const settingsRoutes: RouteConfig[] = [
|
export const settingsRoutes: RouteConfig[] = [
|
||||||
{
|
{
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Settings" */ "@/views/Settings.vue"),
|
import(/* webpackChunkName: "Settings" */ "@/views/Settings.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
@ -47,7 +47,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "account/general",
|
path: "account/general",
|
||||||
name: SettingsRouteName.ACCOUNT_SETTINGS_GENERAL,
|
name: SettingsRouteName.ACCOUNT_SETTINGS_GENERAL,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "AccountSettings" */ "@/views/Settings/AccountSettings.vue"
|
/* webpackChunkName: "AccountSettings" */ "@/views/Settings/AccountSettings.vue"
|
||||||
),
|
),
|
||||||
@ -57,7 +57,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "preferences",
|
path: "preferences",
|
||||||
name: SettingsRouteName.PREFERENCES,
|
name: SettingsRouteName.PREFERENCES,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Preferences" */ "@/views/Settings/Preferences.vue"
|
/* webpackChunkName: "Preferences" */ "@/views/Settings/Preferences.vue"
|
||||||
),
|
),
|
||||||
@ -67,7 +67,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "notifications",
|
path: "notifications",
|
||||||
name: SettingsRouteName.NOTIFICATIONS,
|
name: SettingsRouteName.NOTIFICATIONS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Notifications" */ "@/views/Settings/Notifications.vue"
|
/* webpackChunkName: "Notifications" */ "@/views/Settings/Notifications.vue"
|
||||||
),
|
),
|
||||||
@ -83,7 +83,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/dashboard",
|
path: "admin/dashboard",
|
||||||
name: SettingsRouteName.ADMIN_DASHBOARD,
|
name: SettingsRouteName.ADMIN_DASHBOARD,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Dashboard" */ "@/views/Admin/Dashboard.vue"
|
/* webpackChunkName: "Dashboard" */ "@/views/Admin/Dashboard.vue"
|
||||||
),
|
),
|
||||||
@ -92,7 +92,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/settings",
|
path: "admin/settings",
|
||||||
name: SettingsRouteName.ADMIN_SETTINGS,
|
name: SettingsRouteName.ADMIN_SETTINGS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "AdminSettings" */ "@/views/Admin/Settings.vue"
|
/* webpackChunkName: "AdminSettings" */ "@/views/Admin/Settings.vue"
|
||||||
),
|
),
|
||||||
@ -102,7 +102,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/users",
|
path: "admin/users",
|
||||||
name: SettingsRouteName.USERS,
|
name: SettingsRouteName.USERS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Users" */ "@/views/Admin/Users.vue"),
|
import(/* webpackChunkName: "Users" */ "@/views/Admin/Users.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
@ -110,7 +110,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/users/:id",
|
path: "admin/users/:id",
|
||||||
name: SettingsRouteName.ADMIN_USER_PROFILE,
|
name: SettingsRouteName.ADMIN_USER_PROFILE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "AdminUserProfile" */ "@/views/Admin/AdminUserProfile.vue"
|
/* webpackChunkName: "AdminUserProfile" */ "@/views/Admin/AdminUserProfile.vue"
|
||||||
),
|
),
|
||||||
@ -120,7 +120,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/profiles",
|
path: "admin/profiles",
|
||||||
name: SettingsRouteName.PROFILES,
|
name: SettingsRouteName.PROFILES,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "AdminProfiles" */ "@/views/Admin/Profiles.vue"
|
/* webpackChunkName: "AdminProfiles" */ "@/views/Admin/Profiles.vue"
|
||||||
),
|
),
|
||||||
@ -130,7 +130,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/profiles/:id",
|
path: "admin/profiles/:id",
|
||||||
name: SettingsRouteName.ADMIN_PROFILE,
|
name: SettingsRouteName.ADMIN_PROFILE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "AdminProfile" */ "@/views/Admin/AdminProfile.vue"
|
/* webpackChunkName: "AdminProfile" */ "@/views/Admin/AdminProfile.vue"
|
||||||
),
|
),
|
||||||
@ -140,7 +140,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/groups",
|
path: "admin/groups",
|
||||||
name: SettingsRouteName.ADMIN_GROUPS,
|
name: SettingsRouteName.ADMIN_GROUPS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "GroupProfiles" */ "@/views/Admin/GroupProfiles.vue"
|
/* webpackChunkName: "GroupProfiles" */ "@/views/Admin/GroupProfiles.vue"
|
||||||
),
|
),
|
||||||
@ -150,7 +150,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "admin/groups/:id",
|
path: "admin/groups/:id",
|
||||||
name: SettingsRouteName.ADMIN_GROUP_PROFILE,
|
name: SettingsRouteName.ADMIN_GROUP_PROFILE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "AdminGroupProfile" */ "@/views/Admin/AdminGroupProfile.vue"
|
/* webpackChunkName: "AdminGroupProfile" */ "@/views/Admin/AdminGroupProfile.vue"
|
||||||
),
|
),
|
||||||
@ -161,14 +161,14 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
path: "admin/relays",
|
path: "admin/relays",
|
||||||
name: SettingsRouteName.RELAYS,
|
name: SettingsRouteName.RELAYS,
|
||||||
redirect: { name: SettingsRouteName.RELAY_FOLLOWINGS },
|
redirect: { name: SettingsRouteName.RELAY_FOLLOWINGS },
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Follows" */ "@/views/Admin/Follows.vue"),
|
import(/* webpackChunkName: "Follows" */ "@/views/Admin/Follows.vue"),
|
||||||
meta: { requiredAuth: true },
|
meta: { requiredAuth: true },
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "followings",
|
path: "followings",
|
||||||
name: SettingsRouteName.RELAY_FOLLOWINGS,
|
name: SettingsRouteName.RELAY_FOLLOWINGS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Followings" */ "@/components/Admin/Followings.vue"
|
/* webpackChunkName: "Followings" */ "@/components/Admin/Followings.vue"
|
||||||
),
|
),
|
||||||
@ -177,7 +177,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "followers",
|
path: "followers",
|
||||||
name: SettingsRouteName.RELAY_FOLLOWERS,
|
name: SettingsRouteName.RELAY_FOLLOWERS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Followers" */ "@/components/Admin/Followers.vue"
|
/* webpackChunkName: "Followers" */ "@/components/Admin/Followers.vue"
|
||||||
),
|
),
|
||||||
@ -195,7 +195,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/moderation/reports/:filter?",
|
path: "/moderation/reports/:filter?",
|
||||||
name: SettingsRouteName.REPORTS,
|
name: SettingsRouteName.REPORTS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "ReportList" */ "@/views/Moderation/ReportList.vue"
|
/* webpackChunkName: "ReportList" */ "@/views/Moderation/ReportList.vue"
|
||||||
),
|
),
|
||||||
@ -205,7 +205,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/moderation/report/:reportId",
|
path: "/moderation/report/:reportId",
|
||||||
name: SettingsRouteName.REPORT,
|
name: SettingsRouteName.REPORT,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "Report" */ "@/views/Moderation/Report.vue"
|
/* webpackChunkName: "Report" */ "@/views/Moderation/Report.vue"
|
||||||
),
|
),
|
||||||
@ -215,7 +215,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/moderation/logs",
|
path: "/moderation/logs",
|
||||||
name: SettingsRouteName.REPORT_LOGS,
|
name: SettingsRouteName.REPORT_LOGS,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "ModerationLogs" */ "@/views/Moderation/Logs.vue"
|
/* webpackChunkName: "ModerationLogs" */ "@/views/Moderation/Logs.vue"
|
||||||
),
|
),
|
||||||
@ -231,7 +231,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/identity/create",
|
path: "/identity/create",
|
||||||
name: SettingsRouteName.CREATE_IDENTITY,
|
name: SettingsRouteName.CREATE_IDENTITY,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue"
|
/* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue"
|
||||||
),
|
),
|
||||||
@ -244,7 +244,7 @@ export const settingsRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/identity/update/:identityName?",
|
path: "/identity/update/:identityName?",
|
||||||
name: SettingsRouteName.UPDATE_IDENTITY,
|
name: SettingsRouteName.UPDATE_IDENTITY,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue"
|
/* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue"
|
||||||
),
|
),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { beforeRegisterGuard } from "@/router/guards/register-guard";
|
import { beforeRegisterGuard } from "@/router/guards/register-guard";
|
||||||
import { Route, RouteConfig } from "vue-router";
|
import { Route, RouteConfig } from "vue-router";
|
||||||
import { EsModuleComponent } from "vue/types/options";
|
import { ImportedComponent } from "vue/types/options";
|
||||||
|
|
||||||
export enum UserRouteName {
|
export enum UserRouteName {
|
||||||
REGISTER = "Register",
|
REGISTER = "Register",
|
||||||
@ -17,7 +17,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/register/user",
|
path: "/register/user",
|
||||||
name: UserRouteName.REGISTER,
|
name: UserRouteName.REGISTER,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "RegisterUser" */ "@/views/User/Register.vue"
|
/* webpackChunkName: "RegisterUser" */ "@/views/User/Register.vue"
|
||||||
),
|
),
|
||||||
@ -28,7 +28,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/register/profile",
|
path: "/register/profile",
|
||||||
name: UserRouteName.REGISTER_PROFILE,
|
name: UserRouteName.REGISTER_PROFILE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"
|
/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"
|
||||||
),
|
),
|
||||||
@ -42,7 +42,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/resend-instructions",
|
path: "/resend-instructions",
|
||||||
name: UserRouteName.RESEND_CONFIRMATION,
|
name: UserRouteName.RESEND_CONFIRMATION,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "ResendConfirmation" */ "@/views/User/ResendConfirmation.vue"
|
/* webpackChunkName: "ResendConfirmation" */ "@/views/User/ResendConfirmation.vue"
|
||||||
),
|
),
|
||||||
@ -52,7 +52,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/password-reset/send",
|
path: "/password-reset/send",
|
||||||
name: UserRouteName.SEND_PASSWORD_RESET,
|
name: UserRouteName.SEND_PASSWORD_RESET,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "SendPasswordReset" */ "@/views/User/SendPasswordReset.vue"
|
/* webpackChunkName: "SendPasswordReset" */ "@/views/User/SendPasswordReset.vue"
|
||||||
),
|
),
|
||||||
@ -62,7 +62,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/password-reset/:token",
|
path: "/password-reset/:token",
|
||||||
name: UserRouteName.PASSWORD_RESET,
|
name: UserRouteName.PASSWORD_RESET,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "PasswordReset" */ "@/views/User/PasswordReset.vue"
|
/* webpackChunkName: "PasswordReset" */ "@/views/User/PasswordReset.vue"
|
||||||
),
|
),
|
||||||
@ -72,7 +72,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/validate/email/:token",
|
path: "/validate/email/:token",
|
||||||
name: UserRouteName.EMAIL_VALIDATE,
|
name: UserRouteName.EMAIL_VALIDATE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "EmailValidate" */ "@/views/User/EmailValidate.vue"
|
/* webpackChunkName: "EmailValidate" */ "@/views/User/EmailValidate.vue"
|
||||||
),
|
),
|
||||||
@ -82,7 +82,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/validate/:token",
|
path: "/validate/:token",
|
||||||
name: UserRouteName.VALIDATE,
|
name: UserRouteName.VALIDATE,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Validate" */ "@/views/User/Validate.vue"),
|
import(/* webpackChunkName: "Validate" */ "@/views/User/Validate.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiresAuth: false },
|
meta: { requiresAuth: false },
|
||||||
@ -90,7 +90,7 @@ export const userRoutes: RouteConfig[] = [
|
|||||||
{
|
{
|
||||||
path: "/login",
|
path: "/login",
|
||||||
name: UserRouteName.LOGIN,
|
name: UserRouteName.LOGIN,
|
||||||
component: (): Promise<EsModuleComponent> =>
|
component: (): Promise<ImportedComponent> =>
|
||||||
import(/* webpackChunkName: "Login" */ "@/views/User/Login.vue"),
|
import(/* webpackChunkName: "Login" */ "@/views/User/Login.vue"),
|
||||||
props: true,
|
props: true,
|
||||||
meta: { requiredAuth: false },
|
meta: { requiredAuth: false },
|
||||||
|
@ -57,7 +57,8 @@ export class Actor implements IActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function usernameWithDomain(actor: IActor, force = false): string {
|
export function usernameWithDomain(actor: IActor, force = false): string {
|
||||||
if (actor.domain) {
|
if (!actor) return "";
|
||||||
|
if (actor?.domain) {
|
||||||
return `${actor.preferredUsername}@${actor.domain}`;
|
return `${actor.preferredUsername}@${actor.domain}`;
|
||||||
}
|
}
|
||||||
if (force) {
|
if (force) {
|
||||||
|
@ -7,7 +7,7 @@ import type { IDiscussion } from "../discussions";
|
|||||||
import type { IPost } from "../post.model";
|
import type { IPost } from "../post.model";
|
||||||
import type { IAddress } from "../address.model";
|
import type { IAddress } from "../address.model";
|
||||||
import { Address } from "../address.model";
|
import { Address } from "../address.model";
|
||||||
import { ActorType, Openness } from "../enums";
|
import { ActorType, GroupVisibility, Openness } from "../enums";
|
||||||
import type { IMember } from "./member.model";
|
import type { IMember } from "./member.model";
|
||||||
import type { ITodoList } from "../todolist";
|
import type { ITodoList } from "../todolist";
|
||||||
import { IActivity } from "../activity.model";
|
import { IActivity } from "../activity.model";
|
||||||
@ -20,6 +20,7 @@ export interface IGroup extends IActor {
|
|||||||
organizedEvents: Paginate<IEvent>;
|
organizedEvents: Paginate<IEvent>;
|
||||||
physicalAddress: IAddress;
|
physicalAddress: IAddress;
|
||||||
openness: Openness;
|
openness: Openness;
|
||||||
|
visibility: GroupVisibility;
|
||||||
manuallyApprovesFollowers: boolean;
|
manuallyApprovesFollowers: boolean;
|
||||||
activity: Paginate<IActivity>;
|
activity: Paginate<IActivity>;
|
||||||
}
|
}
|
||||||
@ -43,6 +44,7 @@ export class Group extends Actor implements IGroup {
|
|||||||
|
|
||||||
this.patch(hash);
|
this.patch(hash);
|
||||||
}
|
}
|
||||||
|
visibility: GroupVisibility = GroupVisibility.PUBLIC;
|
||||||
activity: Paginate<IActivity> = { elements: [], total: 0 };
|
activity: Paginate<IActivity> = { elements: [], total: 0 };
|
||||||
|
|
||||||
openness: Openness = Openness.INVITE_ONLY;
|
openness: Openness = Openness.INVITE_ONLY;
|
||||||
|
@ -1443,8 +1443,9 @@ div.sidebar {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
.media-content {
|
.media-content {
|
||||||
width: calc(100% - 32px - 1rem);
|
width: calc(100% - 32px - 1rem);
|
||||||
|
max-width: 80vw;
|
||||||
|
|
||||||
p.has-text-grey {
|
p.has-text-grey-dark {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ const EVENTS_PAGE_LIMIT = 10;
|
|||||||
const { group } = this;
|
const { group } = this;
|
||||||
return {
|
return {
|
||||||
title: this.$t("{group} events", {
|
title: this.$t("{group} events", {
|
||||||
group: group.name || usernameWithDomain(group),
|
group: group?.name || usernameWithDomain(group),
|
||||||
}) as string,
|
}) as string,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,11 +4,12 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<router-link
|
<router-link
|
||||||
|
v-if="group"
|
||||||
:to="{
|
:to="{
|
||||||
name: RouteName.GROUP,
|
name: RouteName.GROUP,
|
||||||
params: { preferredUsername: usernameWithDomain(group) },
|
params: { preferredUsername: usernameWithDomain(group) },
|
||||||
}"
|
}"
|
||||||
>{{ group.name }}</router-link
|
>{{ group.name || usernameWithDomain(group) }}</router-link
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -37,10 +38,10 @@
|
|||||||
>
|
>
|
||||||
<form @submit.prevent="updateGroup">
|
<form @submit.prevent="updateGroup">
|
||||||
<b-field :label="$t('Group name')">
|
<b-field :label="$t('Group name')">
|
||||||
<b-input v-model="group.name" />
|
<b-input v-model="editableGroup.name" />
|
||||||
</b-field>
|
</b-field>
|
||||||
<b-field :label="$t('Group short description')">
|
<b-field :label="$t('Group short description')">
|
||||||
<editor mode="basic" v-model="group.summary" :maxSize="500"
|
<editor mode="basic" v-model="editableGroup.summary" :maxSize="500"
|
||||||
/></b-field>
|
/></b-field>
|
||||||
<b-field :label="$t('Avatar')">
|
<b-field :label="$t('Avatar')">
|
||||||
<picture-upload
|
<picture-upload
|
||||||
@ -62,7 +63,7 @@
|
|||||||
<p class="label">{{ $t("Group visibility") }}</p>
|
<p class="label">{{ $t("Group visibility") }}</p>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="group.visibility"
|
v-model="editableGroup.visibility"
|
||||||
name="groupVisibility"
|
name="groupVisibility"
|
||||||
:native-value="GroupVisibility.PUBLIC"
|
:native-value="GroupVisibility.PUBLIC"
|
||||||
>
|
>
|
||||||
@ -76,9 +77,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="group.visibility"
|
v-model="editableGroup.visibility"
|
||||||
name="groupVisibility"
|
name="groupVisibility"
|
||||||
:native-value="GroupVisibility.PRIVATE"
|
:native-value="GroupVisibility.UNLISTED"
|
||||||
>{{ $t("Only accessible through link") }}<br />
|
>{{ $t("Only accessible through link") }}<br />
|
||||||
<small>{{
|
<small>{{
|
||||||
$t(
|
$t(
|
||||||
@ -110,7 +111,7 @@
|
|||||||
<p class="label">{{ $t("New members") }}</p>
|
<p class="label">{{ $t("New members") }}</p>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="group.openness"
|
v-model="editableGroup.openness"
|
||||||
name="groupOpenness"
|
name="groupOpenness"
|
||||||
:native-value="Openness.OPEN"
|
:native-value="Openness.OPEN"
|
||||||
>
|
>
|
||||||
@ -124,7 +125,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="group.openness"
|
v-model="editableGroup.openness"
|
||||||
name="groupOpenness"
|
name="groupOpenness"
|
||||||
:native-value="Openness.INVITE_ONLY"
|
:native-value="Openness.INVITE_ONLY"
|
||||||
>{{ $t("Manually invite new members") }}<br />
|
>{{ $t("Manually invite new members") }}<br />
|
||||||
@ -140,14 +141,14 @@
|
|||||||
:label="$t('Followers')"
|
:label="$t('Followers')"
|
||||||
:message="$t('Followers will receive new public events and posts.')"
|
:message="$t('Followers will receive new public events and posts.')"
|
||||||
>
|
>
|
||||||
<b-checkbox v-model="group.manuallyApprovesFollowers">
|
<b-checkbox v-model="editableGroup.manuallyApprovesFollowers">
|
||||||
{{ $t("Manually approve new followers") }}
|
{{ $t("Manually approve new followers") }}
|
||||||
</b-checkbox>
|
</b-checkbox>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<full-address-auto-complete
|
<full-address-auto-complete
|
||||||
:label="$t('Group address')"
|
:label="$t('Group address')"
|
||||||
v-model="group.physicalAddress"
|
v-model="editableGroup.physicalAddress"
|
||||||
:value="currentAddress"
|
:value="currentAddress"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -171,14 +172,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component } from "vue-property-decorator";
|
import { Component, Watch } from "vue-property-decorator";
|
||||||
import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue";
|
import FullAddressAutoComplete from "@/components/Event/FullAddressAutoComplete.vue";
|
||||||
import { Route } from "vue-router";
|
import { Route } from "vue-router";
|
||||||
import PictureUpload from "@/components/PictureUpload.vue";
|
import PictureUpload from "@/components/PictureUpload.vue";
|
||||||
import { mixins } from "vue-class-component";
|
import { mixins } from "vue-class-component";
|
||||||
import GroupMixin from "@/mixins/group";
|
import GroupMixin from "@/mixins/group";
|
||||||
import { GroupVisibility, Openness } from "@/types/enums";
|
import { GroupVisibility, Openness } from "@/types/enums";
|
||||||
import RouteName from "../../router/name";
|
|
||||||
import { UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group";
|
import { UPDATE_GROUP, DELETE_GROUP } from "../../graphql/group";
|
||||||
import { IGroup, usernameWithDomain } from "../../types/actor";
|
import { IGroup, usernameWithDomain } from "../../types/actor";
|
||||||
import { Address, IAddress } from "../../types/address.model";
|
import { Address, IAddress } from "../../types/address.model";
|
||||||
@ -186,6 +186,8 @@ import { CONFIG } from "@/graphql/config";
|
|||||||
import { IConfig } from "@/types/config.model";
|
import { IConfig } from "@/types/config.model";
|
||||||
import { ServerParseError } from "@apollo/client/link/http";
|
import { ServerParseError } from "@apollo/client/link/http";
|
||||||
import { ErrorResponse } from "@apollo/client/link/error";
|
import { ErrorResponse } from "@apollo/client/link/error";
|
||||||
|
import RouteName from "@/router/name";
|
||||||
|
import { buildFileFromIMedia } from "@/utils/image";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
@ -225,9 +227,12 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
|||||||
|
|
||||||
showCopiedTooltip = false;
|
showCopiedTooltip = false;
|
||||||
|
|
||||||
|
editableGroup!: IGroup;
|
||||||
|
|
||||||
async updateGroup(): Promise<void> {
|
async updateGroup(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const variables = this.buildVariables();
|
const variables = this.buildVariables();
|
||||||
|
console.log(variables);
|
||||||
await this.$apollo.mutate<{ updateGroup: IGroup }>({
|
await this.$apollo.mutate<{ updateGroup: IGroup }>({
|
||||||
mutation: UPDATE_GROUP,
|
mutation: UPDATE_GROUP,
|
||||||
variables,
|
variables,
|
||||||
@ -270,18 +275,38 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Watch("group")
|
||||||
|
async watchUpdateGroup(oldGroup: IGroup, newGroup: IGroup): Promise<void> {
|
||||||
|
if (
|
||||||
|
oldGroup?.avatar !== undefined &&
|
||||||
|
oldGroup?.avatar !== newGroup?.avatar
|
||||||
|
) {
|
||||||
|
this.avatarFile = await buildFileFromIMedia(this.group.avatar);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
oldGroup?.banner !== undefined &&
|
||||||
|
oldGroup?.banner !== newGroup?.banner
|
||||||
|
) {
|
||||||
|
this.bannerFile = await buildFileFromIMedia(this.group.banner);
|
||||||
|
}
|
||||||
|
this.editableGroup = { ...this.group };
|
||||||
|
}
|
||||||
|
|
||||||
private buildVariables() {
|
private buildVariables() {
|
||||||
let avatarObj = {};
|
let avatarObj = {};
|
||||||
let bannerObj = {};
|
let bannerObj = {};
|
||||||
const variables = { ...this.group };
|
const variables = { ...this.editableGroup };
|
||||||
|
const physicalAddress = {
|
||||||
|
...variables.physicalAddress,
|
||||||
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
delete variables.__typename;
|
delete variables.__typename;
|
||||||
if (variables.physicalAddress) {
|
if (physicalAddress) {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
delete variables.physicalAddress.__typename;
|
delete physicalAddress.__typename;
|
||||||
}
|
}
|
||||||
delete variables.avatar;
|
delete variables.avatar;
|
||||||
delete variables.banner;
|
delete variables.banner;
|
||||||
@ -291,7 +316,7 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
|||||||
avatar: {
|
avatar: {
|
||||||
media: {
|
media: {
|
||||||
name: this.avatarFile.name,
|
name: this.avatarFile.name,
|
||||||
alt: `${this.group.preferredUsername}'s avatar`,
|
alt: `${this.editableGroup.preferredUsername}'s avatar`,
|
||||||
file: this.avatarFile,
|
file: this.avatarFile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -303,14 +328,20 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
|||||||
banner: {
|
banner: {
|
||||||
media: {
|
media: {
|
||||||
name: this.bannerFile.name,
|
name: this.bannerFile.name,
|
||||||
alt: `${this.group.preferredUsername}'s banner`,
|
alt: `${this.editableGroup.preferredUsername}'s banner`,
|
||||||
file: this.bannerFile,
|
file: this.bannerFile,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...variables,
|
id: this.group.id,
|
||||||
|
name: this.editableGroup.name,
|
||||||
|
summary: this.editableGroup.summary,
|
||||||
|
visibility: this.editableGroup.visibility,
|
||||||
|
openness: this.editableGroup.openness,
|
||||||
|
manuallyApprovesFollowers: this.editableGroup.manuallyApprovesFollowers,
|
||||||
|
physicalAddress,
|
||||||
...avatarObj,
|
...avatarObj,
|
||||||
...bannerObj,
|
...bannerObj,
|
||||||
};
|
};
|
||||||
@ -322,7 +353,7 @@ export default class GroupSettings extends mixins(GroupMixin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get currentAddress(): IAddress {
|
get currentAddress(): IAddress {
|
||||||
return new Address(this.group.physicalAddress);
|
return new Address(this.editableGroup.physicalAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
get avatarMaxSize(): number | undefined {
|
get avatarMaxSize(): number | undefined {
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<picture-upload
|
<picture-upload
|
||||||
v-model="pictureFile"
|
v-model="pictureFile"
|
||||||
:textFallback="$t('Headline picture')"
|
:textFallback="$t('Headline picture')"
|
||||||
:defaultImage="post.picture"
|
:defaultImage="editablePost.picture"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<b-field
|
<b-field
|
||||||
@ -61,21 +61,21 @@
|
|||||||
size="is-large"
|
size="is-large"
|
||||||
aria-required="true"
|
aria-required="true"
|
||||||
required
|
required
|
||||||
v-model="post.title"
|
v-model="editablePost.title"
|
||||||
/>
|
/>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<tag-input v-model="post.tags" :data="tags" path="title" />
|
<tag-input v-model="editablePost.tags" :data="tags" path="title" />
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">{{ $t("Post") }}</label>
|
<label class="label">{{ $t("Post") }}</label>
|
||||||
<p v-if="errors.body" class="help is-danger">{{ errors.body }}</p>
|
<p v-if="errors.body" class="help is-danger">{{ errors.body }}</p>
|
||||||
<editor v-model="post.body" />
|
<editor v-model="editablePost.body" />
|
||||||
</div>
|
</div>
|
||||||
<subtitle>{{ $t("Who can view this post") }}</subtitle>
|
<subtitle>{{ $t("Who can view this post") }}</subtitle>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="post.visibility"
|
v-model="editablePost.visibility"
|
||||||
name="postVisibility"
|
name="postVisibility"
|
||||||
:native-value="PostVisibility.PUBLIC"
|
:native-value="PostVisibility.PUBLIC"
|
||||||
>{{ $t("Visible everywhere on the web") }}</b-radio
|
>{{ $t("Visible everywhere on the web") }}</b-radio
|
||||||
@ -83,7 +83,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="post.visibility"
|
v-model="editablePost.visibility"
|
||||||
name="postVisibility"
|
name="postVisibility"
|
||||||
:native-value="PostVisibility.UNLISTED"
|
:native-value="PostVisibility.UNLISTED"
|
||||||
>{{ $t("Only accessible through link") }}</b-radio
|
>{{ $t("Only accessible through link") }}</b-radio
|
||||||
@ -91,7 +91,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<b-radio
|
<b-radio
|
||||||
v-model="post.visibility"
|
v-model="editablePost.visibility"
|
||||||
name="postVisibility"
|
name="postVisibility"
|
||||||
:native-value="PostVisibility.PRIVATE"
|
:native-value="PostVisibility.PRIVATE"
|
||||||
>{{ $t("Only accessible to members of the group") }}</b-radio
|
>{{ $t("Only accessible to members of the group") }}</b-radio
|
||||||
@ -166,7 +166,7 @@ import {
|
|||||||
|
|
||||||
import { IPost } from "../../types/post.model";
|
import { IPost } from "../../types/post.model";
|
||||||
import Editor from "../../components/Editor.vue";
|
import Editor from "../../components/Editor.vue";
|
||||||
import { IActor, IGroup, usernameWithDomain } from "../../types/actor";
|
import { IActor, usernameWithDomain } from "../../types/actor";
|
||||||
import TagInput from "../../components/Event/TagInput.vue";
|
import TagInput from "../../components/Event/TagInput.vue";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import Subtitle from "../../components/Utils/Subtitle.vue";
|
import Subtitle from "../../components/Utils/Subtitle.vue";
|
||||||
@ -249,8 +249,6 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
tags: [],
|
tags: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
group!: IGroup;
|
|
||||||
|
|
||||||
PostVisibility = PostVisibility;
|
PostVisibility = PostVisibility;
|
||||||
|
|
||||||
pictureFile: File | null = null;
|
pictureFile: File | null = null;
|
||||||
@ -259,6 +257,8 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
|
|
||||||
RouteName = RouteName;
|
RouteName = RouteName;
|
||||||
|
|
||||||
|
editablePost!: IPost;
|
||||||
|
|
||||||
usernameWithDomain = usernameWithDomain;
|
usernameWithDomain = usernameWithDomain;
|
||||||
|
|
||||||
async mounted(): Promise<void> {
|
async mounted(): Promise<void> {
|
||||||
@ -270,6 +270,7 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
if (oldPost.picture !== newPost.picture) {
|
if (oldPost.picture !== newPost.picture) {
|
||||||
this.pictureFile = await buildFileFromIMedia(this.post.picture);
|
this.pictureFile = await buildFileFromIMedia(this.post.picture);
|
||||||
}
|
}
|
||||||
|
this.editablePost = { ...this.post };
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line consistent-return
|
// eslint-disable-next-line consistent-return
|
||||||
@ -280,11 +281,11 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
const { data } = await this.$apollo.mutate({
|
const { data } = await this.$apollo.mutate({
|
||||||
mutation: UPDATE_POST,
|
mutation: UPDATE_POST,
|
||||||
variables: {
|
variables: {
|
||||||
id: this.post.id,
|
id: this.editablePost.id,
|
||||||
title: this.post.title,
|
title: this.editablePost.title,
|
||||||
body: this.post.body,
|
body: this.editablePost.body,
|
||||||
tags: (this.post.tags || []).map(({ title }) => title),
|
tags: (this.editablePost.tags || []).map(({ title }) => title),
|
||||||
visibility: this.post.visibility,
|
visibility: this.editablePost.visibility,
|
||||||
draft,
|
draft,
|
||||||
...(await this.buildPicture()),
|
...(await this.buildPicture()),
|
||||||
},
|
},
|
||||||
@ -300,9 +301,9 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
const { data } = await this.$apollo.mutate({
|
const { data } = await this.$apollo.mutate({
|
||||||
mutation: CREATE_POST,
|
mutation: CREATE_POST,
|
||||||
variables: {
|
variables: {
|
||||||
...this.post,
|
...this.editablePost,
|
||||||
...(await this.buildPicture()),
|
...(await this.buildPicture()),
|
||||||
tags: (this.post.tags || []).map(({ title }) => title),
|
tags: (this.editablePost.tags || []).map(({ title }) => title),
|
||||||
attributedToId: this.actualGroup.id,
|
attributedToId: this.actualGroup.id,
|
||||||
draft,
|
draft,
|
||||||
},
|
},
|
||||||
@ -362,16 +363,16 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
obj = { ...obj, ...pictureObj };
|
obj = { ...obj, ...pictureObj };
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (this.post.picture && this.pictureFile) {
|
if (this.editablePost.picture && this.pictureFile) {
|
||||||
const oldPictureFile = (await buildFileFromIMedia(
|
const oldPictureFile = (await buildFileFromIMedia(
|
||||||
this.post.picture
|
this.editablePost.picture
|
||||||
)) as File;
|
)) as File;
|
||||||
const oldPictureFileContent = await readFileAsync(oldPictureFile);
|
const oldPictureFileContent = await readFileAsync(oldPictureFile);
|
||||||
const newPictureFileContent = await readFileAsync(
|
const newPictureFileContent = await readFileAsync(
|
||||||
this.pictureFile as File
|
this.pictureFile as File
|
||||||
);
|
);
|
||||||
if (oldPictureFileContent === newPictureFileContent) {
|
if (oldPictureFileContent === newPictureFileContent) {
|
||||||
obj.picture = { mediaId: this.post.picture.id };
|
obj.picture = { mediaId: this.editablePost.picture.id };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -381,7 +382,7 @@ export default class EditPost extends mixins(GroupMixin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get actualGroup(): IActor {
|
get actualGroup(): IActor {
|
||||||
if (!this.group.id) {
|
if (!this.group?.id) {
|
||||||
return this.post.attributedTo as IActor;
|
return this.post.attributedTo as IActor;
|
||||||
}
|
}
|
||||||
return this.group;
|
return this.group;
|
||||||
|
@ -86,7 +86,7 @@ import { IMember } from "@/types/actor/member.model";
|
|||||||
import { FETCH_GROUP_POSTS } from "../../graphql/post";
|
import { FETCH_GROUP_POSTS } from "../../graphql/post";
|
||||||
import { Paginate } from "../../types/paginate";
|
import { Paginate } from "../../types/paginate";
|
||||||
import { IPost } from "../../types/post.model";
|
import { IPost } from "../../types/post.model";
|
||||||
import { IGroup, IPerson, usernameWithDomain } from "../../types/actor";
|
import { usernameWithDomain } from "../../types/actor";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import PostElementItem from "../../components/Post/PostElementItem.vue";
|
import PostElementItem from "../../components/Post/PostElementItem.vue";
|
||||||
|
|
||||||
@ -138,14 +138,10 @@ const POSTS_PAGE_LIMIT = 10;
|
|||||||
export default class PostList extends mixins(GroupMixin) {
|
export default class PostList extends mixins(GroupMixin) {
|
||||||
@Prop({ required: true, type: String }) preferredUsername!: string;
|
@Prop({ required: true, type: String }) preferredUsername!: string;
|
||||||
|
|
||||||
group!: IGroup;
|
|
||||||
|
|
||||||
posts!: Paginate<IPost>;
|
posts!: Paginate<IPost>;
|
||||||
|
|
||||||
memberships!: IMember[];
|
memberships!: IMember[];
|
||||||
|
|
||||||
currentActor!: IPerson;
|
|
||||||
|
|
||||||
postsPage = 1;
|
postsPage = 1;
|
||||||
|
|
||||||
RouteName = RouteName;
|
RouteName = RouteName;
|
||||||
|
@ -1,61 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<article class="container" v-if="post">
|
||||||
<article class="container" v-if="post">
|
<header>
|
||||||
<section class="heading-section">
|
<div class="banner-container">
|
||||||
<h1 class="title">{{ post.title }}</h1>
|
<lazy-image
|
||||||
<i18n tag="span" path="By {author}" class="authors">
|
v-if="post.picture"
|
||||||
<router-link
|
:src="post.picture.url"
|
||||||
slot="author"
|
:width="post.picture.metadata.width"
|
||||||
:to="{
|
:height="post.picture.metadata.height"
|
||||||
name: RouteName.GROUP,
|
:blurhash="post.picture.metadata.blurhash"
|
||||||
params: {
|
/>
|
||||||
preferredUsername: usernameWithDomain(post.attributedTo),
|
</div>
|
||||||
},
|
<div class="heading-section">
|
||||||
}"
|
<div class="heading-wrapper">
|
||||||
>{{ post.attributedTo.name }}</router-link
|
<div class="title-metadata">
|
||||||
>
|
<h1 class="title">{{ post.title }}</h1>
|
||||||
</i18n>
|
<p class="metadata">
|
||||||
<p class="published has-text-grey-dark" v-if="!post.draft">
|
<router-link
|
||||||
{{ post.publishAt | formatDateTimeString }}
|
slot="author"
|
||||||
</p>
|
:to="{
|
||||||
<small
|
name: RouteName.GROUP,
|
||||||
v-if="post.visibility === PostVisibility.PRIVATE"
|
params: {
|
||||||
class="has-text-grey-dark"
|
preferredUsername: usernameWithDomain(post.attributedTo),
|
||||||
>
|
},
|
||||||
<b-icon icon="lock" size="is-small" />
|
}"
|
||||||
{{
|
>
|
||||||
$t("Accessible only to members", { group: post.attributedTo.name })
|
<actor-inline :actor="post.attributedTo" />
|
||||||
}}
|
</router-link>
|
||||||
</small>
|
<span class="published has-text-grey-dark" v-if="!post.draft">
|
||||||
<p class="buttons" v-if="isCurrentActorMember">
|
<b-icon icon="clock" size="is-small" />
|
||||||
<b-tag type="is-warning" size="is-medium" v-if="post.draft">{{
|
{{ post.publishAt | formatDateTimeString }}
|
||||||
$t("Draft")
|
</span>
|
||||||
}}</b-tag>
|
<span
|
||||||
<router-link
|
v-if="post.visibility === PostVisibility.PRIVATE"
|
||||||
v-if="
|
class="has-text-grey-dark"
|
||||||
currentActor.id === post.author.id ||
|
>
|
||||||
isCurrentActorAGroupModerator
|
<b-icon icon="lock" size="is-small" />
|
||||||
"
|
{{
|
||||||
:to="{ name: RouteName.POST_EDIT, params: { slug: post.slug } }"
|
$t("Accessible only to members", {
|
||||||
tag="button"
|
group: post.attributedTo.name,
|
||||||
class="button is-text"
|
})
|
||||||
>{{ $t("Edit") }}</router-link
|
}}
|
||||||
>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<img v-if="post.picture" :src="post.picture.url" alt="" />
|
</div>
|
||||||
</section>
|
<p class="buttons" v-if="isCurrentActorMember">
|
||||||
<section v-html="post.body" class="content" />
|
<b-tag type="is-warning" size="is-medium" v-if="post.draft">{{
|
||||||
<section class="tags">
|
$t("Draft")
|
||||||
<router-link
|
}}</b-tag>
|
||||||
v-for="tag in post.tags"
|
<router-link
|
||||||
:key="tag.title"
|
v-if="
|
||||||
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
|
currentActor.id === post.author.id ||
|
||||||
>
|
isCurrentActorAGroupModerator
|
||||||
<tag>{{ tag.title }}</tag>
|
"
|
||||||
</router-link>
|
:to="{ name: RouteName.POST_EDIT, params: { slug: post.slug } }"
|
||||||
</section>
|
tag="button"
|
||||||
</article>
|
class="button is-text"
|
||||||
</div>
|
>{{ $t("Edit") }}</router-link
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section v-html="post.body" class="content" />
|
||||||
|
<section class="tags">
|
||||||
|
<router-link
|
||||||
|
v-for="tag in post.tags"
|
||||||
|
:key="tag.title"
|
||||||
|
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
|
||||||
|
>
|
||||||
|
<tag>{{ tag.title }}</tag>
|
||||||
|
</router-link>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@ -66,11 +83,12 @@ import { PostVisibility } from "@/types/enums";
|
|||||||
import { IMember } from "@/types/actor/member.model";
|
import { IMember } from "@/types/actor/member.model";
|
||||||
import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "../../graphql/actor";
|
import { CURRENT_ACTOR_CLIENT, PERSON_MEMBERSHIPS } from "../../graphql/actor";
|
||||||
import { FETCH_POST } from "../../graphql/post";
|
import { FETCH_POST } from "../../graphql/post";
|
||||||
|
|
||||||
import { IPost } from "../../types/post.model";
|
import { IPost } from "../../types/post.model";
|
||||||
import { usernameWithDomain } from "../../types/actor";
|
import { usernameWithDomain } from "../../types/actor";
|
||||||
import RouteName from "../../router/name";
|
import RouteName from "../../router/name";
|
||||||
import Tag from "../../components/Tag.vue";
|
import Tag from "../../components/Tag.vue";
|
||||||
|
import LazyImage from "../../components/Image/LazyImage.vue";
|
||||||
|
import ActorInline from "../../components/Account/ActorInline.vue";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
apollo: {
|
apollo: {
|
||||||
@ -106,6 +124,8 @@ import Tag from "../../components/Tag.vue";
|
|||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Tag,
|
Tag,
|
||||||
|
LazyImage,
|
||||||
|
ActorInline,
|
||||||
},
|
},
|
||||||
metaInfo() {
|
metaInfo() {
|
||||||
return {
|
return {
|
||||||
@ -148,78 +168,93 @@ export default class Post extends mixins(GroupMixin) {
|
|||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
article {
|
article {
|
||||||
section.heading-section {
|
background: $white !important;
|
||||||
text-align: center;
|
header {
|
||||||
position: relative;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: auto -3rem 2rem;
|
.banner-container {
|
||||||
|
display: flex;
|
||||||
h1.title {
|
|
||||||
margin: 0 auto;
|
|
||||||
padding-top: 3rem;
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.authors {
|
|
||||||
margin-top: 2rem;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.published {
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
height: 0.2rem;
|
|
||||||
content: " ";
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
background-color: $purple-1;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
height: 30vh;
|
||||||
& > * {
|
|
||||||
z-index: 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& > img {
|
.heading-section {
|
||||||
position: absolute;
|
position: relative;
|
||||||
left: 0;
|
display: flex;
|
||||||
top: 0;
|
flex-direction: column;
|
||||||
width: 100%;
|
margin-bottom: 2rem;
|
||||||
height: 100%;
|
|
||||||
opacity: 0.3;
|
|
||||||
object-fit: cover;
|
|
||||||
object-position: 50% 50%;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
section.content {
|
.heading-wrapper {
|
||||||
font-size: 1.1rem;
|
padding: 15px 10px;
|
||||||
}
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
section.tags {
|
.title-metadata {
|
||||||
padding-bottom: 5rem;
|
min-width: 300px;
|
||||||
|
flex: 20;
|
||||||
|
|
||||||
a {
|
p.metadata {
|
||||||
text-decoration: none;
|
margin-top: 16px;
|
||||||
}
|
display: flex;
|
||||||
span {
|
justify-content: flex-start;
|
||||||
&.tag {
|
flex-wrap: wrap;
|
||||||
margin: 0 2px;
|
|
||||||
|
*:not(:first-child) {
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.buttons {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 38px;
|
||||||
|
font-family: "Roboto", "Helvetica", "Arial", serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.authors {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
height: 0.2rem;
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
background-color: $purple-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > section {
|
||||||
|
margin: 0 2rem;
|
||||||
|
|
||||||
|
&.content {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tags {
|
||||||
|
padding-bottom: 5rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
&.tag {
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
background: $white;
|
|
||||||
max-width: 700px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 3rem;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
2285
js/yarn.lock
2285
js/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -76,14 +76,19 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
|
|||||||
@doc """
|
@doc """
|
||||||
Find an actor in our local database or call WebFinger to find what's its AP ID is and then fetch it
|
Find an actor in our local database or call WebFinger to find what's its AP ID is and then fetch it
|
||||||
"""
|
"""
|
||||||
@spec find_or_make_actor_from_nickname(String.t(), atom() | nil) :: tuple()
|
@spec find_or_make_actor_from_nickname(String.t(), atom() | nil) ::
|
||||||
|
{:ok, Actor.t()} | {:error, any()}
|
||||||
def find_or_make_actor_from_nickname(nickname, type \\ nil) do
|
def find_or_make_actor_from_nickname(nickname, type \\ nil) do
|
||||||
case Actors.get_actor_by_name(nickname, type) do
|
case Actors.get_actor_by_name_with_preload(nickname, type) do
|
||||||
%Actor{} = actor ->
|
%Actor{url: actor_url} = actor ->
|
||||||
{:ok, actor}
|
if Actors.needs_update?(actor) do
|
||||||
|
make_actor_from_url(actor_url, true)
|
||||||
|
else
|
||||||
|
{:ok, actor}
|
||||||
|
end
|
||||||
|
|
||||||
nil ->
|
nil ->
|
||||||
make_actor_from_nickname(nickname)
|
make_actor_from_nickname(nickname, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -94,10 +99,10 @@ defmodule Mobilizon.Federation.ActivityPub.Actor do
|
|||||||
Create an actor inside our database from username, using WebFinger to find out its AP ID and then fetch it
|
Create an actor inside our database from username, using WebFinger to find out its AP ID and then fetch it
|
||||||
"""
|
"""
|
||||||
@spec make_actor_from_nickname(String.t()) :: {:ok, %Actor{}} | {:error, any()}
|
@spec make_actor_from_nickname(String.t()) :: {:ok, %Actor{}} | {:error, any()}
|
||||||
def make_actor_from_nickname(nickname) do
|
def make_actor_from_nickname(nickname, preload \\ false) do
|
||||||
case WebFinger.finger(nickname) do
|
case WebFinger.finger(nickname) do
|
||||||
{:ok, url} when is_binary(url) ->
|
{:ok, url} when is_binary(url) ->
|
||||||
make_actor_from_url(url)
|
make_actor_from_url(url, preload)
|
||||||
|
|
||||||
_e ->
|
_e ->
|
||||||
{:error, "No ActivityPub URL found in WebFinger"}
|
{:error, "No ActivityPub URL found in WebFinger"}
|
||||||
|
11
lib/web/cache/activity_pub.ex
vendored
11
lib/web/cache/activity_pub.ex
vendored
@ -4,10 +4,11 @@ defmodule Mobilizon.Web.Cache.ActivityPub do
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
alias Mobilizon.{Actors, Discussions, Events, Posts, Resources, Todos, Tombstone}
|
alias Mobilizon.{Actors, Discussions, Events, Posts, Resources, Todos, Tombstone}
|
||||||
alias Mobilizon.Actors.{Actor, Member}
|
alias Mobilizon.Actors.Actor, as: ActorModel
|
||||||
|
alias Mobilizon.Actors.Member
|
||||||
alias Mobilizon.Discussions.{Comment, Discussion}
|
alias Mobilizon.Discussions.{Comment, Discussion}
|
||||||
alias Mobilizon.Events.Event
|
alias Mobilizon.Events.Event
|
||||||
alias Mobilizon.Federation.ActivityPub.Relay
|
alias Mobilizon.Federation.ActivityPub.{Actor, Relay}
|
||||||
alias Mobilizon.Posts.Post
|
alias Mobilizon.Posts.Post
|
||||||
alias Mobilizon.Resources.Resource
|
alias Mobilizon.Resources.Resource
|
||||||
alias Mobilizon.Todos.{Todo, TodoList}
|
alias Mobilizon.Todos.{Todo, TodoList}
|
||||||
@ -23,8 +24,8 @@ defmodule Mobilizon.Web.Cache.ActivityPub do
|
|||||||
{:commit, Actor.t()} | {:ignore, nil}
|
{:commit, Actor.t()} | {:ignore, nil}
|
||||||
def get_actor_by_name(name) do
|
def get_actor_by_name(name) do
|
||||||
Cachex.fetch(@cache, "actor_" <> name, fn "actor_" <> name ->
|
Cachex.fetch(@cache, "actor_" <> name, fn "actor_" <> name ->
|
||||||
case Actors.get_actor_by_name_with_preload(name) do
|
case Actor.find_or_make_actor_from_nickname(name) do
|
||||||
%Actor{} = actor ->
|
{:ok, %ActorModel{} = actor} ->
|
||||||
{:commit, actor}
|
{:commit, actor}
|
||||||
|
|
||||||
nil ->
|
nil ->
|
||||||
@ -41,7 +42,7 @@ defmodule Mobilizon.Web.Cache.ActivityPub do
|
|||||||
def get_local_actor_by_name(name) do
|
def get_local_actor_by_name(name) do
|
||||||
Cachex.fetch(@cache, "local_actor_" <> name, fn "local_actor_" <> name ->
|
Cachex.fetch(@cache, "local_actor_" <> name, fn "local_actor_" <> name ->
|
||||||
case Actors.get_local_actor_by_name(name) do
|
case Actors.get_local_actor_by_name(name) do
|
||||||
%Actor{} = actor ->
|
%ActorModel{} = actor ->
|
||||||
{:commit, actor}
|
{:commit, actor}
|
||||||
|
|
||||||
nil ->
|
nil ->
|
||||||
|
Loading…
Reference in New Issue
Block a user