From bcfce44a86c4adfaa39b4282b7ad353467a73069 Mon Sep 17 00:00:00 2001 From: Johannes Wachter Date: Thu, 20 Apr 2017 12:40:04 +0200 Subject: [PATCH] Added filter by category to article-list (#147) * added filter by category overlay for article-list * fixed name of filter-by --- Controller/ArticleController.php | 4 + .../articles/list/category-selection/main.js | 1 + .../dist/components/articles/list/main.js | 2 +- .../articles/list/category-selection/main.js | 125 ++++++++++++++++++ .../js/components/articles/list/main.js | 95 ++++++++++--- Resources/translations/sulu/backend.de.xlf | 8 +- Resources/translations/sulu/backend.en.xlf | 8 +- .../Controller/ArticleControllerTest.php | 46 +++++++ 8 files changed, 262 insertions(+), 27 deletions(-) create mode 100644 Resources/public/dist/components/articles/list/category-selection/main.js create mode 100644 Resources/public/js/components/articles/list/category-selection/main.js diff --git a/Controller/ArticleController.php b/Controller/ArticleController.php index df2ced226..44511e772 100644 --- a/Controller/ArticleController.php +++ b/Controller/ArticleController.php @@ -134,6 +134,10 @@ public function cgetAction(Request $request) $search->addQuery($boolQuery); } + if (null !== ($categoryId = $request->get('categoryId'))) { + $search->addQuery(new TermQuery('excerpt.categories.id', $categoryId), BoolQuery::MUST); + } + if (null === $search->getQueries()) { $search->addQuery(new MatchAllQuery()); } diff --git a/Resources/public/dist/components/articles/list/category-selection/main.js b/Resources/public/dist/components/articles/list/category-selection/main.js new file mode 100644 index 000000000..af7518014 --- /dev/null +++ b/Resources/public/dist/components/articles/list/category-selection/main.js @@ -0,0 +1 @@ +define(["jquery"],function(a){"use strict";var b={options:{data:{contact:null},selectCallback:function(a){},matchings:[{name:"name",content:"Name"},{name:"id",disabled:!0},{name:"children",disabled:!0},{name:"parent",disabled:!0}]},translations:{title:"sulu_article.category-selection-overlay.title"},templates:{skeleton:['
','
','
',"
","
"].join("")}};return{defaults:b,initialize:function(){var b=a("
");this.$el.append(b),this.data=this.options.data,this.sandbox.start([{name:"overlay@husky",options:{el:b,instanceName:"category-selection",openOnStart:!0,removeOnClose:!0,skin:"medium",slides:[{title:this.translations.title,data:a(this.templates.skeleton({translations:this.translations})),okCallback:this.okCallbackOverlay.bind(this)}]}}]),this.sandbox.once("husky.overlay.category-selection.opened",function(){this.sandbox.start([{name:"datagrid@husky",options:{el:b.find(".category-selection-list"),instanceName:"category-selection",url:"/admin/api/categories?locale="+this.options.locale+"&flat=true&sortBy=name&sortOrder=asc",resultKey:"categories",sortable:!1,selectedCounter:!1,preselected:this.options.data.category?[this.options.data.category.id]:[],paginationOptions:{dropdown:{limit:20}},childrenPropertyName:"hasChildren",viewOptions:{table:{cropContents:!1,noItemsText:"sulu.category.no-categories-available",showHead:!1,cssClass:"white-box",selectItem:{type:"radio",inFirstCell:!0}}},matchings:this.options.matchings}}])}.bind(this))},okCallbackOverlay:function(){this.sandbox.emit("husky.datagrid.category-selection.items.get-selected",function(a,b){b.length>0&&(this.data.categoryId=a[0],this.data.categoryItem=b[0]),this.options.selectCallback(this.data),this.sandbox.stop()}.bind(this),!0)}}}); \ No newline at end of file diff --git a/Resources/public/dist/components/articles/list/main.js b/Resources/public/dist/components/articles/list/main.js index 92a9faaf6..ede4de286 100644 --- a/Resources/public/dist/components/articles/list/main.js +++ b/Resources/public/dist/components/articles/list/main.js @@ -1 +1 @@ -define(["underscore","services/husky/storage","sulucontent/components/copy-locale-overlay/main","sulucontent/components/open-ghost-overlay/main","services/suluarticle/article-manager"],function(a,b,c,d,e){"use strict";var f={options:{config:{},storageName:"articles"},templates:{list:['
','
','
','
'].join(""),draftIcon:'',publishedIcon:'',route:["articles","<% if (!!type) { %>:<%=type%><% } %>","/<%=locale%>"].join("")},translations:{headline:"sulu_article.list.title",unpublished:"public.unpublished",publishedWithDraft:"public.published-with-draft",filterMe:"sulu_article.list.filter.me",filterAll:"sulu_article.list.filter.all",filterBy:"sulu_article.list.filter.by",openGhostOverlay:{info:"sulu_article.settings.open-ghost-overlay.info","new":"sulu_article.settings.open-ghost-overlay.new",copy:"sulu_article.settings.open-ghost-overlay.copy",ok:"sulu_article.settings.open-ghost-overlay.ok"}}};return{defaults:f,data:{contactId:null},header:function(){this.storage=b.get("sulu",this.options.storageName);var c,d=this.options.config.types,e=this.options.config.typeNames,f={icon:"plus-circle",title:"public.add-new"},g=!1,h=null,i=this.options.type||this.storage.getWithDefault("type",null);return 1===e.length?f.callback=function(){this.toAdd(e[0])}.bind(this):(f.dropdownItems=a.map(e,function(a){return{title:d[a].title,callback:function(){this.toAdd(a)}.bind(this)}}.bind(this)),c=[],this.options.config.displayTabAll===!0&&c.push({name:"public.all",key:null}),a.each(e,function(a){c.push({id:a,name:d[a].title,key:a}),a===i&&(h=d[a].title)}.bind(this)),g={componentOptions:{callback:this.typeChange.bind(this),preselector:"name",preselect:h},data:c}),{noBack:!0,tabs:g,toolbar:{buttons:{addArticle:{options:f},deleteSelected:{}},languageChanger:{data:this.options.config.languageChanger,preSelected:this.options.locale}}}},layout:{content:{width:"max"}},initialize:function(){if(this.options.type)this.storage.set("type",this.options.type);else if(this.storage.has("type")){var a=this.templates.route({type:this.storage.get("type"),locale:this.options.locale});this.sandbox.emit("sulu.router.navigate",a,!1,!1),this.options.type=this.storage.get("type")}this.render(),this.bindCustomEvents()},render:function(){this.$el.html(this.templates.list());var a="/admin/api/articles?sortBy=authored&sortOrder=desc&locale="+this.options.locale+(this.options.type?"&type="+this.options.type:""),b=this.getContactFilterFromStorage(),f=this.getContactFilterTitle(b.filterKey,b.contact);b.contact&&(a+="&contactId="+b.contact.id),this.sandbox.sulu.initListToolbarAndList.call(this,"article","/admin/api/articles/fields",{el:this.$find(".list-toolbar-container"),instanceName:"articles",template:this.retrieveListToolbarTemplate(f)},{el:this.sandbox.dom.find(".datagrid-container"),url:a,storageName:this.options.storageName,searchInstanceName:"articles",searchFields:["title"],resultKey:"articles",instanceName:"articles",actionCallback:function(a,b){"ghost"===b.localizationState.state?e.load(a,this.options.locale).then(function(b){d.openGhost.call(this,b,this.translations.openGhostOverlay).then(function(b,d){b?c.copyLocale.call(this,a,d,[this.options.locale],function(){this.toEdit(a)}.bind(this)):this.toEdit(a)}.bind(this))}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,data)}.bind(this)):this.toEdit(a)}.bind(this),viewOptions:{table:{actionIconColumn:"title",badges:[{column:"title",callback:function(a,b){return!(!a.localizationState||"ghost"!==a.localizationState.state||a.localizationState.locale===this.options.locale)&&(b.title=a.localizationState.locale,b)}.bind(this)},{column:"title",callback:function(a,b){var c="",d=this.translations.unpublished;return a.published&&!a.publishedState&&(d=this.translations.publishedWithDraft,c+=this.templates.publishedIcon({title:d})),a.publishedState||(c+=this.templates.draftIcon({title:d})),b.title=c,b.cssClass="badge-none",b}.bind(this)}]}}})},toEdit:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/edit:"+a+"/details")},toAdd:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/add"+(this.options.config.typeNames.length>1?":"+a:""))},toList:function(a){1!==this.options.config.typeNames.length&&this.options.type?this.sandbox.emit("sulu.router.navigate","articles:"+this.options.type+"/"+(a||this.options.locale)):this.sandbox.emit("sulu.router.navigate","articles/"+(a||this.options.locale))},deleteItems:function(b){e.remove(b,this.options.locale).then(function(){a.each(b,function(a){this.sandbox.emit("husky.datagrid.articles.record.remove",a)}.bind(this))}.bind(this))},typeChange:function(a){var b=this.templates.route({type:a.key,locale:this.options.locale});this.options.type=a.key,this.sandbox.emit("husky.datagrid.articles.url.update",{page:1,type:a.key}),this.sandbox.emit("sulu.router.navigate",b,!1,!1),this.storage.set("type",a.key)},getCopyLocaleUrl:function(a,b,c){return e.getCopyLocaleUrl(a,b,c)},bindCustomEvents:function(){this.sandbox.on("husky.datagrid.articles.number.selections",function(a){var b=a>0?"enable":"disable";this.sandbox.emit("sulu.header.toolbar.item."+b,"deleteSelected",!1)}.bind(this)),this.sandbox.on("sulu.toolbar.delete",function(){this.sandbox.emit("husky.datagrid.articles.items.get-selected",this.deleteItems.bind(this))}.bind(this)),this.sandbox.on("sulu.header.language-changed",function(a){a.id!==this.options.locale&&(this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),this.toList(a.id))}.bind(this)),this.sandbox.on("husky.toolbar.articles.initialized",function(){this.sandbox.emit("husky.toolbar.articles.item.mark",this.getContactFilterFromStorage().filterKey)}.bind(this))},retrieveListToolbarTemplate:function(a){return this.sandbox.sulu.buttons.get({settings:{options:{dropdownItems:[{type:"columnOptions"}]}},contactIdFilter:{options:{icon:"filter",group:2,title:a,showTitle:!0,dropdownOptions:{idAttribute:"id",markSelected:!0,changeButton:!1},dropdownItems:[{id:"all",title:this.translations.filterAll,callback:function(){this.applyFilterToList.call(this,"all",null)}.bind(this)},{id:"me",title:this.translations.filterMe,callback:function(){this.applyFilterToList.call(this,"me",this.sandbox.sulu.user.contact)}.bind(this)},{id:"filterBy",title:this.translations.filterBy+"...",callback:this.openContactSelectionOverlay.bind(this)}]}}})},openContactSelectionOverlay:function(){var a=$("
");this.$el.append(a),this.sandbox.start([{name:"articles/list/contact-selection@suluarticle",options:{el:a,locale:this.options.locale,data:{contact:this.getContactFilterFromStorage.call(this).contact},selectCallback:function(a){this.applyFilterToList.call(this,"filterBy",a.contactItem),this.sandbox.emit("husky.overlay.contact-selection.close")}.bind(this)}}])},applyFilterToList:function(a,b){this.storage.set("contactFilter",{contact:b,filterKey:a}),this.sandbox.emit("husky.datagrid.articles.url.update",{contactId:b?b.id:null}),this.sandbox.emit("husky.toolbar.articles.button.set","contactIdFilter",{title:this.getContactFilterTitle(a,b)})},getContactFilterFromStorage:function(){return this.storage.getWithDefault("contactFilter",{filterKey:"all",contact:null})},getContactFilterTitle:function(a,b){var c="";switch(a){case"all":c=this.translations.filterAll;break;case"filterBy":c=this.translations.filterBy+" "+b.firstName+" "+b.lastName;break;case"me":c=this.translations.filterMe}return c}}}); \ No newline at end of file +define(["underscore","services/husky/storage","sulucontent/components/copy-locale-overlay/main","sulucontent/components/open-ghost-overlay/main","services/suluarticle/article-manager"],function(a,b,c,d,e){"use strict";var f={options:{config:{},storageName:"articles"},templates:{list:['
','
','
','
'].join(""),draftIcon:'',publishedIcon:'',route:["articles","<% if (!!type) { %>:<%=type%><% } %>","/<%=locale%>"].join("")},translations:{headline:"sulu_article.list.title",unpublished:"public.unpublished",publishedWithDraft:"public.published-with-draft",filterMe:"sulu_article.list.filter.me",filterAll:"sulu_article.list.filter.all",filterByAuthor:"sulu_article.list.filter.by-author",filterByCategory:"sulu_article.list.filter.by-category",openGhostOverlay:{info:"sulu_article.settings.open-ghost-overlay.info","new":"sulu_article.settings.open-ghost-overlay.new",copy:"sulu_article.settings.open-ghost-overlay.copy",ok:"sulu_article.settings.open-ghost-overlay.ok"}}};return{defaults:f,data:{contactId:null},header:function(){this.storage=b.get("sulu",this.options.storageName);var c,d=this.options.config.types,e=this.options.config.typeNames,f={icon:"plus-circle",title:"public.add-new"},g=!1,h=null,i=this.options.type||this.storage.getWithDefault("type",null);return 1===e.length?f.callback=function(){this.toAdd(e[0])}.bind(this):(f.dropdownItems=a.map(e,function(a){return{title:d[a].title,callback:function(){this.toAdd(a)}.bind(this)}}.bind(this)),c=[],this.options.config.displayTabAll===!0&&c.push({name:"public.all",key:null}),a.each(e,function(a){c.push({id:a,name:d[a].title,key:a}),a===i&&(h=d[a].title)}.bind(this)),g={componentOptions:{callback:this.typeChange.bind(this),preselector:"name",preselect:h},data:c}),{noBack:!0,tabs:g,toolbar:{buttons:{addArticle:{options:f},deleteSelected:{}},languageChanger:{data:this.options.config.languageChanger,preSelected:this.options.locale}}}},layout:{content:{width:"max"}},initialize:function(){if(this.options.type)this.storage.set("type",this.options.type);else if(this.storage.has("type")){var a=this.templates.route({type:this.storage.get("type"),locale:this.options.locale});this.sandbox.emit("sulu.router.navigate",a,!1,!1),this.options.type=this.storage.get("type")}this.render(),this.bindCustomEvents()},render:function(){this.$el.html(this.templates.list());var a="/admin/api/articles?sortBy=authored&sortOrder=desc&locale="+this.options.locale+(this.options.type?"&type="+this.options.type:""),b=this.getFilterFromStorage(),f=this.getFilterTitle(b.filterKey,b.contact,b.category);b.contact&&(a+="&contactId="+b.contact.id),b.category&&(a+="&categoryId="+b.category.id),this.sandbox.sulu.initListToolbarAndList.call(this,"article","/admin/api/articles/fields",{el:this.$find(".list-toolbar-container"),instanceName:"articles",template:this.retrieveListToolbarTemplate(f)},{el:this.sandbox.dom.find(".datagrid-container"),url:a,storageName:this.options.storageName,searchInstanceName:"articles",searchFields:["title"],resultKey:"articles",instanceName:"articles",actionCallback:function(a,b){"ghost"===b.localizationState.state?e.load(a,this.options.locale).then(function(b){d.openGhost.call(this,b,this.translations.openGhostOverlay).then(function(b,d){b?c.copyLocale.call(this,a,d,[this.options.locale],function(){this.toEdit(a)}.bind(this)):this.toEdit(a)}.bind(this))}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,data)}.bind(this)):this.toEdit(a)}.bind(this),viewOptions:{table:{actionIconColumn:"title",badges:[{column:"title",callback:function(a,b){return!(!a.localizationState||"ghost"!==a.localizationState.state||a.localizationState.locale===this.options.locale)&&(b.title=a.localizationState.locale,b)}.bind(this)},{column:"title",callback:function(a,b){var c="",d=this.translations.unpublished;return a.published&&!a.publishedState&&(d=this.translations.publishedWithDraft,c+=this.templates.publishedIcon({title:d})),a.publishedState||(c+=this.templates.draftIcon({title:d})),b.title=c,b.cssClass="badge-none",b}.bind(this)}]}}})},toEdit:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/edit:"+a+"/details")},toAdd:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/add"+(this.options.config.typeNames.length>1?":"+a:""))},toList:function(a){1!==this.options.config.typeNames.length&&this.options.type?this.sandbox.emit("sulu.router.navigate","articles:"+this.options.type+"/"+(a||this.options.locale)):this.sandbox.emit("sulu.router.navigate","articles/"+(a||this.options.locale))},deleteItems:function(b){e.remove(b,this.options.locale).then(function(){a.each(b,function(a){this.sandbox.emit("husky.datagrid.articles.record.remove",a)}.bind(this))}.bind(this))},typeChange:function(a){var b=this.templates.route({type:a.key,locale:this.options.locale});this.options.type=a.key,this.sandbox.emit("husky.datagrid.articles.url.update",{page:1,type:a.key}),this.sandbox.emit("sulu.router.navigate",b,!1,!1),this.storage.set("type",a.key)},getCopyLocaleUrl:function(a,b,c){return e.getCopyLocaleUrl(a,b,c)},bindCustomEvents:function(){this.sandbox.on("husky.datagrid.articles.number.selections",function(a){var b=a>0?"enable":"disable";this.sandbox.emit("sulu.header.toolbar.item."+b,"deleteSelected",!1)}.bind(this)),this.sandbox.on("sulu.toolbar.delete",function(){this.sandbox.emit("husky.datagrid.articles.items.get-selected",this.deleteItems.bind(this))}.bind(this)),this.sandbox.on("sulu.header.language-changed",function(a){a.id!==this.options.locale&&(this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),this.toList(a.id))}.bind(this)),this.sandbox.on("husky.toolbar.articles.initialized",function(){this.sandbox.emit("husky.toolbar.articles.item.mark",this.getFilterFromStorage().filterKey)}.bind(this))},retrieveListToolbarTemplate:function(a){return this.sandbox.sulu.buttons.get({settings:{options:{dropdownItems:[{type:"columnOptions"}]}},filter:{options:{icon:"filter",group:2,title:a,showTitle:!0,dropdownOptions:{idAttribute:"id",markSelected:!0,changeButton:!1},dropdownItems:[{id:"all",title:this.translations.filterAll,callback:function(){this.applyFilterToList.call(this,"all",null)}.bind(this)},{id:"me",title:this.translations.filterMe,callback:function(){this.applyFilterToList.call(this,"me",this.sandbox.sulu.user.contact)}.bind(this)},{id:"filterByAuthor",title:this.translations.filterByAuthor+"...",callback:this.openContactSelectionOverlay.bind(this)},{divider:!0},{id:"filterByCategory",title:this.translations.filterByCategory,callback:this.openCategorySelectionOverlay.bind(this)}]}}})},openContactSelectionOverlay:function(){var a=$("
");this.$el.append(a),this.sandbox.start([{name:"articles/list/contact-selection@suluarticle",options:{el:a,locale:this.options.locale,data:{contact:this.getFilterFromStorage().contact},selectCallback:function(a){this.applyFilterToList.call(this,"filterByAuthor",a.contactItem)}.bind(this)}}])},openCategorySelectionOverlay:function(){var a=$("
");this.$el.append(a),this.sandbox.start([{name:"articles/list/category-selection@suluarticle",options:{el:a,locale:this.options.locale,data:{category:this.getFilterFromStorage().category},selectCallback:function(a){this.applyFilterToList.call(this,"category",null,a.categoryItem)}.bind(this)}}])},applyFilterToList:function(a,b,c){this.storage.set("filter",{contact:b,category:c,filterKey:a});var d={contactId:b?b.id:null,categoryId:c?c.id:null};this.sandbox.emit("husky.datagrid.articles.url.update",d),this.sandbox.emit("husky.toolbar.articles.button.set","filter",{title:this.getFilterTitle(a,b,c)})},getFilterFromStorage:function(){return this.storage.getWithDefault("filter",{filterKey:"all",contact:null,category:null})},getFilterTitle:function(a,b,c){var d="";switch(a){case"all":d=this.translations.filterAll;break;case"filterByAuthor":d=this.translations.filterByAuthor+" "+b.firstName+" "+b.lastName;break;case"me":d=this.translations.filterMe;break;case"category":d=this.translations.filterByCategory+" "+c.name}return d}}}); \ No newline at end of file diff --git a/Resources/public/js/components/articles/list/category-selection/main.js b/Resources/public/js/components/articles/list/category-selection/main.js new file mode 100644 index 000000000..48bc0e453 --- /dev/null +++ b/Resources/public/js/components/articles/list/category-selection/main.js @@ -0,0 +1,125 @@ +/* + * This file is part of Sulu. + * + * (c) MASSIVE ART WebServices GmbH + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +define(['jquery'], function($) { + + 'use strict'; + + var defaults = { + options: { + data: { + contact: null + }, + selectCallback: function(data) { + }, + matchings: [ + {'name': 'name', 'content': 'Name'}, + {'name': 'id', 'disabled': true}, + {'name': 'children', 'disabled': true}, + {'name': 'parent', 'disabled': true} + ] + }, + translations: { + title: 'sulu_article.category-selection-overlay.title' + }, + templates: { + skeleton: [ + '
', + '
', + '
', + '
', + '
' + ].join('') + } + }; + + return { + + defaults: defaults, + + initialize: function() { + var $overlayContainer = $('
'); + this.$el.append($overlayContainer); + + this.data = this.options.data; + + // start overlay + this.sandbox.start([{ + name: 'overlay@husky', + options: { + el: $overlayContainer, + instanceName: 'category-selection', + openOnStart: true, + removeOnClose: true, + skin: 'medium', + slides: [ + { + title: this.translations.title, + data: $(this.templates.skeleton({ + translations: this.translations + })), + okCallback: this.okCallbackOverlay.bind(this) + } + ] + } + }]); + + this.sandbox.once('husky.overlay.category-selection.opened', function() { + this.sandbox.start([ + { + name: 'datagrid@husky', + options: { + el: $overlayContainer.find('.category-selection-list'), + instanceName: 'category-selection', + url: '/admin/api/categories?locale=' + this.options.locale + '&flat=true&sortBy=name&sortOrder=asc', + resultKey: 'categories', + sortable: false, + selectedCounter: false, + preselected: !!this.options.data.category ? [this.options.data.category.id] : [], + paginationOptions: { + dropdown: { + limit: 20 + } + }, + childrenPropertyName: 'hasChildren', + viewOptions: { + table: { + cropContents: false, + noItemsText: 'sulu.category.no-categories-available', + showHead: false, + cssClass: 'white-box', + selectItem: { + type: 'radio', + inFirstCell: true + } + } + }, + matchings: this.options.matchings + } + } + ]); + }.bind(this)); + }, + + /** + * OK callback of the overlay. + */ + okCallbackOverlay: function() { + this.sandbox.emit('husky.datagrid.category-selection.items.get-selected', function(ids, items) { + if (items.length > 0) { + this.data.categoryId = ids[0]; + this.data.categoryItem = items[0]; + } + + this.options.selectCallback(this.data); + this.sandbox.stop(); + }.bind(this), true); + } + }; +}); diff --git a/Resources/public/js/components/articles/list/main.js b/Resources/public/js/components/articles/list/main.js index 7c5ee612a..8aca73024 100644 --- a/Resources/public/js/components/articles/list/main.js +++ b/Resources/public/js/components/articles/list/main.js @@ -45,7 +45,8 @@ define([ publishedWithDraft: 'public.published-with-draft', filterMe: 'sulu_article.list.filter.me', filterAll: 'sulu_article.list.filter.all', - filterBy: 'sulu_article.list.filter.by', + filterByAuthor: 'sulu_article.list.filter.by-author', + filterByCategory: 'sulu_article.list.filter.by-category', openGhostOverlay: { info: 'sulu_article.settings.open-ghost-overlay.info', new: 'sulu_article.settings.open-ghost-overlay.new', @@ -172,11 +173,14 @@ define([ this.$el.html(this.templates.list()); var urlArticleApi = '/admin/api/articles?sortBy=authored&sortOrder=desc&locale=' + this.options.locale + (this.options.type ? ('&type=' + this.options.type) : ''); - var contactFilter = this.getContactFilterFromStorage(); - var filterTitle = this.getContactFilterTitle(contactFilter.filterKey, contactFilter.contact); + var filter = this.getFilterFromStorage(); + var filterTitle = this.getFilterTitle(filter.filterKey, filter.contact, filter.category); - if (!!contactFilter.contact) { - urlArticleApi += '&contactId=' + contactFilter.contact.id; + if (!!filter.contact) { + urlArticleApi += '&contactId=' + filter.contact.id; + } + if (!!filter.category) { + urlArticleApi += '&categoryId=' + filter.category.id; } this.sandbox.sulu.initListToolbarAndList.call(this, @@ -341,7 +345,7 @@ define([ }.bind(this)); this.sandbox.on('husky.toolbar.articles.initialized', function() { - this.sandbox.emit('husky.toolbar.articles.item.mark', this.getContactFilterFromStorage().filterKey); + this.sandbox.emit('husky.toolbar.articles.item.mark', this.getFilterFromStorage().filterKey); }.bind(this)); }, @@ -361,7 +365,7 @@ define([ ] } }, - contactIdFilter: { + filter: { options: { icon: 'filter', group: 2, @@ -396,9 +400,17 @@ define([ }.bind(this) }, { - id: 'filterBy', - title: this.translations.filterBy + '...', + id: 'filterByAuthor', + title: this.translations.filterByAuthor + '...', callback: this.openContactSelectionOverlay.bind(this) + }, + { + divider: true + }, + { + id: 'filterByCategory', + title: this.translations.filterByCategory, + callback: this.openCategorySelectionOverlay.bind(this) } ] } @@ -420,15 +432,42 @@ define([ el: $container, locale: this.options.locale, data: { - contact: this.getContactFilterFromStorage.call(this).contact + contact: this.getFilterFromStorage().contact }, selectCallback: function(data) { this.applyFilterToList.call( this, - 'filterBy', + 'filterByAuthor', data.contactItem ); - this.sandbox.emit('husky.overlay.contact-selection.close'); + }.bind(this) + } + }]); + }, + + /** + * Opens contact selection overlay. + */ + openCategorySelectionOverlay: function() { + var $container = $('
'); + + this.$el.append($container); + + this.sandbox.start([{ + name: 'articles/list/category-selection@suluarticle', + options: { + el: $container, + locale: this.options.locale, + data: { + category: this.getFilterFromStorage().category + }, + selectCallback: function(data) { + this.applyFilterToList.call( + this, + 'category', + null, + data.categoryItem + ); }.bind(this) } }]); @@ -440,15 +479,23 @@ define([ * * @param {string} filterKey * @param {Object} contact + * @param {Object} category */ - applyFilterToList: function(filterKey, contact) { - this.storage.set('contactFilter', { + applyFilterToList: function(filterKey, contact, category) { + this.storage.set('filter', { contact: contact, + category: category, filterKey: filterKey }); - this.sandbox.emit('husky.datagrid.articles.url.update', {contactId: contact ? contact.id : null}); - this.sandbox.emit('husky.toolbar.articles.button.set', 'contactIdFilter', { - title: this.getContactFilterTitle(filterKey, contact) + + var update = { + contactId: contact ? contact.id : null, + categoryId: category ? category.id : null + }; + + this.sandbox.emit('husky.datagrid.articles.url.update', update); + this.sandbox.emit('husky.toolbar.articles.button.set', 'filter', { + title: this.getFilterTitle(filterKey, contact, category) }); }, @@ -457,8 +504,8 @@ define([ * * @returns {Object} */ - getContactFilterFromStorage: function() { - return this.storage.getWithDefault('contactFilter', {filterKey: 'all', contact: null}); + getFilterFromStorage: function() { + return this.storage.getWithDefault('filter', {filterKey: 'all', contact: null, category: null}); }, /** @@ -466,21 +513,25 @@ define([ * * @param {String} filterKey * @param {Object} contact + * @param {Object} category * @return {String} */ - getContactFilterTitle: function(filterKey, contact) { + getFilterTitle: function(filterKey, contact, category) { var title = ''; switch(filterKey) { case 'all': title = this.translations.filterAll; break; - case 'filterBy': - title = this.translations.filterBy + ' ' + contact.firstName + ' ' + contact.lastName + case 'filterByAuthor': + title = this.translations.filterByAuthor + ' ' + contact.firstName + ' ' + contact.lastName; break; case 'me': title = this.translations.filterMe; break; + case 'category': + title = this.translations.filterByCategory + ' ' + category.name; + break; } return title; diff --git a/Resources/translations/sulu/backend.de.xlf b/Resources/translations/sulu/backend.de.xlf index 5fa6691a4..55ce72cd6 100644 --- a/Resources/translations/sulu/backend.de.xlf +++ b/Resources/translations/sulu/backend.de.xlf @@ -126,10 +126,14 @@ sulu_article.list.filter.all Alle - - sulu_article.list.filter.all + + sulu_article.list.filter.by-author Nur von + + sulu_article.list.filter.by-category + Nur Kategorie + sulu_article.contact-selection-overlay.title Artikel nach Kontakt filtern diff --git a/Resources/translations/sulu/backend.en.xlf b/Resources/translations/sulu/backend.en.xlf index aa79dc426..e29b8e8a4 100644 --- a/Resources/translations/sulu/backend.en.xlf +++ b/Resources/translations/sulu/backend.en.xlf @@ -126,10 +126,14 @@ sulu_article.list.filter.all All - - sulu_article.list.filter.all + + sulu_article.list.filter.by-author Only from + + sulu_article.list.filter.by-category + Only Category + sulu_article.contact-selection-overlay.title Filter article by contact diff --git a/Tests/Functional/Controller/ArticleControllerTest.php b/Tests/Functional/Controller/ArticleControllerTest.php index d492a646f..68e4680f0 100644 --- a/Tests/Functional/Controller/ArticleControllerTest.php +++ b/Tests/Functional/Controller/ArticleControllerTest.php @@ -13,6 +13,8 @@ use Sulu\Bundle\ArticleBundle\Document\ArticleDocument; use Sulu\Bundle\ArticleBundle\Document\Index\IndexerInterface; +use Sulu\Bundle\CategoryBundle\Entity\Category; +use Sulu\Bundle\ContactBundle\Entity\Contact; use Sulu\Bundle\MediaBundle\DataFixtures\ORM\LoadCollectionTypes; use Sulu\Bundle\MediaBundle\DataFixtures\ORM\LoadMediaTypes; use Sulu\Bundle\MediaBundle\Entity\Collection; @@ -767,6 +769,38 @@ function ($item) { $this->assertContains([$article2['id'], $article2['title'], ['state' => 'ghost', 'locale' => 'de']], $items); } + public function testCgetFilterByCategory() + { + $title = 'Test-Article'; + $template = 'default'; + $category = $this->createCategory(); + + $client = $this->createAuthenticatedClient(); + $client->request( + 'POST', + '/api/articles?locale=de', + [ + 'title' => $title, + 'template' => $template, + 'authored' => '2016-01-01', + 'ext' => ['excerpt' => ['categories' => [$category->getId()]]], + ] + ); + + $this->assertHttpStatusCode(200, $client->getResponse()); + + $article1 = json_decode($client->getResponse()->getContent(), true); + // create second article which should not appear in response + $article2 = $this->testPost(); + + $client->request('GET', '/api/articles?locale=de&categoryId=' . $category->getId()); + $this->assertHttpStatusCode(200, $client->getResponse()); + $result = json_decode($client->getResponse()->getContent(), true); + + $this->assertCount(1, $result['_embedded']['articles']); + $this->assertEquals($article1['id'], $result['_embedded']['articles'][0]['id']); + } + /** * @return Media */ @@ -785,6 +819,18 @@ private function createMedia() return $media; } + private function createCategory() + { + $entityManager = $this->getEntityManager(); + + $category = new Category(); + $category->setDefaultLocale('de'); + $entityManager->persist($category); + $entityManager->flush(); + + return $category; + } + private function purgeIndex() { /** @var IndexerInterface $indexer */