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 @@ -31,4 +31,5 @@ export interface SFProjectUserConfig extends ProjectData {
editorTabsOpen: EditorTabPersistData[];
lynxInsightState: LynxInsightUserData;
selectedDraftTargetParatextId?: string;
showEditorTabsInSinglePane?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ export class SFProjectUserConfigService extends SFProjectDataService<SFProjectUs
},
selectedDraftTargetParatextId: {
bsonType: 'string'
},
showEditorTabsInSinglePane: {
bsonType: 'bool'
}
},
additionalProperties: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,11 @@ export class TabStateService<TGroupId extends string, T extends TabInfo<string>>

consolidatedTabs.push(...group.tabs);

// Order the tabs with the immovable tabs first
const orderedTabs = [...consolidatedTabs].sort((a, b) => Number(a.movable) - Number(b.movable));

// Clear tabs from all groups except 'into' group
group.setTabs(group.groupId === into ? consolidatedTabs : []);
group.setTabs(group.groupId === into ? orderedTabs : []);
});

// Remove tab from restore list if tab is removed from consolidated group
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
[(chapter)]="chapter"
[chapters]="chapters"
></app-book-chapter-chooser>
@if (showSourceTab || translatorSettingsEnabled) {
<div class="toolbar-separator" [ngClass]="{ 'hide-lt-sm': !translatorSettingsEnabled }">&nbsp;</div>
@if (canShowSourceTab) {
<div class="toolbar-separator">&nbsp;</div>
@if (showSourceTab) {
<button
mat-icon-button
Expand All @@ -26,18 +26,16 @@
<mat-icon>swap_horiz</mat-icon>
</button>
}
@if (translatorSettingsEnabled) {
<button
mat-icon-button
appBlurOnClick
type="button"
id="settings-btn"
(click)="openTranslatorSettings()"
[matTooltip]="t('configure_translator_settings')"
>
<mat-icon>settings</mat-icon>
</button>
}
<button
mat-icon-button
appBlurOnClick
type="button"
id="settings-btn"
(click)="openTranslatorSettings()"
[matTooltip]="t('configure_translator_settings')"
>
<mat-icon>settings</mat-icon>
</button>
}
@if (canShare) {
<div class="toolbar-separator">&nbsp;</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
{ provide: TabMenuService, useValue: EditorTabMenuService },
{ provide: PermissionsService, useMock: mockedPermissionsService },
{ provide: LynxWorkspaceService, useMock: mockedLynxWorkspaceService },
provideNoopAnimations()

Check warning on line 223 in src/SIL.XForge.Scripture/ClientApp/src/app/translate/editor/editor.component.spec.ts

View workflow job for this annotation

GitHub Actions / Lint and Prettier (22.13.0, 11.11.0, 11.10.0)

`provideNoopAnimations` is deprecated. 20.2 Use `animate.enter` or `animate.leave` instead. Intent to remove in v23
]
}));

Expand Down Expand Up @@ -382,6 +382,44 @@
expect(env.component.chapters.length).toEqual(50);
}));

describe('Show editor tabs in single pane setting', () => {
it('shows the source tab if showEditorTabsInSinglePane is undefined', fakeAsync(() => {
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };
const env = new TestEnvironment();
env.setCurrentUser('user01');
env.setupProject();
env.setProjectUserConfig({ showEditorTabsInSinglePane: undefined });
env.routeWithParams(navigationParams);
env.wait();
expect(env.component.showSourceTab).toBeTrue();
env.dispose();
}));

it('shows the source tab if showEditorTabsInSinglePane is false', fakeAsync(() => {
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };
const env = new TestEnvironment();
env.setCurrentUser('user01');
env.setupProject();
env.setProjectUserConfig({ showEditorTabsInSinglePane: false });
env.routeWithParams(navigationParams);
env.wait();
expect(env.component.showSourceTab).toBeTrue();
env.dispose();
}));

it('does not show the source tab if showEditorTabsInSinglePane is true', fakeAsync(() => {
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };
const env = new TestEnvironment();
env.setCurrentUser('user01');
env.setupProject();
env.setProjectUserConfig({ showEditorTabsInSinglePane: true });
env.routeWithParams(navigationParams);
env.wait();
expect(env.component.showSourceTab).toBeFalse();
env.dispose();
}));
});

describe('Translation Suggestions enabled', () => {
it('start with no previous selection', fakeAsync(() => {
const env = new TestEnvironment();
Expand Down Expand Up @@ -3585,136 +3623,46 @@
});

describe('Translator settings enabled/disabled', () => {
it('shows translator settings when translation suggestions are enabled but lynx features are disabled', fakeAsync(() => {
const projectConfig = {
translateConfig: { ...defaultTranslateConfig, translationSuggestionsEnabled: true },
lynxConfig: {
autoCorrectionsEnabled: false,
assessmentsEnabled: false
}
};
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
env.setupProject(projectConfig);
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.translatorSettingsButton).toBeTruthy();
env.dispose();
}));

it('hides translator settings when suggestions are enabled for the project but user cant edit', fakeAsync(() => {
const projectConfig = {
translateConfig: { ...defaultTranslateConfig, translationSuggestionsEnabled: true }
};
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
env.setCurrentUser('user06'); //has read but not edit
env.setupProject(projectConfig);
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.translatorSettingsButton).toBeFalsy();
env.dispose();
}));

it('hides translator settings when both translation suggestions and lynx features are disabled', fakeAsync(() => {
const projectConfig = {
translateConfig: { ...defaultTranslateConfig, translationSuggestionsEnabled: false },
lynxConfig: {
autoCorrectionsEnabled: false,
assessmentsEnabled: false
}
};
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
env.setupProject(projectConfig);
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.translatorSettingsButton).toBeFalsy();
env.dispose();
}));

it('hides translator settings when lynx features are enabled but user cant edit', fakeAsync(() => {
const projectConfig = {
translateConfig: { ...defaultTranslateConfig, translationSuggestionsEnabled: false },
lynxConfig: {
autoCorrectionsEnabled: true,
assessmentsEnabled: true
}
};
it('shows translator settings when the user has a paratext role', fakeAsync(() => {
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
env.setCurrentUser('user06'); //has read but not edit
env.setupProject(projectConfig);
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.translatorSettingsButton).toBeFalsy();
env.dispose();
}));

it('shows translator settings when suggestions are disabled but lynx features are enabled', fakeAsync(() => {
const projectConfig = {
translateConfig: { ...defaultTranslateConfig, translationSuggestionsEnabled: false },
lynxConfig: {
autoCorrectionsEnabled: true,
assessmentsEnabled: false
}
};
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
env.setupProject(projectConfig);
env.setCurrentUser('user06'); // Paratext Observer
env.setupProject();
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.component.showSourceTab).toBeTrue();
expect(env.translatorSettingsButton).toBeTruthy();
env.dispose();
}));

it('shows translator settings when both suggestions and lynx features are enabled', fakeAsync(() => {
const projectConfig = {
translateConfig: { ...defaultTranslateConfig, translationSuggestionsEnabled: true },
lynxConfig: {
autoCorrectionsEnabled: true,
assessmentsEnabled: true
}
};
it('shows translator settings when the user does not have a paratext role but the project has a source', fakeAsync(() => {
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
env.setupProject(projectConfig);
env.setCurrentUser('user05'); // SF Commenter
env.setupProject();
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.component.showSourceTab).toBeTrue();
expect(env.translatorSettingsButton).toBeTruthy();
env.dispose();
}));

it('shows translator settings when lynx features are enabled but no source access', fakeAsync(() => {
const projectConfig = {
translateConfig: { translationSuggestionsEnabled: false },
lynxConfig: {
autoCorrectionsEnabled: true,
assessmentsEnabled: false
}
};
it('hides translator settings when the user does not have a paratext role and there is no source', fakeAsync(() => {
const navigationParams: Params = { projectId: 'project01', bookId: 'MRK' };

const env = new TestEnvironment();
// Remove source from project to simulate no source access
delete env.testProjectProfile.translateConfig.source;
env.setupProject(projectConfig);
env.setCurrentUser('user05'); // SF Commenter
env.setupProject();
env.setProjectUserConfig();
env.routeWithParams(navigationParams);
env.wait();
expect(env.translatorSettingsButton).toBeTruthy();
expect(env.component.showSourceTab).toBeFalse();
expect(env.translatorSettingsButton).toBeFalsy();
env.dispose();
}));

Expand Down Expand Up @@ -4205,6 +4153,41 @@
expect(tabs.find(t => t.projectId === absentProjectId)).toBeUndefined();
env.dispose();
}));

it('should not add a resource tab if it matches the source', fakeAsync(() => {
const env = new TestEnvironment();
env.setProjectUserConfig({
editorTabsOpen: [{ tabType: 'project-resource', groupId: 'source', projectId: 'project02' }]
});
const spyCreateTab = spyOn(env.tabFactory, 'createTab').and.callThrough();
env.wait();
expect(spyCreateTab).not.toHaveBeenCalledWith('project-resource', jasmine.any(Object));
discardPeriodicTasks();
}));

it('should add a resource tab if it does not match the source', fakeAsync(() => {
const env = new TestEnvironment();
env.setupProject({
translateConfig: {
source: {
paratextId: 'resource01',
name: 'Resource 1',
shortName: 'SRC',
projectRef: 'resource01',
writingSystem: {
tag: 'qaa'
}
}
}
});
env.setProjectUserConfig({
editorTabsOpen: [{ tabType: 'project-resource', groupId: 'source', projectId: 'project02' }]
});
const spyCreateTab = spyOn(env.tabFactory, 'createTab').and.callThrough();
env.wait();
expect(spyCreateTab).toHaveBeenCalledWith('project-resource', jasmine.any(Object));
discardPeriodicTasks();
}));
});

describe('updateDraftTabVisibility', () => {
Expand Down
Loading
Loading