429 lines
16 KiB
JavaScript
429 lines
16 KiB
JavaScript
/* -*- 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 Gio = imports.gi.Gio;
|
|
const GLib = imports.gi.GLib;
|
|
const Gtk = imports.gi.Gtk;
|
|
const Gdk = imports.gi.Gdk;
|
|
|
|
// It's common practice to keep GNOME API and JS imports in separate blocks
|
|
const Lang = imports.lang;
|
|
const ExtensionUtils = imports.misc.extensionUtils;
|
|
const Me = ExtensionUtils.getCurrentExtension();
|
|
const Convenience = Me.imports.convenience;
|
|
const Mainloop = imports.mainloop;
|
|
|
|
const Gettext = imports.gettext.domain('monito');
|
|
const _ = Gettext.gettext;
|
|
const N_ = function (e) {
|
|
return e;
|
|
};
|
|
|
|
const SETTINGS_SCHEMA = "org.gnome.shell.extensions.monito";
|
|
const SETTINGS_SCHEMA_ACCOUNT = "org.gnome.shell.extensions.monito.account";
|
|
const SETTINGS_SCHEMA_ACCOUNT_PATH = "/org/gnome/shell/extensions/monito/account";
|
|
|
|
|
|
const prefs = [
|
|
{ type: Gtk.Entry, category: 'Settings', label: _('Name'), key: 'name' },
|
|
{ type: Gtk.ComboBoxText, category: 'Settings', label: _('Type'), key: 'type' },
|
|
{ type: Gtk.Entry, category: 'Settings', label: _('Username'), key: 'username' },
|
|
{ type: Gtk.Entry, category: 'Settings', label: _('Password'), key: 'password' },
|
|
{ type: Gtk.Entry, category: 'Settings', label: _('URL CGI'), key: 'urlcgi' },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('OK background color'), key: 'ok-color', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Warning background color'), key: 'warning-color', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Critical background color'), key: 'critical-color', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Unknown background color'), key: 'unknown-color', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Pending background color'), key: 'pending-color', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('OK color'), key: 'ok-fg', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Warning color'), key: 'warning-fg', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Critical color'), key: 'critical-fg', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Unknown color'), key: 'unknown-fg', align: Gtk.Align.START },
|
|
{ type: Gtk.ColorButton, category: 'Colors', label: _('Pending color'), key: 'pending-fg', align: Gtk.Align.START },
|
|
{ type: Gtk.Switch, category: 'Filters', label: _('Do <b>not</b> display acknowledged services'), key: 'acknowledged-filter-out', align: Gtk.Align.START },
|
|
{ type: Gtk.Entry, category: 'Filters', label: _('Only display hosts matching'), key: 'host-grep' },
|
|
{ type: Gtk.Entry, category: 'Filters', label: _('Only display services matching'), key: 'service-grep' },
|
|
{ type: Gtk.Entry, category: 'Filters', label: _('Only display status info matching'), key: 'status-info-grep' },
|
|
{ type: Gtk.Entry, category: 'Filters', label: _('Do <b>not</b> display hosts matching'), key: 'host-filter-out' },
|
|
{ type: Gtk.Entry, category: 'Filters', label: _('Do <b>not</b> display services matching'), key: 'service-filter-out' },
|
|
{ type: Gtk.Entry, category: 'Filters', label: _('Do <b>not</b> display status info matching'), key: 'status-info-filter-out' },
|
|
{ type: Gtk.Entry, category: 'Replacements', label: _('Host regexp ...'), key: 'host-match' },
|
|
{ type: Gtk.Entry, category: 'Replacements', label: _('... to replace with'), key: 'host-replace' },
|
|
{ type: Gtk.Entry, category: 'Replacements', label: _('Service regexp ...'), key: 'service-match' },
|
|
{ type: Gtk.Entry, category: 'Replacements', label: _('... to replace with'), key: 'service-replace' },
|
|
{ type: Gtk.Entry, category: 'Replacements', label: _('Status info regexp ...'), key: 'status-info-match' },
|
|
{ type: Gtk.Entry, category: 'Replacements', label: _('... to replace with'), key: 'status-info-replace' },
|
|
];
|
|
|
|
|
|
// Like 'extension.js' this is used for any one-time setup like translations.
|
|
function init() {
|
|
monitoLog('initializing ${Me.metadata.name} Preferences');
|
|
this.settings = ExtensionUtils.getSettings(SETTINGS_SCHEMA);
|
|
monitoLog ( 'Foo: ' + Me.metadata );
|
|
}
|
|
|
|
|
|
// This function is called when the preferences window is first created to build
|
|
// and return a Gtk widget. As an example we'll create and return a GtkLabel.
|
|
function buildPrefsWidget() {
|
|
|
|
// Copy the same GSettings code from `extension.js`
|
|
this.settings = ExtensionUtils.getSettings(SETTINGS_SCHEMA);
|
|
|
|
let mainVbox = new Gtk.Box( { orientation: Gtk.Orientation.VERTICAL } );
|
|
|
|
let mainWidget = new Gtk.Notebook( { } );
|
|
|
|
let prefsWidget = new Gtk.Grid({
|
|
margin: 18,
|
|
column_spacing: 12,
|
|
row_spacing: 12,
|
|
column_homogeneous: false,
|
|
});
|
|
|
|
this.prefWidgets = { };
|
|
|
|
// Add a simple title and add it to the prefsWidget
|
|
let title = new Gtk.Label({
|
|
label: `<b>${Me.metadata.name} Preferences</b>`,
|
|
halign: Gtk.Align.START,
|
|
use_markup: true,
|
|
});
|
|
prefsWidget.attach(title, 0, 0, 2, 1);
|
|
|
|
let _label = new Gtk.Label({
|
|
label: 'Poll delay in seconds',
|
|
visible: true,
|
|
halign: Gtk.Align.START,
|
|
});
|
|
prefsWidget.attach ( _label, 0, 1, 1, 1 );
|
|
|
|
let _entry = new Gtk.SpinButton ({
|
|
numeric: true,
|
|
halign: Gtk.Align.FILL,
|
|
visible: true,
|
|
hexpand: true,
|
|
can_focus: true,
|
|
});
|
|
_entry.set_range ( 1, 1000 );
|
|
_entry.set_increments ( 1, 5 );
|
|
prefsWidget.attach ( _entry, 1, 1, 1, 1 );
|
|
this.settings.bind ( 'poll-delay', _entry, 'value', Gio.SettingsBindFlags.DEFAULT );
|
|
|
|
// Misc Settings (TBD)
|
|
mainWidget.append_page ( prefsWidget,
|
|
new Gtk.Label ( { label: 'General', } ) );
|
|
|
|
|
|
// Accounts
|
|
this._accountsWidgetContainer = new Gtk.Box( { orientation: Gtk.Orientation.HORIZONTAL,
|
|
homogeneous: false, } );
|
|
mainWidget.append_page ( this._accountsWidgetContainer,
|
|
new Gtk.Label ( { label: 'Servers', } ) );
|
|
|
|
let accountsChooserContainer = new Gtk.Box( { orientation: Gtk.Orientation.VERTICAL,
|
|
homogeneous: false, } );
|
|
this._accountsWidgetContainer.pack_start(accountsChooserContainer, true, true, 0);
|
|
|
|
this.accountsChooser = new Gtk.ListBox ( { valign: Gtk.Align.FILL,
|
|
hexpand: true,
|
|
vexpand: true } );
|
|
accountsChooserContainer.pack_start(this.accountsChooser, true, true, 0);
|
|
|
|
// Account list
|
|
for ( var server_id of this.getServersList ( ) )
|
|
this.addAccountLine ( server_id );
|
|
this.accountsChooser.connect ( 'row-activated', Lang.bind ( this, this.activateAccountRow ) );
|
|
|
|
// Action Bar
|
|
let accountsChooserActionBar = new Gtk.ActionBar ( { valign: Gtk.Align.END } );
|
|
accountsChooserContainer.pack_start(accountsChooserActionBar, true, true, 0);
|
|
|
|
let accountCreateButton = Gtk.Button.new_from_icon_name ( 'list-add',
|
|
Gtk.IconSize.BUTTON );
|
|
accountsChooserActionBar.add ( accountCreateButton );
|
|
accountCreateButton.connect ( 'clicked', Lang.bind ( this, this.createAccount ) );
|
|
|
|
let accountRemoveButton = Gtk.Button.new_from_icon_name ( 'list-remove',
|
|
Gtk.IconSize.BUTTON );
|
|
accountsChooserActionBar.add ( accountRemoveButton );
|
|
accountRemoveButton.connect ( 'clicked', Lang.bind ( this, this.removeAccount ) );
|
|
|
|
this.createAccountWidgets ( false ) ;
|
|
|
|
mainVbox.pack_start(mainWidget, true, true, 0);
|
|
mainVbox.show_all();
|
|
|
|
return mainVbox;
|
|
}
|
|
|
|
|
|
function getServersList ( )
|
|
{
|
|
if ( ! this.settings )
|
|
this.settings = ExtensionUtils.getSettings(SETTINGS_SCHEMA);
|
|
|
|
return this.settings.get_string ( 'servers' ) . split ( ',' );
|
|
}
|
|
|
|
|
|
function getAccountSettings ( id )
|
|
{
|
|
let _path = SETTINGS_SCHEMA_ACCOUNT_PATH + '/' + id + '/';
|
|
return Convenience.getSettings(SETTINGS_SCHEMA_ACCOUNT, _path);
|
|
}
|
|
|
|
|
|
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 )
|
|
{
|
|
this.prefWidgets = { };
|
|
|
|
this._accountsWidget = new Gtk.Notebook( { } );
|
|
this._accountsWidgetContainer.pack_start(this._accountsWidget, true, true, 0);
|
|
|
|
for ( var _tab of [ 'Settings', 'Colors', 'Filters', 'Replacements' ] )
|
|
{
|
|
this.createPrefWidgets ( _accountsWidget, _tab, isActive );
|
|
}
|
|
|
|
// Settings
|
|
this.prefWidgets['name'].connect('changed', Lang.bind(this, function () {
|
|
let _row = this.accountsChooser.get_selected_row();
|
|
_row.get_child().label = this.prefWidgets['name'].text;
|
|
} ) );
|
|
|
|
|
|
this._accountsWidget.show_all();
|
|
}
|
|
|
|
|
|
function createPrefWidgets ( noteBook, type, isActive )
|
|
{
|
|
let grid = new Gtk.Grid ( {
|
|
halign: Gtk.Align.FILL,
|
|
margin: 18,
|
|
column_spacing: 12,
|
|
row_spacing: 12,
|
|
visible: true,
|
|
column_homogeneous: false,
|
|
});
|
|
noteBook.append_page ( grid, new Gtk.Label ( { label: _(type), } ) );
|
|
|
|
let y = 0;
|
|
for ( var prefEntry of prefs )
|
|
{
|
|
if ( prefEntry.category != type )
|
|
continue;
|
|
|
|
let _label = new Gtk.Label({
|
|
label: prefEntry.label + ':',
|
|
visible: true,
|
|
halign: Gtk.Align.START,
|
|
use_markup: true,
|
|
});
|
|
grid.attach ( _label, 0, y, 1, 1 );
|
|
|
|
this.prefWidgets[prefEntry.key] = new prefEntry.type ( {
|
|
halign: ( prefEntry.align ? prefEntry.align : Gtk.Align.FILL ),
|
|
visible: true,
|
|
hexpand: true,
|
|
can_focus: isActive,
|
|
} );
|
|
|
|
let boundValue = 'text';
|
|
if ( prefEntry.key == 'password' )
|
|
{
|
|
this.prefWidgets[prefEntry.key].set_input_purpose ( Gtk.InputPurpose.PASSWORD );
|
|
this.prefWidgets[prefEntry.key].set_visibility ( false );
|
|
}
|
|
else if ( prefEntry.key == 'type' )
|
|
{
|
|
[ { name: 'Icinga', value: 'Icinga server' },
|
|
{ name: 'Icinga2API', value: 'Icinga2 server (using API, prefered)' },
|
|
{ name: 'Icinga2', value: 'Icinga2 server (using Icingaweb2, limited)' } ].forEach((item) => {
|
|
this.prefWidgets[prefEntry.key].insert ( -1, item.name, item.value );
|
|
} );
|
|
}
|
|
|
|
grid.attach(this.prefWidgets[prefEntry.key], 1, y, 1, 1);
|
|
|
|
if ( prefEntry.type != Gtk.ComboBoxText )
|
|
{
|
|
// this.account_settings.bind(
|
|
// prefEntry.key,
|
|
// _entry,
|
|
// boundValue,
|
|
// Gio.SettingsBindFlags.DEFAULT
|
|
// );
|
|
}
|
|
y++;
|
|
}
|
|
}
|
|
|
|
function activateAccountRow ( ) {
|
|
|
|
if ( this._accountsWidget )
|
|
this._accountsWidget.destroy ( );
|
|
this.createAccountWidgets ( true );
|
|
|
|
let _row = this.accountsChooser.get_selected_row();
|
|
monitoLog('Active:' + _row.server);
|
|
let _account_settings = getAccountSettings ( _row.server );
|
|
|
|
if ( ! _account_settings )
|
|
return;
|
|
|
|
for ( var prefEntry of prefs )
|
|
{
|
|
if ( prefEntry.type == Gtk.Entry )
|
|
{
|
|
_account_settings.bind (
|
|
prefEntry.key,
|
|
this.prefWidgets[prefEntry.key],
|
|
'text',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
);
|
|
}
|
|
else if ( prefEntry.type == Gtk.Switch )
|
|
{
|
|
_account_settings.bind (
|
|
prefEntry.key,
|
|
this.prefWidgets[prefEntry.key],
|
|
'active',
|
|
Gio.SettingsBindFlags.DEFAULT
|
|
);
|
|
}
|
|
else if ( prefEntry.type == Gtk.ColorButton )
|
|
{
|
|
let _color = new Gdk.RGBA ( );
|
|
_color.parse (_account_settings.get_string(prefEntry.key) );
|
|
this.prefWidgets[prefEntry.key].set_use_alpha ( false );
|
|
this.prefWidgets[prefEntry.key].set_rgba ( _color );
|
|
this.prefWidgets[prefEntry.key].connect('color-set', Lang.bind ( { key: prefEntry.key, settings: _account_settings }, setColor ) );
|
|
}
|
|
else if ( prefEntry.type == Gtk.ComboBoxText )
|
|
{
|
|
this.prefWidgets[prefEntry.key].set_active(_account_settings.get_enum('type'));
|
|
this.prefWidgets[prefEntry.key].connect('changed', Lang.bind(this, function (e) {
|
|
monitoLog ( e ) ;
|
|
monitoLog('Active:' + this.prefWidgets['type'].get_active());
|
|
let _account_settings = getAccountSettings ( _row.server );
|
|
_account_settings.set_enum('type', this.prefWidgets['type'].get_active());
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function addAccountLine ( server_id )
|
|
{
|
|
monitoLog ( '> Add line ' + server_id );
|
|
let _account_settings = getAccountSettings ( server_id );
|
|
let row = new Gtk.ListBoxRow ( { hexpand: true,
|
|
halign: Gtk.Align.FILL } );
|
|
row.server = server_id;
|
|
|
|
let _label = new Gtk.Label ( { label: _account_settings.get_string('name'),
|
|
hexpand: true,
|
|
margin: 5,
|
|
halign: Gtk.Align.START,
|
|
expand: true } );
|
|
row.add ( _label );
|
|
this.accountsChooser.add ( row );
|
|
this.accountsChooser.show_all();
|
|
}
|
|
|
|
|
|
function createAccount ( ) {
|
|
monitoLog ( '> Create Account' );
|
|
|
|
let _servers = this.getServersList ( );
|
|
let _max = Math.max ( ..._servers );
|
|
let _server_id = _max + 1;
|
|
_servers.push ( _server_id );
|
|
|
|
let _account_settings = getAccountSettings ( _server_id );
|
|
_account_settings.set_string ( 'name', _('New server #') + _server_id );
|
|
|
|
this.addAccountLine ( _max + 1 );
|
|
this.settings.set_string ( 'servers', _servers.join(',') );
|
|
}
|
|
|
|
|
|
function removeAccount ( ) {
|
|
let _row = this.accountsChooser.get_selected_row();
|
|
monitoLog('Active:' + _row.server);
|
|
|
|
let _servers = this.getServersList ( );
|
|
_servers.splice ( _servers.indexOf ( _row.server ), 1 );
|
|
monitoLog ( _servers );
|
|
|
|
if ( ! _row )
|
|
return;
|
|
|
|
_row.destroy();
|
|
this.settings.set_string ( 'servers', _servers . join ( ',' ) );
|
|
}
|
|
|
|
|
|
function setColor ( color )
|
|
{
|
|
monitoLog ( 'Color ' + + ': ' + color );
|
|
let _output = '#%02x%02x%02x'.format(
|
|
255 * color.get_rgba().red,
|
|
255 * color.get_rgba().green,
|
|
255 * color.get_rgba().blue );
|
|
this.settings.set_string('' + this.key, _output);
|
|
|
|
}
|
|
|
|
|
|
function monitoLog ( msg )
|
|
{
|
|
log ( 'Monito: ' + msg );
|
|
}
|