Skip to content

Commit

Permalink
feat: Add tailining window manager with slider
Browse files Browse the repository at this point in the history
  • Loading branch information
dominik003 committed Oct 31, 2023
1 parent 896627d commit 05c7bca
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 9 deletions.
4 changes: 4 additions & 0 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -164,6 +166,7 @@ import { SettingsComponent } from './settings/settings.component';
CreateReadonlySessionComponent,
CreateReadonlySessionDialogComponent,
CreateT4cModelNewRepositoryComponent,
DefaultValuePipe,
DeleteGitSettingsDialogComponent,
DeleteSessionDialogComponent,
DisplayValueComponent,
Expand Down Expand Up @@ -221,6 +224,7 @@ import { SettingsComponent } from './settings/settings.component';
T4CRepoDeletionDialogComponent,
T4CSettingsComponent,
T4CSettingsWrapperComponent,
TailingWindowManagerComponent,
TextLineSkeletonLoaderComponent,
ToolDeletionDialogComponent,
ToolDetailsComponent,
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/app/helpers/default-value.pipe.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@
></div>
<div [ngClass]="draggingActive ? 'iframe-overlay' : ''"></div>
<iframe
[title]="
(session.version?.tool?.name | defaultValue: 'unknown tool name') +
'-' +
(session.version?.name | defaultValue: 'unknown version name') +
'-' +
session.type
"
[id]="'session-' + session.id"
[src]="session.safeResourceURL"
class="h-full w-full"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class FloatingWindowManagerComponent implements OnInit {
unfocusSession(focusedSession: Session) {
this.sessions
.filter((session) => session !== focusedSession)
.map((session) => (session.focused = false));
.forEach((session) => (session.focused = false));
}

dragStart() {
Expand Down
27 changes: 21 additions & 6 deletions frontend/src/app/sessions/session/session.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,12 @@
</div>
<div class="mt-2">
<mat-radio-group [(ngModel)]="selectedWindowType">
<mat-radio-button value="floating">Floating window</mat-radio-button>
<mat-radio-button value="tailing">Tailing window</mat-radio-button>
<mat-radio-button value="floating"
>Floating window manager</mat-radio-button
>
<mat-radio-button value="tailing"
>Tailing window manager</mat-radio-button
>
</mat-radio-group>
</div>

Expand All @@ -69,10 +73,21 @@
</div>
</div>

<app-floating-window-manager
*ngIf="selectedSessions.length"
[sessions]="selectedSessions"
></app-floating-window-manager>
<ng-container *ngIf="selectedSessions.length">
<app-floating-window-manager
*ngIf="isFloatingWindowManager; else tailingWindow"
[sessions]="selectedSessions"
>
</app-floating-window-manager>

<ng-template #tailingWindow>
<app-tailing-window-manager
*ngIf="isTailingWindowManager"
[sessions]="selectedSessions"
>
</app-tailing-window-manager>
</ng-template>
</ng-container>

<div class="fixed bottom-4 right-4 z-50">
<button
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/app/sessions/session/session.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ export class SessionComponent implements OnInit {
return this.cachedSessions?.filter((session) => session.checked);
}

get isTailingWindow(): boolean {
get isTailingWindowManager(): boolean {
return this.selectedWindowType === 'tailing';
}

get isFloatingWindow() {
get isFloatingWindowManager(): boolean {
return this.selectedWindowType === 'floating';
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors
* SPDX-License-Identifier: Apache-2.0
*/

.height {
height: calc(100vh - 2vh - 65px - 110px);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!--
~ SPDX-FileCopyrightText: Copyright DB Netz AG and the capella-collab-manager contributors
~ SPDX-License-Identifier: Apache-2.0
-->

<div class="flex gap-0.5">
<ng-container *ngFor="let session of sessions; let i = index">
<div
class="flex flex-col"
[ngClass]="{
height: (fullscreenService.isFullscreen$ | async) === false,
'h-screen': fullscreenService.isFullscreen$ | async
}"
[style.width]="widths[i] + 'px'"
>
<div
class="flex items-center justify-between gap-2 rounded-t bg-slate-100 p-1"
>
<span>
{{ session.version?.tool?.name }} {{ session.version?.name }},
{{ session.type }}
<span *ngIf="session.type === 'readonly'"
>(project {{ session.project!.name }})</span
>
</span>
</div>

<div class="relative grow">
<iframe
[title]="
(session.version?.tool?.name | defaultValue: 'unknown tool name') +
'-' +
(session.version?.name | defaultValue: 'unknown version name') +
'-' +
session.type
"
[id]="'session-' + session.id"
[src]="session.safeResourceURL"
class="h-full w-full"
allow="clipboard-read; clipboard-write"
>
</iframe>
</div>
</div>

<div
*ngIf="i < sessions.length - 1"
class="my-2 w-2 cursor-col-resize bg-gray-300"
(mousedown)="onMouseDown($event, i)"
></div>
</ng-container>
</div>
Original file line number Diff line number Diff line change
@@ -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,
);
}
}

0 comments on commit 05c7bca

Please sign in to comment.