Skip to content

Commit

Permalink
feat: split board header into separate component
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfran committed Jan 9, 2025
1 parent 6a0cc10 commit ee333f9
Show file tree
Hide file tree
Showing 8 changed files with 341 additions and 294 deletions.
3 changes: 2 additions & 1 deletion apps/web/src/app/modules/board/board/board.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@
}

@defer {
<tapiz-header [allowSwitchMode]="!isReadonlyUser()" />
<tapiz-header />
<tapiz-board-header-options [allowSwitchMode]="!isReadonlyUser()" />
@if (!isDemo) {
<tapiz-users />
}
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/app/modules/board/board/board.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ 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 { BoardDragDirective } from './directives/board-drag.directive';
import { BoardHeaderOptionsComponent } from '../components/board-header-options/board-header-options.component';

@Component({
selector: 'tapiz-board',
Expand Down Expand Up @@ -132,6 +133,7 @@ import { BoardDragDirective } from './directives/board-drag.directive';
PopupPortalComponent,
NotesVisibilityComponent,
NoteHeightCalculatorComponent,
BoardHeaderOptionsComponent,
],
hostDirectives: [
CopyPasteDirective,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
@if (boardMode() === 0) {
@if (isAdmin() && !isDemo) {
<button
title="Settings"
aria-label="Settings"
class="button-action"
(click)="settings()">
<mat-icon svgIcon="settings"></mat-icon>
</button>
}
<button
title="Share"
aria-label="Share"
class="button-action"
(click)="share()">
<mat-icon svgIcon="share"></mat-icon>
</button>
<button
title="Download"
aria-label="Download"
class="button-action"
(click)="export()">
<mat-icon svgIcon="download"></mat-icon>
</button>
}

@if (allowSwitchMode()) {
<div class="change-mode-button-holder">
@if (boardMode() === 0) {
<button
title="Edit board"
aria-label="Edit board"
class="change-mode-button change-edit"
(click)="changeBoardMode(1)">
Edit board
</button>
} @else {
<button
title="Edit board"
aria-label="Edit board"
class="change-mode-button change-close"
(click)="changeBoardMode(0)">
Close board edition
<mat-icon>close</mat-icon>
</button>
}
</div>
}

@if (boardMode() === 0 && !isDemo && showUsers() && users().length > 0) {
<button class="user-count">
<mat-icon svgIcon="user"></mat-icon>
<span class="user-hover">{{ users().length + 1 }} Users</span>
</button>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
:host {
--toolbar-button-height: 3rem;
--toolbar-button-width: 3rem;

align-items: center;
cursor: default;
display: flex;
justify-content: space-between;
right: 1rem;
position: fixed;
top: 1rem;
transition: background 0.5s ease;
background: var(--blur-bg);
border-radius: var(--radius-6);
gap: var(--spacing-1);
margin-inline-start: auto;
flex-shrink: 0;
padding: var(--size-2);
height: 65px;
backdrop-filter: blur(90px);
}

.change-mode-button-holder {
display: flex;
}

.change-mode-button {
align-items: center;
display: flex;
font-family:
"Inter",
-apple-system,
system-ui,
sans-serif;
justify-content: center;
block-size: 50px;
padding: var(--spacing-3) var(--spacing-4);
color: var(--grey-90);
background: var(--grey-30);
border-radius: var(--radius-6);
font-size: var(--font-size-1);

mat-icon {
--icon-size: 16px;
inline-size: var(--icon-size);
block-size: var(--icon-size);
font-size: var(--icon-size);
margin-block-start: 1px;
}

&:hover {
background: var(--grey-40);
}
}

.change-edit mat-icon {
margin-inline-end: 2px;
}

.change-close mat-icon {
margin-inline-start: 4px;
}

.textarea {
color: var(--white);
background: transparent;
border: none;
height: 100%;
outline: none;
overflow: hidden;
resize: none;
}

.button-action {
display: flex;
align-items: center;
color: var(--primary-color-button-bg);
border-radius: var(--radius-round);
padding: var(--spacing-2);
justify-content: center;
height: var(--toolbar-button-height);
width: var(--toolbar-button-width);
.mat-icon {
color: var(--primary-color-button-bg);
fill: var(--primary-color-button-bg);
}
&:hover {
transition: background 0.2s ease;
background: var(--grey-30);
}
}

.avatar {
border-radius: var(--radius-round);
width: 48px;
height: 48px;
img {
display: block;
}
}

.user-count {
align-items: center;
background: var(--grey-30);
border-radius: 30px;
box-sizing: border-box;
color: #2c2c2c;
display: inline-flex;
font-family:
"Work Sans",
-apple-system,
system-ui,
sans-serif;
font-size: var(--font-size-1);
font-weight: 400;
height: 44px;
width: 44px;
justify-content: center;
line-height: 1.2;
margin-left: 8px;
position: relative;

&:hover {
background: var(--grey-40);

.user-hover {
background: var(--grey-90);
border-radius: 20px;
color: var(--white);
display: flex;
align-items: center;
font-size: 16px;
font-weight: var(--font-weight-medium);
line-height: 1.2;
height: 44px;
width: 200%;
padding: 0 16px;
opacity: 1;

&::after {
content: "";
position: absolute;
top: 50%; /* Start at vertical center */
left: calc(100% - 0.18rem); /* Align to the right edge */
transform: translateY(-50%); /* Center vertically */

/* Create the triangle using borders */
width: 0;
height: 0;
border-left: 10px solid #1f255a; /* Color matches the bubble background */
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
}
}
}

.user-hover {
height: 0;
width: 0;
opacity: 0;
position: absolute;
right: calc(100% + 0.5rem);
top: 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import {
Component,
ChangeDetectionStrategy,
inject,
input,
} from '@angular/core';
import { Store } from '@ngrx/store';
import { PageActions } from '../../actions/page.actions';
import { selectIsAdmin, selectUserId } from '../../selectors/page.selectors';
import { ExportService } from '../../services/export.service';
import { MatIconModule } from '@angular/material/icon';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { ShareBoardComponent } from '../share-board/share-board.component';
import { pageFeature } from '../../reducers/page.reducer';
import { BoardSettingsComponent } from '../board-settings/board-settings.component';
import { toSignal } from '@angular/core/rxjs-interop';
import { map } from 'rxjs';
import { computed } from '@angular/core';
import { ConfigService } from '../../../../services/config.service';
import { MatButtonModule } from '@angular/material/button';
import { BoardFacade } from '../../../../services/board-facade.service';

@Component({
selector: 'tapiz-board-header-options',
templateUrl: './board-header-options.component.html',
styleUrls: ['./board-header-options.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [MatIconModule, MatDialogModule, MatButtonModule],
})
export class BoardHeaderOptionsComponent {
#exportService = inject(ExportService);
#store = inject(Store);
#dialog = inject(MatDialog);
#boardFacade = inject(BoardFacade);
#boardUsers = this.#store.selectSignal(pageFeature.selectBoardUsers);
#configService = inject(ConfigService);
#users = toSignal(
this.#boardFacade
.getUsers()
.pipe(map((users) => users.map((user) => user.content))),
{ initialValue: [] },
);
userId = this.#store.selectSignal(selectUserId);
users = computed(() => {
const boardUsers = this.#boardUsers();

return this.#users()
.filter((user) => user.id !== this.userId())
.map((user) => {
const boardUser = boardUsers.find(
(boardUser) => boardUser.id === user.id,
);

return {
...user,
picture: boardUser?.picture,
};
});
});
#settings = toSignal(this.#boardFacade.getSettings(), { initialValue: null });

showUsers = computed(() => {
return !this.#settings()?.content.anonymousMode;
});

allowSwitchMode = input(true);

boardMode = this.#store.selectSignal(pageFeature.selectBoardMode);
isAdmin = this.#store.selectSignal(selectIsAdmin);
boardId = this.#store.selectSignal(pageFeature.selectBoardId);

get isDemo() {
return !!this.#configService.config.DEMO;
}

changeBoardMode(boardMode: number) {
this.#store.dispatch(
PageActions.changeBoardMode({
boardMode,
}),
);
}

export() {
this.#exportService.getExportFile().then(
(url) => {
const fileLink = document.createElement('a');

fileLink.href = url;
fileLink.download = `${this.boardId()}.json`;
fileLink.click();
},
() => {
console.error('export error');
},
);
}

share() {
this.#dialog.open(ShareBoardComponent, {
width: '600px',
autoFocus: 'dialog',
});
}

settings() {
this.#dialog.open(BoardSettingsComponent, {
width: '600px',
autoFocus: 'dialog',
});
}
}
Loading

0 comments on commit ee333f9

Please sign in to comment.