I have a standalone action which I call from my front end via a button click using CloudSDK, I get my value but the action does not redirect to the view. I have specified the responseType as view in my success exit but this does not seem to work.
Button code in page.js file:
clickVerifyBtn: async function(uid) {
await Cloud.userIdVerify(uid);
},
the action
module.exports = {
friendlyName: 'User id verify',
description: '',
inputs: {
uid: {
description: 'Id of the user',
type: 'number'
},
},
exits: {
success:{
responseType: 'view',
viewTemplatePath: 'pages/admin/verification-doc',
}
},
fn: async function (inputs, exits) {
// All done.
var userdoc = await Photo.findOne({ownerId: inputs.uid, isRemoved:false, photoType:0})
var imageSrc = '/images/useruploads/'+userdoc.imageFileName;
return exits.success({imageSrc: imageSrc});
}
};
What is the correct way to achieve this ? Should I submitting my value to the action via the ajax-form component bundled in Sails?
Any help is greatly appreciated.
The action2 returns the variables not to the view directly but to the view's page instance (your_view.page.js) submitted method.
Related
I have got to the point where I can click a button on a card and show my app, but I dont know how to pass the board information to my app.
Steps:
In trello, I click on card.. then the power up button. It works, as I see this
Code:
const callback = function (t) {
return t.modal({
url: '../public/index.html',
fullscreen: true,
});
};
const t = window.TrelloPowerUp.initialize({
'card-buttons': function (t, options) {
return [
{
text: 'Hello World',
callback: callback,
},
];
},
});
In docs I see there's an args key that passes an object.
" // optional arguments to be passed to the iframe as query parameters
// access later with t.arg('text')
args: { text: 'Hello' }," - https://developer.atlassian.com/cloud/trello/power-ups/ui-functions/modal/
How do I get either my board info into args.. or use window.TrelloPowerUp.initialize or window.TrelloPowerUp.iframe within the modal?
I have a Vue app with Vuex dependency. Program logic is that message should be sent after successful Facebook share.
This is the method getting triggered on button click for sending the message:
onSubmit() {
if(this.shouldShowShareModal){
this.$store.dispatch('openModal', 'SHARE_MODAL');
return;
}
this.$store.dispatch('sendMessage', {
conversation_id: this.conversationId,
message : this.messageText,
message_type_id: 1
}).then(() => {
this.messageText = '';
this.scrollToBottom();
});
},
openModal simply sets the value of the given modal to true, thus v-if shows the modal which has the button which upon share method triggers a Facebook share:
share() {
var self = this;
FB.ui({
method: 'share',
href: 'https://developers.facebook.com/docs/'
}, function(){
self.$store.dispatch('sharedThroughFacebook');
self.$store.dispatch('closeModal', 'SHARE_MODAL');
});
}
Now the issue I have is how can I continue sending the message after Facebook callback is successful? Currently with sharedThroughFacebook I am simply setting the store sharing flag to true, but I am not sure about the best approach for sending the message only after a successful callback? If I push the data to modal, that seems like a dirty solution and that modal should not be aware of message state. On the other hand putting the conversation ID, message, type and text on Vuex store seems like an overhead since this component is the only one using the data.
You can compose your action like this
actions: {
async share ({ dispatch, commit }) {
await dispatch('sharedThroughFacebook') // wait for `sharedThroughFacebook` to finish
await dispatch('closeModal') // close the modal before sending the message
commit('sendMesseage')
},
async sharedThroughFacebook (context, payload) {
FB.ui({
method: 'share',
href: 'https://developers.facebook.com/docs/'
})
}
}
I want to send a button in bot.postMessageToChannel() and want to call a function(handleMessage) on Click of that button.
//start handler
bot.on('start', () => {
const params = {
icon_emoji: ':information_source:'
}
//here i want to post a button to a channel.
bot.postMessageToChannel(
'ABC', //channel name
'*Welcome to AB*...',
params
)
})
function i want to call,
handleMessage = (message) => {
console.log("hello")
}
I have tried the slack API.
Message Buttons with Node.js but it is from the slash commands.
interactive message button it is just giving me similar JSON data.
I wanted to confirm what you were looking for before I answered. I did something similar recently - where I would return a button off of a command, mainly so that when the user clicked on the button I would have a trigger_id that I could use to send a modal form for them to provide more info. An example of how I handled this:
First go to the Event Subscriptions section of your app settings page, and enable it. Provide the url that will listen for said events, then you need to select the events that your bot will be listening for. I subscribed to app_mention ( which will fire when your bot is #), and message.channels, which will fire on every message sent to the channel your bot is in.
Once you have done that you can subscribe to events... (by using the slack SDK https://slack.dev/node-slack-sdk/)
slackEvents.on('message', (event, body) => {
// do something here
console.log(`Received a message event: user ${event.user} in channel ${event.channel} says ${event.text}`);
});
In my case, once I received that message (I parse through the text to handle multiple commands) I would then use blocks to create a message with a button and send it back...
Payload:
channel: context.channelId,
text: "",
blocks: JSON.stringify([
{
type: "section",
text: {
type: "mrkdwn",
text: "So, you say you want to create a new task?\n*Great!*\nI just need your permission first, in order to initiate this action.\nPlease click the button below to launch this process, or cancel if you have changed your mind"
}
},
{
type: "actions",
block_id: "processAddTask",
elements: [
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Process"
},
style: "primary",
value: "1"
},
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Cancel"
},
style: "danger",
value: "0"
}
]
}
])
Then send that payload back to channel...
const response = await web.chat.postMessage(responseMessage);
Once all this was done the user would be presented with a couple of buttons, and when they clicked on the "go" button it will fire another event that you can catch:
slackInteractions.action({ callbackId: 'addTaskRequest' }, (payload, respond) => {
console.log('payload', payload);
let triggerId = payload.trigger_id;
let view = payloads.addTaskModal({ triggerId });
(async () => {
try {
let result = await slackClient.callAPIMethod("views.open", view);
respond("");
} catch (error) {
if (error.code === ErrorCode.PlatformError) {
respond(error.data);
} else {
respond('Well, that was unexpected.');
}
}
})();
});
I am rockie in sails and kick start with action 2(action as machine). I am stuck how to configure view locals in actions 2.
For instance, in standalone action I can configure and add layout to view by the below snippet:
res.view('./pages/coffee/Boss/sell', { layout: 'layouts/layout-boss' })
My question is How can we do the same thing with action as machine(action2) ?
exits: {
success: {
responseType: "view",
viewTemplatePath: './pages/coffee/Boss/listDrink'
//Here I want to configure locals of view
//Specifically, I want to configure layout of the view
},
notFound: {
description: 'The data of drinks are empty',
respondType: 'notFound'
}
},
Looks like you can set any specific parameters in the exits.success call, like the layout or any ejs local variables you might need in the template:
fn: async function (inputs, exits) {
return exits.success({layout: 'layouts/layout-boss', ejsLocalVariable: 'value'});
}
and the exit declaration would just be
exits: {
success: {
responseType: "view",
viewTemplatePath: './pages/coffee/Boss/listDrink'
},
notFound: {
description: 'The data of drinks are empty',
respondType: 'notFound'
}
},
In SailsJS, to apply a layout to a template in an actions2 object you can do the following:
Declare your success exit as usual:
exits: {
success: {
responseType: 'view',
viewTemplatePath: 'pages/hello',
},
},
When returning from your method , add the layout to any any other values that you are passing to your template.
return exits.success({name1:value1, name2:value2, layout: 'layouts/backoffice'});
As far as I understand the layout is another local, and locals are explained here:
https://sailsjs.com/documentation/concepts/views/locals
I am new to extjs, and I try to integrate extjs 5 with django 1.7 on my localhost. I have set the backend and got the rest api work (at /api/), as at https://github.com/MaZderMind/django-vs-extjs , but when the index.html runs app.js, which displays the login page, it seems that:
The controller file (Login.js) isn't loaded,
the launch function is not executed.
In firebug I can see that it reads the function definition and then returns without executing it automatically (also, when defining controller it steps over like it is simple command, but on the require statement steps into the function that fetches them), hence the login page is not displayed. But the other js files (for authentication) are loaded, as I see in console. Do you have any ideas what is happening? The codes are:
app.js
Ext.Loader.setConfig({enabled:true});
Ext.application({
// base-package of all classes
name: 'MyApp',
// url to load js-files from - adapted to django project
appFolder : 'static/static',
// required controllers
controllers: ['Login'],
// other required components
requires: [
'MyApp.helper.CrsfTokenHelper',
'MyApp.helper.PhantomStoreInserter'
],
// application launch method
launch: function () {
// save the scope
var app = this;
console.log('launched');
// ensure the user is logged in before showing her the main navigation with all our application goodies
app.getController('Login').ensureLoggedIn(function(userinfo) {
console.log('Login-Controller ensured that user', userinfo.username, 'is is currently loggeg in. Proceeding to navigation.')
// upate display of the navigation conteoller and show it
//app.getController('Navigation')
//.updateUserinfo(userinfo)
//.view.show();
console.log('Here should be loaded the view after the login page');
});
}
});
Login.js (controller)
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
mixins: ['Ext.mixin.Observable'],
views: ['Login'],
// pointers into the view
refs: [
{ 'ref': 'userField', selector: '#user' },
{ 'ref': 'passField', selector: '#pass' },
{ 'ref': 'submitButton', selector: '#submit' }
],
// stored user information as received from the server
userinfo: null,
// controller initialisation
init: function() {
// save the scope
var loginController = this;
// create an instance of the view
var win = loginController.loginWindow = loginController.getView('Login').create();
this.control({
// register for the login-click
'#submit': {
click: function() {
// retrieve username & password from view
var username = this.getUserField().getValue(), password = this.getPassField().getValue();
// mask the form out
win.mask('Verifying…');
// process the login with the backend
loginController.performLogin(username, password, function(success) {
// the user was successfully authorized
if(success) {
// now request additional information on the user (name and such)
loginController.fetchLoginStatus(function(userinfo) {
// test if the server responded with data as expected
if(userinfo) {
// hide the login-window
win.hide();
// store received information locally
loginController.userinfo = userinfo;
// raise a event on the controller when finished
loginController.fireEvent('login', userinfo);
loginController.fireEvent('ready', userinfo);
}
// we did not receive valid data from the server
// this sould not fail, but if it does, just handle it like a failed login
else {
// disable the login on the form
win.unmask();
// set error-message on password-field
loginController.clearPasswordAndFocus().setPasswordError('Invalid Username or Password!');
}
})
}
// authorization was not successful
// unmask the form, show an error message and restart login process
else {
win.unmask();
loginController.clearPasswordAndFocus().showError('Invalid Username or Password!');
}
})
}
}
});
// register keyboard handler
this.nav = new Ext.KeyNav(win.getEl(), {
// enter key -> login-button click
enter: function() {
loginController.getSubmitButton().fireEvent('click')
}
});
},
// test if the user is logged in.
// if she is, call back immediatly. if she is not, show a login form
// delay the callback until she logged in successfully
ensureLoggedIn: function(callback) {
// save the scope
var loginController = this;
// test if the backend knows us
loginController.fetchLoginStatus(function(userinfo) {
// analyze if a user is logged in
if(userinfo) {
// callback, if she is
loginController.userinfo = userinfo;
loginController.fireEvent('ready', userinfo);
return callback(userinfo);
}
// no, we're not. show the login-window
console.log('no user logged in, showing login-window');
// login-testing and re-trying is handled by the handler set in the init-method
// it raises an event on the controller once it is finished
// we listen on this event and relay it to our callback - but only once
// -> the callback shouldn't be called multiple times
loginController.on('login', callback, {single: true});
// initiate login procedure by showing the login window
loginController.loginWindow.show();
loginController.clearForm();
});
},
// ask the backend if and which user is currently logged in
fetchLoginStatus: function(callback) {
console.info('requesting current userinfo from backend');
Ext.Ajax.request({
url: '/api/auth/user/',
success: function(response) {
// decode json-response
var userinfo = Ext.util.JSON.decode(response.responseText);
// request user permission list
Ext.Ajax.request({
url: '/api/auth/permissions/',
success: function(response) {
// decode json-response
userinfo.permissions = Ext.util.JSON.decode(response.responseText);
// callback with the decoded response
console.log('received userinfo:', userinfo);
callback(userinfo);
},
failure: function(response) {
// callback without info
console.log('received no permission list - nobody logged in');
callback();
}
});
},
failure: function(response) {
// callback without info
console.log('received no userinfo - nobody logged in');
callback();
}
});
},
// submit username & password to the backend
performLogin: function(username, password, callback) {
console.info('trying to log into backend with username=', username, 'password=', password.length, 'Chars');
// send login data via ajax to the server and callback with result
Ext.Ajax.request({
url: '/api/auth/login/',
method: 'POST',
params: {
'username': username,
'password': password
},
success: function(){
callback(true);
},
failure: function() {
callback(false);
}
});
},
// ask the backend to throw away our session which makes us logged out
performLogout: function(callback) {
console.info('trying to log out from backend');
// ensure userinfo is unset
this.userinfo = null;
Ext.Ajax.request({
url: '/api/auth/logout/',
method: 'GET',
success: function(){
callback(true);
},
failure: function() {
callback(false);
}
});
},
// shorthand to test iff userinfo is available
isLoggedIn: function() {
// null -> false, string -> true
return !!this.userinfo;
},
// shorthand to get the current username
getUserinfo: function() {
return this.userinfo;
},
// shorthand to get the current username
getUsername: function() {
return this.isLoggedIn() ? this.getUserinfo().username : null;
},
// shorthand to get the current username
getPermissions: function() {
return this.isLoggedIn() ? this.userinfo.permissions.user_permissions : [];
},
// shorthand to get the current username
isSuperuser: function() {
return this.isLoggedIn() ? this.userinfo.permissions.is_superuser : [];
},
hasPermission: function(permission) {
return this.isLoggedIn() && (this.isSuperuser() || this.getPermissions().indexOf(permission) !== -1)
},
// clears all form elements in the view
clearForm: function() {
this.loginWindow.unmask();
this.getPassField().setValue('').unsetActiveError();
this.getUserField().setValue('').unsetActiveError();
this.getUserField().focus();
return this;
},
// clears the password-field in the view and sets the typing-focus to it
clearPasswordAndFocus: function() {
this.getPassField().setValue('').focus();
return this;
},
// set an error-message on the password-fieldy
setPasswordError: function(msg) {
this.getPassField().setActiveErrors([msg]);
return this;
}
});
Login.js (view)
Ext.define('MyApp.view.Login', {
extend: 'Ext.window.Window',
renderTo: Ext.getBody(),
id: "loginBox",
title: 'Login',
width: 400,
layout: 'form',
bodyPadding: 5,
closable: false,
resizable: false,
draggable: false,
defaultFocus: 'user',
defaultType: 'textfield',
items: [{
itemId: 'user',
fieldLabel: 'Username',
allowBlank: false
},{
inputType: 'password',
fieldLabel: 'Password',
itemId: 'pass',
allowBlank: false
}],
buttons: [{
text: 'Login',
itemId: 'submit'
}]
});
console output:
GET localhost /static/static/helper/CrsfTokenHelper.js?_dc=1414444486439 200 OK 3ms ext-all-debug.js (line 1010)
GET localhost /static/static/helper/PhantomStoreInserter.js?_dc=1414444486439 200 OK 2ms ext-all-debug.js (line 1010)
Thanks anyway!
Well, apparently you are getting errors with your required files. If you comment the requires line inside your Ext.application:
Ext.application({
// base-package of all classes
name: 'MyApp',
// url to load js-files from - adapted to django project
appFolder : 'static/static',
// required controllers
controllers: ['Login'],
// other required components
//requires: [
// 'MyApp.helper.CrsfTokenHelper',
// 'MyApp.helper.PhantomStoreInserter'
//],
...
});
You will see that your Login window will show up. Assuming of course that you have your folder structure setup correctly
index.html
app.js
static/
static/static/
static/static/controller/Login.js
static/static/view/Login.js