Backbone nested views - javascript

I'm working on a Backbone application and I'm not sure if the way what I'm trying to do is the correct way.
I have an application view and inside that application view I'm trying to append a collection view, and each view in that collection is a collection too.
Let me explain that graphically.
----------------------------------------------------------------------
| |
| Application view |
| |
| ------------------------------------------------------------- |
| | Windows Collection view | |
| | | |
| | -------------------------- -------------------------- | |
| | | Tabs collection view | | Tabs collection view | | |
| | | | | | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | | |Tab view| |Tab view| | | |Tab view| |Tab view| | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | | | | | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | | |Tab view| |Tab view| | | |Tab view| |Tab view| | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | |------------------------| |------------------------| | |
| | | |
| | -------------------------- -------------------------- | |
| | | Tabs collection view | | Tabs collection view | | |
| | | | | | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | | |Tab view| |Tab view| | | |Tab view| |Tab view| | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | | | | | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | | |Tab view| |Tab view| | | |Tab view| |Tab view| | | |
| | | ---------- ---------- | | ---------- ---------- | | |
| | |------------------------| |------------------------| | |
| | | |
| ------------------------------------------------------------- |
| |
| |
----------------------------------------------------------------------
Currently I'm loading the application view from the initialize method in my Backbone router. That view loads the Windows collection view.
The main problem is that I'm not sure if I'm on the right way.
The second problem is that I'm not really sure how to load each Tabs collection view from my Windows Collecion view.
PS: Just to make things even clearer, I'm trying to replicate Firefox's panorama view: http://i.i.com.com/cnwk.1d/i/tim//2010/08/24/firefox-panorama.jpg

I would highly recommend using Marionette.js to structure your application.
It already has collection views built in which makes rendering easy. Your application seems to be a perfect use case. You will get a lot of boilerplate code for free.

I'm just posting this here so others can see how I solved the problem
A working demo of the solution can be found here (original fiddle).
As you can see from the link, the work is done thanks to Marionette's CompositeView which lets recursively render collections.
var TreeView = Backbone.Marionette.CompositeView.extend({
initialize: function(){
if(this.model.tabs){
this.template = "#window-template";
}else{
this.template = "#tab-template";
}
this.collection = this.model.tabs;
},
appendHtml: function(cv, iv){
cv.$("#tabs").append(iv.el);
},
onRender: function() {
if(_.isUndefined(this.collection)){
this.$("#tabs").remove();
}
}
});
The small trick I'm using in the initialize (the if/else with the template asignation) works the following way:
I get the current model and check if it has a "tabs" key. If it does have it, it means that the current model is a Window Data Model, so I need to use the window-template, else use the tab-template
The rest is pretty much plain Backbone structure.

Related

DISTINCT on results of a knex.js INNER JOIN

I have two tables, metadata and view_events. Both metadata and view_events have config_id and config_type columns. I'm trying to select all view_events for a given user email, distinct by config_id and config_type, ordered by timestamp, desc, and limited to the 10 most recent. The following knex.js code isn't working but hopefully expresses what I'm trying to achieve:
return dbClient<AuthenticatedUserIndexRow>(METADATA_TABLE_NAME)
.select([
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_ID}`,
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_TYPE}`,
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.DESCRIPTION}`,
`${VIEW_EVENTS_TABLE_NAME}.${VIEW_EVENTS_COLUMNS.TIMESTAMP}`,
])
.innerJoin<AuthenticatedUserIndexRow>(VIEW_EVENTS_TABLE_NAME, function innerJoinOnViewEvents() {
this.on(
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.STORAGE_ID}`,
'=',
`${VIEW_EVENTS_TABLE_NAME}.${VIEW_EVENTS_COLUMNS.CONFIG_STORAGE_ID}`,
)
.andOn(
`${VIEW_EVENTS_TABLE_NAME}.${VIEW_EVENTS_COLUMNS.USER_EMAIL}`,
'=',
rawSql('?', [authUserEmail]),
)
.andOn(`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.DELETED}`, '=', rawSql('?', [false]));
})
.distinct([
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_TYPE}`,
`${METADATA_TABLE_NAME}.${METADATA_COLUMNS.CONFIG_ID}`,
])
.limit(EVENT_LIMIT)
.orderBy(VIEW_EVENTS_COLUMNS.TIMESTAMP, 'desc');
For example, given the following tables:
view_events
+-------------+-----------+--------------------------+----------------------+
| config_type | config_id | timestamp | email |
+-------------+-----------+--------------------------+----------------------+
| a | foo | 2020-01-23T03:08:14.618Z | john.smith#gmail.com |
| a | foo | 2020-01-23T03:08:14.500Z | jane.doe#gmail.com |
| a | foo | 2020-01-23T03:08:13.618Z | john.smith#gmail.com |
| a | bar | 2020-01-23T03:08:12.618Z | john.smith#gmail.com |
| a | foo | 2020-01-23T03:08:11.618Z | john.smith#gmail.com |
| b | foo | 2020-01-23T03:08:10.618Z | john.smith#gmail.com |
| a | baz | 2020-01-23T03:08:09.618Z | john.smith#gmail.com |
| a | foo | 2020-01-23T03:08:08.618Z | john.smith#gmail.com |
+-------------+-----------+--------------------------+----------------------+
metadata
+-------------+-----------+---------------------------+
| config_type | config_id | description |
+-------------+-----------+---------------------------+
| a | foo | Type a config with id foo |
| a | bar | Type a config with id bar |
| b | foo | Type b config with id foo |
| a | baz | Type a config with id baz |
+-------------+-----------+---------------------------+
I am trying to obtain the following output (given an authUserEmail of john.smith#gmail.com):
+-------------+-----------+---------------------------+
| config_type | config_id | description |
+-------------+-----------+---------------------------+
| a | foo | Type a config with id foo |
| a | bar | Type a config with id foo |
| b | foo | Type b config with id foo |
| a | baz | Type a config with id baz |
+-------------+-----------+---------------------------+
I'm not a SQL expert, but am generally aware that the use of SELECT and DISTINCT together here doesn't work. What's the correct approach?
Does the following roughly work for you? I did using with as so we could grab the 10 most recent configs (max(timestamp)..group by config) and then remove the timestamp column in the final projection. Note the final records may not appear in exact timestamp order as you did not want timestamp in your final output, but they will be the 10 most recent. I haven't added the DELETED column but imagine you will re-add that based on the code in your question.
knex.with('ordered_items', (qb) =>
qb.table('metadata')
.innerJoin('view_events', function() {
this.on('metadata.config_id', '=', 'view_events.config_id')
.andOn('metadata.config_type', '=', 'view_events.config_type')
})
.where({'view_events.email': 'john.smith#gmail.com'})
.select(['metadata.config_type', 'metadata.config_id',
'metadata.description'])
.max('view_events.timestamp', {as: 'max_ts'})
.groupBy(['metadata.config_id', 'metadata.config_type', 'metadata.description'])
.orderBy('max_ts', 'desc')
.limit(10))
.table('ordered_items')
.select(['config_type', 'config_id', 'description'])
My input and output:
sqlite> select * from metadata;
a|foo|Type a config with id foo
a|bar|Type a config with id bar
b|foo|Type b config with id foo
a|baz|Type a config with id baz
sqlite> select * from view_events;
a|foo|2020-01-23T03:08:14.618Z|john.smith#gmail.com
a|foo|2020-01-23T03:08:14.500Z|jane.doe#gmail.com
a|foo|2020-01-23T03:08:13.618Z|john.smith#gmail.com
a|bar|2020-01-23T03:08:12.618Z|john.smith#gmail.com
a|foo|2020-01-23T03:08:11.618Z|john.smith#gmail.com
b|foo|2020-01-23T03:08:10.618Z|john.smith#gmail.com
a|baz|2020-01-23T03:08:09.618Z|john.smith#gmail.com
a|foo|2020-01-23T03:08:08.618Z|john.smith#gmail.com
[ { config_type: 'a',
config_id: 'foo',
description: 'Type a config with id foo' },
{ config_type: 'a',
config_id: 'bar',
description: 'Type a config with id bar' },
{ config_type: 'b',
config_id: 'foo',
description: 'Type b config with id foo' },
{ config_type: 'a',
config_id: 'baz',
description: 'Type a config with id baz' } ]

Nested Json response from NodeJs and MySql

I have 3 Mysql tables, a vendor table with a list of vendors, a categories table with a list of categories that these vendors have in there stores, the categories table is linked to to the vendors table with a secondary key(vendor_id), i also have a product table that has all the products in these categories and it is linked to the category table using a foreign key (category_id). How do i write a NodeJs/ express route that returns a json object that looks like this,
{
"id": 1,
"vendor": "Food place",
"category": "Chicken"[
{
"id": "1,
"name": "Fried chicken",
"price": "100"
},
{
"id": "2,
"name": "Soup Chicken",
"price": "150"
}
}
So the json object returns a vendor all the categories they have in there store, and inside the categories all the products that be long to these categories
The tables look similar to this
Vendor table:
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| category | varchar(255) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+
Category table:
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| vendor_id | int(11) | NO | MUL | NULL | |
+-----------+-------------+------+-----+---------+----------------+
Product table:
+-----------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| price | decimal(10,0) | NO | | NULL | |
| name | varchar(255) | YES | | NULL | |
| category_id | int(11) | YES | MUL | NULL | |
+-----------------+---------------+------+-----+---------+----------------+
Route
export const route = (router: any) => {
return router.get('/your_route_here', (req: any, res: any) => {
// do your logic here
});
}
export default route;

How create a result table with result group of the columns

I need make a group with result of 2 columns and separate by lines from name and columns from size.
Example: Table Base
Name | Size | Item
Frankincense | 5ml | 1562
Frankincense | 10ml | 1563
Frankincense | 15ml | 1564
Geranium | 5ml | 1565
Geranium | 10ml | 1566
Geranium | 15ml | 1567
Ginger | 5ml | 1568
Ginger | 10ml | 1569
Ginger | 15ml | 1570
Grapefruit | 5ml | 1571
Grapefruit | 10ml | 1572
Grapefruit | 15ml | 1573
Lavender | 5ml | 1574
Lavender | 10ml | 1575
Lavender | 15ml | 1576
Example: Table Result
Name/Size | 5ml | 10ml | 15ml
Frankincense | 1562 | 1563 | 1564
Geranium | 1565 | 1566 | 1567
Ginger | 1568 | 1569 | 1570
Grapefruit | 1571 | 1572 | 1573
Lavender | 1574 | 1575 | 1576
I found something, but don't have the result yet. I need group the column size and made sure the result is correct.
data = [['Frankincense','5ml','1562'],
['Frankincense','10ml','1563'],
['Frankincense','15ml','1564'],
['Geranium','5ml','1565'],
['Geranium','10ml','1566'],
['Geranium','15ml','1567'],
['Ginger','5ml','1568'],
['Ginger','10ml','1569'],
['Ginger','15ml','1570'],
['Grapefruit','5ml','1571'],
['Grapefruit','10ml','1572'],
['Grapefruit','15ml','1573'],
['Lavender','5ml','1574'],
['Lavender','10ml','1575'],
['Lavender','15ml','1576']]
data.sort()
var title = data.reduce(function(result, value) {
if ( result.indexOf(value[1]) === -1 ) {
result.push(value[1]);
}
return result;
}, []).map(function(group) {
return group
});
var result = data.reduce(function(result, value) {
if ( result.indexOf(value[0]) === -1 ) {
result.push(value[0]);
}
return result;
}, []).map(function(group) {
return [group,...data.filter(function(_el) {
return _el[0] === group;
}).map(function(_el) { return _el[2]; })]
});
title.unshift('Name/Size')
result.unshift(title)
result.forEach(item => console.log(item.join('\t| ')))

AlaSQL nested arrays

I'm trying tu use the AlaSQL Array agregator inside an array, it appears to be not supported :(
Trying to acomplish this output (or like this):
[
{
"keyword":"project 1",
"projects": [
{
"year":2014,
"description":"this is a project description",
"budget": 5600,
"status": "closed",
"metadata": [
{
"key":"provider",
"value":"just me"
},
{
"key":"client",
"value":"someone"
},
{
"key":"any thing",
"value":"any data..."
}
]
}
]
}
]
My Database Structure
people e
| name | type |
|-----------|---------|
| name | varchar |
| lastname | varchar |
| person_id | varchar |
| cel | int |
projects p
| name | type |
|-------------|---------|
| keyword | varchar |
| year | int |
| description | text |
| budget | int |
PeopleProjects x
| name | type |
|-------------|---------|
| e_person_id | varchar |
| p_keyword | varchar |
| p_year | int |
| status | varchar |
metadata m
| name | type |
|-------------|---------|
| e_person_id | varchar |
| p_keyword | varchar |
| p_year | int |
| key | varchar |
| value | varchar |
My query
alasql("SELECT p.keyword, \
ARRAY({year:p.year, description:p.description, budget:p.budget, status:x.status, \
ARRAY({key:m.key, value:m.value}) as metadata \
}) AS projects \
FROM projects p, PeopleProjects x, metadata m \
WHERE \
p.keyword = x.p_keyword AND x.p_keyword = m.p_keyword AND \
p.year = x.p_year AND x.p_year = m.p_year \
x.e_person_id = x.e_person_id AND AND x.e_person_id = 2 \
GROUP BY p.keyword");
At the moment, I divided the query in two and then combine the data to produce the hole thing.
Any ideas?
I managed to get the output I want by fetching two times:
First, projects:
var projects = alasql("SELECT p.keyword, ARRAY({status:x.status, year:p.year, description:p.description, budget:p.budget }) AS years \
FROM PeopleProjects x, projects p \
WHERE x.p_keyword = p.keyword AND x.p_year = p.year AND x.e_person_id = "+person_id+" \
GROUP BY p.keyword");
Second, metadata:
var mdata = alasql("SELECT m.e_person_id, m.p_keyword, m.p_year, ARRAY({key:m.key,value:m.value}) as [metadata] \
FROM metadata m, PeopleProjects x \
WHERE x.e_person_id = m.e_person_id AND x.p_keyword = m.p_keyword AND x.p_year = m.p_year AND x.e_person_id = "+person_id+" \
GROUP BY m.e_person_id, m.p_keyword, m.p_year");
Then, loop over projects, searching and storing the metadata:
for(i=0;i<projects.length;i++){
for(j=0;j<projects[i].years.length;j++){
current = projects[i].keyword;
current_year = projects[i].years[0].year;
search = alasql("SEARCH / * WHERE(year="+current_year+" AND keyword='"+current+"') FROM ?",[mdata]);
projects[i].years[j]["metadata"] = search[0].metadata;
}
}
Now projects has all the data.
Any suggestion will be welcome.

ER_BAD_FIELD_ERROR in sails.js using waterline

I know there are similar questions but they haven't help me.
I've got an error when trying to use .find() method on model: product2
(.query() method is working )
I was trying to find out how to get more verbose output from database, but with failure.
{
"error": "E_UNKNOWN",
"status": 500,
"summary": "Encountered an unexpected error",
"raw": {
"code": "ER_BAD_FIELD_ERROR",
"errno": 1054,
"sqlState": "42S22",
"index": 0
}
}%
my model "Product2.js"
module.exports = {
connection:'someMysqlServer',
migration:'safe',
tableName:'NUTR_DATA',
attributes:{
id:{
columnName:'Nutr_No',
primaryKey:true,
type:'string'
}
}
};
routes.js
module.exports.routes{
'GET /select':'Product2Controller.select'
};
Product2Controller.js
module.exports = {
select:function(req,res){
Product2.find({limit:10}).exec(function(err, results) {
if (err){res.serverError(err)}
else{res.json(results)};
});
}
};
database schema
+---------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| NDB_No | varchar(5) | NO | PRI | NULL | |
| Nutr_No | varchar(3) | NO | PRI | NULL | |
| Nutr_Val | decimal(13,3) | NO | | NULL | |
| Num_Data_Ptr | decimal(10,0) | NO | | NULL | |
| Std_Error | decimal(11,3) | YES | | NULL | |
| Src_Cd | varchar(2) | NO | | NULL | |
| Deriv_cd | varchar(4) | YES | | NULL | |
| Ref_NDB_No | varchar(5) | YES | | NULL | |
| Add_Nutr_Mark | varchar(1) | YES | | NULL | |
| Num_Studies | int(11) | YES | | NULL | |
| Min | decimal(13,3) | YES | | NULL | |
| Max | decimal(13,3) | YES | | NULL | |
| DF | int(11) | YES | | NULL | |
| Low_EB | decimal(13,3) | YES | | NULL | |
| Up_EB | decimal(13,3) | YES | | NULL | |
| Stat_cmd | varchar(10) | YES | | NULL | |
| AddMod_Date | varchar(10) | YES | | NULL | |
| CC | varchar(1) | YES | | NULL | |
+---------------+---------------+------+-----+---------+-------+
Any ideas as to what is going wrong?
Thank you for your responses. The problem was not setted
autoCreatedAt: false,
autoUpdatedAt: false
i hadn't see that my ide actually give me more verbose output then curl. Maybe it would be better if errors would be placed under calming picture of boat and info about lifted server :P
The likely problem is that you're defining your own primary key field, but Waterline is still atuomatically adding its own id field. You can turn off this behavior by adding autoPK: false to your model configuration. Docs for autoPK are here.

Categories

Resources