mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
Merge pull request #209 from YunoHost/new-diagnosis-interface
[enh] New diagnosis interface
This commit is contained in:
commit
ca5b2eeecd
12 changed files with 219 additions and 66 deletions
|
@ -101,10 +101,6 @@ button {
|
|||
color: transparent;
|
||||
}
|
||||
|
||||
.label {
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
/*
|
||||
* The top heading of the doc
|
||||
*
|
||||
|
@ -941,3 +937,30 @@ input[type='radio'].nice-radio {
|
|||
-o-transition: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
/* Just to be able to override list-group-item with alert-success's background and border colors */
|
||||
.alert-success-yo {
|
||||
background-color: #dff0d8;
|
||||
border-color: #d6e9c6;
|
||||
}
|
||||
|
||||
.alert-warning-yo {
|
||||
background-color: #fcf8e3;
|
||||
border-color: #faebcc;
|
||||
}
|
||||
|
||||
.alert-danger-yo {
|
||||
background-color: #f2dede;
|
||||
border-color: #ebccd1;
|
||||
}
|
||||
|
||||
.alert-info-yo {
|
||||
background-color: #d9edf7;
|
||||
border-color: #bce8f1;
|
||||
}
|
||||
|
||||
.alert-ignored-yo {
|
||||
background-color: ghostwhite;
|
||||
border-color: lightgrey;
|
||||
color: grey;
|
||||
}
|
||||
|
|
100
src/js/yunohost/controllers/diagnosis.js
Normal file
100
src/js/yunohost/controllers/diagnosis.js
Normal file
|
@ -0,0 +1,100 @@
|
|||
(function() {
|
||||
// Get application context
|
||||
var app = Sammy.apps['#main'];
|
||||
var store = app.store;
|
||||
|
||||
// *********
|
||||
// Diagnosis
|
||||
// *********
|
||||
|
||||
app.get('#/diagnosis', function (c) {
|
||||
c.api('GET', '/diagnosis/show?full', {}, function(data) {
|
||||
|
||||
// Prepare data to be displayed ...
|
||||
for (var i = 0 ; i < data.reports.length ; i++)
|
||||
{
|
||||
// Convert timestamp to datetime
|
||||
data.reports[i].time = new Date(data.reports[i].timestamp*1000);
|
||||
data.reports[i].warnings = 0;
|
||||
data.reports[i].errors = 0;
|
||||
data.reports[i].ignored = 0;
|
||||
for (var j = 0 ; j < data.reports[i].items.length ; j++)
|
||||
{
|
||||
var type_ = data.reports[i].items[j].status;
|
||||
type_ = type_.toLowerCase();
|
||||
var ignored = data.reports[i].items[j].ignored;
|
||||
var icon = "";
|
||||
var issue = false;
|
||||
|
||||
if (type_ == "success") {
|
||||
icon = "check-circle";
|
||||
}
|
||||
else if (ignored == true) {
|
||||
icon = type_;
|
||||
if (type_ == "error") {
|
||||
icon = "times"
|
||||
}
|
||||
type_ = "ignored";
|
||||
data.reports[i].ignored++;
|
||||
}
|
||||
else if (type_ == "warning") {
|
||||
icon = "warning";
|
||||
issue = true;
|
||||
data.reports[i].warnings++;
|
||||
}
|
||||
else if (type_ == "error") {
|
||||
type_ = "danger";
|
||||
icon = "times";
|
||||
issue = true;
|
||||
data.reports[i].errors++;
|
||||
}
|
||||
data.reports[i].items[j].status = type_;
|
||||
data.reports[i].items[j].icon = icon;
|
||||
data.reports[i].items[j].issue = issue;
|
||||
// We want filter_args to be something like "dnsrecords,domain=yolo.test,category=xmpp"
|
||||
data.reports[i].items[j].filter_args = data.reports[i].id;
|
||||
for (prop in data.reports[i].items[j].meta) {
|
||||
data.reports[i].items[j].filter_args = data.reports[i].items[j].filter_args + ","+prop+"="+data.reports[i].items[j].meta[prop];
|
||||
}
|
||||
};
|
||||
data.reports[i].noIssues = data.reports[i].warnings + data.reports[i].errors ? false : true;
|
||||
};
|
||||
|
||||
// Render and display the view
|
||||
c.view('diagnosis/diagnosis_show', data, function() {
|
||||
|
||||
// Configure share with yunopaste button
|
||||
$("button[data-action='share']").click(function() {
|
||||
c.api('GET', '/diagnosis/show?share', {}, function(data) {
|
||||
c.hideLoader();
|
||||
window.open(data.url, '_blank');
|
||||
});
|
||||
});
|
||||
|
||||
// Configure 'rerun diagnosis' button behavior
|
||||
$("button[data-action='rerun-diagnosis']").click(function() {
|
||||
var category = $(this).data("category");
|
||||
c.api('POST', '/diagnosis/run?force', {"categories": [category]}, function(data) {
|
||||
c.refresh();
|
||||
});
|
||||
});
|
||||
|
||||
// Configure 'ignore' / 'unignore' buttons behavior
|
||||
$("button[data-action='ignore']").click(function() {
|
||||
var filter_args = $(this).data("filter-args");
|
||||
c.api('POST', '/diagnosis/ignore', {'add_filter': filter_args.split(',') }, function(data) {
|
||||
c.refresh();
|
||||
})
|
||||
});
|
||||
|
||||
$("button[data-action='unignore']").click(function() {
|
||||
var filter_args = $(this).data("filter-args");
|
||||
c.api('POST', '/diagnosis/ignore', {'remove_filter': filter_args.split(',') }, function(data) {
|
||||
c.refresh();
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
|
@ -251,21 +251,6 @@
|
|||
});
|
||||
});
|
||||
|
||||
// Diagnosis
|
||||
app.get('#/tools/diagnosis(/:private)?', function (c) {
|
||||
// See http://sammyjs.org/docs/routes for splat documentation
|
||||
var private = (c.params.splat[0] == 'private');
|
||||
|
||||
var endurl = (private) ? '?private' : '';
|
||||
c.api('GET', '/diagnosis'+endurl, {}, function(diagnosis) {
|
||||
c.view('tools/tools_diagnosis', {
|
||||
'diagnosis' : JSON.stringify(diagnosis, undefined, 4),
|
||||
'raw' : diagnosis,
|
||||
'private' : private
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Migrations
|
||||
app.get('#/tools/migrations', function (c) {
|
||||
c.api('GET', '/migrations?pending', {}, function(pending_migrations) {
|
||||
|
|
|
@ -69,13 +69,10 @@
|
|||
c.flash('fail', y18n.t('error_retrieve_feed', [securityFeed]));
|
||||
});
|
||||
|
||||
c.api("GET", "/diagnosis", {}, function(data) {
|
||||
versions = data.packages;
|
||||
$('#yunohost-version').html(y18n.t('footer_version', [versions.yunohost.version, versions.yunohost.repo]));
|
||||
if (data.security["CVE-2017-5754"].vulnerable) {
|
||||
c.flash('danger', y18n.t('meltdown'));
|
||||
}
|
||||
c.hideLoader();
|
||||
c.api("GET", "/diagnosis/show?full", {}, function(data) {
|
||||
basesystem = data.reports.filter(function(r) { return r.id == "basesystem"; })[0];
|
||||
version_info = basesystem.items.filter(function(i) { return (i.meta && i.meta.test && i.meta.test == "ynh_versions"); })[0];
|
||||
$('#yunohost-version').html(y18n.t('footer_version', [version_info.data.main_version, version_info.data.repo]));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -525,6 +525,18 @@
|
|||
c.hideLoader();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
force_redirect: function(to) {
|
||||
c = this;
|
||||
// This is a copy-pasta of some of the redirect/refresh code of
|
||||
// sammy.js because for some reason calling the origina
|
||||
// redirect/refresh function in some context does not work >.>
|
||||
// (e.g. if you're already on the page)
|
||||
c.trigger('redirect', {to: to});
|
||||
c.app.last_location = c.path;
|
||||
c.app.setLocation(to);
|
||||
c.app.trigger('location-changed');
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -181,9 +181,10 @@
|
|||
sam.store.set('url', window.location.hostname + '/yunohost/api');
|
||||
|
||||
if (sam.store.get('connected')) {
|
||||
this.api('GET', '/diagnosis', {}, function(diagnosis) {
|
||||
versions = diagnosis.packages;
|
||||
$('#yunohost-version').html(y18n.t('footer_version', [versions.yunohost.version, versions.yunohost.repo]));
|
||||
this.api('GET', '/diagnosis/show?full', {}, function(data) {
|
||||
basesystem = data.reports.filter(function(r) { return r.id == "basesystem"; })[0];
|
||||
version_info = basesystem.items.filter(function(i) { return (i.meta && i.meta.test && i.meta.test == "ynh_versions"); })[0];
|
||||
$('#yunohost-version').html(y18n.t('footer_version', [version_info.data.main_version, version_info.data.repo]));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -88,11 +88,10 @@
|
|||
"default": "Default",
|
||||
"delete": "Delete",
|
||||
"description": "Description",
|
||||
"details": "Details",
|
||||
"domain_dns_conf_is_just_a_recommendation": "This page shows you the *recommended* configuration. It does *not* configure the DNS for you. It is your responsability to configure your DNS zone in your DNS registrar according to this recommendation.",
|
||||
"diagnosis": "Diagnosis",
|
||||
"diagnosis_hide_private": "Show diagnostic information without private data",
|
||||
"diagnosis_view_private": "Show diagnostic information including private data",
|
||||
"diagnosis_with_private": "Diagnosis with private data",
|
||||
"diagnosis_experimental_disclaimer": "Be aware that the diagnosis feature is still experimental and being polished, and it may not be fully reliable.",
|
||||
"disable": "Disable",
|
||||
"disabled": "Disabled",
|
||||
"dns": "DNS",
|
||||
|
@ -117,12 +116,14 @@
|
|||
"download": "Download",
|
||||
"enable": "Enable",
|
||||
"enabled": "Enabled",
|
||||
"errors": "%s errors",
|
||||
"error_modify_something": "You should modify something",
|
||||
"error_retrieve_feed": "Could not retrieve feed: %s. You might have a plugin prevent your browser from performing this request (or the website is down).",
|
||||
"error_select_domain": "You should indicate a domain",
|
||||
"error_server": "Server error",
|
||||
"error_server_unexpected": "Unexpected server error (%s)",
|
||||
"error_connection_interrupted": "The server closed the connection instead of answering it. Has nginx or the yunohost-api been restarted or stoppted for some reason? (Error code/message: %s)",
|
||||
"everything_good": "Everything good!",
|
||||
"experimental_warning": "Warning: this feature is experimental and not consider stable, you shouldn't be using it except if you know what you are doing.",
|
||||
"firewall": "Firewall",
|
||||
"footer_version": "Powered by <a href='https://yunohost.org'>YunoHost</a> %s (%s).",
|
||||
|
@ -162,6 +163,8 @@
|
|||
"hook_data_mail": "Mail",
|
||||
"hook_data_mail_desc": "Raw emails stored on the server",
|
||||
"id": "ID",
|
||||
"ignore": "Ignore",
|
||||
"ignored": "%s ignored",
|
||||
"inactive": "Inactive",
|
||||
"infos": "Info",
|
||||
"install": "Install",
|
||||
|
@ -176,6 +179,7 @@
|
|||
"ipv6": "IPv6",
|
||||
"label": "Label",
|
||||
"label_for_manifestname": "Label for %s",
|
||||
"last_ran": "Last time ran:",
|
||||
"level": "level",
|
||||
"license": "License",
|
||||
"loading": "Loading …",
|
||||
|
@ -224,10 +228,6 @@
|
|||
"passwords_dont_match": "Passwords don't match",
|
||||
"passwords_too_short": "Password is too short",
|
||||
"path": "Path",
|
||||
"diagnosis": "Diagnosis",
|
||||
"diagnosis_with_private": "Diagnosis with private data",
|
||||
"diagnosis_view_private": "Show diagnosis with private data",
|
||||
"diagnosis_hide_private": "Show diagnosis without private data",
|
||||
"logs": "Logs",
|
||||
"logs_operation": "Operations made on system with YunoHost",
|
||||
"logs_history": "History of command run on system",
|
||||
|
@ -257,6 +257,7 @@
|
|||
"previous": "Previous",
|
||||
"protocol": "Protocol",
|
||||
"read_more": "Read more",
|
||||
"rerun_diagnosis": "Rerun diagnosis",
|
||||
"refresh_app_list": "Refresh list",
|
||||
"request_adoption": "waiting adoption",
|
||||
"request_adoption_details": "The current maintainer would like to stop maintaining this app. Feel free to propose yourself as the new maintainer!",
|
||||
|
@ -318,6 +319,7 @@
|
|||
"tools_shutdown_reboot": "Shutdown/Reboot",
|
||||
"udp": "UDP",
|
||||
"unauthorized": "Unauthorized",
|
||||
"unignore": "Unignore",
|
||||
"uninstall": "Uninstall",
|
||||
"unknown_action": "Unknown action %s",
|
||||
"unknown_argument": "Unknown argument: %s",
|
||||
|
@ -344,6 +346,7 @@
|
|||
"users_new": "New user",
|
||||
"users_no": "No users.",
|
||||
"version": "Version",
|
||||
"warnings": "%s warnings",
|
||||
"warning_first_user": "You probably need to <a href='#/users/create' class='alert-link'>create a user</a> first.",
|
||||
"wrong_password": "Wrong password",
|
||||
"yes": "Yes",
|
||||
|
|
57
src/views/diagnosis/diagnosis_show.ms
Normal file
57
src/views/diagnosis/diagnosis_show.ms
Normal file
|
@ -0,0 +1,57 @@
|
|||
<div class="btn-breadcrumb">
|
||||
<a href="#/" ><i class="fa-home"></i><span class="sr-only">{{t 'home'}}</span></a>
|
||||
<a href="#/diagnosis">{{t 'diagnosis'}}</a>
|
||||
</div>
|
||||
|
||||
<div class="actions-group">
|
||||
<button class="btn btn-success" data-action="share">
|
||||
<span class="fa-cloud-upload"></span> {{t 'logs_share_with_yunopaste'}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div class="alert alert-warning">{{t 'diagnosis_experimental_disclaimer'}}</div>
|
||||
|
||||
{{#reports}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title" style="display: inline-block; margin-right: 10px;">
|
||||
<a data-toggle="collapse" href="#category-{{id}}">{{ description }}</a>
|
||||
</h2>
|
||||
{{#if noIssues}}<span class="label label-success">{{t 'everything_good'}}</span>{{/if}}
|
||||
{{#if errors}}<span class="label label-danger">{{t 'errors' errors }}</span>{{/if}}
|
||||
{{#if warnings}}<span class="label label-warning">{{t 'warnings' warnings }}</span>{{/if}}
|
||||
{{#if ignored}}<span class="label label-default">{{t 'ignored' ignored }}</span>{{/if}}
|
||||
<button class="btn btn-sm btn-info pull-right" data-action="rerun-diagnosis" data-category="{{ id }}"><span class="fa-fw fa-refresh"></span> {{t 'rerun_diagnosis'}}</button>
|
||||
</div>
|
||||
<div class="panel-body collapse {{#if errors}}in{{/if}}" id="category-{{id}}">
|
||||
<ul class="list-group" style="margin-bottom: 0px">
|
||||
<p>{{t 'last_ran' }} {{formatRelative time day="numeric" month="long" year="numeric" hour="numeric" minute="numeric" }}</p>
|
||||
{{#items}}
|
||||
<li class="list-group-item alert alert-{{status}} alert-{{status}}-yo clearfix">
|
||||
{{#if icon}}
|
||||
<span class="fa-fw fa-{{icon}}"></span>
|
||||
{{/if}}
|
||||
{{summary}}
|
||||
{{#if ignored}}
|
||||
<button class="btn btn-sm btn-default pull-right" data-action="unignore" data-filter-args="{{ filter_args }}"><span class="fa-fw fa-bell"></span> {{t 'unignore'}}</button>
|
||||
{{else}}
|
||||
{{#if issue}}
|
||||
<button class="btn btn-sm btn-warning pull-right" data-action="ignore" data-filter-args="{{ filter_args }}"><span class="fa-fw fa-bell-slash"></span> {{t 'ignore'}}</button>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if details}}
|
||||
<a role="button" class="btn btn-sm btn-default pull-right" data-toggle="collapse" href="#details-{{../id}}-{{@index}}" aria-expanded="false" aria-controls="details-{{../id}}-{{@index}}"><span class="fa-fw fa-level-down"></span>{{t 'details'}}</a>
|
||||
<div class="collapse" id="details-{{../id}}-{{@index}}">
|
||||
<ul>
|
||||
{{#details}}<li>{{.}}</li>{{/details}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/items}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/reports}}
|
|
@ -23,6 +23,10 @@
|
|||
<span class="pull-right fa-chevron-right"></span>
|
||||
<h2 class="list-group-item-heading"><span class="fa-fw fa-wrench"></span> {{t 'tools'}}</h2>
|
||||
</a>
|
||||
<a href="#/diagnosis" class="list-group-item slide clearfix">
|
||||
<span class="pull-right fa-chevron-right"></span>
|
||||
<h2 class="list-group-item-heading"><span class="fa-fw fa-stethoscope"></span> {{t 'diagnosis'}}</h2>
|
||||
</a>
|
||||
<a href="#/backup" class="list-group-item slide clearfix">
|
||||
<span class="pull-right fa-chevron-right"></span>
|
||||
<h2 class="list-group-item-heading"><span class="fa-fw fa-archive"></span> {{t 'backup'}}</h2>
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<div class="btn-breadcrumb">
|
||||
<a href="#/" ><i class="fa-home"></i><span class="sr-only">{{t 'home'}}</span></a>
|
||||
<a href="#/tools">{{t 'tools'}}</a>
|
||||
<a href="#/tools/diagnosis">{{t 'diagnosis'}}</a>
|
||||
{{#private}}
|
||||
<a href="#/tools/diagnosis/private">{{t 'diagnosis_with_private'}}</a>
|
||||
{{/private}}
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title"><span class="fa-fw fa-stethoscope"></span> {{t 'diagnosis'}}</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<pre id="diagnosis">{{ diagnosis }}</pre>
|
||||
{{#if private}}
|
||||
<a class="btn btn-primary" role="button" href="#/tools/diagnosis"><i class="fa-eye-slash"></i> {{t 'diagnosis_hide_private'}}</a>
|
||||
{{else}}
|
||||
<a class="btn btn-primary" role="button" href="#/tools/diagnosis/private"><i class="fa-eye"></i> {{t 'diagnosis_view_private'}}</a>
|
||||
{{/if}}
|
||||
<button data-paste-content="#diagnosis"><i class="fa-cloud-upload"></i> {{t 'upload'}}</button>
|
||||
</div>
|
||||
</div>
|
|
@ -6,10 +6,6 @@
|
|||
<div class="separator"></div>
|
||||
|
||||
<div class="list-group">
|
||||
<a href="#/tools/diagnosis" class="list-group-item slide clearfix">
|
||||
<span class="pull-right fa-chevron-right"></span>
|
||||
<h2 class="list-group-item-heading">{{t 'diagnosis'}}</h2>
|
||||
</a>
|
||||
<a href="#/tools/logs" class="list-group-item slide clearfix">
|
||||
<span class="pull-right fa-chevron-right"></span>
|
||||
<h2 class="list-group-item-heading">{{t 'logs'}}</h2>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<div class="list-group-item clearfix">
|
||||
<button class="btn btn-success pull-right" data-upgrade="{{id}}">{{t 'system_upgrade_btn'}}</button>
|
||||
<h3 class="list-group-item-heading">{{label}} <small>{{id}}</small></h3>
|
||||
<p class="list-group-item-text">{{t 'from_to' current_version new_version}}</p>
|
||||
<span class="list-group-item-text">{{t 'from_to' current_version new_version}}</span>
|
||||
</div>
|
||||
{{/apps}}
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue