インスタンス運営者がピン留めユーザーを設定できるように

Related #4892
This commit is contained in:
syuilo 2019-05-10 17:30:28 +09:00
parent c6ce479c57
commit 94cd2fdcd5
8 changed files with 81 additions and 2 deletions

View file

@ -338,6 +338,7 @@ auth/views/index.vue:
sign-in: "サインインしてください" sign-in: "サインインしてください"
common/views/pages/explore.vue: common/views/pages/explore.vue:
pinned-users: "ピン留めされたユーザー"
popular-users: "人気のユーザー" popular-users: "人気のユーザー"
recently-updated-users: "最近投稿したユーザー" recently-updated-users: "最近投稿したユーザー"
recently-registered-users: "新規ユーザー" recently-registered-users: "新規ユーザー"
@ -1262,7 +1263,7 @@ admin/views/instance.vue:
invite: "招待" invite: "招待"
save: "保存" save: "保存"
saved: "保存しました" saved: "保存しました"
user-recommendation-config: "おすすめユーザー" pinned-users: "ピン留めユーザー"
email-config: "メールサーバーの設定" email-config: "メールサーバーの設定"
email-config-info: "メールアドレス確認やパスワードリセットの際に使われます。" email-config-info: "メールアドレス確認やパスワードリセットの際に使われます。"
enable-email: "メール配信を有効にする" enable-email: "メール配信を有効にする"

View file

@ -0,0 +1,13 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class PinnedUsers1557476068003 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "meta" ADD "pinnedUsers" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedUsers"`);
}
}

View file

@ -82,6 +82,14 @@
</section> </section>
</ui-card> </ui-card>
<ui-card>
<template #title>{{ $t('pinned-users') }}</template>
<section>
<ui-textarea v-model="pinnedUsers"></ui-textarea>
<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
</section>
</ui-card>
<ui-card> <ui-card>
<template #title>{{ $t('invite') }}</template> <template #title>{{ $t('invite') }}</template>
<section> <section>
@ -190,6 +198,7 @@ export default Vue.extend({
enableServiceWorker: false, enableServiceWorker: false,
swPublicKey: null, swPublicKey: null,
swPrivateKey: null, swPrivateKey: null,
pinnedUsers: [],
faHeadset, faShieldAlt, faGhost, faUserPlus, farEnvelope, faBolt faHeadset, faShieldAlt, faGhost, faUserPlus, farEnvelope, faBolt
}; };
}, },
@ -239,6 +248,7 @@ export default Vue.extend({
this.enableServiceWorker = meta.enableServiceWorker; this.enableServiceWorker = meta.enableServiceWorker;
this.swPublicKey = meta.swPublickey; this.swPublicKey = meta.swPublickey;
this.swPrivateKey = meta.swPrivateKey; this.swPrivateKey = meta.swPrivateKey;
this.pinnedUsers = meta.pinnedUsers.join('\n');
}); });
}, },
@ -297,7 +307,8 @@ export default Vue.extend({
smtpPass: this.smtpAuth ? this.smtpPass : '', smtpPass: this.smtpAuth ? this.smtpPass : '',
enableServiceWorker: this.enableServiceWorker, enableServiceWorker: this.enableServiceWorker,
swPublicKey: this.swPublicKey, swPublicKey: this.swPublicKey,
swPrivateKey: this.swPrivateKey swPrivateKey: this.swPrivateKey,
pinnedUsers: this.pinnedUsers.split('\n')
}).then(() => { }).then(() => {
this.$root.dialog({ this.$root.dialog({
type: 'success', type: 'success',

View file

@ -26,6 +26,9 @@
</mk-user-list> </mk-user-list>
<template v-if="tag == null"> <template v-if="tag == null">
<mk-user-list :make-promise="pinnedUsers">
<fa :icon="faBookmark" fixed-width/>{{ $t('pinned-users') }}
</mk-user-list>
<mk-user-list :make-promise="popularUsers"> <mk-user-list :make-promise="popularUsers">
<fa :icon="faChartLine" fixed-width/>{{ $t('popular-users') }} <fa :icon="faChartLine" fixed-width/>{{ $t('popular-users') }}
</mk-user-list> </mk-user-list>
@ -57,6 +60,7 @@ export default Vue.extend({
data() { data() {
return { return {
pinnedUsers: () => this.$root.api('pinned-users'),
popularUsers: () => this.$root.api('users', { popularUsers: () => this.$root.api('users', {
state: 'alive', state: 'alive',
origin: 'local', origin: 'local',

View file

@ -69,6 +69,11 @@ export class Meta {
}) })
public langs: string[]; public langs: string[];
@Column('varchar', {
length: 256, array: true, default: '{}'
})
public pinnedUsers: string[];
@Column('varchar', { @Column('varchar', {
length: 256, array: true, default: '{}' length: 256, array: true, default: '{}'
}) })

View file

@ -56,6 +56,13 @@ export const meta = {
} }
}, },
pinnedUsers: {
validator: $.optional.nullable.arr($.str),
desc: {
'ja-JP': 'ピン留めユーザー'
}
},
hiddenTags: { hiddenTags: {
validator: $.optional.nullable.arr($.str), validator: $.optional.nullable.arr($.str),
desc: { desc: {
@ -353,6 +360,10 @@ export default define(meta, async (ps) => {
set.useStarForReactionFallback = ps.useStarForReactionFallback; set.useStarForReactionFallback = ps.useStarForReactionFallback;
} }
if (Array.isArray(ps.pinnedUsers)) {
set.pinnedUsers = ps.pinnedUsers;
}
if (Array.isArray(ps.hiddenTags)) { if (Array.isArray(ps.hiddenTags)) {
set.hiddenTags = ps.hiddenTags; set.hiddenTags = ps.hiddenTags;
} }

View file

@ -160,6 +160,7 @@ export default define(meta, async (ps, me) => {
if (me && (me.isAdmin || me.isModerator)) { if (me && (me.isAdmin || me.isModerator)) {
response.useStarForReactionFallback = instance.useStarForReactionFallback; response.useStarForReactionFallback = instance.useStarForReactionFallback;
response.pinnedUsers = instance.pinnedUsers;
response.hiddenTags = instance.hiddenTags; response.hiddenTags = instance.hiddenTags;
response.recaptchaSecretKey = instance.recaptchaSecretKey; response.recaptchaSecretKey = instance.recaptchaSecretKey;
response.proxyAccount = instance.proxyAccount; response.proxyAccount = instance.proxyAccount;

View file

@ -0,0 +1,33 @@
import define from '../define';
import { Users } from '../../../models';
import { types, bool } from '../../../misc/schema';
import { fetchMeta } from '../../../misc/fetch-meta';
import parseAcct from '../../../misc/acct/parse';
import { User } from '../../../models/entities/user';
export const meta = {
tags: ['users'],
requireCredential: false,
params: {
},
res: {
type: types.array,
optional: bool.false, nullable: bool.false,
items: {
type: types.object,
optional: bool.false, nullable: bool.false,
ref: 'User',
}
},
};
export default define(meta, async (ps, me) => {
const meta = await fetchMeta();
const users = await Promise.all(meta.pinnedUsers.map(acct => Users.findOne(parseAcct(acct))));
return await Users.packMany(users.filter(x => x !== undefined) as User[], me, { detail: true });
});