How to go to the correct filemaker layout given a layout id? - macos

A FileMaker snapshot file has a layout id. However, using the go to layout number does not work as I had expected.
Set Variable [$json; Value:Get(ScriptParameter)]
Set Variable [$layout_id; Value:JSONGetElement ( $json ; "UIState.Layout.#id" )]
Go to Layout [$layout_id] // layout number by calculation
// ends up on a completely different layout than the one the snapshot file opens.
I've discovered that the layout id and layout number are two different numbers ... which is why the go-to layout number script step failed.
The JSON string used as a parameter for the above script is.
{
"UIState": {
"UniversalPathList": "fmnet:/10.1.1.63/Balanced.fmp12\nfmnet:/10.1.1.220/Balanced.fmp12\nfmnet:/169.254.254.47/Balanced.fmp12\nfilemac:/Macintosh HD/source/fmp16/Balanced.fmp12",
"Rows": {
"#rowCount": "1",
"#baseTableId": "131",
"#text": "21383239"
},
"Layout": {
"#id": "2"
},
"View": [
],
"SelectedRow": {
"#id": "21383239"
},
"StatusToolbar": {
"#visible": "True"
},
"Mode": {
"#value": "browseMode"
},
"SortList": {
"#Maintain": "True",
"#value": "False"
}
}
}
Which can be run from the command line. Example
open 'fmp://filemaker.server/Balanced.fmp12?script=snapshot_link&param={ "UIState": { "UniversalPathList": "fmnet:/10.1.1.63/Balanced.fmp12\nfmnet:/10.1.1.220/Balanced.fmp12\nfmnet:/169.254.254.47/Balanced.fmp12\nfilemac:/Macintosh HD/source/fmp16/Balanced.fmp12", "Rows": { "#rowCount": "1", "#baseTableId": "131", "#text": "21383239" }, "Layout": { "#id": "2" }, "View": [], "SelectedRow": { "#id": "21383239" }, "StatusToolbar": { "#visible": "True" }, "Mode": { "#value": "browseMode" }, "SortList": { "#Maintain": "True", "#value": "False" } } }'
What would be a good way to find the right layout to display in FileMaker given a valid layout id?

I believe you can calculate the layout number by finding the index number of a given layout ID in the list returned by the LayoutIDs function, say =
Let (
listOfIDs = LayoutIDs ( "" )
;
ValueCount ( Left ( listOfIDs ; Position ( ¶ & listOfIDs & ¶ ; ¶ & $layout_ID & ¶ ; 1 ; 1 ) ) )
)

Related

JSONata array to array manipulation with mapping

I need to transform array to array with some extra logic:
Map field name in array if it exists in the mapping object, if not process it as it is in the source
Sum up values of objects with the same name
Remove objects with zero value
for example here is the source json:
{
"additive": [
{
"name": "field-1",
"volume": "10"
},
{
"name": "field-2",
"volume": "10"
},
{
"name": "field-3",
"volume": "0"
},
{
"name": "field-4",
"volume": "5"
}
]
}
object with mapping config(field-1 and field-2 is mapped to the same value):
{
"field-1": "field-1-mapped",
"field-2": "field-1-mapped",
"field-3": "field-3-mapped"
}
and this is the result that I need to have
{
"chemicals": [
{
"name": "field-1-mapped",
"value": 20
},
{
"name": "field-4",
"value": 5
}
]
}
as you can see field-1 and field-2 is mapped to field-1-mapped so the values are summed up, field-3 has 0 value so it is removed and field-4 is passed as it is because it's missing in the mapping.
so my question is: is it possible to make it with JSONata?
I have tried to make it work but I stuck with this lookup function that doesn't return default value when name is missing in mapping:
{
"chemicals": additive # $additive #$.{
"name": $res := $lookup({
"field-1": "field-1-mapped",
"field-2": "field-1-mapped",
"field-3": "field-3-mapped"
}, $additive.name)[ $res ? $res : $additive.name],
"amount": $number($additive.volume),
} [amount>0]
}
Probably easiest to break it down into steps as follows:
(
/* define lookup table */
$table := {
"field-1": "field-1-mapped",
"field-2": "field-1-mapped",
"field-3": "field-3-mapped"
};
/* substitute the name; if it's not in the table, just use the name */
$mapped := additive.{
"name": [$lookup($table, name), name][0],
"volume": $number(volume)
};
/* group by name, and aggregate the volumes */
$grouped := $mapped[volume > 0]{name: $sum(volume)};
/* convert back to array */
{
"chemicals": $each($grouped, function($v, $n) {{
"name": $n,
"volume": $v
}})
}
)
See https://try.jsonata.org/0BWeRcRoZ

How can i form the property in compose to return int(0) if condition is true and not return anything if condition is false?

How can i form this expression to return int value of 0 if true and don't return the property if false? warehouse event is an array and the property is inside a compose.
Expression:
if(contains(variables('WareHouseEvent'), 'OB_2910'), int(0), <not
return anything)
An alternative to the first answer is to always add and then remove it after the fact.
This is an example you can copy into your own tenant for testing.
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose_JSON_Object": {
"inputs": {
"AnotherProperty": "Another Value",
"TestProperty": "#variables('Data')"
},
"runAfter": {
"Initialize_Integer": [
"Succeeded"
]
},
"type": "Compose"
},
"Initialize_Integer": {
"inputs": {
"variables": [
{
"name": "Data",
"type": "integer",
"value": 0
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"New_JSON_Object": {
"inputs": {
"variables": [
{
"name": "New Object",
"type": "object",
"value": "#if(equals(variables('Data'), 1), removeProperty(outputs('Compose_JSON_Object'), 'TestProperty'), outputs('Compose_JSON_Object'))"
}
]
},
"runAfter": {
"Compose_JSON_Object": [
"Succeeded"
]
},
"type": "InitializeVariable"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"manual": {
"conditions": [],
"inputs": {},
"kind": "Http",
"type": "Request"
}
}
},
"parameters": {}
}
I have an integer variable at the top which stores a value of either 1 or 0.
Then in my compose, I add that value to a property in the compose statement.
Then beneath that, I set a new variable with the (potentially) updated object using an expression to determine if the added property should be removed or not.
You'd just need to adjust the condition portion of the IF statement with your expression.
if(equals(variables('Data'), 1), removeProperty(outputs('Compose_JSON_Object'), 'TestProperty'), outputs('Compose_JSON_Object'))
The property will be removed depending on the value of the Data variable.
Removed
Retained
One of the workarounds is that you can use Condition connector when if the mentioned condition satisfies it executes true block else it executes false. From there you can use the same Compose content.
Here is the screenshot of the logic app -
output :-

DynamoDB DocumentClient returns Set of strings (SS) attribute as an object

I'm new to DynamoDB.
When I read data from the table with AWS.DynamoDB.DocumentClient class, the query works but I get the result in the wrong format.
Query:
{
TableName: "users",
ExpressionAttributeValues: {
":param": event.pathParameters.cityId,
":date": moment().tz("Europe/London").format()
},
FilterExpression: ":date <= endDate",
KeyConditionExpression: "cityId = :param"
}
Expected:
{
"user": "boris",
"phones": ["+23xxxxx999", "+23xxxxx777"]
}
Actual:
{
"user": "boris",
"phones": {
"type": "String",
"values": ["+23xxxxx999", "+23xxxxx777"],
"wrapperName": "Set"
}
}
Thanks!
The [unmarshall] function from the [AWS.DynamoDB.Converter] is one solution if your data comes as e.g:
{
"Attributes": {
"last_names": {
"S": "UPDATED last name"
},
"names": {
"S": "I am the name"
},
"vehicles": {
"NS": [
"877",
"9801",
"104"
]
},
"updatedAt": {
"S": "2018-10-19T01:55:15.240Z"
},
"createdAt": {
"S": "2018-10-17T11:49:34.822Z"
}
}
}
Please notice the object/map {} spec per attribute, holding the attr type.
Means you are using the [dynamodb]class and not the [DynamoDB.DocumentClient].
The [unmarshall] will Convert a DynamoDB record into a JavaScript object.
Stated and backed by AWS. Ref. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/Converter.html#unmarshall-property
Nonetheless, I faced the exact same use case, as yours. Having one only attribute, TYPE SET (NS) in my case, and I had to manually do it. Next a snippet:
// Please notice the <setName>, which represents your set attribute name
ddbTransHandler.update(params).promise().then((value) =>{
value.Attributes[<setName>] = value.Attributes[<setName>].values;
return value; // or value.Attributes
});
Cheers,
Hamlet

Getting started with Step Functions and I can't get Choice to work correctly

I'm doctoring up my first step function, and as a newb into this I am struggling to make this work right. The documentation on AWS is helpful but lacks examples of what I am trying understand. I found a couple similar issues on the site here, but they didn't really answer my question either.
I have a test Step Function that works really simply. I have a small Lambda function that kicks out a single line JSON with a "Count" from a request in a DynamoDB:
def lambda_handler(event, context):
"""lambda_handler
Keyword arguments:
event -- dict -- A dict of parameters to be validated.
context --
Return:
json object with the hubID from DynamoDB of the new hub.
Exceptions:
None
"""
# Prep the Boto3 resources needed
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('TransitHubs')
# By default we assume there are no new hubs
newhub = { 'Count' : 0 }
# Query the DynamoDB to see if the name exists or not:
response = table.query(
IndexName='Status-index',
KeyConditionExpression=Key('Status').eq("NEW"),
Limit=1
)
if response['Count']:
newhub['Count'] = response['Count']
return json.dumps(newhub)
A normal output would be:
{ "Count": 1 }
And then I create this Step Function:
{
"StartAt": "Task",
"States": {
"Task": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-west-2:OMGSUPERSECRET:function:LaunchNode-get_new_hubs",
"TimeoutSeconds": 60,
"Next": "Choice"
},
"Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.Count",
"NumericEquals": 0,
"Next": "Failed"
},
{
"Variable": "$.Count",
"NumericEquals": 1,
"Next": "Succeed"
}
]
},
"Succeed": {
"Type": "Succeed"
},
"Failed": {
"Type": "Fail"
}
}
}
So I kick off the State Function and I get this output:
TaskStateExited
{
"name": "Task",
"output": {
"Count": 1
}
}
ChoiceStateEntered
{
"name": "Choice",
"input": {
"Count": 1
}
}
ExecutionFailed
{
"error": "States.Runtime",
"cause": "An error occurred while executing the state 'Choice' (entered at the event id #7). Invalid path '$.Count': The choice state's condition path references an invalid value."
}
So my question: I don't get why this is failing with that error message. Shouldn't Choice just pick up that value from the JSON? Isn't the default "$" input the "input" path?
I have figured out what the issue is, and here it is:
In my Python code, I was attempting to json.dumps(newhub) for the response thinking that what I needed was a string output representing the json formatted response. But it appears that is incorrect. When I alter the code to be simply "return newhub" and return the DICT, the step-functions process accepts that correctly. I'm assuming it parses the DICT to JSON for me? But the output difference is clearly obvious:
old Task output from above returning json.dumps(newhub):
{
"name": "Task",
"output": {
"Count": 1
}
}
new Task output from above returning newhub:
{
"Count": 1
}
And the Choice now correctly matches the Count variable in my output.
In case this is helpful for someone else. I also experienced the kind of error you did ( you had the below... just copy-pasting yours... )
{
"error": "States.Runtime",
"cause": "An error occurred while executing the state 'Choice' (entered at the event id #7). Invalid path '$.Count': The choice state's condition path references an invalid value."
}
But my problem turned out when I was missing the "Count" key all together.
But I did not want verbose payloads.
But per reading these docs I discovered I can also do...
"Choice": {
"Type": "Choice",
"Choices": [
{
"And": [
{
"Variable": "$.Count",
"IsPresent": true
},
{
"Variable": "$.Count",
"NumericEquals": 0,
}
],
"Next": "Failed"
},
{
"And": [
{
"Variable": "$.Count",
"IsPresent": true
},
{
"Variable": "$.Count",
"NumericEquals": 1,
}
],
"Next": "Succeed"
}
]
},
even I was facing the same issue. Give the ResultPath as InputPath and give the choice value as .value name
{
"Comment": "Step function to execute lengthy synchronous requests",
"StartAt": "StartProcessing",
"States": {
"StartProcessing": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:703569030910:function:shravanthDemo-shravanthGetItems-GHF7ZA1p6auQ",
"InputPath": "$.lambda",
"ResultPath": "$.lambda",
"Next": "VerifyProcessor"
},
"VerifyProcessor": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.lambda.cursor",
"IsNull": false,
"Next": "StartProcessing"
},
{
"Variable": "$.lambda.cursor",
"IsNull": true,
"Next": "EndOfUpdate"
}
]
},
"EndOfUpdate": {
"Type": "Pass",
"Result": "ProcessingComplete",
"End": true
}
}
}

Filter where attribute is in supplied array

Suppose I have these documents in a Things table:
{
"name": "Cali",
"state": "CA"
},
{
"name": "Vega",
"state": "NV",
},
{
"name": "Wash",
"state": "WA"
}
My UI is a state-picker where the user can select multiple states. I want to display the appropriate results. The SQL equivalent would be:
SELECT * FROM Things WHERE state IN ('CA', 'WA')
I have tried:
r.db('test').table('Things').filter(r.expr(['CA', 'WA']).contains(r('state')))
but that doesn't return anything and I don't understand why that wouldn't have worked.
This works for getting a single state:
r.db('test').table('Things').filter(r.row('state').eq('CA'))
r.db('test').table('Things').filter(r.expr(['CA', 'WA']).contains(r.row('state')))
seems to be working in some versions and returns
[
{
"id": "b20cdcab-35ab-464b-b10b-b2f644df73e6" ,
"name": "Cali" ,
"state": "CA"
} ,
{
"id": "506a4d1f-3752-409a-8a93-83385eb0a81b" ,
"name": "Wash" ,
"state": "WA"
}
]
Anyway, you can use a function instead of r.row:
r.db('test').table('Things').filter(function(row) {
return r.expr(['CA', 'WA']).contains(row('state'))
})

Resources