├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── amplify ├── .config │ └── project-config.json └── backend │ ├── api │ └── quicknotes │ │ ├── parameters.json │ │ ├── schema.graphql │ │ └── stacks │ │ └── CustomResources.json │ ├── auth │ └── quicknotes9506fafe │ │ ├── parameters.json │ │ └── quicknotes9506fafe-cloudformation-template.yml │ ├── backend-config.json │ └── predictions │ ├── speechGeneratorc72b6c38 │ ├── parameters.json │ └── speechGeneratorc72b6c38-template.json │ └── transcriptione65259cc │ ├── parameters.json │ └── transcriptione65259cc-template.json ├── example.jpg ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.css ├── App.js ├── components │ ├── Dialog.js │ ├── Note.js │ ├── Notes.js │ ├── Record.js │ ├── Recording-Editor.js │ └── Screens.js ├── graphql │ ├── mutations.js │ ├── queries.js │ ├── schema.json │ └── subscriptions.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/** 2 | build/** 3 | 4 | #amplify 5 | amplify/\#current-cloud-backend 6 | amplify/.config/local-* 7 | amplify/logs 8 | amplify/mock-data 9 | amplify/backend/amplify-meta.json 10 | amplify/backend/awscloudformation 11 | amplify/backend/.temp 12 | build/ 13 | dist/ 14 | node_modules/ 15 | aws-exports.js 16 | awsconfiguration.json 17 | amplifyconfiguration.json 18 | amplifyconfiguration.dart 19 | amplify-build-config.json 20 | amplify-gradle-config.json 21 | amplifytools.xcconfig 22 | .secret-* -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Quick Notes (Archived) 2 | 3 | #### Deploy a full stack web app to help you organize your notes when you're on the go. 4 | 5 | 🛠 Built with React, GraphQL, AWS Amplify, AWS AppSync, Amazon Transcribe, & Amazon Polly 6 | 7 | ### Features 8 | 9 | - 🎙 Record notes 10 | - 🔈 Play notes back 11 | - 📖 Read notes 12 | - 👮‍ Authenticated 13 | - 🔥 Serverless back end 14 | - 🚀 GraphQL 15 | - 💻 Deploy back end in minutes 16 | 17 | ![](./example.jpg) 18 | 19 | ## Deploy the App 20 | 21 | To automatically deploy the app, click the big orange button 👇 22 | 23 | [![amplifybutton](https://oneclick.amplifyapp.com/button.svg)](https://console.aws.amazon.com/amplify/home#/deploy?repo=https://github.com/aws-samples/aws-amplify-quick-notes) 24 | 25 | > If you wish to manually deploy the app, follow the instructions below. 26 | 27 | ### Deploy the back end and run the app 28 | 29 | 1. Clone the repo & install the dependencies 30 | 31 | ```sh 32 | ~ git clone https://github.com/aws-samples/aws-amplify-quick-notes.git 33 | ~ cd aws-amplify-quick-notes 34 | ~ npm install 35 | ``` 36 | 37 | 2. Initialize and deploy the Amplify project 38 | 39 | ```sh 40 | ~ amplify init 41 | ? Enter a name for the environment: dev (or whatever you would like to call this env) 42 | ? Choose your default editor: 43 | ? Do you want to use an AWS profile? Y 44 | 45 | ~ amplify push 46 | ? Are you sure you want to continue? Y 47 | ? Do you want to generate code for your newly created GraphQL API? N 48 | > We already have the GraphQL code generated for this project, so generating it here is not necessary. 49 | ``` 50 | 51 | 3. Start the app and register a new user 52 | 53 | ```sh 54 | ~ yarn start 55 | ``` 56 | 57 | ### Deploy the front end 58 | 59 | 1. Create a new repository with your git service of choice 60 | 61 | 2. Push the project to your new repository 62 | 63 | ```sh 64 | ~ git remote add origin 65 | ~ git push --set-upstream master 66 | ``` 67 | 68 | 3. Connect to [AWS Amplify Console](https://console.aws.amazon.com/amplify/home) and wait for build to start. You will be given a production URL and you are ready to take some notes! 69 | 70 | 71 | ### License 72 | 73 | This library is licensed under the MIT-0 License. See the LICENSE file. 74 | -------------------------------------------------------------------------------- /amplify/.config/project-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "quick-notes", 3 | "version": "2.0", 4 | "frontend": "javascript", 5 | "javascript": { 6 | "framework": "react", 7 | "config": { 8 | "SourceDir": "src", 9 | "DistributionDir": "build", 10 | "BuildCommand": "npm run-script build", 11 | "StartCommand": "npm run-script start" 12 | } 13 | }, 14 | "providers": [ 15 | "awscloudformation" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /amplify/backend/api/quicknotes/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSyncApiName": "quicknotes", 3 | "DynamoDBBillingMode": "PAY_PER_REQUEST", 4 | "DynamoDBEnableServerSideEncryption": "false", 5 | "AuthCognitoUserPoolId": { 6 | "Fn::GetAtt": [ 7 | "authquicknotes9506fafe", 8 | "Outputs.UserPoolId" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /amplify/backend/api/quicknotes/schema.graphql: -------------------------------------------------------------------------------- 1 | type Note @model @auth(rules: [{ allow: owner }]) { 2 | id: ID! 3 | title: String! 4 | text: String! 5 | createdAt: String 6 | updatedAt: String 7 | } 8 | -------------------------------------------------------------------------------- /amplify/backend/api/quicknotes/stacks/CustomResources.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "An auto-generated nested stack.", 4 | "Metadata": {}, 5 | "Parameters": { 6 | "AppSyncApiId": { 7 | "Type": "String", 8 | "Description": "The id of the AppSync API associated with this project." 9 | }, 10 | "AppSyncApiName": { 11 | "Type": "String", 12 | "Description": "The name of the AppSync API", 13 | "Default": "AppSyncSimpleTransform" 14 | }, 15 | "env": { 16 | "Type": "String", 17 | "Description": "The environment name. e.g. Dev, Test, or Production", 18 | "Default": "NONE" 19 | }, 20 | "S3DeploymentBucket": { 21 | "Type": "String", 22 | "Description": "The S3 bucket containing all deployment assets for the project." 23 | }, 24 | "S3DeploymentRootKey": { 25 | "Type": "String", 26 | "Description": "An S3 key relative to the S3DeploymentBucket that points to the root\nof the deployment directory." 27 | } 28 | }, 29 | "Resources": { 30 | "EmptyResource": { 31 | "Type": "Custom::EmptyResource", 32 | "Condition": "AlwaysFalse" 33 | } 34 | }, 35 | "Conditions": { 36 | "HasEnvironmentParameter": { 37 | "Fn::Not": [ 38 | { 39 | "Fn::Equals": [ 40 | { 41 | "Ref": "env" 42 | }, 43 | "NONE" 44 | ] 45 | } 46 | ] 47 | }, 48 | "AlwaysFalse": { 49 | "Fn::Equals": [ 50 | "true", 51 | "false" 52 | ] 53 | } 54 | }, 55 | "Outputs": { 56 | "EmptyOutput": { 57 | "Description": "An empty output. You may delete this if you have at least one resource above.", 58 | "Value": "" 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /amplify/backend/auth/quicknotes9506fafe/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "quicknotes9506fafe_identitypool_9506fafe", 3 | "allowUnauthenticatedIdentities": false, 4 | "resourceNameTruncated": "quickn9506fafe", 5 | "userPoolName": "quicknotes9506fafe_userpool_9506fafe", 6 | "autoVerifiedAttributes": [ 7 | "email" 8 | ], 9 | "mfaConfiguration": "OFF", 10 | "mfaTypes": [ 11 | "SMS Text Message" 12 | ], 13 | "smsAuthenticationMessage": "Your authentication code is {####}", 14 | "smsVerificationMessage": "Your verification code is {####}", 15 | "emailVerificationSubject": "Your verification code", 16 | "emailVerificationMessage": "Your verification code is {####}", 17 | "defaultPasswordPolicy": false, 18 | "passwordPolicyMinLength": 8, 19 | "passwordPolicyCharacters": [], 20 | "requiredAttributes": [ 21 | "email" 22 | ], 23 | "userpoolClientGenerateSecret": true, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "quickn9506fafe_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "resourceName": "quicknotes9506fafe", 34 | "authSelections": "identityPoolAndUserPool", 35 | "authRoleArn": { 36 | "Fn::GetAtt": [ 37 | "AuthRole", 38 | "Arn" 39 | ] 40 | }, 41 | "unauthRoleArn": { 42 | "Fn::GetAtt": [ 43 | "UnauthRole", 44 | "Arn" 45 | ] 46 | }, 47 | "useDefault": "default", 48 | "usernameAttributes": [ 49 | "email" 50 | ], 51 | "triggers": "{}", 52 | "parentStack": { 53 | "Ref": "AWS::StackId" 54 | }, 55 | "permissions": [], 56 | "dependsOn": [] 57 | } -------------------------------------------------------------------------------- /amplify/backend/auth/quicknotes9506fafe/quicknotes9506fafe-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Parameters: 4 | env: 5 | Type: String 6 | authRoleArn: 7 | Type: String 8 | unauthRoleArn: 9 | Type: String 10 | 11 | 12 | 13 | 14 | identityPoolName: 15 | Type: String 16 | 17 | allowUnauthenticatedIdentities: 18 | Type: String 19 | 20 | resourceNameTruncated: 21 | Type: String 22 | 23 | userPoolName: 24 | Type: String 25 | 26 | autoVerifiedAttributes: 27 | Type: CommaDelimitedList 28 | 29 | mfaConfiguration: 30 | Type: String 31 | 32 | mfaTypes: 33 | Type: CommaDelimitedList 34 | 35 | smsAuthenticationMessage: 36 | Type: String 37 | 38 | smsVerificationMessage: 39 | Type: String 40 | 41 | emailVerificationSubject: 42 | Type: String 43 | 44 | emailVerificationMessage: 45 | Type: String 46 | 47 | defaultPasswordPolicy: 48 | Type: String 49 | 50 | passwordPolicyMinLength: 51 | Type: Number 52 | 53 | passwordPolicyCharacters: 54 | Type: CommaDelimitedList 55 | 56 | requiredAttributes: 57 | Type: CommaDelimitedList 58 | 59 | userpoolClientGenerateSecret: 60 | Type: String 61 | 62 | userpoolClientRefreshTokenValidity: 63 | Type: Number 64 | 65 | userpoolClientWriteAttributes: 66 | Type: CommaDelimitedList 67 | 68 | userpoolClientReadAttributes: 69 | Type: CommaDelimitedList 70 | 71 | userpoolClientLambdaRole: 72 | Type: String 73 | 74 | userpoolClientSetAttributes: 75 | Type: String 76 | 77 | resourceName: 78 | Type: String 79 | 80 | authSelections: 81 | Type: String 82 | 83 | useDefault: 84 | Type: String 85 | 86 | usernameAttributes: 87 | Type: CommaDelimitedList 88 | 89 | triggers: 90 | Type: String 91 | 92 | parentStack: 93 | Type: String 94 | 95 | permissions: 96 | Type: CommaDelimitedList 97 | 98 | dependsOn: 99 | Type: CommaDelimitedList 100 | 101 | Conditions: 102 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 103 | 104 | Resources: 105 | 106 | 107 | # BEGIN SNS ROLE RESOURCE 108 | SNSRole: 109 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 110 | Type: AWS::IAM::Role 111 | Properties: 112 | RoleName: !If [ShouldNotCreateEnvResources, 'quickn9506fafe_sns-role', !Join ['',['quickn9506fafe_sns-role', '-', !Ref env]]] 113 | AssumeRolePolicyDocument: 114 | Version: "2012-10-17" 115 | Statement: 116 | - Sid: "" 117 | Effect: "Allow" 118 | Principal: 119 | Service: "cognito-idp.amazonaws.com" 120 | Action: 121 | - "sts:AssumeRole" 122 | Condition: 123 | StringEquals: 124 | sts:ExternalId: quickn9506fafe_role_external_id 125 | Policies: 126 | - 127 | PolicyName: quickn9506fafe-sns-policy 128 | PolicyDocument: 129 | Version: "2012-10-17" 130 | Statement: 131 | - 132 | Effect: "Allow" 133 | Action: 134 | - "sns:Publish" 135 | Resource: "*" 136 | # BEGIN USER POOL RESOURCES 137 | UserPool: 138 | # Created upon user selection 139 | # Depends on SNS Role for Arn if MFA is enabled 140 | Type: AWS::Cognito::UserPool 141 | UpdateReplacePolicy: Retain 142 | Properties: 143 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 144 | 145 | Schema: 146 | 147 | - 148 | Name: email 149 | Required: true 150 | Mutable: true 151 | 152 | 153 | 154 | 155 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 156 | 157 | 158 | EmailVerificationMessage: !Ref emailVerificationMessage 159 | EmailVerificationSubject: !Ref emailVerificationSubject 160 | 161 | Policies: 162 | PasswordPolicy: 163 | MinimumLength: !Ref passwordPolicyMinLength 164 | RequireLowercase: false 165 | RequireNumbers: false 166 | RequireSymbols: false 167 | RequireUppercase: false 168 | 169 | UsernameAttributes: !Ref usernameAttributes 170 | 171 | MfaConfiguration: !Ref mfaConfiguration 172 | SmsVerificationMessage: !Ref smsVerificationMessage 173 | SmsConfiguration: 174 | SnsCallerArn: !GetAtt SNSRole.Arn 175 | ExternalId: quickn9506fafe_role_external_id 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | # Updating lambda role with permissions to Cognito 187 | 188 | 189 | UserPoolClientWeb: 190 | # Created provide application access to user pool 191 | # Depends on UserPool for ID reference 192 | Type: "AWS::Cognito::UserPoolClient" 193 | Properties: 194 | ClientName: quickn9506fafe_app_clientWeb 195 | 196 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 197 | UserPoolId: !Ref UserPool 198 | DependsOn: UserPool 199 | UserPoolClient: 200 | # Created provide application access to user pool 201 | # Depends on UserPool for ID reference 202 | Type: "AWS::Cognito::UserPoolClient" 203 | Properties: 204 | ClientName: quickn9506fafe_app_client 205 | 206 | GenerateSecret: !Ref userpoolClientGenerateSecret 207 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 208 | UserPoolId: !Ref UserPool 209 | DependsOn: UserPool 210 | # BEGIN USER POOL LAMBDA RESOURCES 211 | UserPoolClientRole: 212 | # Created to execute Lambda which gets userpool app client config values 213 | Type: 'AWS::IAM::Role' 214 | Properties: 215 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 216 | AssumeRolePolicyDocument: 217 | Version: '2012-10-17' 218 | Statement: 219 | - Effect: Allow 220 | Principal: 221 | Service: 222 | - lambda.amazonaws.com 223 | Action: 224 | - 'sts:AssumeRole' 225 | DependsOn: UserPoolClient 226 | UserPoolClientLambda: 227 | # Lambda which gets userpool app client config values 228 | # Depends on UserPool for id 229 | # Depends on UserPoolClientRole for role ARN 230 | Type: 'AWS::Lambda::Function' 231 | Properties: 232 | Code: 233 | ZipFile: !Join 234 | - |+ 235 | - - 'const response = require(''cfn-response'');' 236 | - 'const aws = require(''aws-sdk'');' 237 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 238 | - 'exports.handler = (event, context, callback) => {' 239 | - ' if (event.RequestType == ''Delete'') { ' 240 | - ' response.send(event, context, response.SUCCESS, {})' 241 | - ' }' 242 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 243 | - ' const params = {' 244 | - ' ClientId: event.ResourceProperties.clientId,' 245 | - ' UserPoolId: event.ResourceProperties.userpoolId' 246 | - ' };' 247 | - ' identity.describeUserPoolClient(params).promise()' 248 | - ' .then((res) => {' 249 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 250 | - ' })' 251 | - ' .catch((err) => {' 252 | - ' response.send(event, context, response.FAILED, {err});' 253 | - ' });' 254 | - ' }' 255 | - '};' 256 | Handler: index.handler 257 | Runtime: nodejs12.x 258 | Timeout: '300' 259 | Role: !GetAtt 260 | - UserPoolClientRole 261 | - Arn 262 | DependsOn: UserPoolClientRole 263 | UserPoolClientLambdaPolicy: 264 | # Sets userpool policy for the role that executes the Userpool Client Lambda 265 | # Depends on UserPool for Arn 266 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 267 | Type: 'AWS::IAM::Policy' 268 | Properties: 269 | PolicyName: quickn9506fafe_userpoolclient_lambda_iam_policy 270 | Roles: 271 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 272 | PolicyDocument: 273 | Version: '2012-10-17' 274 | Statement: 275 | - Effect: Allow 276 | Action: 277 | - 'cognito-idp:DescribeUserPoolClient' 278 | Resource: !GetAtt UserPool.Arn 279 | DependsOn: UserPoolClientLambda 280 | UserPoolClientLogPolicy: 281 | # Sets log policy for the role that executes the Userpool Client Lambda 282 | # Depends on UserPool for Arn 283 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 284 | Type: 'AWS::IAM::Policy' 285 | Properties: 286 | PolicyName: quickn9506fafe_userpoolclient_lambda_log_policy 287 | Roles: 288 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 289 | PolicyDocument: 290 | Version: 2012-10-17 291 | Statement: 292 | - Effect: Allow 293 | Action: 294 | - 'logs:CreateLogGroup' 295 | - 'logs:CreateLogStream' 296 | - 'logs:PutLogEvents' 297 | Resource: !Sub 298 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 299 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 300 | DependsOn: UserPoolClientLambdaPolicy 301 | UserPoolClientInputs: 302 | # Values passed to Userpool client Lambda 303 | # Depends on UserPool for Id 304 | # Depends on UserPoolClient for Id 305 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 306 | Type: 'Custom::LambdaCallout' 307 | Properties: 308 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 309 | clientId: !Ref UserPoolClient 310 | userpoolId: !Ref UserPool 311 | DependsOn: UserPoolClientLogPolicy 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | # BEGIN IDENTITY POOL RESOURCES 320 | 321 | 322 | IdentityPool: 323 | # Always created 324 | Type: AWS::Cognito::IdentityPool 325 | Properties: 326 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'quicknotes9506fafe_identitypool_9506fafe', !Join ['',['quicknotes9506fafe_identitypool_9506fafe', '__', !Ref env]]] 327 | 328 | CognitoIdentityProviders: 329 | - ClientId: !Ref UserPoolClient 330 | ProviderName: !Sub 331 | - cognito-idp.${region}.amazonaws.com/${client} 332 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 333 | - ClientId: !Ref UserPoolClientWeb 334 | ProviderName: !Sub 335 | - cognito-idp.${region}.amazonaws.com/${client} 336 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 337 | 338 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 339 | 340 | 341 | DependsOn: UserPoolClientInputs 342 | 343 | 344 | IdentityPoolRoleMap: 345 | # Created to map Auth and Unauth roles to the identity pool 346 | # Depends on Identity Pool for ID ref 347 | Type: AWS::Cognito::IdentityPoolRoleAttachment 348 | Properties: 349 | IdentityPoolId: !Ref IdentityPool 350 | Roles: 351 | unauthenticated: !Ref unauthRoleArn 352 | authenticated: !Ref authRoleArn 353 | DependsOn: IdentityPool 354 | 355 | 356 | Outputs : 357 | 358 | IdentityPoolId: 359 | Value: !Ref 'IdentityPool' 360 | Description: Id for the identity pool 361 | IdentityPoolName: 362 | Value: !GetAtt IdentityPool.Name 363 | 364 | 365 | 366 | 367 | UserPoolId: 368 | Value: !Ref 'UserPool' 369 | Description: Id for the user pool 370 | UserPoolName: 371 | Value: !Ref userPoolName 372 | AppClientIDWeb: 373 | Value: !Ref 'UserPoolClientWeb' 374 | Description: The user pool app client id for web 375 | AppClientID: 376 | Value: !Ref 'UserPoolClient' 377 | Description: The user pool app client id 378 | AppClientSecret: 379 | Value: !GetAtt UserPoolClientInputs.appSecret 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | -------------------------------------------------------------------------------- /amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "quicknotes9506fafe": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [] 7 | } 8 | }, 9 | "api": { 10 | "quicknotes": { 11 | "service": "AppSync", 12 | "providerPlugin": "awscloudformation", 13 | "output": { 14 | "securityType": "AMAZON_COGNITO_USER_POOLS" 15 | } 16 | } 17 | }, 18 | "predictions": { 19 | "transcriptione65259cc": { 20 | "providerPlugin": "awscloudformation", 21 | "service": "Transcribe", 22 | "convertType": "transcription" 23 | }, 24 | "speechGeneratorc72b6c38": { 25 | "providerPlugin": "awscloudformation", 26 | "service": "Polly", 27 | "convertType": "speechGenerator" 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /amplify/backend/predictions/speechGeneratorc72b6c38/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceName": "speechGeneratorc72b6c38", 3 | "convertPolicyName": "speechGeneratorPolicyc72b6c38", 4 | "authRoleName": { 5 | "Ref": "AuthRoleName" 6 | }, 7 | "unauthRoleName": { 8 | "Ref": "UnauthRoleName" 9 | }, 10 | "convertType": "speechGenerator", 11 | "language": "en-US", 12 | "voice": "Kendra", 13 | "access": "auth" 14 | } 15 | -------------------------------------------------------------------------------- /amplify/backend/predictions/speechGeneratorc72b6c38/speechGeneratorc72b6c38-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Convert resource(s) stack creation using Amplify CLI", 4 | "Parameters": { 5 | "authRoleName": { 6 | "Type": "String" 7 | }, 8 | "unauthRoleName": { 9 | "Type": "String" 10 | }, 11 | "convertPolicyName": { 12 | "Type": "String" 13 | }, 14 | "convertType": { 15 | "Type": "String" 16 | }, 17 | "access": { 18 | "Type": "String" 19 | }, 20 | "resourceName": { 21 | "Type": "String" 22 | }, 23 | "language": { 24 | "Type": "String" 25 | }, 26 | "voice": { 27 | "Type": "String" 28 | }, 29 | "env": { 30 | "Type": "String" 31 | } 32 | }, 33 | "Conditions": { 34 | "AuthGuestRoleAccess": { 35 | "Fn::Equals": [ 36 | { 37 | "Ref": "access" 38 | }, 39 | "authAndGuest" 40 | ] 41 | } 42 | }, 43 | "Outputs": { 44 | "region": { 45 | "Value": { 46 | "Fn::FindInMap": [ 47 | "RegionMapping", 48 | { 49 | "Ref": "AWS::Region" 50 | }, 51 | { 52 | "Ref": "convertType" 53 | } 54 | ] 55 | } 56 | }, 57 | "language": { 58 | "Value": { 59 | "Ref": "language" 60 | } 61 | }, 62 | "voice": { 63 | "Value": { 64 | "Ref": "voice" 65 | } 66 | } 67 | }, 68 | "Resources": { 69 | "PollyPolicy": { 70 | "Type": "AWS::IAM::Policy", 71 | "Properties": { 72 | "PolicyName": { 73 | "Ref": "convertPolicyName" 74 | }, 75 | "Roles": { 76 | "Fn::If": [ 77 | "AuthGuestRoleAccess", 78 | [ 79 | { 80 | "Ref": "authRoleName" 81 | }, 82 | { 83 | "Ref": "unauthRoleName" 84 | } 85 | ], 86 | [ 87 | { 88 | "Ref": "authRoleName" 89 | } 90 | ] 91 | ] 92 | }, 93 | "PolicyDocument": { 94 | "Version": "2012-10-17", 95 | "Statement": [ 96 | { 97 | "Effect": "Allow", 98 | "Action": [ 99 | "polly:SynthesizeSpeech" 100 | ], 101 | "Resource": "*" 102 | } 103 | ] 104 | } 105 | } 106 | } 107 | }, 108 | "Mappings": { 109 | "RegionMapping": { 110 | "us-east-1": { 111 | "speechGenerator": "us-east-1" 112 | }, 113 | "us-east-2": { 114 | "speechGenerator": "us-east-2" 115 | }, 116 | "us-west-2": { 117 | "speechGenerator": "us-west-2" 118 | }, 119 | "eu-west-1": { 120 | "speechGenerator": "eu-west-1" 121 | }, 122 | "eu-west-2": { 123 | "speechGenerator": "eu-west-2" 124 | }, 125 | "eu-central-1": { 126 | "speechGenerator": "eu-central-1" 127 | }, 128 | "ap-northeast-1": { 129 | "speechGenerator": "ap-northeast-1" 130 | }, 131 | "ap-northeast-2": { 132 | "speechGenerator": "ap-northeast-2" 133 | }, 134 | "ap-southeast-1": { 135 | "speechGenerator": "ap-southeast-1" 136 | }, 137 | "ap-southeast-2": { 138 | "speechGenerator": "ap-southeast-2" 139 | }, 140 | "ap-south-1": { 141 | "speechGenerator": "ap-south-1" 142 | } 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /amplify/backend/predictions/transcriptione65259cc/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "resourceName": "transcriptione65259cc", 3 | "convertPolicyName": "transcriptionPolicye65259cc", 4 | "authRoleName": { 5 | "Ref": "AuthRoleName" 6 | }, 7 | "unauthRoleName": { 8 | "Ref": "UnauthRoleName" 9 | }, 10 | "convertType": "transcription", 11 | "language": "en-US", 12 | "access": "auth" 13 | } -------------------------------------------------------------------------------- /amplify/backend/predictions/transcriptione65259cc/transcriptione65259cc-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Convert resource(s) stack creation using Amplify CLI", 4 | "Parameters": { 5 | "authRoleName": { 6 | "Type": "String" 7 | }, 8 | "unauthRoleName": { 9 | "Type": "String" 10 | }, 11 | "convertPolicyName": { 12 | "Type": "String" 13 | }, 14 | "convertType": { 15 | "Type": "String" 16 | }, 17 | "access": { 18 | "Type": "String" 19 | }, 20 | "resourceName": { 21 | "Type": "String" 22 | }, 23 | "language": { 24 | "Type": "String" 25 | }, 26 | "env": { 27 | "Type": "String" 28 | } 29 | }, 30 | "Conditions": { 31 | "AuthGuestRoleAccess": { 32 | "Fn::Equals": [ 33 | { 34 | "Ref": "access" 35 | }, 36 | "authAndGuest" 37 | ] 38 | } 39 | }, 40 | "Outputs": { 41 | "region": { 42 | "Value": { 43 | "Fn::FindInMap": [ 44 | "RegionMapping", 45 | { 46 | "Ref": "AWS::Region" 47 | }, 48 | { 49 | "Ref": "convertType" 50 | } 51 | ] 52 | } 53 | }, 54 | "language": { 55 | "Value": { 56 | "Ref": "language" 57 | } 58 | } 59 | }, 60 | "Resources": { 61 | "PollyPolicy": { 62 | "Type": "AWS::IAM::Policy", 63 | "Properties": { 64 | "PolicyName": { 65 | "Ref": "convertPolicyName" 66 | }, 67 | "Roles": { 68 | "Fn::If": [ 69 | "AuthGuestRoleAccess", 70 | [ 71 | { 72 | "Ref": "authRoleName" 73 | }, 74 | { 75 | "Ref": "unauthRoleName" 76 | } 77 | ], 78 | [ 79 | { 80 | "Ref": "authRoleName" 81 | } 82 | ] 83 | ] 84 | }, 85 | "PolicyDocument": { 86 | "Version": "2012-10-17", 87 | "Statement": [ 88 | { 89 | "Effect": "Allow", 90 | "Action": [ 91 | "transcribe:GetTranscriptionJob", 92 | "transcribe:StartStreamTranscription", 93 | "transcribe:StartStreamTranscriptionWebSocket", 94 | "transcribe:StartTranscriptionJob" 95 | ], 96 | "Resource": "*" 97 | } 98 | ] 99 | } 100 | } 101 | } 102 | }, 103 | "Mappings": { 104 | "RegionMapping": { 105 | "us-east-1": { 106 | "transcription": "us-east-1" 107 | }, 108 | "us-east-2": { 109 | "transcription": "us-east-2" 110 | }, 111 | "us-west-2": { 112 | "transcription": "us-west-2" 113 | }, 114 | "eu-west-1": { 115 | "transcription": "eu-west-1" 116 | }, 117 | "eu-west-2": { 118 | "transcription": "eu-west-2" 119 | }, 120 | "eu-central-1": { 121 | "transcription": "eu-central-1" 122 | }, 123 | "ap-northeast-1": { 124 | "transcription": "ap-northeast-2" 125 | }, 126 | "ap-northeast-2": { 127 | "transcription": "ap-northeast-2" 128 | }, 129 | "ap-southeast-1": { 130 | "transcription": "ap-southeast-1" 131 | }, 132 | "ap-southeast-2": { 133 | "transcription": "ap-southeast-2" 134 | }, 135 | "ap-south-1": { 136 | "transcription": "ap-south-1" 137 | } 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-amplify-quick-notes/7f29c52bea9e753ead2ea9f3c99454a1c015981e/example.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quick-notes", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@aws-amplify/predictions": "^4.0.6", 7 | "@emotion/core": "^10.0.28", 8 | "@emotion/styled": "^10.0.27", 9 | "@reach/dialog": "^0.9.1", 10 | "@reach/tabs": "^0.9.1", 11 | "@rebass/emotion": "^3.2.0", 12 | "@rebass/forms": "^4.0.6", 13 | "aws-amplify": "^4.3.14", 14 | "aws-amplify-react": "^5.0.6", 15 | "formik": "^2.1.4", 16 | "microphone-stream": "^6.0.1", 17 | "normalize.css": "^8.0.1", 18 | "react": "^16.13.1", 19 | "react-dom": "^16.13.1", 20 | "react-icons": "^3.9.0", 21 | "react-scripts": "^5.0.0" 22 | }, 23 | "scripts": { 24 | "start": "react-scripts start", 25 | "build": "react-scripts build", 26 | "test": "react-scripts test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "eslintConfig": { 30 | "extends": "react-app" 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | }, 44 | "resolutions": { 45 | "lodash": "4.17.21", 46 | "websocket-extensions": "0.1.4" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-amplify-quick-notes/7f29c52bea9e753ead2ea9f3c99454a1c015981e/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-amplify-quick-notes/7f29c52bea9e753ead2ea9f3c99454a1c015981e/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-amplify-quick-notes/7f29c52bea9e753ead2ea9f3c99454a1c015981e/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | pointer-events: none; 9 | } 10 | 11 | .App-header { 12 | background-color: #282c34; 13 | min-height: 100vh; 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | justify-content: center; 18 | font-size: calc(10px + 2vmin); 19 | color: white; 20 | } 21 | 22 | .App-link { 23 | color: #61dafb; 24 | } 25 | 26 | @keyframes App-logo-spin { 27 | from { 28 | transform: rotate(0deg); 29 | } 30 | to { 31 | transform: rotate(360deg); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import { Auth } from "aws-amplify"; 3 | import { Authenticator } from "aws-amplify-react"; 4 | import styled from "@emotion/styled"; 5 | 6 | import awsExports from "./aws-exports"; 7 | import Screens from "./components/Screens"; 8 | 9 | const Title = styled("h1")` 10 | text-align: center; 11 | text-transform: uppercase; 12 | color: #a7d7c5; 13 | margin-bottom: 8px; 14 | `; 15 | 16 | const theme = { 17 | formContainer: { 18 | margin: 0, 19 | padding: "8px 24px 24px" 20 | }, 21 | formSection: { 22 | backgroundColor: "#ffffff", 23 | borderRadius: "4px" 24 | }, 25 | sectionHeader: { 26 | color: "#74b49b" 27 | }, 28 | sectionFooterSecondaryContent: { 29 | color: "#303952" 30 | }, 31 | inputLabel: { 32 | color: "#74b49b" 33 | }, 34 | input: { 35 | backgroundColor: "#f4f9f4", 36 | color: "#74b49b" 37 | }, 38 | hint: { 39 | color: "#74b49b" 40 | }, 41 | button: { 42 | borderRadius: "3px", 43 | backgroundColor: "#a7d7c5" 44 | }, 45 | a: { 46 | color: "#a7d7c5" 47 | } 48 | }; 49 | 50 | function App() { 51 | const [state, setState] = useState({ isLoggedIn: false, user: null }); 52 | 53 | const checkLoggedIn = () => { 54 | Auth.currentAuthenticatedUser() 55 | .then(data => { 56 | const user = { username: data.username, ...data.attributes }; 57 | setState({ isLoggedIn: true, user }); 58 | }) 59 | .catch(error => console.log(error)); 60 | }; 61 | 62 | useEffect(() => { 63 | checkLoggedIn(); 64 | }, []); 65 | 66 | return state.isLoggedIn ? ( 67 | 68 | ) : ( 69 | <> 70 | Quick Notes 71 | { 73 | if (authState === "signedIn") { 74 | checkLoggedIn(); 75 | } 76 | }} 77 | amplifyConfig={awsExports} 78 | theme={theme} 79 | /> 80 | 81 | ); 82 | } 83 | 84 | export default App; 85 | -------------------------------------------------------------------------------- /src/components/Dialog.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Dialog, DialogOverlay, DialogContent } from "@reach/dialog"; 3 | import styled from "@emotion/styled"; 4 | 5 | const StyledDialogOverlay = styled(DialogOverlay)` 6 | position: fixed; 7 | top: 0; 8 | bottom: 0; 9 | left: 0; 10 | right: 0; 11 | background-color: hsla(120, 29%, 97%, 0.95); 12 | padding: 24px; 13 | z-index: 99; 14 | `; 15 | 16 | const StyledDialogContent = styled(DialogContent)` 17 | background-color: #ffffff; 18 | border-radius: 4px; 19 | max-width: 800px; 20 | box-shadow: 0 0 9px rgba(255, 255, 255, 0.3); 21 | padding: 24px; 22 | margin: 24px auto; 23 | `; 24 | 25 | const DialogComponent = props => ( 26 | 27 | 28 | {props.children} 29 | 30 | 31 | ); 32 | 33 | export default DialogComponent; -------------------------------------------------------------------------------- /src/components/Note.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import styled from "@emotion/styled"; 3 | import { FaRegEdit, FaPlay, FaRegTrashAlt } from "react-icons/fa"; 4 | import { Predictions } from "aws-amplify"; 5 | 6 | import RecordingEditor from "./Recording-Editor"; 7 | 8 | const Note = styled("div")` 9 | background-color: #ffffff; 10 | border-radius: 4px; 11 | margin-bottom: 24px; 12 | display: flex; 13 | flex-direction: column; 14 | justify-content: space-between; 15 | align-items: stretch; 16 | overflow: hidden; 17 | box-shadow: 0 2px 4px rgba(116, 180, 155, 0.2); 18 | `; 19 | 20 | const Title = styled("h2")` 21 | color: #74b49b; 22 | margin-top: 0; 23 | margin-bottom: 8px; 24 | `; 25 | 26 | const Text = styled("p")` 27 | color: #74b49b; 28 | margin-top: 0; 29 | `; 30 | 31 | const Icon = styled("button")` 32 | padding: 8px 10px; 33 | display: inline-flex; 34 | justify-content: center; 35 | align-items: center; 36 | color: #74b49b; 37 | border: none; 38 | cursor: pointer; 39 | flex: 1; 40 | background-color: #ffffff; 41 | 42 | &:hover { 43 | color: #ffffff; 44 | background-color: #74b49b; 45 | } 46 | `; 47 | 48 | const Divider = styled("div")` 49 | height: 2px; 50 | background-color: #f4f9f4; 51 | `; 52 | 53 | const NoteActions = styled("div")` 54 | display: flex; 55 | justify-content: stretch; 56 | align-items: stretch; 57 | height: 50px; 58 | background-color: #74b49b; 59 | `; 60 | 61 | const Info = styled.div` 62 | padding: 24px; 63 | `; 64 | 65 | const NotesComponent = props => { 66 | const [showEditor, setShowEditor] = useState(false); 67 | 68 | const playAudio = async () => { 69 | const result = await Predictions.convert({ 70 | textToSpeech: { 71 | source: { 72 | text: props.text 73 | } 74 | } 75 | }); 76 | 77 | const audioCtx = new AudioContext(); 78 | const source = audioCtx.createBufferSource(); 79 | 80 | audioCtx.decodeAudioData( 81 | result.audioStream, 82 | buffer => { 83 | source.buffer = buffer; 84 | source.connect(audioCtx.destination); 85 | source.start(0); 86 | }, 87 | error => console.log(error) 88 | ); 89 | }; 90 | 91 | return ( 92 | 93 | 94 | {props.title} 95 | {props.text} 96 | 97 | 98 | 99 | playAudio()}> 100 | 101 | 102 | setShowEditor(true)}> 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | {showEditor && ( 111 | { 115 | setShowEditor(false); 116 | }} 117 | onSave={props.onSaveChanges} 118 | /> 119 | )} 120 | 121 | ); 122 | }; 123 | 124 | export default NotesComponent; -------------------------------------------------------------------------------- /src/components/Notes.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { API, graphqlOperation } from "aws-amplify"; 3 | import styled from "@emotion/styled"; 4 | 5 | import Note from "./Note"; 6 | import { listNotes } from "../graphql/queries"; 7 | import { updateNote, deleteNote } from "../graphql/mutations"; 8 | 9 | const Container = styled("div")` 10 | max-width: 800px; 11 | margin: 16px auto; 12 | width: 100%; 13 | `; 14 | 15 | const NotesComponent = () => { 16 | const [notes, setNotes] = useState([]); 17 | 18 | useEffect(() => { 19 | const fetchNotes = async () => { 20 | const result = await API.graphql(graphqlOperation(listNotes)); 21 | 22 | setNotes( 23 | result.data.listNotes.items.sort((a, b) => { 24 | if (a.updatedAt > b.updatedAt) return -1; 25 | else return 1; 26 | }) 27 | ); 28 | }; 29 | 30 | fetchNotes(); 31 | }, []); 32 | 33 | return ( 34 | 35 | {notes.map(note => ( 36 | { 40 | const result = await API.graphql( 41 | graphqlOperation(updateNote, { 42 | input: { 43 | ...note, 44 | ...values 45 | } 46 | }) 47 | ); 48 | 49 | setNotes( 50 | notes.map(n => { 51 | return n.id === note.id ? result.data.updateNote : n; 52 | }) 53 | ); 54 | }} 55 | onDelete={async () => { 56 | await API.graphql( 57 | graphqlOperation(deleteNote, { 58 | input: { 59 | id: note.id 60 | } 61 | }) 62 | ); 63 | 64 | setNotes(notes.filter(n => n.id !== note.id)); 65 | }} 66 | /> 67 | ))} 68 | 69 | ); 70 | }; 71 | 72 | export default NotesComponent; -------------------------------------------------------------------------------- /src/components/Record.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { API, graphqlOperation } from "aws-amplify"; 3 | import { Predictions } from "aws-amplify"; 4 | import { keyframes, css } from "@emotion/core"; 5 | import styled from "@emotion/styled"; 6 | import { 7 | FaMicrophone, 8 | FaMicrophoneAlt, 9 | FaMicrophoneAltSlash 10 | } from "react-icons/fa"; 11 | import mic from "microphone-stream"; 12 | 13 | import RecordingEditor from "./Recording-Editor"; 14 | import { createNote } from "../graphql/mutations"; 15 | 16 | const Container = styled("div")` 17 | margin: 16px auto; 18 | display: flex; 19 | flex-direction: column; 20 | justify-content: space-around; 21 | align-items: center; 22 | `; 23 | 24 | const pulse = keyframes` 25 | 0% { 26 | transform: scale(1); 27 | opacity: 0.3; 28 | } 29 | 30 | 100% { 31 | transform: scale(2); 32 | opacity: 0; 33 | } 34 | `; 35 | 36 | const RecordComponent = props => { 37 | const [isRecording, setIsRecording] = useState(false); 38 | const [showRecordingEditor, setShowRecordingEditor] = useState(false); 39 | const [recordingText, setRecordingText] = useState(""); 40 | const [isConverting, setIsConverting] = useState(""); 41 | const [micStream, setMicStream] = useState(); 42 | const [audioBuffer] = useState( 43 | (function() { 44 | let buffer = []; 45 | function add(raw) { 46 | buffer = buffer.concat(...raw); 47 | return buffer; 48 | } 49 | function newBuffer() { 50 | console.log("reseting buffer"); 51 | buffer = []; 52 | } 53 | 54 | return { 55 | reset: function() { 56 | newBuffer(); 57 | }, 58 | addData: function(raw) { 59 | return add(raw); 60 | }, 61 | getData: function() { 62 | return buffer; 63 | } 64 | }; 65 | })() 66 | ); 67 | 68 | const startRecording = async () => { 69 | const stream = await window.navigator.mediaDevices.getUserMedia({ 70 | video: false, 71 | audio: true 72 | }); 73 | const startMic = new mic(); 74 | 75 | startMic.setStream(stream); 76 | startMic.on("data", chunk => { 77 | var raw = mic.toRaw(chunk); 78 | if (raw == null) { 79 | return; 80 | } 81 | audioBuffer.addData(raw); 82 | }); 83 | 84 | setMicStream(startMic); 85 | setIsRecording(true); 86 | }; 87 | 88 | const stopRecording = async () => { 89 | micStream.stop(); 90 | setIsRecording(false); 91 | setIsConverting(true); 92 | 93 | const buffer = audioBuffer.getData(); 94 | const result = await Predictions.convert({ 95 | transcription: { 96 | source: { 97 | bytes: buffer 98 | } 99 | } 100 | }); 101 | 102 | setMicStream(null); 103 | audioBuffer.reset(); 104 | setRecordingText(result.transcription.fullText); 105 | setIsConverting(false); 106 | setShowRecordingEditor(true); 107 | }; 108 | 109 | return ( 110 | 111 |
120 |
139 |
{ 152 | if (!isRecording) { 153 | startRecording(); 154 | } else { 155 | stopRecording(); 156 | } 157 | }} 158 | > 159 | {isConverting ? ( 160 | 164 | ) : isRecording ? ( 165 | 169 | ) : ( 170 | 174 | )} 175 |
176 |
177 | {showRecordingEditor && ( 178 | { 181 | setShowRecordingEditor(false); 182 | }} 183 | onSave={async data => { 184 | await API.graphql(graphqlOperation(createNote, { input: data })); 185 | props.setTabIndex(0); 186 | }} 187 | /> 188 | )} 189 | 190 | ); 191 | }; 192 | 193 | export default RecordComponent; -------------------------------------------------------------------------------- /src/components/Recording-Editor.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "@emotion/styled"; 3 | import { Button } from "@rebass/emotion"; 4 | import { Label, Input } from "@rebass/forms"; 5 | import { Formik } from "formik"; 6 | 7 | import Dialog from "./Dialog"; 8 | 9 | const StyledButton = styled(Button)` 10 | background-color: #74b49b; 11 | cursor: pointer; 12 | `; 13 | 14 | const StyledLabel = styled(Label)` 15 | color: #74b49b; 16 | margin-bottom: 4px; 17 | `; 18 | 19 | const StyledInput = styled(Input)` 20 | color: #74b49b; 21 | border-radius: 3px; 22 | background-color: #f4f9f4; 23 | `; 24 | 25 | const StyledTextarea = styled("textarea")` 26 | color: #74b49b; 27 | background-color: #f4f9f4; 28 | width: 100%; 29 | min-height: 80px; 30 | border-radius: 3px; 31 | resize: vertical; 32 | `; 33 | 34 | const FormInputs = styled("div")` 35 | max-height: 450px; 36 | overflow: scroll; 37 | padding: 16px; 38 | 39 | @media (max-height: 570px) { 40 | max-height: 300px; 41 | } 42 | 43 | @media (max-height: 675px) { 44 | max-height: 350px; 45 | } 46 | `; 47 | 48 | const Actions = styled("div")` 49 | display: flex; 50 | justify-content: flex-end; 51 | align-items: center; 52 | margin-top: 24px; 53 | `; 54 | 55 | const InputContainer = styled("div")` 56 | margin-bottom: 16px; 57 | `; 58 | 59 | const Title = styled("h2")` 60 | color: #74b49b; 61 | `; 62 | 63 | const RecordingEditor = props => ( 64 | 65 | {props.title ? "Edit Note" : "Create Note"} 66 | { 72 | props.onSave({ 73 | title: values.title || `${values.text.substr(0, 20)}...`, 74 | text: values.text 75 | }); 76 | setSubmitting(false); 77 | resetForm(); 78 | props.onDismiss(); 79 | }} 80 | > 81 | {({ values, handleSubmit, isSubmitting, handleChange }) => ( 82 |
83 | 84 | 85 | Title 86 | 92 | 93 | 94 | 95 | Note 96 | 101 | 102 | 103 | 104 | 105 | { 107 | props.onDismiss(); 108 | }} 109 | style={{ marginRight: "8px" }} 110 | > 111 | Cancel 112 | 113 | 114 | {isSubmitting ? "Saving..." : "Save"} 115 | 116 | 117 |
118 | )} 119 |
120 |
121 | ); 122 | 123 | export default RecordingEditor; -------------------------------------------------------------------------------- /src/components/Screens.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import styled from "@emotion/styled"; 3 | import { Auth } from "aws-amplify"; 4 | import { Button } from "@rebass/emotion"; 5 | import { Tabs, TabList, Tab, TabPanels, TabPanel } from "@reach/tabs"; 6 | 7 | import Notes from "./Notes"; 8 | import Record from "./Record"; 9 | 10 | const Header = styled("div")` 11 | background-color: #ffffff; 12 | padding-left: 16px; 13 | padding-right: 16px; 14 | display: flex; 15 | justify-content: space-between; 16 | align-items: center; 17 | position: fixed; 18 | right: 0; 19 | left: 0; 20 | height: 80px; 21 | z-index: 2; 22 | `; 23 | 24 | const Title = styled("h1")` 25 | margin-top: 0; 26 | margin-bottom: 0; 27 | text-transform: uppercase; 28 | color: #74b49b; 29 | font-size: 24px; 30 | `; 31 | 32 | const SignOutButton = styled(Button)` 33 | background-color: #74b49b; 34 | cursor: pointer; 35 | `; 36 | 37 | const StyledTabs = styled(Tabs)` 38 | padding-top: 80px; 39 | display: flex; 40 | flex-direction: column; 41 | height: calc(100vh - 80px); 42 | `; 43 | 44 | const StyledTabList = styled(TabList)` 45 | display: flex; 46 | justify-content: stretch; 47 | align-items: center; 48 | position: fixed; 49 | top: 80px; 50 | left: 0; 51 | right: 0; 52 | height: 40px; 53 | box-shadow: 0 6px 6px rgba(116, 180, 155, 0.4); 54 | 55 | & > [data-selected] { 56 | border-bottom-color: #74b49b; 57 | color: #74b49b; 58 | } 59 | `; 60 | 61 | const StyledTabPanels = styled(TabPanels)` 62 | padding-top: 50px; 63 | flex: 1; 64 | 65 | [hidden] { 66 | display: none; 67 | } 68 | `; 69 | 70 | const StyledTabPanel = styled(TabPanel)` 71 | flex: 1; 72 | padding: 16px; 73 | display: flex; 74 | min-height: calc(100% - 32px); 75 | `; 76 | 77 | const StyledTab = styled(Tab)` 78 | text-transform: uppercase; 79 | flex: 1; 80 | padding: 16px; 81 | color: #74b49b; 82 | background-color: #ffffff; 83 | font-size: 16px; 84 | border: none; 85 | border-bottom: 3px solid #ffffff; 86 | `; 87 | 88 | const Screens = () => { 89 | const [tabIndex, setTabIndex] = useState(0); 90 | 91 | return ( 92 | <> 93 |
94 | Quick Notes 95 | { 97 | Auth.signOut().then(() => window.location.reload()); 98 | }} 99 | > 100 | Sign Out 101 | 102 |
103 | setTabIndex(index)}> 104 | 105 | Notes 106 | Record 107 | 108 | 109 | 110 | {tabIndex === 0 && } 111 | 112 | 113 | {tabIndex === 1 && } 114 | 115 | 116 | 117 | 118 | ); 119 | }; 120 | 121 | export default Screens; -------------------------------------------------------------------------------- /src/graphql/mutations.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const createNote = `mutation CreateNote($input: CreateNoteInput!) { 5 | createNote(input: $input) { 6 | id 7 | title 8 | text 9 | createdAt 10 | updatedAt 11 | } 12 | } 13 | `; 14 | export const updateNote = `mutation UpdateNote($input: UpdateNoteInput!) { 15 | updateNote(input: $input) { 16 | id 17 | title 18 | text 19 | createdAt 20 | updatedAt 21 | } 22 | } 23 | `; 24 | export const deleteNote = `mutation DeleteNote($input: DeleteNoteInput!) { 25 | deleteNote(input: $input) { 26 | id 27 | title 28 | text 29 | createdAt 30 | updatedAt 31 | } 32 | } 33 | `; 34 | -------------------------------------------------------------------------------- /src/graphql/queries.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const getNote = `query GetNote($id: ID!) { 5 | getNote(id: $id) { 6 | id 7 | title 8 | text 9 | createdAt 10 | updatedAt 11 | } 12 | } 13 | `; 14 | export const listNotes = `query ListNotes( 15 | $filter: ModelNoteFilterInput 16 | $limit: Int 17 | $nextToken: String 18 | ) { 19 | listNotes(filter: $filter, limit: $limit, nextToken: $nextToken) { 20 | items { 21 | id 22 | title 23 | text 24 | createdAt 25 | updatedAt 26 | } 27 | nextToken 28 | } 29 | } 30 | `; 31 | -------------------------------------------------------------------------------- /src/graphql/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "data" : { 3 | "__schema" : { 4 | "queryType" : { 5 | "name" : "Query" 6 | }, 7 | "mutationType" : { 8 | "name" : "Mutation" 9 | }, 10 | "subscriptionType" : { 11 | "name" : "Subscription" 12 | }, 13 | "types" : [ { 14 | "kind" : "OBJECT", 15 | "name" : "Query", 16 | "description" : null, 17 | "fields" : [ { 18 | "name" : "getNote", 19 | "description" : null, 20 | "args" : [ { 21 | "name" : "id", 22 | "description" : null, 23 | "type" : { 24 | "kind" : "NON_NULL", 25 | "name" : null, 26 | "ofType" : { 27 | "kind" : "SCALAR", 28 | "name" : "ID", 29 | "ofType" : null 30 | } 31 | }, 32 | "defaultValue" : null 33 | } ], 34 | "type" : { 35 | "kind" : "OBJECT", 36 | "name" : "Note", 37 | "ofType" : null 38 | }, 39 | "isDeprecated" : false, 40 | "deprecationReason" : null 41 | }, { 42 | "name" : "listNotes", 43 | "description" : null, 44 | "args" : [ { 45 | "name" : "filter", 46 | "description" : null, 47 | "type" : { 48 | "kind" : "INPUT_OBJECT", 49 | "name" : "ModelNoteFilterInput", 50 | "ofType" : null 51 | }, 52 | "defaultValue" : null 53 | }, { 54 | "name" : "limit", 55 | "description" : null, 56 | "type" : { 57 | "kind" : "SCALAR", 58 | "name" : "Int", 59 | "ofType" : null 60 | }, 61 | "defaultValue" : null 62 | }, { 63 | "name" : "nextToken", 64 | "description" : null, 65 | "type" : { 66 | "kind" : "SCALAR", 67 | "name" : "String", 68 | "ofType" : null 69 | }, 70 | "defaultValue" : null 71 | } ], 72 | "type" : { 73 | "kind" : "OBJECT", 74 | "name" : "ModelNoteConnection", 75 | "ofType" : null 76 | }, 77 | "isDeprecated" : false, 78 | "deprecationReason" : null 79 | } ], 80 | "inputFields" : null, 81 | "interfaces" : [ ], 82 | "enumValues" : null, 83 | "possibleTypes" : null 84 | }, { 85 | "kind" : "OBJECT", 86 | "name" : "Note", 87 | "description" : null, 88 | "fields" : [ { 89 | "name" : "id", 90 | "description" : null, 91 | "args" : [ ], 92 | "type" : { 93 | "kind" : "NON_NULL", 94 | "name" : null, 95 | "ofType" : { 96 | "kind" : "SCALAR", 97 | "name" : "ID", 98 | "ofType" : null 99 | } 100 | }, 101 | "isDeprecated" : false, 102 | "deprecationReason" : null 103 | }, { 104 | "name" : "title", 105 | "description" : null, 106 | "args" : [ ], 107 | "type" : { 108 | "kind" : "NON_NULL", 109 | "name" : null, 110 | "ofType" : { 111 | "kind" : "SCALAR", 112 | "name" : "String", 113 | "ofType" : null 114 | } 115 | }, 116 | "isDeprecated" : false, 117 | "deprecationReason" : null 118 | }, { 119 | "name" : "text", 120 | "description" : null, 121 | "args" : [ ], 122 | "type" : { 123 | "kind" : "NON_NULL", 124 | "name" : null, 125 | "ofType" : { 126 | "kind" : "SCALAR", 127 | "name" : "String", 128 | "ofType" : null 129 | } 130 | }, 131 | "isDeprecated" : false, 132 | "deprecationReason" : null 133 | }, { 134 | "name" : "createdAt", 135 | "description" : null, 136 | "args" : [ ], 137 | "type" : { 138 | "kind" : "SCALAR", 139 | "name" : "String", 140 | "ofType" : null 141 | }, 142 | "isDeprecated" : false, 143 | "deprecationReason" : null 144 | }, { 145 | "name" : "updatedAt", 146 | "description" : null, 147 | "args" : [ ], 148 | "type" : { 149 | "kind" : "SCALAR", 150 | "name" : "String", 151 | "ofType" : null 152 | }, 153 | "isDeprecated" : false, 154 | "deprecationReason" : null 155 | } ], 156 | "inputFields" : null, 157 | "interfaces" : [ ], 158 | "enumValues" : null, 159 | "possibleTypes" : null 160 | }, { 161 | "kind" : "SCALAR", 162 | "name" : "ID", 163 | "description" : "Built-in ID", 164 | "fields" : null, 165 | "inputFields" : null, 166 | "interfaces" : null, 167 | "enumValues" : null, 168 | "possibleTypes" : null 169 | }, { 170 | "kind" : "SCALAR", 171 | "name" : "String", 172 | "description" : "Built-in String", 173 | "fields" : null, 174 | "inputFields" : null, 175 | "interfaces" : null, 176 | "enumValues" : null, 177 | "possibleTypes" : null 178 | }, { 179 | "kind" : "OBJECT", 180 | "name" : "ModelNoteConnection", 181 | "description" : null, 182 | "fields" : [ { 183 | "name" : "items", 184 | "description" : null, 185 | "args" : [ ], 186 | "type" : { 187 | "kind" : "LIST", 188 | "name" : null, 189 | "ofType" : { 190 | "kind" : "OBJECT", 191 | "name" : "Note", 192 | "ofType" : null 193 | } 194 | }, 195 | "isDeprecated" : false, 196 | "deprecationReason" : null 197 | }, { 198 | "name" : "nextToken", 199 | "description" : null, 200 | "args" : [ ], 201 | "type" : { 202 | "kind" : "SCALAR", 203 | "name" : "String", 204 | "ofType" : null 205 | }, 206 | "isDeprecated" : false, 207 | "deprecationReason" : null 208 | } ], 209 | "inputFields" : null, 210 | "interfaces" : [ ], 211 | "enumValues" : null, 212 | "possibleTypes" : null 213 | }, { 214 | "kind" : "INPUT_OBJECT", 215 | "name" : "ModelNoteFilterInput", 216 | "description" : null, 217 | "fields" : null, 218 | "inputFields" : [ { 219 | "name" : "id", 220 | "description" : null, 221 | "type" : { 222 | "kind" : "INPUT_OBJECT", 223 | "name" : "ModelIDFilterInput", 224 | "ofType" : null 225 | }, 226 | "defaultValue" : null 227 | }, { 228 | "name" : "title", 229 | "description" : null, 230 | "type" : { 231 | "kind" : "INPUT_OBJECT", 232 | "name" : "ModelStringFilterInput", 233 | "ofType" : null 234 | }, 235 | "defaultValue" : null 236 | }, { 237 | "name" : "text", 238 | "description" : null, 239 | "type" : { 240 | "kind" : "INPUT_OBJECT", 241 | "name" : "ModelStringFilterInput", 242 | "ofType" : null 243 | }, 244 | "defaultValue" : null 245 | }, { 246 | "name" : "createdAt", 247 | "description" : null, 248 | "type" : { 249 | "kind" : "INPUT_OBJECT", 250 | "name" : "ModelStringFilterInput", 251 | "ofType" : null 252 | }, 253 | "defaultValue" : null 254 | }, { 255 | "name" : "updatedAt", 256 | "description" : null, 257 | "type" : { 258 | "kind" : "INPUT_OBJECT", 259 | "name" : "ModelStringFilterInput", 260 | "ofType" : null 261 | }, 262 | "defaultValue" : null 263 | }, { 264 | "name" : "and", 265 | "description" : null, 266 | "type" : { 267 | "kind" : "LIST", 268 | "name" : null, 269 | "ofType" : { 270 | "kind" : "INPUT_OBJECT", 271 | "name" : "ModelNoteFilterInput", 272 | "ofType" : null 273 | } 274 | }, 275 | "defaultValue" : null 276 | }, { 277 | "name" : "or", 278 | "description" : null, 279 | "type" : { 280 | "kind" : "LIST", 281 | "name" : null, 282 | "ofType" : { 283 | "kind" : "INPUT_OBJECT", 284 | "name" : "ModelNoteFilterInput", 285 | "ofType" : null 286 | } 287 | }, 288 | "defaultValue" : null 289 | }, { 290 | "name" : "not", 291 | "description" : null, 292 | "type" : { 293 | "kind" : "INPUT_OBJECT", 294 | "name" : "ModelNoteFilterInput", 295 | "ofType" : null 296 | }, 297 | "defaultValue" : null 298 | } ], 299 | "interfaces" : null, 300 | "enumValues" : null, 301 | "possibleTypes" : null 302 | }, { 303 | "kind" : "INPUT_OBJECT", 304 | "name" : "ModelIDFilterInput", 305 | "description" : null, 306 | "fields" : null, 307 | "inputFields" : [ { 308 | "name" : "ne", 309 | "description" : null, 310 | "type" : { 311 | "kind" : "SCALAR", 312 | "name" : "ID", 313 | "ofType" : null 314 | }, 315 | "defaultValue" : null 316 | }, { 317 | "name" : "eq", 318 | "description" : null, 319 | "type" : { 320 | "kind" : "SCALAR", 321 | "name" : "ID", 322 | "ofType" : null 323 | }, 324 | "defaultValue" : null 325 | }, { 326 | "name" : "le", 327 | "description" : null, 328 | "type" : { 329 | "kind" : "SCALAR", 330 | "name" : "ID", 331 | "ofType" : null 332 | }, 333 | "defaultValue" : null 334 | }, { 335 | "name" : "lt", 336 | "description" : null, 337 | "type" : { 338 | "kind" : "SCALAR", 339 | "name" : "ID", 340 | "ofType" : null 341 | }, 342 | "defaultValue" : null 343 | }, { 344 | "name" : "ge", 345 | "description" : null, 346 | "type" : { 347 | "kind" : "SCALAR", 348 | "name" : "ID", 349 | "ofType" : null 350 | }, 351 | "defaultValue" : null 352 | }, { 353 | "name" : "gt", 354 | "description" : null, 355 | "type" : { 356 | "kind" : "SCALAR", 357 | "name" : "ID", 358 | "ofType" : null 359 | }, 360 | "defaultValue" : null 361 | }, { 362 | "name" : "contains", 363 | "description" : null, 364 | "type" : { 365 | "kind" : "SCALAR", 366 | "name" : "ID", 367 | "ofType" : null 368 | }, 369 | "defaultValue" : null 370 | }, { 371 | "name" : "notContains", 372 | "description" : null, 373 | "type" : { 374 | "kind" : "SCALAR", 375 | "name" : "ID", 376 | "ofType" : null 377 | }, 378 | "defaultValue" : null 379 | }, { 380 | "name" : "between", 381 | "description" : null, 382 | "type" : { 383 | "kind" : "LIST", 384 | "name" : null, 385 | "ofType" : { 386 | "kind" : "SCALAR", 387 | "name" : "ID", 388 | "ofType" : null 389 | } 390 | }, 391 | "defaultValue" : null 392 | }, { 393 | "name" : "beginsWith", 394 | "description" : null, 395 | "type" : { 396 | "kind" : "SCALAR", 397 | "name" : "ID", 398 | "ofType" : null 399 | }, 400 | "defaultValue" : null 401 | } ], 402 | "interfaces" : null, 403 | "enumValues" : null, 404 | "possibleTypes" : null 405 | }, { 406 | "kind" : "INPUT_OBJECT", 407 | "name" : "ModelStringFilterInput", 408 | "description" : null, 409 | "fields" : null, 410 | "inputFields" : [ { 411 | "name" : "ne", 412 | "description" : null, 413 | "type" : { 414 | "kind" : "SCALAR", 415 | "name" : "String", 416 | "ofType" : null 417 | }, 418 | "defaultValue" : null 419 | }, { 420 | "name" : "eq", 421 | "description" : null, 422 | "type" : { 423 | "kind" : "SCALAR", 424 | "name" : "String", 425 | "ofType" : null 426 | }, 427 | "defaultValue" : null 428 | }, { 429 | "name" : "le", 430 | "description" : null, 431 | "type" : { 432 | "kind" : "SCALAR", 433 | "name" : "String", 434 | "ofType" : null 435 | }, 436 | "defaultValue" : null 437 | }, { 438 | "name" : "lt", 439 | "description" : null, 440 | "type" : { 441 | "kind" : "SCALAR", 442 | "name" : "String", 443 | "ofType" : null 444 | }, 445 | "defaultValue" : null 446 | }, { 447 | "name" : "ge", 448 | "description" : null, 449 | "type" : { 450 | "kind" : "SCALAR", 451 | "name" : "String", 452 | "ofType" : null 453 | }, 454 | "defaultValue" : null 455 | }, { 456 | "name" : "gt", 457 | "description" : null, 458 | "type" : { 459 | "kind" : "SCALAR", 460 | "name" : "String", 461 | "ofType" : null 462 | }, 463 | "defaultValue" : null 464 | }, { 465 | "name" : "contains", 466 | "description" : null, 467 | "type" : { 468 | "kind" : "SCALAR", 469 | "name" : "String", 470 | "ofType" : null 471 | }, 472 | "defaultValue" : null 473 | }, { 474 | "name" : "notContains", 475 | "description" : null, 476 | "type" : { 477 | "kind" : "SCALAR", 478 | "name" : "String", 479 | "ofType" : null 480 | }, 481 | "defaultValue" : null 482 | }, { 483 | "name" : "between", 484 | "description" : null, 485 | "type" : { 486 | "kind" : "LIST", 487 | "name" : null, 488 | "ofType" : { 489 | "kind" : "SCALAR", 490 | "name" : "String", 491 | "ofType" : null 492 | } 493 | }, 494 | "defaultValue" : null 495 | }, { 496 | "name" : "beginsWith", 497 | "description" : null, 498 | "type" : { 499 | "kind" : "SCALAR", 500 | "name" : "String", 501 | "ofType" : null 502 | }, 503 | "defaultValue" : null 504 | } ], 505 | "interfaces" : null, 506 | "enumValues" : null, 507 | "possibleTypes" : null 508 | }, { 509 | "kind" : "SCALAR", 510 | "name" : "Int", 511 | "description" : "Built-in Int", 512 | "fields" : null, 513 | "inputFields" : null, 514 | "interfaces" : null, 515 | "enumValues" : null, 516 | "possibleTypes" : null 517 | }, { 518 | "kind" : "OBJECT", 519 | "name" : "Mutation", 520 | "description" : null, 521 | "fields" : [ { 522 | "name" : "createNote", 523 | "description" : null, 524 | "args" : [ { 525 | "name" : "input", 526 | "description" : null, 527 | "type" : { 528 | "kind" : "NON_NULL", 529 | "name" : null, 530 | "ofType" : { 531 | "kind" : "INPUT_OBJECT", 532 | "name" : "CreateNoteInput", 533 | "ofType" : null 534 | } 535 | }, 536 | "defaultValue" : null 537 | } ], 538 | "type" : { 539 | "kind" : "OBJECT", 540 | "name" : "Note", 541 | "ofType" : null 542 | }, 543 | "isDeprecated" : false, 544 | "deprecationReason" : null 545 | }, { 546 | "name" : "updateNote", 547 | "description" : null, 548 | "args" : [ { 549 | "name" : "input", 550 | "description" : null, 551 | "type" : { 552 | "kind" : "NON_NULL", 553 | "name" : null, 554 | "ofType" : { 555 | "kind" : "INPUT_OBJECT", 556 | "name" : "UpdateNoteInput", 557 | "ofType" : null 558 | } 559 | }, 560 | "defaultValue" : null 561 | } ], 562 | "type" : { 563 | "kind" : "OBJECT", 564 | "name" : "Note", 565 | "ofType" : null 566 | }, 567 | "isDeprecated" : false, 568 | "deprecationReason" : null 569 | }, { 570 | "name" : "deleteNote", 571 | "description" : null, 572 | "args" : [ { 573 | "name" : "input", 574 | "description" : null, 575 | "type" : { 576 | "kind" : "NON_NULL", 577 | "name" : null, 578 | "ofType" : { 579 | "kind" : "INPUT_OBJECT", 580 | "name" : "DeleteNoteInput", 581 | "ofType" : null 582 | } 583 | }, 584 | "defaultValue" : null 585 | } ], 586 | "type" : { 587 | "kind" : "OBJECT", 588 | "name" : "Note", 589 | "ofType" : null 590 | }, 591 | "isDeprecated" : false, 592 | "deprecationReason" : null 593 | } ], 594 | "inputFields" : null, 595 | "interfaces" : [ ], 596 | "enumValues" : null, 597 | "possibleTypes" : null 598 | }, { 599 | "kind" : "INPUT_OBJECT", 600 | "name" : "CreateNoteInput", 601 | "description" : null, 602 | "fields" : null, 603 | "inputFields" : [ { 604 | "name" : "id", 605 | "description" : null, 606 | "type" : { 607 | "kind" : "SCALAR", 608 | "name" : "ID", 609 | "ofType" : null 610 | }, 611 | "defaultValue" : null 612 | }, { 613 | "name" : "title", 614 | "description" : null, 615 | "type" : { 616 | "kind" : "NON_NULL", 617 | "name" : null, 618 | "ofType" : { 619 | "kind" : "SCALAR", 620 | "name" : "String", 621 | "ofType" : null 622 | } 623 | }, 624 | "defaultValue" : null 625 | }, { 626 | "name" : "text", 627 | "description" : null, 628 | "type" : { 629 | "kind" : "NON_NULL", 630 | "name" : null, 631 | "ofType" : { 632 | "kind" : "SCALAR", 633 | "name" : "String", 634 | "ofType" : null 635 | } 636 | }, 637 | "defaultValue" : null 638 | }, { 639 | "name" : "createdAt", 640 | "description" : null, 641 | "type" : { 642 | "kind" : "SCALAR", 643 | "name" : "String", 644 | "ofType" : null 645 | }, 646 | "defaultValue" : null 647 | }, { 648 | "name" : "updatedAt", 649 | "description" : null, 650 | "type" : { 651 | "kind" : "SCALAR", 652 | "name" : "String", 653 | "ofType" : null 654 | }, 655 | "defaultValue" : null 656 | } ], 657 | "interfaces" : null, 658 | "enumValues" : null, 659 | "possibleTypes" : null 660 | }, { 661 | "kind" : "INPUT_OBJECT", 662 | "name" : "UpdateNoteInput", 663 | "description" : null, 664 | "fields" : null, 665 | "inputFields" : [ { 666 | "name" : "id", 667 | "description" : null, 668 | "type" : { 669 | "kind" : "NON_NULL", 670 | "name" : null, 671 | "ofType" : { 672 | "kind" : "SCALAR", 673 | "name" : "ID", 674 | "ofType" : null 675 | } 676 | }, 677 | "defaultValue" : null 678 | }, { 679 | "name" : "title", 680 | "description" : null, 681 | "type" : { 682 | "kind" : "SCALAR", 683 | "name" : "String", 684 | "ofType" : null 685 | }, 686 | "defaultValue" : null 687 | }, { 688 | "name" : "text", 689 | "description" : null, 690 | "type" : { 691 | "kind" : "SCALAR", 692 | "name" : "String", 693 | "ofType" : null 694 | }, 695 | "defaultValue" : null 696 | }, { 697 | "name" : "createdAt", 698 | "description" : null, 699 | "type" : { 700 | "kind" : "SCALAR", 701 | "name" : "String", 702 | "ofType" : null 703 | }, 704 | "defaultValue" : null 705 | }, { 706 | "name" : "updatedAt", 707 | "description" : null, 708 | "type" : { 709 | "kind" : "SCALAR", 710 | "name" : "String", 711 | "ofType" : null 712 | }, 713 | "defaultValue" : null 714 | } ], 715 | "interfaces" : null, 716 | "enumValues" : null, 717 | "possibleTypes" : null 718 | }, { 719 | "kind" : "INPUT_OBJECT", 720 | "name" : "DeleteNoteInput", 721 | "description" : null, 722 | "fields" : null, 723 | "inputFields" : [ { 724 | "name" : "id", 725 | "description" : null, 726 | "type" : { 727 | "kind" : "SCALAR", 728 | "name" : "ID", 729 | "ofType" : null 730 | }, 731 | "defaultValue" : null 732 | } ], 733 | "interfaces" : null, 734 | "enumValues" : null, 735 | "possibleTypes" : null 736 | }, { 737 | "kind" : "OBJECT", 738 | "name" : "Subscription", 739 | "description" : null, 740 | "fields" : [ { 741 | "name" : "onCreateNote", 742 | "description" : null, 743 | "args" : [ ], 744 | "type" : { 745 | "kind" : "OBJECT", 746 | "name" : "Note", 747 | "ofType" : null 748 | }, 749 | "isDeprecated" : false, 750 | "deprecationReason" : null 751 | }, { 752 | "name" : "onUpdateNote", 753 | "description" : null, 754 | "args" : [ ], 755 | "type" : { 756 | "kind" : "OBJECT", 757 | "name" : "Note", 758 | "ofType" : null 759 | }, 760 | "isDeprecated" : false, 761 | "deprecationReason" : null 762 | }, { 763 | "name" : "onDeleteNote", 764 | "description" : null, 765 | "args" : [ ], 766 | "type" : { 767 | "kind" : "OBJECT", 768 | "name" : "Note", 769 | "ofType" : null 770 | }, 771 | "isDeprecated" : false, 772 | "deprecationReason" : null 773 | } ], 774 | "inputFields" : null, 775 | "interfaces" : [ ], 776 | "enumValues" : null, 777 | "possibleTypes" : null 778 | }, { 779 | "kind" : "INPUT_OBJECT", 780 | "name" : "ModelFloatFilterInput", 781 | "description" : null, 782 | "fields" : null, 783 | "inputFields" : [ { 784 | "name" : "ne", 785 | "description" : null, 786 | "type" : { 787 | "kind" : "SCALAR", 788 | "name" : "Float", 789 | "ofType" : null 790 | }, 791 | "defaultValue" : null 792 | }, { 793 | "name" : "eq", 794 | "description" : null, 795 | "type" : { 796 | "kind" : "SCALAR", 797 | "name" : "Float", 798 | "ofType" : null 799 | }, 800 | "defaultValue" : null 801 | }, { 802 | "name" : "le", 803 | "description" : null, 804 | "type" : { 805 | "kind" : "SCALAR", 806 | "name" : "Float", 807 | "ofType" : null 808 | }, 809 | "defaultValue" : null 810 | }, { 811 | "name" : "lt", 812 | "description" : null, 813 | "type" : { 814 | "kind" : "SCALAR", 815 | "name" : "Float", 816 | "ofType" : null 817 | }, 818 | "defaultValue" : null 819 | }, { 820 | "name" : "ge", 821 | "description" : null, 822 | "type" : { 823 | "kind" : "SCALAR", 824 | "name" : "Float", 825 | "ofType" : null 826 | }, 827 | "defaultValue" : null 828 | }, { 829 | "name" : "gt", 830 | "description" : null, 831 | "type" : { 832 | "kind" : "SCALAR", 833 | "name" : "Float", 834 | "ofType" : null 835 | }, 836 | "defaultValue" : null 837 | }, { 838 | "name" : "contains", 839 | "description" : null, 840 | "type" : { 841 | "kind" : "SCALAR", 842 | "name" : "Float", 843 | "ofType" : null 844 | }, 845 | "defaultValue" : null 846 | }, { 847 | "name" : "notContains", 848 | "description" : null, 849 | "type" : { 850 | "kind" : "SCALAR", 851 | "name" : "Float", 852 | "ofType" : null 853 | }, 854 | "defaultValue" : null 855 | }, { 856 | "name" : "between", 857 | "description" : null, 858 | "type" : { 859 | "kind" : "LIST", 860 | "name" : null, 861 | "ofType" : { 862 | "kind" : "SCALAR", 863 | "name" : "Float", 864 | "ofType" : null 865 | } 866 | }, 867 | "defaultValue" : null 868 | } ], 869 | "interfaces" : null, 870 | "enumValues" : null, 871 | "possibleTypes" : null 872 | }, { 873 | "kind" : "SCALAR", 874 | "name" : "Float", 875 | "description" : "Built-in Float", 876 | "fields" : null, 877 | "inputFields" : null, 878 | "interfaces" : null, 879 | "enumValues" : null, 880 | "possibleTypes" : null 881 | }, { 882 | "kind" : "ENUM", 883 | "name" : "ModelSortDirection", 884 | "description" : null, 885 | "fields" : null, 886 | "inputFields" : null, 887 | "interfaces" : null, 888 | "enumValues" : [ { 889 | "name" : "ASC", 890 | "description" : null, 891 | "isDeprecated" : false, 892 | "deprecationReason" : null 893 | }, { 894 | "name" : "DESC", 895 | "description" : null, 896 | "isDeprecated" : false, 897 | "deprecationReason" : null 898 | } ], 899 | "possibleTypes" : null 900 | }, { 901 | "kind" : "INPUT_OBJECT", 902 | "name" : "ModelIntFilterInput", 903 | "description" : null, 904 | "fields" : null, 905 | "inputFields" : [ { 906 | "name" : "ne", 907 | "description" : null, 908 | "type" : { 909 | "kind" : "SCALAR", 910 | "name" : "Int", 911 | "ofType" : null 912 | }, 913 | "defaultValue" : null 914 | }, { 915 | "name" : "eq", 916 | "description" : null, 917 | "type" : { 918 | "kind" : "SCALAR", 919 | "name" : "Int", 920 | "ofType" : null 921 | }, 922 | "defaultValue" : null 923 | }, { 924 | "name" : "le", 925 | "description" : null, 926 | "type" : { 927 | "kind" : "SCALAR", 928 | "name" : "Int", 929 | "ofType" : null 930 | }, 931 | "defaultValue" : null 932 | }, { 933 | "name" : "lt", 934 | "description" : null, 935 | "type" : { 936 | "kind" : "SCALAR", 937 | "name" : "Int", 938 | "ofType" : null 939 | }, 940 | "defaultValue" : null 941 | }, { 942 | "name" : "ge", 943 | "description" : null, 944 | "type" : { 945 | "kind" : "SCALAR", 946 | "name" : "Int", 947 | "ofType" : null 948 | }, 949 | "defaultValue" : null 950 | }, { 951 | "name" : "gt", 952 | "description" : null, 953 | "type" : { 954 | "kind" : "SCALAR", 955 | "name" : "Int", 956 | "ofType" : null 957 | }, 958 | "defaultValue" : null 959 | }, { 960 | "name" : "contains", 961 | "description" : null, 962 | "type" : { 963 | "kind" : "SCALAR", 964 | "name" : "Int", 965 | "ofType" : null 966 | }, 967 | "defaultValue" : null 968 | }, { 969 | "name" : "notContains", 970 | "description" : null, 971 | "type" : { 972 | "kind" : "SCALAR", 973 | "name" : "Int", 974 | "ofType" : null 975 | }, 976 | "defaultValue" : null 977 | }, { 978 | "name" : "between", 979 | "description" : null, 980 | "type" : { 981 | "kind" : "LIST", 982 | "name" : null, 983 | "ofType" : { 984 | "kind" : "SCALAR", 985 | "name" : "Int", 986 | "ofType" : null 987 | } 988 | }, 989 | "defaultValue" : null 990 | } ], 991 | "interfaces" : null, 992 | "enumValues" : null, 993 | "possibleTypes" : null 994 | }, { 995 | "kind" : "INPUT_OBJECT", 996 | "name" : "ModelBooleanFilterInput", 997 | "description" : null, 998 | "fields" : null, 999 | "inputFields" : [ { 1000 | "name" : "ne", 1001 | "description" : null, 1002 | "type" : { 1003 | "kind" : "SCALAR", 1004 | "name" : "Boolean", 1005 | "ofType" : null 1006 | }, 1007 | "defaultValue" : null 1008 | }, { 1009 | "name" : "eq", 1010 | "description" : null, 1011 | "type" : { 1012 | "kind" : "SCALAR", 1013 | "name" : "Boolean", 1014 | "ofType" : null 1015 | }, 1016 | "defaultValue" : null 1017 | } ], 1018 | "interfaces" : null, 1019 | "enumValues" : null, 1020 | "possibleTypes" : null 1021 | }, { 1022 | "kind" : "SCALAR", 1023 | "name" : "Boolean", 1024 | "description" : "Built-in Boolean", 1025 | "fields" : null, 1026 | "inputFields" : null, 1027 | "interfaces" : null, 1028 | "enumValues" : null, 1029 | "possibleTypes" : null 1030 | }, { 1031 | "kind" : "OBJECT", 1032 | "name" : "__Schema", 1033 | "description" : "A GraphQL Introspection defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, the entry points for query, mutation, and subscription operations.", 1034 | "fields" : [ { 1035 | "name" : "types", 1036 | "description" : "A list of all types supported by this server.", 1037 | "args" : [ ], 1038 | "type" : { 1039 | "kind" : "NON_NULL", 1040 | "name" : null, 1041 | "ofType" : { 1042 | "kind" : "LIST", 1043 | "name" : null, 1044 | "ofType" : { 1045 | "kind" : "NON_NULL", 1046 | "name" : null, 1047 | "ofType" : { 1048 | "kind" : "OBJECT", 1049 | "name" : "__Type", 1050 | "ofType" : null 1051 | } 1052 | } 1053 | } 1054 | }, 1055 | "isDeprecated" : false, 1056 | "deprecationReason" : null 1057 | }, { 1058 | "name" : "queryType", 1059 | "description" : "The type that query operations will be rooted at.", 1060 | "args" : [ ], 1061 | "type" : { 1062 | "kind" : "NON_NULL", 1063 | "name" : null, 1064 | "ofType" : { 1065 | "kind" : "OBJECT", 1066 | "name" : "__Type", 1067 | "ofType" : null 1068 | } 1069 | }, 1070 | "isDeprecated" : false, 1071 | "deprecationReason" : null 1072 | }, { 1073 | "name" : "mutationType", 1074 | "description" : "If this server supports mutation, the type that mutation operations will be rooted at.", 1075 | "args" : [ ], 1076 | "type" : { 1077 | "kind" : "OBJECT", 1078 | "name" : "__Type", 1079 | "ofType" : null 1080 | }, 1081 | "isDeprecated" : false, 1082 | "deprecationReason" : null 1083 | }, { 1084 | "name" : "directives", 1085 | "description" : "'A list of all directives supported by this server.", 1086 | "args" : [ ], 1087 | "type" : { 1088 | "kind" : "NON_NULL", 1089 | "name" : null, 1090 | "ofType" : { 1091 | "kind" : "LIST", 1092 | "name" : null, 1093 | "ofType" : { 1094 | "kind" : "NON_NULL", 1095 | "name" : null, 1096 | "ofType" : { 1097 | "kind" : "OBJECT", 1098 | "name" : "__Directive", 1099 | "ofType" : null 1100 | } 1101 | } 1102 | } 1103 | }, 1104 | "isDeprecated" : false, 1105 | "deprecationReason" : null 1106 | }, { 1107 | "name" : "subscriptionType", 1108 | "description" : "'If this server support subscription, the type that subscription operations will be rooted at.", 1109 | "args" : [ ], 1110 | "type" : { 1111 | "kind" : "OBJECT", 1112 | "name" : "__Type", 1113 | "ofType" : null 1114 | }, 1115 | "isDeprecated" : false, 1116 | "deprecationReason" : null 1117 | } ], 1118 | "inputFields" : null, 1119 | "interfaces" : [ ], 1120 | "enumValues" : null, 1121 | "possibleTypes" : null 1122 | }, { 1123 | "kind" : "OBJECT", 1124 | "name" : "__Type", 1125 | "description" : null, 1126 | "fields" : [ { 1127 | "name" : "kind", 1128 | "description" : null, 1129 | "args" : [ ], 1130 | "type" : { 1131 | "kind" : "NON_NULL", 1132 | "name" : null, 1133 | "ofType" : { 1134 | "kind" : "ENUM", 1135 | "name" : "__TypeKind", 1136 | "ofType" : null 1137 | } 1138 | }, 1139 | "isDeprecated" : false, 1140 | "deprecationReason" : null 1141 | }, { 1142 | "name" : "name", 1143 | "description" : null, 1144 | "args" : [ ], 1145 | "type" : { 1146 | "kind" : "SCALAR", 1147 | "name" : "String", 1148 | "ofType" : null 1149 | }, 1150 | "isDeprecated" : false, 1151 | "deprecationReason" : null 1152 | }, { 1153 | "name" : "description", 1154 | "description" : null, 1155 | "args" : [ ], 1156 | "type" : { 1157 | "kind" : "SCALAR", 1158 | "name" : "String", 1159 | "ofType" : null 1160 | }, 1161 | "isDeprecated" : false, 1162 | "deprecationReason" : null 1163 | }, { 1164 | "name" : "fields", 1165 | "description" : null, 1166 | "args" : [ { 1167 | "name" : "includeDeprecated", 1168 | "description" : null, 1169 | "type" : { 1170 | "kind" : "SCALAR", 1171 | "name" : "Boolean", 1172 | "ofType" : null 1173 | }, 1174 | "defaultValue" : "false" 1175 | } ], 1176 | "type" : { 1177 | "kind" : "LIST", 1178 | "name" : null, 1179 | "ofType" : { 1180 | "kind" : "NON_NULL", 1181 | "name" : null, 1182 | "ofType" : { 1183 | "kind" : "OBJECT", 1184 | "name" : "__Field", 1185 | "ofType" : null 1186 | } 1187 | } 1188 | }, 1189 | "isDeprecated" : false, 1190 | "deprecationReason" : null 1191 | }, { 1192 | "name" : "interfaces", 1193 | "description" : null, 1194 | "args" : [ ], 1195 | "type" : { 1196 | "kind" : "LIST", 1197 | "name" : null, 1198 | "ofType" : { 1199 | "kind" : "NON_NULL", 1200 | "name" : null, 1201 | "ofType" : { 1202 | "kind" : "OBJECT", 1203 | "name" : "__Type", 1204 | "ofType" : null 1205 | } 1206 | } 1207 | }, 1208 | "isDeprecated" : false, 1209 | "deprecationReason" : null 1210 | }, { 1211 | "name" : "possibleTypes", 1212 | "description" : null, 1213 | "args" : [ ], 1214 | "type" : { 1215 | "kind" : "LIST", 1216 | "name" : null, 1217 | "ofType" : { 1218 | "kind" : "NON_NULL", 1219 | "name" : null, 1220 | "ofType" : { 1221 | "kind" : "OBJECT", 1222 | "name" : "__Type", 1223 | "ofType" : null 1224 | } 1225 | } 1226 | }, 1227 | "isDeprecated" : false, 1228 | "deprecationReason" : null 1229 | }, { 1230 | "name" : "enumValues", 1231 | "description" : null, 1232 | "args" : [ { 1233 | "name" : "includeDeprecated", 1234 | "description" : null, 1235 | "type" : { 1236 | "kind" : "SCALAR", 1237 | "name" : "Boolean", 1238 | "ofType" : null 1239 | }, 1240 | "defaultValue" : "false" 1241 | } ], 1242 | "type" : { 1243 | "kind" : "LIST", 1244 | "name" : null, 1245 | "ofType" : { 1246 | "kind" : "NON_NULL", 1247 | "name" : null, 1248 | "ofType" : { 1249 | "kind" : "OBJECT", 1250 | "name" : "__EnumValue", 1251 | "ofType" : null 1252 | } 1253 | } 1254 | }, 1255 | "isDeprecated" : false, 1256 | "deprecationReason" : null 1257 | }, { 1258 | "name" : "inputFields", 1259 | "description" : null, 1260 | "args" : [ ], 1261 | "type" : { 1262 | "kind" : "LIST", 1263 | "name" : null, 1264 | "ofType" : { 1265 | "kind" : "NON_NULL", 1266 | "name" : null, 1267 | "ofType" : { 1268 | "kind" : "OBJECT", 1269 | "name" : "__InputValue", 1270 | "ofType" : null 1271 | } 1272 | } 1273 | }, 1274 | "isDeprecated" : false, 1275 | "deprecationReason" : null 1276 | }, { 1277 | "name" : "ofType", 1278 | "description" : null, 1279 | "args" : [ ], 1280 | "type" : { 1281 | "kind" : "OBJECT", 1282 | "name" : "__Type", 1283 | "ofType" : null 1284 | }, 1285 | "isDeprecated" : false, 1286 | "deprecationReason" : null 1287 | } ], 1288 | "inputFields" : null, 1289 | "interfaces" : [ ], 1290 | "enumValues" : null, 1291 | "possibleTypes" : null 1292 | }, { 1293 | "kind" : "ENUM", 1294 | "name" : "__TypeKind", 1295 | "description" : "An enum describing what kind of type a given __Type is", 1296 | "fields" : null, 1297 | "inputFields" : null, 1298 | "interfaces" : null, 1299 | "enumValues" : [ { 1300 | "name" : "SCALAR", 1301 | "description" : "Indicates this type is a scalar.", 1302 | "isDeprecated" : false, 1303 | "deprecationReason" : null 1304 | }, { 1305 | "name" : "OBJECT", 1306 | "description" : "Indicates this type is an object. `fields` and `interfaces` are valid fields.", 1307 | "isDeprecated" : false, 1308 | "deprecationReason" : null 1309 | }, { 1310 | "name" : "INTERFACE", 1311 | "description" : "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", 1312 | "isDeprecated" : false, 1313 | "deprecationReason" : null 1314 | }, { 1315 | "name" : "UNION", 1316 | "description" : "Indicates this type is a union. `possibleTypes` is a valid field.", 1317 | "isDeprecated" : false, 1318 | "deprecationReason" : null 1319 | }, { 1320 | "name" : "ENUM", 1321 | "description" : "Indicates this type is an enum. `enumValues` is a valid field.", 1322 | "isDeprecated" : false, 1323 | "deprecationReason" : null 1324 | }, { 1325 | "name" : "INPUT_OBJECT", 1326 | "description" : "Indicates this type is an input object. `inputFields` is a valid field.", 1327 | "isDeprecated" : false, 1328 | "deprecationReason" : null 1329 | }, { 1330 | "name" : "LIST", 1331 | "description" : "Indicates this type is a list. `ofType` is a valid field.", 1332 | "isDeprecated" : false, 1333 | "deprecationReason" : null 1334 | }, { 1335 | "name" : "NON_NULL", 1336 | "description" : "Indicates this type is a non-null. `ofType` is a valid field.", 1337 | "isDeprecated" : false, 1338 | "deprecationReason" : null 1339 | } ], 1340 | "possibleTypes" : null 1341 | }, { 1342 | "kind" : "OBJECT", 1343 | "name" : "__Field", 1344 | "description" : null, 1345 | "fields" : [ { 1346 | "name" : "name", 1347 | "description" : null, 1348 | "args" : [ ], 1349 | "type" : { 1350 | "kind" : "NON_NULL", 1351 | "name" : null, 1352 | "ofType" : { 1353 | "kind" : "SCALAR", 1354 | "name" : "String", 1355 | "ofType" : null 1356 | } 1357 | }, 1358 | "isDeprecated" : false, 1359 | "deprecationReason" : null 1360 | }, { 1361 | "name" : "description", 1362 | "description" : null, 1363 | "args" : [ ], 1364 | "type" : { 1365 | "kind" : "SCALAR", 1366 | "name" : "String", 1367 | "ofType" : null 1368 | }, 1369 | "isDeprecated" : false, 1370 | "deprecationReason" : null 1371 | }, { 1372 | "name" : "args", 1373 | "description" : null, 1374 | "args" : [ ], 1375 | "type" : { 1376 | "kind" : "NON_NULL", 1377 | "name" : null, 1378 | "ofType" : { 1379 | "kind" : "LIST", 1380 | "name" : null, 1381 | "ofType" : { 1382 | "kind" : "NON_NULL", 1383 | "name" : null, 1384 | "ofType" : { 1385 | "kind" : "OBJECT", 1386 | "name" : "__InputValue", 1387 | "ofType" : null 1388 | } 1389 | } 1390 | } 1391 | }, 1392 | "isDeprecated" : false, 1393 | "deprecationReason" : null 1394 | }, { 1395 | "name" : "type", 1396 | "description" : null, 1397 | "args" : [ ], 1398 | "type" : { 1399 | "kind" : "NON_NULL", 1400 | "name" : null, 1401 | "ofType" : { 1402 | "kind" : "OBJECT", 1403 | "name" : "__Type", 1404 | "ofType" : null 1405 | } 1406 | }, 1407 | "isDeprecated" : false, 1408 | "deprecationReason" : null 1409 | }, { 1410 | "name" : "isDeprecated", 1411 | "description" : null, 1412 | "args" : [ ], 1413 | "type" : { 1414 | "kind" : "NON_NULL", 1415 | "name" : null, 1416 | "ofType" : { 1417 | "kind" : "SCALAR", 1418 | "name" : "Boolean", 1419 | "ofType" : null 1420 | } 1421 | }, 1422 | "isDeprecated" : false, 1423 | "deprecationReason" : null 1424 | }, { 1425 | "name" : "deprecationReason", 1426 | "description" : null, 1427 | "args" : [ ], 1428 | "type" : { 1429 | "kind" : "SCALAR", 1430 | "name" : "String", 1431 | "ofType" : null 1432 | }, 1433 | "isDeprecated" : false, 1434 | "deprecationReason" : null 1435 | } ], 1436 | "inputFields" : null, 1437 | "interfaces" : [ ], 1438 | "enumValues" : null, 1439 | "possibleTypes" : null 1440 | }, { 1441 | "kind" : "OBJECT", 1442 | "name" : "__InputValue", 1443 | "description" : null, 1444 | "fields" : [ { 1445 | "name" : "name", 1446 | "description" : null, 1447 | "args" : [ ], 1448 | "type" : { 1449 | "kind" : "NON_NULL", 1450 | "name" : null, 1451 | "ofType" : { 1452 | "kind" : "SCALAR", 1453 | "name" : "String", 1454 | "ofType" : null 1455 | } 1456 | }, 1457 | "isDeprecated" : false, 1458 | "deprecationReason" : null 1459 | }, { 1460 | "name" : "description", 1461 | "description" : null, 1462 | "args" : [ ], 1463 | "type" : { 1464 | "kind" : "SCALAR", 1465 | "name" : "String", 1466 | "ofType" : null 1467 | }, 1468 | "isDeprecated" : false, 1469 | "deprecationReason" : null 1470 | }, { 1471 | "name" : "type", 1472 | "description" : null, 1473 | "args" : [ ], 1474 | "type" : { 1475 | "kind" : "NON_NULL", 1476 | "name" : null, 1477 | "ofType" : { 1478 | "kind" : "OBJECT", 1479 | "name" : "__Type", 1480 | "ofType" : null 1481 | } 1482 | }, 1483 | "isDeprecated" : false, 1484 | "deprecationReason" : null 1485 | }, { 1486 | "name" : "defaultValue", 1487 | "description" : null, 1488 | "args" : [ ], 1489 | "type" : { 1490 | "kind" : "SCALAR", 1491 | "name" : "String", 1492 | "ofType" : null 1493 | }, 1494 | "isDeprecated" : false, 1495 | "deprecationReason" : null 1496 | } ], 1497 | "inputFields" : null, 1498 | "interfaces" : [ ], 1499 | "enumValues" : null, 1500 | "possibleTypes" : null 1501 | }, { 1502 | "kind" : "OBJECT", 1503 | "name" : "__EnumValue", 1504 | "description" : null, 1505 | "fields" : [ { 1506 | "name" : "name", 1507 | "description" : null, 1508 | "args" : [ ], 1509 | "type" : { 1510 | "kind" : "NON_NULL", 1511 | "name" : null, 1512 | "ofType" : { 1513 | "kind" : "SCALAR", 1514 | "name" : "String", 1515 | "ofType" : null 1516 | } 1517 | }, 1518 | "isDeprecated" : false, 1519 | "deprecationReason" : null 1520 | }, { 1521 | "name" : "description", 1522 | "description" : null, 1523 | "args" : [ ], 1524 | "type" : { 1525 | "kind" : "SCALAR", 1526 | "name" : "String", 1527 | "ofType" : null 1528 | }, 1529 | "isDeprecated" : false, 1530 | "deprecationReason" : null 1531 | }, { 1532 | "name" : "isDeprecated", 1533 | "description" : null, 1534 | "args" : [ ], 1535 | "type" : { 1536 | "kind" : "NON_NULL", 1537 | "name" : null, 1538 | "ofType" : { 1539 | "kind" : "SCALAR", 1540 | "name" : "Boolean", 1541 | "ofType" : null 1542 | } 1543 | }, 1544 | "isDeprecated" : false, 1545 | "deprecationReason" : null 1546 | }, { 1547 | "name" : "deprecationReason", 1548 | "description" : null, 1549 | "args" : [ ], 1550 | "type" : { 1551 | "kind" : "SCALAR", 1552 | "name" : "String", 1553 | "ofType" : null 1554 | }, 1555 | "isDeprecated" : false, 1556 | "deprecationReason" : null 1557 | } ], 1558 | "inputFields" : null, 1559 | "interfaces" : [ ], 1560 | "enumValues" : null, 1561 | "possibleTypes" : null 1562 | }, { 1563 | "kind" : "OBJECT", 1564 | "name" : "__Directive", 1565 | "description" : null, 1566 | "fields" : [ { 1567 | "name" : "name", 1568 | "description" : null, 1569 | "args" : [ ], 1570 | "type" : { 1571 | "kind" : "SCALAR", 1572 | "name" : "String", 1573 | "ofType" : null 1574 | }, 1575 | "isDeprecated" : false, 1576 | "deprecationReason" : null 1577 | }, { 1578 | "name" : "description", 1579 | "description" : null, 1580 | "args" : [ ], 1581 | "type" : { 1582 | "kind" : "SCALAR", 1583 | "name" : "String", 1584 | "ofType" : null 1585 | }, 1586 | "isDeprecated" : false, 1587 | "deprecationReason" : null 1588 | }, { 1589 | "name" : "locations", 1590 | "description" : null, 1591 | "args" : [ ], 1592 | "type" : { 1593 | "kind" : "LIST", 1594 | "name" : null, 1595 | "ofType" : { 1596 | "kind" : "NON_NULL", 1597 | "name" : null, 1598 | "ofType" : { 1599 | "kind" : "ENUM", 1600 | "name" : "__DirectiveLocation", 1601 | "ofType" : null 1602 | } 1603 | } 1604 | }, 1605 | "isDeprecated" : false, 1606 | "deprecationReason" : null 1607 | }, { 1608 | "name" : "args", 1609 | "description" : null, 1610 | "args" : [ ], 1611 | "type" : { 1612 | "kind" : "NON_NULL", 1613 | "name" : null, 1614 | "ofType" : { 1615 | "kind" : "LIST", 1616 | "name" : null, 1617 | "ofType" : { 1618 | "kind" : "NON_NULL", 1619 | "name" : null, 1620 | "ofType" : { 1621 | "kind" : "OBJECT", 1622 | "name" : "__InputValue", 1623 | "ofType" : null 1624 | } 1625 | } 1626 | } 1627 | }, 1628 | "isDeprecated" : false, 1629 | "deprecationReason" : null 1630 | }, { 1631 | "name" : "onOperation", 1632 | "description" : null, 1633 | "args" : [ ], 1634 | "type" : { 1635 | "kind" : "SCALAR", 1636 | "name" : "Boolean", 1637 | "ofType" : null 1638 | }, 1639 | "isDeprecated" : true, 1640 | "deprecationReason" : "Use `locations`." 1641 | }, { 1642 | "name" : "onFragment", 1643 | "description" : null, 1644 | "args" : [ ], 1645 | "type" : { 1646 | "kind" : "SCALAR", 1647 | "name" : "Boolean", 1648 | "ofType" : null 1649 | }, 1650 | "isDeprecated" : true, 1651 | "deprecationReason" : "Use `locations`." 1652 | }, { 1653 | "name" : "onField", 1654 | "description" : null, 1655 | "args" : [ ], 1656 | "type" : { 1657 | "kind" : "SCALAR", 1658 | "name" : "Boolean", 1659 | "ofType" : null 1660 | }, 1661 | "isDeprecated" : true, 1662 | "deprecationReason" : "Use `locations`." 1663 | } ], 1664 | "inputFields" : null, 1665 | "interfaces" : [ ], 1666 | "enumValues" : null, 1667 | "possibleTypes" : null 1668 | }, { 1669 | "kind" : "ENUM", 1670 | "name" : "__DirectiveLocation", 1671 | "description" : "An enum describing valid locations where a directive can be placed", 1672 | "fields" : null, 1673 | "inputFields" : null, 1674 | "interfaces" : null, 1675 | "enumValues" : [ { 1676 | "name" : "QUERY", 1677 | "description" : "Indicates the directive is valid on queries.", 1678 | "isDeprecated" : false, 1679 | "deprecationReason" : null 1680 | }, { 1681 | "name" : "MUTATION", 1682 | "description" : "Indicates the directive is valid on mutations.", 1683 | "isDeprecated" : false, 1684 | "deprecationReason" : null 1685 | }, { 1686 | "name" : "FIELD", 1687 | "description" : "Indicates the directive is valid on fields.", 1688 | "isDeprecated" : false, 1689 | "deprecationReason" : null 1690 | }, { 1691 | "name" : "FRAGMENT_DEFINITION", 1692 | "description" : "Indicates the directive is valid on fragment definitions.", 1693 | "isDeprecated" : false, 1694 | "deprecationReason" : null 1695 | }, { 1696 | "name" : "FRAGMENT_SPREAD", 1697 | "description" : "Indicates the directive is valid on fragment spreads.", 1698 | "isDeprecated" : false, 1699 | "deprecationReason" : null 1700 | }, { 1701 | "name" : "INLINE_FRAGMENT", 1702 | "description" : "Indicates the directive is valid on inline fragments.", 1703 | "isDeprecated" : false, 1704 | "deprecationReason" : null 1705 | }, { 1706 | "name" : "SCHEMA", 1707 | "description" : "Indicates the directive is valid on a schema SDL definition.", 1708 | "isDeprecated" : false, 1709 | "deprecationReason" : null 1710 | }, { 1711 | "name" : "SCALAR", 1712 | "description" : "Indicates the directive is valid on a scalar SDL definition.", 1713 | "isDeprecated" : false, 1714 | "deprecationReason" : null 1715 | }, { 1716 | "name" : "OBJECT", 1717 | "description" : "Indicates the directive is valid on an object SDL definition.", 1718 | "isDeprecated" : false, 1719 | "deprecationReason" : null 1720 | }, { 1721 | "name" : "FIELD_DEFINITION", 1722 | "description" : "Indicates the directive is valid on a field SDL definition.", 1723 | "isDeprecated" : false, 1724 | "deprecationReason" : null 1725 | }, { 1726 | "name" : "ARGUMENT_DEFINITION", 1727 | "description" : "Indicates the directive is valid on a field argument SDL definition.", 1728 | "isDeprecated" : false, 1729 | "deprecationReason" : null 1730 | }, { 1731 | "name" : "INTERFACE", 1732 | "description" : "Indicates the directive is valid on an interface SDL definition.", 1733 | "isDeprecated" : false, 1734 | "deprecationReason" : null 1735 | }, { 1736 | "name" : "UNION", 1737 | "description" : "Indicates the directive is valid on an union SDL definition.", 1738 | "isDeprecated" : false, 1739 | "deprecationReason" : null 1740 | }, { 1741 | "name" : "ENUM", 1742 | "description" : "Indicates the directive is valid on an enum SDL definition.", 1743 | "isDeprecated" : false, 1744 | "deprecationReason" : null 1745 | }, { 1746 | "name" : "ENUM_VALUE", 1747 | "description" : "Indicates the directive is valid on an enum value SDL definition.", 1748 | "isDeprecated" : false, 1749 | "deprecationReason" : null 1750 | }, { 1751 | "name" : "INPUT_OBJECT", 1752 | "description" : "Indicates the directive is valid on an input object SDL definition.", 1753 | "isDeprecated" : false, 1754 | "deprecationReason" : null 1755 | }, { 1756 | "name" : "INPUT_FIELD_DEFINITION", 1757 | "description" : "Indicates the directive is valid on an input object field SDL definition.", 1758 | "isDeprecated" : false, 1759 | "deprecationReason" : null 1760 | } ], 1761 | "possibleTypes" : null 1762 | } ], 1763 | "directives" : [ { 1764 | "name" : "include", 1765 | "description" : "Directs the executor to include this field or fragment only when the `if` argument is true", 1766 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 1767 | "args" : [ { 1768 | "name" : "if", 1769 | "description" : "Included when true.", 1770 | "type" : { 1771 | "kind" : "NON_NULL", 1772 | "name" : null, 1773 | "ofType" : { 1774 | "kind" : "SCALAR", 1775 | "name" : "Boolean", 1776 | "ofType" : null 1777 | } 1778 | }, 1779 | "defaultValue" : null 1780 | } ], 1781 | "onOperation" : false, 1782 | "onFragment" : true, 1783 | "onField" : true 1784 | }, { 1785 | "name" : "skip", 1786 | "description" : "Directs the executor to skip this field or fragment when the `if`'argument is true.", 1787 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 1788 | "args" : [ { 1789 | "name" : "if", 1790 | "description" : "Skipped when true.", 1791 | "type" : { 1792 | "kind" : "NON_NULL", 1793 | "name" : null, 1794 | "ofType" : { 1795 | "kind" : "SCALAR", 1796 | "name" : "Boolean", 1797 | "ofType" : null 1798 | } 1799 | }, 1800 | "defaultValue" : null 1801 | } ], 1802 | "onOperation" : false, 1803 | "onFragment" : true, 1804 | "onField" : true 1805 | }, { 1806 | "name" : "defer", 1807 | "description" : "This directive allows results to be deferred during execution", 1808 | "locations" : [ "FIELD" ], 1809 | "args" : [ ], 1810 | "onOperation" : false, 1811 | "onFragment" : false, 1812 | "onField" : true 1813 | }, { 1814 | "name" : "aws_publish", 1815 | "description" : "Tells the service which subscriptions will be published to when this mutation is called. This directive is deprecated use @aws_susbscribe directive instead.", 1816 | "locations" : [ "FIELD_DEFINITION" ], 1817 | "args" : [ { 1818 | "name" : "subscriptions", 1819 | "description" : "List of subscriptions which will be published to when this mutation is called.", 1820 | "type" : { 1821 | "kind" : "LIST", 1822 | "name" : null, 1823 | "ofType" : { 1824 | "kind" : "SCALAR", 1825 | "name" : "String", 1826 | "ofType" : null 1827 | } 1828 | }, 1829 | "defaultValue" : null 1830 | } ], 1831 | "onOperation" : false, 1832 | "onFragment" : false, 1833 | "onField" : false 1834 | }, { 1835 | "name" : "aws_api_key", 1836 | "description" : "Tells the service this field/object has access authorized by an API key.", 1837 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 1838 | "args" : [ ], 1839 | "onOperation" : false, 1840 | "onFragment" : false, 1841 | "onField" : false 1842 | }, { 1843 | "name" : "aws_auth", 1844 | "description" : "Directs the schema to enforce authorization on a field", 1845 | "locations" : [ "FIELD_DEFINITION" ], 1846 | "args" : [ { 1847 | "name" : "cognito_groups", 1848 | "description" : "List of cognito user pool groups which have access on this field", 1849 | "type" : { 1850 | "kind" : "LIST", 1851 | "name" : null, 1852 | "ofType" : { 1853 | "kind" : "SCALAR", 1854 | "name" : "String", 1855 | "ofType" : null 1856 | } 1857 | }, 1858 | "defaultValue" : null 1859 | } ], 1860 | "onOperation" : false, 1861 | "onFragment" : false, 1862 | "onField" : false 1863 | }, { 1864 | "name" : "aws_iam", 1865 | "description" : "Tells the service this field/object has access authorized by sigv4 signing.", 1866 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 1867 | "args" : [ ], 1868 | "onOperation" : false, 1869 | "onFragment" : false, 1870 | "onField" : false 1871 | }, { 1872 | "name" : "aws_subscribe", 1873 | "description" : "Tells the service which mutation triggers this subscription.", 1874 | "locations" : [ "FIELD_DEFINITION" ], 1875 | "args" : [ { 1876 | "name" : "mutations", 1877 | "description" : "List of mutations which will trigger this subscription when they are called.", 1878 | "type" : { 1879 | "kind" : "LIST", 1880 | "name" : null, 1881 | "ofType" : { 1882 | "kind" : "SCALAR", 1883 | "name" : "String", 1884 | "ofType" : null 1885 | } 1886 | }, 1887 | "defaultValue" : null 1888 | } ], 1889 | "onOperation" : false, 1890 | "onFragment" : false, 1891 | "onField" : false 1892 | }, { 1893 | "name" : "deprecated", 1894 | "description" : null, 1895 | "locations" : [ "FIELD_DEFINITION", "ENUM_VALUE" ], 1896 | "args" : [ { 1897 | "name" : "reason", 1898 | "description" : null, 1899 | "type" : { 1900 | "kind" : "SCALAR", 1901 | "name" : "String", 1902 | "ofType" : null 1903 | }, 1904 | "defaultValue" : "\"No longer supported\"" 1905 | } ], 1906 | "onOperation" : false, 1907 | "onFragment" : false, 1908 | "onField" : false 1909 | }, { 1910 | "name" : "aws_cognito_user_pools", 1911 | "description" : "Tells the service this field/object has access authorized by a Cognito User Pools token.", 1912 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 1913 | "args" : [ { 1914 | "name" : "cognito_groups", 1915 | "description" : "List of cognito user pool groups which have access on this field", 1916 | "type" : { 1917 | "kind" : "LIST", 1918 | "name" : null, 1919 | "ofType" : { 1920 | "kind" : "SCALAR", 1921 | "name" : "String", 1922 | "ofType" : null 1923 | } 1924 | }, 1925 | "defaultValue" : null 1926 | } ], 1927 | "onOperation" : false, 1928 | "onFragment" : false, 1929 | "onField" : false 1930 | }, { 1931 | "name" : "aws_oidc", 1932 | "description" : "Tells the service this field/object has access authorized by an OIDC token.", 1933 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 1934 | "args" : [ ], 1935 | "onOperation" : false, 1936 | "onFragment" : false, 1937 | "onField" : false 1938 | } ] 1939 | } 1940 | } 1941 | } -------------------------------------------------------------------------------- /src/graphql/subscriptions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const onCreateNote = `subscription OnCreateNote { 5 | onCreateNote { 6 | id 7 | title 8 | text 9 | createdAt 10 | updatedAt 11 | } 12 | } 13 | `; 14 | export const onUpdateNote = `subscription OnUpdateNote { 15 | onUpdateNote { 16 | id 17 | title 18 | text 19 | createdAt 20 | updatedAt 21 | } 22 | } 23 | `; 24 | export const onDeleteNote = `subscription OnDeleteNote { 25 | onDeleteNote { 26 | id 27 | title 28 | text 29 | createdAt 30 | updatedAt 31 | } 32 | } 33 | `; 34 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f4f9f4; 3 | font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; 4 | min-height: 100vh; 5 | margin: 0; 6 | } 7 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Amplify from "aws-amplify"; 4 | import { AmazonAIPredictionsProvider } from "@aws-amplify/predictions"; 5 | 6 | import App from "./App"; 7 | import * as serviceWorker from "./serviceWorker"; 8 | import "normalize.css/normalize.css"; 9 | import "./index.css"; 10 | import "@reach/tabs/styles.css"; 11 | import "@reach/dialog/styles.css"; 12 | import amplifyConfig from "./aws-exports"; 13 | 14 | Amplify.configure(amplifyConfig); 15 | Amplify.addPluggable(new AmazonAIPredictionsProvider()); 16 | 17 | ReactDOM.render(, document.getElementById("root")); 18 | 19 | // If you want your app to work offline and load faster, you can change 20 | // unregister() to register() below. Note this comes with some pitfalls. 21 | // Learn more about service workers: https://bit.ly/CRA-PWA 22 | serviceWorker.unregister(); 23 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | --------------------------------------------------------------------------------