LCOV - code coverage report
Current view: top level - pkg/systemd - overview.jsx Coverage Total Hit
Test: cockpit Lines: 96.9 % 127 123
Test Date: 2026-07-17 07:33:01

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2019 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5              : 
       6              : import '../lib/patternfly/patternfly-6-cockpit.scss';
       7              : import 'polyfills';
       8              : import 'cockpit-dark-theme'; // once per page
       9           92 : import cockpit from "cockpit";
      10              : 
      11           92 : import React from 'react';
      12           92 : import { createRoot } from "react-dom/client";
      13              : import { Page, PageSection, PageSectionVariants } from "@patternfly/react-core/dist/esm/components/Page/index.js";
      14              : import { Gallery } from "@patternfly/react-core/dist/esm/layouts/Gallery/index.js";
      15              : import { Dropdown, DropdownItem, DropdownList } from '@patternfly/react-core/dist/esm/components/Dropdown/index.js';
      16              : import { MenuToggle, MenuToggleAction } from "@patternfly/react-core/dist/esm/components/MenuToggle";
      17              : 
      18              : import { superuser } from "superuser";
      19              : 
      20              : import { SystemInformationCard } from './overview-cards/systemInformationCard.jsx';
      21              : import { ConfigurationCard } from './overview-cards/configurationCard.jsx';
      22              : import { HealthCard } from './overview-cards/healthCard.jsx';
      23              : import { MotdCard } from './overview-cards/motdCard.jsx';
      24              : import { UsageCard } from './overview-cards/usageCard.jsx';
      25              : import { SuperuserAlert } from './superuser-alert.jsx';
      26              : import { superuser_proxy, SuperuserIndicator } from "superuser-dialogs";
      27              : import { ShutdownModal } from 'cockpit-components-shutdown.jsx';
      28              : import { WithDialogs, DialogsContext } from "dialogs.jsx";
      29              : 
      30              : import "./overview.scss";
      31              : 
      32           92 : const _ = cockpit.gettext;
      33              : 
      34           92 : class OverviewPage extends React.Component {
      35           92 :     static contextType = DialogsContext;
      36              : 
      37           92 :     constructor(props) {
      38           92 :         super(props);
      39              : 
      40           92 :         this.state = {
      41           92 :             actionIsOpen: false,
      42           92 :             privileged: true,
      43           92 :         };
      44           92 :         this.hostnameMonitor = this.hostnameMonitor.bind(this);
      45           92 :         this.onPermissionChanged = this.onPermissionChanged.bind(this);
      46              : 
      47           92 :         this.superuser = superuser_proxy();
      48           92 :     }
      49              : 
      50           92 :     componentDidMount() {
      51           92 :         this.hostnameMonitor();
      52           92 :         superuser.addEventListener("changed", this.onPermissionChanged);
      53           92 :         this.onPermissionChanged();
      54           92 :     }
      55              : 
      56            0 :     componentWillUnmount() {
      57            0 :         superuser.removeEventListener("changed", this.onPermissionChanged);
      58            0 :     }
      59              : 
      60           92 :     onPermissionChanged() {
      61           92 :         this.setState({ privileged: superuser.allowed });
      62           92 :     }
      63              : 
      64           92 :     hostname_text() {
      65           92 :         if (!this.state.hostnameData)
      66           92 :             return undefined;
      67              : 
      68           82 :         const pretty_hostname = this.state.hostnameData.PrettyHostname;
      69           82 :         const static_hostname = this.state.hostnameData.StaticHostname;
      70           82 :         let str = this.state.hostnameData.Hostname;
      71              : 
      72           16 :         if (pretty_hostname && static_hostname && static_hostname != pretty_hostname)
      73           16 :             str = pretty_hostname + " (" + static_hostname + ")";
      74           82 :         else if (static_hostname)
      75           81 :             str = static_hostname;
      76              : 
      77           16 :         return str || '';
      78           92 :     }
      79              : 
      80           92 :     hostnameMonitor() {
      81           92 :         this.client = cockpit.dbus('org.freedesktop.hostname1');
      82           92 :         this.hostname_proxy = this.client.proxy('org.freedesktop.hostname1',
      83           92 :                                                 '/org/freedesktop/hostname1');
      84           83 :         this.hostname_proxy.addEventListener("changed", data => {
      85           83 :             this.setState({ hostnameData: data.detail });
      86           83 :         });
      87           92 :     }
      88              : 
      89           92 :     render() {
      90           92 :         const Dialogs = this.context;
      91           92 :         const { actionIsOpen } = this.state;
      92           92 :         const dropdownItems = [
      93           92 :             <DropdownItem key="reboot" id="reboot"
      94            0 :                           onClick={() => Dialogs.show(<ShutdownModal />)}
      95           92 :                           component="button">
      96           92 :                 {_("Reboot")}
      97           92 :             </DropdownItem>,
      98           92 :             <DropdownItem key="shutdown" id="shutdown"
      99            1 :                           onClick={() => Dialogs.show(<ShutdownModal shutdown />)}
     100           92 :                           component="button">
     101           92 :                 {_("Shutdown")}
     102           92 :             </DropdownItem>,
     103           92 :         ];
     104              : 
     105           92 :         let headerActions = null;
     106           92 :         if (this.state.privileged)
     107           92 :             headerActions = (
     108            1 :                 <Dropdown onSelect={() => this.setState({ actionIsOpen: false })}
     109           92 :                     toggle={(toggleRef) => (
     110           92 :                         <MenuToggle
     111           92 :                             ref={toggleRef}
     112           92 :                             variant="secondary"
     113           92 :                             splitButtonItems={[
     114           92 :                                 <MenuToggleAction
     115           92 :                                         id='reboot-button'
     116           92 :                                         key='reboot-button'
     117            1 :                                         onClick={() => Dialogs.show(<ShutdownModal />)}
     118              :                                 >
     119           92 :                                     {_("Reboot")}
     120           92 :                                 </MenuToggleAction>
     121           92 :                             ]}
     122            1 :                             onClick={() => this.setState({ actionIsOpen: !actionIsOpen })}
     123           92 :                             id="shutdown-group"
     124           92 :                         />
     125              :                     )}
     126           92 :                     isOpen={actionIsOpen}
     127           92 :                     popperProps={{ position: "right" }}
     128              :                 >
     129           92 :                     <DropdownList>
     130           92 :                         {dropdownItems}
     131           92 :                     </DropdownList>
     132           92 :                 </Dropdown>
     133              :             );
     134              : 
     135           92 :         const show_superuser = (
     136           92 :             cockpit.transport.host && cockpit.transport.host != "localhost" &&
     137           33 :             !(window.parent.name == "cockpit1" && window.parent.features &&
     138           33 :               window.parent.features.navbar_is_for_current_machine));
     139              : 
     140           92 :         return (
     141           92 :             <Page className='pf-m-no-sidebar'>
     142           92 :                 <SuperuserAlert />
     143           92 :                 <PageSection hasBodyWrapper={false} className='ct-overview-header' padding={{ default: 'padding' }}>
     144           92 :                     <div className='ct-overview-header-hostname'>
     145           92 :                         <h1>
     146           92 :                             {this.hostname_text()}
     147           92 :                         </h1>
     148           92 :                         {this.state.hostnameData &&
     149           82 :                          this.state.hostnameData.OperatingSystemPrettyName &&
     150           82 :                          <div className="ct-overview-header-subheading" id="system_information_os_text">{cockpit.format(_("running $0"), this.state.hostnameData.OperatingSystemPrettyName)}</div>}
     151           92 :                     </div>
     152           92 :                     <div className='ct-overview-header-actions'>
     153           16 :                         { show_superuser && <SuperuserIndicator proxy={this.superuser} /> }
     154           92 :                         { "\n" }
     155           92 :                         { headerActions }
     156           92 :                     </div>
     157           92 :                 </PageSection>
     158           92 :                 <PageSection hasBodyWrapper={false} variant={PageSectionVariants.default}>
     159           92 :                     <Gallery className='ct-system-overview' hasGutter>
     160           92 :                         <MotdCard />
     161           92 :                         <HealthCard />
     162           92 :                         <UsageCard />
     163           92 :                         <SystemInformationCard />
     164           92 :                         <ConfigurationCard hostname={this.hostname_text()} />
     165           92 :                     </Gallery>
     166           92 :                 </PageSection>
     167           92 :             </Page>
     168              :         );
     169           92 :     }
     170           92 : }
     171              : 
     172           92 : function init() {
     173           92 :     cockpit.translate();
     174           92 :     const root = createRoot(document.getElementById("overview"));
     175           92 :     root.render(<WithDialogs><OverviewPage /></WithDialogs>);
     176           92 : }
     177              : 
     178           92 : document.addEventListener("DOMContentLoaded", init);
        

Generated by: LCOV version 2.0-1