Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: popover target slot width changes according to lsb width change in metricLSB, verification message when adding a user #5239

Open
wants to merge 8 commits into
base: fix/lsb-width_workspace-navigation
Choose a base branch
from
18 changes: 14 additions & 4 deletions apps/web/src/common/modules/page-layouts/VerticalPageLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { PVerticalLayout } from '@cloudforet/mirinae';

import { useGlobalUIStore } from '@/store/global-ui/global-ui-store';

import { MENU_ID } from '@/lib/menu/config';

import { useCurrentMenuId } from '@/common/composables/current-menu-id';
import FNB from '@/common/modules/navigations/FNB.vue';
import { useGnbStore } from '@/common/modules/navigations/stores/gnb-store';
import type { Breadcrumb } from '@/common/modules/page-layouts/type';
Expand All @@ -35,6 +38,9 @@ const { width: contentsWidth } = useElementSize(contentRef);
const storeState = reactive({
isMinimizeNavRail: computed(() => gnbGetters.isMinimizeNavRail),
});

const { currentMenuId } = useCurrentMenuId();

const state = reactive({
padding: computed(() => {
if (contentsWidth.value <= 1920) return '0';
Expand All @@ -52,10 +58,14 @@ watch(() => props.breadcrumbs, () => {
</script>

<template>
<p-vertical-layout v-bind="$props"
ref="contentRef"
class="vertical-page-layout"
v-on="$listeners"
<p-vertical-layout
v-bind="$props"
ref="contentRef"
class="vertical-page-layout"
:width="width"
:min-width="240"
:enable-double-click-resize="currentMenuId === MENU_ID.METRIC_EXPLORER"
v-on="$listeners"
>
<template #sidebar="prop">
<slot name="sidebar"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ onUnmounted(() => {
<template>
<fragment>
<vertical-page-layout v-if="state.lsbVisible">
<template #sidebar>
<asset-inventory-l-s-b />
<template #sidebar="prop">
<asset-inventory-l-s-b :width="prop.width" />
</template>
<template #default>
<router-view />
Expand Down
6 changes: 5 additions & 1 deletion apps/web/src/services/asset-inventory/AssetInventoryLSB.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import MetricExplorerLSB from '@/services/asset-inventory/components/MetricExplo
import SecurityLSB from '@/services/asset-inventory/components/SecurityLSB.vue';

const { currentMenuId } = useCurrentMenuId();
interface props {
width: number;
}
const props = defineProps<props>();
</script>

<template>
<fragment>
<cloud-service-l-s-b v-if="currentMenuId === MENU_ID.CLOUD_SERVICE" />
<metric-explorer-l-s-b v-else-if="currentMenuId === MENU_ID.METRIC_EXPLORER" />
<metric-explorer-l-s-b v-else-if="currentMenuId === MENU_ID.METRIC_EXPLORER" :width="width"/>
<security-l-s-b v-else-if="currentMenuId === MENU_ID.SECURITY" />
</fragment>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ import { useAssetInventorySettingsStore } from '@/services/asset-inventory/store
import { useMetricExplorerPageStore } from '@/services/asset-inventory/stores/metric-explorer-page-store';
import type { NamespaceSubItemType } from '@/services/asset-inventory/types/asset-analysis-type';

interface props {
width : number
}
const props = defineProps<props>();

const lsbRef = ref<HTMLElement|null>(null);
const { width: lsbWidth } = useElementSize(lsbRef);

Expand Down Expand Up @@ -295,16 +300,18 @@ watch(() => storeState.selectedNamespace, (selectedNamespace) => {
<template>
<div class="metric-explorer-l-s-b">
<p-popover class="metric-select-guide-popover"
:is-visible="guidePopoverState.metricGuideVisible"
:is-visible.sync="guidePopoverState.metricGuideVisible"
position="right"
ignore-outside-click
ignore-target-click
boundary=".metric-explorer-l-s-b"
:trigger="POPOVER_TRIGGER.NONE"
min-width="21.5rem"
:style="{ left: `${lsbWidth}px`}"
>
<l-s-b ref="lsbRef"
:menu-set="state.menuSet"
:style="{ width: `${props.width}px` }"
>
<template #collapsible-contents-starred>
<div v-if="state.starredMenuSet.length > 0">
Expand Down Expand Up @@ -418,6 +425,7 @@ watch(() => storeState.selectedNamespace, (selectedNamespace) => {
/>
</template>
</l-s-b>

<template #content>
<div class="metric-select-guide-content">
<p class="title">
Expand Down
71 changes: 30 additions & 41 deletions apps/web/src/services/iam/components/UserManagementAddUser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
} from 'vue';
import type { TranslateResult } from 'vue-i18n';

import { debounce } from 'lodash';

import { SpaceConnector } from '@cloudforet/core-lib/space-connector';
import {
PContextMenu, PEmpty, PFieldGroup, PIconButton, PSelectDropdown, PBadge,
Expand All @@ -26,7 +24,6 @@ import { checkEmailFormat } from '@/services/iam/helpers/user-management-form-va
import { useUserPageStore } from '@/services/iam/store/user-page-store';
import type { AddModalMenuItem, LocalType } from '@/services/iam/types/user-type';


const userPageStore = useUserPageStore();
const userPageState = userPageStore.state;
const domainStore = useDomainStore();
Expand Down Expand Up @@ -62,70 +59,63 @@ const validationState = reactive({
const hideMenu = () => {
emit('change-input', { userList: state.selectedItems });
state.menuVisible = false;
validationState.userIdInvalid = false;
validationState.userIdInvalidText = '';
formState.searchText = '';
};
const handleClickTextInput = async () => {
state.menuVisible = true;
resetValidationState();
};
const handleChangeTextInput = (value: string) => {
validationState.userIdInvalid = false;
validationState.userIdInvalidText = '';
resetValidationState();
formState.searchText = value;
if (!userPageState.isAdminMode || userPageState.afterWorkspaceCreated) {
fetchListUsers();
state.menuVisible = true;
}
};
const handleEnterTextInput = debounce(async (value) => {
const handleEnterTextInput = async () => {
if (formState.searchText === '') return;
if (validateUserId()) {
const isFocusOut = value.type === 'focusout';
await getUserList(isFocusOut);
await getUserList();
}
}, 100);
};
const handleClickDeleteButton = (idx: number) => {
state.selectedItems.splice(idx, 1);
emit('change-input', { userList: state.selectedItems });
};
const handleSelectDropdownItem = (selected: AuthType|LocalType) => {
formState.selectedMenuItem = selected;
validationState.userIdInvalid = false;
validationState.userIdInvalidText = '';
resetValidationState();
};
const getUserList = async (isFocusOut?: boolean) => {

const getUserList = async () => {
let isNew = userPageState.isAdminMode || userPageState.afterWorkspaceCreated;
try {
const trimmedText = formState.searchText.trim();
if (userPageState.isAdminMode || userPageState.afterWorkspaceCreated) {
await fetchGetUsers(formState.searchText);
await fetchGetUsers(trimmedText);
} else {
const isIndependentUser = state.independentUsersList.find((user) => user.user_id === formState.searchText);
isNew = !isIndependentUser;
await fetchGetWorkspaceUsers(formState.searchText);
await fetchGetWorkspaceUsers(trimmedText);
}
} catch (e) {
if (!isFocusOut) {
addSelectedItem(isNew);
}
} finally {
addSelectedItem(isNew);
await hideMenu();
formState.searchText = '';
resetValidationState();
}
};
const checkEmailValidation = () => {
const { isValid, invalidText } = checkEmailFormat(formState.searchText);
if (formState.selectedMenuItem === 'EMAIL') {
if (!isValid) {
validationState.userIdInvalid = true;
validationState.userIdInvalidText = invalidText;
updateValidationState(invalidText);
return false;
}
}
if (formState.selectedMenuItem === 'ID') {
if (isValid) {
validationState.userIdInvalid = true;
validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.ID_INVALID');
updateValidationState(i18n.t('IAM.USER.FORM.ID_INVALID'));
return false;
}
}
Expand All @@ -135,10 +125,14 @@ const resetValidationState = () => {
validationState.userIdInvalid = false;
validationState.userIdInvalidText = '';
};

const updateValidationState = (invalidText: TranslateResult = '', isInvalid = true) => {
validationState.userIdInvalid = isInvalid;
validationState.userIdInvalidText = invalidText;
};
const validateUserId = () => {
if (formState.searchText === '') {
validationState.userIdInvalid = true;
validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.ALT_E_INVALID_FULL_NAME');
updateValidationState(i18n.t('IAM.USER.FORM.ALT_E_INVALID_FULL_NAME'));
return false;
}
return checkEmailValidation();
Expand All @@ -163,15 +157,16 @@ const initAuthTypeList = async () => {
};
const addSelectedItem = (isNew: boolean) => {
if (!formState.searchText) return;
const trimmedText = formState.searchText.trim();
if (state.selectedItems.some((item) => item.name === trimmedText && item.auth_type === formState.selectedMenuItem)) return;

state.selectedItems.unshift({
user_id: formState.searchText?.trim(),
label: formState.searchText?.trim(),
name: formState.searchText?.trim(),
user_id: trimmedText,
label: trimmedText,
name: trimmedText,
isNew,
auth_type: formState.selectedMenuItem,
});
formState.searchText = '';
resetValidationState();
};

/* API */
Expand Down Expand Up @@ -205,19 +200,13 @@ const fetchGetWorkspaceUsers = async (userId: string) => {
await SpaceConnector.clientV2.identity.workspaceUser.get<WorkspaceUserGetParameters, WorkspaceUserModel>({
user_id: userId,
});
validationState.userIdInvalid = true;
validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.USER_ID_INVALID_WORKSPACE', { userId });
updateValidationState(i18n.t('IAM.USER.FORM.USER_ID_INVALID_WORKSPACE', { userId }));
};
const fetchGetUsers = async (userId: string) => {
await SpaceConnector.clientV2.identity.user.get<UserGetParameters, UserModel>({
user_id: userId,
});
if (userPageState.afterWorkspaceCreated) {
addSelectedItem(false);
} else {
validationState.userIdInvalid = true;
validationState.userIdInvalidText = i18n.t('IAM.USER.FORM.USER_ID_INVALID_DOMAIN', { userId });
}
updateValidationState(i18n.t('IAM.USER.FORM.USER_ID_INVALID_DOMAIN', { userId }));
};

onClickOutside(containerRef, clickOutside);
Expand Down Expand Up @@ -271,7 +260,7 @@ onMounted(() => {
class="user-id-input"
:class="{'invalid': invalid}"
@click="handleClickTextInput"
@focusout="handleEnterTextInput"
@blur="handleEnterTextInput"
@keyup.enter="handleEnterTextInput"
@input="handleChangeTextInput($event.target.value)"
>
Expand Down
21 changes: 21 additions & 0 deletions packages/language-pack/console-translation-2.8.babel
Original file line number Diff line number Diff line change
Expand Up @@ -46174,6 +46174,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ID_INVALID</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>en-US</language>
<approved>true</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>true</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>true</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>MEMBER</name>
<definition_loaded>false</definition_loaded>
Expand Down
1 change: 1 addition & 0 deletions packages/language-pack/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,7 @@
"EMAIL_INVALID": "Invalid e-mail format.",
"GENERATE": "Generate",
"GENERATE_PLACEHOLDER": "Generate or Enter Password",
"ID_INVALID": "Invalid ID format.",
"MEMBER": "Member",
"NAME": "Name",
"NAME_VALID": "You can use this ID",
Expand Down
1 change: 1 addition & 0 deletions packages/language-pack/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,7 @@
"EMAIL_INVALID": "無効なメール形式です",
"GENERATE": "生成",
"GENERATE_PLACEHOLDER": "生成またはパスワード入力",
"ID_INVALID": "無効なID形式です。",
"MEMBER": "構成員",
"NAME": "お名前",
"NAME_VALID": "使用可能なIDです",
Expand Down
1 change: 1 addition & 0 deletions packages/language-pack/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -2559,6 +2559,7 @@
"EMAIL_INVALID": "잘못된 이메일 형식입니다. ",
"GENERATE": "생성",
"GENERATE_PLACEHOLDER": "비밀번호 자동 생성 또는 입력",
"ID_INVALID": "잘못된 ID 형식입니다.",
"MEMBER": "멤버",
"NAME": "이름",
"NAME_VALID": "사용 가능한 아이디입니다.",
Expand Down
7 changes: 6 additions & 1 deletion packages/mirinae/src/data-display/popover/PPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ interface PopoverProps {
hideArrow?: boolean;
boundary?: string;
width?: string;
minWidth?: string;
}

const ARROW_STATIC_SIDES = {
Expand Down Expand Up @@ -137,6 +138,10 @@ export default defineComponent<PopoverProps>({
type: String,
default: '',
},
minWidth: {
type: String,
default: '',
},
},
setup(props, { emit }) {
const state = reactive({
Expand Down Expand Up @@ -210,7 +215,7 @@ export default defineComponent<PopoverProps>({
size({
apply({ rects, elements }) {
Object.assign(elements.floating.style, {
minWidth: `${rects.reference.width}px`,
minWidth: props.minWidth ? props.minWidth : `${rects.reference.width}px`,
});
},
}),
Expand Down
16 changes: 16 additions & 0 deletions packages/mirinae/src/data-display/popover/story-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const getPopoverArgs = (): Args => ({
hideArrow: false,
boundary: '',
width: '',
minWidth: '',
'v-model': false,
defaultSlot: null,
contentRefSlot: null,
Expand Down Expand Up @@ -198,6 +199,21 @@ export const getPopoverArgTypes = (): ArgTypes => {
},
control: 'text',
},
minWidth: {
name: 'minWidth',
type: { name: 'string' },
description: 'minWidth of the popover. If the minWidth is not set, it would be calculated based on the width of the component it is applied to.',
table: {
type: {
summary: 'string',
},
category: 'props',
defaultValue: {
summary: false,
},
},
control: 'text',
},
// model
'v-model': {
name: 'v-model',
Expand Down
Loading
Loading