Skip to content
Open
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 @@ -25,6 +25,7 @@ <h2 class="heading-source-side">{{ t("overview_reference") }} {{ preHyphenate(re
<button
mat-button
(click)="trainingSources.push(undefined); $event.preventDefault()"
[disabled]="!appOnline"
class="add-another-project"
>
<mat-icon>add</mat-icon> {{ t("add_another_reference_project") }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
}
</mat-list>
}
<button mat-button (click)="openUploadDialog()">
<button mat-button (click)="openUploadDialog()" [disabled]="!appOnline">
<mat-icon>file_upload</mat-icon>
{{ t("upload_spreadsheet") }}
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { FileService } from 'xforge-common/file.service';
import { I18nService } from 'xforge-common/i18n.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { Locale } from 'xforge-common/models/i18n-locale';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { SFProjectProfileDoc } from '../../../core/models/sf-project-profile-doc';
Expand All @@ -22,6 +23,7 @@ const mockActivatedProjectService = mock(ActivatedProjectService);
const mockDialogService = mock(DialogService);
const mockFileService = mock(FileService);
const mockI18nService = mock(I18nService);
const mockOnlineStatusService = mock(OnlineStatusService);
const mockTrainingDataService = mock(TrainingDataService);
const mockTrainingDataUploadDialogComponent = mock<MatDialogRef<TrainingDataUploadDialogComponent>>(MatDialogRef);
const mockUserService = mock(UserService);
Expand Down Expand Up @@ -56,6 +58,7 @@ describe('TrainingDataMultiSelectComponent', () => {
{ provide: DialogService, useMock: mockDialogService },
{ provide: FileService, useMock: mockFileService },
{ provide: I18nService, useMock: mockI18nService },
{ provide: OnlineStatusService, useMock: mockOnlineStatusService },
{ provide: TrainingDataService, useMock: mockTrainingDataService },
{ provide: UserService, useMock: mockUserService }
]
Expand Down Expand Up @@ -105,6 +108,7 @@ describe('TrainingDataMultiSelectComponent', () => {
mockDialogService.confirm('training_data_multi_select.confirm_delete', 'training_data_multi_select.delete')
).thenResolve(true);
when(mockI18nService.locale$).thenReturn(of(locale));
when(mockOnlineStatusService.isOnline).thenReturn(true);
when(mockTrainingDataUploadDialogComponent.afterClosed()).thenReturn(of({ dataId: 'data04' }));
fixture = TestBed.createComponent(TrainingDataMultiSelectComponent);
component = fixture.componentInstance;
Expand Down Expand Up @@ -138,6 +142,14 @@ describe('TrainingDataMultiSelectComponent', () => {
expect(result).not.toContain(mockTrainingData[0]);
}));

it('cannot show the upload dialog if offline', fakeAsync(() => {
when(mockOnlineStatusService.isOnline).thenReturn(false);
component.openUploadDialog();
tick();

verify(mockDialogService.openMatDialog(TrainingDataUploadDialogComponent, anything())).never();
}));

it('should show the upload dialog', fakeAsync(() => {
let result: TrainingData[] = [];
component.trainingDataSelect.subscribe((_result: TrainingData[]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ActivatedProjectService } from 'xforge-common/activated-project.service
import { DialogService } from 'xforge-common/dialog.service';
import { FileService } from 'xforge-common/file.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { UserService } from 'xforge-common/user.service';
import {
TrainingDataUploadDialogComponent,
Expand All @@ -33,9 +34,14 @@ export class TrainingDataMultiSelectComponent {
private readonly activatedProjectService: ActivatedProjectService,
private readonly dialogService: DialogService,
private readonly fileService: FileService,
private readonly onlineStatus: OnlineStatusService,
private readonly userService: UserService
) {}

get appOnline(): boolean {
return this.onlineStatus.isOnline;
}

canDeleteTrainingData(trainingData: TrainingData): boolean {
const userId: string = this.userService.currentUserId;
const project: SFProjectProfile | undefined = this.activatedProjectService.projectDoc?.data;
Expand All @@ -61,6 +67,7 @@ export class TrainingDataMultiSelectComponent {

openUploadDialog(): void {
if (this.activatedProjectService.projectId == null) return;
if (!this.appOnline) return;
const dialogConfig: MatDialogConfig<TrainingDataUploadDialogData> = {
data: { projectId: this.activatedProjectService.projectId, availableTrainingData: this.availableTrainingData },
width: '320px'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h2 mat-dialog-title>{{ t("upload_training_data") }}</h2>
<button mat-button [mat-dialog-close]="'close'" type="button" id="upload-cancel-btn">
{{ t("cancel") }}
</button>
<button mat-flat-button color="primary" type="submit" (click)="save()" id="upload-save-btn">
<button mat-flat-button color="primary" type="submit" (click)="save()" [disabled]="!appOnline" id="upload-save-btn">
{{ t("save") }}
</button>
</mat-dialog-actions>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import { OverlayContainer } from '@angular/cdk/overlay';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { NgZone } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { ngfModule } from 'angular-file';
import { TrainingData } from 'realtime-server/lib/esm/scriptureforge/models/training-data';
import { anything, mock, when } from 'ts-mockito';
import { anything, mock, verify, when } from 'ts-mockito';
import { FileService } from 'xforge-common/file.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { ChildViewContainerComponent, configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { TrainingDataDoc } from '../../../core/models/training-data-doc';
import { TrainingDataFileUpload, TrainingDataUploadDialogComponent } from './training-data-upload-dialog.component';
import { TrainingDataService } from './training-data.service';

const mockedFileService = mock(FileService);
const mockOnlineStatusService = mock(OnlineStatusService);
const mockedTrainingDataService = mock(TrainingDataService);
const mockedUserService = mock(UserService);

describe('TrainingDataUploadDialogComponent', () => {
configureTestingModule(() => ({
imports: [ngfModule, getTestTranslocoModule()],
providers: [
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
{ provide: FileService, useMock: mockedFileService },
{ provide: OnlineStatusService, useMock: mockOnlineStatusService },
{ provide: TrainingDataService, useMock: mockedTrainingDataService },
{ provide: UserService, useMock: mockedUserService }
]
Expand All @@ -40,6 +39,31 @@ describe('TrainingDataUploadDialogComponent', () => {
overlayContainer.ngOnDestroy();
});

it('cannot save if offline', async () => {
const env = new TestEnvironment();
when(mockOnlineStatusService.isOnline).thenReturn(false);
let result: TrainingData = { dataId: '' } as TrainingData;
env.dialogRef.afterClosed().subscribe((_result: TrainingData) => {
result = _result;
});
env.component.updateTrainingData(env.trainingDataFile);
await env.component.save();
await env.wait();

verify(
mockedFileService.onlineUploadFileOrFail(
anything(),
anything(),
anything(),
anything(),
anything(),
anything(),
anything()
)
).never();
expect(result.dataId).toEqual('');
});

it('should upload training data and return the object on save', async () => {
const env = new TestEnvironment();
let result: TrainingData = { dataId: '' } as TrainingData;
Expand Down Expand Up @@ -121,6 +145,7 @@ class TestEnvironment {
true
)
).thenResolve('training data file url');
when(mockOnlineStatusService.isOnline).thenReturn(true);
when(mockedUserService.currentUserId).thenReturn('user01');

const blob = new Blob(['source_1,target_2\nsource_2,target_2'], { type: 'text/csv' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DialogService } from 'xforge-common/dialog.service';
import { FileService } from 'xforge-common/file.service';
import { I18nService } from 'xforge-common/i18n.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { UserService } from 'xforge-common/user.service';
import { objectId } from 'xforge-common/utils';
import { TrainingDataDoc } from '../../../core/models/training-data-doc';
Expand Down Expand Up @@ -66,9 +67,14 @@ export class TrainingDataUploadDialogComponent implements AfterViewInit {
private readonly dialogRef: MatDialogRef<TrainingDataUploadDialogComponent, TrainingData | undefined>,
private readonly dialogService: DialogService,
private readonly fileService: FileService,
private readonly onlineStatus: OnlineStatusService,
private readonly userService: UserService
) {}

get appOnline(): boolean {
return this.onlineStatus.isOnline;
}

get hasBeenUploaded(): boolean {
return this.trainingDataFile?.blob != null && this.trainingDataFile?.fileName != null;
}
Expand Down Expand Up @@ -113,7 +119,7 @@ export class TrainingDataUploadDialogComponent implements AfterViewInit {

async save(): Promise<void> {
// We cannot save a file if it has not been uploaded, or if offline
if (!this.hasBeenUploaded) {
if (!this.hasBeenUploaded || !this.appOnline) {
return;
}

Expand Down
Loading