diff --git a/.grit/patterns/xforge_common_absolute_only.md b/.grit/patterns/xforge_common_absolute_only.md
index f84f3bb391f..5694efc4d60 100644
--- a/.grit/patterns/xforge_common_absolute_only.md
+++ b/.grit/patterns/xforge_common_absolute_only.md
@@ -18,9 +18,9 @@ language js
## Basic example
```ts
-import { UICommonModule } from "../../xforge-common/ui-common.module";
+import { UserService } from "../../xforge-common/user.service";
```
```ts
-import { UICommonModule } from "xforge-common/ui-common.module";
+import { UserService } from "xforge-common/user.service";
```
diff --git a/src/SIL.XForge.Scripture/ClientApp/.storybook/preview.ts b/src/SIL.XForge.Scripture/ClientApp/.storybook/preview.ts
index f8072e27ff4..0ac1f7d3d61 100644
--- a/src/SIL.XForge.Scripture/ClientApp/.storybook/preview.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/.storybook/preview.ts
@@ -1,15 +1,16 @@
import { OverlayContainer } from '@angular/cdk/overlay';
-import { importProvidersFrom } from '@angular/core';
import { getTestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
import { provideAnimations } from '@angular/platform-browser/animations';
import { setCompodocJson } from '@storybook/addon-docs/angular';
import { applicationConfig } from '@storybook/angular';
-import docJson from '../documentation.json';
-import { I18nStoryDecorator, I18nStoryModule } from 'xforge-common/i18n-story.module';
+import { I18nStoryDecorator, provideI18nStory } from 'xforge-common/i18n-story';
import { I18nService } from 'xforge-common/i18n.service';
import { APP_ROOT_ELEMENT_SELECTOR, InAppRootOverlayContainer } from 'xforge-common/overlay-container';
+import { provideUICommon } from 'xforge-common/ui-common-providers';
import { getI18nLocales } from 'xforge-common/utils';
+import docJson from '../documentation.json';
+import { provideSFTabs } from '../src/app/shared/sf-tab-group';
setCompodocJson(docJson);
@@ -42,8 +43,10 @@ export const decorators = [
I18nStoryDecorator,
applicationConfig({
providers: [
- importProvidersFrom(I18nStoryModule),
+ provideI18nStory(),
provideAnimations(),
+ provideUICommon(),
+ provideSFTabs(),
{ provide: APP_ROOT_ELEMENT_SELECTOR, useValue: 'storybook-root' },
{ provide: OverlayContainer, useClass: InAppRootOverlayContainer }
]
diff --git a/src/SIL.XForge.Scripture/ClientApp/.storybook/util/mat-dialog-launch.ts b/src/SIL.XForge.Scripture/ClientApp/.storybook/util/mat-dialog-launch.ts
index adfdb76102b..fb63c157839 100644
--- a/src/SIL.XForge.Scripture/ClientApp/.storybook/util/mat-dialog-launch.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/.storybook/util/mat-dialog-launch.ts
@@ -1,9 +1,7 @@
-import { CommonModule } from '@angular/common';
import { Component, Inject, InjectionToken, Injector, OnInit, Provider } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
+import { MAT_DIALOG_DATA, MatDialog, MatDialogModule } from '@angular/material/dialog';
import { TranslocoModule } from '@ngneat/transloco';
import { StoryFn } from '@storybook/angular';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { hasProp } from '../../src/type-utils';
export function getOverlays(element: HTMLElement): HTMLElement[] {
@@ -25,7 +23,6 @@ export interface MatDialogStoryConfig {
imports?: any[];
declarations?: any[];
providers?: Provider[];
- standaloneComponent?: boolean;
}
@Component({ template: '' })
@@ -57,8 +54,8 @@ export class MatDialogLaunchComponent implements OnInit {
export function matDialogStory(component: any, config?: MatDialogStoryConfig): StoryFn {
const story: StoryFn = args => ({
moduleMetadata: {
- imports: [UICommonModule, CommonModule, TranslocoModule, ...(config?.imports ?? [])],
- declarations: [...(config?.standaloneComponent ? [] : [component]), ...(config?.declarations ?? [])],
+ imports: [MatDialogModule, TranslocoModule, component, ...(config?.imports ?? [])],
+ declarations: [...(config?.declarations ?? [])],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: args.data },
{ provide: COMPONENT_UNDER_TEST, useValue: component },
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/app-routing.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/app-routing.module.ts
deleted file mode 100644
index 8fa7b160df4..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/app-routing.module.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-import { AuthGuard } from 'xforge-common/auth.guard';
-import { SystemAdminAuthGuard } from 'xforge-common/system-admin-auth.guard';
-import { SystemAdministrationComponent } from 'xforge-common/system-administration/system-administration.component';
-import { ConnectProjectComponent } from './connect-project/connect-project.component';
-import { EventMetricsAuthGuard } from './event-metrics/event-metrics-auth.guard';
-import { EventMetricsComponent } from './event-metrics/event-metrics.component';
-import { JoinComponent } from './join/join.component';
-import { MyProjectsComponent } from './my-projects/my-projects.component';
-import { PermissionsViewerComponent } from './permissions-viewer/permissions-viewer.component';
-import { ProjectComponent } from './project/project.component';
-import { ServalAdminAuthGuard } from './serval-administration/serval-admin-auth.guard';
-import { ServalAdministrationComponent } from './serval-administration/serval-administration.component';
-import { ServalProjectComponent } from './serval-administration/serval-project.component';
-import { SettingsComponent } from './settings/settings.component';
-import { PageNotFoundComponent } from './shared/page-not-found/page-not-found.component';
-import { SettingsAuthGuard, SyncAuthGuard } from './shared/project-router.guard';
-import { SyncComponent } from './sync/sync.component';
-
-const routes: Routes = [
- { path: 'callback/auth0', component: MyProjectsComponent, canActivate: [AuthGuard] },
- { path: 'connect-project', component: ConnectProjectComponent, canActivate: [AuthGuard] },
- { path: 'login', redirectTo: 'projects', pathMatch: 'full' },
- { path: 'join/:shareKey', component: JoinComponent },
- { path: 'join/:shareKey/:locale', component: JoinComponent },
- { path: 'projects/:projectId/event-log', component: EventMetricsComponent, canActivate: [EventMetricsAuthGuard] },
- { path: 'projects/:projectId/settings', component: SettingsComponent, canActivate: [SettingsAuthGuard] },
- { path: 'projects/:projectId/sync', component: SyncComponent, canActivate: [SyncAuthGuard] },
- { path: 'projects/:projectId', component: ProjectComponent, canActivate: [AuthGuard] },
- { path: 'projects', component: MyProjectsComponent, canActivate: [AuthGuard] },
- { path: 'system-administration/permissions-viewer', component: PermissionsViewerComponent },
- { path: 'serval-administration/:projectId', component: ServalProjectComponent, canActivate: [ServalAdminAuthGuard] },
- { path: 'serval-administration', component: ServalAdministrationComponent, canActivate: [ServalAdminAuthGuard] },
- { path: 'system-administration', component: SystemAdministrationComponent, canActivate: [SystemAdminAuthGuard] },
- { path: '**', component: PageNotFoundComponent }
-];
-
-@NgModule({
- imports: [
- RouterModule.forRoot(routes, {
- // This setting was introduced to prevent canceling the "prompt on leave" dialog for pages like draft-usfm-format
- // from mangling the browser history (SF-3577).
- canceledNavigationResolution: 'computed'
- })
- ],
- exports: [RouterModule]
-})
-export class AppRoutingModule {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.spec.ts
index 46179a7be9e..713eedbcd4d 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.spec.ts
@@ -2,9 +2,12 @@ import { BreakpointObserver } from '@angular/cdk/layout';
import { Location } from '@angular/common';
import { Component, DebugElement, NgZone } from '@angular/core';
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
+import { MatIcon } from '@angular/material/icon';
+import { MatMenu } from '@angular/material/menu';
+import { MatTooltip } from '@angular/material/tooltip';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { Route, Router, RouterModule } from '@angular/router';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
+import { provideRouter, Route, Router } from '@angular/router';
import { CookieService } from 'ngx-cookie-service';
import { SystemRole } from 'realtime-server/lib/esm/common/models/system-role';
import { User } from 'realtime-server/lib/esm/common/models/user';
@@ -30,12 +33,11 @@ import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { PWA_BEFORE_PROMPT_CAN_BE_SHOWN_AGAIN, PwaService } from 'xforge-common/pwa.service';
import { TestBreakpointObserver } from 'xforge-common/test-breakpoint-observer';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { AppComponent } from './app.component';
import { SFProjectProfileDoc } from './core/models/sf-project-profile-doc';
@@ -65,8 +67,7 @@ const mockedErrorReportingService = mock(ErrorReportingService);
const mockedDialogService = mock(DialogService);
@Component({
- template: `
Mock
`,
- standalone: false
+ template: `Mock
`
})
class MockComponent {}
@@ -87,18 +88,20 @@ const ROUTES: Route[] = [
describe('AppComponent', () => {
configureTestingModule(() => ({
- declarations: [AppComponent, NavigationComponent],
imports: [
- UICommonModule,
- NoopAnimationsModule,
- RouterModule.forRoot(ROUTES),
- TestTranslocoModule,
- TestOnlineStatusModule.forRoot(),
- TestRealtimeModule.forRoot(SF_TYPE_REGISTRY),
+ AppComponent,
+ NavigationComponent,
+ getTestTranslocoModule(),
AvatarComponent,
- GlobalNoticesComponent
+ GlobalNoticesComponent,
+ MatMenu,
+ MatIcon,
+ MatTooltip
],
providers: [
+ provideRouter(ROUTES),
+ provideTestOnlineStatus(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: AuthService, useMock: mockedAuthService },
{ provide: UserService, useMock: mockedUserService },
{ provide: SettingsAuthGuard, useMock: mockedSettingsAuthGuard },
@@ -116,7 +119,8 @@ describe('AppComponent', () => {
{ provide: FileService, useMock: mockedFileService },
{ provide: ErrorReportingService, useMock: mockedErrorReportingService },
{ provide: BreakpointObserver, useClass: TestBreakpointObserver },
- { provide: DialogService, useMock: mockedDialogService }
+ { provide: DialogService, useMock: mockedDialogService },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.ts
index 8c03b2bedde..be249b1a954 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/app.component.ts
@@ -1,9 +1,20 @@
+import { BidiModule } from '@angular/cdk/bidi';
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
-import { DOCUMENT } from '@angular/common';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { AsyncPipe, DOCUMENT } from '@angular/common';
import { Component, DestroyRef, Inject, OnDestroy, OnInit } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
-import { NavigationEnd, Router } from '@angular/router';
+import { MatButton, MatIconAnchor, MatIconButton } from '@angular/material/button';
+import { MatDivider } from '@angular/material/divider';
+import { MatIcon } from '@angular/material/icon';
+import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
+import { MatProgressBar } from '@angular/material/progress-bar';
+import { MatDrawer, MatDrawerContainer } from '@angular/material/sidenav';
+import { MatToolbar, MatToolbarRow } from '@angular/material/toolbar';
+import { MatTooltip } from '@angular/material/tooltip';
+import { NavigationEnd, Router, RouterLink, RouterOutlet } from '@angular/router';
import Bugsnag from '@bugsnag/js';
+import { TranslocoModule } from '@ngneat/transloco';
import { cloneDeep } from 'lodash-es';
import { CookieService } from 'ngx-cookie-service';
import { SystemRole } from 'realtime-server/lib/esm/common/models/system-role';
@@ -13,6 +24,7 @@ import { Observable, Subscription } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { ActivatedProjectService } from 'xforge-common/activated-project.service';
import { AuthService } from 'xforge-common/auth.service';
+import { AvatarComponent } from 'xforge-common/avatar/avatar.component';
import { DataLoadingComponent } from 'xforge-common/data-loading-component';
import { DiagnosticOverlayService } from 'xforge-common/diagnostic-overlay.service';
import { DialogService } from 'xforge-common/dialog.service';
@@ -28,6 +40,7 @@ import { UserDoc } from 'xforge-common/models/user-doc';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { PWA_BEFORE_PROMPT_CAN_BE_SHOWN_AGAIN, PwaService } from 'xforge-common/pwa.service';
+import { RouterLinkDirective } from 'xforge-common/router-link.directive';
import {
BrowserIssue,
SupportedBrowsersDialogComponent
@@ -42,6 +55,8 @@ import { SFProjectProfileDoc } from './core/models/sf-project-profile-doc';
import { roleCanAccessTranslate } from './core/models/sf-project-role-info';
import { SFProjectUserConfigDoc } from './core/models/sf-project-user-config-doc';
import { SFProjectService } from './core/sf-project.service';
+import { NavigationComponent } from './navigation/navigation.component';
+import { GlobalNoticesComponent } from './shared/global-notices/global-notices.component';
import { checkAppAccess } from './shared/utils';
declare function gtag(...args: any): void;
@@ -50,7 +65,33 @@ declare function gtag(...args: any): void;
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
- standalone: false
+ imports: [
+ AsyncPipe,
+ TranslocoModule,
+ RouterLink,
+ AvatarComponent,
+ RouterLinkDirective,
+ NavigationComponent,
+ GlobalNoticesComponent,
+ RouterOutlet,
+ MatIcon,
+ MatDrawerContainer,
+ MatButton,
+ MatIconAnchor,
+ MatIconButton,
+ MatMenu,
+ MatMenuItem,
+ MatMenuTrigger,
+ MatTooltip,
+ MatToolbar,
+ MatToolbarRow,
+ MatProgressBar,
+ MatDivider,
+ MatDrawer,
+ MatDrawerContainer,
+ CdkScrollable,
+ BidiModule
+ ]
})
export class AppComponent extends DataLoadingComponent implements OnInit, OnDestroy {
version: string = versionData.version;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/app.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/app.module.ts
deleted file mode 100644
index 754f9705121..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/app.module.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { OverlayContainer } from '@angular/cdk/overlay';
-import { DatePipe } from '@angular/common';
-import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
-import { APP_ID, ErrorHandler, inject, NgModule, provideAppInitializer } from '@angular/core';
-import { MatRipple } from '@angular/material/core';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { ServiceWorkerModule } from '@angular/service-worker';
-import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
-import { CookieService } from 'ngx-cookie-service';
-import { QuillModule } from 'ngx-quill';
-import {
- defaultTranslocoMarkupTranspilers,
- provideTranslationMarkupTranspiler,
- TranslocoMarkupModule
-} from 'ngx-transloco-markup';
-import { translocoMarkupRouterLinkRenderer } from 'ngx-transloco-markup-router-link';
-import { AvatarComponent } from 'xforge-common/avatar/avatar.component';
-import { EditNameDialogComponent } from 'xforge-common/edit-name-dialog/edit-name-dialog.component';
-import { ErrorDialogComponent } from 'xforge-common/error-dialog/error-dialog.component';
-import { ExceptionHandlingService } from 'xforge-common/exception-handling.service';
-import { FeatureFlagsDialogComponent } from 'xforge-common/feature-flags/feature-flags-dialog.component';
-import { EmTextTranspiler } from 'xforge-common/i18n-transpilers/em-text.transpiler';
-import { InAppRootOverlayContainer } from 'xforge-common/overlay-container';
-import { SupportedBrowsersDialogComponent } from 'xforge-common/supported-browsers-dialog/supported-browsers-dialog.component';
-import { UICommonModule } from 'xforge-common/ui-common.module';
-import { WriteStatusComponent } from 'xforge-common/write-status/write-status.component';
-import { XForgeCommonModule } from 'xforge-common/xforge-common.module';
-import { environment } from '../environments/environment';
-import { AppRoutingModule } from './app-routing.module';
-import { AppComponent } from './app.component';
-import { CheckingModule } from './checking/checking.module';
-import { ConnectProjectComponent } from './connect-project/connect-project.component';
-import { CoreModule } from './core/core.module';
-import { JoinComponent } from './join/join.component';
-import { MyProjectsComponent } from './my-projects/my-projects.component';
-import { NavigationComponent } from './navigation/navigation.component';
-import { ProjectComponent } from './project/project.component';
-import { ScriptureChooserDialogComponent } from './scripture-chooser-dialog/scripture-chooser-dialog.component';
-import { DeleteProjectDialogComponent } from './settings/delete-project-dialog/delete-project-dialog.component';
-import { SettingsComponent } from './settings/settings.component';
-import { GlobalNoticesComponent } from './shared/global-notices/global-notices.component';
-import { SharedModule } from './shared/shared.module';
-import { TextNoteDialogComponent } from './shared/text/text-note-dialog/text-note-dialog.component';
-import { preloadEnglishTranslations } from './shared/utils';
-import { SyncComponent } from './sync/sync.component';
-import { LynxInsightsModule } from './translate/editor/lynx/insights/lynx-insights.module';
-import { TranslateModule } from './translate/translate.module';
-import { UsersModule } from './users/users.module';
-
-@NgModule({
- declarations: [
- AppComponent,
- NavigationComponent,
- ConnectProjectComponent,
- DeleteProjectDialogComponent,
- ProjectComponent,
- SettingsComponent,
- MyProjectsComponent,
- SyncComponent,
- ScriptureChooserDialogComponent,
- SupportedBrowsersDialogComponent,
- ErrorDialogComponent,
- EditNameDialogComponent,
- FeatureFlagsDialogComponent,
- TextNoteDialogComponent,
- JoinComponent
- ],
- bootstrap: [AppComponent],
- imports: [
- BrowserAnimationsModule,
- CoreModule,
- ServiceWorkerModule.register('sf-service-worker.js', {
- enabled: environment.pwaTest || environment.production,
- registrationStrategy: 'registerImmediately'
- }),
- TranslateModule,
- CheckingModule,
- UsersModule,
- UICommonModule.forRoot(),
- XForgeCommonModule,
- TranslocoModule,
- TranslocoMarkupModule,
- AppRoutingModule,
- SharedModule.forRoot(),
- AvatarComponent,
- MatRipple,
- GlobalNoticesComponent,
- QuillModule.forRoot(),
- LynxInsightsModule.forRoot(),
- WriteStatusComponent
- ],
- providers: [
- { provide: APP_ID, useValue: 'ng-cli-universal' },
- CookieService,
- DatePipe,
- provideTranslationMarkupTranspiler(EmTextTranspiler),
- translocoMarkupRouterLinkRenderer(),
- defaultTranslocoMarkupTranspilers(),
- { provide: ErrorHandler, useClass: ExceptionHandlingService },
- { provide: OverlayContainer, useClass: InAppRootOverlayContainer },
- provideHttpClient(withInterceptorsFromDi()),
- provideAppInitializer(() => {
- const initializerFn = preloadEnglishTranslations(inject(TranslocoService));
- return initializerFn();
- })
- ]
-})
-export class AppModule {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/app.routes.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/app.routes.ts
new file mode 100644
index 00000000000..2fef5e85b6a
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/app.routes.ts
@@ -0,0 +1,96 @@
+import { Routes } from '@angular/router';
+import { AuthGuard } from 'xforge-common/auth.guard';
+import { SystemAdminAuthGuard } from 'xforge-common/system-admin-auth.guard';
+import { SystemAdministrationComponent } from 'xforge-common/system-administration/system-administration.component';
+import { CheckingOverviewComponent } from './checking/checking-overview/checking-overview.component';
+import { CheckingComponent } from './checking/checking/checking.component';
+import { ConnectProjectComponent } from './connect-project/connect-project.component';
+import { EventMetricsAuthGuard } from './event-metrics/event-metrics-auth.guard';
+import { EventMetricsComponent } from './event-metrics/event-metrics.component';
+import { JoinComponent } from './join/join.component';
+import { MyProjectsComponent } from './my-projects/my-projects.component';
+import { PermissionsViewerComponent } from './permissions-viewer/permissions-viewer.component';
+import { ProjectComponent } from './project/project.component';
+import { ServalAdminAuthGuard } from './serval-administration/serval-admin-auth.guard';
+import { ServalAdministrationComponent } from './serval-administration/serval-administration.component';
+import { ServalProjectComponent } from './serval-administration/serval-project.component';
+import { SettingsComponent } from './settings/settings.component';
+import { PageNotFoundComponent } from './shared/page-not-found/page-not-found.component';
+import {
+ CheckingAuthGuard,
+ DraftNavigationAuthGuard,
+ NmtDraftAuthGuard,
+ SettingsAuthGuard,
+ SyncAuthGuard,
+ TranslateAuthGuard,
+ UsersAuthGuard
+} from './shared/project-router.guard';
+import { SyncComponent } from './sync/sync.component';
+import { DraftGenerationComponent } from './translate/draft-generation/draft-generation.component';
+import { DraftSourcesComponent } from './translate/draft-generation/draft-sources/draft-sources.component';
+import { DraftUsfmFormatComponent } from './translate/draft-generation/draft-usfm-format/draft-usfm-format.component';
+import { EditorComponent } from './translate/editor/editor.component';
+import { TranslateOverviewComponent } from './translate/translate-overview/translate-overview.component';
+import { UsersComponent } from './users/users.component';
+
+export const APP_ROUTES: Routes = [
+ { path: 'callback/auth0', component: MyProjectsComponent, canActivate: [AuthGuard] },
+ { path: 'connect-project', component: ConnectProjectComponent, canActivate: [AuthGuard] },
+ { path: 'login', redirectTo: 'projects', pathMatch: 'full' },
+ { path: 'join/:shareKey', component: JoinComponent },
+ { path: 'join/:shareKey/:locale', component: JoinComponent },
+ {
+ path: 'projects/:projectId/checking/:bookId/:chapter',
+ component: CheckingComponent,
+ canActivate: [CheckingAuthGuard]
+ },
+ { path: 'projects/:projectId/checking/:bookId', component: CheckingComponent, canActivate: [CheckingAuthGuard] },
+ { path: 'projects/:projectId/checking', component: CheckingOverviewComponent, canActivate: [CheckingAuthGuard] },
+ {
+ path: 'projects/:projectId/draft-generation/format/:bookId/:chapter',
+ component: DraftUsfmFormatComponent,
+ canActivate: [NmtDraftAuthGuard],
+ canDeactivate: [DraftNavigationAuthGuard]
+ },
+ {
+ path: 'projects/:projectId/draft-generation/format/:bookId',
+ component: DraftUsfmFormatComponent,
+ canActivate: [NmtDraftAuthGuard],
+ canDeactivate: [DraftNavigationAuthGuard]
+ },
+ {
+ path: 'projects/:projectId/draft-generation/format',
+ component: DraftUsfmFormatComponent,
+ canActivate: [NmtDraftAuthGuard],
+ canDeactivate: [DraftNavigationAuthGuard]
+ },
+ {
+ path: 'projects/:projectId/draft-generation/sources',
+ component: DraftSourcesComponent,
+ canActivate: [NmtDraftAuthGuard],
+ canDeactivate: [DraftNavigationAuthGuard]
+ },
+ {
+ path: 'projects/:projectId/draft-generation',
+ component: DraftGenerationComponent,
+ canActivate: [NmtDraftAuthGuard]
+ },
+ { path: 'projects/:projectId/event-log', component: EventMetricsComponent, canActivate: [EventMetricsAuthGuard] },
+ { path: 'projects/:projectId/settings', component: SettingsComponent, canActivate: [SettingsAuthGuard] },
+ { path: 'projects/:projectId/sync', component: SyncComponent, canActivate: [SyncAuthGuard] },
+ {
+ path: 'projects/:projectId/translate/:bookId/:chapter',
+ component: EditorComponent,
+ canActivate: [TranslateAuthGuard]
+ },
+ { path: 'projects/:projectId/translate/:bookId', component: EditorComponent, canActivate: [TranslateAuthGuard] },
+ { path: 'projects/:projectId/translate', component: TranslateOverviewComponent, canActivate: [TranslateAuthGuard] },
+ { path: 'projects/:projectId/users', component: UsersComponent, canActivate: [UsersAuthGuard] },
+ { path: 'projects/:projectId', component: ProjectComponent, canActivate: [AuthGuard] },
+ { path: 'projects', component: MyProjectsComponent, canActivate: [AuthGuard] },
+ { path: 'system-administration/permissions-viewer', component: PermissionsViewerComponent },
+ { path: 'serval-administration/:projectId', component: ServalProjectComponent, canActivate: [ServalAdminAuthGuard] },
+ { path: 'serval-administration', component: ServalAdministrationComponent, canActivate: [ServalAdminAuthGuard] },
+ { path: 'system-administration', component: SystemAdministrationComponent, canActivate: [SystemAdminAuthGuard] },
+ { path: '**', component: PageNotFoundComponent }
+];
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.spec.ts
index 69ad2fea4ff..6a7e1bc0ccb 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.spec.ts
@@ -7,11 +7,10 @@ import { InvalidFileItem } from 'angular-file/file-upload/fileTools';
import { of } from 'rxjs';
import { anything, instance, mock, verify, when } from 'ts-mockito';
import { DialogService } from 'xforge-common/dialog.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
-import { configureTestingModule, getAudioBlob, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
+import { configureTestingModule, getAudioBlob, getTestTranslocoModule } from 'xforge-common/test-utils';
import { AudioRecorderDialogComponent } from '../../shared/audio-recorder-dialog/audio-recorder-dialog.component';
-import { SharedModule } from '../../shared/shared.module';
+import { provideQuillRegistrations } from '../../shared/text/quill-editor-registration/quill-providers';
import { TextAndAudioComponent } from '../text-and-audio/text-and-audio.component';
import { AttachAudioComponent } from './attach-audio.component';
@@ -21,9 +20,12 @@ describe('AttachAudioComponent', () => {
let env: TestEnvironment;
configureTestingModule(() => ({
- imports: [UICommonModule, ngfModule, SharedModule.forRoot(), TestTranslocoModule, TestOnlineStatusModule.forRoot()],
- declarations: [AttachAudioComponent],
- providers: [{ provide: DialogService, useMock: mockDialogService }]
+ imports: [AttachAudioComponent, ngfModule, getTestTranslocoModule()],
+ providers: [
+ provideQuillRegistrations(),
+ provideTestOnlineStatus(),
+ { provide: DialogService, useMock: mockDialogService }
+ ]
}));
beforeEach(async () => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.ts
index 949fddeee21..99c005b2b33 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/attach-audio/attach-audio.component.ts
@@ -1,5 +1,11 @@
+import { NgClass } from '@angular/common';
import { Component, Input, ViewChild } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
import { MatDialogRef } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
+import { ngfModule } from 'angular-file';
import { InvalidFileItem } from 'angular-file/file-upload/fileTools';
import { firstValueFrom } from 'rxjs';
import { DialogService } from 'xforge-common/dialog.service';
@@ -16,7 +22,7 @@ import { TextAndAudioComponent } from '../text-and-audio/text-and-audio.componen
selector: 'app-attach-audio',
templateUrl: './attach-audio.component.html',
styleUrl: './attach-audio.component.scss',
- standalone: false
+ imports: [TranslocoModule, NgClass, MatIconButton, MatTooltip, MatIcon, ngfModule, SingleButtonAudioPlayerComponent]
})
export class AttachAudioComponent {
@ViewChild(SingleButtonAudioPlayerComponent) audioPlayer?: SingleButtonAudioPlayerComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.spec.ts
index 870a4428824..1a687cf08b2 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.spec.ts
@@ -1,8 +1,8 @@
import { OverlayContainer } from '@angular/cdk/overlay';
-import { DebugElement, NgModule, NgZone } from '@angular/core';
+import { DebugElement, NgZone } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { Canon } from '@sillsdev/scripture';
import { ngfModule } from 'angular-file';
import { getTextAudioId, TextAudio } from 'realtime-server/lib/esm/scriptureforge/models/text-audio';
@@ -14,21 +14,21 @@ import { CsvService } from 'xforge-common/csv-service.service';
import { FileService } from 'xforge-common/file.service';
import { FileOfflineData, FileType } from 'xforge-common/models/file-offline-data';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import {
ChildViewContainerComponent,
configureTestingModule,
getAudioBlob,
- getShortAudioBlob
+ getShortAudioBlob,
+ getTestTranslocoModule
} from 'xforge-common/test-utils';
import { QuestionDoc } from '../../core/models/question-doc';
import { SF_TYPE_REGISTRY } from '../../core/models/sf-type-registry';
import { TextAudioDoc } from '../../core/models/text-audio-doc';
import { TextsByBookId } from '../../core/models/texts-by-book-id';
-import { CheckingModule } from '../checking.module';
import { AudioAttachment } from '../checking/checking-audio-player/checking-audio-player.component';
import {
ChapterAudioDialogComponent,
@@ -41,11 +41,14 @@ const mockedFileService = mock(FileService);
describe('ChapterAudioDialogComponent', () => {
configureTestingModule(() => ({
- imports: [DialogTestModule, TestOnlineStatusModule.forRoot(), TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
+ imports: [ngfModule, ChapterAudioDialogComponent, getTestTranslocoModule()],
providers: [
+ provideTestOnlineStatus(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: CsvService, useMock: mockedCsvService },
{ provide: FileService, useMock: mockedFileService },
- { provide: OnlineStatusService, useClass: TestOnlineStatusService }
+ { provide: OnlineStatusService, useClass: TestOnlineStatusService },
+ provideNoopAnimations()
]
}));
@@ -599,11 +602,6 @@ describe('ChapterAudioDialogComponent', () => {
});
});
-@NgModule({
- imports: [NoopAnimationsModule, ngfModule, CheckingModule]
-})
-class DialogTestModule {}
-
class TestEnvironment {
static genesisText: TextInfo = {
bookNum: 1,
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.ts
index 7209fa5efd9..a340e61d7df 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/chapter-audio-dialog/chapter-audio-dialog.component.ts
@@ -1,5 +1,19 @@
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { NgClass } from '@angular/common';
import { AfterViewInit, Component, DestroyRef, ElementRef, Inject, OnDestroy, ViewChild } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { MatAnchor, MatButton } from '@angular/material/button';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogContent,
+ MatDialogRef,
+ MatDialogTitle
+} from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
import { Canon } from '@sillsdev/scripture';
import { cloneDeep, reject } from 'lodash-es';
import { Chapter, TextInfo } from 'realtime-server//lib/esm/scriptureforge/models/text-info';
@@ -21,7 +35,9 @@ import { TextAudioDoc } from '../../core/models/text-audio-doc';
import { TextDocId } from '../../core/models/text-doc';
import { TextsByBookId } from '../../core/models/texts-by-book-id';
import { SFProjectService } from '../../core/sf-project.service';
+import { NoticeComponent } from '../../shared/notice/notice.component';
import { AudioAttachment } from '../checking/checking-audio-player/checking-audio-player.component';
+import { CheckingScriptureAudioPlayerComponent } from '../checking/checking-scripture-audio-player/checking-scripture-audio-player.component';
import { SingleButtonAudioPlayerComponent } from '../checking/single-button-audio-player/single-button-audio-player.component';
const TIMING_FILE_EXTENSION_REGEX = /.(tsv|csv|txt)$/i;
@@ -45,7 +61,23 @@ export interface ChapterAudioDialogResult {
selector: 'app-chapter-audio-dialog',
templateUrl: './chapter-audio-dialog.component.html',
styleUrls: ['./chapter-audio-dialog.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ MatDialogTitle,
+ CdkScrollable,
+ MatDialogContent,
+ MatTooltip,
+ MatButton,
+ NgClass,
+ SingleButtonAudioPlayerComponent,
+ MatIcon,
+ CheckingScriptureAudioPlayerComponent,
+ NoticeComponent,
+ MatDialogActions,
+ MatAnchor,
+ MatDialogClose,
+ MatProgressSpinner
+ ]
})
export class ChapterAudioDialogComponent implements AfterViewInit, OnDestroy {
@ViewChild('dropzone') dropzone!: ElementRef;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.spec.ts
index fe0dfe40144..edd4e65d601 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.spec.ts
@@ -1,9 +1,9 @@
import { Location } from '@angular/common';
-import { DebugElement, NgModule, NgZone } from '@angular/core';
+import { DebugElement, NgZone } from '@angular/core';
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { MatExpansionPanel } from '@angular/material/expansion';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { ActivatedRoute } from '@angular/router';
import { ngfModule } from 'angular-file';
import { saveAs } from 'file-saver';
@@ -32,11 +32,11 @@ import { DialogService } from 'xforge-common/dialog.service';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { noopDestroyRef } from 'xforge-common/realtime.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule } from 'xforge-common/test-utils';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { QuestionDoc } from '../../core/models/question-doc';
import { SFProjectProfileDoc } from '../../core/models/sf-project-profile-doc';
@@ -45,7 +45,6 @@ import { SF_TYPE_REGISTRY } from '../../core/models/sf-type-registry';
import { TextDocId } from '../../core/models/text-doc';
import { SFProjectService } from '../../core/sf-project.service';
import { ChapterAudioDialogService } from '../chapter-audio-dialog/chapter-audio-dialog.service';
-import { CheckingModule } from '../checking.module';
import { CheckingQuestionsService } from '../checking/checking-questions.service';
import { ImportQuestionsDialogComponent } from '../import-questions-dialog/import-questions-dialog.component';
import { QuestionDialogService } from '../question-dialog/question-dialog.service';
@@ -62,8 +61,10 @@ const mockedChapterAudioDialogService = mock(ChapterAudioDialogService);
describe('CheckingOverviewComponent', () => {
configureTestingModule(() => ({
- imports: [DialogTestModule, TestOnlineStatusModule.forRoot(), TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
+ imports: [ngfModule, getTestTranslocoModule()],
providers: [
+ provideTestOnlineStatus(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: ActivatedRoute, useMock: mockedActivatedRoute },
{ provide: DialogService, useMock: mockedDialogService },
{ provide: NoticeService, useMock: mockedNoticeService },
@@ -72,7 +73,8 @@ describe('CheckingOverviewComponent', () => {
{ provide: UserService, useMock: mockedUserService },
{ provide: QuestionDialogService, useMock: mockedQuestionDialogService },
{ provide: OnlineStatusService, useClass: TestOnlineStatusService },
- { provide: ChapterAudioDialogService, useMock: mockedChapterAudioDialogService }
+ { provide: ChapterAudioDialogService, useMock: mockedChapterAudioDialogService },
+ provideNoopAnimations()
]
}));
@@ -665,11 +667,6 @@ describe('CheckingOverviewComponent', () => {
}));
});
-@NgModule({
- imports: [NoopAnimationsModule, ngfModule, CheckingModule]
-})
-class DialogTestModule {}
-
interface UserInfo {
id: string;
user: User;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.ts
index 8b02647d816..47b67641472 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-overview/checking-overview.component.ts
@@ -1,5 +1,18 @@
+import { NgClass } from '@angular/common';
import { Component, DestroyRef, OnDestroy, OnInit } from '@angular/core';
+import { MatButton, MatIconButton, MatMiniFabButton } from '@angular/material/button';
+import { MatCard, MatCardContent } from '@angular/material/card';
+import {
+ MatExpansionPanel,
+ MatExpansionPanelContent,
+ MatExpansionPanelHeader,
+ MatExpansionPanelTitle
+} from '@angular/material/expansion';
+import { MatIcon } from '@angular/material/icon';
+import { MatList, MatListItem, MatSelectionList } from '@angular/material/list';
+import { MatTooltip } from '@angular/material/tooltip';
import { ActivatedRoute } from '@angular/router';
+import { TranslocoModule } from '@ngneat/transloco';
import { Canon } from '@sillsdev/scripture';
import { saveAs } from 'file-saver';
import Papa from 'papaparse';
@@ -11,11 +24,13 @@ import { asyncScheduler, merge, Subscription } from 'rxjs';
import { map, tap, throttleTime } from 'rxjs/operators';
import { DataLoadingComponent } from 'xforge-common/data-loading-component';
import { DialogService } from 'xforge-common/dialog.service';
+import { DonutChartComponent } from 'xforge-common/donut-chart/donut-chart.component';
import { I18nService } from 'xforge-common/i18n.service';
import { L10nNumberPipe } from 'xforge-common/l10n-number.pipe';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
+import { RouterLinkDirective } from 'xforge-common/router-link.directive';
import { UserService } from 'xforge-common/user.service';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { QuestionDoc } from '../../core/models/question-doc';
@@ -38,7 +53,27 @@ import { QuestionDialogService } from '../question-dialog/question-dialog.servic
selector: 'app-checking-overview',
templateUrl: './checking-overview.component.html',
styleUrls: ['./checking-overview.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ NgClass,
+ MatButton,
+ MatIcon,
+ MatMiniFabButton,
+ DonutChartComponent,
+ MatExpansionPanel,
+ MatExpansionPanelHeader,
+ MatExpansionPanelTitle,
+ MatIconButton,
+ MatTooltip,
+ MatExpansionPanelContent,
+ MatSelectionList,
+ MatListItem,
+ MatList,
+ RouterLinkDirective,
+ MatCard,
+ MatCardContent,
+ L10nNumberPipe
+ ]
})
export class CheckingOverviewComponent extends DataLoadingComponent implements OnInit, OnDestroy {
texts: TextInfo[] = [];
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-routing.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-routing.module.ts
deleted file mode 100644
index 03f03db09b9..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking-routing.module.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-
-import { CheckingAuthGuard } from '../shared/project-router.guard';
-import { CheckingOverviewComponent } from './checking-overview/checking-overview.component';
-import { CheckingComponent } from './checking/checking.component';
-
-const routes: Routes = [
- {
- path: 'projects/:projectId/checking/:bookId/:chapter',
- component: CheckingComponent,
- canActivate: [CheckingAuthGuard]
- },
- { path: 'projects/:projectId/checking/:bookId', component: CheckingComponent, canActivate: [CheckingAuthGuard] },
- { path: 'projects/:projectId/checking', component: CheckingOverviewComponent, canActivate: [CheckingAuthGuard] }
-];
-
-@NgModule({
- imports: [RouterModule.forChild(routes)],
- exports: [RouterModule]
-})
-export class CheckingRoutingModule {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking.module.ts
deleted file mode 100644
index adbbac70071..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking.module.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { TranslocoModule } from '@ngneat/transloco';
-import { ngfModule } from 'angular-file';
-import { AngularSplitModule } from 'angular-split';
-import { OwnerComponent } from 'xforge-common/owner/owner.component';
-import { UICommonModule } from 'xforge-common/ui-common.module';
-import { XForgeCommonModule } from 'xforge-common/xforge-common.module';
-import { AudioPlayerComponent } from '../shared/audio/audio-player/audio-player.component';
-import { AudioTimePipe } from '../shared/audio/audio-time-pipe';
-import { SharedModule } from '../shared/shared.module';
-import { TextChooserDialogComponent } from '../text-chooser-dialog/text-chooser-dialog.component';
-import { AttachAudioComponent } from './attach-audio/attach-audio.component';
-import { ChapterAudioDialogComponent } from './chapter-audio-dialog/chapter-audio-dialog.component';
-import { CheckingOverviewComponent } from './checking-overview/checking-overview.component';
-import { CheckingRoutingModule } from './checking-routing.module';
-import { CheckingAnswersComponent } from './checking/checking-answers/checking-answers.component';
-import { CheckingCommentsComponent } from './checking/checking-answers/checking-comments/checking-comments.component';
-import { CheckingInputFormComponent } from './checking/checking-answers/checking-input-form/checking-input-form.component';
-import { CheckingAudioPlayerComponent } from './checking/checking-audio-player/checking-audio-player.component';
-import { CheckingQuestionsComponent } from './checking/checking-questions/checking-questions.component';
-import { CheckingScriptureAudioPlayerComponent } from './checking/checking-scripture-audio-player/checking-scripture-audio-player.component';
-import { CheckingTextComponent } from './checking/checking-text/checking-text.component';
-import { CheckingComponent } from './checking/checking.component';
-import { FontSizeComponent } from './checking/font-size/font-size.component';
-import { ImportQuestionsConfirmationDialogComponent } from './import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component';
-import { ImportQuestionsDialogComponent } from './import-questions-dialog/import-questions-dialog.component';
-import { QuestionDialogComponent } from './question-dialog/question-dialog.component';
-import { TextAndAudioComponent } from './text-and-audio/text-and-audio.component';
-
-@NgModule({
- declarations: [
- CheckingComponent,
- CheckingOverviewComponent,
- CheckingQuestionsComponent,
- CheckingTextComponent,
- CheckingAnswersComponent,
- TextAndAudioComponent,
- AttachAudioComponent,
- QuestionDialogComponent,
- ImportQuestionsDialogComponent,
- ImportQuestionsConfirmationDialogComponent,
- FontSizeComponent,
- CheckingCommentsComponent,
- CheckingInputFormComponent,
- CheckingAudioPlayerComponent,
- AudioPlayerComponent,
- CheckingScriptureAudioPlayerComponent,
- AudioTimePipe,
- TextChooserDialogComponent,
- ChapterAudioDialogComponent
- ],
- imports: [
- CheckingRoutingModule,
- CommonModule,
- SharedModule,
- UICommonModule,
- XForgeCommonModule,
- OwnerComponent,
- AngularSplitModule,
- ngfModule,
- TranslocoModule
- ],
- exports: [CheckingAudioPlayerComponent]
-})
-export class CheckingModule {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-answers.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-answers.component.ts
index 39c26d6a879..779695ee4e0 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-answers.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-answers.component.ts
@@ -1,3 +1,5 @@
+import { Dir } from '@angular/cdk/bidi';
+import { NgClass } from '@angular/common';
import {
Component,
DestroyRef,
@@ -9,7 +11,11 @@ import {
ViewChild,
ViewChildren
} from '@angular/core';
+import { MatButton, MatIconButton } from '@angular/material/button';
import { MatDialogRef } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
import { VerseRef } from '@sillsdev/scripture';
import { cloneDeep } from 'lodash-es';
import { Operation } from 'realtime-server/lib/esm/common/models/project-rights';
@@ -25,6 +31,7 @@ import { I18nService } from 'xforge-common/i18n.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
+import { OwnerComponent } from 'xforge-common/owner/owner.component';
import { UserService } from 'xforge-common/user.service';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { QuestionDoc } from '../../../core/models/question-doc';
@@ -40,7 +47,10 @@ import {
import { CheckingUtils } from '../../checking.utils';
import { QuestionDialogData } from '../../question-dialog/question-dialog.component';
import { QuestionDialogService } from '../../question-dialog/question-dialog.service';
-import { AudioAttachment } from '../checking-audio-player/checking-audio-player.component';
+import {
+ AudioAttachment,
+ CheckingAudioPlayerComponent
+} from '../checking-audio-player/checking-audio-player.component';
import { CheckingTextComponent } from '../checking-text/checking-text.component';
import { CheckingCommentsComponent, CommentAction } from './checking-comments/checking-comments.component';
import { CheckingInput, CheckingInputFormComponent } from './checking-input-form/checking-input-form.component';
@@ -89,7 +99,20 @@ enum LikeAnswerResponse {
selector: 'app-checking-answers',
templateUrl: './checking-answers.component.html',
styleUrls: ['./checking-answers.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ CheckingQuestionComponent,
+ MatIconButton,
+ MatTooltip,
+ MatIcon,
+ MatButton,
+ CheckingInputFormComponent,
+ NgClass,
+ Dir,
+ CheckingAudioPlayerComponent,
+ OwnerComponent,
+ CheckingCommentsComponent
+ ]
})
export class CheckingAnswersComponent implements OnInit {
@ViewChild(CheckingInputFormComponent) answerInput?: CheckingInputFormComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.component.ts
index 88f5ded1bc7..a4e05b85791 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.component.ts
@@ -1,4 +1,9 @@
+import { NgClass } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+import { MatButton, MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
import { cloneDeep, sortBy } from 'lodash-es';
import { Operation } from 'realtime-server/lib/esm/common/models/project-rights';
import { Answer } from 'realtime-server/lib/esm/scriptureforge/models/answer';
@@ -8,11 +13,13 @@ import { SF_PROJECT_RIGHTS, SFProjectDomain } from 'realtime-server/lib/esm/scri
import { debounceTime } from 'rxjs/operators';
import { DialogService } from 'xforge-common/dialog.service';
import { I18nService } from 'xforge-common/i18n.service';
+import { OwnerComponent } from 'xforge-common/owner/owner.component';
import { SubscriptionDisposable } from 'xforge-common/subscription-disposable';
import { UserService } from 'xforge-common/user.service';
import { QuestionDoc } from '../../../../core/models/question-doc';
import { SFProjectUserConfigDoc } from '../../../../core/models/sf-project-user-config-doc';
import { AudioAttachment } from '../../checking-audio-player/checking-audio-player.component';
+import { SingleButtonAudioPlayerComponent } from '../../single-button-audio-player/single-button-audio-player.component';
import { CheckingInputFormComponent } from '../checking-input-form/checking-input-form.component';
export interface CommentAction {
@@ -27,7 +34,17 @@ export interface CommentAction {
selector: 'app-checking-comments',
templateUrl: './checking-comments.component.html',
styleUrls: ['./checking-comments.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ NgClass,
+ SingleButtonAudioPlayerComponent,
+ MatIcon,
+ MatIconButton,
+ MatTooltip,
+ OwnerComponent,
+ CheckingInputFormComponent,
+ MatButton
+ ]
})
export class CheckingCommentsComponent extends SubscriptionDisposable implements OnInit {
@ViewChild(CheckingInputFormComponent) inputComponent?: CheckingInputFormComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.stories.ts
index d7fa30b6fe3..cc633f27be0 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-comments/checking-comments.stories.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { expect, within } from '@storybook/test';
import { createTestUserProfile } from 'realtime-server/lib/esm/common/models/user-test-data';
@@ -6,10 +5,8 @@ import { Comment } from 'realtime-server/lib/esm/scriptureforge/models/comment';
import { createTestProject } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
import { instance, mock, when } from 'ts-mockito';
import { DialogService } from 'xforge-common/dialog.service';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
import { UserProfileDoc } from 'xforge-common/models/user-profile-doc';
import { OwnerComponent } from 'xforge-common/owner/owner.component';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { UserService } from 'xforge-common/user.service';
import { CheckingInputFormComponent } from '../checking-input-form/checking-input-form.component';
import { CheckingCommentsComponent } from './checking-comments.component';
@@ -49,12 +46,11 @@ const meta: Meta = {
component: CheckingCommentsComponent,
decorators: [
moduleMetadata({
- imports: [CommonModule, UICommonModule, I18nStoryModule, OwnerComponent],
+ imports: [OwnerComponent, CheckingInputFormComponent],
providers: [
{ provide: DialogService, useValue: instance(mockedDialogService) },
{ provide: UserService, useValue: instance(mockedUserService) }
- ],
- declarations: [CheckingInputFormComponent]
+ ]
})
],
args: defaultArgs
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.component.ts
index 7500ee4179e..658930968f0 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.component.ts
@@ -1,14 +1,22 @@
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
+import { NgClass } from '@angular/common';
import { Component, DestroyRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { MatButton, MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
import { Answer } from 'realtime-server/lib/esm/scriptureforge/models/answer';
import { Comment } from 'realtime-server/lib/esm/scriptureforge/models/comment';
import { SFProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
import { VerseRefData } from 'realtime-server/lib/esm/scriptureforge/models/verse-ref-data';
+import { AutofocusDirective } from 'xforge-common/autofocus.directive';
import { DialogService } from 'xforge-common/dialog.service';
import { FontService } from 'xforge-common/font.service';
import { I18nService } from 'xforge-common/i18n.service';
import { Breakpoint, MediaBreakpointService } from 'xforge-common/media-breakpoints/media-breakpoint.service';
import { NoticeService } from 'xforge-common/notice.service';
+import { ScrollIntoViewDirective } from 'xforge-common/scroll-into-view';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { QuestionDoc } from '../../../../core/models/question-doc';
import { TextsByBookId } from '../../../../core/models/texts-by-book-id';
@@ -17,6 +25,7 @@ import {
TextChooserDialogData,
TextSelection
} from '../../../../text-chooser-dialog/text-chooser-dialog.component';
+import { AttachAudioComponent } from '../../../attach-audio/attach-audio.component';
import { CheckingUtils } from '../../../checking.utils';
import { TextAndAudioComponent } from '../../../text-and-audio/text-and-audio.component';
import { AudioAttachment } from '../../checking-audio-player/checking-audio-player.component';
@@ -37,7 +46,19 @@ function isAnswer(value: Answer | Comment | undefined): value is Answer {
selector: 'app-checking-input-form',
templateUrl: './checking-input-form.component.html',
styleUrls: ['./checking-input-form.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ FormsModule,
+ ScrollIntoViewDirective,
+ TextAndAudioComponent,
+ AutofocusDirective,
+ NgClass,
+ AttachAudioComponent,
+ MatIconButton,
+ MatTooltip,
+ MatIcon,
+ MatButton
+ ]
})
export class CheckingInputFormComponent {
@Input() project?: SFProjectProfile;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.stories.ts
index a9046bda125..0490eee9e35 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-input-form/checking-input-form.stories.ts
@@ -1,9 +1,7 @@
-import { CommonModule } from '@angular/common';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { expect, userEvent, within } from '@storybook/test';
import { Answer } from 'realtime-server/lib/esm/scriptureforge/models/answer';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { AutofocusDirective } from 'xforge-common/autofocus.directive';
import { AttachAudioComponent } from '../../../attach-audio/attach-audio.component';
import { TextAndAudioComponent } from '../../../text-and-audio/text-and-audio.component';
import { CheckingInputFormComponent } from './checking-input-form.component';
@@ -13,8 +11,7 @@ const meta: Meta = {
component: CheckingInputFormComponent,
decorators: [
moduleMetadata({
- imports: [CommonModule, UICommonModule, I18nStoryModule],
- declarations: [TextAndAudioComponent, AttachAudioComponent]
+ imports: [AutofocusDirective, TextAndAudioComponent, AttachAudioComponent]
})
]
};
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.spec.ts
index b62bd3f7e69..a3b03a2433c 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.spec.ts
@@ -9,9 +9,8 @@ import { BehaviorSubject, lastValueFrom, Subject } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
import { anything, instance, mock, when } from 'ts-mockito';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { QuestionDoc } from '../../../../core/models/question-doc';
import { SFProjectUserConfigDoc } from '../../../../core/models/sf-project-user-config-doc';
import { TextAudioDoc } from '../../../../core/models/text-audio-doc';
@@ -33,7 +32,7 @@ const mockedSFProjectUserConfigDoc = mock(SFProjectUserConfigDoc);
[questionDoc]="questionDoc"
(audioPlayed)="played = true"
>`,
- standalone: false
+ imports: [CheckingQuestionComponent]
})
class MockComponent {
@ViewChild('question') question!: CheckingQuestionComponent;
@@ -60,9 +59,8 @@ class MockComponent {
describe('CheckingQuestionComponent', () => {
configureTestingModule(() => ({
- imports: [UICommonModule, TestTranslocoModule, TestOnlineStatusModule.forRoot()],
- declarations: [CheckingQuestionComponent, SingleButtonAudioPlayerComponent, MockComponent],
- providers: [{ provide: SFProjectService, useMock: mockedSFProjectService }]
+ imports: [CheckingQuestionComponent, SingleButtonAudioPlayerComponent, getTestTranslocoModule(), MockComponent],
+ providers: [provideTestOnlineStatus(), { provide: SFProjectService, useMock: mockedSFProjectService }]
}));
it('selects scripture text when scripture audio is present', async () => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts
index 925bc48045e..09cfbc63ebe 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.component.ts
@@ -9,6 +9,8 @@ import {
SimpleChanges,
ViewChild
} from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
+import { TranslocoModule } from '@ngneat/transloco';
import { VerseRef } from '@sillsdev/scripture';
import { AudioTiming } from 'realtime-server/lib/esm/scriptureforge/models/audio-timing';
import { getTextAudioId, TextAudio } from 'realtime-server/lib/esm/scriptureforge/models/text-audio';
@@ -31,7 +33,7 @@ import { SingleButtonAudioPlayerComponent } from '../../single-button-audio-play
selector: 'app-checking-question',
templateUrl: './checking-question.component.html',
styleUrls: ['./checking-question.component.scss'],
- standalone: false
+ imports: [TranslocoModule, SingleButtonAudioPlayerComponent, MatIcon]
})
export class CheckingQuestionComponent extends SubscriptionDisposable implements OnChanges, OnDestroy {
@Output() audioPlayed: EventEmitter = new EventEmitter();
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.stories.ts
index 7712de97405..4cf3c6bb3fb 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-answers/checking-question/checking-question.stories.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { expect } from '@storybook/test';
import { cloneDeep } from 'mingo/util';
@@ -10,10 +9,8 @@ import {
import { createTestProjectUserConfig } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-user-config-test-data';
import { getTextAudioId, TextAudio } from 'realtime-server/lib/esm/scriptureforge/models/text-audio';
import { anything, instance, mock, when } from 'ts-mockito';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { QuestionDoc } from '../../../../core/models/question-doc';
import { SFProjectUserConfigDoc } from '../../../../core/models/sf-project-user-config-doc';
import { SF_TYPE_REGISTRY } from '../../../../core/models/sf-type-registry';
@@ -68,9 +65,11 @@ const meta: Meta = {
component: CheckingQuestionComponent,
decorators: [
moduleMetadata({
- imports: [CommonModule, UICommonModule, I18nStoryModule, TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
- providers: [{ provide: SFProjectService, useValue: instance(mockedProjectService) }],
- declarations: [SingleButtonAudioPlayerComponent]
+ imports: [SingleButtonAudioPlayerComponent],
+ providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
+ { provide: SFProjectService, useValue: instance(mockedProjectService) }
+ ]
})
],
args: { questionDoc: instance(questionDoc) }
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player-new.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player-new.stories.ts
index 33f82ef7db4..b7677140576 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player-new.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player-new.stories.ts
@@ -1,11 +1,8 @@
-import { CommonModule } from '@angular/common';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { userEvent, within } from '@storybook/test';
import { of } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { AudioPlayerComponent } from '../../../shared/audio/audio-player/audio-player.component';
import { AudioTimePipe } from '../../../shared/audio/audio-time-pipe';
import { InfoComponent } from '../../../shared/info/info.component';
@@ -20,14 +17,8 @@ const meta: Meta = {
component: CheckingAudioPlayerComponent,
decorators: [
moduleMetadata({
- imports: [UICommonModule, CommonModule, I18nStoryModule],
- declarations: [CheckingAudioPlayerComponent, AudioPlayerComponent, AudioTimePipe, InfoComponent],
- providers: [
- {
- provide: OnlineStatusService,
- useValue: instance(mockedOnlineStatusService)
- }
- ]
+ imports: [CheckingAudioPlayerComponent, AudioPlayerComponent, AudioTimePipe, InfoComponent],
+ providers: [{ provide: OnlineStatusService, useValue: instance(mockedOnlineStatusService) }]
})
],
args: { source: './test-audio-player.webm' }
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.spec.ts
index 555a25c6d93..5c7286c9342 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.spec.ts
@@ -5,10 +5,9 @@ import { By } from '@angular/platform-browser';
import { lastValueFrom } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { getAudioBlob, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { getAudioBlob, getTestTranslocoModule } from 'xforge-common/test-utils';
import { AudioStatus } from '../../../shared/audio/audio-player';
import { AudioPlayerComponent } from '../../../shared/audio/audio-player/audio-player.component';
import { AudioTimePipe } from '../../../shared/audio/audio-time-pipe';
@@ -179,7 +178,7 @@ describe('CheckingAudioPlayerComponent', () => {
@Component({
selector: 'app-host',
template: '',
- standalone: false
+ imports: [CheckingAudioPlayerComponent]
})
class HostComponent {
@ViewChild(CheckingAudioPlayerComponent) player1!: CheckingAudioPlayerComponent;
@@ -195,9 +194,15 @@ class TestEnvironment {
constructor(template: string, isOnline = true) {
TestBed.configureTestingModule({
- declarations: [HostComponent, CheckingAudioPlayerComponent, AudioPlayerComponent, AudioTimePipe, InfoComponent],
- providers: [{ provide: OnlineStatusService, useClass: TestOnlineStatusService }],
- imports: [UICommonModule, TestOnlineStatusModule.forRoot(), TestTranslocoModule]
+ imports: [
+ getTestTranslocoModule(),
+ HostComponent,
+ CheckingAudioPlayerComponent,
+ AudioPlayerComponent,
+ AudioTimePipe,
+ InfoComponent
+ ],
+ providers: [{ provide: OnlineStatusService, useClass: TestOnlineStatusService }, provideTestOnlineStatus()]
});
TestBed.overrideComponent(HostComponent, { set: { template: template } });
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.ts
index 7d7fc61b0b9..16cafca0917 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-audio-player/checking-audio-player.component.ts
@@ -1,7 +1,12 @@
+import { Dir } from '@angular/cdk/bidi';
import { AfterViewInit, Component, DestroyRef, Input, ViewChild } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { TranslocoModule } from '@ngneat/transloco';
import { I18nService } from 'xforge-common/i18n.service';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { AudioPlayerComponent } from '../../../shared/audio/audio-player/audio-player.component';
+
export interface AudioAttachment {
status?: 'denied' | 'processed' | 'recording' | 'reset' | 'stopped' | 'uploaded';
url?: string;
@@ -13,7 +18,7 @@ export interface AudioAttachment {
selector: 'app-checking-audio-player',
templateUrl: './checking-audio-player.component.html',
styleUrls: ['./checking-audio-player.component.scss'],
- standalone: false
+ imports: [TranslocoModule, Dir, MatIconButton, MatIcon, AudioPlayerComponent]
})
export class CheckingAudioPlayerComponent implements AfterViewInit {
private _isAudioAvailable = false;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions.service.spec.ts
index b0803f0dd98..b08689940e1 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions.service.spec.ts
@@ -5,7 +5,7 @@ import { FileType } from 'xforge-common/models/file-offline-data';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
import { Snapshot } from 'xforge-common/models/snapshot';
import { noopDestroyRef } from 'xforge-common/realtime.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import { configureTestingModule } from 'xforge-common/test-utils';
import { TypeRegistry } from 'xforge-common/type-registry';
@@ -170,7 +170,7 @@ describe('CheckingQuestionsService', () => {
let realtimeService: TestRealtimeService;
configureTestingModule(() => ({
- imports: [TestRealtimeModule.forRoot(new TypeRegistry([QuestionDoc], [FileType.Audio], []))]
+ providers: [provideTestRealtime(new TypeRegistry([QuestionDoc], [FileType.Audio], []))]
}));
beforeEach(() => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions/checking-questions.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions/checking-questions.component.ts
index a1482ac74d7..2f379a19745 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions/checking-questions.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-questions/checking-questions.component.ts
@@ -1,3 +1,4 @@
+import { NgClass } from '@angular/common';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
@@ -13,7 +14,12 @@ import {
SimpleChanges,
ViewChildren
} from '@angular/core';
-import { MatListItem } from '@angular/material/list';
+import { MatBadge } from '@angular/material/badge';
+import { MatButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatActionList, MatListItem } from '@angular/material/list';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
import { sortBy } from 'lodash-es';
import { Operation } from 'realtime-server/lib/esm/common/models/project-rights';
import { Answer } from 'realtime-server/lib/esm/scriptureforge/models/answer';
@@ -62,7 +68,7 @@ export interface QuestionChangedEvent {
templateUrl: './checking-questions.component.html',
styleUrls: ['./checking-questions.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
- standalone: false
+ imports: [TranslocoModule, MatActionList, MatListItem, NgClass, MatTooltip, MatBadge, MatIcon, MatButton]
})
export class CheckingQuestionsComponent implements OnInit, OnChanges {
@Output() update = new EventEmitter();
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.spec.ts
index a39b99e871b..c4aba153ad6 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.spec.ts
@@ -4,11 +4,11 @@ import { By } from '@angular/platform-browser';
import { AudioTiming } from 'realtime-server/lib/esm/scriptureforge/models/audio-timing';
import { BehaviorSubject } from 'rxjs';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { getTestTranslocoModule } from 'xforge-common/test-utils';
import { TextDocId } from '../../../core/models/text-doc';
+import { AudioPlayerComponent } from '../../../shared/audio/audio-player/audio-player.component';
import { AudioPlayerStub, getAudioTimings, getAudioTimingWithHeadings } from '../../checking-test.utils';
import { CheckingScriptureAudioPlayerComponent } from './checking-scripture-audio-player.component';
@@ -238,7 +238,7 @@ describe('ScriptureAudioComponent', () => {
@Component({
selector: 'app-host',
template: '',
- standalone: false
+ imports: [CheckingScriptureAudioPlayerComponent]
})
class HostComponent {
@ViewChild(CheckingScriptureAudioPlayerComponent) audioPlayer!: CheckingScriptureAudioPlayerComponent;
@@ -246,8 +246,7 @@ class HostComponent {
@Component({
selector: 'app-audio-player',
- template: 'Mock Audio Player
',
- standalone: false
+ template: 'Mock Audio Player
'
})
class AudioPlayerStubComponent {
readonly testOnlineStatusService: TestOnlineStatusService = TestBed.inject(
@@ -278,10 +277,19 @@ class TestEnvironment {
const template = ``;
TestBed.configureTestingModule({
- declarations: [HostComponent, CheckingScriptureAudioPlayerComponent, AudioPlayerStubComponent],
- imports: [UICommonModule, TestOnlineStatusModule.forRoot(), TestTranslocoModule]
+ imports: [
+ getTestTranslocoModule(),
+ HostComponent,
+ CheckingScriptureAudioPlayerComponent,
+ AudioPlayerStubComponent
+ ],
+ providers: [provideTestOnlineStatus()]
});
TestBed.overrideComponent(HostComponent, { set: { template: template } });
+ TestBed.overrideComponent(CheckingScriptureAudioPlayerComponent, {
+ remove: { imports: [AudioPlayerComponent] },
+ add: { imports: [AudioPlayerStubComponent] }
+ });
this.ngZone = TestBed.inject(NgZone);
this.fixture = TestBed.createComponent(HostComponent);
this.component = this.fixture.componentInstance;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.ts
index c6e238125f9..208e6c69ee9 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.component.ts
@@ -1,4 +1,8 @@
+import { Dir } from '@angular/cdk/bidi';
import { AfterViewInit, Component, DestroyRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { TranslocoModule } from '@ngneat/transloco';
import { Canon, VerseRef } from '@sillsdev/scripture';
import { AudioTiming } from 'realtime-server/lib/esm/scriptureforge/models/audio-timing';
import { Subscription } from 'rxjs';
@@ -14,7 +18,7 @@ import { AudioHeadingRef, AudioTextRef, CheckingUtils } from '../../checking.uti
selector: 'app-checking-scripture-audio-player',
templateUrl: './checking-scripture-audio-player.component.html',
styleUrls: ['./checking-scripture-audio-player.component.scss'],
- standalone: false
+ imports: [TranslocoModule, Dir, MatIconButton, MatIcon, AudioPlayerComponent]
})
export class CheckingScriptureAudioPlayerComponent implements AfterViewInit {
@Input() canClose: boolean = true;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.stories.ts
index 4773f61b050..3eab39227c7 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-scripture-audio-player/checking-scripture-audio-player.stories.ts
@@ -1,10 +1,7 @@
-import { CommonModule } from '@angular/common';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { of } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { SFProjectService } from '../../../core/sf-project.service';
import { AudioPlayerComponent } from '../../../shared/audio/audio-player/audio-player.component';
import { AudioTimePipe } from '../../../shared/audio/audio-time-pipe';
@@ -38,17 +35,10 @@ const meta: Meta = {
},
decorators: [
moduleMetadata({
- imports: [UICommonModule, CommonModule, I18nStoryModule],
- declarations: [AudioPlayerComponent, AudioTimePipe],
+ imports: [AudioPlayerComponent, AudioTimePipe],
providers: [
- {
- provide: SFProjectService,
- useValue: instance(mockedSFProjectService)
- },
- {
- provide: OnlineStatusService,
- useValue: instance(mockedOnlineStatusService)
- }
+ { provide: SFProjectService, useValue: instance(mockedSFProjectService) },
+ { provide: OnlineStatusService, useValue: instance(mockedOnlineStatusService) }
]
}),
(story, context) => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.spec.ts
index f51d96a4e4d..96d3777dc62 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.spec.ts
@@ -1,5 +1,5 @@
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { VerseRef } from '@sillsdev/scripture';
import { User } from 'realtime-server/lib/esm/common/models/user';
import { createTestUser } from 'realtime-server/lib/esm/common/models/user-test-data';
@@ -10,19 +10,18 @@ import { anything, mock, when } from 'ts-mockito';
import { DialogService } from 'xforge-common/dialog.service';
import { UserDoc } from 'xforge-common/models/user-doc';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { SFProjectProfileDoc } from '../../../core/models/sf-project-profile-doc';
import { SF_TYPE_REGISTRY } from '../../../core/models/sf-type-registry';
import { TextDoc, TextDocId } from '../../../core/models/text-doc';
import { SFProjectService } from '../../../core/sf-project.service';
-import { SharedModule } from '../../../shared/shared.module';
import { getCombinedVerseTextDoc, getTextDoc } from '../../../shared/test-utils';
+import { provideQuillRegistrations } from '../../../shared/text/quill-editor-registration/quill-providers';
import { EDITOR_READY_TIMEOUT } from '../../../shared/text/text.component';
import { CheckingTextComponent } from './checking-text.component';
@@ -32,20 +31,16 @@ const mockedDialogService = mock(DialogService);
describe('CheckingTextComponent', () => {
configureTestingModule(() => ({
- declarations: [CheckingTextComponent],
- imports: [
- NoopAnimationsModule,
- SharedModule.forRoot(),
- UICommonModule,
- TestRealtimeModule.forRoot(SF_TYPE_REGISTRY),
- TestOnlineStatusModule.forRoot(),
- TestTranslocoModule
- ],
+ imports: [CheckingTextComponent, getTestTranslocoModule()],
providers: [
+ provideQuillRegistrations(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
+ provideTestOnlineStatus(),
{ provide: OnlineStatusService, useClass: TestOnlineStatusService },
{ provide: SFProjectService, useMock: mockedSFProjectService },
{ provide: UserService, useMock: mockedUserService },
- { provide: DialogService, useMock: mockedDialogService }
+ { provide: DialogService, useMock: mockedDialogService },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.ts
index e1b6351d74d..4e1dffdb027 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking-text/checking-text.component.ts
@@ -13,7 +13,7 @@ import { verseRefFromMouseEvent } from '../../../shared/utils';
selector: 'app-checking-text',
templateUrl: './checking-text.component.html',
styleUrls: ['./checking-text.component.scss'],
- standalone: false
+ imports: [TextComponent]
})
export class CheckingTextComponent implements AfterViewInit {
@ViewChild(TextComponent, { static: true }) textComponent!: TextComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts
index ad5cf30fe0a..6895b9a2c17 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.spec.ts
@@ -3,13 +3,14 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { Location } from '@angular/common';
import { DebugElement, DestroyRef, NgZone } from '@angular/core';
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonHarness } from '@angular/material/button/testing';
import { MatDialogRef } from '@angular/material/dialog';
import { MatMenuHarness } from '@angular/material/menu/testing';
import { MatSelectHarness } from '@angular/material/select/testing';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { ActivatedRoute, ActivatedRouteSnapshot, Params, Route, Router, RouterModule } from '@angular/router';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
+import { ActivatedRoute, ActivatedRouteSnapshot, Params, provideRouter, Route, Router } from '@angular/router';
import { Canon, VerseRef } from '@sillsdev/scripture';
import { ngfModule } from 'angular-file';
import { AngularSplitModule } from 'angular-split';
@@ -47,12 +48,11 @@ import { UserProfileDoc } from 'xforge-common/models/user-profile-doc';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { OwnerComponent } from 'xforge-common/owner/owner.component';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule, getAudioBlob, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { configureTestingModule, getAudioBlob, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { objectId } from 'xforge-common/utils';
import { QuestionDoc } from '../../core/models/question-doc';
@@ -67,7 +67,7 @@ import { TranslationEngineService } from '../../core/translation-engine.service'
import { AudioRecorderDialogComponent } from '../../shared/audio-recorder-dialog/audio-recorder-dialog.component';
import { AudioPlayerComponent } from '../../shared/audio/audio-player/audio-player.component';
import { AudioTimePipe } from '../../shared/audio/audio-time-pipe';
-import { SharedModule } from '../../shared/shared.module';
+import { provideQuillRegistrations } from '../../shared/text/quill-editor-registration/quill-providers';
import { TextChooserDialogComponent, TextSelection } from '../../text-chooser-dialog/text-chooser-dialog.component';
import { AttachAudioComponent } from '../attach-audio/attach-audio.component';
import { ChapterAudioDialogService } from '../chapter-audio-dialog/chapter-audio-dialog.service';
@@ -135,9 +135,8 @@ const ROUTES: Route[] = [
describe('CheckingComponent', () => {
configureTestingModule(() => ({
- declarations: [
+ imports: [
AudioTimePipe,
- AudioPlayerComponent,
CheckingAnswersComponent,
CheckingAudioPlayerComponent,
CheckingInputFormComponent,
@@ -145,24 +144,22 @@ describe('CheckingComponent', () => {
CheckingComponent,
CheckingScriptureAudioPlayerComponent,
CheckingQuestionsComponent,
- CheckingTextComponent,
TextAndAudioComponent,
FontSizeComponent,
- AttachAudioComponent
- ],
- imports: [
+ AttachAudioComponent,
+ AudioPlayerComponent,
+ CheckingTextComponent,
AngularSplitModule,
ngfModule,
- NoopAnimationsModule,
- RouterModule.forRoot(ROUTES),
- SharedModule.forRoot(),
- UICommonModule,
+ ReactiveFormsModule,
OwnerComponent,
- TestTranslocoModule,
- TestOnlineStatusModule.forRoot(),
- TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)
+ getTestTranslocoModule()
],
providers: [
+ provideRouter(ROUTES),
+ provideQuillRegistrations(),
+ provideTestOnlineStatus(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: ActivatedRoute, useMock: mockedActivatedRoute },
{ provide: UserService, useMock: mockedUserService },
{ provide: SFProjectService, useMock: mockedProjectService },
@@ -172,7 +169,8 @@ describe('CheckingComponent', () => {
{ provide: QuestionDialogService, useMock: mockedQuestionDialogService },
{ provide: ChapterAudioDialogService, useMock: mockedChapterAudioDialogService },
{ provide: FileService, useMock: mockedFileService },
- { provide: OnlineStatusService, useClass: TestOnlineStatusService }
+ { provide: OnlineStatusService, useClass: TestOnlineStatusService },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts
index 438cd4f85a4..87216fe1063 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/checking.component.ts
@@ -1,8 +1,16 @@
+import { Dir } from '@angular/cdk/bidi';
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
+import { AsyncPipe, KeyValuePipe, NgClass } from '@angular/common';
import { AfterViewInit, Component, DestroyRef, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
+import { MatButton, MatIconButton } from '@angular/material/button';
+import { MatIcon } from '@angular/material/icon';
+import { MatListSubheaderCssMatStyler, MatSelectionList } from '@angular/material/list';
+import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
+import { MatTooltip } from '@angular/material/tooltip';
import { ActivatedRoute, NavigationBehaviorOptions, Router } from '@angular/router';
+import { TranslocoModule } from '@ngneat/transloco';
import { Canon, VerseRef } from '@sillsdev/scripture';
-import { SplitComponent } from 'angular-split';
+import { AngularSplitModule, SplitComponent } from 'angular-split';
import { cloneDeep, debounce } from 'lodash-es';
import { Operation } from 'realtime-server/lib/esm/common/models/project-rights';
import { Answer, AnswerStatus } from 'realtime-server/lib/esm/scriptureforge/models/answer';
@@ -17,12 +25,14 @@ import { toVerseRef, VerseRefData } from 'realtime-server/lib/esm/scriptureforge
import { asyncScheduler, BehaviorSubject, combineLatest, merge, Observable, of, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, map, startWith, take, throttleTime } from 'rxjs/operators';
import { DataLoadingComponent } from 'xforge-common/data-loading-component';
+import { DonutChartComponent } from 'xforge-common/donut-chart/donut-chart.component';
import { I18nService } from 'xforge-common/i18n.service';
import { Breakpoint, MediaBreakpointService } from 'xforge-common/media-breakpoints/media-breakpoint.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
+import { RouterLinkDirective } from 'xforge-common/router-link.directive';
import { UserService } from 'xforge-common/user.service';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { objectId } from 'xforge-common/utils';
@@ -35,6 +45,8 @@ import { TextDocId } from '../../core/models/text-doc';
import { TextsByBookId } from '../../core/models/texts-by-book-id';
import { PermissionsService } from '../../core/permissions.service';
import { SFProjectService } from '../../core/sf-project.service';
+import { BookChapterChooserComponent } from '../../shared/book-chapter-chooser/book-chapter-chooser.component';
+import { ShareButtonComponent } from '../../shared/share/share-button.component';
import { getVerseStrFromSegmentRef } from '../../shared/utils';
import { ChapterAudioDialogData } from '../chapter-audio-dialog/chapter-audio-dialog.component';
import { ChapterAudioDialogService } from '../chapter-audio-dialog/chapter-audio-dialog.service';
@@ -48,6 +60,7 @@ import { CheckingQuestionsService, PreCreationQuestionData, QuestionFilter } fro
import { CheckingQuestionsComponent, QuestionChangedEvent } from './checking-questions/checking-questions.component';
import { CheckingScriptureAudioPlayerComponent } from './checking-scripture-audio-player/checking-scripture-audio-player.component';
import { CheckingTextComponent } from './checking-text/checking-text.component';
+import { FontSizeComponent } from './font-size/font-size.component';
interface Summary {
unread: number;
@@ -59,7 +72,32 @@ interface Summary {
selector: 'app-checking',
templateUrl: './checking.component.html',
styleUrls: ['./checking.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ NgClass,
+ MatMenu,
+ MatSelectionList,
+ MatListSubheaderCssMatStyler,
+ MatMenuItem,
+ MatIcon,
+ MatIconButton,
+ MatButton,
+ MatMenuTrigger,
+ CheckingQuestionsComponent,
+ BookChapterChooserComponent,
+ MatTooltip,
+ FontSizeComponent,
+ ShareButtonComponent,
+ AngularSplitModule,
+ Dir,
+ CheckingTextComponent,
+ CheckingAnswersComponent,
+ CheckingScriptureAudioPlayerComponent,
+ RouterLinkDirective,
+ DonutChartComponent,
+ AsyncPipe,
+ KeyValuePipe
+ ]
})
export class CheckingComponent extends DataLoadingComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('answerPanelContainer') set answersPanelElement(answersPanelContainerElement: ElementRef) {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.spec.ts
index b45b83cef7b..eee3f1f6df7 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.spec.ts
@@ -3,9 +3,8 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MatButtonHarness } from '@angular/material/button/testing';
import { MatMenuHarness, MatMenuItemHarness } from '@angular/material/menu/testing';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
+import { getTestTranslocoModule } from 'xforge-common/test-utils';
import { FontSizeComponent } from './font-size.component';
describe('FontSizeComponent', () => {
@@ -31,8 +30,8 @@ describe('FontSizeComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
- imports: [UICommonModule, NoopAnimationsModule, TestTranslocoModule],
- declarations: [FontSizeComponent]
+ imports: [getTestTranslocoModule(), FontSizeComponent],
+ providers: [provideNoopAnimations()]
}).compileComponents();
fixture = TestBed.createComponent(FontSizeComponent);
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.ts
index d3beb3d8b53..acc66b2ef45 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.component.ts
@@ -1,10 +1,16 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { TranslocoModule } from '@ngneat/transloco';
+import { MatIconButton } from '@angular/material/button';
+import { MatMenuTrigger, MatMenu, MatMenuItem } from '@angular/material/menu';
+import { NgClass } from '@angular/common';
+import { MatTooltip } from '@angular/material/tooltip';
+import { MatIcon } from '@angular/material/icon';
@Component({
selector: 'app-font-size',
templateUrl: './font-size.component.html',
styleUrls: ['./font-size.component.scss'],
- standalone: false
+ imports: [TranslocoModule, MatIconButton, MatMenuTrigger, NgClass, MatTooltip, MatIcon, MatMenu, MatMenuItem]
})
export class FontSizeComponent implements OnInit {
@Input() min: number = 1;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.stories.ts
index 6b231d47192..ad9dd3d541e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/font-size/font-size.stories.ts
@@ -1,9 +1,7 @@
-import { CommonModule } from '@angular/common';
import { componentWrapperDecorator, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { expect, userEvent } from '@storybook/test';
import { PointerEventsCheckLevel } from '@testing-library/user-event';
-import { TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { getTestTranslocoModule } from 'xforge-common/test-utils';
import { FontSizeComponent } from './font-size.component';
export default {
@@ -11,7 +9,7 @@ export default {
component: FontSizeComponent,
decorators: [
moduleMetadata({
- imports: [CommonModule, UICommonModule, TestTranslocoModule]
+ imports: [getTestTranslocoModule()]
}),
componentWrapperDecorator(
story => `
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.spec.ts
index 1bb6cdae3f5..11ffbc90514 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.spec.ts
@@ -1,11 +1,15 @@
+import { NgClass } from '@angular/common';
import { Component, DebugElement, NgZone, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { MatIcon } from '@angular/material/icon';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
+import { MatTooltip } from '@angular/material/tooltip';
import { By } from '@angular/platform-browser';
+import { TranslocoModule } from '@ngneat/transloco';
import { BehaviorSubject } from 'rxjs';
import { instance, mock, resetCalls, verify, when } from 'ts-mockito';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { AudioPlayer, AudioStatus } from '../../../shared/audio/audio-player';
import { AudioSegmentPlayer } from '../../../shared/audio/audio-segment-player';
import { SingleButtonAudioPlayerComponent } from './single-button-audio-player.component';
@@ -15,8 +19,8 @@ when(audioMock.status$).thenReturn(new BehaviorSubject(AudioStatus.
describe('SingleButtonAudioPlayerComponent', () => {
configureTestingModule(() => ({
- imports: [UICommonModule, TestTranslocoModule, TestOnlineStatusModule.forRoot()],
- declarations: [TestComponent, MockComponent]
+ imports: [TestComponent, getTestTranslocoModule(), MockComponent],
+ providers: [provideTestOnlineStatus()]
}));
let env: TestEnvironment;
@@ -158,10 +162,22 @@ class TestEnvironment {
}
@Component({
- template: `
+ selector: 'app-test-player',
+ templateUrl: './single-button-audio-player.component.html',
+ styleUrls: ['./single-button-audio-player.component.scss'],
+ imports: [TranslocoModule, NgClass, MatProgressSpinner, MatIcon, MatTooltip]
+})
+class TestComponent extends SingleButtonAudioPlayerComponent {
+ public setAudio(audioPlayer: AudioPlayer | undefined): void {
+ this.audio = audioPlayer;
+ }
+}
+
+@Component({
+ template: `
play
- `,
- standalone: false
+ `,
+ imports: [TestComponent, MatIcon]
})
class MockComponent {
@ViewChild('player') player!: TestComponent;
@@ -172,9 +188,3 @@ class MockComponent {
this.source = 'test-audio-player.webm';
}
}
-
-class TestComponent extends SingleButtonAudioPlayerComponent {
- public setAudio(audioPlayer: AudioPlayer | undefined): void {
- this.audio = audioPlayer;
- }
-}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.ts
index a97291922f9..1c2dec57e92 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.component.ts
@@ -1,4 +1,9 @@
+import { NgClass } from '@angular/common';
import { Component, Input, OnChanges, OnDestroy } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
+import { MatTooltip } from '@angular/material/tooltip';
+import { TranslocoModule } from '@ngneat/transloco';
import { BehaviorSubject, Subscription } from 'rxjs';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { AudioPlayer, AudioStatus } from '../../../shared/audio/audio-player';
@@ -9,7 +14,7 @@ import { AudioSegmentPlayer } from '../../../shared/audio/audio-segment-player';
selector: 'app-single-button-audio-player',
templateUrl: './single-button-audio-player.component.html',
styleUrls: ['./single-button-audio-player.component.scss'],
- standalone: false
+ imports: [TranslocoModule, NgClass, MatProgressSpinner, MatIcon, MatTooltip]
})
export class SingleButtonAudioPlayerComponent extends AudioPlayerBaseComponent implements OnChanges, OnDestroy {
private _source?: string;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.stories.ts
index a3204b8859b..80df7f08955 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/checking/single-button-audio-player/single-button-audio-player.stories.ts
@@ -1,11 +1,9 @@
-import { CommonModule } from '@angular/common';
import { Component, ViewChild } from '@angular/core';
+import { MatIcon } from '@angular/material/icon';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { of } from 'rxjs';
import { instance, mock, when } from 'ts-mockito';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { SingleButtonAudioPlayerComponent } from './single-button-audio-player.component';
@Component({
@@ -13,7 +11,7 @@ import { SingleButtonAudioPlayerComponent } from './single-button-audio-player.c
template: `
{{ player.playing ? 'stop' : 'play_arrow' }}
`,
- standalone: false
+ imports: [SingleButtonAudioPlayerComponent, MatIcon]
})
class TestComponent {
@ViewChild('player') player!: SingleButtonAudioPlayerComponent;
@@ -31,14 +29,8 @@ const meta: Meta = {
component: TestComponent,
decorators: [
moduleMetadata({
- imports: [UICommonModule, CommonModule, I18nStoryModule],
- providers: [
- {
- provide: OnlineStatusService,
- useValue: instance(mockedOnlineStatusService)
- }
- ],
- declarations: [SingleButtonAudioPlayerComponent, TestComponent]
+ imports: [SingleButtonAudioPlayerComponent, TestComponent],
+ providers: [{ provide: OnlineStatusService, useValue: instance(mockedOnlineStatusService) }]
})
]
};
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.html
index d6acdd07246..25da6b6ec14 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.html
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.html
@@ -1,5 +1,5 @@
-
+
{{ t("some_questions_edited") }}
{{ t("edited_questions_explanation") }}
@@ -44,5 +44,5 @@ {{ t("some_questions_edited") }}
{{ t("done") }}
-
+
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.spec.ts
index c7be2fa0e3c..655c8c99f6a 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.spec.ts
@@ -1,11 +1,9 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { NgModule } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { firstValueFrom } from 'rxjs';
-import { ChildViewContainerComponent, configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { ChildViewContainerComponent, configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import {
EditedQuestion,
ImportQuestionsConfirmationDialogComponent,
@@ -15,7 +13,8 @@ import {
describe('ImportQuestionsConfirmationDialogComponent', () => {
configureTestingModule(() => ({
- imports: [DialogTestModule]
+ imports: [getTestTranslocoModule(), ImportQuestionsConfirmationDialogComponent],
+ providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
}));
it('Allows selecting and unselecting all questions', fakeAsync(async () => {
@@ -69,13 +68,6 @@ describe('ImportQuestionsConfirmationDialogComponent', () => {
}));
});
-@NgModule({
- declarations: [ImportQuestionsConfirmationDialogComponent],
- imports: [UICommonModule, TestTranslocoModule],
- providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
-})
-class DialogTestModule {}
-
class TestEnvironment {
fixture: ComponentFixture;
component: ImportQuestionsConfirmationDialogComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.ts
index 946ccff4ed0..a6e902d3497 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-confirmation-dialog/import-questions-confirmation-dialog.component.ts
@@ -1,7 +1,30 @@
import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
-import { MatTableDataSource } from '@angular/material/table';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogRef,
+ MatDialogTitle,
+ MatDialogContent,
+ MatDialogActions
+} from '@angular/material/dialog';
+import {
+ MatTableDataSource,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCellDef,
+ MatHeaderCell,
+ MatCellDef,
+ MatCell,
+ MatHeaderRowDef,
+ MatHeaderRow,
+ MatRowDef,
+ MatRow
+} from '@angular/material/table';
import { I18nService } from 'xforge-common/i18n.service';
+import { TranslocoModule } from '@ngneat/transloco';
+import { Dir } from '@angular/cdk/bidi';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { MatCheckbox } from '@angular/material/checkbox';
+import { MatButton } from '@angular/material/button';
export interface ImportQuestionsConfirmationDialogData {
questions: EditedQuestion[];
@@ -19,7 +42,26 @@ export interface EditedQuestion {
@Component({
templateUrl: './import-questions-confirmation-dialog.component.html',
styleUrls: ['./import-questions-confirmation-dialog.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ Dir,
+ MatDialogTitle,
+ CdkScrollable,
+ MatDialogContent,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCellDef,
+ MatHeaderCell,
+ MatCheckbox,
+ MatCellDef,
+ MatCell,
+ MatHeaderRowDef,
+ MatHeaderRow,
+ MatRowDef,
+ MatRow,
+ MatDialogActions,
+ MatButton
+ ]
})
export class ImportQuestionsConfirmationDialogComponent {
questions: EditedQuestion[];
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.html
index 5deb5eb2050..527482691b5 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.html
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.html
@@ -178,8 +178,8 @@
|
{{ referenceForDisplay(element.question) }}
|
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.spec.ts
index d6ed5c2900a..ed9a29a21fa 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.spec.ts
@@ -1,12 +1,9 @@
import { OverlayContainer } from '@angular/cdk/overlay';
-import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
-import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { NgModule } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
-import { FormControl } from '@angular/forms';
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { Canon, VerseRef } from '@sillsdev/scripture';
import { ngfModule } from 'angular-file';
import { Answer } from 'realtime-server/lib/esm/scriptureforge/models/answer';
@@ -19,11 +16,10 @@ import { CsvService } from 'xforge-common/csv-service.service';
import { DialogService } from 'xforge-common/dialog.service';
import { RealtimeQuery } from 'xforge-common/models/realtime-query';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { ChildViewContainerComponent, configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { ChildViewContainerComponent, configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { TestingRetryingRequestService } from 'xforge-common/testing-retrying-request.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { QuestionDoc } from '../../core/models/question-doc';
import { TextsByBookId } from '../../core/models/texts-by-book-id';
import { SFProjectService } from '../../core/sf-project.service';
@@ -44,13 +40,21 @@ const mockedRealtimeQuery: RealtimeQuery = mock(RealtimeQuery);
describe('ImportQuestionsDialogComponent', () => {
configureTestingModule(() => ({
- imports: [DialogTestModule, TestOnlineStatusModule.forRoot()],
+ imports: [
+ ReactiveFormsModule,
+ getTestTranslocoModule(),
+ ngfModule,
+ ScriptureChooserDialogComponent,
+ ImportQuestionsDialogComponent
+ ],
providers: [
+ provideTestOnlineStatus(),
{ provide: SFProjectService, useMock: mockedProjectService },
{ provide: CheckingQuestionsService, useMock: mockedQuestionsService },
{ provide: DialogService, useMock: mockedDialogService },
{ provide: CsvService, useMock: mockedCsvService },
- { provide: OnlineStatusService, useClass: TestOnlineStatusService }
+ { provide: OnlineStatusService, useClass: TestOnlineStatusService },
+ provideNoopAnimations()
]
}));
@@ -500,14 +504,6 @@ describe('ImportQuestionsDialogComponent', () => {
}));
});
-@NgModule({
- declarations: [ScriptureChooserDialogComponent, ImportQuestionsDialogComponent],
-
- imports: [UICommonModule, TestTranslocoModule, NoopAnimationsModule, ngfModule],
- providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
-})
-class DialogTestModule {}
-
class TestEnvironment {
fixture: ComponentFixture;
component: ImportQuestionsDialogComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.ts
index 89a453ed1eb..5f99cf9a609 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/import-questions-dialog/import-questions-dialog.component.ts
@@ -1,9 +1,39 @@
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { AsyncPipe } from '@angular/common';
import { Component, DestroyRef, ElementRef, Inject, NgZone, OnDestroy, ViewChild } from '@angular/core';
-import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
+import { AbstractControl, FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatAnchor, MatButton, MatIconButton } from '@angular/material/button';
+import { MatCard, MatCardActions, MatCardContent, MatCardTitle } from '@angular/material/card';
import { MatCheckbox } from '@angular/material/checkbox';
-import { MAT_DIALOG_DATA, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
-import { TranslocoService } from '@ngneat/transloco';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogConfig,
+ MatDialogContent,
+ MatDialogRef,
+ MatDialogTitle
+} from '@angular/material/dialog';
+import { MatError, MatFormField, MatLabel, MatSuffix } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
+import { MatInput } from '@angular/material/input';
+import { MatProgressBar } from '@angular/material/progress-bar';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatTable
+} from '@angular/material/table';
+import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
import { Canon, VerseRef } from '@sillsdev/scripture';
+import { ngfModule } from 'angular-file';
import { Question } from 'realtime-server/lib/esm/scriptureforge/models/question';
import { fromVerseRef, toVerseRef } from 'realtime-server/lib/esm/scriptureforge/models/verse-ref-data';
import { Subject } from 'rxjs';
@@ -68,7 +98,44 @@ type DialogStatus = 'initial' | 'no_questions' | 'filter' | 'loading' | 'progres
@Component({
templateUrl: './import-questions-dialog.component.html',
styleUrls: ['./import-questions-dialog.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ MatDialogTitle,
+ MatIconButton,
+ MatDialogClose,
+ MatIcon,
+ CdkScrollable,
+ MatDialogContent,
+ MatCard,
+ MatCardTitle,
+ MatCardContent,
+ MatCardActions,
+ MatButton,
+ MatAnchor,
+ MatError,
+ ngfModule,
+ MatProgressSpinner,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCellDef,
+ MatHeaderCell,
+ MatCellDef,
+ MatCell,
+ MatHeaderRowDef,
+ MatHeaderRow,
+ MatRowDef,
+ MatRow,
+ FormsModule,
+ ReactiveFormsModule,
+ MatFormField,
+ MatLabel,
+ MatInput,
+ MatSuffix,
+ MatCheckbox,
+ MatProgressBar,
+ MatDialogActions,
+ AsyncPipe
+ ]
})
export class ImportQuestionsDialogComponent implements OnDestroy {
questionSource: null | 'transcelerator' | 'csv_file' = null;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.spec.ts
index 707818e2b03..35638d89825 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.spec.ts
@@ -1,12 +1,9 @@
-import { CommonModule } from '@angular/common';
-import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
-import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { DebugElement, NgModule } from '@angular/core';
+import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { VerseRef } from '@sillsdev/scripture';
import { CookieService } from 'ngx-cookie-service';
import { Delta } from 'quill';
@@ -27,17 +24,16 @@ import { createStorageFileData, FileType } from 'xforge-common/models/file-offli
import { UserDoc } from 'xforge-common/models/user-doc';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import {
ChildViewContainerComponent,
configureTestingModule,
getAudioBlob,
- TestTranslocoModule
+ getTestTranslocoModule
} from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { UserService } from 'xforge-common/user.service';
import { QuestionDoc } from '../../core/models/question-doc';
import { SFProjectProfileDoc } from '../../core/models/sf-project-profile-doc';
@@ -45,10 +41,9 @@ import { SF_TYPE_REGISTRY } from '../../core/models/sf-type-registry';
import { TextDoc, TextDocId } from '../../core/models/text-doc';
import { SFProjectService } from '../../core/sf-project.service';
import { ScriptureChooserDialogComponent } from '../../scripture-chooser-dialog/scripture-chooser-dialog.component';
-import { SharedModule } from '../../shared/shared.module';
import { getTextDoc } from '../../shared/test-utils';
+import { provideQuillRegistrations } from '../../shared/text/quill-editor-registration/quill-providers';
import { EDITOR_READY_TIMEOUT } from '../../shared/text/text.component';
-import { CheckingModule } from '../checking.module';
import { AudioAttachment } from '../checking/checking-audio-player/checking-audio-player.component';
import { QuestionDialogComponent, QuestionDialogData } from './question-dialog.component';
@@ -65,12 +60,14 @@ describe('QuestionDialogComponent', () => {
imports: [
ReactiveFormsModule,
FormsModule,
- DialogTestModule,
- SharedModule.forRoot(),
- TestOnlineStatusModule.forRoot(),
- TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)
+ getTestTranslocoModule(),
+ ScriptureChooserDialogComponent,
+ QuestionDialogComponent
],
providers: [
+ provideQuillRegistrations(),
+ provideTestOnlineStatus(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: AuthService, useMock: mockedAuthService },
{ provide: UserService, useMock: mockedUserService },
{ provide: NoticeService, useMock: mockedNoticeService },
@@ -78,7 +75,8 @@ describe('QuestionDialogComponent', () => {
{ provide: BugsnagService, useMock: mockedBugsnagService },
{ provide: CookieService, useMock: mockedCookieService },
{ provide: FileService, useMock: mockedFileService },
- { provide: OnlineStatusService, useClass: TestOnlineStatusService }
+ { provide: OnlineStatusService, useClass: TestOnlineStatusService },
+ provideNoopAnimations()
]
}));
@@ -575,14 +573,6 @@ describe('QuestionDialogComponent', () => {
}));
});
-@NgModule({
- declarations: [ScriptureChooserDialogComponent],
- exports: [ScriptureChooserDialogComponent],
- imports: [CommonModule, UICommonModule, CheckingModule, TestTranslocoModule, NoopAnimationsModule],
- providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
-})
-class DialogTestModule {}
-
class TestEnvironment {
readonly fixture: ComponentFixture;
readonly component: QuestionDialogComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.ts
index a76f48670f6..7ed6577bdcc 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.component.ts
@@ -1,6 +1,20 @@
+import { CdkScrollable } from '@angular/cdk/scrolling';
import { Component, DestroyRef, Inject, OnInit, ViewChild } from '@angular/core';
-import { AbstractControl, FormControl, FormGroup, Validators } from '@angular/forms';
-import { MAT_DIALOG_DATA, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
+import { AbstractControl, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
+import { MatButton, MatIconButton } from '@angular/material/button';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogConfig,
+ MatDialogContent,
+ MatDialogRef,
+ MatDialogTitle
+} from '@angular/material/dialog';
+import { MatError, MatFormField, MatLabel, MatSuffix } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
+import { MatInput } from '@angular/material/input';
+import { TranslocoModule } from '@ngneat/transloco';
import { VerseRef } from '@sillsdev/scripture';
import { cloneDeep } from 'lodash-es';
import { Question } from 'realtime-server/lib/esm/scriptureforge/models/question';
@@ -18,7 +32,9 @@ import {
} from '../../scripture-chooser-dialog/scripture-chooser-dialog.component';
import { ParentAndStartErrorStateMatcher, SFValidators } from '../../shared/sfvalidators';
import { combineVerseRefStrs } from '../../shared/utils';
+import { AttachAudioComponent } from '../attach-audio/attach-audio.component';
import { AudioAttachment } from '../checking/checking-audio-player/checking-audio-player.component';
+import { CheckingTextComponent } from '../checking/checking-text/checking-text.component';
import { TextAndAudioComponent } from '../text-and-audio/text-and-audio.component';
export interface QuestionDialogData {
questionDoc?: QuestionDoc;
@@ -38,7 +54,27 @@ export interface QuestionDialogResult {
@Component({
templateUrl: './question-dialog.component.html',
styleUrls: ['./question-dialog.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ MatDialogTitle,
+ MatIcon,
+ CdkScrollable,
+ MatDialogContent,
+ FormsModule,
+ ReactiveFormsModule,
+ MatFormField,
+ MatLabel,
+ MatInput,
+ MatIconButton,
+ MatSuffix,
+ MatError,
+ CheckingTextComponent,
+ TextAndAudioComponent,
+ AttachAudioComponent,
+ MatDialogActions,
+ MatButton,
+ MatDialogClose
+ ]
})
export class QuestionDialogComponent implements OnInit {
@ViewChild(TextAndAudioComponent) textAndAudio?: TextAndAudioComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.service.spec.ts
index 2baef174b86..5227764ee0c 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/question-dialog/question-dialog.service.spec.ts
@@ -17,9 +17,9 @@ import { DialogService } from 'xforge-common/dialog.service';
import { FileService } from 'xforge-common/file.service';
import { FileType } from 'xforge-common/models/file-offline-data';
import { NoticeService } from 'xforge-common/notice.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { QuestionDoc } from '../../core/models/question-doc';
import { SFProjectProfileDoc } from '../../core/models/sf-project-profile-doc';
@@ -39,8 +39,9 @@ const mockedFileService = mock(FileService);
describe('QuestionDialogService', () => {
configureTestingModule(() => ({
- imports: [TestTranslocoModule, TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
+ imports: [getTestTranslocoModule(false)],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: FileService, useMock: mockedFileService },
{ provide: DialogService, useMock: mockedDialogService },
{ provide: SFProjectService, useMock: mockedProjectService },
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/text-and-audio/text-and-audio.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/text-and-audio/text-and-audio.component.ts
index 9389e01005f..f8c71dca9c4 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/checking/text-and-audio/text-and-audio.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/checking/text-and-audio/text-and-audio.component.ts
@@ -1,12 +1,22 @@
+import { NgClass } from '@angular/common';
import { AfterViewInit, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
-import { AbstractControl, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
+import {
+ AbstractControl,
+ FormsModule,
+ ReactiveFormsModule,
+ UntypedFormControl,
+ UntypedFormGroup
+} from '@angular/forms';
+import { MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
+import { TranslocoModule } from '@ngneat/transloco';
import { AudioAttachment } from '../checking/checking-audio-player/checking-audio-player.component';
@Component({
selector: 'app-text-and-audio',
templateUrl: './text-and-audio.component.html',
styleUrls: ['./text-and-audio.component.scss'],
- standalone: false
+ imports: [TranslocoModule, FormsModule, ReactiveFormsModule, MatFormField, MatLabel, MatInput, NgClass]
})
export class TextAndAudioComponent implements AfterViewInit, OnInit, OnDestroy {
@Input() input?: { text?: string; audioUrl?: string };
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.spec.ts
index f8fea478f22..89f9e11ea60 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.spec.ts
@@ -2,7 +2,7 @@ import { HttpErrorResponse } from '@angular/common/http';
import { DebugElement, ErrorHandler } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { Router } from '@angular/router';
import { SFProject } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role';
@@ -12,12 +12,11 @@ import { AuthService } from 'xforge-common/auth.service';
import { CommandError, CommandErrorCode } from 'xforge-common/command.service';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { ParatextProject } from '../core/models/paratext-project';
import { SFProjectCreateSettings } from '../core/models/sf-project-create-settings';
import { SFProjectDoc } from '../core/models/sf-project-doc';
@@ -44,15 +43,10 @@ const mockedErrorHandler = mock(ErrorHandler);
describe('ConnectProjectComponent', () => {
configureTestingModule(() => ({
- imports: [
- NoopAnimationsModule,
- UICommonModule,
- TestTranslocoModule,
- TestOnlineStatusModule.forRoot(),
- TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)
- ],
- declarations: [ConnectProjectComponent, ProjectSelectComponent, SyncProgressComponent],
+ imports: [ConnectProjectComponent, ProjectSelectComponent, SyncProgressComponent, getTestTranslocoModule()],
providers: [
+ provideTestOnlineStatus(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: AuthService, useMock: mockedAuthService },
{ provide: ParatextService, useMock: mockedParatextService },
{ provide: ProjectNotificationService, useMock: mockedProjectNotificationService },
@@ -60,7 +54,8 @@ describe('ConnectProjectComponent', () => {
{ provide: SFProjectService, useMock: mockedSFProjectService },
{ provide: NoticeService, useMock: mockedNoticeService },
{ provide: ErrorHandler, useMock: mockedErrorHandler },
- { provide: OnlineStatusService, useClass: TestOnlineStatusService }
+ { provide: OnlineStatusService, useClass: TestOnlineStatusService },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.ts
index 4d1f78d5030..882b6d71635 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/connect-project/connect-project.component.ts
@@ -1,8 +1,13 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Component, DestroyRef, ErrorHandler, OnInit } from '@angular/core';
-import { FormControl, FormGroup } from '@angular/forms';
+import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { MatButton } from '@angular/material/button';
+import { MatCard, MatCardContent, MatCardSubtitle, MatCardTitle } from '@angular/material/card';
+import { MatCheckbox } from '@angular/material/checkbox';
+import { MatDivider } from '@angular/material/divider';
+import { MatError } from '@angular/material/form-field';
import { Router } from '@angular/router';
-import { TranslocoService } from '@ngneat/transloco';
+import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
import { AuthService } from 'xforge-common/auth.service';
import { DataLoadingComponent } from 'xforge-common/data-loading-component';
import { I18nService } from 'xforge-common/i18n.service';
@@ -15,7 +20,9 @@ import { SFProjectCreateSettings } from '../core/models/sf-project-create-settin
import { SFProjectDoc } from '../core/models/sf-project-doc';
import { ParatextService, SelectableProject } from '../core/paratext.service';
import { SFProjectService } from '../core/sf-project.service';
+import { ProjectSelectComponent } from '../project-select/project-select.component';
import { compareProjectsForSorting, projectLabel } from '../shared/utils';
+import { SyncProgressComponent } from '../sync/sync-progress/sync-progress.component';
interface ConnectProjectFormValues {
settings: {
checking: boolean;
@@ -27,7 +34,21 @@ interface ConnectProjectFormValues {
selector: 'app-connect-project',
templateUrl: './connect-project.component.html',
styleUrls: ['./connect-project.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ MatCard,
+ MatCardContent,
+ SyncProgressComponent,
+ FormsModule,
+ ReactiveFormsModule,
+ MatCardTitle,
+ MatCardSubtitle,
+ ProjectSelectComponent,
+ MatError,
+ MatDivider,
+ MatCheckbox,
+ MatButton
+ ]
})
export class ConnectProjectComponent extends DataLoadingComponent implements OnInit {
static readonly errorAlreadyConnectedKey: string = 'error-already-connected';
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/core/core.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/core/core.module.ts
deleted file mode 100644
index 32e4667f793..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/core/core.module.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { ProjectService } from 'xforge-common/project.service';
-import { TypeRegistry } from 'xforge-common/type-registry';
-import { SF_TYPE_REGISTRY } from './models/sf-type-registry';
-import { SFProjectService } from './sf-project.service';
-
-@NgModule({
- imports: [CommonModule],
- providers: [
- { provide: ProjectService, useExisting: SFProjectService },
- { provide: TypeRegistry, useValue: SF_TYPE_REGISTRY }
- ]
-})
-export class CoreModule {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/core/models/note-thread-doc.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/core/models/note-thread-doc.spec.ts
index 88f2c96f5b2..4d8c9d08dff 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/core/models/note-thread-doc.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/core/models/note-thread-doc.spec.ts
@@ -10,7 +10,7 @@ import {
NoteType
} from 'realtime-server/lib/esm/scriptureforge/models/note-thread';
import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import { configureTestingModule } from 'xforge-common/test-utils';
import { NoteThreadDoc, NoteThreadIcon } from './note-thread-doc';
@@ -18,7 +18,7 @@ import { SF_TYPE_REGISTRY } from './sf-type-registry';
describe('NoteThreadDoc', () => {
configureTestingModule(() => ({
- imports: [TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)]
+ providers: [provideTestRealtime(SF_TYPE_REGISTRY)]
}));
let env: TestEnvironment;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/core/permissions.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/core/permissions.service.spec.ts
index c0d76fe05a7..db42efff559 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/core/permissions.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/core/permissions.service.spec.ts
@@ -9,7 +9,7 @@ import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge
import { TextInfoPermission } from 'realtime-server/lib/esm/scriptureforge/models/text-info-permission';
import { anything, instance, mock, verify, when } from 'ts-mockito';
import { UserDoc } from 'xforge-common/models/user-doc';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import { configureTestingModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
@@ -25,8 +25,8 @@ const mockedProjectService = mock(SFProjectService);
const mockedProjectDoc = mock(SFProjectProfileDoc);
describe('PermissionsService', () => {
configureTestingModule(() => ({
- imports: [TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: UserService, useMock: mockedUserService },
{ provide: SFProjectService, useMock: mockedProjectService }
]
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/core/text-doc.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/core/text-doc.service.spec.ts
index 89fd8dbb415..72b9819a4ff 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/core/text-doc.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/core/text-doc.service.spec.ts
@@ -7,7 +7,7 @@ import { Chapter, TextInfo } from 'realtime-server/lib/esm/scriptureforge/models
import { TextInfoPermission } from 'realtime-server/lib/esm/scriptureforge/models/text-info-permission';
import * as RichText from 'rich-text';
import { mock, when } from 'ts-mockito';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import { configureTestingModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
@@ -22,8 +22,8 @@ const mockUserService = mock(UserService);
describe('TextDocService', () => {
configureTestingModule(() => ({
- imports: [TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: SFProjectService, useMock: mockProjectService },
{ provide: UserService, useMock: mockUserService }
]
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.html
index e5b661d5a12..80c3efedb1f 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.html
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.html
@@ -1,5 +1,5 @@
-
+
{{ t("technical_details") }}
@@ -24,5 +24,5 @@ {{ t("exception") }}
-
+
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.spec.ts
index 5f70690c18a..6cf0c2bde9a 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.spec.ts
@@ -1,14 +1,14 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { NgModule } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick } from '@angular/core/testing';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
-import { ChildViewContainerComponent, configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { ChildViewContainerComponent, configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { EventMetricDialogComponent } from './event-metric-dialog.component';
describe('EventMetricDialogComponent', () => {
configureTestingModule(() => ({
- imports: [DialogTestModule]
+ imports: [getTestTranslocoModule(), EventMetricDialogComponent],
+ providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
}));
let dialog: MatDialog;
@@ -61,9 +61,3 @@ describe('EventMetricDialogComponent', () => {
viewContainerFixture = TestBed.createComponent(ChildViewContainerComponent);
});
});
-
-@NgModule({
- imports: [TestTranslocoModule],
- providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
-})
-class DialogTestModule {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.ts
index e1f10097b2a..b9bcb5104b1 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metric-dialog.component.ts
@@ -1,9 +1,14 @@
-import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
+import { MatButton } from '@angular/material/button';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogContent,
+ MatDialogTitle
+} from '@angular/material/dialog';
import { TranslocoModule } from '@ngneat/transloco';
import { I18nService } from 'xforge-common/i18n.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { JsonViewerComponent } from '../shared/json-viewer/json-viewer.component';
import { EventMetric } from './event-metric';
@@ -11,7 +16,15 @@ import { EventMetric } from './event-metric';
selector: 'app-event-metric-dialog',
templateUrl: './event-metric-dialog.component.html',
styleUrls: ['./event-metric-dialog.component.scss'],
- imports: [CommonModule, MatDialogModule, TranslocoModule, UICommonModule, JsonViewerComponent]
+ imports: [
+ MatButton,
+ MatDialogTitle,
+ MatDialogContent,
+ MatDialogActions,
+ MatDialogClose,
+ TranslocoModule,
+ JsonViewerComponent
+ ]
})
export class EventMetricDialogComponent {
constructor(
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.spec.ts
index 3b48aff8df2..78835758cde 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.spec.ts
@@ -2,7 +2,7 @@ import { DebugElement, getDebugNode } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MatDialogRef } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { SystemRole } from 'realtime-server/lib/esm/common/models/system-role';
import { BehaviorSubject } from 'rxjs';
import { anything, instance, mock, verify, when } from 'ts-mockito';
@@ -11,9 +11,9 @@ import { AuthService } from 'xforge-common/auth.service';
import { DialogService } from 'xforge-common/dialog.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { QueryResults } from 'xforge-common/query-parameters';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
import { SFProjectService } from '../core/sf-project.service';
import { EventMetric, EventScope } from './event-metric';
@@ -28,14 +28,16 @@ const mockedUserService = mock(UserService);
describe('EventMetricsLogComponent', () => {
configureTestingModule(() => ({
- imports: [NoopAnimationsModule, TestOnlineStatusModule.forRoot(), TestTranslocoModule],
+ imports: [getTestTranslocoModule()],
providers: [
+ provideTestOnlineStatus(),
{ provide: AuthService, useMock: mockedAuthService },
{ provide: ActivatedProjectService, useMock: mockedActivatedProjectService },
{ provide: DialogService, useMock: mockDialogService },
{ provide: OnlineStatusService, useClass: TestOnlineStatusService },
{ provide: SFProjectService, useMock: mockedProjectService },
- { provide: UserService, useMock: mockedUserService }
+ { provide: UserService, useMock: mockedUserService },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.ts
index 9cbd18eb5bf..7307725cdf3 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics-log.component.ts
@@ -1,5 +1,20 @@
import { Component, DestroyRef, OnInit } from '@angular/core';
+import { MatButton } from '@angular/material/button';
import { MatDialogConfig } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { MatPaginator } from '@angular/material/paginator';
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatTable
+} from '@angular/material/table';
import { TranslocoModule } from '@ngneat/transloco';
import { SystemRole } from 'realtime-server/lib/esm/common/models/system-role';
import { BehaviorSubject, combineLatest, switchMap } from 'rxjs';
@@ -11,7 +26,6 @@ import { I18nService } from 'xforge-common/i18n.service';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { OwnerComponent } from 'xforge-common/owner/owner.component';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { filterNullish, quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { SFProjectService } from '../core/sf-project.service';
import { EventMetric } from './event-metric';
@@ -29,7 +43,23 @@ interface Row {
selector: 'app-event-metrics-log',
templateUrl: './event-metrics-log.component.html',
styleUrls: ['./event-metrics-log.component.scss'],
- imports: [OwnerComponent, TranslocoModule, UICommonModule]
+ imports: [
+ OwnerComponent,
+ TranslocoModule,
+ MatButton,
+ MatIcon,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatCell,
+ MatCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatPaginator
+ ]
})
export class EventMetricsLogComponent extends DataLoadingComponent implements OnInit {
columnsToDisplay: string[] = ['successful', 'scope', 'eventType', 'author'];
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics.component.spec.ts
index 6c55aec8499..6b587ba2815 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/event-metrics/event-metrics.component.spec.ts
@@ -1,10 +1,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { EventMetricsComponent } from './event-metrics.component';
describe('EventMetricsComponent', () => {
configureTestingModule(() => ({
- imports: [TestTranslocoModule]
+ imports: [getTestTranslocoModule()]
}));
it('should be created', () => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.spec.ts
index 0530c5d7b40..0240e965c3e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.spec.ts
@@ -1,7 +1,7 @@
import { DebugElement, ErrorHandler } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { ActivatedRoute, Router } from '@angular/router';
import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role';
import { of } from 'rxjs';
@@ -14,12 +14,11 @@ import { ErrorReportingService } from 'xforge-common/error-reporting.service';
import { I18nService } from 'xforge-common/i18n.service';
import { LocationService } from 'xforge-common/location.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { SF_TYPE_REGISTRY } from '../core/models/sf-type-registry';
import { SFProjectService } from '../core/sf-project.service';
import { NoticeComponent } from '../shared/notice/notice.component';
@@ -38,16 +37,10 @@ const mockedErrorHandler = mock(ErrorHandler);
describe('JoinComponent', () => {
configureTestingModule(() => ({
- declarations: [JoinComponent],
- imports: [
- NoopAnimationsModule,
- TestTranslocoModule,
- TestRealtimeModule.forRoot(SF_TYPE_REGISTRY),
- TestOnlineStatusModule.forRoot(),
- UICommonModule,
- NoticeComponent
- ],
+ imports: [JoinComponent, getTestTranslocoModule(), NoticeComponent],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
+ provideTestOnlineStatus(),
{ provide: ActivatedRoute, useMock: mockedActivatedRoute },
{ provide: AnonymousService, useMock: mockedAnonymousService },
{ provide: AuthService, useMock: mockedAuthService },
@@ -58,7 +51,8 @@ describe('JoinComponent', () => {
{ provide: Router, useMock: mockedRouter },
{ provide: ErrorReportingService, useMock: mockErrorReportingService },
{ provide: SFProjectService, useMock: mockedSFProjectService },
- { provide: ErrorHandler, useMock: mockedErrorHandler }
+ { provide: ErrorHandler, useMock: mockedErrorHandler },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.ts
index 56583838661..5996135d5ff 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.component.ts
@@ -1,7 +1,12 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Component, DestroyRef, ErrorHandler } from '@angular/core';
-import { FormControl, Validators } from '@angular/forms';
+import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
+import { MatButton } from '@angular/material/button';
+import { MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { ActivatedRoute, Router } from '@angular/router';
+import { TranslocoModule } from '@ngneat/transloco';
import { combineLatest } from 'rxjs';
import { distinctUntilChanged, filter, map } from 'rxjs/operators';
import { AnonymousService } from 'xforge-common/anonymous.service';
@@ -18,6 +23,7 @@ import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { XFValidators } from 'xforge-common/xfvalidators';
import { ObjectPaths } from '../../type-utils';
import { SFProjectService } from '../core/sf-project.service';
+import { NoticeComponent } from '../shared/notice/notice.component';
export interface AnonymousShareKeyDetails {
projectName: string;
role: string;
@@ -39,7 +45,17 @@ export const KNOWN_ERROR_CODES: ObjectPaths[] = [
selector: 'app-join',
templateUrl: './join.component.html',
styleUrls: ['./join.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ NoticeComponent,
+ FormsModule,
+ MatFormField,
+ MatLabel,
+ MatInput,
+ ReactiveFormsModule,
+ MatButton,
+ MatProgressSpinner
+ ]
})
export class JoinComponent extends DataLoadingComponent {
name: FormControl = new FormControl('');
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.stories.ts
index f9c8d410fbb..7cb0baba91e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/join/join.stories.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { ActivatedRoute, Router } from '@angular/router';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
@@ -10,11 +9,9 @@ import { AuthService } from 'xforge-common/auth.service';
import { CommandError, CommandErrorCode } from 'xforge-common/command.service';
import { DialogService } from 'xforge-common/dialog.service';
import { GenericDialogComponent } from 'xforge-common/generic-dialog/generic-dialog.component';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
import { LocationService } from 'xforge-common/location.service';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { SFProjectService } from '../core/sf-project.service';
import { NoticeComponent } from '../shared/notice/notice.component';
import { JoinComponent } from './join.component';
@@ -70,8 +67,7 @@ const meta: Meta = {
},
decorators: [
moduleMetadata({
- imports: [UICommonModule, CommonModule, I18nStoryModule, NoticeComponent],
- declarations: [GenericDialogComponent],
+ imports: [NoticeComponent, GenericDialogComponent],
providers: [
{ provide: ActivatedRoute, useValue: instance(mockedActivatedRoute) },
{
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/machine-api/remote-translation-engine.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/machine-api/remote-translation-engine.spec.ts
index ecca87c3f90..c473161c659 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/machine-api/remote-translation-engine.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/machine-api/remote-translation-engine.spec.ts
@@ -7,7 +7,7 @@ import { of, throwError } from 'rxjs';
import { anything, instance, mock, when } from 'ts-mockito';
import { I18nService } from 'xforge-common/i18n.service';
import { NoticeService } from 'xforge-common/notice.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { BuildDto } from './build-dto';
import { BuildStates } from './build-states';
import { EngineDto } from './engine-dto';
@@ -20,7 +20,7 @@ import { WordGraphDto } from './word-graph-dto';
describe('RemoteTranslationEngine', () => {
configureTestingModule(() => ({
- imports: [TestTranslocoModule]
+ imports: [getTestTranslocoModule()]
}));
it('get word graph', async () => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.spec.ts
index d8577cee90a..670edc0e91d 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.spec.ts
@@ -3,7 +3,7 @@ import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { provideAnimations } from '@angular/platform-browser/animations';
-import { Router, RouterModule } from '@angular/router';
+import { provideRouter, Router } from '@angular/router';
import { User } from 'realtime-server/lib/esm/common/models/user';
import { createTestUser } from 'realtime-server/lib/esm/common/models/user-test-data';
import { createTestProjectProfile } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-test-data';
@@ -13,10 +13,9 @@ import { anything, mock, verify, when } from 'ts-mockito';
import { UserDoc } from 'xforge-common/models/user-doc';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { TestOnlineStatusService } from 'xforge-common/test-online-status.service';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { SFUserProjectsService } from 'xforge-common/user-projects.service';
import { UserService } from 'xforge-common/user.service';
import { ParatextProject } from '../core/models/paratext-project';
@@ -24,11 +23,10 @@ import { SFProjectProfileDoc } from '../core/models/sf-project-profile-doc';
import { SFProjectUserConfigDoc } from '../core/models/sf-project-user-config-doc';
import { ParatextService } from '../core/paratext.service';
import { SFProjectService } from '../core/sf-project.service';
-import { SharedModule } from '../shared/shared.module';
+import { provideQuillRegistrations } from '../shared/text/quill-editor-registration/quill-providers';
import { MyProjectsComponent } from './my-projects.component';
@Component({
- template: '',
- standalone: false
+ template: ''
})
class EmptyComponent {}
@@ -40,18 +38,14 @@ const mockedNoticeService = mock(NoticeService);
describe('MyProjectsComponent', () => {
configureTestingModule(() => ({
- declarations: [MyProjectsComponent],
- imports: [
- UICommonModule,
- SharedModule.forRoot(),
- RouterModule.forRoot([
+ imports: [MyProjectsComponent, getTestTranslocoModule()],
+ providers: [
+ provideRouter([
{ path: 'projects/:projectId', component: EmptyComponent },
{ path: 'connect-project', component: EmptyComponent }
]),
- TestOnlineStatusModule.forRoot(),
- TestTranslocoModule
- ],
- providers: [
+ provideQuillRegistrations(),
+ provideTestOnlineStatus(),
provideAnimations(),
{ provide: SFProjectService, useMock: mockedSFProjectService },
{ provide: UserService, useMock: mockedUserService },
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.ts
index 657abd6b96c..11930eac878 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.component.ts
@@ -1,6 +1,13 @@
+import { AsyncPipe } from '@angular/common';
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { Component, DestroyRef, OnInit } from '@angular/core';
+import { MatAnchor, MatButton } from '@angular/material/button';
+import { MatCard } from '@angular/material/card';
+import { MatRipple } from '@angular/material/core';
+import { MatExpansionPanel, MatExpansionPanelHeader } from '@angular/material/expansion';
+import { MatIcon } from '@angular/material/icon';
import { Router } from '@angular/router';
+import { TranslocoModule } from '@ngneat/transloco';
import { isPTUser } from 'realtime-server/lib/esm/common/models/user';
import { isResource } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
import { Observable } from 'rxjs';
@@ -8,6 +15,7 @@ import { en, I18nService } from 'xforge-common/i18n.service';
import { UserDoc } from 'xforge-common/models/user-doc';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
+import { RouterLinkDirective } from 'xforge-common/router-link.directive';
import { SFUserProjectsService } from 'xforge-common/user-projects.service';
import { UserService } from 'xforge-common/user.service';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
@@ -19,12 +27,25 @@ import { SFProjectProfileDoc } from '../core/models/sf-project-profile-doc';
import { ParatextService } from '../core/paratext.service';
import { PermissionsService } from '../core/permissions.service';
import { SFProjectService } from '../core/sf-project.service';
+import { NoticeComponent } from '../shared/notice/notice.component';
/** Presents user with list of available projects to open or connect to. */
@Component({
selector: 'app-my-projects',
templateUrl: './my-projects.component.html',
styleUrls: ['./my-projects.component.scss'],
- standalone: false
+ imports: [
+ TranslocoModule,
+ NoticeComponent,
+ MatCard,
+ MatButton,
+ MatIcon,
+ MatRipple,
+ RouterLinkDirective,
+ MatExpansionPanel,
+ MatExpansionPanelHeader,
+ MatAnchor,
+ AsyncPipe
+ ]
})
export class MyProjectsComponent implements OnInit {
/** PT projects that the user can access. */
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.stories.ts
index 53fd587d4d4..ea0c50c00d2 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/my-projects/my-projects.stories.ts
@@ -1,7 +1,6 @@
import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { Component } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';
-import { ActivatedRoute, RouterModule } from '@angular/router';
+import { ActivatedRoute } from '@angular/router';
import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { User } from 'realtime-server/lib/esm/common/models/user';
import { createTestUser } from 'realtime-server/lib/esm/common/models/user-test-data';
@@ -12,9 +11,7 @@ import { anything, instance, mock, objectContaining, when } from 'ts-mockito';
import { UserDoc } from 'xforge-common/models/user-doc';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
-import { TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { getTestTranslocoModule } from 'xforge-common/test-utils';
import { SFUserProjectsService } from 'xforge-common/user-projects.service';
import { UserService } from 'xforge-common/user.service';
import { ParatextProject } from '../core/models/paratext-project';
@@ -22,12 +19,8 @@ import { SFProjectProfileDoc } from '../core/models/sf-project-profile-doc';
import { ParatextService } from '../core/paratext.service';
import { PermissionsService } from '../core/permissions.service';
import { SFProjectService } from '../core/sf-project.service';
-import { SharedModule } from '../shared/shared.module';
import { MyProjectsComponent } from './my-projects.component';
-@Component({ template: '' })
-class EmptyComponent {}
-
const mockedActivatedRoute = mock(ActivatedRoute);
const mockedUserService = mock(UserService);
const mockedSFProjectService = mock(SFProjectService);
@@ -190,17 +183,7 @@ const meta: Meta = {
},
decorators: [
moduleMetadata({
- imports: [
- UICommonModule,
- SharedModule.forRoot(),
- RouterModule.forChild([
- { path: 'projects/:projectId', component: EmptyComponent },
- { path: 'connect-project', component: EmptyComponent }
- ]),
- TestOnlineStatusModule.forRoot(),
- TestTranslocoModule
- ],
- declarations: [MyProjectsComponent],
+ imports: [getTestTranslocoModule(), MyProjectsComponent],
providers: [
provideAnimations(),
provideHttpClientTesting(),
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.component.ts
index e163f03eef1..375df66ab9f 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.component.ts
@@ -1,5 +1,10 @@
+import { AsyncPipe } from '@angular/common';
import { Component, EventEmitter, Output } from '@angular/core';
+import { MatBadge } from '@angular/material/badge';
+import { MatIcon } from '@angular/material/icon';
+import { MatListItem, MatNavList } from '@angular/material/list';
import { Router } from '@angular/router';
+import { TranslocoModule } from '@ngneat/transloco';
import { Operation } from 'realtime-server/lib/esm/common/models/project-rights';
import { SF_PROJECT_RIGHTS, SFProjectDomain } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-rights';
import { SFProjectRole } from 'realtime-server/lib/esm/scriptureforge/models/sf-project-role';
@@ -9,6 +14,7 @@ import { ActivatedProjectService } from 'xforge-common/activated-project.service
import { FeatureFlagService } from 'xforge-common/feature-flags/feature-flag.service';
import { I18nService } from 'xforge-common/i18n.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
+import { RouterLinkDirective } from 'xforge-common/router-link.directive';
import { UserService } from 'xforge-common/user.service';
import { ResumeCheckingService } from '../checking/checking/resume-checking.service';
import { ResumeTranslateService } from '../checking/checking/resume-translate.service';
@@ -20,7 +26,7 @@ import { NmtDraftAuthGuard, SettingsAuthGuard, SyncAuthGuard, UsersAuthGuard } f
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss'],
- standalone: false
+ imports: [TranslocoModule, MatNavList, MatListItem, RouterLinkDirective, MatIcon, MatBadge, AsyncPipe]
})
export class NavigationComponent {
canSeeSettings$: Observable = this.activatedProjectService.projectId$.pipe(
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.stories.ts
index 946c9c98f61..609f7449c32 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/navigation/navigation.stories.ts
@@ -1,4 +1,3 @@
-import { CommonModule } from '@angular/common';
import { TestBed } from '@angular/core/testing';
import { ActivatedRoute, Router } from '@angular/router';
import { SwUpdate } from '@angular/service-worker';
@@ -13,11 +12,10 @@ import { ActivatedProjectService, TestActivatedProjectService } from 'xforge-com
import { AuthGuard } from 'xforge-common/auth.guard';
import { AuthService } from 'xforge-common/auth.service';
import { createTestFeatureFlag, FeatureFlagService } from 'xforge-common/feature-flags/feature-flag.service';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
+import { provideI18nStory } from 'xforge-common/i18n-story';
import { OnlineStatusService } from 'xforge-common/online-status.service';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { UserService } from 'xforge-common/user.service';
import { ResumeCheckingService } from '../checking/checking/resume-checking.service';
import { ResumeTranslateService } from '../checking/checking/resume-translate.service';
@@ -66,8 +64,11 @@ function setUpMocks(args: StoryState): void {
TestBed.resetTestingModule();
TestBed.configureTestingModule({
- imports: [I18nStoryModule, TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
- providers: [{ provide: UserService, useValue: instance(mockedUserService) }]
+ providers: [
+ provideI18nStory(),
+ provideTestRealtime(SF_TYPE_REGISTRY),
+ { provide: UserService, useValue: instance(mockedUserService) }
+ ]
});
const realtimeService: TestRealtimeService = TestBed.inject(TestRealtimeService);
@@ -107,7 +108,6 @@ const meta: Meta = {
setUpMocks(args as StoryState);
return {
moduleMetadata: {
- imports: [UICommonModule, CommonModule, I18nStoryModule],
providers: [
{ provide: AuthService, useValue: instance(mockedAuthService) },
{
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/permissions-viewer/permissions-viewer.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/permissions-viewer/permissions-viewer.component.ts
index 54df9eea013..640da4524a1 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/permissions-viewer/permissions-viewer.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/permissions-viewer/permissions-viewer.component.ts
@@ -13,8 +13,7 @@ const permissions = rightsByRole;
@Component({
selector: 'app-permissions-viewer',
templateUrl: './permissions-viewer.component.html',
- styleUrls: ['./permissions-viewer.component.scss'],
- standalone: false
+ styleUrls: ['./permissions-viewer.component.scss']
})
export class PermissionsViewerComponent implements OnInit {
// All available roles
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.spec.ts
index d1554c6c312..d96ddb17676 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.spec.ts
@@ -1,9 +1,8 @@
import { Component, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
-import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { ReactiveFormsModule, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
+import { getTestTranslocoModule } from 'xforge-common/test-utils';
import { isSafari } from 'xforge-common/utils';
import { SelectableProject } from '../core/paratext.service';
import { CustomValidatorState, SFValidators } from '../shared/sfvalidators';
@@ -202,7 +201,7 @@ describe('ProjectSelectComponent', () => {
[isDisabled]="isDisabled"
>
`,
- standalone: false
+ imports: [ReactiveFormsModule, ProjectSelectComponent]
})
class HostComponent {
readonly sourceParatextId = new UntypedFormControl(undefined);
@@ -235,8 +234,8 @@ class TestEnvironment {
nonSelectableProjects?: SelectableProject[]
) {
TestBed.configureTestingModule({
- declarations: [HostComponent, ProjectSelectComponent],
- imports: [UICommonModule, TestTranslocoModule, NoopAnimationsModule]
+ imports: [ReactiveFormsModule, getTestTranslocoModule(), HostComponent],
+ providers: [provideNoopAnimations()]
});
this.fixture = TestBed.createComponent(HostComponent);
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts
index a391585e046..710b65a3dc5 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.component.ts
@@ -1,8 +1,18 @@
+import { AsyncPipe } from '@angular/common';
import { Component, DestroyRef, EventEmitter, forwardRef, Input, OnDestroy, Output, ViewChild } from '@angular/core';
-import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, ValidatorFn } from '@angular/forms';
-import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete';
+import {
+ ControlValueAccessor,
+ FormControl,
+ FormsModule,
+ NG_VALUE_ACCESSOR,
+ ReactiveFormsModule,
+ ValidatorFn
+} from '@angular/forms';
+import { MatAutocomplete, MatAutocompleteTrigger, MatOptgroup, MatOption } from '@angular/material/autocomplete';
import { ShowOnDirtyErrorStateMatcher } from '@angular/material/core';
-import { translate } from '@ngneat/transloco';
+import { MatError, MatFormField } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
+import { translate, TranslocoModule } from '@ngneat/transloco';
import { BehaviorSubject, combineLatest, fromEvent, Observable } from 'rxjs';
import { distinctUntilChanged, map, shareReplay, startWith, takeUntil, tap } from 'rxjs/operators';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
@@ -10,6 +20,7 @@ import { hasPropWithValue } from '../../type-utils';
import { SelectableProject } from '../core/paratext.service';
import { SFValidators } from '../shared/sfvalidators';
import { projectLabel } from '../shared/utils';
+
// A value accessor is necessary in order to create a custom form control
export const PROJECT_SELECT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
@@ -23,7 +34,19 @@ export const PROJECT_SELECT_VALUE_ACCESSOR: any = {
templateUrl: 'project-select.component.html',
styleUrls: ['project-select.component.scss'],
providers: [PROJECT_SELECT_VALUE_ACCESSOR],
- standalone: false
+ imports: [
+ TranslocoModule,
+ MatFormField,
+ MatInput,
+ FormsModule,
+ MatAutocompleteTrigger,
+ ReactiveFormsModule,
+ MatError,
+ MatAutocomplete,
+ MatOptgroup,
+ MatOption,
+ AsyncPipe
+ ]
})
export class ProjectSelectComponent implements ControlValueAccessor, OnDestroy {
@Output() valueChange: EventEmitter = new EventEmitter(true);
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.stories.ts
index 101d4e99284..6050fbf3ca0 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/project-select/project-select.stories.ts
@@ -1,21 +1,13 @@
-import { TranslocoModule } from '@ngneat/transloco';
-import { Meta, moduleMetadata, StoryObj } from '@storybook/angular';
+import { Meta, StoryObj } from '@storybook/angular';
import { expect, within } from '@storybook/test';
import userEvent from '@testing-library/user-event';
-import { I18nStoryModule } from 'xforge-common/i18n-story.module';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { SelectableProjectWithLanguageCode } from '../core/paratext.service';
import { projectLabel } from '../shared/utils';
import { ProjectSelectComponent } from './project-select.component';
const meta: Meta = {
title: 'Utility/ProjectSelect',
- component: ProjectSelectComponent,
- decorators: [
- moduleMetadata({
- imports: [I18nStoryModule, TranslocoModule, UICommonModule]
- })
- ]
+ component: ProjectSelectComponent
};
export default meta;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.spec.ts
index 2deb03407cd..037ecaa99fd 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.spec.ts
@@ -17,7 +17,7 @@ import { of } from 'rxjs';
import { anything, deepEqual, mock, verify, when } from 'ts-mockito';
import { DialogService } from 'xforge-common/dialog.service';
import { UserDoc } from 'xforge-common/models/user-doc';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import { configureTestingModule } from 'xforge-common/test-utils';
import { UserService } from 'xforge-common/user.service';
@@ -36,8 +36,8 @@ const mockedDialogService = mock(DialogService);
describe('ProjectComponent', () => {
configureTestingModule(() => ({
- imports: [TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: UserService, useMock: mockedUserService },
{ provide: ActivatedRoute, useMock: mockedActivatedRoute },
{ provide: Router, useMock: mockedRouter },
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.ts
index 73a3f780d97..ce14463708f 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/project/project.component.ts
@@ -18,8 +18,7 @@ type TaskType = 'translate' | 'checking';
@Component({
selector: 'app-projects',
templateUrl: './project.component.html',
- styleUrls: ['./project.component.scss'],
- standalone: false
+ styleUrls: ['./project.component.scss']
})
export class ProjectComponent extends DataLoadingComponent implements OnInit {
constructor(
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.spec.ts
index 1ba653028f3..3005f4cc894 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.spec.ts
@@ -1,20 +1,20 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { DebugElement, NgModule } from '@angular/core';
+import { DebugElement } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing';
import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { Canon, VerseRef } from '@sillsdev/scripture';
import { TextInfo } from 'realtime-server/lib/esm/scriptureforge/models/text-info';
-import { ChildViewContainerComponent, configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
+import { ChildViewContainerComponent, configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { TextsByBookId } from '../core/models/texts-by-book-id';
import { ScriptureChooserDialogComponent, ScriptureChooserDialogData } from './scripture-chooser-dialog.component';
describe('ScriptureChooserDialog', () => {
configureTestingModule(() => ({
- imports: [TestModule]
+ imports: [getTestTranslocoModule(), ScriptureChooserDialogComponent],
+ providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), provideNoopAnimations()]
}));
let env: TestEnvironment;
@@ -397,13 +397,6 @@ describe('ScriptureChooserDialog', () => {
expect(env.component.selection.chapter).toBeUndefined();
}));
- @NgModule({
- declarations: [ScriptureChooserDialogComponent],
- imports: [UICommonModule, TestTranslocoModule, NoopAnimationsModule],
- providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()]
- })
- class TestModule {}
-
class TestEnvironment {
fixture: ComponentFixture;
component: ScriptureChooserDialogComponent;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.ts
index 0cf07e3319c..eb7b5b33cb5 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/scripture-chooser-dialog/scripture-chooser-dialog.component.ts
@@ -1,5 +1,9 @@
+import { CdkScrollable } from '@angular/cdk/scrolling';
import { Component, Inject, OnInit } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { MatButton, MatIconButton } from '@angular/material/button';
+import { MAT_DIALOG_DATA, MatDialogContent, MatDialogRef, MatDialogTitle } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { TranslocoModule } from '@ngneat/transloco';
import { Canon, VerseRef } from '@sillsdev/scripture';
import { I18nService } from 'xforge-common/i18n.service';
import { TextsByBookId } from '../core/models/texts-by-book-id';
@@ -29,7 +33,7 @@ export interface ScriptureChooserDialogData {
selector: 'app-scripture-reference-chooser',
templateUrl: './scripture-chooser-dialog.component.html',
styleUrls: ['./scripture-chooser-dialog.component.scss'],
- standalone: false
+ imports: [TranslocoModule, MatDialogTitle, MatIconButton, MatIcon, CdkScrollable, MatDialogContent, MatButton]
})
export class ScriptureChooserDialogComponent implements OnInit {
showing: 'books' | 'chapters' | 'verses' | 'rangeEnd' = 'books';
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/draft-jobs.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/draft-jobs.component.ts
index 513c0985376..0010f5dff93 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/draft-jobs.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/draft-jobs.component.ts
@@ -1,5 +1,23 @@
import { Component, DestroyRef, OnInit } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
+import { MatOption } from '@angular/material/core';
import { MatDialogConfig } from '@angular/material/dialog';
+import { MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
+import { MatSelect } from '@angular/material/select';
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatTable
+} from '@angular/material/table';
+import { MatTooltip } from '@angular/material/tooltip';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { SystemRole } from 'realtime-server/lib/esm/common/models/system-role';
import { BehaviorSubject, combineLatest, map, Observable, switchMap } from 'rxjs';
@@ -10,7 +28,6 @@ import { I18nService } from 'xforge-common/i18n.service';
import { NoticeService } from 'xforge-common/notice.service';
import { OnlineStatusService } from 'xforge-common/online-status.service';
import { OwnerComponent } from 'xforge-common/owner/owner.component';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { SFProjectService } from '../core/sf-project.service';
import { EventMetric } from '../event-metrics/event-metric';
@@ -74,7 +91,28 @@ const DRAFTING_EVENTS = [
selector: 'app-draft-jobs',
templateUrl: './draft-jobs.component.html',
styleUrls: ['./draft-jobs.component.scss'],
- imports: [OwnerComponent, UICommonModule, RouterLink, NoticeComponent]
+ imports: [
+ OwnerComponent,
+ MatTooltip,
+ MatIconButton,
+ MatFormField,
+ MatLabel,
+ MatSelect,
+ MatOption,
+ MatIcon,
+ MatTable,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatCell,
+ MatCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ RouterLink,
+ NoticeComponent
+ ]
})
export class DraftJobsComponent extends DataLoadingComponent implements OnInit {
columnsToDisplay: string[] = [
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/job-details-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/job-details-dialog.component.ts
index a32f69469eb..89d5edc7153 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/job-details-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/job-details-dialog.component.ts
@@ -1,11 +1,16 @@
-import { CommonModule } from '@angular/common';
import { Component, Inject, OnInit } from '@angular/core';
-import { MatButtonModule } from '@angular/material/button';
-import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
-import { MatIconModule } from '@angular/material/icon';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatTabsModule } from '@angular/material/tabs';
-import { MatTooltipModule } from '@angular/material/tooltip';
+import { MatButton } from '@angular/material/button';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogContent,
+ MatDialogTitle
+} from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { MatProgressSpinner } from '@angular/material/progress-spinner';
+import { MatTab, MatTabGroup } from '@angular/material/tabs';
+import { MatTooltip } from '@angular/material/tooltip';
import { I18nService } from 'xforge-common/i18n.service';
import { L10nNumberPipe } from 'xforge-common/l10n-number.pipe';
import { EventMetric } from '../event-metrics/event-metric';
@@ -41,19 +46,21 @@ const EVENT_TYPE_LABELS: {
*/
@Component({
selector: 'app-job-details-dialog',
- standalone: true,
templateUrl: './job-details-dialog.component.html',
styleUrls: ['./job-details-dialog.component.scss'],
imports: [
- CommonModule,
- MatDialogModule,
- MatIconModule,
- MatProgressSpinnerModule,
- MatTabsModule,
- MatTooltipModule,
+ MatButton,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogContent,
+ MatDialogTitle,
+ MatIcon,
+ MatProgressSpinner,
+ MatTab,
+ MatTabGroup,
+ MatTooltip,
JsonViewerComponent,
NoticeComponent,
- MatButtonModule,
L10nNumberPipe
]
})
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.spec.ts
index 8d74b52d226..2bcf894bbf1 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.spec.ts
@@ -1,12 +1,12 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { ActivatedRoute } from '@angular/router';
import { of } from 'rxjs';
import { mock, when } from 'ts-mockito';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
-import { configureTestingModule, TestTranslocoModule } from 'xforge-common/test-utils';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
+import { configureTestingModule, getTestTranslocoModule } from 'xforge-common/test-utils';
import { SF_TYPE_REGISTRY } from '../core/models/sf-type-registry';
import { ServalAdministrationComponent } from './serval-administration.component';
@@ -15,11 +15,13 @@ when(mockedActivatedRoute.queryParams).thenReturn(of({}));
describe('ServalAdministrationComponent', () => {
configureTestingModule(() => ({
- imports: [NoopAnimationsModule, TestTranslocoModule, TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)],
+ imports: [getTestTranslocoModule()],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting(),
- { provide: ActivatedRoute, useMock: mockedActivatedRoute }
+ { provide: ActivatedRoute, useMock: mockedActivatedRoute },
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.ts
index b6d30f26714..f6b4442e281 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-administration.component.ts
@@ -1,7 +1,6 @@
import { Component, OnInit } from '@angular/core';
-import { MatTabsModule } from '@angular/material/tabs';
+import { MatTab, MatTabContent, MatTabGroup } from '@angular/material/tabs';
import { ActivatedRoute, Router } from '@angular/router';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { MobileNotSupportedComponent } from '../shared/mobile-not-supported/mobile-not-supported.component';
import { DraftJobsComponent } from './draft-jobs.component';
import { ServalProjectsComponent } from './serval-projects.component';
@@ -14,7 +13,14 @@ import { ServalProjectsComponent } from './serval-projects.component';
selector: 'app-serval-administration',
templateUrl: './serval-administration.component.html',
styleUrls: ['./serval-administration.component.scss'],
- imports: [ServalProjectsComponent, MobileNotSupportedComponent, DraftJobsComponent, MatTabsModule, UICommonModule]
+ imports: [
+ ServalProjectsComponent,
+ MobileNotSupportedComponent,
+ DraftJobsComponent,
+ MatTabGroup,
+ MatTab,
+ MatTabContent
+ ]
})
export class ServalAdministrationComponent implements OnInit {
selectedTabIndex = 0;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-project.component.html b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-project.component.html
index 59b81e3d395..9c2d925dfc4 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-project.component.html
+++ b/src/SIL.XForge.Scripture/ClientApp/src/app/serval-administration/serval-project.component.html
@@ -26,9 +26,9 @@ Pre-Translation Configuration
>
- `,
- standalone: false
+ `
})
class HostComponent {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flag.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flag.service.spec.ts
index ef50c811bc2..bd9938c1e2b 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flag.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flag.service.spec.ts
@@ -1,7 +1,7 @@
import { fakeAsync, flush, TestBed } from '@angular/core/testing';
import { mock, verify, when } from 'ts-mockito';
import { AnonymousService } from 'xforge-common/anonymous.service';
-import { TestOnlineStatusModule } from 'xforge-common/test-online-status.module';
+import { provideTestOnlineStatus } from 'xforge-common/test-online-status-providers';
import { configureTestingModule } from 'xforge-common/test-utils';
import { FeatureFlagService } from './feature-flag.service';
@@ -9,8 +9,7 @@ const mockedAnonymousService = mock(AnonymousService);
describe('FeatureFlagService', () => {
configureTestingModule(() => ({
- imports: [TestOnlineStatusModule.forRoot()],
- providers: [{ provide: AnonymousService, useMock: mockedAnonymousService }]
+ providers: [provideTestOnlineStatus(), { provide: AnonymousService, useMock: mockedAnonymousService }]
}));
it('sets and gets the enabled property', fakeAsync(() => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.spec.ts
index 734a2b36d62..07d8577170c 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.spec.ts
@@ -6,7 +6,6 @@ import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
import { mock, when } from 'ts-mockito';
import { ChildViewContainerComponent, configureTestingModule } from 'xforge-common/test-utils';
-import { UICommonModule } from 'xforge-common/ui-common.module';
import { NoticeComponent } from '../../app/shared/notice/notice.component';
import { FeatureFlagService } from './feature-flag.service';
import { FeatureFlagsDialogComponent } from './feature-flags-dialog.component';
@@ -15,8 +14,7 @@ const mockedFeatureFlagService = mock(FeatureFlagService);
describe('FeatureFlagsComponent', () => {
configureTestingModule(() => ({
- declarations: [FeatureFlagsDialogComponent],
- imports: [UICommonModule, NoticeComponent],
+ imports: [FeatureFlagsDialogComponent, NoticeComponent],
providers: [{ provide: FeatureFlagService, useMock: mockedFeatureFlagService }]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.ts
index aeb482ec37a..11e3f4230a7 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/feature-flags/feature-flags-dialog.component.ts
@@ -1,10 +1,16 @@
+import { CdkScrollable } from '@angular/cdk/scrolling';
import { Component } from '@angular/core';
+import { FormsModule } from '@angular/forms';
+import { MatCheckbox } from '@angular/material/checkbox';
+import { MatDialogContent, MatDialogTitle } from '@angular/material/dialog';
+import { MatIcon } from '@angular/material/icon';
+import { NoticeComponent } from '../../app/shared/notice/notice.component';
import { FeatureFlagService } from './feature-flag.service';
@Component({
templateUrl: './feature-flags-dialog.component.html',
styleUrls: ['./feature-flags-dialog.component.scss'],
- standalone: false
+ imports: [MatDialogTitle, MatIcon, CdkScrollable, MatDialogContent, NoticeComponent, MatCheckbox, FormsModule]
})
export class FeatureFlagsDialogComponent {
constructor(readonly featureFlags: FeatureFlagService) {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.spec.ts
index c70c0534bb1..2a2dd507578 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/file.service.spec.ts
@@ -12,9 +12,9 @@ import { FileService, formatFileSource } from './file.service';
import { createDeletionFileData, createStorageFileData, FileOfflineData, FileType } from './models/file-offline-data';
import { ProjectDataDoc } from './models/project-data-doc';
import { OnlineStatusService } from './online-status.service';
-import { TestOnlineStatusModule } from './test-online-status.module';
+import { provideTestOnlineStatus } from './test-online-status-providers';
import { TestOnlineStatusService } from './test-online-status.service';
-import { TestRealtimeModule } from './test-realtime.module';
+import { provideTestRealtime } from './test-realtime-providers';
import { TestRealtimeService } from './test-realtime.service';
import { TypeRegistry } from './type-registry';
import { COMMAND_API_NAMESPACE, PROJECTS_URL } from './url-constants';
@@ -25,11 +25,9 @@ const mockedDialogService = mock(DialogService);
describe('FileService', () => {
configureTestingModule(() => ({
- imports: [
- TestOnlineStatusModule.forRoot(),
- TestRealtimeModule.forRoot(new TypeRegistry([TestDataDoc], [FileType.Audio], []))
- ],
providers: [
+ provideTestRealtime(new TypeRegistry([TestDataDoc], [FileType.Audio], [])),
+ provideTestOnlineStatus(),
FileService,
{ provide: OnlineStatusService, useClass: TestOnlineStatusService },
{ provide: AuthService, useMock: mockedAuthService },
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/generic-dialog/generic-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/generic-dialog/generic-dialog.component.ts
index c723f78d39d..7ba36bc383e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/generic-dialog/generic-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/generic-dialog/generic-dialog.component.ts
@@ -1,6 +1,16 @@
import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogRef,
+ MatDialogTitle,
+ MatDialogContent,
+ MatDialogActions,
+ MatDialogClose
+} from '@angular/material/dialog';
import { Observable } from 'rxjs';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { MatButton } from '@angular/material/button';
+import { AsyncPipe } from '@angular/common';
export interface GenericDialogOptions
{
title?: Observable;
@@ -23,7 +33,7 @@ export interface GenericDialogRef {
@Component({
selector: 'app-generic-dialog',
templateUrl: './generic-dialog.component.html',
- standalone: false
+ imports: [MatDialogTitle, CdkScrollable, MatDialogContent, MatDialogActions, MatButton, MatDialogClose, AsyncPipe]
})
export class GenericDialogComponent {
constructor(@Inject(MAT_DIALOG_DATA) private readonly data: GenericDialogOptions) {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-story.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-story.ts
similarity index 71%
rename from src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-story.module.ts
rename to src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-story.ts
index 4cd2bb7218a..b20354d79b5 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-story.module.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-story.ts
@@ -1,5 +1,11 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
-import { APP_INITIALIZER, NgModule } from '@angular/core';
+import {
+ EnvironmentProviders,
+ importProvidersFrom,
+ inject,
+ makeEnvironmentProviders,
+ provideAppInitializer
+} from '@angular/core';
import { TRANSLOCO_CONFIG, TRANSLOCO_LOADER, TranslocoConfig, TranslocoModule } from '@ngneat/transloco';
import { DecoratorFunction } from '@storybook/types';
import { I18nService, IGNORE_COOKIE_LOCALE, TranslationLoader } from './i18n.service';
@@ -9,14 +15,6 @@ let selectedLocale: string | undefined;
const translocoConfig: TranslocoConfig = { ...I18nService.translocoConfig, prodMode: false };
-function localizationInit(transloco: I18nService): () => void {
- return () => {
- i18nService = transloco;
-
- if (selectedLocale != null) i18nService.trySetLocale(selectedLocale);
- };
-}
-
export const I18nStoryDecorator: DecoratorFunction = (Story, context) => {
// In some cases the locale has been known to be the empty string, so make sure not to set it to that.
const locale = context.parameters.locale || context.globals.locale || I18nService.defaultLocale.canonicalTag;
@@ -25,14 +23,18 @@ export const I18nStoryDecorator: DecoratorFunction = (Story, context) => {
return Story();
};
-@NgModule({
- exports: [TranslocoModule],
- providers: [
- { provide: APP_INITIALIZER, useFactory: localizationInit, deps: [I18nService], multi: true },
+export function provideI18nStory(): EnvironmentProviders {
+ return makeEnvironmentProviders([
+ provideAppInitializer(() => {
+ i18nService = inject(I18nService);
+ if (selectedLocale != null) {
+ i18nService.trySetLocale(selectedLocale);
+ }
+ }),
+ importProvidersFrom(TranslocoModule),
{ provide: TRANSLOCO_CONFIG, useValue: translocoConfig },
{ provide: TRANSLOCO_LOADER, useClass: TranslationLoader },
{ provide: IGNORE_COOKIE_LOCALE, useValue: true },
provideHttpClient(withInterceptorsFromDi())
- ]
-})
-export class I18nStoryModule {}
+ ]);
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-transpilers/em-text.transpiler.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-transpilers/em-text.transpiler.spec.ts
index 3759d1db909..522a76cf879 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-transpilers/em-text.transpiler.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/i18n-transpilers/em-text.transpiler.spec.ts
@@ -6,7 +6,7 @@ import {
TranslationMarkupRendererFactory,
TranslocoMarkupModule
} from 'ngx-transloco-markup';
-import { TestTranslocoModule } from '../test-utils';
+import { getTestTranslocoModule } from '../test-utils';
import { EmTextTranspiler } from './em-text.transpiler';
function createTestTranspiler(): EmTextTranspiler {
@@ -39,9 +39,8 @@ describe('EmTextTranspiler', () => {
beforeEach(() => {
TestBed.configureTestingModule({
- imports: [TestTranslocoModule, TranslocoMarkupModule],
- providers: [provideTranslationMarkupTranspiler(EmTextTranspiler)],
- declarations: [TestComponent]
+ imports: [getTestTranslocoModule(), TranslocoMarkupModule, TestComponent],
+ providers: [provideTranslationMarkupTranspiler(EmTextTranspiler)]
});
fixture = TestBed.createComponent(TestComponent);
@@ -62,7 +61,7 @@ describe('EmTextTranspiler', () => {
@Component({
selector: 'app-test',
template: ``,
- standalone: false
+ imports: [TranslocoMarkupModule]
})
export class TestComponent {
translation: string = '';
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/overlay-container.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/overlay-container.spec.ts
index cdc94fd0b61..1cc31fd89f4 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/overlay-container.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/overlay-container.spec.ts
@@ -3,7 +3,7 @@ import { Component, DebugElement, TemplateRef, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
import { InAppRootOverlayContainer } from './overlay-container';
describe('OverlayContainer', () => {
@@ -15,26 +15,9 @@ describe('OverlayContainer', () => {
}));
});
-/**
- * Host component is generated to contain the element. When tests are rendered the initial component
- * is only rendered as a element whereas this test specifically needs access to the
element
- */
-@Component({
- selector: 'app-host',
- template: '',
- standalone: false
-})
-class HostComponent {
- @ViewChild('root') appRoot?: AppRootComponent;
-
- open(): void {
- this.appRoot?.open();
- }
-}
@Component({
selector: 'app-root',
- template: 'Opened
',
- standalone: false
+ template: 'Opened
'
})
class AppRootComponent {
@ViewChild('bottomSheet') TemplateBottomSheet?: TemplateRef;
@@ -49,15 +32,31 @@ class AppRootComponent {
}
}
+/**
+ * Host component is generated to contain the element. When tests are rendered the initial component
+ * is only rendered as a element whereas this test specifically needs access to the
element
+ */
+@Component({
+ selector: 'app-host',
+ template: '',
+ imports: [AppRootComponent]
+})
+class HostComponent {
+ @ViewChild('root') appRoot?: AppRootComponent;
+
+ open(): void {
+ this.appRoot?.open();
+ }
+}
+
class TestEnvironment {
readonly component: HostComponent;
readonly fixture: ComponentFixture;
constructor() {
TestBed.configureTestingModule({
- declarations: [HostComponent, AppRootComponent],
- imports: [NoopAnimationsModule],
- providers: [{ provide: OverlayContainer, useClass: InAppRootOverlayContainer }]
+ imports: [HostComponent, AppRootComponent],
+ providers: [{ provide: OverlayContainer, useClass: InAppRootOverlayContainer }, provideNoopAnimations()]
});
this.fixture = TestBed.createComponent(HostComponent);
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.spec.ts
index 255d47da357..6f57b8baf89 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.spec.ts
@@ -8,7 +8,7 @@ import { UserProfile } from 'realtime-server/lib/esm/common/models/user';
import { createTestUserProfile } from 'realtime-server/lib/esm/common/models/user-test-data';
import { anything, instance, mock, when } from 'ts-mockito';
import { UserProfileDoc } from 'xforge-common/models/user-profile-doc';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { TestRealtimeService } from 'xforge-common/test-realtime.service';
import { SF_TYPE_REGISTRY } from '../../app/core/models/sf-type-registry';
import { isSafari } from '../utils';
@@ -81,7 +81,7 @@ describe('OwnerComponent', () => {
@Component({
selector: 'app-host',
template: '',
- standalone: false
+ imports: [OwnerComponent]
})
class HostComponent {
@ViewChild(OwnerComponent) checkingOwner!: OwnerComponent;
@@ -96,9 +96,9 @@ class TestEnvironment {
constructor(template: string) {
TestBed.configureTestingModule({
- declarations: [HostComponent],
- imports: [TestRealtimeModule.forRoot(SF_TYPE_REGISTRY), OwnerComponent],
+ imports: [OwnerComponent, HostComponent],
providers: [
+ provideTestRealtime(SF_TYPE_REGISTRY),
{ provide: TranslocoService, useFactory: () => instance(this.mockedTranslocoService) },
provideHttpClient(withInterceptorsFromDi()),
provideHttpClientTesting()
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.ts
index f26cb799349..30f42cdaac7 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/owner/owner.component.ts
@@ -1,4 +1,4 @@
-import { CommonModule } from '@angular/common';
+import { NgClass } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { TranslocoService } from '@ngneat/transloco';
import { UserProfile } from 'realtime-server/lib/esm/common/models/user';
@@ -11,7 +11,7 @@ import { UserService } from '../user.service';
selector: 'app-owner',
templateUrl: './owner.component.html',
styleUrls: ['./owner.component.scss'],
- imports: [AvatarComponent, CommonModule]
+ imports: [AvatarComponent, NgClass]
})
export class OwnerComponent implements OnInit {
@Input() ownerRef?: string;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/realtime.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/realtime.service.spec.ts
index ab5822514d5..cc0eec1587c 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/realtime.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/realtime.service.spec.ts
@@ -6,12 +6,12 @@ import { SF_TYPE_REGISTRY } from '../app/core/models/sf-type-registry';
import { RealtimeDoc } from './models/realtime-doc';
import { RealtimeQuery } from './models/realtime-query';
import { RealtimeService } from './realtime.service';
-import { TestRealtimeModule } from './test-realtime.module';
+import { provideTestRealtime } from './test-realtime-providers';
import { configureTestingModule } from './test-utils';
describe('RealtimeService', () => {
configureTestingModule(() => ({
- imports: [TestRealtimeModule.forRoot(SF_TYPE_REGISTRY)]
+ providers: [provideTestRealtime(SF_TYPE_REGISTRY)]
}));
describe('manageQuery', () => {
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/router-link.directive.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/router-link.directive.ts
index ca421406a38..24e83968692 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/router-link.directive.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/router-link.directive.ts
@@ -2,10 +2,7 @@ import { Directive, ElementRef, HostBinding, HostListener, Inject, Input } from
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
import { WINDOW } from './browser-globals';
-@Directive({
- selector: '[appRouterLink]',
- standalone: false
-})
+@Directive({ selector: '[appRouterLink]' })
export class RouterLinkDirective {
@Input() set appRouterLink(value: string | string[]) {
this._route = Array.isArray(value) ? value : [value];
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/scroll-into-view.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/scroll-into-view.ts
index 1e651259cae..33fc294f6c5 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/scroll-into-view.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/scroll-into-view.ts
@@ -1,9 +1,6 @@
import { AfterViewInit, Directive, ElementRef } from '@angular/core';
-@Directive({
- selector: '[appScrollIntoView]',
- standalone: false
-})
+@Directive({ selector: '[appScrollIntoView]' })
export class ScrollIntoViewDirective implements AfterViewInit {
constructor(private readonly elementRef: ElementRef) {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/supported-browsers-dialog/supported-browsers-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/supported-browsers-dialog/supported-browsers-dialog.component.ts
index ca6f1090b80..049b960fb58 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/supported-browsers-dialog/supported-browsers-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/supported-browsers-dialog/supported-browsers-dialog.component.ts
@@ -1,7 +1,16 @@
import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogTitle,
+ MatDialogContent,
+ MatDialogActions,
+ MatDialogClose
+} from '@angular/material/dialog';
import { I18nService } from 'xforge-common/i18n.service';
import { browserLinks, isIosDevice } from 'xforge-common/utils';
+import { TranslocoModule } from '@ngneat/transloco';
+import { CdkScrollable } from '@angular/cdk/scrolling';
+import { MatButton } from '@angular/material/button';
export enum BrowserIssue {
Upgrade = 'upgrade_chrome_firefox',
@@ -11,7 +20,15 @@ export enum BrowserIssue {
@Component({
selector: 'app-supported-browsers-dialog',
templateUrl: './supported-browsers-dialog.component.html',
- standalone: false
+ imports: [
+ TranslocoModule,
+ MatDialogTitle,
+ CdkScrollable,
+ MatDialogContent,
+ MatDialogActions,
+ MatButton,
+ MatDialogClose
+ ]
})
export class SupportedBrowsersDialogComponent {
constructor(
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-delete-dialog.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-delete-dialog.component.ts
index f1908919864..439af1f8ed1 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-delete-dialog.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-delete-dialog.component.ts
@@ -1,6 +1,15 @@
+import { CdkScrollable } from '@angular/cdk/scrolling';
import { Component, Inject } from '@angular/core';
-import { MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatButton } from '@angular/material/button';
+import {
+ MAT_DIALOG_DATA,
+ MatDialogActions,
+ MatDialogClose,
+ MatDialogContent,
+ MatDialogTitle
+} from '@angular/material/dialog';
import { User } from 'realtime-server/lib/esm/common/models/user';
+import { AvatarComponent } from '../avatar/avatar.component';
export interface SaDeleteUserDialogData {
user: User;
@@ -9,7 +18,15 @@ export interface SaDeleteUserDialogData {
@Component({
templateUrl: './sa-delete-dialog.component.html',
styleUrls: ['./sa-delete-dialog.component.scss'],
- standalone: false
+ imports: [
+ MatDialogTitle,
+ CdkScrollable,
+ MatDialogContent,
+ AvatarComponent,
+ MatDialogActions,
+ MatButton,
+ MatDialogClose
+ ]
})
export class SaDeleteDialogComponent {
constructor(@Inject(MAT_DIALOG_DATA) public data: SaDeleteUserDialogData) {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.spec.ts
index 41251483ebb..4d7a007735e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.spec.ts
@@ -4,8 +4,8 @@ import { DebugElement, getDebugNode } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MatCheckbox } from '@angular/material/checkbox';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { RouterModule } from '@angular/router';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
+import { provideRouter } from '@angular/router';
import { escapeRegExp, merge } from 'lodash-es';
import { Project } from 'realtime-server/lib/esm/common/models/project';
import { obj } from 'realtime-server/lib/esm/common/utils/obj-path';
@@ -16,15 +16,14 @@ import { combineLatest, from, Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { anything, mock, verify, when } from 'ts-mockito';
import { FileType } from 'xforge-common/models/file-offline-data';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { SFProjectService } from '../../app/core/sf-project.service';
import { ProjectDoc } from '../models/project-doc';
import { NONE_ROLE, ProjectRoleInfo } from '../models/project-role-info';
import { QueryFilter, QueryParameters } from '../query-parameters';
import { TestRealtimeService } from '../test-realtime.service';
-import { configureTestingModule, emptyHammerLoader, TestTranslocoModule } from '../test-utils';
+import { configureTestingModule, emptyHammerLoader, getTestTranslocoModule } from '../test-utils';
import { TypeRegistry } from '../type-registry';
-import { UICommonModule } from '../ui-common.module';
import { UserService } from '../user.service';
import { SaProjectsComponent } from './sa-projects.component';
@@ -33,20 +32,16 @@ const mockedUserService = mock(UserService);
describe('SaProjectsComponent', () => {
configureTestingModule(() => ({
- imports: [
- NoopAnimationsModule,
- RouterModule.forRoot([]),
- UICommonModule,
- TestTranslocoModule,
- TestRealtimeModule.forRoot(new TypeRegistry([TestProjectDoc], [FileType.Audio], []))
- ],
- declarations: [SaProjectsComponent],
+ imports: [SaProjectsComponent, getTestTranslocoModule()],
providers: [
+ provideRouter([]),
+ provideTestRealtime(new TypeRegistry([TestProjectDoc], [FileType.Audio], [])),
{ provide: SFProjectService, useMock: mockedProjectService },
{ provide: UserService, useMock: mockedUserService },
emptyHammerLoader,
provideHttpClient(withInterceptorsFromDi()),
- provideHttpClientTesting()
+ provideHttpClientTesting(),
+ provideNoopAnimations()
]
}));
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.ts
index 1bde8c5ca81..88cd46d036d 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-projects.component.ts
@@ -1,4 +1,12 @@
import { Component, DestroyRef, HostBinding, OnInit } from '@angular/core';
+import { MatOption } from '@angular/material/autocomplete';
+import { MatCheckbox } from '@angular/material/checkbox';
+import { MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
+import { MatPaginator } from '@angular/material/paginator';
+import { MatSelect } from '@angular/material/select';
+import { MatCell, MatCellDef, MatColumnDef, MatRow, MatRowDef, MatTable } from '@angular/material/table';
+import { TranslocoModule } from '@ngneat/transloco';
import { Project } from 'realtime-server/lib/esm/common/models/project';
import { obj } from 'realtime-server/lib/esm/common/utils/obj-path';
import { SFProject } from 'realtime-server/lib/esm/scriptureforge/models/sf-project';
@@ -11,7 +19,9 @@ import { DataLoadingComponent } from '../data-loading-component';
import { NONE_ROLE, ProjectRoleInfo } from '../models/project-role-info';
import { NoticeService } from '../notice.service';
import { QueryParameters } from '../query-parameters';
+import { RouterLinkDirective } from '../router-link.directive';
import { UserService } from '../user.service';
+
class Row {
isUpdatingRole: boolean = false;
@@ -59,7 +69,23 @@ class Row {
selector: 'app-sa-projects',
templateUrl: './sa-projects.component.html',
styleUrls: ['./sa-projects.component.scss'],
- standalone: false
+ imports: [
+ MatFormField,
+ MatLabel,
+ MatInput,
+ MatTable,
+ MatColumnDef,
+ MatCellDef,
+ MatCell,
+ RouterLinkDirective,
+ MatSelect,
+ MatOption,
+ MatCheckbox,
+ MatRowDef,
+ MatRow,
+ MatPaginator,
+ TranslocoModule
+ ]
})
export class SaProjectsComponent extends DataLoadingComponent implements OnInit {
@HostBinding('class') classes = 'flex-column';
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.spec.ts
index bcbf7ea18b0..0ba947852b8 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.spec.ts
@@ -1,11 +1,11 @@
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { DebugElement, getDebugNode, NgModule } from '@angular/core';
+import { DebugElement, getDebugNode } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { By } from '@angular/platform-browser';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { RouterModule } from '@angular/router';
+import { provideNoopAnimations } from '@angular/platform-browser/animations';
+import { provideRouter } from '@angular/router';
import { escapeRegExp, merge } from 'lodash-es';
import { Project } from 'realtime-server/lib/esm/common/models/project';
import { User } from 'realtime-server/lib/esm/common/models/user';
@@ -17,16 +17,15 @@ import { switchMap } from 'rxjs/operators';
import { anything, instance, mock, verify, when } from 'ts-mockito';
import { AvatarComponent } from 'xforge-common/avatar/avatar.component';
import { FileType } from 'xforge-common/models/file-offline-data';
-import { TestRealtimeModule } from 'xforge-common/test-realtime.module';
+import { provideTestRealtime } from 'xforge-common/test-realtime-providers';
import { environment } from '../../environments/environment';
import { ProjectDoc } from '../models/project-doc';
import { UserDoc } from '../models/user-doc';
import { ProjectService } from '../project.service';
import { QueryFilter, QueryParameters } from '../query-parameters';
import { TestRealtimeService } from '../test-realtime.service';
-import { configureTestingModule, emptyHammerLoader, TestTranslocoModule } from '../test-utils';
+import { configureTestingModule, emptyHammerLoader, getTestTranslocoModule } from '../test-utils';
import { TypeRegistry } from '../type-registry';
-import { UICommonModule } from '../ui-common.module';
import { UserService } from '../user.service';
import { SaDeleteDialogComponent } from './sa-delete-dialog.component';
import { SaUsersComponent } from './sa-users.component';
@@ -37,22 +36,17 @@ const mockedProjectService: ProjectService = mock(ProjectService);
describe('SaUsersComponent', () => {
configureTestingModule(() => ({
- imports: [
- RouterModule.forRoot([]),
- UICommonModule,
- DialogTestModule,
- TestTranslocoModule,
- TestRealtimeModule.forRoot(new TypeRegistry([UserDoc, TestProjectDoc], [FileType.Audio], [])),
- AvatarComponent
- ],
- declarations: [SaUsersComponent],
+ imports: [SaUsersComponent, getTestTranslocoModule(), AvatarComponent],
providers: [
+ provideRouter([]),
+ provideTestRealtime(new TypeRegistry([UserDoc, TestProjectDoc], [FileType.Audio], [])),
{ provide: MatDialog, useMock: mockedMatDialog },
{ provide: UserService, useMock: mockedUserService },
{ provide: ProjectService, useMock: mockedProjectService },
emptyHammerLoader,
provideHttpClient(withInterceptorsFromDi()),
- provideHttpClientTesting()
+ provideHttpClientTesting(),
+ provideNoopAnimations()
]
}));
@@ -161,11 +155,6 @@ class TestProjectDoc extends ProjectDoc {
readonly taskNames: string[] = [];
}
-@NgModule({
- imports: [NoopAnimationsModule]
-})
-class DialogTestModule {}
-
class TestEnvironment {
readonly component: SaUsersComponent;
readonly fixture: ComponentFixture;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.ts
index bfc8eacad7b..8b890dc8980 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/sa-users.component.ts
@@ -1,5 +1,11 @@
import { Component, DestroyRef, HostBinding, OnInit } from '@angular/core';
+import { MatIconButton } from '@angular/material/button';
import { MatDialogConfig } from '@angular/material/dialog';
+import { MatFormField, MatLabel } from '@angular/material/form-field';
+import { MatIcon } from '@angular/material/icon';
+import { MatInput } from '@angular/material/input';
+import { MatPaginator } from '@angular/material/paginator';
+import { MatCell, MatCellDef, MatColumnDef, MatRow, MatRowDef, MatTable } from '@angular/material/table';
import { Project } from 'realtime-server/lib/esm/common/models/project';
import { User } from 'realtime-server/lib/esm/common/models/user';
import { obj } from 'realtime-server/lib/esm/common/utils/obj-path';
@@ -8,14 +14,17 @@ import { RealtimeQuery } from 'xforge-common/models/realtime-query';
import { UserDoc } from 'xforge-common/models/user-doc';
import { quietTakeUntilDestroyed } from 'xforge-common/util/rxjs-util';
import { environment } from '../../environments/environment';
+import { AvatarComponent } from '../avatar/avatar.component';
import { DataLoadingComponent } from '../data-loading-component';
import { DialogService } from '../dialog.service';
import { ProjectDoc } from '../models/project-doc';
import { NoticeService } from '../notice.service';
import { ProjectService } from '../project.service';
import { QueryParameters } from '../query-parameters';
+import { RouterLinkDirective } from '../router-link.directive';
import { UserService } from '../user.service';
import { SaDeleteDialogComponent, SaDeleteUserDialogData } from './sa-delete-dialog.component';
+
interface ProjectInfo {
id: string;
name: string;
@@ -31,7 +40,22 @@ interface Row {
selector: 'app-sa-users',
templateUrl: './sa-users.component.html',
styleUrls: ['./sa-users.component.scss'],
- standalone: false
+ imports: [
+ MatFormField,
+ MatLabel,
+ MatInput,
+ MatTable,
+ MatColumnDef,
+ MatCellDef,
+ MatCell,
+ AvatarComponent,
+ RouterLinkDirective,
+ MatIconButton,
+ MatIcon,
+ MatRowDef,
+ MatRow,
+ MatPaginator
+ ]
})
export class SaUsersComponent extends DataLoadingComponent implements OnInit {
@HostBinding('class') classes = 'flex-column';
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/system-administration.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/system-administration.component.ts
index 2f655bb0d66..ef0fb5ba204 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/system-administration.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/system-administration/system-administration.component.ts
@@ -1,9 +1,13 @@
import { Component } from '@angular/core';
+import { MatTab, MatTabGroup } from '@angular/material/tabs';
+import { MobileNotSupportedComponent } from '../../app/shared/mobile-not-supported/mobile-not-supported.component';
+import { SaProjectsComponent } from './sa-projects.component';
+import { SaUsersComponent } from './sa-users.component';
@Component({
selector: 'app-system-administration',
templateUrl: './system-administration.component.html',
styleUrls: ['./system-administration.component.scss'],
- standalone: false
+ imports: [MobileNotSupportedComponent, MatTabGroup, MatTab, SaUsersComponent, SaProjectsComponent]
})
export class SystemAdministrationComponent {}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-online-status-providers.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-online-status-providers.ts
new file mode 100644
index 00000000000..081906add65
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-online-status-providers.ts
@@ -0,0 +1,17 @@
+import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
+import { provideHttpClientTesting } from '@angular/common/http/testing';
+import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
+import { mock, when } from 'ts-mockito';
+
+/**
+ * Provides a mocked Navigator (defaults to online).
+ */
+export function provideTestOnlineStatus(): EnvironmentProviders {
+ const mockedNavigator = mock(Navigator);
+ when(mockedNavigator.onLine).thenReturn(true);
+ return makeEnvironmentProviders([
+ provideHttpClient(withInterceptorsFromDi()),
+ provideHttpClientTesting(),
+ { provide: Navigator, useValue: mockedNavigator }
+ ]);
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-online-status.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-online-status.module.ts
deleted file mode 100644
index ef93755543d..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-online-status.module.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
-import { provideHttpClientTesting } from '@angular/common/http/testing';
-import { ModuleWithProviders, NgModule } from '@angular/core';
-import { mock, when } from 'ts-mockito';
-
-@NgModule({ providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()] })
-export class TestOnlineStatusModule {
- static forRoot(): ModuleWithProviders {
- const mockedNavigator = mock(Navigator);
- when(mockedNavigator.onLine).thenReturn(true);
- return {
- ngModule: TestOnlineStatusModule,
- providers: [{ provide: Navigator, useValue: mockedNavigator }]
- };
- }
-}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-realtime-providers.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-realtime-providers.ts
new file mode 100644
index 00000000000..8e0a6895d01
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-realtime-providers.ts
@@ -0,0 +1,23 @@
+import { Provider } from '@angular/core';
+import { FileService } from './file.service';
+import { MemoryOfflineStore } from './memory-offline-store';
+import { MemoryRealtimeRemoteStore } from './memory-realtime-remote-store';
+import { OfflineStore } from './offline-store';
+import { RealtimeRemoteStore } from './realtime-remote-store';
+import { RealtimeService } from './realtime.service';
+import { TestRealtimeService } from './test-realtime.service';
+import { TypeRegistry } from './type-registry';
+
+/**
+ * Provides test doubles for realtime services using in-memory stores.
+ */
+export function provideTestRealtime(typeRegistry: TypeRegistry): Provider[] {
+ return [
+ { provide: TypeRegistry, useValue: typeRegistry },
+ { provide: RealtimeRemoteStore, useClass: MemoryRealtimeRemoteStore },
+ { provide: OfflineStore, useClass: MemoryOfflineStore },
+ { provide: TestRealtimeService, useClass: TestRealtimeService },
+ { provide: RealtimeService, useExisting: TestRealtimeService },
+ { provide: FileService, useValue: undefined }
+ ];
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-realtime.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-realtime.module.ts
deleted file mode 100644
index 966f4c268ef..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-realtime.module.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { ModuleWithProviders, NgModule } from '@angular/core';
-import { FileService } from './file.service';
-import { MemoryOfflineStore } from './memory-offline-store';
-import { MemoryRealtimeRemoteStore } from './memory-realtime-remote-store';
-import { OfflineStore } from './offline-store';
-import { RealtimeRemoteStore } from './realtime-remote-store';
-import { RealtimeService } from './realtime.service';
-import { TestRealtimeService } from './test-realtime.service';
-import { TypeRegistry } from './type-registry';
-
-@NgModule()
-export class TestRealtimeModule {
- static forRoot(typeRegistry: TypeRegistry): ModuleWithProviders {
- return {
- ngModule: TestRealtimeModule,
- providers: [
- { provide: TypeRegistry, useValue: typeRegistry },
- { provide: RealtimeRemoteStore, useClass: MemoryRealtimeRemoteStore },
- { provide: OfflineStore, useClass: MemoryOfflineStore },
- { provide: TestRealtimeService, useClass: TestRealtimeService },
- { provide: RealtimeService, useExisting: TestRealtimeService },
- { provide: FileService, useValue: undefined }
- ]
- };
- }
-}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-utils.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-utils.ts
index 6f91dbd77d0..6a7caae3db7 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-utils.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/test-utils.ts
@@ -1,4 +1,12 @@
-import { Component, Directive, Input, NgModule, TemplateRef, ViewChild, ViewContainerRef } from '@angular/core';
+import {
+ Component,
+ Directive,
+ Input,
+ ModuleWithProviders,
+ TemplateRef,
+ ViewChild,
+ ViewContainerRef
+} from '@angular/core';
import { TestBed, TestModuleMetadata } from '@angular/core/testing';
import { HAMMER_LOADER } from '@angular/platform-browser';
import { TranslocoTestingModule } from '@ngneat/transloco';
@@ -52,15 +60,23 @@ export const configureTestingModule = (createModuleDef: () => TestModuleMetadata
});
};
-export const TestTranslocoModule = TranslocoTestingModule.forRoot({
- langs: { en },
- translocoConfig: {
- availableLangs: ['en'],
- reRenderOnLangChange: true,
- fallbackLang: 'en',
- defaultLang: 'en'
- }
-});
+/**
+ * Gets a Transloco testing module with 'en' translations loaded.
+ * @param loadLangs Whether to preload the languages. Set to false if tests want to use the untranslated key.
+ * Default is true.
+ */
+export function getTestTranslocoModule(loadLangs = true): ModuleWithProviders {
+ return TranslocoTestingModule.forRoot({
+ langs: { en },
+ translocoConfig: {
+ availableLangs: ['en'],
+ reRenderOnLangChange: true,
+ fallbackLang: 'en',
+ defaultLang: 'en'
+ },
+ preloadLangs: loadLangs
+ });
+}
// used to prevent Angular from complaining that HammerJS isn't available
export const emptyHammerLoader = {
@@ -387,8 +403,7 @@ export function getShortAudioBlob(): Blob {
@Directive({
// es lint complains that a directive should be used as an attribute
// eslint-disable-next-line @angular-eslint/directive-selector
- selector: 'viewContainerDirective',
- standalone: false
+ selector: 'viewContainerDirective'
})
export class ViewContainerDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
@@ -397,7 +412,7 @@ export class ViewContainerDirective {
@Component({
selector: 'app-view-container',
template: '',
- standalone: false
+ imports: [ViewContainerDirective]
})
export class ChildViewContainerComponent {
@ViewChild(ViewContainerDirective, { static: true }) viewContainer!: ViewContainerDirective;
@@ -407,12 +422,6 @@ export class ChildViewContainerComponent {
}
}
-@NgModule({
- declarations: [ChildViewContainerComponent, ViewContainerDirective],
- exports: [ViewContainerDirective]
-})
-export class ChildViewContainerModule {}
-
export function arrayOfIntsFromZero(size: number): number[] {
return Array.from({ length: size }, (_, i) => i);
}
@@ -426,8 +435,7 @@ export function arrayOfIntsFromOne(size: number): number[] {
*/
@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
- selector: '[transloco]',
- standalone: false
+ selector: '[transloco]'
})
export class MockTranslocoDirective {
@Input() translocoRead?: string;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/theme.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/theme.service.spec.ts
index 8b28dee5ef7..804ca217a06 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/theme.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/theme.service.spec.ts
@@ -1,8 +1,8 @@
import { TestBed } from '@angular/core/testing';
import { anyString, mock, when } from 'ts-mockito';
+import { DOCUMENT } from './browser-globals';
import { LocalSettingsService } from './local-settings.service';
import { configureTestingModule } from './test-utils';
-import { DOCUMENT } from './browser-globals';
import { Theme, ThemeService } from './theme.service';
const mockedLocalSettingsService = mock(LocalSettingsService);
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/ui-common-providers.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/ui-common-providers.ts
new file mode 100644
index 00000000000..3f65851ebcf
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/ui-common-providers.ts
@@ -0,0 +1,48 @@
+import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
+import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
+import { MatPaginatorIntl } from '@angular/material/paginator';
+import { MAT_SELECT_CONFIG } from '@angular/material/select';
+import { MAT_TOOLTIP_DEFAULT_OPTIONS } from '@angular/material/tooltip';
+import { TranslocoService } from '@ngneat/transloco';
+import { NgCircleProgressModule } from 'ng-circle-progress';
+import { Paginator } from './paginator/paginator.component';
+
+/**
+ * Provides Angular Material configuration and other UI-related providers for the application.
+ */
+export function provideUICommon(): EnvironmentProviders {
+ return makeEnvironmentProviders([
+ {
+ provide: MatPaginatorIntl,
+ useClass: Paginator,
+ deps: [TranslocoService]
+ },
+ {
+ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
+ useValue: { appearance: 'outline', hideRequiredMarker: true }
+ },
+ {
+ provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
+ useValue: { disableTooltipInteractivity: true }
+ },
+ {
+ provide: MAT_SELECT_CONFIG,
+ useValue: { panelWidth: null }
+ },
+ ...(NgCircleProgressModule.forRoot({
+ // Defaults
+ radius: 100,
+ outerStrokeWidth: 8,
+ innerStrokeWidth: 4,
+ outerStrokeColor: '#298ed1',
+ innerStrokeColor: '#95c4e6',
+ animationDuration: 1000,
+ startFromZero: false,
+ titleFontSize: '48',
+ unitsFontSize: '20',
+ showSubtitle: false,
+ responsive: true,
+ renderOnClick: false
+ }).providers ?? [])
+ ]);
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/ui-common.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/ui-common.module.ts
deleted file mode 100644
index 71bd1602ca7..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/ui-common.module.ts
+++ /dev/null
@@ -1,140 +0,0 @@
-import { BidiModule } from '@angular/cdk/bidi';
-import { ModuleWithProviders, NgModule } from '@angular/core';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { MatAutocompleteModule } from '@angular/material/autocomplete';
-import { MatBadgeModule } from '@angular/material/badge';
-import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
-import { MatButtonModule } from '@angular/material/button';
-import { MatButtonToggleModule } from '@angular/material/button-toggle';
-import { MatCardModule } from '@angular/material/card';
-import { MatCheckboxModule } from '@angular/material/checkbox';
-import { MatChipsModule } from '@angular/material/chips';
-import { MatOptionModule } from '@angular/material/core';
-import { MatDialogModule } from '@angular/material/dialog';
-import { MatDividerModule } from '@angular/material/divider';
-import { MatExpansionModule } from '@angular/material/expansion';
-import { MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldModule } from '@angular/material/form-field';
-import { MatIconModule } from '@angular/material/icon';
-import { MatInputModule } from '@angular/material/input';
-import { MatListModule } from '@angular/material/list';
-import { MatMenuModule } from '@angular/material/menu';
-import { MatPaginatorIntl, MatPaginatorModule } from '@angular/material/paginator';
-import { MatProgressBarModule } from '@angular/material/progress-bar';
-import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { MatRadioModule } from '@angular/material/radio';
-import { MAT_SELECT_CONFIG, MatSelectModule } from '@angular/material/select';
-import { MatSidenavModule } from '@angular/material/sidenav';
-import { MatSlideToggleModule } from '@angular/material/slide-toggle';
-import { MatSliderModule } from '@angular/material/slider';
-import { MatSnackBarModule } from '@angular/material/snack-bar';
-import { MatSortModule } from '@angular/material/sort';
-import { MatStepperModule } from '@angular/material/stepper';
-import { MatTableModule } from '@angular/material/table';
-import { MatTabsModule } from '@angular/material/tabs';
-import { MatToolbarModule } from '@angular/material/toolbar';
-import { MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipModule } from '@angular/material/tooltip';
-import { TranslocoService } from '@ngneat/transloco';
-import { NgCircleProgressModule } from 'ng-circle-progress';
-import { AutofocusDirective } from './autofocus.directive';
-import { BlurOnClickDirective } from './blur-on-click.directive';
-import { DonutChartModule } from './donut-chart/donut-chart.module';
-import { L10nNumberPipe } from './l10n-number.pipe';
-import { Paginator } from './paginator/paginator.component';
-import { RouterLinkDirective } from './router-link.directive';
-import { ScrollIntoViewDirective } from './scroll-into-view';
-
-const modules = [
- DonutChartModule,
- FormsModule,
- BidiModule,
- MatAutocompleteModule,
- MatBadgeModule,
- MatBottomSheetModule,
- MatButtonModule,
- MatButtonToggleModule,
- MatCardModule,
- MatCheckboxModule,
- MatChipsModule,
- MatDialogModule,
- MatDividerModule,
- MatFormFieldModule,
- MatIconModule,
- MatInputModule,
- MatListModule,
- MatMenuModule,
- MatOptionModule,
- MatPaginatorModule,
- MatProgressBarModule,
- MatProgressSpinnerModule,
- MatRadioModule,
- MatSelectModule,
- MatSidenavModule,
- MatSliderModule,
- MatSlideToggleModule,
- MatSnackBarModule,
- MatSortModule,
- MatStepperModule,
- MatTableModule,
- MatTabsModule,
- MatToolbarModule,
- MatTooltipModule,
- MatExpansionModule,
- ReactiveFormsModule,
- NgCircleProgressModule
-];
-
-@NgModule({
- declarations: [BlurOnClickDirective, AutofocusDirective, ScrollIntoViewDirective, RouterLinkDirective],
- imports: [...modules, L10nNumberPipe],
- exports: [
- ...modules,
- BlurOnClickDirective,
- AutofocusDirective,
- ScrollIntoViewDirective,
- RouterLinkDirective,
- L10nNumberPipe
- ],
- providers: [
- {
- provide: MatPaginatorIntl,
- useClass: Paginator,
- deps: [TranslocoService]
- },
- {
- provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
- useValue: { appearance: 'outline', hideRequiredMarker: true }
- },
- {
- provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
- useValue: { disableTooltipInteractivity: true }
- },
- {
- provide: MAT_SELECT_CONFIG,
- useValue: { panelWidth: null }
- }
- ]
-})
-export class UICommonModule {
- static forRoot(): ModuleWithProviders {
- return {
- ngModule: UICommonModule,
- providers: [
- ...(NgCircleProgressModule.forRoot({
- // Defaults
- radius: 100,
- outerStrokeWidth: 8,
- innerStrokeWidth: 4,
- outerStrokeColor: '#298ed1',
- innerStrokeColor: '#95c4e6',
- animationDuration: 1000,
- startFromZero: false,
- titleFontSize: '48',
- unitsFontSize: '20',
- showSubtitle: false,
- responsive: true,
- renderOnClick: false
- }).providers ?? [])
- ]
- };
- }
-}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user-projects.service.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user-projects.service.ts
index c25d824a060..3f2c5ec6e99 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user-projects.service.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user-projects.service.ts
@@ -8,6 +8,7 @@ import { environment } from '../environments/environment';
import { AuthService, LoginResult } from './auth.service';
import { UserDoc } from './models/user-doc';
import { UserService } from './user.service';
+
/** Service that maintains an up-to-date set of SF project docs that the current user has access to. */
@Injectable({
providedIn: 'root'
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user.service.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user.service.spec.ts
index 13cbc7f42ee..94994046d2e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user.service.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/user.service.spec.ts
@@ -11,9 +11,9 @@ import { DialogService } from './dialog.service';
import { LocalSettingsService } from './local-settings.service';
import { UserDoc } from './models/user-doc';
import { NoticeService } from './notice.service';
-import { TestRealtimeModule } from './test-realtime.module';
+import { provideTestRealtime } from './test-realtime-providers';
import { TestRealtimeService } from './test-realtime.service';
-import { configureTestingModule, TestTranslocoModule } from './test-utils';
+import { configureTestingModule, getTestTranslocoModule } from './test-utils';
import { TypeRegistry } from './type-registry';
import { CURRENT_PROJECT_ID_SETTING, UserService } from './user.service';
@@ -25,8 +25,9 @@ const mockedNoticeService = mock(NoticeService);
describe('UserService', () => {
configureTestingModule(() => ({
- imports: [TestTranslocoModule, TestRealtimeModule.forRoot(new TypeRegistry([UserDoc], [], []))],
+ imports: [getTestTranslocoModule()],
providers: [
+ provideTestRealtime(new TypeRegistry([UserDoc], [], [])),
{ provide: AuthService, useMock: mockedAuthService },
{ provide: LocalSettingsService, useMock: mockedLocalSettingsService },
{ provide: CommandService, useMock: mockedCommandService },
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/util/rxjs-util.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/util/rxjs-util.spec.ts
index fe756ec3704..5ada7948d1d 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/util/rxjs-util.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/util/rxjs-util.spec.ts
@@ -64,9 +64,7 @@ describe('quietTakeUntilDestroyed', () => {
});
});
-@Component({
- standalone: false
-})
+@Component({})
class QuietTakeUntilDestroyedTestComponent implements OnDestroy {
mainSubjectCompleted = false;
subjectCreatedAfterDestroyCompleted = false;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/utils.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/utils.spec.ts
index a559ee33941..c2c8f217244 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/utils.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/utils.spec.ts
@@ -63,9 +63,7 @@ describe('quietTakeUntilDestroyed', () => {
});
});
-@Component({
- standalone: false
-})
+@Component({})
class QuietTakeUntilDestroyedTestComponent implements OnDestroy {
mainSubjectCompleted = false;
subjectCreatedAfterDestroyCompleted = false;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.spec.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.spec.ts
index acea967bdfa..4ab6702a11e 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.spec.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.spec.ts
@@ -7,8 +7,7 @@ import { WriteStatusComponent } from './write-status.component';
describe('WriteStatusComponent', () => {
configureTestingModule(() => ({
- declarations: [TestHostComponent],
- imports: [WriteStatusComponent]
+ imports: [WriteStatusComponent, TestHostComponent]
}));
it('should display done, spinner and error icons', () => {
@@ -64,7 +63,7 @@ class TestEnvironment {
@Component({
template: ``,
- standalone: false
+ imports: [WriteStatusComponent]
})
class TestHostComponent {
testForm: FormGroup = new FormGroup({
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.ts
index 57220471e14..4ad2d749556 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.component.ts
@@ -1,6 +1,6 @@
import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
-import { MatIconModule } from '@angular/material/icon';
+import { MatIcon } from '@angular/material/icon';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { ElementState } from '../models/element-state';
@@ -8,8 +8,7 @@ import { ElementState } from '../models/element-state';
selector: 'app-write-status',
templateUrl: './write-status.component.html',
styleUrls: ['./write-status.component.scss'],
- imports: [MatIconModule, MatProgressSpinner],
- standalone: true
+ imports: [MatIcon, MatProgressSpinner]
})
export class WriteStatusComponent {
@Input() state?: ElementState;
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.stories.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.stories.ts
index 00ce7b72227..26c2c34e80c 100644
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.stories.ts
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/write-status/write-status.stories.ts
@@ -9,7 +9,7 @@ import { WriteStatusComponent } from './write-status.component';
template: ``,
- standalone: false
+ imports: [WriteStatusComponent]
})
class WriteStatusTestComponent {
@Input() state?: ElementState;
@@ -21,8 +21,7 @@ const meta: Meta = {
component: WriteStatusTestComponent,
decorators: [
moduleMetadata({
- declarations: [WriteStatusTestComponent],
- imports: [WriteStatusComponent]
+ imports: [WriteStatusTestComponent]
})
]
};
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/xforge-common-providers.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/xforge-common-providers.ts
new file mode 100644
index 00000000000..a275c61ad46
--- /dev/null
+++ b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/xforge-common-providers.ts
@@ -0,0 +1,24 @@
+import { HTTP_INTERCEPTORS } from '@angular/common/http';
+import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';
+import { TRANSLOCO_CONFIG, TRANSLOCO_INTERCEPTOR, TRANSLOCO_LOADER } from '@ngneat/transloco';
+import { LtrMarkerInterceptor } from '../app/shared/ltr-marker.interceptor';
+import { AuthHttpInterceptor } from './auth-http-interceptor';
+import { I18nService, TranslationLoader } from './i18n.service';
+import { IndexeddbOfflineStore } from './indexeddb-offline-store';
+import { OfflineStore } from './offline-store';
+import { RealtimeRemoteStore } from './realtime-remote-store';
+import { SharedbRealtimeRemoteStore } from './sharedb-realtime-remote-store';
+
+/**
+ * Provides core xForge services including HTTP interceptors, realtime/offline stores, and i18n configuration.
+ */
+export function provideXForgeCommon(): EnvironmentProviders {
+ return makeEnvironmentProviders([
+ { provide: HTTP_INTERCEPTORS, useClass: AuthHttpInterceptor, multi: true },
+ { provide: RealtimeRemoteStore, useExisting: SharedbRealtimeRemoteStore },
+ { provide: OfflineStore, useExisting: IndexeddbOfflineStore },
+ { provide: TRANSLOCO_CONFIG, useValue: I18nService.translocoConfig },
+ { provide: TRANSLOCO_LOADER, useClass: TranslationLoader },
+ { provide: TRANSLOCO_INTERCEPTOR, useClass: LtrMarkerInterceptor }
+ ]);
+}
diff --git a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/xforge-common.module.ts b/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/xforge-common.module.ts
deleted file mode 100644
index c6cea7d6668..00000000000
--- a/src/SIL.XForge.Scripture/ClientApp/src/xforge-common/xforge-common.module.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { CommonModule } from '@angular/common';
-import { HTTP_INTERCEPTORS } from '@angular/common/http';
-import { NgModule } from '@angular/core';
-import { MatDialogModule } from '@angular/material/dialog';
-import { RouterModule } from '@angular/router';
-import { TRANSLOCO_CONFIG, TRANSLOCO_INTERCEPTOR, TRANSLOCO_LOADER, TranslocoModule } from '@ngneat/transloco';
-import { ngfModule } from 'angular-file';
-import { ProjectSelectComponent } from '../app/project-select/project-select.component';
-import { LtrMarkerInterceptor } from '../app/shared/ltr-marker.interceptor';
-import { MobileNotSupportedComponent } from '../app/shared/mobile-not-supported/mobile-not-supported.component';
-import { PageNotFoundComponent } from '../app/shared/page-not-found/page-not-found.component';
-import { SyncProgressComponent } from '../app/sync/sync-progress/sync-progress.component';
-import { AuthHttpInterceptor } from './auth-http-interceptor';
-import { AvatarComponent } from './avatar/avatar.component';
-import { GenericDialogComponent } from './generic-dialog/generic-dialog.component';
-import { I18nService, TranslationLoader } from './i18n.service';
-import { IndexeddbOfflineStore } from './indexeddb-offline-store';
-import { OfflineStore } from './offline-store';
-import { OwnerComponent } from './owner/owner.component';
-import { RealtimeRemoteStore } from './realtime-remote-store';
-import { SharedbRealtimeRemoteStore } from './sharedb-realtime-remote-store';
-import { SaDeleteDialogComponent } from './system-administration/sa-delete-dialog.component';
-import { SaProjectsComponent } from './system-administration/sa-projects.component';
-import { SaUsersComponent } from './system-administration/sa-users.component';
-import { SystemAdministrationComponent } from './system-administration/system-administration.component';
-import { UICommonModule } from './ui-common.module';
-
-const componentExports = [
- GenericDialogComponent,
- SaProjectsComponent,
- SaDeleteDialogComponent,
- SaUsersComponent,
- SystemAdministrationComponent,
- PageNotFoundComponent,
- ProjectSelectComponent,
- SyncProgressComponent
-];
-
-@NgModule({
- imports: [
- CommonModule,
- ngfModule,
- RouterModule,
- UICommonModule,
- TranslocoModule,
- MatDialogModule,
- AvatarComponent,
- OwnerComponent,
- MobileNotSupportedComponent
- ],
- declarations: componentExports,
- exports: componentExports,
- providers: [
- { provide: HTTP_INTERCEPTORS, useClass: AuthHttpInterceptor, multi: true },
- { provide: RealtimeRemoteStore, useExisting: SharedbRealtimeRemoteStore },
- { provide: OfflineStore, useExisting: IndexeddbOfflineStore },
- { provide: TRANSLOCO_CONFIG, useValue: I18nService.translocoConfig },
- { provide: TRANSLOCO_LOADER, useClass: TranslationLoader },
- { provide: TRANSLOCO_INTERCEPTOR, useClass: LtrMarkerInterceptor }
- ]
-})
-export class XForgeCommonModule {}