Fix settings menu
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
dd806896d1
commit
6797075461
@ -17,6 +17,10 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
nav.breadcrumb ul li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
input.input {
|
||||
border-color: $input-border-color !important;
|
||||
}
|
||||
|
@ -1,24 +1,25 @@
|
||||
<template>
|
||||
<li class="setting-menu-item" :class="{ active: isActive }">
|
||||
<router-link v-if="menuItem.to" :to="menuItem.to">
|
||||
<span>{{ menuItem.title }}</span>
|
||||
<router-link v-if="to" :to="to">
|
||||
<span>{{ title }}</span>
|
||||
</router-link>
|
||||
<span v-else>{{ menuItem.title }}</span>
|
||||
<span v-else>{{ title }}</span>
|
||||
</li>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { ISettingMenuSection } from "@/types/setting-menu.model";
|
||||
import { Route } from "vue-router";
|
||||
|
||||
@Component
|
||||
export default class SettingMenuItem extends Vue {
|
||||
@Prop({ required: true, type: Object }) menuItem!: ISettingMenuSection;
|
||||
@Prop({ required: false, type: String }) title!: string;
|
||||
@Prop({ required: true, type: Object }) to!: Route;
|
||||
|
||||
get isActive() {
|
||||
if (!this.menuItem.to) return false;
|
||||
if (this.menuItem.to.name === this.$route.name) {
|
||||
if (this.menuItem.to.params) {
|
||||
return this.menuItem.to.params.identityName === this.$route.params.identityName;
|
||||
if (!this.to) return false;
|
||||
if (this.to.name === this.$route.name) {
|
||||
if (this.to.params) {
|
||||
return this.to.params.identityName === this.$route.params.identityName;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,28 +1,36 @@
|
||||
<template>
|
||||
<li :class="{ active: sectionActive }">
|
||||
<router-link v-if="menuSection.to" :to="menuSection.to">{{ menuSection.title }}</router-link>
|
||||
<b v-else>{{ menuSection.title }}</b>
|
||||
<router-link v-if="to" :to="to">{{ title }}</router-link>
|
||||
<b v-else>{{ title }}</b>
|
||||
<ul>
|
||||
<setting-menu-item :menu-item="item" v-for="item in menuSection.items" :key="item.title" />
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import { ISettingMenuSection } from "@/types/setting-menu.model";
|
||||
import SettingMenuItem from "@/components/Settings/SettingMenuItem.vue";
|
||||
import { Route } from "vue-router";
|
||||
@Component({
|
||||
components: { SettingMenuItem },
|
||||
})
|
||||
export default class SettingMenuSection extends Vue {
|
||||
@Prop({ required: true, type: Object }) menuSection!: ISettingMenuSection;
|
||||
@Prop({ required: false, type: String }) title!: string;
|
||||
@Prop({ required: true, type: Object }) to!: Route;
|
||||
|
||||
get sectionActive(): boolean | undefined {
|
||||
return (
|
||||
this.menuSection.items &&
|
||||
this.menuSection.items.some(({ to }) => to && to.name === this.$route.name)
|
||||
get sectionActive() {
|
||||
if (this.$slots.default) {
|
||||
return this.$slots.default.some(
|
||||
({
|
||||
componentOptions: {
|
||||
// @ts-ignore
|
||||
propsData: { to },
|
||||
},
|
||||
}) => to && to.name === this.$route.name
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,27 +1,88 @@
|
||||
<template>
|
||||
<aside>
|
||||
<ul>
|
||||
<SettingMenuSection
|
||||
v-for="section in menuValue"
|
||||
:key="section.title"
|
||||
:menu-section="section"
|
||||
<SettingMenuSection :title="$t('Account')" :to="{ name: RouteName.ACCOUNT_SETTINGS }">
|
||||
<SettingMenuItem
|
||||
:title="this.$t('General')"
|
||||
:to="{ name: RouteName.ACCOUNT_SETTINGS_GENERAL }"
|
||||
/>
|
||||
<SettingMenuItem :title="$t('Preferences')" :to="{ name: RouteName.PREFERENCES }" />
|
||||
<SettingMenuItem
|
||||
:title="this.$t('Email notifications')"
|
||||
:to="{ name: RouteName.NOTIFICATIONS }"
|
||||
/>
|
||||
</SettingMenuSection>
|
||||
<SettingMenuSection :title="$t('Profiles')" :to="{ name: RouteName.IDENTITIES }">
|
||||
<SettingMenuItem
|
||||
v-for="profile in identities"
|
||||
:key="profile.preferredUsername"
|
||||
:title="profile.preferredUsername"
|
||||
:to="{
|
||||
name: RouteName.UPDATE_IDENTITY,
|
||||
params: { identityName: profile.preferredUsername },
|
||||
}"
|
||||
/>
|
||||
<SettingMenuItem :title="$t('New profile')" :to="{ name: RouteName.CREATE_IDENTITY }" />
|
||||
</SettingMenuSection>
|
||||
<SettingMenuSection
|
||||
v-if="
|
||||
[ICurrentUserRole.MODERATOR, ICurrentUserRole.ADMINISTRATOR].includes(
|
||||
this.currentUser.role
|
||||
)
|
||||
"
|
||||
:title="$t('Moderation')"
|
||||
:to="{ name: RouteName.MODERATION }"
|
||||
>
|
||||
<SettingMenuItem :title="$t('Reports')" :to="{ name: RouteName.REPORTS }" />
|
||||
<SettingMenuItem :title="$t('Moderation log')" :to="{ name: RouteName.REPORT_LOGS }" />
|
||||
<SettingMenuItem :title="$t('Users')" :to="{ name: RouteName.USERS }" />
|
||||
<SettingMenuItem :title="$t('Profiles')" :to="{ name: RouteName.PROFILES }" />
|
||||
</SettingMenuSection>
|
||||
<SettingMenuSection
|
||||
v-if="this.currentUser.role == ICurrentUserRole.ADMINISTRATOR"
|
||||
:title="$t('Admin')"
|
||||
:to="{ name: RouteName.ADMIN }"
|
||||
>
|
||||
<SettingMenuItem :title="$t('Dashboard')" :to="{ name: RouteName.ADMIN_DASHBOARD }" />
|
||||
<SettingMenuItem
|
||||
:title="$t('Instance settings')"
|
||||
:to="{ name: RouteName.ADMIN_SETTINGS }"
|
||||
/>
|
||||
<SettingMenuItem :title="$t('Federation')" :to="{ name: RouteName.RELAYS }" />
|
||||
</SettingMenuSection>
|
||||
</ul>
|
||||
</aside>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
import SettingMenuSection from "@/components/Settings/SettingMenuSection.vue";
|
||||
import { ISettingMenuSection } from "@/types/setting-menu.model";
|
||||
import SettingMenuSection from "./SettingMenuSection.vue";
|
||||
import SettingMenuItem from "./SettingMenuItem.vue";
|
||||
import { IDENTITIES } from "../../graphql/actor";
|
||||
import { IPerson, Person } from "../../types/actor";
|
||||
import { CURRENT_USER_CLIENT } from "../../graphql/user";
|
||||
import { ICurrentUser, ICurrentUserRole } from "../../types/current-user.model";
|
||||
|
||||
import RouteName from "../../router/name";
|
||||
@Component({
|
||||
components: { SettingMenuSection },
|
||||
components: { SettingMenuSection, SettingMenuItem },
|
||||
apollo: {
|
||||
identities: {
|
||||
query: IDENTITIES,
|
||||
update: (data) => data.identities.map((identity: IPerson) => new Person(identity)),
|
||||
},
|
||||
currentUser: CURRENT_USER_CLIENT,
|
||||
},
|
||||
})
|
||||
export default class SettingsMenu extends Vue {
|
||||
@Prop({ required: true, type: Array }) menu!: ISettingMenuSection[];
|
||||
profiles = [];
|
||||
|
||||
get menuValue() {
|
||||
return this.menu;
|
||||
}
|
||||
currentUser!: ICurrentUser;
|
||||
|
||||
identities!: IPerson[];
|
||||
|
||||
ICurrentUserRole = ICurrentUserRole;
|
||||
|
||||
RouteName = RouteName;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
@ -106,6 +106,7 @@ export const USER_SETTINGS_FRAGMENT = gql`
|
||||
export const USER_SETTINGS = gql`
|
||||
query UserSetting {
|
||||
loggedUser {
|
||||
id
|
||||
locale
|
||||
settings {
|
||||
...UserSettingFragment
|
||||
|
@ -695,5 +695,6 @@
|
||||
"contact uninformed": "contact uninformed",
|
||||
"Can be an email or a link, or just plain text.": "Can be an email or a link, or just plain text.",
|
||||
"No profiles found": "No profiles found",
|
||||
"URL copied to clipboard": "URL copied to clipboard"
|
||||
"URL copied to clipboard": "URL copied to clipboard",
|
||||
"Report #{reportNumber}": "Report #{reportNumber}"
|
||||
}
|
||||
|
@ -695,5 +695,6 @@
|
||||
"A place for your code of conduct, rules or guidelines. You can use HTML tags.": "Une section appropriée pour votre code de conduite, règles ou lignes directrices. Vous pouvez utiliser des balises HTML.",
|
||||
"contact uninformed": "contact non renseigné",
|
||||
"Can be an email or a link, or just plain text.": "Peut être une adresse email ou bien un lien, ou alors du simple texte brut.",
|
||||
"URL copied to clipboard": "URL copiée dans le presse-papiers"
|
||||
"URL copied to clipboard": "URL copiée dans le presse-papiers",
|
||||
"Report #{reportNumber}": "Signalement #{reportNumber}"
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
import { Route } from "vue-router";
|
||||
|
||||
export interface ISettingMenuSection {
|
||||
title: string;
|
||||
to: Route;
|
||||
items?: ISettingMenuSection[];
|
||||
parents?: ISettingMenuSection[];
|
||||
}
|
@ -1,4 +1,26 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.IDENTITIES }">{{ $t("Profiles") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active" v-if="isUpdate && identity">
|
||||
<router-link
|
||||
:to="{
|
||||
name: RouteName.UPDATE_IDENTITY,
|
||||
params: { identityName: identity.preferredUsername },
|
||||
}"
|
||||
>{{ identity.name }}</router-link
|
||||
>
|
||||
</li>
|
||||
<li class="is-active" v-else>
|
||||
<router-link :to="{ name: RouteName.CREATE_IDENTITY }">{{
|
||||
$t("New profile")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="root" v-if="identity">
|
||||
<h1 class="title">
|
||||
<span v-if="isUpdate">{{ identity.displayName() }}</span>
|
||||
@ -55,7 +77,9 @@
|
||||
|
||||
<b-field class="submit">
|
||||
<div class="control">
|
||||
<button type="button" class="button is-primary" @click="submit()">{{ $t("Save") }}</button>
|
||||
<button type="button" class="button is-primary" @click="submit()">
|
||||
{{ $t("Save") }}
|
||||
</button>
|
||||
</div>
|
||||
</b-field>
|
||||
|
||||
@ -63,6 +87,7 @@
|
||||
<span @click="openDeleteIdentityConfirmation()">{{ $t("Delete this identity") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped type="scss">
|
||||
@ -148,6 +173,8 @@ export default class EditIdentity extends mixins(identityEditionMixin) {
|
||||
|
||||
private currentActor: IPerson | null = null;
|
||||
|
||||
RouteName = RouteName;
|
||||
|
||||
get message() {
|
||||
if (this.isUpdate) return null;
|
||||
return this.$t("Only alphanumeric characters and underscores are supported.");
|
||||
|
@ -1,4 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ADMIN }">{{ $t("Admin") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.ADMIN_DASHBOARD }">{{ $t("Dashboard") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<h1 class="title">{{ $t("Administration") }}</h1>
|
||||
<div class="tile is-ancestor" v-if="dashboard">
|
||||
@ -48,6 +59,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
|
@ -1,4 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ADMIN }">{{ $t("Admin") }}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.RELAYS }">{{ $t("Federation") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active" v-if="$route.name == RouteName.RELAY_FOLLOWINGS">
|
||||
<router-link :to="{ name: RouteName.RELAY_FOLLOWINGS }">{{
|
||||
$t("Followings")
|
||||
}}</router-link>
|
||||
</li>
|
||||
<li class="is-active" v-if="$route.name == RouteName.RELAY_FOLLOWERS">
|
||||
<router-link :to="{ name: RouteName.RELAY_FOLLOWERS }">{{ $t("Followers") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<h1 class="title">{{ $t("Instances") }}</h1>
|
||||
<div class="tabs is-boxed">
|
||||
@ -35,6 +54,7 @@
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -1,4 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.MODERATION }">{{ $t("Moderation") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.PROFILES }">{{ $t("Profiles") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div v-if="persons">
|
||||
<b-switch v-model="local">{{ $t("Local") }}</b-switch>
|
||||
<b-switch v-model="suspended">{{ $t("Suspended") }}</b-switch>
|
||||
@ -65,6 +76,7 @@
|
||||
</template>
|
||||
</b-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
|
@ -1,4 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ADMIN }">{{ $t("Admin") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.ADMIN_SETTINGS }">{{
|
||||
$t("Instance settings")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section v-if="adminSettings">
|
||||
<form @submit.prevent="updateSettings">
|
||||
<b-field :label="$t('Instance Name')">
|
||||
@ -44,7 +57,9 @@
|
||||
<div class="field">
|
||||
<label class="label has-help">{{ $t("Instance Rules") }}</label>
|
||||
<small>
|
||||
{{ $t("A place for your code of conduct, rules or guidelines. You can use HTML tags.") }}
|
||||
{{
|
||||
$t("A place for your code of conduct, rules or guidelines. You can use HTML tags.")
|
||||
}}
|
||||
</small>
|
||||
<b-input type="textarea" v-model="adminSettings.instanceRules" />
|
||||
</div>
|
||||
@ -196,7 +211,9 @@
|
||||
v-if="adminSettings.instancePrivacyPolicyType === InstancePrivacyType.URL"
|
||||
>
|
||||
<b>{{ $t("URL") }}</b>
|
||||
<p class="content">{{ $t("Set an URL to a page with your own privacy policy.") }}</p>
|
||||
<p class="content">
|
||||
{{ $t("Set an URL to a page with your own privacy policy.") }}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="notification"
|
||||
@ -236,6 +253,7 @@
|
||||
<b-button native-type="submit" type="is-primary">{{ $t("Save") }}</b-button>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
|
@ -1,4 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.MODERATION }">{{ $t("Moderation") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.USERS }">{{ $t("Users") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div v-if="users">
|
||||
<b-table
|
||||
:data="users.elements"
|
||||
@ -73,6 +84,7 @@
|
||||
</template>
|
||||
</b-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
|
@ -1,4 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.GROUP }">{{ group.name }}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.GROUP_SETTINGS }">{{ $t("Settings") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.GROUP_MEMBERS_SETTINGS }">{{
|
||||
$t("Members")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section class="container section" v-if="group">
|
||||
<form @submit.prevent="inviteMember">
|
||||
<b-field :label="$t('Invite a new member')" custom-class="add-relay" horizontal>
|
||||
@ -15,6 +31,7 @@
|
||||
<h1>{{ $t("Group Members") }} ({{ group.members.total }})</h1>
|
||||
<pre>{{ group.members }}</pre>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -2,19 +2,21 @@
|
||||
<aside class="section container">
|
||||
<h1 class="title">{{ $t("Settings") }}</h1>
|
||||
<div class="columns">
|
||||
<SettingsMenu class="column is-one-quarter-desktop" :menu="menu" />
|
||||
<div class="column">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<aside class="column is-one-quarter-desktop">
|
||||
<ul>
|
||||
<li
|
||||
v-for="route in routes.get($route.name)"
|
||||
:class="{ 'is-active': route.to.name === $route.name }"
|
||||
:key="route.title"
|
||||
>
|
||||
<router-link :to="{ name: route.to.name }">{{ route.title }}</router-link>
|
||||
</li>
|
||||
<SettingMenuSection :title="$t('Settings')" :to="{ name: RouteName.GROUP_SETTINGS }">
|
||||
<SettingMenuItem
|
||||
:title="this.$t('Public')"
|
||||
:to="{ name: RouteName.GROUP_PUBLIC_SETTINGS }"
|
||||
/>
|
||||
<SettingMenuItem
|
||||
:title="this.$t('Members')"
|
||||
:to="{ name: RouteName.GROUP_MEMBERS_SETTINGS }"
|
||||
/>
|
||||
</SettingMenuSection>
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
<div class="column">
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
@ -22,70 +24,20 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
import SettingsMenu from "@/components/Settings/SettingsMenu.vue";
|
||||
import { ISettingMenuSection } from "@/types/setting-menu.model";
|
||||
import { Route } from "vue-router";
|
||||
import { IGroup, IPerson } from "@/types/actor";
|
||||
import { FETCH_GROUP } from "@/graphql/actor";
|
||||
import RouteName from "../../router/name";
|
||||
import SettingMenuSection from "../../components/Settings/SettingMenuSection.vue";
|
||||
import SettingMenuItem from "../../components/Settings/SettingMenuItem.vue";
|
||||
|
||||
@Component({
|
||||
components: { SettingsMenu },
|
||||
apollo: {
|
||||
group: {
|
||||
query: FETCH_GROUP,
|
||||
},
|
||||
},
|
||||
components: { SettingMenuSection, SettingMenuItem },
|
||||
})
|
||||
export default class Settings extends Vue {
|
||||
RouteName = RouteName;
|
||||
|
||||
menu: ISettingMenuSection[] = [];
|
||||
|
||||
group!: IGroup[];
|
||||
|
||||
mounted() {
|
||||
this.menu = [
|
||||
{
|
||||
title: this.$t("Settings") as string,
|
||||
to: { name: RouteName.GROUP_SETTINGS } as Route,
|
||||
items: [
|
||||
{
|
||||
title: this.$t("Public") as string,
|
||||
to: { name: RouteName.GROUP_PUBLIC_SETTINGS } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Members") as string,
|
||||
to: { name: RouteName.GROUP_MEMBERS_SETTINGS } as Route,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
get routes(): Map<string, Route[]> {
|
||||
return this.getPath(this.menu);
|
||||
}
|
||||
|
||||
getPath(object: ISettingMenuSection[]) {
|
||||
function iter(menu: ISettingMenuSection[] | ISettingMenuSection, acc: ISettingMenuSection[]) {
|
||||
if (Array.isArray(menu)) {
|
||||
return menu.forEach((item: ISettingMenuSection) => {
|
||||
iter(item, acc.concat(item));
|
||||
});
|
||||
}
|
||||
if (menu.items && menu.items.length > 0) {
|
||||
return menu.items.forEach((item: ISettingMenuSection) => {
|
||||
iter(item, acc.concat(item));
|
||||
});
|
||||
}
|
||||
result.set(menu.to.name, acc);
|
||||
}
|
||||
|
||||
const result = new Map();
|
||||
iter(object, []);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,4 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.MODERATION }">{{ $t("Moderation") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.REPORT_LOGS }">{{
|
||||
$t("Moderation log")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<ul v-if="actionLogs.length > 0">
|
||||
<li v-for="log in actionLogs" :key="log.id">
|
||||
@ -141,6 +154,7 @@
|
||||
<b-message type="is-info">{{ $t("No moderation logs yet") }}</b-message>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
|
@ -1,4 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs" v-if="report">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.MODERATION }">{{ $t("Moderation") }}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.REPORTS }">{{ $t("Reports") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.REPORT, params: { id: report.id } }">{{
|
||||
$t("Report #{reportNumber}", { reportNumber: report.id })
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<b-message title="Error" type="is-danger" v-for="error in errors" :key="error">
|
||||
{{ error }}
|
||||
@ -197,6 +213,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||
|
@ -1,4 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.MODERATION }">{{ $t("Moderation") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.REPORTS }">{{ $t("Reports") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<b-field>
|
||||
<b-radio-button v-model="filterReports" :native-value="ReportStatusEnum.OPEN">{{
|
||||
@ -30,6 +41,7 @@
|
||||
</b-message>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue, Watch } from "vue-property-decorator";
|
||||
|
@ -2,19 +2,8 @@
|
||||
<div class="section container">
|
||||
<h1 class="title">{{ $t("Settings") }}</h1>
|
||||
<div class="columns">
|
||||
<SettingsMenu class="column is-one-quarter-desktop" :menu="menu" />
|
||||
<SettingsMenu class="column is-one-quarter-desktop" />
|
||||
<div class="column">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li
|
||||
v-for="route in routes.get($route.name)"
|
||||
:class="{ 'is-active': route.to.name === $route.name }"
|
||||
:key="route.to.name"
|
||||
>
|
||||
<router-link :to="{ name: route.to.name }">{{ route.title }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
@ -25,7 +14,6 @@ import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
import { Route } from "vue-router";
|
||||
import SettingsMenu from "../components/Settings/SettingsMenu.vue";
|
||||
import RouteName from "../router/name";
|
||||
import { ISettingMenuSection } from "../types/setting-menu.model";
|
||||
import { IPerson, Person } from "../types/actor";
|
||||
import { IDENTITIES } from "../graphql/actor";
|
||||
import { CURRENT_USER_CLIENT } from "../graphql/user";
|
||||
@ -44,148 +32,9 @@ import { ICurrentUser, ICurrentUserRole } from "../types/current-user.model";
|
||||
export default class Settings extends Vue {
|
||||
RouteName = RouteName;
|
||||
|
||||
menu: ISettingMenuSection[] = [];
|
||||
|
||||
identities!: IPerson[];
|
||||
|
||||
newIdentity!: ISettingMenuSection;
|
||||
|
||||
currentUser!: ICurrentUser;
|
||||
|
||||
mounted() {
|
||||
this.newIdentity = {
|
||||
title: this.$t("New profile") as string,
|
||||
to: { name: RouteName.CREATE_IDENTITY } as Route,
|
||||
};
|
||||
this.menu = [
|
||||
{
|
||||
title: this.$t("Account") as string,
|
||||
to: { name: RouteName.ACCOUNT_SETTINGS } as Route,
|
||||
items: [
|
||||
{
|
||||
title: this.$t("General") as string,
|
||||
to: { name: RouteName.ACCOUNT_SETTINGS_GENERAL } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Preferences") as string,
|
||||
to: { name: RouteName.PREFERENCES } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Email notifications") as string,
|
||||
to: { name: RouteName.NOTIFICATIONS } as Route,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t("Profiles") as string,
|
||||
to: { name: RouteName.IDENTITIES } as Route,
|
||||
items: [this.newIdentity],
|
||||
},
|
||||
];
|
||||
if (
|
||||
[ICurrentUserRole.MODERATOR, ICurrentUserRole.ADMINISTRATOR].includes(this.currentUser.role)
|
||||
) {
|
||||
this.menu.push({
|
||||
title: this.$t("Moderation") as string,
|
||||
to: { name: RouteName.MODERATION } as Route,
|
||||
items: [
|
||||
{
|
||||
title: this.$t("Reports") as string,
|
||||
to: { name: RouteName.REPORTS } as Route,
|
||||
items: [
|
||||
{
|
||||
title: this.$t("Report") as string,
|
||||
to: { name: RouteName.REPORT } as Route,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t("Moderation log") as string,
|
||||
to: { name: RouteName.REPORT_LOGS } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Users") as string,
|
||||
to: { name: RouteName.USERS } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Profiles") as string,
|
||||
to: { name: RouteName.PROFILES } as Route,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (this.currentUser.role === ICurrentUserRole.ADMINISTRATOR) {
|
||||
this.menu.push({
|
||||
title: this.$t("Admin") as string,
|
||||
to: { name: RouteName.ADMIN } as Route,
|
||||
items: [
|
||||
{
|
||||
title: this.$t("Dashboard") as string,
|
||||
to: { name: RouteName.ADMIN_DASHBOARD } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Instance settings") as string,
|
||||
to: { name: RouteName.ADMIN_SETTINGS } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Federation") as string,
|
||||
to: { name: RouteName.RELAYS } as Route,
|
||||
items: [
|
||||
{
|
||||
title: this.$t("Followings") as string,
|
||||
to: { name: RouteName.RELAY_FOLLOWINGS } as Route,
|
||||
},
|
||||
{
|
||||
title: this.$t("Followers") as string,
|
||||
to: { name: RouteName.RELAY_FOLLOWERS } as Route,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Watch("identities")
|
||||
updateIdentities(identities: IPerson[]) {
|
||||
if (!identities) return;
|
||||
if (!this.menu[1].items) return;
|
||||
this.menu[1].items = [];
|
||||
this.menu[1].items.push(
|
||||
...identities.map((identity: IPerson) => ({
|
||||
to: ({
|
||||
name: RouteName.UPDATE_IDENTITY,
|
||||
params: { identityName: identity.preferredUsername },
|
||||
} as unknown) as Route,
|
||||
title: `@${identity.preferredUsername}`,
|
||||
}))
|
||||
);
|
||||
this.menu[1].items.push(this.newIdentity);
|
||||
}
|
||||
|
||||
get routes(): Map<string, Route[]> {
|
||||
return this.getPath(this.menu);
|
||||
}
|
||||
|
||||
getPath(object: ISettingMenuSection[]) {
|
||||
function iter(menu: ISettingMenuSection[] | ISettingMenuSection, acc: ISettingMenuSection[]) {
|
||||
if (Array.isArray(menu)) {
|
||||
return menu.forEach((item: ISettingMenuSection) => {
|
||||
iter(item, acc.concat(item));
|
||||
});
|
||||
}
|
||||
if (menu.items && menu.items.length > 0) {
|
||||
return menu.items.forEach((item: ISettingMenuSection) => {
|
||||
iter(item, acc.concat(item));
|
||||
});
|
||||
}
|
||||
result.set(menu.to.name, acc);
|
||||
}
|
||||
|
||||
const result = new Map();
|
||||
iter(object, []);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -1,4 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ACCOUNT_SETTINGS }">{{ $t("Account") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.ACCOUNT_SETTINGS_GENERAL }">{{
|
||||
$t("General")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<div class="setting-title">
|
||||
<h2>{{ $t("Email") }}</h2>
|
||||
@ -140,6 +153,7 @@
|
||||
</section>
|
||||
</b-modal>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -1,5 +1,17 @@
|
||||
<template>
|
||||
<div v-if="loggedUser">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ACCOUNT_SETTINGS }">{{ $t("Account") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.NOTIFICATIONS }">{{
|
||||
$t("Email notifications")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<div class="setting-title">
|
||||
<h2>{{ $t("Participation notifications") }}</h2>
|
||||
|
@ -1,4 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ACCOUNT_SETTINGS }">{{ $t("Account") }}</router-link>
|
||||
</li>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.PREFERENCES }">{{ $t("Preferences") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div>
|
||||
<b-field :label="$t('Language')">
|
||||
<b-select
|
||||
@ -34,6 +45,7 @@
|
||||
})
|
||||
}}</em>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
@ -42,6 +54,7 @@ import { USER_SETTINGS, SET_USER_SETTINGS, UPDATE_USER_LOCALE } from "../../grap
|
||||
import { IConfig } from "../../types/config.model";
|
||||
import { ICurrentUser } from "../../types/current-user.model";
|
||||
import langs from "../../i18n/langs.json";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
@ -58,6 +71,8 @@ export default class Preferences extends Vue {
|
||||
|
||||
locale: string | null = null;
|
||||
|
||||
RouteName = RouteName;
|
||||
|
||||
@Watch("loggedUser")
|
||||
setSavedTimezone(loggedUser: ICurrentUser) {
|
||||
if (loggedUser && loggedUser.settings.timezone) {
|
||||
|
Loading…
Reference in New Issue
Block a user