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 {