Skip to content

Commit

Permalink
WIP - polish actions
Browse files Browse the repository at this point in the history
All card actions are defined via the page and container abstractions,
which will put them into the kebab menu of table rows.  But then,
dangerous and impossible actions are removed from that menu.
  • Loading branch information
mvollmer committed Oct 25, 2023
1 parent 87006de commit 7dc3ab9
Show file tree
Hide file tree
Showing 10 changed files with 385 additions and 350 deletions.
63 changes: 35 additions & 28 deletions pkg/storaged/containers/lvm2-logical-volume.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,23 @@ function repair(lvol) {

export function make_lvm2_logical_volume_container(parent, vgroup, lvol, block) {
const unused_space_warning = check_unused_space(block.path);
const unused_space = !!unused_space_warning;
const status_code = client.lvols_status[lvol.path];
let repair_action = null;
const pool = client.lvols[lvol.ThinPool];

let { info, shrink_excuse, grow_excuse } = get_resize_info(client, block, unused_space);

if (!unused_space && !grow_excuse && !pool && vgroup.FreeSize == 0) {
grow_excuse = (
<div>
{_("Not enough space to grow.")}
<br />
{_("Free up space in this group: Shrink or delete other logical volumes or add another physical volume.")}
</div>
);
}

let repair_action = null;
if (status_code == "degraded" || status_code == "degraded-maybe-partial")
repair_action = { title: _("Repair"), action: () => repair(lvol) };

Expand All @@ -112,6 +126,18 @@ export function make_lvm2_logical_volume_container(parent, vgroup, lvol, block)
component: LVM2LogicalVolumeContainer,
props: { vgroup, lvol, block, unused_space_warning },
actions: [
(!unused_space &&
{
title: _("Shrink"),
action: () => shrink_dialog(client, lvol, info),
excuse: shrink_excuse,
}),
(!unused_space &&
{
title: _("Grow"),
action: () => grow_dialog(client, lvol, info),
excuse: grow_excuse,
}),
{ title: _("Deactivate"), action: () => lvol.Deactivate({}) },
lvm2_create_snapshot_action(lvol),
repair_action,
Expand All @@ -121,22 +147,9 @@ export function make_lvm2_logical_volume_container(parent, vgroup, lvol, block)
return cont;
}

const LVM2LogicalVolumeContainer = ({ container, vgroup, lvol, block, unused_space_warning }) => {
const pool = client.lvols[lvol.ThinPool];
const LVM2LogicalVolumeContainer = ({ container, vgroup, lvol, block, unused_space_warning, resize_info }) => {
const unused_space = !!unused_space_warning;

let { info, shrink_excuse, grow_excuse } = get_resize_info(client, block, unused_space);

if (!unused_space && !grow_excuse && !pool && vgroup.FreeSize == 0) {
grow_excuse = (
<div>
{_("Not enough space to grow.")}
<br />
{_("Free up space in this group: Shrink or delete other logical volumes or add another physical volume.")}
</div>
);
}

function rename() {
dialog_open({
Title: _("Rename logical volume"),
Expand All @@ -154,12 +167,12 @@ const LVM2LogicalVolumeContainer = ({ container, vgroup, lvol, block, unused_spa
});
}

function shrink() {
return shrink_dialog(client, lvol, info, unused_space);
function shrink_to_fit() {
return shrink_dialog(client, lvol, resize_info, true);
}

function grow() {
return grow_dialog(client, lvol, info, unused_space);
function grow_to_fit() {
return grow_dialog(client, lvol, resize_info, true);
}

const layout_desc = {
Expand Down Expand Up @@ -192,13 +205,7 @@ const LVM2LogicalVolumeContainer = ({ container, vgroup, lvol, block, unused_spa
}
<StructureDescription client={client} lvol={lvol} />
{ !unused_space &&
<SDesc title={_("Size")}>
{fmt_size(lvol.Size)}
<div className="tab-row-actions">
<StorageButton excuse={shrink_excuse} onClick={shrink}>{_("Shrink")}</StorageButton>
<StorageButton excuse={grow_excuse} onClick={grow}>{_("Grow")}</StorageButton>
</div>
</SDesc>
<SDesc title={_("Size")} value={fmt_size(lvol.Size)} />
}
</DescriptionList>
{ unused_space &&
Expand All @@ -211,8 +218,8 @@ const LVM2LogicalVolumeContainer = ({ container, vgroup, lvol, block, unused_spa
fmt_size(unused_space_warning.volume_size),
fmt_size(unused_space_warning.content_size))}
<div className='storage_alert_action_buttons'>
<StorageButton excuse={shrink_excuse} onClick={shrink}>{_("Shrink volume")}</StorageButton>
<StorageButton excuse={grow_excuse} onClick={grow}>{_("Grow content")}</StorageButton>
<StorageButton onClick={shrink_to_fit}>{_("Shrink volume")}</StorageButton>
<StorageButton onClick={grow_to_fit}>{_("Grow content")}</StorageButton>
</div>
</Alert>
</>
Expand Down
17 changes: 6 additions & 11 deletions pkg/storaged/containers/lvm2-vdo-pool.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import client from "../client";

import { CardBody } from "@patternfly/react-core/dist/esm/components/Card/index.js";
import { DescriptionList } from "@patternfly/react-core/dist/esm/components/DescriptionList/index.js";
import { StorageButton, StorageOnOff } from "../storage-controls.jsx";
import { StorageOnOff } from "../storage-controls.jsx";

import { SCard } from "../utils/card.jsx";
import { SDesc } from "../utils/desc.jsx";
Expand All @@ -46,16 +46,16 @@ export function make_lvm2_vdo_pool_container(parent, vgroup, lvol) {
component: LVM2VDOPoolContainer,
props: { vgroup, lvol, vdo_iface, vdo_pool_vol },
actions: [
{
title: _("Grow"),
action: () => grow_dialog(client, vdo_pool_vol, { }),
}
],
});
return cont;
}

const LVM2VDOPoolContainer = ({ container, vgroup, lvol, vdo_iface, vdo_pool_vol }) => {
function grow() {
grow_dialog(client, vdo_pool_vol, { });
}

function toggle_compression() {
const new_state = !vdo_iface.Compression;
return vdo_iface.EnableCompression(new_state, {})
Expand All @@ -79,12 +79,7 @@ const LVM2VDOPoolContainer = ({ container, vgroup, lvol, vdo_iface, vdo_pool_vol
<CardBody>
<DescriptionList className="pf-m-horizontal-on-sm">
<SDesc title={_("Name")} value={vdo_pool_vol.Name} />
<SDesc title={_("Size")}>
{fmt_size(vdo_pool_vol.Size)}
<div className="tab-row-actions">
<StorageButton onClick={grow}>{_("Grow")}</StorageButton>
</div>
</SDesc>
<SDesc title={_("Size")} value={fmt_size(vdo_pool_vol.Size)} />
<SDesc title={_("Data used")}>
{fmt_size(vdo_iface.UsedSize)} ({used_pct})
</SDesc>
Expand Down
59 changes: 33 additions & 26 deletions pkg/storaged/containers/partition.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,36 +68,53 @@ export function delete_partition(block, page) {
}

export function make_partition_container(parent, block) {
const block_part = client.blocks_part[block.path];
const unused_space_warning = check_unused_space(block.path);
const unused_space = !!unused_space_warning;
let { info, shrink_excuse, grow_excuse } = get_resize_info(client, block, unused_space);

if (!unused_space_warning && !grow_excuse && free_space_after_part(client, block_part) == 0) {
grow_excuse = _("No free space after this partition");
}

const cont = new_container({
stored_on_format: _("Partition of $0"),
has_warning: !!unused_space_warning,
component: PartitionContainer,
props: { block, unused_space_warning },
props: { block, unused_space_warning, resize_info: info },
actions: [
{ title: _("Delete"), action: () => delete_partition(block, cont.page), danger: true },
(!unused_space &&
{
title: _("Shrink"),
action: () => shrink_dialog(client, block_part, info),
excuse: shrink_excuse,
}),
(!unused_space &&
{
title: _("Grow"),
action: () => grow_dialog(client, block_part, info),
excuse: grow_excuse,
}),
{
title: _("Delete"),
action: () => delete_partition(block, cont.page),
danger: true
},
],
});
return cont;
}

const PartitionContainer = ({ container, block, unused_space_warning }) => {
const PartitionContainer = ({ container, block, unused_space_warning, resize_info }) => {
const block_part = client.blocks_part[block.path];
const unused_space = !!unused_space_warning;

let { info, shrink_excuse, grow_excuse } = get_resize_info(client, block, unused_space);

if (!unused_space && !grow_excuse && free_space_after_part(client, block_part) == 0) {
grow_excuse = _("No free space after this partition");
}

function shrink() {
return shrink_dialog(client, block_part, info, unused_space);
function shrink_to_fit() {
return shrink_dialog(client, block_part, resize_info, true);
}

function grow() {
return grow_dialog(client, block_part, info, unused_space);
function grow_to_fit() {
return grow_dialog(client, block_part, resize_info, true);
}

return (
Expand All @@ -106,17 +123,7 @@ const PartitionContainer = ({ container, block, unused_space_warning }) => {
<DescriptionList className="pf-m-horizontal-on-sm">
<SDesc title={_("Name")} value={block_part.Name || "-"} />
{ !unused_space &&
<SDesc title={_("Size")}>
{fmt_size(block_part.Size)}
<div className="tab-row-actions">
<StorageButton excuse={shrink_excuse} onClick={shrink}>
{_("Shrink")}
</StorageButton>
<StorageButton excuse={grow_excuse} onClick={grow}>
{_("Grow")}
</StorageButton>
</div>
</SDesc>
<SDesc title={_("Size")} value={fmt_size(block_part.Size)} />
}
<SDesc title={_("UUID")} value={block_part.UUID} />
<SDesc title={_("Type")} value={block_part.Type} />
Expand All @@ -131,10 +138,10 @@ const PartitionContainer = ({ container, block, unused_space_warning }) => {
fmt_size(unused_space_warning.volume_size),
fmt_size(unused_space_warning.content_size))}
<div className='storage_alert_action_buttons'>
<StorageButton excuse={shrink_excuse} onClick={shrink}>
<StorageButton onClick={shrink_to_fit}>
{_("Shrink partition")}
</StorageButton>
<StorageButton excuse={grow_excuse} onClick={grow}>
<StorageButton onClick={grow_to_fit}>
{_("Grow content")}
</StorageButton>
</div>
Expand Down
21 changes: 11 additions & 10 deletions pkg/storaged/pages.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { CardBody } from "@patternfly/react-core/dist/esm/components/Card/index.
import { StackItem } from "@patternfly/react-core/dist/esm/layouts/Stack/index.js";
import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
import { ListingTable } from "cockpit-components-table.jsx";
import { DropdownSeparator } from '@patternfly/react-core/dist/esm/deprecated/components/Dropdown/index.js';
import { ExclamationTriangleIcon, ExclamationCircleIcon } from "@patternfly/react-icons";

import { SCard } from "./utils/card.jsx";
Expand Down Expand Up @@ -175,10 +174,10 @@ function make_page_kebab(page) {
function add_actions(actions) {
if (!actions)
return;
if (items.length > 0)
items.push(<DropdownSeparator key={items.length} />);
for (const a of actions)
items.push(make_menu_item(a));
for (const a of actions) {
if (!a.danger && !a.excuse)
items.push(make_menu_item(a));
}
}

add_actions(page.actions);
Expand All @@ -201,15 +200,17 @@ function make_actions_kebab(actions) {
return <StorageBarMenu menuItems={actions.map(make_menu_item)} isKebab />;
}

export const ActionButtons = ({ page, container }) => {
export const ActionButtons = ({ page, container, tag }) => {
const actions = page ? page.actions : container.actions;
if (!actions)
return null;

return actions.map(a =>
<StorageButton key={a.title} onClick={a.action} kind={a.danger ? "danger" : null} excuse={a.excuse}>
{a.title}
</StorageButton>);
return actions
.filter(a => !tag || a.tag == tag)
.map(a =>
<StorageButton key={a.title} onClick={a.action} kind={a.danger ? "danger" : null} excuse={a.excuse}>
{a.title}
</StorageButton>);
};

export function page_type(page) {
Expand Down
23 changes: 14 additions & 9 deletions pkg/storaged/pages/drive.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ import { Flex } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js";

import { SCard } from "../utils/card.jsx";
import { SDesc } from "../utils/desc.jsx";
import { StorageButton } from "../storage-controls.jsx";
import { PageChildrenCard, ParentPageLink, new_page, page_type, block_location } from "../pages.jsx";
import { PageChildrenCard, ParentPageLink, ActionButtons, new_page, page_type, block_location } from "../pages.jsx";
import { block_name, drive_name, format_temperature, fmt_size, fmt_size_long } from "../utils.js";
import { format_disk } from "../content-views.jsx"; // XXX

Expand Down Expand Up @@ -60,6 +59,17 @@ export function make_drive_page(parent, drive) {
block_name(block),
block.Size > 0 ? fmt_size(block.Size) : null
],
actions: [
(block.Size > 0
? {
title: _("Create partition table"),
action: () => format_disk(client, block),
danger: false, // XXX - mark as dangerous when not "unrecognized data"
excuse: block.ReadOnly ? _("Device is read-only") : null,
tag: "content"
}
: null)
],
component: DrivePage,
props: { drive }
});
Expand Down Expand Up @@ -91,12 +101,6 @@ const DrivePage = ({ page, drive }) => {
</SDesc>);
}

const actions =
<StorageButton onClick={() => format_disk(client, block)}
excuse={block && block.ReadOnly ? _("Device is read-only") : null}>
{_("Create partition table")}
</StorageButton>;

return (
<Stack hasGutter>
<StackItem>
Expand Down Expand Up @@ -132,7 +136,8 @@ const DrivePage = ({ page, drive }) => {
{ block && block.Size > 0
? (<StackItem>
<PageChildrenCard title={is_partitioned ? _("Partitions") : _("Content")}
actions={actions} page={page} />
actions={<ActionButtons page={page} tag="content" />}
page={page} />
</StackItem>)
: null
}
Expand Down
Loading

0 comments on commit 7dc3ab9

Please sign in to comment.