Browse Source

3.6: Exhaustive check, discriminations. Code from 03/After.

Frederic G. MARAND 5 years ago
parent
commit
8d6b1f3ffd

+ 51 - 54
.idea/workspace.xml

@@ -2,15 +2,12 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="c6f02f4e-af06-43d1-8bc0-507af01d0573" name="Default Changelist" comment="">
-      <change afterPath="$PROJECT_DIR$/course/src/app/types.ts" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/course/src/app/base-report.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/course/src/app/base-report.component.ts" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" 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.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" />
     </list>
     <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
     <option name="SHOW_DIALOG" value="false" />
@@ -34,31 +31,33 @@
           <entry key="css" value="1" />
           <entry key="gitignore" value="2" />
           <entry key="groovy" value="1" />
+          <entry key="html" value="1" />
           <entry key="json" value="16" />
-          <entry key="ts" value="59" />
+          <entry key="ts" value="65" />
           <entry key="txt" value="1" />
         </counts>
       </usages-collector>
       <usages-collector id="statistics.file.types.open">
         <counts>
           <entry key="CSS" value="1" />
+          <entry key="HTML" value="1" />
           <entry key="JSON" value="3" />
           <entry key="PLAIN_TEXT" value="2" />
           <entry key="Scratch" value="3" />
-          <entry key="TypeScript" value="59" />
+          <entry key="TypeScript" value="65" />
           <entry key="tsconfig" value="13" />
         </counts>
       </usages-collector>
       <usages-collector id="statistics.file.extensions.edit">
         <counts>
           <entry key="json" value="62" />
-          <entry key="ts" value="3768" />
+          <entry key="ts" value="4529" />
         </counts>
       </usages-collector>
       <usages-collector id="statistics.file.types.edit">
         <counts>
           <entry key="JSON" value="5" />
-          <entry key="TypeScript" value="3768" />
+          <entry key="TypeScript" value="4529" />
           <entry key="tsconfig" value="57" />
         </counts>
       </usages-collector>
@@ -77,19 +76,10 @@
   <component name="FileEditorManager">
     <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
       <file pinned="false" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/course/src/app/types.ts">
-          <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="413">
-              <caret line="58" column="37" selection-start-line="58" selection-start-column="37" selection-end-line="58" selection-end-column="37" />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file pinned="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/course/src/app/reports.component.ts">
           <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="352">
-              <caret line="46" column="45" lean-forward="true" selection-start-line="46" selection-start-column="45" selection-end-line="46" selection-end-column="45" />
+            <state relative-caret-position="135">
+              <caret line="9" column="8" selection-start-line="9" selection-start-column="8" selection-end-line="9" selection-end-column="8" />
             </state>
           </provider>
         </entry>
@@ -131,15 +121,15 @@
         <option value="$PROJECT_DIR$/course/src/app/app-routing.module.ts" />
         <option value="$PROJECT_DIR$/course/src/app/app.module.ts" />
         <option value="$PROJECT_DIR$/course/tsconfig.json" />
-        <option value="$PROJECT_DIR$/course/src/app/services/messenger.service.ts" />
-        <option value="$PROJECT_DIR$/course/src/app/services/reportItem.service.ts" />
         <option value="$PROJECT_DIR$/course/src/app/create-report.component.ts" />
-        <option value="$PROJECT_DIR$/course/src/app/create-report-item.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/base-report.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/edit-report.component.ts" />
         <option value="$PROJECT_DIR$/course/src/app/services/reportData.service.ts" />
-        <option value="$PROJECT_DIR$/course/src/app/reports.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" />
       </list>
     </option>
   </component>
@@ -333,12 +323,12 @@
       <updated>1535304175302</updated>
       <workItem from="1535304176395" duration="75000" />
       <workItem from="1535304274687" duration="6343000" />
-      <workItem from="1535393199806" duration="10540000" />
+      <workItem from="1535393199806" duration="11991000" />
     </task>
     <servers />
   </component>
   <component name="TimeTrackingManager">
-    <option name="totallyTimeSpent" value="16958000" />
+    <option name="totallyTimeSpent" value="18409000" />
   </component>
   <component name="ToolWindowManager">
     <frame x="0" y="23" width="1440" height="877" extended-state="6" />
@@ -366,9 +356,9 @@
       <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="right" content_ui="combo" id="Hierarchy" order="4" weight="0.25" />
-      <window_info active="true" anchor="right" content_ui="combo" id="Project" order="5" sideWeight="0.49582636" visible="true" weight="0.25894135" />
+      <window_info anchor="right" content_ui="combo" id="Project" order="5" sideWeight="0.49582636" visible="true" weight="0.25894135" />
       <window_info anchor="right" id="Remote Host" order="6" show_stripe_button="false" />
-      <window_info anchor="right" x="0" y="0" width="310" height="677" id="Documentation" order="7" sideWeight="0.50417364" side_tool="true" weight="0.27110156" />
+      <window_info anchor="right" x="0" y="0" width="310" height="677" id="Documentation" order="7" sideWeight="0.50417364" side_tool="true" weight="0.25894135" />
     </layout>
   </component>
   <component name="TypeScriptGeneratedFilesManager">
@@ -455,13 +445,6 @@
         </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="240">
-          <caret line="15" lean-forward="true" selection-start-line="15" selection-end-line="15" />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/course/src/app/services/window.service.ts">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="45">
@@ -469,13 +452,6 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app/create-report-item.component.ts">
-      <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="300">
-          <caret line="21" column="34" lean-forward="true" selection-start-line="21" selection-start-column="34" selection-end-line="21" selection-end-column="34" />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/course/src/app/create-report.component.ts">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="295">
@@ -483,13 +459,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="15">
-          <caret line="1" column="16" selection-start-line="1" selection-start-column="16" selection-end-line="1" selection-end-column="16" />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/course/src/app/base-report.component.ts">
       <provider selected="true" editor-type-id="text-editor">
         <state relative-caret-position="525">
@@ -553,17 +522,45 @@
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/course/src/app/reports.component.ts">
+    <entry file="file://$PROJECT_DIR$/course/src/app/create-report-item.component.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="285">
+          <caret line="19" column="32" selection-start-line="19" selection-start-column="32" selection-end-line="19" selection-end-column="32" />
+        </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="352">
-          <caret line="46" column="45" lean-forward="true" selection-start-line="46" selection-start-column="45" selection-end-line="46" selection-end-column="45" />
+        <state relative-caret-position="213">
+          <caret line="30" column="38" lean-forward="true" selection-start-line="30" selection-start-column="38" selection-end-line="30" selection-end-column="38" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/course/src/app/create-report-item.component.ts">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="345">
+          <caret line="23" column="38" selection-start-line="23" selection-start-column="38" selection-end-line="23" selection-end-column="38" />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/course/src/app/types.ts">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="413">
-          <caret line="58" column="37" selection-start-line="58" selection-start-column="37" selection-end-line="58" selection-end-column="37" />
+        <state relative-caret-position="144">
+          <caret line="45" column="1" lean-forward="true" selection-start-line="45" selection-start-column="1" selection-end-line="45" selection-end-column="1" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/course/src/app/reports.component.ts">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="135">
+          <caret line="9" column="8" selection-start-line="9" selection-start-column="8" selection-end-line="9" selection-end-column="8" />
         </state>
       </provider>
     </entry>

+ 132 - 66
course/package-lock.json

@@ -3513,24 +3513,28 @@
       "dependencies": {
         "abbrev": {
           "version": "1.1.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+          "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
           "dev": true,
           "optional": true
         },
         "ansi-regex": {
           "version": "2.1.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
           "dev": true
         },
         "aproba": {
           "version": "1.2.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+          "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
           "dev": true,
           "optional": true
         },
         "are-we-there-yet": {
           "version": "1.1.4",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
+          "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3540,12 +3544,14 @@
         },
         "balanced-match": {
           "version": "1.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+          "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
           "dev": true
         },
         "brace-expansion": {
           "version": "1.1.11",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
           "dev": true,
           "requires": {
             "balanced-match": "^1.0.0",
@@ -3554,34 +3560,40 @@
         },
         "chownr": {
           "version": "1.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
+          "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
           "dev": true,
           "optional": true
         },
         "code-point-at": {
           "version": "1.1.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+          "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
           "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+          "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
           "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+          "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
           "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+          "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
           "dev": true,
           "optional": true
         },
         "debug": {
           "version": "2.6.9",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3590,25 +3602,29 @@
         },
         "deep-extend": {
           "version": "0.5.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
+          "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
           "dev": true,
           "optional": true
         },
         "delegates": {
           "version": "1.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+          "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
           "dev": true,
           "optional": true
         },
         "detect-libc": {
           "version": "1.0.3",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+          "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
           "dev": true,
           "optional": true
         },
         "fs-minipass": {
           "version": "1.2.5",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
+          "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3617,13 +3633,15 @@
         },
         "fs.realpath": {
           "version": "1.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+          "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
           "dev": true,
           "optional": true
         },
         "gauge": {
           "version": "2.7.4",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+          "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3639,7 +3657,8 @@
         },
         "glob": {
           "version": "7.1.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3653,13 +3672,15 @@
         },
         "has-unicode": {
           "version": "2.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+          "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
           "dev": true,
           "optional": true
         },
         "iconv-lite": {
           "version": "0.4.21",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz",
+          "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3668,7 +3689,8 @@
         },
         "ignore-walk": {
           "version": "3.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
+          "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3677,7 +3699,8 @@
         },
         "inflight": {
           "version": "1.0.6",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+          "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3687,18 +3710,21 @@
         },
         "inherits": {
           "version": "2.0.3",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
           "dev": true
         },
         "ini": {
           "version": "1.3.5",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+          "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
           "dev": true,
           "optional": true
         },
         "is-fullwidth-code-point": {
           "version": "1.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
           "dev": true,
           "requires": {
             "number-is-nan": "^1.0.0"
@@ -3706,13 +3732,15 @@
         },
         "isarray": {
           "version": "1.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
           "dev": true,
           "optional": true
         },
         "minimatch": {
           "version": "3.0.4",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
           "dev": true,
           "requires": {
             "brace-expansion": "^1.1.7"
@@ -3720,12 +3748,14 @@
         },
         "minimist": {
           "version": "0.0.8",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
           "dev": true
         },
         "minipass": {
           "version": "2.2.4",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
+          "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
           "dev": true,
           "requires": {
             "safe-buffer": "^5.1.1",
@@ -3734,7 +3764,8 @@
         },
         "minizlib": {
           "version": "1.1.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz",
+          "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3743,7 +3774,8 @@
         },
         "mkdirp": {
           "version": "0.5.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+          "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
           "dev": true,
           "requires": {
             "minimist": "0.0.8"
@@ -3751,13 +3783,15 @@
         },
         "ms": {
           "version": "2.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
           "dev": true,
           "optional": true
         },
         "needle": {
           "version": "2.2.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz",
+          "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3768,7 +3802,8 @@
         },
         "node-pre-gyp": {
           "version": "0.10.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz",
+          "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3786,7 +3821,8 @@
         },
         "nopt": {
           "version": "4.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
+          "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3796,13 +3832,15 @@
         },
         "npm-bundled": {
           "version": "1.0.3",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz",
+          "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==",
           "dev": true,
           "optional": true
         },
         "npm-packlist": {
           "version": "1.1.10",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz",
+          "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3812,7 +3850,8 @@
         },
         "npmlog": {
           "version": "4.1.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+          "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3824,18 +3863,21 @@
         },
         "number-is-nan": {
           "version": "1.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+          "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
           "dev": true
         },
         "object-assign": {
           "version": "4.1.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
           "dev": true,
           "optional": true
         },
         "once": {
           "version": "1.4.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+          "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
           "dev": true,
           "requires": {
             "wrappy": "1"
@@ -3843,19 +3885,22 @@
         },
         "os-homedir": {
           "version": "1.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+          "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
           "dev": true,
           "optional": true
         },
         "os-tmpdir": {
           "version": "1.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+          "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
           "dev": true,
           "optional": true
         },
         "osenv": {
           "version": "0.1.5",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+          "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3865,19 +3910,22 @@
         },
         "path-is-absolute": {
           "version": "1.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+          "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
           "dev": true,
           "optional": true
         },
         "process-nextick-args": {
           "version": "2.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+          "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
           "dev": true,
           "optional": true
         },
         "rc": {
           "version": "1.2.7",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz",
+          "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3889,7 +3937,8 @@
           "dependencies": {
             "minimist": {
               "version": "1.2.0",
-              "bundled": true,
+              "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+              "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
               "dev": true,
               "optional": true
             }
@@ -3897,7 +3946,8 @@
         },
         "readable-stream": {
           "version": "2.3.6",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3912,7 +3962,8 @@
         },
         "rimraf": {
           "version": "2.6.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+          "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3921,42 +3972,49 @@
         },
         "safe-buffer": {
           "version": "5.1.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
           "dev": true
         },
         "safer-buffer": {
           "version": "2.1.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+          "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
           "dev": true,
           "optional": true
         },
         "sax": {
           "version": "1.2.4",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+          "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
           "dev": true,
           "optional": true
         },
         "semver": {
           "version": "5.5.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
           "dev": true,
           "optional": true
         },
         "set-blocking": {
           "version": "2.0.0",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+          "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
           "dev": true,
           "optional": true
         },
         "signal-exit": {
           "version": "3.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+          "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
           "dev": true,
           "optional": true
         },
         "string-width": {
           "version": "1.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
           "dev": true,
           "requires": {
             "code-point-at": "^1.0.0",
@@ -3966,7 +4024,8 @@
         },
         "string_decoder": {
           "version": "1.1.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -3975,7 +4034,8 @@
         },
         "strip-ansi": {
           "version": "3.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
           "dev": true,
           "requires": {
             "ansi-regex": "^2.0.0"
@@ -3983,13 +4043,15 @@
         },
         "strip-json-comments": {
           "version": "2.0.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+          "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
           "dev": true,
           "optional": true
         },
         "tar": {
           "version": "4.4.1",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz",
+          "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -4004,13 +4066,15 @@
         },
         "util-deprecate": {
           "version": "1.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+          "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
           "dev": true,
           "optional": true
         },
         "wide-align": {
           "version": "1.1.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
+          "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
           "dev": true,
           "optional": true,
           "requires": {
@@ -4019,12 +4083,14 @@
         },
         "wrappy": {
           "version": "1.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+          "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
           "dev": true
         },
         "yallist": {
           "version": "3.0.2",
-          "bundled": true,
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
+          "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
           "dev": true
         }
       }

+ 2 - 2
course/package.json

@@ -3,13 +3,13 @@
   "description": "PluralSight Typescript courses by Thiago Temple",
   "dependencies": {
     "@angular/animations": "^5.0.1",
-    "@angular/cdk": "^5.0.0-rc0",
+    "@angular/cdk": "^5.0.0",
     "@angular/common": "^5.0.1",
     "@angular/compiler": "^5.0.1",
     "@angular/core": "^5.0.1",
     "@angular/forms": "^5.0.1",
     "@angular/http": "^5.0.1",
-    "@angular/material": "^5.0.0-rc0",
+    "@angular/material": "^5.0.0",
     "@angular/platform-browser": "^5.0.1",
     "@angular/platform-browser-dynamic": "^5.0.1",
     "@angular/router": "^5.0.1",

+ 1 - 1
course/src/app/base-report.component.ts

@@ -6,7 +6,7 @@ import { BehaviorSubject } from "rxjs/BehaviorSubject";
 
 import { ReportDataService } from "./services/reportData.service";
 import { CreateReportItemDialogComponent } from "./create-report-item.component";
-import {ReportItem} from "./types";
+import { ReportItem } from "./types";
 
 export abstract class BaseReportComponent {
     abstract title: string;

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

@@ -1,7 +1,7 @@
 import { Component } from '@angular/core';
 import { MatDialogRef } from '@angular/material';
 import { ReportItemService } from './services/reportItem.service';
-import {ReportItem, ReportItemType} from "./types";
+import { ReportItem, ReportItemType } from './types';
 
 @Component({
     selector: 'ps-create-report-item',
@@ -21,6 +21,7 @@ export class CreateReportItemDialogComponent {
     itemTypeOptions: ReportItemType[] = [
         ReportItemType.unselected,
         ReportItemType.food,
+        ReportItemType.officeSupplies,
         ReportItemType.training,
         ReportItemType.transport,
         ReportItemType.travel

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

@@ -1,10 +1,10 @@
 import { Component } from '@angular/core';
 import { Location } from '@angular/common';
 import { MatDialog } from '@angular/material';
-import {ReportDataService} from './services/reportData.service';
+import { ReportDataService } from './services/reportData.service';
 import 'rxjs/add/operator/switchMap';
 import { BaseReportComponent } from './base-report.component';
-import {NewReport} from "./types";
+import { NewReport } from './types';
 
 @Component({
     selector: 'ps-report',

+ 3 - 2
course/src/app/edit-report.component.ts

@@ -5,7 +5,7 @@ import { ActivatedRoute } from "@angular/router";
 
 import { ReportDataService } from "./services/reportData.service";
 import { BaseReportComponent } from "./base-report.component";
-import {Report} from "./types";
+import { Report } from "./types";
 
 @Component({
     selector: 'ps-report',
@@ -30,7 +30,7 @@ export class EditReportComponent extends BaseReportComponent {
                   this.itemsDataBase.addRange(report.items);
                   this.report = report;
                 } else {
-                    console.log("report is undefined")
+                    console.error('No report found for the specified id');
                 }
             });
     }
@@ -42,5 +42,6 @@ export class EditReportComponent extends BaseReportComponent {
         items: this.itemsDataBase.data
       };
       this.reportDataService.save(modifiedReport);
+        this.location.back();
     }
 }

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

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

+ 25 - 11
course/src/app/reports.component.ts

@@ -7,8 +7,8 @@ import 'rxjs/add/operator/take';
 import { ReportDataService } from './services/reportData.service';
 import { ActivatedRoute, ParamMap } from '@angular/router';
 import { WindowService } from './services/window.service';
-import {isRemoteDataError, isRemoteDataLoading, isRemoteDataOk, Report} from "./types";
-import {MatTableDataSource} from "@angular/material";
+import { Report, RemoteData } from './types';
+import { MatTableDataSource } from '@angular/material';
 
 function mapUser(params: ParamMap): boolean {
     const userName = params.get('user') || '';
@@ -16,8 +16,8 @@ function mapUser(params: ParamMap): boolean {
 }
 
 /**
- *  Special syntax: using "this" as first argument does NOT add a first
- * parameter, but specifies the type of "this" within the function.
+ *  Special syntax: using 'this' as first argument does NOT add a first
+ * parameter, but specifies the type of 'this' within the function.
  */
 function toggleApprovedStyle(this: HTMLElement, approved: boolean) {
     if (approved && this.className.indexOf('approved') === -1) {
@@ -44,14 +44,28 @@ export class ReportsComponent {
         this.isAdmin = this.route.queryParamMap.map(mapUser);
 
         reportDataService.dataChange.subscribe(remoteData => {
-            if (isRemoteDataOk(remoteData)) {
+            this.handleDataChanged(remoteData);
+        });
+    }
+
+    handleDataChanged(remoteData: RemoteData<Report[]>): string {
+        // This is called a "discriminated union".
+        // Here "kind" is the "discriminant" for the remoteData "discriminated
+        // union".
+        switch (remoteData.kind) {
+            case 'ok':
                 this.reports.data = remoteData.data;
-            } else if (isRemoteDataError(remoteData)) {
+                return remoteData.kind;
+            case 'error':
                 alert(remoteData.error);
-            } else if (isRemoteDataLoading(remoteData)) {
-                // display loading spinner.
-            }
-        });
+                return remoteData.kind;
+            case 'loading':
+                // display loading spinner;
+                return remoteData.kind;
+            case 'notFetched':
+                // display initial page;
+                return remoteData.kind;
+        }
     }
 
     approve(report: Report) {
@@ -67,7 +81,7 @@ export class ReportsComponent {
 
     private toggleApprovedStyle(reportId: number, approved: boolean) {
       setTimeout(() => {
-            const row = this._window.document.getElementById(`report$${reportId}`)!.closest("mat-row");
+            const row = this._window.document.getElementById(`report$${reportId}`)!.closest('mat-row');
             toggleApprovedStyle.call(row, approved);
         }, 50);
     }

+ 13 - 5
course/src/app/services/messenger.service.ts

@@ -1,5 +1,5 @@
 import { ReportDataService } from "./reportData.service";
-import {Messenger, Report} from "../types";
+import { Report, Messenger } from "../types";
 
 class ReportCreatedMessenger implements Messenger {
     deliveryMessage(report: Report, user: string): void {
@@ -21,7 +21,12 @@ class ReportRejectMessenger implements Messenger {
     }
 }
 
-function getMessenger(event: string): Messenger {
+type MessengerEventsHandled =
+    'MessengerReportCreated' |
+    'MessengerReportApproved' |
+    'MessengerReportRejected';
+
+function getMessenger(event: MessengerEventsHandled): Messenger {
     switch (event) {
         case 'MessengerReportCreated':
             return new ReportCreatedMessenger();
@@ -29,8 +34,8 @@ function getMessenger(event: string): Messenger {
             return new ReportApprovedMessenger();
         case 'MessengerReportRejected':
             return new ReportRejectMessenger();
-      default:
-            throw new Error('Messenger not found');
+        // No need for a default: all cases possible based on the type are
+        // covered. This is called "exhaustive check".
     }
 }
 
@@ -48,7 +53,10 @@ export class MessengerWatcher {
             .ReportDataService
             .reportApprovedReject
             .subscribe(({ report, user }) => {
-                getMessenger(`MessengerReport${report.approved ? 'Approved' : 'Rejected'}`)
+                const eventType = report.approved ? 
+                    'MessengerReportApproved' :
+                    'MessengerReportRejected';
+                getMessenger(eventType)
                     .deliveryMessage(report, user);
             });
     }

+ 29 - 36
course/src/app/services/reportData.service.ts

@@ -1,41 +1,17 @@
 import { Injectable, Inject } from '@angular/core';
 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
-import { WindowService } from './window.service';
 import { Subject } from 'rxjs/Subject';
-import {isRemoteDataOk, NewReport, PS_REPORTS_KEY, RemoteData, Report} from '../types';
+import { Report, NewReport, PS_REPORTS_KEY, RemoteData, isRemoteDataOK } from '../types';
+import { WindowService } from './window.service';
 
 @Injectable()
 export class ReportDataService {
-    dataChange = new BehaviorSubject<RemoteData<Report[]>>({ kind: 'notFetched' });
+    dataChange = new BehaviorSubject<RemoteData<Report[]>>({ kind: "notFetched" });
     reportCreated: Subject<Report> = new Subject();
     reportApprovedReject: Subject<{ report: Report, user: string }> = new Subject();
 
     constructor(@Inject(WindowService) private _window: Window) {
         this.fetch();
-        const stringfiedReports = _window.localStorage.getItem(PS_REPORTS_KEY);
-        if (stringfiedReports) {
-            this.dataChange.next(JSON.parse(stringfiedReports));
-        }
-    }
-
-    fetch() {
-        this.dataChange.next({ kind: 'loading' });
-        setTimeout(() => {
-            const random = Math.floor((Math.random() * 10) + 1);
-            const stringifiedReports = this._window.localStorage.getItem(PS_REPORTS_KEY);
-            if (random > 3 && stringifiedReports) {
-                this.dataChange.next({
-                    kind: 'ok',
-                    data: JSON.parse(stringifiedReports),
-                });
-            } else {
-                // some error.
-                this.dataChange.next({
-                    kind: 'error',
-                    error: 'Loading the data has failed',
-                });
-            }
-        }, 0);
     }
 
     get remoteData(): RemoteData<Report[]> {
@@ -43,7 +19,7 @@ export class ReportDataService {
     }
 
     getReport(reportId: number): Promise<Report | undefined> {
-        if (isRemoteDataOk(this.remoteData)) {
+        if (isRemoteDataOK(this.remoteData)) {
             return Promise.resolve(this.remoteData.data.find(r => r.id === reportId));
         } else {
             return Promise.resolve(undefined);
@@ -51,7 +27,7 @@ export class ReportDataService {
     }
 
     add(report: NewReport) {
-        if (isRemoteDataOk(this.remoteData)) {
+        if (isRemoteDataOK(this.remoteData)) {
             const newReport = {
                 ...report,
                 // Since this.data: Report[], rep is a Report, so it does have an id
@@ -67,7 +43,7 @@ export class ReportDataService {
     }
 
     save(report: Report) {
-        if (isRemoteDataOk(this.remoteData)) {
+        if (isRemoteDataOK(this.remoteData)) {
             const reportIndex = this.remoteData.data.findIndex(r => r.id === report.id);
             const newData = [...this.remoteData.data];
             newData.splice(reportIndex, 1, report);
@@ -76,20 +52,37 @@ export class ReportDataService {
     }
 
     toggleApproval(report: Report, user: string) {
-        if (isRemoteDataOk(this.remoteData)) {
+        if (isRemoteDataOK(this.remoteData)) {
             const reportIndex = this.remoteData.data.findIndex(r => r.id === report.id);
             const newData = [...this.remoteData.data];
             newData.splice(reportIndex, 1, report);
             this.updateData(newData);
-            this.reportApprovedReject.next({report, user});
+            this.reportApprovedReject.next({ report, user });
         }
     }
 
     private updateData(reports: Report[]) {
         this._window.localStorage.setItem(PS_REPORTS_KEY, JSON.stringify(reports));
-        this.dataChange.next({
-            kind: 'ok',
-            data: reports,
-        });
+        this.dataChange.next({ kind: "ok", data: reports });
     }
+
+    private fetch(): void {
+        this.dataChange.next({ kind: "loading" });
+        setTimeout(() => {
+            const random = Math.floor((Math.random() * 10) + 1);
+            const stringfiedReports = this._window.localStorage.getItem(PS_REPORTS_KEY);
+            if (random > 3 && stringfiedReports) {
+                this.dataChange.next({
+                    kind: "ok",
+                    data: JSON.parse(stringfiedReports)
+                });
+            } else {
+                this.dataChange.next({
+                    kind: 'error',
+                    error: 'The were was an issue loading the data'
+                });
+            }
+        }, 1000);
+    }
+
 }

+ 6 - 8
course/src/app/services/reportItem.service.ts

@@ -1,13 +1,11 @@
 import { Injectable } from '@angular/core';
-import {ReportItem, ReportItemType} from "../types";
-// import {bootstrapItem} from "../../../node_modules/@angular/cli/lib/ast-tools";
+import { ReportItem, ReportItemType } from '../types';
 
 function validateRequired(item: ReportItem): boolean {
     // false is a valid value for these, so exclude them from check.
     const exclude: (keyof ReportItem)[] = ['hasReceipt'];
 
-    return Object.keys(item)
-        .reduce((isValid, memberKey: keyof ReportItem) => {
+    return Object.keys(item).reduce((isValid, memberKey: keyof ReportItem) => {
             if (!isValid) {
                 return isValid;
             }
@@ -34,7 +32,7 @@ function validateReceipt(item: ReportItem): string {
     return item.hasReceipt ? '' : 'The item must have a receipt';
 }
 
-function validateTraining(item: ReportItem): string {
+function validateTraining(item: ReportItem) {
     if (item.amount < 50 && !item.hasReceipt) {
         return '';
     }
@@ -59,7 +57,7 @@ export class ReportItemService {
 
     isValid(item: ReportItem): string {
         if (!validateRequired(item)) {
-            return 'One of the required fields was not filled.';
+            return 'Some of the required fields were not filled.'
         }
 
         switch (item.type) {
@@ -73,6 +71,7 @@ export class ReportItemService {
             case ReportItemType.training:
                 return validateTraining(item);
 
+            case ReportItemType.officeSupplies:
             case ReportItemType.transport:
             case ReportItemType.travel: {
                 const validatedReceipt = validateReceipt(item);
@@ -82,8 +81,7 @@ export class ReportItemService {
                 return this.validateDate(item);
             }
             case ReportItemType.unselected:
-            default:
-                return 'The item type is not supported';
+                return 'Please select an item type';
         }
     }
 }

+ 18 - 16
course/src/app/types.ts

@@ -7,13 +7,14 @@ export type Report = {
     amount: number;
 };
 
-export type NewReport = Pick<Report, 'date' | 'approved' | 'description' | 'items' >
+export type NewReport = Pick<Report, 'date' | 'approved' | 'description' | 'items'>;
 
 export enum ReportItemType {
     food = 'Food',
     travel = 'Travel',
     training = 'Training',
     transport = 'Transport',
+    officeSupplies = 'Office Supplies',
     unselected = ''
 }
 
@@ -32,35 +33,36 @@ export interface Messenger {
 export const PS_REPORTS_KEY = 'ps-reports';
 
 type RemoteDataNotFetched = {
-    kind: "notFetched",
+    kind: "notFetched";
 };
 
 type RemoteDataLoading = {
-    kind: "loading",
+    kind: "loading";
 };
 
-type RemoteDataOk<T> = {
-    kind: "ok",
-    data: T,
-}
+type RemoteDataOK<T> = {
+    kind: "ok";
+    data: T;
+};
 
 type RemoteDataError = {
-    kind: 'error',
-    error: string,
-}
+    kind: "error";
+    error: string;
+};
 
 export type RemoteData<T> =
     RemoteDataNotFetched |
     RemoteDataLoading |
-    RemoteDataOk<T> |
+    RemoteDataOK<T> |
     RemoteDataError;
 
+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';
+    return remoteData.kind === "error";
 }
 export function isRemoteDataLoading<T>(remoteData: RemoteData<T>): remoteData is RemoteDataLoading {
-    return remoteData.kind === 'loading';
-}
-export function isRemoteDataOk<T>(remoteData: RemoteData<T>): remoteData is RemoteDataOk<T> {
-    return remoteData.kind === 'ok';
+    return remoteData.kind === "loading";
 }
+