Merge pull request #572 from taigaio/Issues/2648/fix-tag-filtering
same behavior for issues filters and backlog filtersstable
commit
e86caf338f
|
@ -35,11 +35,13 @@ module = angular.module("taigaBacklog")
|
||||||
## Issues Filters Directive
|
## Issues Filters Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
BacklogFiltersDirective = ($log, $location, $templates) ->
|
BacklogFiltersDirective = ($q, $log, $location, $templates) ->
|
||||||
template = $templates.get("backlog/filters.html", true)
|
template = $templates.get("backlog/filters.html", true)
|
||||||
templateSelected = $templates.get("backlog/filter-selected.html", true)
|
templateSelected = $templates.get("backlog/filter-selected.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
|
currentFiltersType = ''
|
||||||
|
|
||||||
$ctrl = $el.closest(".wrapper").controller()
|
$ctrl = $el.closest(".wrapper").controller()
|
||||||
selectedFilters = []
|
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").html(title)
|
||||||
$el.find("h2 a.subfilter span.title").prop("data-type", type)
|
$el.find("h2 a.subfilter span.title").prop("data-type", type)
|
||||||
|
|
||||||
|
currentFiltersType = getFiltersType()
|
||||||
|
|
||||||
showCategories = ->
|
showCategories = ->
|
||||||
$el.find(".filters-cats").show()
|
$el.find(".filters-cats").show()
|
||||||
$el.find(".filter-list").addClass("hidden")
|
$el.find(".filter-list").addClass("hidden")
|
||||||
$el.find("h2.breadcrumb").addClass("hidden")
|
$el.find("h2.breadcrumb").addClass("hidden")
|
||||||
|
|
||||||
initializeSelectedFilters = (filters) ->
|
initializeSelectedFilters = () ->
|
||||||
showCategories()
|
showCategories()
|
||||||
selectedFilters = []
|
selectedFilters = []
|
||||||
|
|
||||||
for name, values of filters
|
for name, values of $scope.filters
|
||||||
for val in values
|
for val in values
|
||||||
selectedFilters.push(val) if val.selected
|
selectedFilters.push(val) if val.selected
|
||||||
|
|
||||||
|
@ -81,43 +85,62 @@ BacklogFiltersDirective = ($log, $location, $templates) ->
|
||||||
html = template({filters:filters})
|
html = template({filters:filters})
|
||||||
$el.find(".filter-list").html(html)
|
$el.find(".filter-list").html(html)
|
||||||
|
|
||||||
|
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) ->
|
toggleFilterSelection = (type, id) ->
|
||||||
|
currentFiltersType = getFiltersType()
|
||||||
|
|
||||||
filters = $scope.filters[type]
|
filters = $scope.filters[type]
|
||||||
filter = _.find(filters, {id: taiga.toString(id)})
|
filter = _.find(filters, {id: id})
|
||||||
filter.selected = (not filter.selected)
|
filter.selected = (not filter.selected)
|
||||||
|
|
||||||
if filter.selected
|
if filter.selected
|
||||||
selectedFilters.push(filter)
|
selectedFilters.push(filter)
|
||||||
$scope.$apply ->
|
$scope.$apply ->
|
||||||
$ctrl.selectFilter(type, id)
|
$ctrl.selectFilter(type, id)
|
||||||
else
|
else
|
||||||
selectedFilters = _.reject(selectedFilters, filter)
|
selectedFilters = _.reject selectedFilters, (selected) ->
|
||||||
$scope.$apply ->
|
return filter.type == selected.type && filter.id == selected.id
|
||||||
|
|
||||||
$ctrl.unselectFilter(type, id)
|
$ctrl.unselectFilter(type, id)
|
||||||
|
|
||||||
renderSelectedFilters(selectedFilters)
|
renderSelectedFilters(selectedFilters)
|
||||||
|
|
||||||
currentFiltersType = $el.find("h2 a.subfilter span.title").prop('data-type')
|
|
||||||
if type == currentFiltersType
|
if type == currentFiltersType
|
||||||
renderFilters(_.reject(filters, "selected"))
|
renderFilters(_.reject(filters, "selected"))
|
||||||
|
|
||||||
$ctrl.loadUserstories()
|
reloadUserstories()
|
||||||
|
|
||||||
selectQFilter = debounceLeading 100, (value) ->
|
selectQFilter = debounceLeading 100, (value) ->
|
||||||
return if value is undefined
|
return if value is undefined
|
||||||
|
|
||||||
if value.length == 0
|
if value.length == 0
|
||||||
$ctrl.replaceFilter("q", null)
|
$ctrl.replaceFilter("q", null)
|
||||||
else
|
else
|
||||||
$ctrl.replaceFilter("q", value)
|
$ctrl.replaceFilter("q", value)
|
||||||
$ctrl.loadUserstories()
|
|
||||||
|
reloadUserstories()
|
||||||
|
|
||||||
$scope.$watch("filtersQ", selectQFilter)
|
$scope.$watch("filtersQ", selectQFilter)
|
||||||
|
|
||||||
## Angular Watchers
|
## Angular Watchers
|
||||||
$scope.$on "filters:loaded", (ctx, filters) ->
|
$scope.$on "backlog:loaded", (ctx) ->
|
||||||
initializeSelectedFilters(filters)
|
initializeSelectedFilters()
|
||||||
|
|
||||||
$scope.$on "filters:update", (ctx, filters) ->
|
$scope.$on "filters:update", (ctx) ->
|
||||||
renderFilters(filters)
|
$ctrl.generateFilters().then () ->
|
||||||
|
filters = $scope.filters[currentFiltersType]
|
||||||
|
|
||||||
|
if currentFiltersType
|
||||||
|
renderFilters(_.reject(filters, "selected"))
|
||||||
|
|
||||||
## Dom Event Handlers
|
## Dom Event Handlers
|
||||||
$el.on "click", ".filters-cats > ul > li > a", (event) ->
|
$el.on "click", ".filters-cats > ul > li > a", (event) ->
|
||||||
|
@ -126,7 +149,7 @@ BacklogFiltersDirective = ($log, $location, $templates) ->
|
||||||
tags = $scope.filters[target.data("type")]
|
tags = $scope.filters[target.data("type")]
|
||||||
|
|
||||||
renderFilters(_.reject(tags, "selected"))
|
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) ->
|
$el.on "click", ".filters-inner > .filters-step-cat > .breadcrumb > .back", (event) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -153,4 +176,4 @@ BacklogFiltersDirective = ($log, $location, $templates) ->
|
||||||
|
|
||||||
return {link:link}
|
return {link:link}
|
||||||
|
|
||||||
module.directive("tgBacklogFilters", ["$log", "$tgLocation", "$tgTemplate", BacklogFiltersDirective])
|
module.directive("tgBacklogFilters", ["$q", "$log", "$tgLocation", "$tgTemplate", BacklogFiltersDirective])
|
||||||
|
|
|
@ -96,6 +96,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@scope.$on "usform:new:success", =>
|
@scope.$on "usform:new:success", =>
|
||||||
@.loadUserstories()
|
@.loadUserstories()
|
||||||
@.loadProjectStats()
|
@.loadProjectStats()
|
||||||
|
|
||||||
|
@rootscope.$broadcast("filters:update")
|
||||||
@analytics.trackEvent("userstory", "create", "create userstory on backlog", 1)
|
@analytics.trackEvent("userstory", "create", "create userstory on backlog", 1)
|
||||||
|
|
||||||
@scope.$on "sprintform:edit:success", =>
|
@scope.$on "sprintform:edit:success", =>
|
||||||
|
@ -105,9 +107,11 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@.loadSprints()
|
@.loadSprints()
|
||||||
@.loadProjectStats()
|
@.loadProjectStats()
|
||||||
@.loadUserstories()
|
@.loadUserstories()
|
||||||
|
@rootscope.$broadcast("filters:update")
|
||||||
|
|
||||||
@scope.$on "usform:edit:success", =>
|
@scope.$on "usform:edit:success", =>
|
||||||
@.loadUserstories()
|
@.loadUserstories()
|
||||||
|
@rootscope.$broadcast("filters:update")
|
||||||
|
|
||||||
@scope.$on("sprint:us:move", @.moveUs)
|
@scope.$on("sprint:us:move", @.moveUs)
|
||||||
@scope.$on("sprint:us:moved", @.loadSprints)
|
@scope.$on("sprint:us:moved", @.loadSprints)
|
||||||
|
@ -145,10 +149,6 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
refreshTagsColors: ->
|
|
||||||
return @rs.projects.tagsColors(@scope.projectId).then (tags_colors) =>
|
|
||||||
@scope.project.tags_colors = tags_colors
|
|
||||||
|
|
||||||
unloadClosedSprints: ->
|
unloadClosedSprints: ->
|
||||||
@scope.$apply =>
|
@scope.$apply =>
|
||||||
@scope.closedSprints = []
|
@scope.closedSprints = []
|
||||||
|
@ -182,7 +182,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
|
|
||||||
resetFilters: ->
|
resetFilters: ->
|
||||||
selectedTags = _.filter(@scope.filters.tags, "selected")
|
selectedTags = _.filter(@scope.filters.tags, "selected")
|
||||||
selectedStatuses = _.filter(@scope.filters.statuses, "selected")
|
selectedStatuses = _.filter(@scope.filters.status, "selected")
|
||||||
|
|
||||||
@scope.filtersQ = ""
|
@scope.filtersQ = ""
|
||||||
|
|
||||||
|
@ -195,23 +195,20 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@.unselectFilter(item.type, item.id)
|
@.unselectFilter(item.type, item.id)
|
||||||
|
|
||||||
@.loadUserstories()
|
@.loadUserstories()
|
||||||
|
@rootscope.$broadcast("filters:update")
|
||||||
|
|
||||||
loadUserstories: ->
|
loadUserstories: ->
|
||||||
@scope.httpParams = @.getUrlFilters()
|
@scope.httpParams = @.getUrlFilters()
|
||||||
@rs.userstories.storeQueryParams(@scope.projectId, @scope.httpParams)
|
@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) =>
|
return promise.then (userstories) =>
|
||||||
userstories = data[1]
|
|
||||||
# NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files
|
# NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files
|
||||||
@scope.userstories = _.sortBy(userstories, "backlog_order")
|
@scope.userstories = _.sortBy(userstories, "backlog_order")
|
||||||
|
|
||||||
@.setSearchDataFilters()
|
@.setSearchDataFilters()
|
||||||
@.filterVisibleUserstories()
|
|
||||||
@.generateFilters()
|
|
||||||
|
|
||||||
@rootscope.$broadcast("filters:loaded", @scope.filters)
|
|
||||||
# The broadcast must be executed when the DOM has been fully reloaded.
|
# 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
|
# We can't assure when this exactly happens so we need a defer
|
||||||
scopeDefer @scope, =>
|
scopeDefer @scope, =>
|
||||||
|
@ -247,22 +244,10 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@.fillUsersAndRoles(project.members, project.roles)
|
@.fillUsersAndRoles(project.members, project.roles)
|
||||||
@.initializeSubscription()
|
@.initializeSubscription()
|
||||||
|
|
||||||
return promise.then(=> @.loadBacklog())
|
return promise
|
||||||
|
.then(=> @.loadBacklog())
|
||||||
filterVisibleUserstories: ->
|
.then(=> @.generateFilters())
|
||||||
@scope.visibleUserstories = []
|
.then(=> @scope.$emit("backlog:loaded"))
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
prepareBulkUpdateData: (uses, field="backlog_order") ->
|
prepareBulkUpdateData: (uses, field="backlog_order") ->
|
||||||
return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]})
|
return _.map(uses, (x) -> {"us_id": x.id, "order": x[field]})
|
||||||
|
@ -333,13 +318,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@scope.$apply =>
|
@scope.$apply =>
|
||||||
# Add new us to backlog userstories list
|
# Add new us to backlog userstories list
|
||||||
# @scope.userstories.splice(newUsIndex, 0, us)
|
# @scope.userstories.splice(newUsIndex, 0, us)
|
||||||
# @scope.visibleUserstories.splice(newUsIndex, 0, us)
|
|
||||||
args = [newUsIndex, 0].concat(usList)
|
args = [newUsIndex, 0].concat(usList)
|
||||||
Array.prototype.splice.apply(@scope.userstories, args)
|
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.
|
# Remove the us from the sprint list.
|
||||||
sprint = @scope.sprintsById[oldSprintId]
|
sprint = @scope.sprintsById[oldSprintId]
|
||||||
|
@ -376,8 +356,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
|
|
||||||
# Remove moving us from backlog userstories lists.
|
# Remove moving us from backlog userstories lists.
|
||||||
for us, key in usList
|
for us, key in usList
|
||||||
r = @scope.visibleUserstories.indexOf(us)
|
r = @scope.userstories.indexOf(us)
|
||||||
@scope.visibleUserstories.splice(r, 1)
|
@scope.userstories.splice(r, 1)
|
||||||
|
|
||||||
r = @scope.userstories.indexOf(us)
|
r = @scope.userstories.indexOf(us)
|
||||||
@scope.userstories.splice(r, 1)
|
@scope.userstories.splice(r, 1)
|
||||||
|
@ -439,58 +419,43 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@searchdata[name][val] = true
|
@searchdata[name][val] = true
|
||||||
|
|
||||||
getUrlFilters: ->
|
getUrlFilters: ->
|
||||||
return _.pick(@location.search(), "statuses", "tags", "q")
|
return _.pick(@location.search(), "status", "tags", "q")
|
||||||
|
|
||||||
generateFilters: ->
|
generateFilters: ->
|
||||||
urlfilters = @.getUrlFilters()
|
urlfilters = @.getUrlFilters()
|
||||||
@scope.filters = {}
|
@scope.filters = {}
|
||||||
|
|
||||||
#tags
|
loadFilters = {}
|
||||||
plainTags = _.flatten(_.filter(_.map(@scope.visibleUserstories, "tags")))
|
loadFilters.project = @scope.projectId
|
||||||
plainTags.sort()
|
loadFilters.tags = urlfilters.tags
|
||||||
|
loadFilters.status = urlfilters.status
|
||||||
|
loadFilters.q = urlfilters.q
|
||||||
|
loadFilters.milestone = 'null'
|
||||||
|
|
||||||
if plainTags.length == 0 and urlfilters["tags"]
|
return @rs.userstories.filtersData(loadFilters).then (data) =>
|
||||||
plainTags.push(urlfilters["tags"])
|
choicesFiltersFormat = (choices, type, byIdObject) =>
|
||||||
|
_.map choices, (t) ->
|
||||||
|
t.type = type
|
||||||
|
return t
|
||||||
|
|
||||||
@scope.filters.tags = _.map _.countBy(plainTags), (v, k) =>
|
tagsFilterFormat = (tags) =>
|
||||||
obj = {
|
return _.map tags, (t) ->
|
||||||
id: k,
|
t.id = t.name
|
||||||
type: "tags",
|
t.type = 'tags'
|
||||||
name: k,
|
return t
|
||||||
color: @scope.project.tags_colors[k],
|
|
||||||
count: v
|
# Build filters data structure
|
||||||
}
|
@scope.filters.status = choicesFiltersFormat(data.statuses, "status", @scope.usStatusById)
|
||||||
obj.selected = true if @isFilterSelected("tags", obj.id)
|
@scope.filters.tags = tagsFilterFormat(data.tags)
|
||||||
return obj
|
|
||||||
|
|
||||||
selectedTags = _.filter(@scope.filters.tags, "selected")
|
selectedTags = _.filter(@scope.filters.tags, "selected")
|
||||||
selectedTags = _.map(selectedTags, "name")
|
selectedTags = _.map(selectedTags, "id")
|
||||||
|
|
||||||
#status
|
selectedStatuses = _.filter(@scope.filters.status, "selected")
|
||||||
plainStatuses = _.map(@scope.visibleUserstories, "status")
|
|
||||||
|
|
||||||
plainStatuses = _.filter plainStatuses, (status) =>
|
|
||||||
if status
|
|
||||||
return status
|
|
||||||
|
|
||||||
if plainStatuses.length == 0 and urlfilters["statuses"]
|
|
||||||
plainStatuses.push(urlfilters["statuses"])
|
|
||||||
|
|
||||||
@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)
|
|
||||||
|
|
||||||
return obj
|
|
||||||
|
|
||||||
selectedStatuses = _.filter(@scope.filters.statuses, "selected")
|
|
||||||
selectedStatuses = _.map(selectedStatuses, "id")
|
selectedStatuses = _.map(selectedStatuses, "id")
|
||||||
|
|
||||||
|
@.markSelectedFilters(@scope.filters, urlfilters)
|
||||||
|
|
||||||
#store query params
|
#store query params
|
||||||
@rs.userstories.storeQueryParams(@scope.projectId, {
|
@rs.userstories.storeQueryParams(@scope.projectId, {
|
||||||
"status": selectedStatuses,
|
"status": selectedStatuses,
|
||||||
|
@ -499,13 +464,31 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
"milestone": null
|
"milestone": null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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] = {}
|
||||||
|
|
||||||
|
for val in "#{value}".split(",")
|
||||||
|
searchdata[name][val] = true
|
||||||
|
|
||||||
|
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
|
## Template actions
|
||||||
|
|
||||||
updateUserStoryStatus: () ->
|
updateUserStoryStatus: () ->
|
||||||
@.setSearchDataFilters()
|
@.setSearchDataFilters()
|
||||||
@.filterVisibleUserstories()
|
@.generateFilters().then () ->
|
||||||
@.generateFilters()
|
@rootscope.$broadcast("filters:update")
|
||||||
@rootscope.$broadcast("filters:update", @scope.filters['statuses'])
|
|
||||||
@.loadProjectStats()
|
@.loadProjectStats()
|
||||||
|
|
||||||
editUserStory: (us) ->
|
editUserStory: (us) ->
|
||||||
|
@ -519,7 +502,6 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
||||||
@confirm.askOnDelete(title, message).then (finish) =>
|
@confirm.askOnDelete(title, message).then (finish) =>
|
||||||
# We modify the userstories in scope so the user doesn't see the removed US for a while
|
# We modify the userstories in scope so the user doesn't see the removed US for a while
|
||||||
@scope.userstories = _.without(@scope.userstories, us)
|
@scope.userstories = _.without(@scope.userstories, us)
|
||||||
@filterVisibleUserstories()
|
|
||||||
promise = @.repo.remove(us)
|
promise = @.repo.remove(us)
|
||||||
promise.then =>
|
promise.then =>
|
||||||
finish()
|
finish()
|
||||||
|
@ -560,9 +542,9 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
||||||
total_points = stats.total_points
|
total_points = stats.total_points
|
||||||
current_sum = stats.assigned_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
|
current_sum += us.total_points
|
||||||
|
|
||||||
if current_sum > total_points
|
if current_sum > total_points
|
||||||
|
@ -603,7 +585,6 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
||||||
# Update the total of points
|
# Update the total of points
|
||||||
$scope.sprints[0].total_points += totalExtraPoints
|
$scope.sprints[0].total_points += totalExtraPoints
|
||||||
|
|
||||||
$ctrl.filterVisibleUserstories()
|
|
||||||
$repo.saveAll(selectedUss).then ->
|
$repo.saveAll(selectedUss).then ->
|
||||||
$ctrl.loadSprints()
|
$ctrl.loadSprints()
|
||||||
$ctrl.loadProjectStats()
|
$ctrl.loadProjectStats()
|
||||||
|
@ -725,7 +706,7 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
||||||
$el.find(".backlog-table-body").disableSelection()
|
$el.find(".backlog-table-body").disableSelection()
|
||||||
|
|
||||||
filters = $ctrl.getUrlFilters()
|
filters = $ctrl.getUrlFilters()
|
||||||
if filters.statuses ||
|
if filters.status ||
|
||||||
filters.tags ||
|
filters.tags ||
|
||||||
filters.q
|
filters.q
|
||||||
showHideFilter($scope, $el, $ctrl)
|
showHideFilter($scope, $el, $ctrl)
|
||||||
|
|
|
@ -83,8 +83,6 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
@scope.$on "issueform:new:success", =>
|
@scope.$on "issueform:new:success", =>
|
||||||
@analytics.trackEvent("issue", "create", "create issue on issues list", 1)
|
@analytics.trackEvent("issue", "create", "create issue on issues list", 1)
|
||||||
@.loadIssues()
|
@.loadIssues()
|
||||||
@.loadFilters()
|
|
||||||
|
|
||||||
|
|
||||||
initializeSubscription: ->
|
initializeSubscription: ->
|
||||||
routingKey = "changes.project.#{@scope.projectId}.issues"
|
routingKey = "changes.project.#{@scope.projectId}.issues"
|
||||||
|
@ -115,9 +113,10 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
return project
|
return project
|
||||||
|
|
||||||
getUrlFilters: ->
|
getUrlFilters: ->
|
||||||
filters = _.pick(@location.search(), "page", "tags", "statuses", "types",
|
filters = _.pick(@location.search(), "page", "tags", "status", "types",
|
||||||
"q", "severities", "priorities",
|
"q", "severities", "priorities",
|
||||||
"assignedTo", "createdBy", "orderBy")
|
"assignedTo", "createdBy", "orderBy")
|
||||||
|
|
||||||
filters.page = 1 if not filters.page
|
filters.page = 1 if not filters.page
|
||||||
return filters
|
return filters
|
||||||
|
|
||||||
|
@ -180,20 +179,30 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
@scope.filters.myFilters = myFilters
|
@scope.filters.myFilters = myFilters
|
||||||
return myFilters
|
return myFilters
|
||||||
|
|
||||||
|
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
|
# Load default filters data
|
||||||
promise = promise.then =>
|
promise = promise.then =>
|
||||||
return @rs.issues.filtersData(@scope.projectId)
|
return @rs.issues.filtersData(loadFilters)
|
||||||
|
|
||||||
# Format filters and set them on scope
|
# Format filters and set them on scope
|
||||||
return promise.then (data) =>
|
return promise.then (data) =>
|
||||||
usersFiltersFormat = (users, type, unknownOption) =>
|
usersFiltersFormat = (users, type, unknownOption) =>
|
||||||
reformatedUsers = _.map users, (t) =>
|
reformatedUsers = _.map users, (t) =>
|
||||||
return {
|
t.type = type
|
||||||
id: t[0],
|
t.name = if t.full_name then t.full_name else unknownOption
|
||||||
count: t[1],
|
|
||||||
type: type
|
return t
|
||||||
name: if t[0] then @scope.usersById[t[0]].full_name_display else unknownOption
|
|
||||||
}
|
|
||||||
unknownItem = _.remove(reformatedUsers, (u) -> not u.id)
|
unknownItem = _.remove(reformatedUsers, (u) -> not u.id)
|
||||||
reformatedUsers = _.sortBy(reformatedUsers, (u) -> u.name.toUpperCase())
|
reformatedUsers = _.sortBy(reformatedUsers, (u) -> u.name.toUpperCase())
|
||||||
if unknownItem.length > 0
|
if unknownItem.length > 0
|
||||||
|
@ -202,34 +211,27 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
|
|
||||||
choicesFiltersFormat = (choices, type, byIdObject) =>
|
choicesFiltersFormat = (choices, type, byIdObject) =>
|
||||||
_.map choices, (t) ->
|
_.map choices, (t) ->
|
||||||
return {
|
t.type = type
|
||||||
id: t[0],
|
return t
|
||||||
name: byIdObject[t[0]].name,
|
|
||||||
color: byIdObject[t[0]].color,
|
|
||||||
count: t[1],
|
|
||||||
type: type}
|
|
||||||
|
|
||||||
tagsFilterFormat = (tags) =>
|
tagsFilterFormat = (tags) =>
|
||||||
return _.map tags, (t) =>
|
return _.map tags, (t) ->
|
||||||
return {
|
t.id = t.name
|
||||||
id: t[0],
|
t.type = 'tags'
|
||||||
name: t[0],
|
return t
|
||||||
color: @scope.project.tags_colors[t[0]],
|
|
||||||
count: t[1],
|
|
||||||
type: "tags"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build filters data structure
|
# 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.severities = choicesFiltersFormat(data.severities, "severities", @scope.severityById)
|
||||||
@scope.filters.priorities = choicesFiltersFormat(data.priorities, "priorities", @scope.priorityById)
|
@scope.filters.priorities = choicesFiltersFormat(data.priorities, "priorities", @scope.priorityById)
|
||||||
@scope.filters.assignedTo = usersFiltersFormat(data.assigned_to, "assignedTo", "Unassigned")
|
@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.types = choicesFiltersFormat(data.types, "types", @scope.issueTypeById)
|
||||||
@scope.filters.tags = tagsFilterFormat(data.tags)
|
@scope.filters.tags = tagsFilterFormat(data.tags)
|
||||||
|
|
||||||
@.removeNotExistingFiltersFromUrl()
|
@.removeNotExistingFiltersFromUrl()
|
||||||
@.markSelectedFilters(@scope.filters, urlfilters)
|
@.markSelectedFilters(@scope.filters, urlfilters)
|
||||||
|
|
||||||
@rootscope.$broadcast("filters:loaded", @scope.filters)
|
@rootscope.$broadcast("filters:loaded", @scope.filters)
|
||||||
|
|
||||||
# We need to guarantee that the last petition done here is the finally used
|
# We need to guarantee that the last petition done here is the finally used
|
||||||
|
@ -257,7 +259,7 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
name = "assigned_to"
|
name = "assigned_to"
|
||||||
else if name == "createdBy"
|
else if name == "createdBy"
|
||||||
name = "owner"
|
name = "owner"
|
||||||
else if name == "statuses"
|
else if name == "status"
|
||||||
name = "status"
|
name = "status"
|
||||||
else if name == "types"
|
else if name == "types"
|
||||||
name = "type"
|
name = "type"
|
||||||
|
@ -272,14 +274,19 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi
|
||||||
@scope.page = data.current
|
@scope.page = data.current
|
||||||
@scope.count = data.count
|
@scope.count = data.count
|
||||||
@scope.paginatedBy = data.paginatedBy
|
@scope.paginatedBy = data.paginatedBy
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
return promise
|
||||||
|
|
||||||
loadInitialData: ->
|
loadInitialData: ->
|
||||||
promise = @.loadProject()
|
promise = @.loadProject()
|
||||||
return promise.then (project) =>
|
return promise.then (project) =>
|
||||||
@.fillUsersAndRoles(project.members, project.roles)
|
@.fillUsersAndRoles(project.users, project.roles)
|
||||||
@.initializeSubscription()
|
@.initializeSubscription()
|
||||||
return @q.all([@.loadFilters(), @.loadIssues()])
|
@.loadFilters()
|
||||||
|
|
||||||
|
return @.loadIssues()
|
||||||
|
|
||||||
saveCurrentFiltersTo: (newFilter) ->
|
saveCurrentFiltersTo: (newFilter) ->
|
||||||
deferred = @q.defer()
|
deferred = @q.defer()
|
||||||
|
@ -439,12 +446,13 @@ module.directive("tgIssues", ["$log", "$tgLocation", "$tgTemplate", "$compile",
|
||||||
## Issues Filters Directive
|
## 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)
|
template = $template.get("issue/issues-filters.html", true)
|
||||||
templateSelected = $template.get("issue/issues-filters-selected.html", true)
|
templateSelected = $template.get("issue/issues-filters-selected.html", true)
|
||||||
|
|
||||||
link = ($scope, $el, $attrs) ->
|
link = ($scope, $el, $attrs) ->
|
||||||
$ctrl = $el.closest(".wrapper").controller()
|
$ctrl = $el.closest(".wrapper").controller()
|
||||||
|
|
||||||
selectedFilters = []
|
selectedFilters = []
|
||||||
|
|
||||||
showFilters = (title, type) ->
|
showFilters = (title, type) ->
|
||||||
|
@ -490,6 +498,16 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $
|
||||||
html = $compile(html)($scope)
|
html = $compile(html)($scope)
|
||||||
$el.find(".filter-list").html(html)
|
$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) ->
|
toggleFilterSelection = (type, id) ->
|
||||||
if type == "myFilters"
|
if type == "myFilters"
|
||||||
$rs.issues.getMyFilters($scope.projectId).then (data) ->
|
$rs.issues.getMyFilters($scope.projectId).then (data) ->
|
||||||
|
@ -506,7 +524,6 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $
|
||||||
filters = $scope.filters[type]
|
filters = $scope.filters[type]
|
||||||
filterId = if type == 'tags' then taiga.toString(id) else id
|
filterId = if type == 'tags' then taiga.toString(id) else id
|
||||||
filter = _.find(filters, {id: filterId})
|
filter = _.find(filters, {id: filterId})
|
||||||
|
|
||||||
filter.selected = (not filter.selected)
|
filter.selected = (not filter.selected)
|
||||||
|
|
||||||
# Convert id to null as string for properly
|
# Convert id to null as string for properly
|
||||||
|
@ -515,22 +532,23 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $
|
||||||
|
|
||||||
if filter.selected
|
if filter.selected
|
||||||
selectedFilters.push(filter)
|
selectedFilters.push(filter)
|
||||||
$scope.$apply ->
|
|
||||||
$ctrl.selectFilter(type, id)
|
$ctrl.selectFilter(type, id)
|
||||||
$ctrl.selectFilter("page", 1)
|
$ctrl.selectFilter("page", 1)
|
||||||
$ctrl.storeFilters()
|
$ctrl.storeFilters()
|
||||||
$ctrl.loadIssues()
|
|
||||||
else
|
else
|
||||||
selectedFilters = _.reject(selectedFilters, filter)
|
selectedFilters = _.reject selectedFilters, (f) ->
|
||||||
$scope.$apply ->
|
return f.id == filter.id && f.type == filter.type
|
||||||
|
|
||||||
$ctrl.unselectFilter(type, id)
|
$ctrl.unselectFilter(type, id)
|
||||||
$ctrl.selectFilter("page", 1)
|
$ctrl.selectFilter("page", 1)
|
||||||
$ctrl.storeFilters()
|
$ctrl.storeFilters()
|
||||||
$ctrl.loadIssues()
|
|
||||||
|
reloadIssues()
|
||||||
|
|
||||||
renderSelectedFilters(selectedFilters)
|
renderSelectedFilters(selectedFilters)
|
||||||
|
|
||||||
currentFiltersType = $el.find("h2 a.subfilter span.title").prop('data-type')
|
currentFiltersType = getFiltersType()
|
||||||
|
|
||||||
if type == currentFiltersType
|
if type == currentFiltersType
|
||||||
renderFilters(_.reject(filters, "selected"))
|
renderFilters(_.reject(filters, "selected"))
|
||||||
|
|
||||||
|
@ -539,7 +557,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $
|
||||||
initializeSelectedFilters(filters)
|
initializeSelectedFilters(filters)
|
||||||
|
|
||||||
$scope.$on "filters:issueupdate", (ctx, filters) ->
|
$scope.$on "filters:issueupdate", (ctx, filters) ->
|
||||||
html = template({filters:filters.statuses})
|
html = template({filters:filters.status})
|
||||||
html = $compile(html)($scope)
|
html = $compile(html)($scope)
|
||||||
$el.find(".filter-list").html(html)
|
$el.find(".filter-list").html(html)
|
||||||
|
|
||||||
|
@ -554,7 +572,8 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $
|
||||||
else
|
else
|
||||||
$ctrl.replaceFilter("q", value)
|
$ctrl.replaceFilter("q", value)
|
||||||
$ctrl.storeFilters()
|
$ctrl.storeFilters()
|
||||||
$ctrl.loadIssues()
|
|
||||||
|
reloadIssues()
|
||||||
|
|
||||||
$scope.$watch("filtersQ", selectQFilter)
|
$scope.$watch("filtersQ", selectQFilter)
|
||||||
|
|
||||||
|
@ -661,7 +680,7 @@ IssuesFiltersDirective = ($log, $location, $rs, $confirm, $loading, $template, $
|
||||||
|
|
||||||
return {link:link}
|
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])
|
"$tgTemplate", "$translate", "$compile", "$tgAuth", IssuesFiltersDirective])
|
||||||
|
|
||||||
|
|
||||||
|
@ -708,7 +727,7 @@ IssueStatusInlineEditionDirective = ($repo, $template, $rootscope) ->
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
target = angular.element(event.currentTarget)
|
target = angular.element(event.currentTarget)
|
||||||
|
|
||||||
for filter in $scope.filters.statuses
|
for filter in $scope.filters.status
|
||||||
if filter.id == issue.status
|
if filter.id == issue.status
|
||||||
filter.count--
|
filter.count--
|
||||||
|
|
||||||
|
@ -720,13 +739,13 @@ IssueStatusInlineEditionDirective = ($repo, $template, $rootscope) ->
|
||||||
$repo.save(issue).then ->
|
$repo.save(issue).then ->
|
||||||
$ctrl.loadIssues()
|
$ctrl.loadIssues()
|
||||||
|
|
||||||
for filter in $scope.filters.statuses
|
for filter in $scope.filters.status
|
||||||
if filter.id == issue.status
|
if filter.id == issue.status
|
||||||
filter.count++
|
filter.count++
|
||||||
|
|
||||||
$rootscope.$broadcast("filters:issueupdate", $scope.filters)
|
$rootscope.$broadcast("filters:issueupdate", $scope.filters)
|
||||||
|
|
||||||
for filter in $scope.filters.statuses
|
for filter in $scope.filters.status
|
||||||
if filter.id == issue.status
|
if filter.id == issue.status
|
||||||
filter.count++
|
filter.count++
|
||||||
$rootscope.$broadcast("filters:issueupdate", $scope.filters)
|
$rootscope.$broadcast("filters:issueupdate", $scope.filters)
|
||||||
|
|
|
@ -82,6 +82,7 @@ urls = {
|
||||||
"bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order"
|
"bulk-update-us-backlog-order": "/userstories/bulk_update_backlog_order"
|
||||||
"bulk-update-us-sprint-order": "/userstories/bulk_update_sprint_order"
|
"bulk-update-us-sprint-order": "/userstories/bulk_update_sprint_order"
|
||||||
"bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order"
|
"bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order"
|
||||||
|
"userstories-filters": "/userstories/filters_data"
|
||||||
|
|
||||||
# Tasks
|
# Tasks
|
||||||
"tasks": "/tasks"
|
"tasks": "/tasks"
|
||||||
|
@ -91,6 +92,7 @@ urls = {
|
||||||
# Issues
|
# Issues
|
||||||
"issues": "/issues"
|
"issues": "/issues"
|
||||||
"bulk-create-issues": "/issues/bulk_create"
|
"bulk-create-issues": "/issues/bulk_create"
|
||||||
|
"issues-filters": "/issues/filters_data"
|
||||||
|
|
||||||
# Wiki pages
|
# Wiki pages
|
||||||
"wiki": "/wiki"
|
"wiki": "/wiki"
|
||||||
|
|
|
@ -58,8 +58,8 @@ resourceProvider = ($repo, $http, $urls, $storage, $q) ->
|
||||||
service.stats = (projectId) ->
|
service.stats = (projectId) ->
|
||||||
return $repo.queryOneRaw("projects", "#{projectId}/issues_stats")
|
return $repo.queryOneRaw("projects", "#{projectId}/issues_stats")
|
||||||
|
|
||||||
service.filtersData = (projectId) ->
|
service.filtersData = (params) ->
|
||||||
return $repo.queryOneRaw("projects", "#{projectId}/issue_filters_data")
|
return $repo.queryOneRaw("issues-filters", null, params)
|
||||||
|
|
||||||
service.listValues = (projectId, type) ->
|
service.listValues = (projectId, type) ->
|
||||||
params = {"project": projectId}
|
params = {"project": projectId}
|
||||||
|
|
|
@ -41,6 +41,9 @@ resourceProvider = ($repo, $http, $urls, $storage) ->
|
||||||
service.listInAllProjects = (filters) ->
|
service.listInAllProjects = (filters) ->
|
||||||
return $repo.queryMany("userstories", filters)
|
return $repo.queryMany("userstories", filters)
|
||||||
|
|
||||||
|
service.filtersData = (params) ->
|
||||||
|
return $repo.queryOneRaw("userstories-filters", null, params)
|
||||||
|
|
||||||
service.listUnassigned = (projectId, filters) ->
|
service.listUnassigned = (projectId, filters) ->
|
||||||
params = {"project": projectId, "milestone": "null"}
|
params = {"project": projectId, "milestone": "null"}
|
||||||
params = _.extend({}, params, filters or {})
|
params = _.extend({}, params, filters or {})
|
||||||
|
|
|
@ -34,10 +34,10 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
|
||||||
span.text(translate="BACKLOG.TAGS.SHOW")
|
span.text(translate="BACKLOG.TAGS.SHOW")
|
||||||
include ../includes/components/addnewus
|
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
|
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.icon.icon-backlog
|
||||||
span.title(translate="BACKLOG.EMPTY")
|
span.title(translate="BACKLOG.EMPTY")
|
||||||
a(href="", title="{{'BACKLOG.CREATE_NEW_US' | translate}}",
|
a(href="", title="{{'BACKLOG.CREATE_NEW_US' | translate}}",
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
a.single-filter.active(data-type!="<%- f.type %>", data-id!="<%- f.id %>")
|
a.single-filter.active(data-type!="<%- f.type %>", data-id!="<%- f.id %>")
|
||||||
span.name(style!="<%- f.style %>")
|
span.name(style!="<%- f.style %>")
|
||||||
| <%- f.name %>
|
| <%- f.name %>
|
||||||
|
<% if (f.count){ %>
|
||||||
span.number <%- f.count %>
|
span.number <%- f.count %>
|
||||||
|
<% } %>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
a.single-filter(data-type!="<%- f.type %>", data-id!="<%- f.id %>")
|
a.single-filter(data-type!="<%- f.type %>", data-id!="<%- f.id %>")
|
||||||
span.name(style!="<%- f.style %>")
|
span.name(style!="<%- f.style %>")
|
||||||
| <%- f.name %>
|
| <%- f.name %>
|
||||||
|
<% if (f.count){ %>
|
||||||
span.number <%- f.count %>
|
span.number <%- f.count %>
|
||||||
|
<% } %>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% }) %>
|
<% }) %>
|
|
@ -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.user-stories
|
||||||
div.tags-block(tg-colorize-tags="us.tags", tg-colorize-tags-type="backlog")
|
div.tags-block(tg-colorize-tags="us.tags", tg-colorize-tags-type="backlog")
|
||||||
div.user-story-name
|
div.user-story-name
|
||||||
|
|
|
@ -18,7 +18,7 @@ section.filters
|
||||||
div.filters-cats
|
div.filters-cats
|
||||||
ul
|
ul
|
||||||
li
|
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.title(translate="BACKLOG.FILTERS.FILTER_CATEGORY_STATUS")
|
||||||
span.icon.icon-arrow-right
|
span.icon.icon-arrow-right
|
||||||
li
|
li
|
||||||
|
|
|
@ -22,7 +22,7 @@ section.filters
|
||||||
span.title(translate="ISSUES.FILTERS.CATEGORIES.TYPE")
|
span.title(translate="ISSUES.FILTERS.CATEGORIES.TYPE")
|
||||||
span.icon.icon-arrow-right
|
span.icon.icon-arrow-right
|
||||||
li
|
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.title(translate="ISSUES.FILTERS.CATEGORIES.STATUS")
|
||||||
span.icon.icon-arrow-right
|
span.icon.icon-arrow-right
|
||||||
li
|
li
|
||||||
|
|
Loading…
Reference in New Issue