From 97170673fa547668d77b933eb52f8c68183a01f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Thu, 13 Nov 2014 17:29:47 +0100 Subject: [PATCH 1/4] Column fold in taskboard --- app/partials/taskboard.jade | 2 +- .../views/modules/taskboard-table.jade | 9 +- app/styles/components/taskboard-task.scss | 1 - .../modules/backlog/taskboard-table.scss | 85 +++++++++++++++++-- 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/app/partials/taskboard.jade b/app/partials/taskboard.jade index 9cdf3e1e..a9a191c0 100644 --- a/app/partials/taskboard.jade +++ b/app/partials/taskboard.jade @@ -11,7 +11,7 @@ block content span(tg-bo-bind="project.name", class="project-name-short") span.green(tg-bo-bind="sprint.name") span.date(tg-date-range="sprint.estimated_start,sprint.estimated_finish") - include views/components/sprint-summary + //- include views/components/sprint-summary div.graphics-container div.burndown(tg-sprint-graph) diff --git a/app/partials/views/modules/taskboard-table.jade b/app/partials/views/modules/taskboard-table.jade index d346793f..7cd36876 100644 --- a/app/partials/views/modules/taskboard-table.jade +++ b/app/partials/views/modules/taskboard-table.jade @@ -2,9 +2,12 @@ div.taskboard-table div.taskboard-table-header div.taskboard-table-inner(tg-taskboard-row-width-fixer) h2.task-colum-name "User story" + //- Add class .colum-hfold in .task-column h2.task-colum-name(ng-repeat="s in taskStatusList track by s.id", - ng-style="{'border-top-color':s.color}") + ng-style="{'border-top-color':s.color}", tg-bo-title="s.name") span(tg-bo-bind="s.name") + a.icon.icon-vfold.hfold(href="", title="Fold Column") + a.icon.icon-vunfold.hunfold.hidden(href="", title="Unfold Column") div.taskboard-table-body(tg-taskboard-table-height-fixer) div.taskboard-table-inner(tg-taskboard-row-width-fixer) @@ -19,7 +22,7 @@ div.taskboard-table span(ng-bind="us.total_points") span points include ../components/addnewtask.jade - + //- Add class .colum-hfold in .task-column div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", tg-taskboard-sortable) div.taskboard-task(ng-repeat="task in usTasks[us.id][st.id] track by task.id", @@ -31,7 +34,7 @@ div.taskboard-table h3.us-title span Unassigned tasks include ../components/addnewtask.jade - + //- Add class .colum-hfold in .task-column div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", tg-taskboard-sortable) div.taskboard-task(ng-repeat="task in usTasks[null][st.id] track by task.id", diff --git a/app/styles/components/taskboard-task.scss b/app/styles/components/taskboard-task.scss index 7b9fe6e0..2a45c564 100644 --- a/app/styles/components/taskboard-task.scss +++ b/app/styles/components/taskboard-task.scss @@ -45,7 +45,6 @@ } .taskboard-task-inner { @include table-flex(); - min-height: 7rem; padding: .5rem; } .taskboard-user-avatar { diff --git a/app/styles/modules/backlog/taskboard-table.scss b/app/styles/modules/backlog/taskboard-table.scss index 1d028e95..4a0f540d 100644 --- a/app/styles/modules/backlog/taskboard-table.scss +++ b/app/styles/modules/backlog/taskboard-table.scss @@ -1,6 +1,7 @@ //Table basic shared vars $column-width: 300px; +$column-folded-width: 45px; $column-flex: 1; $column-shrink: 0; $column-margin: 0 10px 0 0; @@ -21,18 +22,63 @@ $column-margin: 0 10px 0 0; position: absolute; } .task-colum-name { - @extend %large; @include table-flex-child($column-flex, $column-width, $column-shrink, $column-width); + @include table-flex(); + @include justify-content(space-between); + @extend %large; background: $whitish; border-top: 3px solid $gray-light; + cursor: pointer; margin: $column-margin; - padding: .5rem 0; + max-width: $column-width; + padding: .5rem 1rem; position: relative; - text-align: center; text-transform: uppercase; + width: $column-width; &:last-child { margin-right: 0; } + &:hover { + .icon { + &.hfold, + &.hunfold { + @include transition(opacity .2s linear); + opacity: 1; + } + } + } + .icon { + @extend %medium; + @include transition(color .2s linear); + color: $gray-light; + margin-right: .3rem; + &:hover { + color: $green-taiga; + } + &.hfold, + &.hunfold { + @include transition(opacity .2s linear); + @include transform(rotate(90deg)); + display: inline-block; + opacity: 0; + } + } + &.column-hfold { + @include align-items(center); + @include justify-content(center); + max-width: $column-folded-width; + padding: .3rem 0; + width: $column-folded-width; + span { + display: none; + } + .icon { + &.hfold, + &.hunfold { + margin: 0; + } + } + } } } @@ -42,11 +88,40 @@ $column-margin: 0 10px 0 0; overflow-y: scroll; width: 100%; .task-column { - @include table-flex-child($column-flex, $column-width, $column-shrink, $column-width); + @include table-flex-child(); margin: $column-margin; + max-width: $column-width; + width: $column-width; &:last-child { margin-right: 0; } + &.colum-hfold { + max-width: $column-folded-width; + width: $column-folded-width; + .taskboard-task { + background: none; + border: 0; + margin: 0; + min-height: 0; + .taskboard-task-inner { + padding: .2rem; + } + .taskboard-tagline, + .taskboard-text { + display: none; + } + .avatar { + height: 35px; + width: 35px; + } + .icon { + display: none; + } + &.ui-sortable-helper { + box-shadow: none; + } + } + } } .task-row { @include table-flex(); @@ -74,14 +149,12 @@ $column-margin: 0 10px 0 0; } } .taskboard-tasks-box { - //@include filter(saturate(20%)); background: rgba($red, .1); } } } .taskboard-tasks-box { background: $whitish; - //background: $very-light-gray; } .taskboard-userstory-box { From e1362e84d45203dd457322295b4d5ca0b1c3cea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Thu, 13 Nov 2014 18:05:14 +0100 Subject: [PATCH 2/4] Row Fold --- .../views/modules/taskboard-table.jade | 16 +++--- .../modules/backlog/taskboard-table.scss | 54 +++++++++++++++++-- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/app/partials/views/modules/taskboard-table.jade b/app/partials/views/modules/taskboard-table.jade index 7cd36876..9ca0f95d 100644 --- a/app/partials/views/modules/taskboard-table.jade +++ b/app/partials/views/modules/taskboard-table.jade @@ -2,7 +2,7 @@ div.taskboard-table div.taskboard-table-header div.taskboard-table-inner(tg-taskboard-row-width-fixer) h2.task-colum-name "User story" - //- Add class .colum-hfold in .task-column + //- TODO Add class .colum-fold in .task-column h2.task-colum-name(ng-repeat="s in taskStatusList track by s.id", ng-style="{'border-top-color':s.color}", tg-bo-title="s.name") span(tg-bo-bind="s.name") @@ -11,8 +11,11 @@ div.taskboard-table div.taskboard-table-body(tg-taskboard-table-height-fixer) div.taskboard-table-inner(tg-taskboard-row-width-fixer) - div.task-row(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked}") + //- TODO: Add class .row-fold in .task-column + div.task-row.row-fold(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked}") div.taskboard-userstory-box.task-column(tg-bo-title="us.blocked_note") + a.icon.icon-vfold.vfold(href="", title="Fold Row") + a.icon.icon-vunfold.vunfold.hidden(href="", title="Unfold Row") h3.us-title a(href="", tg-nav="project-userstories-detail:project=project.slug,ref=us.ref", tg-bo-title="'#' + us.ref + ' ' + us.subject") @@ -21,20 +24,21 @@ div.taskboard-table p.points-value span(ng-bind="us.total_points") span points - include ../components/addnewtask.jade - //- Add class .colum-hfold in .task-column + include ../components/addnewtask + //- TODO: Add class .colum-fold in .task-column div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", tg-taskboard-sortable) div.taskboard-task(ng-repeat="task in usTasks[us.id][st.id] track by task.id", tg-taskboard-task) include ../components/taskboard-task - div.task-row(ng-init="us = null") + //- TODO: Add class .row-fold in .task-Column + div.task-row.row-fold(ng-init="us = null") div.taskboard-userstory-box.task-column h3.us-title span Unassigned tasks include ../components/addnewtask.jade - //- Add class .colum-hfold in .task-column + //- TODO Add class .colum-fold in .task-column div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", tg-taskboard-sortable) div.taskboard-task(ng-repeat="task in usTasks[null][st.id] track by task.id", diff --git a/app/styles/modules/backlog/taskboard-table.scss b/app/styles/modules/backlog/taskboard-table.scss index 4a0f540d..d4e46c89 100644 --- a/app/styles/modules/backlog/taskboard-table.scss +++ b/app/styles/modules/backlog/taskboard-table.scss @@ -63,7 +63,7 @@ $column-margin: 0 10px 0 0; opacity: 0; } } - &.column-hfold { + &.column-fold { @include align-items(center); @include justify-content(center); max-width: $column-folded-width; @@ -95,7 +95,7 @@ $column-margin: 0 10px 0 0; &:last-child { margin-right: 0; } - &.colum-hfold { + &.colum-fold { max-width: $column-folded-width; width: $column-folded-width; .taskboard-task { @@ -152,25 +152,71 @@ $column-margin: 0 10px 0 0; background: rgba($red, .1); } } + &.row-fold { + min-height: 0; + .taskboard-userstory-box { + .us-title { + @include ellipsis(100%); + } + .points-value, + .icon-plus, + .icon-bulk { + display: none; + } + } + .task-column { + @include table-flex(); + @include flex-direction(row); + } + .taskboard-task { + background: none; + border: 0; + margin: 0; + max-width: 40px; + min-height: 0; + width: 40px; + .taskboard-task-inner { + padding: .2rem; + } + .taskboard-tagline, + .taskboard-text { + display: none; + } + .avatar { + height: 35px; + width: 35px; + } + .icon { + display: none; + } + &.ui-sortable-helper { + box-shadow: none; + } + } + } } .taskboard-tasks-box { background: $whitish; } .taskboard-userstory-box { - padding: .5rem; + padding: .5rem .5rem .5rem 1.5rem; .icon { @include transition(color .2s linear); color: $gray-light; position: absolute; right: .5rem; - top: 1rem; + top: .7rem; &:hover { color: $green-taiga; } &.icon-plus { right: 2rem; } + &.icon-vfold { + left: 0; + right: inherit; + } } } } From 1619ef9383d6b52e2e6111030cc01821015f6217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Fri, 14 Nov 2014 09:47:22 +0100 Subject: [PATCH 3/4] Fold/unfold comments --- .../views/modules/taskboard-table.jade | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/app/partials/views/modules/taskboard-table.jade b/app/partials/views/modules/taskboard-table.jade index 9ca0f95d..4e3874d1 100644 --- a/app/partials/views/modules/taskboard-table.jade +++ b/app/partials/views/modules/taskboard-table.jade @@ -1,3 +1,19 @@ +// + Column fold integration: + 1. If click on column fold button search all TODOS and add class .colum-fold fold where indicated in comments. + 2. Hide column fold button and show column unfold button (sibling) + 3. Recalculate container table width. + + Row Fold integration: + 1. If click on row fold button search all TODOS and add class .row-fold fold where indicated in comments. + 2. Hide row fold button and show column unfold button (sibling) + 3. Recalculate container table width. + + Row and column integration + 1. I think we will need to do som JS calcs to fix this. Not sure at the moment. + + + div.taskboard-table div.taskboard-table-header div.taskboard-table-inner(tg-taskboard-row-width-fixer) @@ -12,7 +28,7 @@ div.taskboard-table div.taskboard-table-body(tg-taskboard-table-height-fixer) div.taskboard-table-inner(tg-taskboard-row-width-fixer) //- TODO: Add class .row-fold in .task-column - div.task-row.row-fold(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked}") + div.task-row(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked}") div.taskboard-userstory-box.task-column(tg-bo-title="us.blocked_note") a.icon.icon-vfold.vfold(href="", title="Fold Row") a.icon.icon-vunfold.vunfold.hidden(href="", title="Unfold Row") @@ -33,7 +49,7 @@ div.taskboard-table include ../components/taskboard-task //- TODO: Add class .row-fold in .task-Column - div.task-row.row-fold(ng-init="us = null") + div.task-row(ng-init="us = null") div.taskboard-userstory-box.task-column h3.us-title span Unassigned tasks From 533395202be144cb2ee92b9e4963f8c561cc7f76 Mon Sep 17 00:00:00 2001 From: Juanfran Date: Tue, 18 Nov 2014 17:01:12 +0100 Subject: [PATCH 4/4] fold/unfold taskboard tasks columns & us rows --- app/coffee/modules/resources/tasks.coffee | 24 +++ app/coffee/modules/taskboard/main.coffee | 178 +++++++++++++----- .../views/components/taskboard-task.jade | 3 +- .../views/modules/taskboard-table.jade | 50 ++--- app/styles/components/taskboard-task.scss | 1 - .../modules/backlog/taskboard-table.scss | 128 ++++++------- 6 files changed, 223 insertions(+), 161 deletions(-) diff --git a/app/coffee/modules/resources/tasks.coffee b/app/coffee/modules/resources/tasks.coffee index 07cacb18..3e29f612 100644 --- a/app/coffee/modules/resources/tasks.coffee +++ b/app/coffee/modules/resources/tasks.coffee @@ -27,6 +27,8 @@ generateHash = taiga.generateHash resourceProvider = ($repo, $http, $urls, $storage) -> service = {} hashSuffix = "tasks-queryparams" + hashSuffixStatusColumnModes = "tasks-statuscolumnmodels" + hashSuffixUsRowModes = "tasks-usrowmodels" service.get = (projectId, taskId) -> params = service.getQueryParams(projectId) @@ -65,6 +67,28 @@ resourceProvider = ($repo, $http, $urls, $storage) -> hash = generateHash([projectId, ns]) return $storage.get(hash) or {} + service.storeStatusColumnModes = (projectId, params) -> + ns = "#{projectId}:#{hashSuffixStatusColumnModes}" + hash = generateHash([projectId, ns]) + $storage.set(hash, params) + + service.getStatusColumnModes = (projectId) -> + ns = "#{projectId}:#{hashSuffixStatusColumnModes}" + hash = generateHash([projectId, ns]) + return $storage.get(hash) or {} + + service.storeUsRowModes = (projectId, sprintId, params) -> + ns = "#{projectId}:#{hashSuffixUsRowModes}" + hash = generateHash([projectId, sprintId, ns]) + + $storage.set(hash, params) + + service.getUsRowModes = (projectId, sprintId) -> + ns = "#{projectId}:#{hashSuffixUsRowModes}" + hash = generateHash([projectId, sprintId, ns]) + + return $storage.get(hash) or {} + return (instance) -> instance.tasks = service diff --git a/app/coffee/modules/taskboard/main.coffee b/app/coffee/modules/taskboard/main.coffee index e25fe79f..15e5cf7d 100644 --- a/app/coffee/modules/taskboard/main.coffee +++ b/app/coffee/modules/taskboard/main.coffee @@ -103,7 +103,6 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin) loadProject: -> return @rs.projects.get(@scope.projectId).then (project) => @scope.project = project - @scope.$emit('project:loaded', project) # Not used at this momment @scope.pointsList = _.sortBy(project.points, "order") # @scope.roleList = _.sortBy(project.roles, "order") @@ -112,6 +111,9 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin) @scope.taskStatusList = _.sortBy(project.task_statuses, "order") @scope.usStatusList = _.sortBy(project.us_statuses, "order") @scope.usStatusById = groupBy(project.us_statuses, (e) -> e.id) + + @scope.$emit('project:loaded', project) + return project loadSprintStats: -> @@ -218,6 +220,8 @@ class TaskboardController extends mixOf(taiga.Controller, taiga.PageMixin) promise = @repo.save(task) + @rootscope.$broadcast("sprint:task:moved", task) + promise.then => @.refreshTasksOrder(tasks) @.loadSprintStats() @@ -291,22 +295,6 @@ TaskboardTaskDirective = ($rootscope) -> module.directive("tgTaskboardTask", ["$rootScope", TaskboardTaskDirective]) - -############################################################################# -## Taskboard Task Row Size Fixer Directive -############################################################################# - -TaskboardRowWidthFixerDirective = -> - link = ($scope, $el, $attrs) -> - bindOnce $scope, "taskStatusList", (statuses) -> - itemSize = 300 + (10 * statuses.length) - size = (1 + statuses.length) * itemSize - $el.css("width", "#{size}px") - - return {link: link} - -module.directive("tgTaskboardRowWidthFixer", TaskboardRowWidthFixerDirective) - ############################################################################# ## Taskboard Table Height Fixer Directive ############################################################################# @@ -331,64 +319,156 @@ TaskboardTableHeightFixerDirective = -> module.directive("tgTaskboardTableHeightFixer", TaskboardTableHeightFixerDirective) +############################################################################# +## Taskboard Squish Column Directive +############################################################################# + +TaskboardSquishColumnDirective = (rs) -> + avatarWidth = 40 + + link = ($scope, $el, $attrs) -> + $scope.$on "sprint:task:moved", () => + recalculateTaskboardWidth() + + bindOnce $scope, "usTasks", (project) -> + $scope.statusesFolded = rs.tasks.getStatusColumnModes($scope.project.id) + $scope.usFolded = rs.tasks.getUsRowModes($scope.project.id, $scope.sprintId) + + recalculateTaskboardWidth() + + $scope.foldStatus = (status) -> + $scope.statusesFolded[status.id] = !!!$scope.statusesFolded[status.id] + rs.tasks.storeStatusColumnModes($scope.projectId, $scope.statusesFolded) + + recalculateTaskboardWidth() + + $scope.foldUs = (us) -> + if !us + $scope.usFolded["unassigned"] = !!!$scope.usFolded["unassigned"] + else + $scope.usFolded[us.id] = !!!$scope.usFolded[us.id] + + rs.tasks.storeUsRowModes($scope.projectId, $scope.sprintId, $scope.usFolded) + + recalculateTaskboardWidth() + + getCeilWidth = (usId, statusId) => + tasks = $scope.usTasks[usId][statusId].length + + if $scope.statusesFolded[statusId] + if tasks and $scope.usFolded[usId] + tasksMatrixSize = Math.round(Math.sqrt(tasks)) + width = avatarWidth * tasksMatrixSize + else + width = avatarWidth + + return width + + return 0 + + setStatusColumnWidth = (statusId, width) => + column = $el.find(".squish-status-#{statusId}") + + if width + column.css('max-width', width) + else + column.removeAttr("style") + + refreshTaskboardTableWidth = () => + columnWidths = [] + + columns = $el.find(".task-colum-name") + + columnWidths = _.map columns, (column) -> + return $(column).outerWidth(true) + + totalWidth = _.reduce columnWidths, (total, width) -> + return total + width + + $el.find('.taskboard-table-inner').css("width", totalWidth) + + recalculateStatusColumnWidth = (statusId) => + statusFoldedWidth = 0 + + _.forEach $scope.userstories, (us) -> + width = getCeilWidth(us.id, statusId) + + statusFoldedWidth = width if width > statusFoldedWidth + + setStatusColumnWidth(statusId, statusFoldedWidth) + + recalculateTaskboardWidth = () => + _.forEach $scope.taskStatusList, (status) -> + recalculateStatusColumnWidth(status.id) + + refreshTaskboardTableWidth() + + return + + return {link: link} + +module.directive("tgTaskboardSquishColumn", ["$tgResources", TaskboardSquishColumnDirective]) ############################################################################# ## Taskboard User Directive ############################################################################# TaskboardUserDirective = ($log) -> - template = _.template(""" -
- class="not-clickable"<% } %>> - <%- name %> + template = """ +
+ +
- """) # TODO: i18n + + + """ # TODO: i18n clickable = false - link = ($scope, $el, $attrs, $model) -> - if not $attrs.tgTaskboardUserAvatar? - return $log.error "TaskboardUserDirective: no attr is defined" + link = ($scope, $el, $attrs) -> + username_label = $el.parent().find("a.task-assigned") + username_label.on "click", (event) -> + if $el.find('a').hasClass('noclick') + return - wtid = $scope.$watch $attrs.tgTaskboardUserAvatar, (v) -> - if not $scope.usersById? - $log.error "TaskboardUserDirective requires userById set in scope." - wtid() - else - user = $scope.usersById[v] - render(user) + $ctrl = $el.controller() + $ctrl.editTaskAssignedTo($scope.task) + + $scope.$watch 'task.assigned_to', (assigned_to) -> + user = $scope.usersById[assigned_to] - render = (user) -> if user is undefined - ctx = {name: "Unassigned", imgurl: "/images/unnamed.png", clickable: clickable} + _.assign($scope, {name: "Unassigned", imgurl: "/images/unnamed.png", clickable: clickable}) else - ctx = {name: user.full_name_display, imgurl: user.photo, clickable: clickable} + _.assign($scope, {name: user.full_name_display, imgurl: user.photo, clickable: clickable}) - html = template(ctx) - $el.html(html) - username_label = $el.parent().find("a.task-assigned") - username_label.html(ctx.name) - username_label.on "click", (event) -> - if $el.find('a').hasClass('noclick') - return + username_label.text($scope.name) - us = $model.$modelValue - $ctrl = $el.controller() - $ctrl.editTaskAssignedTo(us) bindOnce $scope, "project", (project) -> if project.my_permissions.indexOf("modify_task") > -1 clickable = true - $el.on "click", (event) => + $el.find(".avatar-assigned-to").on "click", (event) => if $el.find('a').hasClass('noclick') return - us = $model.$modelValue $ctrl = $el.controller() - $ctrl.editTaskAssignedTo(us) + $ctrl.editTaskAssignedTo($scope.task) - return {link: link, require:"ngModel"} + return { + link: link, + template: template, + scope: { + "usersById": "=users", + "project": "=", + "task": "=", + } + } module.directive("tgTaskboardUserAvatar", ["$log", TaskboardUserDirective]) diff --git a/app/partials/views/components/taskboard-task.jade b/app/partials/views/components/taskboard-task.jade index 9fd01538..29311f7c 100644 --- a/app/partials/views/components/taskboard-task.jade +++ b/app/partials/views/components/taskboard-task.jade @@ -1,7 +1,6 @@ div.taskboard-tagline(tg-colorize-tags="task.tags", tg-colorize-tags-type="taskboard") div.taskboard-task-inner - div.taskboard-user-avatar(tg-taskboard-user-avatar="task.assigned_to", ng-model="task", - ng-class="{iocaine: task.is_iocaine}") + div.taskboard-user-avatar(tg-taskboard-user-avatar, users="usersById", task="task", project="project", ng-class="{iocaine: task.is_iocaine}") span.icon.icon-iocaine(ng-if="task.is_iocaine", title="Feeling a bit overwhelmed by a task? Make sure others know about it by clicking on Iocaine when editing a task. It's possible to become immune to this (fictional) deadly poison by consuming small amounts over time just as it's possible to get better at what you do by occasionally taking on extra challenges!") p.taskboard-text a.task-assigned(href="", title="Assign task") diff --git a/app/partials/views/modules/taskboard-table.jade b/app/partials/views/modules/taskboard-table.jade index 4e3874d1..0454497e 100644 --- a/app/partials/views/modules/taskboard-table.jade +++ b/app/partials/views/modules/taskboard-table.jade @@ -1,37 +1,18 @@ -// - Column fold integration: - 1. If click on column fold button search all TODOS and add class .colum-fold fold where indicated in comments. - 2. Hide column fold button and show column unfold button (sibling) - 3. Recalculate container table width. - - Row Fold integration: - 1. If click on row fold button search all TODOS and add class .row-fold fold where indicated in comments. - 2. Hide row fold button and show column unfold button (sibling) - 3. Recalculate container table width. - - Row and column integration - 1. I think we will need to do som JS calcs to fix this. Not sure at the moment. - - - -div.taskboard-table +div.taskboard-table(tg-taskboard-squish-column) div.taskboard-table-header - div.taskboard-table-inner(tg-taskboard-row-width-fixer) + div.taskboard-table-inner h2.task-colum-name "User story" - //- TODO Add class .colum-fold in .task-column - h2.task-colum-name(ng-repeat="s in taskStatusList track by s.id", - ng-style="{'border-top-color':s.color}", tg-bo-title="s.name") + h2.task-colum-name(ng-repeat="s in taskStatusList track by s.id", ng-style="{'border-top-color':s.color}", ng-class="{'column-fold':statusesFolded[s.id]}", class="squish-status-{{s.id}}", tg-bo-title="s.name") span(tg-bo-bind="s.name") - a.icon.icon-vfold.hfold(href="", title="Fold Column") - a.icon.icon-vunfold.hunfold.hidden(href="", title="Unfold Column") + a.icon.icon-vfold.hfold(href="", ng-click='foldStatus(s)', title="Fold Column", ng-class='{hidden:statusesFolded[s.id]}') + a.icon.icon-vunfold.hunfold(href="", title="Unfold Column", ng-click='foldStatus(s)', ng-class='{hidden:!statusesFolded[s.id]}') div.taskboard-table-body(tg-taskboard-table-height-fixer) - div.taskboard-table-inner(tg-taskboard-row-width-fixer) - //- TODO: Add class .row-fold in .task-column - div.task-row(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked}") + div.taskboard-table-inner + div.task-row(ng-repeat="us in userstories track by us.id", ng-class="{blocked: us.is_blocked, 'row-fold':usFolded[us.id]}") div.taskboard-userstory-box.task-column(tg-bo-title="us.blocked_note") - a.icon.icon-vfold.vfold(href="", title="Fold Row") - a.icon.icon-vunfold.vunfold.hidden(href="", title="Unfold Row") + a.icon.icon-vfold.vfold(href="", title="Fold Row", ng-click='foldUs(us)', ng-class='{hidden:usFolded[us.id]}') + a.icon.icon-vunfold.vunfold(href="", title="Unfold Row", ng-click='foldUs(us)', ng-class='{hidden:!usFolded[us.id]}') h3.us-title a(href="", tg-nav="project-userstories-detail:project=project.slug,ref=us.ref", tg-bo-title="'#' + us.ref + ' ' + us.subject") @@ -41,22 +22,19 @@ div.taskboard-table span(ng-bind="us.total_points") span points include ../components/addnewtask - //- TODO: Add class .colum-fold in .task-column - div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", - tg-taskboard-sortable) + div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", tg-taskboard-sortable, class="squish-status-{{st.id}}", ng-class="{'column-fold':statusesFolded[st.id]}") div.taskboard-task(ng-repeat="task in usTasks[us.id][st.id] track by task.id", tg-taskboard-task) include ../components/taskboard-task - //- TODO: Add class .row-fold in .task-Column - div.task-row(ng-init="us = null") + div.task-row(ng-init="us = null", ng-class="{'row-fold':usFolded['unassigned']}") div.taskboard-userstory-box.task-column + a.icon.icon-vfold.vfold(href="", title="Fold Row", ng-click='foldUs()', ng-class="{hidden:usFolded['unassigned']}") + a.icon.icon-vunfold.vunfold(href="", title="Unfold Row", ng-click='foldUs()', ng-class="{hidden:!usFolded['unassigned']}") h3.us-title span Unassigned tasks include ../components/addnewtask.jade - //- TODO Add class .colum-fold in .task-column - div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", - tg-taskboard-sortable) + div.taskboard-tasks-box.task-column(ng-repeat="st in taskStatusList track by st.id", tg-taskboard-sortable, class="squish-status-{{st.id}}", ng-class="{'column-fold':statusesFolded[st.id]}") div.taskboard-task(ng-repeat="task in usTasks[null][st.id] track by task.id", tg-taskboard-task) include ../components/taskboard-task diff --git a/app/styles/components/taskboard-task.scss b/app/styles/components/taskboard-task.scss index 2a45c564..a306cf3e 100644 --- a/app/styles/components/taskboard-task.scss +++ b/app/styles/components/taskboard-task.scss @@ -1,5 +1,4 @@ .taskboard-task { - @include transition (all .4s linear); background: $postit; border: 1px solid $postit-hover; box-shadow: none; diff --git a/app/styles/modules/backlog/taskboard-table.scss b/app/styles/modules/backlog/taskboard-table.scss index d4e46c89..c2a35a58 100644 --- a/app/styles/modules/backlog/taskboard-table.scss +++ b/app/styles/modules/backlog/taskboard-table.scss @@ -1,11 +1,46 @@ //Table basic shared vars $column-width: 300px; -$column-folded-width: 45px; -$column-flex: 1; +$column-flex: 0; $column-shrink: 0; $column-margin: 0 10px 0 0; +%fold { + .taskboard-task { + background: none; + border: 0; + margin: 0; + min-height: 0; + .taskboard-task-inner { + padding: .2rem; + } + .taskboard-tagline, + .taskboard-text { + display: none; + } + .avatar { + height: 35px; + width: 35px; + } + .icon { + display: none; + } + &.ui-sortable-helper { + box-shadow: none; + } + } + &.task-column, + .task-column { + @include table-flex(flex-start); + @include flex-direction(row); + } + .avatar-task-link { + display: block; + } + .avatar-assigned-to { + display: none; + } +} .taskboard-table { overflow: hidden; @@ -28,7 +63,6 @@ $column-margin: 0 10px 0 0; @extend %large; background: $whitish; border-top: 3px solid $gray-light; - cursor: pointer; margin: $column-margin; max-width: $column-width; padding: .5rem 1rem; @@ -38,15 +72,6 @@ $column-margin: 0 10px 0 0; &:last-child { margin-right: 0; } - &:hover { - .icon { - &.hfold, - &.hunfold { - @include transition(opacity .2s linear); - opacity: 1; - } - } - } .icon { @extend %medium; @include transition(color .2s linear); @@ -57,18 +82,14 @@ $column-margin: 0 10px 0 0; } &.hfold, &.hunfold { - @include transition(opacity .2s linear); @include transform(rotate(90deg)); display: inline-block; - opacity: 0; } } &.column-fold { @include align-items(center); @include justify-content(center); - max-width: $column-folded-width; padding: .3rem 0; - width: $column-folded-width; span { display: none; } @@ -88,39 +109,22 @@ $column-margin: 0 10px 0 0; overflow-y: scroll; width: 100%; .task-column { - @include table-flex-child(); + @include table-flex-child($column-flex, $column-width, $column-shrink, $column-width); margin: $column-margin; max-width: $column-width; width: $column-width; &:last-child { margin-right: 0; } - &.colum-fold { - max-width: $column-folded-width; - width: $column-folded-width; - .taskboard-task { - background: none; - border: 0; - margin: 0; - min-height: 0; - .taskboard-task-inner { - padding: .2rem; - } - .taskboard-tagline, - .taskboard-text { - display: none; - } - .avatar { - height: 35px; - width: 35px; - } - .icon { - display: none; - } - &.ui-sortable-helper { - box-shadow: none; - } - } + } + .row-fold { + @extend %fold; + } + .column-fold { + @extend %fold; + .taskboard-task { + max-width: 40px; + width: 40px; } } .task-row { @@ -164,35 +168,6 @@ $column-margin: 0 10px 0 0; display: none; } } - .task-column { - @include table-flex(); - @include flex-direction(row); - } - .taskboard-task { - background: none; - border: 0; - margin: 0; - max-width: 40px; - min-height: 0; - width: 40px; - .taskboard-task-inner { - padding: .2rem; - } - .taskboard-tagline, - .taskboard-text { - display: none; - } - .avatar { - height: 35px; - width: 35px; - } - .icon { - display: none; - } - &.ui-sortable-helper { - box-shadow: none; - } - } } } .taskboard-tasks-box { @@ -213,12 +188,19 @@ $column-margin: 0 10px 0 0; &.icon-plus { right: 2rem; } - &.icon-vfold { + &.icon-vfold, + &.icon-vunfold { left: 0; right: inherit; } } } + .avatar-task-link { + display: none; + } + .avatar-assigned-to { + display: block; + } } .taskboard-userstory-box {