Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ <h1 mat-dialog-title>{{ t("translator_settings") }}</h1>
<mat-select
id="num-suggestions-select"
[disabled]="translationSuggestionsDisabled"
[(ngModel)]="numSuggestions"
[ngModel]="numSuggestions"
(ngModelChange)="setNumSuggestions($event)"
>
@for (value of ["1", "2", "3", "4", "5"]; track value) {
<mat-option [value]="value">{{ value }}</mat-option>
Expand All @@ -39,7 +40,7 @@ <h1 mat-dialog-title>{{ t("translator_settings") }}</h1>
}}</span>
<div class="slider-labels">
<span>{{ t("more") }}</span>
<span>{{ confidenceThreshold }}%</span>
<span>{{ confidenceThreshold$ | async }}%</span>
<span>{{ t("better") }}</span>
</div>
<mat-slider
Expand All @@ -50,8 +51,9 @@ <h1 mat-dialog-title>{{ t("translator_settings") }}</h1>
>
<input
matSliderThumb
[(ngModel)]="confidenceThreshold"
(dragEnd)="confidenceThreshold = $event.value"
[ngModel]="confidenceThreshold$ | async"
(ngModelChange)="setConfidenceThreshold($event)"
(dragEnd)="setConfidenceThreshold($event.value)"
/>
</mat-slider>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { CommonModule } from '@angular/common';
import { DebugElement, NgModule } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
Expand Down Expand Up @@ -53,10 +54,10 @@ describe('TranslatorSettingsDialogComponent', () => {
it('update confidence threshold', fakeAsync(() => {
const env = new TestEnvironment();
env.openDialog();
expect(env.component!.confidenceThreshold).toEqual(50);
expect(env.component!.confidenceThreshold$.value).toEqual(50);

env.updateConfidenceThresholdSlider(60);
expect(env.component!.confidenceThreshold).toEqual(60);
expect(env.component!.confidenceThreshold$.value).toEqual(60);
const userConfigDoc = env.getProjectUserConfigDoc();
expect(userConfigDoc.data!.confidenceThreshold).toEqual(0.6);
env.closeDialog();
Expand All @@ -65,14 +66,14 @@ describe('TranslatorSettingsDialogComponent', () => {
it('update suggestions enabled', fakeAsync(async () => {
const env = new TestEnvironment();
env.openDialog();
expect(env.component!.translationSuggestionsUserEnabled).toBe(true);
expect(env.component!['translationSuggestionsUserEnabled']).toBe(true);

const suggestionsToggle = await env.getSuggestionsEnabledToggle();
expect(suggestionsToggle).not.toBeNull();
expect(await env.isToggleChecked(suggestionsToggle!)).toBe(true);

await env.toggleSlideToggle(suggestionsToggle!);
expect(env.component!.translationSuggestionsUserEnabled).toBe(false);
expect(env.component!['translationSuggestionsUserEnabled']).toBe(false);
expect(await env.isToggleChecked(suggestionsToggle!)).toBe(false);

const userConfigDoc = env.getProjectUserConfigDoc();
Expand All @@ -95,7 +96,7 @@ describe('TranslatorSettingsDialogComponent', () => {
it('shows correct confidence threshold even when suggestions disabled', fakeAsync(() => {
const env = new TestEnvironment({ translationSuggestionsEnabled: false });
env.openDialog();
expect(env.component?.confidenceThreshold).toEqual(50);
expect(env.component?.confidenceThreshold$.value).toEqual(50);
env.closeDialog();
}));

Expand Down Expand Up @@ -312,7 +313,7 @@ describe('TranslatorSettingsDialogComponent', () => {
});

@NgModule({
imports: [UICommonModule, TestTranslocoModule, NoticeComponent],
imports: [CommonModule, UICommonModule, TestTranslocoModule, NoticeComponent],
declarations: [TranslatorSettingsDialogComponent]
})
class DialogTestModule {}
Expand Down Expand Up @@ -426,7 +427,7 @@ class TestEnvironment {
}

updateConfidenceThresholdSlider(value: number): void {
this.component!.confidenceThreshold = value;
this.component!.confidenceThreshold$.next(value);
tick(CONFIDENCE_THRESHOLD_TIMEOUT);
this.fixture.detectChanges();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, DestroyRef, Inject, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { BehaviorSubject } from 'rxjs';
import { debounceTime, map, skip, startWith } from 'rxjs/operators';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
Expand All @@ -21,44 +21,46 @@ export interface TranslatorSettingsDialogData {
standalone: false
})
export class TranslatorSettingsDialogComponent implements OnInit {
suggestionsEnabledSwitch = new FormControl<boolean>({ value: false, disabled: !this.onlineStatusService.isOnline });
lynxMasterSwitch = new FormControl<boolean>(false);
lynxAssessmentsEnabled = new FormControl<boolean>(false);
lynxAutoCorrectEnabled = new FormControl<boolean>(false);
readonly suggestionsEnabledSwitch = new FormControl<boolean>({
value: false,
disabled: !this.onlineStatusService.isOnline
});
readonly lynxMasterSwitch = new FormControl<boolean>(false);
readonly lynxAssessmentsEnabled = new FormControl<boolean>(false);
readonly lynxAutoCorrectEnabled = new FormControl<boolean>(false);

showSuggestionsSettings = false;
showLynxSettings = false;
translationSuggestionsDisabled = false;
lynxAssessmentsProjectEnabled = false;
lynxAutoCorrectProjectEnabled = false;
numSuggestions = '1';

readonly confidenceThreshold$ = new BehaviorSubject<number>(20);

private readonly projectDoc: SFProjectProfileDoc = this.data.projectDoc;
private readonly projectUserConfigDoc: SFProjectUserConfigDoc = this.data.projectUserConfigDoc;
private confidenceThreshold$ = new BehaviorSubject<number>(20);

constructor(
@Inject(MAT_DIALOG_DATA) private readonly data: TranslatorSettingsDialogData,
readonly onlineStatusService: OnlineStatusService,
private destroyRef: DestroyRef
private readonly destroyRef: DestroyRef
) {}

ngOnInit(): void {
if (this.projectUserConfigDoc.data != null) {
const percent = Math.round(this.projectUserConfigDoc.data.confidenceThreshold * 100);
this.confidenceThreshold$.next(percent);
}
this.updateComponentState();

this.suggestionsEnabledSwitch.setValue(this.translationSuggestionsUserEnabled);
this.lynxAssessmentsEnabled.setValue(this.lynxAssessmentsUserEnabled);
this.lynxAutoCorrectEnabled.setValue(this.lynxAutoCorrectUserEnabled);
this.lynxMasterSwitch.setValue(this.lynxMasterEnabled);
this.onlineStatusService.onlineStatus$
.pipe(quietTakeUntilDestroyed(this.destroyRef))
.subscribe(() => this.onOnlineStatusChange());

this.projectDoc.changes$
.pipe(startWith(null), quietTakeUntilDestroyed(this.destroyRef))
.subscribe(() => this.updateComponentState());

combineLatest([this.onlineStatusService.onlineStatus$, this.projectDoc.changes$.pipe(startWith(null))])
this.projectUserConfigDoc.changes$
.pipe(quietTakeUntilDestroyed(this.destroyRef))
.subscribe(() => {
this.updateTranslationSuggestionsSwitch();
});

this.projectUserConfigDoc.changes$.pipe(quietTakeUntilDestroyed(this.destroyRef)).subscribe(() => {
this.updateTranslationSuggestionsSwitch();
this.lynxAssessmentsEnabled.setValue(this.lynxAssessmentsUserEnabled, { emitEvent: false });
this.lynxAutoCorrectEnabled.setValue(this.lynxAutoCorrectUserEnabled, { emitEvent: false });
this.lynxMasterSwitch.setValue(this.lynxMasterEnabled, { emitEvent: false });
});
.subscribe(() => this.updateComponentState());

this.confidenceThreshold$
.pipe(
Expand All @@ -73,88 +75,82 @@ export class TranslatorSettingsDialogComponent implements OnInit {
);
}

get translationSuggestionsDisabled(): boolean {
return !this.translationSuggestionsUserEnabled || !this.onlineStatusService.isOnline;
setConfidenceThreshold(value: number): void {
this.confidenceThreshold$.next(value);
}

get translationSuggestionsUserEnabled(): boolean {
return this.projectUserConfigDoc.data == null ? true : this.projectUserConfigDoc.data.translationSuggestionsEnabled;
setNumSuggestions(value: string): void {
this.numSuggestions = value;
void this.projectUserConfigDoc.submitJson0Op(op => op.set(puc => puc.numSuggestions, parseInt(value, 10)));
}

get numSuggestions(): string {
return this.projectUserConfigDoc.data == null ? '1' : this.projectUserConfigDoc.data.numSuggestions.toString();
setTranslationSettingsEnabled(value: boolean): void {
void this.projectUserConfigDoc.submitJson0Op(op =>
op.set<boolean>(puc => puc.translationSuggestionsEnabled, value)
);
}

set numSuggestions(value: string) {
void this.projectUserConfigDoc.submitJson0Op(op => op.set(puc => puc.numSuggestions, parseInt(value, 10)));
setLynxAssessmentsEnabled(value: boolean): void {
this.updateLynxInsightState({ assessmentsEnabled: value });
}

get confidenceThreshold(): number {
return this.confidenceThreshold$.value;
setLynxAutoCorrectEnabled(value: boolean): void {
this.updateLynxInsightState({ autoCorrectionsEnabled: value });
}

set confidenceThreshold(value: number) {
this.confidenceThreshold$.next(value);
setLynxMasterEnabled(value: boolean): void {
this.updateLynxInsightState({
assessmentsEnabled: value,
autoCorrectionsEnabled: value
});
}
private get translationSuggestionsUserEnabled(): boolean {
return this.projectUserConfigDoc.data?.translationSuggestionsEnabled ?? true;
}

get lynxAssessmentsUserEnabled(): boolean {
private get lynxAssessmentsUserEnabled(): boolean {
return this.projectUserConfigDoc.data?.lynxInsightState?.assessmentsEnabled ?? true;
}

get lynxAutoCorrectUserEnabled(): boolean {
private get lynxAutoCorrectUserEnabled(): boolean {
return this.projectUserConfigDoc.data?.lynxInsightState?.autoCorrectionsEnabled ?? true;
}

get lynxAssessmentsProjectEnabled(): boolean {
return !!this.projectDoc.data?.lynxConfig?.assessmentsEnabled;
}

get lynxAutoCorrectProjectEnabled(): boolean {
return !!this.projectDoc.data?.lynxConfig?.autoCorrectionsEnabled;
}

get lynxMasterEnabled(): boolean {
private get lynxMasterEnabled(): boolean {
return (
(this.lynxAssessmentsProjectEnabled && this.lynxAssessmentsUserEnabled) ||
(this.lynxAutoCorrectProjectEnabled && this.lynxAutoCorrectUserEnabled)
);
}

get showSuggestionsSettings(): boolean {
return !!this.projectDoc.data?.translateConfig.translationSuggestionsEnabled;
}

get showLynxSettings(): boolean {
return this.lynxAssessmentsProjectEnabled || this.lynxAutoCorrectProjectEnabled;
}

setTranslationSettingsEnabled(value: boolean): void {
void this.projectUserConfigDoc.submitJson0Op(op =>
op.set<boolean>(puc => puc.translationSuggestionsEnabled, value)
);
}

updateTranslationSuggestionsSwitch(): void {
private onOnlineStatusChange(): void {
if (this.onlineStatusService.isOnline) {
this.suggestionsEnabledSwitch.enable();
this.translationSuggestionsDisabled = !this.translationSuggestionsUserEnabled;
} else {
this.suggestionsEnabledSwitch.disable();
this.translationSuggestionsDisabled = true;
}
}

setLynxAssessmentsEnabled(value: boolean): void {
this.updateLynxInsightState({ assessmentsEnabled: value });
}
private updateComponentState(): void {
this.showSuggestionsSettings = !!this.projectDoc.data?.translateConfig.translationSuggestionsEnabled;
this.lynxAssessmentsProjectEnabled = !!this.projectDoc.data?.lynxConfig?.assessmentsEnabled;
this.lynxAutoCorrectProjectEnabled = !!this.projectDoc.data?.lynxConfig?.autoCorrectionsEnabled;
this.showLynxSettings = this.lynxAssessmentsProjectEnabled || this.lynxAutoCorrectProjectEnabled;
this.translationSuggestionsDisabled = !this.translationSuggestionsUserEnabled || !this.onlineStatusService.isOnline;

setLynxAutoCorrectEnabled(value: boolean): void {
this.updateLynxInsightState({ autoCorrectionsEnabled: value });
}
if (this.projectUserConfigDoc.data != null) {
const percent = Math.round(this.projectUserConfigDoc.data.confidenceThreshold * 100);
this.numSuggestions = this.projectUserConfigDoc.data.numSuggestions.toString();
this.confidenceThreshold$.next(percent);
}

setLynxMasterEnabled(value: boolean): void {
this.updateLynxInsightState({
assessmentsEnabled: value,
autoCorrectionsEnabled: value
});
// Update form control state
this.suggestionsEnabledSwitch.setValue(this.translationSuggestionsUserEnabled, { emitEvent: false });
this.lynxAssessmentsEnabled.setValue(this.lynxAssessmentsUserEnabled, { emitEvent: false });
this.lynxAutoCorrectEnabled.setValue(this.lynxAutoCorrectUserEnabled, { emitEvent: false });
this.lynxMasterSwitch.setValue(this.lynxMasterEnabled, { emitEvent: false });
}

private updateLynxInsightState(updates: { assessmentsEnabled?: boolean; autoCorrectionsEnabled?: boolean }): void {
Expand Down
Loading