diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 99d8fcf77f..2be61ebfe9 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -63,6 +63,7 @@ import { VersionComponent } from './general/metadata/version/version.component'; import { NavBarMenuComponent } from './general/nav-bar-menu/nav-bar-menu.component'; import { NoticeComponent } from './general/notice/notice.component'; import { ConfirmationDialogComponent } from './helpers/confirmation-dialog/confirmation-dialog.component'; +import { DefaultValuePipe } from './helpers/default-value.pipe'; import { DisplayValueComponent } from './helpers/display-value/display-value.component'; import { InputDialogComponent } from './helpers/input-dialog/input-dialog.component'; import { MatIconComponent } from './helpers/mat-icon/mat-icon.component'; @@ -109,6 +110,7 @@ import { WhitespaceUrlInterceptor } from './services/encoder/encoder.interceptor import { DeleteSessionDialogComponent } from './sessions/delete-session-dialog/delete-session-dialog.component'; import { FloatingWindowManagerComponent } from './sessions/session/floating-window-manager/floating-window-manager.component'; import { SessionComponent } from './sessions/session/session.component'; +import { TailingWindowManagerComponent } from './sessions/session/tailing-window-manager/tailing-window-manager.component'; import { SessionOverviewComponent } from './sessions/session-overview/session-overview.component'; import { SessionsComponent } from './sessions/sessions.component'; import { ActiveSessionsComponent } from './sessions/user-sessions-wrapper/active-sessions/active-sessions.component'; @@ -164,6 +166,7 @@ import { SettingsComponent } from './settings/settings.component'; CreateReadonlySessionComponent, CreateReadonlySessionDialogComponent, CreateT4cModelNewRepositoryComponent, + DefaultValuePipe, DeleteGitSettingsDialogComponent, DeleteSessionDialogComponent, DisplayValueComponent, @@ -221,6 +224,7 @@ import { SettingsComponent } from './settings/settings.component'; T4CRepoDeletionDialogComponent, T4CSettingsComponent, T4CSettingsWrapperComponent, + TailingWindowManagerComponent, TextLineSkeletonLoaderComponent, ToolDeletionDialogComponent, ToolDetailsComponent, diff --git a/frontend/src/app/helpers/default-value.pipe.ts b/frontend/src/app/helpers/default-value.pipe.ts new file mode 100644 index 0000000000..ab31513185 --- /dev/null +++ b/frontend/src/app/helpers/default-value.pipe.ts @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'defaultValue', +}) +export class DefaultValuePipe implements PipeTransform { + transform(value: string | undefined, defaultValue: string): string { + return value ?? defaultValue; + } +} diff --git a/frontend/src/app/sessions/session/floating-window-manager/floating-window-manager.component.html b/frontend/src/app/sessions/session/floating-window-manager/floating-window-manager.component.html index f82e079b10..336f59455a 100644 --- a/frontend/src/app/sessions/session/floating-window-manager/floating-window-manager.component.html +++ b/frontend/src/app/sessions/session/floating-window-manager/floating-window-manager.component.html @@ -48,6 +48,13 @@ >
+ + + +
+ + diff --git a/frontend/src/app/sessions/session/tailing-window-manager/tailing-window-manager.component.ts b/frontend/src/app/sessions/session/tailing-window-manager/tailing-window-manager.component.ts new file mode 100644 index 0000000000..2c497826c3 --- /dev/null +++ b/frontend/src/app/sessions/session/tailing-window-manager/tailing-window-manager.component.ts @@ -0,0 +1,95 @@ +/* + * SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Component, HostListener, Input, OnInit } from '@angular/core'; +import { Session } from 'src/app/schemes'; +import { FullscreenService } from '../../service/fullscreen.service'; + +@Component({ + selector: 'app-tailing-window-manager', + templateUrl: './tailing-window-manager.component.html', + styleUrls: ['./tailing-window-manager.component.css'], +}) +export class TailingWindowManagerComponent implements OnInit { + @Input() sessions: Session[] = []; + + widths: number[] = []; + resizeState = { + index: undefined as number | undefined, + startX: undefined as number | undefined, + startWidths: [] as number[], + }; + + lastInvocationTime = new Date().getTime(); + throttleDuration = 10; + + existingMargin = 0; + + constructor(public fullscreenService: FullscreenService) {} + + ngOnInit(): void { + this.fullscreenService.isFullscreen$.subscribe((isFullscreen) => { + this.existingMargin = isFullscreen ? 0 : 27.48; + this.updateWidths(); + }); + } + + onMouseDown(event: MouseEvent, index: number): void { + this.resizeState = { + index: index, + startX: event.clientX, + startWidths: [...this.widths], + }; + event.preventDefault(); + + Array.from(document.getElementsByTagName('iframe')).forEach((iframe) => { + iframe.style.pointerEvents = 'none'; + }); + } + + @HostListener('window:mousemove', ['$event']) + onMouseMove(event: MouseEvent): void { + requestAnimationFrame(() => { + if (this.resizeState.index !== undefined) { + const time = new Date().getTime(); + if (time - this.lastInvocationTime < this.throttleDuration) return; + this.lastInvocationTime = time; + + const delta = event.clientX - this.resizeState.startX!; + const leftPanelIndex = this.resizeState.index; + const rightPanelIndex = this.resizeState.index + 1; + + this.widths[leftPanelIndex] = + this.resizeState.startWidths[leftPanelIndex] + delta; + this.widths[rightPanelIndex] = + this.resizeState.startWidths[rightPanelIndex] - delta; + } + }); + } + + @HostListener('window:mouseup') + onMouseUp(): void { + this.resizeState = { + index: undefined, + startX: undefined, + startWidths: [], + }; + + Array.from(document.getElementsByTagName('iframe')).forEach((iframe) => { + iframe.style.pointerEvents = 'auto'; + }); + } + + @HostListener('window:resize') + onResize() { + this.updateWidths(); + } + + private updateWidths() { + this.widths = this.sessions.map( + () => (window.innerWidth - this.existingMargin) / this.sessions.length, + ); + } +}