Kaynağa Gözat

Merge branch 'features' of onunez/soma-frontend into development

Oscar José Nuñez Chávez 6 yıl önce
ebeveyn
işleme
e370785070
33 değiştirilmiş dosya ile 752 ekleme ve 204 silme
  1. 6 2
      angular.json
  2. 151 74
      package-lock.json
  3. 5 1
      package.json
  4. 81 22
      src/app/components/assets/assets.component.html
  5. 28 2
      src/app/components/assets/assets.component.scss
  6. 251 42
      src/app/components/assets/assets.component.ts
  7. 49 0
      src/app/components/dashboard/dashboard.component.html
  8. 22 2
      src/app/components/dashboard/dashboard.component.ts
  9. 61 4
      src/app/components/organizations/organization/organization.component.html
  10. 41 3
      src/app/components/organizations/organization/organization.component.ts
  11. 3 0
      src/app/components/organizations/organizations.component.html
  12. 2 2
      src/app/components/plugins/weather-card/weather-card.component.html
  13. 2 1
      src/app/components/plugins/weather-card/weather-card.component.scss
  14. 1 1
      src/app/components/shared/navbar/navbar.component.html
  15. 2 2
      src/app/components/shared/sidebar/sidebar.component.html
  16. 5 0
      src/app/components/shared/sidebar/sidebar.component.scss
  17. 2 0
      src/app/components/shared/sidebar/sidebar.component.ts
  18. 2 2
      src/app/components/users/new-user/new-user.component.html
  19. 2 2
      src/app/components/users/users.component.html
  20. 14 0
      src/app/components/users/users.component.ts
  21. 4 1
      src/app/layouts/admin/admin.module.ts
  22. 2 35
      src/app/services/logs.service.ts
  23. BIN
      src/assets/img/barrels2.png
  24. BIN
      src/assets/img/car-smoke.png
  25. BIN
      src/assets/img/car2-icon.png
  26. BIN
      src/assets/img/favicon.png
  27. BIN
      src/assets/img/poweredhouse.png
  28. 1 1
      src/assets/scss/core/_sidebar-and-main-panel.scss
  29. 6 1
      src/assets/scss/material-dashboard.scss
  30. 2 1
      src/index.html
  31. 3 1
      src/material-dashboard.css
  32. 1 1
      src/polyfills.ts
  33. 3 1
      tsconfig.json

+ 6 - 2
angular.json

@@ -33,7 +33,8 @@
               "node_modules/perfect-scrollbar/css/perfect-scrollbar.css",
               "src/assets/scss/material-dashboard.scss",
               "node_modules/leaflet/dist/leaflet.css",
-              "src/styles.scss"
+              "src/styles.scss",
+              "node_modules/bootstrap-select/dist/css/bootstrap-select.css"
             ],
             "scripts": [
               "node_modules/jquery/dist/jquery.js",
@@ -43,6 +44,7 @@
               "node_modules/perfect-scrollbar/dist/perfect-scrollbar.min.js",
               "node_modules/datatables.net/js/jquery.dataTables.js",
               "node_modules/bootstrap-material-design/dist/js/bootstrap-material-design.min.js",
+              "node_modules/bootstrap-select/dist/js/bootstrap-select.min.js"
             ]
           },
           "configurations": {
@@ -111,7 +113,8 @@
               "node_modules/perfect-scrollbar/css/perfect-scrollbar.css",
               "src/assets/scss/material-dashboard.scss",
               "node_modules/leaflet/dist/leaflet.css",
-              "src/styles.scss"
+              "src/styles.scss",
+              "node_modules/bootstrap-select/dist/css/bootstrap-select.css"
             ],
             "scripts": [
               "node_modules/jquery/dist/jquery.js",
@@ -122,6 +125,7 @@
               "node_modules/datatables.net/js/jquery.dataTables.js",
               "node_modules/chart.js/src/chart.js",
               "node_modules/bootstrap-material-design/dist/js/bootstrap-material-design.min.js",
+              "node_modules/bootstrap-select/dist/js/bootstrap-select.min.js"
             ]
           }
         },

+ 151 - 74
package-lock.json

@@ -9,16 +9,6 @@
       "resolved": "https://registry.npmjs.org/@agm/core/-/core-1.0.0-beta.7.tgz",
       "integrity": "sha512-NXJqB2wCahWGSqvQazLHbVrg3Dhg5zTdhG9yP7EVVGfIft5lbY83KLVpbYFeVI/l+ggeJWAC9nVUr7CeDS96uQ=="
     },
-    "@angular-builders/custom-webpack": {
-      "version": "8.2.0",
-      "resolved": "https://registry.npmjs.org/@angular-builders/custom-webpack/-/custom-webpack-8.2.0.tgz",
-      "integrity": "sha512-6654RfyqhTGhCI0edC9YU/iMn1UJnzX01bxYJbDWFgvReCqXdlgy+Fe9tp1MeqKweX6BQ1d0gRroR/WjY1aX0A==",
-      "dev": true,
-      "requires": {
-        "lodash": "^4.17.10",
-        "webpack-merge": "^4.2.1"
-      }
-    },
     "@angular-devkit/architect": {
       "version": "0.802.2",
       "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.802.2.tgz",
@@ -1699,6 +1689,15 @@
       "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
       "dev": true
     },
+    "adler-32": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
+      "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=",
+      "requires": {
+        "exit-on-epipe": "~1.0.1",
+        "printj": "~1.1.0"
+      }
+    },
     "adm-zip": {
       "version": "0.4.13",
       "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz",
@@ -2382,6 +2381,11 @@
       "resolved": "https://registry.npmjs.org/bootstrap-material-design/-/bootstrap-material-design-4.1.2.tgz",
       "integrity": "sha512-hKeUkOM6g2DqpktvEMHrIDpQ5qupV4DSeKlJSJ60tLFQ+8tPlszVCa3JVLTV+ZFbJRMb0UA6UWTsnjW57kYNeg=="
     },
+    "bootstrap-select": {
+      "version": "1.13.12",
+      "resolved": "https://registry.npmjs.org/bootstrap-select/-/bootstrap-select-1.13.12.tgz",
+      "integrity": "sha512-epsPt6WpgmL9Q9Y22JFntajdhhqvCwV/JKiBZF3YFvMHK9YzzDPQft/Cjqvsgq0bhF32BlvG03Qs3qA/pVRAqQ=="
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -2707,6 +2711,27 @@
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
     },
+    "cdk-table-exporter": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/cdk-table-exporter/-/cdk-table-exporter-1.2.2.tgz",
+      "integrity": "sha512-HpRtPLgR7FAfX9XH1t67xVo4wQL6SFzSh2flQyc2SIVvUvtbWbGa9SneZzS9uQ0RyA3igq2FtGKd7/S+bigM9A==",
+      "requires": {
+        "file-saver": "^2.0.2",
+        "tslib": "^1.9.0",
+        "xlsx": "^0.14.1"
+      }
+    },
+    "cfb": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.3.tgz",
+      "integrity": "sha512-joXBW0nMuwV9no7UTMiyVJnQL6XIU3ThXVjFUDHgl9MpILPOomyfaGqC290VELZ48bbQKZXnQ81UT5HouTxHsw==",
+      "requires": {
+        "adler-32": "~1.2.0",
+        "commander": "^2.16.0",
+        "crc-32": "~1.2.0",
+        "printj": "~1.1.2"
+      }
+    },
     "chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -2833,6 +2858,11 @@
         }
       }
     },
+    "classlist.js": {
+      "version": "1.1.20150312",
+      "resolved": "https://registry.npmjs.org/classlist.js/-/classlist.js-1.1.20150312.tgz",
+      "integrity": "sha1-HXCEL3Ai8I2awIbOaeWyUPLFd4k="
+    },
     "clean-css": {
       "version": "4.2.1",
       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
@@ -2969,6 +2999,22 @@
         }
       }
     },
+    "codepage": {
+      "version": "1.14.0",
+      "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz",
+      "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=",
+      "requires": {
+        "commander": "~2.14.1",
+        "exit-on-epipe": "~1.0.1"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.14.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
+          "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
+        }
+      }
+    },
     "collection-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -3008,8 +3054,7 @@
     "commander": {
       "version": "2.20.0",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
-      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
-      "dev": true
+      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
     },
     "commondir": {
       "version": "1.0.1",
@@ -3210,6 +3255,15 @@
         "parse-json": "^4.0.0"
       }
     },
+    "crc-32": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
+      "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
+      "requires": {
+        "exit-on-epipe": "~1.0.1",
+        "printj": "~1.1.0"
+      }
+    },
     "create-ecdh": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@@ -4004,6 +4058,11 @@
       "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
       "dev": true
     },
+    "exit-on-epipe": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
+      "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
+    },
     "expand-brackets": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@@ -4327,6 +4386,11 @@
         }
       }
     },
+    "file-saver": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
+      "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
+    },
     "filename-regex": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
@@ -4489,6 +4553,11 @@
       "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
       "dev": true
     },
+    "frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
+    },
     "fragment-cache": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -5997,8 +6066,7 @@
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "aproba": {
               "version": "1.2.0",
@@ -6041,8 +6109,7 @@
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "concat-map": {
               "version": "0.0.1",
@@ -6053,8 +6120,7 @@
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "core-util-is": {
               "version": "1.0.2",
@@ -6171,8 +6237,7 @@
             "inherits": {
               "version": "2.0.3",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "ini": {
               "version": "1.3.5",
@@ -6184,7 +6249,6 @@
               "version": "1.0.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
               }
@@ -6214,7 +6278,6 @@
               "version": "2.3.5",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
                 "yallist": "^3.0.0"
@@ -6233,7 +6296,6 @@
               "version": "0.5.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "minimist": "0.0.8"
               }
@@ -6314,8 +6376,7 @@
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "object-assign": {
               "version": "4.1.1",
@@ -6327,7 +6388,6 @@
               "version": "1.4.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "wrappy": "1"
               }
@@ -6413,8 +6473,7 @@
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "safer-buffer": {
               "version": "2.1.2",
@@ -6450,7 +6509,6 @@
               "version": "1.0.2",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
                 "is-fullwidth-code-point": "^1.0.0",
@@ -6470,7 +6528,6 @@
               "version": "3.0.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
               }
@@ -6514,14 +6571,12 @@
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "yallist": {
               "version": "3.0.3",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             }
           }
         },
@@ -6962,6 +7017,15 @@
         "object-visit": "^1.0.0"
       }
     },
+    "mat-table-exporter": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/mat-table-exporter/-/mat-table-exporter-1.2.2.tgz",
+      "integrity": "sha512-ctBOg7v2SwvAfKwjUkE1Ha+/QVGDht0JiLxjFi6UOF3UVCJLOAltedf0QWk2Z0FtHbDNbCUnK83+1IHrOg8xCw==",
+      "requires": {
+        "cdk-table-exporter": "^1.2.2",
+        "tslib": "^1.9.0"
+      }
+    },
     "math-random": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
@@ -7591,8 +7655,7 @@
             },
             "console-control-strings": {
               "version": "1.1.0",
-              "bundled": true,
-              "optional": true
+              "bundled": true
             },
             "core-util-is": {
               "version": "1.0.2",
@@ -7695,8 +7758,7 @@
             },
             "inherits": {
               "version": "2.0.3",
-              "bundled": true,
-              "optional": true
+              "bundled": true
             },
             "ini": {
               "version": "1.3.5",
@@ -7732,7 +7794,6 @@
             "minipass": {
               "version": "2.3.5",
               "bundled": true,
-              "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
                 "yallist": "^3.0.0"
@@ -7749,7 +7810,6 @@
             "mkdirp": {
               "version": "0.5.1",
               "bundled": true,
-              "optional": true,
               "requires": {
                 "minimist": "0.0.8"
               }
@@ -7833,7 +7893,6 @@
             "once": {
               "version": "1.4.0",
               "bundled": true,
-              "optional": true,
               "requires": {
                 "wrappy": "1"
               }
@@ -7909,8 +7968,7 @@
             },
             "safe-buffer": {
               "version": "5.1.2",
-              "bundled": true,
-              "optional": true
+              "bundled": true
             },
             "safer-buffer": {
               "version": "2.1.2",
@@ -7940,7 +7998,6 @@
             "string-width": {
               "version": "1.0.2",
               "bundled": true,
-              "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
                 "is-fullwidth-code-point": "^1.0.0",
@@ -7997,13 +8054,11 @@
             },
             "wrappy": {
               "version": "1.0.2",
-              "bundled": true,
-              "optional": true
+              "bundled": true
             },
             "yallist": {
               "version": "3.0.3",
-              "bundled": true,
-              "optional": true
+              "bundled": true
             }
           }
         },
@@ -9269,6 +9324,16 @@
       "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
       "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
     },
+    "print-js": {
+      "version": "1.0.63",
+      "resolved": "https://registry.npmjs.org/print-js/-/print-js-1.0.63.tgz",
+      "integrity": "sha512-WKf79bFeqJpwx5vcjvEuL0J1bRVA5QlKQY+usFksOx0WOApSJwQGgMlgM2PVub/R1uUMF4onc2SWRWPNz4R40g=="
+    },
+    "printj": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
+      "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
+    },
     "process": {
       "version": "0.11.10",
       "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -10833,6 +10898,14 @@
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
+    "ssf": {
+      "version": "0.10.2",
+      "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.2.tgz",
+      "integrity": "sha512-rDhAPm9WyIsY8eZEKyE8Qsotb3j/wBdvMWBUsOhJdfhKGLfQidRjiBUV0y/MkyCLiXQ38FG6LWW/VYUtqlIDZQ==",
+      "requires": {
+        "frac": "~1.1.2"
+      }
+    },
     "sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -12678,8 +12751,7 @@
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "aproba": {
               "version": "1.2.0",
@@ -12707,7 +12779,6 @@
               "version": "1.1.11",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "balanced-match": "^1.0.0",
                 "concat-map": "0.0.1"
@@ -12722,8 +12793,7 @@
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "concat-map": {
               "version": "0.0.1",
@@ -12734,8 +12804,7 @@
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "core-util-is": {
               "version": "1.0.2",
@@ -12852,8 +12921,7 @@
             "inherits": {
               "version": "2.0.3",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "ini": {
               "version": "1.3.5",
@@ -12865,7 +12933,6 @@
               "version": "1.0.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
               }
@@ -12880,7 +12947,6 @@
               "version": "3.0.4",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "brace-expansion": "^1.1.7"
               }
@@ -12888,14 +12954,12 @@
             "minimist": {
               "version": "0.0.8",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "minipass": {
               "version": "2.3.5",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
                 "yallist": "^3.0.0"
@@ -12914,7 +12978,6 @@
               "version": "0.5.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "minimist": "0.0.8"
               }
@@ -12995,8 +13058,7 @@
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "object-assign": {
               "version": "4.1.1",
@@ -13008,7 +13070,6 @@
               "version": "1.4.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "wrappy": "1"
               }
@@ -13094,8 +13155,7 @@
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "safer-buffer": {
               "version": "2.1.2",
@@ -13131,7 +13191,6 @@
               "version": "1.0.2",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
                 "is-fullwidth-code-point": "^1.0.0",
@@ -13151,7 +13210,6 @@
               "version": "3.0.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
               }
@@ -13195,14 +13253,12 @@
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "yallist": {
               "version": "3.0.3",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             }
           }
         },
@@ -13455,6 +13511,27 @@
       "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz",
       "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8="
     },
+    "xlsx": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.14.5.tgz",
+      "integrity": "sha512-s/5f4/mjeWREmIWZ+HtDfh/rnz51ar+dZ4LWKZU3u9VBx2zLdSIWTdXgoa52/pnZ9Oe/Vu1W1qzcKzLVe+lq4w==",
+      "requires": {
+        "adler-32": "~1.2.0",
+        "cfb": "^1.1.2",
+        "codepage": "~1.14.0",
+        "commander": "~2.17.1",
+        "crc-32": "~1.2.0",
+        "exit-on-epipe": "~1.0.1",
+        "ssf": "~0.10.2"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "2.17.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+          "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+        }
+      }
+    },
     "xml2js": {
       "version": "0.4.19",
       "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",

+ 5 - 1
package.json

@@ -33,8 +33,10 @@
     "arrive": "^2.4.1",
     "bootstrap": "^4.3.1",
     "bootstrap-material-design": "^4.1.2",
+    "bootstrap-select": "^1.13.12",
     "c": "^0.1.0",
     "chart.js": "^2.8.0",
+    "classlist.js": "^1.1.20150312",
     "crypto-js": "^3.1.9-1",
     "datatables.net": "^1.10.19",
     "datatables.net-dt": "^1.10.19",
@@ -43,6 +45,7 @@
     "jquery": "^3.4.1",
     "leaflet": "^1.5.1",
     "leaflet-routing-machine": "^3.2.12",
+    "mat-table-exporter": "^1.2.2",
     "moment": "^2.24.0",
     "ng2-charts": "^2.3.0",
     "ngx-animating-datepicker": "^1.2.1",
@@ -50,6 +53,7 @@
     "ngx-daterangepicker": "^1.1.1",
     "perfect-scrollbar": "^1.4.0",
     "popper.js": "^1.15.0",
+    "print-js": "^1.0.63",
     "rxjs": "6.5.2",
     "rxjs-compat": "^6.5.2",
     "sweetalert2": "^8.17.1",
@@ -81,4 +85,4 @@
     "tslint": "~5.15.0",
     "typescript": "~3.5.3"
   }
-}
+}

+ 81 - 22
src/app/components/assets/assets.component.html

@@ -15,22 +15,22 @@
         
         </div>
       </div>
-      <!--<div class="row">
+      <!--
+      <div class="row">
         <div class="col-lg-12">
             <div class="widget environment-meters">
                 <div class="mini-stats">
-                  <span class="dark-yellow-skin"><i class="fa fa-bolt"></i></span>
+                  <span class="green-skin"><i class="fas fa-hand-holding-usd"></i></span>
                   <h5 *ngIf="eProduced">
-                    {{eProduced.thisWeek.total_energy_kWh/1000 | number}}
-                    <small>MWh</small>
+                    300
+                    <small>$</small>
                   </h5>
                 </div>
               </div>
           </div>
       </div>
-    -->  
+    -->
     </div>
-
     <!-- Weather card -->
     <div class="col-lg-6 col-sm-8 p-1">
       <div class="row">
@@ -87,7 +87,7 @@
     <div class="col-xl-3 col-lg-6 col-md-6 col-sm-6 p-1">
       <div class="widget energy-stats">
         <div class="mini-stats ">
-          <span class="dark-yellow-skin"><i class="fa fa-bolt"></i></span>
+          <span class="green-skin"><i class="fa fa-bolt"></i></span>
           <h3 *ngIf="eProduced">
             {{energyYear}}
             <small>MWh</small>
@@ -105,15 +105,76 @@
       <div class="widget">
         <div class="mini-stats">
 
-          <div class="chart-container">
+          <p class="align-right">Seleccione el tipo de visualización</p>
+      
+          <div class=" action-buttons">
+            <button [ngClass]="[chartActive[0]==true ? 'btn  btn-success' : 'btn btn-dark']"  (click)="changeGraphicType('bar')"> 
+              <i class="fa fa-chart-bar"></i>
+              Barra
+            </button>
+            <button [ngClass]="[chartActive[1]==true ? 'btn  btn-success' : 'btn btn-dark']" (click)="changeGraphicType('line')"> 
+              <i class="fa fa-chart-line"></i>
+              Linea
+            </button>
+            <button [ngClass]="[chartActive[2]==true ? 'btn  btn-success' : 'btn btn-dark']" (click)="changeGraphicType('radar')"> 
+              <i class="fa fa-chart-area"></i>
+              Area
+            </button>
+            <button [ngClass]="[chartActive[3]==true ? 'btn  btn-success' : 'btn btn-dark']" (click)="changeToTable()"> 
+              <i class="fa fa-table"></i>
+              Tabla
+            </button>    
+          </div>
+
+          <div class="chart-container" id="chart-wrapper">
             <canvas id="canvas">{{ chart1 }}</canvas>
           </div>
+          
+          <div id="toogleTable">
+            <ng-container class="example-container mat-elevation-z8" *ngIf="showTable" >
+              <div class="example-table-container">
+          
+                <div class="action-buttons">
+                  <button class="btn btn-primary btn-sm" mat-raised-button (click)="exporter.exportTable('xlsx', {fileName:'data-Medidores', sheet: 'sheet_name', Props: {Author: 'INVERLEC'}})">
+                    <i class="fas fa-file-excel"></i>
+                    EXCEL
+                  </button>
+                  <button class="btn btn-primary btn-sm" mat-raised-button (click)="exporter.exportTable('csv', {fileName:'data-Medidores', Props: {Author: 'INVERLEC'}})">
+                    <i class="fas fa-file-csv"></i>
+                    CSV
+                  </button>
+                  <button class="btn btn-primary btn-sm" mat-raised-button (click)="exporter.exportTable('json', {fileName:'data-Medidores', sheet: 'sheet_name', Props: {Author: 'INVERLEC'}})">
+                    <i class="fas fa-file-alt"></i>
+                    JSON
+                  </button>
+                  <button class="btn btn-primary btn-sm" mat-raised-button (click)="printTable()">
+                    <i class="fas fa-file-alt"></i>
+                    IMPRIMIR
+                  </button>
+                </div>
+                
+
+                <mat-table  matTableExporter #table [dataSource]="dataSource"  #exporter="matTableExporter" id="measuresTable">
+          
+                  <div *ngFor="let disCol of displayedColumns; let colIndex = index" matColumnDef="{{disCol}}">
+                    <mat-header-cell *matHeaderCellDef>{{disCol}}</mat-header-cell>
+                    <mat-cell *matCellDef="let element"> {{element[colIndex]}}
+                    </mat-cell>
+                  </div>
+          
+                  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
+                  <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
+                </mat-table>
+              </div>
+            </ng-container>
+            <mat-paginator class="hiddenonload" [pageSizeOptions]="[5, 10, 25] " [length]="dataSource.data.length" [pageIndex]="0" [pageSize]="5"></mat-paginator>
+          </div>
 
           <p>Seleccione un rango de visualización</p>
 
           <button class="btn" [class.btn-success]='isActive[0]' (click)="onMeasureClickRange('day')">Día</button>
-          <button class="btn" [class.btn-success]='isActive[1]' (click)="onMeasureClickRange('week')">Semana</button>
-          <button class="btn" [class.btn-success]='isActive[2]' (click)="onMeasureClickRange('month')">Mes</button>
+          <button class="btn" [class.btn-success]='isActive[1]' (click)="onMeasureClickRange('week')">7 días</button>
+          <button class="btn" [class.btn-success]='isActive[2]' (click)="onMeasureClickRange('month')">30 días</button>
           <button class="btn" [class.btn-success]='isActive[3]' (click)="onMeasureClickRange('year')">Año</button>
           <div class="input-box-container">
             <input class="input-box" placeholder="Click to select a date" 
@@ -134,12 +195,11 @@
       <div class="widget">
         <div class="enviroment-stats">
           <div class="enviromental-icon">
-            <img src="assets/img/tv-icon.png" alt="">
+            <img src="assets/img/barrels2.png" alt="">
           </div>
           <div class="enviromental-text">
-            La energía para operar un televisor durante
-            <span>1,847,140</span>
-            horas
+            <span>{{environmentFuel}}</span>
+            Barriles de petroleo crudo producidos en 1 año.
           </div>
         </div>
       </div>
@@ -149,12 +209,11 @@
       <div class="widget">
         <div class="enviroment-stats">
           <div class="enviromental-icon">
-            <img src="assets/img/car-icon.png" alt="">
+            <img src="assets/img/car2-icon.png" alt="">
           </div>
           <div class="enviromental-text">
-            Los gases de efecto invernadero que emiten 
-            <span>57</span>
-            usuarios de vehiculos en 1 año
+            <span>{{environmentCO2}}Kg.</span>
+            De gases CO2 evitados.
           </div>
         </div>
       </div>
@@ -164,12 +223,12 @@
       <div class="widget">
         <div class="enviroment-stats">
           <div class="enviromental-icon">
-            <img src="assets/img/desktop-pc-icon.png" alt="">
+            <img src="assets/img/poweredhouse.png" alt="">
           </div>
           <div class="enviromental-text">
-            La energía para alimentar 
-            <span>2044</span>
-            computadoras por 1 año
+            La energía que demandan 
+            <span>{{environmentHouse}}</span>
+            hogares durante 1 año.
           </div>
            
         </div>

+ 28 - 2
src/app/components/assets/assets.component.scss

@@ -13,6 +13,25 @@
   }
 }
 
+.savings-wrapper {
+  height: 150px;
+}
+
+#toogleTable {
+  display: none;
+}
+
+.align-right {
+  text-align: right;
+}
+
+.action-buttons {
+  margin-top: 10px;
+  button {
+    margin-right: 7px;
+  }
+}
+
 table {
   width: 100%;
 }
@@ -149,9 +168,16 @@ table {
   }
 }
 
+.btn {
+  padding: 10px 20px;
+}
+
 .chart-container {
   display: block; 
-  height:40vh; 
+  height:48vh; 
+  @media screen and (max-width: 960px) {
+    height:38vh; 
+  }
   position: relative;
 }
 
@@ -167,4 +193,4 @@ table {
     }
 
   }
-}
+}

+ 251 - 42
src/app/components/assets/assets.component.ts

@@ -1,25 +1,21 @@
 import { Component, OnInit, ViewChild,OnChanges } from '@angular/core';
 import { Chart, ChartOptions, ChartType, ChartDataSets } from 'chart.js';
 import { Label, BaseChartDirective } from 'ng2-charts';
-
 import { MeasuresService } from 'src/app/services/measures.service';
 import { PlantsService } from 'src/app/services/plants.service';
 import { LogsService } from 'src/app/services/logs.service';
 
 import { OrganizationsService } from '@app/services/organizations.service';
-
 import { ActivatedRoute } from '@angular/router';
-import { Observable, forkJoin } from 'rxjs';
-
-
-import * as moment from 'moment';
-
+import { MatPaginator } from '@angular/material/paginator';
+import { MatSort } from '@angular/material/sort';
+import { MatTableDataSource } from '@angular/material/table';
 import Swal from 'sweetalert2';
-import { environment } from '@environments/environment';
 import { HttpClient } from '@angular/common/http';
 import { formatDate } from '@angular/common';
 
 import {AngularMyDatePickerDirective,IAngularMyDpOptions, IMyDateModel} from 'angular-mydatepicker';
+import printJS from 'print-js'
 
 @Component({
   selector: 'app-assets',
@@ -31,15 +27,13 @@ export class AssetsComponent implements OnInit {
   
   title = "Plantas";
 
+  // General var declarations
   organizationId:string;
   listAssets:any;
-
   eProduced:any;
   error:boolean;
   errorMessage:string;
   errortest:any;
-  chartjs:boolean;
-  chart1: Chart;
   metersKeys:any;
   metersValues:any;
   view:string;
@@ -47,38 +41,56 @@ export class AssetsComponent implements OnInit {
   energyWeek:any;
   energyMonth:any;
   energyYear:any;
+  environment:any;
+  environmentCO2:any;
+  environmentHouse:any;
+  environmentFuel:any;
+  isActive:[boolean,boolean,boolean,boolean]; //Activated param (chart)
+  chartActive:[boolean,boolean,boolean,boolean]
+  initialLoad: boolean = true;
 
-  //For daterange
+  // For daterange
   daysLabels:any = {su: 'Dom', mo: 'Lun', tu: 'Mar', we: 'Mie', th: 'Jue', fr: 'Vie', sa: 'Sab'};
   monthsLabels:any = { 1: 'Ene', 2: 'Feb', 3: 'Mar', 4: 'Abr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Ago', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dic' };
   todayBtnTxt:string = 'Hoy';
-  
   myDpOptions: IAngularMyDpOptions = {
     dateRange: false,
     dateFormat: 'dd/mm/yyyy',
     dayLabels: this.daysLabels,
     monthLabels: this.monthsLabels,
-    // other options are here...
   };
-
   myDateInit: boolean = true;
   model: IMyDateModel = null;
 
-  // For chartjs
-  tsLabels: any[];
-  barChartColors:any = ['#3c8dbc', '#00a65a', '#f56954']
+  // For MatDataTable
   metersData:any;
   initialDate:any;
+  tableData: any;
+  showTable: boolean;
+  displayedColumns: any;
+  tableData2: any[];
+  array1: any[];
+  array2: any[];
+  array3: any[];
+  dataSource = new MatTableDataSource(this.tableData2);  
+  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
+  @ViewChild(MatSort, { static: true }) sort: MatSort;
 
-
+  // For chartjs
+  chartjs:boolean;
+  chart1: Chart;
+  chart1Type: string;
+  barChartColors:any = ['#5f86b0','#a9d0ea', '#00a65a', '#a7c957', '#f2e8cf', '#3c8dbc', '#f56954', '#ee964b']
+  borderChartColors:any = ['#4573a5','#a2cae4', '#018247', '#91b43d', '#d3cbb7', '#539dc8', '#e4604c', '#d38d51']
   public barChartType: ChartType;
   public barChartLegend:boolean;
   public barChartLabels: Label[];
   public barChartOptions: ChartOptions;
   public barChartData: ChartDataSets[];
+  @ViewChild("baseChart",null) chart: BaseChartDirective;
 
-  isActive:[boolean,boolean,boolean,boolean]; //Activated param (chart)
-
+  
+  // Get selected asset
   constructor(
     private orgService: OrganizationsService, 
     private route: ActivatedRoute, 
@@ -97,13 +109,9 @@ export class AssetsComponent implements OnInit {
         text: 'Espere por favor...'
       });
       Swal.showLoading();
-      
   }
 
-  @ViewChild("baseChart",null) chart: BaseChartDirective;
-
   ngOnInit() {
-
     // Default date is today and set it on a string var and initialize dateRange plugin
     this.initialDate = new Date().toISOString().slice(0, 10);
     if (this.myDateInit) {
@@ -117,17 +125,26 @@ export class AssetsComponent implements OnInit {
         }
       };
     }
-    // Initialize on load
+
+    // Initialize default 'clicked' options for chart button options
     this.isActive = [false, false, false, false];
+    this.chartActive = [true, false, false, false];
 
+    // Get all assets (according to user's assigned organizations)
     let plants = this.plantsService.getAllAssets().subscribe(res => {
       this.listAssets = res["data"]["assets"];
+      
+      // Default values for chart 
       this.view = "month";
       if (this.organizationId == undefined){
         this.organizationId = this.listAssets[0].id;
       }
+      this.chart1Type = "bar";
+
+      // Initialize a draw chart according to the default values
       this.onMeasureClickRange(this.view, this.initialDate);
 
+      // Api call to get the energy summary stats of all assets in the organization
       let energy_produced = this.logsService.getEnergySummaryByAsset(this.organizationId).subscribe(resp => {
         this.eProduced = resp["data"]["energy"];//results[1];
         this.energyDay = this.eProduced.today.total_energy_kWh;
@@ -136,6 +153,15 @@ export class AssetsComponent implements OnInit {
         this.energyYear = this.eProduced.lifeTime.total_energy_kWh > 0 ? (this.eProduced.lifeTime.total_energy_kWh/1000).toFixed(2) : this.eProduced.lifeTime.total_energy_kWh
       });
 
+      this.logsService.getAssetEnviromentalStats(this.organizationId).subscribe(resp => {
+        this.environment = resp["data"]["environmentals"];
+        console.log(this.environment);
+        this.environmentCO2 = this.environment.avoided_kg_of_co2.toFixed(2); 
+        this.environmentHouse = this.environment.number_of_homes.toFixed(0);
+        this.environmentFuel = this.environment.number_of_crude_barrels.toFixed(2);
+      });
+
+
     }, (err) => {
       Swal.fire({
         type: 'error',
@@ -160,13 +186,18 @@ export class AssetsComponent implements OnInit {
     }
   }
 
+  ngOnChanges() {
+    this.dataSource.paginator = this.paginator;
+    this.dataSource.sort = this.sort;
+    //this.dtTrigger.next();
+  }
+
   // Trigger again the chart with the selected assetID
   onChangeObj(event:any) {
     this.organizationId = event.target.value;
     this.onMeasureClickRange(this.view, this.initialDate, this.organizationId);
   }
   
-
   // Change the date range of the chart, according to the selected view (daily, weekly, ...)
   onDateChanged(event: IMyDateModel) {
     let endDate = `${event.singleDate.date.year}-${event.singleDate.date.month}-${event.singleDate.date.day}`;
@@ -193,12 +224,15 @@ export class AssetsComponent implements OnInit {
   // Draw a measure chart using chartjs, given some params, view, for daily, weekly, monthly or yearly measures;
   // measureDate, for a date range given a view and a paramID, for an specific assetID selected in the dropdown  
   onMeasureClickRange(view:string, measureDate?:string, paramId?:string): void {
-    Swal.fire({
-      allowOutsideClick: false,
-      type: 'info',
-      text: 'Espere por favor...'
-    });
-    Swal.showLoading();
+    if(this.initialLoad == false){
+      Swal.fire({
+        allowOutsideClick: false,
+        type: 'info',
+        text: 'Espere por favor...'
+      });
+      Swal.showLoading();
+    }
+    this.initialLoad = false;
     this.view = view;
 
     // Chart (re)initialize, to prevent double load on changing date range or views
@@ -248,30 +282,78 @@ export class AssetsComponent implements OnInit {
         this.isActive = [false, false, false, true];
         break;
       default: 
-        console.log("nada");
-    }  
+    }
 
+    // Get the measures according to the meters, given the params required
     this.logsService.getEnergyProducedByParams(assetId,interval,dateRange).toPromise()
     .then((data: any) => {
       this.metersData = [];      
       this.metersKeys = Object.keys(data["data"]["dataset"]);
-
+      
       // Get all the values according to each index (meter) 
       this.metersValues = Object.values(data["data"]["dataset"]);
 
-      // Get the keys of those values
+      /// Get the keys of those values
       let meterKeys2 = Object.keys(this.metersValues);
+      this.displayedColumns= [];
+      this.tableData = [];
 
+      // The chart data object requires certain ordered params, so we itirate the returned object from the API call,
+      // and build the new object with the required/needed values
       for (let prop in meterKeys2) { 
         //let label = localStorage.getItem("email") == "inverlec@grupomerelec.com" ? `INVERLEC ${prop}` : this.metersValues[prop]["label"];
         let label = this.metersValues[prop]["label"];
         let measure_values = Object.values(this.metersValues[prop]["data"].map(obj => obj.total_energy_kWh).reverse())
-        this.metersData.push({"label": label, backgroundColor: this.barChartColors[prop], data: measure_values });
+        this.metersData.push({"label": label, backgroundColor: this.barChartColors[prop], data: measure_values, borderColor: this.borderChartColors[prop] });
+        this.tableData.push({headers: label+" kWh Generado", dataValues: measure_values})
+      }
+
+      // Initialization of arrays for the table view of the measure values
+      this.array1 = this.array2 = this.array3 = [];
+
+      // Loop to build an object that contains the date and each meter value from a certain asset
+      // This object is required to build the datatable
+      for (let prop in meterKeys2) { 
+        this.array2 = [];
+        //let label = localStorage.getItem("email") == "inverlec@grupomerelec.com" ? `INVERLEC ${prop}` : this.metersValues[prop]["label"];
+        let quantity = Object.keys(this.metersValues[0]["data"]);
+        let mvalues = Object.values(this.metersValues[prop]["data"].map(obj => obj).reverse())
+        
+        for (let prop2 in quantity){
+          // Date insertion
+          this.array3 = [];
+          let columnname = `medidor${prop}`;
+         
+          if (+prop == 0 && mvalues[prop2] != undefined){
+            let dateT = this.getDateWithFormat(this.view, mvalues[prop2]["dateMax"])
+            this.array3.push(dateT);
+          }
+          
+          if (mvalues[prop2] != undefined) { 
+            this.array3.push(mvalues[prop2]["total_energy_kWh"]);
+          }
+          else {
+            this.array3.push(0)
+          }
+
+          if (+prop == 0){
+            this.array2.push(this.array3)
+          }
+          
+          if (+prop != 0) {
+            this.array1[prop2].push(this.array3[0]);
+          }
+        }
+        if (+prop == 0){
+          this.array1 = (this.array2)
+          //this.array1 = [].concat.apply([], this.array1)
+        }    
       }
 
+      // According to the selected interval in the option buttons of the chart, the date is given an specific format 
       switch (view){
         case "day": 
-          this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'hh:mm:ss','es-Es','-0600')).reverse();
+          this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'HH:mm ','es-Es','-0600')).reverse();
           break; 
         case 'week':
           this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'EEEE dd','es-Es','-0600')).reverse();
@@ -283,8 +365,21 @@ export class AssetsComponent implements OnInit {
           this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'dd/MM','es-Es','-0600')).reverse(); 
       }
 
+      // Push the values to the chart object
+      this.tableData.push({headers: "Fecha/Hora", dataValues: this.barChartLabels})
+      this.tableData.reverse()
+      for( let v in Object.keys(this.tableData)){
+        this.displayedColumns.push(this.tableData[v]["headers"]);
+      }
+      this.tableData2 = this.array1;
+
+      this.dataSource.data = this.tableData2;
+      this.dataSource.paginator = this.paginator;
+      this.dataSource.sort = this.sort;
+
+      this.showTable = true;
       this.chart1 = new Chart('canvas', {
-        type: 'bar',
+        type: this.chart1Type,
         options: {
           title: {
             display: true,
@@ -315,6 +410,7 @@ export class AssetsComponent implements OnInit {
           scales: {
             xAxes: [{
               stacked: true,
+              barPercentage: 0.7
             }],
             yAxes: [{
               stacked: true
@@ -328,11 +424,124 @@ export class AssetsComponent implements OnInit {
       });
       this.chartjs = true;
     });
-
     setTimeout(()=>{
       Swal.close();
-    }, 1200)
+    }, 1500)
+  }
+
+  getDateWithFormat(view:string, date:string){
+    let dateT;
+    switch (view){
+      case "day": 
+        dateT = formatDate(date, 'HH:mm','es-Es','-0600');
+        break; 
+      case 'week':
+        dateT = formatDate(date, 'EEEE dd','es-Es','-0600');
+        break;
+      case "year":
+        dateT = formatDate(date, 'MM/yyyy','es-Es','-0600');
+        break;
+      default: 
+        dateT = formatDate(date, 'dd/MM','es-Es','-0600');
+    }
+    return dateT;
+  }
 
+  // Change visualization type to table view
+  changeToTable(){
+    let table = document.getElementById("toogleTable");
+    let chart = document.getElementById("chart-wrapper");
+    this.chartActive = [false, false, false, true];
+    chart.style.display = "none";
+    table.style.display = "block";
+  }
+
+  // Print the table values, according to the generated information
+  printTable(){
+    printJS(
+      { printable: 'measuresTable', type: 'html', 
+        header: '<h3 class="report-header">Datos de la planta </h3>',
+        documentTitle: 'DENMARK - Informacion generada',
+        style: '.report-header{ color: #075D9D; font-size: 24px; }' }
+    );
+  }
+
+  // Function for change the chart type without reloading its values
+  changeGraphicType(chartType:string){
+    let table = document.getElementById("toogleTable");
+    let chart = document.getElementById("chart-wrapper");
+    chart.style.display = "block";
+    table.style.display = "none";
+    let foo = this.metersData; 
+    Object.values(foo)
+    console.log(Object.values(foo));
+    // Select an interval according to the API permitted param
+    let chartT:string;
+    switch (chartType)
+    { 
+      case "bar": 
+        this.chartActive = [true, false, false, false];
+        break; 
+      case "line": 
+        this.chartActive = [false, true, false, false];
+        break; 
+      case "radar":
+        this.chartActive = [false, false, true, false];
+        break; 
+      default: 
+    }  
+
+    this.chart1Type = chartType;
+
+    if (this.chart1 != undefined){
+      this.chart1.destroy();
+    }
+    this.chart1 = undefined;
+    this.chart1 = new Chart('canvas', {
+      type: this.chart1Type,
+
+      options: {
+        title: {
+          display: true,
+        },
+        tooltips: {
+          mode: 'index',
+          callbacks: {
+            // Get the total of the energy produced in every point and show it in the hover tooltip
+            label: function (tooltipItem, data) { 
+              var label = data.datasets[tooltipItem.datasetIndex].label || '';
+              var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
+              var total = 0;
+
+              for (var i = 0; i < data.datasets.length; i++)
+                total += +data.datasets[i].data[tooltipItem.index];
+
+              if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
+                return label + " : " + value;
+              }
+              else {
+                return [label + " : " + value, "TOTAL : " + Math.round(total)];
+              }
+            }
+          }         
+        },
+        responsive: true,
+        maintainAspectRatio: false,
+        scales: {
+          xAxes: [{
+            stacked: true,
+            barPercentage: 0.7
+          }],
+          yAxes: [{
+            stacked: true
+          }]
+        }
+      },
+      data: {
+        labels: this.barChartLabels,
+        datasets: this.metersData,
+      }, 
+    });
   }
 
 }

+ 49 - 0
src/app/components/dashboard/dashboard.component.html

@@ -76,6 +76,55 @@
     </div>
     <br>
 
+    <div class="row">
+      <div class="col-12">
+        <div class="example-container mat-elevation-z8">
+          <div class="example-table-container">
+      
+            <table mat-table [dataSource]="dataSource" class="example-table">
+      
+              <!-- Name Column -->
+              <ng-container matColumnDef="name">
+                <th mat-header-cell *matHeaderCellDef>Planta</th>
+                <td mat-cell *matCellDef="let row">{{row.name}}</td>
+              </ng-container>
+
+              <!-- Country Column -->
+              <ng-container matColumnDef="country">
+                <th mat-header-cell *matHeaderCellDef>País</th>
+                <td mat-cell *matCellDef="let row">{{row.country}}</td>
+              </ng-container>
+
+              <!-- Country Column -->
+              <ng-container matColumnDef="city">
+                <th mat-header-cell *matHeaderCellDef>Ciudad</th>
+                <td mat-cell *matCellDef="let row">{{row.city}}</td>
+              </ng-container>
+              
+              <!--  Column -->
+              <ng-container matColumnDef="id">
+                <th mat-header-cell *matHeaderCellDef>&nbsp;</th>
+                <td mat-cell *matCellDef="let row">
+
+                  <div class="action-buttons">
+                    <a class="btn btn-primary btn-sm" (click)="goToAsset(row.id)" href="javascript:void(0)">
+                      Ir a planta
+                    </a>
+                  
+                  </div>
+                </td>
+              </ng-container>
+      
+              <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+              <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+            </table>
+            <mat-paginator [pageSizeOptions]="[5, 10, 25]"></mat-paginator>
+          </div>
+        </div>
+      </div>
+    </div>
+
 
   </div>
   <br>
+</div>

+ 22 - 2
src/app/components/dashboard/dashboard.component.ts

@@ -1,10 +1,14 @@
 import { ActivatedRoute, Router } from '@angular/router';
-import { Component, OnInit, Input, Output, EventEmitter, OnDestroy, NgZone } from '@angular/core';
+import { Component, OnInit, Input, Output, EventEmitter, OnDestroy, NgZone, ViewChild } from '@angular/core';
 import { Plant } from 'src/app/models/plant';
 import { PlantsService } from 'src/app/services/plants.service';
 import { OrganizationsService } from 'src/app/services/organizations.service';
 import { latLng, tileLayer, marker, Layer, icon, Map, latLngBounds, LatLng, point } from 'leaflet';
 
+import {MatPaginator} from '@angular/material/paginator';
+import {MatSort} from '@angular/material/sort';
+import {MatTableDataSource} from '@angular/material/table';
+
 import { of as observableOf, Observable, throwError, from } from 'rxjs';
 
 import * as moment from 'moment';
@@ -28,6 +32,9 @@ export class DashboardComponent implements OnInit {
 
 
   listAssets: any;
+  dataSource = new MatTableDataSource(this.listAssets);
+  displayedColumns: string[] = ['name', 'country', 'city', 'id'];
+
   error:boolean;
   listOrganizations: any;
   plantId: string;
@@ -69,6 +76,9 @@ export class DashboardComponent implements OnInit {
     zoom: 10,
     center: latLng([13.661714, -89.251530])
   };
+  
+  @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
+  @ViewChild(MatSort, {static: true}) sort: MatSort;
 
   constructor(
     private plantsService: PlantsService,
@@ -86,6 +96,14 @@ export class DashboardComponent implements OnInit {
     
     this.plantsService.getAllAssets().subscribe(res => {
       this.listAssets = res["data"]["assets"];
+
+      console.log(this.listAssets);
+      console.log("assets");
+      
+      this.dataSource.data = this.listAssets;
+      this.dataSource.paginator = this.paginator;
+      this.dataSource.sort = this.sort;
+
       this.assetKeys = Object.keys(this.listAssets);
       for (let prop in this.assetKeys){
         this.meterKeys2 = Object.keys(this.listAssets.map(item => item["meters_installed"])[prop]);
@@ -106,6 +124,7 @@ export class DashboardComponent implements OnInit {
   }
 
   ngOnInit(): void {
+    
 
     var responsiveOptions: any[] = [
       ['screen and (max-width: 640px)', {
@@ -119,13 +138,14 @@ export class DashboardComponent implements OnInit {
     ];
 
     setTimeout(() => {
+     
 
       if (this.listAssets != undefined) {
         this.addMarkers();
       }
 
       Swal.close();
-    }, 2700);
+    }, 1800);
 
   }
 

+ 61 - 4
src/app/components/organizations/organization/organization.component.html

@@ -6,14 +6,71 @@
       
       <div class="col-12 align-right">
         <div class="align-container">
+          <nav aria-label="breadcrumb">
+            <ol class="breadcrumb">
+              <li class="breadcrumb-item"><a [routerLink]="['/']">Dashboard</a></li>
+              <li class="breadcrumb-item"><a [routerLink]="['/organizations']">Organizaciones</a></li>
+              <li class="breadcrumb-item">Detalle de la organización</li>
+            </ol>
+          </nav>
+        </div>
+
+      </div>
+
+    </div>
+    <br>
+    <div class="row justify-content-center">
+      
+      <div class="col-8">
+        <div class="align-container">
+
+          <div class="card" *ngIf="organizationExists">
+            <div class="card-header card-header-icon card-header-rose">
+              <div class="card-icon"><i class="material-icons">map</i></div>
+              <h4 class="card-title">Organización</h4>
+            </div>
+            <div class="card-body">              
+              <div class="align-container">
+                <form class="form-auth-small ng-untouched ng-pristine ng-valid" [formGroup]="organizationForm">
+                  <div class="form-group">
+                    <label for="name">Nombre de la organización: </label>
+                    <input type="text" name="name" class="form-control" readonly formControlName="name" />
+                  </div>
+
+                  <div class="form-group">
+                    <label for="country">País: </label>
+                    <input type="text" name="country" class="form-control" readonly formControlName="country" />
+                  </div>
+                  
+                  <div class="form-group">
+                    <label for="city">Ciudad: </label>
+                    <input type="text" name="city" class="form-control" readonly formControlName="city" />
+                  </div>      
+                  
+                  <div class="form-group">
+                    <label for="contactName">Nombre contacto: </label>
+                    <input type="text" name="contactName" class="form-control" readonly formControlName="contactName" />
+                  </div>
 
-          <button class="btn btn-primary">
-            Nuevo registro
-          </button>
+                  <div class="form-group">
+                    <label for="contactNumber">Teléfono contacto: </label>
+                    <input type="text" name="contactNumber" class="form-control" readonly formControlName="contactNumber" />
+                  </div>
+                  
+                  <div class="form-group">
+                    <label for="address">Dirección: </label>
+                    <textarea name="address" class="form-control" rows="2" readonly formControlName="address"></textarea>
+                  </div>
+                  <!--<div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+                </form>
+              </div>
+            </div>
+          </div>
         </div>
       </div>
 
 
-    </div>          
+    </div>         
+    
   </div>
 </div>

+ 41 - 3
src/app/components/organizations/organization/organization.component.ts

@@ -1,4 +1,8 @@
 import { Component, OnInit } from '@angular/core';
+import { OrganizationsService } from '@app/services/organizations.service';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute } from '@angular/router';
+import Swal from 'sweetalert2';
 
 @Component({
   selector: 'app-organization',
@@ -6,11 +10,45 @@ import { Component, OnInit } from '@angular/core';
   styleUrls: ['./organization.component.scss']
 })
 export class OrganizationComponent implements OnInit {
-  title:string = "Detalle de organización"; 
+  [x: string]: any;
+  title:string = "Detalle de la organización"; 
+  listOrganization: any;
+  organizationExists:boolean;
+  organizationForm: FormGroup;
+  organizationId:any;
+  role_number: any;
 
-  constructor() { }
+  constructor(private orgService: OrganizationsService, private formBuilder: FormBuilder, private route: ActivatedRoute) {
 
-  ngOnInit() {
+    this.route.params.subscribe(params => {
+      this.organizationId = params['id'];
+    });
+
+    this.orgService.getOrganization(this.organizationId).subscribe(res => {
+      this.listOrganization = res["data"]["organization"];
+      this.organizationExists = true;
+
+      this.organizationForm = this.formBuilder.group({
+        name: [this.listOrganization.name],
+        address: [this.listOrganization.address],
+        city: [this.listOrganization.city],
+        country: [this.listOrganization.country],
+        contactName: [this.listOrganization.contactName],
+        contactNumber: [this.listOrganization.contactNumber],
+      });
+
+
+    }, (err) => {
+      Swal.fire({
+        type: 'error',
+        title: 'Error en el servidor',
+        text: "No su pudo obtener la informacion"
+      });
+    });
+
+  }
+
+  ngOnInit() { 
   }
 
 }

+ 3 - 0
src/app/components/organizations/organizations.component.html

@@ -58,6 +58,9 @@
                     <th mat-header-cell *matHeaderCellDef>&nbsp;</th>
                     <td mat-cell *matCellDef="let row">
                       <div class="action-buttons">
+                        <a class="btn btn-dark btn-sm" [routerLink]="['/organization', row.id]" *ngIf="allowedUser()" >
+                          Ver detalles
+                        </a>
                         <a class="btn btn-primary btn-sm" [routerLink]="['/organization', row.id, 'edit']" *ngIf="allowedUser()" >
                           Editar
                         </a>

+ 2 - 2
src/app/components/plugins/weather-card/weather-card.component.html

@@ -1,6 +1,6 @@
 <div class="widget">
   <div class="row">
-    <div class="col-lg-6 col-md-6 col-xs-12">
+    <div class="col-lg-7">
       <div class="date">
         {{currentDate}}
       </div>
@@ -11,7 +11,7 @@
         {{state}}
       </div>
     </div>
-    <div class="col-lg-6 col-md-6 col-xs-12">
+    <div class="col-5">
       <div class="temp">
          <img src="assets/img/{{icon}}.png" alt="" width="60" *ngIf="icon_exists">
          <span>{{temp}}°</span>

+ 2 - 1
src/app/components/plugins/weather-card/weather-card.component.scss

@@ -40,7 +40,8 @@ div.temp
     vertical-align: middle;
     text-align: right;
     margin-bottom: 20px;
-    font-size: 4em;
+    font-size: 3em;
+    font-weight: bold;
   }
 }
 

+ 1 - 1
src/app/components/shared/navbar/navbar.component.html

@@ -17,7 +17,7 @@
     <div class="collapse navbar-collapse justify-content-end" id="navigation">
       <ul class="navbar-nav">
         <li class="nav-item">
-          <a class="nav-link" href="javascript:void(0)" title="Dashboard">
+          <a class="nav-link" [routerLink]="[dashboard]"  title="Dashboard">
             <i class="material-icons">dashboard</i>
             <p>
               <span class="d-lg-none d-md-block">Stats</span>

+ 2 - 2
src/app/components/shared/sidebar/sidebar.component.html

@@ -34,10 +34,10 @@
     </ul>
     <ul *ngIf="adminMenu" class="nav">
       <li class="nav-item">
-        <a class="nav-link" href="javascript:void(0)">
+        <span class="nav-link">
           <i class="material-icons">settings_application</i>
           <p>Administración</p>
-        </a>
+        </span>
       </li>
       <li routerLinkActive="active" *ngFor="let menuItem of adminMenuItems" class="{{menuItem.class}} nav-item">
         <a class="nav-link" [routerLink]="[menuItem.path]" *ngIf="menuItem.allowed_roles.indexOf(+role_number)>-1"> 

+ 5 - 0
src/app/components/shared/sidebar/sidebar.component.scss

@@ -2,3 +2,8 @@ ul.nav.navbar-nav.nav-mobile-menu-bottom {
   bottom: 0;
   width: 100%;
 }
+
+span.nav-link{
+  margin: 10px 15px 0;
+  padding: 10px 12px;
+}

+ 2 - 0
src/app/components/shared/sidebar/sidebar.component.ts

@@ -14,6 +14,8 @@ declare interface RouteInfo {
 export const ROUTES: RouteInfo[] = [
     { path: '/dashboard', title: 'Dashboard',  icon: 'dashboard', class: '' },
     { path: '/assets', title: 'Plantas',  icon: 'wb_sunny', class: '' },
+    //{ path: '/examples', title: 'Ejemplo',  icon: 'wb_sunny', class: '' },
+    
     //{ path: '/profile', title: 'Perfil',  icon:'person', class: '' },
     /*{ path: '/table-list', title: 'Table List',  icon:'content_paste', class: '' },
     { path: '/typography', title: 'Typography',  icon:'library_books', class: '' },

+ 2 - 2
src/app/components/users/new-user/new-user.component.html

@@ -79,9 +79,9 @@
                         </label>
                       </div>
                       <div class="form-check form-check-inline">
-                        <input class="form-check-input" type="radio" formControlName="role" id="roleRadios3" value="3" 
+                        <input class="form-check-input" type="radio" formControlName="role" id="roleRadios4" value="3" 
                         [ngClass]="{ 'is-invalid': submitted && f.role.errors }">
-                        <label class="form-check-label" for="roleRadios3">
+                        <label class="form-check-label" for="roleRadios4">
                           Super Admin
                         </label>
                       </div>

+ 2 - 2
src/app/components/users/users.component.html

@@ -44,13 +44,13 @@
                   <!-- Country Column -->
                   <ng-container matColumnDef="last_name">
                     <th mat-header-cell *matHeaderCellDef>Apellido</th>
-                    <td mat-cell *matCellDef="let row">{{row.last_name}}</td>
+                    <td mat-cell *matCellDef="let row">{{row.role}}</td>
                   </ng-container>
                   
                   <!-- Country Column -->
                   <ng-container matColumnDef="role">
                     <th mat-header-cell *matHeaderCellDef>Rol</th>
-                    <td mat-cell *matCellDef="let row">{{row.role}}</td>
+                    <td mat-cell *matCellDef="let row">{{userType(row.role)}}</td>
                   </ng-container>
 
                   <!--  Column 

+ 14 - 0
src/app/components/users/users.component.ts

@@ -64,6 +64,20 @@ export class UsersComponent implements OnInit {
 
   }
 
+  userType(userRole:any){
+    switch (+userRole){
+      case 0:
+        return "Invitado";
+      case 1:
+        return "Usuario";
+      case 2:
+        return "Administrador";      
+      case 3:
+        return "Super Admin";
+    }
+  }
+
+
   applyFilter(filterValue: string) {
     this.dataSource.filter = filterValue.trim().toLowerCase();
     if (this.dataSource.paginator) {

+ 4 - 1
src/app/layouts/admin/admin.module.ts

@@ -28,6 +28,8 @@ import { NewUserComponent } from '@app/components/users/new-user/new-user.compon
 
 import { PluginsModule } from '../../components/plugins/plugins.module';
 
+import { MatTableExporterModule } from 'mat-table-exporter';
+
 import {
   MatButtonModule,
   MatInputModule,
@@ -63,6 +65,7 @@ import { BreadcrumbModule, IconsModule } from 'angular-bootstrap-md'
     MatPaginatorModule,
     MatProgressSpinnerModule,
     MatSortModule,
+    MatTableExporterModule,
     PluginsModule,
     LeafletModule,
     ChartsModule,
@@ -81,7 +84,7 @@ import { BreadcrumbModule, IconsModule } from 'angular-bootstrap-md'
     EditPlantComponent,
     NewPlantComponent,
     UsersComponent,
-    NewUserComponent
+    NewUserComponent,
   ]
 })
 

+ 2 - 35
src/app/services/logs.service.ts

@@ -40,41 +40,8 @@ export class LogsService {
     )
   }
 
-  getEnergyProducedByDay() {
-    return this.http.get(`${environment.apiUrl}/logs/energyProduced/1D`)
-    .pipe(
-      timeout(this.time),
-      map(response =>{
-        return response;
-      }),
-      catchError(this.errorHandl)
-    )
-  }
-
-  getEnergyProducedByWeek() {
-    return this.http.get(`${environment.apiUrl}/logs/energyProduced/7D`)
-    .pipe(
-      timeout(this.time),
-      map(response =>{
-        return response;
-      }),
-      catchError(this.errorHandl)
-    )
-  }
-  
-  getEnergyProducedByMonth() {
-    return this.http.get(`${environment.apiUrl}/logs/energyProduced/1M`)
-    .pipe(
-      timeout(this.time),
-      map(response =>{
-        return response;
-      }),
-      catchError(this.errorHandl)
-    )
-  }
-
-  getEnergyProducedByYear() {
-    return this.http.get(`${environment.apiUrl}/logs/energyProduced/YTD`)
+  getAssetEnviromentalStats(id:string){
+    return this.http.get(`${environment.productionApiUrl}/asset/${id}/environmentals`)
     .pipe(
       timeout(this.time),
       map(response =>{

BIN
src/assets/img/barrels2.png


BIN
src/assets/img/car-smoke.png


BIN
src/assets/img/car2-icon.png


BIN
src/assets/img/favicon.png


BIN
src/assets/img/poweredhouse.png


+ 1 - 1
src/assets/scss/core/_sidebar-and-main-panel.scss

@@ -131,7 +131,7 @@
         }
 
         li{
-            > a{
+            > a, span{
               &:hover,
               &:focus{
                   background-color: transparent;

+ 6 - 1
src/assets/scss/material-dashboard.scss

@@ -65,7 +65,7 @@
 
 .cream-skin {
   background-color: $palette-cream;
-  border-color: #fdeaa7;
+  border-color: #fdeaa7 !important;
 }
 
 .yellow-skin {
@@ -78,6 +78,11 @@
   border-color: #cf6a14 !important;
 }
 
+.green-skin {
+  background-color: #548c2f;
+  border-color: #104911 !important;
+}
+
 .widget {
   background-color: #fff;
 }

+ 2 - 1
src/index.html

@@ -15,9 +15,10 @@
     <!--     Fonts and icons     -->
     <link href='https://fonts.googleapis.com/css?family=Roboto:400,700,300|Material+Icons' rel='stylesheet' type='text/css'>
     <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDJ2_cgrOMUZ9v3UgDYQrpBYKjO7h70N9E"></script>
-
+    <script src="https://kit.fontawesome.com/22ac039de1.js" crossorigin="anonymous"></script>
     <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
     <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+
 </head>
 <body>
   <app-root>

+ 3 - 1
src/material-dashboard.css

@@ -13188,7 +13188,8 @@ h2.title {
     .sidebar-mini .sidebar .sidebar-wrapper > .nav [data-toggle="collapse"] ~ div > ul > li > a .sidebar-normal,
     .sidebar-mini .sidebar .sidebar-wrapper .user .user-info [data-toggle="collapse"] ~ div > ul > li > a .sidebar-normal,
     .sidebar-mini .sidebar .sidebar-wrapper .user .user-info > a > span,
-    .sidebar-mini .sidebar .sidebar-wrapper > .nav li > a p {
+    .sidebar-mini .sidebar .sidebar-wrapper > .nav li > a p,
+    .sidebar-mini .sidebar .sidebar-wrapper > .nav li > span p {
       -webkit-transform: translate3d(-25px, 0, 0);
       transform: translate3d(-25px, 0, 0);
       opacity: 0; }
@@ -13201,6 +13202,7 @@ h2.title {
     .sidebar-mini .sidebar:hover .sidebar-wrapper {
       width: 260px; }
       .sidebar-mini .sidebar:hover .sidebar-wrapper > .nav li > a p,
+      .sidebar-mini .sidebar .sidebar-wrapper > .nav li > span p,
       .sidebar-mini .sidebar:hover .sidebar-wrapper > .nav [data-toggle="collapse"] ~ div > ul > li > a .sidebar-normal,
       .sidebar-mini .sidebar:hover .sidebar-wrapper .user .user-info [data-toggle="collapse"] ~ div > ul > li > a .sidebar-normal,
       .sidebar-mini .sidebar:hover .sidebar-wrapper .user .user-info > a > span {

+ 1 - 1
src/polyfills.ts

@@ -19,7 +19,7 @@
  */
 
 /** IE10 and IE11 requires the following for NgClass support on SVG elements */
-// import 'classlist.js';  // Run `npm install --save classlist.js`.
+import 'classlist.js';  // Run `npm install --save classlist.js`.
 
 /**
  * Web Animations `@angular/platform-browser/animations`

+ 3 - 1
tsconfig.json

@@ -4,6 +4,7 @@
     "baseUrl": "./",
     "outDir": "./dist/out-tsc",
     "sourceMap": true,
+    "allowSyntheticDefaultImports": true,
     "declaration": false,
     "downlevelIteration": true,
     "experimentalDecorators": true,
@@ -26,6 +27,7 @@
   },
   "angularCompilerOptions": {
     "fullTemplateTypeCheck": true,
-    "strictInjectionParameters": true
+    "strictInjectionParameters": true,
+    "allowSyntheticDefaultImports": true,
   }
 }