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 @@ -280,7 +280,7 @@ export class DraftHandlingService {
*/
opsHaveContent(ops: DeltaOperation[]): boolean {
const indexOfFirstText = ops.findIndex(op => typeof op.insert === 'string');
const onlyTextOpIsTrailingNewline = indexOfFirstText === ops.length - 1 && ops[indexOfFirstText].insert === '\n';
const onlyTextOpIsTrailingNewline = indexOfFirstText === ops.length - 1 && ops[indexOfFirstText]?.insert === '\n';
const hasNoExistingText = indexOfFirstText === -1 || onlyTextOpIsTrailingNewline;
return !hasNoExistingText;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,15 @@ <h1>{{ t("formatting_options") }}</h1>
[book]="bookNum"
(bookChange)="bookChanged($event)"
[(chapter)]="chapterNum"
[chapters]="chapters"
[chapters]="chaptersWithDrafts"
(chapterChange)="chapterChanged($event)"
></app-book-chapter-chooser>
<div class="viewer-container">
<app-text
[isReadOnly]="true"
[subscribeToUpdates]="false"
[isRightToLeft]="isRightToLeft"
[placeholder]="isOnline ? t('chapter_draft_does_not_exist') : t('text_unavailable_offline')"
[class.initializing]="isInitializing"
[class.loading]="isLoadingData"
[style.--project-font]="projectFont"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
flex-direction: row;
column-gap: 8px;
height: 100%;
width: 100%;
margin-top: 8px;

@include breakpoints.media-breakpoint-down(sm) {
Expand Down Expand Up @@ -48,13 +49,15 @@
display: flex;
flex-direction: column;
overflow: hidden;
width: 100%;

@include breakpoints.media-breakpoint-down(sm) {
height: 600px;
overflow: initial;
}

.viewer-container {
height: 100%;
overflow-y: auto;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testin
import { MatRadioButtonHarness } from '@angular/material/radio/testing';
import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { ActivatedRoute } from '@angular/router';
import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info';
import {
DraftConfig,
DraftUsfmConfig,
ParagraphBreakFormat,
QuoteFormat
QuoteFormat,
TranslateConfig
} from 'realtime-server/lib/esm/scriptureforge/models/translate-config';
import { of } from 'rxjs';
import { anything, deepEqual, mock, verify, when } from 'ts-mockito';
Expand Down Expand Up @@ -78,8 +81,15 @@ describe('DraftUsfmFormatComponent', () => {

it('shows message if user is not online', fakeAsync(async () => {
const env = new TestEnvironment({
config: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
project: {
translateConfig: {
draftConfig: {
usfmConfig: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Normalized }
} as DraftConfig
} as TranslateConfig
}
});

expect(env.offlineMessage).toBeNull();

env.onlineStatusService.setIsOnline(false);
Expand All @@ -102,19 +112,63 @@ describe('DraftUsfmFormatComponent', () => {
verify(mockedDraftHandlingService.getDraft(anything(), anything())).once();
}));

it('can navigate to first book and chapter if book does not exist', fakeAsync(() => {
when(mockedActivatedRoute.params).thenReturn(of({ bookId: 'NUM', chapter: '1' }));
const env = new TestEnvironment();
tick(EDITOR_READY_TIMEOUT);
env.fixture.detectChanges();
tick(EDITOR_READY_TIMEOUT);
expect(env.component.bookNum).toBe(1);
expect(env.component.chapterNum).toBe(1);
verify(mockedDraftHandlingService.getDraft(anything(), anything())).once();
}));

it('can navigate to book and chapter if first chapter has no draft', fakeAsync(() => {
const env = new TestEnvironment({
project: {
texts: [
{
bookNum: 1,
chapters: [
{ number: 1, lastVerse: 15, isValid: true, permissions: {}, hasDraft: false },
{ number: 2, lastVerse: 20, isValid: true, permissions: {}, hasDraft: true },
{ number: 3, lastVerse: 18, isValid: true, permissions: {}, hasDraft: true }
],
hasSource: true,
permissions: {}
}
]
}
});
tick(EDITOR_READY_TIMEOUT);
env.fixture.detectChanges();
tick(EDITOR_READY_TIMEOUT);
expect(env.component.bookNum).toBe(1);
expect(env.component.chapterNum).toBe(2);
expect(env.component.chaptersWithDrafts).toEqual([2, 3]);
verify(mockedDraftHandlingService.getDraft(anything(), anything())).once();
}));

// Book and chapter changed
it('navigates to a different book and chapter', fakeAsync(() => {
const env = new TestEnvironment({
config: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
project: {
translateConfig: {
draftConfig: {
usfmConfig: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
} as DraftConfig
} as TranslateConfig
}
});

verify(mockedDraftHandlingService.getDraft(anything(), anything())).once();
expect(env.component.chapters.length).toEqual(1);
expect(env.component.chaptersWithDrafts.length).toEqual(1);
expect(env.component.booksWithDrafts.length).toEqual(2);

env.component.bookChanged(2);
tick();
env.fixture.detectChanges();
expect(env.component.chapters.length).toEqual(2);
expect(env.component.chaptersWithDrafts.length).toEqual(2);
verify(mockedDraftHandlingService.getDraft(anything(), anything())).twice();

env.component.chapterChanged(2);
Expand All @@ -133,15 +187,27 @@ describe('DraftUsfmFormatComponent', () => {

it('should show the currently selected format options', fakeAsync(() => {
const env = new TestEnvironment({
config: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Normalized }
project: {
translateConfig: {
draftConfig: {
usfmConfig: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Normalized }
} as DraftConfig
} as TranslateConfig
}
});
expect(env.component.paragraphFormat.value).toBe(ParagraphBreakFormat.MoveToEnd);
expect(env.component.quoteFormat.value).toBe(QuoteFormat.Normalized);
}));

it('goes back if user chooses different configurations and then goes back', fakeAsync(async () => {
const env = new TestEnvironment({
config: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
project: {
translateConfig: {
draftConfig: {
usfmConfig: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
} as DraftConfig
} as TranslateConfig
}
});
verify(mockedDraftHandlingService.getDraft(anything(), anything())).once();
expect(env.harnesses?.length).toEqual(5);
Expand All @@ -162,7 +228,13 @@ describe('DraftUsfmFormatComponent', () => {

it('should save changes to the draft format', fakeAsync(async () => {
const env = new TestEnvironment({
config: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
project: {
translateConfig: {
draftConfig: {
usfmConfig: { paragraphFormat: ParagraphBreakFormat.MoveToEnd, quoteFormat: QuoteFormat.Denormalized }
} as DraftConfig
} as TranslateConfig
}
});
verify(mockedDraftHandlingService.getDraft(anything(), anything())).once();
expect(env.harnesses?.length).toEqual(5);
Expand Down Expand Up @@ -212,7 +284,7 @@ class TestEnvironment {
readonly projectId = 'project01';
onlineStatusService: TestOnlineStatusService;

constructor(args: { config?: DraftUsfmConfig; quotationAnalysis?: QuotationAnalysis } = {}) {
constructor(args: { project?: Partial<SFProjectProfile>; quotationAnalysis?: QuotationAnalysis } = {}) {
const userDoc = mock(UserDoc);
this.onlineStatusService = TestBed.inject(OnlineStatusService) as TestOnlineStatusService;
when(mockedDraftGenerationService.getLastCompletedBuild(anything())).thenReturn(
Expand All @@ -232,7 +304,7 @@ class TestEnvironment {
when(mockedNoticeService.show(anything())).thenResolve();
when(mockedDialogService.confirm(anything(), anything(), anything())).thenResolve(true);
when(mockedServalAdministration.onlineRetrievePreTranslationStatus(anything())).thenResolve();
this.setupProject(args.config);
this.setupProject(args.project);
this.fixture = TestBed.createComponent(DraftUsfmFormatComponent);
this.component = this.fixture.componentInstance;
const loader = TestbedHarnessEnvironment.loader(this.fixture);
Expand All @@ -257,7 +329,7 @@ class TestEnvironment {
return this.fixture.nativeElement.querySelector('.quote-format-warning');
}

setupProject(config?: DraftUsfmConfig): void {
setupProject(project?: Partial<SFProjectProfile>): void {
const texts: TextInfo[] = [
{
bookNum: 1,
Expand All @@ -283,7 +355,7 @@ class TestEnvironment {
];
const projectDoc = {
id: this.projectId,
data: createTestProjectProfile({ translateConfig: { draftConfig: { usfmConfig: config } }, texts })
data: createTestProjectProfile({ translateConfig: project?.translateConfig, texts: project?.texts ?? texts })
} as SFProjectProfileDoc;
when(mockedActivatedProjectService.projectId).thenReturn(this.projectId);
when(mockedActivatedProjectService.projectDoc$).thenReturn(of(projectDoc));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ActivatedRoute } from '@angular/router';
import { TranslocoModule } from '@ngneat/transloco';
import { Canon } from '@sillsdev/scripture';
import { Delta } from 'quill';
import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info';
import {
DraftUsfmConfig,
Expand Down Expand Up @@ -63,7 +64,7 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
bookNum: number = 1;
booksWithDrafts: number[] = [];
chapterNum: number = 1;
chapters: number[] = [];
chaptersWithDrafts: number[] = [];
isInitializing: boolean = true;
paragraphBreakFormat = ParagraphBreakFormat;
quoteStyle = QuoteFormat;
Expand Down Expand Up @@ -156,11 +157,11 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
defaultBook = Canon.bookIdToNumber(params['bookId']);
}
let defaultChapter = 1;
this.chapters = texts.find(t => t.bookNum === defaultBook)?.chapters.map(c => c.number) ?? [];
if (params['chapter'] !== undefined && this.chapters.includes(Number(params['chapter']))) {
this.chaptersWithDrafts = this.getChaptersWithDrafts(defaultBook, projectDoc.data);
if (params['chapter'] !== undefined && this.chaptersWithDrafts.includes(Number(params['chapter']))) {
defaultChapter = Number(params['chapter']);
} else if (this.chapters.length > 0) {
defaultChapter = this.chapters[0];
} else if (this.chaptersWithDrafts.length > 0) {
defaultChapter = this.chaptersWithDrafts[0];
}
this.projectFont = this.fontService.getFontFamilyFromProject(projectDoc);
this.bookChanged(defaultBook, defaultChapter);
Expand Down Expand Up @@ -190,9 +191,8 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af

bookChanged(bookNum: number, chapterNum?: number): void {
this.bookNum = bookNum;
const texts = this.activatedProjectService.projectDoc!.data!.texts;
this.chapters = texts.find(t => t.bookNum === this.bookNum)?.chapters.map(c => c.number) ?? [];
this.chapterNum = chapterNum ?? this.chapters[0] ?? 1;
this.chaptersWithDrafts = this.getChaptersWithDrafts(bookNum, this.activatedProjectService.projectDoc!.data!);
this.chapterNum = chapterNum ?? this.chaptersWithDrafts[0] ?? 1;
this.reloadText();
}

Expand Down Expand Up @@ -258,4 +258,13 @@ export class DraftUsfmFormatComponent extends DataLoadingComponent implements Af
if (isOnline) this.reloadText();
});
}

private getChaptersWithDrafts(bookNum: number, project: SFProjectProfile): number[] {
return (
project.texts
.find(t => t.bookNum === bookNum)
?.chapters.filter(c => !!c.hasDraft && c.lastVerse > 0)
.map(c => c.number) ?? []
);
}
}
Loading
Loading