From e13c9d1bf37baa9e5599a97a2e6dc42a4dfc39ae Mon Sep 17 00:00:00 2001 From: Katerina Koukiou Date: Mon, 8 Nov 2021 10:40:12 +0100 Subject: [PATCH] Fetch pkg/lib automatically from cockpit instead of keeping a local copy * remove mustache module as it's not used anymore. * port alert component to react-core as the current code creates a broken UI --- .gitignore | 1 + Makefile | 8 + package.json | 2 +- src/index.js | 4 +- src/lib/_fonts.scss | 36 -- src/lib/patternfly-4-cockpit.scss | 14 - src/lib/patternfly-4-overrides.scss | 43 -- src/pkg/lib/cockpit-components-listing.jsx | 363 ------------- src/pkg/lib/console.css | 59 --- src/pkg/lib/journal.css | 134 ----- src/pkg/lib/journal.js | 576 --------------------- src/pkg/lib/journal_day_header.mustache | 1 - src/pkg/lib/journal_line.mustache | 19 - src/pkg/lib/journal_reboot.mustache | 5 - src/pkg/lib/listing.less | 502 ------------------ src/pkg/lib/page.css | 235 --------- src/pkg/lib/table.css | 146 ------ src/pkg/lib/term.css | 522 ------------------- src/pkg/lib/variables.less | 22 - src/player.jsx | 24 +- src/recordings.jsx | 6 +- webpack.config.js | 2 +- 22 files changed, 28 insertions(+), 2696 deletions(-) delete mode 100644 src/lib/_fonts.scss delete mode 100644 src/lib/patternfly-4-cockpit.scss delete mode 100644 src/lib/patternfly-4-overrides.scss delete mode 100644 src/pkg/lib/cockpit-components-listing.jsx delete mode 100644 src/pkg/lib/console.css delete mode 100644 src/pkg/lib/journal.css delete mode 100644 src/pkg/lib/journal.js delete mode 100644 src/pkg/lib/journal_day_header.mustache delete mode 100644 src/pkg/lib/journal_line.mustache delete mode 100644 src/pkg/lib/journal_reboot.mustache delete mode 100644 src/pkg/lib/listing.less delete mode 100644 src/pkg/lib/page.css delete mode 100644 src/pkg/lib/table.css delete mode 100644 src/pkg/lib/term.css delete mode 100644 src/pkg/lib/variables.less diff --git a/.gitignore b/.gitignore index 927248a..62c6bb8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.rpm node_modules/ dist/ +lib/ /*.spec /.vagrant package-lock.json diff --git a/Makefile b/Makefile index 77a9846..4d64e47 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,8 @@ VM_IMAGE=$(CURDIR)/test/images/$(TEST_OS) NODE_MODULES_TEST=package-lock.json # one example file in dist/ from webpack to check if that already ran WEBPACK_TEST=dist/index.html +# one example file in src/lib to check if it was already checked out +LIB_TEST=src/lib/cockpit-po-plugin.js all: $(WEBPACK_TEST) @@ -160,6 +162,12 @@ test/common: git checkout --force FETCH_HEAD -- test/common git reset test/common +# checkout Cockpit's PF/React/build library; again this has no API stability guarantee, so check out a stable tag +$(LIB_TEST): + git clone -b 256 --depth=1 https://github.com/cockpit-project/cockpit.git tmp/cockpit + mv tmp/cockpit/pkg/lib src/ + rm -rf tmp/cockpit + $(NODE_MODULES_TEST): package.json # if it exists already, npm install won't update it; force that so that we always get up-to-date packages rm -f package-lock.json diff --git a/package.json b/package.json index bd0b65b..4c467b3 100644 --- a/package.json +++ b/package.json @@ -51,10 +51,10 @@ "@patternfly/react-table": "^4.8.6", "comment-json": "^1.1.3", "core-js": "3.6.5", + "date-fns": "2.25.0", "ini": "^1.3.5", "jquery": "3.5.1", "moment": "2.27.0", - "mustache": "2.3.0", "raw-loader": "^0.5.1", "react": "16.13.1", "react-dom": "16.13.1", diff --git a/src/index.js b/src/index.js index 85fa0c4..b718ab6 100644 --- a/src/index.js +++ b/src/index.js @@ -17,7 +17,7 @@ * along with Cockpit; If not, see . */ -import "./lib/patternfly-4-cockpit.scss"; +import "./lib/patternfly/patternfly-4-cockpit.scss"; import "core-js/stable"; @@ -31,7 +31,7 @@ import { Application } from './app.jsx'; * out of the dist/index.js and since it will maintain the order of the imported CSS, * the overrides will be correctly in the end of our stylesheet. */ -import "./lib/patternfly-4-overrides.scss"; +import "./lib/patternfly/patternfly-4-overrides.scss"; document.addEventListener("DOMContentLoaded", function () { ReactDOM.render(React.createElement(Application, {}), document.getElementById('app')); diff --git a/src/lib/_fonts.scss b/src/lib/_fonts.scss deleted file mode 100644 index b3cb18a..0000000 --- a/src/lib/_fonts.scss +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Keep in sync with https://github.com/cockpit-project/cockpit/tree/master/src/base1/_fonts.scss - */ - -@mixin printRedHatFont( -$weightValue: 400, -$weightName: "Regular", -$familyName: "RedHatText", -$style: "normal", -$relative: true -) { - $filePath: "../../static/fonts" + "/" + $familyName + "-" + $weightName; - @font-face { - font-family: $familyName; - src: url('#{$filePath}.woff2') format('woff2'); - font-style: #{$style}; - font-weight: $weightValue; - text-rendering: optimizeLegibility; - } -} - -@include printRedHatFont(700, "Bold", $familyName: "RedHatDisplay"); -@include printRedHatFont(700, "BoldItalic", $style: "italic", $familyName: "RedHatDisplay"); -@include printRedHatFont(300, "Black", $familyName: "RedHatDisplay"); -@include printRedHatFont(300, "BlackItalic", $style: "italic", $familyName: "RedHatDisplay"); -@include printRedHatFont(300, "Italic", $style: "italic", $familyName: "RedHatDisplay"); -@include printRedHatFont(400, "Medium", $familyName: "RedHatDisplay"); -@include printRedHatFont(400, "MediumItalic", $style: "italic", $familyName: "RedHatDisplay"); -@include printRedHatFont(300, "Regular", $familyName: "RedHatDisplay"); - -@include printRedHatFont(300, "Bold"); -@include printRedHatFont(300, "BoldItalic", $style: "italic"); -@include printRedHatFont(300, "Italic"); -@include printRedHatFont(700, "Medium"); -@include printRedHatFont(700, "MediumItalic", $style: "italic"); -@include printRedHatFont(400, "Regular"); diff --git a/src/lib/patternfly-4-cockpit.scss b/src/lib/patternfly-4-cockpit.scss deleted file mode 100644 index 40da84e..0000000 --- a/src/lib/patternfly-4-cockpit.scss +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Keep in sync with https://github.com/cockpit-project/cockpit/tree/master/src/base1/patternfly-4-cockpit.scss - */ - -/* Set fake font and icon path variables - we are going to indentify these through - * string replacement and remove the relevant font-face declarations - */ -$pf-global--font-path: 'patternfly-fonts-fake-path'; -$pf-global--fonticon-path: 'patternfly-icons-fake-path'; -$pf-global--disable-fontawesome: true !default; // Disable Font Awesome 5 Free -@import '@patternfly/patternfly/patternfly-base.scss'; - -/* Import our own fonts since the PF4 font-face rules are filtered out with patternfly.sed */ -@import "./fonts"; diff --git a/src/lib/patternfly-4-overrides.scss b/src/lib/patternfly-4-overrides.scss deleted file mode 100644 index a02cb95..0000000 --- a/src/lib/patternfly-4-overrides.scss +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Keep in sync with https://github.com/cockpit-project/cockpit/tree/master/pkg/lib/patternfly-4-overrides.scss - */ - -/*** PF4 overrides ***/ - -/* WORKAROUND: Override word-break bug */ -/* See: https://github.com/patternfly/patternfly-next/issues/2325 */ -.pf-c-table td { - word-break: normal; - overflow-wrap: break-word; -} - -/* WORKAROUND: Dropdown (PF4): Caret is not properly aligned bug */ -/* See: https://github.com/patternfly/patternfly/issues/2715 */ -/* Align the icons inside of all dropdown toggles. */ -/* Part 1 of 2 */ -.pf-c-dropdown__toggle-button { - display: flex; - align-items: center; -} - -/* Make split button dropdowns the same height as their sibling. */ -/* Part 2 of 2 */ -.pf-m-split-button { - align-items: stretch; -} - -/* WORKAROUND: Navigation problems with Tertiary Nav widget on mobile */ -/* See: https://github.com/patternfly/patternfly-design/issues/840 */ -/* Helper mod to wrap pf-c-nav__tertiary */ -.ct-m-nav__tertiary-wrap { - flex-wrap: wrap; - - .pf-c-nav__scroll-button { - display: none; - } -} - -/* Helper mod to center pf-c-nav__tertiary when it wraps */ -.ct-m-nav__tertiary-center { - justify-content: center; -} diff --git a/src/pkg/lib/cockpit-components-listing.jsx b/src/pkg/lib/cockpit-components-listing.jsx deleted file mode 100644 index 19eea66..0000000 --- a/src/pkg/lib/cockpit-components-listing.jsx +++ /dev/null @@ -1,363 +0,0 @@ -/* - * This file is part of Cockpit. - * - * Copyright (C) 2016 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 . - */ - -import PropTypes from 'prop-types'; -import React from 'react'; - -/* entry for an alert in the listing, can be expanded (with details) or standard - * rowId optional: an identifier for the row which will be set as "data-row-id" attribute on the - * columns list of columns to show in the header - * columns to show, can be a string, react component or object with { name: 'name', 'header': false } - * 'header' (or if simple string) defaults to false - * in case 'header' is true, is used for the entries, otherwise - * tabRenderers optional: list of tab renderers for inline expansion, array of objects with - * - name tab name (has to be unique in the entry, used as react key) - * - renderer react component - * - data render data passed to the tab renderer - * - presence 'always', 'onlyActive', 'loadOnDemand', default: 'loadOnDemand' - * - 'always' once a row is expanded, this tab is always rendered, but invisible if not active - * - 'onlyActive' the tab is only rendered when active - * - 'loadOnDemand' the tab is first rendered when it becomes active, then follows 'always' behavior - * if tabRenderers isn't set, item can't be expanded inline - * navigateToItem optional: callback triggered when a row is clicked, pattern suggests navigation - * to view expanded item details, if not set, navigation isn't available - * listingDetail optional: text rendered next to action buttons, similar style to the tab headers - * listingActions optional: buttons that are presented as actions for the expanded item - * selectChanged optional: callback will be used when the "selected" state changes - * selected optional: true if the item is selected, can't be true if row has navigation or expansion - * initiallyExpanded optional: the entry will be initially rendered as expanded, but then behaves normally - * expandChanged optional: callback will be used if the row is either expanded or collapsed passing single `isExpanded` boolean argument - */ -export class ListingRow extends React.Component { - constructor(props) { - super(props); - this.state = { - expanded: this.props.initiallyExpanded, // show expanded view if true, otherwise one line compact - activeTab: this.props.initiallyActiveTab ? this.props.initiallyActiveTab : 0, // currently active tab in expanded mode, defaults to first tab - loadedTabs: {}, // which tabs were already loaded - this is important for 'loadOnDemand' setting - // contains tab indices - selected: this.props.selected, // whether the current row is selected - }; - this.handleNavigateClick = this.handleNavigateClick.bind(this); - this.handleExpandClick = this.handleExpandClick.bind(this); - this.handleSelectClick = this.handleSelectClick.bind(this); - this.handleTabClick = this.handleTabClick.bind(this); - } - - handleNavigateClick(e) { - // only consider primary mouse button - if (!e || e.button !== 0) - return; - this.props.navigateToItem(); - } - - handleExpandClick(e) { - // only consider primary mouse button - if (!e || e.button !== 0) - return; - - const willBeExpanded = !this.state.expanded && this.props.tabRenderers.length > 0; - this.setState({ expanded: willBeExpanded }); - - const loadedTabs = {}; - // unload all tabs if not expanded - if (willBeExpanded) { - // see if we should preload some tabs - let tabIdx; - let tabPresence; - for (tabIdx = 0; tabIdx < this.props.tabRenderers.length; tabIdx++) { - if ('presence' in this.props.tabRenderers[tabIdx]) - tabPresence = this.props.tabRenderers[tabIdx].presence; - else - tabPresence = 'default'; - // the active tab is covered by separate logic - if (tabPresence == 'always') - loadedTabs[tabIdx] = true; - } - // ensure the active tab is loaded - loadedTabs[this.state.activeTab] = true; - } - - this.setState({ loadedTabs: loadedTabs }); - - this.props.expandChanged && this.props.expandChanged(willBeExpanded); - - e.stopPropagation(); - e.preventDefault(); - } - - handleSelectClick(e) { - // only consider primary mouse button - if (!e || e.button !== 0) - return; - - const selected = !this.state.selected; - this.setState({ selected: selected }); - - if (this.props.selectChanged) - this.props.selectChanged(selected); - - e.stopPropagation(); - e.preventDefault(); - } - - handleTabClick(tabIdx, e) { - // only consider primary mouse button - if (!e || e.button !== 0) - return; - const prevTab = this.state.activeTab; - let prevTabPresence = 'default'; - const loadedTabs = this.state.loadedTabs; - if (prevTab !== tabIdx) { - // see if we need to unload the previous tab - if ('presence' in this.props.tabRenderers[prevTab]) - prevTabPresence = this.props.tabRenderers[prevTab].presence; - - if (prevTabPresence == 'onlyActive') - delete loadedTabs[prevTab]; - - // ensure the new tab is loaded and update state - loadedTabs[tabIdx] = true; - this.setState({ loadedTabs: loadedTabs, activeTab: tabIdx }); - } - e.stopPropagation(); - e.preventDefault(); - } - - render() { - const self = this; - // only enable navigation if a function is provided and the row isn't expanded (prevent accidental navigation) - const allowNavigate = !!this.props.navigateToItem && !this.state.expanded; - - const headerEntries = this.props.columns.map((itm, index) => { - if (typeof itm === 'string' || typeof itm === 'number' || itm === null || itm === undefined || itm instanceof String || React.isValidElement(itm)) - return ({itm}); - else if ('header' in itm && itm.header) - return ({itm.name}); - else if ('tight' in itm && itm.tight) - return ({itm.name || itm.element}); - else - return ({itm.name}); - }); - - const allowExpand = (this.props.tabRenderers.length > 0); - let expandToggle; - if (allowExpand) { - expandToggle = ; - } else { - expandToggle = ; - } - - const listingItemClasses = ["listing-ct-item"]; - if (!allowNavigate) - listingItemClasses.push("listing-ct-nonavigate"); - if (!allowExpand) - listingItemClasses.push("listing-ct-noexpand"); - - const allowSelect = !(allowNavigate || allowExpand) && (this.state.selected !== undefined); - let clickHandler; - if (allowSelect) { - clickHandler = this.handleSelectClick; - if (this.state.selected) - listingItemClasses.push("listing-ct-selected"); - } else { - if (allowNavigate) - clickHandler = this.handleNavigateClick; - else - clickHandler = this.handleExpandClick; - } - - const listingItem = ( - - {expandToggle} - {headerEntries} - - ); - - if (this.state.expanded) { - const links = this.props.tabRenderers.map((itm, idx) => { - return ( -
  • - {itm.name} -
  • - ); - }); - const tabs = []; - let tabIdx; - let Renderer; - let rendererData; - let row; - for (tabIdx = 0; tabIdx < this.props.tabRenderers.length; tabIdx++) { - Renderer = this.props.tabRenderers[tabIdx].renderer; - rendererData = this.props.tabRenderers[tabIdx].data; - if (tabIdx !== this.state.activeTab && !(tabIdx in this.state.loadedTabs)) - continue; - row =