diff --git a/.gitignore b/.gitignore index 86d943a..8cd473a 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,15 @@ testem.log # System Files .DS_Store Thumbs.db + +#amplify +amplify/\#current-cloud-backend +amplify/.config/local-* +amplify/mock-data +amplify/backend/amplify-meta.json +amplify/backend/awscloudformation +build/ +dist/ +node_modules/ +aws-exports.js +awsconfiguration.json \ No newline at end of file diff --git a/amplify/.config/project-config.json b/amplify/.config/project-config.json new file mode 100644 index 0000000..fc9461d --- /dev/null +++ b/amplify/.config/project-config.json @@ -0,0 +1,17 @@ +{ + "projectName": "HPIoTWebApp", + "version": "2.0", + "frontend": "javascript", + "javascript": { + "framework": "angular", + "config": { + "SourceDir": "src", + "DistributionDir": "dist/HPIoTWebApp", + "BuildCommand": "npm.cmd run-script build", + "StartCommand": "npm start" + } + }, + "providers": [ + "awscloudformation" + ] +} \ No newline at end of file diff --git a/amplify/backend/backend-config.json b/amplify/backend/backend-config.json new file mode 100644 index 0000000..0a1e195 --- /dev/null +++ b/amplify/backend/backend-config.json @@ -0,0 +1,8 @@ +{ + "hosting": { + "S3AndCloudFront": { + "service": "S3AndCloudFront", + "providerPlugin": "awscloudformation" + } + } +} \ No newline at end of file diff --git a/amplify/backend/hosting/S3AndCloudFront/parameters.json b/amplify/backend/hosting/S3AndCloudFront/parameters.json new file mode 100644 index 0000000..3641037 --- /dev/null +++ b/amplify/backend/hosting/S3AndCloudFront/parameters.json @@ -0,0 +1,3 @@ +{ + "bucketName": "hpiotwebapp" +} \ No newline at end of file diff --git a/amplify/backend/hosting/S3AndCloudFront/template.json b/amplify/backend/hosting/S3AndCloudFront/template.json new file mode 100644 index 0000000..57f33a7 --- /dev/null +++ b/amplify/backend/hosting/S3AndCloudFront/template.json @@ -0,0 +1,271 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Hosting resource stack creation using Amplify CLI", + "Parameters": { + "env": { + "Type": "String" + }, + "bucketName": { + "Type": "String" + } + }, + "Conditions": { + "ShouldNotCreateEnvResources": { + "Fn::Equals": [ + { + "Ref": "env" + }, + "NONE" + ] + } + }, + "Resources": { + "S3Bucket": { + "Type": "AWS::S3::Bucket", + "DeletionPolicy": "Retain", + "Properties": { + "BucketName": { + "Fn::If": [ + "ShouldNotCreateEnvResources", + { + "Ref": "bucketName" + }, + { + "Fn::Join": [ + "", + [ + { + "Ref": "bucketName" + }, + "-", + { + "Ref": "env" + } + ] + ] + } + ] + }, + "WebsiteConfiguration": { + "IndexDocument": "index.html", + "ErrorDocument": "index.html" + }, + "CorsConfiguration": { + "CorsRules": [ + { + "AllowedHeaders": [ + "Authorization", + "Content-Length" + ], + "AllowedMethods": [ + "GET" + ], + "AllowedOrigins": [ + "*" + ], + "MaxAge": 3000 + } + ] + } + } + }, + "PrivateBucketPolicy": { + "Type": "AWS::S3::BucketPolicy", + "DependsOn": "OriginAccessIdentity", + "Properties": { + "PolicyDocument": { + "Id": "MyPolicy", + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "APIReadForGetBucketObjects", + "Effect": "Allow", + "Principal": { + "CanonicalUser": { + "Fn::GetAtt": [ + "OriginAccessIdentity", + "S3CanonicalUserId" + ] + } + }, + "Action": "s3:GetObject", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:aws:s3:::", + { + "Ref": "S3Bucket" + }, + "/*" + ] + ] + } + } + ] + }, + "Bucket": { + "Ref": "S3Bucket" + } + } + }, + "OriginAccessIdentity": { + "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", + "Properties": { + "CloudFrontOriginAccessIdentityConfig": { + "Comment": "CloudFrontOriginAccessIdentityConfig" + } + } + }, + "CloudFrontDistribution": { + "Type": "AWS::CloudFront::Distribution", + "DependsOn": [ + "S3Bucket", + "OriginAccessIdentity" + ], + "Properties": { + "DistributionConfig": { + "Origins": [ + { + "DomainName": { + "Fn::GetAtt": [ + "S3Bucket", + "DomainName" + ] + }, + "Id": "hostingS3Bucket", + "S3OriginConfig": { + "OriginAccessIdentity": { + "Fn::Join": [ + "", + [ + "origin-access-identity/cloudfront/", + { + "Ref": "OriginAccessIdentity" + } + ] + ] + } + } + } + ], + "Enabled": "true", + "DefaultCacheBehavior": { + "AllowedMethods": [ + "DELETE", + "GET", + "HEAD", + "OPTIONS", + "PATCH", + "POST", + "PUT" + ], + "TargetOriginId": "hostingS3Bucket", + "ForwardedValues": { + "QueryString": "false" + }, + "ViewerProtocolPolicy": "redirect-to-https", + "DefaultTTL": 86400, + "MaxTTL": 31536000, + "MinTTL": 60, + "Compress": true + }, + "DefaultRootObject": "index.html", + "CustomErrorResponses": [ + { + "ErrorCachingMinTTL": 300, + "ErrorCode": 400, + "ResponseCode": 200, + "ResponsePagePath": "/" + }, + { + "ErrorCachingMinTTL": 300, + "ErrorCode": 403, + "ResponseCode": 200, + "ResponsePagePath": "/" + }, + { + "ErrorCachingMinTTL": 300, + "ErrorCode": 404, + "ResponseCode": 200, + "ResponsePagePath": "/" + } + ] + } + } + } + }, + "Outputs": { + "Region": { + "Value": { + "Ref": "AWS::Region" + } + }, + "HostingBucketName": { + "Description": "Hosting bucket name", + "Value": { + "Ref": "S3Bucket" + } + }, + "WebsiteURL": { + "Value": { + "Fn::GetAtt": [ + "S3Bucket", + "WebsiteURL" + ] + }, + "Description": "URL for website hosted on S3" + }, + "S3BucketSecureURL": { + "Value": { + "Fn::Join": [ + "", + [ + "https://", + { + "Fn::GetAtt": [ + "S3Bucket", + "DomainName" + ] + } + ] + ] + }, + "Description": "Name of S3 bucket to hold website content" + }, + "CloudFrontDistributionID": { + "Value": { + "Ref": "CloudFrontDistribution" + } + }, + "CloudFrontDomainName": { + "Value": { + "Fn::GetAtt": [ + "CloudFrontDistribution", + "DomainName" + ] + } + }, + "CloudFrontSecureURL": { + "Value": { + "Fn::Join": [ + "", + [ + "https://", + { + "Fn::GetAtt": [ + "CloudFrontDistribution", + "DomainName" + ] + } + ] + ] + } + }, + "CloudFrontOriginAccessIdentity": { + "Value": { + "Ref": "OriginAccessIdentity" + } + } + } +} \ No newline at end of file diff --git a/amplify/team-provider-info.json b/amplify/team-provider-info.json new file mode 100644 index 0000000..e41c0fd --- /dev/null +++ b/amplify/team-provider-info.json @@ -0,0 +1,14 @@ +{ + "dev": { + "awscloudformation": { + "AuthRoleName": "hpiotwebapp-dev-20191011145158-authRole", + "UnauthRoleArn": "arn:aws:iam::860246592755:role/hpiotwebapp-dev-20191011145158-unauthRole", + "AuthRoleArn": "arn:aws:iam::860246592755:role/hpiotwebapp-dev-20191011145158-authRole", + "Region": "us-east-1", + "DeploymentBucketName": "hpiotwebapp-dev-20191011145158-deployment", + "UnauthRoleName": "hpiotwebapp-dev-20191011145158-unauthRole", + "StackName": "hpiotwebapp-dev-20191011145158", + "StackId": "arn:aws:cloudformation:us-east-1:860246592755:stack/hpiotwebapp-dev-20191011145158/95829790-ec60-11e9-a33f-1207b4ca758c" + } + } +} \ No newline at end of file diff --git a/angular.json b/angular.json index f89e216..6925efc 100644 --- a/angular.json +++ b/angular.json @@ -25,9 +25,11 @@ "aot": false, "assets": [ "src/favicon.ico", - "src/assets" + "src/assets", + "src/manifest.webmanifest" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css", "src/styles.scss" ], "scripts": [] @@ -60,7 +62,9 @@ "maximumWarning": "6kb", "maximumError": "10kb" } - ] + ], + "serviceWorker": true, + "ngswConfigPath": "ngsw-config.json" } } }, @@ -90,9 +94,11 @@ "karmaConfig": "karma.conf.js", "assets": [ "src/favicon.ico", - "src/assets" + "src/assets", + "src/manifest.webmanifest" ], "styles": [ + "./node_modules/@angular/material/prebuilt-themes/deeppurple-amber.css", "src/styles.scss" ], "scripts": [] @@ -124,6 +130,7 @@ } } } - }}, + } + }, "defaultProject": "HPIoTWebApp" } \ No newline at end of file diff --git a/ngsw-config.json b/ngsw-config.json new file mode 100644 index 0000000..4ddf1a7 --- /dev/null +++ b/ngsw-config.json @@ -0,0 +1,29 @@ +{ + "$schema": "./node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "assetGroups": [ + { + "name": "app", + "installMode": "prefetch", + "resources": { + "files": [ + "/favicon.ico", + "/index.html", + "/manifest.webmanifest", + "/*.css", + "/*.js" + ] + } + }, { + "name": "assets", + "installMode": "lazy", + "updateMode": "prefetch", + "resources": { + "files": [ + "/assets/**", + "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)" + ] + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index a057706..f6049fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -134,6 +134,23 @@ "tslib": "^1.9.0" } }, + "@angular/cdk": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.2.3.tgz", + "integrity": "sha512-ZwO5Sn720RA2YvBqud0JAHkZXjmjxM0yNzCO8RVtRE9i8Gl26Wk0j0nQeJkVm4zwv2QO8MwbKUKGTMt8evsokA==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^1.7.1" + }, + "dependencies": { + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "optional": true + } + } + }, "@angular/cli": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.2.2.tgz", @@ -996,6 +1013,14 @@ "integrity": "sha512-VJaFkbffRPh4WC8aW01BXljLVyiMs2p32LgGxPTntNZ4cSLDRkUXkIoiCMUK9CHl+RCstFKWhlDnppONDePONw==", "dev": true }, + "@angular/material": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-8.2.3.tgz", + "integrity": "sha512-SOczkIaqes+r+9XF/UUiokidfFKBpHkOPIaFK857sFD0FBNPvPEpOr5oHKCG3feERRwAFqHS7Wo2ohVEWypb5A==", + "requires": { + "tslib": "^1.7.1" + } + }, "@angular/platform-browser": { "version": "8.2.10", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.2.10.tgz", @@ -1012,6 +1037,49 @@ "tslib": "^1.9.0" } }, + "@angular/pwa": { + "version": "0.803.9", + "resolved": "https://registry.npmjs.org/@angular/pwa/-/pwa-0.803.9.tgz", + "integrity": "sha512-x3PMgEVGLolFQ+e5Pj9ppcm3KwSGhut6Ibe6Zy3H9p064H76FSgGrh/PlatUHHAtWHVe2GYb3p7RKXqRrwsK+g==", + "requires": { + "@angular-devkit/core": "8.3.9", + "@angular-devkit/schematics": "8.3.9", + "@schematics/angular": "8.3.9", + "parse5-html-rewriting-stream": "5.1.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.9.tgz", + "integrity": "sha512-LYNdY8UpcEGaqWq0smPhSAiz+Oq1gv4j1LGLLyY1d2CJpf4czIuI8SkTHtmGMjpKy8ss/Vk1mHwRjBrWB0dUag==", + "requires": { + "ajv": "6.10.2", + "fast-json-stable-stringify": "2.0.0", + "magic-string": "0.25.3", + "rxjs": "6.4.0", + "source-map": "0.7.3" + } + }, + "@angular-devkit/schematics": { + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.9.tgz", + "integrity": "sha512-JKrXdbJhyvvMfSoJ01l5zDk1Rhg0em0tgyzFWiqQ+cSt/zbPQrDRDpNJ7f95dPNu6R1KCuojAnaC8MXKRNTm0A==", + "requires": { + "@angular-devkit/core": "8.3.9", + "rxjs": "6.4.0" + } + }, + "@schematics/angular": { + "version": "8.3.9", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.9.tgz", + "integrity": "sha512-hVEkssR35otuZbHUYx9bwhhGms5deM4+lJG+FeasAjPCNkOVzIemVvF/DuBDitb4WxGpr99hjtEBr7yBIyVAUQ==", + "requires": { + "@angular-devkit/core": "8.3.9", + "@angular-devkit/schematics": "8.3.9" + } + } + } + }, "@angular/router": { "version": "8.2.10", "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.10.tgz", @@ -1020,6 +1088,14 @@ "tslib": "^1.9.0" } }, + "@angular/service-worker": { + "version": "8.2.10", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-8.2.10.tgz", + "integrity": "sha512-xBRtK73VmQIr2MuxFwVG9dZOkG6Wlsjdr/T2h8r1IT4+9s0sunBlscPfmeYtg6KaoPVGuMvS0h2vVp9Aq+f+ag==", + "requires": { + "tslib": "^1.9.0" + } + }, "@babel/code-frame": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", @@ -1553,7 +1629,6 @@ "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -3930,14 +4005,12 @@ "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fastparse": { "version": "1.1.2", @@ -4315,6 +4388,11 @@ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", "dev": true }, + "hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" + }, "handle-thing": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", @@ -5418,8 +5496,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { "version": "5.0.1", @@ -6442,7 +6519,6 @@ "version": "0.25.3", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", - "dev": true, "requires": { "sourcemap-codec": "^1.4.4" } @@ -7565,6 +7641,37 @@ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "dev": true }, + "parse5-html-rewriting-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-5.1.0.tgz", + "integrity": "sha512-hZlaOTHJs4dpC5yFHnOSEMh26ErsqTsLzxKqkuRcUqtiu0kMsBQ9pkgANkECDyoBUhJ3+hvb2DPLsyqbtcS61Q==", + "requires": { + "parse5": "^5.1.0", + "parse5-sax-parser": "^5.1.0" + }, + "dependencies": { + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" + } + } + }, + "parse5-sax-parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-5.1.0.tgz", + "integrity": "sha512-VEhdEDhBkoSILPmsZ96SoIIUow3hZbtgQsqXw7r8DxxnqsCIO0fwkT9mWgBcf9SPjVUh92liuEprHrrYzXBPWQ==", + "requires": { + "parse5": "^5.1.0" + }, + "dependencies": { + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" + } + } + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -8104,8 +8211,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "q": { "version": "1.4.1", @@ -9207,8 +9313,7 @@ "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" }, "source-map-loader": { "version": "0.2.4", @@ -9260,8 +9365,7 @@ "sourcemap-codec": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", - "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", - "dev": true + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==" }, "spdx-correct": { "version": "3.1.0", @@ -10127,7 +10231,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, "requires": { "punycode": "^2.1.0" } diff --git a/package.json b/package.json index 130cce7..c63f69d 100644 --- a/package.json +++ b/package.json @@ -12,13 +12,18 @@ "private": true, "dependencies": { "@angular/animations": "~8.2.0", + "@angular/cdk": "~8.2.3", "@angular/common": "~8.2.0", "@angular/compiler": "~8.2.0", "@angular/core": "~8.2.0", "@angular/forms": "~8.2.0", + "@angular/material": "^8.2.3", "@angular/platform-browser": "~8.2.0", "@angular/platform-browser-dynamic": "~8.2.0", + "@angular/pwa": "^0.803.9", "@angular/router": "~8.2.0", + "@angular/service-worker": "~8.2.0", + "hammerjs": "^2.0.8", "rxjs": "~6.4.0", "tslib": "^1.10.0", "zone.js": "~0.9.1" diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 06c7342..be5efb9 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,8 +1,11 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; +import { HomeComponent } from './home/home.component'; -const routes: Routes = []; +const routes: Routes = [ + { path: '', component: HomeComponent} +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.component.html b/src/app/app.component.html index 0f3d9d8..5c7c82b 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,21 +1,51 @@ - -
-

- Welcome to {{ title }}! -

- Angular Logo -
-

Here are some links to help you start:

- - - +
+ + +
+ + + {{route.title}} + + +
+
+ + + + {{title}} +
+ +
+ + +
+ + + {{route.title}} + + +
+
+ +
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/app.component.scss b/src/app/app.component.scss index e69de29..fa6c97b 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -0,0 +1,80 @@ +@import '~@angular/material/theming'; + +// Plus imports for other components in your app. + +// Include the common styles for Angular Material. We include this here so that you only +// have to load a single css file for Angular Material in your app. +// Be sure that you only ever include this mixin once! +@include mat-core(); + +// Define the palettes for your theme using the Material Design palettes available in palette.scss +// (imported above). For each palette, you can optionally specify a default, lighter, and darker +// hue. Available color palettes: https://material.io/design/color/ +$app-primary: mat-palette($mat-indigo, 800); +$app-accent: mat-palette($mat-pink, 800); +$app-active: mat-palette($mat-pink, 800); + +// The warn palette is optional (defaults to red). +$app-warn: mat-palette($mat-red); + +// Create the theme object (a Sass map containing all of the palettes). +$app-theme: mat-light-theme($app-primary, $app-accent, $app-warn); + +// Include theme styles for core and each component used in your app. +// Alternatively, you can import and @include the theme mixins for each component +// that you are using. +@include angular-material-theme($app-theme); + +.active { + color: mat-color($app-primary); +} +.valid, .primary { + color: mat-color($app-primary); +} + + + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } +form { + width: 100%; +} + +form > * { + margin-bottom: 1.5em; + width: 100%; +} + +a { + color: mat-color($app-accent); +} + +.content { + padding: 0.5em; +} + +.sidenav-content { + flex-direction: column; +} + +.sidenav-container { + height: 90%; +} + +.app-content { + flex: 1; + margin: 0 auto; + padding: 2em; +} + +.cursor-pointer { + cursor: pointer; +} + +.full-width { + width: 100%; +} + +.active { + color: mat-color($app-active); +} \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 4c0e390..8819f45 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,6 @@ -import { Component } from '@angular/core'; +import { Component, ChangeDetectorRef, EventEmitter, Output } from '@angular/core'; +import { MediaMatcher } from '@angular/cdk/layout'; +import { MatSidenav } from '@angular/material'; @Component({ selector: 'app-root', @@ -6,5 +8,28 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.scss'] }) export class AppComponent { - title = 'HPIoTWebApp'; + title = 'Material PWA'; + mobileQuery: MediaQueryList; + nav = [ + { + 'title': 'Home', + 'path': '/' + }, + { + 'title': 'This is a second link', + 'path': '/auth' + } + ]; + private mobileQueryListener: () => void; + @Output() toggleSideNav = new EventEmitter(); + constructor( changeDetectorRef: ChangeDetectorRef, media: MediaMatcher ) { + this.mobileQuery = media.matchMedia('(max-width: 600px)'); + this.mobileQueryListener = () => changeDetectorRef.detectChanges(); + this.mobileQuery.addListener(this.mobileQueryListener); + } + toggleMobileNav(nav: MatSidenav) { + if (this.mobileQuery.matches) { + nav.toggle(); + } + } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2c3ba29..a519d65 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -3,14 +3,23 @@ import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { MaterialModule } from './material/material.module'; +import { HomeComponent } from './home/home.component'; +import { ServiceWorkerModule } from '@angular/service-worker'; +import { environment } from '../environments/environment'; @NgModule({ declarations: [ - AppComponent + AppComponent, + HomeComponent ], imports: [ BrowserModule, - AppRoutingModule + AppRoutingModule, + BrowserAnimationsModule, + MaterialModule, + ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }) ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html new file mode 100644 index 0000000..0e3f8ed --- /dev/null +++ b/src/app/home/home.component.html @@ -0,0 +1,12 @@ +
+
+
+

Location: {{ msg.location.S }}

+

Company: {{ msg.company.S }}

+

Volume Flow: {{ msg.volume_flow.N }}

+

Field: {{ msg.field.S }}

+

---------------------------------

+
+
+
+ \ No newline at end of file diff --git a/src/app/home/home.component.scss b/src/app/home/home.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts new file mode 100644 index 0000000..490e81b --- /dev/null +++ b/src/app/home/home.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HomeComponent } from './home.component'; + +describe('HomeComponent', () => { + let component: HomeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HomeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HomeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts new file mode 100644 index 0000000..fcc9da5 --- /dev/null +++ b/src/app/home/home.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit } from '@angular/core'; +import { WebSocketSubject } from 'rxjs/webSocket'; +@Component({ + selector: 'app-home', + templateUrl: './home.component.html', + styleUrls: ['./home.component.scss'] +}) +export class HomeComponent implements OnInit { + + public serverMessages = new Array(); + + private socket$: WebSocketSubject; + + constructor() { + + this.socket$ = new WebSocketSubject('wss://3fseaywb8b.execute-api.us-east-1.amazonaws.com/prototype'); + + this.socket$ + .subscribe( + (message) => this.serverMessages.push(message), + (err) => console.error(err), + () => console.warn('Completed!') + ); + } + + ngOnInit() { + } + +} diff --git a/src/app/material/material.module.ts b/src/app/material/material.module.ts new file mode 100644 index 0000000..aac6f42 --- /dev/null +++ b/src/app/material/material.module.ts @@ -0,0 +1,82 @@ +import { NgModule } from '@angular/core'; +import { CdkTableModule } from '@angular/cdk/table'; +import { CdkTreeModule } from '@angular/cdk/tree'; +import { + MatAutocompleteModule, + MatBadgeModule, + MatBottomSheetModule, + MatButtonModule, + MatButtonToggleModule, + MatCardModule, + MatCheckboxModule, + MatChipsModule, + MatDatepickerModule, + MatDialogModule, + MatDividerModule, + MatExpansionModule, + MatGridListModule, + MatIconModule, + MatInputModule, + MatListModule, + MatMenuModule, + MatNativeDateModule, + MatPaginatorModule, + MatProgressBarModule, + MatProgressSpinnerModule, + MatRadioModule, + MatRippleModule, + MatSelectModule, + MatSidenavModule, + MatSliderModule, + MatSlideToggleModule, + MatSnackBarModule, + MatSortModule, + MatStepperModule, + MatTableModule, + MatTabsModule, + MatToolbarModule, + MatTooltipModule, + MatTreeModule, +} from '@angular/material'; +@NgModule({ + exports: [ + CdkTableModule, + CdkTreeModule, + MatAutocompleteModule, + MatBadgeModule, + MatBottomSheetModule, + MatButtonModule, + MatButtonToggleModule, + MatCardModule, + MatCheckboxModule, + MatChipsModule, + MatStepperModule, + MatDatepickerModule, + MatDialogModule, + MatDividerModule, + MatExpansionModule, + MatGridListModule, + MatIconModule, + MatInputModule, + MatListModule, + MatMenuModule, + MatNativeDateModule, + MatPaginatorModule, + MatProgressBarModule, + MatProgressSpinnerModule, + MatRadioModule, + MatRippleModule, + MatSelectModule, + MatSidenavModule, + MatSliderModule, + MatSlideToggleModule, + MatSnackBarModule, + MatSortModule, + MatTableModule, + MatTabsModule, + MatToolbarModule, + MatTooltipModule, + MatTreeModule, + ] +}) +export class MaterialModule { } diff --git a/src/assets/icons/icon-128x128.png b/src/assets/icons/icon-128x128.png new file mode 100644 index 0000000..9f9241f Binary files /dev/null and b/src/assets/icons/icon-128x128.png differ diff --git a/src/assets/icons/icon-144x144.png b/src/assets/icons/icon-144x144.png new file mode 100644 index 0000000..4a5f8c1 Binary files /dev/null and b/src/assets/icons/icon-144x144.png differ diff --git a/src/assets/icons/icon-152x152.png b/src/assets/icons/icon-152x152.png new file mode 100644 index 0000000..34a1a8d Binary files /dev/null and b/src/assets/icons/icon-152x152.png differ diff --git a/src/assets/icons/icon-192x192.png b/src/assets/icons/icon-192x192.png new file mode 100644 index 0000000..9172e5d Binary files /dev/null and b/src/assets/icons/icon-192x192.png differ diff --git a/src/assets/icons/icon-384x384.png b/src/assets/icons/icon-384x384.png new file mode 100644 index 0000000..e54e8d3 Binary files /dev/null and b/src/assets/icons/icon-384x384.png differ diff --git a/src/assets/icons/icon-512x512.png b/src/assets/icons/icon-512x512.png new file mode 100644 index 0000000..51ee297 Binary files /dev/null and b/src/assets/icons/icon-512x512.png differ diff --git a/src/assets/icons/icon-72x72.png b/src/assets/icons/icon-72x72.png new file mode 100644 index 0000000..2814a3f Binary files /dev/null and b/src/assets/icons/icon-72x72.png differ diff --git a/src/assets/icons/icon-96x96.png b/src/assets/icons/icon-96x96.png new file mode 100644 index 0000000..d271025 Binary files /dev/null and b/src/assets/icons/icon-96x96.png differ diff --git a/src/index.html b/src/index.html index 320037c..282377b 100644 --- a/src/index.html +++ b/src/index.html @@ -7,8 +7,13 @@ + + + + + diff --git a/src/main.ts b/src/main.ts index c7b673c..3b2b7d0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,3 +1,4 @@ +import 'hammerjs'; import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest new file mode 100644 index 0000000..f66e8a7 --- /dev/null +++ b/src/manifest.webmanifest @@ -0,0 +1,51 @@ +{ + "name": "HPIoTWebApp", + "short_name": "HPIoTWebApp", + "theme_color": "#1976d2", + "background_color": "#fafafa", + "display": "standalone", + "scope": "/", + "start_url": "/", + "icons": [ + { + "src": "assets/icons/icon-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "assets/icons/icon-96x96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "assets/icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "assets/icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "assets/icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png" + }, + { + "src": "assets/icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "assets/icons/icon-384x384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "assets/icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} \ No newline at end of file diff --git a/src/styles.scss b/src/styles.scss index 90d4ee0..7e7239a 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1 +1,4 @@ /* You can add global styles to this file, and also import other style files */ + +html, body { height: 100%; } +body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }