summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-11-02 23:05:53 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-11-02 23:05:53 +0900
commitf2e719b3612506493b0d27c4476fcd0879ed1eea (patch)
tree6d3af4d1fd886ea963f6a67821d669b4b1cd53fe /src
parent[API] Implement admin/add-emoji (diff)
downloadsharkey-f2e719b3612506493b0d27c4476fcd0879ed1eea.tar.gz
sharkey-f2e719b3612506493b0d27c4476fcd0879ed1eea.tar.bz2
sharkey-f2e719b3612506493b0d27c4476fcd0879ed1eea.zip
[Client] Admin page improved
Diffstat (limited to 'src')
-rw-r--r--src/client/app/admin/script.ts27
-rw-r--r--src/client/app/admin/style.styl6
-rw-r--r--src/client/app/admin/views/announcements.vue (renamed from src/client/app/desktop/views/pages/admin/admin.announcements.vue)17
-rw-r--r--src/client/app/admin/views/cpu-memory.vue (renamed from src/client/app/desktop/views/pages/admin/admin.cpu-memory.vue)0
-rw-r--r--src/client/app/admin/views/dashboard.vue117
-rw-r--r--src/client/app/admin/views/emoji.vue48
-rw-r--r--src/client/app/admin/views/hashtags.vue (renamed from src/client/app/desktop/views/pages/admin/admin.hashtags.vue)19
-rw-r--r--src/client/app/admin/views/index.vue101
-rw-r--r--src/client/app/admin/views/instance.vue62
-rw-r--r--src/client/app/admin/views/users.vue129
-rw-r--r--src/client/app/boot.js1
-rw-r--r--src/client/app/desktop/script.ts2
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.dashboard.vue135
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.suspend-user.vue57
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.unsuspend-user.vue58
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.unverify-user.vue57
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.verify-user.vue57
-rw-r--r--src/client/app/desktop/views/pages/admin/admin.vue140
18 files changed, 511 insertions, 522 deletions
diff --git a/src/client/app/admin/script.ts b/src/client/app/admin/script.ts
new file mode 100644
index 0000000000..4002734d3d
--- /dev/null
+++ b/src/client/app/admin/script.ts
@@ -0,0 +1,27 @@
+/**
+ * Admin
+ */
+
+import VueRouter from 'vue-router';
+
+// Style
+import './style.styl';
+
+import init from '../init';
+import Index from './views/index.vue';
+
+init(launch => {
+ document.title = 'Admin';
+
+ // Init router
+ const router = new VueRouter({
+ mode: 'history',
+ base: '/admin/',
+ routes: [
+ { path: '/', component: Index },
+ ]
+ });
+
+ // Launch the app
+ launch(router);
+});
diff --git a/src/client/app/admin/style.styl b/src/client/app/admin/style.styl
new file mode 100644
index 0000000000..5ea3950464
--- /dev/null
+++ b/src/client/app/admin/style.styl
@@ -0,0 +1,6 @@
+@import "../app"
+@import "../reset"
+
+html
+ height 100%
+ background #EBEBEB
diff --git a/src/client/app/desktop/views/pages/admin/admin.announcements.vue b/src/client/app/admin/views/announcements.vue
index 5c1ed74b29..049a8d5721 100644
--- a/src/client/app/desktop/views/pages/admin/admin.announcements.vue
+++ b/src/client/app/admin/views/announcements.vue
@@ -1,8 +1,12 @@
<template>
-<div class="qldxjjsrseehkusjuoooapmsprvfrxyl mk-admin-card">
- <header>%i18n:@announcements%</header>
- <textarea v-model="broadcasts" placeholder='[ { "title": "Title1", "text": "Text1" }, { "title": "Title2", "text": "Text2" } ]'></textarea>
- <button class="ui" @click="save">%i18n:@save%</button>
+<div>
+ <ui-card>
+ <div slot="title">%i18n:@announcements%</div>
+ <section>
+ <textarea class="qldxjjsrseehkusjuoooapmsprvfrxyl" v-model="broadcasts" placeholder='[ { "title": "Title1", "text": "Text1" }, { "title": "Title2", "text": "Text2" } ]'></textarea>
+ <ui-button @click="save">%i18n:@save%</ui-button>
+ </section>
+ </ui-card>
</div>
</template>
@@ -45,8 +49,7 @@ export default Vue.extend({
<style lang="stylus" scoped>
.qldxjjsrseehkusjuoooapmsprvfrxyl
- textarea
- width 100%
- min-height 300px
+ width 100%
+ min-height 300px
</style>
diff --git a/src/client/app/desktop/views/pages/admin/admin.cpu-memory.vue b/src/client/app/admin/views/cpu-memory.vue
index 5d03b30ef4..5d03b30ef4 100644
--- a/src/client/app/desktop/views/pages/admin/admin.cpu-memory.vue
+++ b/src/client/app/admin/views/cpu-memory.vue
diff --git a/src/client/app/admin/views/dashboard.vue b/src/client/app/admin/views/dashboard.vue
new file mode 100644
index 0000000000..5af5255e20
--- /dev/null
+++ b/src/client/app/admin/views/dashboard.vue
@@ -0,0 +1,117 @@
+<template>
+<div class="obdskegsannmntldydackcpzezagxqfy">
+ <div v-if="stats" class="stats">
+ <div>
+ <div>%fa:user%</div>
+ <div>
+ <span>%i18n:@original-users%</span>
+ <b>{{ stats.originalUsersCount | number }}</b>
+ </div>
+ </div>
+ <div>
+ <div>%fa:pencil-alt%</div>
+ <div>
+ <span>%i18n:@original-notes%</span>
+ <b>{{ stats.originalNotesCount | number }}</b>
+ </div>
+ </div>
+ <div>
+ <div>%fa:user%</div>
+ <div>
+ <span>%i18n:@all-users%</span>
+ <b>{{ stats.usersCount | number }}</b>
+ </div>
+ </div>
+ <div>
+ <div>%fa:pencil-alt%</div>
+ <div>
+ <span>%i18n:@all-notes%</span>
+ <b>{{ stats.notesCount | number }}</b>
+ </div>
+ </div>
+ </div>
+
+ <div class="cpu-memory">
+ <x-cpu-memory :connection="connection"/>
+ </div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from "vue";
+import XCpuMemory from "./cpu-memory.vue";
+
+export default Vue.extend({
+ components: {
+ XCpuMemory
+ },
+ data() {
+ return {
+ stats: null,
+ connection: null
+ };
+ },
+ created() {
+ this.connection = (this as any).os.stream.useSharedConnection('serverStats');
+
+ (this as any).os.getMeta().then(meta => {
+ this.disableRegistration = meta.disableRegistration;
+ this.disableLocalTimeline = meta.disableLocalTimeline;
+ this.bannerUrl = meta.bannerUrl;
+ });
+
+ (this as any).api('stats').then(stats => {
+ this.stats = stats;
+ });
+ },
+ beforeDestroy() {
+ this.connection.dispose();
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.obdskegsannmntldydackcpzezagxqfy
+ > .stats
+ display flex
+ justify-content space-between
+ margin-bottom 16px
+
+ > div
+ display flex
+ align-items center
+ flex 1
+ max-width 300px
+ margin-right 16px
+ text-align center
+ color var(--text)
+ box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
+ background var(--face)
+ border-radius 8px
+
+ &:last-child
+ margin-right 0
+
+ > div:first-child
+ padding 16px 24px
+ font-size 28px
+
+ > div:last-child
+ flex 1
+ padding 16px 32px 16px 0
+ text-align right
+
+ > span
+ opacity 0.7
+
+ > b
+ display block
+
+ > .cpu-memory
+ margin-bottom 16px
+ padding 32px
+ box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
+ background var(--face)
+ border-radius 8px
+
+</style>
diff --git a/src/client/app/admin/views/emoji.vue b/src/client/app/admin/views/emoji.vue
new file mode 100644
index 0000000000..1446cc1a91
--- /dev/null
+++ b/src/client/app/admin/views/emoji.vue
@@ -0,0 +1,48 @@
+<template>
+<div>
+ <ui-card>
+ <div slot="title">%fa:plus% %i18n:@add-emoji.title%</div>
+ <section class="fit-top">
+ <ui-input v-model="name">
+ <span>%i18n:@add-emoji.name%</span>
+ <span slot="text">%i18n:@add-emoji.name-desc%</span>
+ </ui-input>
+ <ui-input v-model="aliases">
+ <span>%i18n:@add-emoji.aliases%</span>
+ <span slot="text">%i18n:@add-emoji.aliases-desc%</span>
+ </ui-input>
+ <ui-input v-model="url">
+ <span>%i18n:@add-emoji.url%</span>
+ </ui-input>
+ <ui-button @click="add">%i18n:@add-emoji.add%</ui-button>
+ </section>
+ </ui-card>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from "vue";
+
+export default Vue.extend({
+ data() {
+ return {
+ name: '',
+ url: '',
+ aliases: '',
+ };
+ },
+ methods: {
+ add() {
+ (this as any).api('admin/add-emoji', {
+ name: this.name,
+ url: this.url,
+ aliases: this.aliases.split(' ')
+ }).then(() => {
+ (this as any).os.apis.dialog({ text: `Added` });
+ }).catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed ${e}` });
+ });
+ }
+ }
+});
+</script>
diff --git a/src/client/app/desktop/views/pages/admin/admin.hashtags.vue b/src/client/app/admin/views/hashtags.vue
index 10bab1cbd7..be90cea1db 100644
--- a/src/client/app/desktop/views/pages/admin/admin.hashtags.vue
+++ b/src/client/app/admin/views/hashtags.vue
@@ -1,8 +1,12 @@
<template>
-<div class="jdnqwkzlnxcfftthoybjxrebyolvoucw mk-admin-card">
- <header>%i18n:@hided-tags%</header>
- <textarea v-model="hidedTags"></textarea>
- <button class="ui" @click="save">%i18n:@save%</button>
+<div>
+ <ui-card>
+ <div slot="title">%i18n:@hided-tags%</div>
+ <section>
+ <textarea class="jdnqwkzlnxcfftthoybjxrebyolvoucw" v-model="hidedTags"></textarea>
+ <ui-button @click="save">%i18n:@save%</ui-button>
+ </section>
+ </ui-card>
</div>
</template>
@@ -35,11 +39,8 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
-
-
.jdnqwkzlnxcfftthoybjxrebyolvoucw
- textarea
- width 100%
- min-height 300px
+ width 100%
+ min-height 300px
</style>
diff --git a/src/client/app/admin/views/index.vue b/src/client/app/admin/views/index.vue
new file mode 100644
index 0000000000..c674bee028
--- /dev/null
+++ b/src/client/app/admin/views/index.vue
@@ -0,0 +1,101 @@
+<template>
+<div class="mk-admin">
+ <nav>
+ <ul>
+ <li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:home .fw%%i18n:@dashboard%</li>
+ <li @click="nav('instance')" :class="{ active: page == 'instance' }">%fa:cog .fw%%i18n:@instance%</li>
+ <li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
+ <li @click="nav('emoji')" :class="{ active: page == 'emoji' }">%fa:grin R .fw%%i18n:@emoji%</li>
+ <li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
+ <li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
+
+ <!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:common.drive%</li> -->
+ <!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
+ </ul>
+ </nav>
+ <main>
+ <div v-show="page == 'dashboard'"><x-dashboard/></div>
+ <div v-show="page == 'instance'"><x-instance/></div>
+ <div v-if="page == 'users'"><x-users/></div>
+ <div v-show="page == 'emoji'"><x-emoji/></div>
+ <div v-show="page == 'announcements'"><x-announcements/></div>
+ <div v-show="page == 'hashtags'"><x-hashtags/></div>
+ <div v-if="page == 'drive'"></div>
+ <div v-if="page == 'update'"></div>
+ </main>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from "vue";
+import XDashboard from "./dashboard.vue";
+import XInstance from "./instance.vue";
+import XEmoji from "./emoji.vue";
+import XAnnouncements from "./announcements.vue";
+import XHashtags from "./hashtags.vue";
+import XUsers from "./users.vue";
+
+export default Vue.extend({
+ components: {
+ XDashboard,
+ XInstance,
+ XEmoji,
+ XAnnouncements,
+ XHashtags,
+ XUsers
+ },
+ data() {
+ return {
+ page: 'dashboard'
+ };
+ },
+ methods: {
+ nav(page: string) {
+ this.page = page;
+ }
+ }
+});
+</script>
+
+<style lang="stylus">
+.mk-admin
+ display flex
+ height 100%
+
+ > nav
+ position fixed
+ z-index 10000
+ top 0
+ left 0
+ width 250px
+ height 100vh
+ padding 16px 0 0 0
+ overflow auto
+ background #333
+ color #fff
+
+ > ul
+ margin 0
+ padding 0
+ list-style none
+
+ > li
+ display block
+ padding 10px 16px
+ margin 0
+ cursor pointer
+ user-select none
+ transition margin-left 0.2s ease
+
+ > [data-fa]
+ margin-right 4px
+
+ &.active
+ margin-left 8px
+ color var(--primary) !important
+
+ > main
+ width 100%
+ padding 32px 32px 32px calc(32px + 250px)
+
+</style>
diff --git a/src/client/app/admin/views/instance.vue b/src/client/app/admin/views/instance.vue
new file mode 100644
index 0000000000..542a0d54ad
--- /dev/null
+++ b/src/client/app/admin/views/instance.vue
@@ -0,0 +1,62 @@
+<template>
+<div>
+ <ui-card>
+ <div slot="title">%i18n:@banner-url%</div>
+ <section class="fit-top">
+ <ui-input v-model="bannerUrl"/>
+ <ui-button @click="updateMeta">%i18n:@save%</ui-button>
+ </section>
+ </ui-card>
+
+ <ui-card>
+ <div slot="title">%i18n:@disable-registration%</div>
+ <section>
+ <input type="checkbox" v-model="disableRegistration" @change="updateMeta">
+ <button class="ui" @click="invite">%i18n:@invite%</button>
+ <p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
+ </section>
+ </ui-card>
+
+ <ui-card>
+ <div slot="title">%i18n:@disable-local-timeline%</div>
+ <section>
+ <input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta">
+ </section>
+ </ui-card>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from "vue";
+
+export default Vue.extend({
+ data() {
+ return {
+ disableRegistration: false,
+ disableLocalTimeline: false,
+ bannerUrl: null,
+ inviteCode: null,
+ };
+ },
+ methods: {
+ invite() {
+ (this as any).api('admin/invite').then(x => {
+ this.inviteCode = x.code;
+ }).catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed ${e}` });
+ });
+ },
+ updateMeta() {
+ (this as any).api('admin/update-meta', {
+ disableRegistration: this.disableRegistration,
+ disableLocalTimeline: this.disableLocalTimeline,
+ bannerUrl: this.bannerUrl
+ }).then(() => {
+ (this as any).os.apis.dialog({ text: `Saved` });
+ }).catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed ${e}` });
+ });
+ }
+ }
+});
+</script>
diff --git a/src/client/app/admin/views/users.vue b/src/client/app/admin/views/users.vue
new file mode 100644
index 0000000000..3c59943688
--- /dev/null
+++ b/src/client/app/admin/views/users.vue
@@ -0,0 +1,129 @@
+<template>
+<div>
+ <ui-card>
+ <div slot="title">%i18n:@verify-user%</div>
+ <section class="fit-top">
+ <ui-input v-model="verifyUsername" type="text">
+ <span slot="prefix">@</span>
+ </ui-input>
+ <ui-button @click="verifyUser" :disabled="verifying">%i18n:@verify%</ui-button>
+ </section>
+ </ui-card>
+
+ <ui-card>
+ <div slot="title">%i18n:@unverify-user%</div>
+ <section class="fit-top">
+ <ui-input v-model="unverifyUsername" type="text">
+ <span slot="prefix">@</span>
+ </ui-input>
+ <ui-button @click="unverifyUser" :disabled="unverifying">%i18n:@unverify%</ui-button>
+ </section>
+ </ui-card>
+
+ <ui-card>
+ <div slot="title">%i18n:@suspend-user%</div>
+ <section class="fit-top">
+ <ui-input v-model="suspendUsername" type="text">
+ <span slot="prefix">@</span>
+ </ui-input>
+ <ui-button @click="suspendUser" :disabled="suspending">%i18n:@suspend%</ui-button>
+ </section>
+ </ui-card>
+
+ <ui-card>
+ <div slot="title">%i18n:@unsuspend-user%</div>
+ <section class="fit-top">
+ <ui-input v-model="unsuspendUsername" type="text">
+ <span slot="prefix">@</span>
+ </ui-input>
+ <ui-button @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</ui-button>
+ </section>
+ </ui-card>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from "vue";
+import parseAcct from "../../../../misc/acct/parse";
+
+export default Vue.extend({
+ data() {
+ return {
+ verifyUsername: null,
+ verifying: false,
+ unverifyUsername: null,
+ unverifying: false,
+ suspendUsername: null,
+ suspending: false,
+ unsuspendUsername: null,
+ unsuspending: false
+ };
+ },
+
+ methods: {
+ async verifyUser() {
+ this.verifying = true;
+
+ const process = async () => {
+ const user = await (this as any).os.api('users/show', parseAcct(this.verifyUsername));
+ await (this as any).os.api('admin/verify-user', { userId: user.id });
+ (this as any).os.apis.dialog({ text: '%i18n:@verified%' });
+ };
+
+ await process().catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed: ${e}` });
+ });
+
+ this.verifying = false;
+ },
+
+ async unverifyUser() {
+ this.unverifying = true;
+
+ const process = async () => {
+ const user = await (this as any).os.api('users/show', parseAcct(this.unverifyUsername));
+ await (this as any).os.api('admin/unverify-user', { userId: user.id });
+ (this as any).os.apis.dialog({ text: '%i18n:@unverified%' });
+ };
+
+ await process().catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed: ${e}` });
+ });
+
+ this.unverifying = false;
+ },
+
+ async suspendUser() {
+ this.suspending = true;
+
+ const process = async () => {
+ const user = await (this as any).os.api('users/show', parseAcct(this.suspendUsername));
+ await (this as any).os.api('admin/suspend-user', { userId: user.id });
+ (this as any).os.apis.dialog({ text: '%i18n:@suspended%' });
+ };
+
+ await process().catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed: ${e}` });
+ });
+
+ this.suspending = false;
+ },
+
+ async unsuspendUser() {
+ this.unsuspending = true;
+
+ const process = async () => {
+ const user = await (this as any).os.api('users/show', parseAcct(this.unsuspendUsername));
+ await (this as any).os.api('admin/unsuspend-user', { userId: user.id });
+ (this as any).os.apis.dialog({ text: '%i18n:@unsuspended%' });
+ };
+
+ await process().catch(e => {
+ (this as any).os.apis.dialog({ text: `Failed: ${e}` });
+ });
+
+ this.unsuspending = false;
+ }
+ }
+});
+</script>
diff --git a/src/client/app/boot.js b/src/client/app/boot.js
index 063749caee..0d5eefaea9 100644
--- a/src/client/app/boot.js
+++ b/src/client/app/boot.js
@@ -46,6 +46,7 @@
if (`${url.pathname}/`.startsWith('/docs/')) app = 'docs';
if (`${url.pathname}/`.startsWith('/dev/')) app = 'dev';
if (`${url.pathname}/`.startsWith('/auth/')) app = 'auth';
+ if (`${url.pathname}/`.startsWith('/admin/')) app = 'admin';
//#endregion
//#region Detect the user language
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 765ba0202e..255589b014 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -23,7 +23,6 @@ import updateBanner from './api/update-banner';
import MkIndex from './views/pages/index.vue';
import MkHome from './views/pages/home.vue';
import MkDeck from './views/pages/deck/deck.vue';
-import MkAdmin from './views/pages/admin/admin.vue';
import MkStats from './views/pages/stats/stats.vue';
import MkUser from './views/pages/user/user.vue';
import MkFavorites from './views/pages/favorites.vue';
@@ -57,7 +56,6 @@ init(async (launch) => {
{ path: '/', name: 'index', component: MkIndex },
{ path: '/home', name: 'home', component: MkHome },
{ path: '/deck', name: 'deck', component: MkDeck },
- { path: '/admin', name: 'admin', component: MkAdmin },
{ path: '/stats', name: 'stats', component: MkStats },
{ path: '/i/customize-home', component: MkHomeCustomize },
{ path: '/i/favorites', component: MkFavorites },
diff --git a/src/client/app/desktop/views/pages/admin/admin.dashboard.vue b/src/client/app/desktop/views/pages/admin/admin.dashboard.vue
deleted file mode 100644
index c0075220bc..0000000000
--- a/src/client/app/desktop/views/pages/admin/admin.dashboard.vue
+++ /dev/null
@@ -1,135 +0,0 @@
-<template>
-<div class="obdskegsannmntldydackcpzezagxqfy mk-admin-card">
- <header>%i18n:@dashboard%</header>
-
- <div v-if="stats" class="stats">
- <div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div>
- <div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div>
- <div><b>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div>
- <div><span>%fa:pencil-alt% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div>
- </div>
-
- <div class="cpu-memory">
- <x-cpu-memory :connection="connection"/>
- </div>
-
- <div v-if="this.$store.state.i && this.$store.state.i.isAdmin" class="form">
- <div>
- <label>
- <p>%i18n:@banner-url%</p>
- <input v-model="bannerUrl">
- </label>
- <button class="ui" @click="updateMeta">%i18n:@save%</button>
- </div>
-
- <div>
- <label>
- <input type="checkbox" v-model="disableRegistration" @change="updateMeta">
- <span>%i18n:@disableRegistration%</span>
- </label>
- <button class="ui" @click="invite">%i18n:@invite%</button>
- <p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
- </div>
-
- <div>
- <label>
- <input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta">
- <span>%i18n:@disableLocalTimeline%</span>
- </label>
- </div>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from "vue";
-import XCpuMemory from "./admin.cpu-memory.vue";
-
-export default Vue.extend({
- components: {
- XCpuMemory
- },
- data() {
- return {
- stats: null,
- disableRegistration: false,
- disableLocalTimeline: false,
- bannerUrl: null,
- inviteCode: null,
- connection: null
- };
- },
- created() {
- this.connection = (this as any).os.stream.useSharedConnection('serverStats');
-
- (this as any).os.getMeta().then(meta => {
- this.disableRegistration = meta.disableRegistration;
- this.disableLocalTimeline = meta.disableLocalTimeline;
- this.bannerUrl = meta.bannerUrl;
- });
-
- (this as any).api('stats').then(stats => {
- this.stats = stats;
- });
- },
- beforeDestroy() {
- this.connection.dispose();
- },
- methods: {
- invite() {
- (this as any).api('admin/invite').then(x => {
- this.inviteCode = x.code;
- }).catch(e => {
- (this as any).os.apis.dialog({ text: `Failed ${e}` });
- });
- },
- updateMeta() {
- (this as any).api('admin/update-meta', {
- disableRegistration: this.disableRegistration,
- disableLocalTimeline: this.disableLocalTimeline,
- bannerUrl: this.bannerUrl
- }).then(() => {
- (this as any).os.apis.dialog({ text: `Saved` });
- }).catch(e => {
- (this as any).os.apis.dialog({ text: `Failed ${e}` });
- });
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-
-
-.obdskegsannmntldydackcpzezagxqfy
- > .stats
- display flex
- justify-content center
- margin-bottom 16px
- padding 16px
- border solid 1px #eee
- border-radius 8px
-
- > div
- flex 1
- text-align center
-
- > *:first-child
- display block
- color var(--primary)
-
- > *:last-child
- font-size 70%
-
- > .cpu-memory
- margin-bottom 16px
- padding 16px
- border solid 1px #eee
- border-radius: 8px
-
- > .form
- > div
- padding 16px
- border-bottom solid 1px #eee
-
-</style>
diff --git a/src/client/app/desktop/views/pages/admin/admin.suspend-user.vue b/src/client/app/desktop/views/pages/admin/admin.suspend-user.vue
deleted file mode 100644
index a8ff937bbe..0000000000
--- a/src/client/app/desktop/views/pages/admin/admin.suspend-user.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-<template>
-<div class="mk-admin-card">
- <header>%i18n:@suspend-user%</header>
- <input v-model="username" type="text" class="ui"/>
- <button class="ui" @click="suspendUser" :disabled="suspending">%i18n:@suspend%</button>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from "vue";
-import parseAcct from "../../../../../../misc/acct/parse";
-
-export default Vue.extend({
- data() {
- return {
- username: null,
- suspending: false
- };
- },
- methods: {
- async suspendUser() {
- this.suspending = true;
-
- const process = async () => {
- const user = await (this as any).os.api(
- "users/show",
- parseAcct(this.username)
- );
-
- await (this as any).os.api("admin/suspend-user", {
- userId: user.id
- });
-
- (this as any).os.apis.dialog({ text: "%i18n:@suspended%" });
- };
-
- await process().catch(e => {
- (this as any).os.apis.dialog({ text: `Failed: ${e}` });
- });
-
- this.suspending = false;
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-
-
-header
- margin 10px 0
-
-
-button
- margin 16px 0
-
-</style>
diff --git a/src/client/app/desktop/views/pages/admin/admin.unsuspend-user.vue b/src/client/app/desktop/views/pages/admin/admin.unsuspend-user.vue
deleted file mode 100644
index 146f5a41d4..0000000000
--- a/src/client/app/desktop/views/pages/admin/admin.unsuspend-user.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-<template>
-<div class="mk-admin-card">
- <header>%i18n:@unsuspend-user%</header>
- <input v-model="username" type="text" class="ui"/>
- <button class="ui" @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</button>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from "vue";
-import parseAcct from "../../../../../../misc/acct/parse";
-
-export default Vue.extend({
- data() {
- return {
- username: null,
- unsuspending: false
- };
- },
- methods: {
- async unsuspendUser() {
- this.unsuspending = true;
-
- const process = async () => {
- const user = await (this as any).os.api(
- "users/show",
- parseAcct(this.username)
- );
-
- await (this as any).os.api("admin/unsuspend-user", {
- userId: user.id
- });
-
- (this as any).os.apis.dialog({ text: "%i18n:@unsuspended%" });
- };
-
- await process().catch(e => {
- (this as any).os.apis.dialog({ text: `Failed: ${e}` });
- });
-
- this.unsuspending = false;
-
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-
-
-header
- margin 10px 0
-
-
-button
- margin 16px 0
-
-</style>
diff --git a/src/client/app/desktop/views/pages/admin/admin.unverify-user.vue b/src/client/app/desktop/views/pages/admin/admin.unverify-user.vue
deleted file mode 100644
index 5e0fdae5c1..0000000000
--- a/src/client/app/desktop/views/pages/admin/admin.unverify-user.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-<template>
-<div class="mk-admin-card">
- <header>%i18n:@unverify-user%</header>
- <input v-model="username" type="text" class="ui"/>
- <button class="ui" @click="unverifyUser" :disabled="unverifying">%i18n:@unverify%</button>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from "vue";
-import parseAcct from "../../../../../../misc/acct/parse";
-
-export default Vue.extend({
- data() {
- return {
- username: null,
- unverifying: false
- };
- },
- methods: {
- async unverifyUser() {
- this.unverifying = true;
-
- const process = async () => {
- const user = await (this as any).os.api(
- "users/show",
- parseAcct(this.username)
- );
-
- await (this as any).os.api("admin/unverify-user", {
- userId: user.id
- });
-
- (this as any).os.apis.dialog({ text: "%i18n:@unverified%" });
- };
-
- await process().catch(e => {
- (this as any).os.apis.dialog({ text: `Failed: ${e}` });
- });
-
- this.unverifying = false;
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-
-
-header
- margin 10px 0
-
-
-button
- margin 16px 0
-
-</style>
diff --git a/src/client/app/desktop/views/pages/admin/admin.verify-user.vue b/src/client/app/desktop/views/pages/admin/admin.verify-user.vue
deleted file mode 100644
index d237a5f9c1..0000000000
--- a/src/client/app/desktop/views/pages/admin/admin.verify-user.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-<template>
-<div class="mk-admin-card">
- <header>%i18n:@verify-user%</header>
- <input v-model="username" type="text" class="ui"/>
- <button class="ui" @click="verifyUser" :disabled="verifying">%i18n:@verify%</button>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from "vue";
-import parseAcct from "../../../../../../misc/acct/parse";
-
-export default Vue.extend({
- data() {
- return {
- username: null,
- verifying: false
- };
- },
- methods: {
- async verifyUser() {
- this.verifying = true;
-
- const process = async () => {
- const user = await (this as any).os.api(
- "users/show",
- parseAcct(this.username)
- );
-
- await (this as any).os.api("admin/verify-user", {
- userId: user.id
- });
-
- (this as any).os.apis.dialog({ text: "%i18n:@verified%" });
- };
-
- await process().catch(e => {
- (this as any).os.apis.dialog({ text: `Failed: ${e}` });
- });
-
- this.verifying = false;
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-
-
-header
- margin 10px 0
-
-
-button
- margin 16px 0
-
-</style>
diff --git a/src/client/app/desktop/views/pages/admin/admin.vue b/src/client/app/desktop/views/pages/admin/admin.vue
deleted file mode 100644
index c1f5a7f0e0..0000000000
--- a/src/client/app/desktop/views/pages/admin/admin.vue
+++ /dev/null
@@ -1,140 +0,0 @@
-<template>
-<div class="mk-admin">
- <nav>
- <ul>
- <li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:chalkboard .fw%%i18n:@dashboard%</li>
-
- <li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
- @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
-
- <li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
- @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
-
- <li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
- @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
-
- <!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:common.drive%</li> -->
- <!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
- </ul>
- </nav>
- <main>
- <div v-show="page == 'dashboard'">
- <x-dashboard/>
- <x-charts/>
- </div>
- <div v-show="page == 'announcements'">
- <x-announcements/>
- </div>
- <div v-show="page == 'hashtags'">
- <x-hashtags/>
- </div>
- <div v-if="page == 'users'">
- <x-suspend-user/>
- <x-unsuspend-user/>
- <x-verify-user/>
- <x-unverify-user/>
- </div>
- <div v-if="page == 'drive'"></div>
- <div v-if="page == 'update'"></div>
- </main>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from "vue";
-import XDashboard from "./admin.dashboard.vue";
-import XAnnouncements from "./admin.announcements.vue";
-import XHashtags from "./admin.hashtags.vue";
-import XSuspendUser from "./admin.suspend-user.vue";
-import XUnsuspendUser from "./admin.unsuspend-user.vue";
-import XVerifyUser from "./admin.verify-user.vue";
-import XUnverifyUser from "./admin.unverify-user.vue";
-import XCharts from "../../components/charts.vue";
-
-export default Vue.extend({
- components: {
- XDashboard,
- XAnnouncements,
- XHashtags,
- XSuspendUser,
- XUnsuspendUser,
- XVerifyUser,
- XUnverifyUser,
- XCharts
- },
- data() {
- return {
- page: 'dashboard'
- };
- },
- methods: {
- nav(page: string) {
- this.page = page;
- }
- }
-});
-</script>
-
-<style lang="stylus">
-
-
-.mk-admin
- display flex
- height 100%
- margin 32px
-
- > nav
- flex 0 0 250px
- width 100%
- height 100%
- padding 16px 0 0 0
- overflow auto
- border-right solid 1px #ddd
-
- > ul
- list-style none
-
- > li
- display block
- padding 10px 16px
- margin 0
- color #666
- cursor pointer
- user-select none
- transition margin-left 0.2s ease
-
- > [data-fa]
- margin-right 4px
-
-
- &:hover
- color #555
-
- &.active
- margin-left 8px
- color var(--primary) !important
-
- > main
- width 100%
- padding 16px 32px
-
- > div
- > div
- max-width 800px
-
-.mk-admin-card
- padding 32px
- background #fff
- box-shadow 0 2px 8px rgba(#000, 0.1)
-
- &:not(:last-child)
- margin-bottom 16px
-
- > header
- margin 0 0 1em 0
- padding 0 0 8px 0
- font-size 1em
- color #555
- border-bottom solid 1px #eee
-
-</style>