Skip to content

Commit

Permalink
shell: Include many files in type checking
Browse files Browse the repository at this point in the history
  • Loading branch information
mvollmer committed Jan 8, 2025
1 parent 651fc0d commit ac58a25
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* along with Cockpit; If not, see <https://www.gnu.org/licenses/>.
*/

// @cockpit-ts-relaxed

import cockpit from "cockpit";

import React, { useState } from "react";
Expand All @@ -27,9 +29,11 @@ import { Split, SplitItem } from "@patternfly/react-core/dist/esm/layouts/Split/
import { Modal } from "@patternfly/react-core/dist/esm/components/Modal/index.js";
import { useInit } from "hooks";

import { ShellState } from "./state";

const _ = cockpit.gettext;

export const ActivePagesDialog = ({ dialogResult, state }) => {
export const ActivePagesDialog = ({ dialogResult, state } : { dialogResult, state: ShellState }) => {
function get_pages() {
const result = [];
for (const frame of Object.values(state.frames)) {
Expand Down
25 changes: 18 additions & 7 deletions pkg/shell/failures.jsx → pkg/shell/failures.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* along with Cockpit; If not, see <https://www.gnu.org/licenses/>.
*/

// @cockpit-ts-relaxed

import cockpit from "cockpit";
import React from "react";

Expand All @@ -26,7 +28,7 @@ import { Page, PageSection, PageSectionVariants } from "@patternfly/react-core/d
import { Stack } from "@patternfly/react-core/dist/esm/layouts/Stack/index.js";
import { ExclamationCircleIcon } from "@patternfly/react-icons";

import { EmptyStatePanel } from "cockpit-components-empty-state.jsx";
import { EmptyStatePanel } from "cockpit-components-empty-state";

import { codes } from "./hosts_dialog.jsx";

Expand Down Expand Up @@ -61,20 +63,29 @@ export const EarlyFailure = () => {
};

const EarlyFailureReady = ({
loading,
loading = false,
title,
paragraph,
reconnect,
troubleshoot,
onTroubleshoot,
reconnect = false,
troubleshoot = false,
onTroubleshoot = () => {},
watchdog_problem,
onReconnect
onReconnect = () => {},
} : {
loading?: boolean,
title: string,
paragraph: string,
reconnect?: boolean,
troubleshoot?: boolean,
onTroubleshoot?: () => void,
watchdog_problem?: string,
onReconnect?: () => void,
}) => {
return (
<div id="early-failure-ready" className="curtains-ct">
<Page>
<PageSection variant={PageSectionVariants.light}>
<EmptyStatePanel icon={!loading ? ExclamationCircleIcon : undefined}
<EmptyStatePanel {... !loading ? { icon: ExclamationCircleIcon } : {} }
loading={loading}
title={title}
action={<>
Expand Down
65 changes: 46 additions & 19 deletions pkg/shell/hosts.jsx → pkg/shell/hosts.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
/*
* This file is part of Cockpit.
*
* Copyright (C) 2024 Red Hat, Inc.
*
* Cockpit is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Cockpit is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Cockpit; If not, see <https://www.gnu.org/licenses/>.
*/

// @cockpit-ts-relaxed

import cockpit from "cockpit";

import React from 'react';
import ReactDOM from "react-dom";
import PropTypes from 'prop-types';
import { Button } from "@patternfly/react-core/dist/esm/components/Button";
import {
CaretDownIcon,
Expand All @@ -19,23 +39,30 @@ import { encode_location } from "./util.jsx";
import { split_connection_string } from "./machines/machines";
import { add_host, edit_host, connect_host } from "./hosts_dialog.jsx";

import { ShellState } from "./state";

const _ = cockpit.gettext;

class HostsSelector extends React.Component {
constructor() {
super();
el: HTMLDivElement;
props: { children };

constructor(props) {
super(props);
this.props = props;

this.el = document.createElement("div");
this.el.className = "view-hosts";
}

componentDidMount() {
const hosts_sel = document.getElementById("nav-hosts");
hosts_sel.appendChild(this.el);
hosts_sel?.appendChild(this.el);
}

componentWillUnmount() {
const hosts_sel = document.getElementById("nav-hosts");
hosts_sel.removeChild(this.el);
hosts_sel?.removeChild(this.el);
}

render() {
Expand Down Expand Up @@ -63,10 +90,16 @@ export const CockpitCurrentHost = ({ current_user, machine }) => {
);
};

interface CockpitHostsState { opened, editing, current_user, current_key }

// full host switcher
export class CockpitHosts extends React.Component {
props: { selector, host_modal_state, state: ShellState };
state: CockpitHostsState;

constructor(props) {
super(props);
this.props = props;

this.state = {
opened: false,
Expand All @@ -91,7 +124,7 @@ export class CockpitHosts extends React.Component {

static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.state.current_machine.key !== prevState.current_key) {
document.getElementById(nextProps.selector).classList.toggle("interact", false);
document.getElementById(nextProps.selector)?.classList.toggle("interact", false);
return {
current_key: nextProps.state.current_machine.key,
opened: false,
Expand All @@ -102,9 +135,9 @@ export class CockpitHosts extends React.Component {
}

toggleMenu() {
document.getElementById(this.props.selector).classList.toggle("interact", !this.state.opened);
document.getElementById(this.props.selector)?.classList.toggle("interact", !this.state.opened);

this.setState(s => {
this.setState((s: CockpitHostsState) => {
return (
{
opened: !s.opened,
Expand All @@ -118,7 +151,7 @@ export class CockpitHosts extends React.Component {
await add_host(this.props.host_modal_state, this.props.state);
}

async onHostEdit(event, machine) {
async onHostEdit(_event, machine) {
await edit_host(this.props.host_modal_state, this.props.state, machine);
}

Expand All @@ -133,7 +166,7 @@ export class CockpitHosts extends React.Component {
}

onEditHosts() {
this.setState(s => { return { editing: !s.editing } });
this.setState((s: CockpitHostsState) => { return { editing: !s.editing } });
}

onRemove(event, machine) {
Expand Down Expand Up @@ -202,8 +235,8 @@ export class CockpitHosts extends React.Component {
</Tooltip>
</>}
/>;
const label = current_machine.label || "";
const user = current_machine.user || this.state.current_user;
const label = current_machine?.label || "";
const user = current_machine?.user || this.state.current_user;

const add_host_action = <Button variant="secondary" onClick={this.onAddNewHost}>{_("Add new host")}</Button>;

Expand Down Expand Up @@ -238,7 +271,7 @@ export class CockpitHosts extends React.Component {
selector={this.props.selector}
groups={groups}
item_render={render}
sorting={(a, b) => true}
sorting={(_a, _b) => true}
filtering={this.filterHosts}
current={label}
jump={() => console.error("internal error: jump not supported in hosts selector")}
Expand All @@ -254,9 +287,3 @@ export class CockpitHosts extends React.Component {
);
}
}

CockpitHosts.propTypes = {
state: PropTypes.object.isRequired,
host_modal_state: PropTypes.object.isRequired,
selector: PropTypes.string.isRequired,
};
3 changes: 1 addition & 2 deletions pkg/shell/hosts_dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ export const HostModalState = () => {
close_modal,
};

cockpit.event_target(self);
return self;
return cockpit.event_target(self);
};

/* Activate and jump to a newly added machine, identified by its
Expand Down
22 changes: 15 additions & 7 deletions pkg/shell/shell.jsx → pkg/shell/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* along with Cockpit; If not, see <https://www.gnu.org/licenses/>.
*/

// @cockpit-ts-relaxed

import cockpit from "cockpit";

import React, { useEffect } from 'react';
Expand Down Expand Up @@ -47,7 +49,7 @@ const SkipLink = ({ focus_id, children }) => {
<a className="screenreader-text skiplink desktop_v"
href={"#" + focus_id}
onClick={ev => {
document.getElementById(focus_id).focus();
document.getElementById(focus_id)?.focus();
ev.preventDefault();
}}>
{children}
Expand Down Expand Up @@ -86,6 +88,8 @@ const Shell = () => {
if (!ready)
return null;

cockpit.assert(current_machine && current_manifest_item);

const title_parts = [];
if (current_manifest_item.label)
title_parts.push(current_manifest_item.label);
Expand All @@ -112,7 +116,7 @@ const Shell = () => {
style={
{
'--ct-color-host-accent': (current_machine.address == "localhost" ? undefined : current_machine.color)
}
} as React.CSSProperties
}>

<SkipLink focus_id="content">{_("Skip to content")}</SkipLink>
Expand Down Expand Up @@ -155,6 +159,10 @@ const Shell = () => {
</div>);
};

interface ShellWindow extends Window {
features?: object;
}

function init() {
cockpit.translate();

Expand All @@ -165,17 +173,17 @@ function init() {
window.name = "cockpit1";

/* Tell the pages about our features. */
window.features = {
(window as ShellWindow).features = {
navbar_is_for_current_machine: true
};

function follow(arg) {
/* A promise of some sort */
if (arguments.length == 1 && typeof arg.then == "function") {
arg.then(function() { console.log.apply(console, arguments) },
function() { console.error.apply(console, arguments) });
arg.then(function(...args) { console.log(...args) },
function(...args) { console.error(...args) });
if (typeof arg.stream == "function")
arg.stream(function() { console.log.apply(console, arguments) });
arg.stream(function(...args) { console.log(...args) });
}
}

Expand All @@ -190,7 +198,7 @@ function init() {
}
});

const root = createRoot(document.getElementById("shell"));
const root = createRoot(document.getElementById("shell")!);
root.render(<WithDialogs><Shell /></WithDialogs>);
}

Expand Down
25 changes: 15 additions & 10 deletions pkg/shell/superuser.jsx → pkg/shell/superuser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* along with Cockpit; If not, see <https://www.gnu.org/licenses/>.
*/

// @cockpit-ts-relaxed

import cockpit from "cockpit";
import React, { useState } from "react";
import { useObject, useInit, useEvent } from "hooks";
Expand Down Expand Up @@ -48,14 +50,14 @@ const UnlockDialog = ({ proxy, host }) => {
const D = useDialogs();
useInit(init, [proxy, host]);

const [methods, setMethods] = useState(null);
const [method, setMethod] = useState(false);
const [methods, setMethods] = useState<string[] | null>(null);
const [method, setMethod] = useState<string | false>(false);
const [busy, setBusy] = useState(false);
const [cancel, setCancel] = useState(() => D.close);
const [prompt, setPrompt] = useState(null);
const [message, setMessage] = useState(null);
const [prompt, setPrompt] = useState<{ message: string, prompt: string, echo: boolean } | null>(null);
const [message, setMessage] = useState<string | null>(null);
const [error, setError] = useState(null);
const [errorVariant, setErrorVariant] = useState(null);
const [errorVariant, setErrorVariant] = useState<"danger" | "warning" | null>(null);
const [value, setValue] = useState("");

function start(method) {
Expand All @@ -67,7 +69,7 @@ const UnlockDialog = ({ proxy, host }) => {

let did_prompt = false;

const onprompt = (event, message, prompt, def, echo, error) => {
const onprompt = (_event, message, prompt, def, echo, error) => {
setBusy(false);
setPrompt({
message: sudo_polish(message),
Expand Down Expand Up @@ -134,7 +136,7 @@ const UnlockDialog = ({ proxy, host }) => {
const validated = errorVariant == "danger" ? "error" : errorVariant;

let title = null;
let title_icon = null;
let title_icon: null | "danger" = null;
let body = null;
let footer = null;

Expand Down Expand Up @@ -230,7 +232,7 @@ const UnlockDialog = ({ proxy, host }) => {
variant="medium"
onClose={cancel}
title={title}
titleIconVariant={title_icon}
titleIconVariant={title_icon || undefined}
footer={footer}>
{body}
</Modal>
Expand Down Expand Up @@ -283,7 +285,7 @@ const LockDialog = ({ proxy, host }) => {
);
};

const SuperuserDialogs = ({ superuser_proxy, host, create_trigger }) => {
const SuperuserDialogs = ({ superuser_proxy, host = undefined, create_trigger }) => {
const D = useDialogs();
useEvent(superuser_proxy, "changed",
() => {
Expand Down Expand Up @@ -338,7 +340,10 @@ export const SuperuserIndicator = ({ proxy, host }) => {
};

export const SuperuserButton = () => {
const proxy = useObject(() => cockpit.dbus(null, { bus: "internal" }).proxy("cockpit.Superuser", "/superuser"));
const proxy = useObject(
() => cockpit.dbus(null, { bus: "internal" }).proxy("cockpit.Superuser", "/superuser"),
null,
[]);

const create_trigger = (unlocked, onclick) =>
<Button onClick={onclick}>
Expand Down
Loading

0 comments on commit ac58a25

Please sign in to comment.