🏡 index : quine-global/quine-anaconda-webui.git

/*
 * Copyright (C) 2022 Red Hat, Inc.
 * SPDX-License-Identifier: LGPL-2.1-or-later
 */
import cockpit from "cockpit";

import React, { useContext, useEffect, useState } from "react";
import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
import { DescriptionListDescription, DescriptionListGroup, DescriptionListTerm } from "@patternfly/react-core/dist/esm/components/DescriptionList/index.js";
import { Form, FormGroup, FormHelperText } from "@patternfly/react-core/dist/esm/components/Form/index.js";
import { HelperText, HelperTextItem } from "@patternfly/react-core/dist/esm/components/HelperText/index.js";
import { Modal, ModalBody, ModalFooter, ModalHeader } from "@patternfly/react-core/dist/esm/components/Modal/index.js";
import { TextInput } from "@patternfly/react-core/dist/esm/components/TextInput/index.js";
import { Flex, FlexItem } from "@patternfly/react-core/dist/esm/layouts/Flex/index.js";

import { setHostname } from "../../apis/network.js";

import { NetworkContext } from "../../contexts/Common.jsx";

const _ = cockpit.gettext;
const SCREEN_ID = "anaconda-screen-review";

const ChangeHostname = ({ initHostname }) => {
    const [currentHostname, setCurrentHostname] = useState(initHostname);
    const [error, setError] = useState([]);
    const [isModalOpen, setIsModalOpen] = useState(false);

    const validateHostname = (value) => {
        const validationError = [];
        if (value.length > 64) {
            validationError.push(_("Real hostname must be 64 characters or less"));
        }

        if (!value.match(/^$|^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*\.?$/)) {
            validationError.push(_("Real hostname can only contain characters, digits, dashes (not starting or ending a character) and dots"));
        }

        setError(validationError);
    };

    const onHostnameChanged = (value) => {
        validateHostname(value);
        setCurrentHostname(value);
    };
    const onSubmit = (event) => {
        setHostname({ hostname: currentHostname })
                .then(() => {
                    handleModalToggle();
                })
                .catch(() => {
                    setError(_("This hostname can't be submitted"));
                });

        if (event) {
            event.preventDefault();
        }
        return false;
    };

    const handleModalToggle = () => {
        setIsModalOpen(!isModalOpen);
    };

    const onClose = () => {
        setCurrentHostname(initHostname);
        setError([]);
        handleModalToggle();
    };

    const disabled = error.length || (initHostname === currentHostname);
    return (
        <>
            <Button
              id="system_information_hostname_button" variant="link"
              onClick={handleModalToggle}
              isInline aria-label="edit hostname">
                {_("edit")}
            </Button>
            <Modal
              id="system_information_change_hostname"
              isOpen={isModalOpen}
              onClose={onClose}
              position="top"
              variant="small"
            >
                <ModalHeader
                  title={initHostname === "" ? _("Set custom hostname") : _("Change hostname")}
                />
                <ModalBody>
                    <Form isHorizontal onSubmit={onSubmit}>
                        <FormGroup fieldId="review-handle-hostname-hostname" label={_("Hostname")}>
                            <TextInput
                              id="review-handle-hostname-hostname" value={currentHostname}
                              onChange={(_event, value) => onHostnameChanged(value)}
                              validated={error.length ? "error" : "default"} />
                            {error.length > 0
                                ? (
                                    <FormHelperText>
                                        <HelperText>
                                            {error.map((err, i) =>
                                                <HelperTextItem key={i} variant="error">
                                                    {err}
                                                </HelperTextItem>
                                            )}
                                        </HelperText>
                                    </FormHelperText>)
                                : (
                                    <FormHelperText>
                                        <HelperText>
                                            <HelperTextItem>
                                                {_("May contain letters, numbers, and dashes.")}
                                            </HelperTextItem>
                                            <HelperTextItem>
                                                {_("If empty, hostname will be transient and set by network information.")}
                                            </HelperTextItem>
                                        </HelperText>
                                    </FormHelperText>
                                )}
                        </FormGroup>
                    </Form>
                </ModalBody>
                <ModalFooter>
                    <Button
                      variant="primary" isAriaDisabled={disabled}
                      onClick={onSubmit}>{initHostname === "" ? _("Save") : _("Change")}
                    </Button>
                    <Button variant="link" onClick={onClose}>{_("Cancel")}</Button>
                </ModalFooter>
            </Modal>
        </>
    );
};

export const HostnameRow = () => {
    const network = useContext(NetworkContext);
    const [initHostname, setInitHostname] = useState(network.hostname || "");

    useEffect(() => {
        setInitHostname(network.hostname);
    }, [network.hostname]);

    return (
        <DescriptionListGroup>
            <DescriptionListTerm>
                {_("Hostname")}
            </DescriptionListTerm>
            <DescriptionListDescription id={SCREEN_ID + "-target-system-hostname"}>
                <Flex
                  spaceItems={{ default: "spaceItemsMd" }}
                  alignItems={{ default: "alignItemsCenter" }}>
                    <FlexItem>
                        {initHostname !== ""
                            ? initHostname
                            : <div className="pf-v6-u-color-400">{_("transient, will use DHCP")}</div>}
                    </FlexItem>
                    <FlexItem>
                        <ChangeHostname
                          initHostname={initHostname}
                          setInitHostname={setInitHostname} />
                    </FlexItem>
                </Flex>
            </DescriptionListDescription>
        </DescriptionListGroup>
    );
};