diff --git a/.all-contributorsrc b/.all-contributorsrc index 7a9fd3886..6f2f57401 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -29,6 +29,10 @@ "translation-ru": { "symbol": "🇷🇺", "description": "Translate in Russian" + }, + "translation-ch": { + "symbol": "🇨🇳", + "description": "Translate in Chinese" } }, "contributors": [ @@ -304,6 +308,61 @@ "contributions": [ "bug" ] + }, + { + "login": "EnochGao", + "name": "Enoch Gao", + "avatar_url": "https://avatars.githubusercontent.com/u/41459067?v=4", + "profile": "https://enochgao.github.io/", + "contributions": [ + "doc", + "translation-ch" + ] + }, + { + "login": "fpalmab", + "name": "Francisco Palma", + "avatar_url": "https://avatars.githubusercontent.com/u/7729812?v=4", + "profile": "https://github.com/fpalmab", + "contributions": [ + "bug" + ] + }, + { + "login": "michalgrzegorczyk-dev", + "name": "Michał Grzegorczyk", + "avatar_url": "https://avatars.githubusercontent.com/u/47832176?v=4", + "profile": "https://github.com/michalgrzegorczyk-dev", + "contributions": [ + "doc" + ] + }, + { + "login": "tamim36", + "name": "Tamim Arefin Anik", + "avatar_url": "https://avatars.githubusercontent.com/u/42251521?v=4", + "profile": "https://github.com/tamim36", + "contributions": [ + "bug" + ] + }, + { + "login": "WhoisBsa", + "name": "Matheus B.", + "avatar_url": "https://avatars.githubusercontent.com/u/36895235?v=4", + "profile": "https://github.com/WhoisBsa", + "contributions": [ + "bug" + ] + }, + { + "login": "StefH", + "name": "Stef Heyenrath", + "avatar_url": "https://avatars.githubusercontent.com/u/249938?v=4", + "profile": "https://sourcerer.io/stefh", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/.eslintrc.json b/.eslintrc.json index 3bd2a22fb..de9b234b6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,6 +6,7 @@ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { + "@angular-eslint/no-host-metadata-property": "off", "@nx/enforce-module-boundaries": [ "error", { @@ -18,12 +19,6 @@ } ] } - ], - "@angular-eslint/no-host-metadata-property": [ - "error", - { - "allowStatic": true - } ] } }, diff --git a/.github/github-action/contributors.js b/.github/github-action/contributors.js index 50d4c3917..cea002096 100644 --- a/.github/github-action/contributors.js +++ b/.github/github-action/contributors.js @@ -9,9 +9,23 @@ const contributors = [ 'kabrunko-dev', 'Sanjar1304', 'tsironis13', + 'EnochGao', ]; -const sponsors = ['ddotx', 'LMFinney', 'alannelucq', 'SidV2']; +const sponsors = [ + 'ddotx', + 'LMFinney', + 'alannelucq', + 'SidV2', + 'fpalmab', + 'CivilEngeneer', + 'apalaio', + 'amosISA', + 'michalgrzegorczyk-dev', + 'zealotrahl', + 'DzoeL123', + 'allan1989', +]; module.exports = { contributors, diff --git a/.github/workflows/close-inactive-pr.yml b/.github/workflows/close-inactive-pr.yml index 66d984d5f..d5e0e9c95 100644 --- a/.github/workflows/close-inactive-pr.yml +++ b/.github/workflows/close-inactive-pr.yml @@ -17,8 +17,8 @@ jobs: stale-issue-label: 'stale' stale-issue-message: 'This issue is stale because it has been open for 15 days with no activity.' exempt-issue-labels: 'long-term' - days-before-pr-stale: 10 - days-before-pr-close: 2 + days-before-pr-stale: 20 + days-before-pr-close: 7 stale-pr-label: 'stale' stale-pr-message: 'This pull request is stale because it has been open for 15 days with no activity.' close-pr-message: 'This pull request was closed because it has been inactive for 5 days since being marked as stale.' diff --git a/.github/workflows/label-issue.yml b/.github/workflows/label-issue.yml index 6918818fd..a5fd40632 100644 --- a/.github/workflows/label-issue.yml +++ b/.github/workflows/label-issue.yml @@ -2,9 +2,25 @@ name: Add Labels on: pull_request_target: - types: [ opened ] + types: [ opened, edited, synchronize ] jobs: + check-title: + runs-on: ubuntu-latest + steps: + - name: Check PR title + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + echo "Checking PR Title: '$PR_TITLE'" + if [[ ! "$PR_TITLE" =~ ^Answer: ]]; then + echo "❌ PR title should start with 'Answer:[#challenge number]'" + echo "### ❌ PR title should start with 'Answer:[#challenge number]'" >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "✅ PR title format is correct." + echo "### ✅ PR title format is correct." >> $GITHUB_STEP_SUMMARY + fi add_labels: runs-on: ubuntu-latest if: ${{ startsWith(github.event.pull_request.title, 'Answer') }} diff --git a/.gitignore b/.gitignore index 5472d6bdf..cad0abc01 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ Thumbs.db TODO.md .nx/cache +.nx/workspace-data + +.cursorrules \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index ab639d33d..a4684ea74 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,4 +5,5 @@ .angular -/.nx/cache \ No newline at end of file +/.nx/cache +/.nx/workspace-data \ No newline at end of file diff --git a/README.md b/README.md index 9b4cd8e6d..2965ecc08 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ If you would like to propose a challenge, this project is open source, so feel f ## Challenges -Check [all 55 challenges](https://angular-challenges.vercel.app/) +Check [all 59 challenges](https://angular-challenges.vercel.app/) ## Contributors ✨ @@ -69,6 +69,14 @@ Check [all 55 challenges](https://angular-challenges.vercel.app/) fixed_michal
fixed_michal

🐛 Tenessy
Tenessy

🐛 + + Enoch Gao
Enoch Gao

📖 🇨🇳 + Francisco Palma
Francisco Palma

🐛 + Michał Grzegorczyk
Michał Grzegorczyk

📖 + Tamim Arefin Anik
Tamim Arefin Anik

🐛 + Matheus B.
Matheus B.

🐛 + Stef Heyenrath
Stef Heyenrath

📖 + diff --git a/apps/angular/1-projection/project.json b/apps/angular/1-projection/project.json index df91001f3..d40912c35 100644 --- a/apps/angular/1-projection/project.json +++ b/apps/angular/1-projection/project.json @@ -7,12 +7,12 @@ "tags": [], "targets": { "build": { - "executor": "@angular-devkit/build-angular:application", + "executor": "@angular-devkit/build-angular:browser", "outputs": ["{options.outputPath}"], "options": { "outputPath": "dist/apps/angular/1-projection", "index": "apps/angular/1-projection/src/index.html", - "browser": "apps/angular/1-projection/src/main.ts", + "main": "apps/angular/1-projection/src/main.ts", "polyfills": ["apps/angular/1-projection/src/polyfills.ts"], "tsConfig": "apps/angular/1-projection/tsconfig.app.json", "inlineStyleLanguage": "scss", @@ -41,7 +41,9 @@ "outputHashing": "all" }, "development": { + "buildOptimizer": false, "optimization": false, + "vendorChunk": true, "extractLicenses": false, "sourceMap": true, "namedChunks": true @@ -68,10 +70,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/1-projection/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/1-projection/src/app/app.component.ts b/apps/angular/1-projection/src/app/app.component.ts index b1d076a9f..df654bbc2 100644 --- a/apps/angular/1-projection/src/app/app.component.ts +++ b/apps/angular/1-projection/src/app/app.component.ts @@ -7,12 +7,11 @@ import { TeacherCardComponent } from './component/teacher-card/teacher-card.comp selector: 'app-root', template: `
- - - + + +
`, - standalone: true, imports: [TeacherCardComponent, StudentCardComponent, CityCardComponent], }) export class AppComponent {} diff --git a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts index 30c8f88ec..8895c8c84 100644 --- a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts @@ -1,13 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'app-city-card', template: 'TODO City', - standalone: true, imports: [], + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class CityCardComponent implements OnInit { - constructor() {} - - ngOnInit(): void {} -} +export class CityCardComponent {} diff --git a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts index 441cda189..bdfa4abd4 100644 --- a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts +++ b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts @@ -1,19 +1,22 @@ -import { Component, OnInit } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + OnInit, +} from '@angular/core'; import { FakeHttpService } from '../../data-access/fake-http.service'; import { StudentStore } from '../../data-access/student.store'; import { CardType } from '../../model/card.model'; -import { Student } from '../../model/student.model'; import { CardComponent } from '../../ui/card/card.component'; @Component({ selector: 'app-student-card', template: ` + customClass="bg-light-green" /> `, - standalone: true, styles: [ ` ::ng-deep .bg-light-green { @@ -22,19 +25,16 @@ import { CardComponent } from '../../ui/card/card.component'; `, ], imports: [CardComponent], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class StudentCardComponent implements OnInit { - students: Student[] = []; - cardType = CardType.STUDENT; + private http = inject(FakeHttpService); + private store = inject(StudentStore); - constructor( - private http: FakeHttpService, - private store: StudentStore, - ) {} + students = this.store.students; + cardType = CardType.STUDENT; ngOnInit(): void { this.http.fetchStudents$.subscribe((s) => this.store.addAll(s)); - - this.store.students$.subscribe((s) => (this.students = s)); } } diff --git a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts index 995cb7c2f..adf0ad3c1 100644 --- a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts +++ b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts @@ -1,15 +1,14 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, inject, OnInit } from '@angular/core'; import { FakeHttpService } from '../../data-access/fake-http.service'; import { TeacherStore } from '../../data-access/teacher.store'; import { CardType } from '../../model/card.model'; -import { Teacher } from '../../model/teacher.model'; import { CardComponent } from '../../ui/card/card.component'; @Component({ selector: 'app-teacher-card', template: ` `, @@ -20,21 +19,16 @@ import { CardComponent } from '../../ui/card/card.component'; } `, ], - standalone: true, imports: [CardComponent], }) export class TeacherCardComponent implements OnInit { - teachers: Teacher[] = []; - cardType = CardType.TEACHER; + private http = inject(FakeHttpService); + private store = inject(TeacherStore); - constructor( - private http: FakeHttpService, - private store: TeacherStore, - ) {} + teachers = this.store.teachers; + cardType = CardType.TEACHER; ngOnInit(): void { this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t)); - - this.store.teachers$.subscribe((t) => (this.teachers = t)); } } diff --git a/apps/angular/1-projection/src/app/data-access/city.store.ts b/apps/angular/1-projection/src/app/data-access/city.store.ts index 711dad1d7..a8b523569 100644 --- a/apps/angular/1-projection/src/app/data-access/city.store.ts +++ b/apps/angular/1-projection/src/app/data-access/city.store.ts @@ -1,23 +1,21 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import { Injectable, signal } from '@angular/core'; import { City } from '../model/city.model'; @Injectable({ providedIn: 'root', }) export class CityStore { - private cities = new BehaviorSubject([]); - cities$ = this.cities.asObservable(); + private cities = signal([]); addAll(cities: City[]) { - this.cities.next(cities); + this.cities.set(cities); } - addOne(student: City) { - this.cities.next([...this.cities.value, student]); + addOne(city: City) { + this.cities.set([...this.cities(), city]); } deleteOne(id: number) { - this.cities.next(this.cities.value.filter((s) => s.id !== id)); + this.cities.set(this.cities().filter((s) => s.id !== id)); } } diff --git a/apps/angular/1-projection/src/app/data-access/student.store.ts b/apps/angular/1-projection/src/app/data-access/student.store.ts index 7918118c3..6e7f57022 100644 --- a/apps/angular/1-projection/src/app/data-access/student.store.ts +++ b/apps/angular/1-projection/src/app/data-access/student.store.ts @@ -1,23 +1,21 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import { Injectable, signal } from '@angular/core'; import { Student } from '../model/student.model'; @Injectable({ providedIn: 'root', }) export class StudentStore { - private students = new BehaviorSubject([]); - students$ = this.students.asObservable(); + public students = signal([]); addAll(students: Student[]) { - this.students.next(students); + this.students.set(students); } addOne(student: Student) { - this.students.next([...this.students.value, student]); + this.students.set([...this.students(), student]); } deleteOne(id: number) { - this.students.next(this.students.value.filter((s) => s.id !== id)); + this.students.set(this.students().filter((s) => s.id !== id)); } } diff --git a/apps/angular/1-projection/src/app/data-access/teacher.store.ts b/apps/angular/1-projection/src/app/data-access/teacher.store.ts index 93f68c4b1..5f6dae989 100644 --- a/apps/angular/1-projection/src/app/data-access/teacher.store.ts +++ b/apps/angular/1-projection/src/app/data-access/teacher.store.ts @@ -1,23 +1,21 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import { Injectable, signal } from '@angular/core'; import { Teacher } from '../model/teacher.model'; @Injectable({ providedIn: 'root', }) export class TeacherStore { - private teachers = new BehaviorSubject([]); - teachers$ = this.teachers.asObservable(); + public teachers = signal([]); addAll(teachers: Teacher[]) { - this.teachers.next(teachers); + this.teachers.set(teachers); } addOne(teacher: Teacher) { - this.teachers.next([...this.teachers.value, teacher]); + this.teachers.set([...this.teachers(), teacher]); } deleteOne(id: number) { - this.teachers.next(this.teachers.value.filter((t) => t.id !== id)); + this.teachers.set(this.teachers().filter((t) => t.id !== id)); } } diff --git a/apps/angular/1-projection/src/app/ui/card/card.component.ts b/apps/angular/1-projection/src/app/ui/card/card.component.ts index f06c9ae00..1a6c3648c 100644 --- a/apps/angular/1-projection/src/app/ui/card/card.component.ts +++ b/apps/angular/1-projection/src/app/ui/card/card.component.ts @@ -1,5 +1,5 @@ -import { NgFor, NgIf } from '@angular/common'; -import { Component, Input } from '@angular/core'; +import { NgOptimizedImage } from '@angular/common'; +import { Component, inject, input } from '@angular/core'; import { randStudent, randTeacher } from '../../data-access/fake-http.service'; import { StudentStore } from '../../data-access/student.store'; import { TeacherStore } from '../../data-access/teacher.store'; @@ -11,22 +11,21 @@ import { ListItemComponent } from '../list-item/list-item.component'; template: `
- - + [class]="customClass()"> + @if (type() === CardType.TEACHER) { + + } + @if (type() === CardType.STUDENT) { + + }
- + @for (item of list(); track item) { + + }
`, - standalone: true, - imports: [NgIf, NgFor, ListItemComponent], + imports: [ListItemComponent, NgOptimizedImage], }) export class CardComponent { - @Input() list: any[] | null = null; - @Input() type!: CardType; - @Input() customClass = ''; + private teacherStore = inject(TeacherStore); + private studentStore = inject(StudentStore); - CardType = CardType; + readonly list = input(null); + readonly type = input.required(); + readonly customClass = input(''); - constructor( - private teacherStore: TeacherStore, - private studentStore: StudentStore, - ) {} + CardType = CardType; addNewItem() { - if (this.type === CardType.TEACHER) { + const type = this.type(); + if (type === CardType.TEACHER) { this.teacherStore.addOne(randTeacher()); - } else if (this.type === CardType.STUDENT) { + } else if (type === CardType.STUDENT) { this.studentStore.addOne(randStudent()); } } diff --git a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts index c0f9cff7f..cffabb451 100644 --- a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts +++ b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts @@ -1,4 +1,9 @@ -import { Component, Input } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + input, +} from '@angular/core'; import { StudentStore } from '../../data-access/student.store'; import { TeacherStore } from '../../data-access/teacher.store'; import { CardType } from '../../model/card.model'; @@ -7,28 +12,28 @@ import { CardType } from '../../model/card.model'; selector: 'app-list-item', template: `
- {{ name }} -
`, standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ListItemComponent { - @Input() id!: number; - @Input() name!: string; - @Input() type!: CardType; + private teacherStore = inject(TeacherStore); + private studentStore = inject(StudentStore); - constructor( - private teacherStore: TeacherStore, - private studentStore: StudentStore, - ) {} + readonly id = input.required(); + readonly name = input.required(); + readonly type = input.required(); delete(id: number) { - if (this.type === CardType.TEACHER) { + const type = this.type(); + if (type === CardType.TEACHER) { this.teacherStore.deleteOne(id); - } else if (this.type === CardType.STUDENT) { + } else if (type === CardType.STUDENT) { this.studentStore.deleteOne(id); } } diff --git a/apps/angular/1-projection/src/main.ts b/apps/angular/1-projection/src/main.ts index 9cd15da95..31c5da482 100644 --- a/apps/angular/1-projection/src/main.ts +++ b/apps/angular/1-projection/src/main.ts @@ -1,4 +1,4 @@ import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; -bootstrapApplication(AppComponent); +bootstrapApplication(AppComponent).catch((err) => console.error(err)); diff --git a/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts b/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts index d91fc7436..764d4b9d0 100644 --- a/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts +++ b/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts @@ -3,7 +3,6 @@ import { Component } from '@angular/core'; import { PersonUtils } from './person.utils'; @Component({ - standalone: true, imports: [NgFor], selector: 'app-root', template: ` diff --git a/apps/angular/13-highly-customizable-css/src/app/page.component.ts b/apps/angular/13-highly-customizable-css/src/app/page.component.ts index 067453294..029ca52d2 100644 --- a/apps/angular/13-highly-customizable-css/src/app/page.component.ts +++ b/apps/angular/13-highly-customizable-css/src/app/page.component.ts @@ -5,7 +5,6 @@ import { TextComponent } from './text.component'; @Component({ selector: 'page', - standalone: true, imports: [TextStaticComponent, TextComponent], template: ` diff --git a/apps/angular/13-highly-customizable-css/src/app/static-text.component.ts b/apps/angular/13-highly-customizable-css/src/app/static-text.component.ts index cdfd1c19f..70d57d9a3 100644 --- a/apps/angular/13-highly-customizable-css/src/app/static-text.component.ts +++ b/apps/angular/13-highly-customizable-css/src/app/static-text.component.ts @@ -6,7 +6,6 @@ export type StaticTextType = 'normal' | 'warning' | 'error'; @Component({ selector: 'static-text', - standalone: true, imports: [TextComponent], template: ` This is a static text diff --git a/apps/angular/16-master-dependency-injection/src/app/app.component.ts b/apps/angular/16-master-dependency-injection/src/app/app.component.ts index f80851729..5bb91c2b2 100644 --- a/apps/angular/16-master-dependency-injection/src/app/app.component.ts +++ b/apps/angular/16-master-dependency-injection/src/app/app.component.ts @@ -23,7 +23,6 @@ export class ProductDirective { } @Component({ - standalone: true, imports: [TableComponent, CurrencyPipe, AsyncPipe, NgFor, ProductDirective], providers: [CurrencyService], selector: 'app-root', diff --git a/apps/angular/21-anchor-navigation/project.json b/apps/angular/21-anchor-navigation/project.json index dd4c732c1..b8ba74b04 100644 --- a/apps/angular/21-anchor-navigation/project.json +++ b/apps/angular/21-anchor-navigation/project.json @@ -69,10 +69,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/21-anchor-navigation/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/21-anchor-navigation/src/app/app.component.ts b/apps/angular/21-anchor-navigation/src/app/app.component.ts index 3fb7c5df0..5caca0271 100644 --- a/apps/angular/21-anchor-navigation/src/app/app.component.ts +++ b/apps/angular/21-anchor-navigation/src/app/app.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterOutlet], selector: 'app-root', template: ` diff --git a/apps/angular/21-anchor-navigation/src/app/foo.component.ts b/apps/angular/21-anchor-navigation/src/app/foo.component.ts index 87f9b59d9..6744c3662 100644 --- a/apps/angular/21-anchor-navigation/src/app/foo.component.ts +++ b/apps/angular/21-anchor-navigation/src/app/foo.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { NavButtonComponent } from './nav-button.component'; @Component({ - standalone: true, imports: [NavButtonComponent], selector: 'app-foo', template: ` diff --git a/apps/angular/21-anchor-navigation/src/app/home.component.ts b/apps/angular/21-anchor-navigation/src/app/home.component.ts index 0f24ff6e7..6ef9bc2b6 100644 --- a/apps/angular/21-anchor-navigation/src/app/home.component.ts +++ b/apps/angular/21-anchor-navigation/src/app/home.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { NavButtonComponent } from './nav-button.component'; @Component({ - standalone: true, imports: [NavButtonComponent], selector: 'app-home', template: ` diff --git a/apps/angular/22-router-input/src/app/app.component.ts b/apps/angular/22-router-input/src/app/app.component.ts index 1ef7e32aa..9dfc11200 100644 --- a/apps/angular/22-router-input/src/app/app.component.ts +++ b/apps/angular/22-router-input/src/app/app.component.ts @@ -3,7 +3,6 @@ import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { RouterLink, RouterModule } from '@angular/router'; @Component({ - standalone: true, imports: [RouterLink, RouterModule, ReactiveFormsModule], selector: 'app-root', template: ` diff --git a/apps/angular/22-router-input/src/app/home.component.ts b/apps/angular/22-router-input/src/app/home.component.ts index 2ef8c5eb4..0ddc1501d 100644 --- a/apps/angular/22-router-input/src/app/home.component.ts +++ b/apps/angular/22-router-input/src/app/home.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-home', - standalone: true, imports: [], template: `
Home
diff --git a/apps/angular/22-router-input/src/app/test.component.ts b/apps/angular/22-router-input/src/app/test.component.ts index 88c1465f3..747ab4483 100644 --- a/apps/angular/22-router-input/src/app/test.component.ts +++ b/apps/angular/22-router-input/src/app/test.component.ts @@ -5,7 +5,6 @@ import { map } from 'rxjs'; @Component({ selector: 'app-subscription', - standalone: true, imports: [AsyncPipe], template: `
TestId: {{ testId$ | async }}
diff --git a/apps/angular/3-directive-enhancement/src/app/app.component.ts b/apps/angular/3-directive-enhancement/src/app/app.component.ts index cd1d5f23c..8d37369a1 100644 --- a/apps/angular/3-directive-enhancement/src/app/app.component.ts +++ b/apps/angular/3-directive-enhancement/src/app/app.component.ts @@ -6,7 +6,6 @@ interface Person { } @Component({ - standalone: true, imports: [NgFor, NgIf], selector: 'app-root', template: ` diff --git a/apps/angular/31-module-to-standalone/src/app/app.component.ts b/apps/angular/31-module-to-standalone/src/app/app.component.ts index 95eeab5b9..986df84b5 100644 --- a/apps/angular/31-module-to-standalone/src/app/app.component.ts +++ b/apps/angular/31-module-to-standalone/src/app/app.component.ts @@ -25,5 +25,6 @@ import { Component } from '@angular/core'; host: { class: 'flex flex-col p-4 gap-3', }, + standalone: false, }) export class AppComponent {} diff --git a/apps/angular/32-change-detection-bug/project.json b/apps/angular/32-change-detection-bug/project.json index 41b4090cc..48eb9ef1e 100644 --- a/apps/angular/32-change-detection-bug/project.json +++ b/apps/angular/32-change-detection-bug/project.json @@ -68,10 +68,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/32-change-detection-bug/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/32-change-detection-bug/src/app/app.component.ts b/apps/angular/32-change-detection-bug/src/app/app.component.ts index 046492f9b..217999c3a 100644 --- a/apps/angular/32-change-detection-bug/src/app/app.component.ts +++ b/apps/angular/32-change-detection-bug/src/app/app.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterOutlet], selector: 'app-root', template: ` diff --git a/apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts b/apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts index c8a6f6d22..3d5ce20f8 100644 --- a/apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts +++ b/apps/angular/32-change-detection-bug/src/app/main-navigation.component.ts @@ -10,7 +10,6 @@ interface MenuItem { @Component({ selector: 'app-nav', - standalone: true, imports: [RouterLink, RouterLinkActive, NgFor], template: ` @@ -38,7 +37,6 @@ export class NavigationComponent { } @Component({ - standalone: true, imports: [NavigationComponent, NgIf, AsyncPipe], template: ` diff --git a/apps/angular/33-decoupling-components/src/app/app.component.ts b/apps/angular/33-decoupling-components/src/app/app.component.ts index 34082c331..0d78f4d34 100644 --- a/apps/angular/33-decoupling-components/src/app/app.component.ts +++ b/apps/angular/33-decoupling-components/src/app/app.component.ts @@ -3,7 +3,6 @@ import { BtnHelmetDirective } from '@angular-challenges/decoupling/helmet'; import { Component } from '@angular/core'; @Component({ - standalone: true, imports: [BtnDisabledDirective, BtnHelmetDirective], selector: 'app-root', template: ` diff --git a/apps/angular/39-injection-token/project.json b/apps/angular/39-injection-token/project.json index d5ae3f98e..8dba72d55 100644 --- a/apps/angular/39-injection-token/project.json +++ b/apps/angular/39-injection-token/project.json @@ -68,10 +68,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/39-injection-token/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/39-injection-token/src/app/app.component.ts b/apps/angular/39-injection-token/src/app/app.component.ts index 5ac8087cb..280dc090a 100644 --- a/apps/angular/39-injection-token/src/app/app.component.ts +++ b/apps/angular/39-injection-token/src/app/app.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterOutlet, RouterLink], selector: 'app-root', template: ` diff --git a/apps/angular/39-injection-token/src/app/phone.component.ts b/apps/angular/39-injection-token/src/app/phone.component.ts index a58b3cd99..41ee3cfc0 100644 --- a/apps/angular/39-injection-token/src/app/phone.component.ts +++ b/apps/angular/39-injection-token/src/app/phone.component.ts @@ -3,7 +3,6 @@ import { TimerContainerComponent } from './timer-container.component'; @Component({ selector: 'app-phone', - standalone: true, imports: [TimerContainerComponent], template: `
diff --git a/apps/angular/39-injection-token/src/app/timer-container.component.ts b/apps/angular/39-injection-token/src/app/timer-container.component.ts index 30af69354..67db6059a 100644 --- a/apps/angular/39-injection-token/src/app/timer-container.component.ts +++ b/apps/angular/39-injection-token/src/app/timer-container.component.ts @@ -3,7 +3,6 @@ import { DEFAULT_TIMER } from './data'; import { TimerComponent } from './timer.component'; @Component({ selector: 'timer-container', - standalone: true, imports: [TimerComponent], template: `
diff --git a/apps/angular/39-injection-token/src/app/video.component.ts b/apps/angular/39-injection-token/src/app/video.component.ts index 2c218071a..ba0a218b4 100644 --- a/apps/angular/39-injection-token/src/app/video.component.ts +++ b/apps/angular/39-injection-token/src/app/video.component.ts @@ -3,7 +3,6 @@ import { TimerContainerComponent } from './timer-container.component'; @Component({ selector: 'app-video', - standalone: true, imports: [TimerContainerComponent], template: `
diff --git a/apps/angular/4-typed-context-outlet/src/app/app.component.ts b/apps/angular/4-typed-context-outlet/src/app/app.component.ts index 2683ba9d4..23be9dac6 100644 --- a/apps/angular/4-typed-context-outlet/src/app/app.component.ts +++ b/apps/angular/4-typed-context-outlet/src/app/app.component.ts @@ -4,7 +4,6 @@ import { ListComponent } from './list.component'; import { PersonComponent } from './person.component'; @Component({ - standalone: true, imports: [NgTemplateOutlet, PersonComponent, ListComponent], selector: 'app-root', template: ` diff --git a/apps/angular/4-typed-context-outlet/src/app/list.component.ts b/apps/angular/4-typed-context-outlet/src/app/list.component.ts index 5212a425e..b9946e428 100644 --- a/apps/angular/4-typed-context-outlet/src/app/list.component.ts +++ b/apps/angular/4-typed-context-outlet/src/app/list.component.ts @@ -9,7 +9,6 @@ import { @Component({ selector: 'list', - standalone: true, imports: [CommonModule], template: `
diff --git a/apps/angular/4-typed-context-outlet/src/app/person.component.ts b/apps/angular/4-typed-context-outlet/src/app/person.component.ts index 1550cf274..59eb00ab1 100644 --- a/apps/angular/4-typed-context-outlet/src/app/person.component.ts +++ b/apps/angular/4-typed-context-outlet/src/app/person.component.ts @@ -7,7 +7,6 @@ interface Person { } @Component({ - standalone: true, imports: [NgTemplateOutlet], selector: 'person', template: ` diff --git a/apps/angular/44-view-transition/src/app/app.component.ts b/apps/angular/44-view-transition/src/app/app.component.ts index da56c04c0..1fcb0c548 100644 --- a/apps/angular/44-view-transition/src/app/app.component.ts +++ b/apps/angular/44-view-transition/src/app/app.component.ts @@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterOutlet], selector: 'app-root', template: ` diff --git a/apps/angular/44-view-transition/src/app/blog/blog.component.ts b/apps/angular/44-view-transition/src/app/blog/blog.component.ts index 68ffcde50..29291d21e 100644 --- a/apps/angular/44-view-transition/src/app/blog/blog.component.ts +++ b/apps/angular/44-view-transition/src/app/blog/blog.component.ts @@ -4,7 +4,6 @@ import { ThumbnailComponent } from './thumbnail.component'; @Component({ selector: 'blog', - standalone: true, imports: [ThumbnailComponent], template: `
diff --git a/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts b/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts index 6263e97ab..dd2e25e26 100644 --- a/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts +++ b/apps/angular/44-view-transition/src/app/blog/thumbnail.component.ts @@ -6,7 +6,6 @@ import { ThumbnailHeaderComponent } from './thumbnail-header.component'; @Component({ selector: 'blog-thumbnail', - standalone: true, imports: [NgOptimizedImage, ThumbnailHeaderComponent, RouterLinkWithHref], template: ` diff --git a/apps/angular/44-view-transition/src/app/post/post-header.component.ts b/apps/angular/44-view-transition/src/app/post/post-header.component.ts index 8b62a6c48..6d5f30e54 100644 --- a/apps/angular/44-view-transition/src/app/post/post-header.component.ts +++ b/apps/angular/44-view-transition/src/app/post/post-header.component.ts @@ -3,7 +3,6 @@ import { Component, input } from '@angular/core'; @Component({ selector: 'post-header', - standalone: true, imports: [NgOptimizedImage], template: `
diff --git a/apps/angular/44-view-transition/src/app/post/post.component.ts b/apps/angular/44-view-transition/src/app/post/post.component.ts index 1e1c6fd89..edb87f780 100644 --- a/apps/angular/44-view-transition/src/app/post/post.component.ts +++ b/apps/angular/44-view-transition/src/app/post/post.component.ts @@ -12,7 +12,6 @@ import { PostHeaderComponent } from './post-header.component'; @Component({ selector: 'post', - standalone: true, imports: [ ThumbnailHeaderComponent, NgOptimizedImage, diff --git a/apps/angular/45-react-in-angular/project.json b/apps/angular/45-react-in-angular/project.json index b2fe821a1..bce6fe70e 100644 --- a/apps/angular/45-react-in-angular/project.json +++ b/apps/angular/45-react-in-angular/project.json @@ -66,10 +66,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/45-react-in-angular/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/45-react-in-angular/src/app/app.component.ts b/apps/angular/45-react-in-angular/src/app/app.component.ts index a914cc65f..87b9675cc 100644 --- a/apps/angular/45-react-in-angular/src/app/app.component.ts +++ b/apps/angular/45-react-in-angular/src/app/app.component.ts @@ -4,7 +4,6 @@ import { PostComponent } from './react/post.component'; type Post = { title: string; description: string }; @Component({ - standalone: true, imports: [PostComponent], selector: 'app-root', template: ` diff --git a/apps/angular/46-simple-animations/project.json b/apps/angular/46-simple-animations/project.json index 70e17fd1e..1d00fd246 100644 --- a/apps/angular/46-simple-animations/project.json +++ b/apps/angular/46-simple-animations/project.json @@ -66,10 +66,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/46-simple-animations/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/46-simple-animations/src/app/app.component.ts b/apps/angular/46-simple-animations/src/app/app.component.ts index 9f537b3fb..ae63db419 100644 --- a/apps/angular/46-simple-animations/src/app/app.component.ts +++ b/apps/angular/46-simple-animations/src/app/app.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; @Component({ - standalone: true, imports: [], selector: 'app-root', styles: ` diff --git a/apps/angular/5-crud-application/project.json b/apps/angular/5-crud-application/project.json index c9cca6fb6..cdad9374a 100644 --- a/apps/angular/5-crud-application/project.json +++ b/apps/angular/5-crud-application/project.json @@ -73,10 +73,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/5-crud-application/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/5-crud-application/src/app/app.component.ts b/apps/angular/5-crud-application/src/app/app.component.ts index 8c3d1b8ae..9152ff5e4 100644 --- a/apps/angular/5-crud-application/src/app/app.component.ts +++ b/apps/angular/5-crud-application/src/app/app.component.ts @@ -4,7 +4,6 @@ import { Component, OnInit } from '@angular/core'; import { randText } from '@ngneat/falso'; @Component({ - standalone: true, imports: [CommonModule], selector: 'app-root', template: ` diff --git a/apps/angular/52-lazy-load-component/project.json b/apps/angular/52-lazy-load-component/project.json index 7767de52c..d3b28088a 100644 --- a/apps/angular/52-lazy-load-component/project.json +++ b/apps/angular/52-lazy-load-component/project.json @@ -65,14 +65,15 @@ "buildTarget": "angular-lazy-load-component:build" } }, - "lint": { - "executor": "@nx/eslint:lint" - }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/52-lazy-load-component/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/52-lazy-load-component/src/app/app.component.ts b/apps/angular/52-lazy-load-component/src/app/app.component.ts index ccad6321c..6d8c03d29 100644 --- a/apps/angular/52-lazy-load-component/src/app/app.component.ts +++ b/apps/angular/52-lazy-load-component/src/app/app.component.ts @@ -16,6 +16,7 @@ import { Component, signal } from '@angular/core'; }
`, + standalone: false, }) export class AppComponent { topLoaded = signal(false); diff --git a/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts b/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts index 051e39491..cbb2b5fa6 100644 --- a/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts +++ b/apps/angular/52-lazy-load-component/src/app/placeholder.component.ts @@ -13,5 +13,6 @@ import { Component } from '@angular/core'; height: 50%; } `, + standalone: false, }) export class PlaceholderComponent {} diff --git a/apps/angular/52-lazy-load-component/src/app/top.component.ts b/apps/angular/52-lazy-load-component/src/app/top.component.ts index d9104bef3..e1ca9012c 100644 --- a/apps/angular/52-lazy-load-component/src/app/top.component.ts +++ b/apps/angular/52-lazy-load-component/src/app/top.component.ts @@ -13,5 +13,6 @@ import { Component } from '@angular/core'; height: 50%; } `, + standalone: false, }) export class TopComponent {} diff --git a/apps/angular/55-back-button-navigation/project.json b/apps/angular/55-back-button-navigation/project.json index 62c7b2773..f53d65e27 100644 --- a/apps/angular/55-back-button-navigation/project.json +++ b/apps/angular/55-back-button-navigation/project.json @@ -70,14 +70,15 @@ "buildTarget": "angular-back-button-navigation:build" } }, - "lint": { - "executor": "@nx/eslint:lint" - }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/angular/55-back-button-navigation/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/angular/55-back-button-navigation/src/app/app.component.ts b/apps/angular/55-back-button-navigation/src/app/app.component.ts index 22c15ea54..baffdae25 100644 --- a/apps/angular/55-back-button-navigation/src/app/app.component.ts +++ b/apps/angular/55-back-button-navigation/src/app/app.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { RouterLink, RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterOutlet, RouterLink], selector: 'app-root', templateUrl: './app.component.html', diff --git a/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts b/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts index e1142967e..9a9dd0fef 100644 --- a/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts +++ b/apps/angular/55-back-button-navigation/src/app/dialog/dialog.component.ts @@ -11,7 +11,6 @@ import { @Component({ selector: 'app-dialog-dialog', templateUrl: './dialog.component.html', - standalone: true, imports: [ MatButtonModule, MatDialogActions, diff --git a/apps/angular/55-back-button-navigation/src/app/home/home.component.ts b/apps/angular/55-back-button-navigation/src/app/home/home.component.ts index 0e68bbd3d..18c4147b1 100644 --- a/apps/angular/55-back-button-navigation/src/app/home/home.component.ts +++ b/apps/angular/55-back-button-navigation/src/app/home/home.component.ts @@ -3,7 +3,6 @@ import { MatButtonModule } from '@angular/material/button'; import { RouterLink } from '@angular/router'; @Component({ - standalone: true, imports: [MatButtonModule, RouterLink], selector: 'app-home', templateUrl: './home.component.html', diff --git a/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts b/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts index a44a1ea8b..a97282c33 100644 --- a/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts +++ b/apps/angular/55-back-button-navigation/src/app/sensitive-action/sensitive-action.component.ts @@ -4,7 +4,6 @@ import { MatDialog } from '@angular/material/dialog'; import { DialogComponent } from '../dialog/dialog.component'; @Component({ - standalone: true, imports: [MatButtonModule], selector: 'app-sensitive-action', templateUrl: './sensitive-action.component.html', diff --git a/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts b/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts index 458e0b102..fe97e7368 100644 --- a/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts +++ b/apps/angular/55-back-button-navigation/src/app/simple-action/simple-action.component.ts @@ -4,7 +4,6 @@ import { MatDialog } from '@angular/material/dialog'; import { DialogComponent } from '../dialog/dialog.component'; @Component({ - standalone: true, imports: [MatButtonModule], selector: 'app-simple-action', templateUrl: './simple-action.component.html', diff --git a/apps/angular/55-back-button-navigation/src/styles.scss b/apps/angular/55-back-button-navigation/src/styles.scss index b20428941..acd290007 100644 --- a/apps/angular/55-back-button-navigation/src/styles.scss +++ b/apps/angular/55-back-button-navigation/src/styles.scss @@ -6,7 +6,8 @@ @tailwind components; @tailwind utilities; -@include mat.core(); +@include mat.elevation-classes(); +@include mat.app-background(); $theme-primary: mat.m2-define-palette(mat.$m2-indigo-palette); $theme-accent: mat.m2-define-palette(mat.$m2-pink-palette, A200, A100, A400); diff --git a/apps/ngrx/2-effect-vs-selector/.eslintrc.json b/apps/angular/57-content-projection-default/.eslintrc.json similarity index 100% rename from apps/ngrx/2-effect-vs-selector/.eslintrc.json rename to apps/angular/57-content-projection-default/.eslintrc.json diff --git a/apps/ngrx/7-power-of-effect/README.md b/apps/angular/57-content-projection-default/README.md similarity index 53% rename from apps/ngrx/7-power-of-effect/README.md rename to apps/angular/57-content-projection-default/README.md index b18500402..fc4579558 100644 --- a/apps/ngrx/7-power-of-effect/README.md +++ b/apps/angular/57-content-projection-default/README.md @@ -1,13 +1,13 @@ -# Power of Effect +# Content Projection Default > author: thomas-laforge ### Run Application ```bash -npx nx serve ngrx-power-of-effect +npx nx serve angular-content-projection-default ``` ### Documentation and Instruction -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/ngrx/7-power-effect/). +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/57-content-projection-default/). diff --git a/apps/angular/57-content-projection-default/project.json b/apps/angular/57-content-projection-default/project.json new file mode 100644 index 000000000..a57738bff --- /dev/null +++ b/apps/angular/57-content-projection-default/project.json @@ -0,0 +1,81 @@ +{ + "name": "angular-content-projection-default", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/57-content-projection-default/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/57-content-projection-default", + "index": "apps/angular/57-content-projection-default/src/index.html", + "browser": "apps/angular/57-content-projection-default/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/57-content-projection-default/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/57-content-projection-default/public" + } + ], + "styles": [ + "apps/angular/57-content-projection-default/src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kb", + "maximumError": "8kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-content-projection-default:build:production" + }, + "development": { + "buildTarget": "angular-content-projection-default:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-content-projection-default:build" + } + }, + "serve-static": { + "executor": "@nx/web:file-server", + "options": { + "buildTarget": "angular-content-projection-default:build", + "staticFilePath": "dist/apps/angular/57-content-projection-default/browser", + "spa": true + } + } + } +} diff --git a/apps/ngrx/2-effect-vs-selector/src/favicon.ico b/apps/angular/57-content-projection-default/public/favicon.ico similarity index 100% rename from apps/ngrx/2-effect-vs-selector/src/favicon.ico rename to apps/angular/57-content-projection-default/public/favicon.ico diff --git a/apps/angular/57-content-projection-default/src/app/app.component.ts b/apps/angular/57-content-projection-default/src/app/app.component.ts new file mode 100644 index 000000000..b3e370a34 --- /dev/null +++ b/apps/angular/57-content-projection-default/src/app/app.component.ts @@ -0,0 +1,16 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { CardComponent } from './card.component'; + +@Component({ + imports: [CardComponent], + selector: 'app-root', + template: ` + + + `, + host: { + class: 'p-4 block flex flex-col gap-1', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent {} diff --git a/apps/angular/57-content-projection-default/src/app/app.config.ts b/apps/angular/57-content-projection-default/src/app/app.config.ts new file mode 100644 index 000000000..034603cfd --- /dev/null +++ b/apps/angular/57-content-projection-default/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [provideZoneChangeDetection({ eventCoalescing: true })], +}; diff --git a/apps/angular/57-content-projection-default/src/app/card.component.ts b/apps/angular/57-content-projection-default/src/app/card.component.ts new file mode 100644 index 000000000..851a6619d --- /dev/null +++ b/apps/angular/57-content-projection-default/src/app/card.component.ts @@ -0,0 +1,22 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; + +@Component({ + selector: 'app-card', + imports: [], + template: ` +
{{ title() }}
+ @if (message()) { +
{{ message() }}
+ } @else { +
Aucun message
+ } + `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'p-4 border border-grey rounded-sm flex flex-col w-[200px]', + }, +}) +export class CardComponent { + title = input.required(); + message = input(undefined); +} diff --git a/apps/ngrx/7-power-of-effect/src/index.html b/apps/angular/57-content-projection-default/src/index.html similarity index 84% rename from apps/ngrx/7-power-of-effect/src/index.html rename to apps/angular/57-content-projection-default/src/index.html index 91cf31032..8b3015d4b 100644 --- a/apps/ngrx/7-power-of-effect/src/index.html +++ b/apps/angular/57-content-projection-default/src/index.html @@ -2,7 +2,7 @@ - ngrx-power-of-effect + angular-content-projection-default diff --git a/apps/ngrx/7-power-of-effect/src/main.ts b/apps/angular/57-content-projection-default/src/main.ts similarity index 99% rename from apps/ngrx/7-power-of-effect/src/main.ts rename to apps/angular/57-content-projection-default/src/main.ts index 6f91f21a3..f3a7223da 100644 --- a/apps/ngrx/7-power-of-effect/src/main.ts +++ b/apps/angular/57-content-projection-default/src/main.ts @@ -1,8 +1,6 @@ -import { appConfig } from './app/app.config'; - import { bootstrapApplication } from '@angular/platform-browser'; - import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err), diff --git a/apps/ngrx/7-power-of-effect/src/styles.scss b/apps/angular/57-content-projection-default/src/styles.scss similarity index 57% rename from apps/ngrx/7-power-of-effect/src/styles.scss rename to apps/angular/57-content-projection-default/src/styles.scss index 90d4ee007..77e408aa8 100644 --- a/apps/ngrx/7-power-of-effect/src/styles.scss +++ b/apps/angular/57-content-projection-default/src/styles.scss @@ -1 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + /* You can add global styles to this file, and also import other style files */ diff --git a/apps/angular/57-content-projection-default/tailwind.config.js b/apps/angular/57-content-projection-default/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/angular/57-content-projection-default/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/angular/57-content-projection-default/tsconfig.app.json b/apps/angular/57-content-projection-default/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/angular/57-content-projection-default/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/57-content-projection-default/tsconfig.editor.json b/apps/angular/57-content-projection-default/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/57-content-projection-default/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/ngrx/7-power-of-effect/tsconfig.json b/apps/angular/57-content-projection-default/tsconfig.json similarity index 92% rename from apps/ngrx/7-power-of-effect/tsconfig.json rename to apps/angular/57-content-projection-default/tsconfig.json index b2dbbf22e..1b86db04e 100644 --- a/apps/ngrx/7-power-of-effect/tsconfig.json +++ b/apps/angular/57-content-projection-default/tsconfig.json @@ -1,17 +1,7 @@ { - "extends": "../../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.editor.json" - } - ], "compilerOptions": { - "target": "es2020", + "target": "es2022", + "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, @@ -19,6 +9,17 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, diff --git a/apps/ngrx/7-power-of-effect/.eslintrc.json b/apps/angular/58-content-projection-condition/.eslintrc.json similarity index 100% rename from apps/ngrx/7-power-of-effect/.eslintrc.json rename to apps/angular/58-content-projection-condition/.eslintrc.json diff --git a/apps/angular/58-content-projection-condition/README.md b/apps/angular/58-content-projection-condition/README.md new file mode 100644 index 000000000..755bd8854 --- /dev/null +++ b/apps/angular/58-content-projection-condition/README.md @@ -0,0 +1,13 @@ +# Content Projection Condition + +> author: thomas-laforge + +### Run Application + +```bash +npx nx serve angular-content-projection-condition +``` + +### Documentation and Instruction + +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/58-content-projection-condition/). diff --git a/apps/angular/58-content-projection-condition/project.json b/apps/angular/58-content-projection-condition/project.json new file mode 100644 index 000000000..42869e68b --- /dev/null +++ b/apps/angular/58-content-projection-condition/project.json @@ -0,0 +1,84 @@ +{ + "name": "angular-content-projection-condition", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/58-content-projection-condition/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/58-content-projection-condition", + "index": "apps/angular/58-content-projection-condition/src/index.html", + "browser": "apps/angular/58-content-projection-condition/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/58-content-projection-condition/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/58-content-projection-condition/public" + } + ], + "styles": [ + "apps/angular/58-content-projection-condition/src/styles.scss" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kb", + "maximumError": "8kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-content-projection-condition:build:production" + }, + "development": { + "buildTarget": "angular-content-projection-condition:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-content-projection-condition:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + }, + "serve-static": { + "executor": "@nx/web:file-server", + "options": { + "buildTarget": "angular-content-projection-condition:build", + "staticFilePath": "dist/apps/angular/58-content-projection-condition/browser", + "spa": true + } + } + } +} diff --git a/apps/ngrx/7-power-of-effect/src/favicon.ico b/apps/angular/58-content-projection-condition/public/favicon.ico similarity index 100% rename from apps/ngrx/7-power-of-effect/src/favicon.ico rename to apps/angular/58-content-projection-condition/public/favicon.ico diff --git a/apps/angular/58-content-projection-condition/src/app/app.component.ts b/apps/angular/58-content-projection-condition/src/app/app.component.ts new file mode 100644 index 000000000..afad56f22 --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/app/app.component.ts @@ -0,0 +1,22 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { CardComponent } from './card.component'; + +@Component({ + imports: [CardComponent], + selector: 'app-root', + template: ` + +
Card 1
+
Message 1
+
+ +
Card 2
+
Message 2
+
+ `, + host: { + class: 'p-4 block flex flex-col gap-1', + }, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AppComponent {} diff --git a/apps/angular/58-content-projection-condition/src/app/app.config.ts b/apps/angular/58-content-projection-condition/src/app/app.config.ts new file mode 100644 index 000000000..034603cfd --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/app/app.config.ts @@ -0,0 +1,5 @@ +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; + +export const appConfig: ApplicationConfig = { + providers: [provideZoneChangeDetection({ eventCoalescing: true })], +}; diff --git a/apps/angular/58-content-projection-condition/src/app/card.component.ts b/apps/angular/58-content-projection-condition/src/app/card.component.ts new file mode 100644 index 000000000..46925977c --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/app/card.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; + +@Component({ + selector: 'app-card', + template: ` + @if (small()) { + + + } @else { +
+
+ +
+ +
+ } + `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'p-4 border border-grey rounded-sm flex flex-col w-[200px]', + }, +}) +export class CardComponent { + small = input(false); +} diff --git a/apps/angular/58-content-projection-condition/src/index.html b/apps/angular/58-content-projection-condition/src/index.html new file mode 100644 index 000000000..f1768ec71 --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/index.html @@ -0,0 +1,13 @@ + + + + + angular-content-projection-condition + + + + + + + + diff --git a/apps/ngrx/2-effect-vs-selector/src/main.ts b/apps/angular/58-content-projection-condition/src/main.ts similarity index 65% rename from apps/ngrx/2-effect-vs-selector/src/main.ts rename to apps/angular/58-content-projection-condition/src/main.ts index 31c2a3482..f3a7223da 100644 --- a/apps/ngrx/2-effect-vs-selector/src/main.ts +++ b/apps/angular/58-content-projection-condition/src/main.ts @@ -1,6 +1,7 @@ import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; - import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; -bootstrapApplication(AppComponent, appConfig); +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/58-content-projection-condition/src/styles.scss b/apps/angular/58-content-projection-condition/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/angular/58-content-projection-condition/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/angular/58-content-projection-condition/tailwind.config.js b/apps/angular/58-content-projection-condition/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/angular/58-content-projection-condition/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/angular/58-content-projection-condition/tsconfig.app.json b/apps/angular/58-content-projection-condition/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/angular/58-content-projection-condition/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/58-content-projection-condition/tsconfig.editor.json b/apps/angular/58-content-projection-condition/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/58-content-projection-condition/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/ngrx/2-effect-vs-selector/tsconfig.json b/apps/angular/58-content-projection-condition/tsconfig.json similarity index 89% rename from apps/ngrx/2-effect-vs-selector/tsconfig.json rename to apps/angular/58-content-projection-condition/tsconfig.json index 52eb4f718..1b86db04e 100644 --- a/apps/ngrx/2-effect-vs-selector/tsconfig.json +++ b/apps/angular/58-content-projection-condition/tsconfig.json @@ -1,20 +1,7 @@ { - "extends": "../../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.editor.json" - } - ], "compilerOptions": { - "target": "es2020", + "target": "es2022", + "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, @@ -22,6 +9,17 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, diff --git a/libs/power-of-effect/model/.eslintrc.json b/apps/angular/59-content-projection-defer/.eslintrc.json similarity index 86% rename from libs/power-of-effect/model/.eslintrc.json rename to apps/angular/59-content-projection-defer/.eslintrc.json index 9247a6e3c..995177b5b 100644 --- a/libs/power-of-effect/model/.eslintrc.json +++ b/apps/angular/59-content-projection-defer/.eslintrc.json @@ -9,11 +9,12 @@ "plugin:@angular-eslint/template/process-inline-templates" ], "rules": { + "@angular-eslint/component-class-suffix": "off", "@angular-eslint/directive-selector": [ "error", { "type": "attribute", - "prefix": "lib", + "prefix": "app", "style": "camelCase" } ], @@ -21,7 +22,7 @@ "error", { "type": "element", - "prefix": "lib", + "prefix": "app", "style": "kebab-case" } ] diff --git a/apps/ngrx/2-effect-vs-selector/README.md b/apps/angular/59-content-projection-defer/README.md similarity index 54% rename from apps/ngrx/2-effect-vs-selector/README.md rename to apps/angular/59-content-projection-defer/README.md index 44640737e..f726842d1 100644 --- a/apps/ngrx/2-effect-vs-selector/README.md +++ b/apps/angular/59-content-projection-defer/README.md @@ -1,13 +1,13 @@ -# Effect vs Selector +# content-projection-defer > author: thomas-laforge ### Run Application ```bash -npx nx serve ngrx-effect-vs-selector +npx nx serve angular-content-projection-defer ``` ### Documentation and Instruction -Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/ngrx/2-effect-selector/). +Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/59-content-projection-defer/). diff --git a/apps/angular/59-content-projection-defer/project.json b/apps/angular/59-content-projection-defer/project.json new file mode 100644 index 000000000..5572ab573 --- /dev/null +++ b/apps/angular/59-content-projection-defer/project.json @@ -0,0 +1,82 @@ +{ + "name": "angular-content-projection-defer", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "prefix": "app", + "sourceRoot": "apps/angular/59-content-projection-defer/src", + "tags": [], + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:application", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "dist/apps/angular/59-content-projection-defer", + "index": "apps/angular/59-content-projection-defer/src/index.html", + "browser": "apps/angular/59-content-projection-defer/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "apps/angular/59-content-projection-defer/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + { + "glob": "**/*", + "input": "apps/angular/59-content-projection-defer/public" + } + ], + "styles": ["apps/angular/59-content-projection-defer/src/styles.scss"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "4kb", + "maximumError": "8kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "angular-content-projection-defer:build:production" + }, + "development": { + "buildTarget": "angular-content-projection-defer:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "angular-content-projection-defer:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + }, + "serve-static": { + "executor": "@nx/web:file-server", + "options": { + "buildTarget": "angular-content-projection-defer:build", + "staticFilePath": "dist/apps/angular/59-content-projection-defer/browser", + "spa": true + } + } + } +} diff --git a/apps/angular/59-content-projection-defer/public/favicon.ico b/apps/angular/59-content-projection-defer/public/favicon.ico new file mode 100644 index 000000000..317ebcb23 Binary files /dev/null and b/apps/angular/59-content-projection-defer/public/favicon.ico differ diff --git a/apps/angular/59-content-projection-defer/src/app/app.component.ts b/apps/angular/59-content-projection-defer/src/app/app.component.ts new file mode 100644 index 000000000..ae40bc880 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/app.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { RouterLink, RouterOutlet } from '@angular/router'; + +@Component({ + imports: [RouterOutlet, RouterLink], + selector: 'app-root', + template: ` +
+ + +
+ + `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'flex flex-col gap-2 ', + }, +}) +export class AppComponent {} diff --git a/apps/angular/59-content-projection-defer/src/app/app.config.ts b/apps/angular/59-content-projection-defer/src/app/app.config.ts new file mode 100644 index 000000000..faf4d099a --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/app.config.ts @@ -0,0 +1,12 @@ +import { provideHttpClient } from '@angular/common/http'; +import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; +import { provideRouter } from '@angular/router'; +import { appRoutes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(appRoutes), + provideHttpClient(), + ], +}; diff --git a/apps/angular/59-content-projection-defer/src/app/app.routes.ts b/apps/angular/59-content-projection-defer/src/app/app.routes.ts new file mode 100644 index 000000000..3ca1b67cc --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/app.routes.ts @@ -0,0 +1,13 @@ +import { Route } from '@angular/router'; + +export const appRoutes: Route[] = [ + { + path: 'page-1', + loadComponent: () => import('./page-1').then((m) => m.Page1), + }, + { + path: 'page-2', + loadComponent: () => import('./page-2').then((m) => m.Page2), + }, + { path: '**', redirectTo: 'page-1' }, +]; diff --git a/apps/angular/59-content-projection-defer/src/app/expandable-card.ts b/apps/angular/59-content-projection-defer/src/app/expandable-card.ts new file mode 100644 index 000000000..8f446ed80 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/expandable-card.ts @@ -0,0 +1,54 @@ +import { ChangeDetectionStrategy, Component, signal } from '@angular/core'; + +@Component({ + selector: 'app-expandable-card', + template: ` + + +
+ +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + host: { + class: 'flex flex-col gap-2 ', + }, +}) +export class ExpandableCard { + public isExpanded = signal(false); +} diff --git a/apps/angular/59-content-projection-defer/src/app/page-1.ts b/apps/angular/59-content-projection-defer/src/app/page-1.ts new file mode 100644 index 000000000..868d76959 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/page-1.ts @@ -0,0 +1,10 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'app-page-1', + template: ` + page1 + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class Page1 {} diff --git a/apps/angular/59-content-projection-defer/src/app/page-2.ts b/apps/angular/59-content-projection-defer/src/app/page-2.ts new file mode 100644 index 000000000..5665466d8 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/app/page-2.ts @@ -0,0 +1,43 @@ +import { httpResource } from '@angular/common/http'; +import { + ChangeDetectionStrategy, + Component, + ResourceStatus, +} from '@angular/core'; +import { ExpandableCard } from './expandable-card'; + +interface Post { + id: number; + title: string; + body: string; + userId: number; +} + +@Component({ + selector: 'app-page-2', + template: ` + page2 + +
Load Post
+
+ @if (postResource.isLoading()) { + Loading... + } @else if (postResource.status() === ResourceStatus.Error) { + Error... + } @else { + @for (post of postResource.value(); track post.id) { +
{{ post.title }}
+ } + } +
+
+ `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ExpandableCard], +}) +export class Page2 { + public postResource = httpResource( + 'https://jsonplaceholder.typicode.com/posts', + ); + protected readonly ResourceStatus = ResourceStatus; +} diff --git a/apps/ngrx/2-effect-vs-selector/src/index.html b/apps/angular/59-content-projection-defer/src/index.html similarity index 84% rename from apps/ngrx/2-effect-vs-selector/src/index.html rename to apps/angular/59-content-projection-defer/src/index.html index d3a909e3b..79f435fa6 100644 --- a/apps/ngrx/2-effect-vs-selector/src/index.html +++ b/apps/angular/59-content-projection-defer/src/index.html @@ -2,7 +2,7 @@ - ngrx-effect-vs-selector + angular-content-projection-defer diff --git a/apps/angular/59-content-projection-defer/src/main.ts b/apps/angular/59-content-projection-defer/src/main.ts new file mode 100644 index 000000000..f3a7223da --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/main.ts @@ -0,0 +1,7 @@ +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; + +bootstrapApplication(AppComponent, appConfig).catch((err) => + console.error(err), +); diff --git a/apps/angular/59-content-projection-defer/src/styles.scss b/apps/angular/59-content-projection-defer/src/styles.scss new file mode 100644 index 000000000..77e408aa8 --- /dev/null +++ b/apps/angular/59-content-projection-defer/src/styles.scss @@ -0,0 +1,5 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* You can add global styles to this file, and also import other style files */ diff --git a/apps/angular/59-content-projection-defer/tailwind.config.js b/apps/angular/59-content-projection-defer/tailwind.config.js new file mode 100644 index 000000000..38183db2c --- /dev/null +++ b/apps/angular/59-content-projection-defer/tailwind.config.js @@ -0,0 +1,14 @@ +const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind'); +const { join } = require('path'); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'), + ...createGlobPatternsForDependencies(__dirname), + ], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/angular/59-content-projection-defer/tsconfig.app.json b/apps/angular/59-content-projection-defer/tsconfig.app.json new file mode 100644 index 000000000..58220429a --- /dev/null +++ b/apps/angular/59-content-projection-defer/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/apps/angular/59-content-projection-defer/tsconfig.editor.json b/apps/angular/59-content-projection-defer/tsconfig.editor.json new file mode 100644 index 000000000..a8ac182c0 --- /dev/null +++ b/apps/angular/59-content-projection-defer/tsconfig.editor.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"], + "compilerOptions": {}, + "exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"] +} diff --git a/libs/power-of-effect/backend/tsconfig.json b/apps/angular/59-content-projection-defer/tsconfig.json similarity index 81% rename from libs/power-of-effect/backend/tsconfig.json rename to apps/angular/59-content-projection-defer/tsconfig.json index 7504c346e..1b86db04e 100644 --- a/libs/power-of-effect/backend/tsconfig.json +++ b/apps/angular/59-content-projection-defer/tsconfig.json @@ -1,17 +1,7 @@ { - "extends": "../../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], "compilerOptions": { - "target": "es2020", + "target": "es2022", + "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, @@ -19,6 +9,17 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.editor.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + "extends": "../../../tsconfig.base.json", "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, diff --git a/apps/angular/6-structural-directive/src/app/app.component.ts b/apps/angular/6-structural-directive/src/app/app.component.ts index d89a2f579..a3d63b374 100644 --- a/apps/angular/6-structural-directive/src/app/app.component.ts +++ b/apps/angular/6-structural-directive/src/app/app.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ - standalone: true, imports: [RouterOutlet], selector: 'app-root', template: ` diff --git a/apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts b/apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts index 72e4b3bef..26bb23284 100644 --- a/apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts +++ b/apps/angular/6-structural-directive/src/app/dashboard/admin.component.ts @@ -4,7 +4,6 @@ import { ButtonComponent } from '../button.component'; @Component({ selector: 'app-dashboard', - standalone: true, imports: [RouterLink, ButtonComponent], template: `

dashboard for Admin works!

diff --git a/apps/angular/6-structural-directive/src/app/information.component.ts b/apps/angular/6-structural-directive/src/app/information.component.ts index e4adeb1b9..81b339520 100644 --- a/apps/angular/6-structural-directive/src/app/information.component.ts +++ b/apps/angular/6-structural-directive/src/app/information.component.ts @@ -4,7 +4,6 @@ import { UserStore } from './user.store'; @Component({ selector: 'app-information', - standalone: true, imports: [CommonModule], template: `

Information Panel

diff --git a/apps/angular/6-structural-directive/src/app/login.component.ts b/apps/angular/6-structural-directive/src/app/login.component.ts index cd36d9603..b8644ed38 100644 --- a/apps/angular/6-structural-directive/src/app/login.component.ts +++ b/apps/angular/6-structural-directive/src/app/login.component.ts @@ -14,7 +14,6 @@ import { import { UserStore } from './user.store'; @Component({ - standalone: true, imports: [InformationComponent, RouterLink, ButtonComponent], selector: 'app-login', template: ` diff --git a/apps/angular/8-pure-pipe/src/app/app.component.ts b/apps/angular/8-pure-pipe/src/app/app.component.ts index 3c19fa169..41dd38e25 100644 --- a/apps/angular/8-pure-pipe/src/app/app.component.ts +++ b/apps/angular/8-pure-pipe/src/app/app.component.ts @@ -2,7 +2,6 @@ import { NgFor } from '@angular/common'; import { Component } from '@angular/core'; @Component({ - standalone: true, imports: [NgFor], selector: 'app-root', template: ` diff --git a/apps/angular/9-wrap-function-pipe/src/app/app.component.ts b/apps/angular/9-wrap-function-pipe/src/app/app.component.ts index d9c163c93..dd576ae49 100644 --- a/apps/angular/9-wrap-function-pipe/src/app/app.component.ts +++ b/apps/angular/9-wrap-function-pipe/src/app/app.component.ts @@ -2,7 +2,6 @@ import { NgFor } from '@angular/common'; import { Component } from '@angular/core'; @Component({ - standalone: true, imports: [NgFor], selector: 'app-root', template: ` diff --git a/apps/forms/41-control-value-accessor/project.json b/apps/forms/41-control-value-accessor/project.json index d958888de..a1ec26bac 100644 --- a/apps/forms/41-control-value-accessor/project.json +++ b/apps/forms/41-control-value-accessor/project.json @@ -66,10 +66,14 @@ } }, "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/forms/41-control-value-accessor/jest.config.ts" + "passWithNoTests": true + }, + "configurations": { + "ci": { + "ci": true, + "coverage": true + } } } } diff --git a/apps/forms/41-control-value-accessor/src/app/app.component.ts b/apps/forms/41-control-value-accessor/src/app/app.component.ts index f56b5d7d9..69134b864 100644 --- a/apps/forms/41-control-value-accessor/src/app/app.component.ts +++ b/apps/forms/41-control-value-accessor/src/app/app.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { FeedbackFormComponent } from './feedback-form/feedback-form.component'; @Component({ - standalone: true, imports: [FeedbackFormComponent], selector: 'app-root', template: ` diff --git a/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts index d99700db1..4110d6cf7 100644 --- a/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts +++ b/apps/forms/41-control-value-accessor/src/app/feedback-form/feedback-form.component.ts @@ -8,7 +8,6 @@ import { import { RatingControlComponent } from '../rating-control/rating-control.component'; @Component({ - standalone: true, imports: [RatingControlComponent, ReactiveFormsModule], selector: 'app-feedback-form', templateUrl: 'feedback-form.component.html', diff --git a/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts index 6ac465e12..2b5adc443 100644 --- a/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts +++ b/apps/forms/48-avoid-losing-form-data/src/app/app.component.ts @@ -3,7 +3,6 @@ import { RouterOutlet } from '@angular/router'; import { NavComponent } from './ui/nav.component'; @Component({ - standalone: true, imports: [RouterOutlet, NavComponent], selector: 'app-root', template: ` diff --git a/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts index 6f5fea9af..51449a7fb 100644 --- a/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts +++ b/apps/forms/48-avoid-losing-form-data/src/app/pages/join.component.ts @@ -2,7 +2,6 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FormComponent } from '../ui/form.component'; @Component({ - standalone: true, imports: [FormComponent], template: `
diff --git a/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts index 2b28c540f..f3190d517 100644 --- a/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts +++ b/apps/forms/48-avoid-losing-form-data/src/app/ui/form.component.ts @@ -3,7 +3,6 @@ import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; @Component({ selector: 'app-form', - standalone: true, imports: [ReactiveFormsModule], template: `
diff --git a/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts b/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts index 491aecac9..269297280 100644 --- a/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts +++ b/apps/forms/48-avoid-losing-form-data/src/app/ui/nav.component.ts @@ -3,7 +3,6 @@ import { RouterLink, RouterLinkActive } from '@angular/router'; @Component({ selector: 'app-nav', - standalone: true, imports: [RouterLink, RouterLinkActive], template: `