Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shell: Make it all reacty #21012

Merged
merged 1 commit into from
Oct 10, 2024

Conversation

mvollmer
Copy link
Member

@mvollmer mvollmer commented Sep 16, 2024

Notes to reviewers:

  • This is bug-compatible with the old shell. Let's concentrate on the code structure here and not on fixing bugs.
  • This is by far not all the cleanups that can be done, it's just the first (big) step to untangle the mess. Let's avoid scope creep and concentrate on making this here solid.
  • Start with shell.jsx and state.jsx.
  • frames.jsx is a bit ugly, but should be well isolated from the rest. Also check shell: Use the "load" event instead of polling to catch ready frames #21061 for a followup that improves it significantly.
  • The rest should be straighforward. :-)

Ideas for followups:

  • The "jump" operation has a quirk re omitting the hash that we could remove. A omitted hash either means "empty hash in the final URL" or "same hash as previously", depending on whether the jump operation actually changes which frame is current or not. This can be avoided by changing all callers of "jump" to pass "/" as the hash when they want to have a empty one. I think it's mostly tests that exploit the quirk.
  • Remove the hacks and botches from the old React components, which is hopefully now possible.
  • Replace HostModalState with useDialogs.
  • Stop polling frames for readiness (which is a ill-defined thing anyway), and just keep them hidden until "onload" has fired. That also fixes the dark-mode flicker on Firefox. shell: Use the "load" event instead of polling to catch ready frames #21061
  • Add current_manifest to ShellState and use that in TopNav to get at the parent field. (TopNav uses the full path to look up the manifest itself, but should really only use the first component.) shell: Take docs from the correct manifest item #21072
  • Convert util.jsx into TypeScript, maybe clean it up / split it up at the same time.

pkg/newshell/base_index.js Fixed Show fixed Hide fixed
pkg/newshell/base_index.js Fixed Show fixed Hide fixed
pkg/newshell/hosts_dialog.jsx Fixed Show fixed Hide fixed
pkg/newshell/hosts_dialog.jsx Fixed Show fixed Hide fixed
pkg/newshell/shell.jsx Fixed Show fixed Hide fixed
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
@garrett
Copy link
Member

garrett commented Sep 16, 2024

The host switcher mockups are so old, they used PF3 and had the dashboard:

unified-sidebar-host-switcher-few-isolated
unified-sidebar-host-switcher-many-isolated

(And the dashboard was where we edited machines prior.)

For PF4, if we're doing a 1:1 port, we should consider doing popovers and having a modal show up when you add or edit without dismissing the popover. (It will look different from these mockups for sure.)

@mvollmer mvollmer added the no-test For doc/workflow changes, or experiments which don't need a full CI run, label Sep 17, 2024
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
@mvollmer mvollmer force-pushed the shell-never-go-full-react branch 3 times, most recently from f845f71 to 08db4e9 Compare September 18, 2024 12:56
@@ -71,6 +71,8 @@ class TestPages(testlib.MachineCase):
m = self.machine
b = self.browser

m.upload(["/home/mvo/work/cockpit/dist/shell"], "/usr/share/cockpit")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^_^

@mvollmer mvollmer force-pushed the shell-never-go-full-react branch 2 times, most recently from fd4891c to 566ddbc Compare September 19, 2024 11:33
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
hosts_sel.appendChild(this.el);
}

componentWillUnmount() {
const hosts_sel = document.getElementById("nav-hosts");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like an easy split off PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it's only necessary here because '#nav-hosts' doesn't exist yet (in this PR only) when the file is loaded. Also, I hope we can get rid of this DOM manipulation completely in this PR. Eventually.

@@ -307,7 +306,6 @@ export class CockpitHosts extends React.Component {
item_render={render}
sorting={(a, b) => true}
filtering={this.filterHosts}
current={label}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it seems CockpitNav does not use current at all, can we then split this removal off?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that was a mistake unfortunately. It uses current to notice when navigation has happened, and then resets the search field.

This might be a good example of hard to understand magic that we want to get rid of. There might be a signal on the ShellState that announces navigation, or we might have a navigation_counter, or something more obvious.

@mvollmer mvollmer force-pushed the shell-never-go-full-react branch 2 times, most recently from b5f4113 to 39ba1c5 Compare September 20, 2024 08:24
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
pkg/shell/state.jsx Fixed Show fixed Hide fixed
pkg/shell/state.jsx Fixed Show fixed Hide fixed
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
pkg/shell/state.jsx Fixed Show fixed Hide fixed
@mvollmer mvollmer force-pushed the shell-never-go-full-react branch 2 times, most recently from 2d3f8aa to 7819c2a Compare September 23, 2024 14:59
pkg/shell/state.jsx Fixed Show fixed Hide fixed
@mvollmer mvollmer force-pushed the shell-never-go-full-react branch 3 times, most recently from 551ed93 to f13e171 Compare September 24, 2024 10:21
@mvollmer
Copy link
Member Author

mvollmer commented Oct 2, 2024

Green, except for the revdeps. Those should go green with #21067.

@mvollmer mvollmer added the blocked Don't land until something else happens first (see task list) label Oct 3, 2024
@mvollmer mvollmer marked this pull request as ready for review October 3, 2024 07:26
pkg/shell/shell.jsx Fixed Show fixed Hide fixed
@mvollmer mvollmer force-pushed the shell-never-go-full-react branch 3 times, most recently from 8894552 to 17bd0ad Compare October 8, 2024 07:31
@mvollmer mvollmer removed the blocked Don't land until something else happens first (see task list) label Oct 8, 2024
pkg/shell/state.jsx Outdated Show resolved Hide resolved
Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for starting to untangle this mess! It's a lot easier to follow now.

I don't want to block this much -- I have two comments which I'd consider a blocker (bringing back the "yaya ssh dangerous" warning and the ensure_frame() comment spelling), but both of them should be trivial. The rest is just thinking aloud or follow-up material, and thus optional.

pkg/shell/util.jsx Show resolved Hide resolved
pkg/shell/util.jsx Outdated Show resolved Hide resolved
pkg/shell/active-pages-modal.jsx Outdated Show resolved Hide resolved
pkg/shell/frames.jsx Show resolved Hide resolved
pkg/shell/hosts_dialog.jsx Outdated Show resolved Hide resolved
pkg/shell/hosts_dialog.jsx Outdated Show resolved Hide resolved
Comment on lines +94 to +97
.catch(e => {
if (e.message.indexOf("GetUInt not available") === -1)
console.warn(e.message);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up: This was introduced so long ago that we can just count on it now.

pkg/shell/state.jsx Outdated Show resolved Hide resolved
martinpitt
martinpitt previously approved these changes Oct 10, 2024
Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cheers! 🚀 from my POV, let's do the rest in all these follow-ups.

And rewrite much of the state handling to make it easier to
understand.

Specifically, the old Index and MachineIndex classes and their
complicated interactions have been replaced with a hopefully much more
straightforward ShellState class.

However, the existing React components such as CockpitHosts and TopNav
have not been significantly touched.

The API for launching the HostModal dialogs has been changed to make
it more suitable for a later rewrite with Dialogs.run() ala
pkg/lib/cockpit-connect-ssh.
@mvollmer
Copy link
Member Author

Cheers! 🚀 from my POV, let's do the rest in all these follow-ups.

Thanks for the review!

I have decided to include #21074 here, after all. It only affects frames.jsx.

Copy link
Member

@martinpitt martinpitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/me reacts with 👍

frame,
active,
selected: active,
displayName: frame.host === "localhost" ? "/" + frame.path : frame.host + ":/" + frame.path,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

Comment on lines +113 to +116
if (machine.restarting) {
title = _("The machine is rebooting");
message = "";
} else if (connecting) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 4 added lines are not executed by any test.

if (frame.ready && iframe.getAttribute("data-ready") == null)
iframe.setAttribute("data-ready", "1");
else if (!frame.ready && iframe.getAttribute("data-ready"))
iframe.removeAttribute("data-ready");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

if (frame.loaded && iframe.getAttribute("data-loaded") == null)
iframe.setAttribute("data-loaded", "1");
else if (!frame.loaded && iframe.getAttribute("data-loaded"))
iframe.removeAttribute("data-loaded");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

Comment on lines +174 to +175
style === "auto") ||
style === "dark") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 added lines are not executed by any test.

Comment on lines +153 to +156
self.search = function(prop, value) {
for (const x in self.items) {
if (self.items[x][prop] === value)
return self.items[x];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 4 added lines are not executed by any test.

Comment on lines +188 to +192
function component_checksum(machine, path) {
const parts = path.split("/");
const pkg = parts[0];
if (machine.manifests && machine.manifests[pkg] && machine.manifests[pkg][".checksum"])
return "$" + machine.manifests[pkg][".checksum"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 5 added lines are not executed by any test.

export function compute_frame_url(machine, path) {
let base, checksum;
if (machine.manifests && machine.manifests[".checksum"])
checksum = "$" + machine.manifests[".checksum"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

Comment on lines +202 to +204
if (checksum && checksum == component_checksum(machine, path)) {
if (machine.connection_string === "localhost")
base = "..";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 3 added lines are not executed by any test.

if (machine.connection_string === "localhost")
base = "..";
else
base = "../../" + checksum;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

@mvollmer mvollmer merged commit 7cd6428 into cockpit-project:main Oct 10, 2024
86 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants