Browse Source

4.4: Advanced generics.

Frederic G. MARAND 5 years ago
parent
commit
eb773fb3ac

+ 0 - 6
.idea/inspectionProfiles/profiles_settings.xml

@@ -1,6 +0,0 @@
-<component name="InspectionProjectProfileManager">
-  <settings>
-    <option name="PROJECT_PROFILE" />
-    <version value="1.0" />
-  </settings>
-</component>

+ 91 - 57
.idea/workspace.xml

@@ -2,9 +2,21 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="c6f02f4e-af06-43d1-8bc0-507af01d0573" name="Default Changelist" comment="">
-      <change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" beforeDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/course/package.json" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/app.module.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/app.module.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/create-report-item.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/create-report-item.component.html" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/create-report-item.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/create-report-item.component.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/create-report.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/create-report.component.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/edit-report.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/edit-report.component.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/reports.component.css" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/reports.component.css" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/reports.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/reports.component.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/services/messenger.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/services/messenger.service.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/services/reportData.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/services/reportData.service.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/src/app/types.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/types.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/course/tsconfig.json" beforeDir="false" afterPath="$PROJECT_DIR$/course/tsconfig.json" afterDir="false" />
     </list>
     <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
     <option name="TRACKING_ENABLED" value="true" />
@@ -73,29 +85,20 @@
   </component>
   <component name="FileEditorManager">
     <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
-      <file leaf-file-name="app.d.ts" pinned="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/course/src/app.d.ts">
+      <file leaf-file-name="reportData.service.ts" pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/course/src/app/services/reportData.service.ts">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="330">
-              <caret line="22" column="47" selection-start-line="22" selection-start-column="47" selection-end-line="22" selection-end-column="47" />
+            <state relative-caret-position="340">
+              <caret line="19" column="4" selection-start-line="19" selection-start-column="4" selection-end-line="19" selection-end-column="4" />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name=".gitignore" pinned="false" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/.gitignore">
+      <file leaf-file-name="reportItem.service.ts" pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/course/src/app/services/reportItem.service.ts">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="34">
-              <caret line="2" column="17" selection-start-line="2" selection-start-column="17" selection-end-line="2" selection-end-column="17" />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="create-report.component.ts" pinned="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/course/src/app/create-report.component.ts">
-          <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="629">
-              <caret line="37" column="33" selection-start-line="37" selection-start-column="33" selection-end-line="37" selection-end-column="33" />
+            <state relative-caret-position="476">
+              <caret line="28" column="1" lean-forward="true" selection-start-line="28" selection-start-column="1" selection-end-line="28" selection-end-column="1" />
             </state>
           </provider>
         </entry>
@@ -121,6 +124,7 @@
       <find>&quot;</find>
       <find>pse</find>
       <find>app.d</find>
+      <find>filter</find>
     </findStrings>
     <replaceStrings>
       <replace>'</replace>
@@ -143,15 +147,15 @@
         <option value="$PROJECT_DIR$/course/src/app/edit-report.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/services/messenger.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/types.ts" />
-        <option value="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/create-report-item.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/reports.component.ts" />
-        <option value="$PROJECT_DIR$/course/src/app/services/reportData.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/create-report.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/app.d.ts" />
         <option value="$PROJECT_DIR$/course/tsconfig.json" />
         <option value="$PROJECT_DIR$/course/src/app.d.ts" />
         <option value="$PROJECT_DIR$/.gitignore" />
+        <option value="$PROJECT_DIR$/course/src/app/services/reportData.service.ts" />
+        <option value="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" />
       </list>
     </option>
   </component>
@@ -161,9 +165,6 @@
     <detection-done>true</detection-done>
     <sorting>DEFINITION_ORDER</sorting>
   </component>
-  <component name="NodeModulesDirectoryManager">
-    <handled-path value="$PROJECT_DIR$/course/node_modules" />
-  </component>
   <component name="NodePackageJsonFileManager">
     <packageJsonPaths>
       <path value="$PROJECT_DIR$/course/package.json" />
@@ -174,8 +175,8 @@
   </component>
   <component name="ProjectFrameBounds" extendedState="6">
     <option name="y" value="23" />
-    <option name="width" value="1440" />
-    <option name="height" value="877" />
+    <option name="width" value="1680" />
+    <option name="height" value="1027" />
   </component>
   <component name="ProjectInspectionProfilesVisibleTreeState">
     <entry key="Project Default">
@@ -207,16 +208,49 @@
               <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
               <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
             </path>
+            <path>
+              <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
+              <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
+              <item name="04" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
+              <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
+              <item name="04" type="462c0819:PsiDirectoryNode" />
+              <item name="demos" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
+              <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
+              <item name="04" type="462c0819:PsiDirectoryNode" />
+              <item name="demos" type="462c0819:PsiDirectoryNode" />
+              <item name="After" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
+              <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
+              <item name="course" type="462c0819:PsiDirectoryNode" />
+            </path>
             <path>
               <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
               <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
               <item name="course" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
             </path>
             <path>
               <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
               <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
               <item name="course" type="462c0819:PsiDirectoryNode" />
               <item name="src" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+            </path>
+            <path>
+              <item name="PluralSight_TS_2" type="b2602c69:ProjectViewProjectNode" />
+              <item name="PluralSight_TS_2" type="462c0819:PsiDirectoryNode" />
+              <item name="course" type="462c0819:PsiDirectoryNode" />
+              <item name="src" type="462c0819:PsiDirectoryNode" />
+              <item name="app" type="462c0819:PsiDirectoryNode" />
+              <item name="services" type="462c0819:PsiDirectoryNode" />
             </path>
           </expand>
           <select />
@@ -291,12 +325,12 @@
       <workItem from="1535304176395" duration="75000" />
       <workItem from="1535304274687" duration="6343000" />
       <workItem from="1535393199806" duration="14824000" />
-      <workItem from="1535540864083" duration="19000" />
+      <workItem from="1535540864083" duration="1750000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="21261000" />
+    <option name="totallyTimeSpent" value="22992000" />
   </component>
   <component name="ToolWindowManager">
     <frame x="0" y="23" width="1677" height="1027" extended-state="6" />
@@ -306,13 +340,15 @@
       <window_info anchor="bottom" id="Event Log" order="0" sideWeight="0.5007153" side_tool="true" weight="0.3299363" />
       <window_info anchor="bottom" id="Database Changes" order="12" show_stripe_button="false" />
       <window_info anchor="bottom" id="Version Control" order="1" />
-      <window_info anchor="bottom" id="Run" order="6" sideWeight="0.49928468" weight="0.23694268" />
+      <window_info active="true" anchor="bottom" id="Run" order="6" sideWeight="0.49928468" visible="true" weight="0.23655914" />
       <window_info anchor="right" id="Mongo Explorer" order="1" />
       <window_info anchor="bottom" id="Terminal" order="2" />
       <window_info anchor="right" id="Remote Host" order="6" show_stripe_button="false" />
-      <window_info active="true" anchor="right" content_ui="combo" id="Project" order="5" sideWeight="0.49415693" visible="true" weight="0.2617737" />
+      <window_info anchor="bottom" id="TypeScript" order="13" />
+      <window_info anchor="right" content_ui="combo" id="Project" order="5" sideWeight="0.49415693" visible="true" weight="0.2617737" />
       <window_info anchor="bottom" id="Docker" order="11" />
       <window_info anchor="right" id="Database" order="0" />
+      <window_info anchor="bottom" id="Find" order="5" weight="0.3299363" />
       <window_info id="Structure" order="1" side_tool="true" visible="true" weight="0.1792049" />
       <window_info id="Favorites" order="0" side_tool="true" />
       <window_info anchor="bottom" id="Debug" order="7" weight="0.4" />
@@ -323,8 +359,6 @@
       <window_info anchor="bottom" id="Cvs" order="8" weight="0.25" />
       <window_info anchor="right" id="Commander" order="2" weight="0.4" />
       <window_info anchor="right" id="Ant Build" order="3" weight="0.25" />
-      <window_info anchor="bottom" id="TypeScript" order="13" />
-      <window_info anchor="bottom" id="Find" order="5" weight="0.3299363" />
       <window_info anchor="right" x="0" y="0" width="310" height="677" id="Documentation" order="7" sideWeight="0.50584304" side_tool="true" weight="0.25894135" />
       <window_info anchor="bottom" id="Message" order="4" />
     </layout>
@@ -474,13 +508,6 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app/services/reportItem.service.ts">
-      <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="153">
-          <caret line="35" column="1" lean-forward="true" selection-start-line="35" selection-start-column="1" selection-end-line="35" selection-end-column="1" />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/course/src/app/services/messenger.service.ts">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="213">
@@ -530,45 +557,52 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app/services/reportData.service.ts">
+    <entry file="file://$PROJECT_DIR$/course/tsconfig.json">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="178">
-          <caret line="65" column="21" selection-start-line="65" selection-start-column="21" selection-end-line="65" selection-end-column="21" />
+        <state relative-caret-position="360">
+          <caret line="24" column="3" lean-forward="true" selection-start-line="24" selection-start-column="3" selection-end-line="24" selection-end-column="3" />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app/create-report.component.ts">
+    <entry file="file://$PROJECT_DIR$/course/src/tsconfig.app.json">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="629">
-          <caret line="37" column="33" selection-start-line="37" selection-start-column="33" selection-end-line="37" selection-end-column="33" />
+        <state relative-caret-position="195">
+          <caret line="13" lean-forward="true" selection-start-line="13" selection-end-line="13" />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/tsconfig.json">
+    <entry file="file://$PROJECT_DIR$/.gitignore">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="360">
-          <caret line="24" column="3" lean-forward="true" selection-start-line="24" selection-start-column="3" selection-end-line="24" selection-end-column="3" />
+        <state relative-caret-position="34">
+          <caret line="2" column="17" selection-start-line="2" selection-start-column="17" selection-end-line="2" selection-end-column="17" />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/tsconfig.app.json">
+    <entry file="file://$PROJECT_DIR$/course/src/app.d.ts">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="195">
-          <caret line="13" lean-forward="true" selection-start-line="13" selection-end-line="13" />
+        <state relative-caret-position="381">
+          <caret line="25" column="1" lean-forward="true" selection-start-line="25" selection-start-column="1" selection-end-line="25" selection-end-column="1" />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app.d.ts">
+    <entry file="file://$PROJECT_DIR$/course/src/app/create-report.component.ts">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="330">
-          <caret line="22" column="47" selection-start-line="22" selection-start-column="47" selection-end-line="22" selection-end-column="47" />
+        <state relative-caret-position="459">
+          <caret line="37" column="33" selection-start-line="37" selection-start-column="33" selection-end-line="37" selection-end-column="33" />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/.gitignore">
+    <entry file="file://$PROJECT_DIR$/course/src/app/services/reportData.service.ts">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="34">
-          <caret line="2" column="17" selection-start-line="2" selection-start-column="17" selection-end-line="2" selection-end-column="17" />
+        <state relative-caret-position="340">
+          <caret line="19" column="4" selection-start-line="19" selection-start-column="4" selection-end-line="19" selection-end-column="4" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/course/src/app/services/reportItem.service.ts">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="476">
+          <caret line="28" column="1" lean-forward="true" selection-start-line="28" selection-start-column="1" selection-end-line="28" selection-end-column="1" />
         </state>
       </provider>
     </entry>

+ 11 - 11
course/package.json

@@ -1,6 +1,16 @@
 {
   "author": "Thiago Temple",
   "description": "PluralSight Typescript courses by Thiago Temple",
+  "name": "ps-expenses",
+  "version": "0.0.0",
+  "license": "MIT",
+  "scripts": {
+    "ng": "ng",
+    "start": "ng serve",
+    "build": "ng build",
+    "lint": "ng lint"
+  },
+  "private": true,
   "dependencies": {
     "@angular/animations": "^5.0.1",
     "@angular/cdk": "^5.0.0",
@@ -28,15 +38,5 @@
     "webpack": "^3.8.1",
     "webpack-dev-server": "^2.9.4",
     "webpack-merge": "^4.1.1"
-  },
-  "license": "MIT",
-  "name": "ps-expenses",
-  "private": true,
-  "scripts": {
-    "ng": "ng",
-    "start": "ng serve",
-    "build": "ng build",
-    "lint": "ng lint"
-  },
-  "version": "0.0.0"
+  }
 }

+ 3 - 3
course/src/app/app.module.ts

@@ -14,7 +14,7 @@ import {
   MatCheckboxModule,
   MatSelectModule,
   MatDatepickerModule,
-  MatNativeDateModule,
+  MatNativeDateModule
 } from '@angular/material';
 
 import { PsRootComponent } from './root.component';
@@ -32,7 +32,7 @@ export const initApp = (messengerWatcher: MessengerWatcher) => () => {
   messengerWatcher.watch();
 }
 
-export const initMessengerWatcher = (reportDataService: ReportDataService) => 
+export const initMessengerWatcher = (reportDataService: ReportDataService) =>
   new MessengerWatcher(reportDataService);
 
 @NgModule({
@@ -67,7 +67,7 @@ export const initMessengerWatcher = (reportDataService: ReportDataService) =>
     {
       provide: MessengerWatcher,
       deps: [ReportDataService],
-      useFactory: initMessengerWatcher
+      useFactory: initMessengerWatcher 
     },
     {
       provide: APP_INITIALIZER,

+ 2 - 2
course/src/app/create-report-item.component.html

@@ -10,7 +10,7 @@
     </mat-form-field>
 
     <mat-form-field>
-        <input matInput [matDatepicker]="picker" placeholder="Choose a date" [(ngModel)]="item.date">
+        <input matInput [matDatepicker]="picker" placeholder="Choose a date" [(ngModel)]="item.date" (dateChange)="addEvent($event)">
         <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
         <mat-datepicker #picker></mat-datepicker>
     </mat-form-field>
@@ -26,4 +26,4 @@
 <div mat-dialog-actions>
     <button mat-button color="primary" (click)="addItem(item)">Add</button>
     <button mat-button mat-dialog-close>Cancel</button>
-</div>
+</div>

+ 1 - 2
course/src/app/create-report-item.component.ts

@@ -15,7 +15,7 @@ export class CreateReportItemDialogComponent {
         amount: 0,
         hasReceipt: false,
         type: ReportItemType.unselected,
-        date: new Date(),
+        date: new Date()
     };
 
     itemTypeOptions: ReportItemType[] = [
@@ -38,5 +38,4 @@ export class CreateReportItemDialogComponent {
                 this.dialogRef.close(item);
             }
         }
-
 }

+ 1 - 0
course/src/app/create-report.component.ts

@@ -31,6 +31,7 @@ export class CreateReportComponent extends BaseReportComponent {
         this.location.back();
     }
 
+    // Example of how to use our intersection types. Does nothing.
     dragStart(event: DragStartEvent) {
         event.dragStart.posX;
     }

+ 9 - 9
course/src/app/edit-report.component.ts

@@ -26,9 +26,9 @@ export class EditReportComponent extends BaseReportComponent {
             .switchMap(params => reportDataService.getReport(+params.get('id')!))
             .subscribe(report => {
                 if (report) {
-                  this.description = report.description;
-                  this.itemsDataBase.addRange(report.items);
-                  this.report = report;
+                    this.description = report.description;
+                    this.itemsDataBase.addRange(report.items);
+                    this.report = report;
                 } else {
                     console.error('No report found for the specified id');
                 }
@@ -36,12 +36,12 @@ export class EditReportComponent extends BaseReportComponent {
     }
 
     save(): void {
-      const modifiedReport = {
-        ...this.report,
-        description: this.description,
-        items: this.itemsDataBase.data
-      };
-      this.reportDataService.save(modifiedReport);
+        const modifiedReport = {
+            ...this.report,
+            description: this.description,
+            items: this.itemsDataBase.data
+        };
+        this.reportDataService.save(modifiedReport);
         this.location.back();
     }
 }

+ 1 - 0
course/src/app/reports.component.css

@@ -10,6 +10,7 @@
         background: none;
     }
 }
+
 .field-full-width {
     width: 100%
 }

+ 7 - 8
course/src/app/reports.component.ts

@@ -27,6 +27,7 @@ function toggleApprovedStyle(this: HTMLElement, approved: boolean) {
     }
 }
 
+
 @Component({
     selector: 'ps-reports',
     templateUrl: './reports.component.html',
@@ -37,10 +38,10 @@ export class ReportsComponent {
     isAdmin = Observable.of(false);
     displayedColumns = ['id', 'description', 'date', 'amount', 'approved', 'actions'];
 
-  constructor(private route: ActivatedRoute,
+    constructor(private route: ActivatedRoute,
         private reportDataService: ReportDataService,
         @Inject(WindowService) private _window: Window) {
-    this.reports = new MatTableDataSource([]);
+        this.reports = new MatTableDataSource([]);
         this.isAdmin = this.route.queryParamMap.map(mapUser);
 
         reportDataService.dataChange.subscribe(remoteData => {
@@ -52,7 +53,7 @@ export class ReportsComponent {
         // This is called a "discriminated union".
         // Here "kind" is the "discriminant" for the remoteData "discriminated
         // union".
-        switch (remoteData.kind) {
+        switch(remoteData.kind) {
             case 'ok':
                 this.reports.data = remoteData.data;
                 return remoteData.kind;
@@ -78,9 +79,8 @@ export class ReportsComponent {
         this.toggleApprovedStyle(report.id, false);
     }
 
-
     private toggleApprovedStyle(reportId: number, approved: boolean) {
-      setTimeout(() => {
+        setTimeout(() => {
             const row = this._window.document.getElementById(`report$${reportId}`)!.closest('mat-row');
             toggleApprovedStyle.call(row, approved);
         }, 50);
@@ -93,10 +93,9 @@ export class ReportsComponent {
             .take(1)
             .map(params => params.get('user'))
             .subscribe(user => {
-              if (user) {
+                if (user) {
                     this.reportDataService.toggleApproval(report, user);
-              }
+                }
             });
-
     }
 }

+ 2 - 1
course/src/app/services/messenger.service.ts

@@ -13,6 +13,7 @@ class ReportApprovedMessenger implements Messenger {
         console.log(`The report id: ${report.id} is now ${report.approved ? 'approved' : 'rejected'}`);
     }
 }
+    
 
 class ReportRejectMessenger implements Messenger {
     // "noUnusedParameters" doesn't complain about parameters named "_*"
@@ -21,7 +22,7 @@ class ReportRejectMessenger implements Messenger {
     }
 }
 
-type MessengerEventsHandled =
+type MessengerEventsHandled = 
     'MessengerReportCreated' |
     'MessengerReportApproved' |
     'MessengerReportRejected';

+ 20 - 2
course/src/app/services/reportData.service.ts

@@ -4,6 +4,25 @@ import { Subject } from 'rxjs/Subject';
 import { Report, NewReport, PS_REPORTS_KEY, RemoteData, isRemoteDataOK } from '../types';
 import { WindowService } from './window.service';
 
+declare global {
+    interface Array<T> {
+        filterWith<TKey extends keyof T, TValue extends T[TKey]>(member: TKey, value: TValue): T[];
+    }
+}
+
+Array.prototype.filterWith = function<T, TKey extends keyof T, TValue extends T[TKey]>(this: T[], member: TKey, value: TValue): T[] {
+    return this.filter(x => x[member] === value);
+}
+
+// Non-generics version.
+// function filter(reports: Report[], term: string): Report[] {
+//     return reports.filter((r => r.description === term));
+// }
+// Generics versions
+const reports: Report[] = [];
+reports.filterWith('approved', true);
+
+
 @Injectable()
 export class ReportDataService {
     dataChange = new BehaviorSubject<RemoteData<Report[]>>({ kind: "notFetched" });
@@ -81,9 +100,8 @@ export class ReportDataService {
                 this.dataChange.next({
                     kind: 'error',
                     error: 'The were was an issue loading the data'
-                });
+                })
             }
         }, 1000);
     }
-
 }

+ 13 - 15
course/src/app/services/reportItem.service.ts

@@ -6,19 +6,19 @@ function validateRequired(item: ReportItem): boolean {
     const exclude: (keyof ReportItem)[] = ['hasReceipt'];
 
     return Object.keys(item).reduce((isValid, memberKey: keyof ReportItem) => {
-            if (!isValid) {
-                return isValid;
-            }
+        if (!isValid) {
+            return isValid;
+        }
 
-            if (memberKey === 'date') {
-                // date is of type Date, because of the keyof typing.
-                const date = item[memberKey];
-                if (date < new Date(1970)) {
-                    return false;
-                }
+        if (memberKey === 'date') {
+            // date is of type Date, because of the keyof typing.
+            const date = item[memberKey];
+            if (date < new Date(1970)) {
+                return false;
             }
-            return exclude.includes(memberKey) || !!item[memberKey];
-        }, true);
+        }
+        return exclude.includes(memberKey) || !!item[memberKey];
+    }, true);
 }
 
 function validateFoodItem(item: ReportItem): string {
@@ -56,10 +56,9 @@ export class ReportItemService {
     }
 
     isValid(item: ReportItem): string {
-        if (!validateRequired(item)) {
-            return 'Some of the required fields were not filled.'
+        if(!validateRequired(item)) {
+            return 'Some of the required fields where not filled.'
         }
-
         switch (item.type) {
             case ReportItemType.food: {
                 const validatedFood = validateFoodItem(item);
@@ -70,7 +69,6 @@ export class ReportItemService {
             }
             case ReportItemType.training:
                 return validateTraining(item);
-
             case ReportItemType.officeSupplies:
             case ReportItemType.transport:
             case ReportItemType.travel: {

+ 4 - 5
course/src/app/types.ts

@@ -32,26 +32,24 @@ export interface Messenger {
 
 export const PS_REPORTS_KEY = 'ps-reports';
 
+
 type RemoteDataNotFetched = {
     kind: "notFetched";
 };
-
 type RemoteDataLoading = {
     kind: "loading";
 };
-
 type RemoteDataOK<T> = {
     kind: "ok";
     data: T;
 };
-
 type RemoteDataError = {
     kind: "error";
     error: string;
 };
 
 export type RemoteData<T> =
-    RemoteDataNotFetched |
+    RemoteDataNotFetched | 
     RemoteDataLoading |
     RemoteDataOK<T> |
     RemoteDataError;
@@ -59,10 +57,11 @@ export type RemoteData<T> =
 export function isRemoteDataOK<T>(remoteData: RemoteData<T>): remoteData is RemoteDataOK<T> {
     return remoteData.kind === "ok";
 }
+
 export function isRemoteDataError<T>(remoteData: RemoteData<T>): remoteData is RemoteDataError {
     return remoteData.kind === "error";
 }
+
 export function isRemoteDataLoading<T>(remoteData: RemoteData<T>): remoteData is RemoteDataLoading {
     return remoteData.kind === "loading";
 }
-

+ 4 - 1
course/tsconfig.json

@@ -22,5 +22,8 @@
     "typeRoots": [
       "node_modules/@types"
     ]
-  }
+  },
+  "exclude": [
+    "node_modules"
+  ]
 }