diff --git a/src/helpers/saveCollapsedBucketState.js b/src/helpers/saveCollapsedBucketState.js new file mode 100644 index 000000000..df44a8802 --- /dev/null +++ b/src/helpers/saveCollapsedBucketState.js @@ -0,0 +1,30 @@ +const key = 'collapsedBuckets' + +const getAllState = () => { + const saved = localStorage.getItem(key) + if (saved === null) { + return {} + } + + return JSON.parse(saved) +} + +export const saveCollapsedBucketState = (listId, collapsedBuckets) => { + const state = getAllState() + state[listId] = collapsedBuckets + for (const bucketId in state[listId]) { + if (!state[listId][bucketId]) { + delete state[listId][bucketId] + } + } + localStorage.setItem(key, JSON.stringify(state)) +} + +export const getCollapsedBucketState = listId => { + const state = getAllState() + if (typeof state[listId] !== 'undefined') { + return state[listId] + } + + return {} +} diff --git a/src/i18n/lang/en.json b/src/i18n/lang/en.json index ec7cdf76e..fdebc1893 100644 --- a/src/i18n/lang/en.json +++ b/src/i18n/lang/en.json @@ -243,7 +243,8 @@ "deleteBucketText2": "This will not delete any tasks but move them into the default bucket.", "deleteBucketSuccess": "The bucket has been deleted successfully.", "bucketTitleSavedSuccess": "The bucket title has been saved successfully.", - "bucketLimitSavedSuccess": "The bucket limit been saved successfully." + "bucketLimitSavedSuccess": "The bucket limit been saved successfully.", + "collapse": "Collapse this bucket" } }, "namespace": { diff --git a/src/styles/components/kanban.scss b/src/styles/components/kanban.scss index 758d6696a..2f2c9908f 100644 --- a/src/styles/components/kanban.scss +++ b/src/styles/components/kanban.scss @@ -2,6 +2,8 @@ $bucket-background: $grey-100; $task-background: $white; $ease-out: all .3s cubic-bezier(0.23, 1, 0.32, 1); $bucket-width: 300px; +$bucket-header-height: 60px; +$bucket-right-margin: 1rem; $crazy-height-calculation: '100vh - 4.5rem - 1.5rem - 1rem - 1.5rem - 11px'; $crazy-height-calculation-tasks: '#{$crazy-height-calculation} - 1rem - 2.5rem - 2rem - #{$button-height} - 1rem'; @@ -31,7 +33,7 @@ $filter-container-height: '1rem - #{$switch-view-height}'; position: relative; flex: 0 0 $bucket-width; - margin: 0 1rem 0 0; + margin: 0 $bucket-right-margin 0 0; max-height: 100%; min-height: 20px; max-width: $bucket-width; @@ -233,6 +235,18 @@ $filter-container-height: '1rem - #{$switch-view-height}'; a.dropdown-item { padding-right: 1rem; } + + &.is-collapsed { + transform: rotate(90deg) translateX($bucket-width / 2 - $bucket-header-height / 2); + // Using negative margins instead of translateY here to make all other buckets fill the empty space + margin-left: ($bucket-width / 2 - $bucket-header-height / 2) * -1; + margin-right: calc(#{($bucket-width / 2 - $bucket-header-height / 2) * -1} + #{$bucket-right-margin}); + cursor: pointer; + + .tasks, .bucket-footer { + display: none; + } + } } .bucket-header { @@ -240,6 +254,7 @@ $filter-container-height: '1rem - #{$switch-view-height}'; align-items: center; justify-content: space-between; padding: .5rem; + height: $bucket-header-height; .limit { padding-left: .5rem; diff --git a/src/views/list/views/Kanban.vue b/src/views/list/views/Kanban.vue index b9bea14e2..3aa6b6e13 100644 --- a/src/views/list/views/Kanban.vue +++ b/src/views/list/views/Kanban.vue @@ -17,8 +17,13 @@ />
-
-
+