Skip to content

Commit

Permalink
feat(dsp-das): image settings (DEV-2995) (#1440)
Browse files Browse the repository at this point in the history
Co-authored-by: Julien Schneider <[email protected]>
  • Loading branch information
irmastnt and derschnee68 authored Feb 8, 2024
1 parent 7825d3d commit 3609b52
Show file tree
Hide file tree
Showing 22 changed files with 397 additions and 20 deletions.
12 changes: 10 additions & 2 deletions apps/dsp-app/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import { CreateProjectFormPageComponent } from './project/create-project-form-pa
import { DataModelsComponent } from './project/data-models/data-models.component';
import { DescriptionComponent } from './project/description/description.component';
import { EditProjectFormPageComponent } from './project/edit-project-form-page/edit-project-form-page.component';
import { ImageSettingsComponent } from './project/image-settings/image-settings.component';
import { ListComponent } from './project/list/list.component';
import { CreateListInfoPageComponent } from './project/list/reusable-list-info-form/create-list-info-page.component';
import { CreateResourceClassDialogComponent } from './project/ontology/create-resource-class-dialog/create-resource-class-dialog.component';
import { OntologyFormComponent } from './project/ontology/ontology-form/ontology-form.component';
import { OntologyComponent } from './project/ontology/ontology.component';
import { OntologyClassInstanceComponent } from './project/ontology-classes/ontology-class-instance/ontology-class-instance.component';
Expand Down Expand Up @@ -102,7 +102,15 @@ const routes: Routes = [
{
path: RouteConstants.home,
pathMatch: 'full',
redirectTo: RouteConstants.collaboration,
redirectTo: RouteConstants.edit,
},
{
path: RouteConstants.edit,
component: EditProjectFormPageComponent,
},
{
path: RouteConstants.imageSettings,
component: ImageSettingsComponent,
},
{
path: RouteConstants.collaboration,
Expand Down
2 changes: 2 additions & 0 deletions apps/dsp-app/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { CreateProjectFormPageComponent } from './project/create-project-form-pa
import { DataModelsComponent } from './project/data-models/data-models.component';
import { DescriptionComponent } from './project/description/description.component';
import { EditProjectFormPageComponent } from './project/edit-project-form-page/edit-project-form-page.component';
import { ImageSettingsComponent } from './project/image-settings/image-settings.component';
import { ActionBubbleComponent } from './project/list/action-bubble/action-bubble.component';
import { ListItemComponent } from './project/list/list-item/list-item.component';
import { ListItemElementComponent } from './project/list/list-item-element/list-item-element.component';
Expand Down Expand Up @@ -263,6 +264,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
CreateProjectFormPageComponent,
ReusableProjectFormComponent,
EditProjectFormPageComponent,
ImageSettingsComponent,
ProjectsComponent,
ProjectsListComponent,
PropertiesComponent,
Expand Down
11 changes: 11 additions & 0 deletions apps/dsp-app/src/app/main/animations/replace-animation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { animate, style, transition, trigger } from '@angular/animations';

export class ReplaceAnimation {
public static enterTime = 500;
public static liveTime = 0;

public static animation = trigger('replaceAnimation', [
transition(':enter', [style({ opacity: 0 }), animate(ReplaceAnimation.enterTime, style({ opacity: 1 }))]),
transition(':leave', [style({ opacity: 1 }), animate(ReplaceAnimation.liveTime, style({ opacity: 0 }))]),
]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ <h3 class="mat-body subtitle">Project {{ project.shortcode }} | {{ project.short
mat-button
*ngIf="(userHasPermission$ | async) && project.status"
class="right"
[routerLink]="RouteConstants.edit"
[routerLink]="RouteConstants.projectEditRelative"
color="primary">
<mat-icon>edit_square</mat-icon>
Edit project description
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ import { map, switchMap, take } from 'rxjs/operators';
(formValueChange)="form = $event"></app-reusable-project-form>
<div style="display: flex; justify-content: space-between">
<button color="primary" mat-button type="reset" [routerLink]="['..']">
{{ 'appLabels.form.action.cancel' | translate }}
</button>
<button
mat-raised-button
type="submit"
Expand All @@ -45,7 +41,7 @@ import { map, switchMap, take } from 'rxjs/operators';
export class EditProjectFormPageComponent {
form: FormGroup;
loading = false;
project$ = this.route.parent.paramMap.pipe(
project$ = this.route.parent.parent.paramMap.pipe(
map(params => params.get(RouteConstants.uuidParameter)),
map(uuid => this._projectService.uuidToIri(uuid)),
switchMap(iri => this._projectApiService.get(iri)),
Expand All @@ -63,7 +59,7 @@ export class EditProjectFormPageComponent {
) {}

onSubmit() {
const projectUuid = this.route.parent.snapshot.paramMap.get(RouteConstants.uuidParameter);
const projectUuid = this.route.parent.parent.snapshot.paramMap.get(RouteConstants.uuidParameter);

const projectData: UpdateProjectRequest = {
longname: this.form.value.longname,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<dasch-swiss-centered-layout>
<dasch-swiss-app-progress-indicator *ngIf="isProjectsLoading$ | async"></dasch-swiss-app-progress-indicator>
<div class="content large middle" *ngIf="(isProjectsLoading$ | async) === false">
<div class="content-container">
<form *ngIf="form" class="form-content" [formGroup]="form">
<div class="large-field aspect">
<mat-slide-toggle formControlName="aspect">
{{ 'appLabels.form.project.imageSettings.aspect' | translate }}
</mat-slide-toggle>
</div>
<div *ngIf="form.controls.aspect.value" [@replaceAnimation]>
<div class="large-field">
<mat-label>
{{ 'appLabels.form.project.imageSettings.percentage-value' | translate }}: {{ percentageSlider.value}}%
</mat-label>
</div>
<mat-slider
min="1"
max="100"
step="1"
showTickMarks
discrete
[displayWith]="formatPercentageLabel"
ngDefaultControl
formControlName="percentage">
<input #percentageSlider matSliderThumb [value]="form.controls.percentage.value" />
</mat-slider>
</div>
<div *ngIf="!form.controls.aspect.value" [@replaceAnimation]>
<div class="large-field">
<mat-label>
{{ 'appLabels.form.project.imageSettings.absolute-width' | translate }}: {{
projectImageSettings.absoluteWidth }} px
</mat-label>
</div>
<mat-slider
[min]="0"
[max]="4"
[step]="1"
showTickMarks
[displayWith]="formatAbsoluteLabel"
discrete
ngDefaultControl
formControlName="absoluteWidthIndex">
<input
(valueChange)="absoluteSliderChange($event)"
[value]="absoluteWidthIndex(projectImageSettings.absoluteWidth)"
matSliderThumb />
</mat-slider>
</div>
</form>
<div class="action-buttons">
<button
mat-raised-button
type="submit"
color="primary"
[disabled]="form?.invalid"
(click)="onSubmit()"
appLoadingButton
[isLoading]="isProjectsLoading$ | async">
{{ 'appLabels.form.action.submit' | translate }}
</button>
</div>
</div>
<div class="content-sidebar">
<img
[@replaceAnimation]
*ngIf="!form.controls.aspect.value"
src="assets/images/image-setting-absolute.png"
[alt]="'appLabels.form.project.imageSettings.absolute' | translate" />
<img
[@replaceAnimation]
*ngIf="form.controls.aspect.value"
src="assets/images/image-setting-percentage.png"
[alt]="'appLabels.form.project.imageSettings.percentage' | translate" />
</div>
</div>
</dasch-swiss-centered-layout>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.content {
display: flex;
flex-direction: row;

.content-sidebar {
max-width: 389px;
flex: 389px;
}

.content-container {
padding-right: 32px;
}

.aspect {
padding-bottom: 32px;
}

.mat-mdc-slider {
width: 100%;
}

.action-buttons {
display: flex;
justify-content: space-between;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { ChangeDetectionStrategy, Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { ProjectRestrictedViewSettings } from '@dasch-swiss/dsp-js';
import { SetRestrictedViewRequest } from '@dasch-swiss/vre/open-api';
import { ProjectApiService } from '@dasch-swiss/vre/shared/app-api';
import { RouteConstants } from '@dasch-swiss/vre/shared/app-config';
import { ProjectService } from '@dasch-swiss/vre/shared/app-helper-services';
import { NotificationService } from '@dasch-swiss/vre/shared/app-notification';
import {
LoadProjectRestrictedViewSettingsAction,
ProjectsSelectors,
UpdateProjectRestrictedViewSettingsAction,
} from '@dasch-swiss/vre/shared/app-state';
import { Actions, Select, Store, ofActionSuccessful } from '@ngxs/store';
import { Observable, combineLatest } from 'rxjs';
import { map, switchMap, take, takeWhile } from 'rxjs/operators';
import { ReplaceAnimation } from '../../main/animations/replace-animation';
import { ProjectImageSettings } from './project-image-settings';

@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-image-settings',
styleUrls: ['./image-settings.component.scss'],
templateUrl: './image-settings.component.html',
animations: [ReplaceAnimation.animation],
})
export class ImageSettingsComponent implements OnInit {
readonly absoluteWidthSteps: number[] = [64, 128, 256, 512, 1024];

projectImageSettings = new ProjectImageSettings();
form: FormGroup;
projectUuid: string;
project$ = this.route.parent.parent.paramMap.pipe(
map(params => params.get(RouteConstants.uuidParameter)),
map(uuid => this._projectService.uuidToIri(uuid)),
switchMap(iri => this._projectApiService.get(iri)),
map(project => project.project)
);

@Output() formValueChange = new EventEmitter<FormGroup>();

@Select(ProjectsSelectors.isProjectsLoading) isProjectsLoading$: Observable<boolean>;
@Select(ProjectsSelectors.projectRestrictedViewSettings)
projectRestrictedViewSettings$: Observable<ProjectRestrictedViewSettings>;

constructor(
private _projectApiService: ProjectApiService,
private _projectService: ProjectService,
private route: ActivatedRoute,
private _store: Store,
private _notification: NotificationService,
private _actions: Actions,
private _fb: FormBuilder
) {}

ngOnInit() {
this._buildForm();
this.setFormData();
}

formatPercentageLabel = (value: number): string => `${value}%`;

formatAbsoluteLabel = (value: number): string => `${this.absoluteWidthSteps[value]}px`;

setFormData() {
this.projectUuid = this.route.parent.parent.snapshot.paramMap.get(RouteConstants.uuidParameter);
this._store.dispatch(new LoadProjectRestrictedViewSettingsAction(this._projectService.uuidToIri(this.projectUuid)));
combineLatest([
this._actions.pipe(ofActionSuccessful(LoadProjectRestrictedViewSettingsAction), take(1)),
this.projectRestrictedViewSettings$.pipe(takeWhile(settings => settings?.watermark === true)),
])
.pipe(
take(1),
map(([action, settings]) => {
this.projectImageSettings = ProjectImageSettings.GetProjectImageSettings(settings.size);
this.form.patchValue({
aspect: this.projectImageSettings.aspect,
percentage: this.projectImageSettings.percentage,
absoluteWidthIndex: this.absoluteWidthSteps[this.projectImageSettings.absoluteWidth],
});
})
)
.subscribe();
}

absoluteWidthIndex = (value: number): number => this.absoluteWidthSteps.findIndex(step => step == value);

absoluteSliderChange(value: number) {
this.projectImageSettings.absoluteWidth = this.absoluteWidthSteps[value];
}

onSubmit() {
const request: SetRestrictedViewRequest = {
size: ProjectImageSettings.FormatToIiifSize(
this.form.value.aspect,
this.form.value.percentage,
this.absoluteWidthSteps[this.form.value.absoluteWidthIndex]
),
watermark: true,
};

this._store.dispatch(new UpdateProjectRestrictedViewSettingsAction(this.projectUuid, request));
this._actions.pipe(ofActionSuccessful(UpdateProjectRestrictedViewSettingsAction), take(1)).subscribe(() => {
this._notification.openSnackBar('You have successfully updated the project image settings.');
});
}

private _buildForm() {
this.form = this._fb.group({
aspect: ['', []],
absoluteWidthIndex: ['', []],
percentage: ['', []],
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export class ProjectImageSettings {
aspect: boolean = false;
absoluteWidth: number = 0;
percentage: number = 0;

/*
!d,d The returned image is scaled so that the width and height of the returned image are not greater than d, while maintaining the aspect ratio.
pct:n The width and height of the returned image is scaled to n percent of the width and height of the extracted region. 1<= n <= 100.
*/
static GetProjectImageSettings(size?: string): ProjectImageSettings {
if (!size) {
return <ProjectImageSettings>{};
}

const isPercentage = size.startsWith('pct');
return <ProjectImageSettings>{
aspect: isPercentage,
absoluteWidth: !isPercentage ? size.substring(1).split(',').pop() : 0,
percentage: isPercentage ? size.split('pct:').pop() : 0,
};
}

static FormatToIiifSize(aspect: any, percentage: any, width: number): string {
return aspect ? `pct:${percentage}` : `!${width},${width}`;
}
}
12 changes: 12 additions & 0 deletions apps/dsp-app/src/app/project/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ import { MenuItem } from '../../main/declarations/menu-item';
})
export class SettingsComponent {
navigation: MenuItem[] = [
{
label: 'Description',
shortLabel: 'Description',
route: RouteConstants.edit,
icon: 'edit_square',
},
{
label: 'Image Settings',
shortLabel: 'Image Settings',
route: RouteConstants.imageSettings,
icon: 'branding_watermark',
},
{
label: 'Project members',
shortLabel: 'Members',
Expand Down
8 changes: 7 additions & 1 deletion apps/dsp-app/src/assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@
"step_3": "Bestätgien",
"more": "Ein weiteres Projekt erstellen"
}
},
"imageSettings": {
"aspect": "Aspekt",
"absolute-width": "absolute Breite",
"percentage-value": "Prozentwert",
"percentage": "Prozentsatz"
}
},
"member": {
Expand All @@ -126,4 +132,4 @@
}
}
}
}
}
Loading

0 comments on commit 3609b52

Please sign in to comment.