### # Copyright (C) 2014 Andrey Antukh # Copyright (C) 2014 Jesús Espino Garcia # Copyright (C) 2014 David Barragán Merino # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # # File: modules/tasks/detail.coffee ### taiga = @.taiga mixOf = @.taiga.mixOf groupBy = @.taiga.groupBy module = angular.module("taigaTasks") ############################################################################# ## Task Detail Controller ############################################################################# class TaskDetailController extends mixOf(taiga.Controller, taiga.PageMixin) @.$inject = [ "$scope", "$rootScope", "$tgRepo", "$tgConfirm", "$tgResources", "$routeParams", "$q", "$tgLocation", "$log", "$appTitle", "$tgNavUrls", "$tgAnalytics", "tgLoader" ] constructor: (@scope, @rootscope, @repo, @confirm, @rs, @params, @q, @location, @log, @appTitle, @navUrls, @analytics, tgLoader) -> @scope.taskRef = @params.taskref @scope.sectionName = "Task Details" @.initializeEventHandlers() promise = @.loadInitialData() promise.then () => @appTitle.set(@scope.task.subject + " - " + @scope.project.name) tgLoader.pageLoaded() promise.then null, @.onInitialDataError.bind(@) initializeEventHandlers: -> @scope.$on "attachment:create", => @analytics.trackEvent("attachment", "create", "create attachment on task", 1) @rootscope.$broadcast("history:reload") @scope.$on "attachment:edit", => @rootscope.$broadcast("history:reload") @scope.$on "attachment:delete", => @rootscope.$broadcast("history:reload") loadProject: -> return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project @scope.$emit('project:loaded', project) @scope.statusList = project.task_statuses @scope.statusById = groupBy(project.task_statuses, (x) -> x.id) @scope.membersById = groupBy(project.memberships, (x) -> x.user) return project loadTask: -> return @rs.tasks.get(@scope.projectId, @scope.taskId).then (task) => @scope.task = task @scope.commentModel = task if @scope.task.neighbors.previous.ref? ctx = { project: @scope.project.slug ref: @scope.task.neighbors.previous.ref } @scope.previousUrl = @navUrls.resolve("project-tasks-detail", ctx) if @scope.task.neighbors.next.ref? ctx = { project: @scope.project.slug ref: @scope.task.neighbors.next.ref } @scope.nextUrl = @navUrls.resolve("project-tasks-detail", ctx) if task.milestone @rs.sprints.get(task.project, task.milestone).then (sprint) => @scope.sprint = sprint if task.user_story @rs.userstories.get(task.project, task.user_story).then (us) => @scope.us = us loadInitialData: -> params = { pslug: @params.pslug taskref: @params.taskref } promise = @repo.resolve(params).then (data) => @scope.projectId = data.project @scope.taskId = data.task return data return promise.then(=> @.loadProject()) .then(=> @.loadUsersAndRoles()) .then(=> @.loadTask()) module.controller("TaskDetailController", TaskDetailController) ############################################################################# ## Task Main Directive ############################################################################# TaskDirective = ($tgrepo, $log, $location, $confirm, $navUrls, $loading) -> linkSidebar = ($scope, $el, $attrs, $ctrl) -> link = ($scope, $el, $attrs) -> $ctrl = $el.controller() linkSidebar($scope, $el, $attrs, $ctrl) if $el.is("form") form = $el.checksley() $el.on "click", ".save-task", (event) -> if not form.validate() return onSuccess = -> $loading.finish(target) $confirm.notify("success") ctx = { project: $scope.project.slug ref: $scope.task.ref } $location.path($navUrls.resolve("project-tasks-detail", ctx)) onError = -> $loading.finish(target) $confirm.notify("error") target = angular.element(event.currentTarget) $loading.start(target) $tgrepo.save($scope.task).then(onSuccess, onError) return {link:link} module.directive("tgTaskDetail", ["$tgRepo", "$log", "$tgLocation", "$tgConfirm", "$tgNavUrls", "$tgLoading", TaskDirective]) ############################################################################# ## Task status directive ############################################################################# TaskStatusDirective = () -> #TODO: i18n template = _.template("""

<% if (status.is_closed) { %> Closed <% } else { %> Open <% } %> <%= status.name %>

<%- owner.full_name_display %>
Created by <%- owner.full_name_display %> <%- date %>
<%= status.name %> <% if (editable) { %> <% } %> status
""") selectionStatusTemplate = _.template(""" """) link = ($scope, $el, $attrs, $model) -> editable = $attrs.editable? renderTaskstatus = (task) -> owner = $scope.usersById?[task.owner] date = moment(task.created_date).format("DD MMM YYYY HH:mm") status = $scope.statusById[task.status] html = template({ owner: owner date: date editable: editable status: status }) $el.html(html) $el.find(".status-data").append(selectionStatusTemplate({statuses:$scope.statusList})) $scope.$watch $attrs.ngModel, (task) -> if task? renderTaskstatus(task) if editable $el.on "click", ".status-data", (event) -> event.preventDefault() event.stopPropagation() $el.find(".pop-status").popover().open() $el.on "click", ".status", (event) -> event.preventDefault() event.stopPropagation() target = angular.element(event.currentTarget) $model.$modelValue.status = target.data("status-id") renderTaskstatus($model.$modelValue) $el.find(".popover").popover().close() return {link:link, require:"ngModel"} module.directive("tgTaskStatus", TaskStatusDirective) TaskIsIocaineButtonDirective = ($rootscope, $tgrepo) -> template = _.template("""
""") link = ($scope, $el, $attrs, $model) -> render = _.once (us) -> $el.html(template()) refresh = (us) -> if us?.is_iocaine $el.find('.is-iocaine').addClass('active') else $el.find('.is-iocaine').removeClass('active') $scope.$watch $attrs.ngModel, (us) -> return if not us render(us) refresh(us) $scope.$on "$destroy", -> $el.off() $el.on "click", ".is-iocaine", (event) -> us = $model.$modelValue.clone() us.is_iocaine = not us.is_iocaine $model.$setViewValue(us) $tgrepo.save($model.$modelValue).then -> $rootscope.$broadcast("history:reload") return { link: link restrict: "EA" require: "ngModel" } module.directive("tgTaskIsIocaineButton", ["$rootScope", "$tgRepo", TaskIsIocaineButtonDirective])