Skip to content

Commit

Permalink
enhance(frontend): コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように (misskey-de…
Browse files Browse the repository at this point in the history
…v#15438)

* enhance(frontend): コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように

* sessionStorageよりも更に短命な方法で持つように変更

* add comment

---------

Co-authored-by: syuilo <[email protected]>
  • Loading branch information
samunohito and syuilo authored Feb 26, 2025
1 parent 28b4069 commit 15b0345
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Enhance: 開発者モードでメニューからファイルIDをコピー出来るように `#15441'
- Enhance: ノートに埋め込まれたメディアのコンテキストメニューから管理者用のファイル管理画面を開けるように ( #15440 )
- Enhance: リアクションする際に確認ダイアログを表示できるように
- Enhance: コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように `#15437`
- Enhance: CWの注釈で入力済みの文字数を表示
- Fix: ノートページで、クリップ一覧が表示されないことがある問題を修正
- Fix: コンディショナルロールを手動で割り当てできる導線を削除 `#13529`
Expand Down
5 changes: 4 additions & 1 deletion packages/frontend/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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) => {
Expand Down
57 changes: 57 additions & 0 deletions packages/frontend/src/memory-storage.ts
Original file line number Diff line number Diff line change
@@ -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();
44 changes: 38 additions & 6 deletions packages/frontend/src/pages/admin/users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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';
Expand All @@ -69,13 +74,22 @@ import { definePageMetadata } from '@/scripts/page-metadata.js';
import MkUserCardMini from '@/components/MkUserCardMini.vue';
import { dateString } from '@/filters/date.js';

type SearchQuery = {
sort?: string;
state?: string;
origin?: string;
username?: string;
hostname?: string;
};

const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>();
const storedQuery = JSON.parse(defaultMemoryStorage.getItem('admin-users-query') ?? '{}') as SearchQuery;

const sort = ref('+createdAt');
const state = ref('all');
const origin = ref('local');
const searchUsername = ref('');
const searchHost = ref('');
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,
Expand Down Expand Up @@ -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,
Expand All @@ -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',
Expand Down

0 comments on commit 15b0345

Please sign in to comment.