n.getFullYear is not a function error when passing an array to google-charts Calendar - google-visualization

I am trying to render a Calendar Chart, but I face a "n.getFullYear is not a function" error and I can't find what's going wrong.
This is my client part:
google.charts.load("current", {packages:["calendar"], callback:function(){
getIt(where.getAttribute('data-chart-uri'), function(status,response){
var data = google.visualization.arrayToDataTable(response,false);
var options = Object.assign({title: where.getAttribute('data-chart-title')||''}, response.options);
google.charts.setOnLoadCallback(function(){
var chart = new google.visualization.Calendar(where);
chart.draw(data, options);
});
});
}});
Note: where is the targeted DOM Element and getIt is a fetch like function.
And this is what is sent by the web service (response):
[
[
{
"label": "Date",
"type": "date"
},
{
"label": "Number of individuals",
"type": "number"
}
],
[
"2021-03-11",
1
],
[
"2021-03-24",
2
],
[
"2021-03-25",
1
]
]
I thought it was the same case like n.getFullYear is not a function error when passing an array with react-google-charts, but not...
For debug purpose,I have added this routine upfront and it works... So the issue it related to the fact that the vizualisation API seems not to consider the 'date' type information. Weird ?
for(var i=1;i<response.length;i++){
response[i][0]=new Date(response[i][0].split('-'));
}

My mistake. As per the Google documentation, dates and times must be parsed when using arrayToDataTable().
Using the Date constructor is useful when manually constructing your
DataTable using the addColumn(), addRow(), and addRows() methods, as
well as the arrayToDataTable() method. However, if using JSON to
specify data, the string representation needs to be used.
https://developers.google.com/chart/interactive/docs/datesandtimes?hl=en

Related

How do I extract a string of numbers from random text in Power Automate?

I am setting up a flow to organize and save emails as PDF in a Dropbox folder. The first email that will arrive includes a 10 digit identification number which I extract along with an address. My flow creates a folder in Dropbox named in this format: 2023568684 : 123 Main St. Over a few weeks, additional emails arrive that I need to put into that folder. The subject always has a 10 digit number in it. I was building around each email and using functions like split, first, last, etc. to isolate the 10 digits ID. The problem is that there is no consistency in the subjects or bodies of the messages to be able to easily find the ID with that method. I ended up starting to build around each email format individually but there are way too many, not to mention the possibility of new senders or format changes.
My idea is to use List files in folder when a new message arrives which will create an array that I can filter to find the folder ID the message needs to be saved to. I know there is a limitation on this because of the 20 file limit but that is a different topic and question.
For now, how do I find a random 10 digit number in a randomly formatted email subject line so I can use it with the filter function?
For this requirement, you really need regex and at present, PowerAutomate doesn't support the use of regex expressions but the good news is that it looks like it's coming ...
https://powerusers.microsoft.com/t5/Power-Automate-Ideas/Support-for-regex-either-in-conditions-or-as-an-action-with/idi-p/24768
There is a connector but it looks like it's not free ...
https://plumsail.com/actions/request-free-license
To get around it for now, my suggestion would be to create a function app in Azure and let it do the work. This may not be your cup of tea but it will work.
I created a .NET (C#) function with the following code (straight in the portal) ...
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string strToSearch = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String((string)data?.Text));
string regularExpression = data?.Pattern;
var matches = System.Text.RegularExpressions.Regex.Matches(strToSearch, regularExpression);
var responseString = JsonConvert.SerializeObject(matches, new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
return new ContentResult()
{
ContentType = "application/json",
Content = responseString
};
}
Then in PowerAutomate, call the HTTP action passing in a base64 encoded string of the content you want to search ...
The is the expression in the JSON ... base64(variables('String to Search')) ... and this is the json you need to pass in ...
{
"Text": "#{base64(variables('String to Search'))}",
"Pattern": "[0-9]{10}"
}
This is an example of the response ...
[
{
"Groups": {},
"Success": true,
"Name": "0",
"Captures": [],
"Index": 33,
"Length": 10,
"Value": "2023568684"
},
{
"Groups": {},
"Success": true,
"Name": "0",
"Captures": [],
"Index": 98,
"Length": 10,
"Value": "8384468684"
}
]
Next, add a Parse JSON action and use this schema ...
{
"type": "array",
"items": {
"type": "object",
"properties": {
"Groups": {
"type": "object",
"properties": {}
},
"Success": {
"type": "boolean"
},
"Name": {
"type": "string"
},
"Captures": {
"type": "array"
},
"Index": {
"type": "integer"
},
"Length": {
"type": "integer"
},
"Value": {
"type": "string"
}
},
"required": [
"Groups",
"Success",
"Name",
"Captures",
"Index",
"Length",
"Value"
]
}
}
Finally, extract the first value that you find which matches the regex pattern. It returns multiple results if found so if you need to, you can do something with those.
This is the expression ... #{first(body('Parse_JSON'))?['value']}
From this string ...
We're going to search for string 2023568684 within this text and we're also going to try and find 8384468684, this should work.
... this is the result ...
Don't have a Premium PowerAutomate licence so can't use the HTTP action?
You can do this exact same thing using the LogicApps service in Azure. It's the same engine with some slight differences re: connectors and behaviour.
Instead of the HTTP, use the Azure Functions action.
In relation to your action to fire when an email is received, in LogicApps, it will poll every x seconds/minutes/hours/etc. rather than fire on event. I'm not 100% sure which email connector you're using but it should exist.
Dropbox connectors exist, that's no problem.
You can export your PowerAutomate flow into a LogicApps format so you don't have to start from scratch.
https://learn.microsoft.com/en-us/azure/logic-apps/export-from-microsoft-flow-logic-app-template
If you're concerned about cost, don't be. Just make sure you use the consumption plan. Costs only really rack up for these services when the apps run for minutes at a time on a regular basis. Just keep an eye on it for your own mental health.
TO get the function URL, you can find it in the function itself. You have to be in the function ...

Multiple Bodies in a POST operation

I have the following question, I want to make a request for a POST, I have 13 different Body's in environment variables, how can I put all 13 at the same time in Postman to execute? Is there any way?
This is my code:
Some Bodies:
{ "et": "conta", "na": "List", "T": "list", "OPT": [ "TL-1", "TL-2" ], "DBY": "names user", "iM": false }
{ "et": "conta", "na": "Integer", "T": "integer", "DBY": "namesUser", "iM": false }
{ "et": "conta", "na": "MultiSelectList", "T": "multiSelect", "opt": [ "L1", "L2", "L3" ], "DBY": "names user", "iM": true }
What I am doing but I get error 400:
[
{{List}},
{{Integer}}
]
So I would like to know if there is any way to be able to execute the 13 Body's placing them all at the same time
Json arrays (https://restfulapi.net/json-array/) should be used for this
[
{
"et": "conta",
"na": "List",
"T": "list",
"OPT": [
"TL-1",
"TL-2"
],
"DBY": "names user",
"iM": false
},
{
(second array)
},
.
.
.
{
(thirteenth array)
}
]
Good to know: you can use this tool to verify your json; https://jsonlint.com/
Whether or not this results in a status 400 error depends on the implementation of the web api's post method (and you mentioned this happens). In .NET, the received json should be converted to a List<T> instead of type T.
If you posting to your own api, try changing it according to: https://forums.asp.net/t/2098779.aspx?How+to+change+WEB+API+to+accept+a+JSON+Array+for+multiple+entries+
If it's an external api, sending an array won't work. You have to send the data sequentially, but there are some tips and tricks preventing you from doing this manually in Postman: How to Send multiple request concurrently/Sequentially in postman with different set of values for each request?

Postman Printing specific information from Response

I'm using Postman's console to display the response of the API Call with console.log, I'm using the runner since I have a lot of iterations. However, a lot of information from the API response are giving me trouble, so I would like to do is to print with console.log specific information of the responseBody.
As test with Postman, I'm using the following:
var body = JSON.parse(responseBody);
console.log(JSON.stringify(body.data));
The response is:
[{"device":"1BED7","time":1505320342,"data":"05b006bcac00000000000000","snr":"21.00","linkQuality":"AVERAGE","seqNumber":555,"rinfos":[{"tap":"A2A","delay":1.4,"lat":"53.0","lng":"2.0"},{"tap":"A2B","delay":0.5,"lat":"53.0","lng":"2.0"}]},{"device":"1CED7","time":1505277142,"data":"05b006bcac00000000000000","snr":"20.68","linkQuality":"AVERAGE","seqNumber":554,"rinfos":[{"tap":"A2C","delay":1.3,"lat":"53.0","lng":"2.0"},{"tap":"232","delay":1.9,"lat":"53.0","lng":"2.0"}]},{"device":"152C3","time":1505233937,"data":"05b006bcac00000000000000","snr":"19.14","linkQuality":"AVERAGE","seqNumber":553,"rinfos":[{"tap":"215","delay":2.4,"lat":"53.0","lng":"2.0"}]},{"device":"1BF81","time":1505190735,"data":"05b006bcac00000000000000","snr":"21.67","linkQuality":"AVERAGE","seqNumber":552,"rinfos":[{"tap":"1CC","delay":2.0,"lat":"53.0","lng":"2.0"},{"tap":"25A","delay":1.6,"lat":"53.0","lng":"2.0"}]},
What I would want to print with console.log would be only the values of device, time and data:
{"1BED7",1505320342,"05b006bcac00000000000000"},{"1CED7",1505277142,"05b006bcac00000000000000"},{"152C3",1505233937,"05b006bcac00000000000000"},
and so on...
My programming skills are very limited so sorry if the answer is so obvious, I have tested a lot of things but I'm still stuck.
Thanks a lot if you can help
I think your your response is array of objects.It is already a json object.So firstly what you are doing wrong is you don't need to parse it.You can directly use it.Check this below code snippet at the end of the answer.I think this satisfies your need.I used the forEach function to iterate through the the response array and push value that you need into the empty array.This result array contains object in following format.you can access each property of each object of this array by javascript . operator.I think that is quite obvious to you.
[
{
"device": "1BED7",
"time": 1505320342,
"data": "05b006bcac00000000000000"
},
{
"device": "1CED7",
"time": 1505277142,
"data": "05b006bcac00000000000000"
},
{
"device": "152C3",
"time": 1505233937,
"data": "05b006bcac00000000000000"
},
{
"device": "1BF81",
"time": 1505190735,
"data": "05b006bcac00000000000000"
}
]
var responseBody=[{"device":"1BED7","time":1505320342,"data":"05b006bcac00000000000000","snr":"21.00","linkQuality":"AVERAGE","seqNumber":555,"rinfos":[{"tap":"A2A","delay":1.4,"lat":"53.0","lng":"2.0"},{"tap":"A2B","delay":0.5,"lat":"53.0","lng":"2.0"}]},
{"device":"1CED7","time":1505277142,"data":"05b006bcac00000000000000","snr":"20.68","linkQuality":"AVERAGE","seqNumber":554,"rinfos":[{"tap":"A2C","delay":1.3,"lat":"53.0","lng":"2.0"},{"tap":"232","delay":1.9,"lat":"53.0","lng":"2.0"}]},{"device":"152C3","time":1505233937,"data":"05b006bcac00000000000000","snr":"19.14","linkQuality":"AVERAGE","seqNumber":553,"rinfos":[{"tap":"215","delay":2.4,"lat":"53.0","lng":"2.0"}]},{"device":"1BF81","time":1505190735,"data":"05b006bcac00000000000000","snr":"21.67","linkQuality":"AVERAGE","seqNumber":552,"rinfos":[{"tap":"1CC","delay":2.0,"lat":"53.0","lng":"2.0"},{"tap":"25A","delay":1.6,"lat":"53.0","lng":"2.0"}]}];
var array=[];
responseBody.forEach(function (obj) {
array.push({device:obj.device,time:obj.time,data:obj.data})
})
console.log(array);
let results = _.map(JSON.parse(responseBody),
(sensor) => { return [sensor.device, sensor.time, sensor.data]});
// results contains an array like
// [[deviceId1, time1, data1], [deviceId1, time1, data1], ...]
console.log(results);

Utterances to test lambda function not working (but lambda function itself executes)

I have a lambda function that executes successfully with an intent called GetEvent that returns a specific string. I've created one utterance for this intent for testing purposes (one that is simple and doesn't require any of the optional slots for invoking the skill), but when using the service simulator to test the lambda function with this utterance for GetEvent I'm met with a lambda response that says "The response is invalid". Here is what the interaction model looks like:
#Intent Schema
{
"intents": [
{
"intent": "GetVessel",
"slots": [
{
"name": "boat",
"type": "LIST_OF_VESSELS"
},
{
"name": "location",
"type": "LIST_OF_LOCATIONS"
},
{
"name": "date",
"type": "AMAZON.DATE"
},
{
"name": "event",
"type": "LIST_OF_EVENTS"
}
]
},
{
"intent": "GetLocation",
"slots": [
{
"name": "event",
"type": "LIST_OF_EVENTS"
},
{
"name": "date",
"type": "AMAZON.DATE"
},
{
"name": "boat",
"type": "LIST_OF_VESSELS"
},
{
"name": "location",
"type": "LIST_OF_LOCATIONS"
}
]
},
{
"intent": "GetEvent",
"slots": [
{
"name": "event",
"type": "LIST_OF_EVENTS"
},
{
"name": "location",
"type": "LIST_OF_LOCATIONS"
}
]
}
]
}
With the appropriate custom skill type syntax and,
#First test Utterances
GetVessel what are the properties of {boat}
GetLocation where did {event} occur
GetEvent get me my query
When giving Alexa the utterance get me my query the lambda response should output the string as it did in the execution. I'm not sure why this isn't the case; this is my first project with the Alexa Skills Kit, so I am pretty new. Is there something I'm not understanding with how the lambda function, the intent schema and the utterances are all pieced together?
UPDATE: Thanks to some help from AWSSupport, I've narrowed the issue down to the area in the json request where new session is flagged as true. For the utterance to work this must be set to false (this works when inputting the json request manually, and this is also the case during the lambda execution). Why is this the case? Does Alexa really care about whether or not it is a new session during invocation? I've cross-posted this to the Amazon Developer Forums as well a couple of days ago, but have yet to get a response from someone.
This may or may not have changed -- the last time I used the service simulator (about two weeks ago at the time of writing) it had a pretty severe bug which would lead to requests being mapped to your first / wrong intent, regardless of actual simulated speech input.
So even if you typed in something random like wafaaefgae it simply tries to map that to the first intent you have defined, providing no slots to said intent which may lead to unexpected results.
Your issue could very well be related to this, triggering the same unexpected / buggy behavior because you aren't using any slots in your sample utterance
Before spending more time debugging this, I'd recommend trying the Intent using an actual echo or alternatively https://echosim.io/ -- interaction via actual speech works as expected, unlike the 'simulator'

Fetching With Distinct/Unique Values

I have a Cloudant database with objects that use the following format:
{
"_id": "0ea1ac7d5ef28860abc7030444515c4c",
"_rev": "1-362058dda0b8680a818b38e9c68c5389",
"text": "text-data",
"time-data": "1452988105",
"time-text": "3:48 PM - 16 Jan 2016",
"link": "http://url/to/website"
}
I want to fetch objects where the text attribute is distinct. There will be objects with duplicate text and I want Cloudant to handle removing them from a query.
How do I go about creating a MapReduce view that will do this for me? I'm completely new to MapReduce and I'm having difficulty understanding the relationship between the map and reduce functions. I tried tinkering with the built-in COUNT function and writing my own view, but they've failed catastrophically, haha.
Anyways, would it be easier to just delete the duplicates? If so, how do I do that?
While I'm trying to study this and find ELI5s, would anyone help me out? Thanks in advance! I appreciate it.
I'm not sure a MapReduce view is what you are looking for. A MapReduce view will essentially allow you to get the text and the number of docs with that same text, but you really won't be able to get the rest of the fields in the doc (because MapReduce has no idea which doc to return when multiple docs match the text). Here is a sample MapReduce view:
{
"_id": "_design/textObjects",
"views": {
"by_text": {
"map": "function (doc) { if (doc.text) { emit(doc.text, 1); }}",
"reduce": "_count"
}
},
"language": "javascript"
}
What this is doing:
The Map part of the Map Reduce takes each doc and maps it into a doc that looks like this:
{"key":"text-data", "value":1}
So, if you had 7 docs, 2 where text="text-data" and 5 where text="other-text-data" the data would look like this:
{"key":"text-data", "value":1}
{"key":"text-data", "value":1}
{"key":"other-text-data", "value":1}
{"key":"other-text-data", "value":1}
{"key":"other-text-data", "value":1}
{"key":"other-text-data", "value":1}
{"key":"other-text-data", "value":1}
The reduce part of the MapReduce ("reduce": "_count") groups the docs above by the key and returns the count:
{"key":"text-data","value":2},
{"key":"other-text-data","value":5}
You can query this view on your Cloudant instance:
https://<yourcloudantinstance>/<databasename>
/_design/textObjects
/_view/by_text?group=true
This will result in something similar to the following:
{"rows":[
{"key":"text-data","value":2},
{"key":"other-text-data","value":5}
]}
If this is not what you are looking for, but rather you are just looking to keep the latest info for a specific text value then you can simply find an existing document that matches that text and update it with new values:
Add an index on text:
{
"index": {
"fields": [
"text"
]
},
"type": "json"
}
Whenever you add a new document find the document with that same exact text:
{
"selector": {
"text": "text-value"
},
"fields": [
"_id",
"text"
]
}
If it exists update it. If not then insert a new document.
Finally, if you want to keep multiple docs with the same text value, but just want to be able to query the latest you could do something like this:
Add a property called latest or similar to your docs.
Add an index on text and latest:
{
"index": {
"fields": [
"text",
"latest"
]
},
"type": "json"
}
Whenever you add a new document find the document with that same exact text where latest == true:
{
"selector": {
"text": "text-value",
"latest" : true
},
"fields": [
"_id",
"text",
"latest"
]
}
Set latest = false on the existing document (if one exists)
Insert the new document with latest = true
This query will find the latest doc for all text values:
{
"selector": {
"text": {"$gt":null}
"latest" : true
},
"fields": [
"_id",
"text",
"latest"
]
}