add energy rate and provider service with enum
This commit is contained in:
parent
0fb92aab85
commit
01d10171e9
21175
package-lock.json
generated
Normal file
21175
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -20,6 +20,9 @@
|
||||
"@angular/platform-browser": "^19.0.0",
|
||||
"@angular/platform-browser-dynamic": "^19.0.0",
|
||||
"@angular/router": "^19.0.0",
|
||||
"@openharbor/data": "^1.0.0-alpha.1",
|
||||
"@openharbor/ngx-data": "^18.0.0-alpha.9",
|
||||
"angular-auth-oidc-client": "^19.0.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.15.0"
|
||||
|
@ -6,10 +6,10 @@
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"endpoint": "https://login-planb.openharbor.io/realms/plan-b",
|
||||
"clientId": "",
|
||||
"scopes": "",
|
||||
"responseType": "",
|
||||
"endpoint": "https://login-planb.openharbor.io/realms/constellation-heating",
|
||||
"clientId": "web-app",
|
||||
"scopes": "openid profile offline_access",
|
||||
"responseType": "code",
|
||||
"secureRoutes": [
|
||||
"https://localhost:7184/"
|
||||
]
|
||||
|
@ -1,9 +1,72 @@
|
||||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideRouter } from '@angular/router';
|
||||
|
||||
import {Observable} from 'rxjs';
|
||||
import { routes } from './app.routes';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import {SettingService} from './services/setting.service';
|
||||
import {provideHttpClient, withInterceptors} from '@angular/common/http';
|
||||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||
import
|
||||
{
|
||||
provideAuth,
|
||||
authInterceptor,
|
||||
StsConfigLoader,
|
||||
OpenIdConfiguration,
|
||||
StsConfigHttpLoader,
|
||||
AbstractSecurityStorage,
|
||||
DefaultLocalStorageService,
|
||||
withAppInitializerAuthCheck
|
||||
} from 'angular-auth-oidc-client';
|
||||
function appInitialized() {
|
||||
return async ()=> {
|
||||
return Promise.all([])
|
||||
}
|
||||
}
|
||||
|
||||
function authConfigFactory(setting: SettingService) {
|
||||
|
||||
const config$ = new Observable<OpenIdConfiguration>(observer => {
|
||||
setting.initialize()
|
||||
.then(() => {
|
||||
|
||||
const config = {
|
||||
authority: setting.auth.endpoint,
|
||||
redirectUrl: window.location.origin,
|
||||
postLogoutRedirectUri: window.location.origin,
|
||||
clientId: setting.auth.clientId,
|
||||
scope: setting.auth.scopes,
|
||||
responseType: setting.auth.responseType,
|
||||
silentRenew: true,
|
||||
useRefreshToken: true,
|
||||
renewTimeBeforeTokenExpiresInSeconds: 30,
|
||||
secureRoutes: setting.auth.secureRoutes
|
||||
};
|
||||
|
||||
observer.next(config);
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
return new StsConfigHttpLoader(config$);
|
||||
}
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimationsAsync()]
|
||||
providers: [
|
||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||
provideRouter(routes),
|
||||
provideHttpClient(withInterceptors([authInterceptor()])),
|
||||
provideAnimationsAsync(),
|
||||
provideAuth(
|
||||
{
|
||||
loader: {
|
||||
provide: StsConfigLoader,
|
||||
useFactory: authConfigFactory,
|
||||
deps: [SettingService],
|
||||
},
|
||||
},
|
||||
withAppInitializerAuthCheck()
|
||||
),
|
||||
{
|
||||
provide: AbstractSecurityStorage,
|
||||
useClass: DefaultLocalStorageService,
|
||||
},
|
||||
]
|
||||
};
|
||||
|
@ -1,15 +1,10 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import {HomeComponent} from './pages/home/home.component';
|
||||
import {TestPage} from './pages/test/test.page'
|
||||
import {autoLoginPartialRoutesGuard} from 'angular-auth-oidc-client';
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: 'test',
|
||||
title: 'Test Page',
|
||||
component: TestPage
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
title: 'Home Component',
|
||||
component: HomeComponent
|
||||
loadChildren: () => import('./layouts/default/default.routes')
|
||||
.then(child => child.routes),
|
||||
canMatch: [autoLoginPartialRoutesGuard]
|
||||
},
|
||||
];
|
||||
|
4
src/app/enum/currency.ts
Normal file
4
src/app/enum/currency.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export enum Currency {
|
||||
USD,
|
||||
CAD,
|
||||
}
|
3
src/app/layouts/default/default.layout.html
Normal file
3
src/app/layouts/default/default.layout.html
Normal file
@ -0,0 +1,3 @@
|
||||
<p>default layout works !</p>
|
||||
<router-outlet />
|
||||
|
38
src/app/layouts/default/default.layout.scss
Normal file
38
src/app/layouts/default/default.layout.scss
Normal file
@ -0,0 +1,38 @@
|
||||
main {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
mat-list-item {
|
||||
width: 100%;
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 8px; /* Adjust spacing between label and icon */
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
mat-drawer-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.account-container {
|
||||
padding: { bottom: 0; left: 25px; right: 25px; top: 25px; };
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navigation-container {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.organization-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 8px; /* Adjust spacing between label and icon */
|
||||
width: 100%;
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HomeComponent } from './home.component';
|
||||
import { DefaultLayout } from './default.layout';
|
||||
|
||||
describe('HomeComponent', () => {
|
||||
let component: HomeComponent;
|
||||
let fixture: ComponentFixture<HomeComponent>;
|
||||
describe('DefaultLayout', () => {
|
||||
let component: DefaultLayout;
|
||||
let fixture: ComponentFixture<DefaultLayout>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HomeComponent]
|
||||
imports: [DefaultLayout]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HomeComponent);
|
||||
fixture = TestBed.createComponent(DefaultLayout);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
14
src/app/layouts/default/default.layout.ts
Normal file
14
src/app/layouts/default/default.layout.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {RouterOutlet} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-default-layout',
|
||||
imports: [
|
||||
RouterOutlet
|
||||
],
|
||||
templateUrl: './default.layout.html',
|
||||
styleUrl: './default.layout.scss'
|
||||
})
|
||||
export class DefaultLayout {
|
||||
|
||||
}
|
22
src/app/layouts/default/default.routes.ts
Normal file
22
src/app/layouts/default/default.routes.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import {DefaultLayout} from './default.layout';
|
||||
import {Routes} from '@angular/router';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DefaultLayout,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
redirectTo: 'home',
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
loadComponent: () =>
|
||||
import('../../pages/home/home.page')
|
||||
.then(page => page.HomePage),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
@ -1,11 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
imports: [],
|
||||
templateUrl: './home.component.html',
|
||||
styleUrl: './home.component.scss'
|
||||
})
|
||||
export class HomeComponent {
|
||||
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TestPage } from './test.page';
|
||||
import { HomePage } from './home.page';
|
||||
|
||||
describe('TestPage', () => {
|
||||
let component: TestPage;
|
||||
let fixture: ComponentFixture<TestPage>;
|
||||
describe('HomePage', () => {
|
||||
let component: HomePage;
|
||||
let fixture: ComponentFixture<HomePage>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [TestPage]
|
||||
imports: [HomePage]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(TestPage);
|
||||
fixture = TestBed.createComponent(HomePage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
11
src/app/pages/home/home.page.ts
Normal file
11
src/app/pages/home/home.page.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
imports: [],
|
||||
templateUrl: './home.page.html',
|
||||
styleUrl: './home.page.scss'
|
||||
})
|
||||
export class HomePage {
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
<p>test works!</p>
|
@ -1,11 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-test',
|
||||
imports: [],
|
||||
templateUrl: './test.page.html',
|
||||
styleUrl: './test.page.scss'
|
||||
})
|
||||
export class TestPage {
|
||||
|
||||
}
|
138
src/app/services/energy-provider.service.ts
Normal file
138
src/app/services/energy-provider.service.ts
Normal file
@ -0,0 +1,138 @@
|
||||
import {Router} from '@angular/router';
|
||||
import {BehaviorSubject, of} from 'rxjs';
|
||||
import {SettingService} from './setting.service';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import {HttpDataSourceService} from '@openharbor/ngx-data';
|
||||
import {IDataSource, IQueryCriteria} from '@openharbor/data';
|
||||
import {OidcSecurityService} from 'angular-auth-oidc-client';
|
||||
|
||||
export interface IEnergyProvider
|
||||
{
|
||||
id: number;
|
||||
name: string;
|
||||
active: boolean;
|
||||
disabled_at: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
export interface IAddEnergyProvider
|
||||
{
|
||||
name: string;
|
||||
}
|
||||
export interface IDisabledEnergyProvider
|
||||
{
|
||||
providerId: number;
|
||||
disabled_at: string;
|
||||
|
||||
}
|
||||
export interface IEnableEnergyProvider
|
||||
{
|
||||
providerId: number;
|
||||
}
|
||||
export interface IUpdateEnergyProvider
|
||||
{
|
||||
providerId: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class EnergyProviderService {
|
||||
|
||||
private readonly hdss = inject(HttpDataSourceService);
|
||||
private readonly settingService = inject(SettingService);
|
||||
private readonly oidcSecurityService = inject(OidcSecurityService);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
private energyProviders: IEnergyProvider[] = [];
|
||||
dataSource?: IDataSource<IQueryCriteria, IEnergyProvider>
|
||||
|
||||
current$ = new BehaviorSubject<IEnergyProvider | null>(null);
|
||||
energyProviders$ = new BehaviorSubject<IEnergyProvider[]>([]);
|
||||
|
||||
constructor() {
|
||||
this.internalDataSource();
|
||||
|
||||
this.oidcSecurityService.isAuthenticated$
|
||||
.subscribe(result => {
|
||||
if (result.isAuthenticated) {
|
||||
this.dataSource?.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dataSourceBuilder() {
|
||||
return this.hdss.builder<IQueryCriteria, IEnergyProvider>()
|
||||
.keyResolver(model => model.id)
|
||||
.addCommandByUrl<IAddEnergyProvider, void>(
|
||||
'addEnergyProvider',
|
||||
this.settingService.getMainCommandUrl('addEnergyProvider'),
|
||||
ev => {
|
||||
return of({
|
||||
name: ev.model.name
|
||||
})
|
||||
})
|
||||
.addCommandByUrl<IDisabledEnergyProvider, void>(
|
||||
'disableEnergyProvider',
|
||||
this.settingService.getMainCommandUrl('disableEnergyProvider'),
|
||||
ev => {
|
||||
return of({
|
||||
providerId: ev.model.id,
|
||||
disabled_at: ev.model.disabled_at
|
||||
})
|
||||
}
|
||||
)
|
||||
.addCommandByUrl<IEnableEnergyProvider, void>(
|
||||
'enableEnergyProvider',
|
||||
this.settingService.getMainCommandUrl('enableEnergyProvider'),
|
||||
ev => {
|
||||
return of({
|
||||
providerId: ev.model.id,
|
||||
})
|
||||
}
|
||||
)
|
||||
.addCommandByUrl<IUpdateEnergyProvider, void>(
|
||||
'updateEnergyProvider',
|
||||
this.settingService.getMainCommandUrl('updateEnergyProvider'),
|
||||
ev => {
|
||||
return of({
|
||||
providerId: ev.model.id,
|
||||
name: ev.model.name
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
selectEnergyProvider(id: number) {
|
||||
const energyProvider = this.energyProviders.find(energyProvider => energyProvider.id === id);
|
||||
if (undefined === energyProvider)
|
||||
return;
|
||||
|
||||
this.current$.next(energyProvider);
|
||||
}
|
||||
private internalDataSource() {
|
||||
if (undefined !== this.dataSource)
|
||||
return;
|
||||
|
||||
this.dataSource = this.dataSourceBuilder()
|
||||
.createDataSource();
|
||||
|
||||
this.dataSource.data$
|
||||
.subscribe(result => {
|
||||
if (null === result || undefined === result.data)
|
||||
return;
|
||||
|
||||
let updateSelection = false;
|
||||
if (this.energyProviders.length === 0) {
|
||||
updateSelection = true;
|
||||
}
|
||||
|
||||
this.energyProviders = result.data;
|
||||
this.energyProviders$.next(this.energyProviders);
|
||||
|
||||
if (updateSelection && this.energyProviders.length > 0)
|
||||
this.selectEnergyProvider(this.energyProviders[0].id)
|
||||
})
|
||||
}
|
||||
}
|
160
src/app/services/energy-rate.service.ts
Normal file
160
src/app/services/energy-rate.service.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import {Router} from '@angular/router';
|
||||
import {BehaviorSubject, of} from 'rxjs';
|
||||
import {Currency} from '../enum/currency';
|
||||
import {SettingService} from './setting.service';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import {HttpDataSourceService} from '@openharbor/ngx-data';
|
||||
import {IDataSource, IQueryCriteria} from '@openharbor/data';
|
||||
import {OidcSecurityService} from 'angular-auth-oidc-client';
|
||||
import {
|
||||
IAddEnergyProvider,
|
||||
IDisabledEnergyProvider,
|
||||
IEnableEnergyProvider,
|
||||
IEnergyProvider, IUpdateEnergyProvider
|
||||
} from './energy-provider.service';
|
||||
|
||||
export interface IEnergyRate
|
||||
{
|
||||
id: number;
|
||||
providerId: number;
|
||||
name: string;
|
||||
rate: number;
|
||||
currency: Currency;
|
||||
active: boolean;
|
||||
started_at: string;
|
||||
disabled_at: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
export interface IAddEnergyRate
|
||||
{
|
||||
providerId: number;
|
||||
name: string;
|
||||
rate: number;
|
||||
currency: Currency;
|
||||
active: boolean;
|
||||
}
|
||||
export interface IDisabledEnergyRate
|
||||
{
|
||||
rateId: number;
|
||||
disabled_at: string;
|
||||
|
||||
}
|
||||
export interface IEnableEnergyRate
|
||||
{
|
||||
rateId: number;
|
||||
}
|
||||
export interface IUpdateEnergyRate
|
||||
{
|
||||
rateId: number;
|
||||
started_at : string;
|
||||
name: string;
|
||||
rate: number;
|
||||
|
||||
}
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class EnergyRateService {
|
||||
private readonly hdss = inject(HttpDataSourceService);
|
||||
private readonly settingService = inject(SettingService);
|
||||
private readonly oidcSecurityService = inject(OidcSecurityService);
|
||||
private readonly router = inject(Router);
|
||||
|
||||
private energyRates: IEnergyRate[] = [];
|
||||
|
||||
dataSource?: IDataSource<IQueryCriteria, IEnergyRate>;
|
||||
|
||||
current$ = new BehaviorSubject<IEnergyRate | null>(null);
|
||||
energyRates$ = new BehaviorSubject<IEnergyRate[]>([]);
|
||||
constructor() {
|
||||
this.internalDataSource();
|
||||
|
||||
this.oidcSecurityService.isAuthenticated$
|
||||
.subscribe(result => {
|
||||
if (result.isAuthenticated) {
|
||||
this.dataSource?.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
dataSourceBuilder() {
|
||||
return this.hdss.builder<IQueryCriteria, IEnergyRate>()
|
||||
.keyResolver(model => model.id)
|
||||
.addCommandByUrl<IAddEnergyRate, void>(
|
||||
'addEnergyRate',
|
||||
this.settingService.getMainCommandUrl('addEnergyRate'),
|
||||
ev => {
|
||||
return of({
|
||||
providerId: ev.model.providerId,
|
||||
name: ev.model.name,
|
||||
rate: ev.model.rate,
|
||||
currency: ev.model.currency,
|
||||
active: ev.model.active,
|
||||
})
|
||||
})
|
||||
.addCommandByUrl<IDisabledEnergyRate, void>(
|
||||
'disableEnergyRate',
|
||||
this.settingService.getMainCommandUrl('disableEnergyRate'),
|
||||
ev => {
|
||||
return of({
|
||||
rateId: ev.model.id,
|
||||
disabled_at: ev.model.disabled_at
|
||||
})
|
||||
}
|
||||
)
|
||||
.addCommandByUrl<IEnableEnergyRate, void>(
|
||||
'enableEnergyRate',
|
||||
this.settingService.getMainCommandUrl('enableEnergyRate'),
|
||||
ev => {
|
||||
return of({
|
||||
rateId: ev.model.id,
|
||||
})
|
||||
}
|
||||
)
|
||||
.addCommandByUrl<IUpdateEnergyRate, void>(
|
||||
'updateEnergyRate',
|
||||
this.settingService.getMainCommandUrl('updateEnergyRate'),
|
||||
ev => {
|
||||
return of({
|
||||
rateId: ev.model.id,
|
||||
started_at: ev.model.started_at,
|
||||
name: ev.model.name,
|
||||
rate: ev.model.rate,
|
||||
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
selectEnergyRate(id: number) {
|
||||
const energyRate = this.energyRates.find(energyRate => energyRate.id === id);
|
||||
if (undefined === energyRate)
|
||||
return;
|
||||
|
||||
this.current$.next(energyRate);
|
||||
}
|
||||
private internalDataSource() {
|
||||
if (undefined !== this.dataSource)
|
||||
return;
|
||||
|
||||
this.dataSource = this.dataSourceBuilder()
|
||||
.createDataSource();
|
||||
|
||||
this.dataSource.data$
|
||||
.subscribe(result => {
|
||||
if (null === result || undefined === result.data)
|
||||
return;
|
||||
|
||||
let updateSelection = false;
|
||||
if (this.energyRates.length === 0) {
|
||||
updateSelection = true;
|
||||
}
|
||||
|
||||
this.energyRates = result.data;
|
||||
this.energyRates$.next(this.energyRates);
|
||||
|
||||
if (updateSelection && this.energyRates.length > 0)
|
||||
this.selectEnergyRate(this.energyRates[0].id)
|
||||
})
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
import {inject, Injectable} from '@angular/core';
|
||||
import {SettingService} from './setting.service';
|
||||
import {of} from 'rxjs';
|
@ -15,7 +15,7 @@ export interface ISettings
|
||||
clientId: string;
|
||||
scopes: string;
|
||||
responseType: string;
|
||||
secureRoute: string[];
|
||||
secureRoutes: string[];
|
||||
}
|
||||
}
|
||||
@Injectable(
|
||||
@ -41,7 +41,7 @@ export class SettingService
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
this.setting = await firstValueFrom(this.http.get<ISettings>('/setting.json'));
|
||||
this.setting = await firstValueFrom(this.http.get<ISettings>('/settings.json'));
|
||||
}
|
||||
|
||||
getMainCommandUrl(command: string): string {
|
||||
|
Loading…
Reference in New Issue
Block a user