diff --git a/src/js/yunohost/controllers/apps.js b/src/js/yunohost/controllers/apps.js index 2da7f490..b1fe4cab 100644 --- a/src/js/yunohost/controllers/apps.js +++ b/src/js/yunohost/controllers/apps.js @@ -160,6 +160,49 @@ }); }); + // Get app actions list + app.get('#/apps/:app/actions', function (c) { + c.api('/apps/'+c.params['app']+'/actions', function(data) { + $.each(data.actions, function(_, action) { + formatYunoHostStyleArguments(action.arguments, c.params); + + // Multilingual description + action.description = (typeof action.description[y18n.locale] !== 'undefined') ? + action.description[y18n.locale] : + action.description['en'] + ; + + }); + + c.view('app/app_actions', data); + return; + }); + }); + + // Perform application + app.put('#/apps/:app/actions/:action', function(c) { + // taken from app install + $.each(c.params, function(k, v) { + if (typeof(v) === 'object' && Array.isArray(v)) { + // And return only first value + c.params[k] = v[0]; + } + }); + + var app_id = c.params['app']; + delete c.params['app']; + var action_id = c.params['action']; + delete c.params['action']; + + var params = { + '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); + }); + // Get app config panel app.get('#/apps/:app/config-panel', function (c) { c.api('/apps/'+c.params['app']+'/config-panel', function(data) { @@ -195,6 +238,141 @@ c.redirect('#/apps/install'); }); + // Helper function that formats YunoHost style arguments for generating a form + function formatYunoHostStyleArguments(args, params) { + if (!args) { + return; + } + + // this is in place modification, I don't like it but it was done this way + $.each(args, function(k, v) { + + // Default values + args[k].type = (typeof v.type !== 'undefined') ? v.type : 'string'; + args[k].inputType = 'text'; + args[k].required = (typeof v.optional !== 'undefined' && v.optional == "true") ? '' : 'required'; + args[k].attributes = ""; + args[k].helpText = ""; + args[k].helpLink = ""; + + + // Multilingual label + args[k].label = (typeof args[k].ask[y18n.locale] !== 'undefined') ? + args[k].ask[y18n.locale] : + args[k].ask['en'] + ; + + // Multilingual help text + if (typeof args[k].help !== 'undefined') { + args[k].helpText = (typeof args[k].help[y18n.locale] !== 'undefined') ? + args[k].help[y18n.locale] : + args[k].help['en'] + ; + } + + // Input with choices becomes select list + if (typeof args[k].choices !== 'undefined') { + // Update choices values with key and checked data + var choices = [] + $.each(args[k].choices, function(ck, cv){ + // Non key/value choices have numeric key, that we don't want. + if (typeof ck == "number") { + // Key is Value in this case. + ck = cv; + } + + choices.push({ + value: ck, + label: cv, + selected: (ck == args[k].default) ? true : false, + }); + }); + args[k].choices = choices; + } + + // Special case for domain input. + // Display a list of available domains + if (v.name == 'domain' || args[k].type == 'domain') { + args[k].choices = []; + $.each(params.domains, function(key, domain){ + args[k].choices.push({ + value: domain, + label: domain, + selected: false + }); + }); + + // Custom help link + args[k].helpLink += ""+y18n.t('manage_domains')+""; + } + + // Special case for admin / user input. + // Display a list of available users + if (v.name == 'admin' || args[k].type == 'user') { + args[k].choices = []; + $.each(params.users, function(username, user){ + args[k].choices.push({ + value: username, + label: user.fullname+' ('+user.mail+')', + selected: false + }); + }); + + // Custom help link + args[k].helpLink += ""+y18n.t('manage_users')+""; + } + + // 'app' type input display a list of available apps + if (args[k].type == 'app') { + args[k].choices = []; + $.each(params.apps, function(key, app){ + args[k].choices.push({ + value: app.id, + label: app.name, + selected: false + }); + }); + + // Custom help link + args[k].helpLink += ""+y18n.t('manage_apps')+""; + } + + // Boolean fields + if (args[k].type == 'boolean') { + args[k].inputType = 'checkbox'; + + // Checked or not ? + if (typeof args[k].default !== 'undefined') { + if (args[k].default == true) { + args[k].attributes = 'checked="checked"'; + } + } + + // 'default' is used as value, so we need to force it for checkboxes. + args[k].default = 1; + + // Checkbox should not be required to be unchecked + args[k].required = ''; + + // Clone a hidden input with empty value + // https://stackoverflow.com/questions/476426/submit-an-html-form-with-empty-checkboxes + var inputClone = { + name : args[k].name, + inputType : 'hidden', + default : 0 + }; + args.push(inputClone); + } + + // 'password' type input. + if (v.name == 'password' || args[k].type == 'password') { + // Change html input type + args[k].inputType = 'password'; + } + + }); + } + // Helper function that build app installation form app.helper('appInstallForm', function(appId, manifest, params) { var data = { @@ -202,134 +380,7 @@ manifest: manifest }; - if (typeof data.manifest.arguments.install !== 'undefined') { - $.each(data.manifest.arguments.install, function(k, v) { - - // Default values - data.manifest.arguments.install[k].type = (typeof v.type !== 'undefined') ? v.type : 'string'; - data.manifest.arguments.install[k].inputType = 'text'; - data.manifest.arguments.install[k].required = (typeof v.optional !== 'undefined' && v.optional == "true") ? '' : 'required'; - data.manifest.arguments.install[k].attributes = ""; - data.manifest.arguments.install[k].helpText = ""; - data.manifest.arguments.install[k].helpLink = ""; - - - // Multilingual label - data.manifest.arguments.install[k].label = (typeof data.manifest.arguments.install[k].ask[y18n.locale] !== 'undefined') ? - data.manifest.arguments.install[k].ask[y18n.locale] : - data.manifest.arguments.install[k].ask['en'] - ; - - // Multilingual help text - if (typeof data.manifest.arguments.install[k].help !== 'undefined') { - data.manifest.arguments.install[k].helpText = (typeof data.manifest.arguments.install[k].help[y18n.locale] !== 'undefined') ? - data.manifest.arguments.install[k].help[y18n.locale] : - data.manifest.arguments.install[k].help['en'] - ; - } - - // Input with choices becomes select list - if (typeof data.manifest.arguments.install[k].choices !== 'undefined') { - // Update choices values with key and checked data - var choices = [] - $.each(data.manifest.arguments.install[k].choices, function(ck, cv){ - // Non key/value choices have numeric key, that we don't want. - if (typeof ck == "number") { - // Key is Value in this case. - ck = cv; - } - - choices.push({ - value: ck, - label: cv, - selected: (ck == data.manifest.arguments.install[k].default) ? true : false, - }); - }); - data.manifest.arguments.install[k].choices = choices; - } - - // Special case for domain input. - // Display a list of available domains - if (v.name == 'domain' || data.manifest.arguments.install[k].type == 'domain') { - data.manifest.arguments.install[k].choices = []; - $.each(params.domains, function(key, domain){ - data.manifest.arguments.install[k].choices.push({ - value: domain, - label: domain, - selected: false - }); - }); - - // Custom help link - data.manifest.arguments.install[k].helpLink += ""+y18n.t('manage_domains')+""; - } - - // Special case for admin / user input. - // Display a list of available users - if (v.name == 'admin' || data.manifest.arguments.install[k].type == 'user') { - data.manifest.arguments.install[k].choices = []; - $.each(params.users, function(username, user){ - data.manifest.arguments.install[k].choices.push({ - value: username, - label: user.fullname+' ('+user.mail+')', - selected: false - }); - }); - - // Custom help link - data.manifest.arguments.install[k].helpLink += ""+y18n.t('manage_users')+""; - } - - // 'app' type input display a list of available apps - if (data.manifest.arguments.install[k].type == 'app') { - data.manifest.arguments.install[k].choices = []; - $.each(params.apps, function(key, app){ - data.manifest.arguments.install[k].choices.push({ - value: app.id, - label: app.name, - selected: false - }); - }); - - // Custom help link - data.manifest.arguments.install[k].helpLink += ""+y18n.t('manage_apps')+""; - } - - // Boolean fields - if (data.manifest.arguments.install[k].type == 'boolean') { - data.manifest.arguments.install[k].inputType = 'checkbox'; - - // Checked or not ? - if (typeof data.manifest.arguments.install[k].default !== 'undefined') { - if (data.manifest.arguments.install[k].default == true) { - data.manifest.arguments.install[k].attributes = 'checked="checked"'; - } - } - - // 'default' is used as value, so we need to force it for checkboxes. - data.manifest.arguments.install[k].default = 1; - - // Checkbox should not be required to be unchecked - data.manifest.arguments.install[k].required = ''; - - // Clone a hidden input with empty value - // https://stackoverflow.com/questions/476426/submit-an-html-form-with-empty-checkboxes - var inputClone = { - name : data.manifest.arguments.install[k].name, - inputType : 'hidden', - default : 0 - }; - data.manifest.arguments.install.push(inputClone); - } - - // 'password' type input. - if (v.name == 'password' || data.manifest.arguments.install[k].type == 'password') { - // Change html input type - data.manifest.arguments.install[k].inputType = 'password'; - } - - }); - } + formatYunoHostStyleArguments(data.manifest.arguments.install, params); // Multilingual description data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ? diff --git a/src/js/yunohost/filters.js b/src/js/yunohost/filters.js index 1fab600a..043d7d14 100644 --- a/src/js/yunohost/filters.js +++ b/src/js/yunohost/filters.js @@ -8,27 +8,28 @@ * Filters * */ - app.before(/domains\/add/, function (req){ + + function prefetchDomains(req) { // Preload domains list. req.params.domains = []; req.api('/domains', function(data) { req.params.domains = data.domains; }); - }); - app.before(/apps\/install\//, function (req){ - // Preload domains list. - req.params.domains = []; - req.api('/domains', function(data) { - req.params.domains = data.domains; - }); - }); - app.before(/apps\/install\//, function (req){ + } + + function prefetchUsers(req){ // Preload users lists. req.params.users = []; req.api('/users', function(data) { req.params.users = data.users; }); - }); + } + + app.before(/domains\/add/, prefetchDomains); + app.before(/apps\/install\//, prefetchDomains); + app.before(/apps\/install\//, prefetchUsers); + app.before(/apps\/\w+\/actions/, prefetchUsers); + app.before(/apps\/\w+\/actions/, prefetchDomains); app.before({except: {path: ['#/logout', '#/login', '#/postinstall', '#/postinstall/domain', '#/postinstall/password']}}, function (req) { @@ -45,4 +46,4 @@ app.after(function () {}); -})(); \ No newline at end of file +})(); diff --git a/src/locales/en.json b/src/locales/en.json index effae38a..56e6fc4b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -29,6 +29,7 @@ "app_install_custom_no_manifest": "No manifest.json file", "app_list": "App list", "app_make_default": "Make default", + "app_no_actions": "This application doesn't have any actions", "app_repository": "Application origin: ", "app_state": "Application state: ", "app_state_inprogress": "In progress", diff --git a/src/views/app/app_actions.ms b/src/views/app/app_actions.ms new file mode 100644 index 00000000..7b80c8a4 --- /dev/null +++ b/src/views/app/app_actions.ms @@ -0,0 +1,68 @@ +
+ {{t 'home'}} + {{t 'applications'}} + {{app_name}} + {{t 'app_actions'}} +
+ +
+ + + +{{#if actions}} +{{#actions}} +
+
+
+

{{name}}

+
+
+

{{description}}

+ {{#if arguments}} + {{#arguments}} +
+ + + {{#if helpText}} + {{{helpText}}} + {{/if}} + +
+ + {{#if choices}} + + {{else}} + + {{/if}} + + {{#if helpLink}} + {{{helpLink}}} + {{/if}} + + {{#if example}} + {{t 'form_input_example' example}} + {{/if}} + +
+
+ {{/arguments}} +
+ {{/if}} + +
+ +
+
+
+
+ +{{/actions}} + +{{else}} +
+ + {{t 'app_no_actions'}} +
+{{/if}}