🏡 index : quine-global-labs/mirror-cockpit-project-cockpit.git

/*
 * 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'; // once per page
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);