Skip to content

Commit

Permalink
Merge pull request #5285 from cloudforet-io/fix/lsb-width_workspace-n…
Browse files Browse the repository at this point in the history
…avigation

merge from fix/lsb-width_workspace-navigation to master
  • Loading branch information
kkdy21 authored Dec 20, 2024
2 parents 7927b20 + 71f7dc2 commit 6b4475c
Show file tree
Hide file tree
Showing 14 changed files with 223 additions and 68 deletions.
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 @@ -46195,6 +46195,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 @@ -2560,6 +2560,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 @@ -2560,6 +2560,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 @@ -2560,6 +2560,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

0 comments on commit 6b4475c

Please sign in to comment.