React select with nested data - javascript

I am trying to make a nested select optgroup and tried the following,
const data = [
{
sectorId: 5,
sectorName: "Sector One",
departments: [
{
deptName: "Production",
jobtitles: [
{
JobTitleID: 167,
DepartmentID: 51,
JobName: "Production Manager",
Deleted: false,
SortOrder: 5
},
{
JobTitleID: 178,
DepartmentID: 51,
JobName: "Production Supervisor",
Deleted: false,
SortOrder: 3
},
{
JobTitleID: 449,
DepartmentID: 51,
JobName: "Senior Wall Panel Designer",
Deleted: false,
SortOrder: 15
}
]
},
{
deptName: "Design/Engineering",
jobtitles: [
{
JobTitleID: 294,
DepartmentID: 52,
JobName: "Senior Truss Designer",
Deleted: false,
SortOrder: 5
}
]
}
]
},
{
sectorId: 24,
sectorName: "Sector Two",
departments: [
{
deptName: "Consulting",
jobtitles: [
{
JobTitleID: 191,
DepartmentID: 92,
JobName: "Saw Shop Supervisor",
Deleted: false,
SortOrder: 1
},
{
JobTitleID: 474,
DepartmentID: 92,
JobName: "Senior Truss Designer - Part Time",
Deleted: false,
SortOrder: 11
}
]
},
{
deptName: "Administration",
jobtitles: [
{
JobTitleID: 461,
DepartmentID: 114,
JobName: "Sawyer",
Deleted: false,
SortOrder: 7
},
{
JobTitleID: 278,
DepartmentID: 114,
JobName: "Service Manager",
Deleted: false,
SortOrder: 2
}
]
}
]
}
];
const App = () => {
return (
<select>
{data.map((levelOne, i) => (
<optgroup label={levelOne.sectorName} key={i}>
{levelOne.departments.map((levelTwo, j) => (
<optgroup label={levelTwo.deptName} key={j}>
{levelTwo.jobtitles.map((job, l) => (
<>
<option key={job.JobTitleID} value={job.JobTitleID}>
{job.JobName}
</option>
</>
))}
</optgroup>
))}
</optgroup>
))}
</select>
);
};
render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"> </div>
Sorry the above snippet has errors and you can also look at the working example here
This doesn't provide nested group of data and it stops with single level itself.
Current output:
Sector One
Sector Two
Expected output:
Sector One
Production
-> Production Manager
-> Production Supervisor
-> Senior Wall Panel Designer
Design/Engineering
-> Senior Truss Designer
Sector Two
Consulting
-> Saw Shop Supervisor
-> Senior Truss Designer - Part Time
Administration
-> Sawyer
-> Service Manager
Here only the jobtitles will be option, so as per the above data, the list that has -> will alone be option and others will be label.
So only using optgroup I have tried the above code, But don't know what mistake I am doing which results in not populating the data as per the expected result.
Kindly please help me to solve the above issue and make the above example work as like the expected output.
Adding any other react based library to achieve this also welcomed.

optgroup may not be nested, so only the sectorName is displayed;
you can try to use the react-selector library. Here is an example react-select nested groups that I've found with nested levels.

Related

Storing an Array of String to a Key in MongoDB

I'm building a post request which will contain various info on each role. E.g in this trial, 'Data Analyst'.
In this position I want to have quite a few sources of data, including things like salary, education and skills.
However, I'm using recharts to visualise it, which means although I need a key, e.g Masters's degree, I also need a num value associated, such as below:
const educationData = [
{
degree: 'Masters',
A: 120,
},
{
degree: 'Bachelor',
A: 98,
},
{
degree: 'PhD',
A: 86,
},
{
degree: 'Industry',
A: 99,
},
{
degree: 'Associate',
A: 85,
}
];
I would like to store this inside my schema created:
const RolesPositionSchema = new mongoose.Schema(
{
title:{type:String, required: true, unique: true},
desc:{type:String, required: true},
skills:{type:Array, required: true},
salary:{type:Array},
education: {type: Array},
popularity: {type: Number},
reccomendations: {type: Array},
},
);
Within this I would like to store the 'educationData' into the DB. Happy to input it in manually for now. I just want to know how to structure my schema/data in the postman request.
E.g Input in "education", stored with "Masters:120", "Bachelor:98", "PhD:86" etc -> within the post request:
{
"title" : "Data Analyst",
"desc": "Using both internal and external data sources you will develop insights to identify trends and opportunities whilst highlighting areas or improvement to optimise member interaction. This is a proactive role where you will own how we interpret data, allowing you to provide valuable insight into the development and implementation of product, customer and channel strategies for our sales, retention, and acquisition goals.",
"skills":["SQL" ,"Excel", "Tableau", "PowerBI", "Python", "Azure", "AWS", "ETL"],
"education": ["INPUT AN ARRAY OF EDUCATION AND THEIR VALUES HERE!]
}
Thankyou!
You could modify first your payload into the format of schema.
Payload
const educationData = [
{
degree: 'Masters',
A: 120,
},
{
degree: 'Bachelor',
A: 98,
},
{
degree: 'PhD',
A: 86,
},
{
degree: 'Industry',
A: 99,
},
{
degree: 'Associate',
A: 85,
}
];
Process
const newEducations = educationData.map(education => {
return `${education.degree}:${education.A}`;
});
const storeRole = new RolesPositionSchema({
title: 'Data Analyst',
desc: 'Using both internal and external data sources you will develop insights to identify trends and opportunities whilst highlighting areas or improvement to optimise member interaction. This is a proactive role where you will own how we interpret data, allowing you to provide valuable insight into the development and implementation of product, customer and channel strategies for our sales, retention, and acquisition goals.',
skills: [{Skill value}],
salary: [{Salary value}],
education: newEducations,
popularity: 0,
reccomendations: [{Recommendation value}]
});
After this saved.
Does it that you want?

JavaScript display fetched object in html table

I have a fetch function that looks like this
let url = 'someurl.com';
var dataObject_ = [];
fetch(url)
.then((res) => res.json())
.then(output => {
var huj = output;
// console.log(huj);
dataObject_.push.apply(dataObject, huj);
}
);
console.log(huj) outputs -> Array(10)
0: {wine_country: "France", wine_name: "Lafite Rothschild", wine_region: "Bordeaux Premier Cru - left bank", wine_year: 2016}
1: {wine_country: "France", wine_name: "Lafite Rothschild", wine_region: "Bordeaux Premier Cru - left bank", wine_year: 2000}
etc...
and I have table that looks like that
var hotSettings = {
data: dataObject_,
columns: [
{
data: 'wine_name',
type: 'text'
},
{
data: 'wine_year',
type: 'numeric'
},
{
data: 'wine_region',
type: 'text'
},
{
data: 'wine_country',
type: 'text'
},
],
stretchH: 'all',
width: 805,
autoWrapRow: true,
height: 487,
maxRows: 22,
manualRowResize: true,
manualColumnResize: true,
rowHeaders: true,
colHeaders: [
'Wine',
'Year',
'Region',
'Country'
],
manualRowMove: true,
manualColumnMove: true,
contextMenu: true,
filters: true,
dropdownMenu: true
};
My goal is to use dataObject_ to display it in the table. When I create a variable and just copypaste json from API it works fine, but when I get data from API call and push it to the array it doesnt output it somehow. I tried different ways of doing it, nothing works. The JSON itself looks like this
{
"wine_country": "France",
"wine_name": "Petrus",
"wine_region": "Bordeaux Pomerols - right bank",
"wine_year": 1990
},
{
"wine_country": "France",
"wine_name": "Petrus",
"wine_region": "Bordeaux Pomerols - right bank",
"wine_year": 1989
}
I am sorry, i am a completely beginner in JavaScript / front-end and if this looks ridiculous
Basically, once you define variable g, that gets stored in global memory with the value that h has. It won't update once h changes because it has no idea what h is. It was only concerned about the value it was holding while initialization.

How do I make my checkbox filter inclusive, rather than exclusive

At the moment, this code is doing half of what I want - it's filtering the data. Unfortunately, it's doing the opposite of what I am attempting to do.
For example, when you click the checkbox, it'll add a new filter to the filter array, and only display the cards that contain everything within that filter array. So if you were to click the 'Green' checkbox, only cards with 'G' in their colors array will be displayed. If you click 'Black' afterwards, only cards with 'G' AND 'B' in their colors array will show
The behavior I am looking for is the opposite. I'd like to start the page with:
filterOptions: [
{checked: true, value: "W", name: "White"},
{checked: true, value: "U", name: "Blue"},
{checked: true, value: "B", name: "Black"},
{checked: true, value: "R", name: "Red"},
{checked: true, value: "G", name: "Green"},
{checked: true, value: "KLD", name: "Kaladesh"},
]
And I'd like this behavior to show all of the cards. Once the checkbox is clicked and 'checked' becomes false, it will filter out the cards that contain that data.
I believe the function that needs to be modified is:
if (this.selectedFilters.length > 0) {
filteredDataByFilters = Object.values(this.filteredData).filter(obj =>
this.selectedFilters.every(val => obj.colors.indexOf(val) >= 0));
this.filteredData = filteredDataByFilters;
}
Below is a snippet that shows what I am currently working with.
const cards = [
{
"Sluiceway Scorpion": {
"colorIdentity": [
"B",
"G"
],
"colors": [
"B",
"G"
],
"convertedManaCost": 4.0,
"isReserved": false,
"layout": "normal",
"legalities": {
"1v1": "Legal",
"commander": "Legal",
"duel": "Legal",
"legacy": "Legal",
"modern": "Legal",
"pauper": "Legal",
"penny": "Legal",
"vintage": "Legal"
},
"manaCost": "{2}{B}{G}",
"name": "Sluiceway Scorpion",
"power": "2",
"printings": [
"RTR"
],
"rulings": [
{
"date": "2013-04-15",
"text": "Exiling the creature card with scavenge is part of the cost of activating the scavenge ability. Once the ability is activated and the cost is paid, it’s too late to stop the ability from being activated by trying to remove the creature card from the graveyard."
}
],
"subtypes": [
"Scorpion"
],
"supertypes": [],
"text": "Deathtouch (Any amount of damage this deals to a creature is enough to destroy it.)\nScavenge {1}{B}{G} ({1}{B}{G}, Exile this card from your graveyard: Put a number of +1/+1 counters equal to this card's power on target creature. Scavenge only as a sorcery.)",
"toughness": "2",
"type": "Creature — Scorpion",
"types": [
"Creature"
],
"uuid": "7b6dbadf-a6f7-4876-9c3f-44e4a33b2bee"
},
"Tezzeret the Seeker": {
"colorIdentity": [
"U"
],
"colors": [
"U"
],
"convertedManaCost": 5.0,
"isReserved": false,
"layout": "normal",
"legalities": {
"1v1": "Legal",
"commander": "Legal",
"duel": "Legal",
"legacy": "Legal",
"modern": "Legal",
"vintage": "Legal"
},
"loyalty": "4",
"manaCost": "{3}{U}{U}",
"name": "Tezzeret the Seeker",
"printings": [
"ALA",
"DDF",
"MM2"
],
"rulings": [{
"date": "2008-10-01",
"text": "The first ability can target zero, one, or two artifacts. You may activate it with no targets just to put a loyalty counter on Tezzeret."
},
{
"date": "2008-10-01",
"text": "For the second ability, you choose the value of X when you activate it. You don’t look through your library until the ability resolves. (In other words, you can’t look through your library, decide what artifact card you want, and then determine what X is.) You can’t choose an X that’s greater than the number of loyalty counters on Tezzeret."
},
{
"date": "2008-10-01",
"text": "The third ability affects all artifacts you control, including artifacts that are already creatures."
},
{
"date": "2008-10-01",
"text": "The third ability causes artifacts you control to become creatures in addition to their other card types."
},
{
"date": "2009-10-01",
"text": "A noncreature permanent that turns into a creature is subject to the “summoning sickness” rule: It can only attack, and its {T} abilities can only be activated, if its controller has continuously controlled that permanent since the beginning of their most recent turn."
},
{
"date": "2009-10-01",
"text": "The effect from the ability overwrites other effects that set power and/or toughness if and only if those effects existed before the ability resolved. It will not overwrite effects that modify power or toughness (whether from a static ability, counters, or a resolved spell or ability), nor will it overwrite effects that set power and toughness which come into existence after the ability resolves. Effects that switch the creature’s power and toughness are always applied after any other power or toughness changing effects, including this one, regardless of the order in which they are created."
}
],
"starter": true,
"subtypes": [
"Tezzeret"
],
"supertypes": [
"Legendary"
],
"text": "+1: Untap up to two target artifacts.\n−X: Search your library for an artifact card with converted mana cost X or less and put it onto the battlefield. Then shuffle your library.\n−5: Artifacts you control become artifact creatures with base power and toughness 5/5 until end of turn.",
"type": "Legendary Planeswalker — Tezzeret",
"types": [
"Planeswalker"
],
"uuid": "e5250db5-6dfc-46ef-a6f7-198a3e0594cc"
},
}
];
new Vue({
el: '#app',
computed: {
selectedFilters: function() {
let filters = [];
let checkedFilters = this.filterOptions.filter(obj => obj.checked);
checkedFilters.forEach(element => {
filters.push(element.value);
});
return filters;
}
},
data: function() {
return {
filteredData: [],
search: "",
filterOptions: [
{checked: false, value: "W", name: "White"},
{checked: false, value: "U", name: "Blue"},
{checked: false, value: "B", name: "Black"},
{checked: false, value: "R", name: "Red"},
{checked: false, value: "G", name: "Green"},
{checked: false, value: "KLD", name: "Kaladesh"},
]
}
},
methods: {
getFilteredData: function(){
this.filteredData = cards[0];
let filteredDataByFilters = [];
let filteredDataBySearch = [];
if (this.selectedFilters.length > 0) {
filteredDataByFilters = Object.values(this.filteredData).filter(obj =>
this.selectedFilters.every(val => obj.colors.indexOf(val) >= 0)
);
this.filteredData = filteredDataByFilters;
}
// set filters
// if (this.selectedFilters.length > 0) {
// filteredDataByFilters = Object.values(this.filteredData).filter(obj =>
// this.selectedFilters.every(val => obj.printings.indexOf(val) >= 0)
// );
// this.filteredData = filteredDataByFilters;
// }
if (this.search !== "") {
filteredDataBySearch = Object.values(this.filteredData).filter(obj =>
obj.name.toLowerCase().indexOf(this.search.toLowerCase()) >= 0);
this.filteredData = filteredDataBySearch;
}
}
},
mounted() {
this.getFilteredData();
}
});
<script src="https://unpkg.com/vue"></script>
<div id="app">
<div class="container-fluid">
<div class="search-wrapper">
<!-- the search bar form -->
<form v-on:submit="getFilteredData">
<div class="form-row">
<div class="col-10">
<input
type="text"
class="form-control"
placeholder="Enter key word ..."
v-model="search"
v-on:keyup="getFilteredData"
>
</div>
<div class="col-2">
<button type="submit" class="btn btn-primary">
<i class="fa fa-search"></i>
</button>
</div>
</div>
</form>
<!-- check boxes -->
<div id="checkboxes">
<div v-for="(filter, index) in filterOptions" :key="index" class="form-check form-check-inline">
<input
class="form-check-input"
type="checkbox"
v-model="filter.checked"
v-on:change="getFilteredData"
>
<label class="form-check-label">{{ filter.name }}</label>
</div>
</div>
</div>
<!-- end of checkboxes -->
<div class="cards-go-here">
<div v-for="(card, index) in filteredData" :key="index">{{card.name}}</div>
</div>
</div>
</div>

Parsing Exception error when using Terms in ElasticSearch

I'm getting an error on this elastic search for terms. The error message is
"[parsing_exception] [terms] unknown token [START_ARRAY] after [activeIds], with { line=1 & col=63 }"
Active Ids is an array of unique ids. It sort of looks like
const activeIds = [ '157621a1-d892-4f4b-80ca-14feddb837a0',
'd04c5c93-a22c-48c3-a3b0-c79a61bdd923',
'296d40d9-f316-4560-bbc9-001d6f46858b',
'2f8c6c37-588d-4d24-9e69-34b6dd7366c2',
'ba0508dd-0e76-4be8-8b6e-9e938ab4abed',
'ab076ed9-1dd5-4987-8842-15f1b995bc0d',
'ea6b0cff-a64f-4ce3-844e-b36d9f161e6f' ]
let items = await es.search({
"index": table,
"body": {
"from": 0, "size": 25,
"query": {
"terms" : {
"growerId" : {
activeIds
}
},
"bool": {
"must_not": [
{ "match":
{
"active": false
}
},
],
"must": [
{ "query_string" :
{
"query": searchQuery,
"fields": ["item_name"]
}
}
],
}
}
}
})
Appreciate the help!
Edit: Answering this question- "What's the expected result? Can you elaborate and share some sample data? – Nishant Saini 15 hours ago"
I'll try to elaborate a bit.
1) Overall I'm trying to retrieve items that belong to active users. There are 2 tables: user and items. So I'm initially running an ES that returns all the users that contain { active: true } from the user table
2) Running that ES returns an array of ids which I'm calling activeIds. The array looks like what I've already displayed in my example. So this works so far (let me know if you want to see the code for that, but if I'm getting an expected result then I don't think we need that now)
3) Now I want to search through the items table, and retrieve only the items that contain one of the active ids. So an item should look like:
4) expected result is retrieve an array of objects that match the growerId with one of the activeIds. So if I do a search query for "flowers", a single expected result should look like:
[ { _index: 'items-dev',
_type: 'items-dev_type',
_id: 'itemId=fc68dadf-21c8-43c2-98d2-cf574f71f06d',
_score: 11.397207,
_source:
{ itemId: 'fc68dadf-21c8-43c2-98d2-cf574f71f06d',
'#SequenceNumber': '522268700000000025760905838',
item_name: 'Flowers',
grower_name: 'Uhs',
image: '630b5d6e-566f-4d55-9d31-6421eb2cff87.jpg',
dev: true,
growerId: 'd04c5c93-a22c-48c3-a3b0-c79a61bdd923',
sold_out: true,
'#timestamp': '2018-12-20T16:09:38.742599',
quantity_type: 'Pounds',
active: true,
pending_inventory: 4,
initial_quantity: 5,
price: 10,
item_description: 'Field of flowers' } },
So here the growerId matches activeIds[1]
But if I do a search for "invisible", which is created by a an inactive user, I get:
[ { _index: 'items-dev',
_type: 'items-dev_type',
_id: 'itemId=15200473-93e1-477c-a1a7-0b67831f5351',
_score: 1,
_source:
{ itemId: '15200473-93e1-477c-a1a7-0b67831f5351',
'#SequenceNumber': '518241400000000004028805117',
item_name: 'Invisible too',
grower_name: 'Field of Greens',
image: '7f37d364-e768-451d-997f-8bb759343300.jpg',
dev: true,
growerId: 'f25040f4-3b8c-4306-9eb5-8b6c9ac58634',
sold_out: false,
'#timestamp': '2018-12-19T20:47:16.128934',
quantity_type: 'Pounds',
pending_inventory: 5,
initial_quantity: 5,
price: 122,
item_description: 'Add' } },
Now that growerId does not match any of the ids in activeIds.
5) Using the code you helped with, it's returning 0 items.
Let me know if you need more detail. I've been working on this for a bit too long :\
Terms query accept array of terms so the terms query should be defined as below:
"terms": {
"growerId": activeIds
}
You might face other errors as well after making the above correction. So below is full query which might help you:
{
"from": 0,
"size": 25,
"query": {
"bool": {
"must_not": [
{
"match": {
"active": false
}
}
],
"must": [
{
"query_string": {
"query": searchQuery,
"fields": [
"item_name"
]
}
},
{
"terms": {
"growerId": activeIds
}
}
]
}
}
}

Angular forEach over Mixed JSON Nests

I am finding it very difficult to re-define the return information so that it is suitable for ng-repeat to iterate over it in the view.
I have two views one for an index that i want the year-month to encompass the countries (might be 1+ or none) and then inside each country i want the name of each event (again could be 1+ or none). The second view i just want to pass the event details and will be calling these details by passing the event index number in order to return all the event details (name, mname, net).
The Data:
{
months: [
{
index: 201602,
year: "2016",
mon: "February",
country1: [
{
index: 12345678,
l: [
{
name: "Test1",
mname: "Test 1",
net: "February 10, 2016 11:39:00 UTC",
}
]
},
{
index: 23456789,
l: [
{
name: "Test2",
mname: "Test 2",
net: "February 10, 2016 11:39:00 UTC",
}
]
}
],
country2: [ ]
},
{
index: 201603,
year: "2016",
mon: "March",
country1: [
{
index: 546547657654,
l: [
{
name: "Test1",
mname: "Test 1",
net: "March 10, 2016 11:39:00 UTC",
}
]
}
],
country2: []
},
{
index: 201604,
year: "2016",
mon: "April",
country1: [ ],
country2: [
{
index: 78676756,
l: [
{
name: "Test1",
mname: "Test 1",
net: "April10, 2016 11:39:00 UTC",
}
]
}
]
}
]
}
In order for ng-repeat to work, you'll have to extract the country data in some another array (transform the initial data somehow).
If those country fields have consistent naming (like 'country' infix on each of them), you can extract them into their own array and use ng-repeat to iterate over it.
Here is working solution. It assumes that country arrays all have the word 'country' in their name:
function MyCtrl($scope) {
$scope.countriesData = prepData(sampleData);
function prepData(data) {
return data.months.map(function(yearMonth) {
var transformed = { yearMonth: yearMonth, countries: [] };
for (var key in yearMonth) {
if (key.indexOf('country') != -1) {
transformed.countries.push(yearMonth[key]);
}
}
return transformed;
});
}
}
var sampleData = {
months: {
//...
}
}
The solution takes the data you've provided and transforms it into an array of entries like this one: { yearMonth: yearMonth, countries: [] };
You'll just have to render them like this:
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="entry in countriesData">
ym-id: {{entry.yearMonth.index}}
<ul>
<li ng-repeat="country in entry.countries">
<ul>
<li ng-repeat="event in country">
event-id: {{event.index}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
You can check the fiddle here: http://jsfiddle.net/tvy4jbvs/

Categories