From 0c01020eaa5028e1c80f7c84e709f8946a041aa2 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Tue, 22 Jul 2014 14:01:24 +0200 Subject: [PATCH] Improving us statuses for admin --- .../modules/admin/project-values.coffee | 133 ++++++++++++++---- .../modules/resources/userstories.coffee | 4 + .../modules/admin/project-us-status.jade | 50 ++++--- app/styles/modules/admin/project-values.scss | 19 +++ 4 files changed, 159 insertions(+), 47 deletions(-) diff --git a/app/coffee/modules/admin/project-values.coffee b/app/coffee/modules/admin/project-values.coffee index f59e0f31..e011ae28 100644 --- a/app/coffee/modules/admin/project-values.coffee +++ b/app/coffee/modules/admin/project-values.coffee @@ -53,18 +53,37 @@ class ProjectValuesController extends mixOf(taiga.Controller, taiga.PageMixin) promise.then null, -> console.log "FAIL" #TODO + @scope.$on("admin:project-values:us-status:move", @.moveUsStatus) + loadProject: -> return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project return project + loadUsStatus: => + return @rs.userstories.listStatuses(@scope.projectId).then (usStatuses) => + @scope.usStatuses = usStatuses + @scope.maxUsStatusOrder = _.max(usStatuses, "order").order + loadInitialData: -> promise = @repo.resolve({pslug: @params.pslug}).then (data) => @scope.projectId = data.project return data - return promise.then(=> @.loadProject()) + return promise.then( => @q.all([ + @.loadProject(), + @.loadUsStatus(), + ])) + moveUsStatus: (ctx, itemUsStatus, itemIndex) => + usStatuses = @scope.usStatuses + r = usStatuses.indexOf(itemUsStatus) + usStatuses.splice(r, 1) + usStatuses.splice(itemIndex, 0, itemUsStatus) + _.each usStatuses, (usStatus, index) -> + usStatus.order = index + + @repo.saveAll(usStatuses) module.controller("ProjectValuesController", ProjectValuesController) @@ -72,15 +91,56 @@ module.controller("ProjectValuesController", ProjectValuesController) ## Project US Values Directive ############################################################################# -ProjectUsStatusDirective = ($log, $repo, $confirm, $location, $model) -> - link = ($scope, $el, $attrs) -> - $ctrl = $el.controller() - $scope.newUs = { - "name": "" - "is_closed": false - "project": $scope.project.id - } +ProjectUsStatusDirective = ($log, $repo, $confirm, $location) -> + ######################### + ## Drag & Drop Link + ######################### + + linkDragAndDrop = ($scope, $el, $attrs) -> + oldParentScope = null + newParentScope = null + itemEl = null + tdom = $el.find(".sortable") + + deleteElement = (itemEl) -> + # Completelly remove item and its scope from dom + itemEl.scope().$destroy() + itemEl.off() + itemEl.remove() + + tdom.sortable({ + handle: ".project-values-row.visualization", + dropOnEmpty: true + connectWith: ".project-values-body" + revert: 400 + axis: "y" + }) + + tdom.on "sortstop", (event, ui) -> + parentEl = ui.item.parent() + itemEl = ui.item + itemUsStatus = itemEl.scope().status + itemIndex = itemEl.index() + $scope.$broadcast("admin:project-values:us-status:move", itemUsStatus, itemIndex) + + $scope.$on "$destroy", -> + $el.off() + + ######################### + ## Status Link + ######################### + + linkStatus = ($scope, $el, $attrs) -> + $ctrl = $el.controller() + + initializeNewUs = -> + $scope.newUs = { + "name": "" + "is_closed": false + } + + initializeNewUs() submit = => promise = $repo.save($scope.project) promise.then -> @@ -104,53 +164,76 @@ ProjectUsStatusDirective = ($log, $repo, $confirm, $location, $model) -> $el.on "click", ".add-new", (event) -> event.preventDefault() + form = $el.find(".new-us-status").parents("form").checksley() + return if not form.validate() + $scope.newUs.project = $scope.project.id - $repo.create("userstory-statuses", $scope.newUs).then => - console.log "LOAD" - $ctrl.loadProject() + $scope.newUs.order = $scope.maxUsStatusOrder + 1 + promise = $repo.create("userstory-statuses", $scope.newUs) + promise.then => + $ctrl.loadUsStatus() + $el.find(".new-us-status").hide() + initializeNewUs() + + promise.then null, (data) -> + form.setErrors(data) $el.on "click", ".delete-new", (event) -> event.preventDefault() $el.find(".new-us-status").hide() + initializeNewUs() $el.on "click", ".edit-us-status", (event) -> event.preventDefault() target = angular.element(event.currentTarget) - target.parents(".project-values-row").find(".visualization").hide() - target.parents(".project-values-row").find(".edition").show() + + row = target.parents(".project-values-row") + row.hide() + row.siblings(".edition").css("display": "flex") $el.on "click", ".save", (event) -> event.preventDefault() target = angular.element(event.currentTarget) - status = $model.make_model("userstory-statuses", target.scope().status) - status.setAttr("name", status.name) - status.setAttr("is_closed", status.is_closed) + form = target.parents("form").checksley() + return if not form.validate() - $repo.save(status).then => - target.parents(".project-values-row").find(".visualization").show() - target.parents(".project-values-row").find(".edition").hide() + status = target.scope().status + promise = $repo.save(status) + promise.then => + row = target.parents(".project-values-row") + row.hide() + row.siblings(".visualization").css("display": "flex") + + promise.then null, (data) -> + form.setErrors(data) $el.on "click", ".cancel", (event) -> event.preventDefault() target = angular.element(event.currentTarget) - target.parents(".project-values-row").find(".visualization").show() - target.parents(".project-values-row").find(".edition").hide() + row = target.parents(".project-values-row") + row.hide() + row.siblings(".visualization").css("display": "flex") $el.on "click", ".delete-us-status", (event) -> event.preventDefault() target = angular.element(event.currentTarget) - status = $model.make_model("userstory-statuses", target.scope().status) + status = target.scope().status #TODO: i18n title = "Delete User Story status" subtitle = status.name $confirm.ask(title, subtitle).then => $repo.remove(status).then => - $ctrl.loadProject() + $ctrl.loadUsStatus() + + link = ($scope, $el, $attrs) -> + linkDragAndDrop($scope, $el, $attrs) + linkStatus($scope, $el, $attrs) $scope.$on "$destroy", -> $el.off() return {link:link} -module.directive("tgProjectUsStatus", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", "$tgModel", ProjectUsStatusDirective]) + +module.directive("tgProjectUsStatus", ["$log", "$tgRepo", "$tgConfirm", "$tgLocation", ProjectUsStatusDirective]) diff --git a/app/coffee/modules/resources/userstories.coffee b/app/coffee/modules/resources/userstories.coffee index a10d51ef..9f272965 100644 --- a/app/coffee/modules/resources/userstories.coffee +++ b/app/coffee/modules/resources/userstories.coffee @@ -44,6 +44,10 @@ resourceProvider = ($repo, $http, $urls) -> service.history = (usId) -> return $repo.queryOneRaw("history/userstory", usId) + service.listStatuses = (projectId) -> + params = {"project": projectId} + return $repo.queryMany("userstory-statuses", params) + return (instance) -> instance.userstories = service diff --git a/app/partials/views/modules/admin/project-us-status.jade b/app/partials/views/modules/admin/project-us-status.jade index cf5e5588..38913d90 100644 --- a/app/partials/views/modules/admin/project-us-status.jade +++ b/app/partials/views/modules/admin/project-us-status.jade @@ -8,27 +8,33 @@ section.project-values-table div.project-values-settings div.project-values-body - div.project-values-row(ng-repeat="status in project.us_statuses") - div.project-values-name - span.visualization {{ status.name }} - input.hidden.edition(type="text", placeholder="Write a name for the new status", ng-model="status.name") - div.project-values-isclosed - span.visualization {{ status.is_closed|yesNo }} - select.hidden.edition(ng-model="status.is_closed") - div.project-values-settings - a.visualization.edit-us-status.icon.icon-edit(href="", title="Edit value") - a.visualization.delete-us-status.icon.icon-delete(href="", title="Delete value") - a.hidden.edition.save.icon.icon-floppy(href="", title="Add") - a.hidden.edition.cancel.icon.icon-delete(href="", title="Delete") + form.sortable + div(ng-repeat="status in usStatuses") + div.project-values-row.visualization + span.icon.icon-drag-v + div.project-values-name + span {{ status.name }} + div.project-values-isclosed + span {{ status.is_closed|yesNo }} + div.project-values-settings + a.edit-us-status.icon.icon-edit(href="", title="Edit value") + a.delete-us-status.icon.icon-delete(href="", title="Delete value") - div.project-values-row.new-us-status.hidden - div.project-values-name - input(type="text", placeholder="Write a name for the new status", ng-model="newUs.name") - div.project-values-isclosed - select(ng-model="newUs.is_closed") - option(selected) No - option Yes + div.project-values-row.edition.hidden + div.project-values-name + input(name="name", type="text", placeholder="Write a name for the new status", ng-model="status.name", data-required="true", data-maxlength="255") + div.project-values-isclosed + select(name="is_closed", ng-model="status.is_closed", ng-options="e.id as e.name for e in [{'id':true, 'name':'Yes'},{'id':false, 'name': 'No'}]", data-required="true") + div.project-values-settings + a.save.icon.icon-floppy(href="", title="Add") + a.cancel.icon.icon-delete(href="", title="Delete") - div.project-values-settings - a.add-new.icon.icon-floppy(href="", title="Add") - a.delete-new.icon.icon-delete(href="", title="Delete") + form + div.project-values-row.new-us-status.hidden + div.project-values-name + input(name="name", type="text", placeholder="Write a name for the new status", ng-model="newUs.name", data-required="true", data-maxlength="255") + div.project-values-isclosed + select(name="is_closed", ng-model="newUs.is_closed", ng-options="e.id as e.name for e in [{'id':true, 'name':'Yes'},{'id':false, 'name': 'No'}]", data-required="true") + div.project-values-settings + a.add-new.icon.icon-floppy(href="", title="Add") + a.delete-new.icon.icon-delete(href="", title="Delete") diff --git a/app/styles/modules/admin/project-values.scss b/app/styles/modules/admin/project-values.scss index 5f490929..06e8c917 100644 --- a/app/styles/modules/admin/project-values.scss +++ b/app/styles/modules/admin/project-values.scss @@ -1,6 +1,25 @@ .project-values-row { @include table-flex(stretch, center, flex, row, wrap, center); border-bottom: 1px solid $whitish; + &:hover { + cursor: move; + @include transition (background .2s ease-in); + background: lighten($green-taiga, 60%); + .icon { + @include transition (opacity .2s ease-in); + opacity: 1; + } + } + + .icon { + @extend %large; + color: $gray-light; + opacity: 0; + &:hover { + @include transition (all .2s ease-in); + color: $grayer; + } + } } .project-values-header {