How to fill in several dropdowns subsequently from JSON in Elm? - json

We are stuck with filling in form from JSON data and need help. The component is about selecting the ward in the district of the given city.
The data structure is a tree of Cities, Districts, and Wards with approximately following structure (everything is wrapped in GeoJSON):
// Cities: '/api/cities/berlin'
{
features: [
{
type: "Feature",
properties: {
slug: "berlin",
name: "Berlin",
districts: [
{name: "Neukölln", slug: "neukolln", ...}
]
},
geometries: {...}
}
]
}
// Districts: '/api/cities/berlin/districts/neukolln'
{
features: [
{
type: "Feature",
properties: {
slug: "neukolln",
name: "Neukölln",
wards: [
{name: "Britz", slug: "britz", ...}
]
},
geometries: {...}
}
]
}
// Wards: '/api/cities/berlin/districts/neukolln/wards'
{
features: [
{
type: "Feature",
properties: {
slug: "britz",
name: "Britz",
},
geometries: {...}
}
]
}
In the view, three are three dropdown boxes for selecting City, District and Ward, thus, when User select City, then District dropdown is filled from the properties.districts field of the JSON response.
Same is applied for the Districts dropdown: wards are filled in from the properties.wards
When the page is loaded it already has an injected JSON of all available Cities (and, accordingly their districts)
What strategy would you advise on:
1) how to get currently selected city and hit server for next administrative divisions? I.e. when a user selects District, get its slug and query server for the wards?
2) how to fill subsequent select from the response or injected JSON on the page? I.e. when user select another City, fill District select box with respective Districts?

Here's how I have done something similar in the past (in elm v0.17.0):
dropdown : List City -> Html Msg
dropdown cities =
div []
[ div []
[ span [] [ text "dropdown label name" ]
, selectOptions cities
]
]
selectOptions : List City -> Html Msg
selectOptions cities =
select [ on "change" ( Json.map (\city -> GetDistrictsMsg city) targetValue ) ]
(List.map setOption cities)
setOption : City -> Html Msg
setOption city =
option [ value city.name ]
[ text city.name ]
And you will repeat the same for districts to get wards.

Start-up
If selected city is known, before the start-up, you can pass in as a flag to Html.App.programWithFlags
The same thing you can do to the list of cities.
Please see the http example, it covers most of the stuff.
If you want to send xhr request on start-up, you might use a little neat trick for that:
init : String -> (Model, Cmd Msg)
init topic =
( Model topic "waiting.gif"
, getRandomGif topic
)
Where getRandomGif will execute the xhr request on start-up, assuming that you have gotten some data for that from passing them as flags or from user input.
On every FetchSucceed, you should send the next xhr to grab the data for the next step.
The flow
Please consider this flow chart, illustrating the flow of your multi step form. Dashed arrows point to steps, where you can restart the cycle, if you want to change the city/district at some point.
Caching layer is optional, Elm offers a variety of data structures for that.

Related

Intersept a FeatureCollection in MongoDB

I have a GeoJson filled with states from Austria and I want to do a query that gives me as output which certain states intercepts my polygon.
This is my query:
db.GeoAustria.find(
{
'features.geometry':{
$geoIntersects:{
$geometry:{
type: "Polygon",
coordinates: [
[
[
16.21685028076172,
48.007381433478855
],
[
16.24225616455078,
47.98716432210271
],
[
16.256675720214844,
48.00669234420252
],
[
16.21685028076172,
48.007381433478855
]
]
]
}
}
}
}
)
But it gives me all the features, including those that don't overlap the polygon...
Where is my mistake in this query?
Basic array match misunderstanding here. The input set is a single doc with 95 polygons in an array in a single FeatureCollection object. When you do a find() on such things, any individual geo that is an intersect will cause the entire doc to be returned as a match. This is exactly the same as:
> db.foo.insert({x:["A","B","C"]})
WriteResult({ "nInserted" : 1 })
> db.foo.find({x:"A"});
{ "_id" : ObjectId("5fb1845b08c09fb8dfe8d1c1"), "x" : [ "A", "B", "C" ] }
The whole doc is returned, not just element "A".
Let's assume that you might have more than one big doc in your collection. This pipeline yields the single target geometry for Baden (I tested it on your input set):
var Xcoords = [
[
[
16.21685028076172,
48.007381433478855
],
[
16.24225616455078,
47.98716432210271
],
[
16.256675720214844,
48.00669234420252
],
[
16.21685028076172,
48.007381433478855
]
]
];
var targ = {type: "Polygon", coordinates: Xcoords};
db.geo1.aggregate([
// First, eliminate any docs where the geometry array has zero intersects. In this
// context, features.geometry means "for each element of array features get the
// geometry field from the object there", almost like saying "features.?.geometry"
{$match: {"features.geometry": {$geoIntersects: {$geometry: targ}} }}
// Next, break up any passing docs of 95 geoms into 95 docs of 1 geom...
,{$unwind: "$features"}
// .. and run THE SAME $match as before to match just the one we are looking for.
// In this context, the array is gone and "features.geometry" means get JUST the
// object named geometry:
,{$match: {"features.geometry": {$geoIntersects: {$geometry: targ}} }}
]);
Beyond this, I might recommend breaking up that FeatureCollection into something that is both indexable (FeatureCollection is NOT indexable in MongoDB) and easier to deal with. For example, this little script run against your single-doc/many-polys design will convert it in 95 docs with extra info:
db.geo2.drop();
mainDoc = db.geo1.findOne(); // the one Austria doc
mainDoc['features'].forEach(function(oneFeature) {
var qq = {
country: "Austria",
crs: mainDoc['crs'],
properties: oneFeature['properties'],
geometry: oneFeature['geometry']
};
db.geo2.insert(qq);
});
db.geo2.aggregate([
{$match: {"geometry": {$geoIntersects: {$geometry: targ}} }}
]);
// yields same single doc output (Baden)
This allows ease of matching and filtering. For more on FeatureCollection vs. GeometryCollection see https://www.moschetti.org/rants/hurricane.html.

Best way to handle data list of REST web service with foreign key(one to many)

I am going to implement the REST base CRUD modal in my my app.I wan to display the list of product data with edit and delete link
Product
id, title, unit_id, product_type_id, currency_id,price
Q1: what should be json response look like?
There are two formats comes in my mind to place the data in Json as a response of REST Get call
[
{
id:1,
title:"T-Shirt",
unit_id:20,
unit_title: "abc"
product_type_id:30,
product_type_title:"xyz"
currency_id: 10,
currency_name: "USD"
min_price:20
},
{...}
]
and the another one is
[
{
id:1,
title:"T-Shirt",
unit: {
id: 20,
title: "abc"
},
product_type: {
id: 30,
title: "xyz"
},
currency_id: {
id:10,
name: "USD"
},
min_price:20
},
{...}
]
what is the better and standard way to handle the above scenario?
Furthermore, let suppose I have 10 more properties in product table which will never display on list page. but i needed it when user going to edit the specific item.
Q2: Should I the load all data once at the time of displaying product list and pass the data to edit component.
or
Load only the needed propeties of product table and pass the id to produt edit component and a new REST GET call with id to get the properties of product.
I am using React + Redux for my front end
Typically, you would create additional methods for API consumers to retrieve the values that populate the lists of currency, product_type and unit when editing in a UI.
I wouldn't return more data than necessary for an individual Product object.

How do I parse a JSON file to bind data to a d3 choropleth map

I'm trying to take data in from a JSON file and link it to my geoJSON file to create a choropleth map with the county colours bound to the "amount" value but also I would like a corresponding "comment" value to be bound to a div for when I mouseover that county.
My code at http://bl.ocks.org/eoiny/6244102 will work to generate a choropleth map when my counties.json data is in the form:
"Carlow":3,"Cavan":4,"Clare":5,"Cork":3,
But things get tricky when I try to use the following form:
{
"id":"Carlow",
"amount":11,
"comment":"The figures for Carlow show a something." },
I can't get my head around how join the "id": "Carlow" from counties.json and "id": "Carlow" path created from ireland.json, while at the same time to have access to the other values in counties.json i.e. "amount" and "comment".
Apologies for my inarticulate question but if anyone could point me to an example or reference I could look up that would be great.
I would preprocess the data when it's loaded to make lookup easier in your quantize function. Basically, replace this: data = json; with this:
data = json.reduce(function(result, county) {
result[county.id] = county;
return result;
}, {});
and then in your quantize function, you get at the amounts like this:
function quantize(d) {
return "q" + Math.min(8, ~~(data[d.id].amount * 9 / 12)) + "-9";
}
What the preprocessing does is turn this array (easily accessed by index):
[{id: 'xyz', ...}, {id: 'pdq', ...}, ...]
into this object with county keys (easily accessed by county id):
{'xyz': {id: 'xyz', ...}, 'pdq': {id: 'pdq', ...}, ...}
Here's the working gist: http://bl.ocks.org/rwaldin/6244803

Converting non-JSON text string into JSON object

I have this simple string repeated 1000's of times for worldwide weather widget I'm using in a large text file:
City Name = "Albuquerque, NM, US" Location = "NAM|US|NM|ALBUQUERQUE" Country = "United States"
Notice how it's formatted.
CITY NAME
LOCATION
COUNTRY
The string I'm actually passing into the Widget is the LOCATION string: "NAM|US|NM|ALBUQUERQUE"
So what I'm trying to do is convert the first example of the CITY NAME, LOCATION and COUNTRY into a JSON OBJECT.
Then, once I have that, I wish to allow the user to INPUT their current location or any location for that matter thereby passing the user input into this:
$('#digiclock').jdigiclock({
// Configuration goes here
clockImagesPath: "images/clock/",
weatherImagesPath: "images/weather/",
am_pm: false,
weatherLocationCode: "NAM|US|TN|CHATTANOOGA",
weatherMetric: "F",
weatherUpdate: "5",
proxyType: "php"
});
The weatherLocationCode is actually the LOCATION in the string above. So when the user inputs their CITY/STATE or just CITY, I want to parse the newly formed JSON object from the above text, capture the location, and stick-it up in the function.
This is what the end result should be:
// JSON OBJECT
{data : [
{
"City Name" : "Aachen, DE",
"Location" : "EUR|DE|GM011|AACHEN",
"Country" : "Germany"
}
]
}
Simple? Not so much.

Can you GET Rally API requirements, defects, and all tasks with one query

Currently I have to make multiple GETs to receive all the information which I need
User Story: FormattedID, _refObjectName, State, Owner._refObjectName
Tasks for each User Story: FormattedID, _refObjectName, State, Owner._refObjectName
Defect: FormattedID, _refObjectName, State, Owner._refObjectName
Tasks for each Defect: FormattedID, _refObjectName, State, Owner._refObjectName
For all of the User Stories I use:
https://rally1.rallydev.com/slm/webservice/1.26/hierarchicalrequirement.js?query=((Project.Name = "[projectName]") and (Iteration.Name = "[iterationName]"))&fetch=true&start=1&pagesize=100
For all of the Defects I use:
https://rally1.rallydev.com/slm/webservice/1.26/defects.js?query=((Project.Name = "[projectName]") and (Iteration.Name = "[iterationName]"))&fetch=true&start=1&pagesize=100
Within each of these, if they have any Tasks, they display as:
{
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "26",
"_ref": "https://rally1.rallydev.com/slm/webservice/1.26/task/9872916743.js",
"_refObjectName": "Update XYZ when ABC",
"_type": "Task"
}
This doesn't have all the information I need, so I hit each of the Tasks' _ref URLs to get the full task information.
This adds up to sometimes 80+ AJAX calls per page load.
Is there a better query which would provide the extra Task information up front?
The fetch parameter can be tricky with queries. If you provide fetch=true you will get all of the fields that exist on the queried type (Story,Defect). If the field is also a domain object (like a tasks or a defect) you will only get the thin ref object like this
{
"_ref": "/task/1234.js"
}
If you want to get fields populated on the sub-objects you will need to specify the fields you want shown in the fetch param fetch=Name,FormattedID,Tasks. This would return an object like the one below:
{
"HierarchicalRequirement" : {
"Name" : "StoryName",
"FormattedID" : "S1234",
"Tasks" : [
{
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "26",
"_ref": "https://rally1.rallydev.com/slm/webservice/1.26/task/9872916743.js",
"_refObjectName": "Update XYZ when ABC",
"_type": "Task",
"FormattedID" : "T1",
"Name" : "Update XYZ when ABC"
}
]
}
}
Let me know if that helped