From 74193e681fc6b689f0ac6ef7fde324a287e27b13 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Thu, 11 Jun 2015 12:20:56 +0200 Subject: [PATCH 1/2] same behavior for issues filters and backlog filters all filter attributes are OR except tags related #2648 test with taiga-back refactoring-filter-data-API --- app/coffee/modules/backlog/filters.coffee | 45 ++++-- app/coffee/modules/backlog/main.coffee | 153 +++++++++--------- app/coffee/modules/issues/list.coffee | 68 +++++--- app/coffee/modules/resources.coffee | 2 + app/coffee/modules/resources/issues.coffee | 4 +- .../modules/resources/userstories.coffee | 3 + app/partials/backlog/backlog.jade | 4 +- .../includes/components/backlog-row.jade | 2 +- .../includes/modules/backlog-filters.jade | 2 +- .../includes/modules/issues-filters.jade | 2 +- 10 files changed, 160 insertions(+), 125 deletions(-) diff --git a/app/coffee/modules/backlog/filters.coffee b/app/coffee/modules/backlog/filters.coffee index bf6a4186..59b219fe 100644 --- a/app/coffee/modules/backlog/filters.coffee +++ b/app/coffee/modules/backlog/filters.coffee @@ -40,6 +40,8 @@ BacklogFiltersDirective = ($log, $location, $templates) -> templateSelected = $templates.get("backlog/filter-selected.html", true) link = ($scope, $el, $attrs) -> + currentFiltersType = '' + $ctrl = $el.closest(".wrapper").controller() selectedFilters = [] @@ -50,16 +52,18 @@ BacklogFiltersDirective = ($log, $location, $templates) -> $el.find("h2 a.subfilter span.title").html(title) $el.find("h2 a.subfilter span.title").prop("data-type", type) + currentFiltersType = getFiltersType() + showCategories = -> $el.find(".filters-cats").show() $el.find(".filter-list").addClass("hidden") $el.find("h2.breadcrumb").addClass("hidden") - initializeSelectedFilters = (filters) -> + initializeSelectedFilters = () -> showCategories() selectedFilters = [] - for name, values of filters + for name, values of $scope.filters for val in values selectedFilters.push(val) if val.selected @@ -81,26 +85,39 @@ BacklogFiltersDirective = ($log, $location, $templates) -> html = template({filters:filters}) $el.find(".filter-list").html(html) + getFiltersType = () -> + return $el.find("h2 a.subfilter span.title").prop('data-type') + toggleFilterSelection = (type, id) -> + currentFiltersType = getFiltersType() + filters = $scope.filters[type] - filter = _.find(filters, {id: taiga.toString(id)}) + filter = _.find(filters, {id: id}) filter.selected = (not filter.selected) + if filter.selected selectedFilters.push(filter) $scope.$apply -> $ctrl.selectFilter(type, id) else - selectedFilters = _.reject(selectedFilters, filter) - $scope.$apply -> - $ctrl.unselectFilter(type, id) + selectedFilters = _.reject selectedFilters, (selected) -> + return filter.type == selected.type && filter.id == selected.id + + $ctrl.unselectFilter(type, id) renderSelectedFilters(selectedFilters) - currentFiltersType = $el.find("h2 a.subfilter span.title").prop('data-type') if type == currentFiltersType renderFilters(_.reject(filters, "selected")) $ctrl.loadUserstories() + .then () -> + # reload the tags when a tag is select or unselected + # and the filters/tags is open + if currentFiltersType == 'tags' + $ctrl.generateFilters().then () -> + tags = $scope.filters["tags"] + renderFilters(_.reject(tags, "selected")) selectQFilter = debounceLeading 100, (value) -> return if value is undefined @@ -113,11 +130,15 @@ BacklogFiltersDirective = ($log, $location, $templates) -> $scope.$watch("filtersQ", selectQFilter) ## Angular Watchers - $scope.$on "filters:loaded", (ctx, filters) -> - initializeSelectedFilters(filters) + $scope.$on "backlog:loaded", (ctx) -> + initializeSelectedFilters() - $scope.$on "filters:update", (ctx, filters) -> - renderFilters(filters) + $scope.$on "filters:update", (ctx) -> + $ctrl.generateFilters().then () -> + filters = $scope.filters[currentFiltersType] + + if currentFiltersType + renderFilters(_.reject(filters, "selected")) ## Dom Event Handlers $el.on "click", ".filters-cats > ul > li > a", (event) -> @@ -126,7 +147,7 @@ BacklogFiltersDirective = ($log, $location, $templates) -> tags = $scope.filters[target.data("type")] renderFilters(_.reject(tags, "selected")) - showFilters(target.attr("title"), target.data("type")) + showFilters(target.attr("title"), target.data('type')) $el.on "click", ".filters-inner > .filters-step-cat > .breadcrumb > .back", (event) -> event.preventDefault() diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index 75bafc3e..fdcc1974 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -96,6 +96,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @scope.$on "usform:new:success", => @.loadUserstories() @.loadProjectStats() + + @rootscope.$broadcast("filters:update") @analytics.trackEvent("userstory", "create", "create userstory on backlog", 1) @scope.$on "sprintform:edit:success", => @@ -105,9 +107,11 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @.loadSprints() @.loadProjectStats() @.loadUserstories() + @rootscope.$broadcast("filters:update") @scope.$on "usform:edit:success", => @.loadUserstories() + @rootscope.$broadcast("filters:update") @scope.$on("sprint:us:move", @.moveUs) @scope.$on("sprint:us:moved", @.loadSprints) @@ -182,7 +186,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F resetFilters: -> selectedTags = _.filter(@scope.filters.tags, "selected") - selectedStatuses = _.filter(@scope.filters.statuses, "selected") + selectedStatuses = _.filter(@scope.filters.status, "selected") @scope.filtersQ = "" @@ -195,6 +199,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @.unselectFilter(item.type, item.id) @.loadUserstories() + @rootscope.$broadcast("filters:update") loadUserstories: -> @scope.httpParams = @.getUrlFilters() @@ -208,10 +213,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @scope.userstories = _.sortBy(userstories, "backlog_order") @.setSearchDataFilters() - @.filterVisibleUserstories() - @.generateFilters() - @rootscope.$broadcast("filters:loaded", @scope.filters) # The broadcast must be executed when the DOM has been fully reloaded. # We can't assure when this exactly happens so we need a defer scopeDefer @scope, => @@ -247,22 +249,10 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @.fillUsersAndRoles(project.members, project.roles) @.initializeSubscription() - return promise.then(=> @.loadBacklog()) - - filterVisibleUserstories: -> - @scope.visibleUserstories = [] - - # Filter by tags - @scope.visibleUserstories = _.reject @scope.userstories, (us) => - return _.some us.tags, (tag) => - return @isFilterSelected("tag", tag) - - # Filter by status - @scope.visibleUserstories = _.filter @scope.visibleUserstories, (us) => - if @searchdata["statuses"] && Object.keys(@searchdata["statuses"]).length - return @isFilterSelected("statuses", taiga.toString(us.status)) - - return true + return promise + .then(=> @.loadBacklog()) + .then(=> @.generateFilters()) + .then(=> @scope.$emit("backlog:loaded")) prepareBulkUpdateData: (uses, field="backlog_order") -> return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]}) @@ -333,13 +323,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @scope.$apply => # Add new us to backlog userstories list # @scope.userstories.splice(newUsIndex, 0, us) - # @scope.visibleUserstories.splice(newUsIndex, 0, us) args = [newUsIndex, 0].concat(usList) Array.prototype.splice.apply(@scope.userstories, args) - Array.prototype.splice.apply(@scope.visibleUserstories, args) - - # Execute the prefiltering of user stories - @.filterVisibleUserstories() # Remove the us from the sprint list. sprint = @scope.sprintsById[oldSprintId] @@ -376,8 +361,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # Remove moving us from backlog userstories lists. for us, key in usList - r = @scope.visibleUserstories.indexOf(us) - @scope.visibleUserstories.splice(r, 1) + r = @scope.userstories.indexOf(us) + @scope.userstories.splice(r, 1) r = @scope.userstories.indexOf(us) @scope.userstories.splice(r, 1) @@ -439,74 +424,82 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @searchdata[name][val] = true getUrlFilters: -> - return _.pick(@location.search(), "statuses", "tags", "q") + return _.pick(@location.search(), "status", "tags", "q") generateFilters: -> urlfilters = @.getUrlFilters() - @scope.filters = {} + @scope.filters = {} - #tags - plainTags = _.flatten(_.filter(_.map(@scope.visibleUserstories, "tags"))) - plainTags.sort() + loadFilters = {} + loadFilters.project = @scope.projectId + loadFilters.tags = urlfilters.tags - if plainTags.length == 0 and urlfilters["tags"] - plainTags.push(urlfilters["tags"]) + return @rs.userstories.filtersData(loadFilters).then (data) => + choicesFiltersFormat = (choices, type, byIdObject) => + _.map choices, (t) -> + return { + id: t[0], + name: byIdObject[t[0]].name, + color: byIdObject[t[0]].color, + count: t[1], + type: type} - @scope.filters.tags = _.map _.countBy(plainTags), (v, k) => - obj = { - id: k, - type: "tags", - name: k, - color: @scope.project.tags_colors[k], - count: v - } - obj.selected = true if @isFilterSelected("tags", obj.id) - return obj + tagsFilterFormat = (tags) => + return _.map tags, (t) => + return { + id: t[0], + name: t[0], + color: @scope.project.tags_colors[t[0]], + count: t[1], + type: "tags" + } - selectedTags = _.filter(@scope.filters.tags, "selected") - selectedTags = _.map(selectedTags, "name") + # Build filters data structure + @scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.usStatusById) + @scope.filters.tags = tagsFilterFormat(data.tags) - #status - plainStatuses = _.map(@scope.visibleUserstories, "status") + selectedTags = _.filter(@scope.filters.tags, "selected") + selectedTags = _.map(selectedTags, "id") - plainStatuses = _.filter plainStatuses, (status) => - if status - return status + selectedStatuses = _.filter(@scope.filters.status, "selected") + selectedStatuses = _.map(selectedStatuses, "id") - if plainStatuses.length == 0 and urlfilters["statuses"] - plainStatuses.push(urlfilters["statuses"]) + @.markSelectedFilters(@scope.filters, urlfilters) - @scope.filters.statuses = _.map _.countBy(plainStatuses), (v, k) => - obj = { - id: k, - type: "statuses", - name: @scope.usStatusById[k].name, - color: @scope.usStatusById[k].color, - count:v - } - obj.selected = true if @isFilterSelected("statuses", obj.id) + #store query params + @rs.userstories.storeQueryParams(@scope.projectId, { + "status": selectedStatuses, + "tags": selectedTags, + "project": @scope.projectId + "milestone": null + }) - return obj + markSelectedFilters: (filters, urlfilters) -> + # Build selected filters (from url) fast lookup data structure + searchdata = {} + for name, value of _.omit(urlfilters, "page", "orderBy") + if not searchdata[name]? + searchdata[name] = {} - selectedStatuses = _.filter(@scope.filters.statuses, "selected") - selectedStatuses = _.map(selectedStatuses, "id") + for val in "#{value}".split(",") + searchdata[name][val] = true - #store query params - @rs.userstories.storeQueryParams(@scope.projectId, { - "status": selectedStatuses, - "tags": selectedTags, - "project": @scope.projectId - "milestone": null - }) + isSelected = (type, id) -> + if searchdata[type]? and searchdata[type][id] + return true + return false + + for key, value of filters + for obj in value + obj.selected = if isSelected(obj.type, obj.id) then true else undefined ## Template actions updateUserStoryStatus: () -> @.setSearchDataFilters() - @.filterVisibleUserstories() - @.generateFilters() - @rootscope.$broadcast("filters:update", @scope.filters['statuses']) - @.loadProjectStats() + @.generateFilters().then () -> + @rootscope.$broadcast("filters:update") + @.loadProjectStats() editUserStory: (us) -> @rootscope.$broadcast("usform:edit", us) @@ -519,7 +512,6 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @confirm.askOnDelete(title, message).then (finish) => # We modify the userstories in scope so the user doesn't see the removed US for a while @scope.userstories = _.without(@scope.userstories, us) - @filterVisibleUserstories() promise = @.repo.remove(us) promise.then => finish() @@ -560,9 +552,9 @@ BacklogDirective = ($repo, $rootscope, $translate) -> total_points = stats.total_points current_sum = stats.assigned_points - return if not $scope.visibleUserstories + return if not $scope.userstories - for us, i in $scope.visibleUserstories + for us, i in $scope.userstories current_sum += us.total_points if current_sum > total_points @@ -603,7 +595,6 @@ BacklogDirective = ($repo, $rootscope, $translate) -> # Update the total of points $scope.sprints[0].total_points += totalExtraPoints - $ctrl.filterVisibleUserstories() $repo.saveAll(selectedUss).then -> $ctrl.loadSprints() $ctrl.loadProjectStats() @@ -725,7 +716,7 @@ BacklogDirective = ($repo, $rootscope, $translate) -> $el.find(".backlog-table-body").disableSelection() filters = $ctrl.getUrlFilters() - if filters.statuses || + if filters.status || filters.tags || filters.q showHideFilter($scope, $el, $ctrl) diff --git a/app/coffee/modules/issues/list.coffee b/app/coffee/modules/issues/list.coffee index d6fbf588..20c6cdc2 100644 --- a/app/coffee/modules/issues/list.coffee +++ b/app/coffee/modules/issues/list.coffee @@ -83,8 +83,6 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi @scope.$on "issueform:new:success", => @analytics.trackEvent("issue", "create", "create issue on issues list", 1) @.loadIssues() - @.loadFilters() - initializeSubscription: -> routingKey = "changes.project.#{@scope.projectId}.issues" @@ -115,9 +113,10 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi return project getUrlFilters: -> - filters = _.pick(@location.search(), "page", "tags", "statuses", "types", + filters = _.pick(@location.search(), "page", "tags", "status", "types", "q", "severities", "priorities", "assignedTo", "createdBy", "orderBy") + filters.page = 1 if not filters.page return filters @@ -180,9 +179,13 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi @scope.filters.myFilters = myFilters return myFilters + loadFilters = {} + loadFilters.project = @scope.projectId + loadFilters.tags = urlfilters.tags + # Load default filters data promise = promise.then => - return @rs.issues.filtersData(@scope.projectId) + return @rs.issues.filtersData(loadFilters) # Format filters and set them on scope return promise.then (data) => @@ -220,16 +223,17 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi } # Build filters data structure - @scope.filters.statuses = choicesFiltersFormat(data.statuses, "statuses", @scope.issueStatusById) + @scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.issueStatusById) @scope.filters.severities = choicesFiltersFormat(data.severities, "severities", @scope.severityById) @scope.filters.priorities = choicesFiltersFormat(data.priorities, "priorities", @scope.priorityById) @scope.filters.assignedTo = usersFiltersFormat(data.assigned_to, "assignedTo", "Unassigned") - @scope.filters.createdBy = usersFiltersFormat(data.created_by, "createdBy", "Unknown") + @scope.filters.createdBy = usersFiltersFormat(data.owners, "createdBy", "Unknown") @scope.filters.types = choicesFiltersFormat(data.types, "types", @scope.issueTypeById) @scope.filters.tags = tagsFilterFormat(data.tags) @.removeNotExistingFiltersFromUrl() @.markSelectedFilters(@scope.filters, urlfilters) + @rootscope.$broadcast("filters:loaded", @scope.filters) # We need to guarantee that the last petition done here is the finally used @@ -257,7 +261,7 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi name = "assigned_to" else if name == "createdBy" name = "owner" - else if name == "statuses" + else if name == "status" name = "status" else if name == "types" name = "type" @@ -272,14 +276,19 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi @scope.page = data.current @scope.count = data.count @scope.paginatedBy = data.paginatedBy + return data + return promise + loadInitialData: -> promise = @.loadProject() return promise.then (project) => - @.fillUsersAndRoles(project.members, project.roles) + @.fillUsersAndRoles(project.users, project.roles) @.initializeSubscription() - return @q.all([@.loadFilters(), @.loadIssues()]) + @.loadFilters() + + return @.loadIssues() saveCurrentFiltersTo: (newFilter) -> deferred = @q.defer() @@ -445,6 +454,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ link = ($scope, $el, $attrs) -> $ctrl = $el.closest(".wrapper").controller() + selectedFilters = [] showFilters = (title, type) -> @@ -506,7 +516,6 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ filters = $scope.filters[type] filterId = if type == 'tags' then taiga.toString(id) else id filter = _.find(filters, {id: filterId}) - filter.selected = (not filter.selected) # Convert id to null as string for properly @@ -515,18 +524,27 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ if filter.selected selectedFilters.push(filter) - $scope.$apply -> - $ctrl.selectFilter(type, id) - $ctrl.selectFilter("page", 1) - $ctrl.storeFilters() - $ctrl.loadIssues() + $ctrl.selectFilter(type, id) + $ctrl.selectFilter("page", 1) + $ctrl.storeFilters() else - selectedFilters = _.reject(selectedFilters, filter) - $scope.$apply -> - $ctrl.unselectFilter(type, id) - $ctrl.selectFilter("page", 1) - $ctrl.storeFilters() - $ctrl.loadIssues() + selectedFilters = _.reject selectedFilters, (f) -> + return f.id == filter.id && f.type == filter.type + + $ctrl.unselectFilter(type, id) + $ctrl.selectFilter("page", 1) + $ctrl.storeFilters() + + $ctrl.loadIssues() + .then () -> + # reload the tags when a tag is select or unselected + # and the filters/tags is open + if filter.type == 'tags' + $ctrl.loadFilters().then () -> + # re-render the tags if the tags filter is open + if currentFiltersType == 'tags' + tags = $scope.filters[filter.type] + renderFilters(_.reject(tags, "selected")) renderSelectedFilters(selectedFilters) @@ -539,7 +557,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ initializeSelectedFilters(filters) $scope.$on "filters:issueupdate", (ctx, filters) -> - html = template({filters:filters.statuses}) + html = template({filters:filters.status}) html = $compile(html)($scope) $el.find(".filter-list").html(html) @@ -708,7 +726,7 @@ IssueStatusInlineEditionDirective = ($repo, $template, $rootscope) -> event.stopPropagation() target = angular.element(event.currentTarget) - for filter in $scope.filters.statuses + for filter in $scope.filters.status if filter.id == issue.status filter.count-- @@ -720,13 +738,13 @@ IssueStatusInlineEditionDirective = ($repo, $template, $rootscope) -> $repo.save(issue).then -> $ctrl.loadIssues() - for filter in $scope.filters.statuses + for filter in $scope.filters.status if filter.id == issue.status filter.count++ $rootscope.$broadcast("filters:issueupdate", $scope.filters) - for filter in $scope.filters.statuses + for filter in $scope.filters.status if filter.id == issue.status filter.count++ $rootscope.$broadcast("filters:issueupdate", $scope.filters) diff --git a/app/coffee/modules/resources.coffee b/app/coffee/modules/resources.coffee index 991133c9..0bfd7199 100644 --- a/app/coffee/modules/resources.coffee +++ b/app/coffee/modules/resources.coffee @@ -82,6 +82,7 @@ urls = { "bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order" "bulk-update-us-sprint-order": "/userstories/bulk_update_sprint_order" "bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order" + "userstories-filters": "/userstories/filters_data" # Tasks "tasks": "/tasks" @@ -91,6 +92,7 @@ urls = { # Issues "issues": "/issues" "bulk-create-issues": "/issues/bulk_create" + "issues-filters": "/issues/filters_data" # Wiki pages "wiki": "/wiki" diff --git a/app/coffee/modules/resources/issues.coffee b/app/coffee/modules/resources/issues.coffee index bf7c27df..22cb0f05 100644 --- a/app/coffee/modules/resources/issues.coffee +++ b/app/coffee/modules/resources/issues.coffee @@ -58,8 +58,8 @@ resourceProvider = ($repo, $http, $urls, $storage, $q) -> service.stats = (projectId) -> return $repo.queryOneRaw("projects", "#{projectId}/issues_stats") - service.filtersData = (projectId) -> - return $repo.queryOneRaw("projects", "#{projectId}/issue_filters_data") + service.filtersData = (params) -> + return $repo.queryOneRaw("issues-filters", null, params) service.listValues = (projectId, type) -> params = {"project": projectId} diff --git a/app/coffee/modules/resources/userstories.coffee b/app/coffee/modules/resources/userstories.coffee index de2f8c9b..0d0fbd3d 100644 --- a/app/coffee/modules/resources/userstories.coffee +++ b/app/coffee/modules/resources/userstories.coffee @@ -41,6 +41,9 @@ resourceProvider = ($repo, $http, $urls, $storage) -> service.listInAllProjects = (filters) -> return $repo.queryMany("userstories", filters) + service.filtersData = (params) -> + return $repo.queryOneRaw("userstories-filters", null, params) + service.listUnassigned = (projectId, filters) -> params = {"project": projectId, "milestone": "null"} params = _.extend({}, params, filters or {}) diff --git a/app/partials/backlog/backlog.jade b/app/partials/backlog/backlog.jade index a4862387..c45275ef 100644 --- a/app/partials/backlog/backlog.jade +++ b/app/partials/backlog/backlog.jade @@ -34,10 +34,10 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl", span.text(translate="BACKLOG.TAGS.SHOW") include ../includes/components/addnewus - section.backlog-table(ng-class="{'hidden': !visibleUserstories.length}") + section.backlog-table(ng-class="{'hidden': !userstories.length}") include ../includes/modules/backlog-table - div.empty.empty-backlog(ng-class="{'hidden': visibleUserstories.length}", tg-backlog-empty-sortable) + div.empty.empty-backlog(ng-class="{'hidden': userstories.length}", tg-backlog-empty-sortable) span.icon.icon-backlog span.title(translate="BACKLOG.EMPTY") a(href="", title="{{'BACKLOG.CREATE_NEW_US' | translate}}", diff --git a/app/partials/includes/components/backlog-row.jade b/app/partials/includes/components/backlog-row.jade index fb8ebfc0..f375076b 100644 --- a/app/partials/includes/components/backlog-row.jade +++ b/app/partials/includes/components/backlog-row.jade @@ -1,4 +1,4 @@ -div.row.us-item-row(ng-repeat="us in visibleUserstories track by us.id", tg-bind-scope, ng-class="{blocked: us.is_blocked}", tg-class-permission="{'readonly': '!modify_us'}") +div.row.us-item-row(ng-repeat="us in userstories track by us.id", tg-bind-scope, ng-class="{blocked: us.is_blocked}", tg-class-permission="{'readonly': '!modify_us'}") div.user-stories div.tags-block(tg-colorize-tags="us.tags", tg-colorize-tags-type="backlog") div.user-story-name diff --git a/app/partials/includes/modules/backlog-filters.jade b/app/partials/includes/modules/backlog-filters.jade index 5533851d..056f65a0 100644 --- a/app/partials/includes/modules/backlog-filters.jade +++ b/app/partials/includes/modules/backlog-filters.jade @@ -18,7 +18,7 @@ section.filters div.filters-cats ul li - a(href="", title="{{'BACKLOG.FILTERS.FILTER_CATEGORY_STATUS' | translate}}", data-type="statuses") + a(href="", title="{{'BACKLOG.FILTERS.FILTER_CATEGORY_STATUS' | translate}}", data-type="status") span.title(translate="BACKLOG.FILTERS.FILTER_CATEGORY_STATUS") span.icon.icon-arrow-right li diff --git a/app/partials/includes/modules/issues-filters.jade b/app/partials/includes/modules/issues-filters.jade index 3b427086..ab735773 100644 --- a/app/partials/includes/modules/issues-filters.jade +++ b/app/partials/includes/modules/issues-filters.jade @@ -22,7 +22,7 @@ section.filters span.title(translate="ISSUES.FILTERS.CATEGORIES.TYPE") span.icon.icon-arrow-right li - a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.STATUS' | translate}}", data-type="statuses") + a(href="", title="{{ 'ISSUES.FILTERS.CATEGORIES.STATUS' | translate}}", data-type="status") span.title(translate="ISSUES.FILTERS.CATEGORIES.STATUS") span.icon.icon-arrow-right li From f98bb43c1d90eeebd28b494568853e8f849c4092 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Wed, 22 Jul 2015 10:13:53 +0200 Subject: [PATCH 2/2] new baclklog/issues filters implementation - all filter attributes are OR except tags --- app/coffee/modules/backlog/filters.coffee | 24 ++++---- app/coffee/modules/backlog/main.coffee | 32 ++++------- app/coffee/modules/issues/list.coffee | 69 ++++++++++++----------- app/partials/backlog/filters.jade | 4 ++ 4 files changed, 63 insertions(+), 66 deletions(-) diff --git a/app/coffee/modules/backlog/filters.coffee b/app/coffee/modules/backlog/filters.coffee index 59b219fe..eda23e8b 100644 --- a/app/coffee/modules/backlog/filters.coffee +++ b/app/coffee/modules/backlog/filters.coffee @@ -35,7 +35,7 @@ module = angular.module("taigaBacklog") ## Issues Filters Directive ############################################################################# -BacklogFiltersDirective = ($log, $location, $templates) -> +BacklogFiltersDirective = ($q, $log, $location, $templates) -> template = $templates.get("backlog/filters.html", true) templateSelected = $templates.get("backlog/filter-selected.html", true) @@ -88,6 +88,13 @@ BacklogFiltersDirective = ($log, $location, $templates) -> getFiltersType = () -> return $el.find("h2 a.subfilter span.title").prop('data-type') + reloadUserstories = () -> + currentFiltersType = getFiltersType() + + $q.all([$ctrl.loadUserstories(), $ctrl.generateFilters()]).then () -> + currentFilters = $scope.filters[currentFiltersType] + renderFilters(_.reject(currentFilters, "selected")) + toggleFilterSelection = (type, id) -> currentFiltersType = getFiltersType() @@ -110,22 +117,17 @@ BacklogFiltersDirective = ($log, $location, $templates) -> if type == currentFiltersType renderFilters(_.reject(filters, "selected")) - $ctrl.loadUserstories() - .then () -> - # reload the tags when a tag is select or unselected - # and the filters/tags is open - if currentFiltersType == 'tags' - $ctrl.generateFilters().then () -> - tags = $scope.filters["tags"] - renderFilters(_.reject(tags, "selected")) + reloadUserstories() selectQFilter = debounceLeading 100, (value) -> return if value is undefined + if value.length == 0 $ctrl.replaceFilter("q", null) else $ctrl.replaceFilter("q", value) - $ctrl.loadUserstories() + + reloadUserstories() $scope.$watch("filtersQ", selectQFilter) @@ -174,4 +176,4 @@ BacklogFiltersDirective = ($log, $location, $templates) -> return {link:link} -module.directive("tgBacklogFilters", ["$log", "$tgLocation", "$tgTemplate", BacklogFiltersDirective]) +module.directive("tgBacklogFilters", ["$q", "$log", "$tgLocation", "$tgTemplate", BacklogFiltersDirective]) diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index fdcc1974..ac50729c 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -149,10 +149,6 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F return stats - refreshTagsColors: -> - return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) => - @scope.project.tags_colors = tags_colors - unloadClosedSprints: -> @scope.$apply => @scope.closedSprints = [] @@ -205,10 +201,9 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F @scope.httpParams = @.getUrlFilters() @rs.userstories.storeQueryParams(@scope.projectId, @scope.httpParams) - promise = @q.all([@.refreshTagsColors(), @rs.userstories.listUnassigned(@scope.projectId, @scope.httpParams)]) + promise = @rs.userstories.listUnassigned(@scope.projectId, @scope.httpParams) - return promise.then (data) => - userstories = data[1] + return promise.then (userstories) => # NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files @scope.userstories = _.sortBy(userstories, "backlog_order") @@ -433,26 +428,21 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F loadFilters = {} loadFilters.project = @scope.projectId loadFilters.tags = urlfilters.tags + loadFilters.status = urlfilters.status + loadFilters.q = urlfilters.q + loadFilters.milestone = 'null' return @rs.userstories.filtersData(loadFilters).then (data) => choicesFiltersFormat = (choices, type, byIdObject) => _.map choices, (t) -> - return { - id: t[0], - name: byIdObject[t[0]].name, - color: byIdObject[t[0]].color, - count: t[1], - type: type} + t.type = type + return t tagsFilterFormat = (tags) => - return _.map tags, (t) => - return { - id: t[0], - name: t[0], - color: @scope.project.tags_colors[t[0]], - count: t[1], - type: "tags" - } + return _.map tags, (t) -> + t.id = t.name + t.type = 'tags' + return t # Build filters data structure @scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.usStatusById) diff --git a/app/coffee/modules/issues/list.coffee b/app/coffee/modules/issues/list.coffee index 20c6cdc2..0435e870 100644 --- a/app/coffee/modules/issues/list.coffee +++ b/app/coffee/modules/issues/list.coffee @@ -182,6 +182,13 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi loadFilters = {} loadFilters.project = @scope.projectId loadFilters.tags = urlfilters.tags + loadFilters.status = urlfilters.status + loadFilters.q = urlfilters.q + loadFilters.types = urlfilters.types + loadFilters.severities = urlfilters.severities + loadFilters.priorities = urlfilters.priorities + loadFilters.assigned_to = urlfilters.assignedTo + loadFilters.owner = urlfilters.createdBy # Load default filters data promise = promise.then => @@ -191,12 +198,11 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi return promise.then (data) => usersFiltersFormat = (users, type, unknownOption) => reformatedUsers = _.map users, (t) => - return { - id: t[0], - count: t[1], - type: type - name: if t[0] then @scope.usersById[t[0]].full_name_display else unknownOption - } + t.type = type + t.name = if t.full_name then t.full_name else unknownOption + + return t + unknownItem = _.remove(reformatedUsers, (u) -> not u.id) reformatedUsers = _.sortBy(reformatedUsers, (u) -> u.name.toUpperCase()) if unknownItem.length > 0 @@ -205,22 +211,14 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi choicesFiltersFormat = (choices, type, byIdObject) => _.map choices, (t) -> - return { - id: t[0], - name: byIdObject[t[0]].name, - color: byIdObject[t[0]].color, - count: t[1], - type: type} + t.type = type + return t tagsFilterFormat = (tags) => - return _.map tags, (t) => - return { - id: t[0], - name: t[0], - color: @scope.project.tags_colors[t[0]], - count: t[1], - type: "tags" - } + return _.map tags, (t) -> + t.id = t.name + t.type = 'tags' + return t # Build filters data structure @scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.issueStatusById) @@ -448,7 +446,7 @@ module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", "$compile", ## Issues Filters Directive ############################################################################# -IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $translate, $compile, $auth) -> +IssuesFiltersDirective = ($q, $log, $location, $rs, $confirm, $loading, $template, $translate, $compile, $auth) -> template = $template.get("issue/issues-filters.html", true) templateSelected = $template.get("issue/issues-filters-selected.html", true) @@ -500,6 +498,16 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ html = $compile(html)($scope) $el.find(".filter-list").html(html) + getFiltersType = () -> + return $el.find("h2 a.subfilter span.title").prop('data-type') + + reloadIssues = () -> + currentFiltersType = getFiltersType() + + $q.all([$ctrl.loadIssues(), $ctrl.loadFilters()]).then () -> + filters = $scope.filters[currentFiltersType] + renderFilters(_.reject(filters, "selected")) + toggleFilterSelection = (type, id) -> if type == "myFilters" $rs.issues.getMyFilters($scope.projectId).then (data) -> @@ -535,20 +543,12 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ $ctrl.selectFilter("page", 1) $ctrl.storeFilters() - $ctrl.loadIssues() - .then () -> - # reload the tags when a tag is select or unselected - # and the filters/tags is open - if filter.type == 'tags' - $ctrl.loadFilters().then () -> - # re-render the tags if the tags filter is open - if currentFiltersType == 'tags' - tags = $scope.filters[filter.type] - renderFilters(_.reject(tags, "selected")) + reloadIssues() renderSelectedFilters(selectedFilters) - currentFiltersType = $el.find("h2 a.subfilter span.title").prop('data-type') + currentFiltersType = getFiltersType() + if type == currentFiltersType renderFilters(_.reject(filters, "selected")) @@ -572,7 +572,8 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ else $ctrl.replaceFilter("q", value) $ctrl.storeFilters() - $ctrl.loadIssues() + + reloadIssues() $scope.$watch("filtersQ", selectQFilter) @@ -679,7 +680,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $ return {link:link} -module.directive("tgIssuesFilters", ["$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading", +module.directive("tgIssuesFilters", ["$q", "$log", "$tgLocation", "$tgResources", "$tgConfirm", "$tgLoading", "$tgTemplate", "$translate", "$compile", "$tgAuth", IssuesFiltersDirective]) diff --git a/app/partials/backlog/filters.jade b/app/partials/backlog/filters.jade index 05faf672..1d504108 100644 --- a/app/partials/backlog/filters.jade +++ b/app/partials/backlog/filters.jade @@ -3,11 +3,15 @@ a.single-filter.active(data-type!="<%- f.type %>", data-id!="<%- f.id %>") span.name(style!="<%- f.style %>") | <%- f.name %> + <% if (f.count){ %> span.number <%- f.count %> + <% } %> <% } else { %> a.single-filter(data-type!="<%- f.type %>", data-id!="<%- f.id %>") span.name(style!="<%- f.style %>") | <%- f.name %> + <% if (f.count){ %> span.number <%- f.count %> + <% } %> <% } %> <% }) %> \ No newline at end of file