add mongodb-angular-expressjs-nodejs docker sample

Signed-off-by: Sohaib Manah <souhaibemanah@gmail.com>
pull/337/head
Sohaib Manah 1 year ago
parent e6b1d2755f
commit c5c2efb203
  1. 160
      mongodb-angular-expressjs-nodejs/README.md
  2. 1
      mongodb-angular-expressjs-nodejs/backend/.env.example
  3. 2
      mongodb-angular-expressjs-nodejs/backend/.gitignore
  4. 13
      mongodb-angular-expressjs-nodejs/backend/Dockerfile
  5. 29
      mongodb-angular-expressjs-nodejs/backend/db/mongodb.js
  6. 1117
      mongodb-angular-expressjs-nodejs/backend/package-lock.json
  7. 19
      mongodb-angular-expressjs-nodejs/backend/package.json
  8. 14
      mongodb-angular-expressjs-nodejs/backend/server.js
  9. 41
      mongodb-angular-expressjs-nodejs/compose.yaml
  10. BIN
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/angular-webpack/2b4a41390572dfa6c1136b7a99cc6bdaaa440b09/0.pack
  11. BIN
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/angular-webpack/2b4a41390572dfa6c1136b7a99cc6bdaaa440b09/1.pack
  12. BIN
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/angular-webpack/2b4a41390572dfa6c1136b7a99cc6bdaaa440b09/2.pack
  13. BIN
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/angular-webpack/2b4a41390572dfa6c1136b7a99cc6bdaaa440b09/index.pack
  14. BIN
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/angular-webpack/2b4a41390572dfa6c1136b7a99cc6bdaaa440b09/index.pack.old
  15. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/0393756699d483a1ce58242ee357ff15.json
  16. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/29b273341c529a73c08b918e6c1d41e7.json
  17. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/2caeb2b0da817c8aba79e61928ee4717.json
  18. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/3df5665e949555641726c76d47832fee.json
  19. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/3f2d13e4eee8e0b3949f177c8bd3a5a0.json
  20. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/72096d2b3cdc20a76aecfd2f27a7f316.json
  21. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/7a778709de42da313499d687824b92c9.json
  22. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/7b1b377d83e76af1f536a6570c68ca32.json
  23. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/80df34367ad55820ef07c04f236bf8ed.json
  24. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/82df0641e11ffa10d1163cc1ab02b15f.json
  25. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/89b149f3914754b96b6b57a15d593d92.json
  26. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/8b893d24db0a4904a7f41e562950c5fc.json
  27. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/9bf1c925b6aeffebb59f725e01be2c6a.json
  28. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/a7aa298a4ffdb00a979a29ce7df63520.json
  29. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/a8641639695418d410f27bb96b29d617.json
  30. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/bc43427a4acec4ebbdf1cd94d6c33e71.json
  31. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/c91d8f958e6aacdcbe67ec2473d895d6.json
  32. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/ce783b0c27914c1fa67690eea5da77c7.json
  33. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/d37f0800a558d4ab804741ecfb4bfc06.json
  34. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/f513ce898f8860a9d4e9168765a6786b.json
  35. 1
      mongodb-angular-expressjs-nodejs/frontend/.angular/cache/13.2.6/babel-webpack/fac40ea59825cc86881240f1205fadcf.json
  36. 31
      mongodb-angular-expressjs-nodejs/frontend/Dockerfile
  37. 27
      mongodb-angular-expressjs-nodejs/frontend/README.md
  38. 106
      mongodb-angular-expressjs-nodejs/frontend/angular.json
  39. 44
      mongodb-angular-expressjs-nodejs/frontend/karma.conf.js
  40. BIN
      mongodb-angular-expressjs-nodejs/frontend/output.png
  41. 10371
      mongodb-angular-expressjs-nodejs/frontend/package-lock.json
  42. 39
      mongodb-angular-expressjs-nodejs/frontend/package.json
  43. 10
      mongodb-angular-expressjs-nodejs/frontend/src/app/app-routing.module.ts
  44. 0
      mongodb-angular-expressjs-nodejs/frontend/src/app/app.component.css
  45. 501
      mongodb-angular-expressjs-nodejs/frontend/src/app/app.component.html
  46. 35
      mongodb-angular-expressjs-nodejs/frontend/src/app/app.component.spec.ts
  47. 10
      mongodb-angular-expressjs-nodejs/frontend/src/app/app.component.ts
  48. 18
      mongodb-angular-expressjs-nodejs/frontend/src/app/app.module.ts
  49. 0
      mongodb-angular-expressjs-nodejs/frontend/src/assets/.gitkeep
  50. 3
      mongodb-angular-expressjs-nodejs/frontend/src/environments/environment.prod.ts
  51. 16
      mongodb-angular-expressjs-nodejs/frontend/src/environments/environment.ts
  52. BIN
      mongodb-angular-expressjs-nodejs/frontend/src/favicon.ico
  53. 13
      mongodb-angular-expressjs-nodejs/frontend/src/index.html
  54. 12
      mongodb-angular-expressjs-nodejs/frontend/src/main.ts
  55. 53
      mongodb-angular-expressjs-nodejs/frontend/src/polyfills.ts
  56. 1
      mongodb-angular-expressjs-nodejs/frontend/src/styles.css
  57. 26
      mongodb-angular-expressjs-nodejs/frontend/src/test.ts
  58. 15
      mongodb-angular-expressjs-nodejs/frontend/tsconfig.app.json
  59. 32
      mongodb-angular-expressjs-nodejs/frontend/tsconfig.json
  60. 18
      mongodb-angular-expressjs-nodejs/frontend/tsconfig.spec.json
  61. 3
      mongodb-angular-expressjs-nodejs/nginx/Dockerfile
  62. 11
      mongodb-angular-expressjs-nodejs/nginx/nginx.conf

@ -0,0 +1,160 @@
## Compose sample application
## Node.js application with Angular and Nginx proxy and Mongodb database
Project structure:
```
mongodb-angular-expressjs-nodejs/
├── backend
│ ├── db
│ │ └── mongodb.js
│ ├── Dockerfile
│ ├── package.json
│ ├── package-lock.json
│ └── server.js
├── compose.yaml
├── frontend
│ ├── angular.json
│ ├── Dockerfile
│ ├── karma.conf.js
│ ├── node_modules
│ ├── output.png
│ ├── package.json
│ ├── package-lock.json
│ ├── README.md
│ ├── src
│ │ ├── app
│ │ │ ├── app.component.css
│ │ │ ├── app.component.html
│ │ │ ├── app.component.spec.ts
│ │ │ ├── app.component.ts
│ │ │ ├── app.module.ts
│ │ │ └── app-routing.module.ts
│ │ ├── assets
│ │ ├── environments
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── polyfills.ts
│ │ ├── styles.css
│ │ └── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
├── nginx
│ ├── Dockerfile
│ └── nginx.conf
└── README.md
9 directories, 33 files
```
[_compose.yaml_](compose.yaml)
```
services:
backend:
restart: on-failure
build: ./backend
volumes:
- ./backend:/usr/src/app
hostname: backend
container_name: backend
mongo:
restart: on-failure
image: mongo
ports:
- '27017:27017'
volumes:
- /data/db
hostname: mongo
container_name: mongo
nginx:
build: ./nginx
ports:
- '80:80'
depends_on:
- backend
- mongo
hostname: nginx
container_name: nginx
frontend:
build:
context: frontend
target: builder
ports:
- 4200:4200
volumes:
- ./frontend:/project
- /project/node_modules
hostname: frontend
container_name: frontend
```
The compose file defines an application with tree services `nginx`, `front` and `backend`.
When deploying the application, docker compose maps port 4200 of the nginx service container to port 4200 of the host as specified in the file.
also you can access to angular app on port 4200
and the mongoDB on port 27017
## Deploy with docker compose
```shell
docker compose up -d
[+] Running 4/0
⠿ Container backend Created 0.0s
⠿ Container frontend Created 0.0s
⠿ Container mongo Created 0.0s
⠿ Container nginx Created
```
## Expected result
Listing containers must show three containers running and the port mapping as below:
```
docker-compose ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f7e46df7806f mongodb-angular-expressjs-nodejs-nginx "/docker-entrypoint.…" 5 minutes ago Up 16 seconds 0.0.0.0:80->80/tcp nginx
7cd374f14cba mongodb-angular-expressjs-nodejs-backend "docker-entrypoint.s…" 5 minutes ago Up 17 seconds 5000/tcp backend
526c12817555 mongodb-angular-expressjs-nodejs-frontend "docker-entrypoint.s…" 5 minutes ago Up 17 seconds 0.0.0.0:4200->4200/tcp frontend
1923a93dae8d mongo "docker-entrypoint.s…" 5 minutes ago Up 17 seconds 0.0.0.0:27017->27017/tcp
```
## Testing the app
1. After the application starts, navigate to
`http://localhost:4200`
2. Check the mongoDB connection with mongodb compass or mongo shell
```
mongosh "mongodb://localhost:27017"
```
3. Check the backend connection with postman or curl
```
curl http://localhost
```
## Stop and remove the containers
```
$ docker compose down
```

@ -0,0 +1 @@
MONGODB_URI=mongodb://mongo:27017

@ -0,0 +1,13 @@
FROM node:19-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
EXPOSE 5000
COPY . .
CMD ["npm","start"]

@ -0,0 +1,29 @@
import { MongoClient, ServerApiVersion } from "mongodb";
import dotenv from "dotenv";
dotenv.config();
// Create a MongoClient with a MongoClientOptions object to set the Stable API version
const client = new MongoClient(
process.env.MONGODB_URI || "mongodb://mongo:27017",
{
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
},
}
);
try {
// Connect the client to the server (optional starting in v4.7)
await client.connect();
// Send a ping to confirm a successful connection
await client.db("admin").command({ ping: 1 });
console.log("Pinged your deployment. You successfully connected to MongoDB!");
} finally {
// Ensures that the client will close when you finish/error
await client.close();
}
export default client.connect();

File diff suppressed because it is too large Load Diff

@ -0,0 +1,19 @@
{
"name": "backend",
"version": "1.0.0",
"description": "Running Node.js and Express.js on Docker",
"main": "server.js",
"type": "module",
"scripts": {
"start": "nodemon server.js"
},
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"mongodb": "^5.1.0",
"nodemon": "^2.0.22"
},
"author": "",
"license": "MIT"
}

@ -0,0 +1,14 @@
import express from "express";
import client from "./db/mongodb.js";
const app = express();
import cors from "cors";
app.use(cors("http://localhost:4200"));
app.get("/", function (req, res) {
res.status(200).json({ message: "Hello World" });
});
app.listen(5000, function () {
console.log("Web application is listening on port 5000");
});

@ -0,0 +1,41 @@
services:
backend:
restart: on-failure
build: ./backend
volumes:
- ./backend:/usr/src/app
hostname: backend
container_name: backend
mongo:
restart: on-failure
image: mongo
ports:
- '27017:27017'
volumes:
- /data/db
hostname: mongo
container_name: mongo
nginx:
build: ./nginx
ports:
- '80:80'
depends_on:
- backend
- mongo
hostname: nginx
container_name: nginx
frontend:
build:
context: frontend
target: builder
ports:
- 4200:4200
volumes:
- ./frontend:/project
- /project/node_modules
hostname: frontend
container_name: frontend

@ -0,0 +1 @@
{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { sample } from './sample';\nimport { interval } from '../observable/interval';\nexport function sampleTime(period, scheduler = asyncScheduler) {\n return sample(interval(period, scheduler));\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/sampleTime.js"],"names":["asyncScheduler","sample","interval","sampleTime","period","scheduler"],"mappings":"AAAA,SAASA,cAAT,QAA+B,oBAA/B;AACA,SAASC,MAAT,QAAuB,UAAvB;AACA,SAASC,QAAT,QAAyB,wBAAzB;AACA,OAAO,SAASC,UAAT,CAAoBC,MAApB,EAA4BC,SAAS,GAAGL,cAAxC,EAAwD;AAC3D,SAAOC,MAAM,CAACC,QAAQ,CAACE,MAAD,EAASC,SAAT,CAAT,CAAb;AACH","sourcesContent":["import { asyncScheduler } from '../scheduler/async';\nimport { sample } from './sample';\nimport { interval } from '../observable/interval';\nexport function sampleTime(period, scheduler = asyncScheduler) {\n return sample(interval(period, scheduler));\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { Observable } from '../Observable';\nimport { executeSchedule } from '../util/executeSchedule';\nexport function scheduleAsyncIterable(input, scheduler) {\n if (!input) {\n throw new Error('Iterable cannot be null');\n }\n\n return new Observable(subscriber => {\n executeSchedule(subscriber, scheduler, () => {\n const iterator = input[Symbol.asyncIterator]();\n executeSchedule(subscriber, scheduler, () => {\n iterator.next().then(result => {\n if (result.done) {\n subscriber.complete();\n } else {\n subscriber.next(result.value);\n }\n });\n }, 0, true);\n });\n });\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/scheduled/scheduleAsyncIterable.js"],"names":["Observable","executeSchedule","scheduleAsyncIterable","input","scheduler","Error","subscriber","iterator","Symbol","asyncIterator","next","then","result","done","complete","value"],"mappings":"AAAA,SAASA,UAAT,QAA2B,eAA3B;AACA,SAASC,eAAT,QAAgC,yBAAhC;AACA,OAAO,SAASC,qBAAT,CAA+BC,KAA/B,EAAsCC,SAAtC,EAAiD;AACpD,MAAI,CAACD,KAAL,EAAY;AACR,UAAM,IAAIE,KAAJ,CAAU,yBAAV,CAAN;AACH;;AACD,SAAO,IAAIL,UAAJ,CAAgBM,UAAD,IAAgB;AAClCL,IAAAA,eAAe,CAACK,UAAD,EAAaF,SAAb,EAAwB,MAAM;AACzC,YAAMG,QAAQ,GAAGJ,KAAK,CAACK,MAAM,CAACC,aAAR,CAAL,EAAjB;AACAR,MAAAA,eAAe,CAACK,UAAD,EAAaF,SAAb,EAAwB,MAAM;AACzCG,QAAAA,QAAQ,CAACG,IAAT,GAAgBC,IAAhB,CAAsBC,MAAD,IAAY;AAC7B,cAAIA,MAAM,CAACC,IAAX,EAAiB;AACbP,YAAAA,UAAU,CAACQ,QAAX;AACH,WAFD,MAGK;AACDR,YAAAA,UAAU,CAACI,IAAX,CAAgBE,MAAM,CAACG,KAAvB;AACH;AACJ,SAPD;AAQH,OATc,EASZ,CATY,EAST,IATS,CAAf;AAUH,KAZc,CAAf;AAaH,GAdM,CAAP;AAeH","sourcesContent":["import { Observable } from '../Observable';\nimport { executeSchedule } from '../util/executeSchedule';\nexport function scheduleAsyncIterable(input, scheduler) {\n if (!input) {\n throw new Error('Iterable cannot be null');\n }\n return new Observable((subscriber) => {\n executeSchedule(subscriber, scheduler, () => {\n const iterator = input[Symbol.asyncIterator]();\n executeSchedule(subscriber, scheduler, () => {\n iterator.next().then((result) => {\n if (result.done) {\n subscriber.complete();\n }\n else {\n subscriber.next(result.value);\n }\n });\n }, 0, true);\n });\n });\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { async } from '../scheduler/async';\nimport { scan } from './scan';\nimport { defer } from '../observable/defer';\nimport { map } from './map';\nexport function timeInterval(scheduler = async) {\n return source => defer(() => {\n return source.pipe(scan(({\n current\n }, value) => ({\n value,\n current: scheduler.now(),\n last: current\n }), {\n current: scheduler.now(),\n value: undefined,\n last: undefined\n }), map(({\n current,\n last,\n value\n }) => new TimeInterval(value, current - last)));\n });\n}\nexport class TimeInterval {\n constructor(value, interval) {\n this.value = value;\n this.interval = interval;\n }\n\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/timeInterval.js"],"names":["async","scan","defer","map","timeInterval","scheduler","source","pipe","current","value","now","last","undefined","TimeInterval","constructor","interval"],"mappings":"AAAA,SAASA,KAAT,QAAsB,oBAAtB;AACA,SAASC,IAAT,QAAqB,QAArB;AACA,SAASC,KAAT,QAAsB,qBAAtB;AACA,SAASC,GAAT,QAAoB,OAApB;AACA,OAAO,SAASC,YAAT,CAAsBC,SAAS,GAAGL,KAAlC,EAAyC;AAC5C,SAAQM,MAAD,IAAYJ,KAAK,CAAC,MAAM;AAC3B,WAAOI,MAAM,CAACC,IAAP,CAAYN,IAAI,CAAC,CAAC;AAAEO,MAAAA;AAAF,KAAD,EAAcC,KAAd,MAAyB;AAAEA,MAAAA,KAAF;AAASD,MAAAA,OAAO,EAAEH,SAAS,CAACK,GAAV,EAAlB;AAAmCC,MAAAA,IAAI,EAAEH;AAAzC,KAAzB,CAAD,EAA+E;AAClGA,MAAAA,OAAO,EAAEH,SAAS,CAACK,GAAV,EADyF;AAElGD,MAAAA,KAAK,EAAEG,SAF2F;AAGlGD,MAAAA,IAAI,EAAEC;AAH4F,KAA/E,CAAhB,EAIHT,GAAG,CAAC,CAAC;AAAEK,MAAAA,OAAF;AAAWG,MAAAA,IAAX;AAAiBF,MAAAA;AAAjB,KAAD,KAA8B,IAAII,YAAJ,CAAiBJ,KAAjB,EAAwBD,OAAO,GAAGG,IAAlC,CAA/B,CAJA,CAAP;AAKH,GANuB,CAAxB;AAOH;AACD,OAAO,MAAME,YAAN,CAAmB;AACtBC,EAAAA,WAAW,CAACL,KAAD,EAAQM,QAAR,EAAkB;AACzB,SAAKN,KAAL,GAAaA,KAAb;AACA,SAAKM,QAAL,GAAgBA,QAAhB;AACH;;AAJqB","sourcesContent":["import { async } from '../scheduler/async';\nimport { scan } from './scan';\nimport { defer } from '../observable/defer';\nimport { map } from './map';\nexport function timeInterval(scheduler = async) {\n return (source) => defer(() => {\n return source.pipe(scan(({ current }, value) => ({ value, current: scheduler.now(), last: current }), {\n current: scheduler.now(),\n value: undefined,\n last: undefined,\n }), map(({ current, last, value }) => new TimeInterval(value, current - last)));\n });\n}\nexport class TimeInterval {\n constructor(value, interval) {\n this.value = value;\n this.interval = interval;\n }\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { defaultThrottleConfig, throttle } from './throttle';\nimport { timer } from '../observable/timer';\nexport function throttleTime(duration, scheduler = asyncScheduler, config = defaultThrottleConfig) {\n const duration$ = timer(duration, scheduler);\n return throttle(() => duration$, config);\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/throttleTime.js"],"names":["asyncScheduler","defaultThrottleConfig","throttle","timer","throttleTime","duration","scheduler","config","duration$"],"mappings":"AAAA,SAASA,cAAT,QAA+B,oBAA/B;AACA,SAASC,qBAAT,EAAgCC,QAAhC,QAAgD,YAAhD;AACA,SAASC,KAAT,QAAsB,qBAAtB;AACA,OAAO,SAASC,YAAT,CAAsBC,QAAtB,EAAgCC,SAAS,GAAGN,cAA5C,EAA4DO,MAAM,GAAGN,qBAArE,EAA4F;AAC/F,QAAMO,SAAS,GAAGL,KAAK,CAACE,QAAD,EAAWC,SAAX,CAAvB;AACA,SAAOJ,QAAQ,CAAC,MAAMM,SAAP,EAAkBD,MAAlB,CAAf;AACH","sourcesContent":["import { asyncScheduler } from '../scheduler/async';\nimport { defaultThrottleConfig, throttle } from './throttle';\nimport { timer } from '../observable/timer';\nexport function throttleTime(duration, scheduler = asyncScheduler, config = defaultThrottleConfig) {\n const duration$ = timer(duration, scheduler);\n return throttle(() => duration$, config);\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function debounceTime(dueTime, scheduler = asyncScheduler) {\n return operate((source, subscriber) => {\n let activeTask = null;\n let lastValue = null;\n let lastTime = null;\n\n const emit = () => {\n if (activeTask) {\n activeTask.unsubscribe();\n activeTask = null;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n\n function emitWhenIdle() {\n const targetTime = lastTime + dueTime;\n const now = scheduler.now();\n\n if (now < targetTime) {\n activeTask = this.schedule(undefined, targetTime - now);\n subscriber.add(activeTask);\n return;\n }\n\n emit();\n }\n\n source.subscribe(new OperatorSubscriber(subscriber, value => {\n lastValue = value;\n lastTime = scheduler.now();\n\n if (!activeTask) {\n activeTask = scheduler.schedule(emitWhenIdle, dueTime);\n subscriber.add(activeTask);\n }\n }, () => {\n emit();\n subscriber.complete();\n }, undefined, () => {\n lastValue = activeTask = null;\n }));\n });\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/debounceTime.js"],"names":["asyncScheduler","operate","OperatorSubscriber","debounceTime","dueTime","scheduler","source","subscriber","activeTask","lastValue","lastTime","emit","unsubscribe","value","next","emitWhenIdle","targetTime","now","schedule","undefined","add","subscribe","complete"],"mappings":"AAAA,SAASA,cAAT,QAA+B,oBAA/B;AACA,SAASC,OAAT,QAAwB,cAAxB;AACA,SAASC,kBAAT,QAAmC,sBAAnC;AACA,OAAO,SAASC,YAAT,CAAsBC,OAAtB,EAA+BC,SAAS,GAAGL,cAA3C,EAA2D;AAC9D,SAAOC,OAAO,CAAC,CAACK,MAAD,EAASC,UAAT,KAAwB;AACnC,QAAIC,UAAU,GAAG,IAAjB;AACA,QAAIC,SAAS,GAAG,IAAhB;AACA,QAAIC,QAAQ,GAAG,IAAf;;AACA,UAAMC,IAAI,GAAG,MAAM;AACf,UAAIH,UAAJ,EAAgB;AACZA,QAAAA,UAAU,CAACI,WAAX;AACAJ,QAAAA,UAAU,GAAG,IAAb;AACA,cAAMK,KAAK,GAAGJ,SAAd;AACAA,QAAAA,SAAS,GAAG,IAAZ;AACAF,QAAAA,UAAU,CAACO,IAAX,CAAgBD,KAAhB;AACH;AACJ,KARD;;AASA,aAASE,YAAT,GAAwB;AACpB,YAAMC,UAAU,GAAGN,QAAQ,GAAGN,OAA9B;AACA,YAAMa,GAAG,GAAGZ,SAAS,CAACY,GAAV,EAAZ;;AACA,UAAIA,GAAG,GAAGD,UAAV,EAAsB;AAClBR,QAAAA,UAAU,GAAG,KAAKU,QAAL,CAAcC,SAAd,EAAyBH,UAAU,GAAGC,GAAtC,CAAb;AACAV,QAAAA,UAAU,CAACa,GAAX,CAAeZ,UAAf;AACA;AACH;;AACDG,MAAAA,IAAI;AACP;;AACDL,IAAAA,MAAM,CAACe,SAAP,CAAiB,IAAInB,kBAAJ,CAAuBK,UAAvB,EAAoCM,KAAD,IAAW;AAC3DJ,MAAAA,SAAS,GAAGI,KAAZ;AACAH,MAAAA,QAAQ,GAAGL,SAAS,CAACY,GAAV,EAAX;;AACA,UAAI,CAACT,UAAL,EAAiB;AACbA,QAAAA,UAAU,GAAGH,SAAS,CAACa,QAAV,CAAmBH,YAAnB,EAAiCX,OAAjC,CAAb;AACAG,QAAAA,UAAU,CAACa,GAAX,CAAeZ,UAAf;AACH;AACJ,KAPgB,EAOd,MAAM;AACLG,MAAAA,IAAI;AACJJ,MAAAA,UAAU,CAACe,QAAX;AACH,KAVgB,EAUdH,SAVc,EAUH,MAAM;AAChBV,MAAAA,SAAS,GAAGD,UAAU,GAAG,IAAzB;AACH,KAZgB,CAAjB;AAaH,GApCa,CAAd;AAqCH","sourcesContent":["import { asyncScheduler } from '../scheduler/async';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function debounceTime(dueTime, scheduler = asyncScheduler) {\n return operate((source, subscriber) => {\n let activeTask = null;\n let lastValue = null;\n let lastTime = null;\n const emit = () => {\n if (activeTask) {\n activeTask.unsubscribe();\n activeTask = null;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n function emitWhenIdle() {\n const targetTime = lastTime + dueTime;\n const now = scheduler.now();\n if (now < targetTime) {\n activeTask = this.schedule(undefined, targetTime - now);\n subscriber.add(activeTask);\n return;\n }\n emit();\n }\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n lastValue = value;\n lastTime = scheduler.now();\n if (!activeTask) {\n activeTask = scheduler.schedule(emitWhenIdle, dueTime);\n subscriber.add(activeTask);\n }\n }, () => {\n emit();\n subscriber.complete();\n }, undefined, () => {\n lastValue = activeTask = null;\n }));\n });\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { Observable } from '../Observable';\nimport { async as asyncScheduler } from '../scheduler/async';\nimport { isScheduler } from '../util/isScheduler';\nimport { isValidDate } from '../util/isDate';\nexport function timer(dueTime = 0, intervalOrScheduler, scheduler = asyncScheduler) {\n let intervalDuration = -1;\n\n if (intervalOrScheduler != null) {\n if (isScheduler(intervalOrScheduler)) {\n scheduler = intervalOrScheduler;\n } else {\n intervalDuration = intervalOrScheduler;\n }\n }\n\n return new Observable(subscriber => {\n let due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;\n\n if (due < 0) {\n due = 0;\n }\n\n let n = 0;\n return scheduler.schedule(function () {\n if (!subscriber.closed) {\n subscriber.next(n++);\n\n if (0 <= intervalDuration) {\n this.schedule(undefined, intervalDuration);\n } else {\n subscriber.complete();\n }\n }\n }, due);\n });\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/observable/timer.js"],"names":["Observable","async","asyncScheduler","isScheduler","isValidDate","timer","dueTime","intervalOrScheduler","scheduler","intervalDuration","subscriber","due","now","n","schedule","closed","next","undefined","complete"],"mappings":"AAAA,SAASA,UAAT,QAA2B,eAA3B;AACA,SAASC,KAAK,IAAIC,cAAlB,QAAwC,oBAAxC;AACA,SAASC,WAAT,QAA4B,qBAA5B;AACA,SAASC,WAAT,QAA4B,gBAA5B;AACA,OAAO,SAASC,KAAT,CAAeC,OAAO,GAAG,CAAzB,EAA4BC,mBAA5B,EAAiDC,SAAS,GAAGN,cAA7D,EAA6E;AAChF,MAAIO,gBAAgB,GAAG,CAAC,CAAxB;;AACA,MAAIF,mBAAmB,IAAI,IAA3B,EAAiC;AAC7B,QAAIJ,WAAW,CAACI,mBAAD,CAAf,EAAsC;AAClCC,MAAAA,SAAS,GAAGD,mBAAZ;AACH,KAFD,MAGK;AACDE,MAAAA,gBAAgB,GAAGF,mBAAnB;AACH;AACJ;;AACD,SAAO,IAAIP,UAAJ,CAAgBU,UAAD,IAAgB;AAClC,QAAIC,GAAG,GAAGP,WAAW,CAACE,OAAD,CAAX,GAAuB,CAACA,OAAD,GAAWE,SAAS,CAACI,GAAV,EAAlC,GAAoDN,OAA9D;;AACA,QAAIK,GAAG,GAAG,CAAV,EAAa;AACTA,MAAAA,GAAG,GAAG,CAAN;AACH;;AACD,QAAIE,CAAC,GAAG,CAAR;AACA,WAAOL,SAAS,CAACM,QAAV,CAAmB,YAAY;AAClC,UAAI,CAACJ,UAAU,CAACK,MAAhB,EAAwB;AACpBL,QAAAA,UAAU,CAACM,IAAX,CAAgBH,CAAC,EAAjB;;AACA,YAAI,KAAKJ,gBAAT,EAA2B;AACvB,eAAKK,QAAL,CAAcG,SAAd,EAAyBR,gBAAzB;AACH,SAFD,MAGK;AACDC,UAAAA,UAAU,CAACQ,QAAX;AACH;AACJ;AACJ,KAVM,EAUJP,GAVI,CAAP;AAWH,GAjBM,CAAP;AAkBH","sourcesContent":["import { Observable } from '../Observable';\nimport { async as asyncScheduler } from '../scheduler/async';\nimport { isScheduler } from '../util/isScheduler';\nimport { isValidDate } from '../util/isDate';\nexport function timer(dueTime = 0, intervalOrScheduler, scheduler = asyncScheduler) {\n let intervalDuration = -1;\n if (intervalOrScheduler != null) {\n if (isScheduler(intervalOrScheduler)) {\n scheduler = intervalOrScheduler;\n }\n else {\n intervalDuration = intervalOrScheduler;\n }\n }\n return new Observable((subscriber) => {\n let due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;\n if (due < 0) {\n due = 0;\n }\n let n = 0;\n return scheduler.schedule(function () {\n if (!subscriber.closed) {\n subscriber.next(n++);\n if (0 <= intervalDuration) {\n this.schedule(undefined, intervalDuration);\n }\n else {\n subscriber.complete();\n }\n }\n }, due);\n });\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { async } from '../scheduler/async';\nimport { isValidDate } from '../util/isDate';\nimport { timeout } from './timeout';\nexport function timeoutWith(due, withObservable, scheduler) {\n let first;\n let each;\n\n let _with;\n\n scheduler = scheduler !== null && scheduler !== void 0 ? scheduler : async;\n\n if (isValidDate(due)) {\n first = due;\n } else if (typeof due === 'number') {\n each = due;\n }\n\n if (withObservable) {\n _with = () => withObservable;\n } else {\n throw new TypeError('No observable provided to switch to');\n }\n\n if (first == null && each == null) {\n throw new TypeError('No timeout provided.');\n }\n\n return timeout({\n first,\n each,\n scheduler,\n with: _with\n });\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/timeoutWith.js"],"names":["async","isValidDate","timeout","timeoutWith","due","withObservable","scheduler","first","each","_with","TypeError","with"],"mappings":"AAAA,SAASA,KAAT,QAAsB,oBAAtB;AACA,SAASC,WAAT,QAA4B,gBAA5B;AACA,SAASC,OAAT,QAAwB,WAAxB;AACA,OAAO,SAASC,WAAT,CAAqBC,GAArB,EAA0BC,cAA1B,EAA0CC,SAA1C,EAAqD;AACxD,MAAIC,KAAJ;AACA,MAAIC,IAAJ;;AACA,MAAIC,KAAJ;;AACAH,EAAAA,SAAS,GAAGA,SAAS,KAAK,IAAd,IAAsBA,SAAS,KAAK,KAAK,CAAzC,GAA6CA,SAA7C,GAAyDN,KAArE;;AACA,MAAIC,WAAW,CAACG,GAAD,CAAf,EAAsB;AAClBG,IAAAA,KAAK,GAAGH,GAAR;AACH,GAFD,MAGK,IAAI,OAAOA,GAAP,KAAe,QAAnB,EAA6B;AAC9BI,IAAAA,IAAI,GAAGJ,GAAP;AACH;;AACD,MAAIC,cAAJ,EAAoB;AAChBI,IAAAA,KAAK,GAAG,MAAMJ,cAAd;AACH,GAFD,MAGK;AACD,UAAM,IAAIK,SAAJ,CAAc,qCAAd,CAAN;AACH;;AACD,MAAIH,KAAK,IAAI,IAAT,IAAiBC,IAAI,IAAI,IAA7B,EAAmC;AAC/B,UAAM,IAAIE,SAAJ,CAAc,sBAAd,CAAN;AACH;;AACD,SAAOR,OAAO,CAAC;AACXK,IAAAA,KADW;AAEXC,IAAAA,IAFW;AAGXF,IAAAA,SAHW;AAIXK,IAAAA,IAAI,EAAEF;AAJK,GAAD,CAAd;AAMH","sourcesContent":["import { async } from '../scheduler/async';\nimport { isValidDate } from '../util/isDate';\nimport { timeout } from './timeout';\nexport function timeoutWith(due, withObservable, scheduler) {\n let first;\n let each;\n let _with;\n scheduler = scheduler !== null && scheduler !== void 0 ? scheduler : async;\n if (isValidDate(due)) {\n first = due;\n }\n else if (typeof due === 'number') {\n each = due;\n }\n if (withObservable) {\n _with = () => withObservable;\n }\n else {\n throw new TypeError('No observable provided to switch to');\n }\n if (first == null && each == null) {\n throw new TypeError('No timeout provided.');\n }\n return timeout({\n first,\n each,\n scheduler,\n with: _with,\n });\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { async } from '../scheduler/async';\nimport { audit } from './audit';\nimport { timer } from '../observable/timer';\nexport function auditTime(duration, scheduler = async) {\n return audit(() => timer(duration, scheduler));\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/auditTime.js"],"names":["async","audit","timer","auditTime","duration","scheduler"],"mappings":"AAAA,SAASA,KAAT,QAAsB,oBAAtB;AACA,SAASC,KAAT,QAAsB,SAAtB;AACA,SAASC,KAAT,QAAsB,qBAAtB;AACA,OAAO,SAASC,SAAT,CAAmBC,QAAnB,EAA6BC,SAAS,GAAGL,KAAzC,EAAgD;AACnD,SAAOC,KAAK,CAAC,MAAMC,KAAK,CAACE,QAAD,EAAWC,SAAX,CAAZ,CAAZ;AACH","sourcesContent":["import { async } from '../scheduler/async';\nimport { audit } from './audit';\nimport { timer } from '../observable/timer';\nexport function auditTime(duration, scheduler = async) {\n return audit(() => timer(duration, scheduler));\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { isFunction } from './isFunction';\nexport function isAsyncIterable(obj) {\n return Symbol.asyncIterator && isFunction(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/util/isAsyncIterable.js"],"names":["isFunction","isAsyncIterable","obj","Symbol","asyncIterator"],"mappings":"AAAA,SAASA,UAAT,QAA2B,cAA3B;AACA,OAAO,SAASC,eAAT,CAAyBC,GAAzB,EAA8B;AACjC,SAAOC,MAAM,CAACC,aAAP,IAAwBJ,UAAU,CAACE,GAAG,KAAK,IAAR,IAAgBA,GAAG,KAAK,KAAK,CAA7B,GAAiC,KAAK,CAAtC,GAA0CA,GAAG,CAACC,MAAM,CAACC,aAAR,CAA9C,CAAzC;AACH","sourcesContent":["import { isFunction } from './isFunction';\nexport function isAsyncIterable(obj) {\n return Symbol.asyncIterator && isFunction(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\nexport const async = asyncScheduler;","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/scheduler/async.js"],"names":["AsyncAction","AsyncScheduler","asyncScheduler","async"],"mappings":"AAAA,SAASA,WAAT,QAA4B,eAA5B;AACA,SAASC,cAAT,QAA+B,kBAA/B;AACA,OAAO,MAAMC,cAAc,GAAG,IAAID,cAAJ,CAAmBD,WAAnB,CAAvB;AACP,OAAO,MAAMG,KAAK,GAAGD,cAAd","sourcesContent":["import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\nexport const async = asyncScheduler;\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { __asyncGenerator, __await } from \"tslib\";\nimport { isFunction } from './isFunction';\nexport function readableStreamLikeToAsyncGenerator(readableStream) {\n return __asyncGenerator(this, arguments, function* readableStreamLikeToAsyncGenerator_1() {\n const reader = readableStream.getReader();\n\n try {\n while (true) {\n const {\n value,\n done\n } = yield __await(reader.read());\n\n if (done) {\n return yield __await(void 0);\n }\n\n yield yield __await(value);\n }\n } finally {\n reader.releaseLock();\n }\n });\n}\nexport function isReadableStreamLike(obj) {\n return isFunction(obj === null || obj === void 0 ? void 0 : obj.getReader);\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/util/isReadableStreamLike.js"],"names":["__asyncGenerator","__await","isFunction","readableStreamLikeToAsyncGenerator","readableStream","arguments","readableStreamLikeToAsyncGenerator_1","reader","getReader","value","done","read","releaseLock","isReadableStreamLike","obj"],"mappings":"AAAA,SAASA,gBAAT,EAA2BC,OAA3B,QAA0C,OAA1C;AACA,SAASC,UAAT,QAA2B,cAA3B;AACA,OAAO,SAASC,kCAAT,CAA4CC,cAA5C,EAA4D;AAC/D,SAAOJ,gBAAgB,CAAC,IAAD,EAAOK,SAAP,EAAkB,UAAUC,oCAAV,GAAiD;AACtF,UAAMC,MAAM,GAAGH,cAAc,CAACI,SAAf,EAAf;;AACA,QAAI;AACA,aAAO,IAAP,EAAa;AACT,cAAM;AAAEC,UAAAA,KAAF;AAASC,UAAAA;AAAT,YAAkB,MAAMT,OAAO,CAACM,MAAM,CAACI,IAAP,EAAD,CAArC;;AACA,YAAID,IAAJ,EAAU;AACN,iBAAO,MAAMT,OAAO,CAAC,KAAK,CAAN,CAApB;AACH;;AACD,cAAM,MAAMA,OAAO,CAACQ,KAAD,CAAnB;AACH;AACJ,KARD,SASQ;AACJF,MAAAA,MAAM,CAACK,WAAP;AACH;AACJ,GAdsB,CAAvB;AAeH;AACD,OAAO,SAASC,oBAAT,CAA8BC,GAA9B,EAAmC;AACtC,SAAOZ,UAAU,CAACY,GAAG,KAAK,IAAR,IAAgBA,GAAG,KAAK,KAAK,CAA7B,GAAiC,KAAK,CAAtC,GAA0CA,GAAG,CAACN,SAA/C,CAAjB;AACH","sourcesContent":["import { __asyncGenerator, __await } from \"tslib\";\nimport { isFunction } from './isFunction';\nexport function readableStreamLikeToAsyncGenerator(readableStream) {\n return __asyncGenerator(this, arguments, function* readableStreamLikeToAsyncGenerator_1() {\n const reader = readableStream.getReader();\n try {\n while (true) {\n const { value, done } = yield __await(reader.read());\n if (done) {\n return yield __await(void 0);\n }\n yield yield __await(value);\n }\n }\n finally {\n reader.releaseLock();\n }\n });\n}\nexport function isReadableStreamLike(obj) {\n return isFunction(obj === null || obj === void 0 ? void 0 : obj.getReader);\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { timer } from './timer';\nexport function interval(period = 0, scheduler = asyncScheduler) {\n if (period < 0) {\n period = 0;\n }\n\n return timer(period, period, scheduler);\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/observable/interval.js"],"names":["asyncScheduler","timer","interval","period","scheduler"],"mappings":"AAAA,SAASA,cAAT,QAA+B,oBAA/B;AACA,SAASC,KAAT,QAAsB,SAAtB;AACA,OAAO,SAASC,QAAT,CAAkBC,MAAM,GAAG,CAA3B,EAA8BC,SAAS,GAAGJ,cAA1C,EAA0D;AAC7D,MAAIG,MAAM,GAAG,CAAb,EAAgB;AACZA,IAAAA,MAAM,GAAG,CAAT;AACH;;AACD,SAAOF,KAAK,CAACE,MAAD,EAASA,MAAT,EAAiBC,SAAjB,CAAZ;AACH","sourcesContent":["import { asyncScheduler } from '../scheduler/async';\nimport { timer } from './timer';\nexport function interval(period = 0, scheduler = asyncScheduler) {\n if (period < 0) {\n period = 0;\n }\n return timer(period, period, scheduler);\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1 @@
{"ast":null,"code":"import { asyncScheduler } from '../scheduler/async';\nimport { delayWhen } from './delayWhen';\nimport { timer } from '../observable/timer';\nexport function delay(due, scheduler = asyncScheduler) {\n const duration = timer(due, scheduler);\n return delayWhen(() => duration);\n}","map":{"version":3,"sources":["/project/node_modules/rxjs/dist/esm/internal/operators/delay.js"],"names":["asyncScheduler","delayWhen","timer","delay","due","scheduler","duration"],"mappings":"AAAA,SAASA,cAAT,QAA+B,oBAA/B;AACA,SAASC,SAAT,QAA0B,aAA1B;AACA,SAASC,KAAT,QAAsB,qBAAtB;AACA,OAAO,SAASC,KAAT,CAAeC,GAAf,EAAoBC,SAAS,GAAGL,cAAhC,EAAgD;AACnD,QAAMM,QAAQ,GAAGJ,KAAK,CAACE,GAAD,EAAMC,SAAN,CAAtB;AACA,SAAOJ,SAAS,CAAC,MAAMK,QAAP,CAAhB;AACH","sourcesContent":["import { asyncScheduler } from '../scheduler/async';\nimport { delayWhen } from './delayWhen';\nimport { timer } from '../observable/timer';\nexport function delay(due, scheduler = asyncScheduler) {\n const duration = timer(due, scheduler);\n return delayWhen(() => duration);\n}\n"]},"metadata":{},"sourceType":"module"}

@ -0,0 +1,31 @@
# syntax=docker/dockerfile:1.4
FROM --platform=$BUILDPLATFORM node:17.0.1-bullseye-slim as builder
RUN mkdir /project
WORKDIR /project
RUN npm install -g @angular/cli@13
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["ng", "serve", "--host", "0.0.0.0"]
FROM builder as dev-envs
RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends git
EOF
RUN <<EOF
useradd -s /bin/bash -m vscode
groupadd docker
usermod -aG docker vscode
EOF
# install Docker tools (cli, buildx, compose)
COPY --from=gloursdocker/docker / /
CMD ["ng", "serve", "--host", "0.0.0.0"]

@ -0,0 +1,27 @@
# Angular
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 13.0.1.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
## Further help
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.

@ -0,0 +1,106 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angular": {
"projectType": "application",
"schematics": {
"@schematics/angular:application": {
"strict": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/angular",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "angular:build:production"
},
"development": {
"browserTarget": "angular:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "angular:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
}
}
}
},
"defaultProject": "angular"
}

@ -0,0 +1,44 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/angular'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

File diff suppressed because it is too large Load Diff

@ -0,0 +1,39 @@
{
"name": "angular",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "~13.0.0",
"@angular/common": "~13.0.0",
"@angular/compiler": "~13.0.0",
"@angular/core": "~13.0.0",
"@angular/forms": "~13.0.0",
"@angular/platform-browser": "~13.0.0",
"@angular/platform-browser-dynamic": "~13.0.0",
"@angular/router": "~13.0.0",
"rxjs": "~7.4.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^13.2.6",
"@angular/cli": "~13.0.1",
"@angular/compiler-cli": "~13.0.0",
"@types/jasmine": "~3.10.0",
"@types/node": "^12.11.1",
"jasmine-core": "~3.10.0",
"karma": "^6.3.17",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.4.3"
}
}

@ -0,0 +1,10 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

@ -0,0 +1,501 @@
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<style>
:host {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 14px;
color: #333;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 8px 0;
}
p {
margin: 0;
}
.spacer {
flex: 1;
}
.toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 60px;
display: flex;
align-items: center;
background-color: #1976d2;
color: white;
font-weight: 600;
}
.toolbar img {
margin: 0 16px;
}
.toolbar #twitter-logo {
height: 40px;
margin: 0 8px;
}
.toolbar #youtube-logo {
height: 40px;
margin: 0 16px;
}
.toolbar #twitter-logo:hover,
.toolbar #youtube-logo:hover {
opacity: 0.8;
}
.content {
display: flex;
margin: 82px auto 32px;
padding: 0 16px;
max-width: 960px;
flex-direction: column;
align-items: center;
}
svg.material-icons {
height: 24px;
width: auto;
}
svg.material-icons:not(:last-child) {
margin-right: 8px;
}
.card svg.material-icons path {
fill: #888;
}
.card-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 16px;
}
.card {
all: unset;
border-radius: 4px;
border: 1px solid #eee;
background-color: #fafafa;
height: 40px;
width: 200px;
margin: 0 8px 16px;
padding: 16px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
transition: all 0.2s ease-in-out;
line-height: 24px;
}
.card-container .card:not(:last-child) {
margin-right: 0;
}
.card.card-small {
height: 16px;
width: 168px;
}
.card-container .card:not(.highlight-card) {
cursor: pointer;
}
.card-container .card:not(.highlight-card):hover {
transform: translateY(-3px);
box-shadow: 0 4px 17px rgba(0, 0, 0, 0.35);
}
.card-container .card:not(.highlight-card):hover .material-icons path {
fill: rgb(105, 103, 103);
}
.card.highlight-card {
background-color: #1976d2;
color: white;
font-weight: 600;
border: none;
width: auto;
min-width: 30%;
position: relative;
}
.card.card.highlight-card span {
margin-left: 60px;
}
svg#rocket {
width: 80px;
position: absolute;
left: -10px;
top: -24px;
}
svg#rocket-smoke {
height: calc(100vh - 95px);
position: absolute;
top: 10px;
right: 180px;
z-index: -10;
}
a,
a:visited,
a:hover {
color: #1976d2;
text-decoration: none;
}
a:hover {
color: #125699;
}
.terminal {
position: relative;
width: 80%;
max-width: 600px;
border-radius: 6px;
padding-top: 45px;
margin-top: 8px;
overflow: hidden;
background-color: rgb(15, 15, 16);
}
.terminal::before {
content: "\2022 \2022 \2022";
position: absolute;
top: 0;
left: 0;
height: 4px;
background: rgb(58, 58, 58);
color: #c2c3c4;
width: 100%;
font-size: 2rem;
line-height: 0;
padding: 14px 0;
text-indent: 4px;
}
.terminal pre {
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;
color: white;
padding: 0 1rem 1rem;
margin: 0;
}
.circle-link {
height: 40px;
width: 40px;
border-radius: 40px;
margin: 8px;
background-color: white;
border: 1px solid #eeeeee;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
transition: 1s ease-out;
}
.circle-link:hover {
transform: translateY(-0.25rem);
box-shadow: 0px 3px 15px rgba(0, 0, 0, 0.2);
}
footer {
margin-top: 8px;
display: flex;
align-items: center;
line-height: 20px;
}
footer a {
display: flex;
align-items: center;
}
.github-star-badge {
color: #24292e;
display: flex;
align-items: center;
font-size: 12px;
padding: 3px 10px;
border: 1px solid rgba(27,31,35,.2);
border-radius: 3px;
background-image: linear-gradient(-180deg,#fafbfc,#eff3f6 90%);
margin-left: 4px;
font-weight: 600;
}
.github-star-badge:hover {
background-image: linear-gradient(-180deg,#f0f3f6,#e6ebf1 90%);
border-color: rgba(27,31,35,.35);
background-position: -.5em;
}
.github-star-badge .material-icons {
height: 16px;
width: 16px;
margin-right: 4px;
}
svg#clouds {
position: fixed;
bottom: -160px;
left: -230px;
z-index: -10;
width: 1920px;
}
/* Responsive Styles */
@media screen and (max-width: 767px) {
.card-container > *:not(.circle-link) ,
.terminal {
width: 100%;
}
.card:not(.highlight-card) {
height: 16px;
margin: 8px 0;
}
.card.highlight-card span {
margin-left: 72px;
}
svg#rocket-smoke {
right: 120px;
transform: rotate(-5deg);
}
}
@media screen and (max-width: 575px) {
svg#rocket-smoke {
display: none;
visibility: hidden;
}
}
</style>
<!-- Toolbar -->
<div class="toolbar" role="banner">
<img
width="40"
alt="Angular Logo"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="
/>
<span>Welcome</span>
<div class="spacer"></div>
<a aria-label="Angular on twitter" target="_blank" rel="noopener" href="https://twitter.com/angular" title="Twitter">
<svg id="twitter-logo" height="24" data-name="Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<rect width="400" height="400" fill="none"/>
<path d="M153.62,301.59c94.34,0,145.94-78.16,145.94-145.94,0-2.22,0-4.43-.15-6.63A104.36,104.36,0,0,0,325,122.47a102.38,102.38,0,0,1-29.46,8.07,51.47,51.47,0,0,0,22.55-28.37,102.79,102.79,0,0,1-32.57,12.45,51.34,51.34,0,0,0-87.41,46.78A145.62,145.62,0,0,1,92.4,107.81a51.33,51.33,0,0,0,15.88,68.47A50.91,50.91,0,0,1,85,169.86c0,.21,0,.43,0,.65a51.31,51.31,0,0,0,41.15,50.28,51.21,51.21,0,0,1-23.16.88,51.35,51.35,0,0,0,47.92,35.62,102.92,102.92,0,0,1-63.7,22A104.41,104.41,0,0,1,75,278.55a145.21,145.21,0,0,0,78.62,23" fill="#fff"/>
</svg>
</a>
<a aria-label="Angular on YouTube" target="_blank" rel="noopener" href="https://youtube.com/angular" title="YouTube">
<svg id="youtube-logo" height="24" width="24" data-name="Logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#fff">
<path d="M0 0h24v24H0V0z" fill="none"/>
<path d="M21.58 7.19c-.23-.86-.91-1.54-1.77-1.77C18.25 5 12 5 12 5s-6.25 0-7.81.42c-.86.23-1.54.91-1.77 1.77C2 8.75 2 12 2 12s0 3.25.42 4.81c.23.86.91 1.54 1.77 1.77C5.75 19 12 19 12 19s6.25 0 7.81-.42c.86-.23 1.54-.91 1.77-1.77C22 15.25 22 12 22 12s0-3.25-.42-4.81zM10 15V9l5.2 3-5.2 3z"/>
</svg>
</a>
</div>
<div class="content" role="main">
<!-- Highlight Card -->
<div class="card highlight-card card-small">
<svg id="rocket" xmlns="http://www.w3.org/2000/svg" width="101.678" height="101.678" viewBox="0 0 101.678 101.678">
<title>Rocket Ship</title>
<g id="Group_83" data-name="Group 83" transform="translate(-141 -696)">
<circle id="Ellipse_8" data-name="Ellipse 8" cx="50.839" cy="50.839" r="50.839" transform="translate(141 696)" fill="#dd0031"/>
<g id="Group_47" data-name="Group 47" transform="translate(165.185 720.185)">
<path id="Path_33" data-name="Path 33" d="M3.4,42.615a3.084,3.084,0,0,0,3.553,3.553,21.419,21.419,0,0,0,12.215-6.107L9.511,30.4A21.419,21.419,0,0,0,3.4,42.615Z" transform="translate(0.371 3.363)" fill="#fff"/>
<path id="Path_34" data-name="Path 34" d="M53.3,3.221A3.09,3.09,0,0,0,50.081,0,48.227,48.227,0,0,0,18.322,13.437c-6-1.666-14.991-1.221-18.322,7.218A33.892,33.892,0,0,1,9.439,25.1l-.333.666a3.013,3.013,0,0,0,.555,3.553L23.985,43.641a2.9,2.9,0,0,0,3.553.555l.666-.333A33.892,33.892,0,0,1,32.647,53.3c8.55-3.664,8.884-12.326,7.218-18.322A48.227,48.227,0,0,0,53.3,3.221ZM34.424,9.772a6.439,6.439,0,1,1,9.106,9.106,6.368,6.368,0,0,1-9.106,0A6.467,6.467,0,0,1,34.424,9.772Z" transform="translate(0 0.005)" fill="#fff"/>
</g>
</g>
</svg>
<span>{{ title }} app is running!</span>
<svg id="rocket-smoke" xmlns="http://www.w3.org/2000/svg" width="516.119" height="1083.632" viewBox="0 0 516.119 1083.632">
<title>Rocket Ship Smoke</title>
<path id="Path_40" data-name="Path 40" d="M644.6,141S143.02,215.537,147.049,870.207s342.774,201.755,342.774,201.755S404.659,847.213,388.815,762.2c-27.116-145.51-11.551-384.124,271.9-609.1C671.15,139.365,644.6,141,644.6,141Z" transform="translate(-147.025 -140.939)" fill="#f5f5f5"/>
</svg>
</div>
<!-- Resources -->
<h2>Resources</h2>
<p>Here are some links to help you get started:</p>
<div class="card-container">
<a class="card" target="_blank" rel="noopener" href="https://angular.io/tutorial">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></svg>
<span>Learn Angular</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg> </a>
<a class="card" target="_blank" rel="noopener" href="https://angular.io/cli">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg>
<span>CLI Documentation</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
</a>
<a class="card" target="_blank" rel="noopener" href="https://blog.angular.io/">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/></svg>
<span>Angular Blog</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
</a>
<a class="card" target="_blank" rel="noopener" href="https://angular.io/devtools/">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M14.73,13.31C15.52,12.24,16,10.93,16,9.5C16,5.91,13.09,3,9.5,3S3,5.91,3,9.5C3,13.09,5.91,16,9.5,16 c1.43,0,2.74-0.48,3.81-1.27L19.59,21L21,19.59L14.73,13.31z M9.5,14C7.01,14,5,11.99,5,9.5S7.01,5,9.5,5S14,7.01,14,9.5 S11.99,14,9.5,14z"/><polygon points="10.29,8.44 9.5,6 8.71,8.44 6.25,8.44 8.26,10.03 7.49,12.5 9.5,10.97 11.51,12.5 10.74,10.03 12.75,8.44"/></g></g></svg>
<span>Angular DevTools</span>
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
</a>
</div>
<!-- Next Steps -->
<h2>Next Steps</h2>
<p>What do you want to do next with your app?</p>
<input type="hidden" #selection>
<div class="card-container">
<button class="card card-small" (click)="selection.value = 'component'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>New Component</span>
</button>
<button class="card card-small" (click)="selection.value = 'material'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Angular Material</span>
</button>
<button class="card card-small" (click)="selection.value = 'pwa'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Add PWA Support</span>
</button>
<button class="card card-small" (click)="selection.value = 'dependency'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Add Dependency</span>
</button>
<button class="card card-small" (click)="selection.value = 'test'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Run and Watch Tests</span>
</button>
<button class="card card-small" (click)="selection.value = 'build'" tabindex="0">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
<span>Build for Production</span>
</button>
</div>
<!-- Terminal -->
<div class="terminal" [ngSwitch]="selection.value">
<pre *ngSwitchDefault>ng generate component xyz</pre>
<pre *ngSwitchCase="'material'">ng add @angular/material</pre>
<pre *ngSwitchCase="'pwa'">ng add @angular/pwa</pre>
<pre *ngSwitchCase="'dependency'">ng add _____</pre>
<pre *ngSwitchCase="'test'">ng test</pre>
<pre *ngSwitchCase="'build'">ng build</pre>
</div>
<!-- Links -->
<div class="card-container">
<a class="circle-link" title="Animations" href="https://angular.io/guide/animations" target="_blank" rel="noopener">
<svg id="Group_20" data-name="Group 20" xmlns="http://www.w3.org/2000/svg" width="21.813" height="23.453" viewBox="0 0 21.813 23.453">
<path id="Path_15" data-name="Path 15" d="M4099.584,972.736h0l-10.882,3.9,1.637,14.4,9.245,5.153,9.245-5.153,1.686-14.4Z" transform="translate(-4088.702 -972.736)" fill="#ffa726"/>
<path id="Path_16" data-name="Path 16" d="M4181.516,972.736v23.453l9.245-5.153,1.686-14.4Z" transform="translate(-4170.633 -972.736)" fill="#fb8c00"/>
<path id="Path_17" data-name="Path 17" d="M4137.529,1076.127l-7.7-3.723,4.417-2.721,7.753,3.723Z" transform="translate(-4125.003 -1058.315)" fill="#ffe0b2"/>
<path id="Path_18" data-name="Path 18" d="M4137.529,1051.705l-7.7-3.723,4.417-2.721,7.753,3.723Z" transform="translate(-4125.003 -1036.757)" fill="#fff3e0"/>
<path id="Path_19" data-name="Path 19" d="M4137.529,1027.283l-7.7-3.723,4.417-2.721,7.753,3.723Z" transform="translate(-4125.003 -1015.199)" fill="#fff"/>
</svg>
</a>
<a class="circle-link" title="CLI" href="https://cli.angular.io/" target="_blank" rel="noopener">
<svg xmlns="http://www.w3.org/2000/svg" width="21.762" height="23.447" viewBox="0 0 21.762 23.447">
<title>Angular CLI Logo</title>
<g id="Group_21" data-name="Group 21" transform="translate(0)">
<path id="Path_20" data-name="Path 20" d="M2660.313,313.618h0l-10.833,3.9,1.637,14.4,9.2,5.152,9.244-5.152,1.685-14.4Z" transform="translate(-2649.48 -313.618)" fill="#37474f"/>
<path id="Path_21" data-name="Path 21" d="M2741.883,313.618v23.447l9.244-5.152,1.685-14.4Z" transform="translate(-2731.05 -313.618)" fill="#263238"/>
<path id="Path_22" data-name="Path 22" d="M2692.293,379.169h11.724V368.618h-11.724Zm11.159-.6h-10.608v-9.345h10.621v9.345Z" transform="translate(-2687.274 -362.17)" fill="#fff"/>
<path id="Path_23" data-name="Path 23" d="M2709.331,393.688l.4.416,2.265-2.28-2.294-2.294-.4.4,1.893,1.893Z" transform="translate(-2702.289 -380.631)" fill="#fff"/>
<rect id="Rectangle_12" data-name="Rectangle 12" width="3.517" height="0.469" transform="translate(9.709 13.744)" fill="#fff"/>
</g>
</svg>
</a>
<a class="circle-link" title="Find a Local Meetup" href="https://www.meetup.com/find/?keywords=angular" target="_blank" rel="noopener">
<svg xmlns="http://www.w3.org/2000/svg" width="24.607" height="23.447" viewBox="0 0 24.607 23.447">
<title>Meetup Logo</title>
<path id="logo--mSwarm" d="M21.221,14.95A4.393,4.393,0,0,1,17.6,19.281a4.452,4.452,0,0,1-.8.069c-.09,0-.125.035-.154.117a2.939,2.939,0,0,1-2.506,2.091,2.868,2.868,0,0,1-2.248-.624.168.168,0,0,0-.245-.005,3.926,3.926,0,0,1-2.589.741,4.015,4.015,0,0,1-3.7-3.347,2.7,2.7,0,0,1-.043-.38c0-.106-.042-.146-.143-.166a3.524,3.524,0,0,1-1.516-.69A3.623,3.623,0,0,1,2.23,14.557a3.66,3.66,0,0,1,1.077-3.085.138.138,0,0,0,.026-.2,3.348,3.348,0,0,1-.451-1.821,3.46,3.46,0,0,1,2.749-3.28.44.44,0,0,0,.355-.281,5.072,5.072,0,0,1,3.863-3,5.028,5.028,0,0,1,3.555.666.31.31,0,0,0,.271.03A4.5,4.5,0,0,1,18.3,4.7a4.4,4.4,0,0,1,1.334,2.751,3.658,3.658,0,0,1,.022.706.131.131,0,0,0,.1.157,2.432,2.432,0,0,1,1.574,1.645,2.464,2.464,0,0,1-.7,2.616c-.065.064-.051.1-.014.166A4.321,4.321,0,0,1,21.221,14.95ZM13.4,14.607a2.09,2.09,0,0,0,1.409,1.982,4.7,4.7,0,0,0,1.275.221,1.807,1.807,0,0,0,.9-.151.542.542,0,0,0,.321-.545.558.558,0,0,0-.359-.534,1.2,1.2,0,0,0-.254-.078c-.262-.047-.526-.086-.787-.138a.674.674,0,0,1-.617-.75,3.394,3.394,0,0,1,.218-1.109c.217-.658.509-1.286.79-1.918a15.609,15.609,0,0,0,.745-1.86,1.95,1.95,0,0,0,.06-1.073,1.286,1.286,0,0,0-1.051-1.033,1.977,1.977,0,0,0-1.521.2.339.339,0,0,1-.446-.042c-.1-.092-.2-.189-.307-.284a1.214,1.214,0,0,0-1.643-.061,7.563,7.563,0,0,1-.614.512A.588.588,0,0,1,10.883,8c-.215-.115-.437-.215-.659-.316a2.153,2.153,0,0,0-.695-.248A2.091,2.091,0,0,0,7.541,8.562a9.915,9.915,0,0,0-.405.986c-.559,1.545-1.015,3.123-1.487,4.7a1.528,1.528,0,0,0,.634,1.777,1.755,1.755,0,0,0,1.5.211,1.35,1.35,0,0,0,.824-.858c.543-1.281,1.032-2.584,1.55-3.875.142-.355.28-.712.432-1.064a.548.548,0,0,1,.851-.24.622.622,0,0,1,.185.539,2.161,2.161,0,0,1-.181.621c-.337.852-.68,1.7-1.018,2.552a2.564,2.564,0,0,0-.173.528.624.624,0,0,0,.333.71,1.073,1.073,0,0,0,.814.034,1.22,1.22,0,0,0,.657-.655q.758-1.488,1.511-2.978.35-.687.709-1.37a1.073,1.073,0,0,1,.357-.434.43.43,0,0,1,.463-.016.373.373,0,0,1,.153.387.7.7,0,0,1-.057.236c-.065.157-.127.316-.2.469-.42.883-.846,1.763-1.262,2.648A2.463,2.463,0,0,0,13.4,14.607Zm5.888,6.508a1.09,1.09,0,0,0-2.179.006,1.09,1.09,0,0,0,2.179-.006ZM1.028,12.139a1.038,1.038,0,1,0,.01-2.075,1.038,1.038,0,0,0-.01,2.075ZM13.782.528a1.027,1.027,0,1,0-.011,2.055A1.027,1.027,0,0,0,13.782.528ZM22.21,6.95a.882.882,0,0,0-1.763.011A.882.882,0,0,0,22.21,6.95ZM4.153,4.439a.785.785,0,1,0,.787-.78A.766.766,0,0,0,4.153,4.439Zm8.221,18.22a.676.676,0,1,0-.677.666A.671.671,0,0,0,12.374,22.658ZM22.872,12.2a.674.674,0,0,0-.665.665.656.656,0,0,0,.655.643.634.634,0,0,0,.655-.644A.654.654,0,0,0,22.872,12.2ZM7.171-.123A.546.546,0,0,0,6.613.43a.553.553,0,1,0,1.106,0A.539.539,0,0,0,7.171-.123ZM24.119,9.234a.507.507,0,0,0-.493.488.494.494,0,0,0,.494.494.48.48,0,0,0,.487-.483A.491.491,0,0,0,24.119,9.234Zm-19.454,9.7a.5.5,0,0,0-.488-.488.491.491,0,0,0-.487.5.483.483,0,0,0,.491.479A.49.49,0,0,0,4.665,18.936Z" transform="translate(0 0.123)" fill="#f64060"/>
</svg>
</a>
<a class="circle-link" title="Join the Conversation on Discord" href="https://discord.gg/angular" target="_blank" rel="noopener">
<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 245 240">
<title>Discord Logo</title>
<path d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z"/>
<path d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z"/>
</svg>
</a>
</div>
<!-- Footer -->
<footer>
Love Angular?&nbsp;
<a href="https://github.com/angular/angular" target="_blank" rel="noopener"> Give our repo a star.
<div class="github-star-badge">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>
Star
</div>
</a>
<a href="https://github.com/angular/angular" target="_blank" rel="noopener">
<svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" fill="#1976d2"/><path d="M0 0h24v24H0z" fill="none"/></svg>
</a>
</footer>
<svg id="clouds" xmlns="http://www.w3.org/2000/svg" width="2611.084" height="485.677" viewBox="0 0 2611.084 485.677">
<title>Gray Clouds Background</title>
<path id="Path_39" data-name="Path 39" d="M2379.709,863.793c10-93-77-171-168-149-52-114-225-105-264,15-75,3-140,59-152,133-30,2.83-66.725,9.829-93.5,26.25-26.771-16.421-63.5-23.42-93.5-26.25-12-74-77-130-152-133-39-120-212-129-264-15-54.084-13.075-106.753,9.173-138.488,48.9-31.734-39.726-84.4-61.974-138.487-48.9-52-114-225-105-264,15a162.027,162.027,0,0,0-103.147,43.044c-30.633-45.365-87.1-72.091-145.206-58.044-52-114-225-105-264,15-75,3-140,59-152,133-53,5-127,23-130,83-2,42,35,72,70,86,49,20,106,18,157,5a165.625,165.625,0,0,0,120,0c47,94,178,113,251,33,61.112,8.015,113.854-5.72,150.492-29.764a165.62,165.62,0,0,0,110.861-3.236c47,94,178,113,251,33,31.385,4.116,60.563,2.495,86.487-3.311,25.924,5.806,55.1,7.427,86.488,3.311,73,80,204,61,251-33a165.625,165.625,0,0,0,120,0c51,13,108,15,157-5a147.188,147.188,0,0,0,33.5-18.694,147.217,147.217,0,0,0,33.5,18.694c49,20,106,18,157,5a165.625,165.625,0,0,0,120,0c47,94,178,113,251,33C2446.709,1093.793,2554.709,922.793,2379.709,863.793Z" transform="translate(142.69 -634.312)" fill="#eee"/>
</svg>
</div>
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<router-outlet></router-outlet>

@ -0,0 +1,35 @@
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'angular'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('angular');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('angular app is running!');
});
});

@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angular';
}

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

@ -0,0 +1,3 @@
export const environment = {
production: true
};

@ -0,0 +1,16 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false
};
/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>

@ -0,0 +1,12 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));

@ -0,0 +1,53 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes recent versions of Safari, Chrome (including
* Opera), Edge on the desktop, and iOS and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

@ -0,0 +1,26 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(),
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

@ -0,0 +1,15 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
}

@ -0,0 +1,32 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2017",
"module": "es2020",
"lib": [
"es2020",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

@ -0,0 +1,18 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

@ -0,0 +1,3 @@
FROM nginx:1.21.6
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf

@ -0,0 +1,11 @@
server {
listen 80;
server_name localhost;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade websocket;
proxy_set_header Connection "Upgrade";
proxy_pass http://backend:5000;
}
}
Loading…
Cancel
Save