fix MkRoleSelectDialog.vue and storybook scenario

This commit is contained in:
samunohito 2024-02-21 08:40:08 +09:00
parent 06c44a9a02
commit 216325840d
5 changed files with 147 additions and 22 deletions

View File

@ -149,3 +149,50 @@ export function inviteCode(isUsed = false, hasExpiration = false, isExpired = fa
used: isUsed, used: isUsed,
} }
} }
export function role(params: {
id?: string,
name?: string,
color?: string | null,
iconUrl?: string | null,
description?: string,
isModerator?: boolean,
isAdministrator?: boolean,
displayOrder?: number,
createdAt?: string,
updatedAt?: string,
target?: 'manual' | 'conditional',
isPublic?: boolean,
isExplorable?: boolean,
asBadge?: boolean,
canEditMembersByModerator?: boolean,
usersCount?: number,
}): entities.Role {
const prefix = params.displayOrder ? params.displayOrder.toString().padStart(3, '0') + '-' : '';
const genId = Math.random().toString(36).substring(10);
return {
id: params.id ?? genId,
name: params.name ?? `${prefix}TestRole-${genId}`,
color: params.color ?? '#445566',
iconUrl: params.iconUrl ?? null,
description: params.description ?? '',
isModerator: params.isModerator ?? false,
isAdministrator: params.isAdministrator ?? false,
displayOrder: params.displayOrder ?? 0,
createdAt: params.createdAt ?? new Date().toISOString(),
updatedAt: params.updatedAt ?? new Date().toISOString(),
target: params.target ?? 'manual',
isPublic: params.isPublic ?? true,
isExplorable: params.isExplorable ?? true,
asBadge: params.asBadge ?? true,
canEditMembersByModerator: params.canEditMembersByModerator ?? false,
usersCount: params.usersCount ?? 10,
condFormula: {
id: '',
type: 'or',
values: []
},
policies: {},
}
}

View File

@ -410,6 +410,7 @@ function toStories(component: string): Promise<string> {
glob('src/components/MkUserSetupDialog.*.vue'), glob('src/components/MkUserSetupDialog.*.vue'),
glob('src/components/MkInviteCode.vue'), glob('src/components/MkInviteCode.vue'),
glob('src/components/MkTagItem.vue'), glob('src/components/MkTagItem.vue'),
glob('src/components/MkRoleSelectDialog.vue'),
glob('src/pages/user/home.vue'), glob('src/pages/user/home.vue'),
]); ]);
const components = globs.flat(); const components = globs.flat();

View File

@ -276,17 +276,19 @@ const align = () => {
const onOpened = () => { const onOpened = () => {
emit('opened'); emit('opened');
// nextTick(() => {
const el = content.value!.children[0]; //
el.addEventListener('mousedown', ev => { const el = content.value!.children[0];
contentClicking = true; el.addEventListener('mousedown', ev => {
window.addEventListener('mouseup', ev => { contentClicking = true;
// click mouseup window.addEventListener('mouseup', ev => {
window.setTimeout(() => { // click mouseup
contentClicking = false; window.setTimeout(() => {
}, 100); contentClicking = false;
}, { passive: true, once: true }); }, 100);
}, { passive: true }); }, { passive: true, once: true });
}, { passive: true });
});
}; };
const alignObserver = new ResizeObserver((entries, observer) => { const alignObserver = new ResizeObserver((entries, observer) => {

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import { http, HttpResponse } from 'msw';
import { role } from '../../.storybook/fakes.js';
import { commonHandlers } from '../../.storybook/mocks.js';
import MkRoleSelectDialog from '@/components/MkRoleSelectDialog.vue';
const roles = [
role({ displayOrder: 1 }), role({ displayOrder: 1 }), role({ displayOrder: 1 }), role({ displayOrder: 1 }),
role({ displayOrder: 2 }), role({ displayOrder: 2 }), role({ displayOrder: 3 }), role({ displayOrder: 3 }),
role({ displayOrder: 4 }), role({ displayOrder: 5 }), role({ displayOrder: 6 }), role({ displayOrder: 7 }),
];
export const Default = {
render(args) {
return {
components: {
MkRoleSelectDialog,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<MkRoleSelectDialog v-bind="props" />',
};
},
args: {
initialRoleIds: undefined,
infoMessage: undefined,
title: undefined,
publicOnly: true,
},
parameters: {
layout: 'centered',
msw: {
handlers: [
...commonHandlers,
http.post('/api/admin/roles/list', ({ params }) => {
return HttpResponse.json(roles);
}),
],
},
},
decorators: [() => ({
template: '<div style="width:100cqmin"><story/></div>',
})],
} satisfies StoryObj<typeof MkRoleSelectDialog>;
export const InitialIds = {
...Default,
args: {
...Default.args,
initialRoleIds: [roles[0].id, roles[1].id, roles[4].id, roles[6].id],
},
} satisfies StoryObj<typeof MkRoleSelectDialog>;

View File

@ -11,23 +11,21 @@
<template #header>{{ title }}</template> <template #header>{{ title }}</template>
<MkSpacer :marginMin="20" :marginMax="28"> <MkSpacer :marginMin="20" :marginMax="28">
<MkLoading v-if="fetching"/> <MkLoading v-if="fetching"/>
<div v-else class="_gaps"> <div v-else class="_gaps" :class="$style.root">
<div :class="$style.header"> <div :class="$style.header">
<MkButton rounded @click="addRole"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton> <MkButton rounded @click="addRole"><i class="ti ti-plus"></i> {{ i18n.ts.add }}</MkButton>
</div> </div>
<div> <div v-if="selectedRoles.length > 0" class="_gaps" :class="$style.roleItemArea">
<div v-if="selectedRoles.length > 0" class="_gaps" :class="$style.roleItemArea"> <div v-for="role in selectedRoles" :key="role.id" :class="$style.roleItem">
<div v-for="role in selectedRoles" :key="role.id" :class="$style.roleItem"> <MkRolePreview :class="$style.role" :role="role" :forModeration="true" :detailed="false" style="pointer-events: none;"/>
<MkRolePreview :class="$style.role" :role="role" :forModeration="true" :detailed="false" style="pointer-events: none;"/> <button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnAssign" @click="removeRole(role.id)"><i class="ti ti-x"></i></button>
<button v-if="role.target === 'manual'" class="_button" :class="$style.roleUnAssign" @click="removeRole(role.id)"><i class="ti ti-x"></i></button> <button v-else class="_button" :class="$style.roleUnAssign" disabled><i class="ti ti-ban"></i></button>
<button v-else class="_button" :class="$style.roleUnAssign" disabled><i class="ti ti-ban"></i></button>
</div>
</div>
<div v-else :class="$style.roleItemArea" style="text-align: center">
何も選択されていません
</div> </div>
</div> </div>
<div v-else :class="$style.roleItemArea" style="text-align: center">
何も選択されていません
</div>
<MkInfo v-if="infoMessage">{{ infoMessage }}</MkInfo> <MkInfo v-if="infoMessage">{{ infoMessage }}</MkInfo>
@ -134,10 +132,18 @@ fetchRoles();
</script> </script>
<style module lang="scss"> <style module lang="scss">
.root {
max-height: 410px;
height: 410px;
display: flex;
flex-direction: column;
}
.roleItemArea { .roleItemArea {
background-color: var(--acrylicBg); background-color: var(--acrylicBg);
border-radius: var(--radius); border-radius: var(--radius);
padding: 12px; padding: 12px;
overflow-y: auto;
} }
.roleItem { .roleItem {
@ -180,6 +186,7 @@ fetchRoles();
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
margin-top: auto;
} }
.divider { .divider {