diff --git a/app/coffee/modules/common.coffee b/app/coffee/modules/common.coffee index 11d3fa79..594469a8 100644 --- a/app/coffee/modules/common.coffee +++ b/app/coffee/modules/common.coffee @@ -29,10 +29,10 @@ module = angular.module("taigaCommon", []) CheckPermissionDirective = -> render = ($el, project, permission) -> - $el.show() if project.my_permissions.indexOf(permission) > -1 + $el.removeClass('hidden') if project.my_permissions.indexOf(permission) > -1 link = ($scope, $el, $attrs) -> - $el.hide() + $el.addClass('hidden') permission = $attrs.tgCheckPermission $scope.$watch "project", (project) -> diff --git a/app/coffee/modules/kanban/main.coffee b/app/coffee/modules/kanban/main.coffee index 3ab7a514..1038f5b3 100644 --- a/app/coffee/modules/kanban/main.coffee +++ b/app/coffee/modules/kanban/main.coffee @@ -276,25 +276,6 @@ KanbanDirective = ($repo, $rootscope) -> module.directive("tgKanban", ["$tgRepo", "$rootScope", KanbanDirective]) -############################################################################# -## Kanban Row Size Fixer Directive -############################################################################# - -KanbanRowWidthFixerDirective = -> - link = ($scope, $el, $attrs) -> - bindOnce $scope, "usStatusList", (statuses) -> - itemSize = 310 - size = (statuses.length * itemSize) - 10 - $el.css("width", "#{size}px") - - $scope.$on "$destroy", -> - $el.off() - - return {link: link} - -module.directive("tgKanbanRowWidthFixer", KanbanRowWidthFixerDirective) - - ############################################################################# ## Kanban Column Height Fixer Directive ############################################################################# @@ -355,6 +336,36 @@ KanbanUserstoryDirective = ($rootscope) -> module.directive("tgKanbanUserstory", ["$rootScope", KanbanUserstoryDirective]) +############################################################################# +## Kanban Squish Column Directive +############################################################################# + +KanbanSquishColumnDirective = (rs) -> + + link = ($scope, $el, $attrs) -> + $scope.$on "project:loaded", (event, project) -> + $scope.folds = rs.kanban.getStatusColumnModes(project.id) + updateTableWidth() + + $scope.foldStatus = (status) -> + $scope.folds[status.id] = !!!$scope.folds[status.id] + rs.kanban.storeStatusColumnModes($scope.projectId, $scope.folds) + updateTableWidth() + return + + updateTableWidth = -> + columnWidths = _.map $scope.usStatusList, (status) -> + if $scope.folds[status.id] + return 40 + else + return 310 + totalWidth = _.reduce columnWidths, (total, width) -> + return total + width + $el.find('.kanban-table-inner').css("width", totalWidth) + + return {link: link} + +module.directive("tgKanbanSquishColumn", ["$tgResources", KanbanSquishColumnDirective]) ############################################################################# ## Kaban WIP Limit Directive diff --git a/app/coffee/modules/resources/kanban.coffee b/app/coffee/modules/resources/kanban.coffee index a5c1fd53..b1268dfe 100644 --- a/app/coffee/modules/resources/kanban.coffee +++ b/app/coffee/modules/resources/kanban.coffee @@ -27,6 +27,7 @@ generateHash = taiga.generateHash resourceProvider = ($storage) -> service = {} hashSuffixStatusViewModes = "kanban-statusviewmodels" + hashSuffixStatusColumnModes = "kanban-statuscolumnmodels" service.storeStatusViewModes = (projectId, params) -> ns = "#{projectId}:#{hashSuffixStatusViewModes}" @@ -38,6 +39,16 @@ resourceProvider = ($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 {} + return (instance) -> instance.kanban = service diff --git a/app/fonts/taiga.eot b/app/fonts/taiga.eot index 4d7ef8bb..3993e361 100644 Binary files a/app/fonts/taiga.eot and b/app/fonts/taiga.eot differ diff --git a/app/fonts/taiga.svg b/app/fonts/taiga.svg index ff41af91..f347cfdc 100644 --- a/app/fonts/taiga.svg +++ b/app/fonts/taiga.svg @@ -11,39 +11,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/fonts/taiga.ttf b/app/fonts/taiga.ttf index 8fb9b030..a41437dd 100644 Binary files a/app/fonts/taiga.ttf and b/app/fonts/taiga.ttf differ diff --git a/app/fonts/taiga.woff b/app/fonts/taiga.woff index 14d2f8f5..383aba43 100644 Binary files a/app/fonts/taiga.woff and b/app/fonts/taiga.woff differ diff --git a/app/partials/views/modules/kanban-table.jade b/app/partials/views/modules/kanban-table.jade index 6f29b442..1e80c37b 100644 --- a/app/partials/views/modules/kanban-table.jade +++ b/app/partials/views/modules/kanban-table.jade @@ -1,31 +1,36 @@ -div.kanban-table +div.kanban-table(tg-kanban-squish-column) div.kanban-table-header - div.kanban-table-inner(tg-kanban-row-width-fixer) - h2.task-colum-name(ng-repeat="s in usStatusList track by s.id", - ng-style="{'border-top-color':s.color}") + div.kanban-table-inner + h2.task-colum-name(ng-repeat="s in usStatusList track by s.id", ng-style="{'border-top-color':s.color}", tg-bo-title="s.name", ng-class='{vfold:folds[s.id]}') span(tg-bo-bind="s.name") + div.options - a.icon.icon-minimize(href="", title="Minimize", - ng-if="statusViewModes[s.id] == 'maximized'", - ng-click="ctrl.updateStatusViewMode(s.id, 'minimized')") - a.icon.icon-maximize(href="", title="Maximize", - ng-if="statusViewModes[s.id] == 'minimized'", - ng-click="ctrl.updateStatusViewMode(s.id, 'maximized')") - a.icon.icon-plus(href="", title="Add New task", - ng-click="ctrl.addNewUs('standard', s.id)", - tg-check-permission="add_us") + a.icon.icon-vfold.hfold(href="", ng-click='foldStatus(s)' title="Fold Column", ng-class='{hidden:folds[s.id]}') + a.icon.icon-vunfold.hunfold(href="", ng-click='foldStatus(s)', title="Unfold Column", ng-class='{hidden:!folds[s.id]}') - a.icon.icon-bulk(href="", title="Add New bulk", - ng-click="ctrl.addNewUs('bulk', s.id)", - tg-check-permission="add_us") + + a.icon.icon-vfold(href="", title="Fold Cards", + ng-class="{hidden:statusViewModes[s.id] == 'minimized'}", + ng-click="ctrl.updateStatusViewMode(s.id, 'minimized')") + a.icon.icon-vunfold(href="", title="Unfold Cards", + ng-class="{hidden:statusViewModes[s.id] == 'maximized'}", + ng-click="ctrl.updateStatusViewMode(s.id, 'maximized')") + + a.icon.icon-plus(href="", title="Add New task", + ng-click="ctrl.addNewUs('standard', s.id)", + tg-check-permission="add_us") + + a.icon.icon-bulk(href="", title="Add New bulk", + ng-click="ctrl.addNewUs('bulk', s.id)", + tg-check-permission="add_us") div.kanban-table-body div.kanban-table-inner(tg-kanban-row-width-fixer) - div.kanban-uses-box.task-column(ng-repeat="status in usStatusList track by status.id", + div.kanban-uses-box.task-column(ng-class='{vfold:folds[s.id]}', ng-repeat="s in usStatusList track by s.id", tg-kanban-sortable, tg-kanban-wip-limit, tg-kanban-column-height-fixer) - div.kanban-task(ng-repeat="us in usByStatus[status.id] track by us.id", + div.kanban-task(ng-repeat="us in usByStatus[s.id] track by us.id", tg-kanban-userstory, ng-model="us", - ng-class="ctrl.getCardClass(status.id)") + ng-class="ctrl.getCardClass(s.id)") diff --git a/app/styles/layout/typography.scss b/app/styles/layout/typography.scss index 6ff57c9e..df7f1103 100755 --- a/app/styles/layout/typography.scss +++ b/app/styles/layout/typography.scss @@ -138,108 +138,115 @@ a:visited { .icon-search:before { content: 'd'; } -.icon-video:before { +.icon-wiki:before { content: 'e'; } -.icon-wiki:before { +.icon-settings:before { content: 'f'; } -.icon-settings:before { +.icon-move:before { content: 'g'; } -.icon-move:before { +.icon-filter:before { content: 'h'; } -.icon-filter:before { +.icon-arrow-up:before { content: 'i'; } -.icon-arrow-up:before { +.icon-arrow-right:before { content: 'j'; } -.icon-arrow-right:before { +.icon-arrow-left:before { content: 'k'; } -.icon-arrow-left:before { +.icon-arrow-bottom:before { content: 'l'; } -.icon-arrow-bottom:before { +.icon-edit:before { content: 'm'; } -.icon-edit:before { +.icon-delete:before { content: 'n'; } -.icon-delete:before { +.icon-iocaine:before { content: 'o'; } -.icon-iocaine:before { +.icon-drag-h:before { content: 'p'; } -.icon-drag-h:before { +.icon-drag-v:before { content: 'q'; } -.icon-drag-v:before { +.icon-document:before { content: 'r'; } -.icon-document:before { +.icon-plus:before { content: 's'; } -.icon-plus:before { +.icon-reload:before { content: 't'; } -.icon-reload:before { +.icon-warning:before { content: 'u'; } -.icon-warning:before { +.icon-notification-error:before { content: 'v'; } -.icon-notification-error:before { +.icon-github:before { content: 'w'; } -.icon-github:before { +.icon-check-square:before { content: 'x'; } -.icon-check-square:before { +.icon-warning-alt:before { content: 'y'; } -.icon-warning-alt:before { +.icon-floppy:before { content: 'z'; } -.icon-floppy:before { +.icon-comment:before { content: 'A'; } -.icon-comment:before { +.icon-documents:before { content: 'B'; } -.icon-documents:before { +.icon-attachments:before { content: 'C'; } -.icon-attachments:before { +.icon-caret-up:before { content: 'D'; } -.icon-caret-up:before { +.icon-caret-down:before { content: 'E'; } -.icon-caret-down:before { +.icon-bulk:before { content: 'F'; } -.icon-bulk:before { +.icon-idea:before { content: 'G'; } -.icon-idea:before { +.icon-spinner:before { content: 'H'; } -.icon-spinner:before { +.icon-minimize:before { content: 'I'; } -.icon-minimize:before { +.icon-maximize:before { content: 'J'; } -.icon-maximize:before { +.icon-stats:before { content: 'K'; } -.icon-stats:before { +.icon-copy:before { content: 'L'; } -.icon-copy:before { +.icon-team:before { content: 'M'; } +.icon-vfold:before { + content: 'N'; +} +.icon-vunfold:before { + content: 'O'; +} + diff --git a/app/styles/modules/kanban/kanban-table.scss b/app/styles/modules/kanban/kanban-table.scss index 18792a43..fe12d441 100644 --- a/app/styles/modules/kanban/kanban-table.scss +++ b/app/styles/modules/kanban/kanban-table.scss @@ -1,13 +1,46 @@ //Table basic shared vars $column-width: 300px; -$column-flex: 1; +$column-folded-width: 30px; +$column-flex: 0; $column-shrink: 0; $column-margin: 0 10px 0 0; .kanban-table { overflow: hidden; width: 100%; + .vfold { + &.task-colum-name { + @include table-flex(); + @include align-items(center); + @include justify-content(center); + @include transition(opacity .3s linear); + cursor: pointer; + opacity: .8; + padding: .5rem 0; + .icon-plus, + .icon-bulk, + .icon-vfold, + .icon-vunfold, + span { + display: none; + } + .hunfold { + margin: 0; + } + } + &.task-colum-name, + &.task-column { + @include table-flex-child(1, 0, 0); + max-width: $column-folded-width; + min-height: 2.5rem; + min-width: $column-folded-width; + width: $column-folded-width; + } + .kanban-task { + display: none; + } + } } .kanban-table-header { @@ -20,34 +53,31 @@ $column-margin: 0 10px 0 0; position: absolute; } .task-colum-name { - @include table-flex-child(); + @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; margin: $column-margin; - padding: .5rem 0; + padding: .5rem .5rem .5rem 1rem; position: relative; - text-align: center; text-transform: uppercase; &:last-child { margin-right: 0; } .icon { + @extend %medium; @include transition(color .2s linear); color: $gray-light; - position: absolute; - right: .5rem; - top: .5rem; + margin-right: .3rem; &:hover { color: $green-taiga; } - &.icon-plus { - right: 2rem; - } - &.icon-maximize, - &.icon-minimize { - left: .5rem; - right: inherit; + &.hfold, + &.hunfold { + @include transform(rotate(90deg)); + display: inline-block; } } } @@ -60,7 +90,7 @@ $column-margin: 0 10px 0 0; overflow-x: auto; width: 100%; .task-column { - @include table-flex-child(); + @include table-flex-child($column-flex, $column-width, $column-shrink, $column-width); margin: $column-margin; overflow-y: auto; &:last-child {