Skip to content

Commit

Permalink
feat: merge board nodes state
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfran committed Jan 21, 2025
1 parent 70e3723 commit 45a83eb
Show file tree
Hide file tree
Showing 131 changed files with 597 additions and 866 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ Tapiz is a **self-hosted**, web-based collaborative board built for teams to run
- 🗒️ **Sticky notes**
- 🎨 **Freehand drawing**
- 📊 **Polling**
- 📋 **Customizable templates**
- 🔢 **Estimations**
-**Voting**
- ⚙️ **Self-hosted**
Expand Down
16 changes: 8 additions & 8 deletions apps/web/src/app/app-node.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { registerNode } from './register-node';
import { ESTIMATION_BOARD_CONFIG } from '@tapiz/nodes/estimation-board';
import { TEXT_CONFIG } from '@tapiz/nodes/text';
import { IMAGE_CONFIG } from '@tapiz/nodes/image';
import { VECTOR_CONFIG } from '@tapiz/nodes/vector';
import { PANEL_CONFIG } from '@tapiz/nodes/panel';
import { POLL_BOARD_CONFIG } from '@tapiz/nodes/poll-board';
import { ESTIMATION_BOARD_CONFIG } from './modules/board/components/estimation-board';
import { TEXT_CONFIG } from './modules/board/components/text';
import { IMAGE_CONFIG } from './modules/board/components/image';
import { VECTOR_CONFIG } from './modules/board/components/vector';
import { PANEL_CONFIG } from './modules/board/components/panel';
import { POLL_BOARD_CONFIG } from './modules/board/components/poll-board';
import { PERSONAL_TOKEN_CONFIG } from './modules/board/components/token/register';
import { NOTE_CONFIG } from '@tapiz/nodes/note';
import { GROUP_CONFIG } from '@tapiz/nodes/group';
import { NOTE_CONFIG } from './modules/board/components/note';
import { GROUP_CONFIG } from './modules/board/components/group';

registerNode('token', PERSONAL_TOKEN_CONFIG);
registerNode('estimation', ESTIMATION_BOARD_CONFIG);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/modules/board/actions/page.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export const PageActions = createActionGroup({
'Node snapshot': props<{ prev: TuNode; curr: TuNode }>(),
'Lock board': props<{ lock: boolean }>(),
'Refetch board': emptyProps(),
Drawing: props<{ drawing: boolean }>(),
'Select nodes': props<{ ids: string[] }>(),
'Set board cursor': props<{ cursor: string }>(),
'Set node selection': props<{ enabled: boolean }>(),
Expand All @@ -80,5 +79,6 @@ export const PageActions = createActionGroup({
}>(),
'Mention user': props<{ userId: string; nodeId?: string }>(),
'New user joined': emptyProps(),
'Set drag enabled': props<{ dragEnabled: boolean }>(),
},
});
8 changes: 4 additions & 4 deletions apps/web/src/app/modules/board/board.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import { provideEffects } from '@ngrx/effects';
import { provideState } from '@ngrx/store';

import { BoardComponent } from './board/board.component';
import { pageFeature } from './reducers/page.reducer';
import { boardPageFeature } from './reducers/boardPage.reducer';
import { BoardEffects } from './effects/board.effects';
import { HistoryEffects } from './effects/history.effects';
import { PageEffects } from './effects/page.effects';
import { BoardPageEffects } from './effects/page.effects';

export const boardRoutes: Route[] = [
{
path: '',
component: BoardComponent,
providers: [
provideState(pageFeature),
provideEffects(BoardEffects, HistoryEffects, PageEffects),
provideState(boardPageFeature),
provideEffects(BoardEffects, HistoryEffects, BoardPageEffects),
],
},
];
133 changes: 49 additions & 84 deletions apps/web/src/app/modules/board/board/board.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,6 @@ import {
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { BoardActions } from '../actions/board.actions';
import { PageActions } from '../actions/page.actions';

import {
selectMoveEnabled,
selectPosition,
selectBoardId,
selectUserId,
selectZoom,
selectSearching,
} from '../selectors/page.selectors';

import { BoardMoveService } from '../services/board-move.service';
import { BoardZoomService } from '../services/board-zoom.service';
import { ActivatedRoute } from '@angular/router';
Expand All @@ -57,14 +47,14 @@ import { HeaderComponent } from '../components/header/header.component';
import { SearchOptionsComponent } from '../components/search-options/search-options.component';
import { CopyPasteDirective } from '../directives/copy-paste.directive';
import { TitleComponent } from '../../../shared/title/title.component';
import { Drawing, Point, StateActions, TuNode } from '@tapiz/board-commons';
import { pageFeature } from '../reducers/page.reducer';
import { Point, StateActions } from '@tapiz/board-commons';
import { boardPageFeature } from '../reducers/boardPage.reducer';
import { MatDialogModule } from '@angular/material/dialog';
import { NodesComponent } from '../components/nodes/nodes.component';
import { ContextMenuComponent } from '@tapiz/ui/context-menu/context-menu.component';
import { ContextMenuStore } from '@tapiz/ui/context-menu/context-menu.store';
import { BoardContextMenuComponent } from '../components/board-context-menu/board-contextmenu.component';
import { HistoryService } from '@tapiz/nodes/services/history.service';
import { HistoryService } from '../services/history.service';
import { MoveService } from '@tapiz/cdk/services/move.service';
import { ResizeService } from '@tapiz/ui/resize/resize.service';
import { RotateService } from '@tapiz/ui/rotate/rotate.service';
Expand All @@ -75,15 +65,11 @@ import { StopHighlightComponent } from '../../../shared/stop-highlight/stop-high
import { BoardFacade } from '../../../services/board-facade.service';
import { appFeature } from '../../../+state/app.reducer';
import { SubscriptionService } from '../../../services/subscription.service';
import { DrawingStore } from '@tapiz/board-components/drawing/drawing.store';
import { DrawingOptionsComponent } from '@tapiz/board-components/drawing-options';
import {
takeUntilDestroyed,
toObservable,
toSignal,
} from '@angular/core/rxjs-interop';
import { CommentsComponent } from '@tapiz/nodes/comments/comments.component';
import { NodesActions } from '@tapiz/nodes/services/nodes-actions';
import { DrawingStore } from '../components/drawing/drawing.store';
import { DrawingOptionsComponent } from '../components/drawing-options';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
import { CommentsComponent } from '../components/comments/comments.component';
import { NodesActions } from '../services/nodes-actions';
import { ConfigService } from '../../../services/config.service';
import { FileUploadService } from '../../../services/file-upload.service';
import { DemoIntroComponent } from '../components/demo-intro/demo-intro.component';
Expand All @@ -95,7 +81,7 @@ import { BoardEditorPortalComponent } from '../components/board-editor-portal/bo
import { BoardShourtcutsDirective } from '../directives/board-shortcuts.directive';
import { PopupPortalComponent } from '@tapiz/ui/popup/popup-portal.component';
import { NotesVisibilityComponent } from '../components/notes-visibility/notes-visibility.component';
import { NoteHeightCalculatorComponent } from '@tapiz/nodes/note';
import { NoteHeightCalculatorComponent } from '../components/note/components/note-height-calculator/note-height-calculator.component';
import { BoardDragDirective } from './directives/board-drag.directive';
import { BoardHeaderOptionsComponent } from '../components/board-header-options/board-header-options.component';

Expand Down Expand Up @@ -173,30 +159,44 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
private configService = inject(ConfigService);
private fileUploadService = inject(FileUploadService);
private destroyRef = inject(DestroyRef);
public readonly boardId$ = this.store.select(selectBoardId);
public readonly boardId$ = this.store.select(boardPageFeature.selectBoardId);
public readonly nodes$ = this.boardFacade.getNodes();

smallScale = computed(() => this.calcPatterns().smallCalc);
bigScale = computed(() => this.calcPatterns().bigCalc);
public readonly userZoom = this.store.selectSignal(pageFeature.selectZoom);
public readonly userZoom = this.store.selectSignal(
boardPageFeature.selectZoom,
);
public readonly historyService = inject(HistoryService);
public readonly newNote$ = new Subject<MouseEvent>();
public readonly drawing = this.drawingStore.drawing;
public readonly search = this.store.selectSignal(selectSearching);
public readonly boardTitle = this.store.selectSignal(pageFeature.selectName);
public readonly folloUser = this.store.selectSignal(pageFeature.selectFollow);
public readonly loaded = this.store.selectSignal(pageFeature.selectLoaded);
public readonly userId = this.store.selectSignal(selectUserId);
public readonly search = this.store.selectSignal(
boardPageFeature.selectSearching,
);
public readonly boardTitle = this.store.selectSignal(
boardPageFeature.selectName,
);
public readonly folloUser = this.store.selectSignal(
boardPageFeature.selectFollow,
);
public readonly loaded = this.store.selectSignal(
boardPageFeature.selectLoaded,
);
public readonly userId = this.store.selectSignal(
boardPageFeature.selectUserId,
);
public readonly boardMode = this.store.selectSignal(
pageFeature.selectBoardMode,
boardPageFeature.selectBoardMode,
);
public readonly nodeSelectionEnabled = this.store.selectSignal(
pageFeature.selectIsNodeSelectionEnabled,
boardPageFeature.selectIsNodeSelectionEnabled,
);
public readonly loadingBar = this.store.selectSignal(
pageFeature.selectLoadingBar,
boardPageFeature.selectLoadingBar,
);
public readonly isAdmin = this.store.selectSignal(
boardPageFeature.selectIsAdmin,
);
public readonly isAdmin = this.store.selectSignal(pageFeature.selectIsAdmin);
public readonly readonly = toSignal(
this.boardFacade.getSettings().pipe(
map((it) => {
Expand All @@ -213,7 +213,7 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
dots = viewChild.required<ElementRef<HTMLElement>>('dots');
#store = inject(Store);
#boardFacade = inject(BoardFacade);
userToFollow$ = this.#store.select(pageFeature.selectFollow).pipe(
userToFollow$ = this.#store.select(boardPageFeature.selectFollow).pipe(
switchMap((follow) => {
return this.#boardFacade.getUsers().pipe(
map((users) => {
Expand Down Expand Up @@ -350,8 +350,8 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
});

this.moveService.setUp({
zoom: this.store.select(selectZoom),
relativePosition: this.store.select(selectPosition),
zoom: this.store.select(boardPageFeature.selectZoom),
relativePosition: this.store.select(boardPageFeature.selectPosition),
});

this.store
Expand All @@ -374,44 +374,9 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
.subscribe(() => {
this.store.dispatch(PageActions.refetchBoard());
});

this.dragConfig();
}
}

public dragConfig() {
// todo: better way to sync
this.boardFacade.selectFocusNodes$
.pipe(takeUntilDestroyed())
.subscribe((nodes) => {
this.drawingStore.selectNode$.next(nodes);
});

this.boardFacade
.getNodes()
.pipe(
takeUntilDestroyed(),
map((nodes) => {
return nodes.filter(
(node) => node.type === 'note' || node.type === 'panel',
) as TuNode<{ drawing: Drawing[] }>[];
}),
)
.subscribe((nodes) => {
this.drawingStore.nodes$.next(nodes);
});

toObservable(this.drawingStore.drawing)
.pipe(takeUntilDestroyed())
.subscribe((drawing) => {
this.store.dispatch(
PageActions.drawing({
drawing,
}),
);
});
}

public initBoard() {
fromEvent<MouseEvent>(this.el.nativeElement, 'wheel', { passive: false })
.pipe(
Expand All @@ -423,7 +388,7 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
});

this.store
.select(pageFeature.selectCurrentBoardCursor)
.select(boardPageFeature.selectCurrentBoardCursor)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((cursor) => {
this.el.nativeElement.style.setProperty('--default-cursor', cursor);
Expand All @@ -438,9 +403,9 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
this.newNote$
.pipe(
withLatestFrom(
this.store.select(selectZoom),
this.store.select(selectPosition),
this.store.select(selectUserId),
this.store.select(boardPageFeature.selectZoom),
this.store.select(boardPageFeature.selectPosition),
this.store.select(boardPageFeature.selectUserId),
),
takeUntilDestroyed(this.destroyRef),
)
Expand All @@ -462,8 +427,8 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
this.boardMoveService.mouseMove$
.pipe(
withLatestFrom(
this.store.select(selectZoom),
this.store.select(selectPosition),
this.store.select(boardPageFeature.selectZoom),
this.store.select(boardPageFeature.selectPosition),
),
throttleTime(0, animationFrameScheduler),
takeUntilDestroyed(this.destroyRef),
Expand All @@ -475,7 +440,7 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
const userView$ = merge(
this.boardZoomService.zoomMove$,
this.boardMoveService.boardMove$.pipe(
withLatestFrom(this.store.select(selectZoom)),
withLatestFrom(this.store.select(boardPageFeature.selectZoom)),
),
).pipe(
map(([move, zoom]) => {
Expand All @@ -488,8 +453,8 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
this.boardMoveService.move$
.pipe(
withLatestFrom(
this.store.select(pageFeature.selectDragInProgress),
this.store.select(selectMoveEnabled),
this.store.select(boardPageFeature.selectDragInProgress),
this.store.select(boardPageFeature.selectMoveEnabled),
),
filter(([, inProgress, moveEnabled]) => !inProgress && moveEnabled),
switchMap(() => {
Expand All @@ -507,7 +472,7 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
.pipe(
withLatestFrom(
this.boardMoveService.mouseMove$.pipe(startWith({ x: 0, y: 0 })),
this.store.select(selectMoveEnabled),
this.store.select(boardPageFeature.selectMoveEnabled),
),
filter(([, , moveEnabled]) => {
return moveEnabled;
Expand Down Expand Up @@ -556,8 +521,8 @@ export class BoardComponent implements AfterViewInit, OnDestroy {
};

combineLatest([
this.store.select(selectZoom),
this.store.select(selectPosition),
this.store.select(boardPageFeature.selectZoom),
this.store.select(boardPageFeature.selectPosition),
])
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe(([zoom, position]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { Directive, inject } from '@angular/core';
import { MultiDragService } from '@tapiz/cdk/services/multi-drag.service';
import { BoardFacade } from '../../../../services/board-facade.service';
import { Store } from '@ngrx/store';
import { pageFeature } from '../../reducers/page.reducer';
import { boardPageFeature } from '../../reducers/boardPage.reducer';
import { isGroup, isPanel } from '@tapiz/board-commons';
import { nodesInsideNode } from '@tapiz/cdk/utils/nodes-inside';
import { getNodeSize } from '../../../../shared/node-size';
import { NodesActions } from '@tapiz/nodes/services/nodes-actions';
import { NodesActions } from '../../services/nodes-actions';
import { BoardActions } from '@tapiz/board-commons/actions/board.actions';
import { PageActions } from '../../actions/page.actions';

Expand All @@ -19,13 +19,13 @@ export class BoardDragDirective {
#store = inject(Store);
#nodesActions = inject(NodesActions);

readonly #focusIds = this.#store.selectSignal(pageFeature.selectFocusId);
readonly #focusIds = this.#store.selectSignal(boardPageFeature.selectFocusId);

constructor() {
this.#multiDragService.setUp({
dragEnabled: this.#store.select(pageFeature.selectDragEnabled),
zoom: this.#store.select(pageFeature.selectZoom),
relativePosition: this.#store.select(pageFeature.selectPosition),
dragEnabled: this.#store.select(boardPageFeature.selectDragEnabled),
zoom: this.#store.select(boardPageFeature.selectZoom),
relativePosition: this.#store.select(boardPageFeature.selectPosition),
draggableIds: (triggerNode: string) => {
const node = this.#boardFacade.getNode(triggerNode);

Expand Down
Loading

0 comments on commit 45a83eb

Please sign in to comment.