In FormFlow, How do i get the form values after form is done? - botframework

I have a complete Form that has different fields. Name, phone and so on.
Before complition, I would like to send the fields to a method then then sends an email. More specificly, I want to put the values on a dictionary and then pass it to the method.
Where are those values stored in the Form so I can get them?
This is my code
form.OnCompletion(processOrder);
var parameters = new Dictionary<string, string>
{
{ "tileid", "open" },
{ "src", "Facebook" },
{ "chid", "9" },
{ "apply-first-name", "xxx" },
{ "apply-last-name", "xxx" },
{ "apply-email", "xxx" }
};
sendAsync(parameters);
return form.Build();

I found the answer. All values are inside the ”state” objekt passed to the oncompletion method.

Related

Dynamically create pages with Gatsby based on many Contentful references

I am currently using Gatsby's collection routes API to create pages for a simple blog with data coming from Contentful.
For example, creating a page for each blogpost category :
-- src/pages/categories/{contentfulBlogPost.category}.js
export const query = graphql`
query categoriesQuery($category: String = "") {
allContentfulBlogPost(filter: { category: { eq: $category } }) {
edges {
node {
title
category
description {
description
}
...
}
}
}
}
...
[React component mapping all blogposts from each category in a list]
...
This is working fine.
But now I would like to have multiple categories per blogpost, so I switched to Contentful's references, many content-type, which allows to have multiple entries for a field :
Now the result of my graphQL query on field category2 is an array of different categories for each blogpost :
Query :
query categoriesQuery {
allContentfulBlogPost {
edges {
node {
category2 {
id
name
slug
}
}
}
}
}
Output :
{
"data": {
"allContentfulBlogPost": {
"edges": [
{
"node": {
"category2": [
{
"id": "75b89e48-a8c9-54fd-9742-cdf70c416b0e",
"name": "Test",
"slug": "test"
},
{
"id": "568r9e48-t1i8-sx4t8-9742-cdf70c4ed789vtu",
"name": "Test2",
"slug": "test-2"
}
]
}
},
{
"node": {
"category2": [
{
"id": "75b89e48-a8c9-54fd-9742-cdf70c416b0e",
"name": "Test",
"slug": "test"
}
]
}
},
...
Now that categories are inside an array, I don't know how to :
write a query variable to filter categories names ;
use the slug field as a route to dynamically create the page.
For blogposts authors I was doing :
query authorsQuery($author__slug: String = "") {
allContentfulBlogPost(filter: { author: { slug: { eq: $author__slug } } }) {
edges {
node {
id
author {
slug
name
}
...
}
...
}
And creating pages with src/pages/authors/{contentfulBlogPost.author__slug}.js
I guess I'll have to use the createPages API instead.
You can achieve the result using the Filesystem API, something like this may work:
src/pages/category/{contentfulBlogPost.category2__name}.js
In this case, it seems that this approach may lead to some caveats, since you may potentially create duplicated pages with the same URL (slug) because the posts can contain multiple and repeated categories.
However, I think it's more succinct to use the createPages API as you said, keeping in mind that you will need to treat the categories to avoid duplicities because they are in a one-to-many relationship.
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allContentfulBlogPost {
edges {
node {
category2 {
id
name
slug
}
}
}
}
}
`)
let categories= { slugs: [], names: [] };
result.data.allContentfulBlogPost.edges.map(({node}))=> {
let { name, slug } = node.category2;
// make some checks if needed here
categories.slugs.push(slug);
categories.names.push(name);
return new Set(categories.slugs) && new Set(categories.names);
});
categories.slugs.forEach((category, index) => {
let name = categories.names[index];
createPage({
path: `category/${category}`,
component: path.resolve(`./src/templates/your-category-template.js`),
context: {
name
}
});
});
}
The code's quite self-explanatory. Basically you are defining an empty object (categories) that contains two arrays, slugs and names:
let categories= { slugs: [], names: [] };
After that, you only need to loop through the result of the query (result) and push the field values (name, slug, and others if needed) to the previous array, making the needed checks if you want (to avoid pushing empty values, or that matches some regular expression, etc) and return a new Set to remove the duplicates.
Then, you only need to loop through the slugs to create pages using createPage API and pass the needed data via context:
context: {
name
}
Because of redundancy, this is the same than doing:
context: {
name: name
}
So, in your template, you will get the name in pageContext props. Replace it with the slug if needed, depending on your situation and your use case, the approach is exactly the same.

Is there a way to get a structure of a Strapi CMS Content Type?

A content-type "Product" having the following fields:
string title
int qty
string description
double price
Is there an API endpoint to retrieve the structure or schema of the "Product" content-type as opposed to getting the values?
For example: On endpoint localhost:1337/products, and response can be like:
[
{
field: "title",
type: "string",
other: "col-xs-12, col-5"
},
{
field: "qty",
type: "int"
},
{
field: "description",
type: "string"
},
{
field: "price",
type: "double"
}
]
where the structure of the schema or the table is sent instead of the actual values?
If not in Strapi CMS, is this possible on other headless CMS such as Hasura and Sanity?
You need to use Models, from the link:
Link is dead -> New link
Models are a representation of the database's structure. They are split into two separate files. A JavaScript file that contains the model options (e.g: lifecycle hooks), and a JSON file that represents the data structure stored in the database.
This is exactly what you are after.
The way I GET this info is by adding a custom endpoint - check my answers here for how to do this - https://stackoverflow.com/a/63283807/5064324 & https://stackoverflow.com/a/62634233/5064324.
For handlers you can do something like:
async getProductModel(ctx) {
return strapi.models['product'].allAttributes;
}
I needed the solution for all Content Types so I made a plugin with /modelStructure/* endpoints where you can supply the model name and then pass to a handler:
//more generic wrapper
async getModel(ctx) {
const { model } = ctx.params;
let data = strapi.models[model].allAttributes;
return data;
},
async getProductModel(ctx) {
ctx.params['model'] = "product"
return this.getModel(ctx)
},
//define all endpoints you need, like maybe a Page content type
async getPageModel(ctx) {
ctx.params['model'] = "page"
return this.getModel(ctx)
},
//finally I ended up writing a `allModels` handler
async getAllModels(ctx) {
Object.keys(strapi.models).forEach(key => {
//iterate through all models
//possibly filter some models
//iterate through all fields
Object.keys(strapi.models[key].allAttributes).forEach(fieldKey => {
//build the response - iterate through models and all their fields
}
}
//return your desired custom response
}
Comments & questions welcome
This answer pointed me in the right direction, but strapi.models was undefined for me on strapi 4.4.3.
What worked for me was a controller like so:
async getFields(ctx) {
const model = strapi.db.config.models.find( model => model.collectionName === 'clients' );
return model.attributes;
},
Where clients is replaced by the plural name of your content-type.

Express that, for a given property value, a property with the same name should exist using json schema?

I'm trying to validate json files which have an element that has a property which contains a value that should exist in another part of the json. I'm using jsonschema Draft 07.
This is a simple little example that shows the scenario I'm trying to validate in my data.
{
"objects": {
"object1": {
"colorKey": "orange"
}
},
"colors": {
"orange": {
"red": "FF",
"green": "AF",
"blue": "00"
}
}
}
How can I validate that the 'value' of colorKey (in this case 'orange') actually exists as a property of the 'colors' object? The data isn't stored in arrays, just defined properties.
For official JSON Schema...
You cannot check that a key in the data is the same as a value of the data.
You cannot extract the value of data from your JSON instance to use in your JSON Schema.
That being said, ajv, the most popular validator, implements some unofficial extensions. One of which is $data.
Example taken from: https://github.com/epoberezkin/ajv#data-reference
var ajv = new Ajv({$data: true});
var schema = {
"properties": {
"smaller": {
"type": "number",
"maximum": { "$data": "1/larger" }
},
"larger": { "type": "number" }
}
};
var validData = {
smaller: 5,
larger: 7
};
ajv.validate(schema, validData); // true
This would not work for anyone else using your schemas.

Extjs validate in separate files

I'm trying to validate fields in my form, but I keep getting an error message.
Here is my code:
Ext.define('ExtDoc.views.extfields.FieldsValidator',{
valEng: function(val) {
var engTest = /^[a-zA-Z0-9\s]+$/;
Ext.apply(Ext.form.field.VTypes, {
eng: function(val, field) {
return engTest.test(val);
},
engText: 'Write it in English Please',
// vtype Mask property: The keystroke filter mask
engMask: /[a-zA-Z0-9_\u0600-\u06FF\s]/i
});
}
});
And I define my field as follow:
{
"name": "tik_moed_chasifa",
"type": "ExtDoc.views.extfields.ExtDocTextField",
"label": "moed_hasifa",
"vtype": "eng",
"msgTarget": "under"
}
The first snippet is in a separate js file, and I have it in my fields js file as required.
When I start typing text in the text field, I keep seeing the following error msg in the explorer debugger:
"SCRIPT438: Object doesn't support property or method 'eng' "
What could it be? Have I declared something wrong?
You have defined your own class with a function valEng(val), but you don't instantiate it, neither do you call the function anywhere.
Furthermore, your function valEng(val) does not require a parameter, because you are not using that parameter anywhere.
It would be far easier and more readable, would you remove the Ext.define part and create the validators right where you need them. For instance if you need them inside an initComponent function:
initComponent:function() {
var me = this;
Ext.apply(Ext.form.field.VTypes, {
mobileNumber:function(val, field) {
var numeric = /^[0-9]+$/
if(!Ext.String.startsWith(val,'+')) return false;
if(!numeric.test(val.substring(1))) return false;
return true;
},
mobileNumberText:'This is not a valid mobile number'
});
Ext.apply(me,{
....
items: [{
xtype:'fieldcontainer',
items:[{
xtype: 'combobox',
vtype: 'mobileNumber',
Or, you could add to your Application.js, in the init method, if you need it quite often at different levels of your application:
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
views: [
],
controllers: [
],
stores: [
],
init:function() {
Ext.apply(Ext.form.field.VTypes, {
mobileNumber:function(val, field) {
var numeric = /^[0-9]+$/
if(!Ext.String.startsWith(val,'+')) return false;
if(!numeric.test(val.substring(1))) return false;
return true;
},
mobileNumberText:'This is not a valid mobile number'
});
}

Parse.com manipulate Response Object

I am trying to work Ember with Parse.com using
ember-model-parse-adapter by samharnack.
I add added a function to make multiple work search(like search engine) for which I have defined a function on cloud using Parse.Cloud.define and run from client.
The problem is the Array that my cloud response returns is not compatible with Ember Model because of two attributes they are __type and className. how can I modify the response to get response similar to that i get when I run a find query from client. i.e without __type and className
Example responses
for App.List.find() = {
"results":[
{
"text":"zzz",
"words":[
"zzz"
],
"createdAt":"2013-06-25T16:19:04.120Z",
"updatedAt":"2013-06-25T16:19:04.120Z",
"objectId":"L1X55krC8x"
}
]
}
for App.List.cloudFunction("sliptSearch",{"text" : this.get("searchText")})
{
"results":[
{
"text":"zzz",
"words":[
"zzz"
],
"createdAt":"2013-06-25T16:19:04.120Z",
"updatedAt":"2013-06-25T16:19:04.120Z",
"objectId":"L1X55krC8x",
"__type" : Object, //undesired
"className" : "Lists" //undesired
}
]
}
Thanks Vlad something like this worked for me for array
resultobj = [];
searchListQuery.find({
success: function(results) {
for( var i=0, l=results.length; i<l; i++ ) {
temp = results.pop();
resultobj.push({
text: temp.get("text"),
createdAt: temp.createdAt,
updatedAt: temp.updatedAt,
objectId: temp.id,
words: "",
hashtags: ""
});
}
In your cloud code before you make any response, create and object and extract from it the attributes/members you need and then response it. like so:
//lets say result is some Parse.User or any other Parse.Object
function(result)
{
var responseObj = {};
responseObj.name = responseObj.get("name");
responseObj.age = responseObj.get("age");
responseObj.id = responseObj.id;
response.success(responseObj);
}
on the response side you will get {"result": {"name": "jhon", "age": "26", "id": "zxc123s21"}}
Hope this would help you

Resources