Skip to content
26 changes: 18 additions & 8 deletions src/components/DiskStateProgressBar/DiskStateProgressBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
$block: &;

$border-width: 1px;
$outer-border-radius: 4px;
$outer-border-radius: var(--g-border-radius-s);
$inner-border-radius: $outer-border-radius - $border-width;
$outer-compact-border-radius: var(--g-border-radius-xs);
$inner-compact-border-radius: $outer-compact-border-radius - $border-width;

--progress-bar-full-height: var(--g-text-body-3-line-height);
--progress-bar-full-height: var(--g-text-subheader-2-line-height);
--progress-bar-compact-height: 12px;

--stripe-width: 4px;
Expand All @@ -16,6 +18,8 @@
position: relative;
z-index: 0;

overflow: hidden;

min-width: 50px;
height: var(--progress-bar-full-height);

Expand All @@ -25,13 +29,14 @@
border: $border-width solid var(--entity-state-border-color);
border-radius: $outer-border-radius;
background-color: var(--entity-state-background-color);
@include mixins.entity-state-colors();

@include mixins.entity-state-colors($block);

&_compact {
min-width: 0;
height: var(--progress-bar-compact-height);

border-radius: 2px;
border-radius: $outer-compact-border-radius;
}

&_faded {
Expand All @@ -42,6 +47,10 @@
opacity: 0.5;
}

&_darkened {
opacity: 0.7;
}

&_empty {
color: var(--g-color-text-hint);
border-style: dashed;
Expand Down Expand Up @@ -78,7 +87,7 @@
}

&_compact {
border-radius: 1px;
border-radius: $inner-compact-border-radius;
}

&_inverted {
Expand All @@ -93,9 +102,10 @@
position: relative;
z-index: 2;

margin-right: var(--g-spacing-1);
margin-right: var(--g-spacing-half);

font-size: var(--g-text-body-1-font-size);
font-family: var(--g-text-caption-font-family);
font-size: var(--g-text-caption-1-font-size);
// bar height minus borders
line-height: calc(var(--progress-bar-full-height) - #{$border-width * 2});

Expand All @@ -106,7 +116,7 @@
position: relative;
z-index: 2;

margin-left: var(--g-spacing-1);
margin-left: calc(var(--g-spacing-1) - $border-width);

color: var(--entity-state-border-color);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ interface DiskStateProgressBarProps {
className?: string;
isDonor?: boolean;
withIcon?: boolean;
highlighted?: boolean;
darkened?: boolean;
}

export function DiskStateProgressBar({
Expand All @@ -38,6 +40,8 @@ export function DiskStateProgressBar({
className,
isDonor,
withIcon,
highlighted,
darkened,
}: DiskStateProgressBarProps) {
const [inverted] = useSetting<boolean | undefined>(SETTING_KEYS.INVERTED_DISKS);

Expand All @@ -48,6 +52,8 @@ export function DiskStateProgressBar({
empty,
inactive,
striped,
highlighted,
darkened,
};

if (isDonor) {
Expand Down
49 changes: 37 additions & 12 deletions src/components/HoverPopup/HoverPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,44 +34,50 @@ export const HoverPopup = ({
delayOpen = DEBOUNCE_TIMEOUT,
}: HoverPopupProps) => {
const [isPopupVisible, setIsPopupVisible] = React.useState(false);
const [isPopupContentHovered, setIsPopupContentHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);

const anchor = React.useRef<HTMLDivElement>(null);

const debouncedHandleShowPopup = React.useMemo(
() =>
debounce(() => {
setIsPopupVisible(true);
onShowPopup?.();
}, delayOpen),
[onShowPopup, delayOpen],
[delayOpen],
);

const hidePopup = React.useCallback(() => {
setIsPopupVisible(false);
onHidePopup?.();
}, [onHidePopup]);
}, []);

const debouncedHandleHidePopup = React.useMemo(
() => debounce(hidePopup, delayClose),
() =>
debounce(() => {
hidePopup();
}, delayClose),
[hidePopup, delayClose],
);

const onMouseEnter = debouncedHandleShowPopup;
const onMouseEnter = () => {
debouncedHandleHidePopup.cancel();
debouncedHandleShowPopup();
};

const onMouseLeave = () => {
debouncedHandleShowPopup.cancel();
debouncedHandleHidePopup();
};

const [isPopupContentHovered, setIsPopupContentHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);

const onPopupMouseEnter = React.useCallback(() => {
setIsPopupContentHovered(true);
}, []);
debouncedHandleHidePopup.cancel();
}, [debouncedHandleHidePopup]);

const onPopupMouseLeave = React.useCallback(() => {
setIsPopupContentHovered(false);
}, []);
debouncedHandleHidePopup();
}, [debouncedHandleHidePopup]);

const onPopupContextMenu = React.useCallback(() => {
setIsFocused(true);
Expand All @@ -87,7 +93,26 @@ export const HoverPopup = ({
hidePopup();
}, [hidePopup]);

const open = isPopupVisible || showPopup || isPopupContentHovered || isFocused;
const internalOpen = isPopupVisible || isPopupContentHovered || isFocused;
const open = internalOpen || showPopup;

const prevInternalOpenRef = React.useRef(internalOpen);

React.useEffect(() => {
const prev = prevInternalOpenRef.current;

if (prev === internalOpen) {
return;
}

if (internalOpen) {
onShowPopup?.();
} else {
onHidePopup?.();
}

prevInternalOpenRef.current = internalOpen;
}, [internalOpen, onShowPopup, onHidePopup]);

return (
<React.Fragment>
Expand Down
12 changes: 9 additions & 3 deletions src/components/VDisk/VDisk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface VDiskProps {
delayOpen?: number;
delayClose?: number;
withIcon?: boolean;
highlighted?: boolean;
darkened?: boolean;
}

export const VDisk = ({
Expand All @@ -35,13 +37,15 @@ export const VDisk = ({
delayClose,
delayOpen,
withIcon,
highlighted,
darkened,
}: VDiskProps) => {
const getVDiskLink = useVDiskPagePath();
const vDiskPath = getVDiskLink({nodeId: data.NodeId, vDiskId: data.StringifiedId});

const severity = data.Severity;
const isReplicatingColor = severity === DISK_COLOR_STATE_TO_NUMERIC_SEVERITY.Blue;
const isHealthyDonor = data.DonorMode && isReplicatingColor;
const isDonor = data.DonorMode;

return (
<HoverPopup
Expand All @@ -60,10 +64,12 @@ export const VDisk = ({
severity={severity}
compact={compact}
inactive={inactive}
striped={isReplicatingColor}
isDonor={isHealthyDonor}
striped={isReplicatingColor || isDonor}
isDonor={isDonor}
className={progressBarClassName}
withIcon={withIcon}
highlighted={highlighted}
darkened={darkened}
/>
</InternalLink>
</div>
Expand Down
37 changes: 32 additions & 5 deletions src/components/VDisk/VDiskWithDonorsStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,64 @@ interface VDiskWithDonorsStackProps extends VDiskProps {
data?: PreparedVDisk;
className?: string;
stackClassName?: string;
highlightedVDisk?: string;
setHighlightedVDisk?: (id?: string) => void;
progressBarClassName?: string;
}

export function VDiskWithDonorsStack({
data,
className,
stackClassName,
withIcon,
highlightedVDisk,
setHighlightedVDisk,
...restProps
}: VDiskWithDonorsStackProps) {
const {Donors: donors, ...restData} = data || {};

const stackId = data?.StringifiedId;
const isHighlighted = Boolean(stackId && highlightedVDisk === stackId);
const isDarkened = Boolean(highlightedVDisk && highlightedVDisk !== stackId);

const handleShowPopup = () => {
if (stackId) {
setHighlightedVDisk?.(stackId);
}
};

const handleHidePopup = () => {
setHighlightedVDisk?.(undefined);
};

const commonVDiskProps: Partial<VDiskProps> = {
withIcon,
showPopup: isHighlighted,
highlighted: isHighlighted,
darkened: isDarkened,
onShowPopup: handleShowPopup,
onHidePopup: handleHidePopup,
...restProps,
};

const content =
donors && donors.length > 0 ? (
<Stack className={stackClassName}>
<VDisk data={restData} withIcon={withIcon} {...restProps} />
<VDisk data={restData} {...commonVDiskProps} />
{donors.map((donor) => {
const isFullData = isFullVDiskData(donor);

// donor and acceptor are always in the same group
return (
<VDisk
key={stringifyVdiskId(isFullData ? donor.VDiskId : donor)}
data={donor}
withIcon={withIcon}
{...restProps}
{...commonVDiskProps}
/>
);
})}
</Stack>
) : (
<VDisk withIcon={withIcon} data={data} {...restProps} />
<VDisk data={data} withIcon={withIcon} {...commonVDiskProps} />
);

return <div className={className}>{content}</div>;
Expand Down
22 changes: 8 additions & 14 deletions src/components/VDiskPopup/VDiskPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -345,21 +345,15 @@ const prepareHeaderLabels = (data: PreparedVDisk): YDBDefinitionListHeaderLabel[
theme: donorConfig.theme,
icon: donorConfig.icon,
});
}

if (isReplicatingColor) {
if (!DonorMode) {
const replicaConfig = VDISK_LABEL_CONFIG.replica;
} else if (isReplicatingColor) {
const replicaConfig = VDISK_LABEL_CONFIG.replica;

labels.push({
id: 'replication',
value: vDiskPopupKeyset('label_replication'),
theme: replicaConfig.theme,
icon: replicaConfig.icon,
});
}

return labels;
labels.push({
id: 'replication',
value: vDiskPopupKeyset('label_replication'),
theme: replicaConfig.theme,
icon: replicaConfig.icon,
});
}

const severity = VDiskState ? getStateSeverity(VDiskState) : NOT_AVAILABLE_SEVERITY;
Expand Down
4 changes: 0 additions & 4 deletions src/components/YDBDefinitionList/YDBDefinitionList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
color: var(--g-color-text-secondary);
}

&__properties-list {
max-width: calc(100% - 40px);
}

&__footer {
margin-top: var(--g-spacing-3);
}
Expand Down
10 changes: 5 additions & 5 deletions src/containers/Storage/Disks/Disks.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
display: flex;
flex-direction: row;
align-items: center;
gap: 20px;
gap: var(--g-spacing-4);

width: max-content;

Expand All @@ -19,13 +19,13 @@
flex-shrink: 0;
}
&__vdisk-progress-bar {
--progress-bar-compact-height: 18px;
--progress-bar-compact-height: 20px;

border-radius: 4px;
border-radius: var(--g-border-radius-m);
}

&__pdisk-item {
min-width: 80px;
min-width: 55px;
margin-right: 4px;

&_with-dc-margin {
Expand All @@ -39,6 +39,6 @@
&__pdisk-progress-bar {
--progress-bar-full-height: 20px;

text-align: left;
border-radius: var(--g-border-radius-m);
}
}
Loading
Loading