Skip to content

Commit

Permalink
[web] WIP: move transactional information
Browse files Browse the repository at this point in the history
  • Loading branch information
ancorgs committed Mar 6, 2024
1 parent 3392064 commit 6252eeb
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 60 deletions.
6 changes: 5 additions & 1 deletion web/src/components/storage/ProposalPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import {
ProposalSettingsSection,
ProposalSpacePolicySection,
ProposalDeviceSection,
ProposalFileSystemsSection
ProposalFileSystemsSection,
ProposalTransactionalInfo
} from "~/components/storage";
import { IDLE } from "~/client/status";

Expand Down Expand Up @@ -201,6 +202,9 @@ export default function ProposalPage() {
const PageContent = () => {
return (
<>
<ProposalTransactionalInfo
settings={state.settings}
/>
<ProposalDeviceSection
settings={state.settings}
availableDevices={state.availableDevices}
Expand Down
68 changes: 21 additions & 47 deletions web/src/components/storage/ProposalSettingsSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@

import React, { useEffect, useState } from "react";
import { Checkbox, Form, Skeleton, Switch, Tooltip } from "@patternfly/react-core";
import { sprintf } from "sprintf-js";

import { _ } from "~/i18n";
import { If, PasswordAndConfirmationInput, Section, Popup } from "~/components/core";
import { Icon } from "~/components/layout";
import { noop } from "~/utils";
import { hasFS, isTransactionalSystem } from "~/components/storage/utils";
import { useProduct } from "~/context/product";
import { hasFS } from "~/components/storage/utils";

/**
* @typedef {import ("~/client/storage").ProposalManager.ProposalSettings} ProposalSettings
Expand Down Expand Up @@ -146,33 +144,28 @@ const SnapshotsField = ({
};

const configurableSnapshots = rootVolume.outline.snapshotsConfigurable;
const forcedSnapshots = !configurableSnapshots && hasFS(rootVolume, "Btrfs") && rootVolume.snapshots;

const SnapshotsToggle = () => {
const explanation = _("Uses Btrfs for the root file system allowing to boot to a previous \
const explanation = _("Uses Btrfs for the root file system allowing to boot to a previous \
version of the system after configuration changes or software upgrades.");

return (
<>
<Switch
id="snapshots"
label={_("Use Btrfs Snapshots")}
isReversed
isChecked={isChecked}
onChange={switchState}
/>
return (
<If
condition={configurableSnapshots}
then={
<div>
{explanation}
<Switch
id="snapshots"
label={_("Use Btrfs Snapshots")}
isReversed
isChecked={isChecked}
onChange={switchState}
/>
<div>
{explanation}
</div>
</div>
</>
);
};

return (
<div>
<If condition={forcedSnapshots} then={_("Btrfs snapshots required by product.")} />
<If condition={configurableSnapshots} then={<SnapshotsToggle />} />
</div>
}
/>
);
};

Expand Down Expand Up @@ -297,8 +290,6 @@ export default function ProposalSettingsSection({
encryptionMethods = [],
onChange = noop
}) {
const { selectedProduct } = useProduct();

const changeEncryption = ({ password, method }) => {
onChange({ encryptionPassword: password, encryptionMethod: method });
};
Expand All @@ -318,29 +309,12 @@ export default function ProposalSettingsSection({

const encryption = settings.encryptionPassword !== undefined && settings.encryptionPassword.length > 0;

const transactional = isTransactionalSystem(settings?.volumes || []);

return (
<>
<Section title={_("Settings")}>
<If
condition={transactional}
then={
<div>
<label>{_("Transactional system")}</label>
<div>
{/* TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) */}
{sprintf(_("%s is an immutable system with atomic updates using a read-only Btrfs \
root file system."), selectedProduct.name)}
</div>
</div>
}
else={
<SnapshotsField
settings={settings}
onChange={changeBtrfsSnapshots}
/>
}
<SnapshotsField
settings={settings}
onChange={changeBtrfsSnapshots}
/>
<EncryptionField
password={settings.encryptionPassword || ""}
Expand Down
17 changes: 5 additions & 12 deletions web/src/components/storage/ProposalSettingsSection.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ jest.mock("@patternfly/react-core", () => {
};
});

jest.mock("~/context/product", () => ({
...jest.requireActual("~/context/product"),
useProduct: () => ({
selectedProduct : { name: "Test" }
})
}));

let props;

beforeEach(() => {
Expand All @@ -48,7 +41,7 @@ beforeEach(() => {

const rootVolume = { mountPath: "/", fsType: "Btrfs", outline: { snapshotsConfigurable: true } };

describe("if the system is not transactional", () => {
describe("if snapshots are configurable", () => {
beforeEach(() => {
props.settings = { volumes: [rootVolume] };
});
Expand All @@ -60,15 +53,15 @@ describe("if the system is not transactional", () => {
});
});

describe("if the system is transactional", () => {
describe("if snapshots are not configurable", () => {
beforeEach(() => {
props.settings = { volumes: [{ ...rootVolume, transactional: true }] };
props.settings = { volumes: [{ ...rootVolume, outline: { ...rootVolume.outline, snapshotsConfigurable: false } }] };
});

it("renders explanation about transactional system", () => {
it("renders the snapshots switch", () => {
plainRender(<ProposalSettingsSection {...props} />);

screen.getByText("Transactional system");
expect(screen.queryByRole("checkbox", { name: "Use Btrfs Snapshots" })).toBeNull();
});
});

Expand Down
66 changes: 66 additions & 0 deletions web/src/components/storage/ProposalTransactionalInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.
*/

import React from "react";
import { Alert } from "@patternfly/react-core";
import { sprintf } from "sprintf-js";

import { _ } from "~/i18n";
import { If, Section } from "~/components/core";
import { isTransactionalSystem } from "~/components/storage/utils";
import { useProduct } from "~/context/product";

/**
* @typedef {import ("~/client/storage").ProposalManager.ProposalSettings} ProposalSettings
*/

/**
* Information about the system being transactional, if needed
* @component
*
* @param {object} props
* @param {ProposalSettings} props.settings - Settings used for calculating a proposal.
* @param {object} settings
*/
export default function ProposalTransactionalInfo({ settings }) {
const transactional = isTransactionalSystem(settings?.volumes || []);
const { selectedProduct } = useProduct();

/* TRANSLATORS: %s is replaced by a product name (e.g., openSUSE Tumbleweed) */
const description = sprintf(
_("%s is an immutable system with atomic updates. It uses a read-only Btrfs file system updated via snapshots."),
selectedProduct.name
);
const title = _("Transactional root file system");

return (
<If
condition={transactional}
then={
<Section>
<Alert isInline variant="info" title={title}>
{description}
</Alert>
</Section>
}
/>
);
}
64 changes: 64 additions & 0 deletions web/src/components/storage/ProposalTransactionalInfo.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.
*/

import React from "react";
import { screen, within } from "@testing-library/react";

Check warning on line 23 in web/src/components/storage/ProposalTransactionalInfo.test.jsx

View workflow job for this annotation

GitHub Actions / frontend_build (18.x)

'within' is defined but never used
import { plainRender } from "~/test-utils";
import { ProposalTransactionalInfo } from "~/components/storage";

jest.mock("~/context/product", () => ({
...jest.requireActual("~/context/product"),
useProduct: () => ({
selectedProduct : { name: "Test" }
})
}));

let props;

beforeEach(() => {
props = {};
});

const rootVolume = { mountPath: "/", fsType: "Btrfs" };

describe("if the system is not transactional", () => {
beforeEach(() => {
props.settings = { volumes: [rootVolume] };
});

it("does not render any explanation about transactional system", () => {
plainRender(<ProposalTransactionalInfo {...props} />);

expect(screen.queryByText("Transactional root file system")).toBeNull();
});
});

describe("if the system is transactional", () => {
beforeEach(() => {
props.settings = { volumes: [{ ...rootVolume, transactional: true }] };
});

it("renders an explanation about the transactional system", () => {
plainRender(<ProposalTransactionalInfo {...props} />);

screen.getByText("Transactional root file system");
});
});
1 change: 1 addition & 0 deletions web/src/components/storage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export { default as ProposalSpacePolicySection } from "./ProposalSpacePolicySect
export { default as ProposalDeviceSection } from "./ProposalDeviceSection";
export { default as ProposalFileSystemsSection } from "./ProposalFileSystemsSection";
export { default as ProposalActionsSection } from "./ProposalActionsSection";
export { default as ProposalTransactionalInfo } from "./ProposalTransactionalInfo";
export { default as ProposalVolumes } from "./ProposalVolumes";
export { default as DASDPage } from "./DASDPage";
export { default as DASDTable } from "./DASDTable";
Expand Down

0 comments on commit 6252eeb

Please sign in to comment.