mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
Merge pull request #279 from YunoHost/app-categories
WIP : App categories
This commit is contained in:
commit
1f47ce7927
8 changed files with 246 additions and 115 deletions
|
@ -631,8 +631,12 @@ input[type='radio'].nice-radio {
|
|||
background-color: darkorchid;
|
||||
}
|
||||
|
||||
.app-category-card {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// only one card for small screens
|
||||
.app-card {
|
||||
.app-card, .app-category-card {
|
||||
width: 100%;
|
||||
.btn-group {
|
||||
width: 100%;
|
||||
|
@ -653,13 +657,16 @@ input[type='radio'].nice-radio {
|
|||
}
|
||||
}
|
||||
|
||||
.app-state {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
.app-title, .app-category-title {
|
||||
margin-top: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.app-card-desc {
|
||||
.app-card-desc, .app-category-card-desc {
|
||||
height: 6rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -670,6 +677,7 @@ input[type='radio'].nice-radio {
|
|||
margin-bottom: 3px;
|
||||
margin-right: 7px;
|
||||
margin-top: -5px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.auto-width {
|
||||
|
@ -686,6 +694,7 @@ input[type='radio'].nice-radio {
|
|||
|
||||
.app-card .panel-body {
|
||||
padding: 1.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
|
@ -697,6 +706,33 @@ input[type='radio'].nice-radio {
|
|||
}
|
||||
}
|
||||
|
||||
.app-category-card .panel-body {
|
||||
padding: 2em;
|
||||
height: 10em;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.subtag-selector {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-category-card {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.app-category-card:hover {
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.app-category-title {
|
||||
line-height: 1em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.app-category-card-desc {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
|
||||
/** Groups View **/
|
||||
#view-groups {
|
||||
|
@ -806,7 +842,7 @@ input[type='radio'].nice-radio {
|
|||
}
|
||||
|
||||
// display 2 cards between 640 and 992px
|
||||
.app-card {
|
||||
.app-card, .app-category-card {
|
||||
width: 47.9%;
|
||||
margin: 1%;
|
||||
}
|
||||
|
@ -908,7 +944,7 @@ input[type='radio'].nice-radio {
|
|||
|
||||
// bootstrap breakpoint for large screen is 992px
|
||||
@media screen and (min-width: 992px) {
|
||||
.app-card {
|
||||
.app-card, .app-category-card {
|
||||
// display 3 cards by row
|
||||
width: 31.3%;
|
||||
margin: 1%;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// List installed apps
|
||||
app.get('#/apps', function (c) {
|
||||
c.api('GET', '/apps?installed', {}, function(data) {
|
||||
c.api('GET', '/apps?full', {}, function(data) {
|
||||
var apps = data['apps'];
|
||||
c.arraySortById(apps);
|
||||
c.view('app/app_list', {apps: apps});
|
||||
|
@ -70,7 +70,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
return 'success';
|
||||
return 'info';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,13 +107,35 @@
|
|||
}
|
||||
}
|
||||
|
||||
// List available apps
|
||||
app.get('#/apps/install', function (c) {
|
||||
c.api('GET', '/apps', {}, function (data) {
|
||||
c.api('GET', '/apps?raw', {}, function (dataraw) {
|
||||
var apps = []
|
||||
$.each(data['apps'], function(k, v) {
|
||||
app = dataraw[v['id']];
|
||||
|
||||
// Display catalog home page where users chooses to browse a specific category
|
||||
app.get('#/apps/catalog', function (c) {
|
||||
c.api('GET', '/appscatalog?full&with_categories', {}, function (data) {
|
||||
c.view('app/app_catalog_home', {categories: data["categories"]}, function() {
|
||||
// Configure layout / rendering for app-category-cards
|
||||
$('#category-selector').isotope({
|
||||
itemSelector: '.app-category-card',
|
||||
layoutMode: 'fitRows',
|
||||
transitionDuration: 200
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Display app catalog for a specific category
|
||||
app.get('#/apps/catalog/:category', function (c) {
|
||||
var category_id = c.params['category'];
|
||||
c.api('GET', '/appscatalog?full&with_categories', {}, function (data) {
|
||||
var apps = [];
|
||||
$.each(data['apps'], function(name, app) {
|
||||
|
||||
// Ignore not working apps
|
||||
if (app.state === 'notworking') { return; }
|
||||
|
||||
// Ignore apps not in this category
|
||||
if ((category_id !== "all") && (app.category !== category_id)) { return; }
|
||||
|
||||
app.id = app.manifest.id;
|
||||
app.level = parseInt(app.level);
|
||||
|
||||
if (app.high_quality && app.level > 7)
|
||||
|
@ -132,10 +154,7 @@
|
|||
app.manifest.maintainer = extractMaintainer(app.manifest);
|
||||
var isWorking = (app.state === 'working' || app.state === "high-quality") && app.level > 0;
|
||||
|
||||
// Keep only the first instance of each app and remove not working apps
|
||||
if (!v['id'].match(/__[0-9]{1,5}$/) && (app.state !== 'notworking')) {
|
||||
|
||||
app.installable = (!v.installed || app.manifest.multi_instance)
|
||||
app.installable = (!app.installed || app.manifest.supports_multi_instance)
|
||||
app.levelFormatted = isNaN(app.level) ? '?' : app.level;
|
||||
|
||||
app.levelColor = levelToColor(app.level);
|
||||
|
@ -149,59 +168,84 @@
|
|||
app.isHighQuality = (app.state === "high-quality") ? "isHighQuality" : "";
|
||||
app.decentQuality = (app.level > 4)?"decentQuality":"badQuality";
|
||||
|
||||
jQuery.extend(app, v);
|
||||
apps.push(app);
|
||||
}
|
||||
});
|
||||
|
||||
var category = undefined;
|
||||
$.each(data['categories'], function(i, this_category) {
|
||||
if (this_category.id === category_id) { category = this_category; }
|
||||
});
|
||||
|
||||
if (category_id === "all") {
|
||||
category = {title: y18n.t("all_apps"), icon: "search"};
|
||||
}
|
||||
|
||||
// Sort app list
|
||||
c.arraySortById(apps);
|
||||
|
||||
// setup filtering of apps once the view is loaded
|
||||
function setupFilterEvents () {
|
||||
// Uses plugin isotope to filter apps (we could had ordering to)
|
||||
var cardGrid = jQuery('.grid').isotope({
|
||||
var cardGrid = jQuery('#apps').isotope({
|
||||
itemSelector: '.app-card',
|
||||
layoutMode: 'fitRows',
|
||||
transitionDuration: 200
|
||||
});
|
||||
|
||||
filterByClassAndName = function () {
|
||||
var input = jQuery("#filter-app-cards").val().toLowerCase();
|
||||
var inputMatch = (jQuery(this).find('.app-title').text().toLowerCase().indexOf(input) > -1);
|
||||
|
||||
var filterClass = jQuery("#dropdownFilter").attr("data-filter");
|
||||
var classMatch = (filterClass === '*') ? true : jQuery(this).hasClass(filterClass);
|
||||
return inputMatch && classMatch;
|
||||
},
|
||||
|
||||
// Default filter is 'decent quality apps'
|
||||
cardGrid.isotope({ filter: '.decentQuality' });
|
||||
|
||||
$(".subtag-selector button").on("click", function() {
|
||||
var selector = $(this).parent();
|
||||
$("button", selector).removeClass("active");
|
||||
$(this).addClass("active");
|
||||
cardGrid.isotope({ filter: filterApps });
|
||||
});
|
||||
|
||||
filterApps = function () {
|
||||
|
||||
// Check text search
|
||||
var input = jQuery("#filter-app-cards").val().toLowerCase();
|
||||
if (jQuery(this).find('.app-title').text().toLowerCase().indexOf(input) <= -1) return false;
|
||||
|
||||
// Check subtags
|
||||
var subtag = $(".subtag-selector button.active").data("subtag");
|
||||
var this_subtags = jQuery(this).data("subtags");
|
||||
if ((subtag !== undefined) && (subtag !== "all")) {
|
||||
if ((subtag === "others") && (this_subtags !== "")) return false;
|
||||
if ((subtag !== "others") && (this_subtags.split(",").indexOf(subtag) <= -1)) return false;
|
||||
}
|
||||
|
||||
// Check quality criteria
|
||||
var class_ = jQuery("#dropdownFilter").data("filter");
|
||||
if ((class_ !== '*') && (! jQuery(this).hasClass(class_))) return false;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
jQuery('.dropdownFilter').on('click', function() {
|
||||
// change dropdown label
|
||||
jQuery('#app-cards-list-filter-text').text(jQuery(this).find('.menu-item').text());
|
||||
// change filter attribute
|
||||
jQuery('#dropdownFilter').attr("data-filter", jQuery(this).attr("data-filter"));
|
||||
jQuery('#dropdownFilter').data("filter", jQuery(this).data("filter"));
|
||||
// filter !
|
||||
cardGrid.isotope({ filter: filterByClassAndName });
|
||||
cardGrid.isotope({ filter: filterApps });
|
||||
});
|
||||
|
||||
jQuery("#filter-app-cards").on("keyup", function() {
|
||||
cardGrid.isotope({ filter: filterByClassAndName });
|
||||
cardGrid.isotope({ filter: filterApps });
|
||||
});
|
||||
};
|
||||
|
||||
// render
|
||||
c.view('app/app_list_install', {apps: apps}, setupFilterEvents);
|
||||
c.view('app/app_catalog_category', {apps: apps, category: category}, setupFilterEvents);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Get app information
|
||||
app.get('#/apps/:app', function (c) {
|
||||
c.api('GET', '/apps/'+c.params['app']+'?raw', {}, function(data) {
|
||||
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(data) {
|
||||
c.api('GET', '/users/permissions', {}, function(data_permissions) {
|
||||
|
||||
// Permissions
|
||||
|
@ -506,9 +550,9 @@
|
|||
|
||||
// App installation form
|
||||
app.get('#/apps/install/:app', function (c) {
|
||||
c.api('GET', '/apps?raw', {}, function(data) {
|
||||
c.api('GET', '/appscatalog?full', {}, function(data) {
|
||||
var app_name = c.params["app"];
|
||||
var app_infos = data[app_name];
|
||||
var app_infos = data["apps"][app_name];
|
||||
if (app_infos['state'] === "validated")
|
||||
{
|
||||
app_infos['state'] = "official";
|
||||
|
@ -535,7 +579,7 @@
|
|||
{
|
||||
c.appInstallForm(
|
||||
c.params['app'],
|
||||
data[c.params['app']].manifest,
|
||||
app_infos.manifest,
|
||||
c.params
|
||||
);
|
||||
}
|
||||
|
@ -622,7 +666,7 @@
|
|||
|
||||
// Get app change label page
|
||||
app.get('#/apps/:app/changelabel', function (c) {
|
||||
c.api('GET', '/apps/'+c.params['app']+'?raw', {}, function(app_data) {
|
||||
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(app_data) {
|
||||
data = {
|
||||
id: c.params['app'],
|
||||
label: app_data.settings.label,
|
||||
|
@ -641,7 +685,7 @@
|
|||
|
||||
// Get app change URL page
|
||||
app.get('#/apps/:app/changeurl', function (c) {
|
||||
c.api('GET', '/apps/'+c.params['app']+'?raw', {}, function(app_data) {
|
||||
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(app_data) {
|
||||
c.api('GET', '/domains', {}, function(domain_data) {
|
||||
|
||||
// Display a list of available domains
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"advanced": "Advanced",
|
||||
"remove": "Remove",
|
||||
"administration_password": "Administration password",
|
||||
"all": "All",
|
||||
"all_apps": "All apps",
|
||||
"api_not_responding": "The YunoHost API is not responding. Maybe 'yunohost-api' is down or got restarted?",
|
||||
"app_change_label": "Change Label",
|
||||
|
@ -23,10 +24,12 @@
|
|||
"app_no_actions": "This application doesn't have any actions",
|
||||
"app_repository": "Application origin: ",
|
||||
"app_state": "Application state: ",
|
||||
"app_state_inprogress": "in progress",
|
||||
"app_state_inprogress": "not yet 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_notworking": "not working",
|
||||
"app_state_notworking_explanation": "This maintainer of this app declared it as 'not working'. IT WILL BREAK YOUR SYSTEM!",
|
||||
"app_state_low_quality": "low quality",
|
||||
"app_state_low_quality_explanation": "This app may be functional, but may still contain issues, or is not fully integrated with YunoHost, or it does not respect the good practices.",
|
||||
"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",
|
||||
|
@ -51,6 +54,7 @@
|
|||
"begin": "Begin",
|
||||
"both": "Both",
|
||||
"cancel": "Cancel",
|
||||
"catalog": "Catalog",
|
||||
"check": "Check",
|
||||
"close": "Close",
|
||||
"configuration": "Configuration",
|
||||
|
@ -218,8 +222,9 @@
|
|||
"only_decent_quality_apps": "Only decent quality apps",
|
||||
"open": "Open",
|
||||
"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!",
|
||||
"orphaned": "Not maintained",
|
||||
"orphaned_details": "This app has not been maintained for quite some time. It may still be working, but won't receive any upgrade until somebody volunteers to take care of it. Feel free to contribute to revive it!",
|
||||
"others": "Others",
|
||||
"password": "Password",
|
||||
"password_confirmation": "Password confirmation",
|
||||
"password_description": "Password must be at least %s characters long.",
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
<div class="btn-breadcrumb">
|
||||
<a href="#/" ><i class="fa-home"></i><span class="sr-only">{{t 'home'}}</span></a>
|
||||
<a href="#/apps">{{t 'applications'}}</a>
|
||||
<a href="#/apps/install">{{t 'install'}}</a>
|
||||
<a href="#/apps/catalog">{{t 'catalog'}}</a>
|
||||
<a href="#/apps/catalog/{{category.id}}">{{category.title}}</a>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div class="input-group" id="app-filter-input">
|
||||
<span class="input-group-addon"><i class="fas fa-search"></i></span>
|
||||
<div class="input-group-btn"><a class="btn btn-primary" href="#/apps/catalog"><i class="fa-arrow-left"></i></a></div>
|
||||
<span class="input-group-addon"><i class="fa-fw fa-{{category.icon}}"></i> {{category.title}}</span>
|
||||
<span class="input-group-addon" style="background: white;border: none;"> </span>
|
||||
<span class="input-group-addon"><i class="fa-search"></i></span>
|
||||
<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">
|
||||
<button type="button" role="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<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_decent_quality_apps'}}</span> <span class="caret"></span>
|
||||
</button>
|
||||
<ul id="dropdownFilter" class="dropdown-menu" data-filter="decentQuality" role="menu">
|
||||
|
@ -24,32 +28,51 @@
|
|||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div class="list-group grid">
|
||||
<div class="subtag-selector">
|
||||
{{#if category.subtags}}
|
||||
<button class="btn btn-default active" data-subtag="all">{{t 'all'}}</button>
|
||||
{{/if}}
|
||||
{{#category.subtags}}
|
||||
<button class="btn btn-default" data-subtag="{{id}}">{{title}}</button>
|
||||
{{/category.subtags}}
|
||||
{{#if category.subtags}}
|
||||
<button class="btn btn-default" data-subtag="others">{{t 'others'}}</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div id="apps" class="list-group grid">
|
||||
{{#apps}}
|
||||
<div class="app-card panel panel-default {{status}} {{state}} {{isWorking}} {{isHighQuality}} {{decentQuality}} {{level}}-level">
|
||||
<div class="app-card panel panel-default {{state}} {{isWorking}} {{isHighQuality}} {{decentQuality}} {{level}}-level" data-subtags="{{#subtags}}{{.}}{{#unless @last}},{{/unless}}{{/subtags}}">
|
||||
<div class="panel-body">
|
||||
<h2 class="app-title">{{name}}</h2>
|
||||
<div class="category">
|
||||
<h2 class="app-title">
|
||||
{{manifest.name}}
|
||||
{{#if (eq state 'working') }}
|
||||
{{#if (eq decentQuality 'badQuality')}}
|
||||
<span class="label label-warning label-as-badge app-state" title="{{t 'app_state_low_quality_explanation' }}">{{t 'app_state_low_quality' }}</span>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<span class="label label-{{stateColor}} label-as-badge app-state" title="{{t (concat 'app_state_' state '_explanation') }}">{{t (concat 'app_state_' 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>
|
||||
<span class="label label-{{maintainedColor}} label-as-badge maintained-status" title="{{t (concat maintained '_details') }}"> {{t maintained}}</span>
|
||||
</div>
|
||||
<div class="app-card-desc">{{description}}</div>
|
||||
{{/if}}
|
||||
</h2>
|
||||
<div class="app-card-desc">{{manifest.description}}</div>
|
||||
</div>
|
||||
<div class="app-card-date-maintainer">
|
||||
<i class="fa-refresh"></i> {{formatDate updateDate day="numeric" month="long" year="numeric"}} -
|
||||
<span title="{{t 'current_maintainer_title'}}" class="maintained"></span><i class="fa-user"></i> {{manifest.maintainer}}</span>
|
||||
{{#if (eq maintainedColor 'danger') }}
|
||||
<span class="text text-warning maintained-status" title="{{t (concat maintained '_details') }}"><i class="fa-fw fa-warning"></i> {{t maintained}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{git.url}}" target="_BLANK" type="button" role="button" class="btn btn-default col-xs-4">
|
||||
<i class="fa-globe"></i> Code
|
||||
<i class="fa-fw fa-code"></i> Code
|
||||
</a>
|
||||
<a href="{{git.url}}/blob/master/README.md" target="_BLANK" type="button" role="button" class="btn btn-default col-xs-4">
|
||||
<i class="fa-book"></i> Readme
|
||||
<i class="fa-fw fa-book"></i> Readme
|
||||
</a>
|
||||
{{#installable}}
|
||||
<a href="#/apps/install/{{id}}" type="button" role="button" class="btn btn-{{installColor}} col-xs-4 active">
|
||||
<i class="fa-plus"></i> {{t 'install'}}{{^isSafe}} <i class="fa-warning"></i>{{/isSafe}}
|
||||
<a href="#/apps/install/{{manifest.id}}" type="button" role="button" class="btn btn-{{installColor}} col-xs-4 active">
|
||||
<i class="fa-fw fa-plus"></i> {{t 'install'}}{{^isSafe}} <i class="fa-fw fa-warning"></i>{{/isSafe}}
|
||||
</a>
|
||||
{{/installable}}
|
||||
{{^installable}}
|
||||
|
@ -66,7 +89,7 @@
|
|||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="alert alert-warning">
|
||||
<span class="fa-warning"></span>
|
||||
<span class="fa-fw fa-warning"></span>
|
||||
{{t 'confirm_install_custom_app'}}
|
||||
</p>
|
||||
<form action="#/apps/install/custom" method="POST" class="form-horizontal">
|
||||
|
@ -75,7 +98,7 @@
|
|||
<div class="col-sm-12">
|
||||
<input type="url" id="url" name="url" class="form-control" value="" placeholder="https://github.com/USER/REPOSITORY" required pattern="^https://github.com/[a-zA-Z0-9-_.]+/[a-zA-Z0-9-_.]+[/]?$">
|
||||
<p class="text-warning">
|
||||
<span class="fa-github"></span> {{t 'custom_app_url_only_github'}}
|
||||
<span class="fa-fw fa-github"></span> {{t 'custom_app_url_only_github'}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
23
src/views/app/app_catalog_home.ms
Normal file
23
src/views/app/app_catalog_home.ms
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div class="btn-breadcrumb">
|
||||
<a href="#/" ><i class="fa-home"></i><span class="sr-only">{{t 'home'}}</span></a>
|
||||
<a href="#/apps">{{t 'applications'}}</a>
|
||||
<a href="#/apps/catalog">{{t 'catalog'}}</a>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div id="category-selector" class="list-group grid">
|
||||
{{#categories}}
|
||||
<a class="app-category-card panel panel-default" href="#/apps/catalog/{{id}}">
|
||||
<div class="panel-body">
|
||||
<h2 class="app-category-title"><span class="fa-fw fa-{{icon}}"></span> {{title}}</h2>
|
||||
<h3 class="app-category-card-desc">{{description}}</h3>
|
||||
</div>
|
||||
</a>
|
||||
{{/categories}}
|
||||
<a class="app-category-card" href="#/apps/catalog/all">
|
||||
<div class="panel-body">
|
||||
<h2 class="app-category-title" style="padding-top: 3em'"><span class="fa-fw fa-search"></span> {{t 'all_apps'}}</h2>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
|
@ -22,7 +22,7 @@
|
|||
<dt>{{t 'version'}}</dt>
|
||||
<dd>{{version}}</dd>
|
||||
<dt>{{t 'multi_instance'}}</dt>
|
||||
<dd>{{manifest.multi_instance}}</dd>
|
||||
<dd>{{supports_multi_instance}}</dd>
|
||||
<dt>{{t 'install_time'}}</dt>
|
||||
<dd>{{formatTime install_time day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}</dd>
|
||||
{{#if settings.domain}}
|
||||
|
@ -64,7 +64,7 @@
|
|||
<hr>
|
||||
<div class="container">
|
||||
<p>{{t 'app_info_changeurl_desc' settings.domain}}</p>
|
||||
{{#if change_url}}
|
||||
{{#if supports_change_url}}
|
||||
<a href="#/apps/{{settings.id}}/changeurl" role="button" class="btn btn-info slide">
|
||||
<span class="fa-exchange"></span> {{t 'app_change_url'}}
|
||||
</a>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class="btn-breadcrumb">
|
||||
<a href="#/" ><i class="fa-home"></i><span class="sr-only">{{t 'home'}}</span></a>
|
||||
<a href="#/apps">{{t 'applications'}}</a>
|
||||
<a href="#/apps/install">{{t 'install'}}</a>
|
||||
<a href="#/apps/install/{{id}}">{{manifest.name}}</a>
|
||||
<a href="#/apps/catalog">{{t 'catalog'}}</a>
|
||||
<a href="#/apps/install/{{id}}">{{t 'install_name' manifest.name}}</a>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
@ -18,7 +18,7 @@
|
|||
<dt>{{t 'id'}}</dt>
|
||||
<dd>{{id}}</dd>
|
||||
<dt>{{t 'description'}}</dt>
|
||||
<dd>{{description}}</dd>
|
||||
<dd>{{manifest.description}}</dd>
|
||||
{{#displayLicense}}
|
||||
<dt>{{t 'license'}}</dt>
|
||||
<dd>{{manifest.license}}</dd>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</div>
|
||||
|
||||
<div class="actions-group">
|
||||
<a role="button" href="#/apps/install" class="btn btn-success slide">
|
||||
<a role="button" href="#/apps/catalog" class="btn btn-success slide">
|
||||
<span class="fa-plus"></span> {{t 'install'}}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<a href="#/apps/{{id}}" class="list-group-item slide" title="{{t 'infos'}}">
|
||||
<span class="fa-chevron-right pull-right"></span>
|
||||
<h2 class="list-group-item-heading">
|
||||
{{label}} <small>{{name}}</small>
|
||||
{{settings.label}} <small>{{name}}</small>
|
||||
</h2>
|
||||
<p class="list-group-item-text">{{description}}</p>
|
||||
</a>
|
||||
|
|
Loading…
Add table
Reference in a new issue