diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2019-02-07 18:11:20 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2019-02-07 18:11:20 +0900 |
| commit | c3140f57b99f9f11437279695b05ee3eccff41ca (patch) | |
| tree | d3f3e30c509c54f7443dc7712479842c03ab5b35 /src | |
| parent | Improve instance stats (diff) | |
| download | sharkey-c3140f57b99f9f11437279695b05ee3eccff41ca.tar.gz sharkey-c3140f57b99f9f11437279695b05ee3eccff41ca.tar.bz2 sharkey-c3140f57b99f9f11437279695b05ee3eccff41ca.zip | |
連合しているインスタンスを一覧できるように
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/app/admin/views/dashboard.vue | 2 | ||||
| -rw-r--r-- | src/client/app/admin/views/federation.vue | 141 | ||||
| -rw-r--r-- | src/client/app/admin/views/index.vue | 10 | ||||
| -rw-r--r-- | src/server/api/endpoints/federation/instances.ts | 84 | ||||
| -rw-r--r-- | src/server/api/endpoints/federation/show-instance.ts | 20 | ||||
| -rw-r--r-- | src/server/api/endpoints/instances.ts | 51 |
6 files changed, 253 insertions, 55 deletions
diff --git a/src/client/app/admin/views/dashboard.vue b/src/client/app/admin/views/dashboard.vue index d21bd17202..b78bd9af10 100644 --- a/src/client/app/admin/views/dashboard.vue +++ b/src/client/app/admin/views/dashboard.vue @@ -124,7 +124,7 @@ export default Vue.extend({ this.meta = meta; }); - this.$root.api('instances', { + this.$root.api('federation/instances', { sort: '+notes' }).then(instances => { for (const i of instances) { diff --git a/src/client/app/admin/views/federation.vue b/src/client/app/admin/views/federation.vue new file mode 100644 index 0000000000..3c23da5139 --- /dev/null +++ b/src/client/app/admin/views/federation.vue @@ -0,0 +1,141 @@ +<template> +<div> + <ui-card> + <div slot="title"><fa :icon="faTerminal"/> {{ $t('federation') }}</div> + <section class="fit-top"> + <ui-input class="target" v-model="target" type="text" @enter="showInstance"> + <span>{{ $t('host') }}</span> + </ui-input> + <ui-button @click="showInstance"><fa :icon="faSearch"/> {{ $t('lookup') }}</ui-button> + + <div class="instance" v-if="instance"> + {{ instance.host }} + </div> + </section> + </ui-card> + + <ui-card> + <div slot="title"><fa :icon="faUsers"/> {{ $t('instances') }}</div> + <section class="fit-top"> + <ui-horizon-group inputs> + <ui-select v-model="sort"> + <span slot="label">{{ $t('sort') }}</span> + <option value="-caughtAt">{{ $t('sorts.caughtAtAsc') }}</option> + <option value="+caughtAt">{{ $t('sorts.caughtAtDesc') }}</option> + <option value="-notes">{{ $t('sorts.notesAsc') }}</option> + <option value="+notes">{{ $t('sorts.notesDesc') }}</option> + <option value="-users">{{ $t('sorts.usersAsc') }}</option> + <option value="+users">{{ $t('sorts.usersDesc') }}</option> + <option value="-following">{{ $t('sorts.followingAsc') }}</option> + <option value="+following">{{ $t('sorts.followingDesc') }}</option> + <option value="-followers">{{ $t('sorts.followersAsc') }}</option> + <option value="+followers">{{ $t('sorts.followersDesc') }}</option> + </ui-select> + </ui-horizon-group> + + <div class="instances"> + <header> + <span>{{ $t('host') }}</span> + <span>{{ $t('notes') }}</span> + <span>{{ $t('users') }}</span> + <span>{{ $t('following') }}</span> + <span>{{ $t('followers') }}</span> + <span>{{ $t('status') }}</span> + </header> + <div v-for="instance in instances"> + <span>{{ instance.host }}</span> + <span>{{ instance.notesCount | number }}</span> + <span>{{ instance.usersCount | number }}</span> + <span>{{ instance.followingCount | number }}</span> + <span>{{ instance.followersCount | number }}</span> + <span>{{ instance.latestStatus }}</span> + </div> + </div> + </section> + </ui-card> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../i18n'; +import { faGlobe, faTerminal, faSearch } from '@fortawesome/free-solid-svg-icons'; + +export default Vue.extend({ + i18n: i18n('admin/views/federation.vue'), + + data() { + return { + instance: null, + target: null, + sort: '+caughtAt', + limit: 50, + instances: [], + faGlobe, faTerminal, faSearch + }; + }, + + watch: { + sort() { + this.instances = []; + this.fetchInstances(); + }, + }, + + mounted() { + this.fetchInstances(); + }, + + methods: { + showInstance() { + this.$root.api('federation/show-instance', { + host: this.target + }).then(instance => { + if (instance == null) { + this.$root.dialog({ + type: 'error', + text: this.$t('instance-not-registered') + }); + } else { + this.instance = instance; + this.target = ''; + } + }); + }, + + fetchInstances() { + this.$root.api('federation/instances', { + sort: this.sort + }).then(instances => { + this.instances = instances; + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.target + margin-bottom 16px !important + +.instances + width 100% + + > header + display flex + + > * + color var(--text) + font-weight bold + + > div + display flex + + > * > * + flex 1 + overflow auto + + &:first-child + min-width 200px + +</style> diff --git a/src/client/app/admin/views/index.vue b/src/client/app/admin/views/index.vue index 9de1da0d09..b37bb8f7f5 100644 --- a/src/client/app/admin/views/index.vue +++ b/src/client/app/admin/views/index.vue @@ -24,7 +24,7 @@ <li @click="nav('moderators')" :class="{ active: page == 'moderators' }"><fa :icon="faHeadset" fixed-width/>{{ $t('moderators') }}</li> <li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>{{ $t('users') }}</li> <li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li> - <!-- <li @click="nav('federation')" :class="{ active: page == 'federation' }"><fa :icon="faShareAlt" fixed-width/>{{ $t('federation') }}</li> --> + <li @click="nav('federation')" :class="{ active: page == 'federation' }"><fa :icon="faGlobe" fixed-width/>{{ $t('federation') }}</li> <li @click="nav('emoji')" :class="{ active: page == 'emoji' }"><fa :icon="faGrin" fixed-width/>{{ $t('emoji') }}</li> <li @click="nav('announcements')" :class="{ active: page == 'announcements' }"><fa icon="broadcast-tower" fixed-width/>{{ $t('announcements') }}</li> <li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }"><fa icon="hashtag" fixed-width/>{{ $t('hashtags') }}</li> @@ -48,6 +48,7 @@ <div v-if="page == 'announcements'"><x-announcements/></div> <div v-if="page == 'hashtags'"><x-hashtags/></div> <div v-if="page == 'drive'"><x-drive/></div> + <div v-if="page == 'federation'"><x-federation/></div> <div v-if="page == 'abuse'"><x-abuse/></div> </div> </main> @@ -68,7 +69,9 @@ import XHashtags from "./hashtags.vue"; import XUsers from "./users.vue"; import XDrive from "./drive.vue"; import XAbuse from "./abuse.vue"; -import { faHeadset, faArrowLeft, faShareAlt, faExclamationCircle, faTasks } from '@fortawesome/free-solid-svg-icons'; +import XFederation from "./federation.vue"; + +import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks } from '@fortawesome/free-solid-svg-icons'; import { faGrin } from '@fortawesome/free-regular-svg-icons'; // Detect the user agent @@ -88,6 +91,7 @@ export default Vue.extend({ XUsers, XDrive, XAbuse, + XFederation, }, provide: { isMobile @@ -101,7 +105,7 @@ export default Vue.extend({ faGrin, faArrowLeft, faHeadset, - faShareAlt, + faGlobe, faExclamationCircle, faTasks }; diff --git a/src/server/api/endpoints/federation/instances.ts b/src/server/api/endpoints/federation/instances.ts new file mode 100644 index 0000000000..723cbe8fd5 --- /dev/null +++ b/src/server/api/endpoints/federation/instances.ts @@ -0,0 +1,84 @@ +import $ from 'cafy'; +import define from '../../define'; +import Instance from '../../../../models/instance'; + +export const meta = { + requireCredential: false, + + params: { + limit: { + validator: $.num.optional.range(1, 100), + default: 30 + }, + + offset: { + validator: $.num.optional.min(0), + default: 0 + }, + + sort: { + validator: $.str.optional, + } + } +}; + +export default define(meta, (ps, me) => new Promise(async (res, rej) => { + let sort; + + if (ps.sort) { + if (ps.sort == '+notes') { + sort = { + notesCount: -1 + }; + } else if (ps.sort == '-notes') { + sort = { + notesCount: 1 + }; + } else if (ps.sort == '+users') { + sort = { + usersCount: -1 + }; + } else if (ps.sort == '-users') { + sort = { + usersCount: 1 + }; + } else if (ps.sort == '+following') { + sort = { + followingCount: -1 + }; + } else if (ps.sort == '-following') { + sort = { + followingCount: 1 + }; + } else if (ps.sort == '+followers') { + sort = { + followersCount: -1 + }; + } else if (ps.sort == '-followers') { + sort = { + followersCount: 1 + }; + } else if (ps.sort == '+caughtAt') { + sort = { + caughtAt: -1 + }; + } else if (ps.sort == '-caughtAt') { + sort = { + caughtAt: 1 + }; + } + } else { + sort = { + _id: -1 + }; + } + + const instances = await Instance + .find({}, { + limit: ps.limit, + sort: sort, + skip: ps.offset + }); + + res(instances); +})); diff --git a/src/server/api/endpoints/federation/show-instance.ts b/src/server/api/endpoints/federation/show-instance.ts new file mode 100644 index 0000000000..ad31c56afc --- /dev/null +++ b/src/server/api/endpoints/federation/show-instance.ts @@ -0,0 +1,20 @@ +import $ from 'cafy'; +import define from '../../define'; +import Instance from '../../../../models/instance'; + +export const meta = { + requireCredential: false, + + params: { + host: { + validator: $.str + } + } +}; + +export default define(meta, (ps, me) => new Promise(async (res, rej) => { + const instance = await Instance + .findOne({ host: ps.host }); + + res(instance); +})); diff --git a/src/server/api/endpoints/instances.ts b/src/server/api/endpoints/instances.ts deleted file mode 100644 index b7c686a353..0000000000 --- a/src/server/api/endpoints/instances.ts +++ /dev/null @@ -1,51 +0,0 @@ -import $ from 'cafy'; -import define from '../define'; -import Instance from '../../../models/instance'; - -export const meta = { - requireCredential: false, - - params: { - limit: { - validator: $.num.optional.range(1, 100), - default: 30 - }, - - offset: { - validator: $.num.optional.min(0), - default: 0 - }, - - sort: { - validator: $.str.optional.or('+notes|-notes'), - } - } -}; - -export default define(meta, (ps, me) => new Promise(async (res, rej) => { - let _sort; - if (ps.sort) { - if (ps.sort == '+notes') { - _sort = { - notesCount: -1 - }; - } else if (ps.sort == '-notes') { - _sort = { - notesCount: 1 - }; - } - } else { - _sort = { - _id: -1 - }; - } - - const instances = await Instance - .find({}, { - limit: ps.limit, - sort: _sort, - skip: ps.offset - }); - - res(instances); -})); |