diff --git a/src/css/style.less b/src/css/style.less index 21b27fa8..1f362492 100644 --- a/src/css/style.less +++ b/src/css/style.less @@ -706,12 +706,15 @@ input[type='radio'].nice-radio { #view-groups { .panel-heading a { text-decoration: none; - &.group-delete { - float:right; - color:lighten(@label-danger-bg, 20%); - :hover { - color:@label-danger-bg; - } + } + .group-delete { + font-size: 24px; + line-height: 24px; + padding: 0; + float:right; + color:lighten(@label-danger-bg, 20%); + :hover { + color:@label-danger-bg; } } .panel-body { @@ -725,6 +728,10 @@ input[type='radio'].nice-radio { .dropdown-menu { max-height: 200px; overflow-y: auto; + + button { + background: none; + } } .label-removable { // The following match properties from regular btn's @@ -743,15 +750,17 @@ input[type='radio'].nice-radio { margin-right:7px; // Spacing between labels - > a { + > button { + line-height: 12px; margin-left:6px; + padding: 0; padding-left:6px; border-left: #ccc 1px solid; color:lighten(@label-info-bg,20); text-decoration: none; } - > a:hover { + > button:hover { color:@label-info-bg; } } @@ -925,3 +934,10 @@ input[type='radio'].nice-radio { float: none !important; } } + +.notransition { + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + transition: none !important; +} diff --git a/src/index.html b/src/index.html index 377f1727..c693f55a 100644 --- a/src/index.html +++ b/src/index.html @@ -81,8 +81,8 @@
diff --git a/src/js/yunohost/controllers/apps.js b/src/js/yunohost/controllers/apps.js index a9694ae0..17c91e10 100644 --- a/src/js/yunohost/controllers/apps.js +++ b/src/js/yunohost/controllers/apps.js @@ -10,7 +10,7 @@ // List installed apps app.get('#/apps', function (c) { - c.api('/apps?installed', function(data) { // http://api.yunohost.org/#!/app/app_list_get_8 + c.api('GET', '/apps?installed', {}, function(data) { var apps = data['apps']; c.arraySortById(apps); c.view('app/app_list', {apps: apps}); @@ -109,8 +109,8 @@ // List available apps app.get('#/apps/install', function (c) { - 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('GET', '/apps', {}, function (data) { + c.api('GET', '/apps?raw', {}, function (dataraw) { var apps = [] $.each(data['apps'], function(k, v) { app = dataraw[v['id']]; @@ -201,30 +201,59 @@ // Get app information app.get('#/apps/:app', function (c) { - c.api('/apps/'+c.params['app']+'?raw', function(data) { // http://api.yunohost.org/#!/app/app_info_get_9 - c.api('/users/permissions', function(data_permissions) { + c.api('GET', '/apps/'+c.params['app']+'?raw', {}, function(data) { + c.api('GET', '/users/permissions', {}, function(data_permissions) { - // Permissions - data.permissions = data_permissions.permissions[c.params['app']+".main"]["allowed"]; + // Permissions + data.permissions = data_permissions.permissions[c.params['app']+".main"]["allowed"]; - // Multilingual description - data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ? - data.manifest.description[y18n.locale] : - data.manifest.description['en'] - ; + // Multilingual description + data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ? + data.manifest.description[y18n.locale] : + data.manifest.description['en'] + ; - // Multi Instance settings - data.manifest.multi_instance = data.manifest.multi_instance ? y18n.t('yes') : y18n.t('no'); - data.install_time = new Date(data.settings.install_time * 1000); + // Multi Instance settings + data.manifest.multi_instance = data.manifest.multi_instance ? y18n.t('yes') : y18n.t('no'); + data.install_time = new Date(data.settings.install_time * 1000); - c.view('app/app_info', data); + c.view('app/app_info', data, function() { + + // Button to set the app as default + $('button[data-action="set-as-default"]').on("click", function() { + var app = $(this).data("app"); + c.confirm( + y18n.t('applications'), + y18n.t('confirm_app_default'), + function() { c.api('PUT', '/apps/'+app+'/default', {}, function() { c.refresh() }); } + ); + }); + + // Button to uninstall the app + $('button[data-action="uninstall"]').on("click", function() { + var app = $(this).data("app"); + c.confirm( + y18n.t('applications'), + y18n.t('confirm_uninstall', [app]), + function() { + c.api('DELETE', '/apps/'+ app, {}, function() { + c.redirect_to('#/apps'); + }); + } + ); + }); }); }); + }); }); + // + // App actions + // + // Get app actions list app.get('#/apps/:app/actions', function (c) { - c.api('/apps/'+c.params['app']+'/actions', function(data) { + c.api('GET', '/apps/'+c.params['app']+'/actions', {}, function(data) { $.each(data.actions, function(_, action) { formatYunoHostStyleArguments(action.arguments, c.params); @@ -241,7 +270,7 @@ }); }); - // Perform application + // Perform app action app.put('#/apps/:app/actions/:action', function(c) { // taken from app install $.each(c.params, function(k, v) { @@ -260,14 +289,18 @@ 'args': c.serialize(c.params.toHash()) } - c.api('/apps/'+app_id+'/actions/'+action_id, function() { // http://api.yunohost.org/#!/app/app_install_post_2 - c.redirect('#/apps/'+app_id+'/actions'); - }, 'PUT', params); + c.api('PUT', '/apps/'+app_id+'/actions/'+action_id, params, function() { + c.redirect_to('#/apps/'+app_id+'/actions', {slide:false}); + }); }); + // + // App config panel + // + // Get app config panel app.get('#/apps/:app/config-panel', function (c) { - c.api('/apps/'+c.params['app']+'/config-panel', function(data) { + c.api('GET', '/apps/'+c.params['app']+'/config-panel', {}, function(data) { $.each(data.config_panel.panel, function(_, panel) { $.each(panel.sections, function(_, section) { formatYunoHostStyleArguments(section.options, c.params); @@ -293,16 +326,16 @@ 'args': c.serialize(c.params.toHash()) } - c.api('/apps/'+app_id+'/config', function() { // http://api.yunohost.org/#!/app/app_install_post_2 - c.redirect('#/apps/'+app_id+'/config-panel'); - }, 'POST', params); + c.api('POST', '/apps/'+app_id+'/config', params, function() { + c.redirect_to('#/apps/'+app_id+'/config-panel', {slide:false}); + }); }) // Special case for custom app installation. app.get('#/apps/install/custom', function (c) { // If we try to GET /apps/install/custom, it means that installation fail. // Need to redirect to apps/install to get rid of pacamn and see the log. - c.redirect('#/apps/install'); + c.redirect_to('#/apps/install'); }); // Helper function that formats YunoHost style arguments for generating a form @@ -473,7 +506,7 @@ // App installation form app.get('#/apps/install/:app', function (c) { - c.api('/apps?raw', function(data) { // http://api.yunohost.org/#!/app/app_list_get_8 + c.api('GET', '/apps?raw', {}, function(data) { var app_name = c.params["app"]; var app_infos = data[app_name]; if (app_infos['state'] === "validated") @@ -495,10 +528,6 @@ app_infos.manifest, c.params ); - }, - function(){ - $('div.loader').remove(); - c.redirect('#/apps/install'); } ); } @@ -539,14 +568,13 @@ delete params['args']; } - c.api('/apps', function() { // http://api.yunohost.org/#!/app/app_install_post_2 - c.redirect('#/apps'); - }, 'POST', params); + c.api('POST', '/apps', params, function() { + c.redirect_to('#/apps'); + }); } else { c.flash('warning', y18n.t('app_install_cancel')); - store.clear('slide'); - c.redirect('#/apps/install'); + c.refresh(); } }); @@ -586,77 +614,35 @@ }) .fail(function(xhr) { c.flash('fail', y18n.t('app_install_custom_no_manifest')); - store.clear('slide'); - c.redirect('#/apps/install'); + c.refresh(); }); - }, - function(){ - c.flash('warning', y18n.t('app_install_cancel')); - store.clear('slide'); - c.redirect('#/apps/install'); - } - ); - }); - - // Remove installed app - app.get('#/apps/:app/uninstall', function (c) { - c.confirm( - y18n.t('applications'), - y18n.t('confirm_uninstall', [c.params['app']]), - function() { - c.api('/apps/'+ c.params['app'], function() { // http://api.yunohost.org/#!/app/app_remove_delete_4 - c.redirect('#/apps'); - }, 'DELETE'); - }, - function() { - store.clear('slide'); - c.redirect('#/apps/'+ c.params['app']); - } - ); - }); - - // Make app default - app.get('#/apps/:app/default', function (c) { - c.confirm( - y18n.t('applications'), - y18n.t('confirm_app_default'), - function() { - c.api('/apps/'+ c.params['app'] +'/default', function() { // - store.clear('slide'); - c.redirect('#/apps/'+ c.params['app']); - }, 'PUT'); - }, - function() { - store.clear('slide'); - c.redirect('#/apps/'+ c.params['app']); } ); }); // Get app change label page app.get('#/apps/:app/changelabel', function (c) { - c.api('/apps/'+c.params['app']+'?raw', function(app_data) { - data = { + c.api('GET', '/apps/'+c.params['app']+'?raw', {}, function(app_data) { + data = { id: c.params['app'], label: app_data.settings.label, - }; - c.view('app/app_changelabel', data); + }; + c.view('app/app_changelabel', data); }); }); // Change app label app.post('#/apps/:app/changelabel', function (c) { params = {'new_label': c.params['label']}; - c.api('/apps/' + c.params['app'] + '/label', function(data) { // Call changelabel API - store.clear('slide'); - c.redirect('#/apps/'+ c.params['app']); - }, 'PUT', params); + c.api('PUT', '/apps/' + c.params['app'] + '/label', params, function(data) { + c.redirect_to('#/apps/'+ c.params['app']); + }); }); // Get app change URL page app.get('#/apps/:app/changeurl', function (c) { - c.api('/apps/'+c.params['app']+'?raw', function(app_data) { - c.api('/domains', function(domain_data) { // http://api.yunohost.org/#!/domain/domain_list_get_2 + c.api('GET', '/apps/'+c.params['app']+'?raw', {}, function(app_data) { + c.api('GET', '/domains', {}, function(domain_data) { // Display a list of available domains var domains = []; @@ -688,14 +674,9 @@ y18n.t('confirm_app_change_url', [c.params['app']]), function() { params = {'domain': c.params['domain'], 'path': c.params['path']}; - c.api('/apps/' + c.params['app'] + '/changeurl', function(data) { // Call changeurl API - store.clear('slide'); - c.redirect('#/apps/'+ c.params['app']); - }, 'PUT', params); - }, - function() { - store.clear('slide'); - c.redirect('#/apps/'+ c.params['app'] + '/changeurl'); + c.api('PUT', '/apps/' + c.params['app'] + '/changeurl', params, function(data) { + c.redirect_to('#/apps/'+ c.params['app']); + }); } ); }); diff --git a/src/js/yunohost/controllers/backup.js b/src/js/yunohost/controllers/backup.js index a4f77b27..42a5d455 100644 --- a/src/js/yunohost/controllers/backup.js +++ b/src/js/yunohost/controllers/backup.js @@ -32,118 +32,9 @@ c.view('backup/backup', {'storages':storages}); }); - // Storage list - app.get('#/storages/create', function (c) { - c.view('backup/storage_create', {}); - }); - - // Create a storage - app.post('#/storages', function (c) { - store.clear('slide'); - c.redirect('#/storages'); - }); - - // Create a backup - app.get('#/backup/:storage/create', function (c) { - var data = []; - data['storage'] = { - id:c.params['storage'], - name:y18n.t('local_archives') - }; - c.api('/hooks/backup', function(hooks) { - data['hooks'] = c.groupHooks(hooks['hooks']); - data['apps'] = {}; - c.api('/apps?with_backup', function(apps_list) { - data['apps'] = apps_list.apps; - c.view('backup/backup_create', data, c.selectAllOrNone); - }); - }); - }); - - - app.post('#/backup/:storage', function (c) { - var params = c.ungroupHooks(c.params['system_parts'],c.params['apps']); - c.api('/backup', function() { - store.clear('slide'); - c.redirect('#/backup/'+ c.params['storage']); - }, 'POST', params); - }); - - // Restore a backup - app.post('#/backup/:storage/:archive/restore', function (c) { - c.confirm( - y18n.t('backup'), - y18n.t('confirm_restore', [c.params['archive']]), - $.proxy(function(c){ - var params = c.ungroupHooks(c.params['system_parts'],c.params['apps']); - params['force'] = ''; - c.api('/backup/restore/'+c.params['archive'], function(data) { - store.clear('slide'); - c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']); - }, 'POST', params); - }, this, c), - function(){ - store.clear('slide'); - c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']); - } - ); - }); - - // Delete a backup - app.get('#/backup/:storage/:archive/delete', function (c) { - c.confirm( - y18n.t('backup'), - y18n.t('confirm_delete', [c.params['archive']]), - function(){ - c.api('/backup/archives/'+c.params['archive'], function(data) { - c.redirect('#/backup/'+ c.params['storage']); - }, 'DELETE'); - }, - function(){ - store.clear('slide'); - c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']); - } - ); - }); - - // Download a backup - app.get('#/backup/:storage/:archive/download', function (c) { - c.api('/backup/'+c.params['archive']+'/download', function(data) { - c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']); - }, 'GET'); - }); - - // Copy a backup - app.get('#/backup/:storage/:archive/copy', function (c) { - store.clear('slide'); - c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']); - }); - - // Upload a backup - app.get('#/backup/:storage/:archive/upload', function (c) { - store.clear('slide'); - c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']); - }); - - // Get archive info - app.get('#/backup/:storage/:archive', function (c) { - c.api('/backup/archives/'+c.params['archive']+'?with_details', function(data) { - data.storage = { - id: c.params['storage'], - name: y18n.t('local_archives') - }; - data.other_storages = []; - data.name = c.params['archive']; - data.system_parts = c.groupHooks(Object.keys(data['system']),data['system']); - data.items = (data['system']!={} || data['apps']!=[]); - data.locale = y18n.locale - c.view('backup/backup_info', data, c.selectAllOrNone); - }); - }); - // Archive list app.get('#/backup/:storage', function (c) { - c.api('/backup/archives?with_info', function(data) { + c.api('GET', '/backup/archives?with_info', {}, function(data) { data.storage = { id: 'local', name: y18n.t('local_archives') @@ -159,4 +50,173 @@ }); }); + // View to create a backup + app.get('#/backup/:storage/create', function (c) { + var data = []; + data['storage'] = { + id:c.params['storage'], + name:y18n.t('local_archives') + }; + c.api('GET', '/hooks/backup', {}, function(hooks) { + data['hooks'] = groupHooks(hooks['hooks']); + data['apps'] = {}; + c.api('GET', '/apps?with_backup', {}, function(apps_list) { + data['apps'] = apps_list.apps; + c.view('backup/backup_create', data, function() { + + // Configure buttons "select all" and "select none" + + // Remove active style from buttons + $(".select_all-none input").click(function(){ $(this).toggleClass("active"); }); + // Select all checkbox in this panel + $(".select_all").click(function(){ + $(this).parents(".panel").children(".list-group").find("input").prop("checked", true); + }); + // Deselect all checkbox in this panel + $(".select_none").click(function(){ + $(this).parents(".panel").children(".list-group").find("input").prop("checked", false); + }); + }); + }); + }); + }); + + // Actually creating the backup + app.post('#/backup/:storage', function (c) { + var params = ungroupHooks(c.params['system_parts'],c.params['apps']); + c.api('POST', '/backup', params, function() { + c.redirect_to('#/backup/'+ c.params['storage']); + }); + }); + + // Get archive info + app.get('#/backup/:storage/:archive', function (c) { + c.api('GET', '/backup/archives/'+c.params['archive']+'?with_details', {}, function(data) { + data.storage = { + id: c.params['storage'], + name: y18n.t('local_archives') + }; + data.name = c.params['archive']; + data.system_parts = groupHooks(Object.keys(data['system']),data['system']); + data.items = (data['system']!={} || data['apps']!=[]); + data.locale = y18n.locale; + c.view('backup/backup_info', data, function() { + + // Configure buttons "select all" and "select none" + + // Remove active style from buttons + $(".select_all-none input").click(function(){ $(this).toggleClass("active"); }); + // Select all checkbox in this panel + $(".select_all").click(function(){ + $(this).parents(".panel").children(".list-group").find("input").prop("checked", true); + }); + // Deselect all checkbox in this panel + $(".select_none").click(function(){ + $(this).parents(".panel").children(".list-group").find("input").prop("checked", false); + }); + + // Delete button + $('button[data-action="delete"]').on('click', function() { + var storage = $(this).data('storage'); + var archive = $(this).data('archive'); + c.confirm( + y18n.t('backup'), + y18n.t('confirm_delete', [archive]), + function(){ + c.api('DELETE', '/backup/archives/'+archive, {}, function(data) { + c.redirect_to('#/backup/'+ storage); + }); + } + ); + }); + }); + }); + }); + + // Restore a backup + app.post('#/backup/:storage/:archive/restore', function (c) { + c.confirm( + y18n.t('backup'), + y18n.t('confirm_restore', [c.params['archive']]), + $.proxy(function(c){ + var params = ungroupHooks(c.params['system_parts'],c.params['apps']); + params['force'] = ''; + c.api('POST', '/backup/restore/'+c.params['archive'], params, function(data) { + c.redirect_to('#/backup/'+ c.params['storage']+'/'+c.params['archive']); + }); + }, this, c) + ); + }); + + function groupHooks(hooks, raw_infos) { + var data = {}; + var rules = [ + { + id:'configuration', + isIn:function (hook) { + return hook.indexOf('conf_')==0 + } + } + ]; + + $.each(hooks, function(i, hook) { + var group_id=hook; + var hook_size=(raw_infos && raw_infos[hook] && raw_infos[hook].size)?raw_infos[hook].size:0; + $.each(rules, function(i, rule) { + if (rule.isIn(hook)) { + group_id = 'adminjs_group_'+rule.id; + return false; + } + }); + + if(group_id in data) { + data[group_id] = { + name:y18n.t('hook_'+group_id), + value:data[group_id].value+','+hook, + description:data[group_id].description+', '+y18n.t('hook_'+hook), + size:data[group_id].size + hook_size + }; + } + else { + data[group_id] = { + name:y18n.t('hook_'+group_id), + value:hook, + description:(group_id==hook)?y18n.t('hook_'+hook+'_desc'):y18n.t('hook_'+hook), + size:hook_size + }; + } + }); + return data; + }; + + function ungroupHooks(system_parts, apps) { + + var data = {}; + data['apps'] = apps || []; + data['system'] = system_parts || []; + + if (data['system'].constructor !== Array) { + data['system'] = [data['system']]; + } + if (data['apps'].constructor !== Array) { + data['apps'] = [data['apps']]; + } + + // Some hook value contains multiple hooks separated by commas + var split_hooks = []; + $.each(data['system'], function(i, hook) { + split_hooks = split_hooks.concat(hook.split(',')); + }); + data['system'] = split_hooks; + + if (data['system'].length == 0) { + delete data['system']; + } + if (data['apps'].length == 0) { + delete data['apps']; + } + return data; + }; + + })(); diff --git a/src/js/yunohost/controllers/domains.js b/src/js/yunohost/controllers/domains.js index d50da321..51850f90 100644 --- a/src/js/yunohost/controllers/domains.js +++ b/src/js/yunohost/controllers/domains.js @@ -10,8 +10,8 @@ // List existing domains app.get('#/domains', function (c) { - c.api('/domains', function(data) { // http://api.yunohost.org/#!/domain/domain_list_get_2 - c.api('/domains/main', function(data2) { + c.api('GET', '/domains', {}, function(data) { + c.api('PUT', '/domains/main', {}, function(data2) { var domains = []; $.each(data.domains, function(k, domain) { domains.push({ @@ -29,7 +29,7 @@ domains: domains, main_domain_form: main_domain_form }); - }, 'PUT'); + }); }); }); @@ -68,8 +68,7 @@ if (c.params['domain'] === '') { if (c.params['ddomain'] === '') { c.flash('fail', y18n.t('error_select_domain')); - store.clear('slide'); - c.redirect('#/domains/add'); + c.redirect_to('#/domains/add'); } params.domain = c.params['ddomain'] + c.params['ddomain-ext']; endurl = 'dyndns'; @@ -77,42 +76,56 @@ params.domain = c.params['domain']; } - c.api('/domains?'+endurl, function(data) { // http://api.yunohost.org/#!/domain/domain_add_post_1 - c.redirect('#/domains'); - }, 'POST', params); + c.api('POST', '/domains?'+endurl, params, function(data) { + c.redirect_to('#/domains'); + }); }); // Get existing domain info app.get('#/domains/:domain', function (c) { - c.api('/domains/main', function(dataMain) { - c.api('/apps?installed', function(data) { // http://api.yunohost.org/#!/app/app_list_get_8 - - // FIXME - This dirty trick (along with the previous API call - // for apps installed) should be removed once letsencrypt_ynh - // is not used by many people anymore. Probably around 07/2017 - // or end of 2017... - var enable_cert_management_ = true; - $.each(data['apps'], function(k, v) { - if (v.id == "letsencrypt") { - enable_cert_management_ = false; - } - }); - + c.api('PUT', '/domains/main', {}, function(dataMain) { + c.api('GET', '/apps?installed', {}, function(data) { var domain = { name: c.params['domain'], main: (c.params['domain'] == dataMain.current_main_domain) ? true : false, - url: "https://"+c.params['domain'], - enable_cert_management: enable_cert_management_ + url: "https://"+c.params['domain'] }; - c.view('domain/domain_info', domain); + c.view('domain/domain_info', domain, function() { + + // Configure "set default" button + $('button[data-action="set_default"]').on("click", function() { + var domain = $(this).data("domain"); + c.confirm( + y18n.t('domains'), + y18n.t('confirm_change_maindomain'), + function() { + c.api('PUT', '/domains/main', {new_main_domain: domain}, function() { c.refresh() }); + } + ) + }); + + // Configure delete button + $('button[data-action="delete"]').on("click", function() { + var domain = $(this).data("domain"); + c.confirm( + y18n.t('domains'), + y18n.t('confirm_delete', [domain]), + function(){ + c.api('DELETE', '/domains/'+ domain, {}, function(data) { + c.redirect_to('#/domains'); + }); + } + ); + }); + }); }); - }, 'PUT'); + }); }); // Domain DNS app.get('#/domains/:domain/dns', function (c) { - c.api('/domains/' + c.params['domain'] + '/dns', function(data) { + c.api('GET', '/domains/' + c.params['domain'] + '/dns', {}, function(data) { var domain = { name: c.params['domain'], dns: data @@ -123,7 +136,7 @@ // Domain certificate app.get('#/domains/:domain/cert-management', function (c) { - c.api('/domains/cert-status/' + c.params['domain'] + '?full', function(data) { + c.api('GET', '/domains/cert-status/' + c.params['domain'] + '?full', {}, function(data) { var s = data["certificates"][c.params['domain']]; var status_ = { @@ -199,132 +212,45 @@ status: status_, actions_enabled : actions_enabled }; - c.view('domain/domain_cert', data_); + + c.view('domain/domain_cert', data_, function() { + // Configure install / renew buttons behavior + $("button[data-action]").on("click", function () { + var action = $(this).data("action"), + domain = $(this).data("domain"), + confirm_key = "", + api_url = ""; + + switch (action) { + case 'install-LE': + confirm_key = 'confirm_cert_install_LE'; + api_url = '/domains/cert-install/' + domain; + break; + case 'regen-selfsigned': + confirm_key = 'confirm_cert_regen_selfsigned'; + api_url = '/domains/cert-install/' + domain + "?self_signed"; + break; + case 'renew-letsencrypt': + confirm_key = 'confirm_cert_manual_renew_LE'; + api_url = '/domains/cert-renew/' + domain + "?force"; + break; + case 'replace-with-selfsigned': + confirm_key = 'confirm_cert_revert_to_selfsigned'; + api_url = '/domains/cert-install/' + domain + "?self_signed&force"; + break; + default: + c.flash('fail', y18n.t('unknown_action', [action])); + return + } + + c.confirm( + y18n.t('certificate'), + y18n.t(confirm_key, [domain]), + function(){ c.api('POST', api_url, {}, function() { c.refresh() }); } + ); + }); + }); }); }); - // Install let's encrypt certificate on domain - app.get('#/domains/:domain/cert-install-LE', function (c) { - c.confirm( - y18n.t('certificate'), - y18n.t('confirm_cert_install_LE', [c.params['domain']]), - function(){ - c.api('/domains/cert-install/' + c.params['domain'], function(data) { - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - }, 'POST'); - }, - function(){ - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - } - ); - }); - - // Regenerate a self-signed certificate - app.get('#/domains/:domain/cert-regen-selfsigned', function (c) { - c.confirm( - y18n.t('certificate'), - y18n.t('confirm_cert_regen_selfsigned', [c.params['domain']]), - function(){ - c.api('/domains/cert-install/' + c.params['domain'] + "?self_signed", function(data) { - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - }, 'POST'); - }, - function(){ - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - } - ); - }); - - // Manually renew a Let's Encrypt certificate - app.get('#/domains/:domain/cert-renew-letsencrypt', function (c) { - c.confirm( - y18n.t('certificate'), - y18n.t('confirm_cert_manual_renew_LE', [c.params['domain']]), - function(){ - c.api('/domains/cert-renew/' + c.params['domain'] + "?force", function(data) { - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - }, 'POST'); - }, - function(){ - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - } - ); - }); - - // Replace valid cert with self-signed - app.get('#/domains/:domain/cert-replace-with-selfsigned', function (c) { - c.confirm( - y18n.t('certificate'), - y18n.t('confirm_cert_revert_to_selfsigned', [c.params['domain']]), - function(){ - c.api('/domains/cert-install/' + c.params['domain'] + "?self_signed&force", function(data) { - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - }, 'POST'); - }, - function(){ - store.clear('slide'); - c.redirect('#/domains/'+c.params['domain']+'/cert-management'); - } - ); - }); - - - // Remove existing domain - app.get('#/domains/:domain/delete', function (c) { - c.confirm( - y18n.t('domains'), - y18n.t('confirm_delete', [c.params['domain']]), - function(){ - c.api('/domains/'+ c.params['domain'], function(data) { // http://api.yunohost.org/#!/domain/domain_remove_delete_3 - store.clear('slide'); - c.redirect('#/domains'); - }, 'DELETE'); - }, - function(){ - store.clear('slide'); - c.redirect('#/domains'); - } - ); - }); - - // Set default domain - app.post('#/domains', function (c) { - if (c.params['domain'] === '') { - c.flash('fail', y18n.t('error_select_domain')); - store.clear('slide'); - c.redirect('#/domains'); - } else { - c.confirm( - y18n.t('domains'), - y18n.t('confirm_change_maindomain'), - function(){ - var params = { - new_main_domain: c.params['domain'] - }; - c.api('/domains/main', function(data) { // http://api.yunohost.org/#!/tools/tools_maindomain_put_1 - store.clear('slide'); - c.redirect('#/domains'); - }, 'PUT', params); - - // Wait 15s and refresh the page - var refreshDomain = window.setTimeout(function(){ - store.clear('slide'); - c.redirect('#/domains'); - }, 15000); - }, - function(){ - store.clear('slide'); - c.redirect('#/domains'); - } - ); - } - }); - })(); diff --git a/src/js/yunohost/controllers/firewall.js b/src/js/yunohost/controllers/firewall.js index beeff865..013d2511 100644 --- a/src/js/yunohost/controllers/firewall.js +++ b/src/js/yunohost/controllers/firewall.js @@ -10,7 +10,7 @@ // Firewall status app.get('#/tools/firewall', function (c) { - c.api('/firewall?raw', function(data) { + c.api('GET', '/firewall?raw', {}, function(data) { var firewall = { ports: {}, upnp: false @@ -30,28 +30,49 @@ // Get UPnP status firewall.upnp = data.uPnP.enabled; - c.view('tools/tools_firewall', firewall); + c.view('tools/tools_firewall', firewall, function() { + + // Buttons in the 'ports' panel to open/close specific ports + $("button[data-port]").on("click", function() { + + var port = $(this).data("port"); + var action = $(this).data("action"); + var protocol = $(this).data("protocol"); + var connection = $(this).data("connection"); + c.confirm( + y18n.t('firewall'), + // confirm_firewall_open and confirm_firewall_close + y18n.t('confirm_firewall_' + action, [ port, y18n.t(protocol), y18n.t(connection)]), + function(){ c.togglePort(port, protocol, connection, action); } + ); + }); + + // Buttons to enable / disable UPnP + $("button[data-upnp]").on("click", function() { + var action = $(this).data("upnp"); + c.confirm( + y18n.t('firewall'), + // confirm_upnp_enable and confirm_upnp_disable + y18n.t('confirm_upnp_' + action), + function(){ c.api('GET', '/firewall/upnp', {action: action}, function() { c.refresh() }); } + ); + }); + }); }); }); - // Enable/Disable UPnP - app.get('#/tools/firewall/upnp/:action', function (c) { + // Update port status from form + app.post('#/tools/firewall/port', function (c) { c.confirm( y18n.t('firewall'), - // confirm_upnp_enable and confirm_upnp_disable - y18n.t('confirm_upnp_' + c.params['action'].toLowerCase()), + y18n.t('confirm_firewall_' + c.params['action'].toLowerCase(), [ c.params['port'], y18n.t(c.params['protocol']), y18n.t(c.params['connection']) ]), function(){ - var params = { - action : c.params['action'] - }; - c.api('/firewall/upnp', function(data) { - store.clear('slide'); - c.redirect('#/tools/firewall'); - }, 'GET', params); - }, - function(){ - store.clear('slide'); - c.redirect('#/tools/firewall'); + c.togglePort( + c.params['port'], + c.params['protocol'], + c.params['connection'], + c.params['action'] + ); } ); }); @@ -65,8 +86,7 @@ if (port != parseInt(port) || port < 0 || port > 65535) { c.flash('fail', y18n.t('unknown_argument', [port])); - store.clear('slide'); - c.redirect('#/tools/firewall'); + c.refresh(); } switch (connection) { @@ -98,75 +118,27 @@ break; default: c.flash('fail', y18n.t('unknown_action', [action])); - store.clear('slide'); - c.redirect('#/tools/firewall'); + c.refresh(); } - if (method !== null && protocol !== null && port !== null) { - // port: - // protocol: - // - UDP - // - TCP - // - Both - // --ipv4-only: - // --ipv6-only: - // --no-upnp: - var params = { - port : port, - protocol : protocol - }; - c.api('/firewall/port?'+endurl, function(data) { - store.clear('slide'); - c.redirect('#/tools/firewall'); - }, method, params); - } - else { - store.clear('slide'); - c.redirect('#/tools/firewall'); - } + // port: + // protocol: + // - UDP + // - TCP + // - Both + // --ipv4-only: + // --ipv6-only: + // --no-upnp: + var params = { + port : port, + protocol : protocol + }; + + c.api(method, '/firewall/port?'+endurl, params, function() { c.refresh() }); + + return; }); - // Update port status from direct link - // #/firewall/port/{{@key}}/tcp/ipv4/close - app.get('#/tools/firewall/port/:port/:protocol/:connection/:action', function (c) { - c.confirm( - y18n.t('firewall'), - // confirm_firewall_open and confirm_firewall_close - y18n.t( 'confirm_firewall_' + c.params['action'].toLowerCase(), [ c.params['port'], y18n.t(c.params['protocol']), y18n.t(c.params['connection'])]), - function(){ - c.togglePort( - c.params['port'], - c.params['protocol'], - c.params['connection'], - c.params['action'] - ); - }, - function(){ - store.clear('slide'); - c.redirect('#/tools/firewall'); - } - ); - }); - // Update port status from form - app.post('#/tools/firewall/port', function (c) { - c.confirm( - y18n.t('firewall'), - y18n.t('confirm_firewall_' + c.params['action'].toLowerCase(), [ c.params['port'], y18n.t(c.params['protocol']), y18n.t(c.params['connection']) ]), - function(){ - c.togglePort( - c.params['port'], - c.params['protocol'], - c.params['connection'], - c.params['action'] - ); - }, - function(){ - store.clear('slide'); - c.redirect('#/tools/firewall'); - } - ); - }); - -})(); \ No newline at end of file +})(); diff --git a/src/js/yunohost/controllers/home.js b/src/js/yunohost/controllers/home.js index ac315c21..9038ed76 100644 --- a/src/js/yunohost/controllers/home.js +++ b/src/js/yunohost/controllers/home.js @@ -24,45 +24,36 @@ $('#masthead').show() .find('.logout-btn').hide(); store.set('path-1', '#/login'); - if ($('div.loader').length === 0) { - $('#main').append(''); + + c.showLoader(); + + // We gonna retry 3 times to check if yunohost is installed + if (app.isInstalledTry === undefined) { + app.isInstalledTry = 3; } c.checkInstall(function(isInstalled) { + if (isInstalled) { - // Remove loader - $('div.loader').remove(); - // Pass domain to hide form field c.view('login', { 'domain': window.location.hostname }); - } else if (typeof isInstalled === 'undefined') { - if (app.isInstalledTry > 0) { - app.isInstalledTry--; - app.loaded = false; // Show pacman - setTimeout(function() { - c.redirect('#/'); - }, 5000); - } - else { - // Reset count - app.isInstalledTry = 3; + return; + } - // API is not responding after 3 try - $( document ).ajaxError(function( event, request, settings ) { - // Display error if status != 200. - // .ajaxError fire even with status code 200 because json is sometimes not valid. - if (request.status !== 200) c.flash('fail', y18n.t('api_not_responding', [request.status+' '+request.statusText] )); - - // Unbind directly - $(document).off('ajaxError'); - }); - - // Remove pacman - app.loaded = true; - $('div.loader').remove(); - } - } else { - $('div.loader').remove(); + if (typeof isInstalled !== 'undefined') { c.redirect('#/postinstall'); + return; + } + + // If the retry counter is still up, retry this function 5 sec + // later + if (app.isInstalledTry > 0) { + app.isInstalledTry--; + setTimeout(function() { + c.redirect('#/'); + }, 5000); + } + else { + c.flash('fail', y18n.t('api_not_responding')); } }); }); @@ -80,7 +71,7 @@ var params = { password: c.params['password'] }; - c.api('/login', function(data) { + c.api('POST', '/login', params, function(data) { store.set('connected', true); c.trigger('login'); $('#masthead .logout-btn').fadeIn(); @@ -90,19 +81,19 @@ } else { c.redirect('#/'); } - }, 'POST', params, false); + }, undefined, false); }); app.get('#/logout', function (c) { - c.api('/logout', function (data) { + c.api('GET', '/logout', {}, function (data) { store.clear('url'); store.clear('connected'); store.set('path', '#/'); c.trigger('logout'); c.flash('success', y18n.t('logged_out')); c.redirect('#/login'); - }, 'GET', {}, false); + }, undefined, false); }); })(); diff --git a/src/js/yunohost/controllers/postinstall.js b/src/js/yunohost/controllers/postinstall.js index 04f7d7e9..d8fc96a7 100644 --- a/src/js/yunohost/controllers/postinstall.js +++ b/src/js/yunohost/controllers/postinstall.js @@ -13,7 +13,7 @@ $('#masthead').hide(); c.checkInstall(function(isInstalled) { if (isInstalled || typeof isInstalled === 'undefined') { - c.redirect('#/login'); + c.redirect_to('#/login'); } else { c.view('postinstall/postinstall_1'); } @@ -41,7 +41,6 @@ if ($('#domain').val() === '') { if ($('#ddomain').val() === '') { e.preventDefault(); - store.clear('slide'); c.flash('fail', y18n.t('error_select_domain')); } else { domain = $('#ddomain').val() + $('select[name="ddomain-ext"]').val(); @@ -51,7 +50,7 @@ } store.set('maindomain', domain); }); - }, false); // We disable enableSlide because that causes some issues with accordion when using the 'previous' button + }); }); }); @@ -59,49 +58,52 @@ app.get('#/postinstall/password', function(c) { $('#masthead').hide(); if (!store.get('maindomain')) { - store.clear('slide'); - c.redirect('#/postinstall/domain'); + c.redirect_to('#/postinstall/domain'); } else { - c.view('postinstall/postinstall_3', { 'domain': store.get('maindomain').toLowerCase() }, - function() { }, - false); // We disable enableSlide because that causes some issues with accordion when using the 'previous' button + c.view('postinstall/postinstall_3', { 'domain': store.get('maindomain').toLowerCase() }); } }); // Execute post-installation app.post('#/postinstall', function (c) { - if (c.params['password'] === '' || c.params['confirmation'] === '') { + + var password = c.params['password']; + var confirmation = c.params['confirmation']; + var domain = c.params['domain'].toLowerCase(); + + // Check password ain't empty + if (password === '' || confirmation === '') { c.flash('fail', y18n.t('password_empty')); + return; } - else if (c.params['password'] == c.params['confirmation']) { - if (c.params['domain'] === '') { - c.flash('fail', y18n.t('error_select_domain')); - store.clear('slide'); - c.redirect('#/postinstall/domain'); - } else { - var params = { - domain: c.params['domain'].toLowerCase() - }; - } - c.confirm( - y18n.t('postinstall'), - y18n.t('confirm_postinstall', [c.params['domain']]), - function(){ - params.password = c.params['password']; - - store.set('url', window.location.hostname +'/yunohost/api'); - store.set('user', 'admin'); - c.api('/postinstall', function(data) { // http://api.yunohost.org/#!/tools/tools_postinstall_post_0 - c.redirect('#/login'); - }, 'POST', params); - }, - function(){ - } - ); - } else { + // Check password matches confirmation + if (password !== confirmation) { c.flash('fail', y18n.t('passwords_dont_match')); + return; } + + // Check domain ain't empty... + if (domain === '') { + c.flash('fail', y18n.t('error_select_domain')); + c.redirect_to('#/postinstall/domain', {slide: false}); + return; + } + + // Ask confirmation to the user + c.confirm( + y18n.t('postinstall'), + y18n.t('confirm_postinstall', [c.params['domain']]), + // Start the actual postinstall process + function(){ + store.set('url', window.location.hostname +'/yunohost/api'); + store.set('user', 'admin'); + c.api('POST', '/postinstall', {domain: domain, password: password}, function() { + c.flash('success', y18n.t('installation_complete')); + c.redirect_to('#/login'); + }); + } + ); }); })(); diff --git a/src/js/yunohost/controllers/services.js b/src/js/yunohost/controllers/services.js index e3de3554..113c34fc 100644 --- a/src/js/yunohost/controllers/services.js +++ b/src/js/yunohost/controllers/services.js @@ -10,7 +10,7 @@ // All services status app.get('#/services', function (c) { - c.api('/services', function(data) { // ? + c.api('GET', '/services', {}, function(data) { var data2 = { services: [] }; @@ -45,7 +45,7 @@ // Status & actions for a service app.get('#/services/:service', function (c) { - c.api('/services/'+ c.params['service'], function(data) { // ? + c.api('GET', '/services/'+ c.params['service'], {}, function(data) { var data2 = { service: data }; @@ -64,9 +64,45 @@ { data2.service.active_at = 0; } - store.clear('slide'); - c.view('service/service_info', data2); - }, 'GET'); + c.view('service/service_info', data2, function() { + + // Configure behavior for enable/disable and start/stop buttons + $('button[data-action]').on('click', function() { + + var service = $(this).data('service'); + var action = $(this).data('action'); + + c.confirm("Service", y18n.t('confirm_service_' + action, [service]), function(){ + + var method = null, + endurl = service; + + switch (action) { + case 'start': + method = 'PUT'; + break; + case 'stop': + method = 'DELETE'; + break; + case 'enable': + method = 'PUT'; + endurl += '/enable'; + break; + case 'disable': + method = 'DELETE'; + endurl += '/enable'; + break; + default: + c.flash('fail', y18n.t('unknown_action', [action])); + c.refresh(); + return; + } + + c.api(method, '/services/'+ endurl, {}, function() { c.refresh(); }); + }); + }); + }); + }); }); // Service log @@ -74,63 +110,14 @@ var params = { number: 50 }; - c.api('/services/'+ c.params['service'] +'/log', function(data) { // ? + c.api('GET', '/services/'+ c.params['service'] +'/log', params, function(data) { // ? data2 = { 'logs': [], 'name': c.params['service'] }; $.each(data, function(k, v) { data2.logs.push({filename: k, filecontent: v.join('\n')}); }); c.view('service/service_log', data2); - }, 'GET', params); - }); - - // Enable/Disable & Start/Stop service - app.get('#/services/:service/:action', function (c) { - c.confirm( - "Service", - // confirm_service_start, confirm_service_stop, confirm_service_enable and confirm_service_disable - y18n.t('confirm_service_' + c.params['action'].toLowerCase(), [c.params['service']]), - function(){ - var method = null, - endurl = c.params['service']; - - switch (c.params['action']) { - case 'start': - method = 'PUT'; - break; - case 'stop': - method = 'DELETE'; - break; - case 'enable': - method = 'PUT'; - endurl += '/enable'; - break; - case 'disable': - method = 'DELETE'; - endurl += '/enable'; - break; - default: - c.flash('fail', y18n.t('unknown_action', [c.params['action']])); - store.clear('slide'); - c.redirect('#/services/'+ c.params['service']); - } - - if (method && endurl) { - c.api('/services/'+ endurl, function(data) { - store.clear('slide'); - c.redirect('#/services/'+ c.params['service']); - }, method); - } - else { - store.clear('slide'); - c.redirect('#/services/'+ c.params['service']); - } - }, - function(){ - store.clear('slide'); - c.redirect('#/services/'+ c.params['service']); - } - ); + }); }); })(); diff --git a/src/js/yunohost/controllers/tools.js b/src/js/yunohost/controllers/tools.js index 8c7fb36c..4e62c693 100644 --- a/src/js/yunohost/controllers/tools.js +++ b/src/js/yunohost/controllers/tools.js @@ -26,77 +26,69 @@ }); if ($.isEmptyObject(params)) { c.flash('fail', y18n.t('error_modify_something')); - store.clear('slide'); - c.redirect('#/tools/adminpw'); - } else if (params['new_password'] !== params['confirm_new_password']) { - c.flash('fail', y18n.t('passwords_dont_match')); - store.clear('slide'); - c.redirect('#/tools/adminpw'); - } else { - c.api('/login', function(data) { - // Remove useless variable - delete params['old_password']; - delete params['confirm_new_password']; - - // Update password and redirect to the home - c.api('/adminpw', function(data) { // http://api.yunohost.org/#!/tools/tools_adminpw_put_3 - c.redirect('#/logout'); - }, 'PUT', params); - }, 'POST', { 'password': params['old_password'] }, false); + c.refresh(); + return; } + if (params['new_password'] !== params['confirm_new_password']) { + c.flash('fail', y18n.t('passwords_dont_match')); + c.refresh(); + return; + } + + c.api('POST', '/login', { 'password': params['old_password'] }, function(data) { + // Remove useless variable + delete params['old_password']; + delete params['confirm_new_password']; + + // Update password and redirect to the home + c.api('PUT', '/adminpw', params, function(data) { + c.redirect_to('#/logout'); + }); + }, undefined, false); }); // System update & upgrade app.get('#/update', function (c) { - c.api('/update', function(data) { - c.view('update/update', data); - }, 'PUT'); - }); + c.api('PUT', '/update', {}, function(data) { + c.view('tools/tools_update', data, function() { + // Configure buttons behaviors + $("button[data-upgrade]").on("click", function() { - // Upgrade apps or packages - app.get('#/upgrade/:type', function (c) { - c.confirm( - y18n.t('tools'), - // confirm_update_apps and confirm_update_packages - y18n.t('confirm_update_' + c.params['type'].toLowerCase()), - function(){ - c.api('/upgrade?'+c.params["type"], - function(data) { - store.clear('slide'); - c.redirect('#/tools/logs'); - }, - 'PUT'); - }, - function(){ - store.clear('slide'); - c.redirect('#/update'); - } - ); - }); + var what = $(this).data("upgrade").toLowerCase(); - // Upgrade a specific apps - app.get('#/upgrade/apps/:app', function (c) { - c.confirm( - y18n.t('tools'), - y18n.t('confirm_update_specific_app', [c.params['app']]), - function(){ - c.api('/upgrade/apps?app='+c.params['app'].toLowerCase(), - function(data) { - store.clear('slide'); - c.redirect('#/tools/logs'); - }, - 'PUT'); - }, - function(){ - store.clear('slide'); - c.redirect('#/update'); - } - ); + // Upgrade all apps or the system + + if ((what == "system") || (what == "system")) + { + var confirm_message = y18n.t('confirm_update_' + what); + var api_url = '/upgrade?'+what; + } + + // Upgrade a specific apps + + else + { + var confirm_message = y18n.t('confirm_update_specific_app', [what]); + var api_url = '/upgrade/apps?app='+what; + } + + c.confirm( + y18n.t('tools'), + confirm_message, + function(){ + c.api('PUT', api_url, {}, function(data) { + c.redirect_to('#/tools/logs'); + }); + } + ); + }); + }); + }); }); // Display journals list app.get('#/tools/logs', function (c) { - c.api("/logs?limit=25&with_details", function(categories) { + c.api('GET', "/logs?limit=25&with_details", {}, function(categories) { data = []; category_icons = { 'operation': 'wrench', @@ -138,8 +130,8 @@ var params = "?path=" + c.params["splat"][0]; var number = (c.params["number"])?c.params["number"]:50; params += "&number=" + number; - - c.api("/logs/display" + params, function(log) { + + c.api('GET', "/logs/display" + params, {}, function(log) { if ('metadata' in log) { if (!'env' in log.metadata && 'args' in log.metadata) { log.metadata.env = log.metadata.args @@ -149,10 +141,19 @@ "log": log, "next_number": log.logs.length == number ? number * 10:false, "locale": y18n.locale + }, function() { + // Configure behavior for the button to share log on Yunohost (it calls display --share) + $('button[data-action="share"]').on("click", function() { + c.api('GET', '/logs/display?path='+$(this).data('log-id')+'&share', {}, + function(data) { + c.hideLoader(); + window.open(data.url, '_blank'); + }); + }); }); }); }); - + // Download SSL Certificate Authority app.get('#/tools/ca', function (c) { @@ -210,59 +211,44 @@ // Reboot or shutdown button app.get('#/tools/reboot', function (c) { - c.view('tools/tools_reboot'); - }); + c.view('tools/tools_reboot', {}, function() { + // Configure reboot/shutdown buttons behavior + $("button[data-action]").on("click", function() { + var action = $(this).data("action"); - // Reboot or shutdown actions - app.get('#/tools/reboot/:action', function (c) { - var action = c.params['action'].toLowerCase(); - if (action == 'reboot' || action == 'shutdown') { - c.confirm( - y18n.t('tools_' + action), - // confirm_reboot_action_reboot or confirm_reboot_action_shutdown - y18n.t('confirm_reboot_action_' + action), - function(){ - c.api('/'+action+'?force', function(data) { - // This code is not executed due to 502 response (reboot or shutdown) - c.redirect('#/logout'); - }, 'PUT', {}, false, function (xhr) { - c.flash('success', y18n.t('tools_' + action + '_done')) - // Disconnect from the webadmin - store.clear('url'); - store.clear('connected'); - store.set('path', '#/'); + c.confirm( + y18n.t('tools_' + action), + y18n.t('confirm_reboot_action_' + action), + function(){ + c.api('PUT', '/'+action+'?force', {}, function(data) { + // This code is not executed due to 502 response (reboot or shutdown) + c.redirect_to('#/logout'); + }, function (xhr) { + c.flash('success', y18n.t('tools_' + action + '_done')) + // Disconnect from the webadmin + store.clear('url'); + store.clear('connected'); + store.set('path', '#/'); - // Rename the page to allow refresh without ask for rebooting - window.location.href = window.location.href.split('#')[0] + '#/'; - // Display reboot or shutdown info - // We can't use template because now the webserver is off - if (action == 'reboot') { - $('#main').replaceWith('helper - c.prePaste(); - - // Run callback - callback(); - - // Force scrollTop on page load - $('html, body').scrollTop(0); - }); - }; - - // Slide back effect - if (enableSlide && store.get('slide') == 'back') { - store.clear('slide'); - $('#slideBack').css('display', 'none'); - $('#slider-container').css('margin-left', '-100%'); - $('#slideTo').show().html($('#main').html()); - leSwap(); - $('#slider-container').css('margin-left', '0px'); - } - // Slide to effect - else if (enableSlide && store.get('slide') == 'to') { - store.clear('slide'); - $('#slideTo').css('display', 'none'); - $('#slider-container').css('margin-left', '0px'); - $('#slideBack').show().html($('#main').html()); - leSwap(); - $('#slider-container').css('margin-left', '-100%'); - } - // No slideing effect - else { - leSwap(); - } - }, - - confirm: function(title, content, confirmCallback, cancelCallback) { // Default callbacks confirmCallback = typeof confirmCallback !== 'undefined' ? confirmCallback : function() {}; cancelCallback = typeof cancelCallback !== 'undefined' ? cancelCallback : function() {}; + c.hideLoader(); + // Get modal element var box = $('#modal'); @@ -335,12 +291,10 @@ $('#modal footer button').unbind( "click" ); // Reset & Hide modal - box - .removeClass('no-title') - .modal('hide'); + box.removeClass('no-title').modal('hide'); // Do corresponding callback - if ($(this).data('action') == 'confirm') { + if ($(this).data('modal-action') == 'confirm') { confirmCallback(); } else { @@ -352,19 +306,165 @@ return box.modal('show'); }, - selectAllOrNone: function () { - // Remove active style from buttons - $(".select_all-none input").click(function(){ $(this).toggleClass("active"); }); - // Select all checkbox in this panel - $(".select_all").click(function(){ - $(this).parents(".panel").children(".list-group").find("input").prop("checked", true); - }); - // Deselect all checkbox in this panel - $(".select_none").click(function(){ - $(this).parents(".panel").children(".list-group").find("input").prop("checked", false); - }); + + // Render view (cross-browser) + view: function (view, data, callback) { + c = this; + + // Default + callback = typeof callback !== 'undefined' ? callback : function() {}; + + // Hide loader and modal + c.hideLoader(); + $('#modal').modal('hide'); + + // Render content + var rendered = this.render('views/'+ view +'.ms', data); + + // Update content helper + var leSwap = function() { + rendered.swap(function() { + // Clicking on those kind of CSS elements will trigger a + // slide effect i.e. the next view rendering will have + // store.get('slide') set to 'back' or 'to' + $('.slide, .btn-breadcrumb a:not(:last-child)').on('click', function() { + $(this).addClass('active'); + if ($(this).hasClass('back') || $(this).parent('.btn-breadcrumb').length) { + store.set('slide', 'back'); + } else { + store.set('slide', 'to'); + } + }); + + // Pastediff --git a/src/views/domain/domain_cert.ms b/src/views/domain/domain_cert.ms index 663f17ea..3969dfa3 100644 --- a/src/views/domain/domain_cert.ms +++ b/src/views/domain/domain_cert.ms @@ -46,36 +46,36 @@helper + c.prePaste(); + + // Run callback + callback(); + + // Force scrollTop on page load + $('html, body').scrollTop(0); + }); + }; + + // Slide back effect + if (store.get('slide') == 'back') { + + store.clear('slide'); + // Disable transition while we tweak CSS + $('#slider-container').addClass('notransition'); + // "Delete" the left part of the slider + $('#slideBack').css('display', 'none'); + + // Push the slider to the left + $('#slider-container').css('margin-left', '-100%'); + // slideTo is the right part, and should contain the old view, + // so we copypasta what's in the "center" slider (#main) + $('#slideTo').show().html($('#main').html()); + // leSwap will put the new view in the "center" slider (#main) + leSwap(); + + // So now things look like: + // | | + // | the screen | + // | | + // + // . #main . #slideTo . + // . the new view . the old view . + // ^ ^ + // margin-left: -100% currently shown + // + // =====>>> sliiiiide =====>>> + + // Re-add transition effect + $('#slider-container').removeClass('notransition'); + + // add the transition event to detect the end of the transition effect + transitionEvent + && $("#slider-container").off(transitionEvent) + && $("#slider-container").on(transitionEvent, resetSliders); + + // And actually play the transition effect that will move the container from left to right + $('#slider-container').css('margin-left', '0px'); + } + // Slide to effect + else if (store.get('slide') == 'to') { + + // Disable transition while we tweak CSS + $('#slider-container').addClass('notransition'); + // "Delete" the right part of the slider + $('#slideTo').css('display', 'none'); + // Push the slider to the right + $('#slider-container').css('margin-left', '0px'); + // slideBack should contain the old view, + // so we copypasta what's in the "center" slider (#main) + $('#slideBack').show().html($('#main').html()); + leSwap(); + + // So now things look like: + // + // | | + // | the screen | + // | | + // + // . . #slideBack . #main . + // . . the old view . the new view . + // ^ ^ ^ + // margin-left: -100% currently shown + // + // <<<===== sliiiiide <<<======= + + + // Re-add transition effect + $('#slider-container').removeClass('notransition'); + + // add the transition event to detect the end of the transition effect + var transitionEvent = whichTransitionEvent(); + transitionEvent + && $("#slider-container").off(transitionEvent) + && $("#slider-container").on(transitionEvent, resetSliders); + + // And actually play the transition effect that will move the container from right to left + $('#slider-container').css('margin-left', '-100%'); + } + // No slideing effect + else { + leSwap(); + } }, + redirect_to: function(destination, options) { + c = this; + + options = options !== undefined ? options : {}; + + // If destination if the same as current url, + // we don't want to display the slide animation + // (or if the code explicitly state to disable slide animation) + if ((c.path.split("#")[1] == destination.split("#")[1]) || (options.slide == false)) + { + store.clear('slide'); + } + + // This is a copy-pasta of some of the redirect/refresh code of + // sammy.js because for some reason calling the original + // redirect/refresh function in some context does not work >.> + // (e.g. if you're already on the page) + c.trigger('redirect', {to: destination}); + c.app.last_location = c.path; + c.app.setLocation(destination); + c.app.trigger('location-changed'); + }, + + refresh: function() { + c = this; + c.redirect_to(c.path, {slide: false}); + }, + + // + // Array / object helpers + // + arraySortById: function(arr) { arr.sort(function(a, b){ if (a.id > b.id) { @@ -385,74 +485,20 @@ }); }, - groupHooks: function(hooks, raw_infos){ - var data = {}; - var rules = [ - { - id:'configuration', - isIn:function (hook) { - return hook.indexOf('conf_')==0 - } - } - ]; - - $.each(hooks, function(i, hook) { - var group_id=hook; - var hook_size=(raw_infos && raw_infos[hook] && raw_infos[hook].size)?raw_infos[hook].size:0; - $.each(rules, function(i, rule) { - if (rule.isIn(hook)) { - group_id = 'adminjs_group_'+rule.id; - return false; - } - }); - - if(group_id in data) { - data[group_id] = { - name:y18n.t('hook_'+group_id), - value:data[group_id].value+','+hook, - description:data[group_id].description+', '+y18n.t('hook_'+hook), - size:data[group_id].size + hook_size - }; - } - else { - data[group_id] = { - name:y18n.t('hook_'+group_id), - value:hook, - description:(group_id==hook)?y18n.t('hook_'+hook+'_desc'):y18n.t('hook_'+hook), - size:hook_size - }; - } - }); - return data; + // Serialize an object + serialize : function(obj) { + var str = []; + for(var p in obj) + if (obj.hasOwnProperty(p)) { + str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); + } + return str.join("&"); }, - ungroupHooks: function(system_parts,apps) { - var data = {}; - data['apps'] = apps || []; - data['system'] = system_parts || []; - if (data['system'].constructor !== Array) { - data['system'] = [data['system']]; - } - if (data['apps'].constructor !== Array) { - data['apps'] = [data['apps']]; - } - - // Some hook value contains multiple hooks separated by commas - var split_hooks = []; - $.each(data['system'], function(i, hook) { - split_hooks = split_hooks.concat(hook.split(',')); - }); - data['system'] = split_hooks; - - if (data['system'].length == 0) { - delete data['system']; - } - if (data['apps'].length == 0) { - delete data['apps']; - } - return data; - }, + // + // Misc helpers used in views etc.. + // // PasteprePaste: function() { @@ -461,8 +507,7 @@ // Get paste content element var preElement = $($(this).data('paste-content')); - // Add pacman loader - $('#main').append(''); + c.showLoader(); // Send to paste.yunohost.org $.ajax({ @@ -477,11 +522,11 @@ c.flash('fail', y18n.t('paste_error')); }) .always(function(){ - // Remove pacman - $('div.loader').remove(); + c.hideLoader(); }); }); } + }); })(); diff --git a/src/js/yunohost/main.js b/src/js/yunohost/main.js index 4d6ef4e4..5219715b 100644 --- a/src/js/yunohost/main.js +++ b/src/js/yunohost/main.js @@ -181,7 +181,7 @@ sam.store.set('url', window.location.hostname + '/yunohost/api'); if (sam.store.get('connected')) { - this.api('/diagnosis', function(diagnosis) { + this.api('GET', '/diagnosis', {}, function(diagnosis) { versions = diagnosis.packages; $('#yunohost-version').html(y18n.t('footer_version', [versions.yunohost.version, versions.yunohost.repo])); }); diff --git a/src/locales/en.json b/src/locales/en.json index f56ad459..ebb1118f 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -385,6 +385,6 @@ "appslists_last_update": "Last update", "appslists_unknown_list": "Unknown apps list: %s", "name": "Name", - "purge_user_data_checkbox": "Purge %s's data? (This will remove the content of it's home and mail directories.)", + "purge_user_data_checkbox": "Purge %s's data? (This will remove the content of its home and mail directories.)", "purge_user_data_warning": "Purging user's data is not reversible. Be sure you know what you're doing!" } diff --git a/src/views/app/app_info.ms b/src/views/app/app_info.ms index 8d46c7ca..7c972a0e 100644 --- a/src/views/app/app_info.ms +++ b/src/views/app/app_info.ms @@ -57,9 +57,9 @@
{{t 'app_info_default_desc' settings.domain}}
- + +
@@ -79,9 +79,9 @@diff --git a/src/views/backup/backup.ms b/src/views/backup/backup.ms index 4da53a75..e4bd4b0c 100644 --- a/src/views/backup/backup.ms +++ b/src/views/backup/backup.ms @@ -3,12 +3,6 @@ {{t 'backup'}} -
{{t 'app_info_uninstall_desc'}}
- + +- --diff --git a/src/views/backup/backup_info.ms b/src/views/backup/backup_info.ms index ae42c67a..117558a7 100644 --- a/src/views/backup/backup_info.ms +++ b/src/views/backup/backup_info.ms @@ -83,41 +83,11 @@-diff --git a/src/views/backup/storage_create.ms b/src/views/backup/storage_create.ms deleted file mode 100644 index bc07a003..00000000 --- a/src/views/backup/storage_create.ms +++ /dev/null @@ -1,52 +0,0 @@ - - - - - -- {{#if other_storages}} -{{t 'backup_archive_delete'}}
- + +
--- {{/if}}{{t 'backup_archive_copy'}}
- -
{{t 'domain_not_eligible_for_ACME'}}
{{/if}} - + +{{t 'manually_renew_letsencrypt_message'}}
- + +{{t 'regenerate_selfsigned_cert_message'}}
- + +{{t 'revert_to_selfsigned_cert_message'}}
- + +- {{t 'domain_default_longdesc'}} -
- {{/if}} - - -{{t 'domain_visit_url' url}}
- {{t 'domain_visit'}} + {{t 'domain_visit'}}{{t 'domain_default_desc'}}
- + {{#if main}} ++ {{t 'domain_default_longdesc'}} +
+ {{else}} + + {{/if}}{{t 'domain_dns_longdesc'}}
- {{t 'domain_dns_config'}} + {{t 'domain_dns_config'}}{{t 'certificate_manage'}}
- {{#unless enable_cert_management}} -- {{t 'certificate_old_letsencrypt_app_conflict'}} -
- {{/unless}} - - {{t 'ssl_certificate'}} + + {{t 'ssl_certificate'}}{{t 'domain_delete_longdesc' name}}
- - {{t 'delete'}} - +{{t 'upnp_enabled'}}
- {{t 'disable'}} + {{else}}{{t 'upnp_disabled'}}
- {{t 'enable'}} + {{/if}}-{{#logs}} - {{.}} -{{/logs}} -- -{{else}} - {{t 'no_log'}} -{{/if}} diff --git a/src/views/user/group_list.ms b/src/views/user/group_list.ms index 7b68e404..a6643f79 100644 --- a/src/views/user/group_list.ms +++ b/src/views/user/group_list.ms @@ -17,10 +17,10 @@ {{text}} - + + {{/inline}} @@ -35,7 +35,7 @@