Implement column ordering + variable columns (need conf tool in the prfs window)

This commit is contained in:
Benjamin Drieu 2021-11-19 17:46:36 +01:00 committed by Benjamin Drieu
parent 0ab8b79ae1
commit 4a66c46042
6 changed files with 216 additions and 80 deletions

View File

@ -46,6 +46,7 @@ const SETTINGS_SCHEMA_ACCOUNT = "org.gnome.shell.extensions.monito.account";
const SETTINGS_SCHEMA_ACCOUNT_PATH = "/org/gnome/shell/extensions/monito/account";
const Convenience = Me.imports.convenience;
const GenericServer = Me.imports.servers.genericserver.GenericServer;
const Icinga = Me.imports.servers.icinga.Icinga;
const Icinga2 = Me.imports.servers.icinga2.Icinga2;
const Preferences = Me.imports.prefs;
@ -53,14 +54,14 @@ const Preferences = Me.imports.prefs;
let settings = Convenience.getSettings(SETTINGS_SCHEMA);
let account_settings = [ ];
const column_definitions = [
{ name: 'status', width: 50, expand: false, },
{ name: 'host_name', width: 300, expand: false, },
{ name: 'service_display_name', width: 300, expand: false, },
{ name: 'last_check', width: 200, expand: false, },
{ name: 'attempts', width: 50, expand: false, },
{ name: 'status_information', width: 600, expand: true, },
];
const column_definitions = {
status: { label: _('Status'), width: 50, expand: false, },
host_name: { label: _('Host name'), width: 300, expand: false, },
service_display_name: { label: _('Service'), width: 300, expand: false, },
last_check: { label: _('Last check'), width: 200, expand: false, },
attempts: { label: _('Attempts'), width: 50, expand: false, },
status_information: { label: _('Information'), width: 600, expand: true, },
};
const Indicator = GObject.registerClass(
@ -77,6 +78,16 @@ class Indicator extends PanelMenu.Button {
this.criticalBoxes = { };
this.unknownBoxes = { };
this.sortIcons = { };
account_settings [ server ] = Preferences.getAccountSettings ( this.server );
this.account_settings = account_settings [ server ];
let type = this.account_settings.get_string ( "type" );
if ( type == 'Icinga' )
this.serverlogic = new Icinga ( this.server );
else if ( type == 'Icinga2' )
this.serverlogic = new Icinga2 ( this.server );
this.initUI ( );
}
@ -85,32 +96,30 @@ class Indicator extends PanelMenu.Button {
this.add_child(box);
monitoLog ( '> Server ' + this.server );
account_settings [ this.server ] = Preferences.getAccountSettings ( this.server );
let _account_settings = account_settings [ this.server ];
let serverBox = new St.BoxLayout ( { style_class: 'monito-serverbox' } );
box.add_child(serverBox);
let name_box = new St.BoxLayout( { style_class: 'monito-namebox' } );
this.namesBoxes [ this.server ] = new St.Label ( { text: _account_settings.get_string ( 'name' ) } );
this.namesBoxes [ this.server ] = new St.Label ( { text: this.account_settings.get_string ( 'name' ) } );
name_box.add_child ( this.namesBoxes [ this.server ] );
serverBox.add_child(name_box);
_account_settings.bind ( 'name', this.namesBoxes [ this.server ], 'text', Gio.SettingsBindFlags.GET );
this.account_settings.bind ( 'name', this.namesBoxes [ this.server ], 'text', Gio.SettingsBindFlags.GET );
this.namesBoxes [ this.server ].connect ( 'button-press-event', Lang.bind ( this, function ( ) { this.setMenu ( this.menu ); } ) );
let warning_box = new St.BoxLayout({ style_class: 'monito-warning-box monito-box' });
warning_box.set_style ( 'background-color: ' + _account_settings.get_string ( 'warning-color' ) );
_account_settings.connect("changed::warning-color", Lang.bind ( { widget: warning_box }, setColor ) );
warning_box.set_style ( 'background-color: ' + this.account_settings.get_string ( 'warning-color' ) );
this.account_settings.connect("changed::warning-color", Lang.bind ( { widget: warning_box }, setColor ) );
this.warningBoxes [ this.server ] = new St.Label({ text: String(_status['WARNING']) })
warning_box.add_child ( this.warningBoxes [ this.server ] );
serverBox.add_child(warning_box);
let critical_box = new St.BoxLayout({ style_class: 'monito-critical-box monito-box' });
critical_box.set_style ( 'background-color: ' + _account_settings.get_string ( 'critical-color' ) );
_account_settings.connect("changed::critical-color", Lang.bind ( { widget: critical_box }, setColor ) );
critical_box.set_style ( 'background-color: ' + this.account_settings.get_string ( 'critical-color' ) );
this.account_settings.connect("changed::critical-color", Lang.bind ( { widget: critical_box }, setColor ) );
this.criticalBoxes [ this.server ] = new St.Label({ text: String(_status['CRITICAL']) })
critical_box.add_child ( this.criticalBoxes [ this.server ] );
@ -135,7 +144,7 @@ class Indicator extends PanelMenu.Button {
_iconBin.child = _icon;
this._buttonMenu.actor.add_actor(_iconBin);
this._mainLabel = new St.Label({ style_class: 'monito-title', text: 'Monito Checker', x_expand: true });
this._mainLabel = new St.Label ( { style_class: 'monito-title', text: 'Monito Checker', x_expand: true } );
this._buttonMenu.actor.add_actor(this._mainLabel);
this._prefsButton = this._createButton ( 'preferences-system-symbolic', 'Preferences', this._onPreferencesActivate );
@ -184,57 +193,63 @@ class Indicator extends PanelMenu.Button {
updateStatus ( )
{
for ( let _server of Preferences.getServersList() )
if ( ! this.serverlogic.refresh ( this ) )
{
let _account_settings = Preferences.getAccountSettings ( this.server );
let type = _account_settings.get_string("type");
let username = _account_settings.get_string("username");
let password = _account_settings.get_string("password");
let urlcgi = _account_settings.get_string("urlcgi");
if ( ! urlcgi )
{
monitoLog ( 'Not updating monito because no URL configured' );
}
else
{
let _serverLogic;
if ( type == 'Icinga' )
_serverLogic = new Icinga ( this.server );
else if ( type == 'Icinga2' )
_serverLogic = new Icinga2 ( this.server );
if ( ! _serverLogic.refresh ( this ) )
{
this.warningBoxes[this.server].set_text ( '…' );
this.criticalBoxes[this.server].set_text ( '…' );
// TODO: Add display of error if any
}
}
this.warningBoxes[this.server].set_text ( '…' );
this.criticalBoxes[this.server].set_text ( '…' );
}
this.setupTimeout ( );
}
createHeaderBin ( status, text, col ) {
let _widths = [ 300, 300, 200, 50, 600 ];
let _bin = new St.Bin({
style_class: 'monito-service-' + status,
width: col.width,
x_expand: col.expand,
child: new St.Button ( {
createHeaderBin ( colName ) {
let col = column_definitions [ colName ];
let _box = new St.BoxLayout ( { vertical: false,
x_expand: true } );
_box.add_child ( new St.Label ( { text: col.label,
x_expand: true,
x_align: Clutter.ActorAlign.START } ) );
let _iconBin = new St.Bin ( { x_align: Clutter.ActorAlign.END });
_box.add_child ( _iconBin );
let _iconName = '';
let _sortOrder = Preferences.getSortOrder ( this.server );
if ( _sortOrder.indexOf ( colName + '+' ) >= 0 )
_iconName = 'view-sort-descending-symbolic';
else if ( _sortOrder.indexOf ( colName + '-' ) >= 0 )
_iconName = 'view-sort-ascending-symbolic';
this.sortIcons [ colName ] = new St.Icon ( {
style_class: 'monito-button-icon',
icon_name: _iconName,
icon_size: 16,
} );
_iconBin.child = this.sortIcons [ colName ];
let _button = new St.Button ( {
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER,
width: col.width,
reactive: true,
can_focus: true,
track_hover: true,
accessible_name: text,
accessible_name: col.label,
style_class: 'button',
label: col.name,
})
} );
_button.column = colName;
_button.add_actor ( _box );
_button.connect ( 'clicked', Lang.bind ( this, this._onSortColumnClick ) );
let _bin = new St.Bin({
style_class: 'monito-service',
width: col.width,
x_expand: col.expand,
child: _button,
});
return _bin;
}
@ -249,14 +264,14 @@ class Indicator extends PanelMenu.Button {
return _bin;
}
refreshUI ( serverLogic ) {
this.initStatus ( ); // Specialize !
refreshUI ( ) {
this.initStatus ( );
this._box.remove_all_children();
if ( serverLogic.error )
if ( this.serverlogic.error )
{
this._box.add_child ( new St.Label ( { style_class: 'monito-network-error', text: serverLogic.error } ) );
this._box.add_child ( new St.Label ( { style_class: 'monito-network-error', text: this.serverlogic.error } ) );
return;
}
@ -265,8 +280,10 @@ class Indicator extends PanelMenu.Button {
x_expand: true
});
this._box.add_child(headerBox);
for ( let col of column_definitions )
headerBox.add_child ( this.createHeaderBin ( '', col.name, col ) );
let _columns = Preferences.getColumns ( this.server );
for ( let _col of _columns )
headerBox.add_child ( this.createHeaderBin ( _col ) );
let scrollBox = new St.ScrollView ( { hscrollbar_policy: St.PolicyType.NEVER,
enable_mouse_scrolling: true, } );
@ -279,29 +296,28 @@ class Indicator extends PanelMenu.Button {
});
scrollBox.add_actor(tableBox);
for ( let i = 0 ; i < serverLogic.status.service_status.length ; i ++ )
for ( let entry of this.serverlogic.getProcessedStatus ( ) )
{
_status [ serverLogic.status.service_status[i].status ] ++;
if ( serverLogic.status.service_status[i].status != 'OK' )
_status [ entry.status ] ++;
if ( entry.status != 'OK' )
{
let infoBox = new St.BoxLayout({
style_class: 'monito-service-line monito-service-line-' + serverLogic.status.service_status[i].status,
style_class: 'monito-service-line monito-service-line-' + entry.status,
track_hover: true,
x_expand: true,
});
tableBox.add_child(infoBox);
for ( let col of column_definitions )
let _columns = Preferences.getColumns ( this.server );
for ( let _col of _columns )
{
infoBox.add_child ( this.createBin ( serverLogic.status.service_status[i].status,
serverLogic.status.service_status[i][col.name],
col ) );
infoBox.add_child ( this.createBin ( entry.status, entry [ _col ], column_definitions [ _col ] ) );
}
}
}
this.warningBoxes[serverLogic.server].set_text ( String(_status.WARNING) );
this.criticalBoxes[serverLogic.server].set_text ( String(_status.CRITICAL) );
this.warningBoxes[this.serverlogic.server].set_text ( String(_status.WARNING) );
this.criticalBoxes[this.serverlogic.server].set_text ( String(_status.CRITICAL) );
return;
}
@ -319,6 +335,26 @@ class Indicator extends PanelMenu.Button {
return 0;
}
_onSortColumnClick ( button ) {
monitoLog ( 'column >> ' + button.column );
let _sortOrder = Preferences.getSortOrder ( this.server );
let _columns = Preferences.getColumns ( this.server );
let _indexPlus = _sortOrder.indexOf ( button.column + '+' );
let _indexMinus = _sortOrder.indexOf ( button.column + '-' );
if ( _indexPlus >= 0 )
_sortOrder [ _indexPlus ] = button.column + '-';
else if ( _indexMinus >= 0 )
_sortOrder.splice ( _indexMinus, 1 );
else
_sortOrder.unshift ( button.column + '+' );
Preferences.setSortOrder ( this.server, _sortOrder );
this.refreshUI ( );
}
_createButton ( icon, text, callback ) {
let button = new St.Button({
x_align: Clutter.ActorAlign.END,

View File

@ -174,6 +174,30 @@ function getAccountSettings ( id )
}
function getSortOrder ( server )
{
return this.getAccountSettings ( server ) . get_strv ( 'columns-order' );
}
function setSortOrder ( server, sort_order )
{
return this.getAccountSettings ( server ) . set_strv ( 'columns-order', sort_order );
}
function getColumns ( server )
{
return this.getAccountSettings ( server ) . get_strv ( 'columns' );
}
function setColumns ( server, columns )
{
return this.getAccountSettings ( server ) . set_strv ( 'columns', columns );
}
function createAccountWidgets ( isActive )
{
// Accounts

View File

@ -93,11 +93,11 @@
</key>
<key name="columns" type="as">
<default>['service_description']</default>
<default>['status','host_name','service_display_name','last_check','attempts','status_information']</default>
</key>
<key name="columns-order" type="ai">
<default>[0]</default>
<key name="columns-order" type="as">
<default>['host_name+','service_display_name+']</default>
</key>
</schema>

76
servers/genericserver.js Normal file
View File

@ -0,0 +1,76 @@
/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Monito Gnome-Shell extension
Copyright (C) 2021 Benjamin Drieu
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
SPDX-License-Identifier: GPL-2.0-or-later
*/
const { Soup } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Lang = imports.lang;
const Main = imports.ui.main;
const Me = ExtensionUtils.getCurrentExtension();
const Preferences = Me.imports.prefs;
let _httpSession;
class GenericServer {
constructor ( _server, _serverType = 'Generic' )
{
log ( '>>> New %s server #%s'.format ( _serverType, _server ) );
this.server = _server;
}
getProcessedStatus ( )
{
let status = this.status.service_status;
this.columns = Preferences.getColumns(this.server);
this.sortOrder = Preferences.getSortOrder(this.server);
log ( this.sortOrder );
status = status.sort ( Lang.bind ( this, this.compareServices ) );
return status;
}
compareServices ( a, b )
{
for ( let _comparison of this.sortOrder )
{
let _name = _comparison.substring ( 0, _comparison.length - 1 );
let _order = _comparison.substring ( _comparison.length - 1, _comparison.length );
if ( _name && _order && _name in a && _name in b )
{
let _result = a [ _name ] . localeCompare ( b [ _name ] );
if ( _result != 0 )
{
if ( _order == '-' )
return - _result;
else
return _result;
}
}
}
return 0;
}
}

View File

@ -27,14 +27,14 @@ const Lang = imports.lang;
const Main = imports.ui.main;
const Me = ExtensionUtils.getCurrentExtension();
const Preferences = Me.imports.prefs;
const GenericServer = Me.imports.servers.genericserver.GenericServer;
let _httpSession;
class Icinga {
class Icinga extends GenericServer {
constructor ( _server ) {
log ( '>>> New Icinga #' + _server );
this.server = _server
super(_server, 'Icinga');
}
refresh ( extension ) {

View File

@ -27,15 +27,15 @@ const Lang = imports.lang;
const Main = imports.ui.main;
const Me = ExtensionUtils.getCurrentExtension();
const Preferences = Me.imports.prefs;
const GenericServer = Me.imports.servers.genericserver.GenericServer;
let _httpSession;
class Icinga2 {
class Icinga2 extends GenericServer {
constructor ( _server ) {
log ( '>>> New Icinga2 #' + _server );
this.server = _server
}
super(_server, 'Icinga2');
}
refresh ( extension ) {
this.extension = extension;