├── src ├── assets │ └── .gitkeep ├── pages │ ├── ngrx │ │ ├── ngrx │ │ │ ├── ngrx.component.scss │ │ │ ├── ngrx.component.ts │ │ │ ├── ngrx.component.html │ │ │ └── ngrx.component.spec.ts │ │ └── ngrx.module.ts │ └── standard │ │ ├── standard │ │ ├── standard.component.scss │ │ ├── standard.component.ts │ │ ├── standard.component.html │ │ └── standard.component.spec.ts │ │ └── standard.module.ts ├── app │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.ts │ ├── app.routing.ts │ ├── app.component.spec.ts │ └── app.module.ts ├── favicon.ico ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── styles.scss ├── main.ts ├── index.html ├── test.ts └── polyfills.ts ├── projects ├── events │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── category-selected.event.ts │ │ │ ├── currency-changed.event.ts │ │ │ └── product-added.event.ts │ │ └── test.ts │ ├── ng-package.json │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── categories │ ├── ng-package.json │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── categories.service.spec.ts │ │ │ ├── categories.module.ts │ │ │ ├── categories.component.spec.ts │ │ │ ├── categories.component.ts │ │ │ └── categories.service.ts │ │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── ngrx-notifications │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── event-handlers │ │ │ │ ├── category-selected.event-handler.ts │ │ │ │ └── product-added.event-handler.ts │ │ │ ├── ngrx-notifications.component.spec.ts │ │ │ ├── ngrx-notifications.component.ts │ │ │ ├── store │ │ │ │ ├── index.ts │ │ │ │ └── notifications.selector.ts │ │ │ └── ngrx-notifications.module.ts │ │ └── test.ts │ ├── ng-package.json │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── products │ ├── ng-package.json │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── products.service.spec.ts │ │ │ ├── event-handlers │ │ │ │ ├── currency-changed.event-handler.ts │ │ │ │ └── category-selected.event-handler.ts │ │ │ ├── products.component.spec.ts │ │ │ ├── products.module.ts │ │ │ ├── products.service.ts │ │ │ └── products.component.ts │ │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── settings │ ├── ng-package.json │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── settings.service.spec.ts │ │ │ ├── settings.module.ts │ │ │ ├── settings.component.spec.ts │ │ │ ├── settings.service.ts │ │ │ └── settings.component.ts │ │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── ngrx-categories │ ├── ng-package.json │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── store │ │ │ │ ├── categories.selector.ts │ │ │ │ ├── select-category.reducer.ts │ │ │ │ └── index.ts │ │ │ ├── ngrx-categories.module.ts │ │ │ ├── ngrx-categories.component.spec.ts │ │ │ └── ngrx-categories.component.ts │ │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── ngrx-products │ ├── ng-package.json │ ├── src │ │ ├── lib │ │ │ ├── store │ │ │ │ ├── select-category.action.ts │ │ │ │ ├── products.effects.ts │ │ │ │ ├── products.eda.effects.ts │ │ │ │ ├── products.selector.ts │ │ │ │ └── index.ts │ │ │ ├── ngrx-products.eda.module.ts │ │ │ ├── ngrx-products.component.spec.ts │ │ │ ├── ngrx-products.module.ts │ │ │ └── ngrx-products.component.ts │ │ ├── public-api.ts │ │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── notifications │ ├── ng-package.json │ ├── src │ │ ├── public-api.ts │ │ ├── lib │ │ │ ├── notifications.service.spec.ts │ │ │ ├── notifications.service.ts │ │ │ ├── notifications.component.ts │ │ │ ├── event-handlers │ │ │ │ ├── category-selected.event-handler.ts │ │ │ │ ├── product-added.event-handler.ts │ │ │ │ └── currency-changed.event-handler.ts │ │ │ ├── notifications.component.spec.ts │ │ │ └── notifications.module.ts │ │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js └── shared │ └── add-product-form │ ├── ng-package.json │ ├── src │ ├── public-api.ts │ ├── lib │ │ ├── add-product-form.module.ts │ │ ├── add-product-form.component.spec.ts │ │ └── add-product-form.component.ts │ └── test.ts │ ├── package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── README.md │ └── karma.conf.js ├── .editorconfig ├── tsconfig.app.json ├── tsconfig.spec.json ├── .browserslistrc ├── .gitignore ├── nx.json ├── package.json ├── karma.conf.js ├── tsconfig.json ├── README.md └── angular.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/ngrx/ngrx/ngrx.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/standard/standard/standard.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .spacer { 2 | flex: 1 1 auto; 3 | } 4 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cobiro/eda/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /projects/events/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of events 3 | */ 4 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /projects/events/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/events", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /projects/categories/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/categories", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngrx-notifications 3 | */ 4 | export * from './lib/ngrx-notifications.component'; 5 | export * from './lib/ngrx-notifications.module'; 6 | -------------------------------------------------------------------------------- /projects/products/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/products", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/settings/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/settings", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/ngrx-categories/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngrx-categories", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/ngrx-products/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngrx-products", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/notifications/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/notifications", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/products/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of products 3 | */ 4 | 5 | export * from './lib/products.service'; 6 | export * from './lib/products.component'; 7 | export * from './lib/products.module'; 8 | -------------------------------------------------------------------------------- /projects/settings/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of settings 3 | */ 4 | 5 | export * from './lib/settings.service'; 6 | export * from './lib/settings.component'; 7 | export * from './lib/settings.module'; 8 | -------------------------------------------------------------------------------- /projects/categories/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of categories 3 | */ 4 | 5 | export * from './lib/categories.service'; 6 | export * from './lib/categories.component'; 7 | export * from './lib/categories.module'; 8 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngrx-notifications", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/store/select-category.action.ts: -------------------------------------------------------------------------------- 1 | import {createAction, props} from "@ngrx/store"; 2 | 3 | export const selectCategory = createAction( 4 | '[Categories] Select', 5 | props<{ categoryName: string }>() 6 | ); 7 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngrx-products 3 | */ 4 | 5 | export * from './lib/ngrx-products.service'; 6 | export * from './lib/ngrx-products.component'; 7 | export * from './lib/ngrx-products.module'; 8 | -------------------------------------------------------------------------------- /projects/notifications/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of notifications 3 | */ 4 | 5 | export * from './lib/notifications.service'; 6 | export * from './lib/notifications.component'; 7 | export * from './lib/notifications.module'; 8 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../../dist/shared/add-product-form", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /projects/events/src/lib/category-selected.event.ts: -------------------------------------------------------------------------------- 1 | import {ApplicationEvent} from "@cobiro/eda"; 2 | 3 | export class CategorySelectedEvent extends ApplicationEvent { 4 | constructor(public readonly categoryName: string) { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/events/src/lib/currency-changed.event.ts: -------------------------------------------------------------------------------- 1 | import {ApplicationEvent} from "@cobiro/eda"; 2 | 3 | export class CurrencyChangedEvent extends ApplicationEvent { 4 | constructor(public readonly currencySymbol: string) { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngrx-categories 3 | */ 4 | 5 | export * from './lib/ngrx-categories.service'; 6 | export * from './lib/ngrx-categories.component'; 7 | export * from './lib/ngrx-categories.module'; 8 | -------------------------------------------------------------------------------- /projects/events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "events", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/products/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "products", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/settings/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "settings", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/categories/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "categories", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/shared/add-product-form/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of add-product-form 3 | */ 4 | 5 | export * from './lib/add-product-form.service'; 6 | export * from './lib/add-product-form.component'; 7 | export * from './lib/add-product-form.module'; 8 | -------------------------------------------------------------------------------- /projects/ngrx-products/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngrx-products", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/notifications/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notifications", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/ngrx-categories/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngrx-categories", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'] 7 | }) 8 | export class AppComponent { 9 | title = 'eda'; 10 | } 11 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngrx-notifications", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/shared/add-product-form/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@shared/add-product-form", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /projects/events/src/lib/product-added.event.ts: -------------------------------------------------------------------------------- 1 | import {ApplicationEvent} from "@cobiro/eda"; 2 | 3 | export class ProductAddedEvent extends ApplicationEvent { 4 | constructor(public readonly name: string, public readonly price: number, public readonly currency: string) { 5 | super(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/lib/store/categories.selector.ts: -------------------------------------------------------------------------------- 1 | import {CategoriesState} from "./select-category.reducer"; 2 | 3 | export const selectCategories = (state: object) => (state as any).categories; 4 | 5 | // export const selectSelectedCategory = (state: CategoriesState) => state.selectedCategory; 6 | -------------------------------------------------------------------------------- /projects/categories/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/events/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/products/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/settings/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/ngrx-categories/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/ngrx-products/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/notifications/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.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/pages/ngrx/ngrx/ngrx.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-ngrx', 5 | templateUrl: './ngrx.component.html', 6 | styleUrls: ['./ngrx.component.scss'] 7 | }) 8 | export class NgrxComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /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 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/pages/standard/standard/standard.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-standard', 5 | templateUrl: './standard.component.html', 6 | styleUrls: ['./standard.component.scss'] 7 | }) 8 | export class StandardComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit(): void { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /projects/categories/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/events/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/products/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/settings/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngrx-categories/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngrx-products/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/notifications/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /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 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/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 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /projects/products/src/lib/products.service.spec.ts: -------------------------------------------------------------------------------- 1 | import {TestBed} from '@angular/core/testing'; 2 | 3 | import {ProductsService} from './products.service'; 4 | 5 | describe('ProductsService', () => { 6 | let service: ProductsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(ProductsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /projects/settings/src/lib/settings.service.spec.ts: -------------------------------------------------------------------------------- 1 | import {TestBed} from '@angular/core/testing'; 2 | 3 | import {SettingsService} from './settings.service'; 4 | 5 | describe('SettingsService', () => { 6 | let service: SettingsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(SettingsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /projects/categories/src/lib/categories.service.spec.ts: -------------------------------------------------------------------------------- 1 | import {TestBed} from '@angular/core/testing'; 2 | 3 | import {CategoriesService} from './categories.service'; 4 | 5 | describe('CategoriesService', () => { 6 | let service: CategoriesService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(CategoriesService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/notifications.service.spec.ts: -------------------------------------------------------------------------------- 1 | import {TestBed} from '@angular/core/testing'; 2 | 3 | import {NotificationsService} from './notifications.service'; 4 | 5 | describe('NotificationsService', () => { 6 | let service: NotificationsService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(NotificationsService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /projects/categories/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/events/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/products/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/settings/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/ngrx-categories/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/ngrx-products/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/notifications/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/settings/src/lib/settings.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {SettingsComponent} from './settings.component'; 3 | import {MatButtonToggleModule} from "@angular/material/button-toggle"; 4 | import {CommonModule} from "@angular/common"; 5 | 6 | 7 | @NgModule({ 8 | declarations: [ 9 | SettingsComponent 10 | ], 11 | imports: [ 12 | CommonModule, 13 | MatButtonToggleModule 14 | ], 15 | exports: [ 16 | SettingsComponent 17 | ] 18 | }) 19 | export class SettingsModule { } 20 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/tsconfig.lib.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/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/pages/ngrx/ngrx/ngrx.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/pages/standard/standard/standard.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/app/app.routing.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from "@angular/core"; 2 | import {RouterModule} from "@angular/router"; 3 | import {StandardComponent} from "../pages/standard/standard/standard.component"; 4 | import {NgrxComponent} from "../pages/ngrx/ngrx/ngrx.component"; 5 | 6 | const APP_ROUTES = [ 7 | { 8 | path: '', 9 | component: StandardComponent, 10 | }, 11 | { 12 | path: 'ngrx', 13 | component: NgrxComponent 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forRoot(APP_ROUTES)], 19 | exports: [RouterModule], 20 | }) 21 | export class AppRoutingModule {} 22 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/notifications.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {BehaviorSubject, Observable} from "rxjs"; 3 | 4 | export interface Notification { 5 | text: string; 6 | } 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class NotificationsService { 12 | private subject = new BehaviorSubject([]); 13 | 14 | public notify(text: string): void { 15 | this.subject.next([...this.subject.getValue(), { text }]); 16 | } 17 | 18 | get data$(): Observable { 19 | return this.subject.asObservable(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Eda 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/notifications.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {NotificationsService} from "./notifications.service"; 3 | 4 | @Component({ 5 | selector: 'lib-notifications', 6 | template: ` 7 | 8 | {{notification.text}} 9 | 10 | `, 11 | }) 12 | export class NotificationsComponent { 13 | 14 | notifications$ = this.notificationService.data$; 15 | 16 | constructor(private notificationService: NotificationsService) { } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /projects/products/src/lib/event-handlers/currency-changed.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {CurrencyChangedEvent} from "../../../../events/src/lib/currency-changed.event"; 3 | import {ProductsService} from "../products.service"; 4 | import {ApplicationEventHandler} from "@cobiro/eda"; 5 | 6 | @Injectable() 7 | export class CurrencyChangedEventHandler implements ApplicationEventHandler { 8 | eventClass = CurrencyChangedEvent; 9 | 10 | constructor(private productsService: ProductsService) {} 11 | 12 | handle(event: CurrencyChangedEvent) { 13 | this.productsService.setCurrency(event.currencySymbol); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/products/src/lib/event-handlers/category-selected.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {CategorySelectedEvent} from "../../../../events/src/lib/category-selected.event"; 3 | import {ProductsService} from "../products.service"; 4 | import {ApplicationEventHandler} from "@cobiro/eda"; 5 | 6 | @Injectable() 7 | export class CategorySelectedEventHandler implements ApplicationEventHandler { 8 | eventClass = CategorySelectedEvent; 9 | 10 | constructor(private productsService: ProductsService) {} 11 | 12 | handle(event: CategorySelectedEvent) { 13 | this.productsService.setCategoryId(event.categoryName) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/src/lib/add-product-form.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { AddProductFormComponent } from './add-product-form.component'; 3 | import {MatInputModule} from "@angular/material/input"; 4 | import {ReactiveFormsModule} from "@angular/forms"; 5 | import {MatButtonModule} from "@angular/material/button"; 6 | 7 | 8 | 9 | @NgModule({ 10 | declarations: [ 11 | AddProductFormComponent 12 | ], 13 | imports: [ 14 | MatInputModule, 15 | ReactiveFormsModule, 16 | MatButtonModule 17 | ], 18 | exports: [ 19 | AddProductFormComponent 20 | ] 21 | }) 22 | export class AddProductFormModule { } 23 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/event-handlers/category-selected.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {CategorySelectedEvent} from "../../../../events/src/lib/category-selected.event"; 3 | import {NotificationsService} from "../notifications.service"; 4 | import {ApplicationEventHandler} from "@cobiro/eda"; 5 | 6 | @Injectable() 7 | export class CategorySelectedEventHandler implements ApplicationEventHandler { 8 | eventClass = CategorySelectedEvent; 9 | 10 | constructor(private notifyService: NotificationsService) {} 11 | 12 | handle(event: CategorySelectedEvent) { 13 | this.notifyService.notify(`Selected ${event.categoryName}`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/event-handlers/product-added.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {NotificationsService} from "../notifications.service"; 3 | import {ProductAddedEvent} from "../../../../events/src/lib/product-added.event"; 4 | import {ApplicationEventHandler} from "@cobiro/eda"; 5 | 6 | @Injectable() 7 | export class ProductAddedEventHandler implements ApplicationEventHandler { 8 | eventClass = ProductAddedEvent; 9 | 10 | constructor(private notifyService: NotificationsService) {} 11 | 12 | handle(event: ProductAddedEvent) { 13 | this.notifyService.notify(`Added ${event.name} ${event.currency}${event.price}`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/store/products.effects.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {Actions, createEffect, ofType} from '@ngrx/effects'; 3 | import {map} from 'rxjs/operators'; 4 | import {notify} from "../../../../ngrx-notifications/src/lib/store/notifications.selector"; 5 | 6 | @Injectable() 7 | export class ProductsEffects { 8 | 9 | notification$ = createEffect(() => this.actions$.pipe( 10 | ofType('[Categories] Select'), 11 | map(({categoryName}) => { 12 | return notify({notification: {text: `Category ${categoryName} selected`}}) 13 | }) 14 | ) 15 | ); 16 | 17 | constructor( 18 | private actions$: Actions, 19 | ) {} 20 | } 21 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/event-handlers/currency-changed.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {NotificationsService} from "../notifications.service"; 3 | import {CurrencyChangedEvent} from "../../../../events/src/lib/currency-changed.event"; 4 | import {ApplicationEventHandler} from "@cobiro/eda"; 5 | 6 | @Injectable() 7 | export class CurrencyChangedEventHandler implements ApplicationEventHandler { 8 | eventClass = CurrencyChangedEvent; 9 | 10 | constructor(private notifyService: NotificationsService) {} 11 | 12 | handle(event: CurrencyChangedEvent) { 13 | this.notifyService.notify(`Currency changed to ${event.currencySymbol}`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/event-handlers/category-selected.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {CategorySelectedEvent} from "../../../../events/src/lib/category-selected.event"; 3 | import {Store} from "@ngrx/store"; 4 | import {notify} from "../store/notifications.selector"; 5 | import {ApplicationEventHandler} from "@cobiro/eda"; 6 | 7 | @Injectable() 8 | export class CategorySelectedEventHandler implements ApplicationEventHandler { 9 | eventClass = CategorySelectedEvent; 10 | 11 | constructor(private store: Store) {} 12 | 13 | handle(event: CategorySelectedEvent) { 14 | this.store.dispatch(notify({notification: {text: `Selected ${event.categoryName}`}})); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/event-handlers/product-added.event-handler.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {ProductAddedEvent} from "../../../../events/src/lib/product-added.event"; 3 | import {notify} from "../store/notifications.selector"; 4 | import {Store} from "@ngrx/store"; 5 | import {ApplicationEventHandler} from "@cobiro/eda"; 6 | 7 | @Injectable() 8 | export class ProductAddedEventHandler implements ApplicationEventHandler { 9 | eventClass = ProductAddedEvent; 10 | 11 | constructor(private store: Store) {} 12 | 13 | handle(event: ProductAddedEvent) { 14 | this.store.dispatch(notify({notification: {text: `Added ${event.name} ${event.currency}${event.price}`}})); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /projects/categories/src/lib/categories.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {CategoriesComponent} from './categories.component'; 3 | import {CommonModule} from "@angular/common"; 4 | import {BrowserModule} from "@angular/platform-browser"; 5 | import {MatListModule} from "@angular/material/list"; 6 | import {ReactiveFormsModule} from "@angular/forms"; 7 | import {MatBadgeModule} from "@angular/material/badge"; 8 | 9 | @NgModule({ 10 | declarations: [ 11 | CategoriesComponent 12 | ], 13 | imports: [ 14 | CommonModule, BrowserModule, MatListModule, ReactiveFormsModule, MatBadgeModule 15 | ], 16 | exports: [ 17 | CategoriesComponent 18 | ] 19 | }) 20 | export class CategoriesModule { } 21 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /src/pages/ngrx/ngrx/ngrx.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NgrxComponent } from './ngrx.component'; 4 | 5 | describe('NgrxComponent', () => { 6 | let component: NgrxComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NgrxComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NgrxComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/ngrx-products.eda.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { NgrxProductsComponent } from './ngrx-products.component'; 3 | import {CommonModule} from "@angular/common"; 4 | import {MatListModule} from "@angular/material/list"; 5 | import {MatButtonModule} from "@angular/material/button"; 6 | import {StoreModule} from "@ngrx/store"; 7 | import * as fromProducts from "./store/products.selector"; 8 | import {EffectsModule} from "@ngrx/effects"; 9 | import {ProductsEffects} from "./store/products.effects"; 10 | import {ProductsEDAEffects} from "./store/products.eda.effects"; 11 | 12 | @NgModule({ 13 | imports: [ 14 | EffectsModule.forFeature([ProductsEDAEffects]) 15 | ], 16 | }) 17 | export class NgrxProductsEDAModule { } 18 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /projects/products/src/lib/products.component.spec.ts: -------------------------------------------------------------------------------- 1 | import {ComponentFixture, TestBed} from '@angular/core/testing'; 2 | 3 | import {ProductsComponent} from './products.component'; 4 | 5 | describe('ProductsComponent', () => { 6 | let component: ProductsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ProductsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ProductsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/settings/src/lib/settings.component.spec.ts: -------------------------------------------------------------------------------- 1 | import {ComponentFixture, TestBed} from '@angular/core/testing'; 2 | 3 | import {SettingsComponent} from './settings.component'; 4 | 5 | describe('SettingsComponent', () => { 6 | let component: SettingsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ SettingsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(SettingsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/lib/store/select-category.reducer.ts: -------------------------------------------------------------------------------- 1 | // TODO: Move to core module 2 | import {Category} from "../../../../categories/src/lib/categories.service"; 3 | import {Action, createReducer, on} from "@ngrx/store"; 4 | 5 | export interface CategoriesState { 6 | categories: Category[], 7 | } 8 | 9 | export const categoryInitialState: CategoriesState = { 10 | categories: [ 11 | { name: 'Shoes', productCount: 0 }, 12 | { name: 'Jackets', productCount: 0 } 13 | ] 14 | } 15 | 16 | const selectCategoryReducer = createReducer( 17 | categoryInitialState, 18 | ); 19 | 20 | export const categoriesFeatureKey = 'categories'; 21 | 22 | export function reducer(state: CategoriesState | undefined, action: Action) { 23 | return selectCategoryReducer(state, action); 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/standard/standard/standard.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { StandardComponent } from './standard.component'; 4 | 5 | describe('StandardComponent', () => { 6 | let component: StandardComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ StandardComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(StandardComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/categories/src/lib/categories.component.spec.ts: -------------------------------------------------------------------------------- 1 | import {ComponentFixture, TestBed} from '@angular/core/testing'; 2 | 3 | import {CategoriesComponent} from './categories.component'; 4 | 5 | describe('CategoriesComponent', () => { 6 | let component: CategoriesComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CategoriesComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CategoriesComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /.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 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | 16 | # IDEs and editors 17 | /.idea 18 | .project 19 | .classpath 20 | .c9/ 21 | *.launch 22 | .settings/ 23 | *.sublime-workspace 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | .history/* 32 | 33 | # misc 34 | /.sass-cache 35 | /connect.lock 36 | /coverage 37 | /libpeerconnection.log 38 | npm-debug.log 39 | yarn-error.log 40 | testem.log 41 | /typings 42 | 43 | # System Files 44 | .DS_Store 45 | Thumbs.db 46 | -------------------------------------------------------------------------------- /projects/settings/src/lib/settings.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {Observable, of, ReplaySubject} from "rxjs"; 3 | 4 | export enum CURRENCY_SYMBOL { 5 | USD = '$', 6 | EUR = '€', 7 | GBR = '£' 8 | } 9 | 10 | @Injectable({ 11 | providedIn: 'root' 12 | }) 13 | export class SettingsService { 14 | 15 | private selectedCurrency = new ReplaySubject(1); 16 | 17 | changeCurrency(currency: CURRENCY_SYMBOL): void { 18 | this.selectedCurrency.next(currency); 19 | } 20 | 21 | get selectedCurrency$(): Observable { 22 | return this.selectedCurrency.asObservable(); 23 | } 24 | 25 | get currencies$(): Observable { 26 | return of([CURRENCY_SYMBOL.USD, CURRENCY_SYMBOL.EUR, CURRENCY_SYMBOL.GBR]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/lib/ngrx-categories.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { NgrxCategoriesComponent } from './ngrx-categories.component'; 3 | import {MatListModule} from "@angular/material/list"; 4 | import {MatBadgeModule} from "@angular/material/badge"; 5 | import {StoreModule} from "@ngrx/store"; 6 | import * as fromCategories from './store'; 7 | import {CommonModule} from "@angular/common"; 8 | 9 | 10 | @NgModule({ 11 | declarations: [ 12 | NgrxCategoriesComponent 13 | ], 14 | imports: [ 15 | CommonModule, 16 | MatListModule, 17 | MatBadgeModule, 18 | StoreModule.forFeature(fromCategories.categoriesFeatureKey, fromCategories.reducer), 19 | ], 20 | exports: [ 21 | NgrxCategoriesComponent 22 | ] 23 | }) 24 | export class NgrxCategoriesModule { } 25 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/lib/store/index.ts: -------------------------------------------------------------------------------- 1 | import {Category} from "../../../../categories/src/lib/categories.service"; 2 | import {Action, createReducer} from "@ngrx/store"; 3 | 4 | export interface CategoriesState { 5 | categories: Category[], 6 | } 7 | 8 | export const categoryInitialState: CategoriesState = { 9 | categories: [ 10 | { name: 'Shoes', productCount: 2 }, 11 | { name: 'Jackets', productCount: 1 } 12 | ] 13 | } 14 | 15 | const selectCategoryReducer = createReducer( 16 | categoryInitialState 17 | ); 18 | 19 | export const selectCategories = (state: object) => (state as any).categories; 20 | 21 | export const categoriesFeatureKey = 'categories'; 22 | 23 | export function reducer(state: CategoriesState | undefined, action: Action) { 24 | return selectCategoryReducer(state, action); 25 | } 26 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/ngrx-products.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NgrxProductsComponent } from './ngrx-products.component'; 4 | 5 | describe('NgrxProductsComponent', () => { 6 | let component: NgrxProductsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NgrxProductsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NgrxProductsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/notifications.component.spec.ts: -------------------------------------------------------------------------------- 1 | import {ComponentFixture, TestBed} from '@angular/core/testing'; 2 | 3 | import {NotificationsComponent} from './notifications.component'; 4 | 5 | describe('NotificationsComponent', () => { 6 | let component: NotificationsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NotificationsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NotificationsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/lib/ngrx-categories.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NgrxCategoriesComponent } from './ngrx-categories.component'; 4 | 5 | describe('NgrxCategoriesComponent', () => { 6 | let component: NgrxCategoriesComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NgrxCategoriesComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NgrxCategoriesComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting() 21 | ); 22 | // Then we find all the tests. 23 | const context = require.context('./', true, /\.spec\.ts$/); 24 | // And load the modules. 25 | context.keys().map(context); 26 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/src/lib/add-product-form.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { AddProductFormComponent } from './add-product-form.component'; 4 | 5 | describe('AddProductFormComponent', () => { 6 | let component: AddProductFormComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ AddProductFormComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(AddProductFormComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/products/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import {getTestBed} from '@angular/core/testing'; 6 | import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing'; 7 | 8 | declare const require: { 9 | context(path: string, deep?: boolean, filter?: RegExp): { 10 | keys(): string[]; 11 | (id: string): T; 12 | }; 13 | }; 14 | 15 | // First, initialize the Angular testing environment. 16 | getTestBed().initTestEnvironment( 17 | BrowserDynamicTestingModule, 18 | platformBrowserDynamicTesting() 19 | ); 20 | // Then we find all the tests. 21 | const context = require.context('./', true, /\.spec\.ts$/); 22 | // And load the modules. 23 | context.keys().map(context); 24 | -------------------------------------------------------------------------------- /projects/settings/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import {getTestBed} from '@angular/core/testing'; 6 | import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing'; 7 | 8 | declare const require: { 9 | context(path: string, deep?: boolean, filter?: RegExp): { 10 | keys(): string[]; 11 | (id: string): T; 12 | }; 13 | }; 14 | 15 | // First, initialize the Angular testing environment. 16 | getTestBed().initTestEnvironment( 17 | BrowserDynamicTestingModule, 18 | platformBrowserDynamicTesting() 19 | ); 20 | // Then we find all the tests. 21 | const context = require.context('./', true, /\.spec\.ts$/); 22 | // And load the modules. 23 | context.keys().map(context); 24 | -------------------------------------------------------------------------------- /projects/categories/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import {getTestBed} from '@angular/core/testing'; 6 | import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing'; 7 | 8 | declare const require: { 9 | context(path: string, deep?: boolean, filter?: RegExp): { 10 | keys(): string[]; 11 | (id: string): T; 12 | }; 13 | }; 14 | 15 | // First, initialize the Angular testing environment. 16 | getTestBed().initTestEnvironment( 17 | BrowserDynamicTestingModule, 18 | platformBrowserDynamicTesting() 19 | ); 20 | // Then we find all the tests. 21 | const context = require.context('./', true, /\.spec\.ts$/); 22 | // And load the modules. 23 | context.keys().map(context); 24 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/ngrx-notifications.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NgrxNotificationsComponent } from './ngrx-notifications.component'; 4 | 5 | describe('NgrxNotificationsComponent', () => { 6 | let component: NgrxNotificationsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NgrxNotificationsComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NgrxNotificationsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /projects/notifications/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import {getTestBed} from '@angular/core/testing'; 6 | import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing'; 7 | 8 | declare const require: { 9 | context(path: string, deep?: boolean, filter?: RegExp): { 10 | keys(): string[]; 11 | (id: string): T; 12 | }; 13 | }; 14 | 15 | // First, initialize the Angular testing environment. 16 | getTestBed().initTestEnvironment( 17 | BrowserDynamicTestingModule, 18 | platformBrowserDynamicTesting() 19 | ); 20 | // Then we find all the tests. 21 | const context = require.context('./', true, /\.spec\.ts$/); 22 | // And load the modules. 23 | context.keys().map(context); 24 | -------------------------------------------------------------------------------- /projects/events/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: { 12 | context(path: string, deep?: boolean, filter?: RegExp): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment( 20 | BrowserDynamicTestingModule, 21 | platformBrowserDynamicTesting() 22 | ); 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: { 12 | context(path: string, deep?: boolean, filter?: RegExp): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment( 20 | BrowserDynamicTestingModule, 21 | platformBrowserDynamicTesting() 22 | ); 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/store/products.eda.effects.ts: -------------------------------------------------------------------------------- 1 | import {Inject, Injectable} from "@angular/core"; 2 | import {Actions, createEffect, ofType} from "@ngrx/effects"; 3 | import {map, tap} from "rxjs/operators"; 4 | import {CategorySelectedEvent} from "../../../../events/src/lib/category-selected.event"; 5 | import {APPLICATION_BUS, Dispatcher} from "@cobiro/eda"; 6 | 7 | @Injectable() 8 | export class ProductsEDAEffects { 9 | 10 | notification$ = createEffect(() => this.actions$.pipe( 11 | ofType('[Categories] Select'), 12 | tap(({categoryName}) => { 13 | return this.dispatcher.dispatch(new CategorySelectedEvent(categoryName)) 14 | }), 15 | map(_ => ({type: '[Noop]'})) 16 | ) 17 | ); 18 | 19 | constructor( 20 | private actions$: Actions, 21 | @Inject(APPLICATION_BUS) private dispatcher: Dispatcher 22 | ) {} 23 | } 24 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: { 12 | context(path: string, deep?: boolean, filter?: RegExp): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment( 20 | BrowserDynamicTestingModule, 21 | platformBrowserDynamicTesting() 22 | ); 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: { 12 | context(path: string, deep?: boolean, filter?: RegExp): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment( 20 | BrowserDynamicTestingModule, 21 | platformBrowserDynamicTesting() 22 | ); 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js'; 4 | import 'zone.js/testing'; 5 | import { getTestBed } from '@angular/core/testing'; 6 | import { 7 | BrowserDynamicTestingModule, 8 | platformBrowserDynamicTesting 9 | } from '@angular/platform-browser-dynamic/testing'; 10 | 11 | declare const require: { 12 | context(path: string, deep?: boolean, filter?: RegExp): { 13 | keys(): string[]; 14 | (id: string): T; 15 | }; 16 | }; 17 | 18 | // First, initialize the Angular testing environment. 19 | getTestBed().initTestEnvironment( 20 | BrowserDynamicTestingModule, 21 | platformBrowserDynamicTesting() 22 | ); 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/ngrx-notifications.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import {Observable} from "rxjs"; 3 | import {selectNotifications} from "./store/notifications.selector"; 4 | import {Store} from "@ngrx/store"; 5 | import {Notification} from "../../../notifications/src/lib/notifications.service"; 6 | 7 | @Component({ 8 | selector: 'lib-ngrx-notifications', 9 | template: ` 10 | 11 | {{notification.text}} 12 | 13 | `, 14 | styles: [ 15 | ] 16 | }) 17 | export class NgrxNotificationsComponent { 18 | 19 | // @ts-ignore 20 | notifications$: Observable<{ notifications: Notification[] }> = this.store.select(selectNotifications) 21 | 22 | constructor(private store: Store) { } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/ngrx-products.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {NgrxProductsComponent} from './ngrx-products.component'; 3 | import {CommonModule} from "@angular/common"; 4 | import {MatListModule} from "@angular/material/list"; 5 | import {MatButtonModule} from "@angular/material/button"; 6 | import {StoreModule} from "@ngrx/store"; 7 | import * as fromProducts from "./store/products.selector"; 8 | import {EffectsModule} from "@ngrx/effects"; 9 | import {ProductsEDAEffects} from "./store/products.eda.effects"; 10 | 11 | 12 | @NgModule({ 13 | declarations: [ 14 | NgrxProductsComponent 15 | ], 16 | imports: [ 17 | CommonModule, 18 | MatListModule, 19 | MatButtonModule, 20 | StoreModule.forFeature(fromProducts.productsFeatureKey, fromProducts.reducer), 21 | EffectsModule.forFeature([ProductsEDAEffects]) 22 | ], 23 | exports: [ 24 | NgrxProductsComponent 25 | ] 26 | }) 27 | export class NgrxProductsModule { } 28 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/store/index.ts: -------------------------------------------------------------------------------- 1 | import {Action, createAction, createReducer, on, props} from "@ngrx/store"; 2 | import {Notification} from "../../../../notifications/src/lib/notifications.service"; 3 | 4 | export const notify = createAction( 5 | '[Notifications] Notify', 6 | props<{message: string}>() 7 | ); 8 | 9 | export interface NotificationState { 10 | notifications: Notification[]; 11 | } 12 | 13 | export const notificationsFeatureKey = 'notifications'; 14 | 15 | // @ts-ignore 16 | export const selectNotifications = (state: object) => (state as any).notifications.notifications; 17 | 18 | export const notificationsInitState: NotificationState = { 19 | notifications: [] 20 | } 21 | 22 | const notificationsReducer = createReducer( 23 | notificationsInitState, 24 | on(notify, (state, props) => ({notifications: state.notifications.concat({text: props.message})})) 25 | ); 26 | 27 | export function reducer(state: NotificationState, action: Action) { 28 | return notificationsReducer(state, action); 29 | } 30 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/store/notifications.selector.ts: -------------------------------------------------------------------------------- 1 | import {Action, createAction, createReducer, on, props} from "@ngrx/store"; 2 | import {Notification} from "../../../../notifications/src/lib/notifications.service"; 3 | 4 | export const notificationFeatureKey = 'notifications'; 5 | 6 | export const notify = createAction( 7 | '[Notifications] notify', 8 | props<{notification: Notification}>() 9 | ); 10 | 11 | export interface NotificationsState { 12 | notifications: Notification[]; 13 | } 14 | 15 | export const notificationInitialState: NotificationsState = { 16 | notifications: [] 17 | } 18 | 19 | const notificationReducer = createReducer( 20 | notificationInitialState, 21 | on(notify, (state, {notification}) => ({ notifications: [...state.notifications, notification ]})), 22 | ); 23 | 24 | export function reducer(state: NotificationsState | undefined, action: Action) { 25 | return notificationReducer(state, action); 26 | } 27 | 28 | export const selectNotifications = (notification: NotificationsState) => notification.notifications; 29 | -------------------------------------------------------------------------------- /src/pages/standard/standard.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { StandardComponent } from './standard/standard.component'; 4 | import {NotificationsModule} from "../../../projects/notifications/src/lib/notifications.module"; 5 | import {MatToolbarModule} from "@angular/material/toolbar"; 6 | import {MatCardModule} from "@angular/material/card"; 7 | import {SettingsModule} from "../../../projects/settings/src/lib/settings.module"; 8 | import {CategoriesModule} from "../../../projects/categories/src/lib/categories.module"; 9 | import {ProductsModule} from "../../../projects/products/src/lib/products.module"; 10 | 11 | 12 | 13 | @NgModule({ 14 | declarations: [ 15 | StandardComponent 16 | ], 17 | imports: [ 18 | CommonModule, 19 | MatToolbarModule, 20 | NotificationsModule, 21 | MatCardModule, 22 | CategoriesModule, 23 | ProductsModule, 24 | SettingsModule 25 | ], 26 | exports: [ 27 | StandardComponent 28 | ] 29 | }) 30 | export class StandardModule { } 31 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [ 8 | AppComponent 9 | ], 10 | }).compileComponents(); 11 | }); 12 | 13 | it('should create the app', () => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }); 18 | 19 | it(`should have as title 'eda'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('eda'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement; 29 | expect(compiled.querySelector('.content span').textContent).toContain('eda app is running!'); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /projects/events/README.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project events` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project events`. 8 | > Note: Don't forget to add `--project events` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build events` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build events`, go to the dist folder `cd dist/events` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test events` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/products/README.md: -------------------------------------------------------------------------------- 1 | # Products 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project products` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project products`. 8 | > Note: Don't forget to add `--project products` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build products` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build products`, go to the dist folder `cd dist/products` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test products` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/settings/README.md: -------------------------------------------------------------------------------- 1 | # Settings 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project settings` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project settings`. 8 | > Note: Don't forget to add `--project settings` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build settings` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build settings`, go to the dist folder `cd dist/settings` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test settings` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/categories/README.md: -------------------------------------------------------------------------------- 1 | # Categories 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project categories` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project categories`. 8 | > Note: Don't forget to add `--project categories` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build categories` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build categories`, go to the dist folder `cd dist/categories` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test categories` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/src/lib/add-product-form.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {FormControl, FormGroup} from "@angular/forms"; 3 | 4 | @Component({ 5 | selector: 'lib-add-product-form', 6 | template: ` 7 | Add new product 8 | 9 | 10 | 11 | Name 12 | 13 | 14 | 15 | 16 | 17 | Price 18 | 19 | 20 | 21 | Add 22 | 23 | `, 24 | }) 25 | export class AddProductFormComponent { 26 | public addProduct = new FormGroup({ 27 | name: new FormControl([]), 28 | price: new FormControl([]) 29 | }); 30 | 31 | constructor() { 32 | } 33 | 34 | onFormSubmit() { 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /projects/ngrx-products/README.md: -------------------------------------------------------------------------------- 1 | # NgrxProducts 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project ngrx-products` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngrx-products`. 8 | > Note: Don't forget to add `--project ngrx-products` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build ngrx-products` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build ngrx-products`, go to the dist folder `cd dist/ngrx-products` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test ngrx-products` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/notifications/README.md: -------------------------------------------------------------------------------- 1 | # Notifications 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project notifications` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project notifications`. 8 | > Note: Don't forget to add `--project notifications` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build notifications` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build notifications`, go to the dist folder `cd dist/notifications` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test notifications` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/store/products.selector.ts: -------------------------------------------------------------------------------- 1 | import {Product} from "../../../../products/src/lib/products.service"; 2 | import {Action, createAction, createFeatureSelector, createReducer, createSelector, on} from "@ngrx/store"; 3 | import * as SelectCategoryActions from "./select-category.action"; 4 | 5 | export const productsFeatureKey = 'products'; 6 | 7 | export interface ProductsState { 8 | products: Product[]; 9 | selectedCategory: string; 10 | } 11 | 12 | export const productInitialState: ProductsState = { 13 | products: [ 14 | { name: 'Leather Shoe', categoryId: 'Shoes', price: 100 }, 15 | { name: 'Leather Jacket', categoryId: 'Jackets', price: 500 }, 16 | ], 17 | selectedCategory: 'Shoes' 18 | } 19 | 20 | const productsReducer = createReducer( 21 | productInitialState, 22 | on(SelectCategoryActions.selectCategory, (state, { categoryName }) => ({...state, selectedCategory: categoryName})) 23 | ); 24 | 25 | export function reducer(state: ProductsState | undefined, action: Action) { 26 | return productsReducer(state, action) 27 | } 28 | 29 | export const selectProducts = (state: ProductsState) => state.products; 30 | -------------------------------------------------------------------------------- /projects/ngrx-categories/README.md: -------------------------------------------------------------------------------- 1 | # NgrxCategories 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project ngrx-categories` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngrx-categories`. 8 | > Note: Don't forget to add `--project ngrx-categories` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build ngrx-categories` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build ngrx-categories`, go to the dist folder `cd dist/ngrx-categories` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test ngrx-categories` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {BrowserModule} from '@angular/platform-browser'; 3 | import {AppComponent} from './app.component'; 4 | import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 5 | import {StoreModule} from "@ngrx/store"; 6 | import {AppRoutingModule} from "./app.routing"; 7 | import {StandardModule} from "../pages/standard/standard.module"; 8 | import {NgrxModule} from "../pages/ngrx/ngrx.module"; 9 | import {EffectsModule} from "@ngrx/effects"; 10 | import {ApplicationBusModule, TokenBasedApplicationEventHandlerRegistry} from "@cobiro/eda"; 11 | 12 | @NgModule({ 13 | declarations: [ 14 | AppComponent 15 | ], 16 | imports: [ 17 | BrowserModule, 18 | BrowserAnimationsModule, 19 | ApplicationBusModule.forRoot(), 20 | StoreModule.forRoot({}), 21 | EffectsModule.forRoot(), 22 | AppRoutingModule, 23 | StandardModule, 24 | NgrxModule 25 | ], 26 | providers: [], 27 | bootstrap: [AppComponent] 28 | }) 29 | export class AppModule { 30 | constructor(private registry: TokenBasedApplicationEventHandlerRegistry) { 31 | this.registry.init(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "implicitDependencies": { 3 | "workspace.json": "*", 4 | "package.json": { "dependencies": "*", "devDependencies": "*" }, 5 | "nx.json": "*" 6 | }, 7 | "affected": { "defaultBase": "master" }, 8 | "npmScope": "ngx-eda", 9 | "tasksRunnerOptions": { 10 | "default": { 11 | "runner": "@nrwl/workspace/tasks-runners/default", 12 | "options": { 13 | "cacheableOperations": ["build", "test", "lint", "package", "prepare", "build-storybook"], 14 | "strictlyOrderedTargets": ["build", "package", "prepare"] 15 | } 16 | } 17 | }, 18 | "projects": { 19 | "eda": { "implicitDependencies": [] }, 20 | "application-bus": { "implicitDependencies": [] }, 21 | "events": { "implicitDependencies": [] }, 22 | "categories": { "implicitDependencies": [] }, 23 | "notifications": { "implicitDependencies": [] }, 24 | "products": { "implicitDependencies": [] }, 25 | "settings": { "implicitDependencies": [] }, 26 | "ngrx-products": { "implicitDependencies": [] }, 27 | "ngrx-categories": { "implicitDependencies": [] }, 28 | "ngrx-notifications": { "implicitDependencies": [] } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/src/lib/ngrx-notifications.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { NgrxNotificationsComponent } from './ngrx-notifications.component'; 3 | import {CommonModule} from "@angular/common"; 4 | import {MatSelectModule} from "@angular/material/select"; 5 | import {StoreModule} from "@ngrx/store"; 6 | import {notificationFeatureKey, reducer} from "./store/notifications.selector"; 7 | import {CategorySelectedEventHandler} from "./event-handlers/category-selected.event-handler"; 8 | import {ProductAddedEventHandler} from "./event-handlers/product-added.event-handler"; 9 | import {provideApplicationEventHandler} from "@cobiro/eda"; 10 | 11 | @NgModule({ 12 | declarations: [ 13 | NgrxNotificationsComponent 14 | ], 15 | imports: [ 16 | CommonModule, 17 | MatSelectModule, 18 | StoreModule.forFeature(notificationFeatureKey, reducer) 19 | ], 20 | exports: [ 21 | NgrxNotificationsComponent 22 | ], 23 | providers: [ 24 | provideApplicationEventHandler(CategorySelectedEventHandler), 25 | provideApplicationEventHandler(ProductAddedEventHandler) 26 | ] 27 | }) 28 | export class NgrxNotificationsModule { } 29 | -------------------------------------------------------------------------------- /projects/notifications/src/lib/notifications.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {NotificationsComponent} from './notifications.component'; 3 | import {CommonModule} from "@angular/common"; 4 | import {BrowserModule} from "@angular/platform-browser"; 5 | import {MatSelectModule} from "@angular/material/select"; 6 | import {CategorySelectedEventHandler} from "./event-handlers/category-selected.event-handler"; 7 | import {CurrencyChangedEventHandler} from "./event-handlers/currency-changed.event-handler"; 8 | import {ProductAddedEventHandler} from "./event-handlers/product-added.event-handler"; 9 | import {provideApplicationEventHandler} from "@cobiro/eda"; 10 | 11 | @NgModule({ 12 | declarations: [ 13 | NotificationsComponent 14 | ], 15 | imports: [ 16 | CommonModule, BrowserModule, MatSelectModule 17 | ], 18 | exports: [ 19 | NotificationsComponent 20 | ], 21 | providers: [ 22 | provideApplicationEventHandler(CategorySelectedEventHandler), 23 | provideApplicationEventHandler(CurrencyChangedEventHandler), 24 | provideApplicationEventHandler(ProductAddedEventHandler) 25 | ] 26 | }) 27 | export class NotificationsModule { } 28 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/README.md: -------------------------------------------------------------------------------- 1 | # AddProductForm 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project add-product-form` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project add-product-form`. 8 | > Note: Don't forget to add `--project add-product-form` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build add-product-form` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build add-product-form`, go to the dist folder `cd dist/add-product-form` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test add-product-form` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /projects/settings/src/lib/settings.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {CURRENCY_SYMBOL, SettingsService} from "./settings.service"; 3 | import {NotificationsService} from "../../../notifications/src/lib/notifications.service"; 4 | 5 | @Component({ 6 | selector: 'lib-settings', 7 | template: ` 8 | Currency settings 9 | 10 | {{currency}} 11 | 12 | `, 13 | }) 14 | export class SettingsComponent { 15 | 16 | public currencies$ = this.settings.currencies$; 17 | public selectedCurrency$ = this.settings.selectedCurrency$; 18 | 19 | constructor( 20 | private settings: SettingsService, 21 | private notifier: NotificationsService 22 | ) { 23 | this.settings.changeCurrency(CURRENCY_SYMBOL.USD); 24 | } 25 | 26 | onCurrencyChange(currency: CURRENCY_SYMBOL) { 27 | this.settings.changeCurrency(currency); 28 | this.notifier.notify(`Currency changed to ${currency}`); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/README.md: -------------------------------------------------------------------------------- 1 | # NgrxNotifications 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project ngrx-notifications` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngrx-notifications`. 8 | > Note: Don't forget to add `--project ngrx-notifications` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build ngrx-notifications` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build ngrx-notifications`, go to the dist folder `cd dist/ngrx-notifications` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test ngrx-notifications` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | 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. 25 | -------------------------------------------------------------------------------- /src/pages/ngrx/ngrx.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NgrxComponent } from './ngrx/ngrx.component'; 4 | import {MatToolbarModule} from "@angular/material/toolbar"; 5 | import {SettingsModule} from "../../../projects/settings/src/lib/settings.module"; 6 | import {NgrxProductsModule} from "../../../projects/ngrx-products/src/lib/ngrx-products.module"; 7 | import {NgrxCategoriesModule} from "../../../projects/ngrx-categories/src/lib/ngrx-categories.module"; 8 | import {MatCardModule} from "@angular/material/card"; 9 | import {NgrxNotificationsModule} from "../../../projects/ngrx-notifications/src/lib/ngrx-notifications.module"; 10 | import {AddProductFormModule} from "../../../projects/shared/add-product-form/src/lib/add-product-form.module"; 11 | 12 | @NgModule({ 13 | declarations: [ 14 | NgrxComponent 15 | ], 16 | imports: [ 17 | CommonModule, 18 | MatToolbarModule, 19 | MatCardModule, 20 | NgrxNotificationsModule, 21 | SettingsModule, 22 | NgrxProductsModule, 23 | NgrxCategoriesModule, 24 | SettingsModule, 25 | AddProductFormModule 26 | ] 27 | }) 28 | export class NgrxModule { } 29 | -------------------------------------------------------------------------------- /projects/categories/src/lib/categories.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {CategoriesService} from "./categories.service"; 3 | import {MatSelectionListChange} from "@angular/material/list"; 4 | import {NotificationsService} from "../../../notifications/src/lib/notifications.service"; 5 | 6 | @Component({ 7 | selector: 'lib-categories', 8 | template: ` 9 | Your categories 10 | 11 | {{category.name}} 12 | 13 | `, 14 | }) 15 | export class CategoriesComponent { 16 | 17 | public categories$ = this.categoryService.categories$; 18 | 19 | constructor( 20 | private categoryService: CategoriesService, 21 | private notifier: NotificationsService, 22 | ) { } 23 | 24 | onCategorySelected($event: MatSelectionListChange) { 25 | const categoryName = $event.source.selectedOptions.selected[0].value; 26 | this.categoryService.select(categoryName); 27 | this.notifier.notify(`Selected ${categoryName}`); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /projects/products/src/lib/products.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {ProductsComponent} from './products.component'; 3 | import {ReactiveFormsModule} from "@angular/forms"; 4 | import {CommonModule} from "@angular/common"; 5 | import {MatListModule} from "@angular/material/list"; 6 | import {MatFormFieldModule} from "@angular/material/form-field"; 7 | import {MatInputModule} from "@angular/material/input"; 8 | import {MatButtonModule} from "@angular/material/button"; 9 | import {CategorySelectedEventHandler} from "./event-handlers/category-selected.event-handler"; 10 | import {CurrencyChangedEventHandler} from "./event-handlers/currency-changed.event-handler"; 11 | import {provideApplicationEventHandler} from "@cobiro/eda"; 12 | 13 | 14 | @NgModule({ 15 | declarations: [ 16 | ProductsComponent 17 | ], 18 | imports: [ 19 | ReactiveFormsModule, CommonModule, MatListModule, MatFormFieldModule, MatInputModule, MatButtonModule 20 | ], 21 | exports: [ 22 | ProductsComponent 23 | ], 24 | providers: [ 25 | provideApplicationEventHandler(CategorySelectedEventHandler), 26 | provideApplicationEventHandler(CurrencyChangedEventHandler) 27 | ] 28 | }) 29 | export class ProductsModule { } 30 | -------------------------------------------------------------------------------- /projects/products/src/lib/products.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {BehaviorSubject, Observable, ReplaySubject} from "rxjs"; 3 | 4 | export interface Product { 5 | name: string; 6 | price: number; 7 | categoryId: string; 8 | } 9 | 10 | @Injectable({ 11 | providedIn: 'root' 12 | }) 13 | export class ProductsService { 14 | 15 | private productSubject = new BehaviorSubject([]); 16 | get products$(): Observable { 17 | return this.productSubject.asObservable(); 18 | } 19 | 20 | add(name: string, price: number, categoryId: string): void { 21 | this.productSubject.next([...this.productSubject.getValue(), { name, price, categoryId}]); 22 | } 23 | 24 | private categoryIdSubject = new ReplaySubject<{ name: string}>(1); 25 | setCategoryId(categoryId: string): void { 26 | this.categoryIdSubject.next({ name: categoryId }); 27 | } 28 | get selectedCategory$(): Observable<{ name: string}> { 29 | return this.categoryIdSubject.asObservable(); 30 | } 31 | 32 | private currencySubject = new ReplaySubject(1); 33 | setCurrency(currency: string): void { 34 | this.currencySubject.next(currency); 35 | } 36 | get currency$(): Observable { 37 | return this.currencySubject.asObservable(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/ngrx-products.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {Store} from "@ngrx/store"; 3 | import * as fromProducts from './store/products.selector'; 4 | import * as fromCategories from '../../../ngrx-categories/src/lib/store/categories.selector'; 5 | import {combineLatest, Observable} from "rxjs"; 6 | import {Product} from "../../../products/src/lib/products.service"; 7 | import {map, tap} from "rxjs/operators"; 8 | import {ProductsState} from "./store/products.selector"; 9 | 10 | @Component({ 11 | selector: 'lib-ngrx-products', 12 | template: ` 13 | Category products 14 | 15 | 16 | {{product.name}} {{product.price}} 17 | 18 | 19 | `, 20 | }) 21 | export class NgrxProductsComponent{ 22 | 23 | // @ts-ignore 24 | categoryProducts$: Observable = this.store.select(fromProducts.selectProducts).pipe( 25 | tap(console.log), 26 | map((state: ProductsState) => state.products.filter((product: Product) => product.categoryId === state.selectedCategory)) 27 | ) 28 | 29 | constructor(private store: Store) { } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /projects/categories/src/lib/categories.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {BehaviorSubject, Observable, ReplaySubject} from "rxjs"; 3 | 4 | export interface Category { 5 | name: string; 6 | productCount: number; 7 | } 8 | 9 | @Injectable({ 10 | providedIn: 'root' 11 | }) 12 | export class CategoriesService { 13 | private categoriesSubject = new BehaviorSubject([ 14 | { name: 'Shoes', productCount: 0 }, 15 | { name: 'Jackets', productCount: 0 } 16 | ]); 17 | private selectedCategorySubject = new ReplaySubject(1); 18 | 19 | get categories$(): Observable { 20 | return this.categoriesSubject.asObservable(); 21 | } 22 | 23 | get selectedCategory$(): Observable { 24 | return this.selectedCategorySubject.asObservable(); 25 | } 26 | 27 | select(categoryName: string) { 28 | const category = this.categoriesSubject.getValue().find(category => category.name === categoryName); 29 | if (category) { 30 | this.selectedCategorySubject.next(category); 31 | } 32 | } 33 | 34 | setProductCount(productCount: number, categoryName: string) { 35 | this.categoriesSubject.next(this.categoriesSubject.getValue().map(category => category.name === categoryName ? {...category, productCount} : category)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /projects/ngrx-categories/src/lib/ngrx-categories.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {Store} from "@ngrx/store"; 3 | import {MatSelectionListChange} from "@angular/material/list"; 4 | import {Observable} from "rxjs"; 5 | import {Category} from "../../../categories/src/lib/categories.service"; 6 | import * as fromCategories from "./store/categories.selector"; 7 | import {selectCategory} from "../../../ngrx-products/src/lib/store/select-category.action"; 8 | 9 | @Component({ 10 | selector: 'lib-ngrx-categories', 11 | template: `Your categories 12 | 13 | {{category.name}} 14 | `, 15 | }) 16 | export class NgrxCategoriesComponent implements OnInit { 17 | 18 | public categories$: Observable<{ categories: Category[] }> = this.store.select(fromCategories.selectCategories); 19 | 20 | constructor(private store: Store) { } 21 | 22 | ngOnInit() {} 23 | 24 | onCategorySelected($event: MatSelectionListChange) { 25 | const categoryName = $event.source.selectedOptions.selected[0].value; 26 | this.store.dispatch(selectCategory({categoryName})); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /projects/ngrx-products/src/lib/store/index.ts: -------------------------------------------------------------------------------- 1 | import {Product} from "../../../../products/src/lib/products.service"; 2 | import {Action, createFeatureSelector, createReducer, createSelector, on} from "@ngrx/store"; 3 | import {createAction, props} from "@ngrx/store"; 4 | 5 | export const selectCategory = createAction( 6 | '[Products] Select', 7 | props<{ categoryName: string }>() 8 | ); 9 | 10 | export const productsFeatureKey = 'products'; 11 | 12 | export interface ProductsState { 13 | products: Product[]; 14 | selectedCategory: string; 15 | } 16 | 17 | export const productInitialState: ProductsState = { 18 | products: [ 19 | { name: 'Leather Shoes', categoryId: 'Shoes', price: 100 }, 20 | { name: 'Running Shoes', categoryId: 'Shoes', price: 50 }, 21 | { name: 'Leather Jacket', categoryId: 'Jackets', price: 500 } 22 | ], 23 | selectedCategory: 'Shoes' 24 | } 25 | 26 | const productsReducer = createReducer( 27 | productInitialState, 28 | on(selectCategory, (state, props) => ({...state, selectedCategory: props.categoryName})) 29 | ); 30 | 31 | export function reducer(state: ProductsState, action: Action) { 32 | return productsReducer(state, action); 33 | } 34 | 35 | export const selectProducts = (products: { products: ProductsState }) => products.products.products.filter(product => product.categoryId === products.products.selectedCategory); 36 | export const selectSelectedCategory = (products: { products: ProductsState }) => products.products.selectedCategory; 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eda", 3 | "version": "0.0.1", 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 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "~12.0.2", 14 | "@angular/cdk": "^12.0.2", 15 | "@angular/common": "~12.0.2", 16 | "@angular/compiler": "~12.0.2", 17 | "@angular/core": "~12.0.2", 18 | "@angular/forms": "~12.0.2", 19 | "@angular/material": "^12.0.2", 20 | "@angular/platform-browser": "~12.0.2", 21 | "@angular/platform-browser-dynamic": "~12.0.2", 22 | "@angular/router": "~12.0.2", 23 | "@cobiro/eda": "0.0.2", 24 | "@ngrx/effects": "^12.4.0", 25 | "@ngrx/store": "^12.4.0", 26 | "@nrwl/workspace": "^12.3.5", 27 | "rxjs": "~6.6.0", 28 | "tslib": "^2.1.0", 29 | "zone.js": "~0.11.4" 30 | }, 31 | "devDependencies": { 32 | "@angular-devkit/build-angular": "~12.0.2", 33 | "@angular/cli": "~12.0.2", 34 | "@angular/compiler-cli": "~12.0.2", 35 | "@types/jasmine": "~3.6.0", 36 | "@types/node": "^12.11.1", 37 | "jasmine-core": "~3.7.0", 38 | "karma": "~6.3.0", 39 | "karma-chrome-launcher": "~3.1.0", 40 | "karma-coverage": "~2.0.3", 41 | "karma-jasmine": "~4.0.0", 42 | "karma-jasmine-html-reporter": "^1.5.0", 43 | "ng-packagr": "^12.0.0", 44 | "typescript": "~4.2.3", 45 | "prettier": "^2.0.4", 46 | "ajv": "^6.9.1 " 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/eda'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/events/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/events'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/products/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/products'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/settings/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/settings'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/categories/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/categories'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/ngrx-products/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/ngrx-products'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/notifications/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/notifications'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/ngrx-categories/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/ngrx-categories'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/ngrx-notifications/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../coverage/ngrx-notifications'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /projects/shared/add-product-form/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, '../../../coverage/shared/add-product-form'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "paths": { 6 | "@shared/add-product-form": [ 7 | "dist/shared/add-product-form/shared-add-product-form", 8 | "dist/shared/add-product-form" 9 | ], 10 | "application-bus": [ 11 | "dist/application-bus/application-bus", 12 | "dist/application-bus" 13 | ], 14 | "categories": [ 15 | "dist/categories/categories", 16 | "dist/categories" 17 | ], 18 | "events": [ 19 | "dist/events/events", 20 | "dist/events" 21 | ], 22 | "ngrx-categories": [ 23 | "dist/ngrx-categories/ngrx-categories", 24 | "dist/ngrx-categories" 25 | ], 26 | "ngrx-notifications": [ 27 | "dist/ngrx-notifications/ngrx-notifications", 28 | "dist/ngrx-notifications" 29 | ], 30 | "ngrx-products": [ 31 | "dist/ngrx-products/ngrx-products", 32 | "dist/ngrx-products" 33 | ], 34 | "notifications": [ 35 | "dist/notifications/notifications", 36 | "dist/notifications" 37 | ], 38 | "products": [ 39 | "dist/products/products", 40 | "dist/products" 41 | ], 42 | "settings": [ 43 | "dist/settings/settings", 44 | "dist/settings" 45 | ] 46 | }, 47 | "baseUrl": "./", 48 | "outDir": "./dist/out-tsc", 49 | "forceConsistentCasingInFileNames": true, 50 | "strict": true, 51 | "noImplicitReturns": true, 52 | "noFallthroughCasesInSwitch": true, 53 | "sourceMap": true, 54 | "declaration": false, 55 | "downlevelIteration": true, 56 | "experimentalDecorators": true, 57 | "moduleResolution": "node", 58 | "importHelpers": true, 59 | "target": "es2017", 60 | "module": "es2020", 61 | "lib": [ 62 | "es2018", 63 | "dom" 64 | ] 65 | }, 66 | "angularCompilerOptions": { 67 | "enableI18nLegacyMessageIdFormat": false, 68 | "strictInjectionParameters": true, 69 | "strictInputAccessModifiers": true, 70 | "strictTemplates": true 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | 63 | /*************************************************************************************************** 64 | * APPLICATION IMPORTS 65 | */ 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cobiro Event Driven Architectures ( EDA ) 2 | 3 | This repository contains many examples of usage EDA (**[@cobiro/eda](https://www.npmjs.com/package/@cobiro/eda)**) with Angular and NGRX. 4 | 5 | ## How to use 6 | 7 | Install package 8 | 9 | `npm install @cobiro/eda` 10 | 11 | 12 | Add ApplicationBusModule to your module 13 | ```ts 14 | import {ApplicationBusModule} from "@cobiro/eda"; 15 | 16 | @NgModule({ 17 | declarations: [AppComponent], 18 | imports: [ 19 | BrowserModule, 20 | BrowserAnimationsModule, 21 | ApplicationBusModule.forRoot(), 22 | StoreModule.forRoot({}), 23 | EffectsModule.forRoot(), 24 | AppRoutingModule, 25 | StandardModule, 26 | NgrxModule 27 | ], 28 | providers: [], 29 | bootstrap: [AppComponent] 30 | }) 31 | export class AppModule {} 32 | ``` 33 | 34 | Create ApplicationEvent 35 | 36 | ```ts 37 | import {ApplicationEvent} from "@cobiro/eda"; 38 | 39 | export class ProductAddedEvent extends ApplicationEvent { 40 | constructor(public readonly name: string, public readonly price: number, public readonly currency: string) { 41 | super(); 42 | } 43 | } 44 | ``` 45 | 46 | Dispatch event in your application 47 | 48 | ```ts 49 | import {APPLICATION_BUS, Dispatcher} from "@cobiro/eda"; 50 | import {ProductAddedEvent} from "./product-added.event"; 51 | import {Product} from "./products.service"; 52 | 53 | export class ProductsComponent { 54 | constructor( 55 | @Inject(APPLICATION_BUS) private _applicationBus: Dispatcher 56 | ) { 57 | } 58 | 59 | onProductAddClicked(product: Product): void { 60 | this._applicationBus.dispatch(new ProductAddedEvent(product.name, product.price, product.currency)); 61 | } 62 | } 63 | ``` 64 | 65 | Create ApplicationEventHandler and provide it into your module when you want to handle it: 66 | 67 | ```ts 68 | import {NotificationsService} from "../notifications.service"; 69 | import {ProductAddedEvent} from "../../../../events/src/lib/product-added.event"; 70 | import {ApplicationEventHandler} from "@cobiro/eda"; 71 | 72 | @Injectable() 73 | export class ProductAddedEventsHandler implements ApplicationEventsHandler { 74 | eventsClasses = [ProductAddedEvent]; 75 | strategy = ongoingEventsOrchestrationStrategy; 76 | 77 | constructor(private readonly layoutState: LayoutState) {} 78 | 79 | handle(events: ProductAddedEvent[]) { 80 | const event = events[0]; 81 | this.notifyService.notify(`Added ${event.name} ${event.currency}${event.price}`); 82 | } 83 | } 84 | 85 | @NgModule({ 86 | ..., 87 | providers: [ 88 | provideApplicationEventsHandler(ProductAddedEventHandler) 89 | ] 90 | }) 91 | export class NotificationsModule { } 92 | ``` 93 | ## Strategies 94 | In events handler you can use different various of strategy to orchestrate events. 95 | 96 | - **ongoingEventsOrchestrationStrategy** - it's default strategy will orchestrate events one by one 97 | - **allEventsOnceOrchestrationStrategy** - orchestrate all the events at the same time 98 | - **zipEventsOrchestrationStrategy** - after all events are dispatched 99 | - **limitedOngoingEventsOrchestrationStrategy** - can handle two events when first event is starting event and second is canceling event, when the canceling event is dispatched handler stops listening to events 100 | -------------------------------------------------------------------------------- /projects/products/src/lib/products.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {ProductsService} from "./products.service"; 3 | import {FormControl, FormGroup} from "@angular/forms"; 4 | import {combineLatest} from "rxjs"; 5 | import {map} from "rxjs/operators"; 6 | import {CategoriesService} from "../../../categories/src/lib/categories.service"; 7 | import {SettingsService} from "../../../settings/src/lib/settings.service"; 8 | import {NotificationsService} from "../../../notifications/src/lib/notifications.service"; 9 | 10 | @Component({ 11 | selector: 'lib-products', 12 | template: ` 13 | 14 | 15 | 16 | {{selectedCategory.name}} products 17 | 18 | {{product.name}} {{selectedCurrency}}{{product.price}} 20 | 21 | Add new product 22 | 24 | 25 | 26 | Name 27 | 28 | 29 | 30 | 31 | 32 | Price 33 | {{selectedCurrency}} 34 | 35 | 36 | 37 | Add 38 | 39 | 40 | 41 | 42 | `, 43 | }) 44 | export class ProductsComponent { 45 | 46 | public addProduct = new FormGroup({ 47 | name: new FormControl([]), 48 | price: new FormControl([]) 49 | }); 50 | 51 | public selectedCurrency$ = this.settings.selectedCurrency$; 52 | 53 | public selectedCategory$ = this.categoryService.selectedCategory$; 54 | 55 | categoryProducts$ = combineLatest([ 56 | this.selectedCategory$, 57 | this.productService.products$ 58 | ]).pipe( 59 | map(([selectedCategory, allProducts]) => allProducts.filter(product => product.categoryId === selectedCategory.name)) 60 | ); 61 | 62 | constructor( 63 | private productService: ProductsService, 64 | private categoryService: CategoriesService, 65 | private settings: SettingsService, 66 | private notifier: NotificationsService 67 | ) { 68 | } 69 | 70 | onFormSubmit(categoryId: string, currentProductCount: number, currency: string) { 71 | const productName = this.addProduct.get('name')?.value; 72 | const productPrice = this.addProduct.get('price')?.value; 73 | if (productName && productPrice) { 74 | this.productService.add(productName, productPrice, categoryId); 75 | this.addProduct.reset(); 76 | this.categoryService.setProductCount(currentProductCount + 1, categoryId); 77 | this.notifier.notify(`Added ${productName} ${currency}${productPrice}`); 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "eda": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "style": "scss" 11 | }, 12 | "@schematics/angular:application": { 13 | "strict": true 14 | } 15 | }, 16 | "root": "", 17 | "sourceRoot": "src", 18 | "prefix": "app", 19 | "architect": { 20 | "build": { 21 | "builder": "@angular-devkit/build-angular:browser", 22 | "options": { 23 | "outputPath": "dist/eda", 24 | "index": "src/index.html", 25 | "main": "src/main.ts", 26 | "polyfills": "src/polyfills.ts", 27 | "tsConfig": "tsconfig.app.json", 28 | "inlineStyleLanguage": "scss", 29 | "assets": [ 30 | "src/favicon.ico", 31 | "src/assets" 32 | ], 33 | "styles": [ 34 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 35 | "src/styles.scss" 36 | ], 37 | "scripts": [] 38 | }, 39 | "configurations": { 40 | "production": { 41 | "budgets": [ 42 | { 43 | "type": "initial", 44 | "maximumWarning": "500kb", 45 | "maximumError": "1mb" 46 | }, 47 | { 48 | "type": "anyComponentStyle", 49 | "maximumWarning": "2kb", 50 | "maximumError": "4kb" 51 | } 52 | ], 53 | "fileReplacements": [ 54 | { 55 | "replace": "src/environments/environment.ts", 56 | "with": "src/environments/environment.prod.ts" 57 | } 58 | ], 59 | "outputHashing": "all" 60 | }, 61 | "development": { 62 | "buildOptimizer": false, 63 | "optimization": false, 64 | "vendorChunk": true, 65 | "extractLicenses": false, 66 | "sourceMap": true, 67 | "namedChunks": true 68 | } 69 | }, 70 | "defaultConfiguration": "production" 71 | }, 72 | "serve": { 73 | "builder": "@angular-devkit/build-angular:dev-server", 74 | "configurations": { 75 | "production": { 76 | "browserTarget": "eda:build:production" 77 | }, 78 | "development": { 79 | "browserTarget": "eda:build:development" 80 | } 81 | }, 82 | "defaultConfiguration": "development" 83 | }, 84 | "extract-i18n": { 85 | "builder": "@angular-devkit/build-angular:extract-i18n", 86 | "options": { 87 | "browserTarget": "eda:build" 88 | } 89 | }, 90 | "test": { 91 | "builder": "@angular-devkit/build-angular:karma", 92 | "options": { 93 | "main": "src/test.ts", 94 | "polyfills": "src/polyfills.ts", 95 | "tsConfig": "tsconfig.spec.json", 96 | "karmaConfig": "karma.conf.js", 97 | "inlineStyleLanguage": "scss", 98 | "assets": [ 99 | "src/favicon.ico", 100 | "src/assets" 101 | ], 102 | "styles": [ 103 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 104 | "src/styles.scss" 105 | ], 106 | "scripts": [] 107 | } 108 | } 109 | } 110 | }, 111 | "application-bus": { 112 | "projectType": "library", 113 | "root": "projects/application-bus", 114 | "sourceRoot": "projects/application-bus/src", 115 | "prefix": "lib", 116 | "architect": { 117 | "build": { 118 | "builder": "@angular-devkit/build-angular:ng-packagr", 119 | "options": { 120 | "project": "projects/application-bus/ng-package.json" 121 | }, 122 | "configurations": { 123 | "production": { 124 | "tsConfig": "projects/application-bus/tsconfig.lib.prod.json" 125 | }, 126 | "development": { 127 | "tsConfig": "projects/application-bus/tsconfig.lib.json" 128 | } 129 | }, 130 | "defaultConfiguration": "production" 131 | }, 132 | "test": { 133 | "builder": "@angular-devkit/build-angular:karma", 134 | "options": { 135 | "main": "projects/application-bus/src/test.ts", 136 | "tsConfig": "projects/application-bus/tsconfig.spec.json", 137 | "karmaConfig": "projects/application-bus/karma.conf.js" 138 | } 139 | } 140 | } 141 | }, 142 | "notifications": { 143 | "projectType": "library", 144 | "root": "projects/notifications", 145 | "sourceRoot": "projects/notifications/src", 146 | "prefix": "lib", 147 | "architect": { 148 | "build": { 149 | "builder": "@angular-devkit/build-angular:ng-packagr", 150 | "options": { 151 | "project": "projects/notifications/ng-package.json" 152 | }, 153 | "configurations": { 154 | "production": { 155 | "tsConfig": "projects/notifications/tsconfig.lib.prod.json" 156 | }, 157 | "development": { 158 | "tsConfig": "projects/notifications/tsconfig.lib.json" 159 | } 160 | }, 161 | "defaultConfiguration": "production" 162 | }, 163 | "test": { 164 | "builder": "@angular-devkit/build-angular:karma", 165 | "options": { 166 | "main": "projects/notifications/src/test.ts", 167 | "tsConfig": "projects/notifications/tsconfig.spec.json", 168 | "karmaConfig": "projects/notifications/karma.conf.js" 169 | } 170 | } 171 | } 172 | }, 173 | "categories": { 174 | "projectType": "library", 175 | "root": "projects/categories", 176 | "sourceRoot": "projects/categories/src", 177 | "prefix": "lib", 178 | "architect": { 179 | "build": { 180 | "builder": "@angular-devkit/build-angular:ng-packagr", 181 | "options": { 182 | "project": "projects/categories/ng-package.json" 183 | }, 184 | "configurations": { 185 | "production": { 186 | "tsConfig": "projects/categories/tsconfig.lib.prod.json" 187 | }, 188 | "development": { 189 | "tsConfig": "projects/categories/tsconfig.lib.json" 190 | } 191 | }, 192 | "defaultConfiguration": "production" 193 | }, 194 | "test": { 195 | "builder": "@angular-devkit/build-angular:karma", 196 | "options": { 197 | "main": "projects/categories/src/test.ts", 198 | "tsConfig": "projects/categories/tsconfig.spec.json", 199 | "karmaConfig": "projects/categories/karma.conf.js" 200 | } 201 | } 202 | } 203 | }, 204 | "products": { 205 | "projectType": "library", 206 | "root": "projects/products", 207 | "sourceRoot": "projects/products/src", 208 | "prefix": "lib", 209 | "architect": { 210 | "build": { 211 | "builder": "@angular-devkit/build-angular:ng-packagr", 212 | "options": { 213 | "project": "projects/products/ng-package.json" 214 | }, 215 | "configurations": { 216 | "production": { 217 | "tsConfig": "projects/products/tsconfig.lib.prod.json" 218 | }, 219 | "development": { 220 | "tsConfig": "projects/products/tsconfig.lib.json" 221 | } 222 | }, 223 | "defaultConfiguration": "production" 224 | }, 225 | "test": { 226 | "builder": "@angular-devkit/build-angular:karma", 227 | "options": { 228 | "main": "projects/products/src/test.ts", 229 | "tsConfig": "projects/products/tsconfig.spec.json", 230 | "karmaConfig": "projects/products/karma.conf.js" 231 | } 232 | } 233 | } 234 | }, 235 | "settings": { 236 | "projectType": "library", 237 | "root": "projects/settings", 238 | "sourceRoot": "projects/settings/src", 239 | "prefix": "lib", 240 | "architect": { 241 | "build": { 242 | "builder": "@angular-devkit/build-angular:ng-packagr", 243 | "options": { 244 | "project": "projects/settings/ng-package.json" 245 | }, 246 | "configurations": { 247 | "production": { 248 | "tsConfig": "projects/settings/tsconfig.lib.prod.json" 249 | }, 250 | "development": { 251 | "tsConfig": "projects/settings/tsconfig.lib.json" 252 | } 253 | }, 254 | "defaultConfiguration": "production" 255 | }, 256 | "test": { 257 | "builder": "@angular-devkit/build-angular:karma", 258 | "options": { 259 | "main": "projects/settings/src/test.ts", 260 | "tsConfig": "projects/settings/tsconfig.spec.json", 261 | "karmaConfig": "projects/settings/karma.conf.js" 262 | } 263 | } 264 | } 265 | }, 266 | "events": { 267 | "projectType": "library", 268 | "root": "projects/events", 269 | "sourceRoot": "projects/events/src", 270 | "prefix": "lib", 271 | "architect": { 272 | "build": { 273 | "builder": "@angular-devkit/build-angular:ng-packagr", 274 | "options": { 275 | "project": "projects/events/ng-package.json" 276 | }, 277 | "configurations": { 278 | "production": { 279 | "tsConfig": "projects/events/tsconfig.lib.prod.json" 280 | }, 281 | "development": { 282 | "tsConfig": "projects/events/tsconfig.lib.json" 283 | } 284 | }, 285 | "defaultConfiguration": "production" 286 | }, 287 | "test": { 288 | "builder": "@angular-devkit/build-angular:karma", 289 | "options": { 290 | "main": "projects/events/src/test.ts", 291 | "tsConfig": "projects/events/tsconfig.spec.json", 292 | "karmaConfig": "projects/events/karma.conf.js" 293 | } 294 | } 295 | } 296 | }, 297 | "ngrx-categories": { 298 | "projectType": "library", 299 | "root": "projects/ngrx-categories", 300 | "sourceRoot": "projects/ngrx-categories/src", 301 | "prefix": "lib", 302 | "architect": { 303 | "build": { 304 | "builder": "@angular-devkit/build-angular:ng-packagr", 305 | "options": { 306 | "project": "projects/ngrx-categories/ng-package.json" 307 | }, 308 | "configurations": { 309 | "production": { 310 | "tsConfig": "projects/ngrx-categories/tsconfig.lib.prod.json" 311 | }, 312 | "development": { 313 | "tsConfig": "projects/ngrx-categories/tsconfig.lib.json" 314 | } 315 | }, 316 | "defaultConfiguration": "production" 317 | }, 318 | "test": { 319 | "builder": "@angular-devkit/build-angular:karma", 320 | "options": { 321 | "main": "projects/ngrx-categories/src/test.ts", 322 | "tsConfig": "projects/ngrx-categories/tsconfig.spec.json", 323 | "karmaConfig": "projects/ngrx-categories/karma.conf.js" 324 | } 325 | } 326 | } 327 | }, 328 | "ngrx-products": { 329 | "projectType": "library", 330 | "root": "projects/ngrx-products", 331 | "sourceRoot": "projects/ngrx-products/src", 332 | "prefix": "lib", 333 | "architect": { 334 | "build": { 335 | "builder": "@angular-devkit/build-angular:ng-packagr", 336 | "options": { 337 | "project": "projects/ngrx-products/ng-package.json" 338 | }, 339 | "configurations": { 340 | "production": { 341 | "tsConfig": "projects/ngrx-products/tsconfig.lib.prod.json" 342 | }, 343 | "development": { 344 | "tsConfig": "projects/ngrx-products/tsconfig.lib.json" 345 | } 346 | }, 347 | "defaultConfiguration": "production" 348 | }, 349 | "test": { 350 | "builder": "@angular-devkit/build-angular:karma", 351 | "options": { 352 | "main": "projects/ngrx-products/src/test.ts", 353 | "tsConfig": "projects/ngrx-products/tsconfig.spec.json", 354 | "karmaConfig": "projects/ngrx-products/karma.conf.js" 355 | } 356 | } 357 | } 358 | }, 359 | "ngrx-notifications": { 360 | "projectType": "library", 361 | "root": "projects/ngrx-notifications", 362 | "sourceRoot": "projects/ngrx-notifications/src", 363 | "prefix": "lib", 364 | "architect": { 365 | "build": { 366 | "builder": "@angular-devkit/build-angular:ng-packagr", 367 | "options": { 368 | "project": "projects/ngrx-notifications/ng-package.json" 369 | }, 370 | "configurations": { 371 | "production": { 372 | "tsConfig": "projects/ngrx-notifications/tsconfig.lib.prod.json" 373 | }, 374 | "development": { 375 | "tsConfig": "projects/ngrx-notifications/tsconfig.lib.json" 376 | } 377 | }, 378 | "defaultConfiguration": "production" 379 | }, 380 | "test": { 381 | "builder": "@angular-devkit/build-angular:karma", 382 | "options": { 383 | "main": "projects/ngrx-notifications/src/test.ts", 384 | "tsConfig": "projects/ngrx-notifications/tsconfig.spec.json", 385 | "karmaConfig": "projects/ngrx-notifications/karma.conf.js" 386 | } 387 | } 388 | } 389 | }, 390 | "@shared/add-product-form": { 391 | "projectType": "library", 392 | "root": "projects/shared/add-product-form", 393 | "sourceRoot": "projects/shared/add-product-form/src", 394 | "prefix": "lib", 395 | "architect": { 396 | "build": { 397 | "builder": "@angular-devkit/build-angular:ng-packagr", 398 | "options": { 399 | "project": "projects/shared/add-product-form/ng-package.json" 400 | }, 401 | "configurations": { 402 | "production": { 403 | "tsConfig": "projects/shared/add-product-form/tsconfig.lib.prod.json" 404 | }, 405 | "development": { 406 | "tsConfig": "projects/shared/add-product-form/tsconfig.lib.json" 407 | } 408 | }, 409 | "defaultConfiguration": "production" 410 | }, 411 | "test": { 412 | "builder": "@angular-devkit/build-angular:karma", 413 | "options": { 414 | "main": "projects/shared/add-product-form/src/test.ts", 415 | "tsConfig": "projects/shared/add-product-form/tsconfig.spec.json", 416 | "karmaConfig": "projects/shared/add-product-form/karma.conf.js" 417 | } 418 | } 419 | } 420 | } 421 | }, 422 | "defaultProject": "eda" 423 | } 424 | --------------------------------------------------------------------------------
10 | 11 | Name 12 | 13 | 14 |
16 | 17 | Price 18 | 19 | 20 |
25 | 26 | Name 27 | 28 | 29 |
31 | 32 | Price 33 | {{selectedCurrency}} 34 | 35 | 36 |