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-08-04 16:34:20

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

Generated by: LCOV version 2.0-1