Skip to content

Commit 435cc35

Browse files
committed
decorate categories with active and expanded properties; adapt Categories.getParents to work with store; add category parent resolver; improve mongo-redux; remove duplicate unflatten; add level property to items in unflatten
1 parent 8bc6aac commit 435cc35

File tree

7 files changed

+52
-66
lines changed

7 files changed

+52
-66
lines changed

packages/nova-base-components/lib/categories/CategoriesList.jsx

+26-8
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,37 @@ import { Button, DropdownButton, MenuItem } from 'react-bootstrap';
55
import { withRouter } from 'react-router'
66
import { LinkContainer } from 'react-router-bootstrap';
77
import Categories from 'meteor/nova:categories';
8+
import { withApollo } from 'react-apollo';
89

910
class CategoriesList extends Component {
1011

11-
render() {
12-
12+
getNestedCategories() {
1313
const categories = this.props.results;
1414

15-
const currentQuery = _.clone(this.props.router.location.query);
16-
delete currentQuery.cat;
15+
// check if a category is currently active in the route
16+
const currentCategorySlug = this.props.router.location.query && this.props.router.location.query.cat;
17+
const currentCategory = Categories.findOneInStore(this.props.client.store, {slug: currentCategorySlug});
18+
const parentCategories = Categories.getParents(currentCategory, this.props.client.store);
19+
20+
// decorate categories with active and expanded properties
21+
const categoriesClone = _.map(categories, category => {
22+
return {
23+
...category, // we don't want to modify the objects we got from props
24+
active: currentCategory && category.slug === currentCategory.slug,
25+
expanded: parentCategories && _.contains(_.pluck(parentCategories, 'slug'), category.slug)
26+
};
27+
});
1728

18-
const categoriesClone = _.map(categories, _.clone); // we don't want to modify the objects we got from props
1929
const nestedCategories = Utils.unflatten(categoriesClone, '_id', 'parentId');
2030

31+
return nestedCategories;
32+
}
33+
34+
render() {
35+
36+
const currentQuery = _.clone(this.props.router.location.query);
37+
const nestedCategories = this.getNestedCategories();
38+
2139
return (
2240
<div>
2341
<DropdownButton
@@ -26,8 +44,8 @@ class CategoriesList extends Component {
2644
title={<FormattedMessage id="categories"/>}
2745
id="categories-dropdown"
2846
>
29-
<div className="category-menu-item dropdown-item">
30-
<LinkContainer to={{pathname:"/", query: currentQuery}}>
47+
<div className="category-menu-item category-menu-item-all dropdown-item">
48+
<LinkContainer className="category-menu-item-title" to={{pathname:"/", query: currentQuery}}>
3149
<MenuItem eventKey={0}>
3250
<FormattedMessage id="categories.all"/>
3351
</MenuItem>
@@ -72,4 +90,4 @@ const options = {
7290
pollInterval: 0,
7391
};
7492

75-
registerComponent('CategoriesList', CategoriesList, withRouter, [withList, options]);
93+
registerComponent('CategoriesList', CategoriesList, withRouter, withApollo, [withList, options]);

packages/nova-categories/lib/callbacks.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ function categoriesNewGenerateSlug (category) {
4747
}
4848
addCallback("categories.new.sync", categoriesNewGenerateSlug);
4949

50-
function categoriesEditGenerateSlug (modifier) {
50+
function categoriesEditGenerateSlug (modifier, document) {
5151
// if slug is changing
52-
if (modifier.$set && modifier.$set.slug) {
52+
if (modifier.$set && modifier.$set.slug && modifier.$set.slug !== document.slug) {
5353
const slug = modifier.$set.slug;
5454
modifier.$set.slug = Utils.getUnusedSlug(Categories, slug);
5555
}

packages/nova-categories/lib/helpers.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import { Utils } from 'meteor/nova:core';
66
* @summary Get all of a category's parents
77
* @param {Object} category
88
*/
9-
Categories.getParents = function (category) {
9+
Categories.getParents = function (category, store) {
1010
const categoriesArray = [];
11-
1211
const getParents = function recurse (category) {
13-
const parent = Categories.findOne(category.parentId);
14-
if (parent) {
15-
categoriesArray.push(parent);
16-
recurse(parent);
12+
if (category && category.parentId) {
13+
const parent = store ? Categories.findOneInStore(store, category.parentId) : Categories.findOne(category.parentId);
14+
if (parent) {
15+
categoriesArray.push(parent);
16+
recurse(parent);
17+
}
1718
}
1819
};
1920
getParents(category);

packages/nova-categories/lib/resolvers.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ const specificResolvers = {
77
return post.categories ? context.Categories.find({_id: {$in: post.categories}}, { fields: context.getViewableFields(context.currentUser, context.Categories) }).fetch() : [];
88
},
99
},
10-
// TODO: fix this
11-
// Category: {
12-
// parent(category, args, context) {
13-
// return category.parent ? context.Categories.findOne({_id: category.parent }, { fields: context.getViewableFields(context.currentUser, context.Categories) }) : null;
14-
// }
15-
// },
10+
Category: {
11+
parent(category, args, context) {
12+
return category.parentId ? context.Categories.findOne({_id: category.parentId }, { fields: context.getViewableFields(context.currentUser, context.Categories) }) : null;
13+
}
14+
},
1615
};
1716
GraphQLSchema.addResolvers(specificResolvers);
1817

packages/nova-lib/lib/client/mongo-redux.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ Mongo.Collection.prototype.findRedux = function (selector = {}, options = {}) {
55
return this.findInStore(store, selector, options);
66
}
77

8-
Mongo.Collection.prototype.findOneRedux = function (_id) {
9-
return this.findRedux({_id});
8+
Mongo.Collection.prototype.findOneRedux = function (_idOrObject) {
9+
return this.findOneInStore(store, _idOrObject);
1010
}

packages/nova-lib/lib/mongo-redux.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Mongo.Collection.prototype.findInStore = function (store, selector = {}, options
2020
return {fetch: () => sortedDocs};
2121
}
2222

23-
Mongo.Collection.prototype.findOneInStore = function (store, _id) {
24-
return this.findInStore(store, {_id}).fetch();
23+
Mongo.Collection.prototype.findOneInStore = function (store, _idOrObject) {
24+
const docs = typeof _idOrObject === 'string' ? this.findInStore(store, {_id: _idOrObject}).fetch() : this.findInStore(store, _idOrObject).fetch();
25+
return docs.length === 0 ? undefined: docs[0];
2526
}

packages/nova-lib/lib/utils.js

+7-40
Original file line numberDiff line numberDiff line change
@@ -266,42 +266,6 @@ _.mixin({
266266
}
267267
});
268268

269-
// adapted from http://stackoverflow.com/a/22072374/649299
270-
Utils.unflatten = function( array, idProperty, parentIdProperty, parent, tree ){
271-
272-
tree = typeof tree !== "undefined" ? tree : [];
273-
274-
let children = [];
275-
276-
if (typeof parent === "undefined") {
277-
// if there is no parent, we're at the root level
278-
// so we return all root nodes (i.e. nodes with no parent)
279-
children = _.filter( array, node => !node[parentIdProperty]);
280-
} else {
281-
// if there *is* a parent, we return all its child nodes
282-
// (i.e. nodes whose parentId is equal to the parent's id.)
283-
children = _.filter( array, node => node[parentIdProperty] === parent[idProperty]);
284-
}
285-
286-
// if we found children, we keep on iterating
287-
if (!!children.length) {
288-
289-
if (typeof parent === "undefined") {
290-
// if we're at the root, then the tree consist of all root nodes
291-
tree = children;
292-
} else {
293-
// else, we add the children to the parent as the "childrenResults" property
294-
parent.childrenResults = children;
295-
}
296-
297-
// we call the function on each child
298-
children.forEach(child => {
299-
Utils.unflatten(array, idProperty, parentIdProperty, child);
300-
});
301-
}
302-
303-
return tree;
304-
}
305269

306270
Utils.getFieldLabel = (fieldName, collection) => {
307271
const label = collection.simpleSchema()._schema[fieldName].label;
@@ -344,7 +308,9 @@ Utils.findIndex = (array, predicate) => {
344308
}
345309

346310
// adapted from http://stackoverflow.com/a/22072374/649299
347-
Utils.unflatten = function( array, idProperty, parentIdProperty, parent, tree ){
311+
Utils.unflatten = function(array, idProperty, parentIdProperty, parent, level=0, tree){
312+
313+
level++;
348314

349315
tree = typeof tree !== "undefined" ? tree : [];
350316

@@ -353,11 +319,11 @@ Utils.unflatten = function( array, idProperty, parentIdProperty, parent, tree ){
353319
if (typeof parent === "undefined") {
354320
// if there is no parent, we're at the root level
355321
// so we return all root nodes (i.e. nodes with no parent)
356-
children = _.filter( array, node => !node[parentIdProperty]);
322+
children = _.filter(array, node => !node[parentIdProperty]);
357323
} else {
358324
// if there *is* a parent, we return all its child nodes
359325
// (i.e. nodes whose parentId is equal to the parent's id.)
360-
children = _.filter( array, node => node[parentIdProperty] === parent[idProperty]);
326+
children = _.filter(array, node => node[parentIdProperty] === parent[idProperty]);
361327
}
362328

363329
// if we found children, we keep on iterating
@@ -373,7 +339,8 @@ Utils.unflatten = function( array, idProperty, parentIdProperty, parent, tree ){
373339

374340
// we call the function on each child
375341
children.forEach(child => {
376-
Utils.unflatten(array, idProperty, parentIdProperty, child);
342+
child.level = level;
343+
Utils.unflatten(array, idProperty, parentIdProperty, child, level);
377344
});
378345
}
379346

0 commit comments

Comments
 (0)