├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LAB1.md ├── LAB2.md ├── LAB3.md ├── LAB4.md ├── LAB5.MD ├── LICENSE ├── README.md ├── amplify.yml ├── amplify ├── .config │ └── project-config.json └── backend │ ├── api │ └── teamtasks │ │ ├── parameters.json │ │ ├── schema.graphql │ │ └── stacks │ │ └── CustomResources.json │ ├── auth │ └── teamtasksf9538190 │ │ ├── parameters.json │ │ └── teamtasksf9538190-cloudformation-template.yml │ ├── backend-config.json │ ├── function │ └── teamtasksf9538190PreSignup │ │ ├── function-parameters.json │ │ ├── parameters.json │ │ ├── src │ │ ├── email-filter-whitelist.js │ │ ├── event.json │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ │ └── teamtasksf9538190PreSignup-cloudformation-template.json │ └── hosting │ └── S3AndCloudFront │ ├── parameters.json │ └── template.json ├── angular.json ├── browserslist ├── customer.json ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── karma.conf.js ├── mandatorycomments.json ├── package.json ├── reminder.json ├── src ├── app │ ├── API.service.ts │ ├── app-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── auth │ │ ├── auth.component.css │ │ ├── auth.component.html │ │ ├── auth.component.spec.ts │ │ └── auth.component.ts │ ├── dashboard │ │ ├── dashboard.component.css │ │ ├── dashboard.component.html │ │ ├── dashboard.component.spec.ts │ │ └── dashboard.component.ts │ ├── goals │ │ ├── goals.component.css │ │ ├── goals.component.html │ │ ├── goals.component.spec.ts │ │ └── goals.component.ts │ ├── momentpipe.ts │ ├── monthlytasks │ │ ├── monthlytasks.component.css │ │ ├── monthlytasks.component.html │ │ ├── monthlytasks.component.spec.ts │ │ └── monthlytasks.component.ts │ ├── overview │ │ ├── overview.component.css │ │ ├── overview.component.html │ │ ├── overview.component.spec.ts │ │ └── overview.component.ts │ └── weeklytasks │ │ ├── weeklytasks.component.css │ │ ├── weeklytasks.component.html │ │ ├── weeklytasks.component.spec.ts │ │ └── weeklytasks.component.ts ├── assets │ └── .gitkeep ├── aws-exports.ts ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── graphql │ ├── mutations.graphql │ ├── mutations.ts │ ├── queries.graphql │ ├── queries.ts │ ├── schema.json │ ├── subscriptions.graphql │ └── subscriptions.ts ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css └── test.ts ├── tasks.json ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /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 | -------------------------------------------------------------------------------- /LAB1.md: -------------------------------------------------------------------------------- 1 | # 1. LAB1 : Creating Angular project 2 | 3 | create a new Angular project using command and enable routing capabilities 4 | 5 | ``` 6 | ng new teamtasks --routing 7 | ``` 8 | 9 | 10 | Change directory to the project and install bootstrap css library 11 | 12 | ``` 13 | cd teamtasks 14 | npm install bootstrap --save 15 | ``` 16 | 17 | 18 | Add style in angular.json file. The styles bloc should look like below 19 | 20 | 21 | ``` 22 | 23 | "styles": [` 24 | "src/styles.css", 25 | "node_modules/bootstrap/dist/css/bootstrap.min.css" 26 | `], 27 | 28 | ``` 29 | 30 | 31 | 32 | Create angular components 33 | 34 | ``` 35 | ng g c auth 36 | ng g c weeklytasks 37 | ng g c monthlytasks 38 | ng g c goals 39 | ng g c dashboard 40 | ng g c overview 41 | ``` 42 | 43 | * Auth - Will be used to render amplify authenticator 44 | * weeklytasks - Will display tasks which will be created every week. Associated for every customer/group 45 | * monthlytasks - Will display tasks which will be created every month. Associated for every customer/group 46 | * goals - Will display yearly tasks or goals. These are tasks which are not associated with customer/group 47 | * dashboard - Will display dashboard or landing page after login 48 | * overview - Will display the current status of the tasks 49 | 50 | 51 | Now update app-routing-module.ts so as to navigate between angular components 52 | 53 | 54 | ``` 55 | import { NgModule } from '@angular/core'; 56 | import { Routes, RouterModule } from '@angular/router'; 57 | import { AuthComponent } from './auth/auth.component'; 58 | import { WeeklytasksComponent } from './weeklytasks/weeklytasks.component'; 59 | import { DashboardComponent } from './dashboard/dashboard.component'; 60 | import { MonthlytasksComponent } from './monthlytasks/monthlytasks.component'; 61 | import { GoalsComponent } from './goals/goals.component'; 62 | import { OverviewComponent } from './overview/overview.component'; 63 | 64 | 65 | const routes: Routes = [ 66 | { path: 'weeklytasks', component: WeeklytasksComponent }, 67 | { path: '', component: AuthComponent }, 68 | { path: 'dashboard', component: DashboardComponent }, 69 | { path: 'monthlytasks', component: MonthlytasksComponent }, 70 | { path: 'overview', component: OverviewComponent }, 71 | { path: 'goals', component: GoalsComponent } 72 | 73 | ]; 74 | 75 | @NgModule({ 76 | imports: [RouterModule.forRoot(routes)], 77 | exports: [RouterModule] 78 | }) 79 | export class AppRoutingModule { } 80 | ``` 81 | 82 | 83 | Update the Index.html as follows 84 | 85 | 86 | ``` 87 | 88 | 89 | 90 | 91 | Team tasks 92 | 93 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ``` 106 | 107 | 108 | Add following line in tsconfig.app.json to add node type in compiler option 109 | 110 | ``` 111 | "types":["node"] 112 | ``` 113 | 114 | 115 | 116 | Update the app.component.html file as below. This will add the HTML components for navigation and associate them them with the routes you defined earlier. 117 | 118 | 119 | ``` 120 | 146 | 147 | 148 |
149 | 150 |
151 | ``` 152 | 153 | Run the ng serve command and check if your routes are working properly. To start local server run 154 | 155 | 156 | ``` 157 | ng serve 158 | ``` 159 | 160 | 161 | You should be able to see the following screen when we navigate to http://localhost:4200/ 162 | 163 | ![Stubs](https://user-images.githubusercontent.com/5582133/67894817-5a8b2e80-fb7f-11e9-945a-e4acdbef171f.png) 164 | 165 | 166 | Cick on various menu to check if the routing is working properly 167 | 168 | 169 | 170 | 171 | Now start with installing amplify js libary. You will use the aws-amplify library along with aws-amplify-angular library. You also to use moment js library for time function. Run following command to install this 172 | 173 | ``` 174 | npm install aws-amplify aws-amplify-angular moment 175 | ``` 176 | 177 | 178 | Install the amplify js library and add the amplify angular dependencies in app.module.ts as follows 179 | 180 | 181 | ``` 182 | import { BrowserModule } from '@angular/platform-browser'; 183 | import { NgModule } from '@angular/core'; 184 | 185 | import { AppRoutingModule } from './app-routing.module'; 186 | import { AppComponent } from './app.component'; 187 | import { AuthComponent } from './auth/auth.component'; 188 | import { WeeklytasksComponent } from './weeklytasks/weeklytasks.component'; 189 | import { MonthlytasksComponent } from './monthlytasks/monthlytasks.component'; 190 | import { GoalsComponent } from './goals/goals.component'; 191 | import { DashboardComponent } from './dashboard/dashboard.component'; 192 | import { OverviewComponent } from './overview/overview.component'; 193 | //Import Amplify dependencies 194 | import { AmplifyAngularModule, AmplifyService } from 'aws-amplify-angular'; 195 | 196 | 197 | @NgModule({ 198 | declarations: [ 199 | AppComponent, 200 | AuthComponent, 201 | WeeklytasksComponent, 202 | MonthlytasksComponent, 203 | GoalsComponent, 204 | DashboardComponent, 205 | OverviewComponent 206 | ], 207 | imports: [ 208 | BrowserModule, 209 | AppRoutingModule, 210 | //declare the AmplifyAngularModule 211 | AmplifyAngularModule 212 | ], 213 | providers: [ 214 | //declare the AmplifyService 215 | AmplifyService 216 | ], 217 | bootstrap: [AppComponent] 218 | }) 219 | export class AppModule { } 220 | ``` 221 | 222 | Angular will also create e2e folder for end to end testing . 223 | 224 | src directory will contain app directory which will have the source code for all the angular components created above 225 | 226 | 227 | 228 | 229 | You have completed the client side angular code and now will use amplify library to provision backend infrastructure as well 230 | 231 | [Proceed to Lab 2](LAB2.md) 232 | -------------------------------------------------------------------------------- /LAB2.md: -------------------------------------------------------------------------------- 1 | # LAB2 : Adding Amplify resources 2 | 3 | 4 | Start by initialising amplify project. 5 | 6 | ``` 7 | amplify init 8 | ``` 9 | 10 | Choose following configurations (Answers in **Bold**) 11 | 12 | 13 | > ? Enter a name for the project (teamtasks) **teamtasks** 14 | 15 | > ? Enter a name for the environment **dev** 16 | 17 | > ? Choose your default editor **Visual Studio Code** 18 | 19 | > ? Choose the type of app that you're building **javascript** 20 | 21 | > ? What javascript framework are you using **angular** 22 | 23 | > ? Source Directory Path **src** 24 | 25 | > ? Distribution Directory Path **dist** 26 | 27 | > ? Build Command **npm run-script build** 28 | 29 | > ? Start Command **ng serve** 30 | 31 | > ? Do you want to use an AWS profile? **Yes. **(Since I AWS CLI configured on my local development machine) 32 | 33 | > ? Please choose the profile you want to use **default **(My aws cli profile is named default) 34 | 35 | 36 | 37 | Once the command is run successfully , you will be displayed a message 38 | 39 | 40 | > *Your project has been successfully initialized and connected to the cloud!* 41 | 42 | 43 | 44 | 45 | A new file will be created with name aws-exports.js 46 | This is a dynamically generated file which has the configuration to ensure the javascript angular module can communicate with the API we will be developing. 47 | 48 | Since we are developing a TS project , we might need to copy the aws-exports.js and create a new file with name aws-exports.ts. We need to do this everytime we create/update/delete an serverside resource. You will automate this at later stage. 49 | 50 | 51 | 52 | After that import the exports file in main.ts. The main.ts file should look like this 53 | 54 | 55 | ``` 56 | import { enableProdMode } from '@angular/core'; 57 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 58 | 59 | import { AppModule } from './app/app.module'; 60 | import { environment } from './environments/environment'; 61 | import Amplify from 'aws-amplify'; 62 | import awsconfig from './aws-exports'; 63 | 64 | if (environment.production) { 65 | enableProdMode(); 66 | } 67 | 68 | platformBrowserDynamic().bootstrapModule(AppModule) 69 | .catch(err => console.error(err)); 70 | 71 | Amplify.configure(awsconfig); 72 | ``` 73 | 74 | 75 | 76 | Now start creating resources which includes Auth, API and Hosting. 77 | 78 | To create a auth, run command 79 | 80 | 81 | ``` 82 | amplify add auth 83 | ``` 84 | 85 | 86 | Below are the options you can choose. Chosen option in Bold. 87 | 88 | 89 | > Do you want to use the default authentication and security configuration? **Default configuration** 90 | 91 | > How do you want users to be able to sign in? **Email** 92 | 93 | > Do you want to configure advanced settings? **Yes, I want to make some additional changes**. 94 | 95 | > What attributes are required for signing up? (Press to select, to toggle all, to invert selection)**Email** 96 | 97 | > Do you want to enable any of the following capabilities? **Email Domain Filtering (whitelist)** 98 | 99 | > Enter a comma-delimited list of allowed email domains (example: 'mydomain.com, myotherdo 100 | 101 | > main.com'). [**mydummydomain.com**](http://mydummydomain.com/) 102 | 103 | > Do you want to edit your email-filter-whitelist function now? **N** 104 | 105 | 106 | 107 | Add API (Appsycn) resource by running following command 108 | 109 | 110 | ``` 111 | amplify add api 112 | ``` 113 | 114 | You can choose the following options. Chosen option in Bold. 115 | 116 | 117 | > ? Please select from one of the below mentioned services **GraphQL** 118 | 119 | > ? Provide API name: **teamtasks** 120 | 121 | > ? Choose an authorization type for the API **Amazon Cognito User Pool** 122 | 123 | > ? Do you have an annotated GraphQL schema? **No** 124 | 125 | > ? Do you want a guided schema creation? **No** 126 | 127 | > ? Provide a custom type name **MyType** 128 | 129 | 130 | The above action will create a file named ./teamtasks/amplify/backend/api/teamtasks/schema.graphql 131 | Update the content of the schema file as 132 | 133 | 134 | ``` 135 | # This is reminder model which will contain multiple tasks. Each remider has a frequency associated with it 136 | # Auth attribute ensures that only owner of the reminders can access them 137 | type Reminder @model @auth(rules: [{allow: owner}]) { 138 | id: ID! 139 | user: String! 140 | customer: String! 141 | start: AWSDateTime! 142 | month: Int! 143 | week: Int! 144 | year: Int! 145 | additionalAttribute: String! 146 | type: frequency! 147 | tasks: [Task] @connection(name: "ReminderTasks") 148 | } 149 | 150 | #Each reminder has one or more multiple tasks. Each task as one or more optional comments and one or more mandatory comments 151 | type Task @model @auth(rules: [{allow: owner}]) { 152 | id: ID! 153 | title: String! 154 | description: String! 155 | status: Boolean! 156 | reminder: Reminder @connection(name: "ReminderTasks") 157 | comments: [Comment] @connection(name: "TaskComments") 158 | mandatorycomment: [MandatoryComment] @connection(name: "TaskMandatoryComments") 159 | } 160 | 161 | #This is schema for comment assiciated with comments 162 | type Comment @model @auth(rules: [{allow: owner}]) { 163 | id: ID! 164 | content: String, 165 | addedby: String, 166 | addedon: AWSDateTime! 167 | post: Task @connection(name: "TaskComments") 168 | } 169 | 170 | #This is schema for comment assiciated with comments. It has additional attribute names content to be displayed on the UI control 171 | type MandatoryComment @model @auth(rules: [{allow: owner}]) { 172 | id: ID! 173 | title: String 174 | content: String, 175 | addedby: String, 176 | addedon: AWSDateTime! 177 | task: Task @connection(name: "TaskMandatoryComments") 178 | } 179 | 180 | # Enum for frequency 181 | enum frequency { 182 | WEEKLY 183 | MONTHLY 184 | QUARTERLY 185 | YEARLY 186 | ADHOC 187 | } 188 | 189 | # this is model for customer/group and its assiciation with the application user 190 | # Only users with Admin group can add/remove/update objects 191 | # for all other users mentioned in groupsCanAccess only read operation is permitted. 192 | type Customer @model @auth(rules: [ 193 | { allow: groups, groupsField: "groupsCanAccess", operations: [read] } 194 | { allow: groups, groups: ["Admin"] } 195 | ]){ 196 | id: ID! 197 | customername: String! 198 | user: String! 199 | groupsCanAccess: [String]! 200 | } 201 | 202 | # this is metadata type for creating Reminders 203 | type ReminderMetaData @model @auth(rules: [ 204 | { allow: groups, groupsField: "groupsCanAccess", operations: [read] } 205 | { allow: groups, groups: ["Admin"] } 206 | ]) { 207 | id: ID! 208 | type: frequency! 209 | tasks: [TaskMetaData] @connection(name: "ReminderTasksMeta") 210 | groupsCanAccess: [String]! 211 | } 212 | 213 | # this is metadata type for creating taks 214 | type TaskMetaData @model @auth(rules: [ 215 | { allow: groups, groupsField: "groupsCanAccess", operations: [read] } 216 | { allow: groups, groups: ["Admin"] } 217 | ]) { 218 | id: ID! 219 | title: String! 220 | description: String! 221 | reminder: ReminderMetaData @connection(name: "ReminderTasksMeta") 222 | mandatorycomments: [MandatoryCommentMetaData] @connection(name: "TaskMandatoryCommentsMeta") 223 | groupsCanAccess: [String]! 224 | } 225 | 226 | # this is metadata type for creating mandatory tasks 227 | type MandatoryCommentMetaData @model @auth(rules: [ 228 | { allow: groups, groupsField: "groupsCanAccess", operations: [read] } 229 | { allow: groups, groups: ["Admin"] } 230 | ]){ 231 | id: ID! 232 | title: String 233 | task: TaskMetaData @connection(name: "TaskMandatoryCommentsMeta") 234 | groupsCanAccess: [String]! 235 | } 236 | ``` 237 | 238 | 239 | Create a hosting resource for the application where the angular application will be hosted. Do this by running following command 240 | 241 | 242 | ``` 243 | amplify add hosting 244 | ``` 245 | 246 | 247 | Choose the following options. Selected option in bold 248 | 249 | 250 | > ? Select the environment setup: **PROD (S3 with CloudFront using HTTPS)** 251 | 252 | > ? hosting bucket name **teamtasks-xxxxxxxx-hostingbucket** 253 | 254 | > ? index doc for the website **index.html** 255 | 256 | > ? error doc for the website **index.html** 257 | 258 | 259 | 260 | Now you are done with the resources creation and can check the status by running below command 261 | 262 | 263 | ``` 264 | amplify status 265 | ``` 266 | 267 | 268 | Output shown should be similar as shown below 269 | 270 | ![amplify_status](https://user-images.githubusercontent.com/5582133/67894809-58c16b00-fb7f-11e9-8b45-ec429a54e812.png) 271 | 272 | Publish this resources by running following command 273 | 274 | 275 | ``` 276 | amplify push 277 | ``` 278 | 279 | 280 | Choose following options. Chosen option in bold 281 | 282 | 283 | 284 | > ? Choose the code generation language target **angular** 285 | 286 | > ? Enter the file name pattern of graphql queries, mutations and subscriptions **src/graphql/*/.graphql** 287 | 288 | > ? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions **Yes** 289 | 290 | > ? Enter maximum statement depth [increase from default if your schema is deeply nested] **5** 291 | 292 | > ? Enter the file name for the generated code **src/app/API.service.ts** 293 | 294 | 295 | You can see a folder named Amplify. This is the folder which is managed by amplify tool which dynamically generates a cloudfromation template and updates it based on the resouces added via Amplify CLI 296 | 297 | Once the operation is complete, copy the content from aws-export.js to aws-export.ts. We will automate this step in coming section. 298 | 299 | 300 | In the subsequent sections, you will write the functional logic and consume the amplify API. 301 | 302 | [Proceed to Lab 3](LAB3.md) 303 | -------------------------------------------------------------------------------- /LAB3.md: -------------------------------------------------------------------------------- 1 | # 3. LAB3 : Adding application logic 2 | 3 | Update the app.component.ts as following. Following code is written to redirect to /dashboard route post login 4 | 5 | 6 | ``` 7 | import { Component } from '@angular/core'; 8 | import { Auth } from 'aws-amplify'; 9 | import { Router } from '@angular/router'; 10 | import { AmplifyService } from 'aws-amplify-angular'; 11 | 12 | @Component({ 13 | selector: 'app-root', 14 | templateUrl: './app.component.html', 15 | styleUrls: ['./app.component.css'] 16 | }) 17 | export class AppComponent { 18 | title = 'teamtasks'; 19 | signedIn: boolean; 20 | loggedinuser: string; 21 | user: any; 22 | constructor(private amplifyService: AmplifyService, private router: Router) { 23 | this.amplifyService.authStateChange$ 24 | .subscribe(authState => { 25 | this.signedIn = authState.state === 'signedIn'; 26 | if (!authState.user) { 27 | this.user = null; 28 | 29 | } else { 30 | this.user = authState.user; 31 | this.loggedinuser = this.user.attributes.email; 32 | console.log('Loggedin User', this.user); 33 | this.router.navigate(['/dashboard']); 34 | } 35 | }); 36 | } 37 | async logout() { 38 | await Auth.signOut().then((res) => { 39 | this.router.navigate(['']); 40 | }); 41 | } 42 | } 43 | ``` 44 | 45 | 46 | Update the app.component.html and display the navigation bar if loggedinuser flag is true 47 | 48 | 49 | ``` 50 |