From 8ae0b4d105b25939f95920d62be0f8d8af19ea13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Wed, 25 May 2016 12:56:55 +0200 Subject: [PATCH] Add feedback in points and tags --- app/coffee/modules/common/estimation.coffee | 8 ++++++- app/coffee/modules/common/tags.coffee | 17 +++++++++++++- .../common/components/editable-subject.jade | 11 +++++++--- .../us-estimation-points-per-role.jade | 9 +++++--- app/partials/common/tag/tag-line.jade | 12 +++++++--- app/partials/common/tag/tags-line-tags.jade | 12 ++++++++-- app/styles/components/tag.scss | 22 ++++++++++++++++++- 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/app/coffee/modules/common/estimation.coffee b/app/coffee/modules/common/estimation.coffee index 6cef0ef6..175e546d 100644 --- a/app/coffee/modules/common/estimation.coffee +++ b/app/coffee/modules/common/estimation.coffee @@ -111,14 +111,19 @@ UsEstimationDirective = ($tgEstimationsService, $rootScope, $repo, $template, $c if us estimationProcess = $tgEstimationsService.create($el, us, $scope.project) estimationProcess.onSelectedPointForRole = (roleId, pointId, points) -> + estimationProcess.loading = roleId + estimationProcess.render() save(points).then () -> + estimationProcess.loading = false $rootScope.$broadcast("object:updated") + estimationProcess.render() estimationProcess.render = () -> ctx = { totalPoints: @calculateTotalPoints() roles: @calculateRoles() editable: @isEditable + loading: estimationProcess.loading } mainTemplate = "common/estimation/us-estimation-points-per-role.html" template = $template.get(mainTemplate, true) @@ -154,6 +159,7 @@ EstimationsService = ($template, $repo, $confirm, $q, $qqueue) -> @isEditable = @project.my_permissions.indexOf("modify_us") != -1 @roles = @project.roles @points = @project.points + @loading = false @pointsById = groupBy(@points, (x) -> x.id) @onSelectedPointForRole = (roleId, pointId) -> @render = () -> @@ -163,6 +169,7 @@ EstimationsService = ($template, $repo, $confirm, $q, $qqueue) -> $qqueue.add () => onSuccess = => deferred.resolve() + @render() onError = => $confirm.notify("error") @@ -215,7 +222,6 @@ EstimationsService = ($template, $repo, $confirm, $q, $qqueue) -> pointId = target.data("point-id") @$el.find(".popover").popover().close() - points = _.clone(@us.points, true) points[roleId] = pointId diff --git a/app/coffee/modules/common/tags.coffee b/app/coffee/modules/common/tags.coffee index 0bd42dfa..22e7dc30 100644 --- a/app/coffee/modules/common/tags.coffee +++ b/app/coffee/modules/common/tags.coffee @@ -112,7 +112,7 @@ LbTagLineDirective = ($rs, $template, $compile) -> link = ($scope, $el, $attrs, $model) -> ## Render - renderTags = (tags, tagsColors) -> + renderTags = (tags, tagsColors = []) -> ctx = { tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]}) } @@ -231,6 +231,8 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template link = ($scope, $el, $attrs, $model) -> autocomplete = null + loading = false + deleteTagLoading = null isEditable = -> if $attrs.requiredPerm? @@ -243,7 +245,10 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template ctx = { tags: _.map(tags, (t) -> {name: t, color: tagsColors[t]}) isEditable: isEditable() + loading: loading + deleteTagLoading: deleteTagLoading } + html = $compile(templateTags(ctx))($scope) $el.find("div.tags-container").html(html) @@ -270,8 +275,10 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template ## Aux methods addValue = (value) -> + loading = true value = trim(value.toLowerCase()) return if value.length == 0 + renderTags($model.$modelValue.tags, $scope.project?.tags_colors) transform = $modelTransform.save (item) -> if not item.tags @@ -287,6 +294,8 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template onSuccess = -> $rootScope.$broadcast("object:updated") + loading = false + renderTags($model.$modelValue.tags, $scope.project?.tags_colors) onError = -> $confirm.notify("error") @@ -298,6 +307,8 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template deleteValue = (value) -> value = trim(value.toLowerCase()) return if value.length == 0 + deleteTagLoading = value + renderTags($model.$modelValue.tags, $scope.project?.tags_colors) transform = $modelTransform.save (item) -> tags = _.clone(item.tags, false) @@ -307,9 +318,12 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template onSuccess = -> $rootScope.$broadcast("object:updated") + renderTags($model.$modelValue.tags, $scope.project?.tags_colors) + deleteTagLoading = null onError = -> $confirm.notify("error") + deleteTagLoading = null return transform.then(onSuccess, onError) @@ -357,6 +371,7 @@ TagLineDirective = ($rootScope, $repo, $rs, $confirm, $modelTransform, $template value = target.siblings(".tag-name").text() deleteValue(value) + $scope.$digest() bindOnce $scope, "project.tags_colors", (tags_colors) -> if not isEditable() diff --git a/app/partials/common/components/editable-subject.jade b/app/partials/common/components/editable-subject.jade index 0a294cba..bc1738c5 100644 --- a/app/partials/common/components/editable-subject.jade +++ b/app/partials/common/components/editable-subject.jade @@ -1,11 +1,16 @@ -.view-subject - | {{ item.subject }} +.view-subject {{ item.subject }} tg-svg.edit( svg-icon="icon-edit", title="{{'COMMON.EDIT' | translate}}" ) .edit-subject - input(type="text", ng-model="item.subject", data-required="true", data-maxlength="500", ng-model-options="{ debounce: 200 }") + input( + type="text" + ng-model="item.subject" + data-required="true" + data-maxlength="500" + ng-model-options="{ debounce: 200 }" + ) span.save-container a.save(href="") tg-svg( diff --git a/app/partials/common/estimation/us-estimation-points-per-role.jade b/app/partials/common/estimation/us-estimation-points-per-role.jade index e7a2fbb0..94544c0f 100644 --- a/app/partials/common/estimation/us-estimation-points-per-role.jade +++ b/app/partials/common/estimation/us-estimation-points-per-role.jade @@ -1,11 +1,14 @@ ul.points-per-role <% _.each(roles, function(role) { %> - li.ticket-role-points.total(class!="<% if(editable){ %>clickable<% } %>", data-role-id!="<%- role.id %>", title!="<%- role.name %>") + li.ticket-role-points.total( + class!="<% if(editable){ %>clickable<% } %>" + data-role-id!="<%- role.id %>" + title!="<%- role.name %>" + ) span.points <%- role.points %> tg-svg(svg-icon="icon-arrow-down") - span.role - <%- role.name %> + span.role(tg-loading!="<%- loading == role.id %>") <%- role.name %> <% }); %> li.ticket-role-points.total span.points <%- totalPoints %> diff --git a/app/partials/common/tag/tag-line.jade b/app/partials/common/tag/tag-line.jade index 336b3731..7457060a 100644 --- a/app/partials/common/tag/tag-line.jade +++ b/app/partials/common/tag/tag-line.jade @@ -1,9 +1,15 @@ .tags-container -a(href="#", class="add-tag hidden", title="{{'COMMON.TAGS.ADD' | translate}}") +a.add-tag.hidden( + href="#" + title="{{'COMMON.TAGS.ADD' | translate}}" +) tg-svg(svg-icon="icon-add") span.add-tag-text(translate="COMMON.TAGS.ADD") span.add-tag-input - input(type="text", placeholder="{{'COMMON.TAGS.PLACEHOLDER' | translate}}", class="tag-input hidden") + input.tag-input.hidden( + type="text" + placeholder="{{'COMMON.TAGS.PLACEHOLDER' | translate}}" + ) span.save.hidden(title="{{'COMMON.SAVE' | translate}}") - tg-svg(svg-icon="icon-save") \ No newline at end of file + tg-svg(svg-icon="icon-save") diff --git a/app/partials/common/tag/tags-line-tags.jade b/app/partials/common/tag/tags-line-tags.jade index 90b934e4..53ee66ac 100644 --- a/app/partials/common/tag/tags-line-tags.jade +++ b/app/partials/common/tag/tags-line-tags.jade @@ -1,8 +1,16 @@ <% _.each(tags, function(tag) { %> -span(class="tag", style!="border-left: 5px solid <%- tag.color %>;") +<% if (tag.name == deleteTagLoading) { %> +div(tg-loading="true") +<% } else { %> +span.tag(style!="border-left: 5px solid <%- tag.color %>;") span.tag-name <%- tag.name %> <% if (isEditable) { %> - a.remove-tag(href="", title="{{'COMMON.TAGS.DELETE' | translate}}") + a.remove-tag( + href="" + title="{{'COMMON.TAGS.DELETE' | translate}}" + ) tg-svg(svg-icon="icon-close") <% } %> +<% } %> <% }); %> +div(tg-loading!="<%- loading %>") diff --git a/app/styles/components/tag.scss b/app/styles/components/tag.scss index ff2ed64c..3148af14 100644 --- a/app/styles/components/tag.scss +++ b/app/styles/components/tag.scss @@ -34,8 +34,23 @@ } .tags-block { + align-content: center; + display: flex; + flex-wrap: wrap; .tags-container { - display: inline-block; + align-items: center; + display: flex; + flex-wrap: wrap; + } + .add-tag-input { + align-items: flex-start; + display: flex; + flex-grow: 0; + flex-shrink: 0; + width: 250px; + .icon-save { + margin-top: .5rem; + } } input { margin-right: .25rem; @@ -55,6 +70,9 @@ transition: .2s linear; } } + .loading-spinner { + margin-right: .5rem; + } .tag { @include font-size(small); margin: 0 .5rem .5rem 0; @@ -78,6 +96,8 @@ } .icon-add { @include svg-size(.9rem); + margin-right: .25rem; + margin-top: .5rem; } .add-tag-text { @include font-size(small);