Pre-processing Redux state (location for business logic) - redux

I have created an application in react, which has the purpose to find flights and display them in a results window. With filter settings in the sidebar, you are able to filter these results. Currently I am converting the react app to Redux.
I have the following state in my store:
const defaultState = {
flightOffers,
filteredFlightOffers,
filters
}
Where flightOffers is an array of objects with flightresults:
flightOffers = [{
"inboundFlight": {
"departureDate": "2016-06-02",
"departureTime": "09:00",
"departureTimeSpan": "morning",
"arrivalDate": "2016-06-02",
"arrivalTime": "12:32",
"arrivalTimeSpan": "afternoon",
"marketingAirline": {
"companyShortName": "KL",
"name": KLM,
"imageurl": "images/logos/kl.png"
},
"flightNumber": 5131,
"departureAirport": {
"locationCode": "BCN",
"name": "Barcelona"
},
"arrivalAirport": {
"locationCode": "AMS",
"name": "Amsterdam"
}},
];
The state of filteredFlightOffers is the same, but a subset of the flightOffers state object.
And the filters state object has the following format:
filters = [{
"type": "airlines",
"checked": true,
"label": "Air France",
"count": 579
},
{
"type": "airlines",
"checked": true,
"label": "Brittish Airways",
"count": 554
},
{
"type": "airlines",
"checked": true,
"label": "CityJet",
"count": 576
}
];
The flightOffers state object is retrieved by an API call.
The filteredFlightOffers state object should be created based on all the checked / non-checked items in the filters state object, and should be recreated every time a filter is changed.
The filter stateobject will have a changed checked value every time an item is clicked, but also updated count items for all elements every time the new filteredFlightOffers state object is recreated.
Now I have the following questions:
My filters state object is derived from the flightOffers state object and should be created on the fly when the data from the flightOffers is retreived by the API call. Where in the redux pattern is the good place to implement this logic?
I have a dispatcher for my flightOffers state and for my settings state. When a filter setting is clicked, an action will go to the filter dispatcher and return the new filter state. But how can I calculate all the new filter counts based on the flightOffer state? e.g. Do I need to fire a FlightOfferCounter action and give the filter state as input parameter? If so, can I fire this call from my filter reducer? Or do I have to create a FlightOfferCounter reducer which listenes to the same action as the filter reducer? Problem then would be that these reducers cannot be executed in parallel since the flightOfferCounter is based on the checked values in the filter state.
I am reading things about redux thunk (for implementing business logic). Is that something I need here?
Hope my questions are a bit clear.

Related

How can we differentiate between a secondary and shared calendar in Google Calendar API response

I have a query with respect to the Calendar List API for Google Calendar:
https://developers.google.com/calendar/api/v3/reference/calendarList/list
We have a scenario where user1 has shared his calendar with user2 with Make Changes and Manage Sharing permission.
Now if we invoke the list calendar API on user2, we receive a response as below:
{
"kind": "calendar#calendarListEntry",
"etag": "\"<redacted>\"",
"id": "user1#gmail.com",
"summary": "user1#gmail.com",
"timeZone": "Asia/Kolkata",
"colorId": "4",
"backgroundColor": "#fa573c",
"foregroundColor": "#000000",
"accessRole": "owner",
"defaultReminders": [],
"conferenceProperties": {
"allowedConferenceSolutionTypes": [
"hangoutsMeet"
]
}
}
We can see that the access role above for the user1's calendar is owner and the primary value is absent(false).
Now if user2 has a secondary calendar we again see something similar in the listcalendar API response:
{
"kind": "calendar#calendarListEntry",
"etag": "\"<redacted>\"",
"id": "<redacted>#group.calendar.google.com",
"summary": "Secondary Calendar",
"timeZone": "Asia/Kolkata",
"colorId": "1",
"backgroundColor": "#ac725e",
"foregroundColor": "#000000",
"selected": true,
"accessRole": "owner",
"defaultReminders": [],
"conferenceProperties": {
"allowedConferenceSolutionTypes": [
"hangoutsMeet"
]
}
}
Access role above for the secondary calendar is owner and the primary value is absent(false).
So how can we differentiate between a secondary and shared calendar for user2? We require the same for some specific processing in our application.
As discussed in the comments there does not seem to be a clear way to differentiate the secondary calendars, except for the id and the appearance of the primary field.
Without having a database to control it, it does not seem to be possible to differentiate between a secondary calendar and a shared calendar, except for the calendar id.
You can use this template to explain your case to Google and ask to always have a field where you specify the calendar owner or another element that allows you to identify it.

How to update nested JSON object fields in mongo Db collection using ASP.NET Core

I have a JSON object(Form) in the mongo collection like this
{
"_id": "87124eb6-c9f7-49b9-8470-8c2b7fb07dc8",
"VisitName": "demo visit",
"Version": "string",
"FormStatus": "string",
"FormName": "demo form",
"IsDeleted": false,
"Pages": [
{
"PageName": "demo page",
"PageNo": 1,
"PageStatus": true,
"Field": [
{
"FieldName": "Gender",
"Value": "demo value",
"Comment": "demo comment",
}
]
}
]
}
I need to edit the Field (which is an array of objects ).
Currently, I am loading the full form and replacing the field data to be updated, Then replace the new form with the old one.
loading the whole form for each field update may affect performance, when loading large forms
Is there any way to update only the field details with fieldName(Unique) Instead of fetching the whole Form and editing?
Update: I missed the ASP.NET tag before answering this. I hope, this still gets you to the solution
You can use an update with arrayFilters. Here's a playground link to test it.
db.collection.update({
"FormName": "demo form"
},
{
$set: {
"Pages.$[pageItem].Field.$[fieldItem].Value": "new value"
}
},
{
arrayFilters: [
{
"pageItem.PageName": "demo page"
},
{
"fieldItem.FieldName": "Gender"
}
]
})
Basically, you tell MongoDB, update the nested field in the corresponding array element, that fulfils the filter specified by arrayFilters. So in this case, you update the path: "Pages.$[pageItem].Field.$[fieldItem].Value" to the new value but only in those nested documents, that:
reside in a page, whose name is demo page
and, in that page, there is a filed, whose name is Gender

Adobe Analytics 2.0 API endpoint to get report suite events, props, and evars

I'm having a hard time finding a way in the 2.0 API that I can get a list of Evars, Props and Events for a given report suite. The 1.4 version has the reportSuite.getEvents() endpoint and similar for Evars and Props.
Please let me know if there is a way to get the same data using the 2.0 API endpoints.
The API v2.0 github docs aren't terribly useful, but the Swagger UI is a bit more helpful, showing endpoints and parameters you can push to them, and you can interact with it (logging in with your oauth creds) and see requests/responses.
The two API endpoints in particular you want are metrics and dimensions. There are a number of options you can specify, but to just get a dump of them all, the full endpoint URL for those would be:
https://analytics.adobe.io/api/[client id]/[endpoint]?rsid=[report suite id]
Where:
[client id] - The client id for your company. This should be the same value as the legacy username:companyid (the companyid part) from v1.3/v1.4 API shared secret credentials, with the exception that it is suffixed with "0", e.g. if your old username:companyid was "crayonviolent:foocompany", the [client id] would be "foocompany0", because..reasons? I'm not sure what that's about, but it is what it is.
[endpoint] - Value should be "metrics" to get the events, and dimensions to get the props and eVars. So you will need to make 2 API endpoint requests.
[rsid] - The report suite id you want to get the list of events/props/eVars from.
Example:
https://analytics.adobe.io/api/foocompany0/metrics?rsid=fooglobal
One thing to note about the responses: they aren't like the v1.3 or v1.4 methods where you query for a list of only those specific things. It will return a json array of objects for every single event and dimension respectively, even the native ones, calculated metrics, classifications for a given dimension, etc. AFAIK there is no baked in way to filter the API query (that's in any documentation I can find, anyways..), so you will have to loop through the array and select the relevant ones yourself.
I don't know what language you are using, but here is a javascript example for what I basically do:
var i, l, v, data = { prop:[], evar: [], events:[] };
// dimensionsList - the JSON object returned from dimensions API call
// for each dimension in the list..
for (i=0,l=dimensionsList.length;i<l;i++) {
// The .id property shows the dimension id to eval
if ( dimensionsList[i].id ) {
// the ones we care about are e.g. "variables/prop1" or "variables/evar1"
// note that if you have classifications on a prop or eVar, there are entries
// that look like e.g. "variables/prop1.1" so regex is written to ignore those
v = (''+dimensionsList[i].id).match(/^variables\/(prop|evar)[0-9]+$/);
// if id matches what we're looking for, push it to our data.prop or data.evar array
v && v[1] && data[v[1]].push(dimensionsList[i]);
}
}
// metricsList - the JSON object returned from metrics API call
// basically same song and dance as above, but for events.
for (var i=0,l=metricsList.length;i<l;i++) {
if ( metricsList[i].id ) {
// events ids look like e.g. "metrics/event1"
var v = (''+metricsList[i].id).match(/^metrics\/event[0-9]+$/);
v && data.events.push(metricsList[i]);
}
}
And then the result data object will have data.prop,data.evar, and data.events, each an array of the respective props/evars/events.
Example object entry for an data.events[n]:
{
"id": "metrics/event1",
"title": "(e1) Some event",
"name": "(e1) Some event",
"type": "int",
"extraTitleInfo": "event1",
"category": "Conversion",
"support": ["oberon", "dataWarehouse"],
"allocation": true,
"precision": 0,
"calculated": false,
"segmentable": true,
"supportsDataGovernance": true,
"polarity": "positive"
}
Example object entry for an data.evar[n]:
{
"id": "variables/evar1",
"title": "(v1) Some eVar",
"name": "(v1) Some eVar",
"type": "string",
"category": "Conversion",
"support": ["oberon", "dataWarehouse"],
"pathable": false,
"extraTitleInfo": "evar1",
"segmentable": true,
"reportable": ["oberon"],
"supportsDataGovernance": true
}
Example object entry for a data.prop[n]:
{
"id": "variables/prop1",
"title": "(c1) Some prop",
"name": "(c1) Some prop",
"type": "string",
"category": "Content",
"support": ["oberon", "dataWarehouse"],
"pathable": true,
"extraTitleInfo": "prop1",
"segmentable": true,
"reportable": ["oberon"],
"supportsDataGovernance": true
}

Context size limit inside a node in Watson Conversation

My Watson Conversation bots typically have a node where I load some data into context. This usually contains all possible answers, strings, various other data.
So one of my first nodes in any bot looks like this:
{
"type": "standard",
"title": "Load Messages",
"output": {
"text": {
"values": [
""
],
"selection_policy": "sequential"
}
},
"context": {
// A whole bunch of data here
}
...
Is there a limit on how much data I can put there? Currently I have around 70 kilobytes, but potentially I can put a few megabytes there just for the convenience of running the logic inside Conversation. (Yes I am aware that this entire data will be sent back to the client, which is not very efficient)
There is no documented limit. You are more likely to hit network issues before Watson Assistant has any issues.
But storing your whole applications logic in the context object is considered an anti-pattern.
Your context object should only store what is required in Watson Assistant, and then if possible only for the related portion of the conversation.
For one time context values you can store them in the output object.
{
"context": {
},
"output": {
...
"one_time_var": "abc"
}
}
This will be discarded on your next call.
If you have a large volume of data that could be used at different times, then one pattern to use is a context request object.
For example:
"context": {
"request": "name,address,id"
}
Your next response from the application layer would send this:
"context": {
"name" : "Bob",
"address": "123 street",
"id": "1234"
}
You have your returning response update those variables, then clear the context variables again. If you have other context variables that need to stay, then store those in an object and erase just that object.

structure data for different queries

I am learning firebase and trying to find the best way to structure my data.
Use an example of a simple leave application. Employees can submit and view their leaves. Managers can approve leaves.
Option 1
"leaves": [
{
"employee": "pCIUfttSrXQ1dLPDwH7j9GExCkA2",
"date": "2017-03-01",
"status": "pendingApproval",
},
{
"employee": "YSJCAe4wZdYCplA3e0ejMqzQmEF3",
"date": "2017-01-01",
"status": "approved"
}]
With option 1, filtering will be required in both cases:
When employee lists his leave history (filter by "employee")
When manager lists all the pending leaves (filter by "status=pending")
Option 2
"leaves":
{
"pCIUfttSrXQ1dLPDwH7j9GExCkA2" : [
{
"date": "2017-03-01",
"status": "pendingApproval"
}
],
"YSJCAe4wZdYCplA3e0ejMqzQmEF3" : [
{
"date": "2017-01-01",
"status": "approved"
}
]
}
With option 2, no filtering is required when employee lists his leave history, but filtering is required (and I don't know how) for manager to list pending leaves.
What should be the right way to structure the data? And if it's option 2, how would we filter the pending leaves for all employees?
Use the second option;
For the manager to filter through the pending queries , use:
FIRDatabase.database().reference().child("leaves").queryOrdered(byChild: "status").queryEqual(toValue: "pending").observeSingleEvent(of: .value, with: {(Snapshot) in
print(Snapshot.value!)
// If you have multiple pending request you gotta loop through them
// using for loop, access them as separate entity and operate on them
})

Resources