* Copyright (C) 2019 Red Hat, Inc.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
import '../lib/patternfly/patternfly-6-cockpit.scss';
import 'polyfills';
import 'cockpit-dark-theme';
import cockpit from "cockpit";
import React from 'react';
import { createRoot } from "react-dom/client";
import { Page, PageSection, PageSectionVariants } from "@patternfly/react-core/dist/esm/components/Page/index.js";
import { Gallery } from "@patternfly/react-core/dist/esm/layouts/Gallery/index.js";
import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/dist/esm/components/Dropdown/index.js';
import { MenuToggle, MenuToggleAction } from "@patternfly/react-core/dist/esm/components/MenuToggle";
import { superuser } from "superuser";
import { SystemInformationCard } from './overview-cards/systemInformationCard.jsx';
import { ConfigurationCard } from './overview-cards/configurationCard.jsx';
import { HealthCard } from './overview-cards/healthCard.jsx';
import { MotdCard } from './overview-cards/motdCard.jsx';
import { UsageCard } from './overview-cards/usageCard.jsx';
import { SuperuserAlert } from './superuser-alert.jsx';
import { superuser_proxy, SuperuserIndicator } from "superuser-dialogs";
import { ShutdownModal } from 'cockpit-components-shutdown.jsx';
import { WithDialogs, DialogsContext } from "dialogs.jsx";
import "./overview.scss";
import { Title, TitleSizes } from '@patternfly/react-core/dist/esm/components/Title';
const _ = cockpit.gettext;
class OverviewPage extends React.Component {
static contextType = DialogsContext;
constructor(props) {
super(props);
this.state = {
actionIsOpen: false,
privileged: true,
};
this.hostnameMonitor = this.hostnameMonitor.bind(this);
this.onPermissionChanged = this.onPermissionChanged.bind(this);
this.superuser = superuser_proxy();
}
componentDidMount() {
this.hostnameMonitor();
superuser.addEventListener("changed", this.onPermissionChanged);
this.onPermissionChanged();
}
componentWillUnmount() {
superuser.removeEventListener("changed", this.onPermissionChanged);
}
onPermissionChanged() {
this.setState({ privileged: superuser.allowed });
}
hostname_text() {
if (!this.state.hostnameData)
return undefined;
const pretty_hostname = this.state.hostnameData.PrettyHostname;
const static_hostname = this.state.hostnameData.StaticHostname;
let str = this.state.hostnameData.Hostname;
if (pretty_hostname && static_hostname && static_hostname !== pretty_hostname)
str = pretty_hostname + " (" + static_hostname + ")";
else if (static_hostname)
str = static_hostname;
return str || '';
}
hostnameMonitor() {
this.client = cockpit.dbus('org.freedesktop.hostname1');
this.hostname_proxy = this.client.proxy('org.freedesktop.hostname1',
'/org/freedesktop/hostname1');
this.hostname_proxy.addEventListener("changed", data => {
this.setState({ hostnameData: data.detail });
});
}
render() {
const Dialogs = this.context;
const { actionIsOpen } = this.state;
const dropdownItems = [
<DropdownItem key="reboot" id="reboot"
onClick={() => Dialogs.show(<ShutdownModal />)}
component="button">
{_("Reboot")}
</DropdownItem>,
<DropdownItem key="shutdown" id="shutdown"
onClick={() => Dialogs.show(<ShutdownModal shutdown />)}
component="button">
{_("Shutdown")}
</DropdownItem>,
];
let headerActions = null;
if (this.state.privileged)
headerActions = (
<Dropdown onSelect={() => this.setState({ actionIsOpen: false })}
toggle={(toggleRef) => (
<MenuToggle
ref={toggleRef}
variant="secondary"
splitButtonItems={[
<MenuToggleAction
id='reboot-button'
key='reboot-button'
onClick={() => Dialogs.show(<ShutdownModal />)}
>
{_("Reboot")}
</MenuToggleAction>
]}
onClick={() => this.setState({ actionIsOpen: !actionIsOpen })}
id="shutdown-group"
/>
)}
isOpen={actionIsOpen}
popperProps={{ position: "right" }}
>
<DropdownList>
{dropdownItems}
</DropdownList>
</Dropdown>
);
const show_superuser = (
cockpit.transport.host && cockpit.transport.host !== "localhost" &&
!(window.parent.name === "cockpit1" && window.parent.features &&
window.parent.features.navbar_is_for_current_machine));
return (
<Page className='pf-m-no-sidebar'>
<SuperuserAlert />
<PageSection hasBodyWrapper={false} className='ct-overview-header' padding={{ default: 'padding' }}>
<div className='ct-overview-header-hostname'>
<Title size={TitleSizes['3xl']} headingLevel='h1'>
{this.hostname_text()}
</Title>
{this.state.hostnameData &&
this.state.hostnameData.OperatingSystemPrettyName &&
<div className="ct-overview-header-subheading" id="system_information_os_text">{cockpit.format(_("running $0"), this.state.hostnameData.OperatingSystemPrettyName)}</div>}
</div>
<div className='ct-overview-header-actions'>
{ show_superuser && <SuperuserIndicator proxy={this.superuser} /> }
{ "\n" }
{ headerActions }
</div>
</PageSection>
<PageSection hasBodyWrapper={false} variant={PageSectionVariants.default}>
<Gallery className='ct-system-overview' hasGutter>
<MotdCard />
<HealthCard />
<UsageCard />
<SystemInformationCard />
<ConfigurationCard hostname={this.hostname_text()} />
</Gallery>
</PageSection>
</Page>
);
}
}
function init() {
cockpit.translate();
const root = createRoot(document.getElementById("overview"));
root.render(<WithDialogs><OverviewPage /></WithDialogs>);
}
document.addEventListener("DOMContentLoaded", init);