BotFramework - handleTeamsTaskModuleFetch URL not working - botframework

Below is the continue task module I am returning. The URL works fine when I hit it directly in the browser, but in teams, I always get this:
Task module reponse
handleTeamsTaskModuleFetch() {
return {
task: {
type: "continue",
value: {
title: "response",
url: `${process.env.HostName}/help.html`,
fallbackUrl: `${process.env.HostName}/help.html`,
width: 500,
height: 500
}
}
};
}
Can anyone see what I am doing wrong?
Cheers
Note: This is how I am creating the Adaptive Card
const adaptiveCard = {
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
version: '1.0',
type: 'AdaptiveCard',
body: [{
type: 'TextBlock',
text: 'Task Module Invocation from Adaptive Card',
weight: 'bolder',
size: 3
}],
actions: [{
type: 'Action.Submit',
title: "TEST",
data: { msteams: { type: 'task/fetch'}, data: "meTask" }
}]
}

The URL's domain must be in the app's validDomains array in your app's manifest.

Related

How to create custom resolvers for Gatsby page queries?

I have a Gatsby application pulling data from Sanity.
This is Sanity's schema for the course.js:
import video from './video'
export default {
// Computer name
name: `courses`,
// Visible title
title: `Courses`,
type: `document`,
fields: [
{
name: `title`,
title: `Course title`,
type: `string`,
description: `Name of the course`
},
{
name: `slug`,
title: `slug`,
type: `slug`,
options: {
source: `title`,
maxLength: 100,
}
},
{
name: `price`,
title: `Price`,
type: `number`
},
{
name: `thumbnail`,
title: `Thumbnail`,
type: `image`,
options: {
hotspot: true,
}
},
{
name: `playlist`,
title: `Playlist`,
type: `array`,
of: [
{
title: `Video`,
name: `video`,
type: `video`,
}
]
},
]
}
And this is Sanity's schema for video.js:
export default {
// Computer name
name: `video`,
// Visible title
title: `Video`,
type: `object`,
fields: [
{ name: `title`, type: `string`, title: `Video title` },
{ name: `url`, type: `url`, title: `URL` },
{ name: `public`, title: `public`, type: `boolean`, initialValue: false }
]
}
This Gatsby page query:
{
allSanityCourses {
nodes {
title
price
playlist {
url
title
public
}
}
}
}
Results in:
{
"data": {
"allSanityCourses": {
"nodes": [
{
"title": "Master VS Code",
"price": 149,
"playlist": [
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Introduction",
"public": true
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Philosophy",
"public": false
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Tech and Tools",
"public": false
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Integration",
"public": true
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Extensions",
"public": false
}
]
}
]
}
},
"extensions": {}
}
To prevent the url field from being injected into the React component this Gatsby page query runs on (because these urls are paid for), I need to remove it, if the public field is set to false.
I've tried inserting this into gastby-node.js:
exports.createSchemaCustomization = ({ actions, schema }) => {
const { createTypes } = actions
const typeDefs = [
schema.buildObjectType({
name: "SanityCourses",
fields: {
playlist: {
type: "[SanityVideo]",
url: {
type: "String",
resolve: (source) => "nope"
},
},
},
interfaces: ["Node"],
}),
]
createTypes(typeDefs)
}
And:
exports.createResolvers = ({ createResolvers }) => {
const resolvers = {
SanityCourses: {
playlist: {
type: "[SanityVideo]",
url: {
type: "String",
resolve(source, args, context, info) {
return "nope"
},
}
},
},
}
createResolvers(resolvers)
}
But neither seems to work. The url field returns the url as always. The resolvers don't even seem to fire (I've tried putting console.log()'s in them).
Any help on how to remove the url field if the public field is set to false, or general direction to go in would be very appreciated.
Ditch the attempt in createSchemaCustomization since you don't need to customize the schema here (though I believe there is a way to achieve what you want using it, it is not expected that the data in it is sourced from existing nodes, and this undeclared dependency can create caching issues).
Then update your createResolvers function to something like this:
exports.createResolvers = ({ createResolvers }) => {
createResolvers({
SanityVideo: {
safeUrl: {
type: "String",
resolve: (source, args, context, info) => source.public ? source.url : null
},
},
})
}
I don't believe resolvers can replace schema-originated nodes (fields), hence using safeUrl instead of url
The type you are adding a field to is SanityVideo, and it doesn't matter what the parent node is—this will apply to all instances of SanityVideo in your data

Workflow Builder Steps from Apps tutorial: server-side problem with provided glitch code

I’m following the tutorial at Workflow Builder Steps from Apps:
https://api.slack.com/tutorials/workflow-builder-steps
Glitch template:
https://glitch.com/edit/#!/steps-from-apps
I'm not able to verify the Redirect URL in Slack which I think is because I'm seeing a server-side error on glitch.com immediately after remixing the code.
Error message:
ReferenceError: require is not defined
file:///app/index.js:1
const { App, WorkflowStep } = require("#slack/bolt");
ReferenceError: require is not defined
Jump Toat file:///app/index.js:1:31
at ModuleJob.run (internal/modules/esm/module_job.js:152:23)
at async Loader.import (internal/modules/esm/loader.js:166:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
Glitch:
https://glitch.com/edit/#!/tarry-tremendous-walnut
Any ideas what’s going on?
Thanks!
Rick
index.js:
const { App, WorkflowStep } = require("#slack/bolt");
const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});
// This code saves tasks to this object
// Tasks are stored in memory and not in a persistent database
// This object is refreshed each time your Glitch app restarts
// The result is that your App Home will be cleared with each restart
let TASKS_DB = {};
const ws = new WorkflowStep("copy_review", {
edit: async ({ ack, step, configure }) => {
await ack();
const blocks = [
{
type: "section",
block_id: "intro-section",
text: {
type: "plain_text",
text:
"Create a task in one of the listed projects. The link to the task and other details will be available as variable data in later steps.",
emoji: true
}
},
{
type: "input",
block_id: "task_name_input",
element: {
type: "plain_text_input",
action_id: "name",
placeholder: {
type: "plain_text",
text: "Write a task name"
}
},
label: {
type: "plain_text",
text: "Task name",
emoji: true
}
},
{
type: "input",
block_id: "task_description_input",
element: {
type: "plain_text_input",
action_id: "description",
placeholder: {
type: "plain_text",
text: "Write a description for your task"
}
},
label: {
type: "plain_text",
text: "Task description",
emoji: true
}
},
{
type: "input",
block_id: "task_author_input",
element: {
type: "plain_text_input",
action_id: "author",
placeholder: {
type: "plain_text",
text: "Write a task name"
}
},
label: {
type: "plain_text",
text: "Task author",
emoji: true
}
}
];
await configure({ blocks });
},
save: async ({ ack, step, update, view }) => {
await ack();
const {
task_name_input,
task_description_input,
task_author_input
} = view.state.values;
const taskName = task_name_input.name.value;
const taskDescription = task_description_input.description.value;
const taskAuthorEmail = task_author_input.author.value;
const inputs = {
taskName: { value: taskName },
taskDescription: { value: taskDescription },
taskAuthorEmail: { value: taskAuthorEmail }
};
const outputs = [
{
type: "text",
name: "taskName",
label: "Task Name"
},
{
type: "text",
name: "taskDescription",
label: "Task Description"
},
{
type: "text",
name: "taskAuthorEmail",
label: "Task Author Email"
}
];
await update({ inputs, outputs });
},
execute: async ({ step, complete, fail, client }) => {
try {
const { taskName, taskDescription, taskAuthorEmail } = step.inputs;
const outputs = {
taskName: taskName.value,
taskDescription: taskDescription.value,
taskAuthorEmail: taskAuthorEmail.value
};
const user = await client.users.lookupByEmail({
email: taskAuthorEmail.value
});
const userId = user.user.id;
const newTask = {
task_name: taskName.value,
task_description: taskDescription.value
};
TASKS_DB[userId] = TASKS_DB[userId]
? [...TASKS_DB[userId], newTask]
: [newTask];
const taskBlocksItems = TASKS_DB[userId].map(task => {
return [
{
type: "section",
text: {
type: "plain_text",
text: task.task_name,
emoji: true
}
},
{
type: "divider"
}
];
});
const homeHeader = [
{
type: "header",
text: {
type: "plain_text",
text: "Workflow Builder - Steps from Apps task list",
emoji: true
}
},
{
type: "context",
elements: [
{
type: "mrkdwn",
text:
"_This is a list of tasks generated by your example Workflow Builder Task creation step, found in this tutorial https://api.slack.com/tutorials/workflow-builder-steps. These tasks are stored in the Glitch client, not in a database and refresh every time your Glitch app is restarted. If you'd like to store these tasks in a database, please check out this Glitch page for more information https://glitch.com/#storage _"
}
]
},
{
type: "divider"
}
];
const taskBlocks = [].concat.apply([], taskBlocksItems);
const blocks = homeHeader.concat(taskBlocks);
// update app home
let view = {
type: "home",
blocks
};
const usersTasks = TASKS_DB[userId];
await client.views.publish({
user_id: userId,
view: JSON.stringify(view)
});
// If everything was successful, complete the step
await complete({ outputs });
} catch (e) {
// TODO if something went wrong, fail the step ...
app.logger.error("Error completing step", e.message);
}
}
});
app.step(ws);
(async () => {
// Start your app
const port = process.env.PORT || 3000;
await app.start(port);
console.log(`⚡️ index.js Bolt app is running on port ${port}!`);
})();
Your package.json config has "type": "module" and, according to the original template you're working from, you do not want to be building this script as a module. If you remove that declaration, using require will work.

Kendo Grid renders properly but does not display json data

I have been having a tough time with grids lately, mostly getting them to display properly formatted JSON data that is being fetched from a webservice (which has been checked in VS2013, and JSONLint), if a second set of eyes could please have a look at my solution and tell me whats lacking? I am going bananas!
function SetTelerikGrid() {
// prepare the data object and consume data from web service,...
$.ajax({
type: "GET",
async: false,
url: "http://localhost:38312/SDMSService.svc/GetProductPositionsByLocation/0544",
datatype: "json",
success: function (ProductData, textStatus, jqXHR) {
// populate kendo location grid by data from successful ajax call,...
$("#LocationProductsGrid").kendoGrid({
dataSource: {
data: ProductData, // solution here was: **JSON.parse(LocationData)**
schema: {
model: {
fields: {
Date: { type: "string" },
ProductCode: { type: "string" },
StoreNum: { type: "string" },
ProductQty: { type: "int" }
}
}
},
pageSize: 20
},
height: 550,
scrollable: true,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
{ field: "Date", title: "Date", width: "130px" },
{ field: "ProductCode", title: "Product Code", width: "130px" },
{ field: "StoreNum", title: "Store Number", width: "130px" },
{ field: "ProductQty", title: "Product Qty", width: "130px" }
]
});
}
});
}
There is a breaking change in ASP.NET Core, related to how the JSON serializer
works
You can probably mitigate this by adding a json option like this:
1:
change
services.AddMvc();
to
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
OR
2:
public IActionResult Read()
{
// Override serializer settings per-action
return Json(
MyModel,
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() }
);
}
refrences :
http://www.telerik.com/forums/using-2016-2-630-preview---data-not-displayed#qlHR6zhqhkqLZWuHfdUDpA
https://github.com/telerik/kendo-ui-core/issues/1856#issuecomment-229874309
https://github.com/telerik/kendo-ui-core/issues/1856#issuecomment-230450923
Finally figured it out, the 'ProductData' field - although in perfect JSON format - still required to be parsed as JSON in the datasource configuration, like so,...
Data: JSON.parse(ProductData)

SenchaTouch: Ext.getCmp().setSrc() method is not working

I am trying to change the source of an image using setSrc but I get this error:
Uncaught TypeError: Cannot call method 'setSrc' of undefined
Ext.Ajax.request.success Ext.apply.callback Ext.define.onComplete
Ext.define.onStateChange (anonymous function)
This is my source code :
View Page:
Ext.define('MechanicalTerk.view.Picture', {
extend: 'Ext.Container',
xtype: 'Picture',
requires: [
'Ext.data.Store'
],
config: {
layout: 'vbox',
items:
[
{
xtype: 'toolbar',
docked: 'top',
title: 'Requests',
minHeight: '60px',
items: [
{
xtype:'button',
ui:'back button',
id:'backButton',
text:'Back'
},{
xtype: 'button',
id:'logoutButton',
text: 'Logout'
}
],
},
{
xtype:'image',
height:500,
id:'layoutImage'
}
]
}
});
Controller:
Ext.define('MechanicalTerk.controller.PictureController',{
extend:'Ext.app.Controller',
showPicture: function(userID,sentAt){
Ext.Ajax.request({
url:'app/Model/database.php',
params: {
functionID: 3,
userID: userID,
sentAt: sentAt,
},
success: function (response, opts){
Ext.getCmp('layoutImage').setSrc('http://www.sencha.com/img/20110215-feat-perf.png');
Ext.Viewport.setActiveItem(Ext.create('MechanicalTerk.view.Picture'));
}
});
}
});
Any ideas ?
You should consider not using your own id and instead use an itemId. This is probably happening because you are trying to re-use a component that has been destroyed. I would suggest creating a ref to your image in your controller so you can access it.
So I'm thinking:
Ext.define('MechanicalTerk.controller.PictureController',{
extend:'Ext.app.Controller',
config: {
refs : {
myImage : {
autoCreate: true,
selector: '#myimage',//assuming your image's itemId is 'myimage'
xtype: 'image'
}
}
},
showPicture: function(userID,sentAt){
Ext.Ajax.request({
url:'app/Model/database.php',
params: {
functionID: 3,
userID: userID,
sentAt: sentAt,
},
success: function (response, opts){
var me = this;
me.getMyImage().setSrc('http://www.sencha.com/img/20110215-feat-perf.png');
Ext.Viewport.setActiveItem(Ext.create('MechanicalTerk.view.Picture'));
}
});
}
});
PS: Not tested but try that approach.

Load another view after login with sencha touch 2.0

I'm having a dumb problem and I would like you to give me a hand.Thanks in advance.
The situatios is as follows: I have 2 wiews (both created with sencha architect 2.0), one for login, and another for general purposes. And I would like to load the second view on successful response when trying to log in, this is, after any successful login. The main problem is that I've tried with Ex.create, Ext.Viewport.add, Ext.Viewport.setActiveItem, but I can't manage to make the second view to appear on screen, the login screen just keeps there and the app does not load the other view. Another thing, I don't have to use a navigation view for this.
Here is the code of my controller, from which I want to load my second view. And as you'll see, I even created a reference of the view, which has autoCreate enabled and has that ID "mainTabPanel":
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
config: {
refs: {
loginButton: {
selector: '#login',
xtype: 'button'
},
username: {
selector: '#user',
xtype: 'textfield'
},
password: {
selector: '#pass',
xtype: 'passwordfield'
},
mainTabPanel: {
selector: '#mainTabPanel',
xtype: 'tabpanel',
autoCreate: true
}
},
control: {
"loginButton": {
tap: 'onLoginButtonTap'
}
}
},
onLoginButtonTap: function(button, e, options) {
Ext.Ajax.request({
url: '../../backend/auth.php',
method: 'POST',
params: {
user: this.getUsername().getValue(),
pass: this.getPassword().getValue()
},
success: function(response) {
var json = Ext.decode(response.responseText);
if (json.type == 'success') {
// LOAD THE DAMN SECOND VIEW HERE!
//var paneltab = Ext.create('MyApp.view.MainTabPanel');
//Ext.Viewport.add(paneltab);
//Ext.Viewport.setActiveItem(this.getMainTabPanel());
} else {
alert(json.value);
}
},
failure: function(response) {
alert('The request failed!');
}
});
}
});
And here is the code of my login view:
Ext.define('MyApp.view.LoginForm', {
extend: 'Ext.form.Panel',
config: {
id: 'loginForm',
ui: 'light',
items: [
{
xtype: 'fieldset',
ui: 'light',
title: 'Log into the system',
items: [
{
xtype: 'textfield',
id: 'user',
label: 'User',
name: 'user'
},
{
xtype: 'passwordfield',
id: 'pass',
label: 'Pass',
name: 'pass'
}
]
},
{
xtype: 'button',
id: 'login',
ui: 'confirm',
text: 'Login'
}
]
}
});
And finally, the code of the view I want to load. This view loads normally if I set it as the Initial View, but does not load when a successful login occurs:
Ext.define('MyApp.view.MainTabPanel', {
extend: 'Ext.tab.Panel',
config: {
id: 'mainTabPanel',
layout: {
animation: 'slide',
type: 'card'
},
items: [
{
xtype: 'container',
layout: {
type: 'vbox'
},
title: 'Tab 1',
iconCls: 'time',
items: [
{
xtype: 'titlebar',
docked: 'top',
title: 'General Report',
items: [
{
xtype: 'button',
iconCls: 'refresh',
iconMask: true,
text: '',
align: 'right'
}
]
},
{
xtype: 'container',
height: 138,
flex: 1,
items: [
{
xtype: 'datepickerfield',
label: 'From',
placeHolder: 'mm/dd/yyyy'
},
{
xtype: 'datepickerfield',
label: 'To',
placeHolder: 'mm/dd/yyyy'
},
{
xtype: 'numberfield',
label: 'Hours'
}
]
},
{
xtype: 'dataview',
ui: 'dark',
itemTpl: [
'<div style="height:50px; background-color: white; margin-bottom: 1px;">',
' <span style="color: #0000FF">{user}</span>',
' <span>{description}</span>',
'</div>'
],
store: 'hoursStore',
flex: 1
}
]
},
{
xtype: 'container',
title: 'Tab 2',
iconCls: 'maps'
},
{
xtype: 'container',
title: 'Tab 3',
iconCls: 'favorites'
}
],
tabBar: {
docked: 'bottom'
}
}
});
Please, I need help... :)
I'm stuck here for like 3 days now and can't figure out what the problem is. Thank you.
Could you post your app.js too?
I'm trying your code here and it load the view as expected. Here is my app.js:
Ext.application({
name: 'MyApp',
requires: [
'Ext.MessageBox'
],
controllers: ['Login'],
views: ['LoginForm','MainTabPanel'],
icon: {
'57': 'resources/icons/Icon.png',
'72': 'resources/icons/Icon~ipad.png',
'114': 'resources/icons/Icon#2x.png',
'144': 'resources/icons/Icon~ipad#2x.png'
},
isIconPrecomposed: true,
startupImage: {
'320x460': 'resources/startup/320x460.jpg',
'640x920': 'resources/startup/640x920.png',
'768x1004': 'resources/startup/768x1004.png',
'748x1024': 'resources/startup/748x1024.png',
'1536x2008': 'resources/startup/1536x2008.png',
'1496x2048': 'resources/startup/1496x2048.png'
},
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
//Ext.Viewport.add(Ext.create('MyApp.view.Main'));
Ext.Viewport.add(Ext.create('MyApp.view.LoginForm'));
},
onUpdated: function() {
Ext.Msg.confirm(
"Application Update",
"This application has just successfully been updated to the latest version. Reload now?",
function(buttonId) {
if (buttonId === 'yes') {
window.location.reload();
}
}
);
}
});
Destroy the login panel, You don't really need it anymore...
success: function(response) {
var json = Ext.decode(response.responseText);
if (json.type == 'success') {
// LOAD THE DAMN SECOND VIEW HERE!
var paneltab = Ext.create('MyApp.view.MainTabPanel');
Ext.getCmp('loginForm').destroy();
Ext.Viewport.add(paneltab);
} else {
alert(json.value);
}
},
There are several problems here:
Your autoCreate rule uses an xtype: 'tabpanel' which will only ever create a vanilla Ext.TabPanel with no items in it. You'd need to assign an xtype attribute to your MyApp.view.MainTabPanel like xtype: 'mainTabPanel' and then use that xtype value in your autoCreate rule.
This then explains why this code won't work since this.getMainTabPanel() will return the wrong object. Simpler would be to just use Ext.Viewport.setActiveItem(paneltab).
In general, you usually don't want assign an id to a view (id: 'mainTabPanel'). Safer to just use an xtype to fetch it. Although you don't need it in this case, avoiding global id's allows you to create multiple instances of a view (or any other class type).

Resources