diff --git a/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.html b/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.html
index 3e77ec8f75..e972710e53 100644
--- a/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.html
+++ b/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.html
@@ -20,14 +20,4 @@
[currentTimeRow]="currentTimeRow()"
[isTaskDragActive]="isDragging()"
>
-
- @if (isDragging() && dragPreviewTime()) {
-
-
{{ dragPreviewTime() }}
-
- }
diff --git a/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.ts b/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.ts
index b836d6db5d..a08b6d5d75 100644
--- a/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.ts
+++ b/src/app/features/schedule/schedule-day-panel/schedule-day-panel.component.ts
@@ -36,6 +36,8 @@ import { TaskWithSubTasks } from '../../tasks/task.model';
import { TaskSharedActions } from '../../../root-store/meta/task-shared.actions';
import { Log } from '../../../core/log';
+const DEFAULT_MIN_DURATION = 15 * 60 * 1000;
+
@Component({
selector: 'schedule-day-panel',
standalone: true,
@@ -58,7 +60,6 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
// Drag preview properties
dragPreviewTime = signal(null);
- dragPreviewPosition = signal<{ x: number; y: number }>({ x: 0, y: 0 });
isDragging = signal(false);
private lastCalculatedTimestamp: number | null = null;
@@ -183,11 +184,7 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
}
onDragEnter(event: CdkDragEnter<{ day: string }>): void {
- // Only activate preview for allowed drags (tasks etc.).
- const data: any = (event.item as any)?.data;
- const title: string =
- data && typeof data === 'object' && 'title' in data ? data.title : '';
- this._startScheduleMode(title);
+ this._startScheduleMode();
}
onDragExit(): void {
@@ -206,11 +203,9 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
}
if (!this.isDragging()) return;
- const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX;
const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY;
// Update position for the preview badge (still follow cursor for visibility)
- this.dragPreviewPosition.set({ x: clientX, y: clientY });
// Get the actual drag preview position to match what dropPoint will be
let previewY = clientY;
@@ -229,6 +224,7 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
const date = new Date(timestamp);
const hours = date.getHours();
const minutes = date.getMinutes();
+ // TODO internationalization
const timeStr = `${hours.toString().padStart(2, '0')}:${minutes
.toString()
.padStart(2, '0')}`;
@@ -287,10 +283,9 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
);
// Auto-assign a default duration if none is set
if (!task.timeEstimate || task.timeEstimate <= 0) {
- const FIFTEEN_MIN = 15 * 60 * 1000;
this._store.dispatch(
TaskSharedActions.updateTask({
- task: { id: task.id, changes: { timeEstimate: FIFTEEN_MIN } },
+ task: { id: task.id, changes: { timeEstimate: DEFAULT_MIN_DURATION } },
}),
);
}
@@ -384,16 +379,18 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
private _updatePreviewTimeBadge(timeStr: string): void {
const preview = document.querySelector('.cdk-drag-preview') as HTMLElement | null;
if (!preview) return;
- const timeBadge = preview.querySelector('.time-badge') as HTMLElement | null;
+ const timeBadge = preview.querySelector(
+ '.drag-preview-time-badge',
+ ) as HTMLElement | null;
if (timeBadge) {
timeBadge.textContent = timeStr;
}
}
- private _startScheduleMode(previewTitle?: string): void {
+ private _startScheduleMode(): void {
if (this.isDragging()) return;
this.isDragging.set(true);
- this._applySchedulePreviewStyling(true, previewTitle);
+ this._applySchedulePreviewStyling(true);
this._cdr.markForCheck();
// Track pointer globally so we can leave schedule mode when not over panel
document.addEventListener('mousemove', this._onGlobalPointerMove, {
@@ -435,56 +432,49 @@ export class ScheduleDayPanelComponent implements AfterViewInit, OnDestroy {
}
};
- private _applySchedulePreviewStyling(isEnable: boolean, previewTitle?: string): void {
- const preview = document.querySelector('.cdk-drag-preview') as HTMLElement | null;
- if (!preview) {
+ // we're mutating the dom directly here to add some styling to the drag preview, since it is the most efficient way to do it
+ private _applySchedulePreviewStyling(isEnable: boolean): void {
+ const previewEl = document.querySelector('.cdk-drag-preview') as HTMLElement | null;
+ if (!previewEl) {
return;
}
- if (isEnable) {
- preview.classList.add('as-schedule-event-preview');
- // Try to match the width of the day column
- const containerElement = this.scheduleWeekRef?.nativeElement as
- | HTMLElement
- | undefined;
- const day = this.daysToShow()[0];
- const colEl = containerElement?.querySelector(
- `.grid-container .col[data-day="${day}"]`,
- ) as HTMLElement | null;
- if (colEl) {
- const colRect = colEl.getBoundingClientRect();
- preview.style.width = `${Math.max(40, colRect.width - 10)}px`;
+ if (previewEl.tagName.toLowerCase() === 'task') {
+ if (isEnable) {
+ previewEl.classList.add('as-schedule-event-preview');
+ // Try to match the width of the day column
+ const containerElement = this.scheduleWeekRef?.nativeElement as
+ | HTMLElement
+ | undefined;
+ const day = this.daysToShow()[0];
+ const colEl = containerElement?.querySelector(
+ `.grid-container .col[data-day="${day}"]`,
+ ) as HTMLElement | null;
+ if (colEl) {
+ const colRect = colEl.getBoundingClientRect();
+ previewEl.style.width = `${Math.max(40, colRect.width - 10)}px`;
+ }
+
+ // ensure time badge element exists
+ let timeBadge = previewEl.querySelector(
+ '.drag-preview-time-badge',
+ ) as HTMLElement | null;
+ if (!timeBadge) {
+ timeBadge = document.createElement('div');
+ timeBadge.className = 'drag-preview-time-badge';
+ previewEl.appendChild(timeBadge);
+ }
+ if (this.dragPreviewTime()) {
+ timeBadge.textContent = this.dragPreviewTime()!;
+ }
+ } else {
+ previewEl.classList.remove('as-schedule-event-preview');
+ previewEl.style.removeProperty('width');
+ const timeBadge = previewEl.querySelector('.drag-preview-time-badge');
+ if (timeBadge) {
+ timeBadge.remove();
+ }
}
- // Inject basic content to mimic schedule preview: title
- let titleEl = preview.querySelector('.title') as HTMLElement | null;
- if (!titleEl) {
- titleEl = document.createElement('div');
- titleEl.className = 'title';
- preview.appendChild(titleEl);
- }
- if (previewTitle) {
- titleEl.textContent = previewTitle;
- }
- // ensure time badge element exists
- let timeBadge = preview.querySelector('.time-badge') as HTMLElement | null;
- if (!timeBadge) {
- timeBadge = document.createElement('div');
- timeBadge.className = 'time-badge';
- preview.appendChild(timeBadge);
- }
- if (this.dragPreviewTime()) {
- timeBadge.textContent = this.dragPreviewTime()!;
- }
- } else {
- preview.classList.remove('as-schedule-event-preview');
- preview.style.removeProperty('width');
- const timeBadge = preview.querySelector('.time-badge');
- if (timeBadge) {
- timeBadge.remove();
- }
- // remove injected title
- const titleEl = preview.querySelector('.title');
- if (titleEl) (titleEl as HTMLElement).remove();
}
}
}
diff --git a/src/styles/components/_overwrite-material.scss b/src/styles/components/_overwrite-material.scss
index 3a535ec346..389d3ea9a5 100644
--- a/src/styles/components/_overwrite-material.scss
+++ b/src/styles/components/_overwrite-material.scss
@@ -198,32 +198,21 @@ mat-icon.mat-icon[svgicon] {
// Schedule-style preview should always use accent border while dragging
.cdk-drag-preview.as-schedule-event-preview {
- border: 1px solid var(--c-primary) !important;
-
- .time-badge {
+ .drag-preview-time-badge {
position: absolute;
right: 6px;
top: 50%;
transform: translateY(-50%);
- font-size: 15px;
- height: 20px;
+ font-size: 16px;
+ font-weight: bold;
line-height: 20px;
- padding: 0 3px;
- border: 1px solid var(--extra-border-color);
+ padding: 0 3px 2px;
+ border: 2px solid var(--c-primary);
border-radius: var(--card-border-radius);
- color: var(--text-color);
background: var(--bg-lighter);
z-index: 10;
pointer-events: none;
}
-
- .title {
- font-size: 14px;
- line-height: 1.3;
- overflow: hidden;
- text-overflow: ellipsis;
- flex: 1 1 auto;
- }
}
.cdk-drag-placeholder {