Kuzzle - inter-plugins communication (via method calls) - kuzzle

Is there a way with Kuzzle, to make two plugins communicate with each other?
Let's say a plugin A wants to call a method of a plugin B at boot time, or even runtime for some use cases. How can I do that ?
For now, there is no way to retrieve a particular plugin instance from another plugin. Plugins manager isn't reachable at plugin initialization, but in some way via a Kuzzle request (not the proper way of doing it)
function (request) {
const kSymbol = Object.getOwnPropertySymbols(request.context.user)[0];
request.context.user[kSymbol].pluginsManager.MyPlugin.someMethod(...args);
...
}
The idea behind this question would be to do something like this, when initializing the plugin
function init (customConfig, context) {
const { pluginsManager } = context;
const result = pluginsManager.MyPlugin.someMethod(...args);
// make something with the result ?
// For later use of plugins manager perhaps ?
this.context = context
}
Looks like Kuzzle Pipes would be the right thing to do it, cause they are synchronous and chainable, but pipes don't return anything when triggering an event
function init (customConfig, context) {
const result = context.accessors.trigger('someEvent', {
someAttribute: 'someValue'
});
console.log(result) // undefined
}
Thanks for your help !

full disclosure: I work for Kuzzle
Even if accessing the pluginManager like this may work at this time, we may change the internal implementation without warning since it's not documented so your plugin may not work in next version of Kuzzle.
The easiest way to use a feature from another plugin is exposing a new API method through a custom controller and then call it with the query method of the embedded SDK.
For example if your plugin name is notifier-plugin in the manifest:
this.controllers = {
email: {
send: request => { /* send email */ }
}
};
Then you can call it in another plugin like this:
await this.context.accessors.sdk.query({
controller: 'notifier-plugin/email',
action: 'send'
});
Please note that you can't make API calls in the plugin init method.
If you need to make API calls when Kuzzle start, then you can add a hook/pipe on the core:kuzzleStart event.
this.hooks = {
'core:kuzzleStart': () => this.context.accessors.sdk.query({
controller: 'notifier-plugin/email',
action: 'send'
});
};
Finally I noticed that you can't use pipes returns like in your example but I have proposed a feature to allow plugin developers to use the pipe chain return.
It will be available in the next version of Kuzzle.

Related

Get semantic object and semantic action in controller

I'm trying to get the semantic object and semantic action of my deployed SAPUI5 application. I tried looking into ushell services - URLParsing and LaunchPage but it does not seem to return my semantic objects and actions.
Have anybody tried this?
This worked for me so far:
sap.ui.require([ // modules lazily instead of accessing them with global names.
"sap/ushell/library", // Consider adding `"sap.ushell": { lazy: true }` to dependencies in manifest.json
"sap/ui/core/routing/HashChanger",
], async (sapUshellLib, HashChanger) => {
const fullHash = new HashChanger().getHash(); // returns e.g. "masterDetail-display?sap-ui-theme=sap_fiori_3&/product/HT-1000"
const urlParsing = await sapUshellLib.Container.getServiceAsync("URLParsing");
urlParsing.parseShellHash(fullHash); /** returns e.g. {
action: "display",
appSpecificRoute: "&/product/HT-1000",
contextRaw: undefined,
params: { "sap-ui-theme": "sap_fiori_3" },
semanticObject: "masterDetail"
} **/
});
You can always just use
window.location.hash
Which you can parse yourself pretty easily. If you really want launchpad code, you can often find it here:
sap.ushell.services.AppConfiguration.getCurrentApplication().sShellHash
I've noticed it's not always set though when you're looking at an embedded component
A simplistic way to do this would be:
var oHashObject = new sap.ui.core.routing.HashChanger();
oHashObject.getHash();
//this will return the semantic object and action alongwith the routing params

this$store function is undefined

I am trying to use vuex's store to make some API calls but after installing vuex, importing store to my files and following other stack overflow answers, like making sure vuex is installed, if i am exporting my store file with " Vuex.Store" and etc but my loadCalls function is still not working.
This is the error i get:
this.$store.loadCalls is not a function
Here is my function and how i am trying to call it, it is declared in my ACTIONS section of my store.js file.
loadCalls() {
axios
.get("/some/calls")
.then(res => {
console.log(res)
});
},
I try using it in my beforeMount() when my component loads:
beforeMount(){
this.$store.loadCalls();
}
What am i doing wrong here?
If you defined an action like this:
actions: {
loadCalls() {
// ...
}
}
Then you would call it like this:
this.$store.dispatch('loadCalls');
Actions aren't exposed directly, you call them using dispatch.
https://vuex.vuejs.org/guide/actions.html#dispatching-actions

Writing nested path parameters in FeathersJS

How to generate multi level path parameters in feathers js like below :
api.com/category/catergoryId/subCatergory/subCatergoryId
The following is taken from this Feathers FAQ entry:
Normally we find that they actually aren't needed and that it is much better to keep your routes as flat as possible. For example something like users/:userId/posts is - although nice to read for humans - actually not as easy to parse and process as the equivalent /posts?userId=<userid> that is already supported by Feathers out of the box. Additionaly, this will also work much better when using Feathers through websocket connections which do not have a concept of routes at all.
However, nested routes for services can still be created by registering an existing service on the nested route and mapping the route parameter to a query parameter like this:
app.use('/posts', postService);
app.use('/users', userService);
// re-export the posts service on the /users/:userId/posts route
app.use('/users/:userId/posts', app.service('posts'));
// A hook that updates `data` with the route parameter
function mapUserIdToData(hook) {
if(hook.data && hook.params.userId) {
hook.data.userId = hook.params.userId;
}
}
// For the new route, map the `:userId` route parameter to the query in a hook
app.service('users/:userId/posts').hooks({
before: {
find(hook) {
hook.params.query.userId = hook.params.userId;
},
create: mapUserIdToData,
update: mapUserIdToData,
patch: mapUserIdToData
}
})
Now going to /users/123/posts will call postService.find({ query: { userId: 123 } }) and return all posts for that user.

Get newly created id of a record before redirecting page

I would like to retrieve the id of a newly created record using javascript when I click on save button and just before redirecting page.
Do you have any idea please ?
Thank you !
One way to do this in Sugar 7 would be by overriding the CreateView.
Here an example of a CustomCreateView that outputs the new id in an alert-message after a new Account was successfully created, but before Sugar gets to react to the created record.
custom/modules/Accounts/clients/base/views/create/create.js:
({
extendsFrom: 'CreateView',
// This initialize function override does nothing except log to console,
// so that you can see that your custom view has been loaded.
// You can remove this function entirely. Sugar will default to CreateView's initialize then.
initialize: function(options) {
this._super('initialize', [options]);
console.log('Custom create view initialized.');
},
// saveModel is the function used to save the new record, let's override it.
// Parameters 'success' and 'error' are functions/callbacks.
// (based on clients/base/views/create/create.js)
saveModel: function(success, error) {
// Let's inject our own code into the success callback.
var custom_success = function() {
// Execute our custom code and forward all callback arguments, in case you want to use them.
this.customCodeOnCreate(arguments)
// Execute the original callback (which will show the message and redirect etc.)
success(arguments);
};
// Make sure that the "this" variable will be set to _this_ view when our custom function is called via callback.
custom_success = _.bind(custom_success , this);
// Let's call the original saveModel with our custom callback.
this._super('saveModel', [custom_success, error]);
},
// our custom code
customCodeOnCreate: function() {
console.log('customCodeOnCreate() called with these arguments:', arguments);
// Retrieve the id of the model.
var new_id = this.model.get('id');
// do something with id
if (!_.isEmpty(new_id)) {
alert('new id: ' + new_id);
}
}
})
I tested this with the Accounts module of Sugar 7.7.2.1, but it should be possible to implement this for all other sidecar modules within Sugar.
However, this will not work for modules in backward-compatibility mode (those with #bwc in their URL).
Note: If the module in question already has its own Base<ModuleName>CreateView, you probably should extend from <ModuleName>CreateView (no Base) instead of from the default CreateView.
Be aware that this code has a small chance of breaking during Sugar upgrades, e.g. if the default CreateView code receives changes in the saveModel function definition.
Also, if you want to do some further reading on extending views, there is an SugarCRM dev blog post about this topic: https://developer.sugarcrm.com/2014/05/28/extending-view-javascript-in-sugarcrm-7/
I resolved this by using logic hook (after save), for your information, I am using Sugar 6.5 no matter the version of suitecrm.
Thank you !

Getting value with javascript and use it in controller

First of all i am using play framework with scala,
What i have to do is , using the data which i am getting with that function;
onClick: function(node) {
if(!node) return;
alert(node.id);
var id = node.id;
}
So what the question is how i can call the methods from controller with this id ? Since js is client-side but scala works with server-side , i need something creative.
This is the function i need to call from my controller.
def supertrack(id:Long) = Action {
}
I have just found out that i need use ScalaJavaScriptRouting in order to send a ajax request to the server.
For the documentation
http://www.playframework.com/documentation/2.1.1/ScalaJavascriptRouting