feat(boards): make super basic drag & drop work

This commit is contained in:
Johannes Millan 2025-02-27 18:05:39 +01:00
parent d9af59e619
commit 963701ac7f
9 changed files with 69 additions and 8 deletions

View file

@ -1,6 +1,10 @@
<!--[cdkDropListData]="panelCfg()"-->
<div
class="task-items"
cdkDropList
[cdkDropListData]="panelCfg()"
(cdkDropListDropped)="drop($event)"
>
@for (task of tasks(); track task.id) {
<planner-task

View file

@ -21,6 +21,8 @@
max-height: 100%;
padding: 0 8px;
min-height: 60px;
border: 1px dashed transparent;
border-radius: 8px;
}
.empty {

View file

@ -5,14 +5,16 @@ import {
inject,
input,
} from '@angular/core';
import { CdkDrag, CdkDropList } from '@angular/cdk/drag-drop';
import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop';
import { PlannerTaskComponent } from '../../planner/planner-task/planner-task.component';
import { BoardPanelCfg } from '../boards.model';
import { BoardPanelCfg, BoarFieldsToRemove } from '../boards.model';
import { Store } from '@ngrx/store';
import { selectAllTasks } from '../../tasks/store/task.selectors';
import { toSignal } from '@angular/core/rxjs-interop';
import { AddTaskInlineComponent } from '../../planner/add-task-inline/add-task-inline.component';
import { T } from '../../../t.const';
import { TaskCopy } from '../../tasks/task.model';
import { TaskService } from '../../tasks/task.service';
@Component({
selector: 'board-task-list',
@ -23,10 +25,11 @@ import { T } from '../../../t.const';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BoardTaskListComponent {
// tasks = input.required<TaskCopy[]>();
panelCfg = input.required<BoardPanelCfg>();
fieldsToRemove = input.required<BoarFieldsToRemove>();
store = inject(Store);
taskService = inject(TaskService);
allTasks$ = this.store.select(selectAllTasks);
allTasks = toSignal(this.allTasks$, {
@ -51,4 +54,22 @@ export class BoardTaskListComponent {
});
});
protected readonly T = T;
drop(ev: CdkDragDrop<BoardPanelCfg, string, TaskCopy>): void {
const panelCfg = ev.container.data;
const task = ev.item.data;
const fieldsToRemove = this.fieldsToRemove();
let newTagIds: string[] = [];
if (fieldsToRemove.tagIds?.length) {
newTagIds = task.tagIds.filter((tagId) => !fieldsToRemove.tagIds!.includes(tagId));
}
if (panelCfg.tagIds) {
newTagIds = newTagIds.concat(panelCfg.tagIds);
}
this.taskService.updateTags(task, newTagIds);
// const allTasks = this.tasks();
console.log(ev, panelCfg, task);
}
}

View file

@ -6,6 +6,9 @@
<mat-icon>more_vert</mat-icon>
</button>
</header>
<board-task-list [panelCfg]="panel"></board-task-list>
<board-task-list
[panelCfg]="panel"
[fieldsToRemove]="fieldsToRemove()"
></board-task-list>
</div>
}

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import { BoardCfg } from '../boards.model';
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
import { BoardCfg, BoarFieldsToRemove } from '../boards.model';
import { BoardTaskListComponent } from '../board-task-list/board-task-list.component';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
@ -19,4 +19,15 @@ import { MatIcon } from '@angular/material/icon';
})
export class BoardComponent {
boardCfg = input.required<BoardCfg>();
fieldsToRemove = computed<BoarFieldsToRemove>(() => {
const tagIdsToRemove: string[] = [];
this.boardCfg().panels.forEach((panel) => {
if (panel.tagIds) {
tagIdsToRemove.push(...panel.tagIds);
}
});
return {
tagIds: tagIdsToRemove,
};
});
}

View file

@ -1,10 +1,14 @@
<mat-tab-group
mat-stretch-tabs="false"
dynamicHeight="true"
cdkScrollable
>
@for (board of boards(); track board.id) {
<mat-tab [label]="board.title">
<board [boardCfg]="board"></board>
<board
[boardCfg]="board"
cdkDropListGroup
></board>
</mat-tab>
}

View file

@ -5,11 +5,22 @@ import { T } from '../../t.const';
import { MatIcon } from '@angular/material/icon';
import { DEFAULT_BOARDS } from './boards.const';
import { BoardComponent } from './board/board.component';
import { CdkScrollable } from '@angular/cdk/overlay';
import { CdkDropListGroup } from '@angular/cdk/drag-drop';
@Component({
selector: 'boards',
standalone: true,
imports: [MatTabGroup, MatTab, MatIcon, MatTabContent, MatTabLabel, BoardComponent],
imports: [
MatTabGroup,
MatTab,
MatIcon,
MatTabContent,
MatTabLabel,
BoardComponent,
CdkScrollable,
CdkDropListGroup,
],
templateUrl: './boards.component.html',
styleUrl: './boards.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,

View file

@ -5,6 +5,10 @@ export interface BoardSrcCfg {
filterTaskState?: number[];
}
export interface BoarFieldsToRemove {
tagIds?: string[];
}
export interface BoardPanelCfg extends BoardSrcCfg {
id: string;
title: string;

View file

@ -205,6 +205,7 @@ mat-icon.mat-icon[svgicon] {
.cdk-drop-list-receiving {
outline: 1px dashed $c-primary;
border-color: $c-primary;
border-radius: 6px;
cursor: grabbing;
//border: 2px solid green;