Line data Source code
1 : /*
2 : * Copyright (C) 2021 Red Hat, Inc.
3 : * SPDX-License-Identifier: LGPL-2.1-or-later
4 : */
5 : import '../lib/patternfly/patternfly-6-cockpit.scss';
6 : import "./network-anaconda.scss";
7 1 : import cockpit from "cockpit";
8 : import 'cockpit-dark-theme'; // once per page
9 1 : import React, { useRef } from 'react';
10 1 : import { createRoot } from "react-dom/client";
11 :
12 : import { Button } from "@patternfly/react-core/dist/esm/components/Button/index.js";
13 : import { ExclamationCircleIcon } from "@patternfly/react-icons";
14 :
15 : import { EmptyStatePanel } from "cockpit-components-empty-state.jsx";
16 : import { ModelContext } from './model-context.jsx';
17 : import { NetworkInterfacePage } from './network-interface.jsx';
18 : import { NetworkPage } from './network-main.jsx';
19 : import { UsageMonitor } from './helpers.js';
20 :
21 : import * as service from 'service.js';
22 : import { init as initDialogs, NetworkManagerModel } from './interfaces.js';
23 : import { superuser } from 'superuser';
24 : import { PlotState } from 'plot';
25 :
26 : import { useObject, useEvent, usePageLocation } from "hooks";
27 : import { WithDialogs } from "dialogs.jsx";
28 :
29 1 : const _ = cockpit.gettext;
30 :
31 1 : const App = () => {
32 1 : const nmService = useObject(() => service.proxy("NetworkManager"),
33 1 : null,
34 1 : []);
35 1 : useEvent(nmService, "changed");
36 :
37 1 : const model = useObject(() => new NetworkManagerModel(), null, []);
38 1 : useEvent(model, "changed");
39 :
40 1 : const nmRunning_ref = useRef(undefined);
41 1 : useEvent(model.client, "owner", (event, owner) => { nmRunning_ref.current = owner !== null });
42 :
43 1 : const { path } = usePageLocation();
44 :
45 1 : useEvent(superuser, "changed");
46 :
47 1 : const usage_monitor = useObject(() => new UsageMonitor(), null, []);
48 1 : const plot_state_main = useObject(() => new PlotState(), null, []);
49 1 : const plot_state_iface = useObject(() => new PlotState(), null, []);
50 :
51 0 : if (model.curtain == 'testing' || model.curtain == 'restoring') {
52 0 : return <EmptyStatePanel loading title={model.curtain == 'testing' ? _("Testing connection") : _("Restoring connection")} />;
53 0 : }
54 :
55 1 : if (model.ready === undefined)
56 1 : return <EmptyStatePanel loading />;
57 :
58 : /* Show EmptyStatePanel when nm is not running */
59 0 : if (!nmRunning_ref.current) {
60 0 : if (nmService.enabled) {
61 0 : return (
62 0 : <div id="networking-nm-crashed">
63 0 : <EmptyStatePanel icon={ ExclamationCircleIcon }
64 0 : title={ _("NetworkManager is not running") }
65 0 : action={nmService.exists ? _("Start service") : null}
66 0 : onAction={ nmService.start }
67 0 : secondary={
68 0 : <Button component="a"
69 0 : variant="secondary"
70 0 : onClick={() => cockpit.jump("/system/services#/NetworkManager.service", cockpit.transport.host)}>
71 0 : {_("Troubleshoot…")}
72 0 : </Button>
73 0 : } />
74 0 : </div>
75 : );
76 0 : } else if (!nmService.exists) {
77 0 : return (
78 0 : <div id="networking-nm-not-found">
79 0 : <EmptyStatePanel icon={ ExclamationCircleIcon }
80 0 : title={ _("NetworkManager is not installed") } />
81 :
82 0 : </div>
83 : );
84 0 : } else {
85 0 : return (
86 0 : <div id="networking-nm-disabled">
87 0 : <EmptyStatePanel icon={ ExclamationCircleIcon }
88 0 : title={ _("Network devices and graphs require NetworkManager") }
89 0 : action={nmService.exists ? _("Enable service") : null}
90 0 : onAction={() => {
91 0 : nmService.enable();
92 0 : nmService.start();
93 0 : }} />
94 :
95 0 : </div>
96 : );
97 0 : }
98 0 : }
99 :
100 1 : const interfaces = model.list_interfaces();
101 :
102 : /* At this point NM is running and the model is ready */
103 0 : if (path.length == 0) {
104 0 : return (
105 0 : <ModelContext.Provider value={model}>
106 0 : <WithDialogs key="1">
107 0 : <NetworkPage privileged={superuser.allowed}
108 0 : operationInProgress={model.operationInProgress}
109 0 : usage_monitor={usage_monitor}
110 0 : plot_state={plot_state_main}
111 0 : interfaces={interfaces} />
112 0 : </WithDialogs>
113 0 : </ModelContext.Provider>
114 : );
115 0 : } else if (path.length == 1) {
116 1 : const iface = interfaces.find(iface => iface.Name == path[0]);
117 :
118 1 : if (iface) {
119 1 : return (
120 1 : <ModelContext.Provider value={model}>
121 1 : <WithDialogs key="2">
122 1 : <NetworkInterfacePage privileged={superuser.allowed}
123 1 : operationInProgress={model.operationInProgress}
124 1 : usage_monitor={usage_monitor}
125 1 : plot_state={plot_state_iface}
126 1 : interfaces={interfaces}
127 1 : iface={iface} />
128 1 : </WithDialogs>
129 1 : </ModelContext.Provider>
130 : );
131 1 : }
132 1 : }
133 :
134 0 : return null;
135 1 : };
136 :
137 1 : function init() {
138 1 : initDialogs();
139 1 : const root = createRoot(document.getElementById("network-page"));
140 1 : root.render(<App />);
141 1 : }
142 :
143 1 : document.addEventListener("DOMContentLoaded", init);
|