diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 19b5d6bbf61..996f1c24dc8 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -227,6 +227,7 @@ "Audio_message": "Audio message", "Auth_Token": "Auth Token", "Author": "Author", + "Author_Information": "Author Information", "Authorization_URL": "Authorization URL", "Authorize": "Authorize", "Auto_Load_Images": "Auto Load Images", @@ -263,6 +264,7 @@ "Back_to_integrations": "Back to integrations", "Back_to_integration_detail": "Back to the integration detail", "Back_to_login": "Back to login", + "Back_to_Manage_Rocketlets": "Back to Manage Rocketlets", "Back_to_permissions": "Back to permissions", "Backup_codes": "Backup codes", "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta feature. Depends on Video Conference to be enabled.", @@ -1340,6 +1342,7 @@ "manage-sounds": "Manage Sounds", "manage-sounds_description": "Permission to manage the server sounds", "Manage_Rocketlets": "Manage Rocketlets", + "Manage_the_Rocketlet": "Manage the Rocketlet", "mention-all": "Mention All", "mention-all_description": "Permission to use the @all mention", "mute-user": "Mute User", @@ -1525,6 +1528,8 @@ "Restart_the_server": "Restart the server", "Retry_Count": "Retry Count", "Rocketlets": "Rocketlets", + "Rocketlet_Information": "Rocketlet Information", + "Rocketlets_Settings": "Rocketlet's Settings", "Role": "Role", "Role_Editing": "Role Editing", "Role_removed": "Role removed", @@ -1726,6 +1731,7 @@ "Success": "Success", "Success_message": "Success message", "Sunday": "Sunday", + "Support": "Support", "Survey": "Survey", "Survey_instructions": "Rate each question according to your satisfaction, 1 meaning you are completely unsatisfied and 5 meaning you are completely satisfied.", "Symbols": "Symbols", @@ -1960,6 +1966,7 @@ "WebRTC_Enable_Private": "Enable for Private Channels", "WebRTC_Servers": "STUN/TURN Servers", "WebRTC_Servers_Description": "A list of STUN and TURN servers separated by comma.
Username, password and port are allowed in the format `username:password@stun:host:port` or `username:password@turn:host:port`.", + "Website": "Website", "Wednesday": "Wednesday", "Welcome": "Welcome %s.", "Welcome_to_the": "Welcome to the", diff --git a/packages/rocketchat-lib/client/lib/RestApiClient.js b/packages/rocketchat-lib/client/lib/RestApiClient.js index ab353e69cb1..f19c49b84d6 100644 --- a/packages/rocketchat-lib/client/lib/RestApiClient.js +++ b/packages/rocketchat-lib/client/lib/RestApiClient.js @@ -3,6 +3,10 @@ RocketChat.API = { return RocketChat.API._jqueryCall('GET', endpoint, params); }, + post(endpoint, params, body) { + return RocketChat.API._jqueryCall('POST', endpoint, params, body); + }, + _jqueryCall(method, endpoint, params, body) { let query = ''; if (params) { @@ -22,7 +26,7 @@ RocketChat.API = { 'X-User-Id': localStorage['Meteor.userId'], 'X-Auth-Token': localStorage['Meteor.loginToken'] }, - data: body, + data: JSON.stringify(body), success: function _rlGetSuccess(result) { resolve(result); }, diff --git a/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css b/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css index e69de29bb2d..09e0ffc6fb2 100644 --- a/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css +++ b/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css @@ -0,0 +1,4 @@ +input.rocketlet-author-name { + width: auto !important; + display: inline-block !important; +} diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletManage.html b/packages/rocketchat-rocketlets/client/admin/rocketletManage.html new file mode 100644 index 00000000000..608a4b5e836 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketletManage.html @@ -0,0 +1,230 @@ + diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletManage.js b/packages/rocketchat-rocketlets/client/admin/rocketletManage.js new file mode 100644 index 00000000000..4203dc91d58 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketletManage.js @@ -0,0 +1,111 @@ +Template.rocketletManage.onCreated(function() { + const instance = this; + this.ready = new ReactiveVar(false); + this.rocketlet = new ReactiveVar({}); + this.settings = new ReactiveVar({}); + + const id = FlowRouter.getParam('rocketletId'); + + console.log(id); + + const got = { info: false, settings: false }; + + RocketChat.API.get(`rocketlets/${ id }`).then((result) => { + instance.rocketlet.set(result.rocketlet); + console.log(result.rocketlet); + + got.info = true; + if (got.info && got.settings) { + this.ready.set(true); + } + }); + + RocketChat.API.get(`rocketlets/${ id }/settings`).then((result) => { + Object.keys(result.settings).forEach((k) => { + result.settings[k].oldValue = result.settings[k].value; + }); + + instance.settings.set(result.settings); + console.log(instance.settings.get()); + + got.settings = true; + if (got.info && got.settings) { + this.ready.set(true); + } + }); +}); + +Template.rocketletManage.helpers({ + isReady() { + if (Template.instance().ready != null) { + return Template.instance().ready.get(); + } + + return false; + }, + rocketlet() { + return Template.instance().rocketlet.get(); + }, + settings() { + return Object.values(Template.instance().settings.get()); + }, + parseDescription(i18nDescription) { + const item = RocketChat.Markdown.parseNotEscaped({ html: t(i18nDescription) }); + + item.tokens.forEach((t) => item.html = item.html.replace(t.token, t.text)); + + return item.html; + } +}); + +Template.rocketletManage.events({ + 'click .expand': (e) => { + $(e.currentTarget).closest('.section').removeClass('section-collapsed'); + $(e.currentTarget).closest('button').removeClass('expand').addClass('collapse').find('span').text(TAPi18n.__('Collapse')); + $('.CodeMirror').each((index, codeMirror) => codeMirror.CodeMirror.refresh()); + }, + + 'click .collapse': (e) => { + $(e.currentTarget).closest('.section').addClass('section-collapsed'); + $(e.currentTarget).closest('button').addClass('expand').removeClass('collapse').find('span').text(TAPi18n.__('Expand')); + }, + + 'click .save': (e, t) => { + const toSave = []; + + Object.keys(t.settings.get()).forEach((k) => { + const setting = t.settings.get()[k]; + if (setting.hasChanged) { + toSave.push(setting); + } + }); + + if (toSave.length === 0) { + console.log('Nothing to save..'); + return; + } + + const rocketletId = FlowRouter.getParam('rocketletId'); + RocketChat.API.post(`rocketlets/${ rocketletId }/settings`, undefined, { settings: toSave }).then((result) => { + console.log('Updating results:', result); + }); + }, + + 'change .input-monitor, keyup .input-monitor': _.throttle(function(e, t) { + let value = _.trim($(e.target).val()); + switch (this.type) { + case 'int': + value = parseInt(value); + break; + case 'boolean': + value = value === '1'; + } + + const setting = t.settings.get()[this.id]; + setting.value = value; + + if (setting.oldValue !== setting.value) { + t.settings.get()[this.id].hasChanged = true; + } + }, 500) +}); diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 74fbb58e9f4..29be20cdabe 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -11,7 +11,7 @@ {{#requiresPermission 'manage-rocketlets'}} {{#each rocketlets}} {{/each}} {{/requiresPermission}} diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.js b/packages/rocketchat-rocketlets/client/admin/rocketlets.js index a869c96ec1c..1aabdf0d8bb 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.js +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.js @@ -20,3 +20,15 @@ Template.rocketlets.helpers({ return Template.instance().rocketlets.get(); } }); + +Template.rocketlets.events({ + 'click .manage'() { + const rl = this; + + if (rl && rl.id) { + FlowRouter.go(`/admin/rocketlets/${ rl.id }`); + } else { + // show an error ? I don't think this should ever happen + } + } +}); diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js index b7aef6dc1df..0cffd616287 100644 --- a/packages/rocketchat-rocketlets/client/communication/websockets.js +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -11,8 +11,8 @@ export class RocketletWebsocketReceiver { } onRocketletAdded(rocketletId) { - RocketChat.API.get(`rocketlets/${ rocketletId }`).then((result) => { - this.orch.parseAndLoadLanguages(result.rocketlet.languages); + RocketChat.API.get(`rocketlets/${ rocketletId }/languages`).then((result) => { + this.orch.parseAndLoadLanguages(result.languages); }); } diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index d2ff6dd0211..4c702c0fad2 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -5,7 +5,13 @@ class RocketletClientOrchestrator { this.ws = new RocketletWebsocketReceiver(this); this._addAdminMenuOption(); - setTimeout(() => this._loadLanguages(), 500); + + const loadLangs = setInterval(() => { + if (Meteor.user()) { + clearInterval(loadLangs); + this._loadLanguages(); + } + }, 50); } getWsListener() { @@ -56,3 +62,10 @@ FlowRouter.route('/admin/rocketlets', { BlazeLayout.render('main', { center: 'rocketlets' }); } }); + +FlowRouter.route('/admin/rocketlets/:rocketletId', { + name: 'rocketlet-manage', + action() { + BlazeLayout.render('main', { center: 'rocketletManage' }); + } +}); diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 5ea4ba27e3e..46de00cdc6b 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -11,7 +11,7 @@ Package.onUse(function(api) { 'templating' ]); - api.use(['reactive-var', 'kadira:flow-router'], 'client'); + api.use(['reactive-var', 'kadira:flow-router', 'underscore'], 'client'); api.addFiles('lib/Rocketlets.js', ['client', 'server']); @@ -65,7 +65,9 @@ Package.onUse(function(api) { // Client Admin Management api.addFiles([ 'client/admin/rocketlets.html', - 'client/admin/rocketlets.js' + 'client/admin/rocketlets.js', + 'client/admin/rocketletManage.html', + 'client/admin/rocketletManage.js' ], 'client'); api.addFiles('assets/stylesheets/rocketlets.css', 'client'); @@ -79,6 +81,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.26', - 'temporary-rocketlets-ts-definition': '0.6.26' + 'temporary-rocketlets-server': '0.1.27', + 'temporary-rocketlets-ts-definition': '0.6.27' }); diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index 50aff66c52b..29efe7eed74 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -76,7 +76,6 @@ export class RocketletsRestApi { if (prl) { const info = prl.getInfo(); - info.languages = prl.getStorageItem().languageFiles; return { success: true, rocketlet: info }; } else { @@ -95,5 +94,110 @@ export class RocketletsRestApi { return { success: false, item }; } }); + + this.api.addRoute(':id/languages', { authRequired: true }, { + get() { + console.log(`Getting ${ this.urlParams.id }'s languages..`); + const prl = manager.getOneById(this.urlParams.id); + + if (prl) { + const languages = prl.getStorageItem().languageFiles || {}; + + return { success: true, languages }; + } else { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } + } + }); + + this.api.addRoute(':id/settings', { authRequired: true }, { + get() { + console.log(`Getting ${ this.urlParams.id }'s settings..`); + const prl = manager.getOneById(this.urlParams.id); + + if (prl) { + const settings = Object.assign({}, prl.getStorageItem().settings); + + Object.keys(settings).forEach((k) => { + if (settings[k].hidden) { + delete settings[k]; + } + }); + + return { success: true, settings }; + } else { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } + }, + post() { + console.log(`Updating ${ this.urlParams.id }'s settings..`); + if (!this.bodyParams || !this.bodyParams.settings) { + return RocketChat.API.v1.failure('The settings to update must be present.'); + } + + const prl = manager.getOneById(this.urlParams.id); + + if (!prl) { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } + + const settings = prl.getStorageItem().settings; + + const updated = []; + this.bodyParams.settings.forEach((s) => { + if (settings[s.id]) { + Promise.await(manager.getSettingsManager().updateRocketletSetting(this.urlParams.id, s)); + // Updating? + updated.push(s); + } + }); + + return { success: true, updated }; + } + }); + + this.api.addRoute(':id/settings/:settingId', { authRequired: true }, { + get() { + console.log(`Getting the Rocketlet ${ this.urlParams.id }'s setting ${ this.urlParams.settingId }`); + + try { + const setting = manager.getSettingsManager().getRocketletSetting(this.urlParams.id, this.urlParams.settingId); + + return { + success: true, + setting + }; + } catch (e) { + if (e.message.includes('No setting found')) { + return RocketChat.API.v1.notFound(`No Setting found on the Rocketlet by the id of: "${ this.urlParams.settingId }"`); + } else if (e.message.includes('No Rocketlet found')) { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } else { + return RocketChat.API.v1.failure(e.message); + } + } + }, + post() { + console.log(`Updating the Rocketlet ${ this.urlParams.id }'s setting ${ this.urlParams.settingId }`); + + if (!this.bodyParams.setting) { + return RocketChat.API.v1.failure('Setting to update to must be present on the posted body.'); + } + + try { + Promise.await(manager.getSettingsManager().updateRocketletSetting(this.urlParams.id, this.bodyParams.setting)); + + return { success: true }; + } catch (e) { + if (e.message.includes('No setting found')) { + return RocketChat.API.v1.notFound(`No Setting found on the Rocketlet by the id of: "${ this.urlParams.settingId }"`); + } else if (e.message.includes('No Rocketlet found')) { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } else { + return RocketChat.API.v1.failure(e.message); + } + } + } + }); } } diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index 42a4b2f6f1b..c9a79eb7af1 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -64,6 +64,6 @@ Meteor.startup(function _rocketletServerOrchestrator() { global.Rocketlets = new RocketletServerOrchestrator(); global.Rocketlets.getManager().load() - .then(() => console.log('...done! :)')) + .then(() => console.log('...done! ;)')) .catch((err) => console.warn('...failed!', err)); });