I'm trying to achieve something in LogicApp which I think should be quite easy to achieve, but I'm not managing it.
Say I have a variable from a previous step: 'https://sharepoint/sites/test-site/Documents/somereport.pdf'. From this string, I need to simply create two variables, the first one containing 'https://sharepoint/sites/test-site', the second one containing 'Documents/somereport.pdf'. Both to be used in subsequent steps.
To try and achieve this I try to use the following expressions:
join(slice(split(triggerBody()?['Title'], '/'), 0, 5), '/')
join(slice(split(triggerBody()?['Title'], '/'), 5), '/')
However, I get an error: 'The template language function 'slice' expects its first parameter to be of type string. The provided value is of type 'Array'..
This since the split results in an array. I've now learned that 'slice' is meant for strings, but is there any similar functionality for an array type? Or is there any other (simple) way to achieve this? This seems like it should be basic functionality but I cannot figure it out.
This can be achieved through few ways. If you are trying to use a functionality taking the result as array type then you can use something like below expression.
1. join(take(split(outputs('Compose')?['Title'][0], '/'), 5),'/')
2. join(take(skip(split(outputs('Compose')?['Title'][0], '/'),5), length(split(outputs('Compose')?['Title'][0], '/'))),'/')
However, As an alternative, below is another expression that satisfies your requirement if you are trying to use a functionality taking the result as string type.
1. slice(outputs('Compose')?['Title'][0],0,nthIndexOf(outputs('Compose')?['Title'][0],'/',5))
2. slice(outputs('Compose')?['Title'][0],add(nthIndexOf(outputs('Compose')?['Title'][0],'/',5),1),length(outputs('Compose')?['Title'][0]))
Below is my logic app
RESULTS:
Below is the code-view of my logic app
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": {
"Title": [
"https://sharepoint/sites/test-site/Documents/somereport.pdf"
],
"age": 30,
"name": "John"
},
"runAfter": {},
"type": "Compose"
},
"array_type_-_first_part": {
"inputs": "#join(take(split(outputs('Compose')?['Title'][0], '/'), 5),'/')",
"runAfter": {
"string_type__second_part": [
"Succeeded"
]
},
"type": "Compose"
},
"array_type_-_second_part": {
"inputs": "#join(take(skip(split(outputs('Compose')?['Title'][0], '/'),5), length(split(outputs('Compose')?['Title'][0], '/'))),'/')",
"runAfter": {
"array_type_-_first_part": [
"Succeeded"
]
},
"type": "Compose"
},
"string_type_-_first_part": {
"inputs": "#slice(outputs('Compose')?['Title'][0],0,nthIndexOf(outputs('Compose')?['Title'][0],'/',5))",
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "Compose"
},
"string_type__second_part": {
"inputs": "#slice(outputs('Compose')?['Title'][0],add(nthIndexOf(outputs('Compose')?['Title'][0],'/',5),1),length(outputs('Compose')?['Title'][0]))",
"runAfter": {
"string_type_-_first_part": [
"Succeeded"
]
},
"type": "Compose"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"inputs": {
"schema": {}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
Related
I'm building a simple slack bot and I am playing with the checkboxes element.
When I return the following from my API in a JSON response to a slash-command I get an error failed with the error "invalid_blocks", however, when I put this in the block-kit-builder it works perfectly (including "sending to slack" button)
Any ideas why this is failing when I run my slash command - and is it possible to see more detailed error messages from slack?
{
"blocks": [
{
"elements": [
{
"style": "primary",
"text": {
"emoji": true,
"text": "Create new TODO list",
"type": "plain_text"
},
"type": "button",
"value": "value"
},
{
"style": "primary",
"text": {
"emoji": true,
"text": "Help",
"type": "plain_text"
},
"type": "button",
"value": "value"
}
],
"type": "actions"
},
{
"text": {
"text": "Today",
"type": "mrkdwn"
},
"type": "section"
},
{
"elements": [
{
"initial_options": [
{
"text": {
"text": "Get Into the garden",
"type": "mrkdwn"
},
"value": "foo"
}
],
"options": [
{
"text": {
"text": "Get Into the garden",
"type": "mrkdwn"
},
"value": "foo"
}
],
"type": "checkboxes"
},
{
"style": "primary",
"text": {
"emoji": true,
"text": "Add new Task",
"type": "plain_text"
},
"type": "button",
"value": "value"
}
],
"type": "actions"
}
],
"type": "home"
}
I am using the Slack Web API. I was getting the similar error. After a lot of looking around, here's how I solved it.
import json
blocks = [{...}]
payload = {
"blocks": json.dumps(blocks)
}
You will then send this payload.
in the api, the "blocks" parameter need to be string type. Did you convert it to string or you use it as a JSON ?
https://api.slack.com/methods/chat.postMessage
In the Block Kit Builder, the data is a JSON with a blocks key.
In the Slack API, the blocks param is only the list of JSON objects.
blocks = [
{
"text": {
"text": "Its the list of your blocks",
"type": "mrkdwn"
},
"type": "section"
}
]
text = 'Alternative data in text'
client.chat_postMessage(channel=channel_id, blocks=blocks, text=text)
Another cause of this problem seems to be too many blocks being returned. I can't find any documentation about this whatsoever, but personal experience seems to indicate about 20 blocks is the maximum.
An alternative is to return fewer blocks, with paging actions -- paging works well with the "replace" message so that the content being paged through does not result in many separate messages.
It appears that not all valid elements in block kit tool can be posted as a message, despite the fact that message preview works fine in the Block Tool.
In my case, the code failed when I included an input block and passed when i removed it. The input block was generated by the Block Kit tool.
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Feedback",
"emoji": true
}
}
The error was
{'ok': False, 'error': 'invalid_blocks'}
Also, although the documentation for python says you need to urlEncode the JSON-based array, there is no example, and it is incorrect. https://api.slack.com/methods/chat.postMessage
You can see on line 29 in the SDK test code below that blocks= takes a regular list of dicts not a string.
https://github.com/slackapi/python-slack-sdk/blob/c9dc6aa0907a72c16cf36aa15e7e80031a9fdce2/integration_tests/samples/basic_usage/sending_a_message.py
I am trying to query a collection GeographyPoint within a given range from my index. I am using Azure Search.
My index contains a list of GeographyPoint
public class Parent
{
public List<Child> Coordinates {get; set;}
}
public class Child
{
public GeographyPoint Coordinates { get; set; }
}
I know if there was a single property named location on the index you could query it with something like:
$filter=geo.distance(location, geography'POINT(-82.51571 31.89063)') le 0.1524
but how do you query a collection? I've tried using the any/all filters like:
$filter=geo.distance(IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates), geography'POINT(-82.51571 31.89063)') le 0.1524
but I get the error: "Invalid expression: The Any/All query expression must evaluate to a single boolean value.\r\nParameter name: $filter"
Any help on how to query a collection of GeographyPoint would be much appreciated.
The issue is in how you've constructed your filter. Let's break it down using types, since that's the easiest way to see where things went wrong.
$filter=geo.distance(IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates), geography'POINT(-82.51571 31.89063)') le 0.1524
Starting from the outside in, the top-most expression in a filter must be Boolean, and that checks out here because you're comparing geo.distance (which returns Edm.Double) with a literal distance using le. So that part is fine.
Next, let's look at geo.distance. It takes two points of type Edm.GeographyPoint and returns an Edm.Double. The second parameter is a literal point, so that's fine, but the first parameter is not. Let's look at that next.
The first parameter to geo.distance here is the expression IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates). Although it's really an operator, you can think of any as a kind of function that returns a Boolean. That would be a problem, because geo.distance is expecting a point, not a Boolean. That's our first clue to what's wrong here, but it doesn't actually explain the error message you're seeing. Let's dig further to understand that.
Assume for the moment that the expression IndexedCompany/Offices/any(c: c/PhysicalAddress/Coordinates) was your entire filter. You'd still get the same error message: "Invalid expression: The Any/All query expression must evaluate to a single boolean value." To see why, consider what any and all expect in terms of types. Each one iterates over a collection of some type, applying a predicate in the form of a lambda expression to each element. That lambda expression in this case is c/PhysicalAddress/Coordinates, which (I'm assuming) is an Edm.GeographyPoint, not a Boolean.
Taking a step back, it helps to think about the cardinalities involved here. Each document contains a company, which has many offices, which each has a geo-point location. I'm assuming the goal is to match the whole document in case any of those co-ordinates match the filter. In that case, you really just need to re-order the parts of your query so that the types and cardinalities line up:
$filter=IndexedCompany/Offices/any(office: geo.distance(office/PhysicalAddress/Coordinates, geography'POINT(-82.51571 31.89063)') le 0.1524)
The filter is still a Boolean expression because that's the type of any. The lambda passed to any takes an Office, applies geo.distance to its geo-location, and compares the distance to the desired value. Now everything type checks and the iteration is happening the right place.
Example: search=*
"value": [
{
"#search.score": 1,
"id": "myid1",
"pts": [
{
"type": "Point",
"coordinates": [ 0, 0 ],
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
},
{
"type": "Point",
"coordinates": [ 0, 1 ],
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
}
]
},
{
"#search.score": 1,
"id": "myid2",
"pts": [
{
"type": "Point",
"coordinates": [ 0, 10 ],
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
},
{
"type": "Point",
"coordinates": [ 0, 11 ],
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
}
]
}
]
Example $filter=pts/any(pt: geo.distance(pt, geography'POINT(0 2)') le 111.3192394008)
"value": [
{
"#search.score": 1,
"id": "myid1",
"pts": [
{
"type": "Point",
"coordinates": [ 0, 0 ],
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
},
{
"type": "Point",
"coordinates": [ 0, 1 ],
"crs": { "type": "name", "properties": { "name": "EPSG:4326" } }
}
]
}
]
I'm trying to fetch all users from a specific group via an HTTP connector, a registered app, and Microsoft Graph.
The registered app has Directory.Read.All permissions.
My idea is that I'm calling the nextLink as long as it's there while appending all of the fetched users' userPrincipalName to an array eventually filling the array with all users of the group.
My Logic App looks like this:
Unfortunately, I'm just 1 reputation short of posting images, please forgive. The 3 links should provide an overview of the structure of my app.
First, nextLink is initialized to the first Graph API endpoint. This variable is set to the current nextLink through each iteration of the until loop.
Second, For the purpose of this exercise, I only get the top 5. I know there are only 9 users:
Lastly, I call the union method on the "users" array that I initialized earlier and the "value" array from the HTTP get method, to get one single array consisting of all users:
The issue is that the HTTP action always returns the same top 5 users. I've checked that the nextLink provided in the first HTTP GET call to Graph, is correct by copying it from the Runs history and pasting it into Microsoft Graph Explorer and there the next 4 users are correctly returned.
I also made sure that, for each iteration in the until loop, I call the Graph API with the nextLink from the previous iteration as expected.
The nextLink returned inside of the Logic App is exactly the same when I test it in Graph Explorer, but the same nextLink returns 2 different results when called from Graph Explorer and inside my Logic App.
Why is the result always the same top 5 users and not the next 4 users as expected?
If not sure about the reason why you will get this issue, but based on your requirement, I did a sample below:
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Initialize_variable": {
"inputs": {
"variables": [
{
"name": "GetGroupUrl",
"type": "string",
"value": "https://graph.microsoft.com/v1.0/groups/<your group id>/members?$select=userPrincipalName&$top=5"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Initialize_variable_2": {
"inputs": {
"variables": [
{
"name": "users",
"type": "array"
}
]
},
"runAfter": {
"Initialize_variable": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Until": {
"actions": {
"Compose": {
"inputs": "#union(variables('users'),body('HTTP')['value'])",
"runAfter": {
"HTTP": [
"Succeeded"
]
},
"type": "Compose"
},
"HTTP": {
"inputs": {
"authentication": {
"audience": "https://graph.microsoft.com",
"clientId": "<app id>",
"secret": "<app secret>",
"tenant": "<your secret>",
"type": "ActiveDirectoryOAuth"
},
"method": "GET",
"uri": "#variables('GetGroupUrl')"
},
"runAfter": {},
"type": "Http"
},
"Set_variable": {
"inputs": {
"name": "GetGroupUrl",
"value": "#{if(equals(body('HTTP')?['#odata.nextLink'], null),null,body('HTTP')['#odata.nextLink'])}"
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "SetVariable"
}
},
"expression": "#equals(variables('GetGroupUrl'), '')",
"limit": {
"count": 60,
"timeout": "PT1H"
},
"runAfter": {
"Initialize_variable_2": [
"Succeeded"
]
},
"type": "Until"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"manual": {
"inputs": {
"method": "GET",
"schema": {
"properties": {
"text": {
"type": "string"
}
},
"type": "object"
}
},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
You can just replace the params with your own and paste it into your logic app code view and test it .
It works for me, as you can see , each request results are different :
Hope it helps .
This issue solved by OP self, this issue is due to queries in request URL , copy OP's comment as an answer :
After fiddling a bit more around with what each of you providing I
found a solution. It seems that when the query arguments are passed to
the HTTP GET outside of the endpoint itself (meaning in the "queries"
field inside of the block) it seems to keep overriding the nextLink.
When writing the endpoint URL out entirely with the odata parameters,
it works as intended.
I am trying to build up a response from a variety of schema components using OpenAPI 3. There are basically three parts to the response:
A shared component that other endpoints use (i.e. success/failure flags). - #/components/schemas/core_response_schema inside allOf.
Properties that all responses on this endpoint use (i.e., user_id) - the properties component of the below.
One of several schemas that will vary depending on the type of user. - the oneOf component.
I've determined that I have to use allOf to be able to mix properties (item 2) and the core response (item 1), though this feels wrong as there's only one item. I tried a $ref, but it didn't work.
The below successfully passes three different OpenAPI linting tools, but in the example it builds, Swagger UI does not show the item 2 things (properties), and does show all of the item 3 things (should be oneOf).
"responses": {
"200": {
"description": "Operation successfully executed.",
"content": {
"application/json": {
"schema": {
"properties": {
"user_id": {
"$ref": "#/components/schemas/user_id"
},
"results": {
"type": "array",
"items": {
"$ref": "#/components/schemas/result_user_by_id"
}
}
},
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/core_response_schema"
}
],
"oneOf": [
{
"$ref": "#/components/schemas/user_type_a"
},
{
"$ref": "#/components/schemas/user_type_b"
},
{
"$ref": "#/components/schemas/user_type_c"
}
]
}
}
}
}
},
"components": {
"schemas": {
"core_response_schema": {
"properties": {
"success": {
"description": "A flag indicating whether the request was successfully completed or not.",
"type": "boolean"
},
"num_results": {
"description": "The number of results for this request",
"type": "integer"
}
},
"type": "object"
},
"user_id": {
"description": "Unique 10 character `user_id`.",
"type": "string",
"maxLength": 10,
"minLength": 10,
"example": "a1b2c3d4e5"
},
}
}
And example payloads for two users. Type A and B (it's a contrived example).
User Type A:
{
"success": true,
"num_results": 1,
"user_id": "c1b00cb714",
"results": [{
"user_type": "a",
"group_id": "e7a99e3769",
"name": null,
"title": null,
... (and so on until we get to the stuff that's unique to this type of user) ...
"favourite_artworks": [
"sunflowers",
"landscapes"
],
"artwork_urls": [
"http://sunflowers.example"
]
}
]
}
User Type B:
{
"success": true,
"num_results": 1,
"user_id": "c1b00cb715",
"results": [{
"user_type": "B",
"group_id": "e7a99e3769",
"name": null,
"title": null,
... (and so on until we get to the stuff that's unique to this type of user) ...
"supported_charities": [
"UN Foundations"
],
"charity_urls": [
"http://www.un.int"
],
}
]
}
What's the correct way to merge together different schemas and properties in OpenAPI? Is this right and Swagger UI just can't handle it?
And how do you mix a schema with properties without having to use allOf?
This suggests it's possible: Swagger Schema: oneOf, anyOf, allOf valid at the same time?
After further investigation, I've determined this is a bug in swagger-ui - https://github.com/swagger-api/swagger-ui/issues/3803 - they simply don't support oneOf (or anyOf) currently.
As far as at least three different linting tools are concerned, a mixture of anyOf, oneOf, and allOf can be used together in the same schema.
Redoc appears to have similar problems - https://github.com/Rebilly/ReDoc/issues/641
I have an internal app that uses a webhook listener and some scripting to manipulate the input data. I'm posting this to it:
curl -X POST -d '{
"assignment_id": 12345,
"updated_custom_fields": [{
"name": "RNVIDAYEBB",
"value": "updated!"
},
{
"name": "QUFTXSIBYA",
"value": "and me too"
}
],
"custom_fields": [{
"id": 981,
"name": "RDEXDPVKRD",
"fields": [
{
"id": 4096,
"name": "RNVIDAYEBB",
"default": "EDJEAJICYW",
"required": true,
"value": "Blah"
},
{
"id": 4097,
"name": "QUFTXSIBYA",
"default": "",
"required": true,
"value": ""
}]
}]
}' "https://hooks.zapier.com/hooks/catch/......"
My script is as follows:
update_custom_fields_by_name_pre_write: function(bundle) {
var updatedFields = _.map(bundle.request.data.custom_fields, function(group) {
return _.map(group.fields, function(field) {
return _.extend(field, _.findWhere(bundle.request.data.updated_custom_fields, { name: field.name} ));
});
});
bundle.request.data = updatedFields;
return bundle.request;
}
I know that the merging logic is good, but it appears that the custom_fields and updated_custom_fields arrays are not present in the bundle.request.data object. Anyone know how to get access to them in the script?
It seems like you should be using update_custom_fields_by_name_catch_hook to capture the incoming static webhook data (instead of _pre_write). If you use that, you can capture the data within bundle.cleaned_request.custom_fields and bundle.cleaned_request.updated_custom_fields.