diff --git a/extensions/tags/js/bootstrap.js b/extensions/tags/js/bootstrap.js index 5b1c70d66..403fca38d 100644 --- a/extensions/tags/js/bootstrap.js +++ b/extensions/tags/js/bootstrap.js @@ -65,6 +65,8 @@ app.initializers.add('categories', function() { items.add('separator', Separator.component(), {last: true}); + items.add('uncategorized', CategoryNavItem.component({params: this.stickyParams()}), {last: true}); + app.store.all('categories').forEach(category => { items.add('category'+category.id(), CategoryNavItem.component({category, params: this.stickyParams()}), {last: true}); }); diff --git a/extensions/tags/js/src/components/category-nav-item.js b/extensions/tags/js/src/components/category-nav-item.js index a0806fdad..ce1911468 100644 --- a/extensions/tags/js/src/components/category-nav-item.js +++ b/extensions/tags/js/src/components/category-nav-item.js @@ -5,17 +5,17 @@ export default class CategoryNavItem extends NavItem { view() { var category = this.props.category; var active = this.constructor.active(this.props); - return m('li'+(active ? '.active' : ''), m('a', {href: this.props.href, config: m.route, onclick: () => {app.cache.discussionList = null; m.redraw.strategy('none')}, style: active ? 'color: '+category.color() : ''}, [ + return m('li'+(active ? '.active' : ''), m('a', {href: this.props.href, config: m.route, onclick: () => {app.cache.discussionList = null; m.redraw.strategy('none')}, style: (active && category) ? 'color: '+category.color() : '', title: category ? category.description() : ''}, [ categoryIcon(category, {className: 'icon'}), - category.title() + this.props.label ])); } static props(props) { var category = props.category; - props.params.categories = category.slug(); + props.params.categories = category ? category.slug() : 'uncategorized'; props.href = app.route('category', props.params); - props.label = category.title(); + props.label = category ? category.title() : 'Uncategorized'; return props; } diff --git a/extensions/tags/less/categories.less b/extensions/tags/less/categories.less index 70331163b..8b5fe5dde 100644 --- a/extensions/tags/less/categories.less +++ b/extensions/tags/less/categories.less @@ -30,6 +30,10 @@ display: inline-block; vertical-align: -3px; margin-left: 1px; + + &.uncategorized { + border: 1px dotted @fl-body-muted-color; + } } .categories-area .container { diff --git a/extensions/tags/migrations/2015_02_24_000000_add_category_to_discussions.php b/extensions/tags/migrations/2015_02_24_000000_add_category_to_discussions.php index 68c1b285a..9d4753334 100644 --- a/extensions/tags/migrations/2015_02_24_000000_add_category_to_discussions.php +++ b/extensions/tags/migrations/2015_02_24_000000_add_category_to_discussions.php @@ -13,7 +13,7 @@ class AddCategoryToDiscussions extends Migration public function up() { Schema::table('discussions', function (Blueprint $table) { - $table->integer('category_id')->unsigned(); + $table->integer('category_id')->unsigned()->nullable(); }); } diff --git a/extensions/tags/src/CategoryGambit.php b/extensions/tags/src/CategoryGambit.php index 38b75ddcf..eb5e2bfc3 100644 --- a/extensions/tags/src/CategoryGambit.php +++ b/extensions/tags/src/CategoryGambit.php @@ -38,10 +38,17 @@ class CategoryGambit extends GambitAbstract */ public function conditions($matches, SearcherInterface $searcher) { - $slug = trim($matches[1], '"'); + $slugs = explode(',', trim($matches[1], '"')); - $id = $this->categories->getIdForSlug($slug); - - $searcher->query()->where('category_id', $id); + $searcher->query()->where(function ($query) use ($slugs) { + foreach ($slugs as $slug) { + if ($slug === 'uncategorized') { + $query->orWhereNull('category_id'); + } else { + $id = $this->categories->getIdForSlug($slug); + $query->orWhere('category_id', $id); + } + } + }); } }