Skip to content

Commit

Permalink
fix(web): avoid type definitions errors at build time (#1465)
Browse files Browse the repository at this point in the history
## Problem

After merging #1456, the build task is failing when running it for the
production environment (`NODE_ENV=production npm run build`).

## Solution

Fix these problems having in mind that most of the complaints will be
solved in a better way when migrating components to TypeScript.

## Testing

- [x] `npm run server` succeed.
- [x] `npm run tests` succeed.
- [x] `NODE_ENV=production npm run build` succeed.
  • Loading branch information
imobachgs authored Jul 12, 2024
2 parents 0a35b8b + 2ed8491 commit ef87055
Show file tree
Hide file tree
Showing 27 changed files with 137 additions and 74 deletions.
18 changes: 3 additions & 15 deletions web/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@
},
"sourceType": "module"
},
"plugins": [
"agama-i18n",
"flowtype",
"i18next",
"react",
"react-hooks",
"@typescript-eslint"
],
"plugins": ["agama-i18n", "flowtype", "i18next", "react", "react-hooks", "@typescript-eslint"],
"rules": {
"agama-i18n/string-literals": "error",
"i18next/no-literal-string": "error",
Expand Down Expand Up @@ -69,19 +62,14 @@
"overrides": [
{
// do not check translations in the testing or development files
"files": [
"*.test.*",
"test-utils.js"
],
"files": ["*.test.*", "test-utils.js"],
"rules": {
"i18next/no-literal-string": "off"
}
},
{
// do not check translation arguments in the test, it checks some internals by passing variables
"files": [
"i18n.test.js"
],
"files": ["i18n.test.js"],
"rules": {
"agama-i18n/string-literals": "off"
}
Expand Down
4 changes: 1 addition & 3 deletions web/.stylelintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
{
"plugins": [
"stylelint-prettier"
],
"plugins": ["stylelint-prettier"],
"extends": [
"stylelint-config-standard",
"stylelint-config-standard-scss",
Expand Down
8 changes: 8 additions & 0 deletions web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@testing-library/react": "^15.0.7",
"@testing-library/user-event": "^14.5.1",
"@types/jest": "^29.5.12",
"@types/webpack-env": "^1.18.5",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"ajv": "^8.12.0",
Expand Down
2 changes: 1 addition & 1 deletion web/src/client/network/model.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("createConnection", () => {

it("merges given properties", () => {
const addresses = [{ address: "192.168.0.1", prefix: 24 }];
const connection = createConnection({ addresses, testing: 1 });
const connection = createConnection({ addresses });
expect(connection.method4).toEqual("auto");
expect(connection.gateway4).toEqual("");
expect(connection.addresses).toEqual(addresses);
Expand Down
29 changes: 28 additions & 1 deletion web/src/client/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,32 @@ const ZFCP_DISK_IFACE = "org.opensuse.Agama.Storage1.ZFCP.Disk";

/** @fixme Adapt code depending on D-Bus */
class DBusClient {
proxy() {
/**
* @param {string} service
* @param {string|undefined} address
*/
constructor(service, address) {
console.warn(`FIXME: Adapt code depending on D-Bus ${service} ${address}`);
}

/**
* @param {string} iface
* @param {string} [path]
* @return {Promise<object,undefined>}
*/
async proxy(iface, path) {
console.warn(`FIXME: Adapt code depending on D-Bus ${iface} ${path}`);
return Promise.resolve(undefined);
}

/**
* @param {string|undefined} iface
* @param {string|undefined} path_namespace
* @param {object|undefined} options
* @return {Promise<any>}
*/
async proxies(iface, path_namespace, options) {
console.warn(`FIXME: Adapt code depending on D-Bus ${iface} ${path_namespace} ${options}`);
return Promise.resolve(undefined);
}
}
Expand Down Expand Up @@ -1576,7 +1601,9 @@ class StorageBaseClient {
this.staging = new DevicesManager(this.client, "result");
this.proposal = new ProposalManager(this.client, this.system);
this.iscsi = new ISCSIManager(this.client);
// @ts-ignore
this.dasd = new DASDManager(StorageBaseClient.SERVICE, client);
// @ts-ignore
this.zfcp = new ZFCPManager(StorageBaseClient.SERVICE, client);
}

Expand Down
26 changes: 15 additions & 11 deletions web/src/components/core/CardField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
* @todo write documentation
*/
const CardField = ({
label,
value,
description,
actions,
children = [],
label = undefined,
value = undefined,
description = undefined,
actions = undefined,
children,
cardProps = {},
cardHeaderProps = {},
cardDescriptionProps = {},
Expand All @@ -58,12 +58,16 @@ const CardField = ({
<CardHeader {...cardHeaderProps}>
<CardTitle>
<Flex alignItems={{ default: "alignItemsCenter" }}>
<FlexItem spacer={{ default: "spacerSm" }}>
<h3>{label}</h3>
</FlexItem>
<FlexItem grow={{ default: "grow" }} className={textStyles.fontSizeXl}>
{value}
</FlexItem>
{label && (
<FlexItem spacer={{ default: "spacerSm" }}>
<h3>{label}</h3>
</FlexItem>
)}
{value && (
<FlexItem grow={{ default: "grow" }} className={textStyles.fontSizeXl}>
{value}
</FlexItem>
)}
</Flex>
</CardTitle>
</CardHeader>
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/core/Drawer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* find current contact information at www.suse.com.
*/

// @ts-check
// FIXME: rewrite to .tsx

import React, { forwardRef, useImperativeHandle, useState } from "react";
import {
Expand Down
14 changes: 9 additions & 5 deletions web/src/components/core/EmptyState.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ import { Icon } from "~/components/layout";
* @param {object} props
* @param {string} props.title
* @param {IconName} props.icon
* @param {string} props.color
* @param {string} [props.color="color-100"]
* @param {EmptyStateHeaderProps["headingLevel"]} [props.headingLevel="h4"]
* @param {boolean} [props.noPadding=false]
* @param {React.ReactNode} props.children
* @param {React.ReactNode} [props.children]
* @param {EmptyStateProps} [props.rest]
* @todo write documentation
*/
Expand All @@ -57,19 +57,23 @@ export default function EmptyStateWrapper({
children,
...rest
}) {
// @ts-ignore
if (noPadding) rest.className = [rest.className, "no-padding"].join(" ").trim();

return (
<EmptyState variant="lg" {...rest}>
<EmptyStateHeader
headingLevel={headingLevel}
titleText={title}
// FIXME: Allow more colors, not only PF text utils. See core/Icon.jsx too.
titleClassName={`pf-v5-u-${color}`}
icon={<Icon name={icon} size="xxl" color={color} />}
/>
<EmptyStateBody>
<Stack hasGutter>{children}</Stack>
</EmptyStateBody>
{children && (
<EmptyStateBody>
<Stack hasGutter>{children}</Stack>
</EmptyStateBody>
)}
</EmptyState>
);
}
1 change: 1 addition & 0 deletions web/src/components/core/LoginPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ user privileges.",
<Grid>
<GridItem sm={10} smOffset={1} lg={8} lgOffset={2} xl={6} xlOffset={3}>
<Card component="section" isRounded>
{/** @ts-ignore */}
<EmptyState title={sectionTitle} icon="lock" color="color-info-200" variant="xl">
<p>
{rootExplanationStart} <b>{rootUser}</b> {rootExplanationEnd}
Expand Down
8 changes: 2 additions & 6 deletions web/src/components/core/Page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
// @ts-check

import React from "react";
import { NavLink, Outlet, useNavigate, useMatches, useLocation } from "react-router-dom";
import { NavLink, Outlet, useNavigate } from "react-router-dom";
import {
Button,
Card,
Expand Down Expand Up @@ -85,6 +85,7 @@ const Action = ({ navigateTo, children, ...props }) => {

/**
* Simple action for navigating back
* @param {ActionProps & { text?: string }} props
*/
const CancelAction = ({ text = _("Cancel"), navigateTo }) => {
const navigate = useNavigate();
Expand Down Expand Up @@ -186,11 +187,6 @@ const CardSection = ({ title, children, ...props }) => {
* @param {React.ReactNode} [props.children] - The page content.
*/
const Page = () => {
const location = useLocation();
const matches = useMatches();
const currentRoute = matches.find((r) => r.pathname === location.pathname);
const titleFromRoute = currentRoute?.handle?.name;

return (
<PageGroup>
<Outlet />
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/core/Section.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* find current contact information at www.suse.com.
*/

// @ts-check
// FIXME: Refactor or replace

import React from "react";
import { Link } from "react-router-dom";
Expand Down
3 changes: 1 addition & 2 deletions web/src/components/core/Section.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* find current contact information at www.suse.com.
*/

// @ts-check
// FIXME: Refactor or replace

import React from "react";
import { screen, within } from "@testing-library/react";
Expand Down Expand Up @@ -65,7 +65,6 @@ describe.skip("Section", () => {
});

it("does not render an icon if not valid icon name is given", () => {
// @ts-expect-error: Creating the icon name dynamically is unlikely, but let's be safe.
const { container } = plainRender(
<Section title="Settings" icon={`fake-${Date.now()}-icon`} />,
);
Expand Down
5 changes: 2 additions & 3 deletions web/src/components/layout/Center.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ import React from "react";
*
* @param {object} props
* @param {React.ReactNode} props.children
* @param {React.HTMLAttributes} props.htmlProps
*/
const Center = ({ children, ...htmlProps }) => (
<div className="vertically-centered" {...htmlProps}>
const Center = ({ children }) => (
<div className="vertically-centered">
<div className="full-width stack">{children}</div>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/network/ConnectionsTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { formatIp } from "~/client/network/utils";
import { _ } from "~/i18n";

/**
* @typedef {import("~/client/network/model").Device} Device
* @typedef {import("~/client/network/model").Connection} Connection
*/

Expand All @@ -40,8 +41,8 @@ import { _ } from "~/i18n";
*
* @param {object} props
* @param {Connection[]} props.connections - Connections to be shown
* @param {function} props.onEdit - function to be called for editing a connection
* @param {function} props.onForget - function to be called for forgetting a connection
* @param {Device[]} props.devices - Connections to be shown
* @param {function} [props.onForget] - function to be called for forgetting a connection
*/
export default function ConnectionsTable({ connections, devices, onForget }) {
const navigate = useNavigate();
Expand Down
2 changes: 2 additions & 0 deletions web/src/components/network/NetworkPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { sprintf } from "sprintf-js";
*/
export default function NetworkPage() {
const { network: client } = useInstallerClient();
// @ts-ignore
const { connections: initialConnections, devices: initialDevices, settings } = useLoaderData();
const [connections, setConnections] = useState(initialConnections);
const [devices, setDevices] = useState(initialDevices);
Expand All @@ -64,6 +65,7 @@ export default function NetworkPage() {
NetworkEventTypes.DEVICE_ADDED,
NetworkEventTypes.DEVICE_UPDATED,
NetworkEventTypes.DEVICE_REMOVED,
// @ts-ignore
].includes(type)
) {
setUpdateState(true);
Expand Down
12 changes: 11 additions & 1 deletion web/src/components/storage/BootSelection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,19 @@ const BOOT_DISABLED_ID = "boot-disabled";
* Allows the user to select the boot configuration.
*/
export default function BootSelectionDialog() {
/**
* @typedef {object} BootSelectionState
* @property {boolean} load
* @property {string} [selectedOption]
* @property {boolean} [configureBoot]
* @property {StorageDevice} [bootDevice]
* @property {StorageDevice} [defaultBootDevice]
* @property {StorageDevice[]} [availableDevices]
*/
const { cancellablePromise } = useCancellablePromise();
const { storage: client } = useInstallerClient();
const [state, setState] = useState({});
/** @type ReturnType<typeof useState<BootSelectionState>> */
const [state, setState] = useState({ load: false });
const navigate = useNavigate();

// FIXME: Repeated code, see DeviceSelection. Use a context/hook or whatever
Expand Down
14 changes: 10 additions & 4 deletions web/src/components/storage/DeviceSelection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,31 @@ import { compact, useCancellablePromise } from "~/utils";
import { useInstallerClient } from "~/context/installer";

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

const SELECT_DISK_ID = "select-disk";
const CREATE_LVM_ID = "create-lvm";
const SELECT_DISK_PANEL_ID = "panel-for-disk-selection";
const CREATE_LVM_PANEL_ID = "panel-for-lvm-creation";
const OPTIONS_NAME = "selection-mode";

/**
* Allows the user to select a target device for installation.
* @component
*/
export default function DeviceSelection() {
const [state, setState] = useState({});
/**
* @typedef {object} DeviceSelectionState
* @property {boolean} load
* @property {string} [target]
* @property {StorageDevice} [targetDevice]
* @property {StorageDevice[]} [targetPVDevices]
* @property {StorageDevice[]} [availableDevices]
*/
const navigate = useNavigate();
const { cancellablePromise } = useCancellablePromise();
/** @type ReturnType<typeof useState<DeviceSelectionState>> */
const [state, setState] = useState({ load: false });

const isTargetDisk = state.target === "DISK";
const isTargetNewLvmVg = state.target === "NEW_LVM_VG";
Expand Down
Loading

0 comments on commit ef87055

Please sign in to comment.