mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
Merge pull request #242 from YunoHost/high-quality-apps-and-maintained-states
High quality apps and maintained states
This commit is contained in:
commit
8e8113d743
5 changed files with 130 additions and 41 deletions
|
@ -588,6 +588,10 @@ input[type='radio'].nice-radio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.label-best {
|
||||||
|
background-color: darkorchid;
|
||||||
|
}
|
||||||
|
|
||||||
// only one card for small screens
|
// only one card for small screens
|
||||||
.app-card {
|
.app-card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -18,7 +18,10 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function levelToColor(level) {
|
function levelToColor(level) {
|
||||||
if (level >= 3) {
|
if (level >= 8) {
|
||||||
|
return 'best';
|
||||||
|
}
|
||||||
|
else if (level > 4) {
|
||||||
return 'success';
|
return 'success';
|
||||||
}
|
}
|
||||||
else if (level >= 1) {
|
else if (level >= 1) {
|
||||||
|
@ -32,7 +35,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function stateToColor(state) {
|
function stateToColor(state) {
|
||||||
if (state === "working" || state === "official") {
|
if (state === "high-quality") {
|
||||||
|
return 'best';
|
||||||
|
}
|
||||||
|
else if (state === "working") {
|
||||||
return 'success';
|
return 'success';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -40,6 +46,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function maintainedStateToColor(state) {
|
||||||
|
if ( state === "request_help" ) {
|
||||||
|
return 'info';
|
||||||
|
}
|
||||||
|
else if ( state === "request_adoption" ) {
|
||||||
|
return 'warning';
|
||||||
|
}
|
||||||
|
else if ( state === "orphaned" ) {
|
||||||
|
return 'danger';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 'success';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function combineColors(stateColor, levelColor, installable) {
|
function combineColors(stateColor, levelColor, installable) {
|
||||||
if (stateColor === "danger" || levelColor === "danger") {
|
if (stateColor === "danger" || levelColor === "danger") {
|
||||||
return 'danger';
|
return 'danger';
|
||||||
|
@ -53,36 +74,83 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractMaintainer(manifest) {
|
||||||
|
if (manifest.maintainer === undefined)
|
||||||
|
{
|
||||||
|
if ((manifest.developer !== undefined) && (manifest.developer.name !== undefined))
|
||||||
|
{
|
||||||
|
return manifest.developer.name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Array.isArray(manifest.maintainer))
|
||||||
|
{
|
||||||
|
maintainers = [];
|
||||||
|
manifest.maintainer.forEach(function(maintainer) {
|
||||||
|
if (maintainer.name !== undefined)
|
||||||
|
{
|
||||||
|
maintainers.push(maintainer.name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return maintainers.join(', ');
|
||||||
|
}
|
||||||
|
else if (manifest.maintainer.name !== undefined)
|
||||||
|
{
|
||||||
|
return manifest.maintainer.name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// List available apps
|
// List available apps
|
||||||
app.get('#/apps/install', function (c) {
|
app.get('#/apps/install', function (c) {
|
||||||
c.api('/apps', function (data) { // http://api.yunohost.org/#!/app/app_list_get_8
|
c.api('/apps', function (data) { // http://api.yunohost.org/#!/app/app_list_get_8
|
||||||
c.api('/apps?raw', function (dataraw) { // http://api.yunohost.org/#!/app/app_list_get_8
|
c.api('/apps?raw', function (dataraw) { // http://api.yunohost.org/#!/app/app_list_get_8
|
||||||
var apps = []
|
var apps = []
|
||||||
$.each(data['apps'], function(k, v) {
|
$.each(data['apps'], function(k, v) {
|
||||||
if (dataraw[v['id']]['state'] === "validated")
|
app = dataraw[v['id']];
|
||||||
|
app.level = parseInt(app.level);
|
||||||
|
|
||||||
|
if (app.high_quality && app.level > 7)
|
||||||
{
|
{
|
||||||
dataraw[v['id']]['state'] = "official";
|
app.state = "high-quality";
|
||||||
|
}
|
||||||
|
if ( app.maintained === false )
|
||||||
|
{
|
||||||
|
app.maintained = "orphaned";
|
||||||
|
}
|
||||||
|
else if ( app.maintained === true )
|
||||||
|
{
|
||||||
|
app.maintained = "maintained";
|
||||||
}
|
}
|
||||||
var state = dataraw[v['id']]['state'];
|
|
||||||
var levelFormatted = parseInt(dataraw[v['id']]['level']);
|
|
||||||
var isWorking = (state === 'working' || state === 'official') && levelFormatted > 0;
|
|
||||||
// Keep only the first instance of each app and remove community not working apps
|
|
||||||
if (!v['id'].match(/__[0-9]{1,5}$/) && (dataraw[v['id']]['repository'] === 'yunohost' || state !== 'notworking')) {
|
|
||||||
|
|
||||||
dataraw[v['id']]['installable'] = (!v['installed'] || dataraw[v['id']].manifest.multi_instance)
|
app.manifest.maintainer = extractMaintainer(app.manifest);
|
||||||
dataraw[v['id']]['isCommunity'] = !(dataraw[v['id']]['repository'] === 'yunohost');
|
var isWorking = (app.state === 'working' || app.state === "high-quality") && app.level > 0;
|
||||||
dataraw[v['id']]['levelFormatted'] = isNaN(levelFormatted) ? '?' : levelFormatted;
|
|
||||||
dataraw[v['id']]['levelColor'] = levelToColor(levelFormatted);
|
|
||||||
dataraw[v['id']]['stateColor'] = stateToColor(state);
|
|
||||||
dataraw[v['id']]['installColor'] = combineColors(dataraw[v['id']]['stateColor'], dataraw[v['id']]['levelColor']);
|
|
||||||
dataraw[v['id']]['displayLicense'] = (dataraw[v['id']]['manifest']['license'] !== undefined
|
|
||||||
&& dataraw[v['id']]['manifest']['license'] !== 'free');
|
|
||||||
dataraw[v['id']]['updateDate'] = dataraw[v['id']]['lastUpdate'] * 1000 || 0;
|
|
||||||
dataraw[v['id']]['isSafe'] = (dataraw[v['id']]['installColor'] !== 'danger');
|
|
||||||
dataraw[v['id']]['isWorking'] = isWorking ? "isworking" : "notFullyWorking";
|
|
||||||
|
|
||||||
jQuery.extend(dataraw[v['id']], v);
|
// Keep only the first instance of each app and remove not working apps
|
||||||
apps.push(dataraw[v['id']]);
|
if (!v['id'].match(/__[0-9]{1,5}$/) && (app.state !== 'notworking')) {
|
||||||
|
|
||||||
|
app.installable = (!v.installed || app.manifest.multi_instance)
|
||||||
|
app.levelFormatted = isNaN(app.level) ? '?' : app.level;
|
||||||
|
|
||||||
|
app.levelColor = levelToColor(app.level);
|
||||||
|
app.stateColor = stateToColor(app.state);
|
||||||
|
app.maintainedColor = maintainedStateToColor(app.maintained);
|
||||||
|
app.installColor = combineColors(app.stateColor, app.levelColor);
|
||||||
|
|
||||||
|
app.updateDate = app.lastUpdate * 1000 || 0;
|
||||||
|
app.isSafe = (app.installColor !== 'danger');
|
||||||
|
app.isWorking = isWorking ? "isworking" : "notFullyWorking";
|
||||||
|
app.isHighQuality = (app.state === "high-quality") ? "isHighQuality" : "";
|
||||||
|
app.decentQuality = (app.level > 4)?"decentQuality":"badQuality";
|
||||||
|
|
||||||
|
jQuery.extend(app, v);
|
||||||
|
apps.push(app);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -107,8 +175,8 @@
|
||||||
return inputMatch && classMatch;
|
return inputMatch && classMatch;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Keep only official apps at first render
|
// Default filter is 'decent quality apps'
|
||||||
cardGrid.isotope({ filter: '.isworking' });
|
cardGrid.isotope({ filter: '.decentQuality' });
|
||||||
|
|
||||||
jQuery('.dropdownFilter').on('click', function() {
|
jQuery('.dropdownFilter').on('click', function() {
|
||||||
// change dropdown label
|
// change dropdown label
|
||||||
|
@ -472,7 +540,8 @@
|
||||||
app.helper('appInstallForm', function(appId, manifest, params) {
|
app.helper('appInstallForm', function(appId, manifest, params) {
|
||||||
var data = {
|
var data = {
|
||||||
id: appId,
|
id: appId,
|
||||||
manifest: manifest
|
manifest: manifest,
|
||||||
|
displayLicense: (manifest['license'] !== undefined && manifest['license'] !== 'free')
|
||||||
};
|
};
|
||||||
|
|
||||||
formatYunoHostStyleArguments(data.manifest.arguments.install, params);
|
formatYunoHostStyleArguments(data.manifest.arguments.install, params);
|
||||||
|
|
|
@ -29,16 +29,19 @@
|
||||||
"app_install_cancel": "Installation cancelled.",
|
"app_install_cancel": "Installation cancelled.",
|
||||||
"app_install_custom_no_manifest": "No manifest.json file",
|
"app_install_custom_no_manifest": "No manifest.json file",
|
||||||
"app_list": "App list",
|
"app_list": "App list",
|
||||||
"app_license": "License of the app",
|
|
||||||
"app_level": "App level",
|
"app_level": "App level",
|
||||||
"app_make_default": "Make default",
|
"app_make_default": "Make default",
|
||||||
"app_no_actions": "This application doesn't have any actions",
|
"app_no_actions": "This application doesn't have any actions",
|
||||||
"app_repository": "Application origin: ",
|
"app_repository": "Application origin: ",
|
||||||
"app_state": "Application state: ",
|
"app_state": "Application state: ",
|
||||||
"app_state_inprogress": "In progress",
|
"app_state_inprogress": "in progress",
|
||||||
"app_state_notworking": "Not working",
|
"app_state_inprogress_explanation": "This maintainer of this app declared that this application is not ready yet for production use. BE CAREFUL!",
|
||||||
"app_state_official": "Official",
|
"app_state_notworking": "not working",
|
||||||
"app_state_working": "Working",
|
"app_state_notworking_explanation": "This maintainer of this app declared it as 'not working'. IT WILL BREAK YOUR SYSTEM!",
|
||||||
|
"app_state_high-quality": "high quality",
|
||||||
|
"app_state_high-quality_explanation": "This app is well-integrated with YunoHost. It has been (and is!) peer-reviewed by the YunoHost app team. It can be expected to be safe and maintained on the long-term.",
|
||||||
|
"app_state_working": "working",
|
||||||
|
"app_state_working_explanation": "The maintainer of this app declared it as 'working'. It means that it should be functional (c.f. application level) but is not necessarily peer-reviewed, it may still contain issues or is not fully integrated with YunoHost.",
|
||||||
"application": "Application",
|
"application": "Application",
|
||||||
"applications": "Applications",
|
"applications": "Applications",
|
||||||
"archive_empty": "Empty archive",
|
"archive_empty": "Empty archive",
|
||||||
|
@ -189,6 +192,7 @@
|
||||||
"label": "Label",
|
"label": "Label",
|
||||||
"label_for_manifestname": "Label for %s",
|
"label_for_manifestname": "Label for %s",
|
||||||
"level": "level",
|
"level": "level",
|
||||||
|
"license": "License",
|
||||||
"loading": "Loading …",
|
"loading": "Loading …",
|
||||||
"local_archives": "Local archives",
|
"local_archives": "Local archives",
|
||||||
"local_ip": "Local IP",
|
"local_ip": "Local IP",
|
||||||
|
@ -199,6 +203,8 @@
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"mailbox_quota_description": "For example, 700M is a CD, 4700M is a DVD.",
|
"mailbox_quota_description": "For example, 700M is a CD, 4700M is a DVD.",
|
||||||
"mailbox_quota_placeholder": "Leave empty or set to 0 to disable.",
|
"mailbox_quota_placeholder": "Leave empty or set to 0 to disable.",
|
||||||
|
"maintained": "maintained",
|
||||||
|
"maintained_details": "This app was maintained by its maintainer in the last few months.",
|
||||||
"manage_apps": "Manage apps",
|
"manage_apps": "Manage apps",
|
||||||
"manage_domains": "Manage domains",
|
"manage_domains": "Manage domains",
|
||||||
"manage_users": "Manage users",
|
"manage_users": "Manage users",
|
||||||
|
@ -226,10 +232,13 @@
|
||||||
"no_user_to_add": "No more users to add.",
|
"no_user_to_add": "No more users to add.",
|
||||||
"non_compatible_api": "Non-compatible API",
|
"non_compatible_api": "Non-compatible API",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"only_official_apps": "Only official apps",
|
"only_highquality_apps": "Only high-quality apps",
|
||||||
"only_working_apps": "Only working apps",
|
"only_working_apps": "Only working apps",
|
||||||
|
"only_decent_quality_apps": "Only decent quality apps",
|
||||||
"open": "Open",
|
"open": "Open",
|
||||||
"operations": "Operations",
|
"operations": "Operations",
|
||||||
|
"orphaned": "not maintained",
|
||||||
|
"orphaned_details": "This app is not maintained anymore. It may still be working but won't receive any upgrade. Feel free to come and revive it!",
|
||||||
"os": "OS",
|
"os": "OS",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"password_confirmation": "Password confirmation",
|
"password_confirmation": "Password confirmation",
|
||||||
|
@ -279,6 +288,10 @@
|
||||||
"reception": "Reception",
|
"reception": "Reception",
|
||||||
"refresh_app_list": "Refresh list",
|
"refresh_app_list": "Refresh list",
|
||||||
"remove_access": "Remove access",
|
"remove_access": "Remove access",
|
||||||
|
"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!",
|
||||||
|
"request_help": "need help",
|
||||||
|
"request_help_details": "The current maintainer would like some help with the maintainance of this app. Feel free to come contribute on it!",
|
||||||
"restore": "Restore",
|
"restore": "Restore",
|
||||||
"run": "Run",
|
"run": "Run",
|
||||||
"running": "Running",
|
"running": "Running",
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
<dd>{{id}}</dd>
|
<dd>{{id}}</dd>
|
||||||
<dt>{{t 'description'}}</dt>
|
<dt>{{t 'description'}}</dt>
|
||||||
<dd>{{description}}</dd>
|
<dd>{{description}}</dd>
|
||||||
|
{{#displayLicense}}
|
||||||
|
<dt>{{t 'license'}}</dt>
|
||||||
|
<dd>{{manifest.license}}</dd>
|
||||||
|
{{/displayLicense}}
|
||||||
<dt>{{t 'version'}}</dt>
|
<dt>{{t 'version'}}</dt>
|
||||||
<dd>{{manifest.version}}</dd>
|
<dd>{{manifest.version}}</dd>
|
||||||
<dt>{{t 'multi_instance'}}</dt>
|
<dt>{{t 'multi_instance'}}</dt>
|
||||||
|
|
|
@ -20,11 +20,12 @@
|
||||||
<input type="text" id="filter-app-cards" class="form-control" role="textbox" placeholder="{{t 'search_for_apps'}}" aria-describedby="basic-addon0"/>
|
<input type="text" id="filter-app-cards" class="form-control" role="textbox" placeholder="{{t 'search_for_apps'}}" aria-describedby="basic-addon0"/>
|
||||||
<div class="input-group-btn">
|
<div class="input-group-btn">
|
||||||
<button type="button" role="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<button type="button" role="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<span id="app-cards-list-filter-text">{{t 'only_working_apps'}}</span> <span class="caret"></span>
|
<span id="app-cards-list-filter-text">{{t 'only_decent_quality_apps'}}</span> <span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
<ul id="dropdownFilter" class="dropdown-menu" data-filter="isworking" role="menu">
|
<ul id="dropdownFilter" class="dropdown-menu" data-filter="decentQuality" role="menu">
|
||||||
|
<li role="presentation" class="button dropdownFilter" data-filter="isHighQuality"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'only_highquality_apps'}}</a></li>
|
||||||
|
<li role="presentation" class="button dropdownFilter" data-filter="decentQuality"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'only_decent_quality_apps'}}</a></li>
|
||||||
<li role="presentation" class="button dropdownFilter" data-filter="isworking"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'only_working_apps'}}</a></li>
|
<li role="presentation" class="button dropdownFilter" data-filter="isworking"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'only_working_apps'}}</a></li>
|
||||||
<li role="presentation" class="button dropdownFilter" data-filter="official"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'only_official_apps'}}</a></li>
|
|
||||||
<li role="presentation" class="button dropdownFilter" data-filter="*"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'all_apps'}}</a></li>
|
<li role="presentation" class="button dropdownFilter" data-filter="*"><a class="menu-item" role="menu-item" tabindex="-1">{{t 'all_apps'}}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,21 +35,19 @@
|
||||||
|
|
||||||
<div class="list-group grid">
|
<div class="list-group grid">
|
||||||
{{#apps}}
|
{{#apps}}
|
||||||
<div class="app-card panel panel-default {{status}} {{state}} {{isWorking}} {{level}}-level">
|
<div class="app-card panel panel-default {{status}} {{state}} {{isWorking}} {{isHighQuality}} {{decentQuality}} {{level}}-level">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<h2 class="app-title">{{name}}</h2>
|
<h2 class="app-title">{{name}}</h2>
|
||||||
<div class="category">
|
<div class="category">
|
||||||
{{#isCommunity}} <span class="label label-info label-as-badge app-status">{{t 'community'}}</span>{{/isCommunity}}
|
<span class="label label-{{stateColor}} label-as-badge app-state" title="{{t (concat 'app_state_' state '_explanation') }}">{{t (concat 'app_state_' state) }}</span>
|
||||||
<span class="label label-{{stateColor}} label-as-badge app-state">{{t state}}</span>
|
|
||||||
<a target="_BLANK" href="https://yunohost.org/#/packaging_apps_levels"><span class="label label-{{levelColor}} label-as-badge app-level" title="{{t 'app_level'}}">{{t 'level'}} {{levelFormatted}}</span></a>
|
<a target="_BLANK" href="https://yunohost.org/#/packaging_apps_levels"><span class="label label-{{levelColor}} label-as-badge app-level" title="{{t 'app_level'}}">{{t 'level'}} {{levelFormatted}}</span></a>
|
||||||
{{#displayLicense}}<span class="label label-default app-license" title="{{t 'app_license'}}">{{license}}</span>{{/displayLicense}}
|
<span class="label label-{{maintainedColor}} label-as-badge maintained-status" title="{{t (concat maintained '_details') }}"> {{t maintained}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-card-desc">{{description}}</div>
|
<div class="app-card-desc">{{description}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-card-date-maintainer">
|
<div class="app-card-date-maintainer">
|
||||||
<i class="fa-refresh"></i> {{formatDate updateDate day="numeric" month="long" year="numeric"}} -
|
<i class="fa-refresh"></i> {{formatDate updateDate day="numeric" month="long" year="numeric"}} -
|
||||||
{{#maintained}}<span title="{{t 'current_maintainer_title'}}" class="maintained"></span><i class="fa-user"></i> {{manifest.maintainer.name}}</span>{{/maintained}}
|
<span title="{{t 'current_maintainer_title'}}" class="maintained"></span><i class="fa-user"></i> {{manifest.maintainer}}</span>
|
||||||
{{^maintained}}<i class="fas fa-warning"></i> {{t 'unmaintained'}}{{/maintained}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<a href="{{git.url}}" target="_BLANK" type="button" role="button" class="btn btn-default col-xs-4">
|
<a href="{{git.url}}" target="_BLANK" type="button" role="button" class="btn btn-default col-xs-4">
|
||||||
|
|
Loading…
Add table
Reference in a new issue