Skip to content

Commit

Permalink
Textual Competition Submission & Configuration Adjustements (#136)
Browse files Browse the repository at this point in the history
  • Loading branch information
sauterl authored May 18, 2022
1 parent ea3c8c9 commit f34efda
Show file tree
Hide file tree
Showing 23 changed files with 379 additions and 224 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ Vitrivr NG is a web-based user interface developed to be used with the latest ve

For setup information, consult our [Wiki](https://github.com/vitrivr/vitrivr-ng/wiki)

## Config

There is a `config.json` which enables configuration of the UI to a certain extend.
While we provide a sensible [default config](src/config.json), the
some default values are better explored in the [code](src/app/shared/model/config/config.model.ts).
Information about the configuration can be found in [the wiki](https://github.com/vitrivr/vitrivr-ng/wiki/Configuration).

## Development server

From the project folder, run `ng serve` to start a development server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
Expand Down
1 change: 1 addition & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"styles": [
"node_modules/leaflet/dist/leaflet.css",
"node_modules/leaflet-geosearch/dist/geosearch.css",
"node_modules/@videogular/ngx-videogular/fonts/videogular.css",
"src/vitrivr-theme.scss"
],
"scripts": [],
Expand Down
113 changes: 64 additions & 49 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,73 +1,88 @@
<mat-toolbar color="primary">
<img src="../assets/images/vitrivr_logo.png">
<img src="../assets/images/vitrivr_logo.png">

<span class="spacer-flex"></span>
<span class="spacer-flex"></span>

<button (click)="querysidenav.toggle()" mat-icon-button matTooltip="Toggle query sidebar">
<mat-icon>search</mat-icon>
</button>
<button (click)="querysidenav.toggle()" mat-icon-button matTooltip="Toggle query sidebar">
<mat-icon>search</mat-icon>
</button>

<span class="spacer-xlarge"></span>
<span class="spacer-xlarge"></span>

<a *ngIf="!(_config | GetConfigVariablePipe:competitionHost)" mat-icon-button matTooltip="Gallery view" routerLink="/gallery"
routerLinkActive="active" skipLocationChange="true">
<mat-icon>grid_on</mat-icon>
</a>
<a *ngIf="!(_config | GetConfigVariablePipe:competitionHost)" mat-icon-button matTooltip="Gallery view"
routerLink="/gallery"
routerLinkActive="active" skipLocationChange="true">
<mat-icon>grid_on</mat-icon>
</a>

<span class="spacer-medium"></span>
<span class="spacer-medium"></span>

<a mat-icon-button matTooltip="Mini-gallery view" routerLink="/mini-gallery" routerLinkActive="active"
skipLocationChange="true" (click)="setActiveView(0)" [color]="_active_view === 0 ? 'accent' : ''">
<mat-icon>view_comfy</mat-icon>
</a>
<a mat-icon-button matTooltip="Mini-gallery view" routerLink="/mini-gallery" routerLinkActive="active"
skipLocationChange="true" (click)="setActiveView(0)" [color]="_active_view === 0 ? 'accent' : ''">
<mat-icon>view_comfy</mat-icon>
</a>

<span class="spacer-medium"></span>
<span class="spacer-medium"></span>

<a mat-icon-button matTooltip="List view" routerLink="/list" routerLinkActive="active" skipLocationChange="true"
(click)="setActiveView(1)" [color]="_active_view === 1 ? 'accent' : ''">
<mat-icon>list</mat-icon>
</a>
<a mat-icon-button matTooltip="List view" routerLink="/list" routerLinkActive="active" skipLocationChange="true"
(click)="setActiveView(1)" [color]="_active_view === 1 ? 'accent' : ''">
<mat-icon>list</mat-icon>
</a>

<span class="spacer-medium"></span>
<span class="spacer-medium"></span>

<a mat-icon-button matTooltip="Temporal Scoring view" routerLink="/temporal-list" routerLinkActive="active"
skipLocationChange="true" (click)="setActiveView(2)" [color]="_active_view === 2 ? 'accent' : ''">
<mat-icon>filter_list</mat-icon>
</a>
<a mat-icon-button matTooltip="Temporal Scoring view" routerLink="/temporal-list" routerLinkActive="active"
skipLocationChange="true" (click)="setActiveView(2)" [color]="_active_view === 2 ? 'accent' : ''">
<mat-icon>filter_list</mat-icon>
</a>

<span class="spacer-xlarge"></span>
<span class="spacer-xlarge"></span>

<button (click)="showHistory()" mat-icon-button matTooltip="Show query history.">
<mat-icon>history</mat-icon>
</button>
<button (click)="showHistory()" mat-icon-button matTooltip="Show query history.">
<mat-icon>history</mat-icon>
</button>

<button (click)="settingssidenav.toggle()" mat-icon-button [matBadge]="settingsbadge"
matTooltip="Toggle query refinement sidebar">
<mat-icon>storage</mat-icon>
</button>
<button (click)="settingssidenav.toggle()" mat-icon-button [matBadge]="settingsbadge"
matTooltip="Toggle query refinement sidebar">
<mat-icon>storage</mat-icon>
</button>

<ng-container *ngIf="('' | competitionEnabledPipe |async)">
<span class="spacer-flex"></span>

<app-api-status>
<mat-icon>av timer</mat-icon>
</app-api-status>
<div *ngIf="textualSubmissionOpen">
<app-textual-submission smallFont="true"></app-textual-submission>
</div>
<button mat-icon-button
(click)="textualSubmissionOpen = !textualSubmissionOpen"
[matTooltip]="(textualSubmissionOpen ? 'Close' : 'Open')+' textual submission input'">
<mat-icon>title</mat-icon>
<mat-icon style="transform: translate(-12px, 12px);">{{ textualSubmissionOpen ? 'close' : 'near_me'}}</mat-icon>
</button>
</ng-container>

<span class="spacer-flex"></span>

<app-api-status>
<mat-icon>av timer</mat-icon>
</app-api-status>
</mat-toolbar>

<div>
<mat-progress-bar *ngIf="_loadBool" [attr.color]="'accent'" mode="query"></mat-progress-bar>
<mat-progress-bar *ngIf="_loadBool" [attr.color]="'accent'" mode="query"></mat-progress-bar>
</div>

<mat-sidenav-container fullscreen style="margin-top:75px;">
<mat-sidenav #querysidenav [opened]="true" class="left" mode="side">
<app-query-sidebar></app-query-sidebar>
</mat-sidenav>

<mat-sidenav-content id="scrollable">
<router-outlet></router-outlet>
</mat-sidenav-content>

<mat-sidenav #settingssidenav class="right" mode="side"
position="end">
<app-settings></app-settings>
</mat-sidenav>
<mat-sidenav #querysidenav [opened]="true" class="left" mode="side">
<app-query-sidebar></app-query-sidebar>
</mat-sidenav>

<mat-sidenav-content id="scrollable">
<router-outlet></router-outlet>
</mat-sidenav-content>

<mat-sidenav #settingssidenav class="right" mode="side"
position="end">
<app-settings></app-settings>
</mat-sidenav>
</mat-sidenav-container>
23 changes: 12 additions & 11 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,13 @@ export class AppComponent implements OnInit, AfterViewInit {
settingsbadge = '';

_config: Config;

/** Observable that return the loading state of the QueryService. */
private readonly _loading: Observable<boolean>;

_loadBool = false

textualSubmissionOpen = false;
/** Variable to safe currently selected view */
public _active_view: View;

competitionHost = ((c: Config) => c._config.competition.host);

/** Observable that return the loading state of the QueryService. */
private readonly _loading: Observable<boolean>;

/**
* Default constructor. Subscribe for PING messages at the CineastWebSocketFactoryService.
Expand All @@ -50,10 +46,10 @@ export class AppComponent implements OnInit, AfterViewInit {
}
})
this._loading = _queryService.observable.pipe(
filter(msg => ['STARTED', 'ENDED', 'ERROR'].indexOf(msg) > -1),
map(() => {
return _queryService.running;
})
filter(msg => ['STARTED', 'ENDED', 'ERROR'].indexOf(msg) > -1),
map(() => {
return _queryService.running;
})
);
_configService.configAsObservable.subscribe(c => this._config = c)
this._active_view = View.GALLERY;
Expand Down Expand Up @@ -96,4 +92,9 @@ export class AppComponent implements OnInit, AfterViewInit {
public setActiveView(view: View) {
this._active_view = view;
}

isCompetitionActive() {
return this._configService.configAsObservable;
return this._config.dresEndpointRest && (this._config.get('competition.vbs') || this._config.get('competition.lsc'))
}
}
16 changes: 11 additions & 5 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {Config} from './shared/model/config/config.model';
import {HttpClient} from '@angular/common/http';
import {UUIDGenerator} from './shared/util/uuid-generator.util';
import {MatSnackBar} from '@angular/material/snack-bar';
import {Title} from '@angular/platform-browser';

/**
* A service providing the application's configuration and means to (re) load it.
Expand All @@ -23,7 +24,12 @@ export class AppConfig {
}
} as ProxyHandler<Config>;

constructor(private http: HttpClient, protected _snackBar: MatSnackBar) {
constructor(private http: HttpClient, protected _snackBar: MatSnackBar, private titleService: Title) {
AppConfig.settingsSubject.subscribe(settings => {
if (settings) {
this.titleService.setTitle(settings.get('title'));
}
});
}

/**
Expand All @@ -33,17 +39,17 @@ export class AppConfig {
return AppConfig.settings;
}

public publishChanges() {
AppConfig.settingsSubject.next(AppConfig.settings)
}

/**
* Returns the current configuration as observable. Can be used to monitor changes.
*/
get configAsObservable(): Observable<Config> {
return AppConfig.settingsSubject.asObservable();
}

public publishChanges() {
AppConfig.settingsSubject.next(AppConfig.settings)
}

/**
* Loads the default configuration from a JSON file.
*/
Expand Down
66 changes: 45 additions & 21 deletions src/app/core/vbs/vbs-submission.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,30 +285,54 @@ export class VbsSubmissionService {
mergeMap(([segment, frame]) => {
/* Submit, do some logging and catch HTTP errors. */
return this._dresSubmit.getApiV1Submit(null, segment, null, frame).pipe(
tap((status: SuccessfulSubmissionsStatus) => {
switch (status.submission) {
case 'CORRECT':
this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-success'});
break;
case 'WRONG':
this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-warning'});
break;
default:
this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION});
break;
}
}),
catchError(err => {
if (err.error) {
this._snackBar.open(`Submissions error: ${err.error.description}`, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-error'})
} else {
this._snackBar.open(`Submissions error: ${err.message}`, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-error'})
}
return of(null)
})
tap((status: SuccessfulSubmissionsStatus) => {
this.handleSubmissionResponse(status);
}),
catchError(err => {
return this.handleSubmissionError(err);
})
)
})
).subscribe()

/* Setup submission subscription, which is triggered manually. */
this._submitTextSubscription = this._submitTextSubject.pipe(
mergeMap((text) => {
/* Submit, do some logging and catch HTTP errors. */
return this._dresSubmit.getApiV1Submit(null, null, text).pipe(
tap((status: SuccessfulSubmissionsStatus) => {
this.handleSubmissionResponse(status);
}),
catchError(err => {
return this.handleSubmissionError(err);
})
)
})
).subscribe()
}


private handleSubmissionError(err) {
if (err.error) {
this._snackBar.open(`Submissions error: ${err.error.description}`, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-error'})
} else {
this._snackBar.open(`Submissions error: ${err.message}`, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-error'})
}
return of(null)
}

private handleSubmissionResponse(status: SuccessfulSubmissionsStatus) {
switch (status.submission) {
case 'CORRECT':
this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-success'});
break;
case 'WRONG':
this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION, panelClass: 'snackbar-warning'});
break;
default:
this._snackBar.open(status.description, null, {duration: Config.SNACKBAR_DURATION});
break;
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/app/objectdetails/quick-viewer.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ <h1 class="title" matDialogTitle>{{mediaobject.objectid}} ({{mediaobject.name}})
<app-m3d-loader #modelviewer *ngIf="mediaobject.mediatype === 'MODEL3D'" [height]="400" [interaction]="true"
[width]="400" src="{{mediaobject|ObjectPathPipe}}"></app-m3d-loader>

<button color="primary" mat-flat-button *ngIf="(_vbs |CompetitionEnabledPipe | async)" (click)="onSubmitPressed()">
<button color="primary" mat-flat-button *ngIf=" ('lsc' | competitionEnabledPipe | async)" (click)="onSubmitPressed()">
<mat-icon>send</mat-icon>
</button>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</div>

<div *ngIf="_focus" class="footer" fxLayout="row" fxLayoutAlign="space-evenly">
<button (click)="onSubmitButtonClicked()" *ngIf="(_vbs |CompetitionEnabledPipe | async)"
<button (click)="onSubmitButtonClicked()" *ngIf="('' |competitionEnabledPipe | async)"
mat-icon-button matTooltip="Submit segment to VBS">
<mat-icon>send</mat-icon>
</button>
Expand Down
Loading

0 comments on commit f34efda

Please sign in to comment.