Skip to content

Commit

Permalink
web: Move storage/SpacePolicyField to its own file
Browse files Browse the repository at this point in the history
And adapts it to use a core/Field/SettingsField button.
  • Loading branch information
dgdavid committed Apr 10, 2024
1 parent 035343d commit d4244a4
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 69 deletions.
71 changes: 3 additions & 68 deletions web/src/components/storage/ProposalSettingsSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ import React, { useEffect, useState } from "react";
import { Button, Checkbox, Form, Skeleton, Switch, Tooltip } from "@patternfly/react-core";

import { sprintf } from "sprintf-js";
import { _, n_ } from "~/i18n";
import { BootSelectionDialog, ProposalVolumes, SpacePolicyDialog } from "~/components/storage";
import { _ } from "~/i18n";
import { BootSelectionDialog, ProposalVolumes } from "~/components/storage";
import SpacePolicyField from "~/components/storage/SpacePolicyField";
import { If, PasswordAndConfirmationInput, Section, Popup } from "~/components/core";
import { Icon } from "~/components/layout";
import { noop } from "~/utils";
Expand Down Expand Up @@ -337,72 +338,6 @@ const BootConfigField = ({
);
};

/**
* Allows to select the space policy.
* @component
*
* @param {object} props
* @param {SpacePolicy|undefined} props.policy
* @param {SpaceAction[]} props.actions
* @param {StorageDevice[]} props.devices
* @param {boolean} props.isLoading
* @param {(config: SpacePolicyConfig) => void} props.onChange
*
* @typedef {object} SpacePolicyConfig
* @property {SpacePolicy} spacePolicy
* @property {SpaceAction[]} spaceActions
*/
const SpacePolicyField = ({
policy,
actions,
devices,
isLoading,
onChange
}) => {
const [isDialogOpen, setIsDialogOpen] = useState(false);

const openDialog = () => setIsDialogOpen(true);

const closeDialog = () => setIsDialogOpen(false);

const onAccept = ({ spacePolicy, spaceActions }) => {
closeDialog();
onChange({ spacePolicy, spaceActions });
};

const label = () => {
// eslint-disable-next-line agama-i18n/string-literals
if (policy.summaryLabels.length === 1) return _(policy.summaryLabels[0]);

// eslint-disable-next-line agama-i18n/string-literals
return sprintf(n_(policy.summaryLabels[0], policy.summaryLabels[1], devices.length), devices.length);
};

if (isLoading || !policy) {
return <Skeleton screenreaderText={_("Waiting for information about space policy")} width="25%" />;
}

return (
<div className="split">
<span>{_("Find space")}</span>
<Button variant="link" isInline onClick={openDialog}>{label()}</Button>
<If
condition={isDialogOpen}
then={
<SpacePolicyDialog
isOpen
policy={policy}
actions={actions}
devices={devices}
onAccept={onAccept}
onCancel={closeDialog}
/>
}
/>
</div>
);
};

/**
* Section for editing the proposal settings
* @component
Expand Down
106 changes: 106 additions & 0 deletions web/src/components/storage/SpacePolicyField.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (c) [2024] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

// @ts-check

import React, { useState } from "react";
import { Skeleton } from "@patternfly/react-core";

import { sprintf } from "sprintf-js";
import { _, n_ } from "~/i18n";
import { If, SettingsField } from "~/components/core";
import SpacePolicyDialog from "~/components/storage/SpacePolicyDialog";

/**
* @typedef {import ("~/client/storage").SpaceAction} SpaceAction
* @typedef {import ("~/components/storage/utils").SpacePolicy} SpacePolicy
* @typedef {import ("~/client/storage").StorageDevice} StorageDevice
*
* @typedef {object} SpacePolicyConfig
* @property {SpacePolicy} spacePolicy
* @property {SpaceAction[]} spaceActions
*/

/**
* Allows to select the space policy.
* @component
*
* @param {object} props
* @param {SpacePolicy|undefined} props.policy
* @param {SpaceAction[]} props.actions
* @param {StorageDevice[]} props.devices
* @param {boolean} props.isLoading
* @param {(config: SpacePolicyConfig) => void} props.onChange
*
*/
export default function SpacePolicyField({
policy,
actions,
devices,
isLoading,
onChange
}) {
const [isDialogOpen, setIsDialogOpen] = useState(false);

const openDialog = () => setIsDialogOpen(true);

const closeDialog = () => setIsDialogOpen(false);

const onAccept = ({ spacePolicy, spaceActions }) => {
closeDialog();
onChange({ spacePolicy, spaceActions });
};

let value;
if (isLoading || !policy) {
value = <Skeleton screenreaderText={_("Waiting for information about space policy")} width="25%" />;
} else if (policy.summaryLabels.length === 1) {
// eslint-disable-next-line agama-i18n/string-literals
value = _(policy.summaryLabels[0]);
} else {
// eslint-disable-next-line agama-i18n/string-literals
value = sprintf(n_(policy.summaryLabels[0], policy.summaryLabels[1], devices.length), devices.length);
}

return (
<SettingsField
label={_("Find space")}
value={value}
description={ _("Allocating the file systems might need to find free space \
in the installation device(s).")}
onClick={openDialog}
>
<If
condition={isDialogOpen}
then={
<SpacePolicyDialog
isOpen
policy={policy}
actions={actions}
devices={devices}
onAccept={onAccept}
onCancel={closeDialog}
/>
}
/>
</SettingsField>
);
}
2 changes: 1 addition & 1 deletion web/src/components/storage/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ const deviceLabel = (device) => {
const deviceChildren = (device) => {
const partitionTableChildren = (partitionTable) => {
const { partitions, unusedSlots } = partitionTable;
const children = partitions.concat(unusedSlots);
const children = partitions.concat(unusedSlots).filter(i => !!i);
return children.sort((a, b) => a.start < b.start ? -1 : 1);
};

Expand Down

0 comments on commit d4244a4

Please sign in to comment.