enhance(frontend): コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように (#15438)
* enhance(frontend): コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように * sessionStorageよりも更に短命な方法で持つように変更 * add comment --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
parent
28b40691d5
commit
15b0345335
@ -13,6 +13,7 @@
|
||||
- Enhance: 開発者モードでメニューからファイルIDをコピー出来るように `#15441'
|
||||
- Enhance: ノートに埋め込まれたメディアのコンテキストメニューから管理者用のファイル管理画面を開けるように ( #15440 )
|
||||
- Enhance: リアクションする際に確認ダイアログを表示できるように
|
||||
- Enhance: コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように `#15437`
|
||||
- Enhance: CWの注釈で入力済みの文字数を表示
|
||||
- Fix: ノートページで、クリップ一覧が表示されないことがある問題を修正
|
||||
- Fix: コンディショナルロールを手動で割り当てできる導線を削除 `#13529`
|
||||
|
@ -7,6 +7,7 @@ import { defineAsyncComponent, reactive, ref } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { apiUrl } from '@@/js/config.js';
|
||||
import type { MenuItem, MenuButton } from '@/types/menu.js';
|
||||
import { defaultMemoryStorage } from '@/memory-storage';
|
||||
import { showSuspendedDialog } from '@/scripts/show-suspended-dialog.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
@ -40,6 +41,8 @@ export function incNotesCount() {
|
||||
export async function signout() {
|
||||
if (!$i) return;
|
||||
|
||||
defaultMemoryStorage.clear();
|
||||
|
||||
waiting();
|
||||
document.cookie.split(';').forEach((cookie) => {
|
||||
const cookieName = cookie.split('=')[0].trim();
|
||||
@ -107,7 +110,7 @@ export async function removeAccount(idOrToken: Account['id']) {
|
||||
}
|
||||
|
||||
function fetchAccount(token: string, id?: string, forceShowDialog?: boolean): Promise<Account> {
|
||||
document.cookie = "token=; path=/; max-age=0";
|
||||
document.cookie = 'token=; path=/; max-age=0';
|
||||
document.cookie = `token=${token}; path=/queue; max-age=86400; SameSite=Strict; Secure`; // bull dashboardの認証とかで使う
|
||||
|
||||
return new Promise((done, fail) => {
|
||||
|
57
packages/frontend/src/memory-storage.ts
Normal file
57
packages/frontend/src/memory-storage.ts
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export type MemoryStorage = {
|
||||
has: (key: string) => boolean;
|
||||
getItem: <T>(key: string) => T | null;
|
||||
setItem: (key: string, value: unknown) => void;
|
||||
removeItem: (key: string) => void;
|
||||
clear: () => void;
|
||||
size: number;
|
||||
};
|
||||
|
||||
class MemoryStorageImpl implements MemoryStorage {
|
||||
private readonly storage: Map<string, unknown>;
|
||||
|
||||
constructor() {
|
||||
this.storage = new Map();
|
||||
}
|
||||
|
||||
has(key: string): boolean {
|
||||
return this.storage.has(key);
|
||||
}
|
||||
|
||||
getItem<T>(key: string): T | null {
|
||||
return this.storage.has(key) ? this.storage.get(key) as T : null;
|
||||
}
|
||||
|
||||
setItem(key: string, value: unknown): void {
|
||||
this.storage.set(key, value);
|
||||
}
|
||||
|
||||
removeItem(key: string): void {
|
||||
this.storage.delete(key);
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.storage.clear();
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this.storage.size;
|
||||
}
|
||||
}
|
||||
|
||||
export function createMemoryStorage(): MemoryStorage {
|
||||
return new MemoryStorageImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* SessionStorageよりも更に短い期間でクリアされるストレージです
|
||||
* - ブラウザの再読み込みやタブの閉じると内容が揮発します
|
||||
* - このストレージは他のタブと共有されません
|
||||
* - アカウント切り替えやログアウトを行うと内容が揮発します
|
||||
*/
|
||||
export const defaultMemoryStorage: MemoryStorage = createMemoryStorage();
|
@ -9,6 +9,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||
<MkSpacer :contentMax="900">
|
||||
<div class="_gaps">
|
||||
<div :class="$style.inputs">
|
||||
<MkButton style="margin-left: auto" @click="resetQuery">{{ i18n.ts.reset }}</MkButton>
|
||||
</div>
|
||||
<div :class="$style.inputs">
|
||||
<MkSelect v-model="sort" style="flex: 1;">
|
||||
<template #label>{{ i18n.ts.sort }}</template>
|
||||
@ -57,8 +60,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, shallowRef, ref } from 'vue';
|
||||
import { computed, shallowRef, ref, watchEffect } from 'vue';
|
||||
import XHeader from './_header_.vue';
|
||||
import { defaultMemoryStorage } from '@/memory-storage';
|
||||
import MkButton from '@/components/MkButton.vue';
|
||||
import MkInput from '@/components/MkInput.vue';
|
||||
import MkSelect from '@/components/MkSelect.vue';
|
||||
import MkPagination from '@/components/MkPagination.vue';
|
||||
@ -69,13 +74,22 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||
import { dateString } from '@/filters/date.js';
|
||||
|
||||
const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
type SearchQuery = {
|
||||
sort?: string;
|
||||
state?: string;
|
||||
origin?: string;
|
||||
username?: string;
|
||||
hostname?: string;
|
||||
};
|
||||
|
||||
const sort = ref('+createdAt');
|
||||
const state = ref('all');
|
||||
const origin = ref('local');
|
||||
const searchUsername = ref('');
|
||||
const searchHost = ref('');
|
||||
const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
|
||||
const storedQuery = JSON.parse(defaultMemoryStorage.getItem('admin-users-query') ?? '{}') as SearchQuery;
|
||||
|
||||
const sort = ref(storedQuery.sort ?? '+createdAt');
|
||||
const state = ref(storedQuery.state ?? 'all');
|
||||
const origin = ref(storedQuery.origin ?? 'local');
|
||||
const searchUsername = ref(storedQuery.username ?? '');
|
||||
const searchHost = ref(storedQuery.hostname ?? '');
|
||||
const pagination = {
|
||||
endpoint: 'admin/show-users' as const,
|
||||
limit: 10,
|
||||
@ -119,6 +133,14 @@ function show(user) {
|
||||
os.pageWindow(`/admin/user/${user.id}`);
|
||||
}
|
||||
|
||||
function resetQuery() {
|
||||
sort.value = '+createdAt';
|
||||
state.value = 'all';
|
||||
origin.value = 'local';
|
||||
searchUsername.value = '';
|
||||
searchHost.value = '';
|
||||
}
|
||||
|
||||
const headerActions = computed(() => [{
|
||||
icon: 'ti ti-search',
|
||||
text: i18n.ts.search,
|
||||
@ -137,6 +159,16 @@ const headerActions = computed(() => [{
|
||||
|
||||
const headerTabs = computed(() => []);
|
||||
|
||||
watchEffect(() => {
|
||||
defaultMemoryStorage.setItem('admin-users-query', JSON.stringify({
|
||||
sort: sort.value,
|
||||
state: state.value,
|
||||
origin: origin.value,
|
||||
username: searchUsername.value,
|
||||
hostname: searchHost.value,
|
||||
}));
|
||||
});
|
||||
|
||||
definePageMetadata(() => ({
|
||||
title: i18n.ts.users,
|
||||
icon: 'ti ti-users',
|
||||
|
Loading…
x
Reference in New Issue
Block a user