mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-19 17:05:35 +02:00
refactor: make noImplicitAny true (#17083)
* wip * Update emojis.emoji.vue * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update manager.ts * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update analytics.ts
This commit is contained in:
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<template>
|
||||
<div class="_gaps">
|
||||
<div :class="$style.header">
|
||||
<MkSelect v-model="type" :items="typeDef" :class="$style.typeSelect">
|
||||
<MkSelect v-model="typeModelForMkSelect" :items="typeDef" :class="$style.typeSelect">
|
||||
</MkSelect>
|
||||
<button v-if="draggable" class="_button" :class="$style.dragHandle" :draggable="true" @dragstart.stop="dragStartCallback">
|
||||
<i class="ti ti-menu-2"></i>
|
||||
@@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="type === 'and' || type === 'or'" class="_gaps">
|
||||
<div v-if="v.type === 'and' || v.type === 'or'" class="_gaps">
|
||||
<MkDraggable
|
||||
v-model="v.values"
|
||||
direction="vertical"
|
||||
@@ -32,33 +32,34 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
:modelValue="item"
|
||||
:dragStartCallback="dragStart"
|
||||
draggable
|
||||
@update:modelValue="updated => valuesItemUpdated(updated)"
|
||||
@remove="removeItem(item.id)"
|
||||
@update:modelValue="updated => childValuesItemUpdated(updated)"
|
||||
@remove="removeChildItem(item.id)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</MkDraggable>
|
||||
<MkButton rounded style="margin: 0 auto;" @click="addValue"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
|
||||
<MkButton rounded style="margin: 0 auto;" @click="addChildValue"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
|
||||
</div>
|
||||
|
||||
<div v-else-if="type === 'not'" :class="$style.item">
|
||||
<div v-else-if="v.type === 'not'" :class="$style.item">
|
||||
<RolesEditorFormula v-model="v.value"/>
|
||||
</div>
|
||||
|
||||
<MkInput v-else-if="type === 'createdLessThan' || type === 'createdMoreThan'" v-model="v.sec" type="number">
|
||||
<MkInput v-else-if="v.type === 'createdLessThan' || v.type === 'createdMoreThan'" v-model="v.sec" type="number">
|
||||
<template #suffix>sec</template>
|
||||
</MkInput>
|
||||
|
||||
<MkInput v-else-if="['followersLessThanOrEq', 'followersMoreThanOrEq', 'followingLessThanOrEq', 'followingMoreThanOrEq', 'notesLessThanOrEq', 'notesMoreThanOrEq'].includes(type)" v-model="v.value" type="number">
|
||||
<MkInput v-else-if="v.type === 'followersLessThanOrEq' || v.type === 'followersMoreThanOrEq' || v.type === 'followingLessThanOrEq' || v.type === 'followingMoreThanOrEq' || v.type === 'notesLessThanOrEq' || v.type === 'notesMoreThanOrEq'" v-model="v.value" type="number">
|
||||
</MkInput>
|
||||
|
||||
<MkSelect v-else-if="type === 'roleAssignedTo'" v-model="v.roleId" :items="assignedToDef">
|
||||
<MkSelect v-else-if="v.type === 'roleAssignedTo'" v-model="v.roleId" :items="assignedToDef">
|
||||
</MkSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import type { GetMkSelectValueTypesFromDef, MkSelectItem } from '@/components/MkSelect.vue';
|
||||
import { genId } from '@/utility/id.js';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
@@ -70,12 +71,12 @@ import { deepClone } from '@/utility/clone.js';
|
||||
import { rolesCache } from '@/cache.js';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'update:modelValue', value: any): void;
|
||||
(ev: 'update:modelValue', value: Misskey.entities.Role['condFormula']): void;
|
||||
(ev: 'remove'): void;
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: any;
|
||||
modelValue: Misskey.entities.Role['condFormula'];
|
||||
draggable?: boolean;
|
||||
dragStartCallback?: (ev: DragEvent) => void;
|
||||
}>();
|
||||
@@ -115,37 +116,50 @@ const typeDef = [
|
||||
{ label: i18n.ts._role._condition.not, value: 'not' },
|
||||
] as const satisfies MkSelectItem[];
|
||||
|
||||
const type = computed<GetMkSelectValueTypesFromDef<typeof typeDef>>({
|
||||
type KeyOfUnion<T> = T extends T ? keyof T : never;
|
||||
|
||||
type DistributiveOmit<T, K extends KeyOfUnion<T>> = T extends T
|
||||
? Omit<T, K>
|
||||
: never;
|
||||
|
||||
const typeModelForMkSelect = computed<GetMkSelectValueTypesFromDef<typeof typeDef>>({
|
||||
get: () => v.value.type,
|
||||
set: (t) => {
|
||||
if (t === 'and') v.value.values = [];
|
||||
if (t === 'or') v.value.values = [];
|
||||
if (t === 'not') v.value.value = { id: genId(), type: 'isRemote' };
|
||||
if (t === 'roleAssignedTo') v.value.roleId = '';
|
||||
if (t === 'createdLessThan') v.value.sec = 86400;
|
||||
if (t === 'createdMoreThan') v.value.sec = 86400;
|
||||
if (t === 'followersLessThanOrEq') v.value.value = 10;
|
||||
if (t === 'followersMoreThanOrEq') v.value.value = 10;
|
||||
if (t === 'followingLessThanOrEq') v.value.value = 10;
|
||||
if (t === 'followingMoreThanOrEq') v.value.value = 10;
|
||||
if (t === 'notesLessThanOrEq') v.value.value = 10;
|
||||
if (t === 'notesMoreThanOrEq') v.value.value = 10;
|
||||
v.value.type = t;
|
||||
let newValue: DistributiveOmit<Misskey.entities.Role['condFormula'], 'id'>;
|
||||
switch (t) {
|
||||
case 'and': newValue = { type: 'and', values: [] }; break;
|
||||
case 'or': newValue = { type: 'or', values: [] }; break;
|
||||
case 'not': newValue = { type: 'not', value: { id: genId(), type: 'isRemote' } }; break;
|
||||
case 'roleAssignedTo': newValue = { type: 'roleAssignedTo', roleId: '' }; break;
|
||||
case 'createdLessThan': newValue = { type: 'createdLessThan', sec: 86400 }; break;
|
||||
case 'createdMoreThan': newValue = { type: 'createdMoreThan', sec: 86400 }; break;
|
||||
case 'followersLessThanOrEq': newValue = { type: 'followersLessThanOrEq', value: 10 }; break;
|
||||
case 'followersMoreThanOrEq': newValue = { type: 'followersMoreThanOrEq', value: 10 }; break;
|
||||
case 'followingLessThanOrEq': newValue = { type: 'followingLessThanOrEq', value: 10 }; break;
|
||||
case 'followingMoreThanOrEq': newValue = { type: 'followingMoreThanOrEq', value: 10 }; break;
|
||||
case 'notesLessThanOrEq': newValue = { type: 'notesLessThanOrEq', value: 10 }; break;
|
||||
case 'notesMoreThanOrEq': newValue = { type: 'notesMoreThanOrEq', value: 10 }; break;
|
||||
default: newValue = { type: t }; break;
|
||||
}
|
||||
v.value = { id: v.value.id, ...newValue };
|
||||
},
|
||||
});
|
||||
|
||||
const assignedToDef = computed(() => roles.filter(r => r.target === 'manual').map(r => ({ label: r.name, value: r.id })) satisfies MkSelectItem[]);
|
||||
|
||||
function addValue() {
|
||||
function addChildValue() {
|
||||
if (v.value.type !== 'and' && v.value.type !== 'or') return;
|
||||
v.value.values.push({ id: genId(), type: 'isRemote' });
|
||||
}
|
||||
|
||||
function valuesItemUpdated(item) {
|
||||
function childValuesItemUpdated(item: Misskey.entities.Role['condFormula']) {
|
||||
if (v.value.type !== 'and' && v.value.type !== 'or') return;
|
||||
const i = v.value.values.findIndex(_item => _item.id === item.id);
|
||||
v.value.values[i] = item;
|
||||
}
|
||||
|
||||
function removeItem(itemId) {
|
||||
function removeChildItem(itemId: string) {
|
||||
if (v.value.type !== 'and' && v.value.type !== 'or') return;
|
||||
v.value.values = v.value.values.filter(_item => _item.id !== itemId);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ const paginator = markRaw(new Paginator('admin/abuse-user-reports', {
|
||||
})),
|
||||
}));
|
||||
|
||||
function resolved(reportId) {
|
||||
function resolved(reportId: string) {
|
||||
paginator.removeItem(reportId);
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
@@ -112,7 +113,12 @@ const {
|
||||
const loading = ref(true);
|
||||
const loadingMore = ref(false);
|
||||
|
||||
const announcements = ref<any[]>([]);
|
||||
const announcements = ref<(Omit<Misskey.entities.AdminAnnouncementsListResponse[number], 'id' | 'createdAt' | 'updatedAt' | 'reads' | 'isActive'> & {
|
||||
id: string | null;
|
||||
_id?: string;
|
||||
isActive?: Misskey.entities.AdminAnnouncementsListResponse[number]['isActive'];
|
||||
reads?: Misskey.entities.AdminAnnouncementsListResponse[number]['reads'];
|
||||
})[]>([]);
|
||||
|
||||
watch(announcementsStatus, (to) => {
|
||||
loading.value = true;
|
||||
@@ -136,42 +142,55 @@ function add() {
|
||||
forExistingUsers: false,
|
||||
silence: false,
|
||||
needConfirmationToRead: false,
|
||||
userId: null,
|
||||
});
|
||||
}
|
||||
|
||||
function del(announcement) {
|
||||
os.confirm({
|
||||
async function del(announcement: (typeof announcements)['value'][number]) {
|
||||
if (announcement.id == null) return;
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.tsx.deleteAreYouSure({ x: announcement.title }),
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) return;
|
||||
announcements.value = announcements.value.filter(x => x !== announcement);
|
||||
misskeyApi('admin/announcements/delete', announcement);
|
||||
});
|
||||
if (canceled) return;
|
||||
announcements.value = announcements.value.filter(x => x !== announcement);
|
||||
misskeyApi('admin/announcements/delete', {
|
||||
id: announcement.id,
|
||||
});
|
||||
}
|
||||
|
||||
async function archive(announcement) {
|
||||
async function archive(announcement: (typeof announcements)['value'][number]) {
|
||||
if (announcement.id == null) return;
|
||||
const { _id, ...data } = announcement; // _idを消す
|
||||
await os.apiWithDialog('admin/announcements/update', {
|
||||
...announcement,
|
||||
...data,
|
||||
id: announcement.id, // TSを黙らすため
|
||||
isActive: false,
|
||||
});
|
||||
refresh();
|
||||
}
|
||||
|
||||
async function unarchive(announcement) {
|
||||
async function unarchive(announcement: (typeof announcements)['value'][number]) {
|
||||
if (announcement.id == null) return;
|
||||
const { _id, ...data } = announcement; // _idを消す
|
||||
await os.apiWithDialog('admin/announcements/update', {
|
||||
...announcement,
|
||||
...data,
|
||||
id: announcement.id, // TSを黙らすため
|
||||
isActive: true,
|
||||
});
|
||||
refresh();
|
||||
}
|
||||
|
||||
async function save(announcement) {
|
||||
async function save(announcement: (typeof announcements)['value'][number]) {
|
||||
const { _id, ...data } = announcement; // _idを消す
|
||||
if (announcement.id == null) {
|
||||
await os.apiWithDialog('admin/announcements/create', announcement);
|
||||
await os.apiWithDialog('admin/announcements/create', data);
|
||||
refresh();
|
||||
} else {
|
||||
os.apiWithDialog('admin/announcements/update', announcement);
|
||||
os.apiWithDialog('admin/announcements/update', {
|
||||
...data,
|
||||
id: announcement.id, // TSを黙らすため
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +198,7 @@ function more() {
|
||||
loadingMore.value = true;
|
||||
misskeyApi('admin/announcements/list', {
|
||||
status: announcementsStatus.value,
|
||||
untilId: announcements.value.reduce((acc, announcement) => announcement.id != null ? announcement : acc).id,
|
||||
untilId: announcements.value.reduce((acc, announcement) => announcement.id != null ? announcement : acc).id!,
|
||||
}).then(announcementResponse => {
|
||||
announcements.value = announcements.value.concat(announcementResponse);
|
||||
loadingMore.value = false;
|
||||
|
||||
@@ -51,6 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<script lang="ts">
|
||||
import type { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
||||
import type { GridSortOrderKey } from './custom-emojis-manager.impl.js';
|
||||
import type { PageHeaderItem } from '@/types/page-header.js';
|
||||
|
||||
export type EmojiSearchQuery = {
|
||||
name: string | null;
|
||||
@@ -250,7 +251,7 @@ function setupGrid(): GridSetting {
|
||||
icon: 'ti ti-trash',
|
||||
action: () => {
|
||||
removeDataFromGrid(context, (cell) => {
|
||||
gridItems.value[cell.row.index][cell.column.setting.bindTo] = undefined;
|
||||
(gridItems.value[cell.row.index] as any)[cell.column.setting.bindTo] = undefined;
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -454,7 +455,7 @@ function onGridCellValidation(event: GridCellValidationEvent) {
|
||||
function onGridCellValueChange(event: GridCellValueChangeEvent) {
|
||||
const { row, column, newValue } = event;
|
||||
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
|
||||
gridItems.value[row.index][column.setting.bindTo] = newValue;
|
||||
(gridItems.value[row.index] as any)[column.setting.bindTo] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,7 +526,7 @@ const headerPageMetadata = computed(() => ({
|
||||
icon: 'ti ti-icons',
|
||||
}));
|
||||
|
||||
const headerActions = computed(() => [{
|
||||
const headerActions = computed<PageHeaderItem[]>(() => [{
|
||||
icon: 'ti ti-search',
|
||||
text: i18n.ts.search,
|
||||
handler: async () => {
|
||||
@@ -552,7 +553,7 @@ const headerActions = computed(() => [{
|
||||
}, {
|
||||
icon: 'ti ti-list-numbers',
|
||||
text: i18n.ts._customEmojisManager._gridCommon.searchLimit,
|
||||
handler: (ev: MouseEvent) => {
|
||||
handler: (ev) => {
|
||||
async function changeSearchLimit(to: number) {
|
||||
if (updatedItemsCount.value > 0) {
|
||||
const { canceled } = await os.confirm({
|
||||
|
||||
@@ -58,7 +58,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { computed, onMounted, ref, useCssModule } from 'vue';
|
||||
import type { RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
@@ -339,7 +338,7 @@ function onGridCellValidation(event: GridCellValidationEvent) {
|
||||
function onGridCellValueChange(event: GridCellValueChangeEvent) {
|
||||
const { row, column, newValue } = event;
|
||||
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
|
||||
gridItems.value[row.index][column.setting.bindTo] = newValue;
|
||||
(gridItems.value[row.index] as any)[column.setting.bindTo] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -306,7 +306,7 @@ function onGridEvent(event: GridEvent) {
|
||||
function onGridCellValueChange(event: GridCellValueChangeEvent) {
|
||||
const { row, column, newValue } = event;
|
||||
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
|
||||
gridItems.value[row.index][column.setting.bindTo] = newValue;
|
||||
(gridItems.value[row.index] as any)[column.setting.bindTo] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ const { handler: externalTooltipHandler } = useChartTooltip();
|
||||
|
||||
let chartInstance: Chart | null = null;
|
||||
|
||||
function setData(values) {
|
||||
function setData(values: number[]) {
|
||||
if (chartInstance == null || chartInstance.data.labels == null) return;
|
||||
for (const value of values) {
|
||||
chartInstance.data.labels.push('');
|
||||
@@ -41,7 +41,7 @@ function setData(values) {
|
||||
chartInstance.update();
|
||||
}
|
||||
|
||||
function pushData(value) {
|
||||
function pushData(value: number) {
|
||||
if (chartInstance == null || chartInstance.data.labels == null) return;
|
||||
chartInstance.data.labels.push('');
|
||||
chartInstance.data.datasets[0].data.push(value);
|
||||
|
||||
@@ -294,7 +294,7 @@ function invite() {
|
||||
});
|
||||
}
|
||||
|
||||
function adminLookup(ev: MouseEvent) {
|
||||
function adminLookup(ev: PointerEvent) {
|
||||
os.popupMenu([{
|
||||
text: i18n.ts.user,
|
||||
icon: 'ti ti-user',
|
||||
|
||||
@@ -47,7 +47,7 @@ async function renderChart() {
|
||||
return new Date(y, m, d - ago);
|
||||
};
|
||||
|
||||
const format = (arr) => {
|
||||
const format = (arr: number[]) => {
|
||||
return arr.map((v, i) => ({
|
||||
x: getDate(i).getTime(),
|
||||
y: v,
|
||||
|
||||
@@ -104,7 +104,7 @@ const filesPagination = {
|
||||
noPaging: true,
|
||||
};
|
||||
|
||||
function onInstanceClick(i) {
|
||||
function onInstanceClick(i: Misskey.entities.FederationInstance) {
|
||||
os.pageWindow(`/instance-info/${i.host}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { genId } from '@/utility/id.js';
|
||||
import XEditor from './roles.editor.vue';
|
||||
import { genId } from '@/utility/id.js';
|
||||
import * as os from '@/os.js';
|
||||
import { misskeyApi } from '@/utility/misskey-api.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
@@ -37,8 +37,13 @@ const props = defineProps<{
|
||||
id?: string;
|
||||
}>();
|
||||
|
||||
type RoleLike = Pick<Misskey.entities.Role, 'name' | 'description' | 'isAdministrator' | 'isModerator' | 'color' | 'iconUrl' | 'target' | 'isPublic' | 'isExplorable' | 'asBadge' | 'canEditMembersByModerator' | 'displayOrder' | 'preserveAssignmentOnMoveAccount'> & {
|
||||
condFormula: any;
|
||||
policies: any;
|
||||
};
|
||||
|
||||
const role = ref<Misskey.entities.Role | null>(null);
|
||||
const data = ref<any>(null);
|
||||
const data = ref<RoleLike | null>(null);
|
||||
|
||||
if (props.id) {
|
||||
role.value = await misskeyApi('admin/roles/show', {
|
||||
@@ -61,11 +66,13 @@ if (props.id) {
|
||||
asBadge: false,
|
||||
canEditMembersByModerator: false,
|
||||
displayOrder: 0,
|
||||
preserveAssignmentOnMoveAccount: false,
|
||||
policies: {},
|
||||
};
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (data.value === null) return;
|
||||
rolesCache.delete();
|
||||
if (role.value) {
|
||||
os.apiWithDialog('admin/roles/update', {
|
||||
@@ -75,7 +82,7 @@ async function save() {
|
||||
router.push('/admin/roles/:id', {
|
||||
params: {
|
||||
id: role.value.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const created = await os.apiWithDialog('admin/roles/create', {
|
||||
@@ -84,7 +91,7 @@ async function save() {
|
||||
router.push('/admin/roles/:id', {
|
||||
params: {
|
||||
id: created.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
<template>
|
||||
<div class="_gaps">
|
||||
<MkInput v-if="readonly" :modelValue="role.id" :readonly="true">
|
||||
<MkInput v-if="readonly && role.id != null" :modelValue="role.id" :readonly="true">
|
||||
<template #label>ID</template>
|
||||
</MkInput>
|
||||
|
||||
@@ -866,12 +866,18 @@ import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { deepClone } from '@/utility/clone.js';
|
||||
|
||||
type RoleLike = Pick<Misskey.entities.Role, 'name' | 'description' | 'isAdministrator' | 'isModerator' | 'color' | 'iconUrl' | 'target' | 'isPublic' | 'isExplorable' | 'asBadge' | 'canEditMembersByModerator' | 'displayOrder' | 'preserveAssignmentOnMoveAccount'> & {
|
||||
id?: Misskey.entities.Role['id'] | null;
|
||||
condFormula: any;
|
||||
policies: any;
|
||||
};
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'update:modelValue', v: any): void;
|
||||
(ev: 'update:modelValue', v: RoleLike): void;
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: any;
|
||||
modelValue: RoleLike;
|
||||
readonly?: boolean;
|
||||
}>();
|
||||
|
||||
@@ -910,7 +916,7 @@ const rolePermission = computed<GetMkSelectValueTypesFromDef<typeof rolePermissi
|
||||
|
||||
const q = ref('');
|
||||
|
||||
function getPriorityIcon(option) {
|
||||
function getPriorityIcon(option: { priority: number }): string {
|
||||
if (option.priority === 2) return 'ti ti-arrows-up';
|
||||
if (option.priority === 1) return 'ti ti-arrow-narrow-up';
|
||||
return 'ti ti-point';
|
||||
@@ -936,6 +942,7 @@ const save = throttle(100, () => {
|
||||
isExplorable: role.value.isExplorable,
|
||||
asBadge: role.value.asBadge,
|
||||
canEditMembersByModerator: role.value.canEditMembersByModerator,
|
||||
preserveAssignmentOnMoveAccount: role.value.preserveAssignmentOnMoveAccount,
|
||||
policies: role.value.policies,
|
||||
};
|
||||
|
||||
|
||||
@@ -28,15 +28,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
<template #default="{ items }">
|
||||
<div class="_gaps_s">
|
||||
<div v-for="item in items" :key="item.user.id" :class="[$style.userItem, { [$style.userItemOpened]: expandedItems.includes(item.id) }]">
|
||||
<div v-for="item in items" :key="item.user.id" :class="[$style.userItem, { [$style.userItemOpened]: expandedItemIds.includes(item.id) }]">
|
||||
<div :class="$style.userItemMain">
|
||||
<MkA :class="$style.userItemMainBody" :to="`/admin/user/${item.user.id}`">
|
||||
<MkUserCardMini :user="item.user"/>
|
||||
</MkA>
|
||||
<button class="_button" :class="$style.userToggle" @click="toggleItem(item)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
|
||||
<button class="_button" :class="$style.unassign" @click="unassign(item.user, $event)"><i class="ti ti-x"></i></button>
|
||||
<button class="_button" :class="$style.userToggle" @click="toggleItem(item.id)"><i :class="$style.chevron" class="ti ti-chevron-down"></i></button>
|
||||
<button class="_button" :class="$style.unassign" @click="unassign(item.user.id, $event)"><i class="ti ti-x"></i></button>
|
||||
</div>
|
||||
<div v-if="expandedItems.includes(item.id)" :class="$style.userItemSub">
|
||||
<div v-if="expandedItemIds.includes(item.id)" :class="$style.userItemSub">
|
||||
<div>Assigned: <MkTime :time="item.createdAt" mode="detail"/></div>
|
||||
<div v-if="item.expiresAt">Period: {{ new Date(item.expiresAt).toLocaleString() }}</div>
|
||||
<div v-else>Period: {{ i18n.ts.indefinitely }}</div>
|
||||
@@ -55,6 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, markRaw, reactive, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XEditor from './roles.editor.vue';
|
||||
import MkFolder from '@/components/MkFolder.vue';
|
||||
import * as os from '@/os.js';
|
||||
@@ -81,7 +82,7 @@ const usersPaginator = markRaw(new Paginator('admin/roles/users', {
|
||||
}) : undefined),
|
||||
}));
|
||||
|
||||
const expandedItems = ref<string[]>([]);
|
||||
const expandedItemIds = ref<Misskey.entities.AdminRolesUsersResponse[number]['id'][]>([]);
|
||||
|
||||
const role = reactive(await misskeyApi('admin/roles/show', {
|
||||
roleId: props.id,
|
||||
@@ -91,7 +92,7 @@ function edit() {
|
||||
router.push('/admin/roles/:id/edit', {
|
||||
params: {
|
||||
id: role.id,
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,23 +141,23 @@ async function assign() {
|
||||
//role.users.push(user);
|
||||
}
|
||||
|
||||
async function unassign(user, ev) {
|
||||
async function unassign(userId: Misskey.entities.User['id'], ev: PointerEvent) {
|
||||
os.popupMenu([{
|
||||
text: i18n.ts.unassign,
|
||||
icon: 'ti ti-x',
|
||||
danger: true,
|
||||
action: async () => {
|
||||
await os.apiWithDialog('admin/roles/unassign', { roleId: role.id, userId: user.id });
|
||||
//role.users = role.users.filter(u => u.id !== user.id);
|
||||
await os.apiWithDialog('admin/roles/unassign', { roleId: role.id, userId: userId });
|
||||
//role.users = role.users.filter(u => u.id !== userId);
|
||||
},
|
||||
}], ev.currentTarget ?? ev.target);
|
||||
}
|
||||
|
||||
async function toggleItem(item) {
|
||||
if (expandedItems.value.includes(item.id)) {
|
||||
expandedItems.value = expandedItems.value.filter(x => x !== item.id);
|
||||
async function toggleItem(itemId: string) {
|
||||
if (expandedItemIds.value.includes(itemId)) {
|
||||
expandedItemIds.value = expandedItemIds.value.filter(x => x !== itemId);
|
||||
} else {
|
||||
expandedItems.value.push(item.id);
|
||||
expandedItemIds.value.push(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, markRaw, ref, watchEffect } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { defaultMemoryStorage } from '@/memory-storage';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
@@ -146,7 +147,7 @@ async function addUser() {
|
||||
});
|
||||
}
|
||||
|
||||
function show(user) {
|
||||
function show(user: Misskey.entities.UserDetailed) {
|
||||
os.pageWindow(`/admin/user/${user.id}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user