Skip to content

Commit e53c2db

Browse files
committed
Move to PatternFly Elements and lit
PFE uses lit, so it makes sense to just use that for the main application as well. Web components are pretty much React built into the web platform, and lit adds some convenience around that. This is mostly a demo -- for real Cockpit pages, PF Elements is still missing too many components. Install query-selector-shadow-dom to enable testlib's shiny new support for traversing selectors through shadow DOMs from cockpit-project/cockpit#21233
1 parent 880094d commit e53c2db

File tree

10 files changed

+48
-71
lines changed

10 files changed

+48
-71
lines changed

.eslintrc.json

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
"browser": true,
55
"es6": true
66
},
7-
"extends": ["eslint:recommended", "standard", "standard-jsx", "standard-react"],
7+
"extends": ["eslint:recommended", "standard"],
88
"parserOptions": {
99
"ecmaVersion": "2022",
1010
"sourceType": "module"
1111
},
12-
"plugins": ["react", "react-hooks"],
1312
"rules": {
1413
"indent": ["error", 4,
1514
{
@@ -22,23 +21,15 @@
2221
"no-var": "error",
2322
"lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
2423
"prefer-promise-reject-errors": ["error", { "allowEmptyReject": true }],
25-
"react/jsx-indent": ["error", 4],
2624
"semi": ["error", "always", { "omitLastInOneLineBlock": true }],
2725

28-
"react-hooks/rules-of-hooks": "error",
29-
"react-hooks/exhaustive-deps": "error",
30-
3126
"camelcase": "off",
3227
"comma-dangle": "off",
3328
"curly": "off",
3429
"jsx-quotes": "off",
3530
"key-spacing": "off",
3631
"no-console": "off",
3732
"quotes": "off",
38-
"react/jsx-curly-spacing": "off",
39-
"react/jsx-indent-props": "off",
40-
"react/jsx-no-useless-fragment": "error",
41-
"react/prop-types": "off",
4233
"space-before-function-paren": "off",
4334
"standard/no-callback-literal": "off"
4435
},

Makefile

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ devel-uninstall:
114114
print-version:
115115
@echo "$(VERSION)"
116116

117+
# required for running integration tests
118+
TEST_NPMS = \
119+
node_modules/query-selector-shadow-dom \
120+
$(NULL)
121+
122+
117123
dist: $(TARFILE)
118124
@ls -1 $(TARFILE)
119125

@@ -125,8 +131,8 @@ $(TARFILE): export NODE_ENV=production
125131
$(TARFILE): $(DIST_TEST) $(SPEC)
126132
if type appstream-util >/dev/null 2>&1; then appstream-util validate-relax --nonet *.metainfo.xml; fi
127133
tar --xz $(TAR_ARGS) -cf $(TARFILE) --transform 's,^,$(RPM_NAME)/,' \
128-
--exclude packaging/$(SPEC).in --exclude node_modules \
129-
$$(git ls-files) $(COCKPIT_REPO_FILES) $(NODE_MODULES_TEST) $(SPEC) dist/
134+
--exclude packaging/$(SPEC).in \
135+
$$(git ls-files) $(COCKPIT_REPO_FILES) $(NODE_MODULES_TEST) $(SPEC) $(TEST_NPMS) dist/
130136

131137
$(NODE_CACHE): $(NODE_MODULES_TEST)
132138
tar --xz $(TAR_ARGS) -cf $@ node_modules

package.json

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
"stylelint:fix": "stylelint --fix src/*{.css,scss}"
1919
},
2020
"devDependencies": {
21-
"@types/react": "18.3.12",
22-
"@types/react-dom": "18.3.1",
2321
"@typescript-eslint/eslint-plugin": "8.13.0",
2422
"argparse": "2.0.1",
2523
"esbuild": "0.24.0",
@@ -30,16 +28,14 @@
3028
"eslint": "8.57.1",
3129
"eslint-config-standard": "17.1.0",
3230
"eslint-config-standard-jsx": "11.0.0",
33-
"eslint-config-standard-react": "13.0.0",
3431
"eslint-plugin-import": "2.31.0",
3532
"eslint-plugin-node": "11.1.0",
3633
"eslint-plugin-promise": "6.6.0",
37-
"eslint-plugin-react": "7.37.2",
38-
"eslint-plugin-react-hooks": "4.6.2",
3934
"gettext-parser": "8.0.0",
4035
"glob": "11.0.0",
4136
"htmlparser": "1.7.7",
4237
"jed": "1.1.1",
38+
"query-selector-shadow-dom": "1.0.1",
4339
"qunit": "2.22.0",
4440
"sass": "1.80.3",
4541
"stylelint": "16.10.0",
@@ -50,11 +46,7 @@
5046
"typescript": "5.6.3"
5147
},
5248
"dependencies": {
53-
"@patternfly/patternfly": "5.4.2",
54-
"@patternfly/react-core": "5.4.8",
55-
"@patternfly/react-icons": "5.4.2",
56-
"@patternfly/react-styles": "5.4.1",
57-
"react": "18.3.1",
58-
"react-dom": "18.3.1"
49+
"@patternfly/elements": "4.0.2",
50+
"lit": "3.2.1"
5951
}
6052
}

packaging/cockpit-starter-kit.spec.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ appstream-util validate-relax --nonet %{buildroot}/%{_datadir}/metainfo/*
5757

5858
%files
5959
%doc README.md
60-
%license LICENSE dist/index.js.LEGAL.txt dist/index.css.LEGAL.txt
60+
%license LICENSE dist/index.js.LEGAL.txt
6161
%{_datadir}/cockpit/*
6262
%{_datadir}/metainfo/*
6363

src/app.scss

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/app.tsx

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of Cockpit.
33
*
4-
* Copyright (C) 2017 Red Hat, Inc.
4+
* Copyright (C) 2024 Red Hat, Inc.
55
*
66
* Cockpit is free software; you can redistribute it and/or modify it
77
* under the terms of the GNU Lesser General Public License as published by
@@ -17,32 +17,36 @@
1717
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919

20-
import React, { useEffect, useState } from 'react';
21-
import { Alert } from "@patternfly/react-core/dist/esm/components/Alert/index.js";
22-
import { Card, CardBody, CardTitle } from "@patternfly/react-core/dist/esm/components/Card/index.js";
20+
import { css, html, LitElement } from 'lit';
21+
import { customElement, state } from 'lit/decorators.js';
22+
23+
import '@patternfly/elements/pf-card/pf-card.js';
2324

2425
import cockpit from 'cockpit';
2526

2627
const _ = cockpit.gettext;
2728

28-
export const Application = () => {
29-
const [hostname, setHostname] = useState(_("Unknown"));
29+
@customElement('ct-application')
30+
export class Application extends LitElement {
31+
@state() private accessor hostname = _("Unknown");
32+
33+
static readonly styles = css`
34+
.running-on {
35+
color: green;
36+
}
37+
`;
3038

31-
useEffect(() => {
39+
connectedCallback() {
40+
super.connectedCallback();
3241
const hostname = cockpit.file('/etc/hostname');
33-
hostname.watch(content => setHostname(content?.trim() ?? ""));
34-
return hostname.close;
35-
}, []);
36-
37-
return (
38-
<Card>
39-
<CardTitle>Starter Kit</CardTitle>
40-
<CardBody>
41-
<Alert
42-
variant="info"
43-
title={ cockpit.format(_("Running on $0"), hostname) }
44-
/>
45-
</CardBody>
46-
</Card>
47-
);
48-
};
42+
hostname.watch(content => { this.hostname = content?.trim() ?? "" });
43+
}
44+
45+
render() {
46+
return html`
47+
<pf-card>
48+
<h1 slot="header">Starter Kit</h1>
49+
<p class="running-on">${cockpit.format(_("Running on $0"), this.hostname)}</p>
50+
</pf-card>`;
51+
}
52+
}

src/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@
2929
</head>
3030

3131
<body>
32-
<div id="app"></div>
32+
<ct-application />
3333
</body>
3434
</html>

src/index.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of Cockpit.
33
*
4-
* Copyright (C) 2017 Red Hat, Inc.
4+
* Copyright (C) 2024 Red Hat, Inc.
55
*
66
* Cockpit is free software; you can redistribute it and/or modify it
77
* under the terms of the GNU Lesser General Public License as published by
@@ -17,16 +17,6 @@
1717
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
1818
*/
1919

20-
import React from 'react';
21-
import { createRoot } from 'react-dom/client';
20+
// import "cockpit-dark-theme"; // doesn't work for PFE
2221

23-
import "cockpit-dark-theme";
24-
25-
import { Application } from './app.jsx';
26-
27-
import "patternfly/patternfly-5-cockpit.scss";
28-
import './app.scss';
29-
30-
document.addEventListener("DOMContentLoaded", () => {
31-
createRoot(document.getElementById("app")!).render(<Application />);
32-
});
22+
import './app.jsx';

test/check-application

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ class TestApplication(testlib.MachineCase):
1818

1919
self.login_and_go("/starter-kit")
2020
# verify expected heading
21-
b.wait_text(".pf-v5-c-card__title", "Starter Kit")
21+
b.wait_text("pf-card [slot='header']", "Starter Kit")
2222

2323
# verify expected host name
2424
hostname = m.execute("cat /etc/hostname").strip()
25-
b.wait_in_text(".pf-v5-c-alert__title", "Running on " + hostname)
25+
b.wait_in_text("pf-card .running-on", "Running on " + hostname)
2626

2727
# change current hostname
2828
self.write_file("/etc/hostname", "new-" + hostname)
2929
# verify new hostname name
30-
b.wait_in_text(".pf-v5-c-alert__title", "Running on new-" + hostname)
30+
b.wait_in_text("pf-card .running-on", "Running on new-" + hostname)
3131

3232
# change language to German
3333
b.switch_to_top()
@@ -46,7 +46,7 @@ class TestApplication(testlib.MachineCase):
4646
b.go("/starter-kit")
4747
b.enter_page("/starter-kit")
4848
# page label (from js) should be translated
49-
b.wait_in_text(".pf-v5-c-alert__title", "Läuft auf")
49+
b.wait_in_text("pf-card .running-on", "Läuft auf")
5050

5151

5252
if __name__ == '__main__':

tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
"allowJs": true,
44
"checkJs": true,
55
"exactOptionalPropertyTypes": true,
6-
"jsx": "react",
76
"lib": [
87
"dom",
98
"es2020"

0 commit comments

Comments
 (0)