Skip to content

Commit

Permalink
WIP: [web] Changes in the volumes table
Browse files Browse the repository at this point in the history
  • Loading branch information
ancorgs committed Apr 4, 2024
1 parent 6291da5 commit ad3b86a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 35 deletions.
17 changes: 11 additions & 6 deletions web/src/client/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const ZFCP_DISK_IFACE = "org.opensuse.Agama.Storage1.ZFCP.Disk";
* @typedef {object} Volume
* @property {string} mountPath
* @property {string} target
* @property {string} [targetDevice]
* @property {StorageDevice} [targetDevice]
* @property {string} fsType
* @property {number} minSize
* @property {number} [maxSize]
Expand Down Expand Up @@ -430,7 +430,8 @@ class ProposalManager {
*/
async defaultVolume(mountPath) {
const proxy = await this.proxies.proposalCalculator;
return this.buildVolume(await proxy.DefaultVolume(mountPath));
const systemDevices = await this.system.getDevices();
return this.buildVolume(await proxy.DefaultVolume(mountPath), systemDevices);
}

/**
Expand Down Expand Up @@ -505,7 +506,7 @@ class ProposalManager {
spaceActions: dbusSettings.SpaceActions.v.map(a => buildSpaceAction(a.v)),
encryptionPassword: dbusSettings.EncryptionPassword.v,
encryptionMethod: dbusSettings.EncryptionMethod.v,
volumes: dbusSettings.Volumes.v.map(vol => this.buildVolume(vol.v)),
volumes: dbusSettings.Volumes.v.map(vol => this.buildVolume(vol.v, systemDevices)),
// NOTE: strictly speaking, installation devices does not belong to the settings. It
// should be a separate method instead of an attribute in the settings object.
// Nevertheless, it was added here for simplicity and to avoid passing more props in some
Expand Down Expand Up @@ -559,6 +560,8 @@ class ProposalManager {
MinSize: { t: "t", v: volume.minSize },
MaxSize: { t: "t", v: volume.maxSize },
AutoSize: { t: "b", v: volume.autoSize },
Target: { t: "s", v: volume.target },
TargetDevice: { t: "s", v: volume.targetDevice?.name },
Snapshots: { t: "b", v: volume.snapshots },
Transactional: { t: "b", v: volume.transactional },
});
Expand Down Expand Up @@ -597,6 +600,8 @@ class ProposalManager {
* @property {CockpitBoolean} AutoSize
* @property {CockpitBoolean} Snapshots
* @property {CockpitBoolean} Transactional
* @property {CockpitString} Target
* @property {CockpitString} [TargetDevice]
* @property {CockpitVolumeOutline} Outline
*
* @typedef {Object} DBusVolumeOutline
Expand Down Expand Up @@ -629,7 +634,7 @@ class ProposalManager {
*
* @returns {Volume}
*/
buildVolume(dbusVolume) {
buildVolume(dbusVolume, devices) {
const buildOutline = (dbusOutline) => {
if (dbusOutline === undefined) return null;

Expand All @@ -645,8 +650,8 @@ class ProposalManager {
};

return {
target: dbusVolume.Target.v,
targetDevice: dbusVolume.TargetDevice?.v,
target: dbusVolume.Target?.v || "default",
targetDevice: devices.find(d => d.name === dbusVolume.TargetDevice?.v),
mountPath: dbusVolume.MountPath.v,
fsType: dbusVolume.FsType.v,
minSize: dbusVolume.MinSize.v,
Expand Down
8 changes: 4 additions & 4 deletions web/src/client/storage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1468,7 +1468,7 @@ describe("#proposal", () => {
expect(home).toStrictEqual({
mountPath: "/home",
target: "default",
targetDevice: "",
targetDevice: undefined,
fsType: "XFS",
minSize: 2048,
maxSize: 4096,
Expand All @@ -1491,7 +1491,7 @@ describe("#proposal", () => {
expect(generic).toStrictEqual({
mountPath: "",
target: "default",
targetDevice: "",
targetDevice: undefined,
fsType: "Ext4",
minSize: 1024,
maxSize: 2048,
Expand Down Expand Up @@ -1550,7 +1550,7 @@ describe("#proposal", () => {
{
mountPath: "/",
target: "default",
targetDevice: "",
targetDevice: undefined,
fsType: "Btrfs",
minSize: 1024,
maxSize: 2048,
Expand All @@ -1569,7 +1569,7 @@ describe("#proposal", () => {
{
mountPath: "/home",
target: "default",
targetDevice: "",
targetDevice: undefined,
fsType: "XFS",
minSize: 2048,
maxSize: 4096,
Expand Down
66 changes: 48 additions & 18 deletions web/src/components/storage/ProposalVolumes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ import { Table, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
import { sprintf } from "sprintf-js";

import { _ } from "~/i18n";
import { Em, If, Popup, RowActions, Tip } from '~/components/core';
import { Icon } from '~/components/layout';
import { If, Popup, RowActions, Tip } from '~/components/core';
import { VolumeForm } from '~/components/storage';
import { deviceSize, hasSnapshots, isTransactionalRoot } from '~/components/storage/utils';
import { noop } from "~/utils";
Expand Down Expand Up @@ -185,8 +184,12 @@ const VolumeRow = ({ columns, volume, options, isLoading, onEdit, onDelete }) =>
};

const SizeLimits = ({ volume }) => {
const minSize = deviceSize(volume.minSize);
const maxSize = volume.maxSize ? deviceSize(volume.maxSize) : undefined;
let targetSize;
if (volume.target === "filesystem" || volume.target === "device")
targetSize = volume.targetDevice.size;

const minSize = deviceSize(targetSize || volume.minSize);
const maxSize = targetSize ? deviceSize(targetSize) : volume.maxSize ? deviceSize(volume.maxSize) : undefined;
const isAuto = volume.autoSize;

let size = minSize;
Expand All @@ -203,25 +206,48 @@ const VolumeRow = ({ columns, volume, options, isLoading, onEdit, onDelete }) =>
);
};

const Details = ({ volume, options }) => {
const Details = ({ volume }) => {
const snapshots = hasSnapshots(volume);
const transactional = isTransactionalRoot(volume);

// TRANSLATORS: the filesystem uses a logical volume (LVM)
const text = `${volume.fsType} ${options.lvm ? _("logical volume") : _("partition")}`;
const lockIcon = <Icon name="lock" size="xxxs" />;
const snapshotsIcon = <Icon name="add_a_photo" size="xxxs" />;
const transactionalIcon = <Icon name="sync" size="xxxs" />;
const text = () => {
if (volume.target === "filesystem")
// TRANSLATORS: %s will be replaced by a file-system type like "Btrfs" or "Ext4"
return sprintf(_("Reused %s"), volume.targetDevice?.filesystem?.type || "");
if (transactional)
return _("Transactional Btrfs");
if (snapshots)
return _("Btrfs with snapshots");

return volume.fsType;
};

return (
<div className="split">
<span>{text()}</span>
</div>
);
};

const Location = ({ volume, options }) => {
const text = () => {
if (volume.target === "new_partition")
// TRANSLATORS: %s will be replaced by a disk name (eg. "/dev/sda")
return sprintf(_("Partition at %s"), volume.targetDevice?.name || "");
if (volume.target === "new_vg")
// TRANSLATORS: %s will be replaced by a disk name (eg. "/dev/sda")
return sprintf(_("Separate LVM at %s"), volume.targetDevice?.name || "");
if (volume.target === "device" || volume.target === "filesystem")
return volume.targetDevice?.name || "";
if (options.lvm)
return _("Logical volume at system LVM");

return _("Partition at installation disk");
};

return (
<div className="split">
<span>{text}</span>
{/* TRANSLATORS: filesystem flag, it uses an encryption */}
<If condition={options.encryption} then={<Em icon={lockIcon}>{_("encrypted")}</Em>} />
{/* TRANSLATORS: filesystem flag, it allows creating snapshots */}
<If condition={snapshots && !transactional} then={<Em icon={snapshotsIcon}>{_("with snapshots")}</Em>} />
{/* TRANSLATORS: flag for transactional file system */}
<If condition={transactional} then={<Em icon={transactionalIcon}>{_("transactional")}</Em>} />
<span>{text()}</span>
</div>
);
};
Expand Down Expand Up @@ -265,8 +291,9 @@ const VolumeRow = ({ columns, volume, options, isLoading, onEdit, onDelete }) =>
<>
<Tr>
<Td dataLabel={columns.mountPath}>{volume.mountPath}</Td>
<Td dataLabel={columns.details}><Details volume={volume} options={options} /></Td>
<Td dataLabel={columns.details}><Details volume={volume} /></Td>
<Td dataLabel={columns.size}><SizeLimits volume={volume} /></Td>
<Td dataLabel={columns.location}><Location volume={volume} options={options} /></Td>
<Td isActionCell>
<VolumeActions
volume={volume}
Expand Down Expand Up @@ -311,6 +338,8 @@ const VolumesTable = ({ volumes, options, isLoading, onVolumesChange }) => {
mountPath: _("Mount point"),
details: _("Details"),
size: _("Size"),
// TRANSLATORS: where (and how) the file-system is going to be created
location: _("Location"),
actions: _("Actions")
};

Expand Down Expand Up @@ -352,6 +381,7 @@ const VolumesTable = ({ volumes, options, isLoading, onVolumesChange }) => {
<Th>{columns.mountPath}</Th>
<Th>{columns.details}</Th>
<Th>{columns.size}</Th>
<Th>{columns.location}</Th>
<Th />
</Tr>
</Thead>
Expand Down
14 changes: 7 additions & 7 deletions web/src/components/storage/ProposalVolumes.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ describe("if there are volumes", () => {
const [, body] = await screen.findAllByRole("rowgroup");

expect(within(body).queryAllByRole("row").length).toEqual(3);
within(body).getByRole("row", { name: "/ Btrfs partition 1 KiB - 2 KiB" });
within(body).getByRole("row", { name: "/home XFS partition At least 1 KiB" });
within(body).getByRole("row", { name: "swap Swap partition 1 KiB" });
within(body).getByRole("row", { name: "/ Btrfs 1 KiB - 2 KiB Partition at installation disk" });
within(body).getByRole("row", { name: "/home XFS At least 1 KiB Partition at installation disk" });
within(body).getByRole("row", { name: "swap Swap 1 KiB Partition at installation disk" });
});

it("allows deleting the volume", async () => {
Expand All @@ -192,7 +192,7 @@ describe("if there are volumes", () => {
const { user } = plainRender(<ProposalVolumes {...props} />);

const [, body] = await screen.findAllByRole("rowgroup");
const row = within(body).getByRole("row", { name: "/home XFS partition At least 1 KiB" });
const row = within(body).getByRole("row", { name: "/home XFS At least 1 KiB Partition at installation disk" });
const actions = within(row).getByRole("button", { name: "Actions" });
await user.click(actions);
const deleteAction = within(row).queryByRole("menuitem", { name: "Delete" });
Expand All @@ -207,7 +207,7 @@ describe("if there are volumes", () => {
const { user } = plainRender(<ProposalVolumes {...props} />);

const [, body] = await screen.findAllByRole("rowgroup");
const row = within(body).getByRole("row", { name: "/home XFS partition At least 1 KiB" });
const row = within(body).getByRole("row", { name: "/home XFS At least 1 KiB Partition at installation disk" });
const actions = within(row).getByRole("button", { name: "Actions" });
await user.click(actions);
const editAction = within(row).queryByRole("menuitem", { name: "Edit" });
Expand All @@ -227,7 +227,7 @@ describe("if there are volumes", () => {

const [, volumes] = await screen.findAllByRole("rowgroup");

within(volumes).getByRole("row", { name: "/ Btrfs partition transactional 1 KiB - 2 KiB" });
within(volumes).getByRole("row", { name: "/ Transactional Btrfs 1 KiB - 2 KiB Partition at installation disk" });
});
});

Expand All @@ -241,7 +241,7 @@ describe("if there are volumes", () => {

const [, volumes] = await screen.findAllByRole("rowgroup");

within(volumes).getByRole("row", { name: "/ Btrfs partition with snapshots 1 KiB - 2 KiB" });
within(volumes).getByRole("row", { name: "/ Btrfs with snapshots 1 KiB - 2 KiB Partition at installation disk" });
});
});
});
Expand Down

0 comments on commit ad3b86a

Please sign in to comment.