Skip to content

Commit 09d3303

Browse files
louisgreineraiAdrianemersion
committed
feat: introduce standalone mode
Co-authored-by: adrian_egli <[email protected]> Co-authored-by: Simon Ser <[email protected]>
1 parent ea6a9eb commit 09d3303

18 files changed

+139
-57
lines changed

angular.json

+11
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@
107107
},
108108
"es5": {
109109
"tsConfig": "tsconfig.app.es5.json"
110+
},
111+
"standalone": {
112+
"fileReplacements": [
113+
{
114+
"replace": "src/environments/environment.ts",
115+
"with": "src/environments/environment.standalone.ts"
116+
}
117+
]
110118
}
111119
},
112120
"defaultConfiguration": ""
@@ -125,6 +133,9 @@
125133
},
126134
"es5": {
127135
"buildTarget": "netzgrafik-frontend:build:es5"
136+
},
137+
"standalone": {
138+
"buildTarget": "netzgrafik-frontend:build:standalone"
128139
}
129140
}
130141
},

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
"ng": "ng",
44
"start": "ng serve",
55
"start:local": "ng serve --configuration=local",
6+
"start:standalone": "ng serve --configuration=standalone",
67
"e2e:browserstack": "ng e2e -c browserstack",
78
"e2e:puppeteer": "ng e2e -c puppeteer",
89
"build": "ng run netzgrafik-frontend:ngsscbuild",
10+
"build:standalone": "ng build --configuration=standalone",
911
"test": "ng test -c ci",
1012
"lint": "ng lint",
1113
"e2e": "ng e2e",

src/app/app.component.html

+11-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,17 @@
3030
</button>
3131
</sbb-menu>
3232
</sbb-header-lean>
33-
<sbb-navigation-bar class="noprint"></sbb-navigation-bar>
33+
<ng-container *ngIf="!disableBackend">
34+
<sbb-navigation-bar class="noprint"></sbb-navigation-bar>
35+
</ng-container>
3436
<router-outlet *ngIf="authenticated | async; else loading"></router-outlet>
3537
<ng-template #loading>
36-
<sbb-loading-indicator mode="big"></sbb-loading-indicator>
37-
<div class="login-message">Sie werden angemeldet...</div>
38+
<ng-container *ngIf="!disableBackend">
39+
<sbb-loading-indicator mode="big"></sbb-loading-indicator>
40+
<div class="login-message">Sie werden angemeldet...</div>
41+
</ng-container>
42+
<ng-container *ngIf="disableBackend">
43+
<sbb-netzgrafik-editor></sbb-netzgrafik-editor>
44+
</ng-container>
3845
</ng-template>
46+

src/app/app.component.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,37 @@ import {ProjectDto} from "./api/generated";
1111
styleUrls: ["./app.component.scss"],
1212
})
1313
export class AppComponent {
14+
readonly disableBackend = environment.disableBackend;
15+
1416
version = packageJson.version;
1517
environmentLabel = environment.label;
1618
authenticated: Promise<unknown>;
1719

1820
projectInMenu: Observable<ProjectDto | null>;
1921

2022
get userName() {
23+
if (this.disableBackend) {
24+
return undefined;
25+
}
2126
return this.authService.claims?.name;
2227
}
2328

2429
get email() {
30+
if (this.disableBackend) {
31+
return undefined;
32+
}
2533
return this.authService.claims?.email;
2634
}
2735

2836
constructor(private authService: AuthService) {
29-
this.authenticated = authService.initialized;
37+
if (!this.disableBackend) {
38+
this.authenticated = authService.initialized;
39+
}
3040
}
3141

3242
logout() {
33-
this.authService.logOut();
43+
if (!this.disableBackend) {
44+
this.authService.logOut();
45+
}
3446
}
3547
}

src/app/app.module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ import {ActionMenuComponent} from "./view/action-menu/action-menu/action-menu.co
203203
// and you send a request to these, the access token is appended.
204204
// Documentation:
205205
// https://manfredsteyer.github.io/angular-oauth2-oidc/docs/additional-documentation/working-with-httpinterceptors.html
206-
allowedUrls: [environment.backendUrl],
206+
allowedUrls: environment.backendUrl ? [environment.backendUrl] : [],
207207
sendAccessToken: true,
208208
},
209209
}),
@@ -232,7 +232,7 @@ import {ActionMenuComponent} from "./view/action-menu/action-menu/action-menu.co
232232
],
233233
bootstrap: [AppComponent],
234234
providers: [
235-
{provide: BASE_PATH, useValue: environment.backendUrl},
235+
... environment.backendUrl ? [{provide: BASE_PATH, useValue: environment.backendUrl}] : [],
236236
{provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true},
237237
],
238238
})

src/app/netzgrafik-application/netzgrafik-application.component.html

+20-18
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
<sbb-icon-sidebar-container>
2-
<sbb-icon-sidebar [(expanded)]="expanded">
1+
<sbb-icon-sidebar-container [attr.style]="getSidebarContainerStyle()">
2+
<sbb-icon-sidebar [(expanded)]="expanded" >
33
<!--<a sbbIconSidebarItem label="Varianten" (click)="onVariantenClicked()" class="sbb-active">-->
4-
<a
5-
sbbIconSidebarItem
6-
label="Varianten"
7-
[class]="getVariantsActivatedTag()"
8-
(click)="onVariantenClicked()"
9-
>
10-
<sbb-icon
11-
*ngIf="getVariantIsWritable()"
12-
svgIcon="document-standard-small"
13-
></sbb-icon>
14-
<sbb-icon
15-
*ngIf="!getVariantIsWritable()"
16-
svgIcon="folder-lock-small"
17-
style="color: #c60018"
18-
></sbb-icon>
19-
</a>
4+
<ng-container *ngIf="!disableBackend">
5+
<a
6+
sbbIconSidebarItem
7+
label="Varianten"
8+
[class]="getVariantsActivatedTag()"
9+
(click)="onVariantenClicked()"
10+
>
11+
<sbb-icon
12+
*ngIf="getVariantIsWritable()"
13+
svgIcon="document-standard-small"
14+
></sbb-icon>
15+
<sbb-icon
16+
*ngIf="!getVariantIsWritable()"
17+
svgIcon="folder-lock-small"
18+
style="color: #c60018"
19+
></sbb-icon>
20+
</a>
21+
</ng-container>
2022
<a
2123
sbbIconSidebarItem
2224
label="Filter"

src/app/netzgrafik-application/netzgrafik-application.component.scss

-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
sbb-icon-sidebar-container {
2-
top: 85px;
3-
}
4-
51
::ng-deep a.SideBarMainIcon {
62
background: whitesmoke;
73
}

src/app/netzgrafik-application/netzgrafik-application.component.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {DomSanitizer} from "@angular/platform-browser";
1212
import {EditorMode} from "../view/editor-menu/editor-mode";
1313
import {UndoService} from "../services/data/undo.service";
1414
import {EditorView} from "../view/editor-main-view/data-views/editor.view";
15+
import {NetzgrafikDefault} from "../sample-netzgrafik/netzgrafik.default";
16+
import {environment} from "../../environments/environment";
1517

1618
export enum IconSidebarMode {
1719
VARIANTEN = "varianten",
@@ -29,6 +31,8 @@ export class NetzgrafikApplicationComponent {
2931
mode = IconSidebarMode.NONE;
3032
expanded = false;
3133

34+
readonly disableBackend = environment.disableBackend;
35+
3236
private readonly destroyed = new Subject<void>();
3337

3438
constructor(
@@ -48,13 +52,24 @@ export class NetzgrafikApplicationComponent {
4852
.subscribe((params) => {
4953
uiInteractionService.setEditorMode(EditorMode.NetzgrafikEditing);
5054
uiInteractionService.showNetzgrafik();
51-
versionControlService.load(params.getVariantId(), true);
55+
try {
56+
versionControlService.load(params.getVariantId(), true);
57+
} catch (e) {
58+
versionControlService.loadNetzgrafikDTO(NetzgrafikDefault.getDefaultNetzgrafik());
59+
}
5260
uiInteractionService.setViewboxProperties(
5361
EditorView.svgName,
5462
uiInteractionService.getDefaultViewProperties());
5563
});
5664
}
5765

66+
getSidebarContainerStyle(): string {
67+
if (this.disableBackend) {
68+
return "top: 53px;";
69+
}
70+
return "top: 85px;";
71+
}
72+
5873
getVariantIsWritable(): boolean {
5974
if (this.versionControlService.variant === null) {
6075
return true;

src/app/services/auth/auth.service.ts

+23-21
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,29 @@ export class AuthService {
3030
private router: Router,
3131
location: Location,
3232
) {
33-
this.oauthService.configure(environment.authConfig);
34-
this.oauthService.setupAutomaticSilentRefresh();
35-
// If the user should not be forcefully logged in (e.g. if you have pages, which can be
36-
// accessed anonymously), change loadDiscoveryDocumentAndLogin to
37-
// loadDiscoveryDocumentAndTryLogin and have a login functionality in the
38-
// template of the component injecting the AuthService which calls the login() method.
39-
this.initialized = this.oauthService
40-
.loadDiscoveryDocumentAndLogin({state: location.path()})
41-
// If the user is not logged in, he will be forwarded to the identity provider
42-
// and this promise will not resolve. After being redirected from the identity
43-
// provider, the login promise will return true.
44-
.then((v) => (v ? true : new Promise(() => {})));
45-
// Redirect the user to the url configured with state above or in a separate login call.
46-
this.oauthService.events
47-
.pipe(first((e) => e.type === "token_received"))
48-
.subscribe(() => {
49-
const state = decodeURIComponent(this.oauthService.state || "");
50-
if (state && state !== "/") {
51-
this.router.navigate([state]);
52-
}
53-
});
33+
if (!environment.disableBackend) {
34+
this.oauthService.configure(environment.authConfig);
35+
this.oauthService.setupAutomaticSilentRefresh();
36+
// If the user should not be forcefully logged in (e.g. if you have pages, which can be
37+
// accessed anonymously), change loadDiscoveryDocumentAndLogin to
38+
// loadDiscoveryDocumentAndTryLogin and have a login functionality in the
39+
// template of the component injecting the AuthService which calls the login() method.
40+
this.initialized = this.oauthService
41+
.loadDiscoveryDocumentAndLogin({state: location.path()})
42+
// If the user is not logged in, he will be forwarded to the identity provider
43+
// and this promise will not resolve. After being redirected from the identity
44+
// provider, the login promise will return true.
45+
.then((v) => (v ? true : new Promise(() => {})));
46+
// Redirect the user to the url configured with state above or in a separate login call.
47+
this.oauthService.events
48+
.pipe(first((e) => e.type === "token_received"))
49+
.subscribe(() => {
50+
const state = decodeURIComponent(this.oauthService.state || "");
51+
if (state && state !== "/") {
52+
this.router.navigate([state]);
53+
}
54+
});
55+
}
5456
}
5557

5658
logOut() {

src/app/services/data/undo.service.ts

+4
Original file line numberDiff line numberDiff line change
@@ -128,4 +128,8 @@ export class UndoService implements OnDestroy {
128128
}
129129
this.currentVariantId = variantId;
130130
}
131+
132+
public getCurrentVariantId():number{
133+
return this.currentVariantId;
134+
}
131135
}

src/app/services/data/version-control.service.ts

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Injectable, OnDestroy} from "@angular/core";
1+
import {HostListener, Injectable, OnDestroy} from "@angular/core";
22
import {
33
VariantControllerBackendService,
44
VariantDto,
@@ -13,6 +13,7 @@ import {AutoSaveService} from "./auto-save.service";
1313
import {LogService} from "../../logger/log.service";
1414
import {VersionId} from "../../view/variant/variant-view/variant-history/model";
1515
import {UndoService} from "./undo.service";
16+
import {environment} from "../../../environments/environment";
1617

1718
@Injectable({
1819
providedIn: "root",
@@ -34,7 +35,8 @@ export class VersionControlService implements OnDestroy {
3435
private readonly undoService: UndoService,
3536
private readonly logService: LogService,
3637
) {
37-
autoSaveService.autosaveTrigger$
38+
if (!environment.disableBackend) {
39+
autoSaveService.autosaveTrigger$
3840
.pipe(
3941
takeUntil(this.destroyed),
4042
filter(() => this.variant.isWritable),
@@ -43,6 +45,7 @@ export class VersionControlService implements OnDestroy {
4345
logService.debug("auto saving changes");
4446
this.createSnapshot();
4547
});
48+
}
4649
}
4750

4851
get variant(): VariantDto {
@@ -69,6 +72,12 @@ export class VersionControlService implements OnDestroy {
6972
});
7073
}
7174

75+
loadNetzgrafikDTO(netzgrafik: NetzgrafikDto) {
76+
this.dataService.loadNetzgrafikDto(netzgrafik);
77+
this.autoSaveService.reset();
78+
this.undoService.reset(this.undoService.getCurrentVariantId() + 1);
79+
}
80+
7281
reload(loadModel = false): void {
7382
this.load(this.variant.id, loadModel);
7483
}

src/app/view/column-layout/column-layout.component.html

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
id="cd-layout-content"
33
[ngClass]="['mode-' + mode]"
44
[class.new-view]="newView"
5+
[attr.style]="getLayoutContentStyle()"
56
>
67
<div
78
id="cd-layout-filter"

src/app/view/column-layout/column-layout.component.ts

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Input,
88
Output,
99
} from "@angular/core";
10+
import {environment} from "../../../environments/environment";
1011

1112
/**
1213
* Different layout modes. Generally the layout contains (up to) 3 columns that are distributed over a 4 columen layout:
@@ -70,6 +71,13 @@ export class ColumnLayoutComponent implements AfterViewInit {
7071
this.newView = false;
7172
}
7273

74+
getLayoutContentStyle(): string {
75+
if (environment.disableBackend) {
76+
return "height: 100%;";
77+
}
78+
return "";
79+
}
80+
7381
hideAside() {
7482
switch (this.mode) {
7583
case LayoutMode.FILTER_ONLY:

src/app/view/editor-menu/editor-menu.component.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@
235235
class="NoteEditor"
236236
[class.isStreckengrafikEditing]="isStreckengrafikEditing()"
237237
>
238-
<ng-container *ngIf="!isNoteEditing()">
238+
<ng-container *ngIf="!isNoteEditing() && !disableBackend">
239239
<button
240240
mode="icon"
241241
class="ButtonNoteEditor NetzgrafikEditing"
@@ -254,7 +254,7 @@
254254
></sbb-icon>
255255
</button>
256256
</ng-container>
257-
<ng-container *ngIf="isNoteEditing()">
257+
<ng-container *ngIf="isNoteEditing() && !disableBackend">
258258
<button
259259
mode="icon"
260260
class="ButtonNoteEditor NoteEditing"

src/app/view/editor-menu/editor-menu.component.ts

+3
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ import {TimeSliderService} from "../../streckengrafik/services/time-slider.servi
2323
import {SliderChangeInfo} from "../../streckengrafik/model/util/sliderChangeInfo";
2424
import {IsTrainrunSelectedService} from "../../services/data/is-trainrun-section.service";
2525
import {Node} from "../../models/node.model";
26+
import {environment} from "../../../environments/environment";
2627

2728
@Component({
2829
selector: "sbb-editor-menu",
2930
templateUrl: "./editor-menu.component.html",
3031
styleUrls: ["./editor-menu.component.scss"],
3132
})
3233
export class EditorMenuComponent implements OnInit, OnDestroy {
34+
readonly disableBackend = environment.disableBackend;
35+
3336
public zoomFactor = 100;
3437
public streckengrafikZoomFactor = 0;
3538

src/environments/environment.model.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {AuthConfig} from "angular-oauth2-oidc";
33
export interface Environment {
44
production: boolean;
55
label: string;
6-
backendUrl: string;
7-
authConfig: AuthConfig;
6+
backendUrl?: string;
7+
authConfig?: AuthConfig;
8+
disableBackend: boolean;
89
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {Environment} from "./environment.model";
2+
3+
export const environment: Environment = {
4+
production: true,
5+
label: "standalone",
6+
disableBackend: true,
7+
};

0 commit comments

Comments
 (0)