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 @@
+
+
+ {{#with rocketlet}}
+
+
+ {{> burger}}
+
+
+
+
+
+ {{_ "Manage_the_Rocketlet"}}: "{{name}}"
+
+
+
+ {{#requiresPermission 'manage-rocketlets'}}
+
+ {{/requiresPermission}}
+
+
+ {{/with}}
+ {{#with flexData}}
+ {{> flexTabBar}}
+ {{/with}}
+
+
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));
});