Skip to content

Commit 3382c9a

Browse files
authored
chore: Documentation and GitHub Actions
README updates and add GitHub Actions * Action for applying linting fixes * Action for running unit tests * Action for running e2e tests
1 parent 2dd5b53 commit 3382c9a

40 files changed

Lines changed: 565 additions & 314 deletions

.github/workflows/on-pr.yaml

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
name: Run Linting and Testing
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
7+
jobs:
8+
lint:
9+
runs-on: ubuntu-latest
10+
name: Check for Linting Errors
11+
steps:
12+
- name: Checkout Repository
13+
uses: actions/checkout@v3
14+
with:
15+
ref: ${{ github.event.pull_request.head.ref }}
16+
17+
- name: Setup NodeJS
18+
uses: actions/setup-node@v3
19+
with:
20+
node-version: 18
21+
22+
- name: NPM Install
23+
run: npm install --only-dev
24+
shell: bash
25+
26+
- name: Check for Linting Issues
27+
run: npm run lint
28+
29+
client-unit-tests:
30+
runs-on: ubuntu-latest
31+
name: Run Client Side Unit Tests
32+
steps:
33+
- name: Checkout Repository
34+
uses: actions/checkout@v3
35+
with:
36+
ref: ${{ github.event.pull_request.head.ref }}
37+
38+
- name: Setup NodeJS
39+
uses: actions/setup-node@v3
40+
with:
41+
node-version: 18
42+
43+
- name: NPM Install
44+
run: npm install --only-dev
45+
shell: bash
46+
47+
- name: Run unit tests for the client
48+
run: npm run test --workspace=client
49+
50+
server-unit-tests:
51+
runs-on: ubuntu-latest
52+
name: Run Server Side Unit Tests
53+
steps:
54+
- name: Checkout Repository
55+
uses: actions/checkout@v3
56+
with:
57+
ref: ${{ github.event.pull_request.head.ref }}
58+
59+
- name: Setup NodeJS
60+
uses: actions/setup-node@v3
61+
with:
62+
node-version: 18
63+
64+
- name: NPM Install
65+
run: npm install --only-dev
66+
shell: bash
67+
68+
- name: Run unit tests for the server
69+
run: npm run test --workspace=server
70+
71+
e2e-tests:
72+
runs-on: ubuntu-latest
73+
name: Run E2E Tests
74+
steps:
75+
- name: Checkout Repository
76+
uses: actions/checkout@v3
77+
with:
78+
ref: ${{ github.event.pull_request.head.ref }}
79+
80+
- name: Setup NodeJS
81+
uses: actions/setup-node@v3
82+
with:
83+
node-version: 18
84+
85+
- name: NPM Install
86+
run: npm install --only-dev
87+
shell: bash
88+
89+
- name: Build Code
90+
run: |
91+
npm run build:prod
92+
mkdir -p server/bucket-test/Responses
93+
94+
- name: Start MongoDB Instance
95+
uses: supercharge/mongodb-github-action@1.8.0
96+
97+
- name: Run e2e testing
98+
uses: cypress-io/github-action@v4.2.0
99+
with:
100+
start: npm run start:ci
101+
env:
102+
MONGO_URI: mongodb://localhost:27017/signlab-test
103+
104+
- uses: actions/upload-artifact@v2
105+
if: failure()
106+
with:
107+
name: cypress-screenshots
108+
path: cypress/screenshots
109+
110+
- uses: actions/upload-artifact@v2
111+
if: always()
112+
with:
113+
name: cypress-videos
114+
path: cypress/videos

README.md

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,59 +13,114 @@ processing.
1313
## Code Organization
1414

1515
The code base is made up of an Angular front end (stored in `client/` folder)
16-
and a Hapi backend (stored in `server/` folder). A Dockerfile and Docker
17-
compose file is provided for packing up the application.
18-
19-
The Angular front end is heavily coupled to the Hapi backend. Most of the
16+
and a NestJS backend (stored in `server/` folder). A Dockerfile and Docker
17+
compose file is provided for packing up the application, an official
18+
docker image is also stored in DockerHub. A break down of the top level folders
19+
is shown below.
20+
21+
* `client/`: Angular client side code
22+
* `cypress/`: E2E Testing
23+
* `docs/`: Sphinx documentation
24+
* `server/`: NestJS server side code
25+
* `shared/`: Code shared between client and server, currently only DTOs
26+
27+
The Angular front end is heavily coupled to the NestJS backend. Most of the
2028
logic is contained within the backend with the Angular front end acting
21-
just as an interface to the backend. The system workes by having the Hapi
29+
just as an interface to the backend. The system workes by having the NestJS
2230
backend serve the compiled Angular front end as a static webpage.
2331

24-
The Hapi backend is based on a project [Anchor](https://github.com/hicsail/anchor)
25-
which provides a template for a Hapi + MongoDB server. Part of what is included
26-
from Anchor is a system for managing users, user roles, user authentication,
27-
MongoDB data access, static webpage serving, emailing service, and various
28-
other helpful tools. All of these features are build using existing common
29-
tools and just packaged up in a form that is easy to include in any backend.
32+
## Environment Variables
33+
34+
The SignLab application can be configured via environment variables. Those
35+
environment variables can be supplied in a number of different ways.
36+
37+
For a complete list of configrations used by the server, refer to the file
38+
`server/src/config/configuration.ts`. That file has the SignLab wide settings
39+
and where they come from.
40+
41+
### Locally
42+
43+
Locally, the easiest way to pass in the configuration is via `.env` files.
44+
Below is an example of the usage.
45+
46+
```bash
47+
cd server/
48+
export NODE_ENV=local
49+
npm run start:watch
50+
```
51+
52+
The file `.env.local` in the top level will then be used for configruation.
53+
The server looks for a file `.env.<NODE_ENV>` so additional environments can
54+
be made based on testing needs.
55+
56+
By running `npm run start:watch` at the top level, the application will use the
57+
`.env.local` file.
58+
59+
### Docker
60+
61+
The provided docker-compose file looks for a `deployment.env` file. The
62+
`deployment.env` file is setup identically to a `.env` and is the preferred
63+
method to insert configuration into the dockerized instance.
64+
65+
## Object Storage ("Bucket Storage")
66+
67+
SignLab makes use of object storage for storing the response videos that
68+
are uploaded to the platform. Currently two platforms are supported.
69+
70+
First is an interace for storing the responses in a local folder. This is
71+
handy for testing locally quickly without the need to a dedicated bucket
72+
setup.
73+
74+
Second is S3 complient object storage endpoints. NERC's object storage is S3
75+
complient so can be used as well.
76+
77+
Each object storage has its own set of required configuration, you
78+
can refer to the `bucket` section of the configuration contained
79+
in `server/src/config/configuration.ts`. The user selects which bucket storage
80+
type they are using via the `type` value (which is evaluated from the
81+
environment variable `BUCKET_TYPE`. Setting `BUCKET_TYPE` to `S3` will
82+
have SignLab look for S3 specific settings and use an S3 object container.
83+
Using `LOCAL` as the `BUCKET_TYPE` will result in a local folder being
84+
user for the object container.
85+
86+
GCP is not yet offically supported, but the functionality is stubbed out.
3087

3188
## Running the Code for Development
3289

3390
The following steps will get you setup so you can test SignLab locally and
3491
test out changes in real time.
3592

36-
1. (One time) Install packages for the client side and the server side.
93+
1. (One time) Install dependancies
3794

3895
```bash
39-
cd client
40-
npm install
41-
cd ../server
42-
npm install
96+
npm i
4397
```
4498

45-
2. (Each time) Start up a MongoDB instance using the `mongod` command. Below is
46-
an example.
99+
2. Setup Object Storage
47100

48-
```bash
49-
mongod --dbpath ~/data/signlab
50-
```
101+
For local testing, a folder can be used to emulate an actual object storage
102+
container. By default the provided `.env.local` file expects a folder
103+
`server/bucket/Responses` to exist. Make sure that folder exists when testing
104+
locally using a folder for obect storage emulation.
51105

52-
3. (One time) Run the first time setup script for the Hapi backend.
106+
3. (Each time) Start up a MongoDB instance using the `mongod` command. Below is
107+
an example.
53108

54109
```bash
55-
cd server/
56-
node first-time-setup.js
110+
mongod --dbpath ~/data/signlab
57111
```
58112

59-
4. (Each time) Start the Hapi backend
113+
4. Start up the frontend and backend
60114

61115
```bash
62-
cd server/
63-
npm start
116+
npm run start:watch
64117
```
65118

66-
5. (Each time) Have the Angular code build as changes take place
119+
The command above will build the Angular and NestJS components and watch
120+
for changes. The commands are run with the "concurrent" package so if reading
121+
the output is difficult, you can run the same command separatly for the
122+
`server` and `client` package in different terminals from the respective
123+
folders.
67124

68-
```bash
69-
cd client/
70-
ng build --watch
71-
```
125+
Note: For the server, you need to specify an `env` file to load. The command
126+
above will run the server with `NODE_ENV` set to `local`.

client/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"build:prod": "ng build --prod",
88
"test": "ng test --browsers=ChromeHeadless --watch=false --code-coverage",
99
"test:watch": "ng test",
10-
"lint": "ng lint --fix",
10+
"lint:fix": "ng lint --fix",
11+
"lint": "ng lint",
1112
"setup": "node setup.js"
1213
},
1314
"private": true,

client/src/app/admin-dashboard/components/studies-control/new-study/new-study.component.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ import { TagFormPreviewDialog } from './tag-form-preview.component';
1717
import { JsonSchema } from '@jsonforms/core';
1818
import { Router } from '@angular/router';
1919
import { MatStepper } from '@angular/material/stepper';
20-
import { VideoOptionUpload, videoOptionUploadRendererTester } from '../../../../shared/components/custom-fields/video-option-upload.component';
21-
import { userVideoOptionRendererTester, UserVideoOption } from '../../../../shared/components/custom-fields/user-video-option-field.component';
20+
import {
21+
VideoOptionUpload,
22+
videoOptionUploadRendererTester,
23+
} from '../../../../shared/components/custom-fields/video-option-upload.component';
24+
import {
25+
userVideoOptionRendererTester,
26+
UserVideoOption,
27+
} from '../../../../shared/components/custom-fields/user-video-option-field.component';
2228

2329
@Component({
2430
selector: 'new-study',
@@ -29,7 +35,7 @@ export class NewStudyComponent implements AfterViewInit {
2935
/** Used for the control of the step logic */
3036
@ViewChild(MatStepper) matStepper: MatStepper;
3137
selectedStepNumber = 1;
32-
maxSteps: number = 0;
38+
maxSteps = 0;
3339

3440
/** The study metadata information */
3541
studyMetadata: NewStudyMeta | null = null;
@@ -75,7 +81,11 @@ export class NewStudyComponent implements AfterViewInit {
7581
icon: 'text_format',
7682
},
7783
{ type: TagFieldType.BooleanOption, name: 'Boolean Option', icon: 'flag' },
78-
{ type: TagFieldType.EmbeddedVideoOption, name: 'Video Option', icon: 'video_library' },
84+
{
85+
type: TagFieldType.EmbeddedVideoOption,
86+
name: 'Video Option',
87+
icon: 'video_library',
88+
},
7989
{ type: TagFieldType.FreeText, name: 'Free Text', icon: 'text_fields' },
8090
{ type: TagFieldType.Numeric, name: 'Numeric', icon: 'bar_chart' },
8191
];

client/src/app/admin-dashboard/components/studies-control/new-study/tag-field.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import {
66
FileListField,
77
} from '../../../../shared/components/custom-fields/file-list.component';
88
import { TagField } from '../../../../models/tag-field';
9-
import { VideoOptionUpload, videoOptionUploadRendererTester } from '../../../../shared/components/custom-fields/video-option-upload.component';
9+
import {
10+
VideoOptionUpload,
11+
videoOptionUploadRendererTester,
12+
} from '../../../../shared/components/custom-fields/video-option-upload.component';
1013

1114
@Component({
1215
selector: 'tag-field',

client/src/app/admin-dashboard/components/studies-control/studies-control.component.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ export class StudiesControlComponent {
1818
/** Which study control view is active */
1919
activeView: 'responses' | 'users' | 'tags' = 'responses';
2020

21-
constructor(private dialog: MatDialog,
22-
private studyService: StudyService,
23-
private router: Router) {
21+
constructor(
22+
private dialog: MatDialog,
23+
private studyService: StudyService,
24+
private router: Router
25+
) {
2426
this.studyService.getStudies().then((studies) => {
2527
this.studies = studies;
2628
if (this.studies.length > 0) {
@@ -95,7 +97,7 @@ export class StudiesControlComponent {
9597
'videoURL',
9698
'study',
9799
'user',
98-
...Object.keys(tags[0].study.tagSchema.dataSchema.properties)
100+
...Object.keys(tags[0].study.tagSchema.dataSchema.properties),
99101
];
100102

101103
this.downloadFile(headerElements, flattenedData);

client/src/app/admin-dashboard/components/user-control/user-control.component.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,7 @@ import { User } from 'shared/dtos/user.dto';
1515
export class UserControlComponent implements OnInit {
1616
// TODO: Get roles dynamically from server
1717
/** Columns to display in the user view */
18-
displayedColumns = [
19-
'username',
20-
'name',
21-
'email',
22-
'isAdmin',
23-
];
18+
displayedColumns = ['username', 'name', 'email', 'isAdmin'];
2419
/** Stores the current list of all users, is exposed in the user control view */
2520
userData: User[] = [];
2621

client/src/app/authenticate/components/login.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ import { AuthService } from '../../core/services/auth.service';
3131
[formControl]="pass"
3232
data-cy="passwordField"
3333
/><br />
34-
<button mat-stroked-button class="button" type="submit" data-cy="loginSubmit">
34+
<button
35+
mat-stroked-button
36+
class="button"
37+
type="submit"
38+
data-cy="loginSubmit"
39+
>
3540
Submit
3641
</button>
3742
</form>

0 commit comments

Comments
 (0)