Add a proper setting menu
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
<template>
|
||||
<section class="section container">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li class="is-active">
|
||||
<router-link :to="{ name: RouteName.UPDATE_IDENTITY }" aria-current="page">{{ $t('My account') }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div v-if="currentActor">
|
||||
<div class="header">
|
||||
<figure v-if="currentActor.banner" class="image is-3by1">
|
||||
<img :src="currentActor.banner.url" alt="banner">
|
||||
</figure>
|
||||
</div>
|
||||
|
||||
<div class="columns">
|
||||
<div class="identities column is-4">
|
||||
<identities :currentIdentityName="currentIdentityName" />
|
||||
<div class="buttons">
|
||||
<b-button tag="router-link" type="is-secondary" :to="{ name: RouteName.ACCOUNT_SETTINGS }">{{ $t('Account settings') }}</b-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.header {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.identities {
|
||||
padding-right: 45px;
|
||||
margin-right: 45px;
|
||||
|
||||
.buttons {
|
||||
margin-top: 1.2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { CURRENT_ACTOR_CLIENT } from '@/graphql/actor';
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator';
|
||||
import EventCard from '@/components/Event/EventCard.vue';
|
||||
import { IPerson } from '@/types/actor';
|
||||
import Identities from '@/components/Account/Identities.vue';
|
||||
import { RouteName } from '@/router';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
EventCard,
|
||||
Identities,
|
||||
},
|
||||
apollo: {
|
||||
currentActor: {
|
||||
query: CURRENT_ACTOR_CLIENT,
|
||||
},
|
||||
},
|
||||
})
|
||||
export default class MyAccount extends Vue {
|
||||
currentActor!: IPerson;
|
||||
currentIdentityName: string | null = null;
|
||||
|
||||
RouteName = RouteName;
|
||||
|
||||
@Watch('$route.params.identityName', { immediate: true })
|
||||
async onIdentityParamChanged(val: string) {
|
||||
await this.redirectIfNoIdentitySelected(val);
|
||||
|
||||
this.currentIdentityName = val;
|
||||
}
|
||||
|
||||
private async redirectIfNoIdentitySelected(identityParam?: string) {
|
||||
if (!!identityParam) return;
|
||||
|
||||
if (!!this.currentActor) {
|
||||
await this.$router.push({ params: { identityName: this.currentActor.preferredUsername } });
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "../../variables";
|
||||
@import "~bulma/sass/utilities/_all";
|
||||
@import "~bulma/sass/components/dropdown.sass";
|
||||
</style>
|
||||
@@ -116,7 +116,7 @@ import { CREATE_FEED_TOKEN_ACTOR } from '@/graphql/feed_tokens';
|
||||
EventCard,
|
||||
},
|
||||
})
|
||||
export default class MyAccount extends Vue {
|
||||
export default class Profile extends Vue {
|
||||
@Prop({ type: String, required: true }) name!: string;
|
||||
|
||||
person!: IPerson;
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
<template>
|
||||
<section class="section container">
|
||||
<section>
|
||||
<h1 class="title">{{ $t('Administration') }}</h1>
|
||||
<div class="tile is-ancestor" v-if="dashboard">
|
||||
<div class="tile is-vertical is-4">
|
||||
<div class="tile is-vertical">
|
||||
<div class="tile">
|
||||
<div class="tile is-parent is-vertical is-6">
|
||||
<article class="tile is-child box">
|
||||
<p class="title">{{ dashboard.numberOfEvents }}</p>
|
||||
<p class="dashboard-number">{{ dashboard.numberOfEvents }}</p>
|
||||
<p>{{ $t('Published events')}}</p>
|
||||
</article>
|
||||
<article class="tile is-child box">
|
||||
<p class="title">{{ dashboard.numberOfComments}}</p>
|
||||
<p class="dashboard-number">{{ dashboard.numberOfComments}}</p>
|
||||
<p>{{ $t('Comments')}}</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent is-vertical">
|
||||
<article class="tile is-child box">
|
||||
<p class="title">{{ dashboard.numberOfUsers }}</p>
|
||||
<p class="dashboard-number">{{ dashboard.numberOfUsers }}</p>
|
||||
<p>{{ $t('Users')}}</p>
|
||||
</article>
|
||||
<router-link :to="{ name: RouteName.REPORTS}">
|
||||
<article class="tile is-child box">
|
||||
<p class="title">{{ dashboard.numberOfReports }}</p>
|
||||
<p class="dashboard-number">{{ dashboard.numberOfReports }}</p>
|
||||
<p>{{ $t('Opened reports')}}</p>
|
||||
</article>
|
||||
</router-link>
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="tile is-parent" v-if="dashboard.lastPublicEventPublished">
|
||||
<router-link :to="{ name: RouteName.EVENT, params: { uuid: dashboard.lastPublicEventPublished.uuid } }">
|
||||
<article class="tile is-child box">
|
||||
<p class="title">{{ $t('Last published event') }}</p>
|
||||
<p class="dashboard-number">{{ $t('Last published event') }}</p>
|
||||
<p class="subtitle">{{ dashboard.lastPublicEventPublished.title }}</p>
|
||||
<figure class="image is-4by3" v-if="dashboard.lastPublicEventPublished.picture">
|
||||
<img :src="dashboard.lastPublicEventPublished.picture.url" />
|
||||
@@ -38,33 +38,6 @@
|
||||
</article>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<router-link :to="{ name: RouteName.RELAYS }">
|
||||
<article class="tile is-child box">
|
||||
<span>{{ $t('Instances') }}</span>
|
||||
</article>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<router-link :to="{ name: RouteName.ADMIN_SETTINGS }">
|
||||
<article class="tile is-child box">
|
||||
<span>{{ $t('Settings') }}</span>
|
||||
</article>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child box">
|
||||
<div class="content">
|
||||
<p class="title">{{ $t('Welcome on your administration panel') }}</p>
|
||||
<p class="subtitle">With even more content</p>
|
||||
<div class="content">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam semper diam at erat pulvinar, at pulvinar felis blandit. Vestibulum volutpat tellus diam, consequat gravida libero rhoncus ut. Morbi maximus, leo sit amet vehicula eleifend, nunc dui porta orci, quis semper odio felis ut quam.</p>
|
||||
<p>Suspendisse varius ligula in molestie lacinia. Maecenas varius eget ligula a sagittis. Pellentesque interdum, nisl nec interdum maximus, augue diam porttitor lorem, et sollicitudin felis neque sit amet erat. Maecenas imperdiet felis nisi, fringilla luctus felis hendrerit sit amet. Aenean vitae gravida diam, finibus dignissim turpis. Sed eget varius ligula, at volutpat tortor.</p>
|
||||
<p>Integer sollicitudin, tortor a mattis commodo, velit urna rhoncus erat, vitae congue lectus dolor consequat libero. Donec leo ligula, maximus et pellentesque sed, gravida a metus. Cras ullamcorper a nunc ac porta. Aliquam ut aliquet lacus, quis faucibus libero. Quisque non semper leo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -92,4 +65,13 @@ export default class Dashboard extends Vue {
|
||||
dashboard!: IDashboard;
|
||||
RouteName = RouteName;
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-number {
|
||||
color: #3C376E;
|
||||
font-size: 40px;
|
||||
font-weight: 700;
|
||||
line-height: 1.125;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<section class="section container">
|
||||
<section>
|
||||
<h1 class="title">{{ $t('Instances') }}</h1>
|
||||
<div class="tabs is-boxed">
|
||||
<ul>
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<section class="container section" v-if="adminSettings">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li><router-link :to="{ name: RouteName.DASHBOARD }">{{ $t('Dashboard') }}</router-link></li>
|
||||
<li class="is-active"><router-link :to="{ name: RouteName.ADMIN_SETTINGS }" aria-current="page">{{ $t('Admin settings') }}</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section v-if="adminSettings">
|
||||
<form @submit.prevent="updateSettings">
|
||||
<b-field :label="$t('Instance Name')">
|
||||
<b-input v-model="adminSettings.instanceName" />
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<section class="section container">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li><router-link :to="{ name: RouteName.DASHBOARD }">Dashboard</router-link></li>
|
||||
<li class="is-active"><router-link :to="{ name: RouteName.LOGS }" aria-current="page">Logs</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<ul v-if="actionLogs.length > 0">
|
||||
<li v-for="log in actionLogs">
|
||||
<div class="box">
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
<template>
|
||||
<section class="container section">
|
||||
<section>
|
||||
<b-message title="Error" type="is-danger" v-for="error in errors" :key="error">{{ error }}</b-message>
|
||||
<div class="container" v-if="report">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li><router-link :to="{ name: RouteName.DASHBOARD }">{{ $t('Dashboard') }}</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: { reportId: this.report.id} }" aria-current="page">{{ $t('Report') }}</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="buttons">
|
||||
<b-button v-if="report.status !== ReportStatusEnum.RESOLVED" @click="updateReport(ReportStatusEnum.RESOLVED)" type="is-primary">{{ $t('Mark as resolved') }}</b-button>
|
||||
<b-button v-if="report.status !== ReportStatusEnum.OPEN" @click="updateReport(ReportStatusEnum.OPEN)" type="is-success">{{ $t('Reopen') }}</b-button>
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<section class="container section">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li><router-link :to="{ name: RouteName.DASHBOARD }">{{ $t('Dashboard') }}</router-link></li>
|
||||
<li class="is-active"><router-link :to="{ name: RouteName.REPORTS }" aria-current="page">{{ $t('Reports') }}</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<b-field>
|
||||
<b-radio-button v-model="filterReports"
|
||||
:native-value="ReportStatusEnum.OPEN">
|
||||
|
||||
166
js/src/views/Settings.vue
Normal file
166
js/src/views/Settings.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<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">
|
||||
<ul>
|
||||
<li v-for="route in routes.get($route.name)" :class="{ 'is-active': route.to.name === $route.name }"><router-link :to="{ name: route.to.name }">{{ route.title }}</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator';
|
||||
import SettingsMenu from '@/components/Settings/SettingsMenu.vue';
|
||||
import { RouteName } from '@/router';
|
||||
import { ISettingMenuSection } from '@/types/setting-menu.model';
|
||||
import { Route } from 'vue-router';
|
||||
import { IPerson, Person } from '@/types/actor';
|
||||
import { IDENTITIES } from '@/graphql/actor';
|
||||
|
||||
@Component({
|
||||
components: { SettingsMenu },
|
||||
apollo: {
|
||||
identities: {
|
||||
query: IDENTITIES,
|
||||
update: (data) => { return data.identities.map(identity => new Person(identity)); },
|
||||
},
|
||||
},
|
||||
})
|
||||
export default class Settings extends Vue {
|
||||
RouteName = RouteName;
|
||||
|
||||
menu: ISettingMenuSection[] = [];
|
||||
identities!: IPerson[];
|
||||
newIdentity!: ISettingMenuSection;
|
||||
|
||||
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('Notifications') as string,
|
||||
to: { name: RouteName.NOTIFICATIONS } as Route,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: this.$t('Profiles') as string,
|
||||
to: { name: RouteName.IDENTITIES } as Route,
|
||||
items: [this.newIdentity],
|
||||
},
|
||||
{
|
||||
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('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) {
|
||||
if (!identities) return;
|
||||
if (!this.menu[1].items) return;
|
||||
this.menu[1].items = [];
|
||||
this.menu[1].items.push(...identities.map((identity: IPerson) => {
|
||||
return {
|
||||
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>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
aside.section {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<section class="section container">
|
||||
<nav class="breadcrumb" aria-label="breadcrumbs">
|
||||
<ul>
|
||||
<li><router-link :to="{ name: RouteName.UPDATE_IDENTITY }">{{ $t('My account') }}</router-link></li>
|
||||
<li class="is-active"><router-link :to="{ name: RouteName.ACCOUNT_SETTINGS }" aria-current="page">{{ $t('Account settings') }}</router-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section>
|
||||
<div class="setting-title">
|
||||
<h2>{{ $t('Email') }}</h2>
|
||||
</div>
|
||||
13
js/src/views/Settings/Notifications.vue
Normal file
13
js/src/views/Settings/Notifications.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="subtitle">{{ $t('No notification settings yet') }}</h2>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
@Component
|
||||
export default class Notifications extends Vue {
|
||||
|
||||
}
|
||||
</script>
|
||||
13
js/src/views/Settings/Preferences.vue
Normal file
13
js/src/views/Settings/Preferences.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="subtitle">{{ $t('No preferences yet') }}</h2>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
|
||||
@Component
|
||||
export default class Preferences extends Vue {
|
||||
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user