added auth and data collection
This commit is contained in:
15
.gitignore
vendored
15
.gitignore
vendored
@@ -21,3 +21,18 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
#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
|
||||
amplifyconfiguration.json
|
||||
amplify-gradle-config.json
|
||||
amplifyxc.config
|
||||
17
amplify/.config/project-config.json
Normal file
17
amplify/.config/project-config.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"projectName": "hpiot-react",
|
||||
"version": "3.0",
|
||||
"frontend": "javascript",
|
||||
"javascript": {
|
||||
"framework": "react",
|
||||
"config": {
|
||||
"SourceDir": "src",
|
||||
"DistributionDir": "build",
|
||||
"BuildCommand": "npm run-script build",
|
||||
"StartCommand": "npm run-script start"
|
||||
}
|
||||
},
|
||||
"providers": [
|
||||
"awscloudformation"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
AWSTemplateFormatVersion: 2010-09-09
|
||||
|
||||
Parameters:
|
||||
env:
|
||||
Type: String
|
||||
authRoleArn:
|
||||
Type: String
|
||||
unauthRoleArn:
|
||||
Type: String
|
||||
|
||||
|
||||
|
||||
|
||||
identityPoolName:
|
||||
Type: String
|
||||
|
||||
allowUnauthenticatedIdentities:
|
||||
Type: String
|
||||
|
||||
resourceNameTruncated:
|
||||
Type: String
|
||||
|
||||
userPoolName:
|
||||
Type: String
|
||||
|
||||
autoVerifiedAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
mfaConfiguration:
|
||||
Type: String
|
||||
|
||||
mfaTypes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
smsAuthenticationMessage:
|
||||
Type: String
|
||||
|
||||
smsVerificationMessage:
|
||||
Type: String
|
||||
|
||||
emailVerificationSubject:
|
||||
Type: String
|
||||
|
||||
emailVerificationMessage:
|
||||
Type: String
|
||||
|
||||
defaultPasswordPolicy:
|
||||
Type: String
|
||||
|
||||
passwordPolicyMinLength:
|
||||
Type: Number
|
||||
|
||||
passwordPolicyCharacters:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
requiredAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userpoolClientGenerateSecret:
|
||||
Type: String
|
||||
|
||||
userpoolClientRefreshTokenValidity:
|
||||
Type: Number
|
||||
|
||||
userpoolClientWriteAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userpoolClientReadAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userpoolClientLambdaRole:
|
||||
Type: String
|
||||
|
||||
userpoolClientSetAttributes:
|
||||
Type: String
|
||||
|
||||
resourceName:
|
||||
Type: String
|
||||
|
||||
authSelections:
|
||||
Type: String
|
||||
|
||||
useDefault:
|
||||
Type: String
|
||||
|
||||
usernameAttributes:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
userPoolGroupList:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
dependsOn:
|
||||
Type: CommaDelimitedList
|
||||
|
||||
Conditions:
|
||||
ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ]
|
||||
|
||||
Resources:
|
||||
|
||||
|
||||
# BEGIN SNS ROLE RESOURCE
|
||||
SNSRole:
|
||||
# Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
RoleName: !If [ShouldNotCreateEnvResources, 'hpiotr8c9024fb_sns-role', !Join ['',[ 'sns', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]]
|
||||
AssumeRolePolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
- Sid: ""
|
||||
Effect: "Allow"
|
||||
Principal:
|
||||
Service: "cognito-idp.amazonaws.com"
|
||||
Action:
|
||||
- "sts:AssumeRole"
|
||||
Condition:
|
||||
StringEquals:
|
||||
sts:ExternalId: hpiotr8c9024fb_role_external_id
|
||||
Policies:
|
||||
-
|
||||
PolicyName: hpiotr8c9024fb-sns-policy
|
||||
PolicyDocument:
|
||||
Version: "2012-10-17"
|
||||
Statement:
|
||||
-
|
||||
Effect: "Allow"
|
||||
Action:
|
||||
- "sns:Publish"
|
||||
Resource: "*"
|
||||
# BEGIN USER POOL RESOURCES
|
||||
UserPool:
|
||||
# Created upon user selection
|
||||
# Depends on SNS Role for Arn if MFA is enabled
|
||||
Type: AWS::Cognito::UserPool
|
||||
UpdateReplacePolicy: Retain
|
||||
Properties:
|
||||
UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]]
|
||||
|
||||
Schema:
|
||||
|
||||
-
|
||||
Name: email
|
||||
Required: true
|
||||
Mutable: true
|
||||
|
||||
|
||||
|
||||
|
||||
AutoVerifiedAttributes: !Ref autoVerifiedAttributes
|
||||
|
||||
|
||||
EmailVerificationMessage: !Ref emailVerificationMessage
|
||||
EmailVerificationSubject: !Ref emailVerificationSubject
|
||||
|
||||
Policies:
|
||||
PasswordPolicy:
|
||||
MinimumLength: !Ref passwordPolicyMinLength
|
||||
RequireLowercase: false
|
||||
RequireNumbers: false
|
||||
RequireSymbols: false
|
||||
RequireUppercase: false
|
||||
|
||||
UsernameAttributes: !Ref usernameAttributes
|
||||
|
||||
MfaConfiguration: !Ref mfaConfiguration
|
||||
SmsVerificationMessage: !Ref smsVerificationMessage
|
||||
SmsConfiguration:
|
||||
SnsCallerArn: !GetAtt SNSRole.Arn
|
||||
ExternalId: hpiotr8c9024fb_role_external_id
|
||||
|
||||
|
||||
UserPoolClientWeb:
|
||||
# Created provide application access to user pool
|
||||
# Depends on UserPool for ID reference
|
||||
Type: "AWS::Cognito::UserPoolClient"
|
||||
Properties:
|
||||
ClientName: hpiotr8c9024fb_app_clientWeb
|
||||
|
||||
RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity
|
||||
UserPoolId: !Ref UserPool
|
||||
DependsOn: UserPool
|
||||
UserPoolClient:
|
||||
# Created provide application access to user pool
|
||||
# Depends on UserPool for ID reference
|
||||
Type: "AWS::Cognito::UserPoolClient"
|
||||
Properties:
|
||||
ClientName: hpiotr8c9024fb_app_client
|
||||
|
||||
GenerateSecret: !Ref userpoolClientGenerateSecret
|
||||
RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity
|
||||
UserPoolId: !Ref UserPool
|
||||
DependsOn: UserPool
|
||||
# BEGIN USER POOL LAMBDA RESOURCES
|
||||
UserPoolClientRole:
|
||||
# Created to execute Lambda which gets userpool app client config values
|
||||
Type: 'AWS::IAM::Role'
|
||||
Properties:
|
||||
RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]]
|
||||
AssumeRolePolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service:
|
||||
- lambda.amazonaws.com
|
||||
Action:
|
||||
- 'sts:AssumeRole'
|
||||
DependsOn: UserPoolClient
|
||||
UserPoolClientLambda:
|
||||
# Lambda which gets userpool app client config values
|
||||
# Depends on UserPool for id
|
||||
# Depends on UserPoolClientRole for role ARN
|
||||
Type: 'AWS::Lambda::Function'
|
||||
Properties:
|
||||
Code:
|
||||
ZipFile: !Join
|
||||
- |+
|
||||
- - 'const response = require(''cfn-response'');'
|
||||
- 'const aws = require(''aws-sdk'');'
|
||||
- 'const identity = new aws.CognitoIdentityServiceProvider();'
|
||||
- 'exports.handler = (event, context, callback) => {'
|
||||
- ' if (event.RequestType == ''Delete'') { '
|
||||
- ' response.send(event, context, response.SUCCESS, {})'
|
||||
- ' }'
|
||||
- ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {'
|
||||
- ' const params = {'
|
||||
- ' ClientId: event.ResourceProperties.clientId,'
|
||||
- ' UserPoolId: event.ResourceProperties.userpoolId'
|
||||
- ' };'
|
||||
- ' identity.describeUserPoolClient(params).promise()'
|
||||
- ' .then((res) => {'
|
||||
- ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});'
|
||||
- ' })'
|
||||
- ' .catch((err) => {'
|
||||
- ' response.send(event, context, response.FAILED, {err});'
|
||||
- ' });'
|
||||
- ' }'
|
||||
- '};'
|
||||
Handler: index.handler
|
||||
Runtime: nodejs10.x
|
||||
Timeout: '300'
|
||||
Role: !GetAtt
|
||||
- UserPoolClientRole
|
||||
- Arn
|
||||
DependsOn: UserPoolClientRole
|
||||
UserPoolClientLambdaPolicy:
|
||||
# Sets userpool policy for the role that executes the Userpool Client Lambda
|
||||
# Depends on UserPool for Arn
|
||||
# Marked as depending on UserPoolClientRole for easier to understand CFN sequencing
|
||||
Type: 'AWS::IAM::Policy'
|
||||
Properties:
|
||||
PolicyName: hpiotr8c9024fb_userpoolclient_lambda_iam_policy
|
||||
Roles:
|
||||
- !Ref UserPoolClientRole
|
||||
PolicyDocument:
|
||||
Version: '2012-10-17'
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'cognito-idp:DescribeUserPoolClient'
|
||||
Resource: !GetAtt UserPool.Arn
|
||||
DependsOn: UserPoolClientLambda
|
||||
UserPoolClientLogPolicy:
|
||||
# Sets log policy for the role that executes the Userpool Client Lambda
|
||||
# Depends on UserPool for Arn
|
||||
# Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing
|
||||
Type: 'AWS::IAM::Policy'
|
||||
Properties:
|
||||
PolicyName: hpiotr8c9024fb_userpoolclient_lambda_log_policy
|
||||
Roles:
|
||||
- !Ref UserPoolClientRole
|
||||
PolicyDocument:
|
||||
Version: 2012-10-17
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Action:
|
||||
- 'logs:CreateLogGroup'
|
||||
- 'logs:CreateLogStream'
|
||||
- 'logs:PutLogEvents'
|
||||
Resource: !Sub
|
||||
- arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:*
|
||||
- { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda}
|
||||
DependsOn: UserPoolClientLambdaPolicy
|
||||
UserPoolClientInputs:
|
||||
# Values passed to Userpool client Lambda
|
||||
# Depends on UserPool for Id
|
||||
# Depends on UserPoolClient for Id
|
||||
# Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing
|
||||
Type: 'Custom::LambdaCallout'
|
||||
Properties:
|
||||
ServiceToken: !GetAtt UserPoolClientLambda.Arn
|
||||
clientId: !Ref UserPoolClient
|
||||
userpoolId: !Ref UserPool
|
||||
DependsOn: UserPoolClientLogPolicy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# BEGIN IDENTITY POOL RESOURCES
|
||||
|
||||
|
||||
IdentityPool:
|
||||
# Always created
|
||||
Type: AWS::Cognito::IdentityPool
|
||||
Properties:
|
||||
IdentityPoolName: !If [ShouldNotCreateEnvResources, 'hpiotreact8c9024fb_identitypool_8c9024fb', !Join ['',['hpiotreact8c9024fb_identitypool_8c9024fb', '__', !Ref env]]]
|
||||
|
||||
CognitoIdentityProviders:
|
||||
- ClientId: !Ref UserPoolClient
|
||||
ProviderName: !Sub
|
||||
- cognito-idp.${region}.amazonaws.com/${client}
|
||||
- { region: !Ref "AWS::Region", client: !Ref UserPool}
|
||||
- ClientId: !Ref UserPoolClientWeb
|
||||
ProviderName: !Sub
|
||||
- cognito-idp.${region}.amazonaws.com/${client}
|
||||
- { region: !Ref "AWS::Region", client: !Ref UserPool}
|
||||
|
||||
AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities
|
||||
|
||||
|
||||
DependsOn: UserPoolClientInputs
|
||||
|
||||
|
||||
IdentityPoolRoleMap:
|
||||
# Created to map Auth and Unauth roles to the identity pool
|
||||
# Depends on Identity Pool for ID ref
|
||||
Type: AWS::Cognito::IdentityPoolRoleAttachment
|
||||
Properties:
|
||||
IdentityPoolId: !Ref IdentityPool
|
||||
Roles:
|
||||
unauthenticated: !Ref unauthRoleArn
|
||||
authenticated: !Ref authRoleArn
|
||||
DependsOn: IdentityPool
|
||||
|
||||
|
||||
Outputs :
|
||||
|
||||
IdentityPoolId:
|
||||
Value: !Ref 'IdentityPool'
|
||||
Description: Id for the identity pool
|
||||
IdentityPoolName:
|
||||
Value: !GetAtt IdentityPool.Name
|
||||
|
||||
|
||||
|
||||
|
||||
UserPoolId:
|
||||
Value: !Ref 'UserPool'
|
||||
Description: Id for the user pool
|
||||
UserPoolName:
|
||||
Value: !Ref userPoolName
|
||||
AppClientIDWeb:
|
||||
Value: !Ref 'UserPoolClientWeb'
|
||||
Description: The user pool app client id for web
|
||||
AppClientID:
|
||||
Value: !Ref 'UserPoolClient'
|
||||
Description: The user pool app client id
|
||||
AppClientSecret:
|
||||
Value: !GetAtt UserPoolClientInputs.appSecret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
53
amplify/backend/auth/hpiotreact8c9024fb/parameters.json
Normal file
53
amplify/backend/auth/hpiotreact8c9024fb/parameters.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"identityPoolName": "hpiotreact8c9024fb_identitypool_8c9024fb",
|
||||
"allowUnauthenticatedIdentities": false,
|
||||
"resourceNameTruncated": "hpiotr8c9024fb",
|
||||
"userPoolName": "hpiotreact8c9024fb_userpool_8c9024fb",
|
||||
"autoVerifiedAttributes": [
|
||||
"email"
|
||||
],
|
||||
"mfaConfiguration": "OFF",
|
||||
"mfaTypes": [
|
||||
"SMS Text Message"
|
||||
],
|
||||
"smsAuthenticationMessage": "Your authentication code is {####}",
|
||||
"smsVerificationMessage": "Your verification code is {####}",
|
||||
"emailVerificationSubject": "Your verification code",
|
||||
"emailVerificationMessage": "Your verification code is {####}",
|
||||
"defaultPasswordPolicy": false,
|
||||
"passwordPolicyMinLength": 8,
|
||||
"passwordPolicyCharacters": [],
|
||||
"requiredAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userpoolClientGenerateSecret": true,
|
||||
"userpoolClientRefreshTokenValidity": 30,
|
||||
"userpoolClientWriteAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userpoolClientReadAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userpoolClientLambdaRole": "hpiotr8c9024fb_userpoolclient_lambda_role",
|
||||
"userpoolClientSetAttributes": false,
|
||||
"resourceName": "hpiotreact8c9024fb",
|
||||
"authSelections": "identityPoolAndUserPool",
|
||||
"authRoleArn": {
|
||||
"Fn::GetAtt": [
|
||||
"AuthRole",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
"unauthRoleArn": {
|
||||
"Fn::GetAtt": [
|
||||
"UnauthRole",
|
||||
"Arn"
|
||||
]
|
||||
},
|
||||
"useDefault": "default",
|
||||
"usernameAttributes": [
|
||||
"email"
|
||||
],
|
||||
"userPoolGroupList": [],
|
||||
"dependsOn": []
|
||||
}
|
||||
16
amplify/backend/backend-config.json
Normal file
16
amplify/backend/backend-config.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"hosting": {
|
||||
"S3AndCloudFront": {
|
||||
"service": "S3AndCloudFront",
|
||||
"providerPlugin": "awscloudformation"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"hpiotreact8c9024fb": {
|
||||
"service": "Cognito",
|
||||
"providerPlugin": "awscloudformation",
|
||||
"dependsOn": [],
|
||||
"customAuth": false
|
||||
}
|
||||
}
|
||||
}
|
||||
3
amplify/backend/hosting/S3AndCloudFront/parameters.json
Normal file
3
amplify/backend/hosting/S3AndCloudFront/parameters.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"bucketName": "hpiot-react"
|
||||
}
|
||||
113
amplify/backend/hosting/S3AndCloudFront/template.json
Normal file
113
amplify/backend/hosting/S3AndCloudFront/template.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"AccessControl": "Private",
|
||||
"WebsiteConfiguration": {
|
||||
"IndexDocument": "index.html",
|
||||
"ErrorDocument": "index.html"
|
||||
},
|
||||
"CorsConfiguration": {
|
||||
"CorsRules": [
|
||||
{
|
||||
"AllowedHeaders": [
|
||||
"Authorization",
|
||||
"Content-Length"
|
||||
],
|
||||
"AllowedMethods": [
|
||||
"GET"
|
||||
],
|
||||
"AllowedOrigins": [
|
||||
"*"
|
||||
],
|
||||
"MaxAge": 3000
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
20
amplify/team-provider-info.json
Normal file
20
amplify/team-provider-info.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"hpiot": {
|
||||
"awscloudformation": {
|
||||
"AuthRoleName": "amplify-hpiot-react-hpiot-162610-authRole",
|
||||
"UnauthRoleArn": "arn:aws:iam::860246592755:role/amplify-hpiot-react-hpiot-162610-unauthRole",
|
||||
"AuthRoleArn": "arn:aws:iam::860246592755:role/amplify-hpiot-react-hpiot-162610-authRole",
|
||||
"Region": "us-east-1",
|
||||
"DeploymentBucketName": "amplify-hpiot-react-hpiot-162610-deployment",
|
||||
"UnauthRoleName": "amplify-hpiot-react-hpiot-162610-unauthRole",
|
||||
"StackName": "amplify-hpiot-react-hpiot-162610",
|
||||
"StackId": "arn:aws:cloudformation:us-east-1:860246592755:stack/amplify-hpiot-react-hpiot-162610/1913c1f0-64a8-11ea-baa2-0ee5b74c6229",
|
||||
"AmplifyAppId": "d3hyexpjn33q6q"
|
||||
},
|
||||
"categories": {
|
||||
"auth": {
|
||||
"hpiotreact8c9024fb": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4109
package-lock.json
generated
4109
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -6,9 +6,14 @@
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.5.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"react-scripts": "3.4.0"
|
||||
"aws-amplify": "^2.2.6",
|
||||
"aws-amplify-react": "^3.1.7",
|
||||
"npx": "^10.2.2",
|
||||
"react": "^16.13.1",
|
||||
"react-charts": "^2.0.0-beta.6",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.0",
|
||||
"recharts": "^1.8.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
min-height: 4vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
165
src/App.js
165
src/App.js
@@ -1,26 +1,163 @@
|
||||
import React from 'react';
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
import LineChart from './charts/LineChart';
|
||||
import BarChart from './charts/BarChart';
|
||||
import { WebSocketSubject } from 'rxjs/webSocket';
|
||||
import { Subject } from 'rxjs';
|
||||
import Amplify from 'aws-amplify';
|
||||
import awsconfig from './aws-exports';
|
||||
import { withAuthenticator } from 'aws-amplify-react'; // or 'aws-amplify-react-native';
|
||||
import {Auth} from 'aws-amplify';
|
||||
Amplify.configure(awsconfig);
|
||||
|
||||
|
||||
let serverMessages = [];
|
||||
let socket$ = new WebSocketSubject();
|
||||
let roles = [];
|
||||
let groups = [];
|
||||
let currentRole = "";
|
||||
let roleSubject = new Subject();
|
||||
let token = "";
|
||||
|
||||
|
||||
function connect() {
|
||||
connectWS(token, currentRole);
|
||||
subscribeWS();
|
||||
socket$.next({action: 'getDashboardData', policy: currentRole});
|
||||
}
|
||||
|
||||
function connectWS(token, role) {
|
||||
socket$ = new WebSocketSubject('wss://3fseaywb8b.execute-api.us-east-1.amazonaws.com/prototype?token=' + token +
|
||||
'&role=' + role);
|
||||
//console.log(socket$);
|
||||
}
|
||||
|
||||
function subscribeWS() {
|
||||
socket$.subscribe((message) => {
|
||||
console.log(message);
|
||||
if (message instanceof Array) {
|
||||
message.forEach(element => {
|
||||
updateList(element);
|
||||
});
|
||||
} else {
|
||||
updateList(message);
|
||||
}
|
||||
serverMessages.sort((a, b) => a.location.localeCompare(b.location));
|
||||
console.log(serverMessages);
|
||||
},
|
||||
(err) => console.error(err),
|
||||
() => console.warn('Complete: Websocket closed')
|
||||
);
|
||||
|
||||
|
||||
function updateList(obj) {
|
||||
//console.log(serverMessages);
|
||||
//console.log(obj);
|
||||
const index = serverMessages.findIndex((e) => e.location === obj.location);
|
||||
|
||||
if (index === -1) {
|
||||
serverMessages.push(obj);
|
||||
|
||||
} else {
|
||||
Object.keys(obj).forEach(element => {
|
||||
serverMessages[index][element] = obj[element];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setRole(index) {
|
||||
currentRole = roles[index];
|
||||
roleSubject.next(currentRole);
|
||||
socket$.complete();
|
||||
serverMessages = [];
|
||||
connect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Dashboard extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
promiseIsResolved: false
|
||||
};
|
||||
|
||||
}
|
||||
updateList(obj) {
|
||||
//console.log(serverMessages);
|
||||
//console.log(obj);
|
||||
const index = serverMessages.findIndex((e) => e.location === obj.location);
|
||||
|
||||
if (index === -1) {
|
||||
serverMessages.push(obj);
|
||||
|
||||
} else {
|
||||
Object.keys(obj).forEach(element => {
|
||||
serverMessages[index][element] = obj[element];
|
||||
});
|
||||
}
|
||||
}
|
||||
componentDidMount(){
|
||||
Auth.currentAuthenticatedUser().then(data => {
|
||||
//console.log(data);
|
||||
roles = data.signInUserSession.idToken.payload['cognito:roles'];
|
||||
groups = data.signInUserSession.idToken.payload['cognito:groups'];
|
||||
groups.forEach( (element, index, array) => {
|
||||
array[index] = element.replace(/_/g, ' ');
|
||||
});
|
||||
currentRole = data.signInUserSession.idToken.payload['cognito:roles'][0];
|
||||
token = data.signInUserSession.accessToken.jwtToken;
|
||||
roleSubject.subscribe({
|
||||
next: r => r
|
||||
});
|
||||
socket$ = new WebSocketSubject('wss://3fseaywb8b.execute-api.us-east-1.amazonaws.com/prototype?token=' + token +
|
||||
'&role=' + currentRole);
|
||||
socket$.subscribe((message) => {
|
||||
console.log(message);
|
||||
if (message instanceof Array) {
|
||||
message.forEach(element => {
|
||||
this.updateList(element);
|
||||
});
|
||||
} else {
|
||||
this.updateList(message);
|
||||
}
|
||||
serverMessages.sort((a, b) => a.location.localeCompare(b.location));
|
||||
this.setState({promiseIsResolved: true});
|
||||
console.log(serverMessages);
|
||||
},
|
||||
(err) => console.error(err),
|
||||
() => console.warn('Complete: Websocket closed')
|
||||
);
|
||||
socket$.next({action: 'getDashboardData', policy: currentRole});
|
||||
|
||||
}).catch((err) =>
|
||||
err
|
||||
);
|
||||
}
|
||||
render() {
|
||||
if(!this.state.promiseIsResolved){return null}
|
||||
else{
|
||||
return (
|
||||
<div className="Dashboard">
|
||||
<BarChart data = {serverMessages}/>
|
||||
<LineChart data = {serverMessages}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.js</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
<div className="Nav-bar"><p>This is where the nav-bar will be</p></div>
|
||||
</header>
|
||||
<Dashboard />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default withAuthenticator(App, {includeGreetings: true});
|
||||
|
||||
16
src/aws-exports-old.js
Normal file
16
src/aws-exports-old.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
|
||||
|
||||
const awsmobile = {
|
||||
"aws_project_region": "us-east-1",
|
||||
"aws_content_delivery_bucket": "hpiot-react-hpiot",
|
||||
"aws_content_delivery_bucket_region": "us-east-1",
|
||||
"aws_content_delivery_url": "http://hpiot-react-hpiot.s3-website-us-east-1.amazonaws.com",
|
||||
"aws_cognito_identity_pool_id": "us-east-1:20972146-c6fe-4ada-a723-d1debcc7d074",
|
||||
"aws_cognito_region": "us-east-1",
|
||||
"aws_user_pools_id": "us-east-1_L6XsGIASX",
|
||||
"aws_user_pools_web_client_id": "63ieddff77nfc3i151m8l8k3ip",
|
||||
"oauth": {}
|
||||
};
|
||||
|
||||
|
||||
export default awsmobile;
|
||||
35
src/charts/BarChart.js
Normal file
35
src/charts/BarChart.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
BarChart, Bar, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend,
|
||||
} from 'recharts';
|
||||
|
||||
|
||||
|
||||
export default class Example extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: this.props.data,
|
||||
}
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<BarChart
|
||||
width={1000}
|
||||
height={600}
|
||||
data={this.state.data}
|
||||
margin={{
|
||||
top: 5, right: 30, left: 20, bottom: 5,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="location" />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Bar dataKey="volumeflow" fill="#8884d8" />
|
||||
<Bar dataKey="depth" fill="#82ca9d" />
|
||||
</BarChart>
|
||||
);
|
||||
}
|
||||
}
|
||||
142
src/charts/LineChart.js
Normal file
142
src/charts/LineChart.js
Normal file
@@ -0,0 +1,142 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
Label, LineChart, Line, CartesianGrid, XAxis, YAxis, Tooltip, ReferenceArea,
|
||||
} from 'recharts';
|
||||
|
||||
|
||||
|
||||
const getAxisYDomain = (from, to, ref, offset, data) => {
|
||||
const refData = data.slice(from - 1, to);
|
||||
let [bottom, top] = [refData[0][ref], refData[0][ref]];
|
||||
refData.forEach((d) => {
|
||||
if (d[ref] > top) top = d[ref];
|
||||
if (d[ref] < bottom) bottom = d[ref];
|
||||
});
|
||||
|
||||
return [(bottom | 0) - offset, (top | 0) + offset];
|
||||
};
|
||||
|
||||
|
||||
export default class Example extends PureComponent {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
data: this.props.data,
|
||||
left: 'dataMin',
|
||||
right: 'dataMax',
|
||||
refAreaLeft: '',
|
||||
refAreaRight: '',
|
||||
top: 'dataMax+1',
|
||||
bottom: 'dataMin-1',
|
||||
top2: 'dataMax+20',
|
||||
bottom2: 'dataMin-20',
|
||||
animation: true,
|
||||
};
|
||||
}
|
||||
|
||||
zoom() {
|
||||
let { refAreaLeft, refAreaRight, data } = this.state;
|
||||
|
||||
if (refAreaLeft === refAreaRight || refAreaRight === '') {
|
||||
this.setState(() => ({
|
||||
refAreaLeft: '',
|
||||
refAreaRight: '',
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
// xAxis domain
|
||||
if (refAreaLeft > refAreaRight) [refAreaLeft, refAreaRight] = [refAreaRight, refAreaLeft];
|
||||
|
||||
// yAxis domain
|
||||
const [bottom, top] = getAxisYDomain(refAreaLeft, refAreaRight, 'volumeflow', 5, this.state.data);
|
||||
const [bottom2, top2] = getAxisYDomain(refAreaLeft, refAreaRight, 'depth', 50, this.state.data);
|
||||
|
||||
this.setState(() => ({
|
||||
refAreaLeft: '',
|
||||
refAreaRight: '',
|
||||
data: data.slice(),
|
||||
left: refAreaLeft,
|
||||
right: refAreaRight,
|
||||
bottom,
|
||||
top,
|
||||
bottom2,
|
||||
top2,
|
||||
}));
|
||||
}
|
||||
|
||||
zoomOut() {
|
||||
const { data } = this.state;
|
||||
this.setState(() => ({
|
||||
data: data.slice(),
|
||||
refAreaLeft: '',
|
||||
refAreaRight: '',
|
||||
left: 'dataMin',
|
||||
right: 'dataMax',
|
||||
top: 'dataMax+1',
|
||||
bottom: 'dataMin',
|
||||
top2: 'dataMax+50',
|
||||
bottom2: 'dataMin+50',
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
data, barIndex, left, right, refAreaLeft, refAreaRight, top, bottom, top2, bottom2,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<div className="highlight-bar-charts" style={{ userSelect: 'none' }}>
|
||||
<button
|
||||
// href="javascript: void(0);"
|
||||
className="btn update"
|
||||
onClick={this.zoomOut.bind(this)}
|
||||
>
|
||||
Zoom Out
|
||||
|
||||
</button>
|
||||
|
||||
<LineChart
|
||||
width={800}
|
||||
height={400}
|
||||
data={data}
|
||||
onMouseDown={e => this.setState({ refAreaLeft: e.activeLabel })}
|
||||
onMouseMove={e => this.state.refAreaLeft && this.setState({ refAreaRight: e.activeLabel })}
|
||||
onMouseUp={this.zoom.bind(this)}
|
||||
>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis
|
||||
allowDataOverflow
|
||||
dataKey="timestamp"
|
||||
domain={[left, right]}
|
||||
type="number"
|
||||
/>
|
||||
<YAxis
|
||||
allowDataOverflow
|
||||
domain={[bottom, top]}
|
||||
type="number"
|
||||
yAxisId="1"
|
||||
/>
|
||||
<YAxis
|
||||
orientation="right"
|
||||
allowDataOverflow
|
||||
domain={[bottom2, top2]}
|
||||
type="number"
|
||||
yAxisId="2"
|
||||
/>
|
||||
<Tooltip />
|
||||
<Line yAxisId="1" type="natural" dataKey="volumeflow" stroke="#8884d8" animationDuration={300} />
|
||||
<Line yAxisId="2" type="natural" dataKey="depth" stroke="#82ca9d" animationDuration={300} />
|
||||
|
||||
|
||||
{
|
||||
(refAreaLeft && refAreaRight) ? (
|
||||
<ReferenceArea yAxisId="1" x1={refAreaLeft} x2={refAreaRight} strokeOpacity={0.3} />) : null
|
||||
}
|
||||
</LineChart>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user