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
This commit is contained in:
Katerina Koukiou 2021-11-08 10:40:12 +01:00 committed by Justin Stephenson
parent e49176b966
commit e13c9d1bf3
22 changed files with 28 additions and 2696 deletions

1
.gitignore vendored
View file

@ -4,6 +4,7 @@
*.rpm
node_modules/
dist/
lib/
/*.spec
/.vagrant
package-lock.json

View file

@ -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

View file

@ -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",

View file

@ -17,7 +17,7 @@
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
*/
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'));

View file

@ -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");

View file

@ -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";

View file

@ -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;
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <tr>
* 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, <th> is used for the entries, otherwise <td>
* 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 (<td key={index}>{itm}</td>);
else if ('header' in itm && itm.header)
return (<th key={index}>{itm.name}</th>);
else if ('tight' in itm && itm.tight)
return (<td key={index} className="listing-ct-actions">{itm.name || itm.element}</td>);
else
return (<td key={index}>{itm.name}</td>);
});
const allowExpand = (this.props.tabRenderers.length > 0);
let expandToggle;
if (allowExpand) {
expandToggle = <td key="expandToggle" className="listing-ct-toggle" onClick={ allowNavigate ? this.handleExpandClick : undefined }><i className="fa fa-fw" /></td>;
} else {
expandToggle = <td key="expandToggle-empty" className="listing-ct-toggle" />;
}
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 = (
<tr
data-row-id={ this.props.rowId }
className={ listingItemClasses.join(' ') }
onClick={clickHandler}
>
{expandToggle}
{headerEntries}
</tr>
);
if (this.state.expanded) {
const links = this.props.tabRenderers.map((itm, idx) => {
return (
<li key={idx} className={ (idx === self.state.activeTab) ? "active" : ""}>
<a href="#" tabIndex="0" onClick={ self.handleTabClick.bind(self, idx) }>{itm.name}</a>
</li>
);
});
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 = <Renderer key={ this.props.tabRenderers[tabIdx].name } hidden={ (tabIdx !== this.state.activeTab) } {...rendererData} />;
if (tabIdx === this.state.activeTab)
tabs.push(<div className="listing-ct-body" key={tabIdx}>{row}</div>);
else
tabs.push(<div className="listing-ct-body" key={tabIdx} hidden>{row}</div>);
}
let listingDetail;
if ('listingDetail' in this.props) {
listingDetail = (
<span className="listing-ct-caption">
{this.props.listingDetail}
</span>
);
}
return (
<tbody className="open">
{listingItem}
<tr className="listing-ct-panel">
<td colSpan={ headerEntries.length + (expandToggle ? 1 : 0) }>
<div className="listing-ct-head">
<div className="listing-ct-actions">
{listingDetail}
{this.props.listingActions}
</div>
<ul className="nav nav-tabs nav-tabs-pf">
{links}
</ul>
</div>
{tabs}
</td>
</tr>
</tbody>
);
} else {
return (
<tbody>
{listingItem}
<tr className="listing-ct-panel" />
</tbody>
);
}
}
}
ListingRow.defaultProps = {
tabRenderers: [],
navigateToItem: null,
};
ListingRow.propTypes = {
rowId: PropTypes.string,
columns: PropTypes.array.isRequired,
tabRenderers: PropTypes.array,
navigateToItem: PropTypes.func,
listingDetail: PropTypes.node,
listingActions: PropTypes.arrayOf(PropTypes.node),
selectChanged: PropTypes.func,
selected: PropTypes.bool,
initiallyExpanded: PropTypes.bool,
expandChanged: PropTypes.func,
initiallyActiveTab: PropTypes.bool
};
/* Implements a PatternFly 'List View' pattern
* https://www.patternfly.org/list-view/
* Properties:
* - title
* - fullWidth optional: set width to 100% of parent, defaults to true
* - emptyCaption header caption to show if list is empty, defaults to "No entries"
* - columnTitles: array of column titles, as strings
* - columnTitleClick: optional callback for clicking on column title (for sorting)
* receives the column index as argument
* - actions: additional listing-wide actions (displayed next to the list's title)
*/
export const Listing = (props) => {
const bodyClasses = ["listing", "listing-ct"];
if (props.fullWidth)
bodyClasses.push("listing-ct-wide");
let headerClasses;
let headerRow;
let selectableRows;
if (!props.children || props.children.length === 0) {
headerClasses = "listing-ct-empty";
headerRow = <tr><td>{props.emptyCaption}</td></tr>;
} else if (props.columnTitles.length) {
// check if any of the children are selectable
selectableRows = false;
props.children.forEach(function(r) {
if (r.props.selected !== undefined)
selectableRows = true;
});
if (selectableRows) {
// now make sure that if one is set, it's available on all items
props.children.forEach(function(r) {
if (r.props.selected === undefined)
r.props.selected = false;
});
}
headerRow = (
<tr>
<th key="empty" className="listing-ct-toggle" />
{ props.columnTitles.map((title, index) => {
let clickHandler = null;
if (props.columnTitleClick)
clickHandler = function() { props.columnTitleClick(index) };
return <th key={index} onClick={clickHandler}>{title}</th>;
}) }
</tr>
);
} else {
headerRow = <tr />;
}
let caption;
if (props.title || (props.actions && props.actions.length > 0))
caption = <caption className="cockpit-caption">{props.title}{props.actions}</caption>;
return (
<table className={ bodyClasses.join(" ") }>
{caption}
<thead className={headerClasses}>
{headerRow}
</thead>
{props.children}
</table>
);
};
Listing.defaultProps = {
title: '',
fullWidth: true,
columnTitles: [],
actions: []
};
Listing.propTypes = {
title: PropTypes.string,
fullWidth: PropTypes.bool,
emptyCaption: PropTypes.string.isRequired,
columnTitles: PropTypes.arrayOf(
PropTypes.oneOfType([
PropTypes.string,
PropTypes.element,
])),
columnTitleClick: PropTypes.func,
actions: PropTypes.arrayOf(PropTypes.node)
};

View file

@ -1,59 +0,0 @@
@import "term.css";
/* Our terminal or logs */
.console-ct {
font-family: Menlo, Monaco, Consolas, monospace;
margin-top: 0;
margin-bottom: 0;
font-size: 10px;
text-align: center;
line-height: normal;
}
@media (min-width: 568px) {
.console-ct {
font-size: 12px;
}
}
.console-ct > pre {
padding: 10px;
text-align: left;
display: block;
font-family: inherit;
font-size: inherit;
width: 48em;
height: 310px;
overflow-y: scroll;
white-space: pre-wrap;
margin: 0 auto;
}
.console-ct > .terminal {
color: #F0F0F0;
text-align: left;
outline: medium none;
background-color: black;
border: 1px solid black;
padding: 10px;
}
.terminal .terminal-cursor {
border: 1px solid #f0f0f0;
}
.terminal:focus .terminal-cursor {
border: none;
animation: blink 1s step-end infinite;
}
@keyframes blink {
from {
color: #000;
background: #f0f0f0;
}
50% {
color: #f0f0f0;
background: #000;
}
}

View file

@ -1,134 +0,0 @@
/*
* This file is part of Cockpit.
*
* Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
*/
.cockpit-log-panel {
border: 0;
}
.cockpit-log-panel .panel-heading {
background-color: #333;
border-color: #333;
color: #fff;
padding-left: 10px;
padding-top: 5px;
padding-bottom: 5px;
height: auto;
}
.cockpit-log-panel .panel-body {
padding: 0;
border-bottom: 1px #ddd solid;
}
.cockpit-log-panel .panel-body .panel-heading {
border-left: 1px #ddd solid;
border-right: 1px #ddd solid;
border-top: 0;
border-bottom: 1px #ddd solid;
background-color: #f5f5f5;
font-weight: bold;
padding-top: 2px;
padding-bottom: 2px;
width: auto;
color: #333;
}
.cockpit-log-panel > .panel-heading {
margin-top: 15px;
}
.cockpit-log-panel .cockpit-logline {
border-left: 1px #ddd solid;
border-right: 1px #ddd solid;
background-color: #f5f5f5;
padding-top: 2px;
padding-bottom: 2px;
padding-left: 10px;
}
.cockpit-logline {
font-family: monospace;
min-width: 310px;
border-bottom: 1px solid #DDD;
border-top: none;
}
.cockpit-logline > .row > div:first-child {
padding-left: 20px;
}
.cockpit-log-panel .cockpit-logline:hover {
background-color: #d4edfa;
}
.cockpit-log-panel > .cockpit-logline:hover {
cursor: pointer;
}
.cockpit-logmsg-reboot {
font-style: italic;
}
.cockpit-log-warning {
display: inline-block;
width: 20px;
vertical-align: middle;
}
.cockpit-log-warning > i {
color: black;
}
.cockpit-log-time {
display: inline-block;
width: 40px;
vertical-align: middle;
}
.cockpit-log-service {
width: 200px;
margin-left: 10px;
}
.cockpit-log-service-container {
display: inline-block;
width: 200px;
margin-left: 10px;
}
.cockpit-log-service-reduced {
width: -moz-calc(100% - 70px);
width: -webkit-calc(100% - 70px);
width: calc(100% - 70px);
}
.cockpit-log-message {
width: -moz-calc(100% - 300px);
width: -webkit-calc(100% - 300px);
width: calc(100% - 300px);
}
.cockpit-log-message, .cockpit-log-service, .cockpit-log-service-reduced {
text-overflow: ellipsis;
overflow: hidden;
display: inline-block;
white-space: nowrap;
vertical-align: middle;
}

View file

@ -1,576 +0,0 @@
/*
* This file is part of Cockpit.
*
* Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
*/
(function () {
"use strict";
var cockpit = require("cockpit");
var Mustache = require("mustache");
var day_header_template = require("raw-loader!journal_day_header.mustache");
var line_template = require("raw-loader!journal_line.mustache");
var reboot_template = require("raw-loader!journal_reboot.mustache");
var _ = cockpit.gettext;
var C_ = cockpit.gettext;
var journal = {};
/**
* journalctl([match, ...], [options])
* @match: any number of journal match strings
* @options: an object containing further options
*
* Load and (by default) stream journal entries as
* json objects. This function returns a jQuery deferred
* object which delivers the various journal entries.
*
* The various @match strings are journalctl matches.
* Zero, one or more can be specified. They must be in
* string format, or arrays of strings.
*
* The optional @options object can contain the following:
* * "host": the host to load journal from
* * "count": number of entries to load and/or pre-stream.
* Default is 10
* * "follow": if set to false just load entries and don't
* stream further journal data. Default is true.
* * "directory": optional directory to load journal files
* * "boot": when set only list entries from this specific
* boot id, or if null then the current boot.
* * "since": if specified list entries since the date/time
* * "until": if specified list entries until the date/time
* * "cursor": a cursor to start listing entries from
* * "after": a cursor to start listing entries after
*
* Returns a jQuery deferred promise. You can call these
* functions on the deferred to handle the responses. Note that
* there are additional non-jQuery methods.
*
* .done(function(entries) { }): Called when done, @entries is
* an array of all journal entries loaded. If .stream()
* has been invoked then @entries will be empty.
* .fail(funciton(ex) { }): called if the operation fails
* .stream(function(entries) { }): called when we receive entries
* entries. Called once per batch of journal @entries,
* whether following or not.
* .stop(): stop following or retrieving entries.
*/
journal.journalctl = function journalctl(/* ... */) {
var matches = [];
var i;
var arg;
var options = { follow: true };
for (i = 0; i < arguments.length; i++) {
arg = arguments[i];
if (typeof arg == "string") {
matches.push(arg);
} else if (typeof arg == "object") {
if (arg instanceof Array) {
matches.push.apply(matches, arg);
} else {
cockpit.extend(options, arg);
break;
}
} else {
console.warn("journal.journalctl called with invalid argument:", arg);
}
}
if (options.count === undefined) {
if (options.follow) options.count = 10;
else options.count = null;
}
var cmd = ["journalctl", "--all", "-q", "--output=json"];
if (!options.count) cmd.push("--no-tail");
else cmd.push("--lines=" + options.count);
if (options.directory) cmd.push("--directory=" + options.directory);
if (options.boot) cmd.push("--boot=" + options.boot);
else if (options.boot !== undefined) cmd.push("--boot");
if (options.since) cmd.push("--since=" + options.since);
if (options.until) cmd.push("--until=" + options.until);
if (options.cursor) cmd.push("--cursor=" + options.cursor);
if (options.after) cmd.push("--after=" + options.after);
if (options.merge) cmd.push("-m");
if (options.grep) cmd.push("--grep=" + options.grep);
/* journalctl doesn't allow reverse and follow together */
if (options.reverse) cmd.push("--reverse");
else if (options.follow) cmd.push("--follow");
cmd.push("--");
cmd.push.apply(cmd, matches);
var dfd = new cockpit.defer();
var promise;
var buffer = "";
var entries = [];
var streamers = [];
var interval = null;
function fire_streamers() {
var ents, i;
if (streamers.length && entries.length > 0) {
ents = entries;
entries = [];
for (i = 0; i < streamers.length; i++)
streamers[i].apply(promise, [ents]);
} else {
window.clearInterval(interval);
interval = null;
}
}
var proc = cockpit
.spawn(cmd, {
host: options.host,
batch: 8192,
latency: 300,
superuser: "try",
})
.stream(function (data) {
if (buffer) data = buffer + data;
buffer = "";
var lines = data.split("\n");
var last = lines.length - 1;
lines.forEach(function (line, i) {
if (i == last) {
buffer = line;
} else if (line && line.indexOf("-- ") !== 0) {
try {
entries.push(JSON.parse(line));
} catch (e) {
console.warn(e, line);
}
}
});
if (streamers.length && interval === null)
interval = window.setInterval(fire_streamers, 300);
})
.done(function () {
fire_streamers();
dfd.resolve(entries);
})
.fail(function (ex) {
/* The journalctl command fails when no entries are matched
* so we just ignore this status code */
if (ex.problem == "cancelled" || ex.exit_status === 1) {
fire_streamers();
dfd.resolve(entries);
} else {
dfd.reject(ex);
}
})
.always(function () {
window.clearInterval(interval);
});
promise = dfd.promise();
promise.stream = function stream(callback) {
streamers.push(callback);
return this;
};
promise.stop = function stop() {
proc.close("cancelled");
};
return promise;
};
journal.printable = function printable(value) {
if (value === undefined || value === null) return _("[no data]");
else if (typeof value == "string") return value;
else if (value.length !== undefined)
return cockpit.format(_("[$0 bytes of binary data]"), value.length);
else return _("[binary data]");
};
function output_funcs_for_box(box) {
/* Dereference any jQuery object here */
if (box.jquery) box = box[0];
Mustache.parse(day_header_template);
Mustache.parse(line_template);
Mustache.parse(reboot_template);
function render_line(ident, prio, message, count, time, entry) {
var parts = {
cursor: entry.__CURSOR,
time: time,
message: message,
service: ident,
};
if (count > 1) parts.count = count;
if (ident === "abrt-notification") {
parts.problem = true;
parts.service = entry.PROBLEM_BINARY;
} else if (prio < 4) parts.warning = true;
return Mustache.render(line_template, parts);
}
var reboot = _("Reboot");
var reboot_line = Mustache.render(reboot_template, { message: reboot });
function render_reboot_separator() {
return reboot_line;
}
function render_day_header(day) {
return Mustache.render(day_header_template, { day: day });
}
function parse_html(string) {
var div = document.createElement("div");
div.innerHTML = string.trim();
return div.children[0];
}
return {
render_line: render_line,
render_day_header: render_day_header,
render_reboot_separator: render_reboot_separator,
append: function (elt) {
if (typeof elt == "string") elt = parse_html(elt);
box.appendChild(elt);
},
prepend: function (elt) {
if (typeof elt == "string") elt = parse_html(elt);
if (box.firstChild) box.insertBefore(elt, box.firstChild);
else box.appendChild(elt);
},
remove_last: function () {
if (box.lastChild) box.removeChild(box.lastChild);
},
remove_first: function () {
if (box.firstChild) box.removeChild(box.firstChild);
},
};
}
var month_names = [
C_("month-name", "January"),
C_("month-name", "February"),
C_("month-name", "March"),
C_("month-name", "April"),
C_("month-name", "May"),
C_("month-name", "June"),
C_("month-name", "July"),
C_("month-name", "August"),
C_("month-name", "September"),
C_("month-name", "October"),
C_("month-name", "November"),
C_("month-name", "December"),
];
/* Render the journal entries by passing suitable HTML strings back to
the caller via the 'output_funcs'.
Rendering is context aware. It will insert 'reboot' markers, for
example, and collapse repeated lines. You can extend the output at
the bottom and also at the top.
A new renderer is created by calling 'journal.renderer' like
so:
var renderer = journal.renderer(funcs);
You can feed new entries into the renderer by calling various
methods on the returned object:
- renderer.append(journal_entry)
- renderer.append_flush()
- renderer.prepend(journal_entry)
- renderer.prepend_flush()
A 'journal_entry' is one element of the result array returned by a
call to 'Query' with the 'cockpit.journal_fields' as the fields to
return.
Calling 'append' will append the given entry to the end of the
output, naturally, and 'prepend' will prepend it to the start.
The output might lag behind what has been input via 'append' and
'prepend', and you need to call 'append_flush' and 'prepend_flush'
respectively to ensure that the output is up-to-date. Flushing a
renderer does not introduce discontinuities into the output. You
can continue to feed entries into the renderer after flushing and
repeated lines will be correctly collapsed across the flush, for
example.
The renderer will call methods of the 'output_funcs' object to
produce the desired output:
- output_funcs.append(rendered)
- output_funcs.remove_last()
- output_funcs.prepend(rendered)
- output_funcs.remove_first()
The 'rendered' argument is the return value of one of the rendering
functions described below. The 'append' and 'prepend' methods
should add this element to the output, naturally, and 'remove_last'
and 'remove_first' should remove the indicated element.
If you never call 'prepend' on the renderer, 'output_func.prepend'
isn't called either. If you never call 'renderer.prepend' after
'renderer.prepend_flush', then 'output_func.remove_first' will
never be called. The same guarantees exist for the 'append' family
of functions.
The actual rendering is also done by calling methods on
'output_funcs':
- output_funcs.render_line(ident, prio, message, count, time, cursor)
- output_funcs.render_day_header(day)
- output_funcs.render_reboot_separator()
*/
journal.renderer = function renderer(funcs_or_box) {
var output_funcs;
if (funcs_or_box.render_line) output_funcs = funcs_or_box;
else output_funcs = output_funcs_for_box(funcs_or_box);
function copy_object(o) {
var c = {};
for (var p in o) c[p] = o[p];
return c;
}
// A 'entry' object describes a journal entry in formatted form.
// It has fields 'bootid', 'ident', 'prio', 'message', 'time',
// 'day', all of which are strings.
function format_entry(journal_entry) {
function pad(n) {
var str = n.toFixed();
if (str.length == 1) str = "0" + str;
return str;
}
var d = new Date(journal_entry.__REALTIME_TIMESTAMP / 1000);
return {
cursor: journal_entry.__CURSOR,
full: journal_entry,
day:
month_names[d.getMonth()] +
" " +
d.getDate().toFixed() +
", " +
d.getFullYear().toFixed(),
time: pad(d.getHours()) + ":" + pad(d.getMinutes()),
bootid: journal_entry._BOOT_ID,
ident: journal_entry.SYSLOG_IDENTIFIER || journal_entry._COMM,
prio: journal_entry.PRIORITY,
message: journal.printable(journal_entry.MESSAGE),
};
}
function entry_is_equal(a, b) {
return (
a &&
b &&
a.day == b.day &&
a.bootid == b.bootid &&
a.ident == b.ident &&
a.prio == b.prio &&
a.message == b.message
);
}
// A state object describes a line that should be eventually
// output. It has an 'entry' field as per description above, and
// also 'count', 'last_time', and 'first_time', which record
// repeated entries. Additionally:
//
// line_present: When true, the line has been output already with
// some preliminary data. It needs to be removed before
// outputting more recent data.
//
// header_present: The day header has been output preliminarily
// before the actual log lines. It needs to be removed before
// prepending more lines. If both line_present and
// header_present are true, then the header comes first in the
// output, followed by the line.
function render_state_line(state) {
return output_funcs.render_line(
state.entry.ident,
state.entry.prio,
state.entry.message,
state.count,
state.last_time,
state.entry.full
);
}
// We keep the state of the first and last journal lines,
// respectively, in order to collapse repeated lines, and to
// insert reboot markers and day headers.
//
// Normally, there are two state objects, but if only a single
// line has been output so far, top_state and bottom_state point
// to the same object.
var top_state, bottom_state;
top_state = bottom_state = {};
function start_new_line() {
// If we now have two lines, split the state
if (top_state === bottom_state && top_state.entry) {
top_state = copy_object(bottom_state);
}
}
function top_output() {
if (top_state.header_present) {
output_funcs.remove_first();
top_state.header_present = false;
}
if (top_state.line_present) {
output_funcs.remove_first();
top_state.line_present = false;
}
if (top_state.entry) {
output_funcs.prepend(render_state_line(top_state));
top_state.line_present = true;
}
}
function prepend(journal_entry) {
var entry = format_entry(journal_entry);
if (entry_is_equal(top_state.entry, entry)) {
top_state.count += 1;
top_state.first_time = entry.time;
} else {
top_output();
if (top_state.entry) {
if (entry.bootid != top_state.entry.bootid)
output_funcs.prepend(output_funcs.render_reboot_separator());
if (entry.day != top_state.entry.day)
output_funcs.prepend(
output_funcs.render_day_header(top_state.entry.day)
);
}
start_new_line();
top_state.entry = entry;
top_state.count = 1;
top_state.first_time = top_state.last_time = entry.time;
top_state.line_present = false;
}
}
function prepend_flush() {
top_output();
if (top_state.entry) {
output_funcs.prepend(
output_funcs.render_day_header(top_state.entry.day)
);
top_state.header_present = true;
}
}
function bottom_output() {
if (bottom_state.line_present) {
output_funcs.remove_last();
bottom_state.line_present = false;
}
if (bottom_state.entry) {
output_funcs.append(render_state_line(bottom_state));
bottom_state.line_present = true;
}
}
function append(journal_entry) {
var entry = format_entry(journal_entry);
if (entry_is_equal(bottom_state.entry, entry)) {
bottom_state.count += 1;
bottom_state.last_time = entry.time;
} else {
bottom_output();
if (!bottom_state.entry || entry.day != bottom_state.entry.day) {
output_funcs.append(output_funcs.render_day_header(entry.day));
bottom_state.header_present = true;
}
if (bottom_state.entry && entry.bootid != bottom_state.entry.bootid)
output_funcs.append(output_funcs.render_reboot_separator());
start_new_line();
bottom_state.entry = entry;
bottom_state.count = 1;
bottom_state.first_time = bottom_state.last_time = entry.time;
bottom_state.line_present = false;
}
}
function append_flush() {
bottom_output();
}
return {
prepend: prepend,
prepend_flush: prepend_flush,
append: append,
append_flush: append_flush,
};
};
journal.logbox = function logbox(match, max_entries) {
var entries = [];
var box = document.createElement("div");
function render() {
var renderer = journal.renderer(box);
while (box.firstChild) box.removeChild(box.firstChild);
for (var i = 0; i < entries.length; i++) {
renderer.prepend(entries[i]);
}
renderer.prepend_flush();
if (entries.length > 0) box.removeAttribute("hidden");
else box.setAttribute("hidden", "hidden");
}
render();
var promise = journal
.journalctl(match, { count: max_entries })
.stream(function (tail) {
entries = entries.concat(tail);
if (entries.length > max_entries) entries = entries.slice(-max_entries);
render();
})
.fail(function (error) {
box.appendChild(document.createTextNode(error.message));
box.removeAttribute("hidden");
});
/* Both a DOM element and a promise */
return promise.promise(box);
};
module.exports = journal;
})();

View file

@ -1 +0,0 @@
<div class="panel-heading">{{day}}</div>

View file

@ -1,19 +0,0 @@
<div class="cockpit-logline" data-cursor="{{cursor}}" role="row">
<div class="cockpit-log-warning" role="cell">{{#warning}}
<i class="fa fa-exclamation-triangle"></i>
{{/warning}}{{#problem}}
<i class="fa fa-times-circle-o"></i>
{{/problem}}
</div>
<div class="cockpit-log-time" role="cell">{{time}}</div>
<span class="cockpit-log-message" role="cell">{{message}}</span>
{{! if we have count (repeated messages), show service name and badge - otherwise just the service }}
{{#count}}
<div class="cockpit-log-service-container" role="cell">
<div class="cockpit-log-service-reduced">{{service}}</div>
<span class="badge">{{count}}&#160;<i class="fa fa-caret-right"></i></span>
</div>
{{/count}}{{^count}}
<div class="cockpit-log-service" role="cell">{{service}}</div>
{{/count}}
</div>

View file

@ -1,5 +0,0 @@
<div class="cockpit-logline" role="row">
{{! placeholders for correct message alignment }}
<div class="cockpit-log-warning" role="cell"></div>
<span class="cockpit-log-message cockpit-logmsg-reboot" role="cell">{{message}}</span>
</div>

View file

@ -1,502 +0,0 @@
/* Listing pattern */
@import "./variables.less";
table.listing-ct {
margin-top: @listing-ct-spacing;
min-width: 65%;
}
table.listing-ct > caption,
table.listing-ct > thead h3 {
font-size: @font-size-h2;
padding: @listing-ct-padding 0px @listing-ct-padding;
font-weight: 300;
margin-top: 0;
}
table.listing-ct > caption {
color: inherit;
line-height: 1.1;
}
table.listing-ct > thead td {
padding-top: @listing-ct-padding * 2;
}
table.listing-ct > thead:first-child td {
padding-top: 0;
}
table.listing-ct > thead td > a {
line-height: 30px;
padding: @listing-ct-padding 0 @listing-ct-padding;
}
table.listing-ct > thead th {
border-top: 1px solid @gray-lighter;
font-weight: normal;
padding: @listing-ct-padding;
color: @listing-ct-metadata;
}
table.listing-ct > thead th:first-child {
padding-left: @listing-ct-padding * 2;
}
table.listing-ct > thead th:last-child {
text-align: right;
}
/* A listing item is a row in the table */
tbody > tr.listing-ct-item {
border-top: 1px solid @gray-lighter;
border-bottom: 1px solid @gray-lighter;
cursor: pointer;
}
table.listing-ct > tbody:last-child {
border-bottom: 1px solid @gray-lighter;
}
table.listing-ct > tbody + thead {
border-top: 1px solid @gray-lighter;
}
table.listing-ct > tbody.open:last-child {
border-bottom: none;
}
table.listing-ct > tbody.open + thead {
border-top: none;
}
tbody > tr.listing-ct-item.listing-ct-warning {
background-color: @listing-ct-warning-color;
}
tbody.open > tr.listing-ct-item {
background-color: @color-pf-black-200;
border-bottom: none;
border-top: none;
border-left: 1px solid @listing-ct-border;
border-right: 1px solid @listing-ct-border;
}
tbody.open > tr.listing-ct-item td,
tbody.open > tr.listing-ct-item th {
border-top: 1px solid @listing-ct-border;
}
tbody.open td div.listing-ct-head {
background-color: @color-pf-white;
}
tbody.open .listing-ct-panel {
border: 1px solid @listing-ct-border;
}
tbody.open .listing-ct-panel .listing-ct-body {
border: none;
}
tbody.open > tr.listing-ct-panel + tr.listing-ct-body {
border-top: none;
}
tbody.open > tr.listing-ct-panel td div.listing-ct-head {
border: none;
border-bottom: 1px solid @listing-ct-border;
}
/* only highlight the row if navigation is available */
tbody:not(.open) > tr.listing-ct-item:not(.listing-ct-nonavigate):hover {
background-color: @listing-ct-hover;
}
/* if we can't navigate to a row but expand is available, highlight the caret */
tbody:not(.open) > tr.listing-ct-item.listing-ct-nonavigate:hover td.listing-ct-toggle {
color: @listing-ct-active;
}
/* use gray for a row that's expanded or if navigation isn't available */
tbody.open > tr.listing-ct-item:hover,
tr.listing-ct-item.listing-ct-nonavigate:hover {
background-color: @color-pf-black-200;
}
/* always highlight caret when hovering over an expanded row */
tbody.open > tr.listing-ct-item:hover td.listing-ct-toggle {
color: @listing-ct-active;
}
tr.listing-ct-item .listing-ct-toggle {
padding: 0 !important;
width: 35px;
color: @color-pf-black;
}
table.listing-ct thead .listing-ct-toggle + th,
tr.listing-ct-item .listing-ct-toggle + td,
tr.listing-ct-item .listing-ct-toggle + th {
padding-left: 0;
}
tr:not(.listing-ct-selected) {
td.listing-ct-toggle:hover {
color: @listing-ct-active;
background-color: @color-pf-black-200;
~ td, ~ th {
background-color: @color-pf-black-200;
}
}
}
td.listing-ct-toggle i {
font-size: 24px;
visibility: hidden;
}
tr.listing-ct-item:hover td.listing-ct-toggle i,
tr.listing-ct-item td.listing-ct-toggle:hover i {
visibility: visible;
}
td.listing-ct-toggle i:before {
content: "\f105";
}
tbody.open td.listing-ct-toggle i {
visibility: visible;
}
tbody.open td.listing-ct-toggle i:before {
content: "\f107";
}
/* Listing items have decent padding ... */
tr.listing-ct-item td {
padding: @listing-ct-padding;
}
tr.listing-ct-item th {
padding: @listing-ct-padding @listing-ct-padding @listing-ct-padding @listing-ct-spacing;
}
/* Listing caption is text next to the actions, text should be similar to nav (.nav-tabs-pf > li > a)*/
.listing-ct-actions > .listing-ct-caption {
font-size: @font-size-h5;
vertical-align: middle;
color: @link-color;
padding-right: @listing-ct-padding / 2;
}
/* Listing actions can be used directly as a cell */
tr.listing-ct-item td.listing-ct-actions,
td.listing-ct-actions {
padding: @listing-ct-padding / 2 @listing-ct-padding;
text-align: right;
float: none;
}
/* if the entire row is selected, highlight */
tr.listing-ct-item.listing-ct-selected {
background-color: @color-pf-blue-400;
color: @color-pf-white;
border-color: multiply(@color-pf-black-200, @color-pf-blue-400);
&:hover {
background-color: multiply(@color-pf-black-200, @color-pf-blue-400);
border-color: multiply(@color-pf-black-200, @color-pf-blue-400);
}
}
tr.listing-ct-item.listing-ct-selected .badge {
background-color: multiply(@badge-bg, @color-pf-blue-400);
&:hover {
background-color: multiply(@badge-bg, @color-pf-blue-500);
}
}
.listing-ct-head .listing-ct-actions {
margin-top: -7px;
}
tr.listing-ct-item td:first-child {
padding-left: @listing-ct-padding * 2;
}
/* The last column of a listing is always right aligned */
tr.listing-ct-item td:last-child {
text-align: right;
}
div.listing-ct-panel {
box-shadow: 1px 1px 1px 1px @listing-ct-open;
margin-bottom: @listing-ct-spacing;
}
div.listing-ct-maybe {
border: 1px dashed @listing-ct-border-maybe;
box-shadow: none;
}
div.listing-ct-head {
padding: @listing-ct-padding @listing-ct-padding 0 @listing-ct-padding;
background-color: @listing-ct-open;
border-color: @listing-ct-border;
border-style: solid;
border-width: 1px 1px 0 1px;
overflow: hidden;
}
div.listing-ct-head:last-child {
padding-bottom: @listing-ct-padding;
}
div.listing-ct-maybe div.listing-ct-head,
div.listing-ct-maybe div.listing-ct-body {
background-color: @color-pf-white;
border: none;
}
tbody.active .listing-ct-head {
border-top: @listing-ct-open-width solid #0099d3;
}
.listing-ct-head h3 {
font-weight: normal;
font-size: 18px;
margin-top: 0px;
margin-left: @listing-ct-padding / 2;
margin-bottom: @listing-ct-padding;
}
.listing-ct-head h3 i {
float: left;
padding-right: 7px;
}
.listing-ct-head .nav li a {
padding-top: 0px;
font-size: 13px;
}
.listing-ct-head .nav-tabs {
border-bottom: none;
}
.listing-ct-head .nav-tabs-pf {
margin-left: -@listing-ct-padding;
}
/* To display info instead of tabs */
.listing-ct-head dl {
display: inline-block;
height: 1.6em;
margin-bottom: 5px;
white-space: nowrap;
margin-right: 45px;
margin-left: 5px;
}
.listing-ct-head dt {
font-weight: normal;
display: inline;
margin-right: 0.5em;
color: @listing-ct-metadata;
}
.listing-ct-head dd {
display: inline;
color: black;
}
.listing-ct-body {
padding: @listing-ct-padding * 2 @listing-ct-padding + @listing-ct-spacing;
font-size: 13px;
border: 1px solid @listing-ct-border;
background-color: @color-pf-white;
}
.listing-ct-inline > .listing-ct-body {
border: none;
padding-top: 0px;
padding-left: @listing-ct-padding * 2;
padding-bottom: 0px;
}
.listing-ct-inline > h3 {
border-top: 1px solid @listing-ct-border;
padding-top: 20px;
margin-top: 30px;
}
.listing-ct-inline > h3:first-child {
border-top: none;
padding-top: 0px;
margin-top: 20px;
}
.listing-ct-actions {
float: right;
min-height: 26px;
}
.listing-ct-status {
float: right;
clear: right;
}
.listing-ct-error {
border-top: 1px solid @listing-ct-border;
border-left: 1px solid @listing-ct-border;
border-right: 1px solid @listing-ct-border;
}
.listing-ct-error.alert {
margin-bottom: 0;
}
.listing-ct-body tt {
font-size: 12px
}
.listing-ct-body dl {
margin: 0;
}
.listing-ct-body dl dd dl.inline-dl dt,
.listing-ct-body dt {
clear: left;
float: left;
width: 100px;
min-height: 26px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: @listing-ct-metadata;
font-weight: normal;
}
.listing-ct-body dt {
text-align: right;
}
.listing-ct-body dl dd dl dt {
text-align: left;
}
.listing-ct-body dd {
margin-left: 110px;
min-height: 26px;
max-width: 1000px;
overflow: hidden;
text-overflow: ellipsis;
}
.listing-ct-body dl.full-width dt {
text-align: left;
min-width: none;
max-width: none;
float: none;
width: auto;
}
.listing-ct-body dl.full-width dd {
margin-left: 0px;
}
table.listing-ct tbody.open {
box-shadow: 1px 1px 1px 1px @color-pf-black-150;
}
/* By default these thincgs are hidden */
tbody tr.listing-ct-panel,
tbody tr.listing-ct-body {
display: none;
}
/* ... unless they are in the right state */
tbody.open tr.listing-ct-head,
tbody.open tr.listing-ct-panel,
tbody.open tr.listing-ct-body {
display: table-row;
}
tbody.open tr.listing-ct-head {
border-color: @listing-ct-border;
border-style: solid;
border-width: 1px 1px 0 1px;
border-top: @listing-ct-open-width solid #0099d3;
background-color: @listing-ct-open;
}
tr.listing-ct-head + tr.listing-ct-head {
border-top: none;
}
tr.listing-ct-head + tr.listing-ct-head td {
padding: 0px @listing-ct-padding 0px @listing-ct-padding;
}
tr.listing-ct-body td {
padding: @listing-ct-padding * 2 @listing-ct-padding + @listing-ct-spacing;
font-size: 13px;
}
.listing-ct-empty {
color: #888;
text-align: center;
border-top: 1px solid @listing-ct-border-light;
border-bottom: 1px solid @listing-ct-border-light;
}
/* Used at the end of a group of tbody to show an 'empty' message */
thead.listing-ct-empty td,
table.listing-ct > thead.listing-ct-empty td {
padding: @listing-ct-padding;
}
tbody + thead.listing-ct-empty {
display: none;
}
/* Listing pattern defaults to using full width of parent */
.listing-ct-wide {
width: 100%;
}
div.listing-ct-head {
overflow: visible;
}
.listing-ct-head .btn-group,
.listing-ct-head button:not(.dropdown-toggle) {
margin-left: 0.3em;
}
table.listing-ct > caption a {
font-size: 16px;
}
tbody tr.listing-ct-noexpand {
cursor: default;
}
/* Fix up nav-tabs-pf to work properly */
.nav-tabs-pf > li:first-child a {
margin-left: 0px !important;
padding-left: @listing-ct-spacing !important;
}
.nav-tabs-pf > li a:before {
right: 0px !important;
}
.nav-tabs-pf > li > a:active:before,
.nav-tabs-pf > li > a:focus:before,
.nav-tabs-pf > li > a:hover:before,
.nav-tabs-pf > li.active a:before {
height: @listing-ct-open-width;
left: 0px;
}

View file

@ -1,235 +0,0 @@
a {
cursor: pointer;
}
.disabled {
pointer-events: auto;
}
.btn {
min-height: 26px;
min-width: 26px;
}
.btn.disabled {
pointer-events: auto;
}
.btn.disabled:hover {
z-index: auto;
}
a.disabled {
cursor: not-allowed !important;
text-decoration: none;
pointer-events: none;
color: #8b8d8f;
}
a.disabled:hover {
text-decoration: none;
}
.dropdown-menu > li > a.disabled,
.dropdown-menu > li > a.disabled:hover,
.dropdown-menu > li > a.disabled:focus {
color: #999999;
}
.dropdown-menu > li > a.disabled:hover,
.dropdown-menu > li > a.disabled:focus {
text-decoration: none;
background-color: transparent;
background-image: none;
border-color: transparent;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
cursor: default;
}
/* Limit dropdown menus to 90% of the viewport size */
.dropdown-menu {
height: auto;
overflow-x: hidden;
max-height: 90vh;
}
/* Align these buttons more nicely */
.btn.fa-minus,
.btn.fa-plus {
padding-top: 4px;
}
/* HACK: Workaround for https://github.com/patternfly/patternfly/issues/174*/
.page-ct {
margin-top: 20px;
}
.highlight-ct {
background-color: #d4edfa;
}
/* Well and Blankslate */
.curtains-ct {
top: 0px;
height: 100%;
width: 100%;
position: fixed;
}
.panel .well {
margin-bottom: 0px;
border: none;
border-radius: 0px;
background-color: #FAFAFA;
}
.well.blank-slate-pf {
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.05) inset;
padding-top: 40px;
}
.blank-slate-pf .spinner-lg {
height: 58px;
width: 58px;
}
/*
* Control buttons such as play and stop
* Used with .btn .btn-default
*/
.btn-control-ct,
.btn-control-ct:hover {
background-position: center center;
background-size: 16px 16px;
background-repeat: no-repeat;
background-image: none;
-webkit-border-radius: 2;
-moz-border-radius: 2;
border-radius: 2px;
height: 28px;
width: 28px;
box-shadow: none;
}
.btn-control-ct {
background-color: #eeeeee;
}
.btn-control-ct:hover {
background-color: #e0e0e0;
}
/* On/off switch */
.btn-onoff-ct {
margin: 1px 0px;
text-transform: uppercase;
}
.btn-onoff-ct .btn {
color: transparent;
border-color: #B7B7B7;
padding: 2px 6px 1px 6px;
background-color: white;
background-image: linear-gradient(to bottom, rgb(250, 250, 250) 0px, rgb(237, 237, 237) 100%);
-webkit-box-shadow: none;
box-shadow: none;
width: 37px;
}
.btn-onoff-ct .btn:first-child {
border-right: #00435F;
}
.btn-onoff-ct .btn:last-child {
border-left: #00435F;
padding-left: 5px;
}
.btn-onoff-ct .btn.active {
background-image: none;
width: 36px;
}
.btn-onoff-ct .btn.active:first-child {
background-color: #0086CF;
color: white;
border-right: 1px solid #0071b0;
}
.btn-onoff-ct .btn.active:last-child {
color: #000;
border-left: 1px solid #d6d6d6;
}
.btn-onoff-ct .btn.disabled {
pointer-events: none;
color: transparent !important;
}
.btn-onoff-ct .btn.active.disabled {
background-color: #888 !important;
color: white !important;
}
/* Small list inside a dialog */
/* Alert fixups */
/* HACK: word-wrap workaround for long alerts https://github.com/patternfly/patternfly/issues/491 */
.modal-content .alert {
text-align: left;
padding-top: 5px;
padding-bottom: 5px;
word-wrap: break-word;
}
.modal-content .alert .fa {
position: absolute;
left: 10px;
top: 6px;
font-size: 20px;
}
.modal-content .alert .pficon {
top: 5px;
}
.alert.alert-danger .fa {
color: #af151a;
}
/* Dialog patterns */
.dialog-wait-ct {
margin-top: 3px;
}
.dialog-wait-ct .spinner {
display: inline-block;
}
.dialog-wait-ct span {
vertical-align: 4px;
padding-left: 10px;
}
.dialog-list-ct {
max-height: 230px;
overflow-x: auto;
border: 1px solid #CCC;
margin-bottom: 0px;
}
/* HACK: https://github.com/patternfly/patternfly/issues/255 */
input[type=number] {
padding: 0 0 0 5px;
}
/* Make a dialog visible */
.dialog-ct-visible {
display: block;
}

View file

@ -1,146 +0,0 @@
/* Panels don't draw borders between them */
.panel > .table > tbody:first-child td {
border-top: 1px solid rgb(221, 221, 221);
}
/* Table headers should not generate a double border */
.panel .table thead tr th {
border-bottom: none;
}
.panel-heading {
background: #F5F5F5;
height: 44px;
}
/* Vertically center dropdown buttons in panel headers */
.panel-heading .btn {
margin-top: -3px;
}
/*
* Fix up table row hovering.
*
* When you hover over table rows it's because they're clickable.
* Make the table row hover color match the list-group-item.
*/
.table-hover > tbody > tr > td,
.table-hover > tbody > tr > th,
.dialog-list-ct .list-group-item {
cursor: pointer;
}
.table-hover > tbody > tr:hover > td,
.table-hover > tbody > tr:hover > th,
.dialog-list-ct .list-group-item:hover:not(.active) {
background-color: #d4edfa;
}
/* Override patternfly to fit buttons and such */
.table > thead > tr > th,
.table > tbody > tr > td {
padding: 8px;
}
/* Override the heavy patternfly headers */
.table > thead {
background-image: none;
background-color: #fff;
}
/* Make things line up */
.table tbody tr td:first-child,
.table thead tr th:first-child {
padding-left: 15px;
}
.table tbody tr td:last-child,
.table thead tr th:last-child {
padding-right: 15px;
}
.info-table-ct > tr > td,
.info-table-ct > tbody > tr > td {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 0.75em;
padding-top: 0.25em;
vertical-align: top;
line-height: 26px;
}
.info-table-ct > tr > td:first-child,
.info-table-ct > tbody > tr > td:first-child {
text-align: right;
color: #888888;
}
.info-table-ct > tr > td:not(:first-child),
.info-table-ct > tbody > tr > td:not(:first-child) {
color: black;
}
.info-table-ct > tr > td button,
.info-table-ct > tbody > tr > td button {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.form-table-ct {
width: 100%;
}
.form-table-ct td {
padding-left: 0.75em;
padding-top: 0.25em;
line-height: 26px;
}
.form-table-ct td.top {
vertical-align: top;
}
.form-table-ct td:first-child {
text-align: right;
white-space: nowrap;
color: #888888;
width: 5px; /* will be expanded by nowrap */
}
.form-table-ct td[colspan] {
text-align: inherit;
}
.form-table-ct td {
height: 26px;
}
.form-table-ct td.header {
font-weight: bold;
text-align: left;
color: #4D5258;
padding: 20px 0 10px 0;
}
.form-table-ct label input[type='radio'],
.form-table-ct label input[type='checkbox'] {
margin-right: 4px;
}
.form-table-ct label {
margin-bottom: 0px;
}
.form-table-ct label span {
vertical-align: super;
}
/* Break up sidebar in columns in smaller sizes*/
@media (min-width: 992px) {
.info-table-ct-container .info-table-ct {
table-layout: fixed;
width: 100%;
}
}

View file

@ -1,522 +0,0 @@
.term-bg-color-0 { background-color: #2e3436; }
.term-fg-color-0 { color: #2e3436; }
.term-bg-color-1 { background-color: #cc0000; }
.term-fg-color-1 { color: #cc0000; }
.term-bg-color-2 { background-color: #4e9a06; }
.term-fg-color-2 { color: #4e9a06; }
.term-bg-color-3 { background-color: #c4a000; }
.term-fg-color-3 { color: #c4a000; }
.term-bg-color-4 { background-color: #3465a4; }
.term-fg-color-4 { color: #3465a4; }
.term-bg-color-5 { background-color: #75507b; }
.term-fg-color-5 { color: #75507b; }
.term-bg-color-6 { background-color: #06989a; }
.term-fg-color-6 { color: #06989a; }
.term-bg-color-7 { background-color: #d3d7cf; }
.term-fg-color-7 { color: #d3d7cf; }
.term-bg-color-8 { background-color: #555753; }
.term-fg-color-8 { color: #555753; }
.term-bg-color-9 { background-color: #ef2929; }
.term-fg-color-9 { color: #ef2929; }
.term-bg-color-10 { background-color: #8ae234; }
.term-fg-color-10 { color: #8ae234; }
.term-bg-color-11 { background-color: #fce94f; }
.term-fg-color-11 { color: #fce94f; }
.term-bg-color-12 { background-color: #729fcf; }
.term-fg-color-12 { color: #729fcf; }
.term-bg-color-13 { background-color: #ad7fa8; }
.term-fg-color-13 { color: #ad7fa8; }
.term-bg-color-14 { background-color: #34e2e2; }
.term-fg-color-14 { color: #34e2e2; }
.term-bg-color-15 { background-color: #eeeeec; }
.term-fg-color-15 { color: #eeeeec; }
.term-bg-color-16 { background-color: #000000; }
.term-fg-color-16 { color: #000000; }
.term-bg-color-17 { background-color: #00005f; }
.term-fg-color-17 { color: #00005f; }
.term-bg-color-18 { background-color: #000087; }
.term-fg-color-18 { color: #000087; }
.term-bg-color-19 { background-color: #0000af; }
.term-fg-color-19 { color: #0000af; }
.term-bg-color-20 { background-color: #0000d7; }
.term-fg-color-20 { color: #0000d7; }
.term-bg-color-21 { background-color: #0000ff; }
.term-fg-color-21 { color: #0000ff; }
.term-bg-color-22 { background-color: #005f00; }
.term-fg-color-22 { color: #005f00; }
.term-bg-color-23 { background-color: #005f5f; }
.term-fg-color-23 { color: #005f5f; }
.term-bg-color-24 { background-color: #005f87; }
.term-fg-color-24 { color: #005f87; }
.term-bg-color-25 { background-color: #005faf; }
.term-fg-color-25 { color: #005faf; }
.term-bg-color-26 { background-color: #005fd7; }
.term-fg-color-26 { color: #005fd7; }
.term-bg-color-27 { background-color: #005fff; }
.term-fg-color-27 { color: #005fff; }
.term-bg-color-28 { background-color: #008700; }
.term-fg-color-28 { color: #008700; }
.term-bg-color-29 { background-color: #00875f; }
.term-fg-color-29 { color: #00875f; }
.term-bg-color-30 { background-color: #008787; }
.term-fg-color-30 { color: #008787; }
.term-bg-color-31 { background-color: #0087af; }
.term-fg-color-31 { color: #0087af; }
.term-bg-color-32 { background-color: #0087d7; }
.term-fg-color-32 { color: #0087d7; }
.term-bg-color-33 { background-color: #0087ff; }
.term-fg-color-33 { color: #0087ff; }
.term-bg-color-34 { background-color: #00af00; }
.term-fg-color-34 { color: #00af00; }
.term-bg-color-35 { background-color: #00af5f; }
.term-fg-color-35 { color: #00af5f; }
.term-bg-color-36 { background-color: #00af87; }
.term-fg-color-36 { color: #00af87; }
.term-bg-color-37 { background-color: #00afaf; }
.term-fg-color-37 { color: #00afaf; }
.term-bg-color-38 { background-color: #00afd7; }
.term-fg-color-38 { color: #00afd7; }
.term-bg-color-39 { background-color: #00afff; }
.term-fg-color-39 { color: #00afff; }
.term-bg-color-40 { background-color: #00d700; }
.term-fg-color-40 { color: #00d700; }
.term-bg-color-41 { background-color: #00d75f; }
.term-fg-color-41 { color: #00d75f; }
.term-bg-color-42 { background-color: #00d787; }
.term-fg-color-42 { color: #00d787; }
.term-bg-color-43 { background-color: #00d7af; }
.term-fg-color-43 { color: #00d7af; }
.term-bg-color-44 { background-color: #00d7d7; }
.term-fg-color-44 { color: #00d7d7; }
.term-bg-color-45 { background-color: #00d7ff; }
.term-fg-color-45 { color: #00d7ff; }
.term-bg-color-46 { background-color: #00ff00; }
.term-fg-color-46 { color: #00ff00; }
.term-bg-color-47 { background-color: #00ff5f; }
.term-fg-color-47 { color: #00ff5f; }
.term-bg-color-48 { background-color: #00ff87; }
.term-fg-color-48 { color: #00ff87; }
.term-bg-color-49 { background-color: #00ffaf; }
.term-fg-color-49 { color: #00ffaf; }
.term-bg-color-50 { background-color: #00ffd7; }
.term-fg-color-50 { color: #00ffd7; }
.term-bg-color-51 { background-color: #00ffff; }
.term-fg-color-51 { color: #00ffff; }
.term-bg-color-52 { background-color: #5f0000; }
.term-fg-color-52 { color: #5f0000; }
.term-bg-color-53 { background-color: #5f005f; }
.term-fg-color-53 { color: #5f005f; }
.term-bg-color-54 { background-color: #5f0087; }
.term-fg-color-54 { color: #5f0087; }
.term-bg-color-55 { background-color: #5f00af; }
.term-fg-color-55 { color: #5f00af; }
.term-bg-color-56 { background-color: #5f00d7; }
.term-fg-color-56 { color: #5f00d7; }
.term-bg-color-57 { background-color: #5f00ff; }
.term-fg-color-57 { color: #5f00ff; }
.term-bg-color-58 { background-color: #5f5f00; }
.term-fg-color-58 { color: #5f5f00; }
.term-bg-color-59 { background-color: #5f5f5f; }
.term-fg-color-59 { color: #5f5f5f; }
.term-bg-color-60 { background-color: #5f5f87; }
.term-fg-color-60 { color: #5f5f87; }
.term-bg-color-61 { background-color: #5f5faf; }
.term-fg-color-61 { color: #5f5faf; }
.term-bg-color-62 { background-color: #5f5fd7; }
.term-fg-color-62 { color: #5f5fd7; }
.term-bg-color-63 { background-color: #5f5fff; }
.term-fg-color-63 { color: #5f5fff; }
.term-bg-color-64 { background-color: #5f8700; }
.term-fg-color-64 { color: #5f8700; }
.term-bg-color-65 { background-color: #5f875f; }
.term-fg-color-65 { color: #5f875f; }
.term-bg-color-66 { background-color: #5f8787; }
.term-fg-color-66 { color: #5f8787; }
.term-bg-color-67 { background-color: #5f87af; }
.term-fg-color-67 { color: #5f87af; }
.term-bg-color-68 { background-color: #5f87d7; }
.term-fg-color-68 { color: #5f87d7; }
.term-bg-color-69 { background-color: #5f87ff; }
.term-fg-color-69 { color: #5f87ff; }
.term-bg-color-70 { background-color: #5faf00; }
.term-fg-color-70 { color: #5faf00; }
.term-bg-color-71 { background-color: #5faf5f; }
.term-fg-color-71 { color: #5faf5f; }
.term-bg-color-72 { background-color: #5faf87; }
.term-fg-color-72 { color: #5faf87; }
.term-bg-color-73 { background-color: #5fafaf; }
.term-fg-color-73 { color: #5fafaf; }
.term-bg-color-74 { background-color: #5fafd7; }
.term-fg-color-74 { color: #5fafd7; }
.term-bg-color-75 { background-color: #5fafff; }
.term-fg-color-75 { color: #5fafff; }
.term-bg-color-76 { background-color: #5fd700; }
.term-fg-color-76 { color: #5fd700; }
.term-bg-color-77 { background-color: #5fd75f; }
.term-fg-color-77 { color: #5fd75f; }
.term-bg-color-78 { background-color: #5fd787; }
.term-fg-color-78 { color: #5fd787; }
.term-bg-color-79 { background-color: #5fd7af; }
.term-fg-color-79 { color: #5fd7af; }
.term-bg-color-80 { background-color: #5fd7d7; }
.term-fg-color-80 { color: #5fd7d7; }
.term-bg-color-81 { background-color: #5fd7ff; }
.term-fg-color-81 { color: #5fd7ff; }
.term-bg-color-82 { background-color: #5fff00; }
.term-fg-color-82 { color: #5fff00; }
.term-bg-color-83 { background-color: #5fff5f; }
.term-fg-color-83 { color: #5fff5f; }
.term-bg-color-84 { background-color: #5fff87; }
.term-fg-color-84 { color: #5fff87; }
.term-bg-color-85 { background-color: #5fffaf; }
.term-fg-color-85 { color: #5fffaf; }
.term-bg-color-86 { background-color: #5fffd7; }
.term-fg-color-86 { color: #5fffd7; }
.term-bg-color-87 { background-color: #5fffff; }
.term-fg-color-87 { color: #5fffff; }
.term-bg-color-88 { background-color: #870000; }
.term-fg-color-88 { color: #870000; }
.term-bg-color-89 { background-color: #87005f; }
.term-fg-color-89 { color: #87005f; }
.term-bg-color-90 { background-color: #870087; }
.term-fg-color-90 { color: #870087; }
.term-bg-color-91 { background-color: #8700af; }
.term-fg-color-91 { color: #8700af; }
.term-bg-color-92 { background-color: #8700d7; }
.term-fg-color-92 { color: #8700d7; }
.term-bg-color-93 { background-color: #8700ff; }
.term-fg-color-93 { color: #8700ff; }
.term-bg-color-94 { background-color: #875f00; }
.term-fg-color-94 { color: #875f00; }
.term-bg-color-95 { background-color: #875f5f; }
.term-fg-color-95 { color: #875f5f; }
.term-bg-color-96 { background-color: #875f87; }
.term-fg-color-96 { color: #875f87; }
.term-bg-color-97 { background-color: #875faf; }
.term-fg-color-97 { color: #875faf; }
.term-bg-color-98 { background-color: #875fd7; }
.term-fg-color-98 { color: #875fd7; }
.term-bg-color-99 { background-color: #875fff; }
.term-fg-color-99 { color: #875fff; }
.term-bg-color-100 { background-color: #878700; }
.term-fg-color-100 { color: #878700; }
.term-bg-color-101 { background-color: #87875f; }
.term-fg-color-101 { color: #87875f; }
.term-bg-color-102 { background-color: #878787; }
.term-fg-color-102 { color: #878787; }
.term-bg-color-103 { background-color: #8787af; }
.term-fg-color-103 { color: #8787af; }
.term-bg-color-104 { background-color: #8787d7; }
.term-fg-color-104 { color: #8787d7; }
.term-bg-color-105 { background-color: #8787ff; }
.term-fg-color-105 { color: #8787ff; }
.term-bg-color-106 { background-color: #87af00; }
.term-fg-color-106 { color: #87af00; }
.term-bg-color-107 { background-color: #87af5f; }
.term-fg-color-107 { color: #87af5f; }
.term-bg-color-108 { background-color: #87af87; }
.term-fg-color-108 { color: #87af87; }
.term-bg-color-109 { background-color: #87afaf; }
.term-fg-color-109 { color: #87afaf; }
.term-bg-color-110 { background-color: #87afd7; }
.term-fg-color-110 { color: #87afd7; }
.term-bg-color-111 { background-color: #87afff; }
.term-fg-color-111 { color: #87afff; }
.term-bg-color-112 { background-color: #87d700; }
.term-fg-color-112 { color: #87d700; }
.term-bg-color-113 { background-color: #87d75f; }
.term-fg-color-113 { color: #87d75f; }
.term-bg-color-114 { background-color: #87d787; }
.term-fg-color-114 { color: #87d787; }
.term-bg-color-115 { background-color: #87d7af; }
.term-fg-color-115 { color: #87d7af; }
.term-bg-color-116 { background-color: #87d7d7; }
.term-fg-color-116 { color: #87d7d7; }
.term-bg-color-117 { background-color: #87d7ff; }
.term-fg-color-117 { color: #87d7ff; }
.term-bg-color-118 { background-color: #87ff00; }
.term-fg-color-118 { color: #87ff00; }
.term-bg-color-119 { background-color: #87ff5f; }
.term-fg-color-119 { color: #87ff5f; }
.term-bg-color-120 { background-color: #87ff87; }
.term-fg-color-120 { color: #87ff87; }
.term-bg-color-121 { background-color: #87ffaf; }
.term-fg-color-121 { color: #87ffaf; }
.term-bg-color-122 { background-color: #87ffd7; }
.term-fg-color-122 { color: #87ffd7; }
.term-bg-color-123 { background-color: #87ffff; }
.term-fg-color-123 { color: #87ffff; }
.term-bg-color-124 { background-color: #af0000; }
.term-fg-color-124 { color: #af0000; }
.term-bg-color-125 { background-color: #af005f; }
.term-fg-color-125 { color: #af005f; }
.term-bg-color-126 { background-color: #af0087; }
.term-fg-color-126 { color: #af0087; }
.term-bg-color-127 { background-color: #af00af; }
.term-fg-color-127 { color: #af00af; }
.term-bg-color-128 { background-color: #af00d7; }
.term-fg-color-128 { color: #af00d7; }
.term-bg-color-129 { background-color: #af00ff; }
.term-fg-color-129 { color: #af00ff; }
.term-bg-color-130 { background-color: #af5f00; }
.term-fg-color-130 { color: #af5f00; }
.term-bg-color-131 { background-color: #af5f5f; }
.term-fg-color-131 { color: #af5f5f; }
.term-bg-color-132 { background-color: #af5f87; }
.term-fg-color-132 { color: #af5f87; }
.term-bg-color-133 { background-color: #af5faf; }
.term-fg-color-133 { color: #af5faf; }
.term-bg-color-134 { background-color: #af5fd7; }
.term-fg-color-134 { color: #af5fd7; }
.term-bg-color-135 { background-color: #af5fff; }
.term-fg-color-135 { color: #af5fff; }
.term-bg-color-136 { background-color: #af8700; }
.term-fg-color-136 { color: #af8700; }
.term-bg-color-137 { background-color: #af875f; }
.term-fg-color-137 { color: #af875f; }
.term-bg-color-138 { background-color: #af8787; }
.term-fg-color-138 { color: #af8787; }
.term-bg-color-139 { background-color: #af87af; }
.term-fg-color-139 { color: #af87af; }
.term-bg-color-140 { background-color: #af87d7; }
.term-fg-color-140 { color: #af87d7; }
.term-bg-color-141 { background-color: #af87ff; }
.term-fg-color-141 { color: #af87ff; }
.term-bg-color-142 { background-color: #afaf00; }
.term-fg-color-142 { color: #afaf00; }
.term-bg-color-143 { background-color: #afaf5f; }
.term-fg-color-143 { color: #afaf5f; }
.term-bg-color-144 { background-color: #afaf87; }
.term-fg-color-144 { color: #afaf87; }
.term-bg-color-145 { background-color: #afafaf; }
.term-fg-color-145 { color: #afafaf; }
.term-bg-color-146 { background-color: #afafd7; }
.term-fg-color-146 { color: #afafd7; }
.term-bg-color-147 { background-color: #afafff; }
.term-fg-color-147 { color: #afafff; }
.term-bg-color-148 { background-color: #afd700; }
.term-fg-color-148 { color: #afd700; }
.term-bg-color-149 { background-color: #afd75f; }
.term-fg-color-149 { color: #afd75f; }
.term-bg-color-150 { background-color: #afd787; }
.term-fg-color-150 { color: #afd787; }
.term-bg-color-151 { background-color: #afd7af; }
.term-fg-color-151 { color: #afd7af; }
.term-bg-color-152 { background-color: #afd7d7; }
.term-fg-color-152 { color: #afd7d7; }
.term-bg-color-153 { background-color: #afd7ff; }
.term-fg-color-153 { color: #afd7ff; }
.term-bg-color-154 { background-color: #afff00; }
.term-fg-color-154 { color: #afff00; }
.term-bg-color-155 { background-color: #afff5f; }
.term-fg-color-155 { color: #afff5f; }
.term-bg-color-156 { background-color: #afff87; }
.term-fg-color-156 { color: #afff87; }
.term-bg-color-157 { background-color: #afffaf; }
.term-fg-color-157 { color: #afffaf; }
.term-bg-color-158 { background-color: #afffd7; }
.term-fg-color-158 { color: #afffd7; }
.term-bg-color-159 { background-color: #afffff; }
.term-fg-color-159 { color: #afffff; }
.term-bg-color-160 { background-color: #d70000; }
.term-fg-color-160 { color: #d70000; }
.term-bg-color-161 { background-color: #d7005f; }
.term-fg-color-161 { color: #d7005f; }
.term-bg-color-162 { background-color: #d70087; }
.term-fg-color-162 { color: #d70087; }
.term-bg-color-163 { background-color: #d700af; }
.term-fg-color-163 { color: #d700af; }
.term-bg-color-164 { background-color: #d700d7; }
.term-fg-color-164 { color: #d700d7; }
.term-bg-color-165 { background-color: #d700ff; }
.term-fg-color-165 { color: #d700ff; }
.term-bg-color-166 { background-color: #d75f00; }
.term-fg-color-166 { color: #d75f00; }
.term-bg-color-167 { background-color: #d75f5f; }
.term-fg-color-167 { color: #d75f5f; }
.term-bg-color-168 { background-color: #d75f87; }
.term-fg-color-168 { color: #d75f87; }
.term-bg-color-169 { background-color: #d75faf; }
.term-fg-color-169 { color: #d75faf; }
.term-bg-color-170 { background-color: #d75fd7; }
.term-fg-color-170 { color: #d75fd7; }
.term-bg-color-171 { background-color: #d75fff; }
.term-fg-color-171 { color: #d75fff; }
.term-bg-color-172 { background-color: #d78700; }
.term-fg-color-172 { color: #d78700; }
.term-bg-color-173 { background-color: #d7875f; }
.term-fg-color-173 { color: #d7875f; }
.term-bg-color-174 { background-color: #d78787; }
.term-fg-color-174 { color: #d78787; }
.term-bg-color-175 { background-color: #d787af; }
.term-fg-color-175 { color: #d787af; }
.term-bg-color-176 { background-color: #d787d7; }
.term-fg-color-176 { color: #d787d7; }
.term-bg-color-177 { background-color: #d787ff; }
.term-fg-color-177 { color: #d787ff; }
.term-bg-color-178 { background-color: #d7af00; }
.term-fg-color-178 { color: #d7af00; }
.term-bg-color-179 { background-color: #d7af5f; }
.term-fg-color-179 { color: #d7af5f; }
.term-bg-color-180 { background-color: #d7af87; }
.term-fg-color-180 { color: #d7af87; }
.term-bg-color-181 { background-color: #d7afaf; }
.term-fg-color-181 { color: #d7afaf; }
.term-bg-color-182 { background-color: #d7afd7; }
.term-fg-color-182 { color: #d7afd7; }
.term-bg-color-183 { background-color: #d7afff; }
.term-fg-color-183 { color: #d7afff; }
.term-bg-color-184 { background-color: #d7d700; }
.term-fg-color-184 { color: #d7d700; }
.term-bg-color-185 { background-color: #d7d75f; }
.term-fg-color-185 { color: #d7d75f; }
.term-bg-color-186 { background-color: #d7d787; }
.term-fg-color-186 { color: #d7d787; }
.term-bg-color-187 { background-color: #d7d7af; }
.term-fg-color-187 { color: #d7d7af; }
.term-bg-color-188 { background-color: #d7d7d7; }
.term-fg-color-188 { color: #d7d7d7; }
.term-bg-color-189 { background-color: #d7d7ff; }
.term-fg-color-189 { color: #d7d7ff; }
.term-bg-color-190 { background-color: #d7ff00; }
.term-fg-color-190 { color: #d7ff00; }
.term-bg-color-191 { background-color: #d7ff5f; }
.term-fg-color-191 { color: #d7ff5f; }
.term-bg-color-192 { background-color: #d7ff87; }
.term-fg-color-192 { color: #d7ff87; }
.term-bg-color-193 { background-color: #d7ffaf; }
.term-fg-color-193 { color: #d7ffaf; }
.term-bg-color-194 { background-color: #d7ffd7; }
.term-fg-color-194 { color: #d7ffd7; }
.term-bg-color-195 { background-color: #d7ffff; }
.term-fg-color-195 { color: #d7ffff; }
.term-bg-color-196 { background-color: #ff0000; }
.term-fg-color-196 { color: #ff0000; }
.term-bg-color-197 { background-color: #ff005f; }
.term-fg-color-197 { color: #ff005f; }
.term-bg-color-198 { background-color: #ff0087; }
.term-fg-color-198 { color: #ff0087; }
.term-bg-color-199 { background-color: #ff00af; }
.term-fg-color-199 { color: #ff00af; }
.term-bg-color-200 { background-color: #ff00d7; }
.term-fg-color-200 { color: #ff00d7; }
.term-bg-color-201 { background-color: #ff00ff; }
.term-fg-color-201 { color: #ff00ff; }
.term-bg-color-202 { background-color: #ff5f00; }
.term-fg-color-202 { color: #ff5f00; }
.term-bg-color-203 { background-color: #ff5f5f; }
.term-fg-color-203 { color: #ff5f5f; }
.term-bg-color-204 { background-color: #ff5f87; }
.term-fg-color-204 { color: #ff5f87; }
.term-bg-color-205 { background-color: #ff5faf; }
.term-fg-color-205 { color: #ff5faf; }
.term-bg-color-206 { background-color: #ff5fd7; }
.term-fg-color-206 { color: #ff5fd7; }
.term-bg-color-207 { background-color: #ff5fff; }
.term-fg-color-207 { color: #ff5fff; }
.term-bg-color-208 { background-color: #ff8700; }
.term-fg-color-208 { color: #ff8700; }
.term-bg-color-209 { background-color: #ff875f; }
.term-fg-color-209 { color: #ff875f; }
.term-bg-color-210 { background-color: #ff8787; }
.term-fg-color-210 { color: #ff8787; }
.term-bg-color-211 { background-color: #ff87af; }
.term-fg-color-211 { color: #ff87af; }
.term-bg-color-212 { background-color: #ff87d7; }
.term-fg-color-212 { color: #ff87d7; }
.term-bg-color-213 { background-color: #ff87ff; }
.term-fg-color-213 { color: #ff87ff; }
.term-bg-color-214 { background-color: #ffaf00; }
.term-fg-color-214 { color: #ffaf00; }
.term-bg-color-215 { background-color: #ffaf5f; }
.term-fg-color-215 { color: #ffaf5f; }
.term-bg-color-216 { background-color: #ffaf87; }
.term-fg-color-216 { color: #ffaf87; }
.term-bg-color-217 { background-color: #ffafaf; }
.term-fg-color-217 { color: #ffafaf; }
.term-bg-color-218 { background-color: #ffafd7; }
.term-fg-color-218 { color: #ffafd7; }
.term-bg-color-219 { background-color: #ffafff; }
.term-fg-color-219 { color: #ffafff; }
.term-bg-color-220 { background-color: #ffd700; }
.term-fg-color-220 { color: #ffd700; }
.term-bg-color-221 { background-color: #ffd75f; }
.term-fg-color-221 { color: #ffd75f; }
.term-bg-color-222 { background-color: #ffd787; }
.term-fg-color-222 { color: #ffd787; }
.term-bg-color-223 { background-color: #ffd7af; }
.term-fg-color-223 { color: #ffd7af; }
.term-bg-color-224 { background-color: #ffd7d7; }
.term-fg-color-224 { color: #ffd7d7; }
.term-bg-color-225 { background-color: #ffd7ff; }
.term-fg-color-225 { color: #ffd7ff; }
.term-bg-color-226 { background-color: #ffff00; }
.term-fg-color-226 { color: #ffff00; }
.term-bg-color-227 { background-color: #ffff5f; }
.term-fg-color-227 { color: #ffff5f; }
.term-bg-color-228 { background-color: #ffff87; }
.term-fg-color-228 { color: #ffff87; }
.term-bg-color-229 { background-color: #ffffaf; }
.term-fg-color-229 { color: #ffffaf; }
.term-bg-color-230 { background-color: #ffffd7; }
.term-fg-color-230 { color: #ffffd7; }
.term-bg-color-231 { background-color: #ffffff; }
.term-fg-color-231 { color: #ffffff; }
.term-bg-color-232 { background-color: #080808; }
.term-fg-color-232 { color: #080808; }
.term-bg-color-233 { background-color: #121212; }
.term-fg-color-233 { color: #121212; }
.term-bg-color-234 { background-color: #1c1c1c; }
.term-fg-color-234 { color: #1c1c1c; }
.term-bg-color-235 { background-color: #262626; }
.term-fg-color-235 { color: #262626; }
.term-bg-color-236 { background-color: #303030; }
.term-fg-color-236 { color: #303030; }
.term-bg-color-237 { background-color: #3a3a3a; }
.term-fg-color-237 { color: #3a3a3a; }
.term-bg-color-238 { background-color: #444444; }
.term-fg-color-238 { color: #444444; }
.term-bg-color-239 { background-color: #4e4e4e; }
.term-fg-color-239 { color: #4e4e4e; }
.term-bg-color-240 { background-color: #585858; }
.term-fg-color-240 { color: #585858; }
.term-bg-color-241 { background-color: #626262; }
.term-fg-color-241 { color: #626262; }
.term-bg-color-242 { background-color: #6c6c6c; }
.term-fg-color-242 { color: #6c6c6c; }
.term-bg-color-243 { background-color: #767676; }
.term-fg-color-243 { color: #767676; }
.term-bg-color-244 { background-color: #808080; }
.term-fg-color-244 { color: #808080; }
.term-bg-color-245 { background-color: #8a8a8a; }
.term-fg-color-245 { color: #8a8a8a; }
.term-bg-color-246 { background-color: #949494; }
.term-fg-color-246 { color: #949494; }
.term-bg-color-247 { background-color: #9e9e9e; }
.term-fg-color-247 { color: #9e9e9e; }
.term-bg-color-248 { background-color: #a8a8a8; }
.term-fg-color-248 { color: #a8a8a8; }
.term-bg-color-249 { background-color: #b2b2b2; }
.term-fg-color-249 { color: #b2b2b2; }
.term-bg-color-250 { background-color: #bcbcbc; }
.term-fg-color-250 { color: #bcbcbc; }
.term-bg-color-251 { background-color: #c6c6c6; }
.term-fg-color-251 { color: #c6c6c6; }
.term-bg-color-252 { background-color: #d0d0d0; }
.term-fg-color-252 { color: #d0d0d0; }
.term-bg-color-253 { background-color: #dadada; }
.term-fg-color-253 { color: #dadada; }
.term-bg-color-254 { background-color: #e4e4e4; }
.term-fg-color-254 { color: #e4e4e4; }
.term-bg-color-255 { background-color: #eeeeee; }
.term-fg-color-255 { color: #eeeeee; }
.term-bg-color-default { background-color: #000000; }
.term-bg-color-256 { background-color: #000000; }
.term-fg-color-256 { color: #000000; }
.term-fg-color-default { color: #f0f0f0; }
.term-bg-color-257 { background-color: #f0f0f0; }
.term-fg-color-257 { color: #f0f0f0; }
.term-bold { font-weight: bold; }
.term-underline { text-decoration: underline; }
.term-blink { text-decoration: blink; }
.term-hidden { visibility: hidden; }

View file

@ -1,22 +0,0 @@
@import (less) "../../../node_modules/bootstrap/less/variables.less";
@import (less) "../../../node_modules/patternfly/dist/less/variables.less";
@metadata-color: #888;
@listing-ct-hover: @list-group-hover-bg;
@listing-ct-active: #65bedf;
@listing-ct-padding: 10px;
@listing-ct-spacing: 15px;
@listing-ct-open: #f5f5f5;
@listing-ct-open-width: 3px;
@listing-ct-metadata: @metadata-color;
@listing-ct-warning-color: #fbc7c7;
@listing-ct-border: #ccc;
@listing-ct-border-light: #eee;
@listing-ct-border-maybe: #ddd;
@screen-lg-max: (@screen-xlg-min - 1);
@screen-xlg-min: 1600px;
@screen-xs: 480px;
@screen-xs-min: @screen-xs;
@screen-xxs-max: (@screen-xs-min - 1);

View file

@ -21,6 +21,8 @@ import React from 'react';
import './player.css';
import { Terminal as Term } from 'xterm';
import {
Alert,
AlertGroup,
Button,
Chip,
ChipGroup,
@ -52,10 +54,12 @@ import {
ThumbtackIcon,
MigrationIcon,
} from '@patternfly/react-icons';
import { journal } from 'journal';
const cockpit = require("cockpit");
const _ = cockpit.gettext;
const moment = require("moment");
const Journal = require("journal");
const $ = require("jquery");
const padInt = function (n, w) {
@ -113,21 +117,17 @@ function ErrorList(props) {
}
return (
<>
<AlertGroup>
{list}
</>
</AlertGroup>
);
}
function ErrorItem(props) {
return (
<div className="alert alert-danger alert-dismissable">
<button type="button" className="close" data-dismiss="alert" aria-hidden="true">
<span className="pficon pficon-close" />
</button>
<span className="pficon pficon-error-circle-o" />
<Alert variant="danger" isInline>
{props.message}
</div>
</Alert>
);
}
@ -210,7 +210,7 @@ const PacketBuffer = class {
/* Error which stopped the loading */
this.error = null;
/* The journalctl reading the recording */
this.journalctl = Journal.journalctl(
this.journalctl = journal.journalctl(
this.matchList,
{ count: "all", follow: false, merge: true });
this.journalctl.fail(this.handleError);
@ -596,7 +596,7 @@ const PacketBuffer = class {
this.journalctl = null;
}
/* Continue with the "following" run */
this.journalctl = Journal.journalctl(
this.journalctl = journal.journalctl(
this.matchList,
{
cursor: this.cursor,
@ -636,7 +636,7 @@ class Search extends React.Component {
}
handleSearchSubmit() {
this.journalctl = Journal.journalctl(
this.journalctl = journal.journalctl(
this.props.matchList,
{ count: "all", follow: false, merge: true, grep: this.state.search });
this.journalctl.fail(this.handleError);

View file

@ -59,12 +59,12 @@ import {
} from "@patternfly/react-icons";
import { global_danger_color_200 } from "@patternfly/react-tokens";
import { debounce } from 'throttle-debounce';
import { journal } from 'journal';
const $ = require("jquery");
const cockpit = require("cockpit");
const _ = cockpit.gettext;
const moment = require("moment");
const Journal = require("journal");
const Player = require("./player.jsx");
const Config = require("./config.jsx");
@ -247,7 +247,7 @@ class Logs extends React.Component {
}
const self = this;
this.journalCtl = Journal.journalctl(matches, options)
this.journalCtl = journal.journalctl(matches, options)
.fail(this.journalctlError)
.done(function(data) {
self.journalctlIngest(data);
@ -701,7 +701,7 @@ export default class View extends React.Component {
}
this.journalctlRecordingID = this.state.recordingID;
this.journalctl = Journal.journalctl(matches, options)
this.journalctl = journal.journalctl(matches, options)
.fail(this.journalctlError)
.stream(this.journalctlIngest);
}

View file

@ -14,7 +14,7 @@ const srcdir = (process.env.SRCDIR || __dirname) + path.sep + "src";
const builddir = process.env.SRCDIR || __dirname;
const distdir = builddir + path.sep + "dist";
const section = process.env.ONLYDIR || null;
const libdir = path.resolve(srcdir, "pkg" + path.sep + "lib")
const libdir = path.resolve(srcdir, "lib")
const nodedir = path.resolve(process.env.SRCDIR || __dirname, "node_modules");
/* A standard nodejs and webpack pattern */