diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.html b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.html
new file mode 100644
index 0000000000..68ea9c6a7a
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.html
@@ -0,0 +1,24 @@
+
NG Luigi Library Demo Component
+
+
+ This is a demo component; in Luigi it is a
+ virtual tree.
+
+ If you want to configure an Angular Component to be called in virtual tree,
+ you must use this route configuration:
+
+
+ {{ routeExampleVirtual }}
+
+
+
+
+ If you want to configure an Angular Component to be just created once (like a
+ singleton( you can use this configuration:
+
+
+ {{ routeExampleReuse }}
+
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/preload.component.spec.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.spec.ts
similarity index 55%
rename from client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/preload.component.spec.ts
rename to client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.spec.ts
index f9440ce7be..bee66f0f25 100644
--- a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/preload.component.spec.ts
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.spec.ts
@@ -1,20 +1,19 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { PreloadComponent } from './preload.component';
+import { LuigiPreloadComponent } from './luigi.preload.component';
describe('ClientSupportAngularComponent', () => {
- let component: PreloadComponent;
- let fixture: ComponentFixture;
+ let component: LuigiPreloadComponent;
+ let fixture: ComponentFixture;
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ PreloadComponent ]
- })
- .compileComponents();
+ declarations: [LuigiPreloadComponent]
+ }).compileComponents();
});
beforeEach(() => {
- fixture = TestBed.createComponent(PreloadComponent);
+ fixture = TestBed.createComponent(LuigiPreloadComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.ts
new file mode 100644
index 0000000000..a1ecf62d92
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/component/luigi.preload.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'lib-client-support-angular',
+ templateUrl: './luigi.preload.component.html',
+ styles: []
+})
+export class LuigiPreloadComponent implements OnInit {
+ constructor() {}
+ routeExampleVirtual: string =
+ " {path: 'ng-luigi-demo', component: NgLuigiDemoComponent, data: {fromVirtualTreeRoot: true}}";
+ routeExampleReuse: string =
+ " {path: 'ng-luigi-demo', component: NgLuigiDemoComponent, data: {reuse: true}}";
+ ngOnInit(): void {}
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-auto-routing.service.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-auto-routing.service.ts
deleted file mode 100644
index 3650de743e..0000000000
--- a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-auto-routing.service.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-import { Injectable, OnDestroy } from '@angular/core';
-import { Subscription } from 'rxjs';
-import { Router, NavigationStart, RouterEvent } from '@angular/router';
-import { linkManager } from '@luigi-project/client';
-import { filter } from 'rxjs/operators';
-
-export interface IRouteMappingEntry {
- path: string;
- luigiRoute: string;
-}
-
-export interface IRoutingConfig {
- useVirtualTree?: boolean;
- routeMapping: IRouteMappingEntry[];
-}
-
-@Injectable({
- providedIn: 'root',
-})
-export class LuigiAutoRoutingService implements OnDestroy {
- private subscription: Subscription = new Subscription();
- private routingConfig: IRoutingConfig = null as unknown as IRoutingConfig;
- private routeMap: Map = new Map();
-
- constructor(private router: Router) {
- this.router.events
- .pipe(
- filter((ev): ev is RouterEvent => ev instanceof NavigationStart),
- filter((ev: NavigationStart) => ev.url?.length > 0),
- filter(() => !(history.state && history.state.luigiInduced))
- )
- .subscribe((ev) => {
- const route = this.routeMap.get(ev.url);
- if (route) {
- linkManager().withoutSync().navigate(route.luigiRoute);
- } else if (this.routingConfig?.useVirtualTree) {
- linkManager()
- .fromVirtualTreeRoot()
- .withoutSync()
- .navigate(ev.url);
- }
- });
- }
-
- public setConfig(routingConfig: IRoutingConfig): void {
- this.routingConfig = routingConfig;
- this.routeMap.clear();
- if (routingConfig.routeMapping) {
- this.routeMap = new Map(routingConfig.routeMapping.map((e: IRouteMappingEntry, i) => [e.path, e]));
- routingConfig.routeMapping.forEach(entry => {
- this.routeMap.set(entry.path, entry);
- });
- }
- }
-
- ngOnDestroy(): void {
- this.subscription.unsubscribe();
- }
-}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-context.service.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-context.service.ts
deleted file mode 100644
index b82ed93b91..0000000000
--- a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-context.service.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Injectable } from '@angular/core';
-import { ReplaySubject, Observable } from 'rxjs';
-import { Context, addInitListener, addContextUpdateListener } from '@luigi-project/client';
-
-export type ILuigiContextTypes = 'init' | 'update';
-export interface IContextMessage {
- contextType: ILuigiContextTypes; // will be init or update
- context: Context;
-}
-
-@Injectable({
- providedIn: 'root'
-})
-export class LuigiContextService {
- private static currentContext: IContextMessage = null as unknown as IContextMessage;
- private subject: ReplaySubject = new ReplaySubject(1);
-
-
- constructor() {
- addInitListener(initialContext => {
- this.setContext({
- contextType: 'init',
- context: initialContext
- });
- });
- addContextUpdateListener(updatedContext => {
- this.setContext({
- contextType: 'update',
- context: updatedContext
- });
- });
- }
-
- /**
- * Set current context
- */
- private setContext(obj: IContextMessage): void {
- LuigiContextService.currentContext = obj;
- this.subject.next(obj);
- }
-
- /**
- * Listen to context changes
- * Receives current value, even if the event was already dispatched earlier.
- */
- public contextObservable(): Observable {
- return this.subject.asObservable();
- }
-
- /**
- * Get latest context object retrieved from luigi core application or none, if not yet set.
- */
- public getCurrentContext(): Context {
- return LuigiContextService.currentContext && LuigiContextService.currentContext.context;
- }
-}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi.angular.support.module.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi.angular.support.module.ts
new file mode 100644
index 0000000000..f8e51b842c
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi.angular.support.module.ts
@@ -0,0 +1,50 @@
+import { NgModule } from '@angular/core';
+import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router';
+import { LuigiReuseStrategy } from './route/luigiReuseStrategy';
+import { LuigiPreloadComponent } from './component/luigi.preload.component';
+import { LuigiContextService } from './service/luigi-context-service';
+import { LuigiContextServiceImpl } from './service/luigi-context.service.impl';
+import { LuigiAutoRoutingService } from './service/luigi-auto-routing.service';
+
+export const staticRoutes: Routes = [
+ /** here an example if you want to specify that this component is a virtualThree element in Luigi Core navigation*/
+ {
+ path: 'luigi-client-support-preload',
+ component: LuigiPreloadComponent,
+ data: { fromVirtualTreeRoot: true }
+ },
+ /** here an example if you want to specify that this component it is a luigi component and u want to change the navigation in Luigi core*/
+ {
+ path: 'luigi-client-support-preload',
+ component: LuigiPreloadComponent,
+ data: { luigiRoute: '/home/reload' }
+ },
+ /** here an example if you want to reuse the component and not recreating every time you navigate to it (a singleton Component) */
+ {
+ path: 'luigi-client-support-preload=component',
+ component: LuigiPreloadComponent,
+ data: { reuse: true }
+ }
+];
+
+@NgModule({
+ declarations: [LuigiPreloadComponent],
+ imports: [RouterModule.forChild(staticRoutes)],
+ providers: [
+ {
+ provide: LuigiContextService,
+ useClass: LuigiContextServiceImpl
+ },
+ {
+ provide: RouteReuseStrategy,
+ useClass: LuigiReuseStrategy
+ }
+ ],
+ exports: [LuigiPreloadComponent]
+})
+export class LuigiAngularSupportModule {
+ constructor(
+ navigation: LuigiAutoRoutingService,
+ context: LuigiContextService
+ ) {}
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/preload.component.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/preload.component.ts
deleted file mode 100644
index 27a7c87f0d..0000000000
--- a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/preload.component.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'lib-client-support-angular',
- template: `
-
-
- `,
- styles: [
- ]
-})
-export class PreloadComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit(): void {
- }
-
-}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigi-activated-route-snapshot-helper.spec.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigi-activated-route-snapshot-helper.spec.ts
new file mode 100644
index 0000000000..48396d3072
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigi-activated-route-snapshot-helper.spec.ts
@@ -0,0 +1,7 @@
+import { LuigiActivatedRouteSnapshotHelper } from './luigi-activated-route-snapshot-helper';
+
+describe('NgLuigiActivatedRouteSnapshotService', () => {
+ it('should create an instance', () => {
+ expect(new LuigiActivatedRouteSnapshotHelper()).toBeTruthy();
+ });
+});
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigi-activated-route-snapshot-helper.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigi-activated-route-snapshot-helper.ts
new file mode 100644
index 0000000000..6f9cf8c8c4
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigi-activated-route-snapshot-helper.ts
@@ -0,0 +1,13 @@
+import { ActivatedRouteSnapshot } from '@angular/router';
+
+export class LuigiActivatedRouteSnapshotHelper {
+ private static _current: ActivatedRouteSnapshot;
+
+ static getCurrent(): ActivatedRouteSnapshot {
+ return this._current;
+ }
+
+ static setCurrent(current: ActivatedRouteSnapshot) {
+ this._current = current;
+ }
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigiReuseStrategy.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigiReuseStrategy.ts
new file mode 100644
index 0000000000..da5dab63b0
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/route/luigiReuseStrategy.ts
@@ -0,0 +1,69 @@
+import {
+ RouteReuseStrategy,
+ ActivatedRouteSnapshot,
+ DetachedRouteHandle
+} from '@angular/router';
+import { LuigiActivatedRouteSnapshotHelper } from './luigi-activated-route-snapshot-helper';
+
+export class LuigiReuseStrategy implements RouteReuseStrategy {
+ private handlers: { [key: string]: DetachedRouteHandle } = {};
+
+ shouldDetach(route: ActivatedRouteSnapshot): boolean {
+ if (!route.routeConfig || route.routeConfig.loadChildren) {
+ return false;
+ }
+ let shouldReuse = false;
+ console.debug('checking if this route should be re used or not', route);
+ if (route.routeConfig.data) {
+ route.routeConfig.data.reuse
+ ? (shouldReuse = true)
+ : (shouldReuse = false);
+ }
+
+ return shouldReuse;
+ }
+
+ store(route: ActivatedRouteSnapshot, handler: DetachedRouteHandle): void {
+ console.debug('storing handler');
+ if (handler) {
+ this.handlers[this.getUrl(route)] = handler;
+ }
+ }
+
+ shouldAttach(route: ActivatedRouteSnapshot): boolean {
+ console.debug('checking if it should be re attached');
+ return !!this.handlers[this.getUrl(route)];
+ }
+
+ retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
+ LuigiActivatedRouteSnapshotHelper.setCurrent(route);
+ if (!route.routeConfig || route.routeConfig.loadChildren) {
+ return null;
+ }
+
+ return this.handlers[this.getUrl(route)];
+ }
+
+ shouldReuseRoute(
+ future: ActivatedRouteSnapshot,
+ current: ActivatedRouteSnapshot
+ ): boolean {
+ let reUseUrl = false;
+ if (future.routeConfig) {
+ if (future.routeConfig.data) {
+ reUseUrl = future.routeConfig.data.reuse;
+ }
+ }
+ const defaultReuse = future.routeConfig === current.routeConfig;
+ //return reUseUrl || defaultReuse;
+ return defaultReuse;
+ }
+
+ getUrl(route: ActivatedRouteSnapshot): string {
+ if (route.routeConfig) {
+ const url = route.routeConfig.path;
+ console.debug('returning url', url);
+ return url;
+ }
+ }
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-auto-routing.service.spec.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-auto-routing.service.spec.ts
similarity index 100%
rename from client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-auto-routing.service.spec.ts
rename to client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-auto-routing.service.spec.ts
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-auto-routing.service.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-auto-routing.service.ts
new file mode 100644
index 0000000000..dbbfe06e9b
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-auto-routing.service.ts
@@ -0,0 +1,58 @@
+import { Injectable, OnDestroy } from '@angular/core';
+import { Subscription } from 'rxjs';
+import { NavigationEnd, Router } from '@angular/router';
+import { linkManager } from '@luigi-project/client';
+import { filter } from 'rxjs/operators';
+import { LuigiActivatedRouteSnapshotHelper } from '../route/luigi-activated-route-snapshot-helper';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class LuigiAutoRoutingService implements OnDestroy {
+ private subscription: Subscription = new Subscription();
+
+ constructor(private router: Router) {
+ this.subscription.add(
+ this.router.events.pipe(this.doFilter()).subscribe(this.doSubscription)
+ );
+ }
+
+ doFilter() {
+ return filter(event => {
+ return (
+ event instanceof NavigationEnd &&
+ event.url &&
+ event.url.length > 0 &&
+ !(history.state && history.state.luigiInduced)
+ );
+ });
+ }
+
+ /**
+ * This method will be take in consideration angular route that having in data object the paramter fromVirtualTreeRoot: true, here an example:
+ * {path: 'demo', component: DemoComponent, data:{fromVirtualTreeRoot: true}}
+ * Another option is to specify the LuigiPath: if you add in route data luigiRoute:'/xxxx/xxx'; in the case we will update the path in LuigiCore navigation, here an example
+ * {path: 'demo', component: DemoComponent, data:{luigiRoute: '/home/demo''}}
+ * @param event
+ */
+ doSubscription(event: NavigationEnd) {
+ let current = LuigiActivatedRouteSnapshotHelper.getCurrent();
+ if (current.data.luigiRoute) {
+ linkManager()
+ .withoutSync()
+ .navigate(current.data.luigiRoute);
+ return;
+ }
+ if (current.data.fromVirtualTreeRoot) {
+ console.debug('Calling fromVirtualTreeRoot for ulr ==> ' + event.url);
+ linkManager()
+ .fromVirtualTreeRoot()
+ .withoutSync()
+ .navigate(event.url);
+ }
+ }
+
+ ngOnDestroy(): void {
+ this.subscription.unsubscribe();
+ }
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context-service.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context-service.ts
new file mode 100644
index 0000000000..c56acb7c7a
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context-service.ts
@@ -0,0 +1,25 @@
+import { Context } from '@luigi-project/client';
+import { Observable } from 'rxjs';
+
+export abstract class LuigiContextService {
+ /**
+ * Listen to context changes
+ * Receives current value, even if the event was already dispatched earlier.
+ */
+ abstract contextObservable(): Observable;
+
+ /**
+ * Get latest context object
+ */
+ abstract getContext(): Context;
+}
+
+export enum ILuigiContextTypes {
+ INIT,
+ UPDATE
+}
+
+export interface IContextMessage {
+ contextType: ILuigiContextTypes; // will be init or update
+ context: Context;
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-context.service.spec.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context.service.impl.spec.ts
similarity index 59%
rename from client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-context.service.spec.ts
rename to client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context.service.impl.spec.ts
index d5f9bd0fb5..e9167d3607 100644
--- a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/luigi-context.service.spec.ts
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context.service.impl.spec.ts
@@ -1,13 +1,12 @@
import { TestBed } from '@angular/core/testing';
-
-import { LuigiContextService } from './luigi-context.service';
+import { LuigiContextServiceImpl } from 'client-support-angular';
describe('LuigiContextService', () => {
- let service: LuigiContextService;
+ let service: LuigiContextServiceImpl;
beforeEach(() => {
TestBed.configureTestingModule({});
- service = TestBed.inject(LuigiContextService);
+ service = TestBed.inject(LuigiContextServiceImpl);
});
it('should be created', () => {
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context.service.impl.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context.service.impl.ts
new file mode 100644
index 0000000000..7b56c0a614
--- /dev/null
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/lib/service/luigi-context.service.impl.ts
@@ -0,0 +1,57 @@
+import { Injectable } from '@angular/core';
+import { ReplaySubject, Observable } from 'rxjs';
+import {
+ Context,
+ addInitListener,
+ addContextUpdateListener
+} from '@luigi-project/client';
+import {
+ IContextMessage,
+ ILuigiContextTypes,
+ LuigiContextService
+} from './luigi-context-service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class LuigiContextServiceImpl implements LuigiContextService {
+ private subject: ReplaySubject = new ReplaySubject<
+ IContextMessage
+ >(1);
+ private currentContext: IContextMessage;
+
+ constructor() {
+ addInitListener(initContext => {
+ this.addListener(ILuigiContextTypes.INIT, initContext);
+ });
+ addContextUpdateListener(updateContext => {
+ this.addListener(ILuigiContextTypes.UPDATE, updateContext);
+ });
+ }
+
+ public contextObservable(): Observable {
+ return this.subject.asObservable();
+ }
+
+ /**
+ * Get latest context object retrieved from luigi core application or none, if not yet set.
+ */
+ public getContext(): Context {
+ return this.currentContext && this.currentContext.context;
+ }
+
+ /**
+ * Set current context
+ */
+ protected setContext(obj: IContextMessage): void {
+ this.currentContext = obj;
+ this.subject.next(obj);
+ }
+
+ addListener(contextType: ILuigiContextTypes, context: Context) {
+ this.setContext({
+ contextType,
+ context
+ } as IContextMessage);
+ }
+}
diff --git a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/public-api.ts b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/public-api.ts
index e8504c8194..7a12a649a7 100644
--- a/client-frameworks-support/client-support-angular/projects/client-support-angular/src/public-api.ts
+++ b/client-frameworks-support/client-support-angular/projects/client-support-angular/src/public-api.ts
@@ -2,6 +2,7 @@
* Public API Surface of client-support-angular
*/
-export * from './lib/preload.component';
-export * from './lib/luigi-context.service';
-export * from './lib/luigi-auto-routing.service';
+export * from './lib/component/luigi.preload.component';
+export * from './lib/luigi.angular.support.module';
+export * from './lib/service/luigi-context-service';
+export * from './lib/service/luigi-auto-routing.service';