diff --git a/.gitignore b/.gitignore index 91e8a0b3..77c34383 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ tags tmp/ conf/ app/config/main.coffee +app/plugins/taiga-front-extras diff --git a/CHANGELOG.md b/CHANGELOG.md index 719b202b..285860e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog # +## 1.2.0 (Unreleased) + +### Features +- Multiple User stories Drag & Drop in the backlog. +- Added beta ribbon. + +### Misc +- Lots of small and not so small bugfixes + + ## 1.1.0 (2014-10-13) ### Misc ### diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index 220c50a9..e007c11d 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -114,6 +114,8 @@ configure = ($routeProvider, $locationProvider, $httpProvider, $provide, $tgEven {templateUrl: "/partials/mail-notifications.html"}) $routeProvider.when("/change-email/:email_token", {templateUrl: "/partials/change-email.html"}) + $routeProvider.when("/cancel-account/:cancel_token", + {templateUrl: "/partials/cancel-account.html"}) # Auth $routeProvider.when("/login", diff --git a/app/coffee/modules/admin/roles.coffee b/app/coffee/modules/admin/roles.coffee index 49bf2913..b3c64464 100644 --- a/app/coffee/modules/admin/roles.coffee +++ b/app/coffee/modules/admin/roles.coffee @@ -51,6 +51,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil @scope.sectionName = "Permissions" #i18n @scope.project = {} + @scope.anyComputableRole = true promise = @.loadInitialData() @@ -67,6 +68,8 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project @scope.$emit('project:loaded', project) + @scope.anyComputableRole = _.some(_.map(project.roles, (point) -> point.computable)) + return project loadRoles: -> @@ -104,6 +107,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil return @confirm.askChoice(title, subtitle, choices).then (response) => promise = @repo.remove(@scope.role, {moveTo: response.selected}) promise.then => + @.loadProject() @.loadRoles().finally -> response.finish() promise.then null, => @@ -112,6 +116,7 @@ class RolesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fil setComputable: debounce 2000, -> onSuccess = => @confirm.notify("success") + @.loadProject() onError = => @confirm.notify("error") @@ -168,6 +173,7 @@ NewRoleDirective = ($tgrepo, $confirm) -> $scope.roles.push(role) $ctrl.setRole(role) $el.find(".add-button").show() + $ctrl.loadProject() onError = -> $confirm.notify("error") @@ -326,6 +332,7 @@ RolePermissionsDirective = ($rootscope, $repo, $confirm) -> renderResume(target.parents(".category-config"), categories[categoryId]) $rootscope.$broadcast("projects:reload") $confirm.notify("success") + $ctrl.loadProject() onError = -> $confirm.notify("error") diff --git a/app/coffee/modules/auth.coffee b/app/coffee/modules/auth.coffee index 2695afc6..939d290e 100644 --- a/app/coffee/modules/auth.coffee +++ b/app/coffee/modules/auth.coffee @@ -137,6 +137,10 @@ class AuthService extends taiga.Service data = _.clone(data, false) return @http.post(url, data) + cancelAccount: (data) -> + url = @urls.resolve("users-cancel-account") + data = _.clone(data, false) + return @http.post(url, data) module.service("$tgAuth", AuthService) @@ -458,3 +462,42 @@ ChangeEmailDirective = ($repo, $model, $auth, $confirm, $location, $params, $nav module.directive("tgChangeEmail", ["$tgRepo", "$tgModel", "$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams", "$tgNavUrls", ChangeEmailDirective]) + +############################################################################# +## Cancel account +############################################################################# + +CancelAccountDirective = ($repo, $model, $auth, $confirm, $location, $params, $navUrls) -> + link = ($scope, $el, $attrs) -> + $scope.data = {} + $scope.data.cancel_token = $params.cancel_token + form = $el.find("form").checksley() + + onSuccessSubmit = (response) -> + $auth.logout() + $location.path($navUrls.resolve("home")) + $confirm.success("Our Oompa Loompas removed your account") #TODO: i18n + + onErrorSubmit = (response) -> + $confirm.notify("error", "One of our Oompa Loompas says + '#{response.data._error_message}'.") #TODO: i18n + + submit = -> + if not form.validate() + return + + promise = $auth.cancelAccount($scope.data) + promise.then(onSuccessSubmit, onErrorSubmit) + + $el.on "submit", (event) -> + event.preventDefault() + submit() + + $el.on "click", "a.button-cancel-account", (event) -> + event.preventDefault() + submit() + + return {link:link} + +module.directive("tgCancelAccount", ["$tgRepo", "$tgModel", "$tgAuth", "$tgConfirm", "$tgLocation", "$routeParams", + "$tgNavUrls", CancelAccountDirective]) diff --git a/app/coffee/modules/backlog/main.coffee b/app/coffee/modules/backlog/main.coffee index e15a0005..8201b4f8 100644 --- a/app/coffee/modules/backlog/main.coffee +++ b/app/coffee/modules/backlog/main.coffee @@ -256,6 +256,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F resortUserStories: (uses, field="backlog_order") -> items = [] + for item, index in uses item[field] = index if item.isModified() @@ -263,8 +264,9 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F return items - moveUs: (ctx, us, newUsIndex, newSprintId) -> - oldSprintId = us.milestone + moveUs: (ctx, usList, newUsIndex, newSprintId) -> + oldSprintId = usList[0].milestone + project = usList[0].project # In the same sprint or in the backlog if newSprintId == oldSprintId @@ -277,20 +279,25 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F userstories = @scope.sprintsById[newSprintId].user_stories @scope.$apply -> - r = userstories.indexOf(us) - userstories.splice(r, 1) - userstories.splice(newUsIndex, 0, us) + for us, key in usList + r = userstories.indexOf(us) + userstories.splice(r, 1) + + args = [newUsIndex, 0].concat(usList) + Array.prototype.splice.apply(userstories, args) # If in backlog if newSprintId == null # Rehash userstories order field + items = @.resortUserStories(userstories, "backlog_order") data = @.prepareBulkUpdateData(items, "backlog_order") # Persist in bulk all affected # userstories with order change - @rs.userstories.bulkUpdateBacklogOrder(us.project, data).then => - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rs.userstories.bulkUpdateBacklogOrder(project, data).then => + for us in usList + @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) # For sprint else @@ -300,27 +307,32 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # Persist in bulk all affected # userstories with order change - @rs.userstories.bulkUpdateSprintOrder(us.project, data).then => - @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + @rs.userstories.bulkUpdateSprintOrder(project, data).then => + for us in usList + @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) return promise # From sprint to backlog if newSprintId == null - us.milestone = null + us.milestone = null for us in usList @scope.$apply => # Add new us to backlog userstories list - @scope.userstories.splice(newUsIndex, 0, us) - @scope.visibleUserstories.splice(newUsIndex, 0, us) + # @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] - r = sprint.user_stories.indexOf(us) - sprint.user_stories.splice(r, 1) + for us, key in usList + r = sprint.user_stories.indexOf(us) + sprint.user_stories.splice(r, 1) # Persist the milestone change of userstory promise = @repo.save(us) @@ -340,43 +352,55 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F # From backlog to sprint newSprint = @scope.sprintsById[newSprintId] - if us.milestone == null - us.milestone = newSprintId + if oldSprintId == null + us.milestone = newSprintId for us in usList @scope.$apply => + args = [newUsIndex, 0].concat(usList) + # Add moving us to sprint user stories list - newSprint.user_stories.splice(newUsIndex, 0, us) + Array.prototype.splice.apply(newSprint.user_stories, args) # Remove moving us from backlog userstories lists. - r = @scope.visibleUserstories.indexOf(us) - @scope.visibleUserstories.splice(r, 1) - r = @scope.userstories.indexOf(us) - @scope.userstories.splice(r, 1) + 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) # From sprint to sprint else - us.milestone = newSprintId + us.milestone = newSprintId for us in usList @scope.$apply => + args = [newUsIndex, 0].concat(usList) + # Add new us to backlog userstories list - newSprint.user_stories.splice(newUsIndex, 0, us) + Array.prototype.splice.apply(newSprint.user_stories, args) # Remove the us from the sprint list. - oldSprint = @scope.sprintsById[oldSprintId] - r = oldSprint.user_stories.indexOf(us) - oldSprint.user_stories.splice(r, 1) + for us in usList + oldSprint = @scope.sprintsById[oldSprintId] + r = oldSprint.user_stories.indexOf(us) + oldSprint.user_stories.splice(r, 1) # Persist the milestone change of userstory - promise = @repo.save(us) + promises = _.map usList, (us) => @repo.save(us) # Rehash userstories order field # and persist in bulk all changes. - promise = promise.then => + promise = @q.all.apply(null, promises).then => items = @.resortUserStories(newSprint.user_stories, "sprint_order") data = @.prepareBulkUpdateData(items, "sprint_order") - return @rs.userstories.bulkUpdateSprintOrder(us.project, data).then => + + return @rs.userstories.bulkUpdateSprintOrder(project, data).then => @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + return @rs.userstories.bulkUpdateBacklogOrder(project, data).then => + for us in usList + @rootscope.$broadcast("sprint:us:moved", us, oldSprintId, newSprintId) + promise.then null, -> console.log "FAIL" # TODO @@ -545,6 +569,7 @@ BacklogDirective = ($repo, $rootscope) -> # Enable move to current sprint only when there are selected us's $el.on "change", ".backlog-table-body .user-stories input:checkbox", (event) -> + target = angular.element(event.currentTarget) moveToCurrentSprintDom = $el.find("#move-to-current-sprint") selectedUsDom = $el.find(".backlog-table-body .user-stories input:checkbox:checked") @@ -553,6 +578,8 @@ BacklogDirective = ($repo, $rootscope) -> else moveToCurrentSprintDom.hide() + target.closest('.us-item-row').toggleClass('ui-multisortable-multiple') + $el.on "click", "#move-to-current-sprint", (event) => # Calculating the us's to be modified ussDom = $el.find(".backlog-table-body .user-stories input:checkbox:checked") @@ -661,6 +688,7 @@ UsRolePointsSelectorDirective = ($rootscope) -> $el.append(selectionTemplate({"roles":roles})) else $el.find(".icon-arrow-bottom").remove() + $el.find(".header-points").addClass("not-clickable") $scope.$on "uspoints:select", (ctx, roleId, roleName) -> $el.find(".popover").popover().close() @@ -744,6 +772,20 @@ UsPointsDirective = ($repo) -> if numberOfRoles == 1 selectedRoleId = _.keys(us.points)[0] + computableRoles = _.filter($scope.project.roles, "computable") + + roles = _.map computableRoles, (role) -> + pointId = us.points[role.id] + pointObj = $scope.pointsById[pointId] + + role = _.clone(role, true) + role.points = if pointObj.value? then pointObj.value else "?" + return role + + if roles.length == 0 + $el.find(".icon-arrow-bottom").remove() + $el.find("a.us-points").addClass("not-clickable") + renderPointsSelector = (us, roleId) -> # Prepare data for rendering points = _.map $scope.project.points, (point) -> @@ -767,17 +809,6 @@ UsPointsDirective = ($repo) -> $el.find(".pop-points-open").popover().open() renderRolesSelector = (us) -> - # Prepare data for rendering - computableRoles = _.filter($scope.project.roles, "computable") - - roles = _.map computableRoles, (role) -> - pointId = us.points[role.id] - pointObj = $scope.pointsById[pointId] - - role = _.clone(role, true) - role.points = if pointObj.value? then pointObj.value else "?" - return role - html = rolesTemplate({"roles": roles}) # Render into DOM and show the new created element @@ -818,56 +849,57 @@ UsPointsDirective = ($repo) -> renderPoints(us, null) selectedRoleId = null - $el.on "click", "a.us-points span", (event) -> - event.preventDefault() - event.stopPropagation() + if roles.length > 0 + $el.on "click", "a.us-points span", (event) -> + event.preventDefault() + event.stopPropagation() - us = $scope.$eval($attrs.tgBacklogUsPoints) - updatingSelectedRoleId = selectedRoleId + us = $scope.$eval($attrs.tgBacklogUsPoints) + updatingSelectedRoleId = selectedRoleId - if selectedRoleId? - renderPointsSelector(us, selectedRoleId) - else - renderRolesSelector(us) + if selectedRoleId? + renderPointsSelector(us, selectedRoleId) + else + renderRolesSelector(us) - $el.on "click", ".role", (event) -> - event.preventDefault() - event.stopPropagation() - target = angular.element(event.currentTarget) + $el.on "click", ".role", (event) -> + event.preventDefault() + event.stopPropagation() + target = angular.element(event.currentTarget) - us = $scope.$eval($attrs.tgBacklogUsPoints) + us = $scope.$eval($attrs.tgBacklogUsPoints) - updatingSelectedRoleId = target.data("role-id") + updatingSelectedRoleId = target.data("role-id") - popRolesDom = $el.find(".pop-role") - popRolesDom.find("a").removeClass("active") - popRolesDom.find("a[data-role-id='#{updatingSelectedRoleId}']").addClass("active") + popRolesDom = $el.find(".pop-role") + popRolesDom.find("a").removeClass("active") + popRolesDom.find("a[data-role-id='#{updatingSelectedRoleId}']").addClass("active") - renderPointsSelector(us, updatingSelectedRoleId) + renderPointsSelector(us, updatingSelectedRoleId) - $el.on "click", ".point", (event) -> - event.preventDefault() - event.stopPropagation() + $el.on "click", ".point", (event) -> + event.preventDefault() + event.stopPropagation() - target = angular.element(event.currentTarget) - $el.find(".pop-points-open").hide() - $el.find(".pop-role").hide() + target = angular.element(event.currentTarget) + $el.find(".pop-points-open").hide() + $el.find(".pop-role").hide() - us = $scope.$eval($attrs.tgBacklogUsPoints) + us = $scope.$eval($attrs.tgBacklogUsPoints) - points = _.clone(us.points, true) - points[updatingSelectedRoleId] = target.data("point-id") + points = _.clone(us.points, true) + points[updatingSelectedRoleId] = target.data("point-id") - $scope.$apply -> - us.points = points - us.total_points = calculateTotalPoints(us) + $scope.$apply -> + us.points = points + us.total_points = calculateTotalPoints(us) - renderPoints(us, selectedRoleId) + renderPoints(us, selectedRoleId) - $repo.save(us).then -> - # Little Hack for refresh. - $repo.refresh(us).then -> - $ctrl.loadProjectStats() + $repo.save(us).then -> + # Little Hack for refresh. + $repo.refresh(us).then -> + $ctrl.loadProjectStats() bindOnce $scope, "project", (project) -> # If the user has not enough permissions the click events are unbinded diff --git a/app/coffee/modules/backlog/sortable.coffee b/app/coffee/modules/backlog/sortable.coffee index adcf4baa..e568f742 100644 --- a/app/coffee/modules/backlog/sortable.coffee +++ b/app/coffee/modules/backlog/sortable.coffee @@ -69,23 +69,35 @@ BacklogSortableDirective = ($repo, $rs, $rootscope) -> cursorAt: {right: 15} }) - $el.on "sortreceive", (event, ui) -> + $el.on "multiplesortreceive", (event, ui) -> itemUs = ui.item.scope().us itemIndex = ui.item.index() deleteElement(ui.item) - $scope.$emit("sprint:us:move", itemUs, itemIndex, null) + + $scope.$emit("sprint:us:move", [itemUs], itemIndex, null) ui.item.find('a').removeClass('noclick') - $el.on "sortstop", (event, ui) -> + $el.on "multiplesortstop", (event, ui) -> # When parent not exists, do nothing - if ui.item.parent().length == 0 + if $(ui.items[0]).parent().length == 0 return - itemUs = ui.item.scope().us - itemIndex = ui.item.index() - $scope.$emit("sprint:us:move", itemUs, itemIndex, null) - ui.item.find('a').removeClass('noclick') + items = _.sortBy ui.items, (item) -> + return $(item).index() + + index = _.min _.map items, (item) -> + return $(item).index() + + us = _.map items, (item) -> + item = $(item) + itemUs = item.scope().us + + item.find('a').removeClass('noclick') + + return itemUs + + $scope.$emit("sprint:us:move", us, index, null) $el.on "sortstart", (event, ui) -> ui.item.find('a').addClass('noclick') @@ -113,7 +125,7 @@ BacklogEmptySortableDirective = ($repo, $rs, $rootscope) -> itemIndex = ui.item.index() deleteElement(ui.item) - $scope.$emit("sprint:us:move", itemUs, itemIndex, null) + $scope.$emit("sprint:us:move", [itemUs], itemIndex, null) ui.item.find('a').removeClass('noclick') $scope.$on "$destroy", -> @@ -132,24 +144,33 @@ SprintSortableDirective = ($repo, $rs, $rootscope) -> connectWith: ".sprint-table,.backlog-table-body,.empty-backlog" }) - $el.on "sortreceive", (event, ui) -> - itemUs = ui.item.scope().us - itemIndex = ui.item.index() + $el.on "multiplesortreceive", (event, ui) -> + items = _.sortBy ui.items, (item) -> + return $(item).index() - deleteElement(ui.item) - $scope.$emit("sprint:us:move", itemUs, itemIndex, $scope.sprint.id) - ui.item.find('a').removeClass('noclick') + index = _.min _.map items, (item) -> + return $(item).index() - $el.on "sortstop", (event, ui) -> + us = _.map items, (item) -> + item = $(item) + itemUs = item.scope().us + + deleteElement(item) + item.find('a').removeClass('noclick') + + return itemUs + + $scope.$emit("sprint:us:move", us, index, $scope.sprint.id) + + $el.on "multiplesortstop", (event, ui) -> # When parent not exists, do nothing if ui.item.parent().length == 0 return itemUs = ui.item.scope().us itemIndex = ui.item.index() - - $scope.$emit("sprint:us:move", itemUs, itemIndex, $scope.sprint.id) ui.item.find('a').removeClass('noclick') + $scope.$emit("sprint:us:move", [itemUs], itemIndex, $scope.sprint.id) return {link:link} diff --git a/app/coffee/modules/base.coffee b/app/coffee/modules/base.coffee index 1feb8e91..9a4a309f 100644 --- a/app/coffee/modules/base.coffee +++ b/app/coffee/modules/base.coffee @@ -51,6 +51,7 @@ urls = { "forgot-password": "/forgot-password" "change-password": "/change-password/:token" "change-email": "/change-email/:token" + "cancel-account": "/cancel-account/:token" "register": "/register" "invitation": "/invitation/:token" "create-project": "/create-project" diff --git a/app/coffee/modules/base/repository.coffee b/app/coffee/modules/base/repository.coffee index 2155c846..05ca4846 100644 --- a/app/coffee/modules/base/repository.coffee +++ b/app/coffee/modules/base/repository.coffee @@ -134,9 +134,10 @@ class RepositoryService extends taiga.Service return @http.get(url, params, httpOptions).then (data) => return data.data - queryPaginated: (name, params) -> + queryPaginated: (name, params, options={}) -> url = @urls.resolve(name) - return @http.get(url, params).then (data) => + httpOptions = _.merge({headers: {}}, options) + return @http.get(url, params, httpOptions).then (data) => headers = data.headers() result = {} result.models = _.map(data.data, (x) => @model.make_model(name, x)) diff --git a/app/coffee/modules/common/history.coffee b/app/coffee/modules/common/history.coffee index 98ba3356..5918f71c 100644 --- a/app/coffee/modules/common/history.coffee +++ b/app/coffee/modules/common/history.coffee @@ -282,7 +282,10 @@ HistoryDirective = ($log, $loading) -> return $scope.usersById[userId]?.full_name_display getUserAvatar = (userId) -> - return $scope.usersById[userId]?.photo + if $scope.usersById[userId]? + return $scope.usersById[userId].photo + else + return "/images/unnamed.png" countChanges = (comment) -> return _.keys(comment.values_diff).length @@ -373,7 +376,7 @@ HistoryDirective = ($log, $loading) -> return templateActivity({ avatar: getUserAvatar(comment.user.pk) - userFullName: getUserFullName(comment.user.pk) + userFullName: comment.user.name creationDate: moment(comment.created_at).format("DD MMM YYYY HH:mm") comment: comment.comment_html changesText: renderChangesHelperText(comment) @@ -388,7 +391,7 @@ HistoryDirective = ($log, $loading) -> renderChange = (change) -> return templateActivity({ avatar: getUserAvatar(change.user.pk) - userFullName: getUserFullName(change.user.pk) + userFullName: change.user.name creationDate: moment(change.created_at).format("DD MMM YYYY HH:mm") comment: change.comment_html changes: renderChangeEntries(change, false) diff --git a/app/coffee/modules/issues/list.coffee b/app/coffee/modules/issues/list.coffee index acd31682..b2aab722 100644 --- a/app/coffee/modules/issues/list.coffee +++ b/app/coffee/modules/issues/list.coffee @@ -229,7 +229,12 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi @.markSelectedFilters(@scope.filters, urlfilters) @rootscope.$broadcast("filters:loaded", @scope.filters) - loadIssues: -> + # We need to guarantee that the last petition done here is the finally used + # When searching by text loadIssues can be called fastly with different parameters and + # can be resolved in a different order than generated + # We count the requests made and only if the callback is for the last one data is updated + loadIssuesRequests: 0 + loadIssues: => @scope.urlFilters = @.getUrlFilters() # Convert stored filters to http parameters @@ -255,11 +260,15 @@ class IssuesController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.Fi name = "type" @scope.httpParams[name] = values - return @rs.issues.list(@scope.projectId, @scope.httpParams).then (data) => - @scope.issues = data.models - @scope.page = data.current - @scope.count = data.count - @scope.paginatedBy = data.paginatedBy + promise = @rs.issues.list(@scope.projectId, @scope.httpParams) + @.loadIssuesRequests += 1 + promise.index = @.loadIssuesRequests + promise.then (data) => + if promise.index == @.loadIssuesRequests + @scope.issues = data.models + @scope.page = data.current + @scope.count = data.count + @scope.paginatedBy = data.paginatedBy return data loadInitialData: -> diff --git a/app/coffee/modules/kanban/main.coffee b/app/coffee/modules/kanban/main.coffee index 9240fd48..1446fb39 100644 --- a/app/coffee/modules/kanban/main.coffee +++ b/app/coffee/modules/kanban/main.coffee @@ -317,6 +317,9 @@ KanbanColumnHeightFixerDirective = -> link = ($scope, $el, $attrs) -> timeout(500, -> renderSize($el)) + $scope.$on "resize", -> + renderSize($el) + $scope.$on "$destroy", -> $el.off() diff --git a/app/coffee/modules/projects.coffee b/app/coffee/modules/projects.coffee index 75c024a3..c4b08aec 100644 --- a/app/coffee/modules/projects.coffee +++ b/app/coffee/modules/projects.coffee @@ -1 +1,22 @@ +### +# 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/projects.coffee +### + module = angular.module("taigaProject", []) diff --git a/app/coffee/modules/resources.coffee b/app/coffee/modules/resources.coffee index 6947e804..18675d29 100644 --- a/app/coffee/modules/resources.coffee +++ b/app/coffee/modules/resources.coffee @@ -73,6 +73,7 @@ urls = { "users-change-password-from-recovery": "/users/change_password_from_recovery" "users-change-password": "/users/change_password" "users-change-email": "/users/change_email" + "users-cancel-account": "/users/cancel" "user-storage": "/user-storage" "resolver": "/resolver" "userstory-statuses": "/userstory-statuses" diff --git a/app/coffee/modules/resources/issues.coffee b/app/coffee/modules/resources/issues.coffee index fca4caa3..46c5bc78 100644 --- a/app/coffee/modules/resources/issues.coffee +++ b/app/coffee/modules/resources/issues.coffee @@ -35,11 +35,11 @@ resourceProvider = ($repo, $http, $urls, $storage, $q) -> params.project = projectId return $repo.queryOne("issues", issueId, params) - service.list = (projectId, filters) -> + service.list = (projectId, filters, options) -> params = {project: projectId} params = _.extend({}, params, filters or {}) service.storeQueryParams(projectId, params) - return $repo.queryPaginated("issues", params) + return $repo.queryPaginated("issues", params, options) service.bulkCreate = (projectId, data) -> url = $urls.resolve("bulk-create-issues") diff --git a/app/coffee/modules/taskboard/main.coffee b/app/coffee/modules/taskboard/main.coffee index c89634d7..8cd2dc37 100644 --- a/app/coffee/modules/taskboard/main.coffee +++ b/app/coffee/modules/taskboard/main.coffee @@ -303,6 +303,9 @@ TaskboardTableHeightFixerDirective = -> link = ($scope, $el, $attrs) -> timeout(500, -> renderSize($el)) + $scope.$on "resize", -> + renderSize($el) + return {link:link} diff --git a/app/coffee/modules/user-settings/lightboxes.coffee b/app/coffee/modules/user-settings/lightboxes.coffee index c71a9f68..102c3c1d 100644 --- a/app/coffee/modules/user-settings/lightboxes.coffee +++ b/app/coffee/modules/user-settings/lightboxes.coffee @@ -58,7 +58,10 @@ DeleteUserDirective = ($repo, $rootscope, $auth, $location, $navUrls, lightboxSe event.preventDefault() submit() - return {link:link} + return { + link: link, + templateUrl: "/partials/views/modules/lightbox-delete-account.html" + } module.directive("tgLbDeleteUser", ["$tgRepo", "$rootScope", "$tgAuth", "$tgLocation", "$tgNavUrls", "lightboxService", DeleteUserDirective]) diff --git a/app/fonts/DroidSans-Bold.eot b/app/fonts/DroidSans-Bold.eot deleted file mode 100644 index eb2713a8..00000000 Binary files a/app/fonts/DroidSans-Bold.eot and /dev/null differ diff --git a/app/fonts/DroidSans-Bold.svg b/app/fonts/DroidSans-Bold.svg deleted file mode 100644 index 7261a47f..00000000 --- a/app/fonts/DroidSans-Bold.svg +++ /dev/null @@ -1,2023 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/fonts/DroidSans-Bold.ttf b/app/fonts/DroidSans-Bold.ttf deleted file mode 100644 index d673c96c..00000000 Binary files a/app/fonts/DroidSans-Bold.ttf and /dev/null differ diff --git a/app/fonts/DroidSans-Bold.woff b/app/fonts/DroidSans-Bold.woff deleted file mode 100644 index 17284a0d..00000000 Binary files a/app/fonts/DroidSans-Bold.woff and /dev/null differ diff --git a/app/fonts/DroidSans.eot b/app/fonts/DroidSans.eot deleted file mode 100644 index 4bb3ed5f..00000000 Binary files a/app/fonts/DroidSans.eot and /dev/null differ diff --git a/app/fonts/DroidSans.svg b/app/fonts/DroidSans.svg deleted file mode 100644 index 9f01d0a6..00000000 --- a/app/fonts/DroidSans.svg +++ /dev/null @@ -1,2023 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/fonts/DroidSans.ttf b/app/fonts/DroidSans.ttf deleted file mode 100644 index 3f406f29..00000000 Binary files a/app/fonts/DroidSans.ttf and /dev/null differ diff --git a/app/fonts/DroidSans.woff b/app/fonts/DroidSans.woff deleted file mode 100644 index 51083939..00000000 Binary files a/app/fonts/DroidSans.woff and /dev/null differ diff --git a/app/fonts/OpenSans-CondLight-webfont.eot b/app/fonts/OpenSans-CondLight.eot similarity index 100% rename from app/fonts/OpenSans-CondLight-webfont.eot rename to app/fonts/OpenSans-CondLight.eot diff --git a/app/fonts/OpenSans-CondLight-webfont.svg b/app/fonts/OpenSans-CondLight.svg similarity index 100% rename from app/fonts/OpenSans-CondLight-webfont.svg rename to app/fonts/OpenSans-CondLight.svg diff --git a/app/fonts/OpenSans-CondLight-webfont.ttf b/app/fonts/OpenSans-CondLight.ttf similarity index 100% rename from app/fonts/OpenSans-CondLight-webfont.ttf rename to app/fonts/OpenSans-CondLight.ttf diff --git a/app/fonts/OpenSans-CondLight-webfont.woff b/app/fonts/OpenSans-CondLight.woff similarity index 100% rename from app/fonts/OpenSans-CondLight-webfont.woff rename to app/fonts/OpenSans-CondLight.woff diff --git a/app/fonts/opensans-regular.eot b/app/fonts/opensans-regular.eot new file mode 100644 index 00000000..6bbc3cf5 Binary files /dev/null and b/app/fonts/opensans-regular.eot differ diff --git a/app/fonts/opensans-regular.svg b/app/fonts/opensans-regular.svg new file mode 100644 index 00000000..25a39523 --- /dev/null +++ b/app/fonts/opensans-regular.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/fonts/opensans-regular.ttf b/app/fonts/opensans-regular.ttf new file mode 100644 index 00000000..c537f838 Binary files /dev/null and b/app/fonts/opensans-regular.ttf differ diff --git a/app/fonts/opensans-regular.woff b/app/fonts/opensans-regular.woff new file mode 100644 index 00000000..e231183d Binary files /dev/null and b/app/fonts/opensans-regular.woff differ diff --git a/app/fonts/opensans-semibold.eot b/app/fonts/opensans-semibold.eot new file mode 100644 index 00000000..d8375dd0 Binary files /dev/null and b/app/fonts/opensans-semibold.eot differ diff --git a/app/fonts/opensans-semibold.svg b/app/fonts/opensans-semibold.svg new file mode 100644 index 00000000..eec4db8b --- /dev/null +++ b/app/fonts/opensans-semibold.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/fonts/opensans-semibold.ttf b/app/fonts/opensans-semibold.ttf new file mode 100644 index 00000000..b3290843 Binary files /dev/null and b/app/fonts/opensans-semibold.ttf differ diff --git a/app/fonts/opensans-semibold.woff b/app/fonts/opensans-semibold.woff new file mode 100644 index 00000000..28d6adee Binary files /dev/null and b/app/fonts/opensans-semibold.woff differ diff --git a/app/fonts/ostrichSans.eot b/app/fonts/ostrichSans.eot deleted file mode 100755 index 8cad119a..00000000 Binary files a/app/fonts/ostrichSans.eot and /dev/null differ diff --git a/app/fonts/ostrichSans.svg b/app/fonts/ostrichSans.svg deleted file mode 100755 index ddb14919..00000000 --- a/app/fonts/ostrichSans.svg +++ /dev/null @@ -1,141 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : Copyright c 2011 by Tyler Finck All rights reserved -Designer : Tyler Finck -Foundry : Tyler Finck -Foundry URL : httpwwwsurslycom - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/fonts/ostrichSans.ttf b/app/fonts/ostrichSans.ttf deleted file mode 100755 index 58545d6f..00000000 Binary files a/app/fonts/ostrichSans.ttf and /dev/null differ diff --git a/app/fonts/ostrichSans.woff b/app/fonts/ostrichSans.woff deleted file mode 100755 index 19d50b5c..00000000 Binary files a/app/fonts/ostrichSans.woff and /dev/null differ diff --git a/app/images/menu.png b/app/images/menu.png index 9b5a06d0..ab9bb220 100644 Binary files a/app/images/menu.png and b/app/images/menu.png differ diff --git a/app/js/jquery-ui.drag-multiple-custom.js b/app/js/jquery-ui.drag-multiple-custom.js new file mode 100644 index 00000000..c8d0c0fa --- /dev/null +++ b/app/js/jquery-ui.drag-multiple-custom.js @@ -0,0 +1,160 @@ +(function($) { + var multipleSortableClass = 'ui-multisortable-multiple'; + var dragStarted = false; + + var multiSort = {}; + + multiSort.isBelow = function(elm, compare) { + var elmOriginalPosition = elm.data('dragmultiple:originalPosition'); + var compareOriginalPosition = compare.data('dragmultiple:originalPosition'); + + return elmOriginalPosition.top > compareOriginalPosition.top; + }; + + multiSort.reset = function(elm) { + $(elm) + .removeClass("ui-sortable-helper") + .removeAttr('style') + .data('dragMultipleActive', false); + }; + + multiSort.sort = function(current, positions) { + positions.after.reverse(); + + $.each(positions.after, function () { + multiSort.reset(this); + current.after(this); + }); + + $.each(positions.before, function () { + multiSort.reset(this); + current.before(this); + }); + }; + + multiSort.sortPositions = function(elm, current) { + //saved if the elements are after or before the current + var insertAfter = []; + var insertBefore = []; + + $(elm).find('.' + multipleSortableClass).each(function () { + var elm = $(this); + + if (elm[0] === current[0] || !current.hasClass(multipleSortableClass)) return; + + if (multiSort.isBelow(elm, current)) { + insertAfter.push(elm); + } else { + insertBefore.push(elm); + } + }); + + return {'after': insertAfter, 'before': insertBefore}; + }; + + $.widget( "ui.sortable", $.ui.sortable, { + _mouseStart: function() { + dragStarted = false; + + this._superApply( arguments ); + }, + _createHelper: function () { + var helper = this._superApply( arguments ); + + if ($(helper).hasClass(multipleSortableClass)) { + $(this.element).find('.' + multipleSortableClass).each(function () { + $(this) + .data('dragmultiple:originalPosition', $(this).position()) + .data('dragMultipleActive', true); + }); + } + + return helper; + }, + _mouseStop: function (event, ui) { + var current = this.helper; + var elms = []; + + if (current.hasClass(multipleSortableClass)) { + elms = $(this.element).find('.' + multipleSortableClass); + } + + if (!elms.length) { + elms = [current]; + } + + //save the order of the elements relative to the main + var positions = multiSort.sortPositions(this.element, current); + + this._superApply( arguments ); + + if (this.element !== this.currentContainer.element) { + // change to another sortable list + multiSort.sort(current, positions); + + $(this.currentContainer.element).trigger('multiplesortreceive', { + 'item': current, + 'items': elms + }); + } else if (current.hasClass(multipleSortableClass)) { + // sort in the same list + multiSort.sort(current, positions); + } + + $(this.element).trigger('multiplesortstop', { + 'item': current, + 'items': elms + }); + }, + _mouseDrag: function(key, value) { + this._super(key, value); + + var current = this.helper; + + if (!current.hasClass(multipleSortableClass)) return; + + // following the drag element + var currentLeft = current.position().left; + var currentTop = current.position().top; + var currentZIndex = current.css('z-index'); + var currentPosition = current.css('position'); + + var positions = multiSort.sortPositions(this.element, current); + + positions.before.reverse(); + + [{'positions': positions.after, type: 'after'}, + {'positions': positions.before, type: 'before'}] + .forEach(function (item) { + $.each(item.positions, function (index, elm) { + var top; + + if (item.type === 'after') { + top = currentTop + ((index + 1) * current.outerHeight()); + } else { + top = currentTop - ((index + 1) * current.outerHeight()); + } + + elm + .addClass("ui-sortable-helper") + .css({ + width: elm.outerWidth(), + height: elm.outerHeight(), + position: currentPosition, + zIndex: currentZIndex, + top: top, + left: currentLeft + }); + }); + }); + + // it only refresh position the first time because + // jquery-ui has saved the old positions of the draggable elements + // and with this will remove all elements with dragMultipleActive + if (!dragStarted) { + dragStarted = true; + this.refreshPositions(); + } + } + }); +}(jQuery)) diff --git a/app/js/jquery.ui.git.js b/app/js/jquery.ui.git-custom.js similarity index 99% rename from app/js/jquery.ui.git.js rename to app/js/jquery.ui.git-custom.js index 524b6c72..327fb2a1 100644 --- a/app/js/jquery.ui.git.js +++ b/app/js/jquery.ui.git-custom.js @@ -789,7 +789,6 @@ $.Widget.prototype = { } } } - this.element.trigger( event, data ); return !( $.isFunction( callback ) && callback.apply( this.element[0], [ event ].concat( data ) ) === false || @@ -2368,11 +2367,9 @@ $.ui.ddmanager = { if ( draggable.options.refreshPositions ) { $.ui.ddmanager.prepareOffsets( draggable, event ); } - // Run through all droppables and check their positions based on specific tolerance options $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { - - if ( this.options.disabled || this.greedyChild || !this.visible ) { + if ( this.options.disabled || this.greedyChild || !this.visible || $(this).data('dragMultipleActive')) { return; } @@ -4107,11 +4104,15 @@ return $.widget("ui.sortable", $.ui.mouse, { //Rearrange for (i = this.items.length - 1; i >= 0; i--) { - //Cache variables and intersection, continue if no intersection item = this.items[i]; itemElement = item.item[0]; intersection = this._intersectsWithPointer(item); + + if (item.item.data('dragMultipleActive')) { + continue; + } + if (!intersection) { continue; } @@ -4166,7 +4167,6 @@ return $.widget("ui.sortable", $.ui.mouse, { }, _mouseStop: function(event, noPropagation) { - if(!event) { return; } @@ -4471,6 +4471,9 @@ return $.widget("ui.sortable", $.ui.mouse, { for (i = this.items.length - 1; i >= 0; i--){ item = this.items[i]; + if ($(item.item).data('dragMultipleActive')) { + continue; + } //We ignore calculating positions of all connected containers when we're not over them if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { @@ -4536,7 +4539,6 @@ return $.widget("ui.sortable", $.ui.mouse, { return element; }, update: function(container, p) { - // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified if(className && !o.forcePlaceholderSize) { @@ -4661,7 +4663,6 @@ return $.widget("ui.sortable", $.ui.mouse, { }, _createHelper: function(event) { - var o = this.options, helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); @@ -4888,7 +4889,6 @@ return $.widget("ui.sortable", $.ui.mouse, { }, _rearrange: function(event, i, a, hardRefresh) { - a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); //Various things done here to improve the performance: diff --git a/app/js/sha1.js b/app/js/sha1-custom.js similarity index 100% rename from app/js/sha1.js rename to app/js/sha1-custom.js diff --git a/app/partials/admin-roles.jade b/app/partials/admin-roles.jade index a93539d3..900332e5 100644 --- a/app/partials/admin-roles.jade +++ b/app/partials/admin-roles.jade @@ -21,6 +21,8 @@ block content | {{ role.name }} span ({{ role.members_count }} members with this role) + div.any-computable-role(ng-hide="anyComputableRole") Be careful, no role in your project will be able to estimate the point value for user stories + div.general-category | When enabled, members assigned to this role will be able to estimate the point value for user stories div.check diff --git a/app/partials/cancel-account.jade b/app/partials/cancel-account.jade new file mode 100644 index 00000000..45dd5275 --- /dev/null +++ b/app/partials/cancel-account.jade @@ -0,0 +1,14 @@ +extends dummy-layout + +block head + title Taiga Your agile, free, and open source project management tool + +block content + div.wrapper + div.login-main + div.login-container + h1.logo + img.logo-svg(src="/svg/logo.svg", alt="TAIGA") + p.tagline Your agile, free, and open source project management tool + + include views/modules/cancel-account-form diff --git a/app/partials/user-profile.jade b/app/partials/user-profile.jade index 9b5550c0..0826e8d8 100644 --- a/app/partials/user-profile.jade +++ b/app/partials/user-profile.jade @@ -60,8 +60,7 @@ block content a.delete-account(href="", title="Delete Taiga account", ng-click="ctrl.openDeleteLightbox()") Delete Taiga account - div.lightbox.lightbox-delete-account.hidden(tg-lb-delete-user) - include views/modules/lightbox-delete-account + div.lightbox.lightbox-delete-account.hidden(tg-lb-delete-user) div.lightbox.lightbox-confirm-use-gravatar.hidden include views/modules/lightbox-use-gravatar diff --git a/app/partials/views/modules/cancel-account-form.jade b/app/partials/views/modules/cancel-account-form.jade new file mode 100644 index 00000000..99108c2b --- /dev/null +++ b/app/partials/views/modules/cancel-account-form.jade @@ -0,0 +1,12 @@ +div.change-email-form-container(tg-cancel-account) + p.change-password-text + strong Cancel your account
+ span We're sorry you are leaving the taiga, we hope you enjoyed your stay :) + + form(ng-submit="ctrl.submit()") + fieldset + input(type="hidden", name="cancel_token", ng-model="data.cancel_token", data-required="true", + placeholder="cancel account token") + + a.button.button-cancel-account.button-gray(href="", title="Yes, I'm leaving") Yes, I'm leaving! + input(type="submit", style="display:none") diff --git a/app/styles/components/basic-table.scss b/app/styles/components/basic-table.scss index c89b2c03..d6849312 100644 --- a/app/styles/components/basic-table.scss +++ b/app/styles/components/basic-table.scss @@ -3,8 +3,8 @@ width: 100%; .row { @include table-flex(stretch, center, flex, row, nowrap, flex-start); - border-bottom: 1px solid $gray-light; - padding: .5rem 0; + border-bottom: 1px solid darken($whitish, 4%); + padding: .3rem 0; text-align: left; width: 100%; @for $i from 1 through 8 { diff --git a/app/styles/components/wysiwyg.scss b/app/styles/components/wysiwyg.scss index 115a7d0a..45906f7c 100644 --- a/app/styles/components/wysiwyg.scss +++ b/app/styles/components/wysiwyg.scss @@ -1,8 +1,10 @@ .wysiwyg { + line-height: 1.4rem; + overflow: auto; h1 { @extend %xlarge; @extend %text; - margin-bottom: .5rem; + line-height: 2.5rem; text-transform: uppercase; } h2 { @@ -43,6 +45,7 @@ } } p { + line-height: 1.4rem; margin-bottom: 1rem; } pre, @@ -56,7 +59,7 @@ white-space: pre; } pre { - line-height: 135%; + line-height: 1.4rem; padding: .5rem; } table { diff --git a/app/styles/dependencies/typography.scss b/app/styles/dependencies/typography.scss index 8ea1f17b..92dc71b8 100755 --- a/app/styles/dependencies/typography.scss +++ b/app/styles/dependencies/typography.scss @@ -2,7 +2,7 @@ // Font face -@each $font-face in DroidSans, DroidSans-Bold, OpenSans-CondLight-webfont, taiga { +@each $font-face in OpenSans-CondLight, opensans-regular, opensans-semibold, taiga { @font-face { font-family: '#{$font-face}'; src: url('../fonts/#{$font-face}.eot?#iefix') format('embedded-opentype'), @@ -35,9 +35,9 @@ h6 { %xxlarge {font-size: 3rem;} // __Font Types__ // -%title {font-family: 'OpenSans-CondLight-webfont';} -%text {font-family: 'DroidSans';} -%bold {font-family: 'DroidSans-Bold';} +%title {font-family: 'OpenSans-CondLight';} +%text {font-family: 'opensans-regular'; line-height: 1.3rem;} +%bold {font-family: 'opensans-semibold';} %taiga {font-family: 'taiga';} h1 { diff --git a/app/styles/layout/base.scss b/app/styles/layout/base.scss index 0291d525..9dc54351 100644 --- a/app/styles/layout/base.scss +++ b/app/styles/layout/base.scss @@ -5,9 +5,9 @@ html { width: 100%; } body { + @extend %text; background: #fff; // fallback color: #444; - font: 16px/21px 'DroidSans', Arial, sans-serif; -webkit-font-smoothing: antialiased; // Fix for webkit renderin height: 100%; min-height: 100%; diff --git a/app/styles/modules/admin/admin-roles.scss b/app/styles/modules/admin/admin-roles.scss index a5c6753f..1ae92901 100644 --- a/app/styles/modules/admin/admin-roles.scss +++ b/app/styles/modules/admin/admin-roles.scss @@ -11,6 +11,12 @@ padding-left: .5rem; } } + .any-computable-role { + background: $red; + color: $white; + margin-bottom: .5rem; + padding: .5rem; + } .general-category { align-items: center; display: flex; diff --git a/app/styles/modules/backlog/backlog-table.scss b/app/styles/modules/backlog/backlog-table.scss index e42ef3b7..90bc279c 100644 --- a/app/styles/modules/backlog/backlog-table.scss +++ b/app/styles/modules/backlog/backlog-table.scss @@ -110,6 +110,7 @@ .backlog-table-body { .row { + border-bottom: 1px solid darken($whitish, 4%); cursor: move; flex-wrap: nowrap; position: relative; @@ -134,6 +135,14 @@ background: lighten($green-taiga, 60%); box-shadow: 1px 1px 10px rgba($black, .1); } + .points { + .not-clickable { + &:hover { + color: $black; + cursor: text; + } + } + } } .row-selected { @include transition (background .2s ease-in); diff --git a/app/styles/modules/common/lightbox.scss b/app/styles/modules/common/lightbox.scss index f5de2abe..d3e57bbb 100644 --- a/app/styles/modules/common/lightbox.scss +++ b/app/styles/modules/common/lightbox.scss @@ -382,6 +382,17 @@ @extend %large; @extend %title; } + .newsletter-delete { + margin-top: 1rem; + text-align: center; + input { + margin-right: .5rem; + +label { + @extend %small; + @extend %text; + } + } + } .delete-options { @include table-flex(); a { diff --git a/app/styles/modules/common/nav.scss b/app/styles/modules/common/nav.scss index 19e0198a..37b32b12 100644 --- a/app/styles/modules/common/nav.scss +++ b/app/styles/modules/common/nav.scss @@ -86,6 +86,10 @@ img { margin: 0 5px 10px; width: 80%; + &:hover { + @include transition(border-color .3s linear); + border-color: $fresh-taiga; + } } .user-settings { position: relative; diff --git a/app/styles/modules/common/related-tasks.scss b/app/styles/modules/common/related-tasks.scss index b6ce9e04..37936812 100644 --- a/app/styles/modules/common/related-tasks.scss +++ b/app/styles/modules/common/related-tasks.scss @@ -169,7 +169,7 @@ } } figcaption { - max-width: 60%; + max-width: 50%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/app/styles/modules/issues/issues-table.scss b/app/styles/modules/issues/issues-table.scss index 6f59d3c7..3c773832 100644 --- a/app/styles/modules/issues/issues-table.scss +++ b/app/styles/modules/issues/issues-table.scss @@ -30,7 +30,7 @@ } .table-main { @extend %small; - border-bottom: 1px solid $gray-light; + border-bottom: 1px solid darken($whitish, 4%); } .avatar { @include table-flex(stretch, center, flex, row, wrap, flex-start); diff --git a/conf/main.example.json b/conf/main.example.json index 3585e04a..b71f9e52 100644 --- a/conf/main.example.json +++ b/conf/main.example.json @@ -3,6 +3,7 @@ "eventsUrl": "ws://localhost:8888/events", "debug": "true", "publicRegisterEnabled": true, + "feedbackEnabled": true, "privacyPolicyUrl": null, "termsOfServiceUrl": null } diff --git a/extras/humans.txt b/extras/humans.txt new file mode 100644 index 00000000..3d621351 --- /dev/null +++ b/extras/humans.txt @@ -0,0 +1,86 @@ +/* the humans responsible & colophon */ +/* humanstxt.org */ + + +/* TEAM */ + + Taiga Engineer & Digital Hermit: Lord Juan Francisco Alcántara + Site: http://www.kaleidos.net/40826D/ + Twitter: nil + Location: Madrid, Spain + + Taiga Engineer & Spartan: Lord Alejandro Alonso + Site: http://kaleidos.net/FC8EAC/ + Twitter: @_superalex_ + Location: Madrid, Spain + + Taiga Engineer & Vodka distiller: Lord Andrey Antukh + Site: http://kaleidos.net/A5694F/ + Twitter: @niwibe + Location: Madrid, Russia + + Taiga Engineer: Lord David Barragán Merino + Site: http://kaleidos.net/FFF8E7/ + Twitter: @bameda + Location: Madrid, Spain + + Taiga Engineer & Troll Master: Lord Jesús Espino García + Site: http://kaleidos.net/007000/ + Twitter: @jespinog + Location: Madrid, Spain + + Taiga UX Consultant & Mistress of the Dark: Pilar Esteban + Site: https://www.linkedin.com/in/pilaresteban + Twitter: @devilme + Location: Madrid, Spain + + Taiga Engineer & African Dancer: Anler Hernández + Site: http://www.kaleidos.net/2099DB/ + Twitter: @anler + Location: Madrid, Cuba + + Taiga UI Designer, Frontend Engineer & Paella Masterchef: Lord Xavier Julián + Site: http://kaleidos.net/CC0000/ + Twitter: @Xaviju + Location: Madrid, Spain + + Taiga UI Designer: Juan de la Cruz + Site: http://kaleidos.net + Twitter: @elhombretecla + Location: Madrid, Spain + + Taiga CEO, Community Manager & Chico Almodobar: Ricky Posner + Twitter: @eposner + Location: Madrid, Spain + + Taiga CEO & Dungeon Master: Lord Pablo Ruiz Múzquiz + Site: http://kaleidos.net/761CEC/ + Twitter: @diacritica + Location: Madrid, Spain + + +/* SITE */ + Standards: HTML5, CSS3 + Components: Django, AngularJS, jQuery + Software: PostgreSQL, RabbitMQ, Redis + Languajes: Python, CoffeeScript, Jade, Sass + + + .,,. + ,;;*;;;;, for ponies with + .-'``;-');;. magical powers! + /' .-. /*;; + .' \d \;; .;;;, + / o ` \; ,__. ,;*;;;*;, + \__, _.__,' \_.-') __)--.;;;;;*;;;;, + `""`;;;\ /-')_) __) `\' ';;;;;; + ;*;;; -') `)_) |\ | ;;;;*; + ;;;;| `---` O | | ;;*;;; + *;*;\| O / ;;;;;* + ;;;;;/| .-------\ / ;*;;;;; + ;;;*;/ \ | '. (`. ;;;*;;; + ;;;;;'. ; | ) \ | ;;;;;; + ,;*;;;;\/ |. / /` | ';;;*; + ;;;;;;/ |/ / /__/ ';;; + '*jgs/ | / | ;*; + `""""` `""""` ;' diff --git a/extras/robots.txt b/extras/robots.txt new file mode 100644 index 00000000..118674cf --- /dev/null +++ b/extras/robots.txt @@ -0,0 +1,6 @@ +User-agent: * +Disallow: + +# You rush a miracle man, you get rotten miracles. +# +# -- Miracle Max -- diff --git a/gulpfile.coffee b/gulpfile.coffee index a98469fa..56127693 100644 --- a/gulpfile.coffee +++ b/gulpfile.coffee @@ -7,6 +7,7 @@ uglify = require("gulp-uglify") plumber = require("gulp-plumber") wrap = require("gulp-wrap") rename = require("gulp-rename") +flatten = require('gulp-flatten') minifyHTML = require("gulp-minify-html") sass = require("gulp-ruby-sass") @@ -23,10 +24,12 @@ paths = {} paths.app = "app/" paths.dist = "dist/" paths.tmp = "tmp/" +paths.extras = "extras/" paths.jade = [ paths.app + "index.jade", - paths.app + "partials/**/*.jade" + paths.app + "partials/**/*.jade", + paths.app + "plugins/**/*.jade" ] paths.images = paths.app + "images/**/*" @@ -36,6 +39,7 @@ paths.locales = paths.app + "locales/**/*.json" paths.sass = [ paths.app + "styles/**/*.scss" "!#{paths.app}/styles/bourbon/**/*.scss" + paths.app + "plugins/**/*.scss" ] paths.coffee = [ @@ -81,8 +85,9 @@ paths.js = [ paths.app + "vendor/jquery-textcomplete/jquery.textcomplete.js", paths.app + "vendor/markitup/markitup/jquery.markitup.js", paths.app + "vendor/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js", - paths.app + "js/jquery.ui.git.js", - paths.app + "js/sha1.js", + paths.app + "js/jquery.ui.git-custom.js", + paths.app + "js/jquery-ui.drag-multiple-custom.js", + paths.app + "js/sha1-custom.js", paths.app + "plugins/**/*.js" ] @@ -117,15 +122,17 @@ gulp.task "sass-lint", -> .pipe(scsslint({config: "scsslint.yml"})) gulp.task "sass-watch", ["sass-lint"], -> - gulp.src(paths.app + "styles/main.scss") + gulp.src(["#{paths.app}/styles/main.scss", "#{paths.app}/plugins/**/*.scss"]) .pipe(plumber()) + .pipe(concat("all.scss")) .pipe(sass()) .pipe(rename("app.css")) .pipe(gulp.dest(paths.tmp)) gulp.task "sass-deploy", -> - gulp.src(paths.app + "styles/main.scss") + gulp.src(["#{paths.app}/styles/main.scss", "#{paths.app}/plugins/**/*.scss"]) .pipe(plumber()) + .pipe(concat("all.scss")) .pipe(sass()) .pipe(rename("app.css")) .pipe(gulp.dest(paths.tmp)) @@ -169,7 +176,7 @@ gulp.task "conf", -> gulp.src("conf/main.json") .pipe(wrap("angular.module('taigaBase').value('localconf', <%= contents %>);")) .pipe(concat("conf.js")) - .pipe(gulp.dest(paths.tmp)); + .pipe(gulp.dest(paths.tmp)) gulp.task "locales", -> gulp.src("app/locales/en/app.json") @@ -206,7 +213,7 @@ gulp.task "app-watch", ["coffee", "conf", "locales"], -> gulp.src(_paths) .pipe(concat("app.js")) - .pipe(gulp.dest(paths.dist + "js/")); + .pipe(gulp.dest(paths.dist + "js/")) gulp.task "app-deploy", ["coffee", "conf", "locales"], -> _paths = [ @@ -218,7 +225,7 @@ gulp.task "app-deploy", ["coffee", "conf", "locales"], -> gulp.src(_paths) .pipe(concat("app.js")) .pipe(uglify({mangle:false, preserveComments: false})) - .pipe(gulp.dest(paths.dist + "js/")); + .pipe(gulp.dest(paths.dist + "js/")) ############################################################################## # Common tasks @@ -237,11 +244,20 @@ gulp.task "copy-images", -> gulp.src("#{paths.app}/images/**/*") .pipe(gulp.dest("#{paths.dist}/images/")) + gulp.src("#{paths.app}/plugins/**/images/*") + .pipe(flatten()) + .pipe(gulp.dest("#{paths.dist}/images/")) + gulp.task "copy-plugin-templates", -> gulp.src("#{paths.app}/plugins/**/templates/*") .pipe(gulp.dest("#{paths.dist}/plugins/")) -gulp.task "copy", ["copy-fonts", "copy-images", "copy-plugin-templates", "copy-svg"] +gulp.task "copy-extras", -> + gulp.src("#{paths.extras}/*") + .pipe(gulp.dest("#{paths.dist}/")) + + +gulp.task "copy", ["copy-fonts", "copy-images", "copy-plugin-templates", "copy-svg", "copy-extras"] gulp.task "express", -> express = require("express") diff --git a/package.json b/package.json index bcd67acc..47a2c2ee 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "gulp-coffeelint": "~0.4.0", "gulp-concat": "^2.1.7", "gulp-csslint": "^0.1.5", + "gulp-flatten": "0.0.4", "gulp-if": "0.0.5", "gulp-jade": "^0.5.0", "gulp-jade-inheritance": "0.0.4",