Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Services filtering and other stuff #11241

Merged
merged 12 commits into from
Mar 1, 2019
16 changes: 9 additions & 7 deletions pkg/systemd/host.css
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,12 @@ body {
white-space: nowrap;
}

@media screen and (max-width: 960px) {
.service-unit-data {
white-space: normal;
}
}

.service-unit-failed {
color: red;
}
Expand All @@ -347,10 +353,6 @@ body {
width: 100%;
}

#services > .container-fluid {
margin-top: 5em;
}

.service-template input {
width: 50em;
}
Expand All @@ -359,8 +361,8 @@ body {
padding-left: 10px;
}

#journal-box {
margin-top: 5em;
.content-header-extra + #journal-box {
margin-top: 0.5rem;
}

#journal-entry-message:not(:empty) {
Expand Down Expand Up @@ -431,7 +433,7 @@ body {
border-bottom: 1px solid #ddd;
padding: 10px 20px;
width: 100%;
position: fixed;
position: sticky;
z-index: 900;
top: 0;
}
Expand Down
72 changes: 50 additions & 22 deletions pkg/systemd/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,15 @@ $(function() {
active_state = load_state + " / " + active_state;

unit.CombinedState = active_state;
unit.AutomaticStartup = _("Static");
unit.AutomaticStartupIndex = 3;
if (unit.UnitFileState && startsWith(unit.UnitFileState, 'enabled')) {
unit.AutomaticStartup = _("Enabled");
unit.AutomaticStartupIndex = 1;
} else if (unit.UnitFileState && startsWith(unit.UnitFileState, 'disabled')) {
unit.AutomaticStartup = _("Disabled");
unit.AutomaticStartupIndex = 2;
}

if (unit.Id.slice(-5) == "timer") {
unit.is_timer = true;
Expand Down Expand Up @@ -258,20 +267,22 @@ $(function() {
mustache.parse(units_template);

function render_now() {
var pattern = $('#services-filter button.active').attr('data-pattern');
var pattern = $('#services-filter li.active').attr('data-pattern');
var current_text_filter = $('#services-text-filter').val()
.toLowerCase();
var current_type_filter = parseInt($('#current-service-type').attr("data-num"));

function cmp_path(a, b) { return units_by_path[a].Id.localeCompare(units_by_path[b].Id) }
var sorted_keys = Object.keys(units_by_path).sort(cmp_path);
var enabled = [ ];
var disabled = [ ];
var statics = [ ];
var units = [ ];
var header = {
Description: _("Description"),
Id: _("Id"),
is_timer: (~pattern.indexOf("timer")),
Next_Run_Time: _("Next Run"),
Last_Trigger_Time: _("Last Trigger"),
Current_State: _("State")
Current_State: _("State"),
Automatic_Startup: _("Automatic Startup")
};
if (header.is_timer)
$('#create-timer').show();
Expand All @@ -283,26 +294,23 @@ $(function() {
return;
if (unit.LoadState == "not-found")
return;
if (unit.UnitFileState && startsWith(unit.UnitFileState, 'enabled'))
enabled.push(unit);
else if (unit.UnitFileState && startsWith(unit.UnitFileState, 'disabled'))
disabled.push(unit);
else
statics.push(unit);
if (current_text_filter && unit.Description.toLowerCase().indexOf(current_text_filter) == -1 &&
unit.Id.indexOf(current_text_filter) == -1)
return;
if (current_type_filter !== 0 && current_type_filter !== unit.AutomaticStartupIndex)
return;
units.push(unit);
});
marusak marked this conversation as resolved.
Show resolved Hide resolved

function fill_table(parent, heading, units) {
var text = mustache.render(units_template, {
heading: heading,
var text = "";
if (units.length > 0)
text = mustache.render(units_template, {
table_head: header,
units: units
});
parent.html(text);
}

fill_table($('#services-list-enabled'), _("Enabled"), enabled);
fill_table($('#services-list-disabled'), _("Disabled"), disabled);
fill_table($('#services-list-static'), _("Static"), statics);
else
text = mustache.render(empty_template);
$("#services-list").html(text);
}

var render_holdoff_timer;
Expand All @@ -325,6 +333,16 @@ $(function() {
}
}

function clear_filters() {
$("#services-text-filter").val("");
$('#current-service-type').attr("data-num", 0);
$('#current-service-type').text(_("All"));
render();
}

$("#services-text-filter").on("input", render);
martinpitt marked this conversation as resolved.
Show resolved Hide resolved
$(document).on("click", "#clear-all-filters", clear_filters);

var update_run = 0;

function update_all() {
Expand Down Expand Up @@ -471,8 +489,8 @@ $(function() {
update_all();
});

$('#services-filter button').on('click', function() {
$('#services-filter button')
$('#services-filter li').on('click', function() {
$('#services-filter li')
.removeClass('active')
.removeAttr('aria-current');
$(this)
Expand All @@ -481,6 +499,13 @@ $(function() {
render();
});

$('#services-dropdown .dropdown-menu li').on('click', function() {
var selected = $(this).children(":first");
$("#current-service-type").text(selected.text());
$("#current-service-type").attr("data-num", selected.attr("data-num"));
render();
});

update_all();
}

Expand Down Expand Up @@ -514,6 +539,9 @@ $(function() {
var template_template = $("#service-template-tmpl").html();
mustache.parse(template_template);

var empty_template = $("#service-empty-tmpl").html();
mustache.parse(empty_template);

var unit_primary_actions = [ // <method>:<mode>
{ title: _("Start"), action: 'StartUnit' },
{ title: _("Stop"), action: 'StopUnit' },
Expand Down
83 changes: 83 additions & 0 deletions pkg/systemd/services.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
#services > .content-header-extra + .container-fluid {
margin-top: 1rem;
}

#services-page {
overflow-y: scroll;
marusak marked this conversation as resolved.
Show resolved Hide resolved
}

.comma-list {
display: inline;
list-style: none;
Expand All @@ -16,3 +24,78 @@ table.systemd-unit-relationship-table td:first-child {
vertical-align: top;
text-align: right;
}

#services .content-header-extra {
display: flex;
justify-content: space-between;
}

#services-text-filter {
width: auto;
display: inline;
vertical-align: middle;
padding-right: 35px;
}

.blank-screen {
background-color: initial;
border: initial;
}

#services-dropdown {
display: inline;
}

#service-type {
min-width: 10rem;
}

#services-dropdown .dropdown-menu {
margin-top: 4px;
left: auto;
right: 0;
}

.caret {
margin-top: 6px;
}

#services-list .panel-default {
border: none;
box-shadow: none;
}

#services-list table {
table-layout: fixed;
}

#services-list thead {
color: #72767b; /* pf-black-600 */
background-color: #fff;
font-weight: normal;
}

#services-list th,
#services-list td {
border: 1px solid #d1d1d1; /* pf-black-300 */
border-width: 0 0 1px;
overflow-wrap: anywhere;
}

#services-list tbody th {
/* make tbody th padding the same as td */
padding: 8px;
}

.content-header-extra.with-navtabs {
padding-bottom: 0;
}


.service-unit-description {
width: 40%;
}

#services .nav-tabs {
border-bottom: none;
}
70 changes: 48 additions & 22 deletions pkg/systemd/services.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,54 +15,71 @@

<script id="services-units-tmpl" type="x-template/mustache">
<div class="panel panel-default">
<div class="panel-heading">{{heading}}</div>
<table class="table table-hover">
{{#table_head}}
<thead>
<tr>
<th class="service-unit-description">{{Description}}</th>
<th>{{Id}}</th>
<th scope="col" class="service-unit-id">{{Id}}</th>
Copy link
Member

Choose a reason for hiding this comment

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

These aren't being used anywhere, in CSS nor tests. Is that planned?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

I had them in CSS at some point.

This specific one was being used for the width calculation. The CSS was targeting both the th and td for fixing the width... I looked and found in in the CSS locally, but updated the branch and don't see it anymore; I guess that changed at the end of last week?

Copy link
Member

@garrett garrett Mar 4, 2019

Choose a reason for hiding this comment

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

Not so specific to this PR (anymore), but an aside with background info:

Also, I come across unclassed <th>s, <td>s all the time in Cockpit and see people target them with :first-child, :last-child, :nth-child() and such — we shouldn't target tables (or most elements) like this, unless it's really supposed to be the first or last element and not a specific row. That's why I added it.

(Although, we can fix it on the fly if we do need to target a specific element too.)

<th scope="col" class="service-unit-description">{{Description}}</th>
{{#is_timer}}
<th>{{Next_Run_Time}}</th>
<th>{{Last_Trigger_Time}}</th>
<th scope="col" class="service-unit-next">{{Next_Run_Time}}</th>
<th scope="col" class="service-unit-last">{{Last_Trigger_Time}}</th>
{{/is_timer}}
<th class="service-unit-data {{#HasFailed}}service-unit-failed{{/HasFailed}}">{{Current_State}}</th>
<th scope="col" class="service-unit-status {{#HasFailed}}service-unit-failed{{/HasFailed}}">{{Current_State}}</th>
<th scope="col" class="service-unit-data">{{Automatic_Startup}}</th>
</tr>
</thead>
{{/table_head}}

{{#units}}
<tr data-goto-unit="{{Id}}">
<td class="service-unit-description">{{Description}}</td>
<td>{{Id}}</td>
<td class="service-unit-id">{{Id}}</td>
<th scope="row" class="service-unit-description">{{Description}}</th>
{{#is_timer}}
<td>{{#NextRunTime}}{{NextRunTime}}{{/NextRunTime}}</td>
<td>{{#LastTriggerTime}}{{LastTriggerTime}}{{/LastTriggerTime}}</td>
<td class="service-unit-next">{{#NextRunTime}}{{NextRunTime}}{{/NextRunTime}}</td>
<td class="service-unit-last">{{#LastTriggerTime}}{{LastTriggerTime}}{{/LastTriggerTime}}</td>
{{/is_timer}}
<td class="service-unit-data {{#HasFailed}}service-unit-failed{{/HasFailed}}">
<td class="service-unit-status {{#HasFailed}}service-unit-failed{{/HasFailed}}">
{{CombinedState}}
</td>
<td class="service-unit-data">
{{AutomaticStartup}}
</td>
{{/units}}
</table>
</div>
</script>

<div id="services" hidden>
<div class="content-header-extra">
<div class="btn-group" id="services-filter" role="tablist">
<button class="btn btn-default" role="tab" data-pattern="\.target$" translatable="yes">Targets</button>
<button class="btn btn-default active" role="tab" aria-current=true data-pattern="\.service$" translatable="yes">System Services</button>
<button class="btn btn-default" role="tab" data-pattern="\.socket$" translatable="yes">Sockets</button>
<button class="btn btn-default" role="tab" data-pattern="\.timer$" translatable="yes">Timers</button>
<button class="btn btn-default" role="tab" data-pattern="\.path$" translatable="yes">Paths</button>
<div class="content-header-extra with-navtabs">
<ul class="nav nav-tabs" id="services-filter">
<li tabindex="0" data-pattern="\.target$"><a translatable="yes">Targets</a></li>
<li class="active" aria-current=true tabindex="0" data-pattern="\.service$"><a translatable="yes">System Services</a></li>
<li tabindex="0" data-pattern="\.socket$"><a translatable="yes">Sockets</a></li>
<li tabindex="0" data-pattern="\.timer$"><a translatable="yes">Timers</a><li>
<li tabindex="0" data-pattern="\.path$"><a translatable="yes">Paths</a><li>
Copy link
Member

Choose a reason for hiding this comment

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

Ah, cool to see tabindex as the tabs need to be selected — but why is it in <li> instead of <a>? (Better yet would be to add href to the <a>, instead of using a tabindex, and use a URL fragment* to remember the state in the URL.)

* URL fragment (#this-thing-here), not to be confused with a Document Fragment, React.Fragment, CSS Fragmentation, or anything else called "fragment" in webdev. 😉

</ul>
<div class="filter-group">
<button id="create-timer" data-toggle="#timer-dialog" data-target="#timer-dialog" class="btn btn-primary" translate>Create Timer</button>
<input type="search" id="services-text-filter" class="form-control" aria-label="Filter" placeholder="Filter by Id or description..." translate="placeholder"/>
<div class="dropdown" id="services-dropdown">
Copy link
Member

Choose a reason for hiding this comment

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

FTR, in the spirit of #11155 this should become an actual <select> soon. Right now the selector isn't keyboard navigatable at all. Fine for a follow-up of course.

<button class="btn btn-default dropdown-toggle" type="button" id="service-type" data-toggle="dropdown">
<span id="current-service-type" class="pull-left" data-num=0 translatable="yes">All</span>
<span class="caret pull-right"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="service-type">
<li role="presentation"><a role="menuitem" data-num=0 translatable="yes">All</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" data-num=1 translatable="yes">Enabled</a></li>
<li role="presentation"><a role="menuitem" data-num=2 translatable="yes">Disabled</a></li>
<li role="presentation"><a role="menuitem" data-num=3 translatable="yes">Static</a></li>
</ul>
</div>
</div>
<button id="create-timer" data-toggle="#timer-dialog" data-target="#timer-dialog" class="btn btn-primary pull-right" translate>Create Timer</button>
</div>

<div class="container-fluid" role="tabpanel">
<div id="services-list-enabled"></div>
<div id="services-list-disabled"></div>
<div id="services-list-static"></div>
<div id="services-list"></div>
</div>
</div>

Expand Down Expand Up @@ -168,6 +185,15 @@
</div>
</script>

<script id="service-empty-tmpl" type="x-template/mustache">
<div id="empty-search" class="blank-slate-pf blank-screen">
<h1 translate>No Matching Results</h1>
<p>
<a id="clear-all-filters" href="#" translate>Clear All Filters</a>
</p>
</div>
</script>

<script id="repeat-hourly-tmpl" type="x-template/mustache">
{{#repeat}}
<div class="form-inline">
Expand Down
8 changes: 4 additions & 4 deletions test/avocado/selenium-base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ def test30ChangeTabServices(self):
self.login()
self.click(self.wait_link('Services', cond=clickable))
self.wait_frame("services")
self.wait_id("services-list-enabled")
self.wait_id("services-list")
self.click(self.wait_text("Socket", cond=clickable))
self.wait_text("udev")
self.wait_id("services-list-enabled")
self.wait_id("services-list")
self.click(self.wait_text("Target", cond=clickable))
self.wait_id("services-list-enabled")
self.wait_id("services-list")
self.wait_text("reboot.target")
self.click(self.wait_text("System Services", cond=clickable))
self.wait_id("services-list-enabled")
self.wait_id("services-list")
self.wait_text("sshd.service")
self.mainframe()

Expand Down
Loading