diff --git a/apps/picsa-apps/extension-app-native/android/app/build.gradle b/apps/picsa-apps/extension-app-native/android/app/build.gradle index f82888c7e..ff34e3efe 100644 --- a/apps/picsa-apps/extension-app-native/android/app/build.gradle +++ b/apps/picsa-apps/extension-app-native/android/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "io.picsa.extension" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 3016000 - versionName "3.16.0" + versionCode 3017000 + versionName "3.17.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/apps/picsa-apps/extension-app/project.json b/apps/picsa-apps/extension-app/project.json index 006376cb1..91bc2ee96 100644 --- a/apps/picsa-apps/extension-app/project.json +++ b/apps/picsa-apps/extension-app/project.json @@ -51,6 +51,11 @@ "glob": "**/*", "input": "apps/picsa-tools/resources-tool/src/assets", "output": "assets" + }, + { + "glob": "**/*", + "input": "apps/picsa-tools/option-tool/src/assets", + "output": "assets" } ], "styles": [ diff --git a/apps/picsa-apps/extension-app/src/app/app-routing.module.ts b/apps/picsa-apps/extension-app/src/app/app-routing.module.ts index 1f85e87de..9b26e66b6 100644 --- a/apps/picsa-apps/extension-app/src/app/app-routing.module.ts +++ b/apps/picsa-apps/extension-app/src/app/app-routing.module.ts @@ -4,6 +4,7 @@ import { RouterModule, Routes } from '@angular/router'; import { BudgetToolModule } from '@picsa/budget/src/app/app.module-embedded'; import { ClimateToolModule } from '@picsa/climate/src/app/app.module-embedded'; import { MonitoringToolModule } from '@picsa/monitoring/src/app/app.module-embedded'; +import { OptionsToolModule } from '@picsa/option/src/app/app.module-embedded'; import { ResourcesToolModule } from '@picsa/resources/src/app/app.module-embedded'; const routes: Routes = [ @@ -30,6 +31,13 @@ const routes: Routes = [ (mod) => mod.MonitoringToolModule ), }, + { + path: 'option', + loadChildren: () => + import('@picsa/option/src/app/app.module-embedded').then( + (mod) => mod.OptionsToolModule + ), + }, { path: 'resources', loadChildren: () => @@ -75,6 +83,7 @@ const routes: Routes = [ ClimateToolModule.forRoot({ urlPrefix: 'climate' }), BudgetToolModule.forRoot({ urlPrefix: 'budget' }), MonitoringToolModule.forRoot({ urlPrefix: 'monitoring' }), + OptionsToolModule.forRoot({ urlPrefix: 'option' }), ResourcesToolModule.forRoot({ urlPrefix: 'resources' }), ], exports: [RouterModule], diff --git a/apps/picsa-tools/monitoring-tool/src/app/app.component.ts b/apps/picsa-tools/monitoring-tool/src/app/app.component.ts index 1284cfbe1..283764bdd 100644 --- a/apps/picsa-tools/monitoring-tool/src/app/app.component.ts +++ b/apps/picsa-tools/monitoring-tool/src/app/app.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; @Component({ + // eslint-disable-next-line @angular-eslint/component-selector selector: 'picsa-monitoring-tool', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], @@ -10,7 +11,7 @@ export class AppComponent { } @Component({ - // tslint:disable component-selector + // eslint-disable-next-line @angular-eslint/component-selector selector: 'picsa-monitoring-tool', template: '', }) diff --git a/apps/picsa-tools/option-tool/project.json b/apps/picsa-tools/option-tool/project.json index d353a6e5f..2e6d57e38 100644 --- a/apps/picsa-tools/option-tool/project.json +++ b/apps/picsa-tools/option-tool/project.json @@ -31,7 +31,7 @@ { "type": "initial", "maximumWarning": "500kb", - "maximumError": "1mb" + "maximumError": "2mb" }, { "type": "anyComponentStyle", diff --git a/apps/picsa-tools/option-tool/src/app/app-routing.module.ts b/apps/picsa-tools/option-tool/src/app/app-routing.module.ts new file mode 100644 index 000000000..d79b94d33 --- /dev/null +++ b/apps/picsa-tools/option-tool/src/app/app-routing.module.ts @@ -0,0 +1,26 @@ +import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; +import { NgModule } from '@angular/core'; + +export const ROUTES_COMMON: Routes = [ + { + path: '', + loadChildren: () => + import('./pages/home/home.module').then((m) => m.HomeModule), + title: 'Options', + }, +]; +/** Routes only registered in standalone mode */ +const ROUTES_STANDALONE: Routes = [{ path: '**', redirectTo: '' }]; + +/******************************************************************* + * Standalone Version + ******************************************************************/ +@NgModule({ + imports: [ + RouterModule.forRoot([...ROUTES_COMMON, ...ROUTES_STANDALONE], { + preloadingStrategy: PreloadAllModules, + }), + ], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/apps/picsa-tools/option-tool/src/app/app.component.html b/apps/picsa-tools/option-tool/src/app/app.component.html index 3f5ac7f52..d5e086097 100644 --- a/apps/picsa-tools/option-tool/src/app/app.component.html +++ b/apps/picsa-tools/option-tool/src/app/app.component.html @@ -1 +1,4 @@ - +
+ + +
diff --git a/apps/picsa-tools/option-tool/src/app/app.component.spec.ts b/apps/picsa-tools/option-tool/src/app/app.component.spec.ts index 5cdfbcc7a..926446d93 100644 --- a/apps/picsa-tools/option-tool/src/app/app.component.spec.ts +++ b/apps/picsa-tools/option-tool/src/app/app.component.spec.ts @@ -1,12 +1,10 @@ import { AppComponent } from './app.component'; -import { NxWelcomeComponent } from './nx-welcome.component'; import { TestBed } from '@angular/core/testing'; - describe('AppComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [AppComponent, NxWelcomeComponent], + declarations: [AppComponent], }).compileComponents(); }); diff --git a/apps/picsa-tools/option-tool/src/app/app.component.ts b/apps/picsa-tools/option-tool/src/app/app.component.ts index 11615477f..779bc81eb 100644 --- a/apps/picsa-tools/option-tool/src/app/app.component.ts +++ b/apps/picsa-tools/option-tool/src/app/app.component.ts @@ -1,36 +1,19 @@ import { Component } from '@angular/core'; -import { DomSanitizer } from '@angular/platform-browser'; -import { MatIconRegistry } from '@angular/material/icon'; - @Component({ - selector: 'option-root', + // eslint-disable-next-line @angular-eslint/component-selector + selector: 'picsa-option-tool', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent { - title = 'picsa-tools-option-tool'; - - constructor( - private matIconRegistry: MatIconRegistry, - private domSanitizer: DomSanitizer - ) { - this.registerIcons(); - } - // register custom icons from the assets/svgs folder for access within the app - // icons can be accessed in mat-icon as svgIcon='station_data_${key}' - registerIcons() { - const icons = { - female: 'female', - male: 'male' - }; - for (const [key, value] of Object.entries(icons)) { - const iconName = `picsa_options_${key}`; - const iconUrl = this.domSanitizer.bypassSecurityTrustResourceUrl( - `assets/svgs/${value}.svg` - ); - this.matIconRegistry.addSvgIcon(iconName, iconUrl); - } - } - + title = 'picsa-option'; } + +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: 'picsa-option-tool', + template: '', +}) +// eslint-disable-next-line @angular-eslint/component-class-suffix +export class AppComponentEmbedded extends AppComponent {} diff --git a/apps/picsa-tools/option-tool/src/app/app.module-embedded.ts b/apps/picsa-tools/option-tool/src/app/app.module-embedded.ts new file mode 100644 index 000000000..5bb68632d --- /dev/null +++ b/apps/picsa-tools/option-tool/src/app/app.module-embedded.ts @@ -0,0 +1,53 @@ +import { ModuleWithProviders, NgModule } from '@angular/core'; +import { Router, RouterModule } from '@angular/router'; +import { PicsaTranslateService } from '@picsa/shared/modules'; + +import { registerEmbeddedRoutes } from '@picsa/utils'; + +import { APP_COMMON_IMPORTS } from './app.module'; +import { AppComponentEmbedded } from './app.component'; +import { ROUTES_COMMON } from './app-routing.module'; + +export class EmbeddedConfig { + /** Path app routed through, e.g. 'budget' */ + urlPrefix: string; +} + +/******************************************************************* + * Routes + ******************************************************************/ +@NgModule({ + imports: [RouterModule.forChild([])], +}) +export class EmbeddedRoutingModule { + constructor(router: Router, embeddedConfig: EmbeddedConfig) { + registerEmbeddedRoutes(ROUTES_COMMON, router, embeddedConfig.urlPrefix); + } +} + +/******************************************************************* + * Module + ******************************************************************/ +@NgModule({ + declarations: [AppComponentEmbedded], + imports: [...APP_COMMON_IMPORTS, EmbeddedRoutingModule], + bootstrap: [AppComponentEmbedded], +}) +export class BaseModule { + // ensure translate has been initiated + constructor(public translate: PicsaTranslateService) {} +} + +/** Use to import directly into another app via lazy-loading */ +@NgModule() +export class OptionsToolModule { + static forRoot(config: EmbeddedConfig): ModuleWithProviders { + return { + ngModule: BaseModule, + providers: [ + PicsaTranslateService, + { provide: EmbeddedConfig, useValue: config }, + ], + }; + } +} diff --git a/apps/picsa-tools/option-tool/src/app/app.module.ts b/apps/picsa-tools/option-tool/src/app/app.module.ts index 88595a87f..ee2a72078 100644 --- a/apps/picsa-tools/option-tool/src/app/app.module.ts +++ b/apps/picsa-tools/option-tool/src/app/app.module.ts @@ -1,22 +1,50 @@ +import { + BrowserAnimationsModule, + NoopAnimationsModule, +} from '@angular/platform-browser/animations'; +import { BrowserModule } from '@angular/platform-browser'; +import { HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; +import { + PicsaDbModule, + PicsaTranslateModule, + PicsaTranslateService, +} from '@picsa/shared/modules'; +import { PicsaCommonComponentsModule } from '@picsa/components'; + import { AppComponent } from './app.component'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { BrowserModule } from '@angular/platform-browser'; -import { EditorComponent } from './components/editor/editor.component'; -import { FormsModule } from '@angular/forms'; -import { HomeComponent } from './pages/home/home.component'; -import { HttpClientModule } from '@angular/common/http'; +import { AppRoutingModule } from './app-routing.module'; +import { OptionMaterialModule } from './components/material.module'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { OptionMaterialModule } from './material.module'; -import { ReactiveFormsModule} from '@angular/forms'; +/** Core imports only required when running standalone */ +const StandaloneImports = [ + AppRoutingModule, + BrowserModule, + BrowserAnimationsModule, + NoopAnimationsModule, + PicsaTranslateModule.forRoot(), +]; +/** Common imports used in both standalone and embedded formats */ +export const APP_COMMON_IMPORTS = [ + HttpClientModule, + OptionMaterialModule, + PicsaTranslateModule, + PicsaDbModule.forRoot(), + PicsaCommonComponentsModule, +]; +/******************************************************************* + * Standalone Version + ******************************************************************/ @NgModule({ - declarations: [AppComponent, HomeComponent, EditorComponent], - imports: [BrowserModule, OptionMaterialModule, FormsModule, HttpClientModule, ReactiveFormsModule,BrowserAnimationsModule,NoopAnimationsModule], - providers: [], + declarations: [AppComponent], + imports: [...StandaloneImports, ...APP_COMMON_IMPORTS], bootstrap: [AppComponent], + schemas: [], }) -export class AppModule {} +export class AppModule { + // ensure translate service initialised + constructor(public translate: PicsaTranslateService) {} +} diff --git a/apps/picsa-tools/option-tool/src/app/components/components.module.ts b/apps/picsa-tools/option-tool/src/app/components/components.module.ts new file mode 100644 index 000000000..c3754b1b9 --- /dev/null +++ b/apps/picsa-tools/option-tool/src/app/components/components.module.ts @@ -0,0 +1,30 @@ +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +// Shared modules +import { PicsaCommonComponentsModule } from '@picsa/components'; +import { PicsaTranslateModule } from '@picsa/shared/modules'; + +// Local components +import { EditorComponent } from './editor/editor.component'; +import { OptionMaterialModule } from './material.module'; + +const Components = [EditorComponent]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + OptionMaterialModule, + PicsaCommonComponentsModule, + PicsaTranslateModule, + ReactiveFormsModule, + RouterModule, + ], + exports: [OptionMaterialModule, PicsaCommonComponentsModule, ...Components], + declarations: [Components], + providers: [], +}) +export class OptionToolComponentsModule {} diff --git a/apps/picsa-tools/option-tool/src/app/components/material.module.ts b/apps/picsa-tools/option-tool/src/app/components/material.module.ts new file mode 100644 index 000000000..1fd230e2a --- /dev/null +++ b/apps/picsa-tools/option-tool/src/app/components/material.module.ts @@ -0,0 +1,45 @@ +import { NgModule } from '@angular/core'; + +import { DomSanitizer } from '@angular/platform-browser'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { MatIconRegistry } from '@angular/material/icon'; +import { MatStepperModule } from '@angular/material/stepper'; +import { MatTableModule } from '@angular/material/table'; + +const COMPONENTS = [ + MatButtonModule, + MatDialogModule, + MatIconModule, + MatStepperModule, + MatTableModule, +]; +// use custom module to make it easier to control what is available through app +@NgModule({ + imports: COMPONENTS, + exports: COMPONENTS, +}) +export class OptionMaterialModule { + constructor( + private matIconRegistry: MatIconRegistry, + private domSanitizer: DomSanitizer + ) { + this.registerIcons(); + } + // register custom icons from the assets/svgs folder for access within the app + // icons can be accessed in mat-icon as svgIcon='station_data_${key}' + registerIcons() { + const icons = { + female: 'female', + male: 'male', + }; + for (const [key, value] of Object.entries(icons)) { + const iconName = `picsa_options_${key}`; + const iconUrl = this.domSanitizer.bypassSecurityTrustResourceUrl( + `assets/svgs/${value}.svg` + ); + this.matIconRegistry.addSvgIcon(iconName, iconUrl); + } + } +} diff --git a/apps/picsa-tools/option-tool/src/app/material.module.ts b/apps/picsa-tools/option-tool/src/app/material.module.ts deleted file mode 100644 index 76d490855..000000000 --- a/apps/picsa-tools/option-tool/src/app/material.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NgModule } from '@angular/core'; - -import { MatButtonModule } from '@angular/material/button'; -import { MatDialogModule } from '@angular/material/dialog'; -import { MatIconModule } from '@angular/material/icon'; -import { MatStepperModule } from '@angular/material/stepper'; -import { MatTableModule } from '@angular/material/table'; - -const COMPONENTS = [ - MatButtonModule, - MatDialogModule, - MatIconModule, - MatStepperModule, - MatTableModule, -]; -// use custom module to make it easier to control what is available through app -@NgModule({ - imports: COMPONENTS, - exports: COMPONENTS, -}) -export class OptionMaterialModule {} diff --git a/apps/picsa-tools/option-tool/src/app/pages/home/home.module.ts b/apps/picsa-tools/option-tool/src/app/pages/home/home.module.ts new file mode 100644 index 000000000..c03f160f5 --- /dev/null +++ b/apps/picsa-tools/option-tool/src/app/pages/home/home.module.ts @@ -0,0 +1,26 @@ +import { Route, RouterModule } from '@angular/router'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { PicsaTranslateModule } from '@picsa/shared/modules'; + +import { HomeComponent } from './home.component'; +import { OptionToolComponentsModule } from '../../components/components.module'; + +const routes: Route[] = [ + { + path: '', + component: HomeComponent, + }, +]; + +@NgModule({ + declarations: [HomeComponent], + imports: [ + CommonModule, + RouterModule.forChild(routes), + OptionToolComponentsModule, + PicsaTranslateModule, + ], +}) +export class HomeModule {} diff --git a/apps/picsa-tools/option-tool/src/index.html b/apps/picsa-tools/option-tool/src/index.html index fd0eeae70..2d41dc768 100644 --- a/apps/picsa-tools/option-tool/src/index.html +++ b/apps/picsa-tools/option-tool/src/index.html @@ -8,6 +8,6 @@ - + diff --git a/libs/components/src/components/picsa-header.component.ts b/libs/components/src/components/picsa-header.component.ts index 7e906c921..027a8b84c 100644 --- a/libs/components/src/components/picsa-header.component.ts +++ b/libs/components/src/components/picsa-header.component.ts @@ -73,7 +73,7 @@ export class PicsaHeaderComponent implements OnInit, OnDestroy { let route: ActivatedRouteSnapshot | undefined = snapshot.root; while (route !== undefined) { title = this.titleStrategy.getResolvedTitleForRoute(route) ?? title; - headerStyle = route.data.headerStyle ?? headerStyle; + headerStyle = route.data['headerStyle'] ?? headerStyle; route = route.children.find((child) => child.outlet === 'primary'); } return { title, headerStyle }; diff --git a/libs/configuration/src/provider.ts b/libs/configuration/src/provider.ts index 0b967719b..a371500e9 100644 --- a/libs/configuration/src/provider.ts +++ b/libs/configuration/src/provider.ts @@ -73,7 +73,7 @@ export class ConfigurationService { /** Update theme on config change (better in own service) */ private hackSetTheme() { - document.body.dataset.theme = this.activeConfiguration.theme; + document.body.dataset['theme'] = this.activeConfiguration.theme; } } diff --git a/libs/environments/src/version.ts b/libs/environments/src/version.ts index 5deefdfac..9355c55d3 100644 --- a/libs/environments/src/version.ts +++ b/libs/environments/src/version.ts @@ -4,5 +4,5 @@ import packageJson from '../../../package.json'; export const APP_VERSION = { number: packageJson.version, - date: '2023-03-14', + date: '2023-04-12', }; diff --git a/package.json b/package.json index 88644449e..4cd072cfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "picsa-apps", - "version": "3.16.0", + "version": "3.17.0", "license": "See LICENSE", "scripts": { "ng": "nx", diff --git a/tsconfig.base.json b/tsconfig.base.json index 5017a2f26..aa1fe57bc 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -32,6 +32,7 @@ "@picsa/i18n": ["libs/i18n/src/index.ts"], "@picsa/models": ["libs/models/src/index.ts"], "@picsa/monitoring/*": ["apps/picsa-tools/monitoring-tool/*"], + "@picsa/option/*": ["apps/picsa-tools/option-tool/*"], "@picsa/resources/*": ["apps/picsa-tools/resources-tool/*"], "@picsa/scripts": ["apps/picsa-server/scripts/index.ts"], "@picsa/shared": ["libs/shared/src/index.ts"],