Implement natural date + fixes

This commit is contained in:
Benjamin Drieu 2021-12-06 11:34:55 +01:00
parent f18d8bbd61
commit 5cfb752943
7 changed files with 136 additions and 22 deletions

View File

@ -62,8 +62,8 @@ const column_definitions = {
has_been_acknowledged: { label: _('Ack'), width: 50, expand: false, align: Clutter.ActorAlign.CENTER, style: 'font-weight:bold;' },
last_check: { label: _('Last check'), width: 200, expand: false, type: 'date' },
attempts: { label: _('Attempts'), width: 50, expand: false, },
status_information: { label: _('Information'), width: 600, expand: true, },
actions: { label: 'Actions', width: 100, expand: true, special: 'actions' },
status_information: { label: _('Information'), width: 600, expand: false, },
actions: { label: 'Actions', width: 120, expand: false, special: 'actions' },
};
@ -144,16 +144,19 @@ 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 );
this._prefsButton = this._createButton ( 'preferences-system-symbolic', _('Preferences'), this._onPreferencesActivate );
this._buttonMenu.actor.add_child (this._prefsButton);
this._updateButton = this._createButton ( 'emblem-synchronizing-symbolic', 'Reload', this.updateStatus ); // Implement this
this._buttonMenu.actor.add_child (this._updateButton );
if ( this.serverLogic && this.serverLogic.canRecheck )
{
this._recheckButton = this._createButton ( 'system-run-symbolic', _('Recheck all'), this.recheckAll );
this._buttonMenu.actor.add_child (this._recheckButton );
}
this._reloadButton = this._createButton ( 'view-refresh-symbolic', 'Reload', this.updateStatus );
this._reloadButton = this._createButton ( 'view-refresh-symbolic', _('Reload view'), this.updateStatus );
this._buttonMenu.actor.add_child (this._reloadButton );
let _intermediate = new PopupMenu.PopupBaseMenuItem ( {
@ -194,6 +197,12 @@ class Indicator extends PanelMenu.Button {
'UNKNOWN': 0 };
}
recheckAll ( )
{
this.spinChildOf ( this._recheckButton );
this.serverLogic.recheckAll ( this._recheckButton );
}
updateStatus ( )
{
this.spinChildOf ( this._reloadButton );
@ -262,7 +271,7 @@ class Indicator extends PanelMenu.Button {
_iconBin.child = this.sortIcons [ colName ];
let _button = new St.Button ( {
x_align: Clutter.ActorAlign.START,
x_align: Clutter.ActorAlign.FILL,
y_align: Clutter.ActorAlign.CENTER,
width: col.width,
reactive: true,
@ -294,24 +303,28 @@ class Indicator extends PanelMenu.Button {
if ( ! col [ 'special' ] )
_child = new St.Label ( { style_class: 'monito-label',
width: col.width,
text: text.toString(),
x_align: ( col.align ? col.align : Clutter.ActorAlign.START ),
style: ( col.style ? col.style : '' ) } );
else if ( col.special == 'actions' && this.serverLogic.canRecheck )
{
_child = new St.BoxLayout ( { x_expand: false,
vertical: false } );
_child = new St.BoxLayout ( { x_expand: true,
vertical: false,
width: col.width, } );
let _button = new St.Button ( {
style_class: 'button small-button',
x_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
width: 24,
height: 24,
can_focus: true,
} );
_button.service = text;
_button.connect ( 'clicked', Lang.bind ( this, this._onRecheckButtonClick ) );
_button.child = new St.Icon ( {
icon_name: 'view-refresh-symbolic',
icon_name: 'system-run-symbolic',
icon_size: 16,
width: 16,
height: 16,
@ -320,7 +333,6 @@ class Indicator extends PanelMenu.Button {
}
let _bin = new St.Bin({
// style: 'background: purple',
track_hover: true,
width: col.width,
x_expand: col.expand,
@ -374,7 +386,7 @@ class Indicator extends PanelMenu.Button {
}
let headerBox = new St.BoxLayout({
hover: true,
track_hover: true,
x_expand: true
});
this._box.add_child(headerBox);
@ -389,7 +401,7 @@ class Indicator extends PanelMenu.Button {
this._box.add_child(scrollBox);
let tableBox = new St.BoxLayout({
hover: true,
track_hover: true,
vertical: true,
x_expand: true,
});

View File

@ -281,8 +281,8 @@ function createPrefWidgets ( noteBook, type, isActive )
else if ( prefEntry.key == 'type' )
{
[ { name: 'Icinga', value: 'Icinga server' },
{ name: 'Icinga2', value: 'Icinga2 server (using Icingaweb2)' },
{ name: 'Icinga2API', value: 'Icinga2 server (using API)' } ].forEach((item) => {
{ 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 );
} );
}

View File

@ -22,8 +22,8 @@
<schemalist >
<enum id="org.gnome.shell.extensions.monito.MonitoringType">
<value value="0" nick="Icinga"/>
<value value="1" nick="Icinga2"/>
<value value="2" nick="Icinga2API"/>
<value value="1" nick="Icinga2API"/>
<value value="2" nick="Icinga2"/>
</enum>
<enum id="org.gnome.shell.extensions.monito.DisplayType">

View File

@ -224,4 +224,86 @@ class GenericServer {
}
return 0;
}
formatDate ( date )
{
if ( typeof date == 'string' || date instanceof String )
{
date = Date.parse ( date ) / 1000;
log ( date );
}
return this.timeAgo ( new Date ( date * 1000 ) );
}
getFormattedDate(date, prefomattedDate = false, hideYear = false)
{
const MONTH_NAMES = [
'Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.',
'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.'
];
const day = date.getDate();
const month = MONTH_NAMES[date.getMonth()];
const year = date.getFullYear();
const hours = date.getHours();
let minutes = date.getMinutes();
if (minutes < 10) {
// Adding leading zero to minutes
minutes = _(`0${ minutes }`);
}
if (prefomattedDate) {
// Today at 10:20
// Yesterday at 10:20
return _(`${ prefomattedDate } at ${ hours }:${ minutes }`);
}
if (hideYear) {
// 10. January at 10:20
return _(`${ month } ${ day } at ${ hours }:${ minutes }`);
}
// 10. January 2017. at 10:20
return _(`${ year } ${ month } ${ day }`);
}
timeAgo ( dateParam )
{
if (!dateParam) {
return null;
}
const date = typeof dateParam === 'object' ? dateParam : new Date(dateParam);
const DAY_IN_MS = 86400000; // 24 * 60 * 60 * 1000
const today = new Date();
const yesterday = new Date(today - DAY_IN_MS);
const seconds = Math.round((today - date) / 1000);
const minutes = Math.round(seconds / 60);
const isToday = today.toDateString() === date.toDateString();
const isYesterday = yesterday.toDateString() === date.toDateString();
const isThisYear = today.getFullYear() === date.getFullYear();
if (seconds < 5) {
return 'now';
} else if (seconds < 60) {
return `${ seconds } seconds ago`;
} else if (seconds < 90) {
return 'a minute ago';
} else if (minutes < 60) {
return `${ minutes } minutes ago`;
} else if (isToday) {
return this.getFormattedDate(date, 'today'); // Today at 10:20
} else if (isYesterday) {
return this.getFormattedDate(date, 'yesterday'); // Yesterday at 10:20
} else if (isThisYear) {
return this.getFormattedDate(date, false, true); // 10. January at 10:20
}
return this.getFormattedDate(date); // 10. January 2017. at 10:20
}
}

View File

@ -88,7 +88,11 @@ class Icinga extends GenericServer {
else
{
let json = JSON.parse ( _data );
this.status = json.status;
log ( this.status );
for ( var entry of this.status.service_status )
entry.last_check = this.formatDate ( entry.last_check );
}
this.extension.refreshUI ( this );

View File

@ -71,7 +71,7 @@ class Icinga2 extends GenericServer {
attempts: entry.service_attempt,
has_been_acknowledged: parseInt(entry.service_acknowledged),
status_information: entry.service_output,
last_check: new Date ( parseInt(entry.service_last_state_change) * 1000 ) . toString(),
last_check: this.formatDate(parseInt(entry.service_last_state_change)),
} );
}
}

View File

@ -62,10 +62,25 @@ class Icinga2API extends GenericServer {
message.request_body.flatten();
message.button = entry.button;
// log ( '> Body: ' + message.request_body.data );
message.request_headers.append ( 'Accept', 'application/json' );
// log ( message.request_headers );
this.authenticateAndSend ( message, this.handleCMDMessage );
}
recheckAll ( button )
{
let message = Soup.form_request_new_from_hash ( 'POST', this.urlcgi + '/actions/reschedule-check', { } );
let params = '{ "type": "Service", "force": true, "pretty": true }';
message.request_body.truncate();
message.request_body.append ( params );
message.request_body.flatten();
message.button = button;
message.request_headers.append ( 'Accept', 'application/json' );
log ( message.request_headers );
// log ( message.request_headers );
this.authenticateAndSend ( message, this.handleCMDMessage );
}
@ -84,6 +99,7 @@ class Icinga2API extends GenericServer {
for ( var entry of json.results )
{
// log ( JSON.stringify(entry) );
this.status.service_status.push ( {
status: _statuses [ entry.attrs.state ],
host_name: entry.attrs.host_name,
@ -91,7 +107,7 @@ class Icinga2API extends GenericServer {
has_been_acknowledged: parseInt(entry.attrs.acknowledgement),
attempts: '%d/%d'.format(entry.attrs.check_attempt,entry.attrs.max_check_attempts),
status_information: entry.attrs.last_check_result.output,
last_check: new Date ( entry.attrs.last_state_change * 1000 ) . toString(),
last_check: this.formatDate(parseInt(entry.attrs.last_check)),
} );
}
}