diff --git a/webapps/src/main/resources/locale/portlet/taskManagement_en.properties b/webapps/src/main/resources/locale/portlet/taskManagement_en.properties
index d02b54c87..db8a77a62 100644
--- a/webapps/src/main/resources/locale/portlet/taskManagement_en.properties
+++ b/webapps/src/main/resources/locale/portlet/taskManagement_en.properties
@@ -220,6 +220,7 @@ label.permalink=Permalink
label.listView=List
label.boardView=Board
label.ganttView=Plan
+label.viewOptions=View options
label.cardsView=Cards
label.start.adding.tasks=Add Tasks
diff --git a/webapps/src/main/webapp/skin/css/tasks.less b/webapps/src/main/webapp/skin/css/tasks.less
index a68a9c145..797985dde 100644
--- a/webapps/src/main/webapp/skin/css/tasks.less
+++ b/webapps/src/main/webapp/skin/css/tasks.less
@@ -1125,11 +1125,47 @@
}
.projectTasksDashboard {
min-height: calc(~"100vh - 117px")!important;
- .projectTasksTabFilter {
- flex: 0 1 70%;
+ .projectBoardToolbar {
+ /* Match the agenda header height/spacing (its application-toolbar is a
+ default v-toolbar) while staying a plain flex row, so the view-switcher
+ menu is not trapped in a v-toolbar stacking context. */
+ min-height: 64px;
+ margin-bottom: 4px;
+ /* Match the board columns' horizontal padding (px-3 = 12px) so the back
+ arrow lines up with the first column content and the right-hand icons
+ line up with the last column content. */
+ padding-inline: 12px;
+ /* Normalise the favorite/AI extension icons + their hover area to the
+ same size as the view / search / advanced-filter icons (36x36). */
+ .boardHeaderExtensions {
+ .v-icon {
+ font-size: 20px !important;
+ }
+ .v-btn {
+ width: 36px !important;
+ height: 36px !important;
+ /* Drop the components' own horizontal margins (e.g. the AI button's
+ me-2) so all the header icons are evenly spaced. */
+ margin-inline-start: 0 !important;
+ margin-inline-end: 0 !important;
+ }
+ }
+ .tasksViewSwitcher {
+ position: relative;
+ }
+ .tasksViewSwitcherMenu {
+ position: absolute;
+ top: calc(100% + 4px);
+ inset-inline-end: 0;
+ z-index: 1000;
+ min-width: 160px;
+ /* The kanban cards use 3D transforms (rotateY/backface) which put them
+ on compositing layers; promote the menu to its own layer too so it
+ composites above the board instead of being painted behind it. */
+ transform: translateZ(0);
+ }
}
.taskViewBreadcrumb {
- flex: 0 1 30%;
a {
i {
color: @greyColorLighten1;
@@ -1142,43 +1178,6 @@
}
}
}
- .tasksToolbar {
- height: auto!important;
- .v-toolbar__content {
- height: auto!important;
- padding: 0!important;
- .taskDisplay {
- .projectTasksViewTabs {
- .v-tabs-bar {
- height: auto!important;
- .taskTabBoard {
- border: 1px solid @borderColor;
- border-radius: 5px 0 0 5px;
- height: 38px;
- min-height: 38px;
- .uiIconBoard {
- .far();
- .fa-clipboard();
- }
- }
- .taskTabList {
- border-radius: 0;
- }
- .taskTabGantt {
- border: 1px solid @borderColor;
- border-radius: 0 5px 5px 0;
- height: 38px;
- min-height: 38px;
- .uiIconGantt {
- .fas();
- .fa-stream();
- }
- }
- }
- }
- }
- }
- }
.tasksView {
.projectTaskItem {
position: relative;
@@ -2536,17 +2535,6 @@
}
}
}
-@media (max-width: 599px) {
- .projectTasksDashboard {
- .taskViewBreadcrumb {
- flex: 0 1 80% !important;
- }
- .projectTasksTabFilter{
- flex: 0 1 20% !important;
- }
- }
-}
-
@media (max-width: 399px) {
.taskDrawer {
.drawerTitle .taskProjectName .projectName {
diff --git a/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewDashboard.vue b/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewDashboard.vue
index ba6e7b189..3270575fc 100644
--- a/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewDashboard.vue
+++ b/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewDashboard.vue
@@ -26,39 +26,26 @@
:ok-label="$t('label.ok')"
:cancel-label="$t('popup.cancel')"
@ok="deleteConfirm()" />
-
+
+
+
+
+
+
+
+
+
+
+ fa-chevron-down
+
+
+
+
+
diff --git a/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewToolbar.vue b/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewToolbar.vue
index d09f6d862..a7d99987a 100644
--- a/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewToolbar.vue
+++ b/webapps/src/main/webapp/vue-app/tasks-management/components/ProjectTasks/TasksViewToolbar.vue
@@ -16,58 +16,81 @@
-->
-
-
-
-
-
- {{ $t('label.boardView') }}
-
-
-
- {{ $t('label.listView') }}
-
-
-
- {{ $t('label.ganttView') }}
-
-
-
-
-
+
[]
},
- taskCardTabView: {
- type: String,
- default: ''
- },
- taskListTabView: {
- type: String,
- default: ''
- },
- taskGanttTabView: {
- type: String,
- default: ''
- },
showCompletedTasks: {
type: Boolean,
default: false
@@ -111,35 +122,37 @@ export default {
data () {
return {
keyword: null,
- awaitingSearch: false,
filterNumber: 0,
- searchonkeyChange: true,
taskViewTabName: 'board',
+ searchOpen: false,
+ searchTimer: null,
};
},
- watch: {
- keyword() {
- if (!this.awaitingSearch) {
- const searchonkeyChange = this.searchonkeyChange;
- setTimeout(() => {
- this.$emit('keyword-changed', this.keyword,searchonkeyChange);
- this.awaitingSearch = false;
- }, 1000);
- }
- this.awaitingSearch = true;
- if (this.searchonkeyChange){
- this.resetFields('query'); }
- this.searchonkeyChange= true;
- },
- },
created() {
+ this.filterNumber = Number(localStorage.getItem('filtersNumber')) || 0;
this.$root.$on('hide-tasks-project', () => {
- $('a.v-tab').removeClass('v-tab--active');
- $('a.taskTabBoard').addClass('v-tab--active');
- this.keyword = null ;
+ this.taskViewTabName = 'board';
+ this.keyword = null;
+ this.searchOpen = false;
});
},
methods: {
+ openSearch() {
+ this.searchOpen = true;
+ this.$nextTick(() => this.$refs.searchField && this.$refs.searchField.focus());
+ },
+ closeSearch() {
+ this.searchOpen = false;
+ },
+ onKeyword(term) {
+ this.keyword = term;
+ if (this.searchTimer) {
+ clearTimeout(this.searchTimer);
+ }
+ this.searchTimer = setTimeout(() => {
+ this.$emit('keyword-changed', this.keyword, true);
+ }, 600);
+ },
openDrawer() {
this.$refs.filterTasksDrawer.open();
},
@@ -152,13 +165,10 @@ export default {
this.$root.$emit('open-task-drawer', defaultTask);
},
resetFilterTask(){
- this.searchonkeyChange=false;
- this.keyword='';
- this.searchonkeyChange=true;
+ this.keyword = '';
this.$emit('reset-filter-task-dashboard');
},
filterTasks(e) {
- this.searchonkeyChange = false;
this.keyword = e.tasks.query;
this.$emit('filter-task-dashboard', {
tasks: e.tasks,
@@ -172,26 +182,7 @@ export default {
filterNumChanged(filtersnumber){
this.filterNumber=filtersnumber;
},
- getFilterNum(){
- const numOfFilter = localStorage.getItem('filtersNumber');
- this.filterNumber=Number(numOfFilter);
- if (this.filterNumber>0){
- return `(${this.filterNumber})`;
- } return '';
- },
changeTaskViewTab(view){
- $('a.v-tab').removeClass('v-tab--active');
- if ( view === 'list') {
- $('a.taskTabList').addClass('v-tab--active');
- }
-
- if ( view === 'board') {
- $('a.taskTabBoard').addClass('v-tab--active');
- }
-
- if ( view === 'gantt') {
- $('a.taskTabGantt').addClass('v-tab--active');
- }
this.taskViewTabName=view;
this.$emit('taskViewChangeTab', view);
}
diff --git a/webapps/src/main/webapp/vue-app/tasks-management/initComponents.js b/webapps/src/main/webapp/vue-app/tasks-management/initComponents.js
index 51ee4d655..c42a78282 100644
--- a/webapps/src/main/webapp/vue-app/tasks-management/initComponents.js
+++ b/webapps/src/main/webapp/vue-app/tasks-management/initComponents.js
@@ -47,6 +47,7 @@ import TasksSortByProjectDrawer from './components/tasks/TasksSortByProjectDrawe
import TasksViewDashboard from './components/ProjectTasks/TasksViewDashboard.vue';
import TasksViewToolbar from './components/ProjectTasks/TasksViewToolbar.vue';
+import TasksViewSwitcher from './components/ProjectTasks/TasksViewSwitcher.vue';
import TasksViewBoard from './components/ProjectTasks/TasksViewBoard.vue';
import TasksViewList from './components/ProjectTasks/TasksViewList.vue';
import TasksViewListColumn from './components/ProjectTasks/TasksViewListColumn.vue';
@@ -93,6 +94,7 @@ const components = {
'tasks-view-dashboard': TasksViewDashboard,
'tasks-view-toolbar': TasksViewToolbar,
+ 'tasks-view-switcher': TasksViewSwitcher,
'tasks-view-board': TasksViewBoard,
'tasks-view-board-column': TasksViewBoardColumn,
'tasks-view-list': TasksViewList,