├── src ├── assets │ └── .gitkeep ├── app │ ├── shell │ │ ├── home │ │ │ ├── home.component.css │ │ │ ├── home.component.html │ │ │ └── home.component.ts │ │ ├── +state │ │ │ └── state.ts │ │ ├── navbar │ │ │ ├── navbar.component.html │ │ │ └── navbar.component.ts │ │ ├── sidebar │ │ │ ├── sidebar.component.css │ │ │ ├── sidebar.component.html │ │ │ └── sidebar.component.ts │ │ └── about │ │ │ ├── lazy │ │ │ └── lazy.component.ts │ │ │ └── about.component.ts │ ├── domains │ │ ├── ticketing │ │ │ ├── ui-common │ │ │ │ ├── flight-card │ │ │ │ │ ├── flight-card.component.css │ │ │ │ │ ├── flight-card.component.html │ │ │ │ │ └── flight-card.component.ts │ │ │ │ └── index.ts │ │ │ ├── feature-booking │ │ │ │ ├── flight-edit │ │ │ │ │ ├── flight-edit.component.css │ │ │ │ │ ├── flight-edit.component.html │ │ │ │ │ └── flight-edit.component.ts │ │ │ │ ├── flight-search │ │ │ │ │ ├── flight-search.component.css │ │ │ │ │ ├── flight-search.component.html │ │ │ │ │ └── flight-search.component.ts │ │ │ │ ├── index.ts │ │ │ │ ├── passenger-search │ │ │ │ │ ├── passenger-search.component.css │ │ │ │ │ ├── passenger-search.component.html │ │ │ │ │ └── passenger-search.component.ts │ │ │ │ ├── flight-booking.component.html │ │ │ │ ├── flight-booking.component.ts │ │ │ │ ├── utils │ │ │ │ │ └── booking.interceptor.ts │ │ │ │ ├── provider.ts │ │ │ │ └── flight-booking.routes.ts │ │ │ ├── feature-next-flight │ │ │ │ ├── index.ts │ │ │ │ └── next-flight.component.ts │ │ │ ├── feature-my-tickets │ │ │ │ ├── index.ts │ │ │ │ ├── ticket.service.ts │ │ │ │ ├── my-tickets.component.ts │ │ │ │ └── tickets.module.ts │ │ │ └── data │ │ │ │ ├── passenger.ts │ │ │ │ ├── index.ts │ │ │ │ ├── flight.ts │ │ │ │ ├── +state │ │ │ │ ├── selectors.ts │ │ │ │ ├── actions.ts │ │ │ │ ├── effects.ts │ │ │ │ └── reducers.ts │ │ │ │ └── flight.service.ts │ │ └── checkin │ │ │ ├── data │ │ │ ├── index.ts │ │ │ ├── hidden.service.ts │ │ │ └── checkin.service.ts │ │ │ └── feature-manage │ │ │ ├── feature-manage.component.css │ │ │ ├── index.ts │ │ │ ├── feature-manage.component.html │ │ │ └── feature-manage.component.ts │ ├── shared │ │ ├── util-auth │ │ │ ├── index.ts │ │ │ ├── auth.service.ts │ │ │ └── auth.interceptor.ts │ │ ├── util-logger │ │ │ ├── log-level.ts │ │ │ ├── color-config.ts │ │ │ ├── index.ts │ │ │ ├── log-formatter.ts │ │ │ ├── logger-config.ts │ │ │ ├── color.service.ts │ │ │ ├── log-appender.ts │ │ │ ├── features.ts │ │ │ ├── logger-module.ts │ │ │ ├── log.service.ts │ │ │ └── providers.ts │ │ └── util-common │ │ │ ├── index.ts │ │ │ ├── combine-environment-providers.ts │ │ │ ├── city.pipe.ts │ │ │ ├── city.validator.ts │ │ │ └── legacy.interceptor.ts │ ├── app.component.html │ ├── init.service.ts │ ├── logger.config.ts │ ├── app.component.css │ ├── app.routes.ts │ └── app.component.ts ├── favicon.ico ├── styles.css ├── index.html └── main.ts ├── .detective ├── hash ├── config.json └── log ├── update.sh ├── .vscode ├── extensions.json ├── launch.json ├── tasks.json └── settings.json ├── tsconfig.app.json ├── tsconfig.spec.json ├── .editorconfig ├── .gitignore ├── sheriff.config.ts ├── tsconfig.json ├── README.md ├── .eslintrc.json ├── package.json ├── angular.json └── deps.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/shell/home/home.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.detective/hash: -------------------------------------------------------------------------------- 1 | e86440ef0b0e1366ad344ca1e66eab4093caccde, v1.3.0 -------------------------------------------------------------------------------- /src/app/domains/ticketing/ui-common/flight-card/flight-card.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/shell/home/home.component.html: -------------------------------------------------------------------------------- 1 |

Welcome!

-------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | npm i detective@latest --registry http://localhost:4873 2 | -------------------------------------------------------------------------------- /src/app/domains/checkin/data/index.ts: -------------------------------------------------------------------------------- 1 | export * from './checkin.service'; 2 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/index.ts: -------------------------------------------------------------------------------- 1 | export * from './flight-booking.routes'; -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/passenger-search/passenger-search.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-next-flight/index.ts: -------------------------------------------------------------------------------- 1 | export * from './next-flight.component'; -------------------------------------------------------------------------------- /src/app/domains/ticketing/ui-common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './flight-card/flight-card.component'; 2 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/standalone-example-cli/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/app/shared/util-auth/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auth.interceptor'; 2 | export * from './auth.service'; 3 | -------------------------------------------------------------------------------- /src/app/domains/checkin/feature-manage/feature-manage.component.css: -------------------------------------------------------------------------------- 1 | .form-control { 2 | max-width: 300px; 3 | } -------------------------------------------------------------------------------- /src/app/domains/checkin/feature-manage/index.ts: -------------------------------------------------------------------------------- 1 | // Public API 2 | 3 | export * from './feature-manage.component'; 4 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/log-level.ts: -------------------------------------------------------------------------------- 1 | export enum LogLevel { 2 | DEBUG = 0, 3 | INFO = 1, 4 | ERROR = 2 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | body { 3 | background-color:#fafafa; 4 | } -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-my-tickets/index.ts: -------------------------------------------------------------------------------- 1 | export * from './my-tickets.component'; 2 | export * from './ticket.service'; 3 | export * from './tickets.module'; -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.html: -------------------------------------------------------------------------------- 1 |

Flight Edit

2 | 3 |

Id: {{id}}

4 |

ShowDetails: {{showDetails}}

5 | -------------------------------------------------------------------------------- /src/app/shared/util-common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './city.pipe'; 2 | export * from './city.validator'; 3 | export * from './legacy.interceptor' 4 | export * from './combine-environment-providers' 5 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 |
8 | 9 |
-------------------------------------------------------------------------------- /src/app/domains/ticketing/data/passenger.ts: -------------------------------------------------------------------------------- 1 | export interface Passenger { 2 | id: number; 3 | firstName: string, 4 | name: string; 5 | bonusMiles: number; 6 | passengerStatus: string; 7 | } -------------------------------------------------------------------------------- /src/app/domains/checkin/data/hidden.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({providedIn: 'root'}) 4 | export class HiddenService { 5 | doInternalStuff() { 6 | return 4711; 7 | } 8 | } -------------------------------------------------------------------------------- /src/app/init.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({providedIn: 'root'}) 4 | export class InitService { 5 | init(): void { 6 | console.debug('Initializing stuff ...'); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/app/domains/checkin/feature-manage/feature-manage.component.html: -------------------------------------------------------------------------------- 1 |

Checkin

2 | 3 |
4 | Ticket Number: 5 |
6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/app/shared/util-auth/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({providedIn: 'root'}) 4 | export class AuthService { 5 | isAuthenticated(): boolean { 6 | // Just for demo purposes 7 | return true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/index.ts: -------------------------------------------------------------------------------- 1 | export * from './+state/actions'; 2 | export * from './+state/effects'; 3 | export * from './+state/reducers'; 4 | export * from './+state/selectors'; 5 | export * from './flight.service'; 6 | export * from './flight'; 7 | export * from './passenger'; 8 | -------------------------------------------------------------------------------- /src/app/shell/+state/state.ts: -------------------------------------------------------------------------------- 1 | import { createReducer } from "@ngrx/store" 2 | 3 | export interface AppState { 4 | userName: string; 5 | } 6 | 7 | export const initState: AppState = { 8 | userName: 'Jane Doe' 9 | } 10 | 11 | export const reducer = createReducer( 12 | initState 13 | ); -------------------------------------------------------------------------------- /src/app/logger.config.ts: -------------------------------------------------------------------------------- 1 | import { DefaultLogAppender, defaultLogFormatFn, LoggerConfig, LogLevel } from "./shared/util-logger"; 2 | 3 | export const loggerConfig: Partial = { 4 | level: LogLevel.DEBUG, 5 | appenders: [DefaultLogAppender], 6 | formatter: defaultLogFormatFn, 7 | }; 8 | -------------------------------------------------------------------------------- /src/app/domains/checkin/data/checkin.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class CheckinService { 7 | 8 | checkin(ticketNumber: string): void { 9 | console.log('checking in', ticketNumber); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/flight.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface Flight { 3 | id: number; 4 | from: string; 5 | to: string; 6 | date: string; 7 | delayed: boolean; 8 | } 9 | 10 | export const initFlight: Flight = { 11 | id: 0, 12 | from: '', 13 | to: '', 14 | date: '', 15 | delayed: false 16 | }; 17 | -------------------------------------------------------------------------------- /src/app/shell/navbar/navbar.component.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | Flighs42 10 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- 1 | .sidenav-container { 2 | height: 100%; 3 | } 4 | 5 | .sidenav { 6 | width: 200px; 7 | } 8 | 9 | .sidenav .mat-toolbar { 10 | background: inherit; 11 | } 12 | 13 | .mat-toolbar.mat-primary { 14 | position: sticky; 15 | top: 0; 16 | z-index: 1; 17 | } 18 | 19 | .app-container { 20 | padding: 20px; 21 | } -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /src/app/shell/sidebar/sidebar.component.css: -------------------------------------------------------------------------------- 1 | .sidenav-container { 2 | height: 100%; 3 | } 4 | 5 | .sidenav { 6 | width: 200px; 7 | } 8 | 9 | .sidenav .mat-toolbar { 10 | background: inherit; 11 | } 12 | 13 | .mat-toolbar.mat-primary { 14 | position: sticky; 15 | top: 0; 16 | z-index: 1; 17 | } 18 | 19 | .app-container { 20 | padding: 20px; 21 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StandaloneCli 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/app/shared/util-common/combine-environment-providers.ts: -------------------------------------------------------------------------------- 1 | import { EnvironmentProviders, makeEnvironmentProviders, Provider } from "@angular/core"; 2 | 3 | export function combineEnvironmentProviders(envProviders: EnvironmentProviders[]): EnvironmentProviders { 4 | const providers = envProviders as unknown as Provider[][]; 5 | return makeEnvironmentProviders(providers.flat()); 6 | } 7 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/color-config.ts: -------------------------------------------------------------------------------- 1 | export abstract class ColorConfig { 2 | abstract debug: number; 3 | abstract info: number; 4 | abstract error: number; 5 | } 6 | 7 | // Color Code from https://en.m.wikipedia.org/wiki/ANSI_escape_code#Colors 8 | export const defaultColorConfig: ColorConfig = { 9 | debug: 32, 10 | info: 34, 11 | error: 31 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/index.ts: -------------------------------------------------------------------------------- 1 | export * from './color-config'; 2 | export * from './color.service'; 3 | export * from './features'; 4 | export * from './log-appender'; 5 | export * from './log-formatter'; 6 | export * from './log-level'; 7 | export * from './logger-config'; 8 | export * from './logger-module'; 9 | export * from './log.service'; 10 | export * from './providers'; 11 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/+state/selectors.ts: -------------------------------------------------------------------------------- 1 | import { createFeatureSelector, createSelector } from "@ngrx/store"; 2 | import { BookingState, BOOKING_FEATURE_KEY } from "./reducers"; 3 | 4 | export const selectBooking = createFeatureSelector(BOOKING_FEATURE_KEY); 5 | 6 | export const selectFlights = createSelector( 7 | selectBooking, 8 | booking => booking.flights 9 | ); 10 | -------------------------------------------------------------------------------- /src/app/shell/about/lazy/lazy.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component } from "@angular/core"; 3 | 4 | @Component({ 5 | standalone: true, 6 | selector: 'app-lazy', 7 | imports: [CommonModule], 8 | template: `

{{ title }}

` 9 | }) 10 | export class LazyComponent { 11 | title = 'Standalone Demo'; 12 | visible = true; 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/log-formatter.ts: -------------------------------------------------------------------------------- 1 | import {InjectionToken} from "@angular/core"; 2 | import {LogLevel} from "./log-level"; 3 | 4 | export const LOG_FORMATTER = new InjectionToken('LOG_FORMATTER'); 5 | 6 | export type LogFormatFn = (level: LogLevel, category: string, msg: string) => string; 7 | 8 | export const defaultLogFormatFn: LogFormatFn = (level, category, msg) => { 9 | const levelString = LogLevel[level].padEnd(5); 10 | return `[${levelString}] ${category.toUpperCase()} ${msg}`; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/+state/actions.ts: -------------------------------------------------------------------------------- 1 | import { createAction, props } from "@ngrx/store"; 2 | import { Flight } from "../flight"; 3 | 4 | export const loadFlights = createAction( 5 | "[booking] loadFlights", 6 | props<{from: string, to: string}>() 7 | ); 8 | 9 | export const delayFlight = createAction( 10 | "[booking] delayFlight", 11 | props<{id: number}>() 12 | ); 13 | 14 | export const loadFlightsSuccess = createAction( 15 | "[booking] loadFlightsSuccess", 16 | props<{flights: Flight[]}>() 17 | ); -------------------------------------------------------------------------------- /.detective/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "scopes": [ 3 | "src/app/shared", 4 | "src/app/domains/checkin", 5 | "src/app/domains/ticketing" 6 | ], 7 | "groups": [ 8 | "src/app/domains", 9 | "src/app" 10 | ], 11 | "entries": [], 12 | "filter": { 13 | "files": [], 14 | "logs": [] 15 | }, 16 | "aliases": {}, 17 | "teams": { 18 | "example-team-a": [ 19 | "John Doe", 20 | "Jane Doe" 21 | ], 22 | "example-team-b": [ 23 | "Max Muster", 24 | "Susi Sorglos" 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/passenger-search/passenger-search.component.html: -------------------------------------------------------------------------------- 1 |

Passengers

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
IdFirstNameNameBonus MilesStatus
{{p.id}}{{p.firstName}}{{p.name}}{{p.bonusMiles}}{{p.passengerStatus}}
-------------------------------------------------------------------------------- /src/app/shell/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from "@angular/core"; 2 | import { LogService } from "../../shared/util-logger"; 3 | 4 | @Component({ 5 | standalone: true, 6 | selector: 'app-home', 7 | templateUrl: './home.component.html' 8 | }) 9 | export class HomeComponent { 10 | logger = inject(LogService); 11 | 12 | constructor() { 13 | this.logger.debug('home', 'My Debug Message'); 14 | this.logger.info('home', 'My Info Message'); 15 | this.logger.error('home', 'My Error Message'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-next-flight/next-flight.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | 3 | // eslint-disable-next-line @softarc/sheriff/dependency-rule 4 | import {TicketsModule} from '../feature-my-tickets'; 5 | 6 | @Component({ 7 | selector: 'app-next-flight', 8 | standalone: true, 9 | template: ` 10 | 11 | `, 12 | imports: [ 13 | TicketsModule 14 | ] 15 | }) 16 | export class NextFlightComponent { 17 | } 18 | 19 | export default NextFlightComponent; 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-booking.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 14 | 15 |
16 |
17 | 18 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-booking.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from "@angular/core"; 2 | import { RouterLink, RouterOutlet } from "@angular/router"; 3 | import { LogService } from "../../../shared/util-logger"; 4 | 5 | @Component({ 6 | standalone: true, 7 | selector: 'app-flight-booking', 8 | imports: [ 9 | RouterOutlet, 10 | RouterLink, 11 | ], 12 | templateUrl: './flight-booking.component.html' 13 | }) 14 | export class FlightBookingComponent { 15 | logger = inject(LogService); 16 | 17 | constructor() { 18 | this.logger.info('booking', 'Hello from Booking'); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/shared/util-auth/auth.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { HttpInterceptorFn } from "@angular/common/http"; 2 | import { tap } from "rxjs"; 3 | 4 | export const authInterceptor: HttpInterceptorFn = (req, next) => { 5 | 6 | console.log('authInterceptor (root scope)'); 7 | 8 | if (req.url.startsWith('https://demo.angulararchitects.io/api/')) { 9 | // Setting a dummy token for demonstration 10 | const headers = req.headers.set('Authorization', 'Bearer Auth-1234567'); 11 | req = req.clone({headers}); 12 | } 13 | 14 | return next(req).pipe( 15 | tap(resp => console.log('response', resp)) 16 | ); 17 | } -------------------------------------------------------------------------------- /src/app/shared/util-logger/logger-config.ts: -------------------------------------------------------------------------------- 1 | import { Type } from "@angular/core"; 2 | import { DefaultLogAppender, LogAppender } from "./log-appender"; 3 | import { defaultLogFormatFn, LogFormatFn } from "./log-formatter"; 4 | import { LogLevel } from "./log-level"; 5 | 6 | export abstract class LoggerConfig { 7 | abstract level: LogLevel; 8 | abstract chaining: boolean; 9 | abstract formatter: LogFormatFn; 10 | abstract appenders: Type[]; 11 | } 12 | 13 | export const defaultConfig: LoggerConfig = { 14 | level: LogLevel.DEBUG, 15 | chaining: false, 16 | formatter: defaultLogFormatFn, 17 | appenders: [DefaultLogAppender] 18 | } 19 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/utils/booking.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { HttpInterceptorFn } from "@angular/common/http"; 2 | import { tap } from "rxjs"; 3 | 4 | export const bookingInterceptor: HttpInterceptorFn = (req, next) => { 5 | 6 | console.log('bookingInterceptor (lazy scope)'); 7 | 8 | if (req.url.startsWith('https://demo.angulararchitects.io/api/')) { 9 | // Setting a dummy token for demonstration 10 | const headers = req.headers.set('Authorization', 'Bearer Booking-ABCDEFG'); 11 | req = req.clone({headers}); 12 | } 13 | 14 | return next(req).pipe( 15 | tap(resp => console.log('response', resp)) 16 | ); 17 | } -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-my-tickets/ticket.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Flight } from '../data'; 3 | 4 | @Injectable() 5 | export class TicketService { 6 | 7 | readonly tickets: Flight[] = [ 8 | { id: 4711, from: 'Graz', to: 'Düsseldorf', delayed: false, date: new Date().toISOString()}, 9 | { id: 4712, from: 'Graz', to: 'Paderborn', delayed: false, date: new Date().toISOString()} 10 | ]; 11 | 12 | constructor() { 13 | console.debug('creating ticket service'); 14 | } 15 | 16 | get(limit = -1) { 17 | if (limit === -1) { 18 | return this.tickets; 19 | } 20 | return this.tickets.slice(0, limit); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/+state/effects.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { Actions, createEffect, ofType } from "@ngrx/effects"; 3 | import { map, switchMap } from "rxjs"; 4 | import { FlightService } from "../flight.service"; 5 | import { loadFlights, loadFlightsSuccess } from "./actions"; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class BookingEffects { 11 | 12 | loadFlights$ = createEffect(() => this.actions$.pipe( 13 | ofType(loadFlights), 14 | switchMap(a => this.flightService.find(a.from, a.to)), 15 | map(flights => loadFlightsSuccess({flights})) 16 | )); 17 | 18 | constructor(private actions$: Actions, 19 | private flightService: FlightService) { } 20 | } 21 | -------------------------------------------------------------------------------- /src/app/shell/about/about.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit, ViewChild, ViewContainerRef} from "@angular/core"; 2 | 3 | @Component({ 4 | standalone: true, 5 | selector: 'app-about', 6 | template: ` 7 |

About

8 | 9 | ` 10 | }) 11 | export class AboutComponent implements OnInit{ 12 | title = 'Standalone Demo'; 13 | 14 | @ViewChild('container', {read: ViewContainerRef}) 15 | viewContainer!: ViewContainerRef; 16 | 17 | async ngOnInit() { 18 | const esm = await import('./lazy/lazy.component'); 19 | const ref = this.viewContainer.createComponent(esm.LazyComponent) 20 | ref.instance.title = `Lazy Sub Component !!`; 21 | } 22 | } 23 | 24 | export default AboutComponent; 25 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/color.service.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from "@angular/core"; 2 | import { ColorConfig } from "./color-config"; 3 | import { LogLevel } from "./log-level"; 4 | 5 | export abstract class ColorService { 6 | abstract apply(level: LogLevel, msg: string): string; 7 | } 8 | 9 | @Injectable() 10 | export class DefaultColorService implements ColorService { 11 | config = inject(ColorConfig); 12 | 13 | apply(level: LogLevel, msg: string): string { 14 | const key = LogLevel[level].toLowerCase() as keyof ColorConfig; 15 | const color = this.config[key]; 16 | 17 | // For the sake of simplicity, we don't use an external 18 | // library like chalk here 19 | return `\x1b[${color}m${msg}\x1b[0m`; 20 | } 21 | } -------------------------------------------------------------------------------- /src/app/shared/util-common/city.pipe.ts: -------------------------------------------------------------------------------- 1 | import {Pipe, PipeTransform} from '@angular/core'; 2 | 3 | @Pipe({ 4 | standalone: true, 5 | name: 'city', 6 | pure: true 7 | }) 8 | export class CityPipe implements PipeTransform { 9 | 10 | transform(value: string, fmt: string): string { 11 | 12 | let short, long; 13 | 14 | switch (value) { 15 | case 'Hamburg': 16 | short = 'HAM'; 17 | long = 'Airport Hamburg Fulsbüttel Helmut Schmidt'; 18 | break; 19 | case 'Graz': 20 | short = 'GRZ'; 21 | long = 'Flughafen Graz Thalerhof'; 22 | break; 23 | default: 24 | short = long = value; //'ROM'; 25 | } 26 | 27 | if (fmt === 'short') return short; 28 | return long; 29 | 30 | } 31 | 32 | } 33 | 34 | // TEST 123 456 35 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/ui-common/flight-card/flight-card.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |

{{item.from | city:'short' }} - {{item.to | city:'short'}}

5 |
6 | 7 |
8 |

Flight-No.: #{{item.id}}

9 |

Date: {{item.date | date:'dd.MM.yyyy HH:mm:ss'}}

10 |

11 | 12 | 13 | Edit 14 |

15 |
16 | 17 |
18 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/log-appender.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable, InjectionToken } from "@angular/core"; 2 | import { ColorService } from "./color.service"; 3 | import { LogLevel } from "./log-level"; 4 | 5 | export abstract class LogAppender { 6 | abstract append(level: LogLevel, category: string, msg: string): void 7 | } 8 | 9 | @Injectable() 10 | export class DefaultLogAppender implements LogAppender { 11 | colorService = inject(ColorService, { optional: true, self: true }); 12 | 13 | append(level: LogLevel, category: string, msg: string): void { 14 | if (this.colorService) { 15 | msg = this.colorService.apply(level, msg); 16 | } 17 | console.log(msg); 18 | } 19 | } 20 | 21 | export const LOG_APPENDERS = new InjectionToken('LOG_APPENDERS'); -------------------------------------------------------------------------------- /src/app/domains/checkin/feature-manage/feature-manage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { CheckinService } from '../data'; 5 | 6 | import { LogService} from '../../../shared/util-logger'; 7 | 8 | @Component({ 9 | selector: 'app-feature-manage', 10 | standalone: true, 11 | imports: [CommonModule, FormsModule], 12 | templateUrl: './feature-manage.component.html', 13 | styleUrls: ['./feature-manage.component.css'], 14 | }) 15 | export class FeatureManageComponent { 16 | service = inject(CheckinService); 17 | logger = inject(LogService); 18 | 19 | ticketNumber = ''; 20 | 21 | checkin() { 22 | this.service.checkin(this.ticketNumber); 23 | } 24 | } 25 | 26 | // TEST 123 456 27 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-my-tickets/my-tickets.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, OnInit } from '@angular/core'; 2 | import { Flight } from '../data'; 3 | import { TicketService } from './ticket.service'; 4 | 5 | @Component({ 6 | selector: 'app-my-tickets', 7 | template: ` 8 |

{{title}}

9 | 10 | 11 | 12 | 13 | ` 14 | }) 15 | export class MyTicketsComponent implements OnInit { 16 | 17 | @Input() title = 'My Tickets'; 18 | @Input() limit = -1; 19 | 20 | tickets: Flight[] = []; 21 | 22 | constructor(private ticketService: TicketService) { } 23 | 24 | ngOnInit(): void { 25 | this.tickets = this.ticketService.get(this.limit); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/app/shared/util-common/city.validator.ts: -------------------------------------------------------------------------------- 1 | import { Directive } from '@angular/core'; 2 | import { Validator, AbstractControl, NG_VALIDATORS, ValidationErrors } from '@angular/forms'; 3 | 4 | @Directive({ 5 | standalone: true, 6 | selector: 'input[appCity]', 7 | providers: [ 8 | { 9 | provide: NG_VALIDATORS, 10 | useExisting: CityValidator, 11 | multi: true 12 | } 13 | ] 14 | }) 15 | export class CityValidator implements Validator { 16 | 17 | public validate(c: AbstractControl): ValidationErrors { 18 | 19 | if (c.value === 'Graz' 20 | || c.value === 'Hamburg' 21 | || c.value === 'Frankfurt' 22 | || c.value === 'Wien' 23 | || c.value === 'Mallorca') { 24 | 25 | return {}; 26 | } 27 | 28 | return { 29 | appCity: true 30 | }; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component, Inject, OnInit } from '@angular/core'; 3 | import { ActivatedRoute, RouterModule } from '@angular/router'; 4 | 5 | @Component({ 6 | standalone: true, 7 | imports: [CommonModule, RouterModule], 8 | selector: 'app-flight-edit', 9 | templateUrl: './flight-edit.component.html', 10 | }) 11 | export class FlightEditComponent implements OnInit { 12 | 13 | id: string | undefined; 14 | showDetails: string | undefined; 15 | showWarning = false; 16 | 17 | constructor(@Inject(ActivatedRoute) private route: ActivatedRoute) {} 18 | 19 | ngOnInit() { 20 | this.route.params.subscribe((p) => { 21 | this.id = p['id']; 22 | this.showDetails = p['showDetails']; 23 | }); 24 | } 25 | } 26 | 27 | // TEST 123 456 -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/passenger-search/passenger-search.component.ts: -------------------------------------------------------------------------------- 1 | import { JsonPipe, NgFor } from "@angular/common"; 2 | import { HttpClient } from "@angular/common/http"; 3 | import { Component, inject } from "@angular/core"; 4 | import { Passenger} from '../../data'; 5 | 6 | @Component({ 7 | standalone: true, 8 | imports: [ 9 | JsonPipe, 10 | NgFor, 11 | ], 12 | selector: 'app-passenger-search', 13 | templateUrl: './passenger-search.component.html', 14 | }) 15 | export class PassengerSearchComponent { 16 | private http = inject(HttpClient); 17 | 18 | passengers: Passenger[] = []; 19 | 20 | constructor() { 21 | const url = 'https://demo.angulararchitects.io/api/passenger'; 22 | this.http.get(url).subscribe( 23 | passengers => { 24 | this.passengers = passengers; 25 | } 26 | ); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/app/shared/util-common/legacy.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpInterceptor, HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http'; 3 | import { Observable, tap } from 'rxjs'; 4 | 5 | @Injectable() 6 | export class LegacyInterceptor implements HttpInterceptor { 7 | intercept(req: HttpRequest, next: HttpHandler): Observable> { 8 | 9 | console.log('LegacyInterceptor (root scope)'); 10 | 11 | if (req.url.startsWith('https://demo.angulararchitects.io/api/')) { 12 | // Setting a dummy token for demonstration 13 | const headers = req.headers.set('Authorization', 'Bearer Legacy-1234567'); 14 | req = req.clone({headers}); 15 | } 16 | 17 | return next.handle(req).pipe( 18 | tap(resp => console.log('response', resp)) 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/provider.ts: -------------------------------------------------------------------------------- 1 | import {provideHttpClient, withInterceptors, withRequestsMadeViaParent} from "@angular/common/http"; 2 | import {EnvironmentProviders} from "@angular/core"; 3 | import {provideEffects} from "@ngrx/effects"; 4 | import {provideState} from "@ngrx/store"; 5 | import {combineEnvironmentProviders} from "../../../shared/util-common"; 6 | import {BookingEffects, bookingFeature} from "../data"; 7 | import {bookingInterceptor} from "./utils/booking.interceptor"; 8 | 9 | export function provideBooking(): EnvironmentProviders { 10 | return combineEnvironmentProviders([ 11 | // NGRX 12 | provideState(bookingFeature), 13 | provideEffects(BookingEffects), 14 | 15 | // Http 16 | provideHttpClient( 17 | withRequestsMadeViaParent(), 18 | withInterceptors([bookingInterceptor]) 19 | ), 20 | ]); 21 | } 22 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/features.ts: -------------------------------------------------------------------------------- 1 | import { Provider } from "@angular/core"; 2 | import { ColorConfig, defaultColorConfig } from "./color-config"; 3 | import { ColorService, DefaultColorService } from "./color.service"; 4 | 5 | export enum LoggerFeatureKind { 6 | COLOR, 7 | OTHER_FEATURE, 8 | ADDITIONAL_FEATURE 9 | } 10 | 11 | 12 | export interface LoggerFeature { 13 | kind: LoggerFeatureKind; 14 | providers: Provider[]; 15 | } 16 | 17 | export function withColor(config?: Partial): LoggerFeature { 18 | 19 | const internal = { ...defaultColorConfig, ...config }; 20 | 21 | return { 22 | kind: LoggerFeatureKind.COLOR, 23 | providers: [ 24 | { 25 | provide: ColorConfig, 26 | useValue: internal 27 | }, 28 | { 29 | provide: ColorService, 30 | useClass: DefaultColorService, 31 | } 32 | ] 33 | } 34 | } -------------------------------------------------------------------------------- /src/app/shell/navbar/navbar.component.ts: -------------------------------------------------------------------------------- 1 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 2 | import { CommonModule } from '@angular/common'; 3 | import { Component, Inject } from '@angular/core'; 4 | import { MatIconModule } from '@angular/material/icon'; 5 | import { MatToolbarModule } from '@angular/material/toolbar'; 6 | import { map, shareReplay } from 'rxjs'; 7 | 8 | @Component({ 9 | standalone: true, 10 | selector: 'app-navbar-cmp', 11 | templateUrl: './navbar.component.html', 12 | imports: [ 13 | CommonModule, 14 | MatToolbarModule, 15 | MatIconModule 16 | ] 17 | }) 18 | export class NavbarComponent { 19 | isHandset$ = this.breakpointObserver.observe(Breakpoints.Handset) 20 | .pipe( 21 | map(result => result.matches), 22 | shareReplay() 23 | ); 24 | 25 | constructor( 26 | @Inject(BreakpointObserver) private breakpointObserver: BreakpointObserver) { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/shell/sidebar/sidebar.component.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | Menu 7 | 8 | 9 | Home 10 | Flights 11 | My Tickets 12 | Next Flight 13 |
14 | Checkin 15 |
16 | About 17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 |
25 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-my-tickets/tickets.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { MyTicketsComponent } from './my-tickets.component'; 4 | import { RouterModule } from '@angular/router'; 5 | import { TicketService } from './ticket.service'; 6 | import { FlightCardComponent } from '../ui-common'; 7 | 8 | // This is for demonstrating the interaction between 9 | // code that uses NgModules and code that doesn't. 10 | 11 | @NgModule({ 12 | imports: [ 13 | CommonModule, 14 | FlightCardComponent, 15 | RouterModule.forChild([ 16 | { path: 'my-tickets', component: MyTicketsComponent } 17 | ]) 18 | ], 19 | declarations: [ 20 | MyTicketsComponent 21 | ], 22 | providers: [ 23 | // For demo purposes 24 | // Please consider using providedIn: 'root' instead 25 | TicketService 26 | ], 27 | exports: [ 28 | MyTicketsComponent 29 | ] 30 | }) 31 | export class TicketsModule { } 32 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/logger-module.ts: -------------------------------------------------------------------------------- 1 | import { ModuleWithProviders, NgModule, Type } from '@angular/core'; 2 | import { LogAppender } from './log-appender'; 3 | import { defaultConfig } from './logger-config'; 4 | import { provideCategory, provideLogger } from './providers'; 5 | 6 | // NgModule for legacy code 7 | @NgModule({ 8 | imports: [], 9 | exports: [], 10 | declarations: [], 11 | providers: [], 12 | }) 13 | export class LoggerModule { 14 | 15 | static forRoot(config = defaultConfig): ModuleWithProviders { 16 | return { 17 | ngModule: LoggerModule, 18 | providers: [ 19 | provideLogger(config) 20 | ] 21 | }; 22 | } 23 | 24 | static forCategory(category: string, appender: Type): ModuleWithProviders { 25 | return { 26 | ngModule: LoggerModule, 27 | providers: [ 28 | provideCategory(category, appender) 29 | ] 30 | }; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /sheriff.config.ts: -------------------------------------------------------------------------------- 1 | import { noDependencies, sameTag, SheriffConfig } from '@softarc/sheriff-core'; 2 | 3 | export const sheriffConfig: SheriffConfig = { 4 | version: 1, 5 | tagging: { 6 | 'src/app': { 7 | 'shared': { 8 | 'feature-': ['shared', 'type:feature'], 9 | 'ui-': ['shared', 'type:ui'], 10 | 'data': ['shared', 'type:data'], 11 | 'util-': ['shared', 'type:util'], 12 | }, 13 | 'domains/': { 14 | 'feature-': ['domain:', 'type:feature'], 15 | 'ui-': ['domain:', 'type:ui'], 16 | 'data': ['domain:', 'type:data'], 17 | 'util-': ['domain:', 'type:util'], 18 | }, 19 | }, 20 | }, 21 | depRules: { 22 | 'root': ['*'], 23 | 'domain:*': [sameTag, 'shared'], 24 | 'shared': ['shared'], 25 | 'type:feature': ['type:ui', 'type:data', 'type:util'], 26 | 'type:ui': ['type:data', 'type:util'], 27 | 'type:data': ['type:util'], 28 | 'type:util': noDependencies 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/+state/reducers.ts: -------------------------------------------------------------------------------- 1 | import { createFeature, createReducer, on } from "@ngrx/store"; 2 | import { Flight } from "../flight"; 3 | import { delayFlight, loadFlightsSuccess } from "./actions"; 4 | 5 | export const BOOKING_FEATURE_KEY = 'booking'; 6 | 7 | export interface BookingSlice { 8 | [BOOKING_FEATURE_KEY]: BookingState 9 | } 10 | 11 | export interface BookingState { 12 | flights: Flight[]; 13 | } 14 | 15 | export const initialState: BookingState = { 16 | flights: [] 17 | } 18 | 19 | function updateDate(flight: Flight): Flight { 20 | return {...flight, date: new Date().toISOString() } 21 | } 22 | 23 | export const bookingFeature = createFeature({ 24 | name: BOOKING_FEATURE_KEY, 25 | reducer: createReducer( 26 | initialState, 27 | on(loadFlightsSuccess, (state, action) => { 28 | return { ...state, flights: action.flights }; 29 | }), 30 | on(delayFlight, (state, action) => { 31 | const flights = state.flights.map(f => f.id !== action.id ? f : updateDate(f) ) 32 | return { ...state, flights }; 33 | }) 34 | ) 35 | }); 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "esModuleInterop": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "sourceMap": true, 15 | "declaration": false, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ], 26 | "paths": { 27 | "@demo/checkin/data": ["src/app/domains/checkin/data/index.ts"] 28 | } 29 | }, 30 | "angularCompilerOptions": { 31 | "enableI18nLegacyMessageIdFormat": false, 32 | "strictInjectionParameters": true, 33 | "strictInputAccessModifiers": true, 34 | "strictTemplates": true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StandaloneCli 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.0.0. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": [ 4 | "projects/**/*" 5 | ], 6 | "overrides": [ 7 | { 8 | "files": [ 9 | "*.ts" 10 | ], 11 | "extends": [ 12 | "eslint:recommended", 13 | "plugin:@typescript-eslint/recommended", 14 | "plugin:@angular-eslint/recommended", 15 | "plugin:@angular-eslint/template/process-inline-templates" 16 | ], 17 | "rules": { 18 | "@angular-eslint/directive-selector": [ 19 | "error", 20 | { 21 | "type": "attribute", 22 | "prefix": "app", 23 | "style": "camelCase" 24 | } 25 | ], 26 | "@angular-eslint/component-selector": [ 27 | "error", 28 | { 29 | "type": "element", 30 | "prefix": "app", 31 | "style": "kebab-case" 32 | } 33 | ] 34 | } 35 | }, 36 | { 37 | "files": [ 38 | "*.html" 39 | ], 40 | "extends": [ 41 | "plugin:@angular-eslint/template/recommended" 42 | ], 43 | "rules": {} 44 | }, 45 | { 46 | "files": ["*.ts"], 47 | "extends": ["plugin:@softarc/sheriff/default"] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#93e6fc", 4 | "activityBar.activeBorder": "#fa45d4", 5 | "activityBar.background": "#93e6fc", 6 | "activityBar.foreground": "#15202b", 7 | "activityBar.inactiveForeground": "#15202b99", 8 | "activityBarBadge.background": "#fa45d4", 9 | "activityBarBadge.foreground": "#15202b", 10 | "sash.hoverBorder": "#93e6fc", 11 | "statusBar.background": "#61dafb", 12 | "statusBar.foreground": "#15202b", 13 | "statusBarItem.hoverBackground": "#2fcefa", 14 | "statusBarItem.remoteBackground": "#61dafb", 15 | "statusBarItem.remoteForeground": "#15202b", 16 | "titleBar.activeBackground": "#61dafb", 17 | "titleBar.activeForeground": "#15202b", 18 | "titleBar.inactiveBackground": "#61dafb99", 19 | "titleBar.inactiveForeground": "#15202b99", 20 | "commandCenter.border": "#15202b99" 21 | }, 22 | "peacock.color": "#61dafb", 23 | "files.exclude": { 24 | "**/.git": true, 25 | "**/.svn": true, 26 | "**/.hg": true, 27 | "**/CVS": true, 28 | "**/.DS_Store": true, 29 | "**/Thumbs.db": true 30 | }, 31 | "hide-files.files": [] 32 | } -------------------------------------------------------------------------------- /src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { inject } from "@angular/core"; 2 | import { Routes } from "@angular/router"; 3 | import { AuthService } from "./shared/util-auth"; 4 | import { HomeComponent } from "./shell/home/home.component"; 5 | 6 | export const APP_ROUTES: Routes = [ 7 | { 8 | path: '', 9 | pathMatch: 'full', 10 | redirectTo: 'home' 11 | }, 12 | { 13 | path: 'home', 14 | component: HomeComponent 15 | }, 16 | { 17 | path: 'flight-booking', 18 | canActivate: [() => inject(AuthService).isAuthenticated()], 19 | loadChildren: () => 20 | import('./domains/ticketing/feature-booking') 21 | .then(m => m.FLIGHT_BOOKING_ROUTES) 22 | }, 23 | { 24 | path: 'next-flight', 25 | loadComponent: () => 26 | import('./domains/ticketing/feature-next-flight') 27 | .then(m => m.NextFlightComponent) 28 | }, 29 | { 30 | path: 'checkin', 31 | loadComponent: () => import('./domains/checkin/feature-manage') 32 | .then(m => m.FeatureManageComponent) 33 | }, 34 | { 35 | path: 'about', 36 | loadComponent: () => 37 | import('./shell/about/about.component') 38 | // .then(m => m.AboutComponent) 39 | }, 40 | ]; 41 | -------------------------------------------------------------------------------- /src/app/shell/sidebar/sidebar.component.ts: -------------------------------------------------------------------------------- 1 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 2 | import { CommonModule } from '@angular/common'; 3 | import { Component, Inject } from '@angular/core'; 4 | import { MatButtonModule } from '@angular/material/button'; 5 | import { MatIconModule } from '@angular/material/icon'; 6 | import { MatListModule } from '@angular/material/list'; 7 | import { MatSidenavModule } from '@angular/material/sidenav'; 8 | import { MatToolbarModule } from '@angular/material/toolbar'; 9 | import { RouterModule } from '@angular/router'; 10 | import { map, shareReplay } from 'rxjs'; 11 | 12 | @Component({ 13 | standalone: true, 14 | selector: 'app-sidebar-cmp', 15 | imports: [ 16 | RouterModule, 17 | CommonModule, 18 | MatToolbarModule, 19 | MatButtonModule, 20 | MatSidenavModule, 21 | MatIconModule, 22 | MatListModule, 23 | ], 24 | templateUrl: './sidebar.component.html', 25 | styleUrls: ['./sidebar.component.css'] 26 | }) 27 | export class SidebarComponent { 28 | isHandset$ = this.breakpointObserver.observe(Breakpoints.Handset) 29 | .pipe( 30 | map(result => result.matches), 31 | shareReplay() 32 | ); 33 | 34 | constructor( 35 | @Inject(BreakpointObserver) private breakpointObserver: BreakpointObserver) { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-booking.routes.ts: -------------------------------------------------------------------------------- 1 | import {inject} from '@angular/core'; 2 | import {Routes} from '@angular/router'; 3 | import {provideEffects} from '@ngrx/effects'; 4 | import {provideState} from '@ngrx/store'; 5 | import {AuthService} from '../../../shared/util-auth'; 6 | import {BookingEffects, bookingFeature} from '../data'; 7 | import {FlightBookingComponent} from './flight-booking.component'; 8 | import {FlightEditComponent} from './flight-edit/flight-edit.component'; 9 | import {FlightSearchComponent} from './flight-search/flight-search.component'; 10 | import {PassengerSearchComponent} from './passenger-search/passenger-search.component'; 11 | 12 | export const FLIGHT_BOOKING_ROUTES: Routes = [ 13 | { 14 | path: '', 15 | component: FlightBookingComponent, 16 | canActivate: [() => inject(AuthService).isAuthenticated()], 17 | providers: [ 18 | // NGRX 19 | provideState(bookingFeature), 20 | provideEffects(BookingEffects), 21 | ], 22 | children: [ 23 | { 24 | path: 'flight-search', 25 | component: FlightSearchComponent, 26 | }, 27 | { 28 | path: 'passenger-search', 29 | component: PassengerSearchComponent, 30 | }, 31 | { 32 | path: 'flight-edit/:id', 33 | component: FlightEditComponent, 34 | }, 35 | ], 36 | }, 37 | ]; 38 | 39 | export default FLIGHT_BOOKING_ROUTES; 40 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 2 | import { map, shareReplay } from 'rxjs'; 3 | import { Component, Inject } from '@angular/core'; 4 | 5 | import { RouterOutlet } from '@angular/router'; 6 | import { MatToolbarModule } from '@angular/material/toolbar'; 7 | import { MatButtonModule } from '@angular/material/button'; 8 | import { MatSidenavModule } from '@angular/material/sidenav'; 9 | import { MatIconModule } from '@angular/material/icon'; 10 | import { MatListModule } from '@angular/material/list'; 11 | import { NavbarComponent } from './shell/navbar/navbar.component'; 12 | import { SidebarComponent } from './shell/sidebar/sidebar.component'; 13 | 14 | @Component({ 15 | standalone: true, 16 | selector: 'app-root', 17 | imports: [ 18 | RouterOutlet, 19 | 20 | MatToolbarModule, 21 | MatButtonModule, 22 | MatSidenavModule, 23 | MatIconModule, 24 | MatListModule, 25 | 26 | NavbarComponent, 27 | SidebarComponent, 28 | ], 29 | templateUrl: './app.component.html', 30 | styleUrls: ['./app.component.css'] 31 | }) 32 | export class AppComponent { 33 | 34 | isHandset$ = this.breakpointObserver.observe(Breakpoints.Handset) 35 | .pipe( 36 | map(result => result.matches), 37 | shareReplay() 38 | ); 39 | 40 | constructor( 41 | @Inject(BreakpointObserver) private breakpointObserver: BreakpointObserver) { 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/ui-common/flight-card/flight-card.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, ElementRef, EventEmitter, Input, NgZone, Output, inject } from "@angular/core"; 3 | import { RouterModule } from "@angular/router"; 4 | import { CityPipe } from "src/app/shared/util-common"; 5 | import { Flight, initFlight } from "../../data"; 6 | 7 | @Component({ 8 | standalone: true, 9 | selector: 'app-flight-card', 10 | imports: [CommonModule, RouterModule, CityPipe], 11 | templateUrl: './flight-card.component.html', 12 | }) 13 | export class FlightCardComponent { 14 | private element = inject(ElementRef); 15 | private zone = inject(NgZone); 16 | 17 | @Input() item: Flight = initFlight; 18 | @Input() selected: boolean | undefined; 19 | @Output() selectedChange = new EventEmitter(); 20 | @Input() showEditButton = true; 21 | 22 | select() { 23 | this.selected = true; 24 | this.selectedChange.next(true); 25 | } 26 | 27 | deselect() { 28 | this.selected = false; 29 | this.selectedChange.next(false); 30 | } 31 | 32 | blink() { 33 | // Dirty Hack used to visualize the change detector 34 | this.element.nativeElement.firstChild.style.backgroundColor = 'crimson'; 35 | 36 | this.zone.runOutsideAngular(() => { 37 | setTimeout(() => { 38 | this.element.nativeElement.firstChild.style.backgroundColor = 'white'; 39 | }, 1000); 40 | }); 41 | 42 | return null; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.html: -------------------------------------------------------------------------------- 1 |

Flight Search

2 | 3 |
4 | 5 |
6 | 7 | 8 |
9 | 10 |
11 | Invalid city! 12 |
13 | 14 |
15 | 16 | 17 |
18 |
19 | 24 |
25 | 26 |
27 | 30 | 31 | 34 | 35 |
36 | {{flights.length}} flights found! 37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 | 45 |
46 |
47 | 48 |
{{ basket | json }}
49 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { LayoutModule } from '@angular/cdk/layout'; 2 | import { provideHttpClient, withInterceptors } from '@angular/common/http'; 3 | import { importProvidersFrom } from '@angular/core'; 4 | import { bootstrapApplication } from '@angular/platform-browser'; 5 | import { provideAnimations } from '@angular/platform-browser/animations'; 6 | import { 7 | PreloadAllModules, 8 | provideRouter, 9 | withPreloading, 10 | } from '@angular/router'; 11 | import { provideEffects } from '@ngrx/effects'; 12 | import { provideStore } from '@ngrx/store'; 13 | import { provideStoreDevtools } from '@ngrx/store-devtools'; 14 | import { reducer } from './app/shell/+state/state'; 15 | import { AppComponent } from './app/app.component'; 16 | import { APP_ROUTES } from './app/app.routes'; 17 | import { authInterceptor } from './app/shared/util-auth'; 18 | import { provideLogger } from './app/shared/util-logger'; 19 | import { TicketsModule } from './app/domains/ticketing/feature-my-tickets'; 20 | import { loggerConfig } from './app/logger.config'; 21 | 22 | bootstrapApplication(AppComponent, { 23 | providers: [ 24 | provideHttpClient( 25 | withInterceptors([authInterceptor]), 26 | ), 27 | 28 | provideRouter( 29 | APP_ROUTES, 30 | withPreloading(PreloadAllModules) 31 | ), 32 | 33 | provideLogger(loggerConfig), 34 | 35 | provideStore(reducer), 36 | provideEffects(), 37 | provideStoreDevtools({connectInZone: true}), 38 | provideAnimations(), 39 | 40 | importProvidersFrom(TicketsModule), 41 | importProvidersFrom(LayoutModule), 42 | ], 43 | }); 44 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/log.service.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from '@angular/core'; 2 | import { LogAppender, LOG_APPENDERS } from './log-appender'; 3 | import { LOG_FORMATTER } from './log-formatter'; 4 | import { LogLevel } from './log-level'; 5 | import { LoggerConfig } from './logger-config'; 6 | 7 | @Injectable() 8 | export class LogService { 9 | private appenders = inject(LOG_APPENDERS); 10 | private formatter = inject(LOG_FORMATTER); 11 | private config = inject(LoggerConfig); 12 | 13 | private parentLogger = inject(LogService, { 14 | optional: true, 15 | skipSelf: true, 16 | }); 17 | 18 | readonly categories: Record = {}; 19 | 20 | log(level: LogLevel, category: string, msg: string): void { 21 | if (level < this.config.level) { 22 | return; 23 | } 24 | 25 | const formatted = this.formatter(level, category, msg); 26 | const catAppender = this.categories[category]; 27 | 28 | if (catAppender) { 29 | catAppender.append(level, category, formatted); 30 | } 31 | 32 | for (const a of this.appenders) { 33 | a.append(level, category, formatted); 34 | } 35 | 36 | if (this.config.chaining && this.parentLogger) { 37 | this.parentLogger.log(level, category, msg); 38 | } 39 | } 40 | 41 | error(category: string, msg: string): void { 42 | this.log(LogLevel.ERROR, category, msg); 43 | } 44 | 45 | info(category: string, msg: string): void { 46 | this.log(LogLevel.INFO, category, msg); 47 | } 48 | 49 | debug(category: string, msg: string): void { 50 | this.log(LogLevel.DEBUG, category, msg); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.ts: -------------------------------------------------------------------------------- 1 | import {AsyncPipe, JsonPipe, NgForOf, NgIf} from "@angular/common"; 2 | import {Component, inject} from "@angular/core"; 3 | import {FormsModule} from "@angular/forms"; 4 | import {Store} from "@ngrx/store"; 5 | import {take} from "rxjs"; 6 | import {ActivatedRoute} from "@angular/router"; 7 | import {BookingSlice, delayFlight, loadFlights, selectFlights} from "../../data"; 8 | import {CityValidator} from "src/app/shared/util-common"; 9 | import {FlightCardComponent} from "../../ui-common"; 10 | 11 | // import { HiddenService } from "../../../checkin/data/hidden.service"; 12 | // import { CheckinService } from "@demo/checkin/data"; 13 | 14 | 15 | @Component({ 16 | standalone: true, 17 | imports: [ 18 | // CommonModule, 19 | NgIf, 20 | NgForOf, 21 | AsyncPipe, 22 | JsonPipe, 23 | 24 | FormsModule, 25 | FlightCardComponent, 26 | CityValidator, 27 | ], 28 | selector: 'app-flight-search', 29 | templateUrl: './flight-search.component.html' 30 | }) 31 | export class FlightSearchComponent { 32 | 33 | private store = inject>(Store); 34 | 35 | from = 'Hamburg'; // in Germany 36 | to = 'Graz'; // in Austria 37 | urgent = false; 38 | 39 | flights$ = this.store.select(selectFlights); 40 | 41 | basket: Record = { 42 | 3: true, 43 | 5: true 44 | }; 45 | 46 | search(): void { 47 | if (!this.from || !this.to) return; 48 | 49 | this.store.dispatch(loadFlights({ 50 | from: this.from, 51 | to: this.to 52 | })); 53 | } 54 | 55 | delay(): void { 56 | this.flights$.pipe(take(1)).subscribe(flights => { 57 | const id = flights[0].id; 58 | this.store.dispatch(delayFlight({id})); 59 | }); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/app/shared/util-logger/providers.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EnvironmentProviders, 3 | ENVIRONMENT_INITIALIZER, 4 | inject, 5 | InjectionToken, 6 | makeEnvironmentProviders, 7 | Type, 8 | } from '@angular/core'; 9 | import { LoggerFeature, LoggerFeatureKind } from './features'; 10 | import { LogAppender, LOG_APPENDERS } from './log-appender'; 11 | import { LOG_FORMATTER } from './log-formatter'; 12 | import { LogService } from './log.service'; 13 | import { defaultConfig, LoggerConfig } from './logger-config'; 14 | 15 | export function provideLogger( 16 | config: Partial, 17 | ...features: LoggerFeature[] 18 | ): EnvironmentProviders { 19 | const merged = { ...defaultConfig, ...config }; 20 | 21 | const colorFeatures = 22 | features?.filter((f) => f.kind === LoggerFeatureKind.COLOR)?.length ?? 0; 23 | 24 | if (colorFeatures > 1) { 25 | throw new Error('Only one color feature allowed for logger!'); 26 | } 27 | 28 | return makeEnvironmentProviders([ 29 | LogService, 30 | { 31 | provide: LoggerConfig, 32 | useValue: merged, 33 | }, 34 | { 35 | provide: LOG_FORMATTER, 36 | useValue: merged.formatter, 37 | }, 38 | merged.appenders.map((a) => ({ 39 | provide: LOG_APPENDERS, 40 | useClass: a, 41 | multi: true, 42 | })), 43 | features?.map((f) => f.providers), 44 | ]); 45 | } 46 | 47 | export function provideCategory( 48 | category: string, 49 | appender: Type 50 | ): EnvironmentProviders { 51 | const appenderToken = new InjectionToken('APPENDER_' + category); 52 | return makeEnvironmentProviders([ 53 | { 54 | provide: appenderToken, 55 | useClass: appender, 56 | }, 57 | { 58 | provide: ENVIRONMENT_INITIALIZER, 59 | multi: true, 60 | useValue: () => { 61 | const appender = inject(appenderToken); 62 | const logger = inject(LogService); 63 | 64 | logger.categories[category] = appender; 65 | }, 66 | }, 67 | ]); 68 | } 69 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "standalone-cli", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test", 10 | "lint": "ng lint" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular-architects/paper-design": "^1.0.3", 15 | "@angular/animations": "^18.1.4", 16 | "@angular/cdk": "^18.1.4", 17 | "@angular/common": "^18.1.4", 18 | "@angular/compiler": "^18.1.4", 19 | "@angular/core": "^18.1.4", 20 | "@angular/forms": "^18.1.4", 21 | "@angular/material": "^18.1.4", 22 | "@angular/platform-browser": "^18.1.4", 23 | "@angular/platform-browser-dynamic": "^18.1.4", 24 | "@angular/router": "^18.1.4", 25 | "@ngrx/effects": "^18.0.2", 26 | "@ngrx/operators": "^18.0.0", 27 | "@ngrx/store": "^18.0.2", 28 | "@ngrx/store-devtools": "^18.0.2", 29 | "detective": "^0.0.1", 30 | "rxjs": "~7.8.1", 31 | "tslib": "^2.5.0", 32 | "zone.js": "~0.14.10" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/build-angular": "^18.1.4", 36 | "@angular-eslint/builder": "18.3.0", 37 | "@angular-eslint/eslint-plugin": "18.3.0", 38 | "@angular-eslint/eslint-plugin-template": "18.3.0", 39 | "@angular-eslint/schematics": "18.3.0", 40 | "@angular-eslint/template-parser": "18.3.0", 41 | "@angular/cli": "~18.1.4", 42 | "@angular/compiler-cli": "^18.1.4", 43 | "@softarc/detective": "^1.3.0", 44 | "@softarc/eslint-plugin-sheriff": "^0.16.1", 45 | "@softarc/sheriff-core": "^0.16.1", 46 | "@types/jasmine": "~4.3.1", 47 | "@typescript-eslint/eslint-plugin": "5.59.2", 48 | "@typescript-eslint/parser": "5.59.2", 49 | "eslint": "^8.40.0", 50 | "jasmine-core": "~4.6.0", 51 | "karma": "~6.4.2", 52 | "karma-chrome-launcher": "~3.2.0", 53 | "karma-coverage": "~2.2.0", 54 | "karma-jasmine": "~5.1.0", 55 | "karma-jasmine-html-reporter": "~2.0.0", 56 | "typescript": "~5.4.5" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/app/domains/ticketing/data/flight.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { Flight } from './flight'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class FlightService { 10 | flights: Flight[] = []; 11 | baseUrl = `https://demo.angulararchitects.io/api`; 12 | 13 | reqDelay = 1000; 14 | 15 | constructor(private http: HttpClient) {} 16 | 17 | load(from: string, to: string, urgent: boolean): void { 18 | this.find(from, to, urgent).subscribe({ 19 | next: (flights) => { 20 | this.flights = flights; 21 | }, 22 | error: (err) => console.error('Error loading flights', err), 23 | }); 24 | } 25 | 26 | find( 27 | from: string, 28 | to: string, 29 | urgent = false 30 | ): Observable { 31 | // For offline access 32 | // let url = '/assets/data/data.json'; 33 | 34 | // For online access 35 | let url = [this.baseUrl, 'flight'].join('/'); 36 | 37 | if (urgent) { 38 | url = [this.baseUrl, 'error?code=403'].join('/'); 39 | } 40 | 41 | const params = new HttpParams().set('from', from).set('to', to); 42 | 43 | const headers = new HttpHeaders().set('Accept', 'application/json'); 44 | 45 | return this.http.get(url, { params, headers }); 46 | // return of(flights).pipe(delay(this.reqDelay)) 47 | } 48 | 49 | findById(id: string): Observable { 50 | const reqObj = { params: new HttpParams().set('id', id) }; 51 | const url = [this.baseUrl, 'flight'].join('/'); 52 | return this.http.get(url, reqObj); 53 | // return of(flights[0]).pipe(delay(this.reqDelay)) 54 | } 55 | 56 | save(flight: Flight): Observable { 57 | const url = [this.baseUrl, 'flight'].join('/'); 58 | return this.http.post(url, flight); 59 | } 60 | 61 | delay() { 62 | const ONE_MINUTE = 1000 * 60; 63 | 64 | const oldFlights = this.flights; 65 | const oldFlight = oldFlights[0]; 66 | const oldDate = new Date(oldFlight.date); 67 | 68 | // Mutable 69 | oldDate.setTime(oldDate.getTime() + 15 * ONE_MINUTE); 70 | oldFlight.date = oldDate.toISOString(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "standalone-cli": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:application", 15 | "options": { 16 | "outputPath": { 17 | "base": "dist/standalone-cli" 18 | }, 19 | "index": "src/index.html", 20 | "polyfills": [ 21 | "zone.js" 22 | ], 23 | "tsConfig": "tsconfig.app.json", 24 | "assets": [ 25 | "src/favicon.ico", 26 | "src/assets" 27 | ], 28 | "styles": [ 29 | "node_modules/@angular-architects/paper-design/assets/css/bootstrap.css", 30 | "node_modules/@angular-architects/paper-design/assets/scss/paper-dashboard.scss", 31 | "node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 32 | "src/styles.css" 33 | ], 34 | "scripts": [], 35 | "browser": "src/main.ts" 36 | }, 37 | "configurations": { 38 | "production": { 39 | "budgets": [ 40 | { 41 | "type": "initial", 42 | "maximumWarning": "500kb", 43 | "maximumError": "1mb" 44 | }, 45 | { 46 | "type": "anyComponentStyle", 47 | "maximumWarning": "2kb", 48 | "maximumError": "4kb" 49 | } 50 | ], 51 | "outputHashing": "all" 52 | }, 53 | "development": { 54 | "optimization": false, 55 | "extractLicenses": false, 56 | "sourceMap": true, 57 | "namedChunks": true 58 | } 59 | }, 60 | "defaultConfiguration": "production" 61 | }, 62 | "serve": { 63 | "builder": "@angular-devkit/build-angular:dev-server", 64 | "configurations": { 65 | "production": { 66 | "buildTarget": "standalone-cli:build:production" 67 | }, 68 | "development": { 69 | "buildTarget": "standalone-cli:build:development" 70 | } 71 | }, 72 | "defaultConfiguration": "development" 73 | }, 74 | "extract-i18n": { 75 | "builder": "@angular-devkit/build-angular:extract-i18n", 76 | "options": { 77 | "buildTarget": "standalone-cli:build" 78 | } 79 | }, 80 | "test": { 81 | "builder": "@angular-devkit/build-angular:karma", 82 | "options": { 83 | "polyfills": [ 84 | "zone.js", 85 | "zone.js/testing" 86 | ], 87 | "tsConfig": "tsconfig.spec.json", 88 | "assets": [ 89 | "src/favicon.ico", 90 | "src/assets" 91 | ], 92 | "styles": [ 93 | "src/styles.css" 94 | ], 95 | "scripts": [] 96 | } 97 | }, 98 | "lint": { 99 | "builder": "@angular-eslint/builder:lint", 100 | "options": { 101 | "lintFilePatterns": [ 102 | "src/**/*.ts", 103 | "src/**/*.html" 104 | ] 105 | } 106 | } 107 | } 108 | } 109 | }, 110 | "cli": { 111 | "schematicCollections": [ 112 | "@angular-eslint/schematics" 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "src/main.ts": { 3 | "module": ".", 4 | "tags": [ 5 | "root" 6 | ], 7 | "imports": [ 8 | "src/app/shell/+state/state.ts", 9 | "src/app/app.component.ts", 10 | "src/app/app.routes.ts", 11 | "src/app/shared/util-auth/index.ts", 12 | "src/app/shared/util-logger/index.ts", 13 | "src/app/domains/ticketing/feature-my-tickets/index.ts", 14 | "src/app/logger.config.ts" 15 | ] 16 | }, 17 | "src/app/shell/+state/state.ts": { 18 | "module": ".", 19 | "tags": [ 20 | "root" 21 | ], 22 | "imports": [] 23 | }, 24 | "src/app/app.component.ts": { 25 | "module": ".", 26 | "tags": [ 27 | "root" 28 | ], 29 | "imports": [ 30 | "src/app/shell/navbar/navbar.component.ts", 31 | "src/app/shell/sidebar/sidebar.component.ts" 32 | ] 33 | }, 34 | "src/app/shell/navbar/navbar.component.ts": { 35 | "module": ".", 36 | "tags": [ 37 | "root" 38 | ], 39 | "imports": [] 40 | }, 41 | "src/app/shell/sidebar/sidebar.component.ts": { 42 | "module": ".", 43 | "tags": [ 44 | "root" 45 | ], 46 | "imports": [] 47 | }, 48 | "src/app/app.routes.ts": { 49 | "module": ".", 50 | "tags": [ 51 | "root" 52 | ], 53 | "imports": [ 54 | "src/app/shared/util-auth/index.ts", 55 | "src/app/shell/home/home.component.ts", 56 | "src/app/domains/ticketing/feature-booking/index.ts", 57 | "src/app/domains/ticketing/feature-next-flight/index.ts", 58 | "src/app/domains/checkin/feature-manage/index.ts", 59 | "src/app/shell/about/about.component.ts" 60 | ] 61 | }, 62 | "src/app/shared/util-auth/index.ts": { 63 | "module": "src/app/shared/util-auth", 64 | "tags": [ 65 | "shared", 66 | "type:util" 67 | ], 68 | "imports": [ 69 | "src/app/shared/util-auth/auth.interceptor.ts", 70 | "src/app/shared/util-auth/auth.service.ts" 71 | ] 72 | }, 73 | "src/app/shared/util-auth/auth.interceptor.ts": { 74 | "module": "src/app/shared/util-auth", 75 | "tags": [ 76 | "shared", 77 | "type:util" 78 | ], 79 | "imports": [] 80 | }, 81 | "src/app/shared/util-auth/auth.service.ts": { 82 | "module": "src/app/shared/util-auth", 83 | "tags": [ 84 | "shared", 85 | "type:util" 86 | ], 87 | "imports": [] 88 | }, 89 | "src/app/shell/home/home.component.ts": { 90 | "module": ".", 91 | "tags": [ 92 | "root" 93 | ], 94 | "imports": [ 95 | "src/app/shared/util-logger/index.ts" 96 | ] 97 | }, 98 | "src/app/shared/util-logger/index.ts": { 99 | "module": "src/app/shared/util-logger", 100 | "tags": [ 101 | "shared", 102 | "type:util" 103 | ], 104 | "imports": [ 105 | "src/app/shared/util-logger/color-config.ts", 106 | "src/app/shared/util-logger/color.service.ts", 107 | "src/app/shared/util-logger/features.ts", 108 | "src/app/shared/util-logger/log-appender.ts", 109 | "src/app/shared/util-logger/log-formatter.ts", 110 | "src/app/shared/util-logger/log-level.ts", 111 | "src/app/shared/util-logger/logger-config.ts", 112 | "src/app/shared/util-logger/logger-module.ts", 113 | "src/app/shared/util-logger/logger.ts", 114 | "src/app/shared/util-logger/providers.ts" 115 | ] 116 | }, 117 | "src/app/shared/util-logger/color-config.ts": { 118 | "module": "src/app/shared/util-logger", 119 | "tags": [ 120 | "shared", 121 | "type:util" 122 | ], 123 | "imports": [] 124 | }, 125 | "src/app/shared/util-logger/color.service.ts": { 126 | "module": "src/app/shared/util-logger", 127 | "tags": [ 128 | "shared", 129 | "type:util" 130 | ], 131 | "imports": [ 132 | "src/app/shared/util-logger/color-config.ts", 133 | "src/app/shared/util-logger/log-level.ts" 134 | ] 135 | }, 136 | "src/app/shared/util-logger/log-level.ts": { 137 | "module": "src/app/shared/util-logger", 138 | "tags": [ 139 | "shared", 140 | "type:util" 141 | ], 142 | "imports": [] 143 | }, 144 | "src/app/shared/util-logger/features.ts": { 145 | "module": "src/app/shared/util-logger", 146 | "tags": [ 147 | "shared", 148 | "type:util" 149 | ], 150 | "imports": [ 151 | "src/app/shared/util-logger/color-config.ts", 152 | "src/app/shared/util-logger/color.service.ts" 153 | ] 154 | }, 155 | "src/app/shared/util-logger/log-appender.ts": { 156 | "module": "src/app/shared/util-logger", 157 | "tags": [ 158 | "shared", 159 | "type:util" 160 | ], 161 | "imports": [ 162 | "src/app/shared/util-logger/color.service.ts", 163 | "src/app/shared/util-logger/log-level.ts" 164 | ] 165 | }, 166 | "src/app/shared/util-logger/log-formatter.ts": { 167 | "module": "src/app/shared/util-logger", 168 | "tags": [ 169 | "shared", 170 | "type:util" 171 | ], 172 | "imports": [ 173 | "src/app/shared/util-logger/log-level.ts" 174 | ] 175 | }, 176 | "src/app/shared/util-logger/logger-config.ts": { 177 | "module": "src/app/shared/util-logger", 178 | "tags": [ 179 | "shared", 180 | "type:util" 181 | ], 182 | "imports": [ 183 | "src/app/shared/util-logger/log-appender.ts", 184 | "src/app/shared/util-logger/log-formatter.ts", 185 | "src/app/shared/util-logger/log-level.ts" 186 | ] 187 | }, 188 | "src/app/shared/util-logger/logger-module.ts": { 189 | "module": "src/app/shared/util-logger", 190 | "tags": [ 191 | "shared", 192 | "type:util" 193 | ], 194 | "imports": [ 195 | "src/app/shared/util-logger/log-appender.ts", 196 | "src/app/shared/util-logger/logger-config.ts", 197 | "src/app/shared/util-logger/providers.ts" 198 | ] 199 | }, 200 | "src/app/shared/util-logger/providers.ts": { 201 | "module": "src/app/shared/util-logger", 202 | "tags": [ 203 | "shared", 204 | "type:util" 205 | ], 206 | "imports": [ 207 | "src/app/shared/util-logger/features.ts", 208 | "src/app/shared/util-logger/log-appender.ts", 209 | "src/app/shared/util-logger/log-formatter.ts", 210 | "src/app/shared/util-logger/logger.ts", 211 | "src/app/shared/util-logger/logger-config.ts" 212 | ] 213 | }, 214 | "src/app/shared/util-logger/logger.ts": { 215 | "module": "src/app/shared/util-logger", 216 | "tags": [ 217 | "shared", 218 | "type:util" 219 | ], 220 | "imports": [ 221 | "src/app/shared/util-logger/log-appender.ts", 222 | "src/app/shared/util-logger/log-formatter.ts", 223 | "src/app/shared/util-logger/log-level.ts", 224 | "src/app/shared/util-logger/logger-config.ts" 225 | ] 226 | }, 227 | "src/app/domains/ticketing/feature-booking/index.ts": { 228 | "module": "src/app/domains/ticketing/feature-booking", 229 | "tags": [ 230 | "domain:ticketing", 231 | "type:feature" 232 | ], 233 | "imports": [ 234 | "src/app/domains/ticketing/feature-booking/flight-booking.routes.ts" 235 | ] 236 | }, 237 | "src/app/domains/ticketing/feature-booking/flight-booking.routes.ts": { 238 | "module": "src/app/domains/ticketing/feature-booking", 239 | "tags": [ 240 | "domain:ticketing", 241 | "type:feature" 242 | ], 243 | "imports": [ 244 | "src/app/shared/util-auth/index.ts", 245 | "src/app/domains/ticketing/data/index.ts", 246 | "src/app/domains/ticketing/feature-booking/flight-booking.component.ts", 247 | "src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.ts", 248 | "src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.ts", 249 | "src/app/domains/ticketing/feature-booking/passenger-search/passenger-search.component.ts" 250 | ] 251 | }, 252 | "src/app/domains/ticketing/data/index.ts": { 253 | "module": "src/app/domains/ticketing/data", 254 | "tags": [ 255 | "domain:ticketing", 256 | "type:data" 257 | ], 258 | "imports": [ 259 | "src/app/domains/ticketing/data/+state/actions.ts", 260 | "src/app/domains/ticketing/data/+state/effects.ts", 261 | "src/app/domains/ticketing/data/+state/reducers.ts", 262 | "src/app/domains/ticketing/data/+state/selectors.ts", 263 | "src/app/domains/ticketing/data/flight.service.ts", 264 | "src/app/domains/ticketing/data/flight.ts", 265 | "src/app/domains/ticketing/data/passenger.ts" 266 | ] 267 | }, 268 | "src/app/domains/ticketing/data/+state/actions.ts": { 269 | "module": "src/app/domains/ticketing/data", 270 | "tags": [ 271 | "domain:ticketing", 272 | "type:data" 273 | ], 274 | "imports": [ 275 | "src/app/domains/ticketing/data/flight.ts" 276 | ] 277 | }, 278 | "src/app/domains/ticketing/data/flight.ts": { 279 | "module": "src/app/domains/ticketing/data", 280 | "tags": [ 281 | "domain:ticketing", 282 | "type:data" 283 | ], 284 | "imports": [] 285 | }, 286 | "src/app/domains/ticketing/data/+state/effects.ts": { 287 | "module": "src/app/domains/ticketing/data", 288 | "tags": [ 289 | "domain:ticketing", 290 | "type:data" 291 | ], 292 | "imports": [ 293 | "src/app/domains/ticketing/data/flight.service.ts", 294 | "src/app/domains/ticketing/data/+state/actions.ts" 295 | ] 296 | }, 297 | "src/app/domains/ticketing/data/flight.service.ts": { 298 | "module": "src/app/domains/ticketing/data", 299 | "tags": [ 300 | "domain:ticketing", 301 | "type:data" 302 | ], 303 | "imports": [ 304 | "src/app/domains/ticketing/data/flight.ts" 305 | ] 306 | }, 307 | "src/app/domains/ticketing/data/+state/reducers.ts": { 308 | "module": "src/app/domains/ticketing/data", 309 | "tags": [ 310 | "domain:ticketing", 311 | "type:data" 312 | ], 313 | "imports": [ 314 | "src/app/domains/ticketing/data/flight.ts", 315 | "src/app/domains/ticketing/data/+state/actions.ts" 316 | ] 317 | }, 318 | "src/app/domains/ticketing/data/+state/selectors.ts": { 319 | "module": "src/app/domains/ticketing/data", 320 | "tags": [ 321 | "domain:ticketing", 322 | "type:data" 323 | ], 324 | "imports": [ 325 | "src/app/domains/ticketing/data/+state/reducers.ts" 326 | ] 327 | }, 328 | "src/app/domains/ticketing/data/passenger.ts": { 329 | "module": "src/app/domains/ticketing/data", 330 | "tags": [ 331 | "domain:ticketing", 332 | "type:data" 333 | ], 334 | "imports": [] 335 | }, 336 | "src/app/domains/ticketing/feature-booking/flight-booking.component.ts": { 337 | "module": "src/app/domains/ticketing/feature-booking", 338 | "tags": [ 339 | "domain:ticketing", 340 | "type:feature" 341 | ], 342 | "imports": [ 343 | "src/app/shared/util-logger/index.ts" 344 | ] 345 | }, 346 | "src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.ts": { 347 | "module": "src/app/domains/ticketing/feature-booking", 348 | "tags": [ 349 | "domain:ticketing", 350 | "type:feature" 351 | ], 352 | "imports": [] 353 | }, 354 | "src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.ts": { 355 | "module": "src/app/domains/ticketing/feature-booking", 356 | "tags": [ 357 | "domain:ticketing", 358 | "type:feature" 359 | ], 360 | "imports": [ 361 | "src/app/domains/ticketing/data/index.ts", 362 | "src/app/domains/ticketing/ui-common/index.ts" 363 | ] 364 | }, 365 | "src/app/domains/ticketing/ui-common/index.ts": { 366 | "module": "src/app/domains/ticketing/ui-common", 367 | "tags": [ 368 | "domain:ticketing", 369 | "type:ui" 370 | ], 371 | "imports": [ 372 | "src/app/domains/ticketing/ui-common/flight-card/flight-card.component.ts" 373 | ] 374 | }, 375 | "src/app/domains/ticketing/ui-common/flight-card/flight-card.component.ts": { 376 | "module": "src/app/domains/ticketing/ui-common", 377 | "tags": [ 378 | "domain:ticketing", 379 | "type:ui" 380 | ], 381 | "imports": [ 382 | "src/app/domains/ticketing/data/index.ts" 383 | ] 384 | }, 385 | "src/app/domains/ticketing/feature-booking/passenger-search/passenger-search.component.ts": { 386 | "module": "src/app/domains/ticketing/feature-booking", 387 | "tags": [ 388 | "domain:ticketing", 389 | "type:feature" 390 | ], 391 | "imports": [ 392 | "src/app/domains/ticketing/data/index.ts" 393 | ] 394 | }, 395 | "src/app/domains/ticketing/feature-next-flight/index.ts": { 396 | "module": "src/app/domains/ticketing/feature-next-flight", 397 | "tags": [ 398 | "domain:ticketing", 399 | "type:feature" 400 | ], 401 | "imports": [ 402 | "src/app/domains/ticketing/feature-next-flight/next-flight.component.ts" 403 | ] 404 | }, 405 | "src/app/domains/ticketing/feature-next-flight/next-flight.component.ts": { 406 | "module": "src/app/domains/ticketing/feature-next-flight", 407 | "tags": [ 408 | "domain:ticketing", 409 | "type:feature" 410 | ], 411 | "imports": [ 412 | "src/app/domains/ticketing/feature-my-tickets/index.ts" 413 | ] 414 | }, 415 | "src/app/domains/ticketing/feature-my-tickets/index.ts": { 416 | "module": "src/app/domains/ticketing/feature-my-tickets", 417 | "tags": [ 418 | "domain:ticketing", 419 | "type:feature" 420 | ], 421 | "imports": [ 422 | "src/app/domains/ticketing/feature-my-tickets/my-tickets.component.ts", 423 | "src/app/domains/ticketing/feature-my-tickets/ticket.service.ts", 424 | "src/app/domains/ticketing/feature-my-tickets/tickets.module.ts" 425 | ] 426 | }, 427 | "src/app/domains/ticketing/feature-my-tickets/my-tickets.component.ts": { 428 | "module": "src/app/domains/ticketing/feature-my-tickets", 429 | "tags": [ 430 | "domain:ticketing", 431 | "type:feature" 432 | ], 433 | "imports": [ 434 | "src/app/domains/ticketing/data/index.ts", 435 | "src/app/domains/ticketing/feature-my-tickets/ticket.service.ts" 436 | ] 437 | }, 438 | "src/app/domains/ticketing/feature-my-tickets/ticket.service.ts": { 439 | "module": "src/app/domains/ticketing/feature-my-tickets", 440 | "tags": [ 441 | "domain:ticketing", 442 | "type:feature" 443 | ], 444 | "imports": [ 445 | "src/app/domains/ticketing/data/index.ts" 446 | ] 447 | }, 448 | "src/app/domains/ticketing/feature-my-tickets/tickets.module.ts": { 449 | "module": "src/app/domains/ticketing/feature-my-tickets", 450 | "tags": [ 451 | "domain:ticketing", 452 | "type:feature" 453 | ], 454 | "imports": [ 455 | "src/app/domains/ticketing/feature-my-tickets/my-tickets.component.ts", 456 | "src/app/domains/ticketing/feature-my-tickets/ticket.service.ts", 457 | "src/app/domains/ticketing/ui-common/index.ts" 458 | ] 459 | }, 460 | "src/app/domains/checkin/feature-manage/index.ts": { 461 | "module": "src/app/domains/checkin/feature-manage", 462 | "tags": [ 463 | "domain:checkin", 464 | "type:feature" 465 | ], 466 | "imports": [ 467 | "src/app/domains/checkin/feature-manage/feature-manage.component.ts" 468 | ] 469 | }, 470 | "src/app/domains/checkin/feature-manage/feature-manage.component.ts": { 471 | "module": "src/app/domains/checkin/feature-manage", 472 | "tags": [ 473 | "domain:checkin", 474 | "type:feature" 475 | ], 476 | "imports": [ 477 | "src/app/domains/checkin/data/index.ts" 478 | ] 479 | }, 480 | "src/app/domains/checkin/data/index.ts": { 481 | "module": "src/app/domains/checkin/data", 482 | "tags": [ 483 | "domain:checkin", 484 | "type:data" 485 | ], 486 | "imports": [ 487 | "src/app/domains/checkin/data/checkin.service.ts" 488 | ] 489 | }, 490 | "src/app/domains/checkin/data/checkin.service.ts": { 491 | "module": "src/app/domains/checkin/data", 492 | "tags": [ 493 | "domain:checkin", 494 | "type:data" 495 | ], 496 | "imports": [] 497 | }, 498 | "src/app/shell/about/about.component.ts": { 499 | "module": ".", 500 | "tags": [ 501 | "root" 502 | ], 503 | "imports": [ 504 | "src/app/shell/about/lazy/lazy.component.ts" 505 | ] 506 | }, 507 | "src/app/shell/about/lazy/lazy.component.ts": { 508 | "module": ".", 509 | "tags": [ 510 | "root" 511 | ], 512 | "imports": [] 513 | }, 514 | "src/app/logger.config.ts": { 515 | "module": ".", 516 | "tags": [ 517 | "root" 518 | ], 519 | "imports": [ 520 | "src/app/shared/util-logger/index.ts" 521 | ] 522 | } 523 | } 524 | -------------------------------------------------------------------------------- /.detective/log: -------------------------------------------------------------------------------- 1 | "Manfred Steyer ,Wed Aug 28 23:56:55 2024 +0200 e524211520ff682f6be10a7d51370c976cba87bf,chore: rename logger.service to log.service" 2 | 2 2 src/app/domains/checkin/feature-manage/feature-manage.component.ts 3 | 2 2 src/app/domains/ticketing/feature-booking/flight-booking.component.ts 4 | 1 1 src/app/shared/util-logger/index.ts 5 | 2 2 src/app/shared/util-logger/{logger.service.ts => log.service.ts} 6 | 3 3 src/app/shared/util-logger/providers.ts 7 | 2 2 src/app/shell/home/home.component.ts 8 | 9 | "Manfred Steyer ,Wed Aug 28 23:55:40 2024 +0200 d9e9902f69872dffcd6bd9326bc1ba67edf08352,chore: rename logger to logger.service" 10 | 1 3 src/app/domains/checkin/feature-manage/feature-manage.component.ts 11 | 1 1 src/app/shared/util-logger/index.ts 12 | 0 0 src/app/shared/util-logger/{logger.ts => logger.service.ts} 13 | 1 1 src/app/shared/util-logger/providers.ts 14 | 15 | "Manfred Steyer ,Sun Aug 25 11:45:48 2024 +0200 ed821213214f63d48edf7e9ae7ca7ba1cfea8f25,add some connections for demo" 16 | 5 1 src/app/domains/checkin/feature-manage/feature-manage.component.ts 17 | 18 | "Manfred Steyer ,Sat Aug 24 01:37:50 2024 +0200 f9fc5d243eca50f043a4064bea7d04693233aba7,dito" 19 | 1 1 src/app/domains/checkin/feature-manage/feature-manage.component.ts 20 | 1 1 src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.ts 21 | 1 1 src/app/shared/util-common/city.pipe.ts 22 | 23 | "Manfred Steyer ,Sat Aug 24 01:36:38 2024 +0200 43e329ef73dd31e63d959e5ade48ebbaaf5701eb,dito" 24 | 1 1 src/app/domains/checkin/feature-manage/feature-manage.component.ts 25 | 1 1 src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.ts 26 | 1 1 src/app/shared/util-common/city.pipe.ts 27 | 28 | "Manfred Steyer ,Sat Aug 24 01:28:29 2024 +0200 ad3315077081d78a98a141c959d600739c0edf05,dummy commit to introduce change coupling" 29 | 523 0 deps.json 30 | 3152 16652 package-lock.json 31 | 11 10 package.json 32 | 2 0 src/app/domains/checkin/feature-manage/feature-manage.component.ts 33 | 2 1 src/app/domains/ticketing/feature-booking/flight-edit/flight-edit.component.ts 34 | 2 0 src/app/shared/util-common/city.pipe.ts 35 | 1 0 update.sh 36 | 37 | "Manfred Steyer ,Wed Aug 14 18:25:53 2024 +0200 01688aa9a9d9e74648e7b49c55429b9e4789df73,update to Angular CDK and Material 18" 38 | 27 1632 package-lock.json 39 | 2 2 package.json 40 | 41 | "Manfred Steyer ,Wed Aug 14 18:22:49 2024 +0200 c26d2be54a4f51bc2630fadf81d27a5dc1f96f32,upgrade to Angular 18" 42 | 6 6 angular.json 43 | 9679 6972 package-lock.json 44 | 16 15 package.json 45 | 1 4 src/main.ts 46 | 1 1 tsconfig.json 47 | 48 | "Manfred Steyer ,Wed Aug 14 18:20:01 2024 +0200 612397914b1c922a5ceae98033de6618cca3fbda,chore: upgrade to Angular 17" 49 | 3 3 angular.json 50 | 6009 3821 package-lock.json 51 | 16 16 package.json 52 | 1 1 src/main.ts 53 | 54 | "Manfred Steyer ,Wed Jun 28 11:46:36 2023 +0200 45e4dcf26fcf042c6d8c7661ebe92e42e08a01c1,remove router in flight search to simplify example for presentatinos" 55 | 0 14 src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.ts 56 | 57 | "Manfred Steyer ,Wed Jun 28 01:47:12 2023 +0200 71d6946aeaab8067c6583515a88cb6e25785e6b1,type record" 58 | 0 4 src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.html 59 | 1 2 src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.ts 60 | 61 | "Manfred Steyer ,Wed Jun 21 23:52:34 2023 +0200 d55cdbc51d5059264ce4f44f6b75cb8038fbf626,update to ng 16.1" 62 | 3782 4597 package-lock.json 63 | 16 16 package.json 64 | 65 | "Manfred Steyer ,Sat May 6 13:49:02 2023 +0200 3620e95c4e857483a14b1d431b98c204c85ddb46,add blink to flight-card" 66 | 3 1 src/app/domains/ticketing/ui-common/flight-card/flight-card.component.ts 67 | 68 | "Manfred Steyer ,Sat May 6 13:48:12 2023 +0200 660bf60c81d493236dfed3195e656c9d8cc9aa8d,add blink to flight-card" 69 | 13 0 src/app/domains/ticketing/ui-common/flight-card/flight-card.component.ts 70 | 71 | "Manfred Steyer ,Fri May 5 22:51:54 2023 +0200 bb5b9ea81a93be89dc6b2a59e6adf9b384941d89,ng16" 72 | 6234 3752 package-lock.json 73 | 35 35 package.json 74 | 75 | "Manfred Steyer ,Tue Apr 25 17:46:00 2023 +0100 e7bd3c0e07d5fb25a7c3f6b2c5fc5a651c216d9a,prep" 76 | 8 8 package-lock.json 77 | 1 1 package.json 78 | 4 0 src/app/domains/ticketing/feature-booking/flight-search/flight-search.component.ts 79 | 80 | "Manfred Steyer ,Mon Apr 3 16:49:10 2023 +0200 4840e564f339a8d3e1dbb48b6b6b8d7a66a6032a,use sheriff" 81 | 50 0 .eslintrc.json 82 | 14 0 angular.json 83 | 3309 363 package-lock.json 84 | 29 18 package.json 85 | 30 0 sheriff.config.ts 86 | 3 2 src/app/app.component.ts 87 | 12 7 src/app/app.routes.ts 88 | 0 46 src/app/booking/+state/effects.spec.ts 89 | 0 71 src/app/booking/flight-booking.routes.ts 90 | 0 62 src/app/booking/flight-search/flight-search.component.router.spec.ts 91 | 0 83 src/app/booking/flight-search/flight-search.component.shallow.spec.ts 92 | 0 58 src/app/booking/flight-search/flight-search.component.spec.ts 93 | 0 76 src/app/booking/flight-search/flight-search.component.store.spec.ts 94 | 0 22 src/app/booking/provider.ts 95 | 0 2 src/app/data/index.ts 96 | 12 0 src/app/domains/checkin/data/checkin.service.ts 97 | 8 0 src/app/domains/checkin/data/hidden.service.ts 98 | 1 0 src/app/domains/checkin/data/index.ts 99 | 3 0 src/app/domains/checkin/feature-manage/feature-manage.component.css 100 | 8 0 src/app/domains/checkin/feature-manage/feature-manage.component.html 101 | 22 0 src/app/domains/checkin/feature-manage/feature-manage.component.ts 102 | 3 0 src/app/domains/checkin/feature-manage/index.ts 103 | 1 1 src/app/{booking => domains/ticketing/data}/+state/actions.ts 104 | 1 1 src/app/{booking => domains/ticketing/data}/+state/effects.ts 105 | 1 1 src/app/{booking => domains/ticketing/data}/+state/reducers.ts 106 | 0 0 src/app/{booking => domains/ticketing/data}/+state/selectors.ts 107 | 1 1 src/app/{ => domains/ticketing}/data/flight.service.ts 108 | 0 0 src/app/{ => domains/ticketing}/data/flight.ts 109 | 7 0 src/app/domains/ticketing/data/index.ts 110 | 0 0 src/app/{ => domains/ticketing}/data/passenger.ts 111 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/flight-booking.component.html 112 | 3 3 src/app/{booking => domains/ticketing/feature-booking}/flight-booking.component.ts 113 | 39 0 src/app/domains/ticketing/feature-booking/flight-booking.routes.ts 114 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/flight-edit/flight-edit.component.css 115 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/flight-edit/flight-edit.component.html 116 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/flight-edit/flight-edit.component.ts 117 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/flight-search/flight-search.component.css 118 | 2 2 src/app/{booking => domains/ticketing/feature-booking}/flight-search/flight-search.component.html 119 | 17 23 src/app/{booking => domains/ticketing/feature-booking}/flight-search/flight-search.component.ts 120 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/index.ts 121 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/passenger-search/passenger-search.component.css 122 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/passenger-search/passenger-search.component.html 123 | 1 1 src/app/{booking => domains/ticketing/feature-booking}/passenger-search/passenger-search.component.ts 124 | 21 0 src/app/domains/ticketing/feature-booking/provider.ts 125 | 0 0 src/app/{booking => domains/ticketing/feature-booking}/utils/booking.interceptor.ts 126 | 3 0 src/app/domains/ticketing/feature-my-tickets/index.ts 127 | 3 3 src/app/{tickets => domains/ticketing/feature-my-tickets}/my-tickets.component.ts 128 | 3 3 src/app/{tickets => domains/ticketing/feature-my-tickets}/ticket.service.ts 129 | 1 1 src/app/{tickets => domains/ticketing/feature-my-tickets}/tickets.module.ts 130 | 1 0 src/app/domains/ticketing/feature-next-flight/index.ts 131 | 19 0 src/app/domains/ticketing/feature-next-flight/next-flight.component.ts 132 | 0 0 src/app/{booking => domains/ticketing/ui-common}/flight-card/flight-card.component.css 133 | 0 0 src/app/{booking => domains/ticketing/ui-common}/flight-card/flight-card.component.html 134 | 4 4 src/app/{booking => domains/ticketing/ui-common}/flight-card/flight-card.component.ts 135 | 1 0 src/app/domains/ticketing/ui-common/index.ts 136 | 0 23 src/app/home/home.component.spec.ts 137 | 2 4 src/app/init.service.ts 138 | 2 6 src/app/logger.config.ts 139 | 0 23 src/app/next-flight/next-flight.component.ts 140 | 0 12 src/app/shared/custom-appender.ts 141 | 0 2 src/app/shared/index.ts 142 | 0 0 src/app/shared/{ => util-auth}/auth.interceptor.ts 143 | 1 3 src/app/shared/{ => util-auth}/auth.service.ts 144 | 2 0 src/app/shared/util-auth/index.ts 145 | 0 0 src/app/shared/{ => util-common}/city.pipe.ts 146 | 0 0 src/app/shared/{ => util-common}/city.validator.ts 147 | 0 0 src/app/shared/{ => util-common}/combine-environment-providers.ts 148 | 4 0 src/app/shared/util-common/index.ts 149 | 0 0 src/app/shared/{ => util-common}/legacy.interceptor.ts 150 | 0 0 src/app/shared/{logger => util-logger}/color-config.ts 151 | 0 0 src/app/shared/{logger => util-logger}/color.service.ts 152 | 0 0 src/app/shared/{logger => util-logger}/features.ts 153 | 10 0 src/app/shared/util-logger/index.ts 154 | 0 0 src/app/shared/{logger => util-logger}/log-appender.ts 155 | 2 2 src/app/shared/{logger => util-logger}/log-formatter.ts 156 | 1 1 src/app/shared/{logger => util-logger}/log-level.ts 157 | 0 0 src/app/shared/{logger => util-logger}/logger-config.ts 158 | 0 0 src/app/shared/{logger => util-logger}/logger-module.ts 159 | 0 0 src/app/shared/{logger => util-logger}/logger.ts 160 | 0 0 src/app/shared/{logger => util-logger}/providers.ts 161 | 0 0 src/app/{+state/index.ts => shell/+state/state.ts} 162 | 2 2 src/app/{ => shell}/about/about.component.ts 163 | 0 0 src/app/{ => shell}/about/lazy/lazy.component.ts 164 | 0 0 src/app/{ => shell}/home/home.component.css 165 | 0 0 src/app/{ => shell}/home/home.component.html 166 | 1 1 src/app/{ => shell}/home/home.component.ts 167 | 0 11 src/app/shell/index.ts 168 | 3 1 src/app/shell/sidebar/sidebar.component.html 169 | 2 2 src/app/shell/sidebar/sidebar.component.ts 170 | 7 31 src/main.ts 171 | 1 12 tsconfig.json 172 | 173 | "Manfred Steyer ,Wed Feb 22 10:52:34 2023 +0100 ebb100682f29a64dd8fbbc857ec4e4c470ba5a5a,clean up" 174 | 0 2 src/app/app.component.ts 175 | 1 1 src/app/booking/flight-booking.component.ts 176 | 0 6 src/main.ts 177 | 178 | "Manfred Steyer ,Sun Feb 19 18:15:29 2023 +0100 aeec2fe28bd7e756154a69e8bb22f41febb9f509,remove unused imports" 179 | 1 5 src/main.ts 180 | 181 | "Manfred Steyer ,Sun Feb 19 15:27:23 2023 +0100 fceac843abb4a6ac1b9ebed90b106024977a13c5,update to angular 15.2" 182 | 908 517 package-lock.json 183 | 13 13 package.json 184 | 185 | "Manfred Steyer ,Sat Feb 18 21:04:31 2023 +0100 888a15d66e7876bfa443024b69a627b7bffc30dc,update to 15.1.5" 186 | 1610 1571 package-lock.json 187 | 14 14 package.json 188 | 189 | "Manfred Steyer ,Sat Feb 18 20:59:14 2023 +0100 18bfbd48c089bc92b061531057d5b9c6223b872b,just allow functional log-formatter" 190 | 1 1 package.json 191 | 2 2 src/app/logger.config.ts 192 | 0 12 src/app/shared/custom-formatter.ts 193 | 1 13 src/app/shared/logger/log-formatter.ts 194 | 3 3 src/app/shared/logger/logger-config.ts 195 | 2 11 src/app/shared/logger/logger.ts 196 | 5 10 src/app/shared/logger/providers.ts 197 | 198 | "Manfred Steyer ,Fri Feb 3 15:51:39 2023 +0100 72db20edbe7d17868169e2417966113c66bdece0,add logger" 199 | 2 1 src/app/shared/logger/log-appender.ts 200 | 2 1 src/app/shared/logger/log-formatter.ts 201 | 202 | "Manfred Steyer ,Fri Jan 13 15:09:44 2023 +0100 10936613b42c5be829f0e424c343e9d2fb5accec,refactor(logger): using an enum for LoggerFeatureKind" 203 | 7 2 src/app/shared/logger/features.ts 204 | 66 51 src/app/shared/logger/providers.ts 205 | 206 | "Manfred Steyer ,Fri Jan 13 13:42:32 2023 +0100 e521194e46d90f4b0dc99d63817abebd084fef7e,done" 207 | 1 1 src/app/booking/flight-booking.routes.ts 208 | 2 2 src/app/shared/logger/logger-config.ts 209 | 1 1 src/app/shared/logger/logger.ts 210 | 211 | "Manfred Steyer ,Tue Jan 10 17:49:48 2023 +0100 57d420f47248b2a43e8d9e0c2b5ff7e5beee5bf0,done" 212 | 10 0 src/app/shared/logger/log-formatter.ts 213 | 2 2 src/app/shared/logger/logger-config.ts 214 | 1 1 src/app/shared/logger/logger-module.ts 215 | 12 3 src/app/shared/logger/logger.ts 216 | 6 3 src/app/shared/logger/providers.ts 217 | 28 27 src/main.ts 218 | 219 | "Manfred Steyer ,Tue Jan 10 17:35:04 2023 +0100 29c40de9243972f9ab243e5edde828f626b5bd4f,bubble up to parent logger" 220 | 32 25 src/app/shared/logger/logger.ts 221 | 222 | "Manfred Steyer ,Tue Jan 10 17:24:11 2023 +0100 ca89ab28f7332d3cb98787758e9bab7adf37f0fe,demo" 223 | 8 1 src/app/booking/flight-booking.component.ts 224 | 61 37 src/app/booking/flight-booking.routes.ts 225 | 1 1 src/app/shared/logger/log-appender.ts 226 | 2 0 src/app/shared/logger/logger-config.ts 227 | 12 2 src/app/shared/logger/logger-module.ts 228 | 11 2 src/app/shared/logger/logger.ts 229 | 23 2 src/app/shared/logger/providers.ts 230 | 4 1 src/main.ts 231 | 232 | "Manfred Steyer ,Tue Jan 10 16:38:23 2023 +0100 b568ee164d47f19637bd9b5cce38a5241c3cfbf4,demo for logger" 233 | 9 1 src/app/home/home.component.ts 234 | 11 0 src/app/logger.config.ts 235 | 12 0 src/app/shared/custom-appender.ts 236 | 12 0 src/app/shared/custom-formatter.ts 237 | 13 0 src/app/shared/logger/color-config.ts 238 | 21 0 src/app/shared/logger/color.service.ts 239 | 29 0 src/app/shared/logger/features.ts 240 | 20 0 src/app/shared/logger/log-appender.ts 241 | 12 0 src/app/shared/logger/log-formatter.ts 242 | 6 0 src/app/shared/logger/log-level.ts 243 | 16 0 src/app/shared/logger/logger-config.ts 244 | 23 0 src/app/shared/logger/logger-module.ts 245 | 36 0 src/app/shared/logger/logger.ts 246 | 34 0 src/app/shared/logger/providers.ts 247 | 11 0 src/main.ts 248 | 249 | "Manfred Steyer ,Sun Jan 8 20:02:10 2023 +0100 76c0f544be9ce369cf8be624e2b07fed9c8e4136,migrate to 15.1 rc.0 and add self-closing tags" 250 | 1688 1539 package-lock.json 251 | 12 12 package.json 252 | 5 2 src/app/booking/flight-search/flight-search.component.html 253 | 254 | "Manfred Steyer ,Sun Jan 8 19:51:49 2023 +0100 9f1a64ea51cf1054f2a54fb05a36dbf702dd8ebb,add auth service" 255 | 10 1 .vscode/settings.json 256 | 3 0 src/app/app.routes.ts 257 | 3 0 src/app/booking/flight-booking.routes.ts 258 | 1 1 src/app/shared/auth.service.ts 259 | 260 | "Manfred Steyer ,Sat Nov 26 21:04:59 2022 +0100 da9a057889e386875b82260d149e009a6e4c7283,Merge branch 'testing'" 261 | "Manfred Steyer ,Sat Nov 26 21:04:44 2022 +0100 21b43ed4387b5f71f190f40a56e88ac633e7247b,update for testing article" 262 | 5 1 src/app/booking/+state/effects.spec.ts 263 | 2 2 src/app/booking/flight-search/flight-search.component.router.spec.ts 264 | 4 12 src/app/booking/flight-search/flight-search.component.shallow.spec.ts 265 | 31 3 src/app/booking/flight-search/flight-search.component.store.spec.ts 266 | 11 0 src/app/shared/auth.service.ts 267 | 268 | "Manfred Steyer ,Mon Nov 21 21:55:22 2022 +0100 3215471652e213b866de2a6294a51021f03b9c77,small changes for presentation on Nov 21, 22" 269 | 2 1 src/app/app.component.ts 270 | 3 3 src/app/app.routes.ts 271 | 1 1 src/app/booking/flight-booking.routes.ts 272 | 273 | "Manfred Steyer ,Sun Nov 20 20:11:50 2022 +0100 b912d46078e9de825878a81def5e58e6e9a91098,prepare interceptor demo" 274 | 2 0 src/app/about/about.component.ts 275 | 1 0 src/app/app.component.html 276 | 4 2 src/app/app.routes.ts 277 | 1 0 src/app/booking/flight-booking.routes.ts 278 | 19 3 src/app/booking/passenger-search/passenger-search.component.html 279 | 21 1 src/app/booking/passenger-search/passenger-search.component.ts 280 | 2 2 src/app/booking/utils/booking.interceptor.ts 281 | 7 0 src/app/data/passenger.ts 282 | 3 1 src/app/next-flight/next-flight.component.ts 283 | 2 2 src/app/shared/auth.interceptor.ts 284 | 3 2 src/app/shared/legacy.interceptor.ts 285 | 1 1 src/main.ts 286 | 3 0 src/styles.css 287 | 288 | "Manfred Steyer ,Sat Nov 19 23:34:51 2022 +0100 579e98b8c98965d8fdbd68a30e3ca711048791c2,test: just exchange flight-card for shallow testing" 289 | 9 8 src/app/booking/flight-search/flight-search.component.shallow.spec.ts 290 | 291 | "Manfred Steyer ,Sat Nov 19 23:31:04 2022 +0100 5c4d996b333a4cb409f5efe383d79876dd29ee69,add some tests" 292 | 42 0 src/app/booking/+state/effects.spec.ts 293 | 1 0 src/app/booking/flight-booking.routes.ts 294 | 62 0 src/app/booking/flight-search/flight-search.component.router.spec.ts 295 | 90 0 src/app/booking/flight-search/flight-search.component.shallow.spec.ts 296 | 13 4 src/app/booking/flight-search/flight-search.component.spec.ts 297 | 48 0 src/app/booking/flight-search/flight-search.component.store.spec.ts 298 | 16 3 src/app/booking/flight-search/flight-search.component.ts 299 | 22 0 src/app/booking/provider.ts 300 | 6 0 src/app/shared/combine-environment-providers.ts 301 | 302 | "Manfred Steyer ,Sat Nov 19 14:53:51 2022 +0100 512d9cdbe7a6577212e33cd55ea0836514f638e3,test: add test for flight-search" 303 | 49 0 src/app/booking/flight-search/flight-search.component.spec.ts 304 | 1 1 src/app/data/flight.service.ts 305 | 5 7 src/app/home/home.component.spec.ts 306 | 307 | "Manfred Steyer ,Sat Nov 19 13:53:21 2022 +0100 a637d924f66929707225f3d8ce23c8d4f9afb971,ng 15 setup" 308 | 2 2 README.md 309 | 13 20 angular.json 310 | 0 44 karma.conf.js 311 | 3102 3581 package-lock.json 312 | 24 24 package.json 313 | 8 11 src/app/booking/+state/effects.ts 314 | 0 3 src/environments/environment.prod.ts 315 | 0 16 src/environments/environment.ts 316 | 1 1 src/index.html 317 | 4 9 src/main.ts 318 | 0 53 src/polyfills.ts 319 | 1 14 src/styles.css 320 | 0 14 src/test.ts 321 | 1 2 tsconfig.app.json 322 | 4 5 tsconfig.json 323 | 0 4 tsconfig.spec.json 324 | 325 | "Manfred Steyer ,Sat Nov 19 13:25:54 2022 +0100 a935184b0aba51b82bf67c1a2378561569573943,some adjustments" 326 | 1 0 src/app/app.component.ts 327 | 2 0 src/app/booking/flight-booking.routes.ts 328 | 9 0 src/app/shell/index.ts 329 | 330 | "Manfred Steyer ,Wed Nov 2 11:34:35 2022 +0100 e2e77cdd7bde6e909249592b7290e829a58d2dd1,resolve" 331 | "Manfred Steyer ,Wed Nov 2 11:28:53 2022 +0100 1321b420d9d5cd4b1eefa2a827e41279aa6680f4,add standalone api for http client" 332 | 8 1 src/app/booking/flight-booking.routes.ts 333 | 17 0 src/app/booking/utils/booking.interceptor.ts 334 | 17 0 src/app/shared/auth.interceptor.ts 335 | 20 0 src/app/shared/legacy.interceptor.ts 336 | 14 4 src/main.ts 337 | 338 | "Manfred Steyer ,Wed Nov 2 11:20:01 2022 +0100 3018e2283e19fe063df04a461066d829949665ff,migrate to angular 15" 339 | 1607 31 package-lock.json 340 | 4 4 package.json 341 | 2 2 src/app/shell/sidebar/sidebar.component.ts 342 | 1 0 tsconfig.json 343 | 344 | "Manfred Steyer ,Wed Nov 2 11:13:10 2022 +0100 4097abaf676f038e3c7fee6cf92184c7b33f1b72,update to angular 15" 345 | 0 16 .browserslistrc 346 | 2270 3207 package-lock.json 347 | 12 12 package.json 348 | 2 2 src/app/booking/flight-booking.component.ts 349 | 0 12 src/test.ts 350 | 15 6 tsconfig.json 351 | 352 | "Manfred Steyer ,Wed Nov 2 10:39:05 2022 +0100 b6dc3616dccb77150c40c88ebb3be26995fdb13d,small change" 353 | 2 14 src/app/app.component.ts 354 | 7 2 src/app/booking/flight-search/flight-search.component.ts 355 | 0 2 src/app/shell/index.ts 356 | 6 4 src/main.ts 357 | 358 | "Manfred Steyer ,Thu Sep 1 15:35:51 2022 -0600 c613f4234a505163064c9fd0d60e366390fd1f7e,small correction" 359 | 4 3 src/app/app.component.ts 360 | 3 2 src/app/app.routes.ts 361 | 1 1 src/app/booking/flight-booking.component.ts 362 | 1 1 src/app/booking/index.ts 363 | 6 1 src/app/shell/index.ts 364 | 6 3 src/main.ts 365 | 366 | "Manfred Steyer ,Thu Sep 1 15:35:51 2022 -0600 6402f47f08e60132cb5e685cd5506488405790ad,small correction" 367 | 3 3 src/app/app.component.ts 368 | 1 1 src/app/app.routes.ts 369 | 1 1 src/app/booking/index.ts 370 | 1 6 src/app/shell/index.ts 371 | 1 1 src/main.ts 372 | 373 | "Manfred Steyer ,Sun Aug 28 01:13:53 2022 +0200 d1b61832200ee84617c34ff3a0c57cda461eeb59,init" 374 | 16 0 .browserslistrc 375 | 16 0 .editorconfig 376 | 42 0 .gitignore 377 | 4 0 .vscode/extensions.json 378 | 20 0 .vscode/launch.json 379 | 23 0 .vscode/settings.json 380 | 42 0 .vscode/tasks.json 381 | 27 0 README.md 382 | 108 0 angular.json 383 | 44 0 karma.conf.js 384 | 20610 0 package-lock.json 385 | 44 0 package.json 386 | 13 0 src/app/+state/index.ts 387 | 22 0 src/app/about/about.component.ts 388 | 13 0 src/app/about/lazy/lazy.component.ts 389 | 21 0 src/app/app.component.css 390 | 8 0 src/app/app.component.html 391 | 43 0 src/app/app.component.ts 392 | 29 0 src/app/app.routes.ts 393 | 17 0 src/app/booking/+state/actions.ts 394 | 23 0 src/app/booking/+state/effects.ts 395 | 35 0 src/app/booking/+state/reducers.ts 396 | 9 0 src/app/booking/+state/selectors.ts 397 | 18 0 src/app/booking/flight-booking.component.html 398 | 14 0 src/app/booking/flight-booking.component.ts 399 | 33 0 src/app/booking/flight-booking.routes.ts 400 | 0 0 src/app/booking/flight-card/flight-card.component.css 401 | 17 0 src/app/booking/flight-card/flight-card.component.html 402 | 29 0 src/app/booking/flight-card/flight-card.component.ts 403 | 0 0 src/app/booking/flight-edit/flight-edit.component.css 404 | 4 0 src/app/booking/flight-edit/flight-edit.component.html 405 | 26 0 src/app/booking/flight-edit/flight-edit.component.ts 406 | 0 0 src/app/booking/flight-search/flight-search.component.css 407 | 49 0 src/app/booking/flight-search/flight-search.component.html 408 | 61 0 src/app/booking/flight-search/flight-search.component.ts 409 | 1 0 src/app/booking/index.ts 410 | 0 0 src/app/booking/passenger-search/passenger-search.component.css 411 | 3 0 src/app/booking/passenger-search/passenger-search.component.html 412 | 9 0 src/app/booking/passenger-search/passenger-search.component.ts 413 | 72 0 src/app/data/flight.service.ts 414 | 16 0 src/app/data/flight.ts 415 | 2 0 src/app/data/index.ts 416 | 0 0 src/app/home/home.component.css 417 | 1 0 src/app/home/home.component.html 418 | 25 0 src/app/home/home.component.spec.ts 419 | 9 0 src/app/home/home.component.ts 420 | 11 0 src/app/init.service.ts 421 | 21 0 src/app/next-flight/next-flight.component.ts 422 | 32 0 src/app/shared/city.pipe.ts 423 | 32 0 src/app/shared/city.validator.ts 424 | 2 0 src/app/shared/index.ts 425 | 7 0 src/app/shell/index.ts 426 | 10 0 src/app/shell/navbar/navbar.component.html 427 | 28 0 src/app/shell/navbar/navbar.component.ts 428 | 21 0 src/app/shell/sidebar/sidebar.component.css 429 | 22 0 src/app/shell/sidebar/sidebar.component.html 430 | 37 0 src/app/shell/sidebar/sidebar.component.ts 431 | 28 0 src/app/tickets/my-tickets.component.ts 432 | 22 0 src/app/tickets/ticket.service.ts 433 | 31 0 src/app/tickets/tickets.module.ts 434 | 0 0 src/assets/.gitkeep 435 | 3 0 src/environments/environment.prod.ts 436 | 16 0 src/environments/environment.ts 437 | - - src/favicon.ico 438 | 13 0 src/index.html 439 | 56 0 src/main.ts 440 | 53 0 src/polyfills.ts 441 | 14 0 src/styles.css 442 | 26 0 src/test.ts 443 | 15 0 tsconfig.app.json 444 | 38 0 tsconfig.json 445 | 18 0 tsconfig.spec.json 446 | --------------------------------------------------------------------------------