From c45080527ef06f484de8aca752b893f207aea679 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 17 Oct 2025 16:34:47 +0200 Subject: [PATCH 1/7] feat(customizerMenu): first draft for component --- .../desktop-panel-buttons.component.ts | 16 +- .../mobile-side-panel-menu.component.ts | 14 +- .../mobile-bottom-nav.component.html | 5 +- .../mobile-bottom-nav.component.ts | 6 +- .../features/panels/panel-content.service.ts | 24 +- .../right-panel-content.component.html | 8 - .../right-panel-content.component.ts | 12 +- .../task-view-customizer-panel.component.html | 239 ++++++++++-------- .../task-view-customizer-panel.component.scss | 56 ++-- .../task-view-customizer-panel.component.ts | 8 +- 10 files changed, 194 insertions(+), 194 deletions(-) diff --git a/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts b/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts index 443da1f879..2407b52948 100644 --- a/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts +++ b/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts @@ -5,20 +5,28 @@ import { MatTooltip } from '@angular/material/tooltip'; import { TranslatePipe } from '@ngx-translate/core'; import { LayoutService } from '../../layout/layout.service'; import { TaskViewCustomizerService } from '../../../features/task-view-customizer/task-view-customizer.service'; +import { TaskViewCustomizerPanelComponent } from '../../../features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component'; import { T } from '../../../t.const'; import { KeyboardConfig } from '../../../features/config/keyboard-config.model'; +import { MatMenuTrigger } from '@angular/material/menu'; @Component({ selector: 'desktop-panel-buttons', standalone: true, - imports: [MatIconButton, MatIcon, MatTooltip, TranslatePipe], + imports: [ + MatIconButton, + MatIcon, + MatTooltip, + TranslatePipe, + TaskViewCustomizerPanelComponent, + MatMenuTrigger, + ], template: ` + + + + - +

{{ T.F.TASK_VIEW.CUSTOMIZER.TITLE | translate }}

+ +
+ + + + @for (opt of sortOptions; track opt.value) { + {{ opt.label | translate }} + } + + +
+ +
+ + + + @for (opt of groupOptions; track opt.value) { + {{ opt.label | translate }} + } + + +
+ +
+ + + + @for (opt of filterOptions; track opt.value) { + {{ opt.label | translate }} + } + + + + @if (customizerService.selectedFilter() === 'tag') { + + + + } + + @if (customizerService.selectedFilter() === 'project') { + + + + } + + @if (customizerService.selectedFilter() === 'scheduledDate') { + + + @for (option of scheduledPresets; track option.value) { + {{ + option.label | translate + }} + } + + + } + + @if (customizerService.selectedFilter() === 'estimatedTime') { + + + @for (option of timePresets; track option.value) { + {{ + option.label | translate + }} + } + + + } + + @if (customizerService.selectedFilter() === 'timeSpent') { + + + @for (option of timePresets; track option.value) { + {{ + option.label | translate + }} + } + + + } +
+ + + + diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss index c6cc0d9150..29fbba6d7c 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss @@ -1,33 +1,37 @@ -.customizer-panel { - // Align layout with other right-panel contents (e.g. issue-panel) - // Fill the container and let the parent handle scrolling - position: absolute; - inset: 8px 16px; - padding: 8px 0; - display: flex; - flex-direction: column; - height: 100%; +::ng-deep .customizer-menu { + .menu-content { + padding: 16px; + max-width: 400px; + min-width: 300px; - h3 { - text-align: center; - margin-bottom: 20px; - } - - .form-group { - margin-bottom: 15px; - display: flex; - flex-direction: column; - - label { - margin-bottom: 5px; + h3 { + text-align: center; + margin-top: 0; + margin-bottom: 20px; } - mat-form-field { + .form-group { + margin-bottom: 15px; + display: flex; + flex-direction: column; + + label { + margin-bottom: 5px; + font-weight: 500; + } + + mat-form-field { + width: 100%; + } + + mat-slide-toggle { + align-self: flex-start; + } + } + + button { width: 100%; - } - - mat-slide-toggle { - align-self: flex-start; + margin-top: 8px; } } } diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts index af1594eef4..4af9a96594 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, ViewChild } from '@angular/core'; import { OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; @@ -7,6 +7,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatMenuModule, MatMenu } from '@angular/material/menu'; import { TaskViewCustomizerService } from '../task-view-customizer.service'; import { TranslatePipe } from '@ngx-translate/core'; import { T } from 'src/app/t.const'; @@ -17,6 +18,7 @@ import { T } from 'src/app/t.const'; styleUrls: ['./task-view-customizer-panel.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, + exportAs: 'customizerMenu', imports: [ CommonModule, FormsModule, @@ -25,12 +27,16 @@ import { T } from 'src/app/t.const'; MatInputModule, MatButtonModule, MatSlideToggleModule, + MatMenuModule, TranslatePipe, ], }) export class TaskViewCustomizerPanelComponent implements OnInit { customizerService = inject(TaskViewCustomizerService); + @ViewChild('customizerMenu', { static: false }) + menu!: MatMenu; + T = T; selectedSort: string = 'default'; selectedGroup: string = 'default'; From 008134d2d537c7fab5bbaead644c428a8ac14d75 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 17 Oct 2025 16:43:44 +0200 Subject: [PATCH 2/7] feat(customizerMenu): second draft for component --- .../task-view-customizer-panel.component.html | 374 ++++++++++++------ .../task-view-customizer-panel.component.scss | 47 +-- .../task-view-customizer-panel.component.ts | 35 ++ 3 files changed, 311 insertions(+), 145 deletions(-) diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html index a9f69c5d9c..d8aed7d856 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html @@ -2,127 +2,265 @@ #customizerMenu="matMenu" class="customizer-menu" > + + + + + + + + + + + + + + + + + + @for (opt of sortOptions; track opt.value) { + + } + + + + + @for (opt of groupOptions; track opt.value) { + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + @for (option of scheduledPresets; track option.value) { + + } + + + + + @for (option of timePresets; track option.value) { + + } + + + + + @for (option of timePresets; track option.value) { + + } + diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss index 29fbba6d7c..1ef2ef4765 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss @@ -1,37 +1,30 @@ ::ng-deep .customizer-menu { - .menu-content { - padding: 16px; - max-width: 400px; - min-width: 300px; + .mat-mdc-menu-item { + position: relative; - h3 { - text-align: center; - margin-top: 0; - margin-bottom: 20px; + &.active { + background-color: rgba(0, 0, 0, 0.04); } - .form-group { - margin-bottom: 15px; - display: flex; - flex-direction: column; - - label { - margin-bottom: 5px; - font-weight: 500; - } - - mat-form-field { - width: 100%; - } - - mat-slide-toggle { - align-self: flex-start; - } + .current-value { + margin-left: auto; + padding-left: 16px; + font-size: 0.875em; + opacity: 0.7; + font-style: italic; } - button { + mat-icon:first-child { + margin-right: 8px; + } + } + + .menu-input-wrapper { + padding: 8px 16px; + min-width: 250px; + + .menu-input { width: 100%; - margin-top: 8px; } } } diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts index 4af9a96594..13d42590fc 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.ts @@ -8,6 +8,8 @@ import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { MatMenuModule, MatMenu } from '@angular/material/menu'; +import { MatIconModule } from '@angular/material/icon'; +import { MatDividerModule } from '@angular/material/divider'; import { TaskViewCustomizerService } from '../task-view-customizer.service'; import { TranslatePipe } from '@ngx-translate/core'; import { T } from 'src/app/t.const'; @@ -28,6 +30,8 @@ import { T } from 'src/app/t.const'; MatButtonModule, MatSlideToggleModule, MatMenuModule, + MatIconModule, + MatDividerModule, TranslatePipe, ], }) @@ -95,6 +99,37 @@ export class TaskViewCustomizerPanelComponent implements OnInit { this.filterInputValue = this.customizerService.filterInputValue(); } + getSortLabel(value: string): string { + const option = this.sortOptions.find((opt) => opt.value === value); + return option ? option.label : ''; + } + + getGroupLabel(value: string): string { + const option = this.groupOptions.find((opt) => opt.value === value); + return option ? option.label : ''; + } + + getFilterLabel(value: string): string { + const option = this.filterOptions.find((opt) => opt.value === value); + return option ? option.label : ''; + } + + onFilterSelect(filterType: string): void { + this.customizerService.setFilter(filterType); + } + + onFilterInputChange(filterType: string, value: string): void { + if (this.customizerService.selectedFilter() !== filterType) { + this.customizerService.setFilter(filterType); + } + this.customizerService.setFilterInputValue(value); + } + + onFilterWithValue(filterType: string, value: string): void { + this.customizerService.setFilter(filterType); + this.customizerService.setFilterInputValue(value); + } + onResetAll(): void { this.customizerService.resetAll(); } From 4f4021ee3eef1a56034a1579ad4ac4e8101746c1 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 17 Oct 2025 18:43:31 +0200 Subject: [PATCH 3/7] feat(customizerMenu): try to move checkmark to the right --- .../task-view-customizer-panel.component.html | 128 ++++++++++-------- .../task-view-customizer-panel.component.scss | 56 +++++--- 2 files changed, 114 insertions(+), 70 deletions(-) diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html index d8aed7d856..47a00f174a 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.html @@ -64,10 +64,12 @@ (click)="customizerService.setSort(opt.value)" [class.active]="customizerService.selectedSort() === opt.value" > - @if (customizerService.selectedSort() === opt.value) { - check - } - {{ opt.label | translate }} + + {{ opt.label | translate }} + @if (customizerService.selectedSort() === opt.value) { + check + } + } @@ -80,10 +82,12 @@ (click)="customizerService.setGroup(opt.value)" [class.active]="customizerService.selectedGroup() === opt.value" > - @if (customizerService.selectedGroup() === opt.value) { - check - } - {{ opt.label | translate }} + + {{ opt.label | translate }} + @if (customizerService.selectedGroup() === opt.value) { + check + } + } @@ -95,10 +99,12 @@ (click)="onFilterSelect('default')" [class.active]="customizerService.selectedFilter() === 'default'" > - @if (customizerService.selectedFilter() === 'default') { - check - } - {{ T.F.TASK_VIEW.CUSTOMIZER.FILTER_DEFAULT | translate }} + + {{ T.F.TASK_VIEW.CUSTOMIZER.FILTER_DEFAULT | translate }} + @if (customizerService.selectedFilter() === 'default') { + check + } + @@ -210,13 +226,15 @@ customizerService.filterInputValue() === option.value " > - @if ( - customizerService.selectedFilter() === 'scheduledDate' && - customizerService.filterInputValue() === option.value - ) { - check - } - {{ option.label | translate }} + + {{ option.label | translate }} + @if ( + customizerService.selectedFilter() === 'scheduledDate' && + customizerService.filterInputValue() === option.value + ) { + check + } + } @@ -232,13 +250,15 @@ customizerService.filterInputValue() === option.value " > - @if ( - customizerService.selectedFilter() === 'estimatedTime' && - customizerService.filterInputValue() === option.value - ) { - check - } - {{ option.label | translate }} + + {{ option.label | translate }} + @if ( + customizerService.selectedFilter() === 'estimatedTime' && + customizerService.filterInputValue() === option.value + ) { + check + } + } @@ -254,13 +274,15 @@ customizerService.filterInputValue() === option.value " > - @if ( - customizerService.selectedFilter() === 'timeSpent' && - customizerService.filterInputValue() === option.value - ) { - check - } - {{ option.label | translate }} + + {{ option.label | translate }} + @if ( + customizerService.selectedFilter() === 'timeSpent' && + customizerService.filterInputValue() === option.value + ) { + check + } + } diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss index 1ef2ef4765..4bbc21c23b 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss @@ -1,30 +1,52 @@ ::ng-deep .customizer-menu { .mat-mdc-menu-item { position: relative; + display: flex !important; + align-items: center; &.active { background-color: rgba(0, 0, 0, 0.04); } - - .current-value { - margin-left: auto; - padding-left: 16px; - font-size: 0.875em; - opacity: 0.7; - font-style: italic; - } - - mat-icon:first-child { - margin-right: 8px; - } } - .menu-input-wrapper { - padding: 8px 16px; - min-width: 250px; + .current-value { + padding-left: 16px; + font-size: 0.875em; + opacity: 0.7; + font-style: italic; + } - .menu-input { - width: 100%; + mat-icon:first-child:not(.check-icon) { + margin-right: 8px; + } + + .menu-item-content { + display: flex; + align-items: center; + width: 100%; + flex: 1; + flex-grow: 1; + margin-right: 0 !important; + border: 1px solid red !important; + + > span:first-child { + flex: 1; + } + + .check-icon { + border: 1px solid deeppink !important; + margin-left: auto !important; + flex-shrink: 0; + margin-right: 0 !important; } } } + +.menu-input-wrapper { + padding: 8px 16px; + min-width: 250px; + + .menu-input { + width: 100%; + } +} From 5889c8601b85647d47d38612f19542ec206e9baf Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 17 Oct 2025 18:56:36 +0200 Subject: [PATCH 4/7] feat(customizerMenu): move filter button left of play button --- .../desktop-panel-buttons.component.ts | 32 +------------------ .../main-header/main-header.component.html | 21 ++++++++++-- .../main-header/main-header.component.scss | 26 +++++++++++++++ .../main-header/main-header.component.ts | 9 ++++-- 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts b/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts index 2407b52948..d0a0fd048b 100644 --- a/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts +++ b/src/app/core-ui/main-header/desktop-panel-buttons/desktop-panel-buttons.component.ts @@ -4,41 +4,14 @@ import { MatIcon } from '@angular/material/icon'; import { MatTooltip } from '@angular/material/tooltip'; import { TranslatePipe } from '@ngx-translate/core'; import { LayoutService } from '../../layout/layout.service'; -import { TaskViewCustomizerService } from '../../../features/task-view-customizer/task-view-customizer.service'; -import { TaskViewCustomizerPanelComponent } from '../../../features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component'; import { T } from '../../../t.const'; import { KeyboardConfig } from '../../../features/config/keyboard-config.model'; -import { MatMenuTrigger } from '@angular/material/menu'; @Component({ selector: 'desktop-panel-buttons', standalone: true, - imports: [ - MatIconButton, - MatIcon, - MatTooltip, - TranslatePipe, - TaskViewCustomizerPanelComponent, - MatMenuTrigger, - ], + imports: [MatIconButton, MatIcon, MatTooltip, TranslatePipe], template: ` - - - - + + + } + diff --git a/src/app/core-ui/main-header/main-header.component.scss b/src/app/core-ui/main-header/main-header.component.scss index 226c7c9775..1042e818e9 100644 --- a/src/app/core-ui/main-header/main-header.component.scss +++ b/src/app/core-ui/main-header/main-header.component.scss @@ -98,6 +98,32 @@ button.isActive2 { margin-left: var(--s); } } + + .task-filter-btn { + position: relative; + transition: all 0.2s ease; + overflow: visible !important; + + .mat-icon { + transition: transform 0.2s ease; + display: block; + } + + &.isCustomized { + box-shadow: 0px -2px 3px 0px var(--separator-alpha); + background: var(--c-accent); + } + + &:hover:not(.isCustomized):not(:disabled) { + background-color: var(--hover-color, rgba(0, 0, 0, 0.04)); + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + background: transparent !important; + } + } } @keyframes pulse { diff --git a/src/app/core-ui/main-header/main-header.component.ts b/src/app/core-ui/main-header/main-header.component.ts index 0bbaa21a2d..a106a3cfe8 100644 --- a/src/app/core-ui/main-header/main-header.component.ts +++ b/src/app/core-ui/main-header/main-header.component.ts @@ -44,6 +44,9 @@ import { toSignal } from '@angular/core/rxjs-interop'; import { MetricService } from '../../features/metric/metric.service'; import { DateService } from '../../core/date/date.service'; import { MsToMinuteClockStringPipe } from '../../ui/duration/ms-to-minute-clock-string.pipe'; +import { TaskViewCustomizerService } from '../../features/task-view-customizer/task-view-customizer.service'; +import { TaskViewCustomizerPanelComponent } from '../../features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component'; +import { MatMenuTrigger } from '@angular/material/menu'; @Component({ selector: 'main-header', @@ -64,6 +67,8 @@ import { MsToMinuteClockStringPipe } from '../../ui/duration/ms-to-minute-clock- PageTitleComponent, PlayButtonComponent, DesktopPanelButtonsComponent, + TaskViewCustomizerPanelComponent, + MatMenuTrigger, MsToMinuteClockStringPipe, ], }) @@ -83,6 +88,7 @@ export class MainHeaderComponent implements OnDestroy { private readonly _configService = inject(GlobalConfigService); private readonly _metricService = inject(MetricService); private readonly _dateService = inject(DateService); + readonly taskViewCustomizerService = inject(TaskViewCustomizerService); T: typeof T = T; isShowSimpleCounterBtnsMobile = signal(false); @@ -145,9 +151,6 @@ export class MainHeaderComponent implements OnDestroy { enabledSimpleCounters = toSignal(this.simpleCounterService.enabledSimpleCounters$, { initialValue: [], }); - isShowTaskViewCustomizerPanel = computed(() => - this.layoutService.isShowTaskViewCustomizerPanel(), - ); isShowIssuePanel = computed(() => this.layoutService.isShowIssuePanel()); isShowNotes = computed(() => this.layoutService.isShowNotes()); syncIsEnabledAndReady = toSignal(this.syncWrapperService.isEnabledAndReady$); From 1c4b12531daad43fdef578f7671b2b6eada4f3ae Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 17 Oct 2025 19:03:37 +0200 Subject: [PATCH 5/7] feat(customizerMenu): move filter button to right of project title --- .../main-header/main-header.component.html | 19 ---- .../main-header/main-header.component.scss | 26 ------ .../main-header/main-header.component.ts | 6 -- .../page-title/page-title.component.ts | 92 ++++++++++++++++--- 4 files changed, 81 insertions(+), 62 deletions(-) diff --git a/src/app/core-ui/main-header/main-header.component.html b/src/app/core-ui/main-header/main-header.component.html index ddcc877645..7095b1ecdb 100644 --- a/src/app/core-ui/main-header/main-header.component.html +++ b/src/app/core-ui/main-header/main-header.component.html @@ -85,25 +85,6 @@ - @if (showDesktopButtons()) { - - - - } - @if (!isXxxs()) { - +
+ + + +
} @@ -84,23 +108,56 @@ import { WorkContextService } from '../../../features/work-context/work-context. } } + .page-title-actions { + display: flex; + align-items: center; + gap: var(--s-quarter); + margin-left: calc(-1 * var(--s)); + margin-right: var(--s2); + } + .project-settings-btn { display: none; @media (min-width: 600px) { display: block; transition: var(--transition-standard); opacity: 0; - margin-right: var(--s2); - margin-left: calc(-1 * var(--s)); position: relative; z-index: 1; } &:hover, - .page-title:hover + & { + .page-title:hover + .page-title-actions &, + .page-title-actions:hover & { opacity: 1; } } + + .task-filter-btn { + position: relative; + transition: all 0.2s ease; + overflow: visible !important; + + .mat-icon { + transition: transform 0.2s ease; + display: block; + } + + &.isCustomized { + box-shadow: 0px -2px 3px 0px var(--separator-alpha); + background: var(--c-accent); + } + + &:hover:not(.isCustomized):not(:disabled) { + background-color: var(--hover-color, rgba(0, 0, 0, 0.04)); + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + background: transparent !important; + } + } `, ], changeDetection: ChangeDetectionStrategy.OnPush, @@ -109,6 +166,8 @@ export class PageTitleComponent { private _breakpointObserver = inject(BreakpointObserver); private _router = inject(Router); private _workContextService = inject(WorkContextService); + readonly taskViewCustomizerService = inject(TaskViewCustomizerService); + private readonly _configService = inject(GlobalConfigService); readonly T = T; @@ -140,6 +199,13 @@ export class PageTitleComponent { ); isBoardsSection = toSignal(this._isBoardsSection$, { initialValue: false }); + private _isWorkViewPage$ = this._router.events.pipe( + filter((event): event is NavigationEnd => event instanceof NavigationEnd), + map((event) => !!event.urlAfterRedirects.match(/tasks$/)), + startWith(!!this._router.url.match(/tasks$/)), + ); + isWorkViewPage = toSignal(this._isWorkViewPage$, { initialValue: false }); + // Override title for special routes displayTitle = computed(() => { if (this.isScheduleSection()) { @@ -158,4 +224,8 @@ export class PageTitleComponent { isXxxs = toSignal(this._isXxxs$.pipe(map((result) => result.matches)), { initialValue: false, }); + + get kb(): KeyboardConfig { + return (this._configService.cfg()?.keyboard as KeyboardConfig) || {}; + } } From aaf731652fbbb8e2d016dcae4e1dddef45dfe533 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 17 Oct 2025 19:07:58 +0200 Subject: [PATCH 6/7] feat(customizerMenu): change color of active filter button --- .../core-ui/main-header/page-title/page-title.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/core-ui/main-header/page-title/page-title.component.ts b/src/app/core-ui/main-header/page-title/page-title.component.ts index 9dcd6ee294..c132d17f1d 100644 --- a/src/app/core-ui/main-header/page-title/page-title.component.ts +++ b/src/app/core-ui/main-header/page-title/page-title.component.ts @@ -144,8 +144,8 @@ import { KeyboardConfig } from '../../../features/config/keyboard-config.model'; } &.isCustomized { - box-shadow: 0px -2px 3px 0px var(--separator-alpha); - background: var(--c-accent); + color: var(--c-accent); + box-shadow: none; } &:hover:not(.isCustomized):not(:disabled) { From 832f7a95a0be25b7f349ee0a0cbd69bb7add8dd7 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Tue, 21 Oct 2025 16:37:29 +0200 Subject: [PATCH 7/7] feat(customizerMenu): polish new filter menu button and menu --- .../page-title/page-title.component.ts | 28 ++++++------ .../task-view-customizer-panel.component.scss | 45 +------------------ src/assets/i18n/en.json | 4 +- src/styles/components/_components.scss | 1 + src/styles/components/_customizer-menu.scss | 41 +++++++++++++++++ 5 files changed, 61 insertions(+), 58 deletions(-) create mode 100644 src/styles/components/_customizer-menu.scss diff --git a/src/app/core-ui/main-header/page-title/page-title.component.ts b/src/app/core-ui/main-header/page-title/page-title.component.ts index c132d17f1d..e1822bb0d9 100644 --- a/src/app/core-ui/main-header/page-title/page-title.component.ts +++ b/src/app/core-ui/main-header/page-title/page-title.component.ts @@ -117,20 +117,22 @@ import { KeyboardConfig } from '../../../features/config/keyboard-config.model'; } .project-settings-btn { - display: none; - @media (min-width: 600px) { - display: block; - transition: var(--transition-standard); - opacity: 0; - position: relative; - z-index: 1; - } + opacity: 1; - &:hover, - .page-title:hover + .page-title-actions &, - .page-title-actions:hover & { - opacity: 1; - } + /*display: none;*/ + /*@media (min-width: 600px) {*/ + /* display: block;*/ + /* transition: var(--transition-standard);*/ + /* opacity: 0;*/ + /* position: relative;*/ + /* z-index: 1;*/ + /*}*/ + + /*&:hover,*/ + /*.page-title:hover + .page-title-actions &,*/ + /*.page-title-actions:hover & {*/ + /* opacity: 1;*/ + /*}*/ } .task-filter-btn { diff --git a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss index 4bbc21c23b..092c645048 100644 --- a/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss +++ b/src/app/features/task-view-customizer/task-view-customizer-panel/task-view-customizer-panel.component.scss @@ -1,46 +1,5 @@ -::ng-deep .customizer-menu { - .mat-mdc-menu-item { - position: relative; - display: flex !important; - align-items: center; - - &.active { - background-color: rgba(0, 0, 0, 0.04); - } - } - - .current-value { - padding-left: 16px; - font-size: 0.875em; - opacity: 0.7; - font-style: italic; - } - - mat-icon:first-child:not(.check-icon) { - margin-right: 8px; - } - - .menu-item-content { - display: flex; - align-items: center; - width: 100%; - flex: 1; - flex-grow: 1; - margin-right: 0 !important; - border: 1px solid red !important; - - > span:first-child { - flex: 1; - } - - .check-icon { - border: 1px solid deeppink !important; - margin-left: auto !important; - flex-shrink: 0; - margin-right: 0 !important; - } - } -} +// Menu styles are in global styles: src/styles/components/_customizer-menu.scss +// This is necessary because mat-menu renders in a global overlay container .menu-input-wrapper { padding: 8px 16px; diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 39989effac..a391ace338 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1459,8 +1459,8 @@ }, "TASK_VIEW": { "CUSTOMIZER": { - "ENTER_PROJECT": "Enter project", - "ENTER_TAG": "Enter tag", + "ENTER_PROJECT": "Filter Projects", + "ENTER_TAG": "Filter Tag", "ESTIMATED_TIME": "Estimated Time", "FILTER_BY": "Filter By", "FILTER_DEFAULT": "No Filter", diff --git a/src/styles/components/_components.scss b/src/styles/components/_components.scss index d4d19e7ea5..e766e64843 100644 --- a/src/styles/components/_components.scss +++ b/src/styles/components/_components.scss @@ -16,5 +16,6 @@ @use './planner-shared'; @use './mentions'; @use './bottom-panel'; +@use './customizer-menu'; //@import '../../app/ui/custom-datetime-picker/sass/picker'; diff --git a/src/styles/components/_customizer-menu.scss b/src/styles/components/_customizer-menu.scss new file mode 100644 index 0000000000..1c5e9a753f --- /dev/null +++ b/src/styles/components/_customizer-menu.scss @@ -0,0 +1,41 @@ +// TASK VIEW CUSTOMIZER MENU +// Styles for the task view customizer menu component +// Menu renders in global overlay, so styles must be global + +.menu-item-content { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + gap: 16px; + + > span:first-child { + flex: 1; + } + + .check-icon { + flex-shrink: 0; + margin-left: auto; + margin-right: 0 !important; + } +} + +.customizer-menu { + .mat-mdc-menu-item { + &.active { + background-color: rgba(0, 0, 0, 0.08); + font-weight: 500; + } + } + + .current-value { + padding-left: 16px; + font-size: 0.875em; + opacity: 0.7; + font-style: italic; + } + + mat-icon:first-child:not(.check-icon) { + margin-right: 8px; + } +}