Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import React, { PropsWithChildren, useMemo } from 'react';
import {
OsdsRadio,
OsdsRadioButton,
OsdsRadioGroup,
OsdsText,
} from '@ovhcloud/ods-components/react';
import { Subtitle } from '@ovh-ux/manager-react-components';
import {
ODS_RADIO_BUTTON_SIZE,
ODS_TEXT_LEVEL,
ODS_TEXT_SIZE,
} from '@ovhcloud/ods-components';
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import { Badge } from '@ovh-ux/manager-pci-common';
import clsx from 'clsx';
import { PropsWithChildren, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
Badge,
BADGE_COLOR,
BADGE_SIZE,
Radio as OdsRadio,
RadioControl,
RadioGroup,
RadioLabel,
Text,
TEXT_PRESET,
} from '@ovhcloud/ods-react';
import { EncryptionType } from '@/api/select/volume';
import { useVolumeEncryptions } from '@/api/hooks/useCatalog';

Expand All @@ -23,25 +19,14 @@ const Radio = ({
value,
disabled,
}: PropsWithChildren<{ value: string; disabled?: boolean }>) => (
<OsdsRadio
<OdsRadio
value={value}
name="encryption"
aria-label="encryption"
{...(disabled ? { disabled: true } : {})}
>
<OsdsRadioButton
size={ODS_RADIO_BUTTON_SIZE.xs}
color={ODS_THEME_COLOR_INTENT.primary}
>
<OsdsText
color={ODS_THEME_COLOR_INTENT.text}
size={ODS_TEXT_SIZE._400}
slot="end"
className={clsx(!disabled && 'cursor-pointer')}
>
{children}
</OsdsText>
</OsdsRadioButton>
</OsdsRadio>
<RadioControl />
<RadioLabel>{children}</RadioLabel>
</OdsRadio>
);

interface Props {
Expand Down Expand Up @@ -83,64 +68,49 @@ export const Encryption = ({

return (
<fieldset className="border-0 p-0" role="radiogroup">
<legend className="flex items-baseline p-0">
<Subtitle>{title}</Subtitle>
<legend className="flex items-center p-0 mb-4 gap-4">
<Text preset={TEXT_PRESET.heading3}>{title}</Text>
{isNew && (
<Badge
color="new"
label={t('common:pci_projects_project_storages_blocks_new')}
className="ml-4"
/>
<Badge color={BADGE_COLOR.new}>
{t('common:pci_projects_project_storages_blocks_new')}
</Badge>
)}
</legend>

{description && (
<OsdsText
size={ODS_TEXT_SIZE._400}
level={ODS_TEXT_LEVEL.body}
color={ODS_THEME_COLOR_INTENT.text}
>
{description}
</OsdsText>
)}
{description && <Text>{description}</Text>}

<div>
<OsdsRadioGroup
name="encryption"
value={encryptionType ?? 'none'}
onOdsValueChange={({ detail }) =>
onChange(
detail.newValue === 'none'
? null
: (detail.newValue as EncryptionType),
)
}
>
{enabledEncryptions.map(({ value, label }) => (
<Radio value={value} key={value}>
{label}
</Radio>
))}
</OsdsRadioGroup>
<RadioGroup
name="encryption"
className="pl-6 mt-4"
value={encryptionType ?? 'none'}
onValueChange={({ value }) =>
onChange(value === 'none' ? null : (value as EncryptionType))
}
>
{enabledEncryptions.map(({ value, label }) => (
<Radio value={value} key={value}>
{label}
</Radio>
))}
{/* We need to put it outside radio group because ODS does weird things with disable */}
{disabledEncryptions.map(({ value, label, comingSoon }) => (
<div key={value} className="flex items-baseline">
<div key={value} className="flex items-center">
<Radio value={value} disabled>
{label}
</Radio>

{comingSoon && (
<Badge
label={t(
'common:pci_projects_project_storages_blocks_coming_soon',
)}
color="neutral"
color={BADGE_COLOR.neutral}
className="ml-5"
/>
size={BADGE_SIZE.sm}
>
{t('common:pci_projects_project_storages_blocks_coming_soon')}
</Badge>
)}
</div>
))}
</div>
</RadioGroup>
</fieldset>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TilesInput, useBytes } from '@ovh-ux/manager-pci-common';
import { useMemo } from 'react';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import clsx from 'clsx';
import { TVolumeModel } from '@/api/hooks/useCatalog';
import { TVolumeRetypeModel } from '@/api/hooks/useCatalogWithPreselection';

Expand All @@ -10,6 +11,7 @@ type Props<T = TVolumeModel | TVolumeRetypeModel> = {
onChange: (value: T) => void;
label: string;
locked?: boolean;
horizontal?: boolean;
};

export const VolumeModelTilesInput = ({
Expand All @@ -18,22 +20,61 @@ export const VolumeModelTilesInput = ({
onChange,
label = '',
locked = false,
horizontal = false,
}: Props) => {
const { t } = useTranslation(['add', 'common']);
const { formatBytes } = useBytes();

const getDescription = useCallback(
(model: TVolumeModel | TVolumeRetypeModel) => {
const zoneText = model.availabilityZonesCount
? t(
'add:pci_projects_project_storages_blocks_add_type_availability_zone',
{ count: model.availabilityZonesCount },
)
: undefined;

const capacityMax = t(
'add:pci_projects_project_storages_blocks_add_type_addon_capacity_max',
{
capacity: formatBytes(model.capacity.max),
},
);

if (horizontal) {
const zoneDescription = zoneText ? `${zoneText}.\n` : '';
return `${zoneDescription}${model.iops}, ${capacityMax}`;
}

return zoneText;
},
[t, formatBytes],
);

const getFeatures = useCallback(
(m: TVolumeModel | TVolumeRetypeModel) => {
if (horizontal) return [];

return [
m.iops,
t(
'add:pci_projects_project_storages_blocks_add_type_addon_capacity_max',
{
capacity: formatBytes(m.capacity.max),
},
),
...(m.bandwidth ? [m.bandwidth] : []),
];
},
[t, formatBytes],
);

const volumeTypes = useMemo(
() =>
volumeModels.map((m) => ({
...m,
label: m.displayName,
description:
m.availabilityZonesCount !== null
? t(
'add:pci_projects_project_storages_blocks_add_type_availability_zone',
{ count: m.availabilityZonesCount },
)
: undefined,
description: getDescription(m),
badges: [
m.encrypted
? {
Expand All @@ -53,18 +94,10 @@ export const VolumeModelTilesInput = ({
icon: 'lock' as const,
},
],
features: [
m.iops,
t(
'add:pci_projects_project_storages_blocks_add_type_addon_capacity_max',
{
capacity: formatBytes(m.capacity.max),
},
),
].concat(m.bandwidth ? [m.bandwidth] : []),
features: getFeatures(m),
price: m.hourlyPrice,
})),
[volumeModels, t, formatBytes],
[volumeModels, t, getDescription, getFeatures],
);

const volumeTypeValue = useMemo(
Expand All @@ -73,13 +106,20 @@ export const VolumeModelTilesInput = ({
);

return (
<TilesInput
name="volume-type"
label={label}
value={volumeTypeValue}
elements={volumeTypes}
onChange={(e) => onChange(e)}
locked={locked}
/>
<div
className={clsx(
horizontal && '[&_.config-card\\_\\_badges]:w-full whitespace-pre-line',
)}
>
<TilesInput
name="volume-type"
label={label}
value={volumeTypeValue}
elements={volumeTypes}
onChange={(e) => onChange(e)}
locked={locked}
horizontal={horizontal}
/>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ export function VolumeTypeStep({
<Encryption
encryptionType={encryptionType}
onChange={setEncryptionType}
title={t('common:pci_projects_project_storages_blocks_new')}
title={t(
'common:pci_projects_project_storages_blocks_encrypted_label',
)}
description={t(
'add:pci_projects_project_storages_blocks_add_encryption_description',
)}
Expand All @@ -110,7 +112,7 @@ export function VolumeTypeStep({
)
}
actionName="select_volume_add"
actionValues={[volumeType.name]}
actionValues={[volumeModel.name]}
className="w-fit"
>
{t('common_stepper_next_button_label')}
Expand Down
Loading
Loading