Skip to content

Commit 1878d87

Browse files
committed
web: stop using custom generateEncodedPath
It was introduced to work around React Router v6's issue of not encoding parameters in the generatePath function. However, after migrating to v7, tests began failing due to double encoding. This revealed that React Router v7 already handles encoding parameters in generatePath. See remix-run/react-router#13530 Thus, this commit reverts the changes made in #2576
1 parent 3fb632a commit 1878d87

File tree

11 files changed

+24
-104
lines changed

11 files changed

+24
-104
lines changed

web/src/components/network/WifiConnectionDetails.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ import {
3232
GridItem,
3333
Stack,
3434
} from "@patternfly/react-core";
35+
import { generatePath } from "react-router";
3536
import { Link, Page } from "~/components/core";
3637
import InstallationOnlySwitch from "./InstallationOnlySwitch";
3738
import { Device, WifiNetwork } from "~/types/network";
3839
import { NETWORK } from "~/routes/paths";
3940
import { formatIp } from "~/utils/network";
40-
import { generateEncodedPath } from "~/utils";
4141
import { _ } from "~/i18n";
4242

4343
const NetworkDetails = ({ network }: { network: WifiNetwork }) => {
@@ -96,7 +96,7 @@ const IpDetails = ({ device, settings }: { device: Device; settings: WifiNetwork
9696
title={_("IP settings")}
9797
pfCardProps={{ isPlain: false, isFullHeight: false }}
9898
actions={
99-
<Link to={generateEncodedPath(NETWORK.editConnection, { id: device.connection })}>
99+
<Link to={generatePath(NETWORK.editConnection, { id: device.connection })}>
100100
{_("Edit")}
101101
</Link>
102102
}

web/src/components/network/WifiNetworksList.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
*/
2222

2323
import React, { useId } from "react";
24-
import { useNavigate } from "react-router-dom";
24+
import { generatePath, useNavigate } from "react-router";
2525
import {
2626
Content,
2727
DataList,
@@ -41,7 +41,6 @@ import { Connection, ConnectionState, WifiNetwork, WifiNetworkStatus } from "~/t
4141
import { useConnections, useNetworkChanges, useWifiNetworks } from "~/queries/network";
4242
import { NETWORK as PATHS } from "~/routes/paths";
4343
import { isEmpty } from "radashi";
44-
import { generateEncodedPath } from "~/utils";
4544
import { formatIp } from "~/utils/network";
4645
import { sprintf } from "sprintf-js";
4746
import { _ } from "~/i18n";
@@ -190,7 +189,7 @@ function WifiNetworksList({ showIp = true, ...props }: WifiNetworksListProps) {
190189

191190
return (
192191
<DataList
193-
onSelectDataListItem={(_, ssid) => navigate(generateEncodedPath(PATHS.wifiNetwork, { ssid }))}
192+
onSelectDataListItem={(_, ssid) => navigate(generatePath(PATHS.wifiNetwork, { ssid }))}
194193
{...props}
195194
>
196195
{networks.map((n) => (

web/src/components/network/WiredConnectionDetails.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ import {
3737
Tabs,
3838
TabTitleText,
3939
} from "@patternfly/react-core";
40+
import { generatePath } from "react-router";
4041
import { Link, Page } from "~/components/core";
4142
import InstallationOnlySwitch from "./InstallationOnlySwitch";
4243
import { Connection, Device } from "~/types/network";
4344
import { connectionBindingMode, formatIp } from "~/utils/network";
4445
import { NETWORK } from "~/routes/paths";
4546
import { useNetworkDevices } from "~/queries/network";
46-
import { generateEncodedPath } from "~/utils";
4747
import { isEmpty } from "radashi";
4848
import { sprintf } from "sprintf-js";
4949
import { _ } from "~/i18n";
@@ -73,7 +73,7 @@ const BindingSettings = ({ connection }: { connection: Connection }) => {
7373
pfCardProps={{ isPlain: false, isFullHeight: false }}
7474
actions={
7575
<Link
76-
to={generateEncodedPath(NETWORK.editBindingSettings, {
76+
to={generatePath(NETWORK.editBindingSettings, {
7777
id: connection.id,
7878
})}
7979
>
@@ -203,7 +203,7 @@ const ConnectionDetails = ({ connection }: { connection: Connection }) => {
203203
title={_("Settings")}
204204
pfCardProps={{ isPlain: false, isFullHeight: false }}
205205
actions={
206-
<Link to={generateEncodedPath(NETWORK.editConnection, { id: connection.id })}>
206+
<Link to={generatePath(NETWORK.editConnection, { id: connection.id })}>
207207
{_("Edit connection settings")}
208208
</Link>
209209
}

web/src/components/network/WiredConnectionsList.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
*/
2222

2323
import React, { useId } from "react";
24-
import { useNavigate } from "react-router";
24+
import { generatePath, useNavigate } from "react-router";
2525
import {
2626
Content,
2727
DataList,
@@ -39,7 +39,6 @@ import { useConnections, useNetworkDevices } from "~/queries/network";
3939
import { NETWORK as PATHS } from "~/routes/paths";
4040
import { formatIp } from "~/utils/network";
4141
import { _ } from "~/i18n";
42-
import { generateEncodedPath } from "~/utils";
4342

4443
type ConnectionListItemProps = { connection: Connection };
4544

@@ -93,7 +92,7 @@ function WiredConnectionsList(props: DataListProps) {
9392

9493
return (
9594
<DataList
96-
onSelectDataListItem={(_, id) => navigate(generateEncodedPath(PATHS.wiredConnection, { id }))}
95+
onSelectDataListItem={(_, id) => navigate(generatePath(PATHS.wiredConnection, { id }))}
9796
{...props}
9897
>
9998
{wiredConnections.map((c: Connection) => (

web/src/components/storage/FilesystemMenu.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@
2222

2323
import React, { useId } from "react";
2424
import { Divider, Flex } from "@patternfly/react-core";
25-
import { useNavigate } from "react-router";
25+
import { generatePath, useNavigate } from "react-router";
2626
import Text from "~/components/core/Text";
2727
import MenuHeader from "~/components/core/MenuHeader";
2828
import MenuButton from "~/components/core/MenuButton";
2929
import { STORAGE as PATHS } from "~/routes/paths";
3030
import { model } from "~/types/storage";
3131
import * as driveUtils from "~/components/storage/utils/drive";
3232
import { filesystemType, formattedPath } from "~/components/storage/utils";
33-
import { generateEncodedPath } from "~/utils";
3433
import { sprintf } from "sprintf-js";
3534
import { _ } from "~/i18n";
3635

@@ -61,7 +60,7 @@ export default function FilesystemMenu({ deviceModel }: FilesystemMenuProps): Re
6160
const ariaLabelId = useId();
6261
const toggleTextId = useId();
6362
const { list, listIndex } = deviceModel;
64-
const editFilesystemPath = generateEncodedPath(PATHS.formatDevice, { list, listIndex });
63+
const editFilesystemPath = generatePath(PATHS.formatDevice, { list, listIndex });
6564

6665
// TRANSLATORS: %s is the name of device, like '/dev/sda'.
6766
const detailsAriaLabel = sprintf(_("Details for %s"), deviceModel.name);

web/src/components/storage/PartitionsMenu.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import React, { useId } from "react";
2424
import { Divider, Stack, Flex } from "@patternfly/react-core";
25-
import { useNavigate } from "react-router";
25+
import { generatePath, useNavigate } from "react-router";
2626
import Text from "~/components/core/Text";
2727
import MenuButton from "~/components/core/MenuButton";
2828
import MenuHeader from "~/components/core/MenuHeader";
@@ -31,14 +31,13 @@ import { Partition } from "~/api/storage/types/model";
3131
import { STORAGE as PATHS } from "~/routes/paths";
3232
import { useDeletePartition } from "~/hooks/storage/partition";
3333
import * as driveUtils from "~/components/storage/utils/drive";
34-
import { generateEncodedPath } from "~/utils";
3534
import { sprintf } from "sprintf-js";
3635
import { _, n_ } from "~/i18n";
3736

3837
const PartitionMenuItem = ({ device, mountPath }) => {
3938
const partition = device.getPartition(mountPath);
4039
const { list, listIndex } = device;
41-
const editPath = generateEncodedPath(PATHS.editPartition, {
40+
const editPath = generatePath(PATHS.editPartition, {
4241
list,
4342
listIndex,
4443
partitionId: mountPath,
@@ -140,7 +139,7 @@ export default function PartitionsMenu({ device }) {
140139
const ariaLabelId = useId();
141140
const toggleTextId = useId();
142141
const { list, listIndex } = device;
143-
const newPartitionPath = generateEncodedPath(PATHS.addPartition, { list, listIndex });
142+
const newPartitionPath = generatePath(PATHS.addPartition, { list, listIndex });
144143
// TRANSLATORS: %s is the name of device, like '/dev/sda'.
145144
const detailsAriaLabel = sprintf(_("Details for %s"), device.name);
146145
const hasPartitions = device.partitions.some((p: Partition) => p.mountPath);

web/src/components/storage/SpacePolicyMenu.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,12 @@ import React from "react";
2424
import { Flex } from "@patternfly/react-core";
2525
import MenuButton from "~/components/core/MenuButton";
2626
import Text from "~/components/core/Text";
27-
import { useNavigate } from "react-router";
27+
import { generatePath, useNavigate } from "react-router";
2828
import { useSetSpacePolicy } from "~/hooks/storage/space-policy";
2929
import { SPACE_POLICIES } from "~/components/storage/utils";
3030
import { apiModel } from "~/api/storage/types";
3131
import { STORAGE as PATHS } from "~/routes/paths";
3232
import * as driveUtils from "~/components/storage/utils/drive";
33-
import { generateEncodedPath } from "~/utils";
3433
import { isEmpty } from "radashi";
3534
import { _ } from "~/i18n";
3635

@@ -57,7 +56,7 @@ export default function SpacePolicyMenu({ modelDevice, device }) {
5756

5857
const onSpacePolicyChange = (spacePolicy: apiModel.SpacePolicy) => {
5958
if (spacePolicy === "custom") {
60-
return navigate(generateEncodedPath(PATHS.editSpacePolicy, { list, listIndex }));
59+
return navigate(generatePath(PATHS.editSpacePolicy, { list, listIndex }));
6160
} else {
6261
setSpacePolicy(list, listIndex, { type: spacePolicy });
6362
}

web/src/components/storage/UnusedMenu.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@
2222

2323
import React, { useId } from "react";
2424
import { Flex } from "@patternfly/react-core";
25-
import { useNavigate } from "react-router";
25+
import { generatePath, useNavigate } from "react-router";
2626
import Text from "~/components/core/Text";
2727
import MenuButton from "~/components/core/MenuButton";
2828
import { STORAGE as PATHS } from "~/routes/paths";
2929
import { model } from "~/types/storage";
30-
import { generateEncodedPath } from "~/utils";
3130
import { sprintf } from "sprintf-js";
3231
import { _ } from "~/i18n";
3332

@@ -38,8 +37,8 @@ export default function UnusedMenu({ deviceModel }: UnusedMenuProps): React.Reac
3837
const ariaLabelId = useId();
3938
const toggleTextId = useId();
4039
const { list, listIndex } = deviceModel;
41-
const newPartitionPath = generateEncodedPath(PATHS.addPartition, { list, listIndex });
42-
const formatDevicePath = generateEncodedPath(PATHS.formatDevice, { list, listIndex });
40+
const newPartitionPath = generatePath(PATHS.addPartition, { list, listIndex });
41+
const formatDevicePath = generatePath(PATHS.formatDevice, { list, listIndex });
4342

4443
// TRANSLATORS: %s is the name of device, like '/dev/sda'.
4544
const detailsAriaLabel = sprintf(_("Details for %s"), deviceModel.name);

web/src/components/storage/VolumeGroupEditor.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import React, { useId } from "react";
2424
import { Divider, Flex, Title } from "@patternfly/react-core";
25-
import { useNavigate } from "react-router";
25+
import { generatePath, useNavigate } from "react-router";
2626
import Link from "~/components/core/Link";
2727
import Text from "~/components/core/Text";
2828
import MenuButton from "~/components/core/MenuButton";
@@ -36,7 +36,6 @@ import { baseName, formattedPath } from "~/components/storage/utils";
3636
import { contentDescription } from "~/components/storage/utils/volume-group";
3737
import { useDeleteVolumeGroup } from "~/hooks/storage/volume-group";
3838
import { useDeleteLogicalVolume } from "~/hooks/storage/logical-volume";
39-
import { generateEncodedPath } from "~/utils";
4039
import { isEmpty } from "radashi";
4140
import { sprintf } from "sprintf-js";
4241
import { _, n_, formatList } from "~/i18n";
@@ -93,7 +92,7 @@ const EditVgOption = ({ vg }: { vg: model.VolumeGroup }) => {
9392
itemId="edit-volume-group"
9493
description={_("Modify settings and physical volumes")}
9594
role="menuitem"
96-
onClick={() => navigate(generateEncodedPath(PATHS.volumeGroup.edit, { id: vg.vgName }))}
95+
onClick={() => navigate(generatePath(PATHS.volumeGroup.edit, { id: vg.vgName }))}
9796
>
9897
{_("Edit volume group")}
9998
</MenuButton.Item>
@@ -130,7 +129,7 @@ const LogicalVolumes = ({ vg }: { vg: model.VolumeGroup }) => {
130129
const deleteLogicalVolume = useDeleteLogicalVolume();
131130
const ariaLabelId = useId();
132131
const toggleTextId = useId();
133-
const newLvPath = generateEncodedPath(PATHS.volumeGroup.logicalVolume.add, { id: vg.vgName });
132+
const newLvPath = generatePath(PATHS.volumeGroup.logicalVolume.add, { id: vg.vgName });
134133
const menuAriaLabel = sprintf(_("Logical volumes for %s"), vg.vgName);
135134

136135
if (isEmpty(vg.logicalVolumes)) {
@@ -176,7 +175,7 @@ const LogicalVolumes = ({ vg }: { vg: model.VolumeGroup }) => {
176175
<MountPathMenuItem
177176
key={lv.mountPath}
178177
device={lv}
179-
editPath={generateEncodedPath(PATHS.volumeGroup.logicalVolume.edit, {
178+
editPath={generatePath(PATHS.volumeGroup.logicalVolume.edit, {
180179
id: vg.vgName,
181180
logicalVolumeId: lv.mountPath,
182181
})}

web/src/utils.test.ts

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,7 @@
2020
* find current contact information at www.suse.com.
2121
*/
2222

23-
import {
24-
compact,
25-
localConnection,
26-
hex,
27-
mask,
28-
timezoneTime,
29-
generateEncodedPath,
30-
sortCollection,
31-
} from "./utils";
23+
import { compact, localConnection, hex, mask, timezoneTime, sortCollection } from "./utils";
3224

3325
describe("compact", () => {
3426
it("removes null and undefined values", () => {
@@ -197,49 +189,6 @@ describe("localConnection", () => {
197189
});
198190
});
199191

200-
describe("generateEncodedPath", () => {
201-
it("encodes special characters in parameters", () => {
202-
const path = "/network/:id";
203-
const params = { id: "Wired #1" };
204-
205-
const result = generateEncodedPath(path, params);
206-
207-
expect(result).toBe("/network/Wired%20%231");
208-
});
209-
210-
it("handles multiple parameters", () => {
211-
const path = "/network/:id/bridge/:bridge";
212-
const params = { id: "Wired #1", bridge: "br $0" };
213-
214-
const result = generateEncodedPath(path, params);
215-
216-
expect(result).toBe("/network/Wired%20%231/bridge/br%20%240");
217-
});
218-
219-
it("leaves safe characters unchanged", () => {
220-
const path = "/product/:id";
221-
const params = { id: "12345" };
222-
223-
const result = generateEncodedPath(path, params);
224-
225-
expect(result).toBe("/product/12345");
226-
});
227-
228-
it("works with empty params", () => {
229-
const path = "/static/path";
230-
231-
const result = generateEncodedPath(path, {});
232-
233-
expect(result).toBe("/static/path");
234-
});
235-
236-
it("throws if a param is missing", () => {
237-
const path = "/network/:id";
238-
239-
expect(() => generateEncodedPath(path, {})).toThrow();
240-
});
241-
});
242-
243192
describe("simpleFastSort", () => {
244193
const fakeDevices = [
245194
{ sid: 100, name: "/dev/sdz", size: 5 },

0 commit comments

Comments
 (0)