* Copyright (C) 2019 Red Hat, Inc.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
import React, { useState } from 'react';
import { Alert, AlertActionCloseButton } from "@patternfly/react-core/dist/esm/components/Alert/index.js";
import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
import {
Modal, ModalBody, ModalFooter, ModalHeader
} from '@patternfly/react-core/dist/esm/components/Modal/index.js';
import { Stack } from "@patternfly/react-core/dist/esm/layouts/Stack/index.js";
import { TextArea } from "@patternfly/react-core/dist/esm/components/TextArea/index.js";
import { EditIcon } from '@patternfly/react-icons';
import { ModalError } from 'cockpit-components-inline-notification.jsx';
import { superuser } from "superuser";
import { useDialogs } from "dialogs.jsx";
import { useInit } from "hooks";
import cockpit from "cockpit";
import './motdCard.scss';
const _ = cockpit.gettext;
const MotdEditDialog = ({ text, expectedTag }) => {
const Dialogs = useDialogs();
const [value, setValue] = useState(text);
const [error, setError] = useState(null);
const [errorDetail, setErrorDetail] = useState(null);
return (
<Modal position="top"
variant="medium" isOpen
id="motd-box-edit-modal"
onClose={Dialogs.close}>
<ModalHeader title={_("Edit /etc/motd")} />
<ModalBody>
<Stack hasGutter>
{error &&
<ModalError dialogError={error}
dialogErrorDetail={errorDetail} />}
<TextArea resizeOrientation="vertical"
value={value}
onChange={(_event, value) => setValue(value)} />
</Stack>
</ModalBody>
<ModalFooter>
<Button variant='primary'
onClick={() => cockpit.file("/etc/motd", { superuser: "try", err: "message" })
.replace(value, expectedTag)
.then(Dialogs.close)
.catch(exc => {
setError(_("Failed to save changes in /etc/motd"));
setErrorDetail(exc.message);
})}>
{_("Save changes")}
</Button>
<Button variant='link'
onClick={Dialogs.close}>
{_("Cancel")}
</Button>
</ModalFooter>
</Modal>);
};
export const MotdCard = () => {
const Dialogs = useDialogs();
const [motdText, setMotdText] = useState("");
const [motdTag, setMotdTag] = useState(null);
const [motdVisible, setMotdVisible] = useState(false);
useInit(() => {
cockpit.file("/etc/motd").watch((content, tag) => {
if (content)
content = content.trimEnd().replace(/^\s*\n/, '');
if (content && content !== cockpit.localStorage.getItem('dismissed-motd')) {
setMotdText(content);
setMotdTag(tag);
setMotdVisible(true);
} else {
setMotdVisible(false);
}
});
});
function hideAlert() {
setMotdVisible(false);
cockpit.localStorage.setItem('dismissed-motd', motdText);
}
if (!motdVisible)
return null;
const actionClose = <>
{superuser.allowed &&
<Button icon={<EditIcon />} variant="plain"
id="motd-box-edit"
onClick={() => Dialogs.show(<MotdEditDialog text={motdText} expectedTag={motdTag} />)}
aria-label={_("Edit motd")} />}
<AlertActionCloseButton onClose={hideAlert} />
</>;
return <Alert id="motd-box" isInline className="motd-box"
variant="custom"
title={<pre id="motd">{motdText}</pre>}
actionClose={actionClose} />;
};