Skip to content

Commit

Permalink
First set of UI changes for wireless configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
teclator committed Jun 21, 2024
1 parent f2e54cc commit 72abba0
Show file tree
Hide file tree
Showing 8 changed files with 569 additions and 13 deletions.
1 change: 1 addition & 0 deletions web/src/client/network/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const DeviceState = Object.freeze({
UNAVAILABLE: "unavailable",
DISCONNECTED: "disconnected",
CONFIG: "config",
IPCHECK: "ipCheck",
NEEDAUTH: "needAuth",
ACTIVATED: "activated",
DEACTIVATING: "deactivating",
Expand Down
8 changes: 4 additions & 4 deletions web/src/components/network/NetworkPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
import React, { useEffect, useState } from "react";
import { Button, CardBody, Grid, GridItem, Split, Skeleton, Stack } from "@patternfly/react-core";
import { useLoaderData } from "react-router-dom";
import { CardField, EmptyState, Page } from "~/components/core";
import { ConnectionsTable, WifiSelector } from "~/components/network";
import { ButtonLink, CardField, EmptyState, Page } from "~/components/core";
import { ConnectionsTable } from "~/components/network";
import { NetworkEventTypes } from "~/client/network";
import { useInstallerClient } from "~/context/installer";
import { _ } from "~/i18n";
Expand Down Expand Up @@ -106,9 +106,9 @@ export default function NetworkPage() {
if (!wifiAvailable) return;

return (
<Button variant={activeConnection ? "primary" : "secondary"}>
<ButtonLink isPrimary={activeConnection} to="wifis">
{activeConnection ? _("Change") : _("Connect")}
</Button>
</ButtonLink>
);
};

Expand Down
9 changes: 2 additions & 7 deletions web/src/components/network/WifiConnectionForm.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.
*/

import React, { useEffect, useRef, useState } from "react";
import React, { useState } from "react";
import {
ActionGroup,
Alert,
Expand Down Expand Up @@ -59,18 +59,13 @@ const securityFrom = (supported) => {

export default function WifiConnectionForm({ network, onCancel, onSubmitCallback }) {
const { network: client } = useInstallerClient();
const formRef = useRef();
const [error, setError] = useState(false);
const [isConnecting, setIsConnecting] = useState(false);
const [ssid, setSsid] = useState(network?.ssid || "");
const [password, setPassword] = useState(network?.password || "");
const [security, setSecurity] = useState(securityFrom(network?.security || []));
const hidden = network?.hidden || false;

useEffect(() => {
setTimeout(() => { formRef.current?.scrollIntoView({ behavior: "smooth" }) }, 200);
}, []);

const accept = async e => {
e.preventDefault();
setError(false);
Expand All @@ -86,7 +81,7 @@ export default function WifiConnectionForm({ network, onCancel, onSubmitCallback
};

return (
<Form id={`${ssid}-connection-form`} onSubmit={accept} innerRef={formRef}>
<Form id={`${ssid}-connection-form`} onSubmit={accept}>
{error &&
<Alert variant="warning" isInline title={_("Something went wrong")}>
<p>{_("Please, review provided settings and try again.")}</p>
Expand Down
113 changes: 113 additions & 0 deletions web/src/components/network/WifiNetworkListItemPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) [2022] 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 { Flex, Radio, Spinner, Split, Text } from "@patternfly/react-core";
import { Icon } from "~/components/layout";
import { WifiNetworkMenu, WifiConnectionForm } from "~/components/network";
import { Popup } from "~/components/core";
import { DeviceState } from "~/client/network/model";
import { _ } from "~/i18n";
import { sprintf } from "sprintf-js";

const networkState = (state) => {
switch (state) {
case DeviceState.CONFIG:
// TRANSLATORS: Wifi network status
return _("Connecting");
case DeviceState.ACTIVATED:
// TRANSLATORS: Wifi network status
return _("Connected");
case DeviceState.DEACTIVATING:
// TRANSLATORS: Wifi network status
return _("Disconnecting");
case DeviceState.FAILED:
return _("Failed");
case DeviceState.DISCONNECTED:
// TRANSLATORS: Wifi network status
return _("Disconnected");
default:
return "";
}
};

const isStateChanging = (network) => {
const state = network.device?.state;
return state === DeviceState.CONFIG || state === DeviceState.NEEDAUTH || state === DeviceState.DEACTIVATING || state === DeviceState.FAILED;
};

/**
* Component for displaying a Wi-Fi network within a NetworkList
*
* @param {object} props - component props
* @param {object} props.networks - the ap/configured network to be displayed
* @param {boolean} [props.isSelected] - whether the network has been selected by the user
* @param {boolean} [props.isActive] - whether the network is currently active
* @param {function} props.needAuth - function to execute when the network requires authentication
* @param {function} props.onSelect - function to execute when the network is selected
* @param {function} props.onCancel - function to execute when the selection is cancelled
*/
function WifiNetworkListItemPage({ network, isSelected, isActive, onSelect, onCancel }) {
// Do not wait until receive the next D-Bus network event to have the connection object available
// and display the spinner as soon as possible. I.e., renders it immediately when the user clicks
// on an already configured network.
const showSpinner = (isSelected && network.settings && !network.device) || isStateChanging(network);

return (
<li
key={network.ssid}
data-state={(isSelected && !network.settings && "focused") || null}
>
<Flex justifyContent={{ default: "justifyContentSpaceBetween" }}>
<Radio
id={network.ssid}
label={network.ssid}
description={
<>
<Icon name="lock" size="10" fill="grey" /> {network.security.join(", ")}{" "}
<Icon name="signal_cellular_alt" size="10" fill="grey" /> {network.strength}
</>
}
isChecked={isSelected || isActive || false}
onClick={onSelect}
/>
<Split hasGutter>
{/* TRANSLATORS: %s is replaced by a WiFi network name */}
{false && showSpinner && <Spinner size="md" aria-label={sprintf(_("%s connection is waiting for an state change"), network.ssid)} />}
{showSpinner && network.device && network.device?.state === DeviceState.CONFIG}
<Text component="small" className="keep-words">
{network.device && networkState(network.device?.state)}
</Text>
{network.settings &&
<WifiNetworkMenu settings={network.settings} device={network.device} onConnect={onSelect} />}
</Split>
</Flex>
{((isSelected && (network && (!network.settings || network.error))) || network.needAuth) &&
<Popup title="Whatever">
<div className="content">
<WifiConnectionForm network={network} onCancel={onCancel} />
</div>
</Popup>}
</li>
);
}

export default WifiNetworkListItemPage;
Loading

0 comments on commit 72abba0

Please sign in to comment.