enhance(backend/frontend): モデレーションノートをユーザーのプロフィールページからも閲覧および編集できるように
This commit is contained in:
parent
bd1c2abffc
commit
10ff379b4c
|
@ -34,6 +34,7 @@
|
||||||
* デフォルトがオフになるので、ロールタイムラインを表示する場合はオンにしてください。
|
* デフォルトがオフになるので、ロールタイムラインを表示する場合はオンにしてください。
|
||||||
- ロールに強制的にNSFWを付与するポリシーを追加
|
- ロールに強制的にNSFWを付与するポリシーを追加
|
||||||
* アップロード済みのファイルはNSFWにならない為注意してください。
|
* アップロード済みのファイルはNSFWにならない為注意してください。
|
||||||
|
- モデレーションノートがユーザーのプロフィールページからも閲覧および編集できるようになりました。
|
||||||
- カスタム絵文字のライセンスを複数でセットできるようになりました。
|
- カスタム絵文字のライセンスを複数でセットできるようになりました。
|
||||||
- 管理者が予約ユーザー名を設定できるようになりました。
|
- 管理者が予約ユーザー名を設定できるようになりました。
|
||||||
- Fix: フォローリクエストの通知が残る問題を修正
|
- Fix: フォローリクエストの通知が残る問題を修正
|
||||||
|
|
|
@ -292,7 +292,7 @@ export class UserEntityService implements OnModuleInit {
|
||||||
|
|
||||||
public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>(
|
public async pack<ExpectsMe extends boolean | null = null, D extends boolean = false>(
|
||||||
src: User['id'] | User,
|
src: User['id'] | User,
|
||||||
me?: { id: User['id'] } | null | undefined,
|
me?: { id: User['id']; isRoot: boolean; } | null | undefined,
|
||||||
options?: {
|
options?: {
|
||||||
detail?: D,
|
detail?: D,
|
||||||
includeSecrets?: boolean,
|
includeSecrets?: boolean,
|
||||||
|
@ -308,6 +308,7 @@ export class UserEntityService implements OnModuleInit {
|
||||||
|
|
||||||
const meId = me ? me.id : null;
|
const meId = me ? me.id : null;
|
||||||
const isMe = meId === user.id;
|
const isMe = meId === user.id;
|
||||||
|
const iAmModerator = me ? await this.roleService.isModerator(me) : false;
|
||||||
|
|
||||||
const relation = meId && !isMe && opts.detail ? await this.getRelation(meId, user.id) : null;
|
const relation = meId && !isMe && opts.detail ? await this.getRelation(meId, user.id) : null;
|
||||||
const pins = opts.detail ? await this.userNotePiningsRepository.createQueryBuilder('pin')
|
const pins = opts.detail ? await this.userNotePiningsRepository.createQueryBuilder('pin')
|
||||||
|
@ -411,6 +412,7 @@ export class UserEntityService implements OnModuleInit {
|
||||||
userId: meId,
|
userId: meId,
|
||||||
targetUserId: user.id,
|
targetUserId: user.id,
|
||||||
}).then(row => row?.memo ?? null),
|
}).then(row => row?.memo ?? null),
|
||||||
|
moderationNote: iAmModerator ? profile!.moderationNote : null,
|
||||||
} : {}),
|
} : {}),
|
||||||
|
|
||||||
...(opts.detail && isMe ? {
|
...(opts.detail && isMe ? {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<!-- <div class="punished" v-if="user.isSilenced"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSilenced }}</div> -->
|
<!-- <div class="punished" v-if="user.isSilenced"><i class="ti ti-alert-triangle" style="margin-right: 8px;"></i> {{ i18n.ts.userSilenced }}</div> -->
|
||||||
|
|
||||||
<div class="profile _gaps">
|
<div class="profile _gaps">
|
||||||
<MkAccountMoved v-if="user.movedTo" :movedTo="user.movedTo" />
|
<MkAccountMoved v-if="user.movedTo" :moved-to="user.movedTo"/>
|
||||||
<MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!" class="warn"/>
|
<MkRemoteCaution v-if="user.host != null" :href="user.url ?? user.uri!" class="warn"/>
|
||||||
|
|
||||||
<div :key="user.id" class="main _panel">
|
<div :key="user.id" class="main _panel">
|
||||||
|
@ -42,6 +42,17 @@
|
||||||
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
|
<span v-if="user.isBot" :title="i18n.ts.isBot"><i class="ti ti-robot"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="user.roles.length > 0" class="roles">
|
||||||
|
<span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role" :style="{ '--color': role.color }">
|
||||||
|
<img v-if="role.iconUrl" style="height: 1.3em; vertical-align: -22%;" :src="role.iconUrl"/>
|
||||||
|
{{ role.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="iAmModerator" class="moderationNote">
|
||||||
|
<MkTextarea v-model="moderationNote" manual-save>
|
||||||
|
<template #label>Moderation note</template>
|
||||||
|
</MkTextarea>
|
||||||
|
</div>
|
||||||
<div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}">
|
<div v-if="isEditingMemo || memoDraft" class="memo" :class="{'no-memo': !memoDraft}">
|
||||||
<div class="heading" v-text="i18n.ts.memo"/>
|
<div class="heading" v-text="i18n.ts.memo"/>
|
||||||
<textarea
|
<textarea
|
||||||
|
@ -53,12 +64,6 @@
|
||||||
@input="adjustMemoTextarea"
|
@input="adjustMemoTextarea"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="user.roles.length > 0" class="roles">
|
|
||||||
<span v-for="role in user.roles" :key="role.id" v-tooltip="role.description" class="role" :style="{ '--color': role.color }">
|
|
||||||
<img v-if="role.iconUrl" style="height: 1.3em; vertical-align: -22%;" :src="role.iconUrl"/>
|
|
||||||
{{ role.name }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<MkOmit>
|
<MkOmit>
|
||||||
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i"/>
|
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i"/>
|
||||||
|
@ -134,6 +139,7 @@ import MkNote from '@/components/MkNote.vue';
|
||||||
import MkFollowButton from '@/components/MkFollowButton.vue';
|
import MkFollowButton from '@/components/MkFollowButton.vue';
|
||||||
import MkAccountMoved from '@/components/MkAccountMoved.vue';
|
import MkAccountMoved from '@/components/MkAccountMoved.vue';
|
||||||
import MkRemoteCaution from '@/components/MkRemoteCaution.vue';
|
import MkRemoteCaution from '@/components/MkRemoteCaution.vue';
|
||||||
|
import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
import MkOmit from '@/components/MkOmit.vue';
|
import MkOmit from '@/components/MkOmit.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import { getScrollPosition } from '@/scripts/scroll';
|
import { getScrollPosition } from '@/scripts/scroll';
|
||||||
|
@ -143,7 +149,7 @@ import { userPage } from '@/filters/user';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { useRouter } from '@/router';
|
import { useRouter } from '@/router';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { $i } from '@/account';
|
import { $i, iAmModerator } from '@/account';
|
||||||
import { dateString } from '@/filters/date';
|
import { dateString } from '@/filters/date';
|
||||||
import { confetti } from '@/scripts/confetti';
|
import { confetti } from '@/scripts/confetti';
|
||||||
import MkNotes from '@/components/MkNotes.vue';
|
import MkNotes from '@/components/MkNotes.vue';
|
||||||
|
@ -168,8 +174,12 @@ let rootEl = $ref<null | HTMLElement>(null);
|
||||||
let bannerEl = $ref<null | HTMLElement>(null);
|
let bannerEl = $ref<null | HTMLElement>(null);
|
||||||
let memoTextareaEl = $ref<null | HTMLElement>(null);
|
let memoTextareaEl = $ref<null | HTMLElement>(null);
|
||||||
let memoDraft = $ref(props.user.memo);
|
let memoDraft = $ref(props.user.memo);
|
||||||
|
|
||||||
let isEditingMemo = $ref(false);
|
let isEditingMemo = $ref(false);
|
||||||
|
let moderationNote = $ref(props.user.moderationNote);
|
||||||
|
|
||||||
|
watch($$(moderationNote), async () => {
|
||||||
|
await os.api('admin/update-user-note', { userId: props.user.id, text: moderationNote });
|
||||||
|
});
|
||||||
|
|
||||||
const pagination = {
|
const pagination = {
|
||||||
endpoint: 'users/notes' as const,
|
endpoint: 'users/notes' as const,
|
||||||
|
@ -426,6 +436,10 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .moderationNote {
|
||||||
|
margin: 12px 24px 0 154px;
|
||||||
|
}
|
||||||
|
|
||||||
> .memo {
|
> .memo {
|
||||||
margin: 12px 24px 0 154px;
|
margin: 12px 24px 0 154px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
@ -593,6 +607,10 @@ onUnmounted(() => {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .moderationNote {
|
||||||
|
margin: 16px 16px 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
> .memo {
|
> .memo {
|
||||||
margin: 16px 16px 0 16px;
|
margin: 16px 16px 0 16px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue