Compare commits
254 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b364d79ef8 | ||
|
9e20782c07 | ||
|
a722d755fd | ||
|
793e7891b3 | ||
|
dbbd14399e | ||
|
89dfe3293d | ||
|
ac9b101b47 | ||
|
1c38198fc7 | ||
|
fa32a61df9 | ||
|
32dbb37034 | ||
|
396bbf06d2 | ||
|
1f79340896 | ||
|
ab7d3b1abd | ||
|
f863f35de7 | ||
|
b07c99f805 | ||
|
82aba63baf | ||
|
8924540757 | ||
|
f0f706e575 | ||
|
469b2bca36 | ||
|
e9bae6fe2d | ||
|
cf7b0da5ad | ||
|
3145a99e23 | ||
|
b8271dd5b0 | ||
|
1a1f5d8e1f | ||
|
730f904a58 | ||
|
b61ea4e54d | ||
|
7cb90e23c0 | ||
|
1ed46b8ade | ||
|
d95f0036ac | ||
|
df80486f45 | ||
|
e2b9c98176 | ||
|
be31dbfbd7 | ||
|
78f627b39d | ||
|
d964d1e275 | ||
|
c09e82c6ab | ||
|
f300c740c4 | ||
|
79e7561beb | ||
|
18f79936fe | ||
|
42a560ab0e | ||
|
18a3230ad7 | ||
|
1347e3bbc1 | ||
|
7b8fea9d67 | ||
|
eb3133c676 | ||
|
4d40c72158 | ||
|
11b152fec9 | ||
|
64d57ffd90 | ||
|
23bf3a2c84 | ||
|
3580941207 | ||
|
9bc5b5624b | ||
|
0d17ddee53 | ||
|
fa7b8dc7f5 | ||
|
5943a5c8ef | ||
|
5621139dd7 | ||
|
a65b65d748 | ||
|
7cac0bc0a8 | ||
|
30d01e33c9 | ||
|
841cb1df14 | ||
|
b3a8add8ee | ||
|
842c703d1a | ||
|
a5fa45b054 | ||
|
20cdc4ce76 | ||
|
a68bf60f44 | ||
|
d01c4d2ef5 | ||
|
58e4f6fdeb | ||
|
ea41495e49 | ||
|
5405cbfd7c | ||
|
6ca0ee1763 | ||
|
7757d1d0da | ||
|
5aa1616f17 | ||
|
529f24f306 | ||
|
c1fd10c268 | ||
|
e74b3f5597 | ||
|
eb4cb54b05 | ||
|
6a0708a3f0 | ||
|
fbea45e151 | ||
|
68020ccae7 | ||
|
603fb849f3 | ||
|
dcee487737 | ||
|
1cdaa63935 | ||
|
929de8c98b | ||
|
beb3e6cc98 | ||
|
131e14d611 | ||
|
bc6012af76 | ||
|
5ee4c4d231 | ||
|
fd07a93d50 | ||
|
9d7a928032 | ||
|
29fca61a85 | ||
|
5c4e4c38f4 | ||
|
b7d79b6b50 | ||
|
0ca848e26b | ||
|
847e8a1aa1 | ||
|
46bdee7b68 | ||
|
f44d8713a0 | ||
|
7bdeafa483 | ||
|
5e06bd0cf7 | ||
|
dd0bcbe57d | ||
|
f91520ed85 | ||
|
e77fe1406c | ||
|
57be3a11ed | ||
|
c381bd1f60 | ||
|
1484a882b2 | ||
|
f99cfd0eff | ||
|
a63552f32b | ||
|
ae2e14172d | ||
|
af4378ee40 | ||
|
39aa535864 | ||
|
9ff58a1c2c | ||
|
4c649e7770 | ||
|
5db9320dae | ||
|
b2dd734ade | ||
|
622d324c9a | ||
|
5901888475 | ||
|
de1ec502b1 | ||
|
4832726b14 | ||
|
0b7e101bb2 | ||
|
e6ac5ea33d | ||
|
31633ff825 | ||
|
5443b61825 | ||
|
aeab069dec | ||
|
f5d9b6e906 | ||
|
3ebefac2db | ||
|
a9bf42a849 | ||
|
53f51bce5f | ||
|
1017bd48a2 | ||
|
3131391d92 | ||
|
88ac0aea66 | ||
|
c7d2a5434d | ||
|
ade244707a | ||
|
33e619c2d5 | ||
|
83a0358869 | ||
|
5ba0dab1a1 | ||
|
1dfd8c91a2 | ||
|
ecff5313a1 | ||
|
a12de4e058 | ||
|
9194dd5166 | ||
|
63a7d5ce1f | ||
|
9f9ac19b71 | ||
|
0912ea7956 | ||
|
b5e5a88163 | ||
|
5f1a246e6a | ||
|
4073d2cc4b | ||
|
23657853e5 | ||
|
ec9d0246ca | ||
|
1cbefee26f | ||
|
dd56207892 | ||
|
123057f0f1 | ||
|
50283be4f5 | ||
|
46b1ec4b07 | ||
|
661feafa40 | ||
|
68b0c8edf5 | ||
|
5d2c446551 | ||
|
52bc6a27a4 | ||
|
1db54e9f7a | ||
|
d70881c912 | ||
|
1798835807 | ||
|
1055f7ef26 | ||
|
5a05741e08 | ||
|
4c5132c2b2 | ||
|
49f85d5468 | ||
|
9ef3c59fee | ||
|
069aff88af | ||
|
6d126f6085 | ||
|
948f638cd7 | ||
|
b24b1110f6 | ||
|
eed39f580f | ||
|
259018ca97 | ||
|
142e6d93b6 | ||
|
a5ac2dc940 | ||
|
331f8e731c | ||
|
19bbabe9b4 | ||
|
4336157371 | ||
|
9e82dae202 | ||
|
ccbf060c8c | ||
|
1f832aadd2 | ||
|
6ce15a094e | ||
|
8a1c210515 | ||
|
c412282e04 | ||
|
8c2ad629d2 | ||
|
7b7abad2e6 | ||
|
70c863c378 | ||
|
12e818e079 | ||
|
250617776b | ||
|
9c531771f2 | ||
|
131553ddeb | ||
|
c5cc7bf309 | ||
|
302af4bbd5 | ||
|
3c7b5f7f4e | ||
|
3a7ed2fb16 | ||
|
dd3e0cfefb | ||
|
d284f0ddf2 | ||
|
3db5f62a5c | ||
|
4f2d88db9f | ||
|
c3944d476b | ||
|
8a9a32414e | ||
|
e73a544ab2 | ||
|
ce6b8fcfa6 | ||
|
db3e8dba8d | ||
|
f2edc4dc6a | ||
|
5d331c3800 | ||
|
f340f3ed82 | ||
|
2a6dbc0503 | ||
|
72e2f0fa03 | ||
|
3b1b0cfd57 | ||
|
e7d8eaea59 | ||
|
85d583e1b8 | ||
|
bec66f1385 | ||
|
1c1ac64c58 | ||
|
5668e68594 | ||
|
8338156cb8 | ||
|
3e909ed381 | ||
|
20e9842aea | ||
|
7035fa46ee | ||
|
23ae101f56 | ||
|
1379c22f6f | ||
|
78c07f27d3 | ||
|
c5229c7bc1 | ||
|
20afab9b1f | ||
|
2e95147336 | ||
|
ef5dccfd1a | ||
|
d5be6a2e4d | ||
|
274a05fdc2 | ||
|
65815998e9 | ||
|
cac2b0bf07 | ||
|
82be561bfe | ||
|
b75e4172b4 | ||
|
32323eaf83 | ||
|
f332b27168 | ||
|
0a39039e9c | ||
|
baa722b55e | ||
|
9cf7baf3e5 | ||
|
f6a9fb7fc5 | ||
|
a91c9bc7ef | ||
|
5f84e700d1 | ||
|
46cee253f3 | ||
|
ca89953d41 | ||
|
425bc45453 | ||
|
3422f584f9 | ||
|
89b7319dd8 | ||
|
5e83338668 | ||
|
6493fbd171 | ||
|
416d26658d | ||
|
6c00246e2d | ||
|
c45aec116b | ||
|
1518fda766 | ||
|
e4755dd074 | ||
|
c66f43f6e9 | ||
|
02f493e33b | ||
|
ad723543e8 | ||
|
56dceb5edb | ||
|
41905a219b | ||
|
467828d388 | ||
|
81ada40ca3 | ||
|
cc6df228ed | ||
|
1d453bdd49 |
@@ -1,33 +1,20 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"es2021": true,
|
"es2021": true,
|
||||||
"node": true
|
"node": true
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
"extends": "eslint:recommended",
|
||||||
"overrides": [
|
"overrides": [],
|
||||||
],
|
"parserOptions": {
|
||||||
"parserOptions": {
|
"ecmaVersion": "latest",
|
||||||
"ecmaVersion": "latest",
|
"sourceType": "module"
|
||||||
"sourceType": "module"
|
},
|
||||||
},
|
"rules": {
|
||||||
"rules": {
|
"indent": ["error", "tab"],
|
||||||
"indent": [
|
"linebreak-style": ["error", "unix"],
|
||||||
"error",
|
"quotes": ["error", "double"],
|
||||||
"tab"
|
"semi": ["error", "always"],
|
||||||
],
|
"no-global-assign": 0
|
||||||
"linebreak-style": [
|
}
|
||||||
"error",
|
}
|
||||||
"unix"
|
|
||||||
],
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"double"
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
],
|
|
||||||
"no-global-assign": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
46
.github/workflows/css-linting.yml
vendored
@@ -1,23 +1,23 @@
|
|||||||
name: CSS Linting
|
name: CSS Linting
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Single deploy job since we're just deploying
|
# Single deploy job since we're just deploying
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install apt updates
|
- name: Install apt updates
|
||||||
run: sudo apt -y update; sudo apt -y upgrade;
|
run: sudo apt -y update; sudo apt -y upgrade;
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo npm install
|
run: sudo npm install
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: sudo npm run lintCSS
|
run: sudo npm run lint-css
|
||||||
|
96
.github/workflows/deploy-githubpages.yml
vendored
@@ -1,43 +1,53 @@
|
|||||||
# Simple workflow for deploying static content to GitHub Pages
|
# Simple workflow for deploying static content to GitHub Pages
|
||||||
name: Deploy GitHub Pages
|
name: Deploy GitHub Pages
|
||||||
|
|
||||||
on:
|
on:
|
||||||
# Runs on pushes targeting the default branch
|
# Runs on pushes targeting the default branch
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
pages: write
|
pages: write
|
||||||
id-token: write
|
id-token: write
|
||||||
|
|
||||||
# Allow one concurrent deployment
|
# Allow one concurrent deployment
|
||||||
concurrency:
|
concurrency:
|
||||||
group: "pages"
|
group: "pages"
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Single deploy job since we're just deploying
|
# Single deploy job since we're just deploying
|
||||||
deploy:
|
deploy:
|
||||||
environment:
|
environment:
|
||||||
name: github-pages
|
name: github-pages
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Install apt updates
|
||||||
uses: actions/checkout@v3
|
run: sudo apt -y update; sudo apt -y upgrade;
|
||||||
- name: Setup Pages
|
- name: Install prerequisites
|
||||||
uses: actions/configure-pages@v2
|
uses: actions/setup-node@v3
|
||||||
- name: Upload artifact
|
with:
|
||||||
uses: actions/upload-pages-artifact@v1
|
node-version: 18
|
||||||
with:
|
- name: Checkout
|
||||||
# Upload only the src repository
|
uses: actions/checkout@v3
|
||||||
path: './source/'
|
- name: Install dependencies
|
||||||
- name: Deploy to GitHub Pages
|
run: sudo npm install
|
||||||
id: deployment
|
- name: Run tests
|
||||||
uses: actions/deploy-pages@v1
|
run: sudo npm run js-doc
|
||||||
|
- name: Setup Pages
|
||||||
|
uses: actions/configure-pages@v2
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v1
|
||||||
|
with:
|
||||||
|
# Upload only the src repository
|
||||||
|
path: "./source/"
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v1
|
||||||
|
46
.github/workflows/html-linting.yml
vendored
@@ -1,23 +1,23 @@
|
|||||||
name: HTML Linting
|
name: HTML Linting
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Single deploy job since we're just deploying
|
# Single deploy job since we're just deploying
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install apt updates
|
- name: Install apt updates
|
||||||
run: sudo apt -y update; sudo apt -y upgrade;
|
run: sudo apt -y update; sudo apt -y upgrade;
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo npm install
|
run: sudo npm install
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: sudo npm run lintHTML
|
run: sudo npm run lint-html
|
||||||
|
50
.github/workflows/js-linting.yml
vendored
@@ -1,25 +1,25 @@
|
|||||||
name: JS Linting
|
name: JS Linting
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Single deploy job since we're just deploying
|
# Single deploy job since we're just deploying
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install apt updates
|
- name: Install apt updates
|
||||||
run: sudo apt -y update; sudo apt -y upgrade;
|
run: sudo apt -y update; sudo apt -y upgrade;
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
run: sudo apt install -y nodejs npm;
|
run: sudo apt install -y nodejs npm;
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo npm install
|
run: sudo npm install
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: sudo npm run lint
|
run: sudo npm run lint-js
|
||||||
|
46
.github/workflows/js-unittest.yml
vendored
@@ -1,29 +1,29 @@
|
|||||||
name: JS Unit Test
|
name: JS Unit Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Single deploy job since we're just deploying
|
# Single deploy job since we're just deploying
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Install apt updates
|
- name: Install apt updates
|
||||||
run: sudo apt -y update; sudo apt -y upgrade;
|
run: sudo apt -y update; sudo apt -y upgrade;
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo npm install
|
run: sudo npm install
|
||||||
- name: Start local http server
|
- name: Start local http server
|
||||||
run: sudo npm run http-server
|
run: sudo npm run http-server &
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: sudo npm test
|
run: sudo npm test
|
||||||
|
27
.github/workflows/prettier-linting.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Prettier
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Single deploy job since we're just deploying
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Install apt updates
|
||||||
|
run: sudo apt -y update; sudo apt -y upgrade;
|
||||||
|
- name: Install prerequisites
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo npm install
|
||||||
|
- name: Run tests
|
||||||
|
run: sudo npm run lint-prettier
|
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
**/.devcontainer/*
|
**/.devcontainer/*
|
||||||
**/node_modules/*
|
**/node_modules/*
|
||||||
**/package-lock.json
|
**/package-lock.json
|
||||||
|
**/*.vscode/*
|
@@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"attr-value-not-empty": false
|
"attr-value-not-empty": false,
|
||||||
}
|
"space-tab-mixed-disabled": "tab"
|
||||||
|
}
|
||||||
|
5
.prettierrc.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 160,
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": true
|
||||||
|
}
|
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "stylelint-config-standard"
|
"extends": "stylelint-config-standard",
|
||||||
}
|
"ignore": ["inside-parens", "param", "value"],
|
||||||
|
"rules": {
|
||||||
|
"indentation": "tab"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
47
110722-sprint1.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Meeting Minutes (11/07/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: First Sprint
|
||||||
|
|
||||||
|
Meeting notes for the first sprint
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gavyn Ezell
|
||||||
|
4. Henry Feng
|
||||||
|
5. Kara Hoagland
|
||||||
|
6. Marc Reta
|
||||||
|
7. Sanjit Joseph
|
||||||
|
8. Daniel Hernandez
|
||||||
|
9. Arthur Lu
|
||||||
|
|
||||||
|
## Absentees
|
||||||
|
|
||||||
|
1. Isaac Otero
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/07/2022 at 6:00PM
|
||||||
|
- Where: CSE Building Second Floor
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
|
- N/A
|
||||||
|
- ### New Business
|
||||||
|
- The first sprint:
|
||||||
|
- Create more Gitflows and automation. Verify current workflows and actions
|
||||||
|
- Determine interface details for the app (user experience)
|
||||||
|
- Start on the backend
|
||||||
|
- ### Next Meeting's Business
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Linting details decided (TABS NOT SPACES)
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/07/2022 at 8:00PM
|
@@ -1,2 +1,5 @@
|
|||||||
# cse110-fa22-group29
|
# cse110-fa22-group29
|
||||||
[Team Page Link](https://github.com/cse110-fa22-group29/cse110-fa22-group29/blob/main/admin/team.md)
|
|
||||||
|
[Team Page Link](https://github.com/cse110-fa22-group29/cse110-fa22-group29/blob/main/admin/team.md)
|
||||||
|
|
||||||
|
[Food Journal](https://cse110-fa22-group29.github.io/cse110-fa22-group29/)
|
||||||
|
@@ -1,36 +1,39 @@
|
|||||||
# CI/CD Phase 1
|
# CI/CD Phase 1
|
||||||
|
|
||||||
## Overall Pipeline Architecture
|
## Overall Pipeline Architecture
|
||||||
|
|
||||||
Rather than create one large pipeline with many steps which increases complexity, we decided to create many small independent pipelines which work in parallel to conduct code quality checking. Using this strategy, if any one pipeline has issues, we can still continue development without delay, and the quality of code is likely to remain high.
|
Rather than create one large pipeline with many steps which increases complexity, we decided to create many small independent pipelines which work in parallel to conduct code quality checking. Using this strategy, if any one pipeline has issues, we can still continue development without delay, and the quality of code is likely to remain high.
|
||||||
|
|
||||||
## Overview of Pipeline Features
|
## Overview of Pipeline Features
|
||||||
|
|
||||||
We've identified 5 major features which we definitely want to implement in the CI/CD pipeline.
|
We've identified 5 major features which we definitely want to implement in the CI/CD pipeline.
|
||||||
|
|
||||||
- Deployment
|
- Deployment
|
||||||
- Unit Testing
|
- Unit Testing
|
||||||
- Linting
|
- Linting
|
||||||
- End To End Validation
|
- End To End Validation
|
||||||
- Manual Validation
|
- Manual Validation
|
||||||
|
|
||||||
We created this diagram to demonstrate our strategy of multiple simple pipelines.
|
We created this diagram to demonstrate our strategy of multiple simple pipelines.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Finished Features and Implementation
|
## Finished Features and Implementation
|
||||||
|
|
||||||
So far the features listed below have been completed to some degree:
|
So far the features listed below have been completed to some degree:
|
||||||
|
|
||||||
- Deployment
|
- Deployment
|
||||||
- Implemented: action triggered on any push to main, uses the github pages action to publish the app
|
- Implemented: action triggered on any push to main, uses the github pages action to publish the app
|
||||||
- ToDo: Add minifications ste between trigger and github pages action
|
- ToDo: Add minifications ste between trigger and github pages action
|
||||||
- Unit Testing
|
- Unit Testing
|
||||||
- Implemented: action triggers on any PR, uses mocha to perform unit testing on core components
|
- Implemented: action triggers on any PR, uses mocha to perform unit testing on core components
|
||||||
- ToDo: trigger workflow only on certain PRs which relate to JS code
|
- ToDo: trigger workflow only on certain PRs which relate to JS code
|
||||||
- Linting (JS)
|
- Linting (JS)
|
||||||
- Implemented: ction triggers on any PR, uses eslint to perform style enforcement on all JS components
|
- Implemented: ction triggers on any PR, uses eslint to perform style enforcement on all JS components
|
||||||
- ToDo: trigger workflow only on certain PRs which relate to JS code
|
- ToDo: trigger workflow only on certain PRs which relate to JS code
|
||||||
|
- Linting (HTML)
|
||||||
|
- Implemented: action triggers on any PR, uses HTMLhint to perform style enforcement on all HTML components
|
||||||
## Planned Features and Timeline
|
- Linting (CSS)
|
||||||
|
- Implemented: action triggers on any PR, uses Stylelint to perform style enforcement on all CSS components
|
||||||
|
|
||||||
|
## Planned Features and Timeline
|
||||||
|
BIN
admin/cipipeline/phase2.drawio.png
Normal file
After Width: | Height: | Size: 49 KiB |
48
admin/cipipeline/phase2.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# CI/CD Phase 2
|
||||||
|
|
||||||
|
## Overall Pipeline Architecture
|
||||||
|
|
||||||
|
Rather than create one large pipeline with many steps which increases complexity, we decided to create many small independent pipelines which work in parallel to conduct code quality checking. Using this strategy, if any one pipeline has issues, we can still continue development without delay, and the quality of code is likely to remain high.
|
||||||
|
|
||||||
|
## Overview of Pipeline Features
|
||||||
|
|
||||||
|
We've identified 5 major features which we definitely want to implement in the CI/CD pipeline.
|
||||||
|
|
||||||
|
- Deployment
|
||||||
|
- Unit Testing
|
||||||
|
- Linting
|
||||||
|
- End To End Validation
|
||||||
|
- Manual Validation
|
||||||
|
|
||||||
|
We also identified some features which are nice to have:
|
||||||
|
|
||||||
|
- Automatic documentation publishing
|
||||||
|
- Minification
|
||||||
|
- HTML Validation and accessibility scoring
|
||||||
|
|
||||||
|
We created this diagram to demonstrate our strategy of multiple simple pipelines.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Finished Features and Implementation
|
||||||
|
|
||||||
|
So far the features listed below have been completed to some degree:
|
||||||
|
|
||||||
|
- Deployment
|
||||||
|
- Implemented: action triggered on any push to main, uses the github pages action to publish the app
|
||||||
|
- Implemented: uses JSDoc to generate documentation on the same site at [docs](https://cse110-fa22-group29.github.io/cse110-fa22-group29/docs/)
|
||||||
|
- ToDo: Add minification step between trigger and github pages action
|
||||||
|
- Unit Testing
|
||||||
|
- Implemented: action triggers on PR to main, uses mocha to perform unit testing on core components
|
||||||
|
- End to end testing
|
||||||
|
- Implemented: action triggers on PR to main, uses mocha and puppeteer to perform end to end testing
|
||||||
|
- Linting (JS)
|
||||||
|
- Implemented: action triggers on PR to main, uses eslint to perform style enforcement on all JS components
|
||||||
|
- Linting (HTML)
|
||||||
|
- Implemented: action triggers on PR to main, uses HTMLhint to perform style enforcement on all HTML components
|
||||||
|
- Linting (CSS)
|
||||||
|
- Implemented: action triggers on PR to main, uses Stylelint to perform style enforcement on all CSS components
|
||||||
|
- Linting (general)
|
||||||
|
- Implemented: action triggers on PR to main, uses Prettier to perform style checking on all file types
|
||||||
|
|
||||||
|
## Planned Features and Timeline
|
BIN
admin/cipipeline/phase2.mp4
Normal file
@@ -1,47 +1,54 @@
|
|||||||
# Meeting Minutes (10/12/2022)
|
# Meeting Minutes (10/12/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Kickoff Meeting
|
## Team 29: Hackers1995
|
||||||
This meeting is being held to kickoff the start of many meetings to come during the quarter.
|
|
||||||
## Attendance
|
## Meeting Topic: Kickoff Meeting
|
||||||
1. Rhea Bhutada
|
|
||||||
2. George Dubinin
|
This meeting is being held to kickoff the start of many meetings to come during the quarter.
|
||||||
3. Gavyn Ezell
|
|
||||||
4. Henry Feng
|
## Attendance
|
||||||
5. Kara Hoagland
|
|
||||||
6. Marc Reta
|
1. Rhea Bhutada
|
||||||
7. Sanjit Joseph
|
2. George Dubinin
|
||||||
8. Isaac Otero
|
3. Gavyn Ezell
|
||||||
9. Daniel Hernandez
|
4. Henry Feng
|
||||||
|
5. Kara Hoagland
|
||||||
## Absentees
|
6. Marc Reta
|
||||||
1. Arthur Lu
|
7. Sanjit Joseph
|
||||||
|
8. Isaac Otero
|
||||||
## Meeting Details
|
9. Daniel Hernandez
|
||||||
- When: 10/12/2022 at 3:30PM
|
|
||||||
- Where: Zoom
|
## Absentees
|
||||||
|
|
||||||
## Agenda:
|
1. Arthur Lu
|
||||||
- ### Old/Unresolved Business
|
|
||||||
- N/A
|
## Meeting Details
|
||||||
- ### New Business
|
|
||||||
- go over github organization
|
- When: 10/12/2022 at 3:30PM
|
||||||
- review assignments
|
- Where: Zoom
|
||||||
- go through rules
|
|
||||||
- start branding/team name
|
## Agenda:
|
||||||
- ### Next Meeting's Business
|
|
||||||
- figure out roles
|
- ### Old/Unresolved Business
|
||||||
- decide weekly meeting times
|
- N/A
|
||||||
- figure out team bonding events
|
- ### New Business
|
||||||
- brainstorm CRUD applications
|
- go over github organization
|
||||||
- complete any remaining assignments
|
- review assignments
|
||||||
|
- go through rules
|
||||||
## Decisions Made
|
- start branding/team name
|
||||||
- went over github organizations and reviewed the assignments
|
- ### Next Meeting's Business
|
||||||
- went through the rules and agreed on the contract
|
- figure out roles
|
||||||
- figured out the brand name
|
- decide weekly meeting times
|
||||||
|
- figure out team bonding events
|
||||||
## End Time
|
- brainstorm CRUD applications
|
||||||
- 10/12/2022 at 4:30PM
|
- complete any remaining assignments
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- went over github organizations and reviewed the assignments
|
||||||
|
- went through the rules and agreed on the contract
|
||||||
|
- figured out the brand name
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/12/2022 at 4:30PM
|
||||||
|
@@ -1,32 +1,41 @@
|
|||||||
# Meeting Minutes (10/12/2022)
|
# Meeting Minutes (10/12/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Weekly Check-In Meeting
|
## Team 29: Hackers1995
|
||||||
This meeting is the first weekly meeting with TA
|
|
||||||
## Attendance
|
## Meeting Topic: Weekly Check-In Meeting
|
||||||
1. Gagan Gopalaiah
|
|
||||||
2. Rhea Bhutada
|
This meeting is the first weekly meeting with TA
|
||||||
3. Kara Hoagland
|
|
||||||
4. Marc Reta
|
## Attendance
|
||||||
5. Arthur
|
|
||||||
|
1. Gagan Gopalaiah
|
||||||
## Meeting Details
|
2. Rhea Bhutada
|
||||||
- When: 10/12/2022 at 8:00PM
|
3. Kara Hoagland
|
||||||
- Where: Zoom
|
4. Marc Reta
|
||||||
|
5. Arthur
|
||||||
## Agenda:
|
|
||||||
- ### Reviewed Project Details
|
## Meeting Details
|
||||||
- building CRUD app
|
|
||||||
- utilizing HTML, CSS, JavaScript
|
- When: 10/12/2022 at 8:00PM
|
||||||
- general domain is better than specific domain
|
- Where: Zoom
|
||||||
- ### Get Started early
|
|
||||||
- brainstorm CRUD apps
|
## Agenda:
|
||||||
- review assignments
|
|
||||||
- figure out unit test code
|
- ### Reviewed Project Details
|
||||||
- familiarize yourself with GitHub Actions
|
- building CRUD app
|
||||||
|
- utilizing HTML, CSS, JavaScript
|
||||||
## Important Information
|
- general domain is better than specific domain
|
||||||
- Gagan OH (6:30PM-7:30PM on Wednesday) in CSE Basement
|
- ### Get Started early
|
||||||
- Reserved the room if any of us want to meet there. TA not going to present unless required.
|
- brainstorm CRUD apps
|
||||||
|
- review assignments
|
||||||
## End Time
|
- figure out unit test code
|
||||||
- 10/12/2022 at 8:30PM
|
- familiarize yourself with GitHub Actions
|
||||||
|
|
||||||
|
## Important Information
|
||||||
|
|
||||||
|
- Gagan OH (6:30PM-7:30PM on Wednesday) in CSE Basement
|
||||||
|
- Reserved the room if any of us want to meet there. TA not going to present unless required.
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/12/2022 at 8:30PM
|
||||||
|
@@ -1,50 +1,62 @@
|
|||||||
# Meeting Minutes (10/19/2022)
|
# Meeting Minutes (10/19/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Weekly Check-In Meeting
|
## Team 29: Hackers1995
|
||||||
This meeting is the second weekly meeting with TA.
|
|
||||||
|
## Meeting Topic: Weekly Check-In Meeting
|
||||||
## Attendance
|
|
||||||
1. Gagan Gopalaiah
|
This meeting is the second weekly meeting with TA.
|
||||||
2. Rhea Bhutada
|
|
||||||
3. George Dubinin
|
## Attendance
|
||||||
4. Kara Hoagland
|
|
||||||
5. Marc Reta
|
1. Gagan Gopalaiah
|
||||||
6. Arthur Lu
|
2. Rhea Bhutada
|
||||||
7. Gavyn Ezell
|
3. George Dubinin
|
||||||
8. Isaac Otero
|
4. Kara Hoagland
|
||||||
|
5. Marc Reta
|
||||||
## Meeting Details
|
6. Arthur Lu
|
||||||
- When: 10/19/2022 at 8:00PM
|
7. Gavyn Ezell
|
||||||
- Where: Zoom
|
8. Isaac Otero
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
- ### Recap of last week
|
|
||||||
- went over assignments
|
- When: 10/19/2022 at 8:00PM
|
||||||
- discussed feelings on the midterm
|
- Where: Zoom
|
||||||
|
|
||||||
- ### New Potential Meeting Time
|
## Agenda:
|
||||||
- without TA unless necessary
|
|
||||||
- before lecture on Monday in CSE Basement
|
- ### Recap of last week
|
||||||
|
|
||||||
- ### Upcoming Assignments
|
- went over assignments
|
||||||
- two coming up
|
- discussed feelings on the midterm
|
||||||
- brainstorm activity (due 10/23)
|
|
||||||
- continue brainstorming throughout the week
|
- ### New Potential Meeting Time
|
||||||
- due sunday
|
|
||||||
- pitch (11/1)
|
- without TA unless necessary
|
||||||
- initial draft by 10/25 - 10/26
|
- before lecture on Monday in CSE Basement
|
||||||
|
|
||||||
- ### Tips on Designing
|
- ### Upcoming Assignments
|
||||||
- user center design
|
|
||||||
- define the problem first, then the tools/techniques
|
- two coming up
|
||||||
- finalize on the product and its features, then decide on how to build it
|
- brainstorm activity (due 10/23)
|
||||||
|
- continue brainstorming throughout the week
|
||||||
- ### Standup
|
- due sunday
|
||||||
- not expected everyday
|
- pitch (11/1)
|
||||||
- once every two days is ideal
|
- initial draft by 10/25 - 10/26
|
||||||
- doesn't have to be too descriptive
|
|
||||||
|
- ### Tips on Designing
|
||||||
- ### Review of Recent Brainstorming Session
|
|
||||||
|
- user center design
|
||||||
## End Time
|
- define the problem first, then the tools/techniques
|
||||||
- 10/19/2022 at 3:50PM
|
- finalize on the product and its features, then decide on how to build it
|
||||||
|
|
||||||
|
- ### Standup
|
||||||
|
|
||||||
|
- not expected everyday
|
||||||
|
- once every two days is ideal
|
||||||
|
- doesn't have to be too descriptive
|
||||||
|
|
||||||
|
- ### Review of Recent Brainstorming Session
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/19/2022 at 3:50PM
|
||||||
|
@@ -1,44 +1,54 @@
|
|||||||
# Meeting Minutes (10/21/2022)
|
# Meeting Minutes (10/21/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Application Brainstorming
|
## Team 29: Hackers1995
|
||||||
This meeting is held to help the group decide on what application. We will also discuss preliminary designs.
|
|
||||||
## Attendance
|
## Meeting Topic: Application Brainstorming
|
||||||
1. George Dubinin
|
|
||||||
2. Gavyn Ezell
|
This meeting is held to help the group decide on what application. We will also discuss preliminary designs.
|
||||||
3. Henry Feng
|
|
||||||
4. Arthur Lu
|
## Attendance
|
||||||
5. Marc Reta
|
|
||||||
6. Kara Hoagland
|
1. George Dubinin
|
||||||
7. Sanjit Joseph
|
2. Gavyn Ezell
|
||||||
8. Rhea Bhutada
|
3. Henry Feng
|
||||||
9. Isaac Otero
|
4. Arthur Lu
|
||||||
10. Daniel Hernandez
|
5. Marc Reta
|
||||||
|
6. Kara Hoagland
|
||||||
## Absentees
|
7. Sanjit Joseph
|
||||||
N/A
|
8. Rhea Bhutada
|
||||||
|
9. Isaac Otero
|
||||||
## Meeting Details
|
10. Daniel Hernandez
|
||||||
- When:
|
|
||||||
- 10/21/2022 at 10:00AM
|
## Absentees
|
||||||
- 10/21/2022 at 1:30PM
|
|
||||||
- Where: Zoom
|
N/A
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
- ### Old/Unresolved Business
|
|
||||||
- N/A
|
- When:
|
||||||
- ### New Business
|
- 10/21/2022 at 10:00AM
|
||||||
- List ideas that have been shared so far
|
- 10/21/2022 at 1:30PM
|
||||||
- List new ideas/ideas that haven't been recorded on the doc yet
|
- Where: Zoom
|
||||||
- Discuss, vote, and decide on one idea
|
|
||||||
- ### Next Meeting's Business
|
## Agenda:
|
||||||
- Discuss design features for the chosen app
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
## Decisions Made
|
- N/A
|
||||||
- Added UCSD Food Reviewer App idea to the brainstorming doc
|
- ### New Business
|
||||||
- The 10AM group cast 3 votes for the Social Media Auxilary and 1 vote for the UCSD Food Reviewer App (one participant voted twice)
|
- List ideas that have been shared so far
|
||||||
- The 1:30PM group cast 7 votes for the UCSD Food Reviewer App and 5 votes for the Copy/Paste App
|
- List new ideas/ideas that haven't been recorded on the doc yet
|
||||||
- We will move forward with the UCSD Food Reviewer App
|
- Discuss, vote, and decide on one idea
|
||||||
|
- ### Next Meeting's Business
|
||||||
## End Time
|
- Discuss design features for the chosen app
|
||||||
- 10/21/2022 at 11:00AM
|
|
||||||
- 10/21/2022 at 2:30PM
|
## Decisions Made
|
||||||
|
|
||||||
|
- Added UCSD Food Reviewer App idea to the brainstorming doc
|
||||||
|
- The 10AM group cast 3 votes for the Social Media Auxilary and 1 vote for the UCSD Food Reviewer App (one participant voted twice)
|
||||||
|
- The 1:30PM group cast 7 votes for the UCSD Food Reviewer App and 5 votes for the Copy/Paste App
|
||||||
|
- We will move forward with the UCSD Food Reviewer App
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/21/2022 at 11:00AM
|
||||||
|
- 10/21/2022 at 2:30PM
|
||||||
|
@@ -1,40 +1,50 @@
|
|||||||
# Meeting Minutes (10/23/2022)
|
# Meeting Minutes (10/23/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Application Final Decision
|
## Team 29: Hackers1995
|
||||||
This meeting is held to help the group decide on which kind of app to build.
|
|
||||||
## Attendance
|
## Meeting Topic: Application Final Decision
|
||||||
1. George Dubinin
|
|
||||||
2. Henry Feng
|
This meeting is held to help the group decide on which kind of app to build.
|
||||||
3. Arthur Lu
|
|
||||||
4. Marc Reta
|
## Attendance
|
||||||
5. Kara Hoagland
|
|
||||||
6. Rhea Bhutada
|
1. George Dubinin
|
||||||
7. Isaac Otero
|
2. Henry Feng
|
||||||
|
3. Arthur Lu
|
||||||
## Absentees
|
4. Marc Reta
|
||||||
1. Sanjit Joseph
|
5. Kara Hoagland
|
||||||
2. Gavyn Ezell
|
6. Rhea Bhutada
|
||||||
3. Daniel Hernandez
|
7. Isaac Otero
|
||||||
|
|
||||||
## Meeting Details
|
## Absentees
|
||||||
- When:
|
|
||||||
- 10/23/2022 at 1:00PM
|
1. Sanjit Joseph
|
||||||
- Where: Zoom (Rhea's Meeting Room)
|
2. Gavyn Ezell
|
||||||
|
3. Daniel Hernandez
|
||||||
## Agenda:
|
|
||||||
- ### Old/Unresolved Business
|
## Meeting Details
|
||||||
- N/A
|
|
||||||
- ### New Business
|
- When:
|
||||||
- Decide on a final app idea
|
- 10/23/2022 at 1:00PM
|
||||||
- ### Next Meeting's Business
|
- Where: Zoom (Rhea's Meeting Room)
|
||||||
- Discuss design features for the chosen app
|
|
||||||
|
## Agenda:
|
||||||
## Decisions Made
|
|
||||||
- Maybe for the food reviewer app. Presenting possible writeup to Gagan
|
- ### Old/Unresolved Business
|
||||||
- Maybe for the resume builder. Presenting possible writeup to Gagan https://docs.google.com/document/d/1zdvVxd47Ivdz-D0rZGNJqc3D9GiQj0n_xMJKapOV39A/edit?usp=sharing
|
- N/A
|
||||||
- Maybe for Social Media Local Archive. Presenting possible writeup to Gagan https://docs.google.com/document/d/1upNr6lneB2uzCoQ12_aa1CMg1W8p2NBFb6xmP7i4-z4/edit?usp=sharing
|
- ### New Business
|
||||||
- No to the copy/paste app (not local first)
|
- Decide on a final app idea
|
||||||
|
- ### Next Meeting's Business
|
||||||
## End Time
|
- Discuss design features for the chosen app
|
||||||
- When:
|
|
||||||
- 10/23/2022 at 2:00PM
|
## Decisions Made
|
||||||
|
|
||||||
|
- Maybe for the food reviewer app. Presenting possible writeup to Gagan
|
||||||
|
- Maybe for the resume builder. Presenting possible writeup to Gagan https://docs.google.com/document/d/1zdvVxd47Ivdz-D0rZGNJqc3D9GiQj0n_xMJKapOV39A/edit?usp=sharing
|
||||||
|
- Maybe for Social Media Local Archive. Presenting possible writeup to Gagan https://docs.google.com/document/d/1upNr6lneB2uzCoQ12_aa1CMg1W8p2NBFb6xmP7i4-z4/edit?usp=sharing
|
||||||
|
- No to the copy/paste app (not local first)
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- When:
|
||||||
|
- 10/23/2022 at 2:00PM
|
||||||
|
@@ -1,44 +1,54 @@
|
|||||||
# Meeting Minutes (10/26/2022)
|
# Meeting Minutes (10/26/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Weekly Check-In Meeting
|
## Team 29: Hackers1995
|
||||||
This is our third weekly meeting with Gagan.
|
|
||||||
|
## Meeting Topic: Weekly Check-In Meeting
|
||||||
## Attendance
|
|
||||||
TA. Gagan Gopalaiah
|
This is our third weekly meeting with Gagan.
|
||||||
1. Rhea Bhutada
|
|
||||||
2. George Dubinin
|
## Attendance
|
||||||
3. Sanjit Joseph
|
|
||||||
4. Arthur Lu
|
TA. Gagan Gopalaiah
|
||||||
5. Gavyn Ezell
|
|
||||||
|
1. Rhea Bhutada
|
||||||
## Meeting Details
|
2. George Dubinin
|
||||||
- When: 10/26/2022 at 3:00 PM
|
3. Sanjit Joseph
|
||||||
- Where: Zoom (Gagan's Zoom room: https://ucsd.zoom.us/j/5177090642)
|
4. Arthur Lu
|
||||||
|
5. Gavyn Ezell
|
||||||
## Agenda:
|
|
||||||
- ### Present our ideas to Gagan
|
## Meeting Details
|
||||||
- All ideas seem to be doable
|
|
||||||
- Consider a few tweaks to "CRUDify" apps
|
- When: 10/26/2022 at 3:00 PM
|
||||||
- Gagan is partial to food review app idea, but any of them can work
|
- Where: Zoom (Gagan's Zoom room: https://ucsd.zoom.us/j/5177090642)
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
- ### Tips for projects
|
|
||||||
- SOCIAL MEDIA ORGANIZER: avoid API integration if possible/only make it a small part, not a main feature
|
- ### Present our ideas to Gagan
|
||||||
- RESUME BUILDER: try to "CRUDify" it more if we're going for this
|
|
||||||
|
- All ideas seem to be doable
|
||||||
- ### Standups
|
- Consider a few tweaks to "CRUDify" apps
|
||||||
- Once per 2 days, 3 in worst case
|
- Gagan is partial to food review app idea, but any of them can work
|
||||||
- Perhaps make a separate slack channel for these to avoid clutter
|
|
||||||
|
- ### Tips for projects
|
||||||
## Moving forward:
|
|
||||||
- ### BY FRIDAY:
|
- SOCIAL MEDIA ORGANIZER: avoid API integration if possible/only make it a small part, not a main feature
|
||||||
- Try and meet tomorrow (10/27) to make a final decision
|
- RESUME BUILDER: try to "CRUDify" it more if we're going for this
|
||||||
- Let Gagan know what we've decided on
|
|
||||||
- Complete project pitch assignment - need to present to Gagan tomorrow 10/27, due on canvas 11/1
|
- ### Standups
|
||||||
|
- Once per 2 days, 3 in worst case
|
||||||
- ### OVER WEEKEND:
|
- Perhaps make a separate slack channel for these to avoid clutter
|
||||||
- (If possible) Start on CI/CD pipeline (basic js app/unit tests, use Github actions to set up)
|
|
||||||
|
## Moving forward:
|
||||||
|
|
||||||
## End Time
|
- ### BY FRIDAY:
|
||||||
- 10/26/2022 at 4:00 PM
|
|
||||||
|
- Try and meet tomorrow (10/27) to make a final decision
|
||||||
|
- Let Gagan know what we've decided on
|
||||||
|
- Complete project pitch assignment - need to present to Gagan tomorrow 10/27, due on canvas 11/1
|
||||||
|
|
||||||
|
- ### OVER WEEKEND:
|
||||||
|
- (If possible) Start on CI/CD pipeline (basic js app/unit tests, use Github actions to set up)
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/26/2022 at 4:00 PM
|
||||||
|
@@ -1,60 +1,69 @@
|
|||||||
# Meeting Minutes (10/27/2022)
|
# Meeting Minutes (10/27/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Final Project Decision
|
## Team 29: Hackers1995
|
||||||
We're figuring out what project we're going to do, and figure out what we need for the starting pitch.
|
|
||||||
|
## Meeting Topic: Final Project Decision
|
||||||
## Attendance
|
|
||||||
1. Rhea Bhutada
|
We're figuring out what project we're going to do, and figure out what we need for the starting pitch.
|
||||||
2. Sanjit Joseph
|
|
||||||
3. Arthur Lu
|
## Attendance
|
||||||
4. Henry Feng
|
|
||||||
5. Marc Reta
|
1. Rhea Bhutada
|
||||||
6. Kara Hoagland
|
2. Sanjit Joseph
|
||||||
7. Daniel Hernandez
|
3. Arthur Lu
|
||||||
8. Gavyn Ezell
|
4. Henry Feng
|
||||||
9. Isaac Otero
|
5. Marc Reta
|
||||||
|
6. Kara Hoagland
|
||||||
## Meeting Details
|
7. Daniel Hernandez
|
||||||
- When: 10/27/2022 at 5:00 PM
|
8. Gavyn Ezell
|
||||||
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
|
9. Isaac Otero
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
- ### Decide which project we're doing
|
|
||||||
- Gagan seemed to like the food review app idea best in their current states
|
- When: 10/27/2022 at 5:00 PM
|
||||||
- We all seem to agree that the food review app is acceptable
|
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
|
||||||
- Made a couple clarifications, no major changes or objections to the app
|
|
||||||
|
## Agenda:
|
||||||
- ### Start project pitch
|
|
||||||
- Created google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing**
|
- ### Decide which project we're doing
|
||||||
- Prof recommends skimming the book: **https://basecamp.com/shapeup** (esp. ch.5 on risks and rabbit holes)
|
|
||||||
- Finishing Risks + Rabbit holes here in the meeting
|
- Gagan seemed to like the food review app idea best in their current states
|
||||||
- Kara posted a design prototype in Slack: https://cse110fall2022.slack.com/archives/C04598WA7P1/p1666918573779859
|
- We all seem to agree that the food review app is acceptable
|
||||||
|
- Made a couple clarifications, no major changes or objections to the app
|
||||||
- ### App Description
|
|
||||||
- Renaming it to a "Food Diary" app, not limited to UCSD
|
- ### Start project pitch
|
||||||
- Allows users to store info about recent foods, restaurant name, location, price, your rating etc.
|
|
||||||
- Probably provides food suggestions based on where you've eaten (and liked) before
|
- Created google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing**
|
||||||
- We're not going to try anything with external data atm.
|
- Prof recommends skimming the book: **https://basecamp.com/shapeup** (esp. ch.5 on risks and rabbit holes)
|
||||||
|
- Finishing Risks + Rabbit holes here in the meeting
|
||||||
|
- Kara posted a design prototype in Slack: https://cse110fall2022.slack.com/archives/C04598WA7P1/p1666918573779859
|
||||||
## Moving forward:
|
|
||||||
- ### BY TOMORROW:
|
- ### App Description
|
||||||
- FINISH PITCH SLIDES
|
- Renaming it to a "Food Diary" app, not limited to UCSD
|
||||||
- MUST CHANGE DIAGRAM TO ALL RESTAURANTS (Isaac will change this)
|
- Allows users to store info about recent foods, restaurant name, location, price, your rating etc.
|
||||||
- Daniel will update the pitch slides by adding images/graphics.
|
- Probably provides food suggestions based on where you've eaten (and liked) before
|
||||||
- Daniel + Sanjit are doing visual representation.
|
- We're not going to try anything with external data atm.
|
||||||
- Gayvn is doing potential competitors
|
|
||||||
- Henry, Sanjit, Kara are doing user personas
|
## Moving forward:
|
||||||
- Rhea is doing statement + purpose
|
|
||||||
- Arthur + Marc are doing "why it's a CRUD app"
|
- ### BY TOMORROW:
|
||||||
|
|
||||||
- See if we can have a short meeting tomorrow before meeting Gagan just to review our pitch.
|
- FINISH PITCH SLIDES
|
||||||
- Put all components in specs folder before pitch
|
- MUST CHANGE DIAGRAM TO ALL RESTAURANTS (Isaac will change this)
|
||||||
- Meet at 2:30? Meeting with Gagan is probably at 3:30
|
- Daniel will update the pitch slides by adding images/graphics.
|
||||||
|
- Daniel + Sanjit are doing visual representation.
|
||||||
- ### LATER:
|
- Gayvn is doing potential competitors
|
||||||
- Have some people split off and work on the basic UI design. Technically Sanjit had the 'art role' according to the TA but not sure what that entails. More ppl would def be helpful. TBD who else is helping
|
- Henry, Sanjit, Kara are doing user personas
|
||||||
|
- Rhea is doing statement + purpose
|
||||||
|
- Arthur + Marc are doing "why it's a CRUD app"
|
||||||
## End Time
|
|
||||||
- 10/27/2022 at 6:15 PM
|
- See if we can have a short meeting tomorrow before meeting Gagan just to review our pitch.
|
||||||
|
- Put all components in specs folder before pitch
|
||||||
|
- Meet at 2:30? Meeting with Gagan is probably at 3:30
|
||||||
|
|
||||||
|
- ### LATER:
|
||||||
|
- Have some people split off and work on the basic UI design. Technically Sanjit had the 'art role' according to the TA but not sure what that entails. More ppl would def be helpful. TBD who else is helping
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/27/2022 at 6:15 PM
|
||||||
|
@@ -1,24 +1,31 @@
|
|||||||
# Meeting Minutes (10/28/2022)
|
# Meeting Minutes (10/28/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Project Pitch
|
## Team 29: Hackers1995
|
||||||
We finished up the project pitch docs and presenting them to Gagan.
|
|
||||||
|
## Meeting Topic: Project Pitch
|
||||||
Google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing**
|
|
||||||
|
We finished up the project pitch docs and presenting them to Gagan.
|
||||||
## Meeting Details
|
|
||||||
- When: 10/28/2022 at 2:30 PM
|
Google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing**
|
||||||
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
|
|
||||||
|
## Meeting Details
|
||||||
## Agenda:
|
|
||||||
- ### Finish Project Pitch documents
|
- When: 10/28/2022 at 2:30 PM
|
||||||
- Finished user stories/diagrams and uploaded to github
|
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
|
||||||
- Went over presentation before showing TA
|
|
||||||
- Presented project to Gagan
|
## Agenda:
|
||||||
- **Overall reaction - he liked our app! More feedback to come, but we can feel free to start some basic work.**
|
|
||||||
|
- ### Finish Project Pitch documents
|
||||||
## Moving forward:
|
- Finished user stories/diagrams and uploaded to github
|
||||||
- I think we need to upload our project pitch to canvas by 11/1
|
- Went over presentation before showing TA
|
||||||
- Start on the really basic stuff as discussed in lecture (hello world for CI/CD setup, etc)
|
- Presented project to Gagan
|
||||||
|
- **Overall reaction - he liked our app! More feedback to come, but we can feel free to start some basic work.**
|
||||||
## End Time
|
|
||||||
- 10/28/2022 at 4:00 PM
|
## Moving forward:
|
||||||
|
|
||||||
|
- I think we need to upload our project pitch to canvas by 11/1
|
||||||
|
- Start on the really basic stuff as discussed in lecture (hello world for CI/CD setup, etc)
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 10/28/2022 at 4:00 PM
|
||||||
|
@@ -1,41 +1,50 @@
|
|||||||
# Meeting Minutes (11/01/2022)
|
# Meeting Minutes (11/01/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Work going forward
|
## Team 29: Hackers1995
|
||||||
We're trying to figure out what our goals are for the project and how to get started.
|
|
||||||
|
## Meeting Topic: Work going forward
|
||||||
## Meeting Details
|
|
||||||
- When: 11/01/2022 at 7:00 PM
|
We're trying to figure out what our goals are for the project and how to get started.
|
||||||
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
|
|
||||||
|
## Meeting Details
|
||||||
## Attendance
|
|
||||||
1. Rhea
|
- When: 11/01/2022 at 7:00 PM
|
||||||
2. Gavyn
|
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
|
||||||
3. Isaac
|
|
||||||
4. Kara
|
## Attendance
|
||||||
5. Marc
|
|
||||||
6. Henry
|
1. Rhea
|
||||||
7. Daniel
|
2. Gavyn
|
||||||
8. Sanjit
|
3. Isaac
|
||||||
|
4. Kara
|
||||||
## Notes:
|
5. Marc
|
||||||
- Gagan suggests we have a feature backlog and pull stuff from that
|
6. Henry
|
||||||
- Using Github Issues for our feature backlog
|
7. Daniel
|
||||||
|
8. Sanjit
|
||||||
- Perhaps integrate TTS from Lab5 into something (pick a random restaurant while driving, etc)
|
|
||||||
|
## Notes:
|
||||||
- Created figma sketch for app design, uploaded to github and google slides
|
|
||||||
|
- Gagan suggests we have a feature backlog and pull stuff from that
|
||||||
## Moving forward:
|
- Using Github Issues for our feature backlog
|
||||||
- ### BY TONIGHT:
|
|
||||||
- We'll submit our pitch files
|
- Perhaps integrate TTS from Lab5 into something (pick a random restaurant while driving, etc)
|
||||||
- ### LATER:
|
|
||||||
- Sanjit will upload a basic hello world program in order to test deployment/github actions
|
- Created figma sketch for app design, uploaded to github and google slides
|
||||||
- Arthur will start figuring out how to configure github actions
|
|
||||||
|
## Moving forward:
|
||||||
- ### PREFERENCES:
|
|
||||||
- BACKEND: Henry, Gavyn, Kara
|
- ### BY TONIGHT:
|
||||||
- FRONTEND: Isaac
|
- We'll submit our pitch files
|
||||||
- NO PREFERENCE: Daniel, Marc, Rhea, Sanjit
|
- ### LATER:
|
||||||
|
|
||||||
## End Time
|
- Sanjit will upload a basic hello world program in order to test deployment/github actions
|
||||||
- 11/01/2022 at 9:00 PM
|
- Arthur will start figuring out how to configure github actions
|
||||||
|
|
||||||
|
- ### PREFERENCES:
|
||||||
|
- BACKEND: Henry, Gavyn, Kara
|
||||||
|
- FRONTEND: Isaac
|
||||||
|
- NO PREFERENCE: Daniel, Marc, Rhea, Sanjit
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/01/2022 at 9:00 PM
|
||||||
|
@@ -1,34 +1,39 @@
|
|||||||
# Meeting Minutes (11/02/2022)
|
# Meeting Minutes (11/02/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Weekly TA Catchup with Gagan
|
## Team 29: Hackers1995
|
||||||
We are meeting with Gagan to discuss early phase design concepts and decisions we need to think about as we start the early coding phase.
|
|
||||||
|
## Meeting Topic: Weekly TA Catchup with Gagan
|
||||||
## Attendance
|
|
||||||
1. Rhea Bhutada
|
We are meeting with Gagan to discuss early phase design concepts and decisions we need to think about as we start the early coding phase.
|
||||||
2. George Dubinin
|
|
||||||
3. Gagan Gopalaiah
|
## Attendance
|
||||||
|
|
||||||
## Meeting Details
|
1. Rhea Bhutada
|
||||||
- When: 11/02/2022 at 3:30PM
|
2. George Dubinin
|
||||||
- Where: Zoom
|
3. Gagan Gopalaiah
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
|
|
||||||
## Discussion Points by Gagan
|
- When: 11/02/2022 at 3:30PM
|
||||||
- Now that we finished designs stage there are 2 approaches
|
- Where: Zoom
|
||||||
- The first is to just start coding without thinking about design (cowboy coding). It works but can get bumpy down the road
|
|
||||||
- The second is to look at the project from a birds eye view and break it down into milestones and tasks. First break it down into weeks and then decide on what to do each day of the week. This will make it easier to keep things organized.
|
## Agenda:
|
||||||
- Jira and GitHub issues will be super helpful. Jira is a more expensive option so instead prof recommends creating issues.
|
|
||||||
- Start thinking about storage options. Think local first and decide on options like:
|
## Discussion Points by Gagan
|
||||||
- locally stored json files
|
|
||||||
- browser local storage
|
- Now that we finished designs stage there are 2 approaches
|
||||||
- "real" database like IndexDB
|
- The first is to just start coding without thinking about design (cowboy coding). It works but can get bumpy down the road
|
||||||
- Think about different models to keep track of changes and versions. Consider the branching model (one central repository and everyone has a branch or one breanch per feature) and the forking model (the central repository is copied and developers work in these copies and push changes to their own copies before syncing to the central repo). Useful info here: https://www.flagship.io/git-branching-strategies/
|
- The second is to look at the project from a birds eye view and break it down into milestones and tasks. First break it down into weeks and then decide on what to do each day of the week. This will make it easier to keep things organized.
|
||||||
- Think about how pull requests will be approved and create a system for PR review and suggests.
|
- Jira and GitHub issues will be super helpful. Jira is a more expensive option so instead prof recommends creating issues.
|
||||||
- Break down the project and decide on which tasks to be completed. Then decide on how long sprints will last and how tasks will be assigned.
|
- Start thinking about storage options. Think local first and decide on options like:
|
||||||
- We need to create the ADR and place it in the brainstorming section of the repo. This will contain details about specific project decisions that we made like database decisions (for example).
|
- locally stored json files
|
||||||
|
- browser local storage
|
||||||
## End Time
|
- "real" database like IndexDB
|
||||||
- 11/02/2022 at 4:00PM
|
- Think about different models to keep track of changes and versions. Consider the branching model (one central repository and everyone has a branch or one breanch per feature) and the forking model (the central repository is copied and developers work in these copies and push changes to their own copies before syncing to the central repo). Useful info here: https://www.flagship.io/git-branching-strategies/
|
||||||
|
- Think about how pull requests will be approved and create a system for PR review and suggests.
|
||||||
|
- Break down the project and decide on which tasks to be completed. Then decide on how long sprints will last and how tasks will be assigned.
|
||||||
|
- We need to create the ADR and place it in the brainstorming section of the repo. This will contain details about specific project decisions that we made like database decisions (for example).
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/02/2022 at 4:00PM
|
||||||
|
@@ -1,44 +1,48 @@
|
|||||||
# Meeting Minutes (11/03/2022)
|
# Meeting Minutes (11/03/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Technologies Discussion
|
## Team 29: Hackers1995
|
||||||
We're deciding on what web technologies we will incorporate into our food blog application.
|
|
||||||
|
## Meeting Topic: Technologies Discussion
|
||||||
## Attendance
|
|
||||||
1. Rhea Bhutada
|
We're deciding on what web technologies we will incorporate into our food blog application.
|
||||||
2. Sanjit Joseph
|
|
||||||
3. Arthur Lu
|
## Attendance
|
||||||
4. Henry Feng
|
|
||||||
5. Marc Reta
|
1. Rhea Bhutada
|
||||||
6. Kara Hoagland
|
2. Sanjit Joseph
|
||||||
7. Daniel Hernandez
|
3. Arthur Lu
|
||||||
8. Gavyn Ezell
|
4. Henry Feng
|
||||||
9. Isaac Otero
|
5. Marc Reta
|
||||||
|
6. Kara Hoagland
|
||||||
## Meeting Details
|
7. Daniel Hernandez
|
||||||
- When: 11/03/2022 at 3:00PM
|
8. Gavyn Ezell
|
||||||
- Where: In-person (CSE Basement B250) and George's Zoom room
|
9. Isaac Otero
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
- ### Answer the questions that Gagan's asked the team leads yesterday
|
|
||||||
- What high level approach will we have to coding?
|
- When: 11/03/2022 at 3:00PM
|
||||||
- Slow approach with diagrams and short sprints of around 3 days. Biweekly meetings where we catch up with what happened end of each sprint.
|
- Where: In-person (CSE Basement B250) and George's Zoom room
|
||||||
- What issue tracker will we use?
|
|
||||||
- Use GitHub issues for tracking. Assign and breakdown tasks at the begining of each sprint.
|
## Agenda:
|
||||||
- What database will we use?
|
|
||||||
- Rely on localStorage short-term and implement a non-relational database like MongoDB later.
|
- ### Answer the questions that Gagan's asked the team leads yesterday
|
||||||
- What branching/forking strategy will we use
|
- What high level approach will we have to coding?
|
||||||
- We will be creating branches for different features and be submitting PRs direclty to the master branch. Forks will only be created for large overhaul type changes
|
- Slow approach with diagrams and short sprints of around 3 days. Biweekly meetings where we catch up with what happened end of each sprint.
|
||||||
- How will PRs be approved
|
- What issue tracker will we use?
|
||||||
- The team will be split up into groups for different aspects of the app (front end, ui, database for example) and PRs will be reviewed and approved by 1 other member of the respective group
|
- Use GitHub issues for tracking. Assign and breakdown tasks at the begining of each sprint.
|
||||||
- Introduce the ADR and discuss how we will create it
|
- What database will we use?
|
||||||
-
|
- Rely on localStorage short-term and implement a non-relational database like MongoDB later.
|
||||||
|
- What branching/forking strategy will we use
|
||||||
|
- We will be creating branches for different features and be submitting PRs direclty to the master branch. Forks will only be created for large overhaul type changes
|
||||||
|
- How will PRs be approved
|
||||||
## Assignments:
|
- The team will be split up into groups for different aspects of the app (front end, ui, database for example) and PRs will be reviewed and approved by 1 other member of the respective group
|
||||||
- ### By X point in time:
|
- ## Introduce the ADR and discuss how we will create it
|
||||||
-
|
|
||||||
|
## Assignments:
|
||||||
|
|
||||||
## End Time
|
- ### By X point in time:
|
||||||
- 11/03/2022 at 4:00 PM
|
-
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/03/2022 at 4:00 PM
|
||||||
|
@@ -1,32 +1,41 @@
|
|||||||
# Meeting Minutes (11/04/2022)
|
# Meeting Minutes (11/04/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Technologies Discussion
|
## Team 29: Hackers1995
|
||||||
We're planning out our first sprint and breaking up the project into tasks. Tasks will be assigned to groups and GitHub issues will be created
|
|
||||||
for each task and assigned to a group.
|
## Meeting Topic: Technologies Discussion
|
||||||
|
|
||||||
## Attendance
|
We're planning out our first sprint and breaking up the project into tasks. Tasks will be assigned to groups and GitHub issues will be created
|
||||||
1. Rhea Bhutada
|
for each task and assigned to a group.
|
||||||
2. Sanjit Joseph
|
|
||||||
3. Arthur Lu
|
## Attendance
|
||||||
4. Marc Reta
|
|
||||||
6. Kara Hoagland
|
1. Rhea Bhutada
|
||||||
7. Daniel Hernandez
|
2. Sanjit Joseph
|
||||||
8. Gavyn Ezell
|
3. Arthur Lu
|
||||||
9. Isaac Otero
|
4. Marc Reta
|
||||||
10. Henry Feng
|
5. Kara Hoagland
|
||||||
|
6. Daniel Hernandez
|
||||||
## Meeting Details
|
7. Gavyn Ezell
|
||||||
- When: 11/04/2022 at 10:00AM
|
8. Isaac Otero
|
||||||
- Where: George's Zoom room
|
9. Henry Feng
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
## Sprint 1 Categories and Assignments
|
|
||||||
Frontend: Isaac, Sanjit, and Daniel
|
- When: 11/04/2022 at 10:00AM
|
||||||
Backend: Rhea, George, Gavyn, Kara,
|
- Where: George's Zoom room
|
||||||
- Save to database
|
|
||||||
- Load from database
|
## Agenda:
|
||||||
- Clear database
|
|
||||||
Unit Testing: Arthur, Marc
|
## Sprint 1 Categories and Assignments
|
||||||
|
|
||||||
## End Time
|
Frontend: Isaac, Sanjit, and Daniel
|
||||||
- 11/03/2022 at 10:30 AM
|
Backend: Rhea, George, Gavyn, Kara,
|
||||||
|
|
||||||
|
- Save to database
|
||||||
|
- Load from database
|
||||||
|
- Clear database
|
||||||
|
Unit Testing: Arthur, Marc
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/03/2022 at 10:30 AM
|
||||||
|
@@ -1,41 +0,0 @@
|
|||||||
# Meeting Minutes (11/07/2022)
|
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: First Sprint
|
|
||||||
Meeting notes for the first sprint
|
|
||||||
|
|
||||||
## Attendance
|
|
||||||
1. Rhea Bhutada
|
|
||||||
2. George Dubinin
|
|
||||||
3. Gavyn Ezell
|
|
||||||
4. Henry Feng
|
|
||||||
5. Kara Hoagland
|
|
||||||
6. Marc Reta
|
|
||||||
7. Sanjit Joseph
|
|
||||||
8. Daniel Hernandez
|
|
||||||
9. Arthur Lu
|
|
||||||
|
|
||||||
## Absentees
|
|
||||||
1. Isaac Otero
|
|
||||||
|
|
||||||
## Meeting Details
|
|
||||||
- When: 11/07/2022 at 6:00PM
|
|
||||||
- Where: CSE Building Second Floor
|
|
||||||
|
|
||||||
## Agenda:
|
|
||||||
- ### Old/Unresolved Business
|
|
||||||
- N/A
|
|
||||||
- ### New Business
|
|
||||||
- The first sprint:
|
|
||||||
- Create more Gitflows and automation. Verify current workflows and actions
|
|
||||||
- Determine interface details for the app (user experience)
|
|
||||||
- Start on the backend
|
|
||||||
- ### Next Meeting's Business
|
|
||||||
|
|
||||||
## Decisions Made
|
|
||||||
- Linting details decided (TABS NOT SPACES)
|
|
||||||
|
|
||||||
## End Time
|
|
||||||
- 11/07/2022 at 8:00PM
|
|
||||||
|
|
||||||
|
|
||||||
|
|
45
admin/meetings/110822-sprint1day2.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Meeting Minutes (11/08/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: In-Person First Sprint Day 2
|
||||||
|
|
||||||
|
Meeting notes for the first sprint
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gavyn Ezell
|
||||||
|
4. Kara Hoagland
|
||||||
|
5. Sanjit Joseph
|
||||||
|
6. Daniel Hernandez
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/08/2022 at 2:00PM
|
||||||
|
- Where: Mike's Red Tacos
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
|
- N/A
|
||||||
|
- ### New Business
|
||||||
|
- Isaac now knows what Wolftown is
|
||||||
|
- Pair programming setup with VSCode
|
||||||
|
- ### Next Meeting's Business
|
||||||
|
|
||||||
|
## App Progress
|
||||||
|
|
||||||
|
- The landing page is closer
|
||||||
|
- Review card css file entered
|
||||||
|
- Review Card javascript logic implemented (thanks Gavin)
|
||||||
|
-
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Linting details decided (TABS NOT SPACES)
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/07/2022 at 8:00PM
|
@@ -1,36 +1,43 @@
|
|||||||
# Meeting Minutes (11/09/2022)
|
# Meeting Minutes (11/09/2022)
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: Weekly TA Catchup with Gagan
|
## Team 29: Hackers1995
|
||||||
We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing.
|
|
||||||
|
## Meeting Topic: Weekly TA Catchup with Gagan
|
||||||
## Attendance
|
|
||||||
1. Rhea Bhutada
|
We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing.
|
||||||
2. George Dubinin
|
|
||||||
3. Gagan Gopalaiah
|
## Attendance
|
||||||
4. Sanjit Joseph
|
|
||||||
|
1. Rhea Bhutada
|
||||||
## Meeting Details
|
2. George Dubinin
|
||||||
- When: 11/09/2022 at 3:30PM
|
3. Gagan Gopalaiah
|
||||||
- Where: Zoom
|
4. Sanjit Joseph
|
||||||
|
|
||||||
## Agenda:
|
## Meeting Details
|
||||||
|
|
||||||
## Discussion Points by Gagan
|
- When: 11/09/2022 at 3:30PM
|
||||||
- Provided updates on first sprint
|
- Where: Zoom
|
||||||
- Testing Tips
|
|
||||||
- functionality testing
|
## Agenda:
|
||||||
- test one feature
|
|
||||||
- test individual functions
|
## Discussion Points by Gagan
|
||||||
- static testing
|
|
||||||
- checking if its meeting the conventions and standards for specific programming language
|
- Provided updates on first sprint
|
||||||
- linting
|
- Testing Tips
|
||||||
- specific to programming language
|
- functionality testing
|
||||||
- overall
|
- test one feature
|
||||||
- if tested properly, we reduce problems end-to-end testing
|
- test individual functions
|
||||||
- Documentation
|
- static testing
|
||||||
- What the code does?
|
- checking if its meeting the conventions and standards for specific programming language
|
||||||
- What the file is for?
|
- linting
|
||||||
- JS Docs
|
- specific to programming language
|
||||||
|
- overall
|
||||||
## End Time
|
- if tested properly, we reduce problems end-to-end testing
|
||||||
- 11/09/2022 at 4:00PM
|
- Documentation
|
||||||
|
- What the code does?
|
||||||
|
- What the file is for?
|
||||||
|
- JS Docs
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/09/2022 at 4:00PM
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
# Sprint 1 Retrospective (11/14/2022)
|
# Sprint 1 Retrospective (11/14/2022)
|
||||||
|
|
||||||
## Team 29: Hackers1995
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
## Meeting Topic: Sprint 1 Retrospective
|
## Meeting Topic: Sprint 1 Retrospective
|
||||||
|
|
||||||
## Attendance
|
## Attendance
|
||||||
|
|
||||||
1. Rhea Bhutada
|
1. Rhea Bhutada
|
||||||
2. George Dubinin
|
2. George Dubinin
|
||||||
3. Sanjit Joseph
|
3. Sanjit Joseph
|
||||||
@@ -15,54 +18,64 @@
|
|||||||
10. Isaac Otero
|
10. Isaac Otero
|
||||||
|
|
||||||
## Meeting Details
|
## Meeting Details
|
||||||
- When: 11/14/2022 at 4:30PM
|
|
||||||
- Where: On Campus
|
- When: 11/14/2022 at 4:30PM
|
||||||
|
- Where: On Campus
|
||||||
|
|
||||||
## Agenda:
|
## Agenda:
|
||||||
|
|
||||||
Discuss the review, share more detailed thoughts on sprint 1, and create some resolutions for sprint 2
|
Discuss the review, share more detailed thoughts on sprint 1, and create some resolutions for sprint 2
|
||||||
|
|
||||||
## Sprint 1 Review Below (for convenience)
|
## Sprint 1 Review Below (for convenience)
|
||||||
|
|
||||||
## Sprint 1 REVIEW
|
## Sprint 1 REVIEW
|
||||||
|
|
||||||
In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
|
In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
|
||||||
|
|
||||||
### What do you think worked well in the first sprint?
|
### What do you think worked well in the first sprint?
|
||||||
|
|
||||||
We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be.
|
We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be.
|
||||||
|
|
||||||
### What can we improve on for the next sprint?
|
### What can we improve on for the next sprint?
|
||||||
|
|
||||||
We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process.
|
We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process.
|
||||||
|
|
||||||
### What was your contribution to the sprint?
|
### What was your contribution to the sprint?
|
||||||
* Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
|
|
||||||
* Gavyn Etzel: Helped with javascript side of things for website
|
- Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
|
||||||
* Henry Feng: Local image store and meeting support
|
- Gavyn Etzel: Helped with javascript side of things for website
|
||||||
* Sanjit: Default photo design and frontend star rating css
|
- Henry Feng: Local image store and meeting support
|
||||||
* Daniel: Helped modify html, added upload file feature
|
- Sanjit: Default photo design and frontend star rating css
|
||||||
* Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action
|
- Daniel: Helped modify html, added upload file feature
|
||||||
* Marc Rheta: Added HTML Linting and CSS Linting
|
- Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action
|
||||||
* Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html
|
- Marc Rheta: Added HTML Linting and CSS Linting
|
||||||
* George Dubinin: Meeting notes, Repo organization, cookies
|
- Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html
|
||||||
* Kara Hoagland: CRUD backend functionality
|
- George Dubinin: Meeting notes, Repo organization, cookies
|
||||||
|
- Kara Hoagland: CRUD backend functionality
|
||||||
|
|
||||||
### Was there anything blocking your progress in the sprint?
|
### Was there anything blocking your progress in the sprint?
|
||||||
Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues.
|
|
||||||
|
Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues.
|
||||||
|
|
||||||
Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break.
|
Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break.
|
||||||
|
|
||||||
## Resolutions
|
## Resolutions
|
||||||
* Divide up tasks and assign tasks to members
|
|
||||||
* Define objectives for team groups (frontend, backend, and unit testing)
|
- Divide up tasks and assign tasks to members
|
||||||
* Scheduled meetings with more notice and keep meetings at a more central location so that more members can attend
|
- Define objectives for team groups (frontend, backend, and unit testing)
|
||||||
* Get the unit testing modules up to date
|
- Scheduled meetings with more notice and keep meetings at a more central location so that more members can attend
|
||||||
* To-do: create a style guide
|
- Get the unit testing modules up to date
|
||||||
* Heed the styles and documentation (to avoid linter issues)
|
- To-do: create a style guide
|
||||||
|
- Heed the styles and documentation (to avoid linter issues)
|
||||||
|
|
||||||
## Early Issues
|
## Early Issues
|
||||||
* restructure local storage to store individual (key, review) pairs rather than storing data under one key (current schema)
|
|
||||||
* implement a file upload system (think canvas file upload)
|
- restructure local storage to store individual (key, review) pairs rather than storing data under one key (current schema)
|
||||||
* add a cuisine attribute for tagging and filtering
|
- implement a file upload system (think canvas file upload)
|
||||||
* Create UI buttons and low fidelity css
|
- add a cuisine attribute for tagging and filtering
|
||||||
* Unit test all the above
|
- Create UI buttons and low fidelity css
|
||||||
|
- Unit test all the above
|
||||||
|
|
||||||
## End Time
|
## End Time
|
||||||
- 11/14/2022 at 5:00PM
|
|
||||||
|
- 11/14/2022 at 5:00PM
|
||||||
|
@@ -1,9 +1,13 @@
|
|||||||
# Sprint 1 Review Meeting Minutes (11/13/2022)
|
# Sprint 1 Review Meeting Minutes (11/13/2022)
|
||||||
|
|
||||||
## Team 29: Hackers1995
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
## Meeting Topic: Sprint 1 Review
|
## Meeting Topic: Sprint 1 Review
|
||||||
|
|
||||||
We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing.
|
We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing.
|
||||||
|
|
||||||
## Attendance
|
## Attendance
|
||||||
|
|
||||||
1. Rhea Bhutada
|
1. Rhea Bhutada
|
||||||
2. George Dubinin
|
2. George Dubinin
|
||||||
3. Sanjit Joseph
|
3. Sanjit Joseph
|
||||||
@@ -16,37 +20,45 @@ We are meeting with Gagan to discuss progress made on Sprint 1 and testing strat
|
|||||||
10. Isaac Otero
|
10. Isaac Otero
|
||||||
|
|
||||||
## Meeting Details
|
## Meeting Details
|
||||||
- When: 11/13/2022 at 1:00PM
|
|
||||||
- Where: Capital One Cafe and Zoom
|
- When: 11/13/2022 at 1:00PM
|
||||||
|
- Where: Capital One Cafe and Zoom
|
||||||
|
|
||||||
## Agenda:
|
## Agenda:
|
||||||
|
|
||||||
Review the week 7 sprint and get the writeup for the Agile review assignemnt
|
Review the week 7 sprint and get the writeup for the Agile review assignemnt
|
||||||
|
|
||||||
## Sprint 1 REVIEW
|
## Sprint 1 REVIEW
|
||||||
|
|
||||||
In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
|
In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
|
||||||
|
|
||||||
### What do you think worked well in the first sprint?
|
### What do you think worked well in the first sprint?
|
||||||
|
|
||||||
We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be.
|
We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be.
|
||||||
|
|
||||||
### What can we improve on for the next sprint?
|
### What can we improve on for the next sprint?
|
||||||
|
|
||||||
We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process.
|
We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process.
|
||||||
|
|
||||||
### What was your contribution to the sprint?
|
### What was your contribution to the sprint?
|
||||||
* Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
|
|
||||||
* Gavyn Etzel: Helped with javascript side of things for website
|
- Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
|
||||||
* Henry Feng: Local image store and meeting support
|
- Gavyn Etzel: Helped with javascript side of things for website
|
||||||
* Sanjit: Default photo design and frontend star rating css
|
- Henry Feng: Local image store and meeting support
|
||||||
* Daniel: Helped modify html, added upload file feature
|
- Sanjit: Default photo design and frontend star rating css
|
||||||
* Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action
|
- Daniel: Helped modify html, added upload file feature
|
||||||
* Marc Rheta: Added HTML Linting and CSS Linting
|
- Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action
|
||||||
* Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html
|
- Marc Rheta: Added HTML Linting and CSS Linting
|
||||||
* George Dubinin: Meeting notes, Repo organization, cookies
|
- Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html
|
||||||
* Kara Hoagland: CRUD backend functionality
|
- George Dubinin: Meeting notes, Repo organization, cookies
|
||||||
|
- Kara Hoagland: CRUD backend functionality
|
||||||
|
|
||||||
### Was there anything blocking your progress in the sprint?
|
### Was there anything blocking your progress in the sprint?
|
||||||
Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues.
|
|
||||||
|
Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues.
|
||||||
|
|
||||||
Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break.
|
Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break.
|
||||||
|
|
||||||
## End Time
|
## End Time
|
||||||
- 11/13/2022 at 3:00PM
|
|
||||||
|
- 11/13/2022 at 3:00PM
|
||||||
|
40
admin/meetings/111622-checkin6.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Meeting Minutes (11/16/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Weekly TA Catchup with Gagan
|
||||||
|
|
||||||
|
We are meeting with Gagan to discuss Checkpoint 1 and Sprint 2 resolutions.
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gagan Gopalaiah
|
||||||
|
4. Kara Hoagland
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/16/2022 at 3:30PM
|
||||||
|
- Where: Zoom
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
## Discussion Points by Gagan
|
||||||
|
|
||||||
|
- Updated Gagan on Sprint 1
|
||||||
|
- looked at Girhub actions
|
||||||
|
- looked at the published page so far
|
||||||
|
- discussed retrospective
|
||||||
|
- Upcoming Assignments
|
||||||
|
- we have to come up with a video on the status of our app
|
||||||
|
- ramp up the styling part, so u can brag about the design of the app
|
||||||
|
- this video is supposed to encourage healthy competition
|
||||||
|
- Other Concerns
|
||||||
|
- JSDocs - not primary concern right now
|
||||||
|
- GitHub Pages vs. Netlify
|
||||||
|
- Gagan sees Netlify as more professional and not to difficult to implement
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/16/2022 at 3:45PM
|
59
admin/meetings/111722-sprint2meeting1.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# Meeting Minutes (11/07/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: First Sprint
|
||||||
|
|
||||||
|
Meeting notes for the first sprint
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gavyn Ezell
|
||||||
|
4. Henry Feng
|
||||||
|
5. Kara Hoagland
|
||||||
|
6. Marc Reta
|
||||||
|
7. Sanjit Joseph
|
||||||
|
8. Daniel Hernandez
|
||||||
|
9. Arthur Lu
|
||||||
|
10. Isaac Otero
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/17/2022 at 11:30PM
|
||||||
|
- Where: Design & Innovation Building
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
|
- N/A
|
||||||
|
- ### New Business
|
||||||
|
|
||||||
|
- Second sprint commences!
|
||||||
|
- Focus on design progress for the project showoff
|
||||||
|
- Cuisine vs Tag identifiers for reviews (both?)
|
||||||
|
|
||||||
|
- localStorage will hold:
|
||||||
|
- list of active IDs which is updated for very create operation. An ID uniquely identifies a review
|
||||||
|
- value, "nextId" denoting the index of the next available slot for an Id
|
||||||
|
- entries for every single review (javascript object)
|
||||||
|
- a list for every tag that denotes which Ids belong to reviews containing this tag
|
||||||
|
|
||||||
|
End2end tests will rely on specific html element names which include the following:
|
||||||
|
|
||||||
|
- "create-btn" (located on homepage and used to create a new review)
|
||||||
|
- "submit-btn" (located on form and used to post review)
|
||||||
|
- "update-btn" (located on a specific review page)
|
||||||
|
- "delete-btn" (located on a specific review page)
|
||||||
|
- "tag-add-btn" (located on the review create form)
|
||||||
|
|
||||||
|
- ### Next Meeting's Business
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/17/2022 at 1:00PM
|
48
admin/meetings/112022-sprint2meeting3.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# Meeting Minutes (11/20/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Second Sprint Meeting 3
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gavyn Ezell
|
||||||
|
4. Henry Feng
|
||||||
|
5. Kara Hoagland
|
||||||
|
6. Marc Reta
|
||||||
|
7. Sanjit Joseph
|
||||||
|
8. Daniel Hernandez
|
||||||
|
9. Arthur Lu
|
||||||
|
10. Isaac Otero
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/20/2022 at 1:00PM
|
||||||
|
- Where: CSE Building Second Floor
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
|
- N/A
|
||||||
|
- ### New Business
|
||||||
|
|
||||||
|
- Planning for the Agile Steam Status Video
|
||||||
|
|
||||||
|
- _Present the status of your software_
|
||||||
|
- Show off the preliminary design of index.html
|
||||||
|
- Walk through the process of creating a journal entry
|
||||||
|
- _Description of current challenges to development_
|
||||||
|
- _Preview of the next sprint and what to look forward to_
|
||||||
|
|
||||||
|
- Front end redo for home page including semantic restructuring and enhanced CSS
|
||||||
|
- Documentation session for JS, CSS, and HTML files
|
||||||
|
- Pipeline details have largely been ironed out
|
||||||
|
|
||||||
|
- ### Next Meeting's Business
|
||||||
|
- Creation of team status video
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/20/2022 at 3:00PM
|
40
admin/meetings/112322-checkin7.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Meeting Minutes (11/23/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Weekly TA Catchup with Gagan
|
||||||
|
|
||||||
|
We are meeting with Gagan to discuss status video and general updates on project.
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gagan Gopalaiah
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/23/2022 at 3:30PM
|
||||||
|
- Where: Zoom
|
||||||
|
|
||||||
|
## Discussion Points by Gagan
|
||||||
|
|
||||||
|
- progress looks good!!
|
||||||
|
- deadline for project
|
||||||
|
- december 3rd/4th code freeze
|
||||||
|
- no new features
|
||||||
|
- only debugging
|
||||||
|
- after december 3rd/4th we need to focus on making a good final video
|
||||||
|
- final video
|
||||||
|
- played on finals day, voted on in class
|
||||||
|
- need to spend a good amount of time on it
|
||||||
|
- essential to make this good
|
||||||
|
- last week there are going to be one-to-one sessions held
|
||||||
|
- Gagan will be asking questions to the team
|
||||||
|
- everyone needs to be aware of all aspects of the project
|
||||||
|
- start end-to-end testing on project
|
||||||
|
- quickly discussed team roles
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/23/2022 at 3:52PM
|
77
admin/meetings/112722-sprint-2-review.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Sprint 2 Review Meeting Minutes (11/27/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Sprint 2 Review
|
||||||
|
|
||||||
|
We are reviewing the second sprint 2 progress made and highlights
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Sanjit Joseph
|
||||||
|
4. Kara Hoagland
|
||||||
|
5. Arthur Lu
|
||||||
|
6. Mark Rheta
|
||||||
|
7. Henry Feng
|
||||||
|
8. Gavyn Etzel
|
||||||
|
9. Sanjit Joseph
|
||||||
|
10. Isaac Otero
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/27/2022 at 4:30PM
|
||||||
|
- Where: Zoom
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
Review the second sprint and discuss assiget the writeup for the Agile review assignemnt
|
||||||
|
|
||||||
|
## Sprint 2 REVIEW
|
||||||
|
|
||||||
|
In collecting feedback for the sprint the leads decided to ask members individually about their experience during sprint 2 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
|
||||||
|
|
||||||
|
### ➼ What do you think worked well in the first sprint?
|
||||||
|
|
||||||
|
Communication within the group was improved and our joint study sessions where more productive. The design team got the support they needed to accomplish the majority of their work on the project. The push to emphasize the sub-teams responsible for different tasks turned out to be a great idea and everyone put in a good effort.
|
||||||
|
|
||||||
|
### ➼ What can we improve on for the next sprint?
|
||||||
|
|
||||||
|
With the vast majority of feature implementation underway the rapid progress created a lot of bugs which otherwise could have been avoid with more careful planning. Some members felt that even though they made a great effort they weren't able to contribute as much as they wanted to. Some of the code documentation fell behind and some design discussions were circumvented because some members where busy. One consequence was that relatively few ADRs were created even though we made many important design decisions during sprint 2.
|
||||||
|
|
||||||
|
### ➼ What was your contribution to the sprint?
|
||||||
|
|
||||||
|
- Rhea Bhutada: I mainly helped implement the backend for the CRUD features of the app and documentation related to this. This mainly entailed changing the way that we were storing user data in local storage. Additionally, I helped design the form and homepage.
|
||||||
|
- Gavyn Etzel: Helped with JavaScript functionality (CRUD Features), and also did a lot of the documentation for the script files
|
||||||
|
Helped work through the storage revamp for our review cards
|
||||||
|
Also helped integrate our first design/style setup with functionality
|
||||||
|
- Henry Feng: Worked on implementing local image uploading and storing features for updating and creating profiles.
|
||||||
|
- Sanjit: I reimplemented the star ratings since they had some issues and weren’t merged with sprint 1. I fixed a bunch of linting issues that popped up from that as well. I did a fair bit of color palette brainstorming with the team. I also went over our app design for the sprint video and edited that together. Most importantly I put a chef hat on the raccoon
|
||||||
|
- Daniel: Helped in initial CreatePage and HomePage design which improved through feedback from the rest of the group.
|
||||||
|
Helped in styling suggestions.
|
||||||
|
- Arthur Lu: Worked on fixing some CI/CD pipeline issues
|
||||||
|
Implemented e2e testing for basic update and delete functionality
|
||||||
|
Helped with fixing the homepage and review page layout
|
||||||
|
Helped with fixing the article tag overflow issue
|
||||||
|
- Marc Rheta: Implemented the e2e testing for reading and create
|
||||||
|
Allowed tabs for CSS/HTML linters
|
||||||
|
- Isaac Otero: I was able to help out with the sprint video for the last sprint and thought of how our page will look like, Started working on homepage.html
|
||||||
|
- George Dubinin: Meeting notes, Repo organization, Front-end (a little), Project Status Review video.
|
||||||
|
- Kara Hoagland: I helped set up the new local storage design, reimplemented the CRUD features using the new local storage design, contributed to the styling, added a default img, backend on the details page
|
||||||
|
|
||||||
|
### ➼ Was there anything blocking your progress in the sprint?
|
||||||
|
|
||||||
|
A few members got sick over the break and with midterms picking up for other classes some members had trouble dedicting time for the project but everyone still put in a great effort overall.
|
||||||
|
|
||||||
|
## Next Sprint Goals
|
||||||
|
|
||||||
|
- Resolve the 4 issues open on GitHub right now
|
||||||
|
- Make the project "local first" by creating a cache
|
||||||
|
- Bug fixes and final product adjustments possibly pushed to sprint 4
|
||||||
|
- We aim to keep sprint 3 short (a few days max)
|
||||||
|
- JS docs (we can potentially leave this out with an explanation of where our documentation is)
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/27/2022 at 5:00PM
|
84
admin/meetings/112822-retrospective.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Sprint 1 Retrospective (11/28/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Sprint 1 Retrospective
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Sanjit Joseph
|
||||||
|
4. Kara Hoagland
|
||||||
|
5. Arthur Lu
|
||||||
|
6. Mark Rheta
|
||||||
|
7. Henry Feng
|
||||||
|
8. Gavyn Etzel
|
||||||
|
9. Sanjit Joseph
|
||||||
|
10. Isaac Otero
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/28/2022 at 4:00PM
|
||||||
|
- Where: Zoom
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
Discuss the review, share more detailed thoughts on sprint 2, and create some resolutions for sprint 3
|
||||||
|
|
||||||
|
## Sprint 3 Review Below (for convenience)
|
||||||
|
|
||||||
|
In collecting feedback for the sprint the leads decided to ask members individually about their experience during sprint 2 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
|
||||||
|
|
||||||
|
### ➼ What do you think worked well in the first sprint?
|
||||||
|
|
||||||
|
Communication within the group was improved and our joint study sessions where more productive. The design team got the support they needed to accomplish the majority of their work on the project. The push to emphasize the sub-teams responsible for different tasks turned out to be a great idea and everyone put in a good effort.
|
||||||
|
|
||||||
|
### ➼ What can we improve on for the next sprint?
|
||||||
|
|
||||||
|
With the vast majority of feature implementation underway the rapid progress created a lot of bugs which otherwise could have been avoid with more careful planning. Some members felt that even though they made a great effort they weren't able to contribute as much as they wanted to. Some of the code documentation fell behind and some design discussions were circumvented because some members where busy. One consequence was that relatively few ADRs were created even though we made many important design decisions during sprint 2.
|
||||||
|
|
||||||
|
### ➼ What was your contribution to the sprint?
|
||||||
|
|
||||||
|
- Rhea Bhutada: I mainly helped implement the backend for the CRUD features of the app and documentation related to this. This mainly entailed changing the way that we were storing user data in local storage. Additionally, I helped design the form and homepage.
|
||||||
|
- Gavyn Etzel: Helped with JavaScript functionality (CRUD Features), and also did a lot of the documentation for the script files
|
||||||
|
Helped work through the storage revamp for our review cards
|
||||||
|
Also helped integrate our first design/style setup with functionality
|
||||||
|
- Henry Feng: Worked on implementing local image uploading and storing features for updating and creating profiles.
|
||||||
|
- Sanjit: I reimplemented the star ratings since they had some issues and weren’t merged with sprint 1. I fixed a bunch of linting issues that popped up from that as well. I did a fair bit of color palette brainstorming with the team. I also went over our app design for the sprint video and edited that together. Most importantly I put a chef hat on the raccoon
|
||||||
|
- Daniel: Helped in initial CreatePage and HomePage design which improved through feedback from the rest of the group.
|
||||||
|
Helped in styling suggestions.
|
||||||
|
- Arthur Lu: Worked on fixing some CI/CD pipeline issues
|
||||||
|
Implemented e2e testing for basic update and delete functionality
|
||||||
|
Helped with fixing the homepage and review page layout
|
||||||
|
Helped with fixing the article tag overflow issue
|
||||||
|
- Marc Rheta: Implemented the e2e testing for reading and create
|
||||||
|
Allowed tabs for CSS/HTML linters
|
||||||
|
- Isaac Otero: I was able to help out with the sprint video for the last sprint and thought of how our page will look like, Started working on homepage.html
|
||||||
|
- George Dubinin: Meeting notes, Repo organization, Front-end (a little), Project Status Review video.
|
||||||
|
- Kara Hoagland: I helped set up the new local storage design, reimplemented the CRUD features using the new local storage design, contributed to the styling, added a default img, backend on the details page
|
||||||
|
|
||||||
|
### ➼ Was there anything blocking your progress in the sprint?
|
||||||
|
|
||||||
|
A few members got sick over the break and with midterms picking up for other classes some members had trouble dedicting time for the project but everyone still put in a great effort overall.
|
||||||
|
|
||||||
|
## Next Sprint Goals
|
||||||
|
|
||||||
|
- Resolve the 4 issues open on GitHub right now
|
||||||
|
- Make the project "local first" by creating a cache
|
||||||
|
- Bug fixes and final product adjustments possibly pushed to sprint 4
|
||||||
|
- We aim to keep sprint 3 short (a few days max)
|
||||||
|
- JS docs (we can potentially leave this out with an explanation of where our documentation is)
|
||||||
|
|
||||||
|
## Resolutions
|
||||||
|
|
||||||
|
- Sprint 3 first meeting happening 11-29 at 5:00PM
|
||||||
|
- Make sure that there's enough communication between front-end and back-end
|
||||||
|
- Focus on meeting with your subgroup and then touch base with the main group
|
||||||
|
- Keep documentation up to date with the rest of the project
|
||||||
|
- We need to finalize the home page design (this has been open for a while).
|
||||||
|
- Fix image sizing issues by focusing on supporting 300x300 pixel images with sizes of around 2-5 megabytes
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/14/2022 at 5:00PM
|
41
admin/meetings/112922-Sprint3Opener.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Meeting Minutes (11/29/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Sprint 3 Debut Meeting
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gavyn Ezell
|
||||||
|
4. Henry Feng
|
||||||
|
5. Kara Hoagland
|
||||||
|
6. Marc Reta (remote)
|
||||||
|
7. Sanjit Joseph
|
||||||
|
8. Daniel Hernandez
|
||||||
|
9. Arthur Lu (remote)
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/29/2022 at 5:00PM
|
||||||
|
- Where: Design and Innovation Building
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
|
- Resolve pretty print linting PR
|
||||||
|
- Resolve documentation not being merged to main PR
|
||||||
|
- ### New Business
|
||||||
|
- Create ADR for image storage
|
||||||
|
- Review sorting defaults (recent or top rated)
|
||||||
|
- Adding lists of reviewIDs corresponding to reviews which share specific star ratings
|
||||||
|
- Create function for retrieving top 20 reviews organized by decreasing star ratings
|
||||||
|
- Implement search for for flitering tags
|
||||||
|
- Frontend checked out new branch for alternate home page designs
|
||||||
|
- ### Next Meeting's Business
|
||||||
|
- Creation of team status video
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/20/2022 at 3:00PM
|
36
admin/meetings/113022-Sprint3Cont.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Meeting Minutes (11/30/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Sprint 3 Continued
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Henry Feng
|
||||||
|
4. Kara Hoagland
|
||||||
|
5. Sanjit Joseph
|
||||||
|
6. Arthur Lu
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 11/30/2022 at 2:00PM
|
||||||
|
- Where: Design and Innovation Building
|
||||||
|
|
||||||
|
## Agenda:
|
||||||
|
|
||||||
|
- ### Old/Unresolved Business
|
||||||
|
- Fix empty page for no-tag search
|
||||||
|
- Catch testing up with what we implemented yesterday
|
||||||
|
- ### New Business
|
||||||
|
- Cache the site for local first (high priority)
|
||||||
|
- Implement editing form "in place" (optional for this sprint)
|
||||||
|
- Change icon for "add review" entry
|
||||||
|
- Overcoming UI test challenges
|
||||||
|
- ### Next Meeting's Business
|
||||||
|
- Creation of team status video
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 11/30/2022 at 2:00PM
|
@@ -1,39 +0,0 @@
|
|||||||
# Meeting Minutes (11/08/2022)
|
|
||||||
## Team 29: Hackers1995
|
|
||||||
## Meeting Topic: In-Person First Sprint Day 2
|
|
||||||
Meeting notes for the first sprint
|
|
||||||
|
|
||||||
## Attendance
|
|
||||||
1. Rhea Bhutada
|
|
||||||
2. George Dubinin
|
|
||||||
3. Gavyn Ezell
|
|
||||||
4. Kara Hoagland
|
|
||||||
5. Sanjit Joseph
|
|
||||||
6. Daniel Hernandez
|
|
||||||
|
|
||||||
## Meeting Details
|
|
||||||
- When: 11/08/2022 at 2:00PM
|
|
||||||
- Where: Mike's Red Tacos
|
|
||||||
|
|
||||||
## Agenda:
|
|
||||||
- ### Old/Unresolved Business
|
|
||||||
- N/A
|
|
||||||
- ### New Business
|
|
||||||
- Isaac now knows what Wolftown is
|
|
||||||
- Pair programming setup with VSCode
|
|
||||||
- ### Next Meeting's Business
|
|
||||||
|
|
||||||
## App Progress
|
|
||||||
- The landing page is closer
|
|
||||||
- Review card css file entered
|
|
||||||
- Review Card javascript logic implemented (thanks Gavin)
|
|
||||||
-
|
|
||||||
|
|
||||||
## Decisions Made
|
|
||||||
- Linting details decided (TABS NOT SPACES)
|
|
||||||
|
|
||||||
## End Time
|
|
||||||
- 11/07/2022 at 8:00PM
|
|
||||||
|
|
||||||
|
|
||||||
|
|
29
admin/meetings/1212022-check10.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Meeting Minutes (12/1/2022)
|
||||||
|
|
||||||
|
## Team 29: Hackers1995
|
||||||
|
|
||||||
|
## Meeting Topic: Weekly TA Catchup with Gagan
|
||||||
|
|
||||||
|
We are meeting with Gagan to discuss status video and general updates on project.
|
||||||
|
|
||||||
|
## Attendance
|
||||||
|
|
||||||
|
1. Rhea Bhutada
|
||||||
|
2. George Dubinin
|
||||||
|
3. Gagan Gopalaiah
|
||||||
|
|
||||||
|
## Meeting Details
|
||||||
|
|
||||||
|
- When: 12/1/2022 at 12:00PM
|
||||||
|
- Where: Zoom
|
||||||
|
|
||||||
|
## Discussion Points by Gagan
|
||||||
|
|
||||||
|
- Don't code up anything after Sunday. Reserve the time for bug fixes
|
||||||
|
- Final Interview is a 4-5 minute interview about general course specific topics
|
||||||
|
- Live demo of the app for Gagan
|
||||||
|
- Gagan asks us to evaluate instructional assistants
|
||||||
|
|
||||||
|
## End Time
|
||||||
|
|
||||||
|
- 12/1/2022 at 12:20PM
|
@@ -1,57 +1,66 @@
|
|||||||
# Team Working Agreement
|
# Team Working Agreement
|
||||||
## Term: Fall 2022
|
|
||||||
## Creation: 10/12/2022; Revised: N/A
|
## Term: Fall 2022
|
||||||
## Group Identification
|
|
||||||
- Team 29
|
## Creation: 10/12/2022; Revised: N/A
|
||||||
- TA: Gagan Gopalaiah
|
|
||||||
- Instructor: Professor Thomas Powell
|
## Group Identification
|
||||||
- Team Name: Hackers1995
|
|
||||||
|
- Team 29
|
||||||
## Team member info (name/email)
|
- TA: Gagan Gopalaiah
|
||||||
1. Rhea Bhutada, rbhutada@ucsd.edu
|
- Instructor: Professor Thomas Powell
|
||||||
2. George Dubinin, gdubinin@ucsd.edu
|
- Team Name: Hackers1995
|
||||||
3. Gavyn Ezell, gezell@ucsd.edu
|
|
||||||
4. Henry Feng, hefeng@ucsd.edu
|
## Team member info (name/email)
|
||||||
5. Kara Hoagland, khoaglan@ucsd.edu
|
|
||||||
6. Marc Reta, mreta@ucsd.edu
|
1. Rhea Bhutada, rbhutada@ucsd.edu
|
||||||
7. Sanjit Joseph, smjoseph@ucsd.edu
|
2. George Dubinin, gdubinin@ucsd.edu
|
||||||
8. Isaac Otero, irotero@ucsd.edu
|
3. Gavyn Ezell, gezell@ucsd.edu
|
||||||
9. Arthur Lu, a8lu@ucsd.edu
|
4. Henry Feng, hefeng@ucsd.edu
|
||||||
10. Daniel Hernandez, d7hernan@ucsd.edu
|
5. Kara Hoagland, khoaglan@ucsd.edu
|
||||||
|
6. Marc Reta, mreta@ucsd.edu
|
||||||
## RULES:
|
7. Sanjit Joseph, smjoseph@ucsd.edu
|
||||||
#### 1) Primary Means of Communication and Expectations
|
8. Isaac Otero, irotero@ucsd.edu
|
||||||
- All members will communicate via Slack.
|
9. Arthur Lu, a8lu@ucsd.edu
|
||||||
- All members will be expected to read messages from group chats and direct messages, and respond in no more than 4 hours and no later than 10PM.
|
10. Daniel Hernandez, d7hernan@ucsd.edu
|
||||||
- All pull requests require 3 people to review the code being pushed to main.
|
|
||||||
|
## RULES:
|
||||||
#### 2) Scheduling Meetings (Schedule at least one meeting as part of constructing your team agreement.)
|
|
||||||
- Members are expected to meet at least once a week with the group either in-person or on Zoom. Future meeting details will be determined within a 24 hours window.
|
#### 1) Primary Means of Communication and Expectations
|
||||||
- Team members hosting the meeting will send out a reminder of the meeting with an agenda 2 hours before the meeting.
|
|
||||||
|
- All members will communicate via Slack.
|
||||||
#### 3) General Responsibilities for All Team Members
|
- All members will be expected to read messages from group chats and direct messages, and respond in no more than 4 hours and no later than 10PM.
|
||||||
|
- All pull requests require 3 people to review the code being pushed to main.
|
||||||
- Respect the contributions of others.
|
|
||||||
- Work on assignments early to allow others to review and debug any issues.
|
#### 2) Scheduling Meetings (Schedule at least one meeting as part of constructing your team agreement.)
|
||||||
- Communicate any issues or problems as early as possible.
|
|
||||||
- Be open to criticism.
|
- Members are expected to meet at least once a week with the group either in-person or on Zoom. Future meeting details will be determined within a 24 hours window.
|
||||||
|
- Team members hosting the meeting will send out a reminder of the meeting with an agenda 2 hours before the meeting.
|
||||||
#### 4) Specific Team Member Responsibilities/Deadlines (Optional)
|
|
||||||
|
#### 3) General Responsibilities for All Team Members
|
||||||
- A daily standup is required every day from every team member. A daily standup includes what you've completed, what you want to work on, and what issues you encountered for the day. If you haven't done anything for that day, write down what you will be contributing.
|
|
||||||
|
- Respect the contributions of others.
|
||||||
#### 5) Conflict Resolution
|
- Work on assignments early to allow others to review and debug any issues.
|
||||||
|
- Communicate any issues or problems as early as possible.
|
||||||
- Conflicts between individuals will first try to be resolved amongst the people involved.
|
- Be open to criticism.
|
||||||
- Group conflicts will be voted on.
|
|
||||||
- Ongoing conflicts will be reported to the TA.
|
#### 4) Specific Team Member Responsibilities/Deadlines (Optional)
|
||||||
- Unprofessionalism of any kind will not be tolerated. Conflicts involving this will immediately be brought up with the TA
|
|
||||||
|
- A daily standup is required every day from every team member. A daily standup includes what you've completed, what you want to work on, and what issues you encountered for the day. If you haven't done anything for that day, write down what you will be contributing.
|
||||||
#### 6) Expectations of Faculty and GTA’s
|
|
||||||
|
#### 5) Conflict Resolution
|
||||||
- If a team member fails to live up to this agreement, the situation may be reported to the staff, but the team will still be responsible for submitting a completed assignment. Staff will be available to meet with teams to resolve issues.
|
|
||||||
|
- Conflicts between individuals will first try to be resolved amongst the people involved.
|
||||||
## Team Signatures
|
- Group conflicts will be voted on.
|
||||||
|
- Ongoing conflicts will be reported to the TA.
|
||||||
#### Print Name:
|
- Unprofessionalism of any kind will not be tolerated. Conflicts involving this will immediately be brought up with the TA
|
||||||
#### Signature:
|
|
||||||
|
#### 6) Expectations of Faculty and GTA’s
|
||||||
|
|
||||||
|
- If a team member fails to live up to this agreement, the situation may be reported to the staff, but the team will still be responsible for submitting a completed assignment. Staff will be available to meet with teams to resolve issues.
|
||||||
|
|
||||||
|
## Team Signatures
|
||||||
|
|
||||||
|
#### Print Name:
|
||||||
|
|
||||||
|
#### Signature:
|
||||||
|
149
admin/team.md
@@ -1,73 +1,76 @@
|
|||||||
# **Hackers1995**
|
# **Hackers1995**
|
||||||
|
|
||||||
## **Brand**
|
## **Brand**
|
||||||

|
|
||||||
|

|
||||||
## **Values**
|
|
||||||
- Openness
|
## **Values**
|
||||||
- Honesty
|
|
||||||
- Respect
|
- Openness
|
||||||
- Integrity
|
- Honesty
|
||||||
- Diversity/Inclusion
|
- Respect
|
||||||
|
- Integrity
|
||||||
## **Roster**
|
- Diversity/Inclusion
|
||||||
### **TA: Gagan Gopalaiah**
|
|
||||||
|
## **Roster**
|
||||||
|
|
||||||
### **Team Lead: Rhea Bhutada**
|
### **TA: Gagan Gopalaiah**
|
||||||
- #### About Me:
|
|
||||||
- My name is Rhea Bhutada and I am currently a CS major and CogSci minor at ERC. The intersection between neuroscience and computer science really fascinates me and I generally try to apply myself to projects that deal with the overlap of both of these fields. This year I'm working as an undergraduate researcher at the Swartz Center for Computational Neuroscience, which has been an extremely cool experience. Other than that I love to stay active. I used to play basketball in high school and was in an NCAA commercial with Shaq. But lately, I’ve been really into running. Overall, I'm excited to contribute to this project! Although I haven't had too much industry experience, I am interested to see how I can apply my previous course work to backend or frontend design.
|
### **Team Lead: Rhea Bhutada**
|
||||||
- #### Link to Github: https://github.com/rheabhutada02
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Rhea Bhutada and I am currently a CS major and CogSci minor at ERC. The intersection between neuroscience and computer science really fascinates me and I generally try to apply myself to projects that deal with the overlap of both of these fields. This year I'm working as an undergraduate researcher at the Swartz Center for Computational Neuroscience, which has been an extremely cool experience. Other than that I love to stay active. I used to play basketball in high school and was in an NCAA commercial with Shaq. But lately, I’ve been really into running. Overall, I'm excited to contribute to this project! Although I haven't had too much industry experience, I am interested to see how I can apply my previous course work to backend or frontend design.
|
||||||
### **Team Lead: George Dubinin**
|
- #### Link to Github: https://github.com/rheabhutada02
|
||||||
- #### About Me:
|
|
||||||
- Hello World! I'm a fifth year (3rd year transfer) computer science major from the North Bay Area. Web development has been a big focus of mine since taking Prof Powell's 134B last winter and I'm stoked to be back in the "full stack" developer seat for 110. I am the second the team lead and in addition to my love for leading and working on team projects I am also fascinated by web development technologies including containerization, infrastructure as code (IaC), software as a service (SAAS), and web-based encryption (security). I am also an avid DJ and the traininer manmager for the DJ club on campus. This quarter is shaping up to be a memorable one!
|
### **Team Lead: George Dubinin**
|
||||||
- #### Link to Github: https://github.com/look-its-ashton
|
|
||||||
|
- #### About Me:
|
||||||
|
- Hello World! I'm a fifth year (3rd year transfer) computer science major from the North Bay Area. Web development has been a big focus of mine since taking Prof Powell's 134B last winter and I'm stoked to be back in the "full stack" developer seat for 110. I am the second the team lead and in addition to my love for leading and working on team projects I am also fascinated by web development technologies including containerization, infrastructure as code (IaC), software as a service (SAAS), and web-based encryption (security). I am also an avid DJ and the traininer manmager for the DJ club on campus. This quarter is shaping up to be a memorable one!
|
||||||
### **Gavyn Ezell**
|
- #### Link to Github: https://github.com/look-its-ashton
|
||||||
- #### About Me:
|
|
||||||
- My name is Gavyn Ezell and I’m from Hawaii. Currently a 3rd year CS Major at Muir. I love video games, playing piano, and going to the gym. For SWE, backend interests me most (I am not good with design and visuals), and I’m hoping to learn a lot more backend from this project!
|
### **Gavyn Ezell**
|
||||||
- #### Link to Github: https://github.com/gavyn-ezell
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Gavyn Ezell and I’m from Hawaii. Currently a 3rd year CS Major at Muir. I love video games, playing piano, and going to the gym. For SWE, backend interests me most (I am not good with design and visuals), and I’m hoping to learn a lot more backend from this project!
|
||||||
### **Daniel Hernandez**
|
- #### Link to Github: https://github.com/gavyn-ezell
|
||||||
- #### About Me:
|
|
||||||
- My name is Daniel Hernandez and I am a 3rd year Computer Science major and music minor. Some of my interests in the CS field are ML, AI, and Cybersecurity. Outside of school, I play drums for a local band. For SE, the backend aspect appeals to me the most since I am able to utilize more of what I learned from my past classes. However, I would want to try frontend since I do enjoy design to some extent.
|
### **Daniel Hernandez**
|
||||||
- #### Link to Github: https://github.com/d7hernan
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Daniel Hernandez and I am a 3rd year Computer Science major and music minor. Some of my interests in the CS field are ML, AI, and Cybersecurity. Outside of school, I play drums for a local band. For SE, the backend aspect appeals to me the most since I am able to utilize more of what I learned from my past classes. However, I would want to try frontend since I do enjoy design to some extent.
|
||||||
### **Henry Feng**
|
- #### Link to Github: https://github.com/d7hernan
|
||||||
- #### About Me:
|
|
||||||
- My name is Henry, and I am a 3rd year CS major. I was born in China and grew up in New Zealand. I wrote my first line of code, in Python during my second year of high school. My favourite foods are ramen, steak and pasta. Some of my hobbies include playing guitar, hiking, cooking, video games, and music (from the Persona series). I am excited to start this project and hope to contribute to both frontend and backend.
|
### **Henry Feng**
|
||||||
- #### Link to Github: https://github.com/dusk-moon
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Henry, and I am a 3rd year CS major. I was born in China and grew up in New Zealand. I wrote my first line of code, in Python during my second year of high school. My favourite foods are ramen, steak and pasta. Some of my hobbies include playing guitar, hiking, cooking, video games, and music (from the Persona series). I am excited to start this project and hope to contribute to both frontend and backend.
|
||||||
### **Kara Hoagland**
|
- #### Link to Github: https://github.com/dusk-moon
|
||||||
- #### About Me:
|
|
||||||
- My name is Kara Hoagland and I am a 3rd year Computer Engineering major. CS-wise, I'm interested in topics such as computer vision and RFID, but it's hard to limit oneself because there's so many interesting topics out there. Outside of CS, I enjoy D&D, biking, and reading. I got some industry experience over summer and love getting to see how that experience and my previous classes all apply to this project. I'm interested in full stack but more so the backend of things.
|
### **Kara Hoagland**
|
||||||
- #### Link to Github: https://github.com/KH-Cl
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Kara Hoagland and I am a 3rd year Computer Engineering major. CS-wise, I'm interested in topics such as computer vision and RFID, but it's hard to limit oneself because there's so many interesting topics out there. Outside of CS, I enjoy D&D, biking, and reading. I got some industry experience over summer and love getting to see how that experience and my previous classes all apply to this project. I'm interested in full stack but more so the backend of things.
|
||||||
### **Marc Reta**
|
- #### Link to Github: https://github.com/KH-Cl
|
||||||
- #### About Me: My name is Marc Reta and I am a 3rd year Computer Engineering major in Warren College. I love exploring San Diego and going on adventures. I have a huge interest in Public Transportation. I'm looking foward to working with everyone in my group and learn how to create an application.
|
|
||||||
- #### Link to Github: https://github.com/Graydogminer
|
### **Marc Reta**
|
||||||
|
|
||||||
|
- #### About Me: My name is Marc Reta and I am a 3rd year Computer Engineering major in Warren College. I love exploring San Diego and going on adventures. I have a huge interest in Public Transportation. I'm looking foward to working with everyone in my group and learn how to create an application.
|
||||||
### **Sanjit Joseph**
|
- #### Link to Github: https://github.com/Graydogminer
|
||||||
- #### About Me:
|
|
||||||
- Hi! My name is Sanjit Joseph and I'm a 3rd year CE major at Sixth. I'm from the Bay Area, so I've been surrounded by technology most of my life. I'm into building computers and I waste a lot of time (and money) messing with my PC and playing video games on it. I enjoy things outside of tech, though--as an Eagle Scout, I've done tons of backpacking throughout California and the US. I also hold a black belt in Shotokan Karate. As for this class, I'm pretty excited about all the different aspects of software engineering; frontend and backend both appeal to me, but I'm really just excited to work on a long class project in a team setting.
|
### **Sanjit Joseph**
|
||||||
- #### Link to Github: https://github.com/sm-joseph
|
|
||||||
|
- #### About Me:
|
||||||
|
- Hi! My name is Sanjit Joseph and I'm a 3rd year CE major at Sixth. I'm from the Bay Area, so I've been surrounded by technology most of my life. I'm into building computers and I waste a lot of time (and money) messing with my PC and playing video games on it. I enjoy things outside of tech, though--as an Eagle Scout, I've done tons of backpacking throughout California and the US. I also hold a black belt in Shotokan Karate. As for this class, I'm pretty excited about all the different aspects of software engineering; frontend and backend both appeal to me, but I'm really just excited to work on a long class project in a team setting.
|
||||||
### **Isaac Otero**
|
- #### Link to Github: https://github.com/sm-joseph
|
||||||
- #### About Me:
|
|
||||||
- My name is Isaac Otero, I am a 5th year Cog Sci major. I am interested in front end development. I want to implement what I’ve learned from my design classes into my projects for front end development.
|
### **Isaac Otero**
|
||||||
- #### Link to Github: https://github.com/Isaac-Otero
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Isaac Otero, I am a 5th year Cog Sci major. I am interested in front end development. I want to implement what I’ve learned from my design classes into my projects for front end development.
|
||||||
### **Arthur Lu**
|
- #### Link to Github: https://github.com/Isaac-Otero
|
||||||
- #### About Me:
|
|
||||||
- My name is Arthur Lu and I am a 3rd year CE major. I am primarily interested in low level systems design, hardware development and optimization, and HPC architecture. I work as an undergraduate research assistant for Prof. Turakhia developing hardware accelerators for long length genome alignment. When I’m not busy, I like to relax with some retro video games.
|
### **Arthur Lu**
|
||||||
- #### Link to Github: https://github.com/ltcptgeneral
|
|
||||||
|
- #### About Me:
|
||||||
|
- My name is Arthur Lu and I am a 3rd year CE major. I am primarily interested in low level systems design, hardware development and optimization, and HPC architecture. I work as an undergraduate research assistant for Prof. Turakhia developing hardware accelerators for long length genome alignment. When I’m not busy, I like to relax with some retro video games.
|
||||||
|
- #### Link to Github: https://github.com/ltcptgeneral
|
||||||
|
BIN
admin/videos/statusvideo1.mp4
Normal file
46
package.json
@@ -1,23 +1,27 @@
|
|||||||
{
|
{
|
||||||
"name": "food-journal",
|
"name": "food-journal",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha --recursive --require mock-local-storage './{,!(node_modules)/**}/*.test.js'",
|
"test": "mocha --recursive --require mock-local-storage './{,!(node_modules)/**}/*.test.js'",
|
||||||
"lint": "eslint '**/*.js'",
|
"lint-js": "eslint **/*.js",
|
||||||
"fix-style": "eslint --fix **/*.js",
|
"fix-js": "eslint --fix **/*.js",
|
||||||
"lintHTML": "htmlhint '**/*.html'",
|
"lint-html": "htmlhint **/*.html",
|
||||||
"lintCSS": "stylelint '**/*.css'",
|
"lint-css": "stylelint **/*.css",
|
||||||
"http-server": "http-server source"
|
"fix-css": "stylelint --fix **/*.css",
|
||||||
},
|
"http-server": "http-server source",
|
||||||
"devDependencies": {
|
"lint-prettier": "prettier --check .",
|
||||||
"eslint": "^8.27.0",
|
"fix-prettier": "prettier --write ."
|
||||||
"htmlhint": "1.1.4",
|
},
|
||||||
"mocha": "10",
|
"devDependencies": {
|
||||||
"mock-local-storage": "^1.1.23",
|
"eslint": "^8.27.0",
|
||||||
"stylelint": "14.14.1",
|
"htmlhint": "1.1.4",
|
||||||
"stylelint-config-standard": "^29.0.0",
|
"http-server": "",
|
||||||
"puppeteer": "18",
|
"mocha": "10",
|
||||||
"http-server": ""
|
"mock-local-storage": "^1.1.23",
|
||||||
}
|
"prettier": "2.8.0",
|
||||||
|
"puppeteer": "^18.2.1",
|
||||||
|
"stylelint": "14.14.1",
|
||||||
|
"stylelint-config-standard": "^29.0.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,77 +1,93 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Food Journal</title>
|
||||||
|
|
||||||
<head>
|
<!--Add Favicon-->
|
||||||
<meta charset="UTF-8" />
|
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Food Journal</title>
|
|
||||||
|
|
||||||
<!-- Recipe Card Custom Element -->
|
<!-- Review Card Custom Element -->
|
||||||
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
||||||
|
|
||||||
|
<!-- Create Page Stylesheets & Scripts -->
|
||||||
|
<link rel="stylesheet" href="./static/CreatePage.css" />
|
||||||
|
<link rel="stylesheet" href="./static/Form.css" />
|
||||||
|
<script src="./assets/scripts/CreatePage.js" type="module"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
<!-- Main Stylesheets & Scripts -->
|
<header>
|
||||||
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
|
<!-- Setting up logo and site name at the top of the website -->
|
||||||
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
|
<div class="top-bar">
|
||||||
<link rel="stylesheet" href="./static/ReviewCard.css" />
|
<img src="./assets/images/Logo.png" alt="logo" />
|
||||||
<script src="./assets/scripts/CreatePage.js" type="module"></script>
|
<h1>Food Journal</h1>
|
||||||
|
<img src="./assets/images/Logo.png" alt="logo" />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
</head>
|
<body>
|
||||||
|
<div class="journal-form">
|
||||||
|
<h1>New Entry</h1>
|
||||||
|
|
||||||
<body>
|
<form id="new-food-entry">
|
||||||
<input type="button" value="Home" id="home-btn" onclick="window.location.assign('./index.html')">
|
<fieldset>
|
||||||
<form id="new-food-entry">
|
<legend>PICTURE:</legend>
|
||||||
<fieldset>
|
<select id="select" name="select">
|
||||||
<legend>Pic:</legend>
|
<option value="file">File Upload</option>
|
||||||
<label for="mealImage">
|
<option value="photo">Take a Photo</option>
|
||||||
Source:
|
</select>
|
||||||
<input type="text" id="mealImg" name="mealImg">
|
<input type="file" accept="image/*" id="mealImg" name="mealImg" />
|
||||||
</label>
|
</fieldset>
|
||||||
<label for="image-alt">
|
|
||||||
Alt Text:
|
|
||||||
<input type="text" id="imgAlt" name="imgAlt">
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
|
|
||||||
<legend> Meal: </legend>
|
<fieldset>
|
||||||
<label for="Meal: ">Meal:
|
<video id="player" width="320" height="240" autoplay hidden></video>
|
||||||
<input type="text" id="mealName" name="mealName" required>
|
<canvas id="photoCanvas" width="320" height="240" hidden></canvas>
|
||||||
</label>
|
<button type="button" id="photoButton" hidden>Take Photo</button>
|
||||||
<label for="comments">Comments:
|
</fieldset>
|
||||||
<br>
|
|
||||||
<textarea name="comments" id="comments"></textarea>
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset class="rating">
|
<fieldset>
|
||||||
<legend> Rating: </legend>
|
<legend>MEAL NAME:</legend>
|
||||||
<input type="radio" id="s5" name="rating" value="5"/> <label for="s5"> 5 stars </label>
|
<label for="Name: "> <input type="text" id="mealName" name="mealName" required /> </label>
|
||||||
<input type="radio" id="s4" name="rating" value="4"/> <label for="s4"> 4 stars </label>
|
</fieldset>
|
||||||
<input type="radio" id="s3" name="rating" value="3"/> <label for="s3"> 3 stars </label>
|
|
||||||
<input type="radio" id="s2" name="rating" value="2"/> <label for="s2"> 2 stars </label>
|
|
||||||
<input type="radio" id="s1" name="rating" value="1"/> <label for="s1"> 1 star </label>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Other Info:</legend>
|
<legend>RESTAURANT NAME:</legend>
|
||||||
<label for="restaurant">
|
<label for="Name:"> <input type="text" id="restaurant" name="restaurant" required /> </label>
|
||||||
Restaurant:
|
</fieldset>
|
||||||
<input type="text" id="restaurant" name="restaurant" required>
|
|
||||||
</label>
|
|
||||||
<label for="tag-form">
|
|
||||||
Tags:
|
|
||||||
<input type="text" id="tag-form" name="tag-form">
|
|
||||||
<div class='tag-container' id="tag-container-form">
|
|
||||||
|
|
||||||
</div>
|
<fieldset>
|
||||||
<button type="button" id="tagAdd">Add Tag</button>
|
<legend>RATING:</legend>
|
||||||
</label>
|
<div style="display: flex; justify-content: flex-start; align-items: center">
|
||||||
|
<div class="rating">
|
||||||
|
<input type="radio" id="s5" name="rating" value="5" /> <label for="s5" id="s5-select"> 5 stars </label>
|
||||||
|
<input type="radio" id="s4" name="rating" value="4" /> <label for="s4" id="s4-select"> 4 stars </label>
|
||||||
|
<input type="radio" id="s3" name="rating" value="3" /> <label for="s3" id="s3-select"> 3 stars </label>
|
||||||
|
<input type="radio" id="s2" name="rating" value="2" /> <label for="s2" id="s2-select"> 2 stars </label>
|
||||||
|
<input type="radio" id="s1" name="rating" value="1" /> <label for="s1" id="s1-select"> 1 star </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
</fieldset>
|
<fieldset>
|
||||||
<button type="submit" id="save-btn" value="Submit">Save Review</button>
|
<legend>COMMENTS:</legend>
|
||||||
</form>
|
<textarea name="comments" id="comments" rows="5" style="resize: none; width: 100%"></textarea>
|
||||||
</body>
|
</fieldset>
|
||||||
|
|
||||||
</html>
|
<fieldset>
|
||||||
|
<legend>TAGS: (ex. cuisine, distance, cost, etc)</legend>
|
||||||
|
<input type="text" id="tag-form" name="tag-form" />
|
||||||
|
|
||||||
|
<div class="tag-container" id="tag-container-form"></div>
|
||||||
|
<button type="button" id="tag-add-btn">+</button>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<button type="submit" id="save-btn" value="Submit">Save</button>
|
||||||
|
|
||||||
|
<!-- Button that allows user to go back to the homepage -->
|
||||||
|
<input type="button" value="Cancel" id="home-btn" onclick="window.location.assign('./index.html')" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
@@ -1,78 +1,146 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Food Journal</title>
|
<title>Food Journal</title>
|
||||||
|
|
||||||
<!-- Recipe Card Custom Element -->
|
<!--Add Favicon-->
|
||||||
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico" />
|
||||||
|
|
||||||
|
<!-- Review Card Custom Element -->
|
||||||
|
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
||||||
|
|
||||||
<!-- Main Stylesheets & Scripts -->
|
<!-- Main Stylesheets & Scripts -->
|
||||||
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
|
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
|
||||||
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
|
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
|
||||||
<link rel="stylesheet" href="./static/ReviewCard.css" />
|
<link rel="stylesheet" href="./static/ReviewDetails.css" />
|
||||||
<script src="assets/scripts/ReviewDetails.js" type="module"></script>
|
<link rel="stylesheet" href="./static/Form.css" />
|
||||||
|
<script src="assets/scripts/ReviewDetails.js" type="module"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<div class="top-bar">
|
||||||
|
<img src="./assets/images/Logo.png" alt="logo" />
|
||||||
|
<h1>Food Journal</h1>
|
||||||
|
<img src="./assets/images/Logo.png" alt="logo" />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
</head>
|
<main>
|
||||||
<body>
|
<div class="journal-form" id="review-details">
|
||||||
<main>
|
<form>
|
||||||
<input type="button" value="Home" id="home-btn" onclick="window.location.assign('./index.html')">
|
<fieldset class="meal-name">
|
||||||
<button type="button" id="update-btn">Update</button>
|
<h1 id="d-meal-name" style="font-family: Century Gothic"></h1>
|
||||||
<button type="button" id="delete-btn" class="danger">Delete</button>
|
<h1 id="d-restaurant" style="font-family: Century Gothic; font-size: 30px"></h1>
|
||||||
</main>
|
</fieldset>
|
||||||
<!----> <form id="update-food-entry" class="hidden">
|
|
||||||
<fieldset>
|
|
||||||
<legend>Pic:</legend>
|
|
||||||
<label for="mealImage">
|
|
||||||
Source:
|
|
||||||
<input type="text" id="mealImg" name="mealImg">
|
|
||||||
</label>
|
|
||||||
<label for="image-alt">
|
|
||||||
Alt Text:
|
|
||||||
<input type="text" id="imgAlt" name="imgAlt">
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
|
|
||||||
<legend> Meal: </legend>
|
|
||||||
<label for="Meal: ">Meal:
|
|
||||||
<input type="text" id="mealName" name="mealName" required>
|
|
||||||
</label>
|
|
||||||
<label for="comments">Comments:
|
|
||||||
<br>
|
|
||||||
<textarea name="comments" id="comments"></textarea>
|
|
||||||
</label>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset class="rating">
|
|
||||||
<legend> Rating: </legend>
|
|
||||||
<input type="radio" id="s5" name="rating" value="5"/> <label for="s5"> 5 stars </label>
|
|
||||||
<input type="radio" id="s4" name="rating" value="4"/> <label for="s4"> 4 stars </label>
|
|
||||||
<input type="radio" id="s3" name="rating" value="3"/> <label for="s3"> 3 stars </label>
|
|
||||||
<input type="radio" id="s2" name="rating" value="2"/> <label for="s2"> 2 stars </label>
|
|
||||||
<input type="radio" id="s1" name="rating" value="1"/> <label for="s1"> 1 star </label>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<fieldset class="meal-pics">
|
||||||
<legend>Other Info:</legend>
|
<!-- image source -->
|
||||||
<label for="restaurant">
|
<img width="40%" height="40%" id="d-meal-img" style="margin-left: auto; margin-right: auto; display: block" />
|
||||||
Restaurant:
|
</fieldset>
|
||||||
<input type="text" id="restaurant" name="restaurant" required>
|
|
||||||
</label>
|
<fieldset class="stars-and-comments" style="text-align: center">
|
||||||
<label for="tag-form">
|
<img width="30%" height="30%" id="d-rating" style="margin-left: auto; margin-right: auto; display: block" />
|
||||||
Tags:
|
<p id="d-comments"></p>
|
||||||
<input type="text" id="tag-form" name="tag-form">
|
</fieldset>
|
||||||
<div class='tag-container' id="tag-container-form">
|
|
||||||
|
<fieldset class="meal-tags">
|
||||||
</div>
|
<div class="tag-container" id="d-tags" style="justify-content: center"></div>
|
||||||
<button type="button" id="tag-add-btn">Add Tag</button>
|
</fieldset>
|
||||||
</label>
|
</form>
|
||||||
|
</div>
|
||||||
</fieldset>
|
|
||||||
<button type="submit" value="Submit">Add Review</button>
|
<!---Navigation Buttons-->
|
||||||
</form>
|
<div style="display: flex; justify-content: center">
|
||||||
</body>
|
<img
|
||||||
|
src="./assets/images/home_button_for_interface.png"
|
||||||
|
style="margin: 20px 10px 20px 10px"
|
||||||
|
id="home-btn"
|
||||||
|
title="Home Page"
|
||||||
|
onclick="window.location.assign('./index.html')"
|
||||||
|
height="50"
|
||||||
|
width="50"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="./assets/images/edit_button_for_interface.png"
|
||||||
|
style="margin: 20px 10px 20px 10px"
|
||||||
|
id="update-btn"
|
||||||
|
title="Edit Review"
|
||||||
|
height="50"
|
||||||
|
width="50"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="./assets/images/delete_icon_for_interface.png"
|
||||||
|
style="margin: 20px 10px 20px 10px"
|
||||||
|
id="delete-btn"
|
||||||
|
title="Delete Review"
|
||||||
|
class="danger"
|
||||||
|
height="50"
|
||||||
|
width="50"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div class="journal-form hidden" id="update-form">
|
||||||
|
<h1>Update Entry</h1>
|
||||||
|
|
||||||
|
<form id="new-food-entry">
|
||||||
|
<fieldset>
|
||||||
|
<legend>PICTURE:</legend>
|
||||||
|
<select id="select" name="select">
|
||||||
|
<option value="file">File Upload</option>
|
||||||
|
<option value="photo">Take a Photo</option>
|
||||||
|
</select>
|
||||||
|
<input type="file" accept="image/*" id="mealImg" name="mealImg" />
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<video id="player" width="320" height="240" autoplay hidden></video>
|
||||||
|
<canvas id="photoCanvas" width="320" height="240" hidden></canvas>
|
||||||
|
<button type="button" id="photoButton" hidden>Take Photo</button>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>MEAL NAME:</legend>
|
||||||
|
<label for="Name: "> <input type="text" id="mealName" name="mealName" required /> </label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>RESTAURANT NAME:</legend>
|
||||||
|
<label for="Name:"> <input type="text" id="restaurant" name="restaurant" required /> </label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>RATING:</legend>
|
||||||
|
<div style="display: flex; justify-content: flex-start; align-items: center">
|
||||||
|
<div class="rating">
|
||||||
|
<input type="radio" id="s5" name="rating" value="5" /> <label for="s5" id="s5-select"> 5 stars </label>
|
||||||
|
<input type="radio" id="s4" name="rating" value="4" /> <label for="s4" id="s4-select"> 4 stars </label>
|
||||||
|
<input type="radio" id="s3" name="rating" value="3" /> <label for="s3" id="s3-select"> 3 stars </label>
|
||||||
|
<input type="radio" id="s2" name="rating" value="2" /> <label for="s2" id="s2-select"> 2 stars </label>
|
||||||
|
<input type="radio" id="s1" name="rating" value="1" /> <label for="s1" id="s1-select"> 1 star </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>COMMENTS:</legend>
|
||||||
|
<textarea name="comments" id="comments" rows="5" style="resize: none; width: 100%"></textarea>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>TAGS: (ex. cuisine, distance, cost, etc)</legend>
|
||||||
|
<input type="text" id="tag-form" name="tag-form" />
|
||||||
|
|
||||||
|
<div class="tag-container" id="tag-container-form"></div>
|
||||||
|
<button type="button" id="tag-add-btn">+</button>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<button type="submit" id="save-btn" value="Submit">Save</button>
|
||||||
|
<input type="button" value="Cancel" id="home-btn" onclick="window.location.assign('./index.html')" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
source/assets/images/Logo.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
source/assets/images/create_button.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
source/assets/images/default_plate.png
Normal file
After Width: | Height: | Size: 2.7 MiB |
BIN
source/assets/images/delete_icon_for_interface.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
source/assets/images/edit_button_for_interface.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
source/assets/images/favicon.ico
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
source/assets/images/home_button_for_interface.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 311 KiB |
Before Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 253 KiB |
BIN
source/assets/images/search_button.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
@@ -1,78 +1,175 @@
|
|||||||
|
import { newReviewToStorage } from "./localStorage.js";
|
||||||
|
|
||||||
window.addEventListener("DOMContentLoaded", init);
|
window.addEventListener("DOMContentLoaded", init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates the functionality for creating review cards.
|
||||||
|
*/
|
||||||
function init() {
|
function init() {
|
||||||
// get next id
|
initFormHandler();
|
||||||
|
|
||||||
// creates the key
|
|
||||||
initFormHandler();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a form and associates a new ID with the new review card.
|
||||||
|
*/
|
||||||
function initFormHandler() {
|
function initFormHandler() {
|
||||||
|
// Accesses form components
|
||||||
//accessing form components
|
|
||||||
let tagContainer = document.getElementById("tag-container-form");
|
let tagContainer = document.getElementById("tag-container-form");
|
||||||
let form = document.querySelector("form");
|
let form = document.querySelector("form");
|
||||||
|
|
||||||
form.addEventListener("submit", function(e){
|
// Declaring variable storing image data url
|
||||||
/*
|
let imgDataURL = "";
|
||||||
* User submits the form for their review.
|
|
||||||
* We create reviewCard and put in storage
|
// Accessing components related to taking photo
|
||||||
*/
|
let videoMode = true;
|
||||||
|
let player = document.getElementById("player");
|
||||||
|
let canvas = document.getElementById("photoCanvas");
|
||||||
|
let photoButton = document.getElementById("photoButton");
|
||||||
|
let context = canvas.getContext("2d");
|
||||||
|
|
||||||
|
// Event listener for the photo taking/reset button
|
||||||
|
photoButton.addEventListener("click", () => {
|
||||||
|
// capturing the current video frame
|
||||||
|
if (videoMode) {
|
||||||
|
videoMode = false;
|
||||||
|
|
||||||
|
// setting up the appropriate components for displaying the photo preview
|
||||||
|
photoButton.innerText = "Retake";
|
||||||
|
player.setAttribute("hidden", "");
|
||||||
|
canvas.removeAttribute("hidden", "");
|
||||||
|
|
||||||
|
// displaying the captured snapshot on a canvas and saving it as a data url
|
||||||
|
context.drawImage(player, 0, 0, canvas.width, canvas.height);
|
||||||
|
imgDataURL = canvas.toDataURL();
|
||||||
|
}
|
||||||
|
// returning to displaying the video stream
|
||||||
|
else {
|
||||||
|
videoMode = true;
|
||||||
|
|
||||||
|
// setting up the appropriate components for the video stream
|
||||||
|
photoButton.innerText = "Take Photo";
|
||||||
|
canvas.setAttribute("hidden", "");
|
||||||
|
player.removeAttribute("hidden", "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event listener for reading image form different data
|
||||||
|
let select = document.getElementById("select");
|
||||||
|
const input = document.getElementById("mealImg");
|
||||||
|
select.addEventListener("change", function () {
|
||||||
|
// Select a photo with HTML file selector
|
||||||
|
if (select.value == "file") {
|
||||||
|
// enabling file upload components and hiding photo taking components
|
||||||
|
input.removeAttribute("hidden", "");
|
||||||
|
player.setAttribute("hidden", "");
|
||||||
|
canvas.setAttribute("hidden", "");
|
||||||
|
photoButton.setAttribute("hidden", "");
|
||||||
|
|
||||||
|
// stopping the video stream
|
||||||
|
player.srcObject.getVideoTracks()[0].stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take a photo
|
||||||
|
else {
|
||||||
|
// enabling photo taking components and hiding file upload components
|
||||||
|
videoMode = true;
|
||||||
|
photoButton.innerText = "Take Photo";
|
||||||
|
input.setAttribute("hidden", "");
|
||||||
|
player.removeAttribute("hidden", "");
|
||||||
|
photoButton.removeAttribute("hidden", "");
|
||||||
|
|
||||||
|
// getting video stream from user's camera then displaying it on a video element
|
||||||
|
navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
|
||||||
|
player.srcObject = stream;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Addresses sourcing image from local file
|
||||||
|
document.getElementById("mealImg").addEventListener("change", function () {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
// Store image data URL after successful image load
|
||||||
|
reader.addEventListener(
|
||||||
|
"load",
|
||||||
|
() => {
|
||||||
|
imgDataURL = reader.result;
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert image file into data URL for local storage
|
||||||
|
reader.readAsDataURL(document.getElementById("mealImg").files[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
form.addEventListener("submit", function (e) {
|
||||||
|
// Create reviewObject and put in storage
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let formData = new FormData(form);
|
let formData = new FormData(form);
|
||||||
let reviewObject = {};
|
let reviewObject = {};
|
||||||
|
|
||||||
|
// Adds data to the reviewObject from form data
|
||||||
for (let [key, value] of formData) {
|
for (let [key, value] of formData) {
|
||||||
console.log(`${key}`);
|
console.log(`${key}`);
|
||||||
console.log(`${value}`);
|
console.log(`${value}`);
|
||||||
if (`${key}` !== "tag-form") {
|
if (`${key}` !== "tag-form") {
|
||||||
reviewObject[`${key}`] = `${value}`;
|
reviewObject[`${key}`] = `${value}`;
|
||||||
}
|
}
|
||||||
}
|
if (`${key}` === "mealImg" && imgDataURL !== "") {
|
||||||
reviewObject["tags"] = [];
|
reviewObject["mealImg"] = imgDataURL;
|
||||||
|
}
|
||||||
let tags = document.querySelectorAll(".tag");
|
|
||||||
for(let i = 0; i < tags.length; i ++) {
|
|
||||||
reviewObject["tags"].push(tags[i].innerHTML);
|
|
||||||
tagContainer.removeChild(tags[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//grabbing the nextID, and putting our review object in storage associated with the ID
|
// Makes sure that ratings is filled
|
||||||
let nextReviewId = JSON.parse(localStorage.getItem("nextID"));
|
if (reviewObject["rating"] != null) {
|
||||||
reviewObject["reviewID"] = nextReviewId;
|
//Adds rags separately as an array
|
||||||
|
reviewObject["tags"] = [];
|
||||||
|
|
||||||
localStorage.setItem("review"+nextReviewId, JSON.stringify(reviewObject));
|
// Grabs tags
|
||||||
sessionStorage.setItem("currID", JSON.stringify(nextReviewId));
|
let tags = document.querySelectorAll(".tag");
|
||||||
|
for (let i = 0; i < tags.length; i++) {
|
||||||
|
reviewObject["tags"].push(tags[i].innerHTML);
|
||||||
|
tagContainer.removeChild(tags[i]);
|
||||||
|
}
|
||||||
|
|
||||||
//updating our activeIDS list
|
// Assigns the new review with a new ID
|
||||||
let tempIdArr = JSON.parse(localStorage.getItem("activeIDS"));
|
let nextReviewId = newReviewToStorage(reviewObject);
|
||||||
tempIdArr.push(nextReviewId);
|
sessionStorage.setItem("currID", JSON.stringify(nextReviewId));
|
||||||
localStorage.setItem("activeIDS", JSON.stringify(tempIdArr));
|
|
||||||
|
|
||||||
|
|
||||||
//increment nextID for next review creation
|
|
||||||
nextReviewId++;
|
|
||||||
localStorage.setItem("nextID", JSON.stringify(nextReviewId));
|
|
||||||
|
|
||||||
window.location.assign('./ReviewDetails.html');
|
// Redirects to a page that shows the newly created review
|
||||||
|
window.location.assign("./ReviewDetails.html");
|
||||||
|
}
|
||||||
|
// Does not let user proceed if rating is not complete
|
||||||
|
else {
|
||||||
|
window.alert("NO! FILL IN STARS");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let tagAddBtn = document.getElementById("tagAdd");
|
// Event listener for tag functionality
|
||||||
tagAddBtn.addEventListener("click", ()=> {
|
let tagAddBtn = document.getElementById("tag-add-btn");
|
||||||
|
//Set used to track tags and ensure no duplicates
|
||||||
|
let tagSet = new Set();
|
||||||
|
tagAddBtn.addEventListener("click", () => {
|
||||||
let tagField = document.getElementById("tag-form");
|
let tagField = document.getElementById("tag-form");
|
||||||
if (tagField.value.length > 0) {
|
|
||||||
let tagLabel = document.createElement("label");
|
|
||||||
tagLabel.innerHTML = tagField.value;
|
|
||||||
tagLabel.setAttribute("class","tag");
|
|
||||||
tagLabel.addEventListener("click",()=> {
|
|
||||||
tagContainer.removeChild(tagLabel);
|
|
||||||
});
|
|
||||||
|
|
||||||
tagContainer.append(tagLabel);
|
|
||||||
tagField.value = "";
|
|
||||||
|
|
||||||
|
// If there is a tag, it'll display the tag
|
||||||
|
if (tagField.value.length > 0) {
|
||||||
|
let tagSetVal = tagField.value.toLocaleLowerCase();
|
||||||
|
if (!tagSet.has(tagSetVal)) {
|
||||||
|
let tagLabel = document.createElement("label");
|
||||||
|
tagLabel.innerHTML = tagField.value;
|
||||||
|
tagLabel.setAttribute("class", "tag");
|
||||||
|
tagSet.add(tagSetVal);
|
||||||
|
tagLabel.addEventListener("click", () => {
|
||||||
|
tagContainer.removeChild(tagLabel);
|
||||||
|
tagSet.delete(tagSetVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
tagContainer.append(tagLabel);
|
||||||
|
} else {
|
||||||
|
window.alert("No duplicate tags allowed");
|
||||||
|
}
|
||||||
|
tagField.value = "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,250 +4,265 @@ class ReviewCard extends HTMLElement {
|
|||||||
// Called once when document.createElement('review-card') is called, or
|
// Called once when document.createElement('review-card') is called, or
|
||||||
// the element is written into the DOM directly as <review-card>
|
// the element is written into the DOM directly as <review-card>
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
let shadowEl = this.attachShadow({mode:"open"});
|
let shadowEl = this.attachShadow({ mode: "open" });
|
||||||
|
|
||||||
let articleEl = document.createElement("article");
|
let articleEl = document.createElement("article");
|
||||||
|
|
||||||
let styleEl = document.createElement("style");
|
let styleEl = document.createElement("style");
|
||||||
styleEl.textContent = `
|
styleEl.textContent = `
|
||||||
* {
|
* {
|
||||||
font-family: sans-serif;
|
font-family: Century Gothic;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
cursor: pointer;
|
||||||
|
}
|
||||||
a {
|
|
||||||
text-decoration: none;
|
a {
|
||||||
}
|
text-decoration: none;
|
||||||
|
}
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
a:hover {
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
article {
|
|
||||||
align-items: center;
|
article {
|
||||||
border: 1px solid rgb(223, 225, 229);
|
align-items: center;
|
||||||
border-radius: 8px;
|
border: 2px solid rgb(31, 41, 32);
|
||||||
display: grid;
|
border-radius: 8px;
|
||||||
grid-template-rows: 118px 56px 14px 18px 15px 36px;
|
height: auto;
|
||||||
height: auto;
|
row-gap: 5px;
|
||||||
row-gap: 5px;
|
padding: 0 16px 16px 16px;
|
||||||
padding: 0 16px 16px 16px;
|
width: 200px;
|
||||||
width: 178px;
|
margin: 8px 8px 8px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.rating {
|
div.rating {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 5px;
|
display: flex;
|
||||||
display: flex;
|
}
|
||||||
}
|
|
||||||
|
div.rating>img {
|
||||||
div.rating>img {
|
height: auto;
|
||||||
height: auto;
|
display: inline-block;
|
||||||
display: inline-block;
|
object-fit: scale-down;
|
||||||
object-fit: scale-down;
|
}
|
||||||
width: 78px;
|
|
||||||
}
|
article>img {
|
||||||
|
border-top-left-radius: 6px;
|
||||||
article>img {
|
border-top-right-radius: 6px;
|
||||||
border-top-left-radius: 8px;
|
height: 120px;
|
||||||
border-top-right-radius: 8px;
|
object-fit: cover;
|
||||||
height: 118px;
|
margin-left: -16px;
|
||||||
object-fit: cover;
|
margin-right: -16px;
|
||||||
margin-left: -16px;
|
width: calc(100% + 32px);
|
||||||
width: calc(100% + 32px);
|
}
|
||||||
}
|
|
||||||
|
.meal-name-div {
|
||||||
label.restaurant-name {
|
height: 54px;
|
||||||
color: black !important;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
label.meal-name {
|
label.restaurant-name {
|
||||||
display: -webkit-box;
|
color: black !important;
|
||||||
font-size: 16px;
|
}
|
||||||
height: 36px;
|
|
||||||
line-height: 18px;
|
label.meal-name {
|
||||||
overflow: hidden;
|
font-size: 24px;
|
||||||
-webkit-line-clamp: 2;
|
height: 36px;
|
||||||
-webkit-box-orient: vertical;
|
}
|
||||||
}
|
|
||||||
|
label:not(.meal-name),
|
||||||
label:not(.meal-name),
|
span,
|
||||||
span,
|
time {
|
||||||
time {
|
color: #70757A;
|
||||||
color: #70757A;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
}
|
||||||
}
|
|
||||||
`;
|
.tag-container-div {
|
||||||
|
margin-top: 20px;
|
||||||
|
height: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-container {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.a-tag {
|
||||||
|
background-color:#94da97;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #94da97;
|
||||||
|
padding: 0px 6px 2px 6px;
|
||||||
|
margin: 2px 2px 2px 2px;
|
||||||
|
font-weight: bold;
|
||||||
|
overflow: hidden;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
articleEl.append(styleEl);
|
articleEl.append(styleEl);
|
||||||
shadowEl.append(articleEl);
|
shadowEl.append(articleEl);
|
||||||
this.shadowEl = shadowEl;
|
this.shadowEl = shadowEl;
|
||||||
//attach event listener to each recipe-card
|
|
||||||
|
// Attach event listener to each review-card
|
||||||
this.addEventListener("click", (event) => {
|
this.addEventListener("click", (event) => {
|
||||||
console.log(event.target);
|
console.log(event.target);
|
||||||
console.log(event.target.reviewId);
|
console.log(event.target.reviewId);
|
||||||
//Option 1: sending current data to second html page using localStorage (could also just store index)
|
// Saves the ID for corresponding review on new page (for data retrieval)
|
||||||
sessionStorage.setItem("currID", JSON.stringify(event.target.data.reviewID));
|
sessionStorage.setItem("currID", JSON.stringify(event.target.data.reviewID));
|
||||||
|
// Goes to the new page for the review
|
||||||
window.location.assign("./ReviewDetails.html");
|
window.location.assign("./ReviewDetails.html");
|
||||||
/*
|
|
||||||
//Option 2: sending current data to second html page using string query w/ url (currently not storing value)
|
|
||||||
let reviewFields = window.location.search.slice(1).split("&");
|
|
||||||
for(let i = 0; i < reviewFields.length; i++) {
|
|
||||||
let kv = reviewFields[i].split("=");
|
|
||||||
let key = kv[0];
|
|
||||||
let value = kv[1];
|
|
||||||
console.log(key);
|
|
||||||
console.log(value);
|
|
||||||
// What you want to do with name and value...
|
|
||||||
}*/
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the .data property is set on this element.
|
* Called when the .data property is set on this element.
|
||||||
*
|
*
|
||||||
* For Example:
|
* For Example:
|
||||||
* let reviewCard = document.createElement('review-card');
|
* let reviewCard = document.createElement('review-card');
|
||||||
* reviewCard.data = { foo: 'bar' }
|
* reviewCard.data = { foo: 'bar' }
|
||||||
*
|
*
|
||||||
* @param {Object} data - The data to pass into the <review-card>, must be of the
|
* @param {Object} data - The data to pass into the <review-card>, must be of the
|
||||||
* following format:
|
* following format:
|
||||||
* {
|
* {
|
||||||
* "mealImg": "string",
|
* "mealImg": string,
|
||||||
* "imgAlt": "string",
|
* "mealName": string,
|
||||||
* "mealName": "string",
|
* "comments": string,
|
||||||
* "comments": "string",
|
* "rating": number,
|
||||||
* "rating": number,
|
* "restaurant": string,
|
||||||
* "restaurant": "string",
|
* "reviewID": number,
|
||||||
* "tags": string array
|
* "tags": string array
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
set data(data) {
|
set data(data) {
|
||||||
// If nothing was passed in, return
|
// If nothing was passed in, return
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
// Select the <article> we added to the Shadow DOM in the constructor
|
// Select the <article> we added to the Shadow DOM in the constructor
|
||||||
let articleEl = this.shadowEl.querySelector("article");
|
let articleEl = this.shadowEl.querySelector("article");
|
||||||
|
|
||||||
// setting the article elements for the review card
|
|
||||||
this.reviewID = data["reviewID"];
|
|
||||||
|
|
||||||
//image setup
|
// Setting the article elements for the review card
|
||||||
|
this.reviewID = data["reviewID"];
|
||||||
|
|
||||||
|
// Image setup
|
||||||
let mealImg = document.createElement("img");
|
let mealImg = document.createElement("img");
|
||||||
mealImg.setAttribute("id", "a-mealImg");
|
mealImg.setAttribute("id", "a-meal-img");
|
||||||
mealImg.setAttribute("alt",data["imgAlt"]);
|
mealImg.setAttribute("alt", "Meal Photo Corrupted");
|
||||||
if(data["mealImg"] != ""){
|
mealImg.setAttribute("src", data["mealImg"]);
|
||||||
mealImg.setAttribute("src",data["mealImg"]);
|
mealImg.addEventListener("error", function (e) {
|
||||||
}
|
mealImg.setAttribute("src", "./assets/images/default_plate.png");
|
||||||
else{
|
e.onerror = null;
|
||||||
mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png");
|
});
|
||||||
}
|
|
||||||
|
|
||||||
//meal name setup
|
// Meal name setup
|
||||||
|
let meallabelDiv = document.createElement("div");
|
||||||
|
meallabelDiv.setAttribute("class", "meal-name-div");
|
||||||
let mealLabel = document.createElement("label");
|
let mealLabel = document.createElement("label");
|
||||||
mealLabel.setAttribute("id", "a-mealName");
|
mealLabel.setAttribute("id", "a-meal-name");
|
||||||
mealLabel.setAttribute("class","meal-name");
|
mealLabel.setAttribute("class", "meal-name");
|
||||||
mealLabel.innerHTML = data["mealName"];
|
mealLabel.innerHTML = data["mealName"];
|
||||||
|
meallabelDiv.append(mealLabel);
|
||||||
|
|
||||||
//restaurant name setup
|
// Restaurant name setup
|
||||||
let restaurantLabel = document.createElement("label");
|
let restaurantLabel = document.createElement("label");
|
||||||
restaurantLabel.setAttribute("id", "a-restaurant");
|
restaurantLabel.setAttribute("id", "a-restaurant");
|
||||||
restaurantLabel.setAttribute("class","restaurant-name");
|
restaurantLabel.setAttribute("class", "restaurant-name");
|
||||||
restaurantLabel.innerHTML = data["restaurant"];
|
restaurantLabel.innerHTML = data["restaurant"];
|
||||||
|
|
||||||
//comment section setup (display set to none)
|
// Comment section setup (display set to none)
|
||||||
let comments = document.createElement("p");
|
let comments = document.createElement("p");
|
||||||
comments.setAttribute("id", "a-comments");
|
comments.setAttribute("id", "a-comments");
|
||||||
comments.style.display = "none";
|
comments.style.display = "none";
|
||||||
comments.innerText = data["comments"];
|
comments.innerText = data["comments"];
|
||||||
|
|
||||||
//other info: rating
|
// Rating setup
|
||||||
let ratingDiv = document.createElement("div");
|
let ratingDiv = document.createElement("div");
|
||||||
ratingDiv.setAttribute("class", "rating");
|
ratingDiv.setAttribute("class", "rating");
|
||||||
let starsImg = document.createElement("img");
|
let starsImg = document.createElement("img");
|
||||||
starsImg.setAttribute("id", "a-rating");
|
starsImg.setAttribute("id", "a-rating");
|
||||||
starsImg.setAttribute("src", "./assets/images/icons/"+data["rating"]+"-star.svg");
|
starsImg.setAttribute("src", "./assets/images/" + data["rating"] + "-star.svg");
|
||||||
starsImg.setAttribute("alt", data["rating"] +" stars");
|
starsImg.setAttribute("alt", data["rating"] + " stars");
|
||||||
starsImg.setAttribute("num", data["rating"]);
|
starsImg.setAttribute("num", data["rating"]);
|
||||||
ratingDiv.append(starsImg);
|
ratingDiv.append(starsImg);
|
||||||
|
|
||||||
//added tags
|
// Tags setup
|
||||||
|
let tagContainerDiv = document.createElement("div");
|
||||||
|
tagContainerDiv.setAttribute("class", "tag-container-div");
|
||||||
let tagContainer = document.createElement("div");
|
let tagContainer = document.createElement("div");
|
||||||
tagContainer.setAttribute("class", "tag-container");
|
tagContainer.setAttribute("class", "tag-container");
|
||||||
tagContainer.setAttribute("id", "a-tags");
|
tagContainer.setAttribute("id", "a-tags");
|
||||||
tagContainer.setAttribute("list", data["tags"]);
|
tagContainer.setAttribute("list", data["tags"]);
|
||||||
if(data["tags"]){
|
|
||||||
|
// Checks if user gave tags, if so added to review card
|
||||||
|
if (data["tags"]) {
|
||||||
for (let i = 0; i < data["tags"].length; i++) {
|
for (let i = 0; i < data["tags"].length; i++) {
|
||||||
let newTag = document.createElement("label");
|
let newTag = document.createElement("label");
|
||||||
newTag.setAttribute("class","tag");
|
newTag.setAttribute("class", "a-tag");
|
||||||
newTag.innerHTML = data["tags"][i];
|
newTag.innerHTML = data["tags"][i];
|
||||||
tagContainer.append(newTag);
|
tagContainer.append(newTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tagContainerDiv.append(tagContainer);
|
||||||
|
|
||||||
//adding final ID to data!
|
// Setting all the data to the review card
|
||||||
|
|
||||||
articleEl.append(mealImg);
|
articleEl.append(mealImg);
|
||||||
articleEl.append(mealLabel);
|
articleEl.append(meallabelDiv);
|
||||||
articleEl.append(restaurantLabel);
|
articleEl.append(restaurantLabel);
|
||||||
articleEl.append(ratingDiv);
|
articleEl.append(ratingDiv);
|
||||||
articleEl.append(tagContainer);
|
articleEl.append(tagContainerDiv);
|
||||||
articleEl.append(comments);
|
articleEl.append(comments);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when getting the .data property of this element.
|
* Called when getting the .data property of this element.
|
||||||
*
|
*
|
||||||
* For Example:
|
* For Example:
|
||||||
* let reviewCard = document.createElement('review-card');
|
* let reviewCard = document.createElement('review-card');
|
||||||
* reviewCard.data = { foo: 'bar' }
|
* reviewCard.data = { foo: 'bar' }
|
||||||
*
|
*
|
||||||
* @return {Object} data - The data from the <review-card>, of the
|
* @return {Object} data - The data from the <review-card>, of the
|
||||||
* following format:
|
* following format:
|
||||||
* {
|
* {
|
||||||
* "mealImg": "string",
|
* "mealImg": string,
|
||||||
* "imgAlt": "string",
|
* "mealName": string,
|
||||||
* "mealName": "string",
|
* "comments": string,
|
||||||
* "comments": "string",
|
* "rating": number,
|
||||||
* "rating": number,
|
* "restaurant": string,
|
||||||
* "restaurant": "string",
|
* "reviewID": number,
|
||||||
* "tags": string array
|
* "tags": string array
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
get data() {
|
get data() {
|
||||||
|
|
||||||
let dataContainer = {};
|
let dataContainer = {};
|
||||||
|
|
||||||
// getting the article elements for the review card
|
// Getting the article elements for the review card
|
||||||
dataContainer["reviewID"] = this.reviewID;
|
dataContainer["reviewID"] = this.reviewID;
|
||||||
|
|
||||||
//get image
|
//get image
|
||||||
let mealImg = this.shadowEl.getElementById("a-mealImg");
|
let mealImg = this.shadowEl.getElementById("a-meal-img");
|
||||||
dataContainer["mealImg"] = mealImg.getAttribute("src");
|
dataContainer["mealImg"] = mealImg.getAttribute("src");
|
||||||
dataContainer["imgAlt"] = mealImg.getAttribute("alt");
|
|
||||||
|
|
||||||
//get meal name
|
//get meal name
|
||||||
let mealLabel = this.shadowEl.getElementById("a-mealName");
|
let mealLabel = this.shadowEl.getElementById("a-meal-name");
|
||||||
dataContainer["mealName"] = mealLabel.innerHTML;
|
dataContainer["mealName"] = mealLabel.innerHTML;
|
||||||
|
|
||||||
//get comment section
|
// Get comment section
|
||||||
let comments = this.shadowEl.getElementById("a-comments");
|
let comments = this.shadowEl.getElementById("a-comments");
|
||||||
console.log(comments);
|
console.log(comments);
|
||||||
dataContainer["comments"] = comments.innerText;
|
dataContainer["comments"] = comments.innerText;
|
||||||
|
|
||||||
//get other info: rating
|
// Get rating
|
||||||
let starsImg = this.shadowEl.getElementById("a-rating");
|
let starsImg = this.shadowEl.getElementById("a-rating");
|
||||||
dataContainer["rating"] = starsImg.getAttribute("num");
|
dataContainer["rating"] = starsImg.getAttribute("num");
|
||||||
|
|
||||||
//get restaurant name
|
//Get restaurant name
|
||||||
let restaurantLabel = this.shadowEl.getElementById("a-restaurant");
|
let restaurantLabel = this.shadowEl.getElementById("a-restaurant");
|
||||||
dataContainer["restaurant"] = restaurantLabel.innerHTML;
|
dataContainer["restaurant"] = restaurantLabel.innerHTML;
|
||||||
|
|
||||||
//get tags
|
// Get tags
|
||||||
let tagContainer = this.shadowEl.getElementById("a-tags");
|
let tagContainer = this.shadowEl.getElementById("a-tags");
|
||||||
dataContainer["tags"] = tagContainer.getAttribute("list").split(",");
|
dataContainer["tags"] = tagContainer.getAttribute("list").split(",");
|
||||||
|
|
||||||
|
@@ -1,114 +1,272 @@
|
|||||||
//reviewDetails.js
|
//reviewDetails.js
|
||||||
import {getReviewsFromStorage, saveReviewsToStorage} from "./localStorage.js";
|
import { deleteReviewFromStorage, getReviewFromStorage, updateReviewToStorage } from "./localStorage.js";
|
||||||
|
|
||||||
// Run the init() function when the page has loaded
|
// Run the init() function when the page has loaded
|
||||||
window.addEventListener("DOMContentLoaded", init);
|
window.addEventListener("DOMContentLoaded", init);
|
||||||
|
|
||||||
function init(){
|
/**
|
||||||
|
* Populates the relevant data to the details from local storage review.
|
||||||
|
*/
|
||||||
|
function init() {
|
||||||
|
setupInfo();
|
||||||
setupDelete();
|
setupDelete();
|
||||||
setupUpdate();
|
setupUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDelete(){
|
/**
|
||||||
|
* Populates the relevant data to the details from local storage review
|
||||||
|
*/
|
||||||
|
function setupInfo() {
|
||||||
|
let currID = JSON.parse(sessionStorage.getItem("currID"));
|
||||||
|
let currReview = getReviewFromStorage(currID);
|
||||||
|
|
||||||
|
//meal image
|
||||||
|
let mealImg = document.getElementById("d-meal-img");
|
||||||
|
mealImg.setAttribute("src", currReview["mealImg"]);
|
||||||
|
mealImg.addEventListener("error", function (e) {
|
||||||
|
mealImg.setAttribute("src", "./assets/images/default_plate.png");
|
||||||
|
e.onerror = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
//meal name
|
||||||
|
let mealLabel = document.getElementById("d-meal-name");
|
||||||
|
mealLabel.innerHTML = currReview["mealName"];
|
||||||
|
|
||||||
|
//restaurant name
|
||||||
|
let restaurantLabel = document.getElementById("d-restaurant");
|
||||||
|
restaurantLabel.innerHTML = currReview["restaurant"];
|
||||||
|
|
||||||
|
//comments
|
||||||
|
let comments = document.getElementById("d-comments");
|
||||||
|
comments.innerText = currReview["comments"];
|
||||||
|
|
||||||
|
//rating
|
||||||
|
let starsImg = document.getElementById("d-rating");
|
||||||
|
starsImg.setAttribute("src", "./assets/images/" + currReview["rating"] + "-star.svg");
|
||||||
|
starsImg.setAttribute("alt", currReview["rating"] + " stars");
|
||||||
|
|
||||||
|
//tags
|
||||||
|
let tagContainer = document.getElementById("d-tags");
|
||||||
|
if (currReview["tags"]) {
|
||||||
|
for (let i = 0; i < currReview["tags"].length; i++) {
|
||||||
|
let newTag = document.createElement("label");
|
||||||
|
newTag.setAttribute("class", "d-tag");
|
||||||
|
newTag.innerHTML = currReview["tags"][i];
|
||||||
|
tagContainer.append(newTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up delete button to delete reveiw from storage and switch to homepage.
|
||||||
|
*/
|
||||||
|
function setupDelete() {
|
||||||
let deleteBtn = document.getElementById("delete-btn");
|
let deleteBtn = document.getElementById("delete-btn");
|
||||||
let currID = JSON.parse(sessionStorage.getItem("currID"));
|
let currID = JSON.parse(sessionStorage.getItem("currID"));
|
||||||
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
|
deleteBtn.addEventListener("click", function () {
|
||||||
deleteBtn.addEventListener("click", function(){
|
if (window.confirm("Are you sure you want to delete this entry?")) {
|
||||||
if(window.confirm("Are you sure you want to delete this entry?")){
|
deleteReviewFromStorage(currID);
|
||||||
for (let i in activeIDS) {
|
sessionStorage.removeItem("currID");
|
||||||
if (activeIDS[i] == currID) {
|
window.location.assign("./index.html");
|
||||||
activeIDS.splice(i,1);
|
|
||||||
localStorage.setItem('activeIDS', JSON.stringify(activeIDS));
|
|
||||||
sessionStorage.removeItem('currID');
|
|
||||||
localStorage.removeItem(`review${currID}`);
|
|
||||||
window.location.assign("./index.html");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupUpdate(){
|
/**
|
||||||
|
* Sets up update button to reveal form and update info in storage and the current page.
|
||||||
|
*/
|
||||||
|
function setupUpdate() {
|
||||||
let updateBtn = document.getElementById("update-btn");
|
let updateBtn = document.getElementById("update-btn");
|
||||||
let currID = JSON.parse(sessionStorage.getItem("currID"));
|
let currID = JSON.parse(sessionStorage.getItem("currID"));
|
||||||
let currReview = JSON.parse(localStorage.getItem(`review${currID}`));
|
let currReview = getReviewFromStorage(currID);
|
||||||
let form = document.getElementById("update-food-entry");
|
let form = document.getElementById("new-food-entry");
|
||||||
updateBtn.addEventListener("click", function(){
|
let updateDiv = document.getElementById("update-form");
|
||||||
|
updateBtn.addEventListener("click", function () {
|
||||||
//update function
|
//update function
|
||||||
if(currReview){
|
|
||||||
form.style.display = "block";
|
|
||||||
let tagContainer = document.getElementById("tag-container-form");
|
|
||||||
|
|
||||||
//Set value of each input element to current's values
|
updateDiv.classList.remove("hidden");
|
||||||
document.getElementById("mealImg").defaultValue = currReview["mealImg"];
|
|
||||||
document.getElementById("imgAlt").defaultValue = currReview["imgAlt"];
|
|
||||||
document.getElementById("mealName").defaultValue = currReview["mealName"];
|
|
||||||
document.getElementById("comments").textContent = currReview["comments"];
|
|
||||||
document.getElementById("s" + `${currReview["rating"]}`).checked = true;
|
|
||||||
document.getElementById("restaurant").defaultValue = currReview["restaurant"];
|
|
||||||
|
|
||||||
if(currReview["tags"]){
|
let tagContainer = document.getElementById("tag-container-form");
|
||||||
while (tagContainer.firstChild) {
|
|
||||||
tagContainer.removeChild(tagContainer.firstChild);
|
//Set value of each input element to current's values
|
||||||
|
document.getElementById("mealImg").defaultValue = currReview["mealImg"];
|
||||||
|
document.getElementById("mealName").defaultValue = currReview["mealName"];
|
||||||
|
document.getElementById("comments").textContent = currReview["comments"];
|
||||||
|
document.getElementById("s" + `${currReview["rating"]}`).checked = true;
|
||||||
|
document.getElementById("restaurant").defaultValue = currReview["restaurant"];
|
||||||
|
|
||||||
|
//Set used to track tags and ensure no duplicates
|
||||||
|
let tagSet = new Set();
|
||||||
|
|
||||||
|
if (currReview["tags"]) {
|
||||||
|
while (tagContainer.firstChild) {
|
||||||
|
tagContainer.removeChild(tagContainer.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tagSetVal;
|
||||||
|
for (let i = 0; i < currReview["tags"].length; i++) {
|
||||||
|
tagSetVal = currReview["tags"][i].toLocaleLowerCase();
|
||||||
|
tagSet.add(tagSetVal);
|
||||||
|
let newTag = document.createElement("label");
|
||||||
|
newTag.setAttribute("class", "tag");
|
||||||
|
newTag.innerHTML = currReview["tags"][i];
|
||||||
|
newTag.addEventListener("click", () => {
|
||||||
|
tagContainer.removeChild(newTag);
|
||||||
|
tagSet.delete(tagSetVal);
|
||||||
|
});
|
||||||
|
tagContainer.append(newTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declaring variable storing image data url
|
||||||
|
let imgDataURL = "";
|
||||||
|
|
||||||
|
// Accessing components related to taking photo
|
||||||
|
let videoMode = true;
|
||||||
|
let player = document.getElementById("player");
|
||||||
|
let canvas = document.getElementById("photoCanvas");
|
||||||
|
let photoButton = document.getElementById("photoButton");
|
||||||
|
let context = canvas.getContext("2d");
|
||||||
|
|
||||||
|
// Event listener for the photo taking/reset button
|
||||||
|
photoButton.addEventListener("click", () => {
|
||||||
|
// capturing the current video frame
|
||||||
|
if (videoMode) {
|
||||||
|
videoMode = false;
|
||||||
|
|
||||||
|
// setting up the appropriate components for displaying the photo preview
|
||||||
|
photoButton.innerText = "Retake";
|
||||||
|
player.setAttribute("hidden", "");
|
||||||
|
canvas.removeAttribute("hidden", "");
|
||||||
|
|
||||||
|
// displaying the captured snapshot on a canvas and saving it as a data url
|
||||||
|
context.drawImage(player, 0, 0, canvas.width, canvas.height);
|
||||||
|
imgDataURL = canvas.toDataURL();
|
||||||
|
}
|
||||||
|
// returning to displaying the video stream
|
||||||
|
else {
|
||||||
|
videoMode = true;
|
||||||
|
|
||||||
|
// setting up the appropriate components for the video stream
|
||||||
|
photoButton.innerText = "Take Photo";
|
||||||
|
canvas.setAttribute("hidden", "");
|
||||||
|
player.removeAttribute("hidden", "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* change the input source of the image between local file and taking photo
|
||||||
|
* depending on user's selection
|
||||||
|
*/
|
||||||
|
let select = document.getElementById("select");
|
||||||
|
const input = document.getElementById("mealImg");
|
||||||
|
select.addEventListener("change", function () {
|
||||||
|
console.log("1");
|
||||||
|
// Select a photo with HTML file selector
|
||||||
|
if (select.value == "file") {
|
||||||
|
// enabling file upload components and hiding photo taking components
|
||||||
|
input.removeAttribute("hidden", "");
|
||||||
|
player.setAttribute("hidden", "");
|
||||||
|
canvas.setAttribute("hidden", "");
|
||||||
|
photoButton.setAttribute("hidden", "");
|
||||||
|
|
||||||
|
// stopping the video stream
|
||||||
|
player.srcObject.getVideoTracks()[0].stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take a photo
|
||||||
|
else {
|
||||||
|
// enabling photo taking components and hiding file upload components
|
||||||
|
videoMode = true;
|
||||||
|
photoButton.innerText = "Take Photo";
|
||||||
|
input.setAttribute("hidden", "");
|
||||||
|
player.removeAttribute("hidden", "");
|
||||||
|
photoButton.removeAttribute("hidden", "");
|
||||||
|
|
||||||
|
// getting video stream from user's camera then displaying it on a video element
|
||||||
|
navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
|
||||||
|
player.srcObject = stream;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//addressing sourcing image from local file
|
||||||
|
document.getElementById("mealImg").addEventListener("change", function () {
|
||||||
|
console.log("reading used");
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
//store image data URL after successful image load
|
||||||
|
reader.addEventListener(
|
||||||
|
"load",
|
||||||
|
() => {
|
||||||
|
imgDataURL = reader.result;
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
//convert image file into data URL for local storage
|
||||||
|
reader.readAsDataURL(document.getElementById("mealImg").files[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Take formdata values as newData when submit
|
||||||
|
form.addEventListener("submit", function () {
|
||||||
|
/*
|
||||||
|
* User submits the form for their review.
|
||||||
|
* We create reviewCard data, replace in storage, and update tags
|
||||||
|
*/
|
||||||
|
let formData = new FormData(form);
|
||||||
|
let newData = {};
|
||||||
|
//iterate through formData and add to newData
|
||||||
|
for (let [key, value] of formData) {
|
||||||
|
console.log(`${key}`);
|
||||||
|
console.log(`${value}`);
|
||||||
|
if (`${key}` !== "tag-form") {
|
||||||
|
newData[`${key}`] = `${value}`;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < currReview["tags"].length; i++) {
|
// Account for the case where image is not updated
|
||||||
let newTag = document.createElement("label");
|
if (`${key}` === "mealImg" && imgDataURL === "") {
|
||||||
newTag.setAttribute("class","tag");
|
newData["mealImg"] = currReview["mealImg"];
|
||||||
newTag.innerHTML = currReview["tags"][i];
|
} else if (`${key}` === "mealImg") {
|
||||||
newTag.addEventListener("click",()=> {
|
newData["mealImg"] = imgDataURL;
|
||||||
tagContainer.removeChild(newTag);
|
|
||||||
});
|
|
||||||
tagContainer.append(newTag);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Take formdata values as newData when submit
|
newData["tags"] = [];
|
||||||
form.addEventListener("submit", function(){
|
|
||||||
/*
|
|
||||||
* User submits the form for their review.
|
|
||||||
* We create reviewCard and put in storage
|
|
||||||
*/
|
|
||||||
let formData = new FormData(form);
|
|
||||||
let newData = {};
|
|
||||||
for (let [key, value] of formData) {
|
|
||||||
console.log(`${key}`);
|
|
||||||
console.log(`${value}`);
|
|
||||||
if (`${key}` !== "tag-form") {
|
|
||||||
newData[`${key}`] = `${value}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newData["tags"] = [];
|
|
||||||
|
|
||||||
let tags = document.querySelectorAll(".tag");
|
|
||||||
for(let i = 0; i < tags.length; i ++) {
|
|
||||||
newData["tags"].push(tags[i].innerHTML);
|
|
||||||
tagContainer.removeChild(tags[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
newData["reviewID"] = currID;
|
let tags = document.querySelectorAll(".tag");
|
||||||
|
for (let i = 0; i < tags.length; i++) {
|
||||||
|
newData["tags"].push(tags[i].innerHTML);
|
||||||
|
tagContainer.removeChild(tags[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
newData["reviewID"] = currID;
|
||||||
|
|
||||||
localStorage.setItem("review"+currID, JSON.stringify(newData));
|
updateReviewToStorage(currID, newData);
|
||||||
|
|
||||||
form.style.display = "none";
|
updateDiv.classList.add("hidden");
|
||||||
|
});
|
||||||
|
|
||||||
});
|
// Adding tag to form functionality
|
||||||
|
let tagAddBtn = document.getElementById("tag-add-btn");
|
||||||
let tagAddBtn = document.getElementById("tag-add-btn");
|
tagAddBtn.addEventListener("click", () => {
|
||||||
tagAddBtn.addEventListener("click", ()=> {
|
let tagField = document.getElementById("tag-form");
|
||||||
let tagField = document.getElementById("tag-form");
|
if (tagField.value.length > 0) {
|
||||||
if (tagField.value.length > 0) {
|
let tagSetVal = tagField.value.toLocaleLowerCase();
|
||||||
|
if (!tagSet.has(tagSetVal)) {
|
||||||
let tagLabel = document.createElement("label");
|
let tagLabel = document.createElement("label");
|
||||||
tagLabel.innerHTML = tagField.value;
|
tagLabel.innerHTML = tagField.value;
|
||||||
tagLabel.setAttribute("class","tag");
|
tagLabel.setAttribute("class", "tag");
|
||||||
tagLabel.addEventListener("click",()=> {
|
tagSet.add(tagSetVal);
|
||||||
|
tagLabel.addEventListener("click", () => {
|
||||||
tagContainer.removeChild(tagLabel);
|
tagContainer.removeChild(tagLabel);
|
||||||
|
tagSet.delete(tagSetVal);
|
||||||
});
|
});
|
||||||
|
|
||||||
tagContainer.append(tagLabel);
|
tagContainer.append(tagLabel);
|
||||||
tagField.value = "";
|
} else {
|
||||||
|
window.alert("No duplicate tags allowed");
|
||||||
}
|
}
|
||||||
});
|
tagField.value = "";
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
// Run the init() function when the page has loaded
|
|
||||||
window.addEventListener("DOMContentLoaded", init);
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
let result = sessionStorage.getItem("currReview");
|
|
||||||
|
|
||||||
let main = document.querySelector("main");
|
|
||||||
|
|
||||||
main.innerHTML = result;
|
|
||||||
let p = document.createElement("p");
|
|
||||||
p.innerHTML = JSON.parse(result)["comments"];
|
|
||||||
main.append(p);
|
|
||||||
}
|
|
72
source/assets/scripts/appTestHelpers.js
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { strict as assert } from "node:assert";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills out a create or update review form
|
||||||
|
* @param {Object} page the page object which contains the create or update form
|
||||||
|
* @param {Object} review review data to input into the form
|
||||||
|
*/
|
||||||
|
export async function setReviewForm(page, review) {
|
||||||
|
// Set text fields
|
||||||
|
await page.$eval("#mealName", (el, value) => (el.value = value), review.mealName);
|
||||||
|
await page.$eval("#comments", (el, value) => (el.value = value), review.comments);
|
||||||
|
await page.$eval("#restaurant", (el, value) => (el.value = value), review.restaurant);
|
||||||
|
|
||||||
|
// Get all tag elements and click them to delete them
|
||||||
|
let tag_items = await page.$$(".tag");
|
||||||
|
if (tag_items !== null) {
|
||||||
|
for (let i = 0; i < tag_items.length; i++) {
|
||||||
|
await tag_items[i].click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the button needed to add new tags
|
||||||
|
let tag_btn = await page.$("#tag-add-btn");
|
||||||
|
for (let i = 0; i < review.tags.length; i++) {
|
||||||
|
await page.$eval("#tag-form", (el, value) => (el.value = value), review.tags[i]);
|
||||||
|
await tag_btn.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select a new rating
|
||||||
|
let rating_select = await page.$(`#s${review.rating}-select`);
|
||||||
|
await rating_select.click({ delay: 100 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a page or shadowDOM for correct element text or src values
|
||||||
|
* @param {Object} root page or shodowDOM to test
|
||||||
|
* @param {string} prefix prefix character for element IDs
|
||||||
|
* @param {Object} expected values for each element
|
||||||
|
*/
|
||||||
|
export async function checkCorrectness(root, prefix, expected) {
|
||||||
|
// Get the review image and check src
|
||||||
|
let img = await root.$(`#${prefix}-meal-img`);
|
||||||
|
let imgSrc = await img.getProperty("src");
|
||||||
|
// Check src
|
||||||
|
assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc);
|
||||||
|
|
||||||
|
// Get the title, comment, and restaurant
|
||||||
|
let title = await root.$(`#${prefix}-meal-name`);
|
||||||
|
let title_text = await title.getProperty("innerText");
|
||||||
|
let comment = await root.$(`#${prefix}-comments`);
|
||||||
|
let comment_text = await comment.getProperty("innerText");
|
||||||
|
let restaurant = await root.$(`#${prefix}-restaurant`);
|
||||||
|
let restaurant_text = await restaurant.getProperty("innerText");
|
||||||
|
|
||||||
|
// Check title, comment, and restaurant
|
||||||
|
assert.strictEqual(await title_text.jsonValue(), expected.mealName);
|
||||||
|
assert.strictEqual(await comment_text.jsonValue(), expected.comments);
|
||||||
|
assert.strictEqual(await restaurant_text.jsonValue(), expected.restaurant);
|
||||||
|
|
||||||
|
// Check tags
|
||||||
|
let tags = await root.$$(`.${prefix}-tag`);
|
||||||
|
assert.strictEqual(await tags.length, expected.tags.length);
|
||||||
|
for (let i = 0; i < expected.tags.length; i++) {
|
||||||
|
let tag_text = await tags[i].getProperty("innerText");
|
||||||
|
assert.strictEqual(await tag_text.jsonValue(), expected.tags[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check stars
|
||||||
|
let stars = await root.$(`#${prefix}-rating`);
|
||||||
|
let stars_src = await stars.getProperty("src");
|
||||||
|
assert.strictEqual(await stars_src.jsonValue(), expected.rating);
|
||||||
|
}
|
@@ -1,27 +1,267 @@
|
|||||||
/**
|
/**
|
||||||
* @returns {Array<Object>} An array of reviews found in localStorage
|
* Creates a new review to storage and performs related meta tasks
|
||||||
|
* @param {Object} review to store
|
||||||
|
* @return {number} ID of the newly added review
|
||||||
*/
|
*/
|
||||||
export function getReviewsFromStorage() {
|
export function newReviewToStorage(review) {
|
||||||
if (!(localStorage.getItem("activeIDS"))) {
|
//grabbing the nextID, and putting our review object in storage associated with the ID
|
||||||
|
let nextReviewId = JSON.parse(localStorage.getItem("nextID"));
|
||||||
|
review["reviewID"] = nextReviewId;
|
||||||
|
|
||||||
|
// set the review entry to the review object
|
||||||
|
localStorage.setItem(`review${nextReviewId}`, JSON.stringify(review));
|
||||||
|
|
||||||
|
// adding to the tag keys
|
||||||
|
addTagsToStorage(nextReviewId, review["tags"]);
|
||||||
|
|
||||||
|
//adding to the star storage
|
||||||
|
let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`));
|
||||||
|
if (!starArr) {
|
||||||
|
starArr = [];
|
||||||
|
}
|
||||||
|
starArr.push(nextReviewId);
|
||||||
|
localStorage.setItem(`star${review["rating"]}`, JSON.stringify(starArr));
|
||||||
|
|
||||||
|
//updating our activeIDS list
|
||||||
|
let tempIdArr = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
|
tempIdArr.push(nextReviewId);
|
||||||
|
localStorage.setItem("activeIDS", JSON.stringify(tempIdArr));
|
||||||
|
|
||||||
|
//increment nextID for next review creation
|
||||||
|
localStorage.setItem("nextID", JSON.stringify(nextReviewId + 1));
|
||||||
|
|
||||||
|
return nextReviewId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a single review by ID from storage
|
||||||
|
* @param {string} ID of the review to get
|
||||||
|
* @returns {Object} review object corresponding to param ID
|
||||||
|
*/
|
||||||
|
export function getReviewFromStorage(ID) {
|
||||||
|
return JSON.parse(localStorage.getItem(`review${ID}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a single review by ID to storage
|
||||||
|
* @param {string} ID of review to update
|
||||||
|
* @param {Object} review to store
|
||||||
|
*/
|
||||||
|
export function updateReviewToStorage(ID, review) {
|
||||||
|
let oldReview = JSON.parse(localStorage.getItem(`review${ID}`));
|
||||||
|
let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`));
|
||||||
|
|
||||||
|
//activeID update recency
|
||||||
|
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
|
for (let i in activeIDS) {
|
||||||
|
if (activeIDS[i] == ID) {
|
||||||
|
activeIDS.splice(i, 1);
|
||||||
|
activeIDS.push(ID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localStorage.setItem("activeIDS", JSON.stringify(activeIDS));
|
||||||
|
|
||||||
|
//star local storage update
|
||||||
|
if (oldReview["rating"] !== review["rating"]) {
|
||||||
|
//first delete from previous rating array in storage
|
||||||
|
let oldStarArr = JSON.parse(localStorage.getItem(`star${oldReview["rating"]}`));
|
||||||
|
for (let i in oldStarArr) {
|
||||||
|
if (oldStarArr[i] == ID) {
|
||||||
|
//removing from corresponding rating array and updating local Storage
|
||||||
|
oldStarArr.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldStarArr.length != 0) {
|
||||||
|
localStorage.setItem(`star${oldReview["rating"]}`, JSON.stringify(oldStarArr));
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(`star${oldReview["rating"]}`);
|
||||||
|
}
|
||||||
|
//then add ID to array corresponding to new review rating
|
||||||
|
let newStarArr = starArr;
|
||||||
|
if (!newStarArr) {
|
||||||
|
newStarArr = [];
|
||||||
|
}
|
||||||
|
newStarArr.push(ID);
|
||||||
|
localStorage.setItem(`star${review["rating"]}`, JSON.stringify(newStarArr));
|
||||||
|
} else if (starArr.length !== 1) {
|
||||||
|
//stars update recency if unchanged
|
||||||
|
for (let i in starArr) {
|
||||||
|
if (starArr[i] == ID) {
|
||||||
|
starArr.splice(i, 1);
|
||||||
|
starArr.push(ID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localStorage.setItem(`star${review["rating"]}`, JSON.stringify(starArr));
|
||||||
|
}
|
||||||
|
|
||||||
|
//specifically the unchanged tags update recency
|
||||||
|
let repeatedTags = review["tags"].filter((x) => oldReview["tags"].includes(x));
|
||||||
|
let tagArr = [];
|
||||||
|
for (let i in repeatedTags) {
|
||||||
|
tagArr = JSON.parse(localStorage.getItem(`!${repeatedTags[i].toLocaleLowerCase()}`));
|
||||||
|
if (tagArr.length !== 1) {
|
||||||
|
for (let j in tagArr) {
|
||||||
|
if (tagArr[j] == ID) {
|
||||||
|
tagArr.splice(j, 1);
|
||||||
|
tagArr.push(ID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localStorage.setItem(`!${repeatedTags[i].toLocaleLowerCase()}`, JSON.stringify(tagArr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get diff of tags and update storage
|
||||||
|
let deletedTags = oldReview["tags"].filter((x) => !review["tags"].includes(x));
|
||||||
|
let addedTags = review["tags"].filter((x) => !oldReview["tags"].includes(x));
|
||||||
|
deleteTagsFromStorage(ID, deletedTags);
|
||||||
|
addTagsToStorage(ID, addedTags);
|
||||||
|
|
||||||
|
// set the review entry with ID to the review object
|
||||||
|
localStorage.setItem(`review${ID}`, JSON.stringify(review));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a review by ID from storage
|
||||||
|
* @param {string} ID of the review to delete
|
||||||
|
*/
|
||||||
|
export function deleteReviewFromStorage(ID) {
|
||||||
|
//removing id number from activeIDS and star{rating}
|
||||||
|
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
|
let reviewRating = JSON.parse(localStorage.getItem(`review${ID}`))["rating"];
|
||||||
|
let starArr = JSON.parse(localStorage.getItem(`star${reviewRating}`));
|
||||||
|
|
||||||
|
for (let i in starArr) {
|
||||||
|
if (starArr[i] == ID) {
|
||||||
|
//removing from corresponding rating array and updating local Storage
|
||||||
|
starArr.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (starArr.length != 0) {
|
||||||
|
localStorage.setItem(`star${reviewRating}`, JSON.stringify(starArr));
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(`star${reviewRating}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in activeIDS) {
|
||||||
|
if (activeIDS[i] == ID) {
|
||||||
|
activeIDS.splice(i, 1);
|
||||||
|
localStorage.setItem("activeIDS", JSON.stringify(activeIDS));
|
||||||
|
|
||||||
|
let currReview = JSON.parse(localStorage.getItem(`review${ID}`));
|
||||||
|
deleteTagsFromStorage(ID, currReview["tags"]);
|
||||||
|
localStorage.removeItem(`review${ID}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(`could not find review${ID} in localStorage`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete ID from the specified tags' storage
|
||||||
|
* @param {string} ID to delete from lists
|
||||||
|
* @param {string[]} deletedTags to modify storage of
|
||||||
|
*/
|
||||||
|
function deleteTagsFromStorage(ID, deletedTags) {
|
||||||
|
for (let i in deletedTags) {
|
||||||
|
//get local storage of each tag and remove id from tag list
|
||||||
|
let tagName = "!" + deletedTags[i].toLocaleLowerCase();
|
||||||
|
let tagArr = JSON.parse(localStorage.getItem(tagName));
|
||||||
|
for (let j in tagArr) {
|
||||||
|
if (tagArr[j] == ID) {
|
||||||
|
tagArr.splice(j, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tagArr.length != 0) {
|
||||||
|
localStorage.setItem(tagName, JSON.stringify(tagArr));
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ID from the specified tags' storage
|
||||||
|
* @param {string} ID to add to lists
|
||||||
|
* @param {string[]} addedTags to modify storage of
|
||||||
|
*/
|
||||||
|
function addTagsToStorage(ID, addedTags) {
|
||||||
|
for (let i in addedTags) {
|
||||||
|
let tagName = "!" + addedTags[i].toLocaleLowerCase();
|
||||||
|
let tagArr = JSON.parse(localStorage.getItem(tagName));
|
||||||
|
if (!tagArr) {
|
||||||
|
tagArr = [];
|
||||||
|
}
|
||||||
|
tagArr.push(ID);
|
||||||
|
localStorage.setItem(tagName, JSON.stringify(tagArr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Helper Function to get all reviews from local storage
|
||||||
|
* @returns {Object} all active reviews from local storage
|
||||||
|
*/
|
||||||
|
export function getAllReviewsFromStorage() {
|
||||||
|
if (!localStorage.getItem("activeIDS")) {
|
||||||
// we wanna init the active ID array and start the nextID count
|
// we wanna init the active ID array and start the nextID count
|
||||||
localStorage.setItem("activeIDS", JSON.stringify([]));
|
localStorage.setItem("activeIDS", JSON.stringify([]));
|
||||||
localStorage.setItem("nextID", JSON.stringify(0));
|
localStorage.setItem("nextID", JSON.stringify(0));
|
||||||
}
|
}
|
||||||
//iterate thru activeIDS
|
//iterate thru activeIDS
|
||||||
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
|
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
let reviews = []
|
let reviews = [];
|
||||||
for (let i = 0; i < activeIDS.length; i++) {
|
for (let i = 0; i < activeIDS.length; i++) {
|
||||||
let currReview = JSON.parse(localStorage.getItem('review'+activeIDS[i]));
|
let currReview = JSON.parse(localStorage.getItem(`review${activeIDS[i]}`));
|
||||||
reviews.push(currReview);
|
reviews.push(currReview);
|
||||||
}
|
}
|
||||||
return reviews;
|
return reviews;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes in an array of reviews, converts it to a string, and then
|
* Get all IDs of active reviews (order: most recent)
|
||||||
* saves that string to 'reviews' in localStorage
|
* @returns {number[]} list of all active IDs by recency
|
||||||
* @param {Array<Object>} reviews An array of reviews
|
|
||||||
*/
|
*/
|
||||||
export function saveReviewsToStorage(reviews) {
|
export function getIDsFromStorage() {
|
||||||
localStorage.setItem(`review${reviewId}`, JSON.stringify(reviews));
|
if (!localStorage.getItem("activeIDS")) {
|
||||||
|
// we wanna init the active ID array and start the nextID count
|
||||||
|
localStorage.setItem("activeIDS", JSON.stringify([]));
|
||||||
|
localStorage.setItem("nextID", JSON.stringify(0));
|
||||||
|
}
|
||||||
|
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
|
return activeIDS.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all review IDs which contain the same tag specified (order: most recent)
|
||||||
|
* @param {string} tag to filter by
|
||||||
|
* @returns {number[]} list of IDs of reviews that all contain the specified tag by recency
|
||||||
|
*/
|
||||||
|
export function getIDsByTag(tag) {
|
||||||
|
let tagArr = JSON.parse(localStorage.getItem("!" + tag.toLocaleLowerCase()));
|
||||||
|
if (!tagArr) {
|
||||||
|
tagArr = [];
|
||||||
|
}
|
||||||
|
return tagArr.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the top rated review IDs in order.
|
||||||
|
* @returns {number[]} list of IDs of reviews in order of top rating (most recent if equal rating)
|
||||||
|
*/
|
||||||
|
export function getTopIDsFromStorage() {
|
||||||
|
let resultArr = [];
|
||||||
|
for (let i = 5; i > 0; i--) {
|
||||||
|
let starArr = JSON.parse(localStorage.getItem(`star${i}`));
|
||||||
|
if (!starArr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resultArr = resultArr.concat(starArr.reverse());
|
||||||
|
}
|
||||||
|
return resultArr;
|
||||||
}
|
}
|
||||||
|
@@ -1,49 +1,319 @@
|
|||||||
import {strict as assert} from "node:assert";
|
import { strict as assert } from "node:assert";
|
||||||
import {describe, it, beforeEach} from "mocha";
|
import { describe, it, before, after } from "mocha";
|
||||||
import {saveReviewsToStorage, getReviewsFromStorage} from "./localStorage.js";
|
import {
|
||||||
|
newReviewToStorage,
|
||||||
|
getReviewFromStorage,
|
||||||
|
updateReviewToStorage,
|
||||||
|
deleteReviewFromStorage,
|
||||||
|
getAllReviewsFromStorage,
|
||||||
|
getIDsByTag,
|
||||||
|
getTopIDsFromStorage,
|
||||||
|
} from "./localStorage.js";
|
||||||
|
|
||||||
describe("test app localStorage interaction", () => {
|
describe("test CRUD localStorage interaction", () => {
|
||||||
|
before(() => {
|
||||||
beforeEach(() => {
|
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("get after init", () => {
|
it("test localStorage state after init", () => {
|
||||||
assert.deepEqual(getReviewsFromStorage(), []);
|
assert.deepEqual(getAllReviewsFromStorage(), []);
|
||||||
|
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), []);
|
||||||
|
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 0);
|
||||||
});
|
});
|
||||||
it("store one then get", () => {
|
|
||||||
let reviews = [{
|
|
||||||
"imgSrc": "sample src",
|
|
||||||
"imgAlt": "sample alt",
|
|
||||||
"mealName": "sample name",
|
|
||||||
"restaurant": "sample restaurant",
|
|
||||||
"rating": 5,
|
|
||||||
"tags": ["tag 1", "tag 2", "tag 3"]
|
|
||||||
}];
|
|
||||||
|
|
||||||
saveReviewsToStorage(reviews);
|
it("test localStorage state after adding one review", () => {
|
||||||
assert.deepEqual(getReviewsFromStorage(), reviews);
|
let review = {
|
||||||
|
imgSrc: "sample src",
|
||||||
|
mealName: "sample name",
|
||||||
|
restaurant: "sample restaurant",
|
||||||
|
rating: 5,
|
||||||
|
tags: ["tag 1", "tag 2", "tag 3"],
|
||||||
|
};
|
||||||
|
|
||||||
|
newReviewToStorage(review);
|
||||||
|
|
||||||
|
review.reviewID = 0;
|
||||||
|
|
||||||
|
assert.deepEqual(getAllReviewsFromStorage(), [review]);
|
||||||
|
assert.deepEqual(getReviewFromStorage(0), review);
|
||||||
|
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), [0]);
|
||||||
|
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1);
|
||||||
});
|
});
|
||||||
it("repeated store one more and get", () => {
|
|
||||||
let reviews = [];
|
|
||||||
|
|
||||||
assert.deepEqual(getReviewsFromStorage(), reviews);
|
it("test localStorage state during adding 999 reviews", () => {
|
||||||
|
let reviews = getAllReviewsFromStorage();
|
||||||
|
let ids = [0];
|
||||||
|
|
||||||
for(let i = 0; i < 1000; i++){
|
for (let i = 1; i < 1000; i++) {
|
||||||
reviews = getReviewsFromStorage();
|
ids.push(i);
|
||||||
|
let new_review = {
|
||||||
reviews.push(
|
imgSrc: `sample src ${i}`,
|
||||||
{
|
mealName: `sample name ${i}`,
|
||||||
"imgSrc": `sample src ${i}`,
|
restaurant: `sample restaurant ${i}`,
|
||||||
"imgAlt": `sample alt ${i}`,
|
rating: i,
|
||||||
"mealName": `sample name ${i}`,
|
tags: [`tag ${3 * i}`, `tag ${3 * i + 1}`, `tag ${3 * i + 2}`],
|
||||||
"restaurant": `sample restaurant ${i}`,
|
};
|
||||||
"rating": i,
|
|
||||||
"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`]
|
new_review.reviewID = newReviewToStorage(new_review);
|
||||||
}
|
reviews.push(new_review);
|
||||||
);
|
|
||||||
saveReviewsToStorage(reviews);
|
assert.deepEqual(getAllReviewsFromStorage(), reviews);
|
||||||
assert.deepEqual(getReviewsFromStorage(), reviews);
|
assert.deepEqual(getReviewFromStorage(i), new_review);
|
||||||
|
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids);
|
||||||
|
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), i + 1);
|
||||||
}
|
}
|
||||||
}).timeout(10000);
|
}).timeout(5000);
|
||||||
|
|
||||||
|
it("test localStorage state during updating 1000 reviews", () => {
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
let old_review = getReviewFromStorage(i);
|
||||||
|
let id = old_review.reviewID;
|
||||||
|
|
||||||
|
let new_review = {
|
||||||
|
imgSrc: `updated sample src ${id}`,
|
||||||
|
mealName: `updated sample name ${id}`,
|
||||||
|
restaurant: `updated sample restaurant ${id}`,
|
||||||
|
reviewID: id,
|
||||||
|
rating: (id % 5) + 1,
|
||||||
|
tags: [`tag ${3 * id}`, `tag ${3 * id + 1}`, `tag ${3 * id + 2}`],
|
||||||
|
};
|
||||||
|
|
||||||
|
updateReviewToStorage(id, new_review);
|
||||||
|
|
||||||
|
let all_reviews = getAllReviewsFromStorage();
|
||||||
|
let active_ids = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
|
|
||||||
|
assert.deepEqual(all_reviews[999], new_review);
|
||||||
|
assert.strictEqual(active_ids[999], id);
|
||||||
|
assert.deepEqual(getReviewFromStorage(i), new_review);
|
||||||
|
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000);
|
||||||
|
}
|
||||||
|
}).timeout(5000);
|
||||||
|
|
||||||
|
it("test localStorage state during deleting 1000 reviews", () => {
|
||||||
|
let reviews = getAllReviewsFromStorage();
|
||||||
|
let ids = JSON.parse(localStorage.getItem("activeIDS"));
|
||||||
|
|
||||||
|
for (let i = 999; i >= 0; i--) {
|
||||||
|
deleteReviewFromStorage(i);
|
||||||
|
ids.pop();
|
||||||
|
reviews.pop();
|
||||||
|
|
||||||
|
assert.deepEqual(getAllReviewsFromStorage(), reviews);
|
||||||
|
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids);
|
||||||
|
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000);
|
||||||
|
}
|
||||||
|
}).timeout(5000);
|
||||||
|
|
||||||
|
it("test localStorage state after all deletes", () => {
|
||||||
|
assert.deepEqual(getAllReviewsFromStorage(), []);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test sort/filter localStorage interaction", () => {
|
||||||
|
before(() => {
|
||||||
|
localStorage.clear();
|
||||||
|
getAllReviewsFromStorage();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("add sample data for sort and filter", () => {
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
let review = {
|
||||||
|
imgSrc: `sample src ${i}`,
|
||||||
|
mealName: `sample name ${i}`,
|
||||||
|
restaurant: `sample restaurant ${i}`,
|
||||||
|
rating: (i % 5) + 1,
|
||||||
|
tags: [`tag ${i % 3}`, `tag ${i < 50}`, "tag x"],
|
||||||
|
};
|
||||||
|
|
||||||
|
newReviewToStorage(review);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test getTopIDsFromStorage end behavior after create", () => {
|
||||||
|
let top_reviews = getTopIDsFromStorage();
|
||||||
|
let prev = Infinity;
|
||||||
|
for (let i = 0; i < top_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(top_reviews[i]);
|
||||||
|
assert.strictEqual(review.rating <= prev, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test getIDsByTag end behavior after create", () => {
|
||||||
|
let specific_tagged_reviews = [];
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 0");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 34);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 0"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 1");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 33);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 1"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 2");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 33);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 2"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 3, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag true");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 50);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag true"), true);
|
||||||
|
assert.strictEqual(review.reviewID < 50, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag false");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 50);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag false"), true);
|
||||||
|
assert.strictEqual(review.reviewID >= 50, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag x");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 100);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag y");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("update sample data for sort and filter", () => {
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
let old_review = getReviewFromStorage(i);
|
||||||
|
let new_review = {
|
||||||
|
imgSrc: `sample src ${i}`,
|
||||||
|
mealName: `sample name ${i}`,
|
||||||
|
restaurant: `sample restaurant ${i}`,
|
||||||
|
reviewID: old_review.reviewID,
|
||||||
|
rating: (i % 5) + 1,
|
||||||
|
tags: [`tag ${i % 4}`, `tag ${i < 37}`, "tag y"],
|
||||||
|
};
|
||||||
|
|
||||||
|
updateReviewToStorage(old_review.reviewID, new_review);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test getTopIDsFromStorage end behavior after create", () => {
|
||||||
|
let top_reviews = getTopIDsFromStorage();
|
||||||
|
let prev = Infinity;
|
||||||
|
for (let i = 0; i < top_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(top_reviews[i]);
|
||||||
|
assert.strictEqual(review.rating <= prev, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test getIDsByTag end behavior after update", () => {
|
||||||
|
let specific_tagged_reviews = [];
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 0");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 25);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 0"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 1");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 25);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 1"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 4, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 2");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 25);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 2"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 4, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 3");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 25);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag 3"), true);
|
||||||
|
assert.strictEqual(review.reviewID % 4, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag true");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 37);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag true"), true);
|
||||||
|
assert.strictEqual(review.reviewID < 37, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag false");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 63);
|
||||||
|
for (let i = 0; i < specific_tagged_reviews.length; i++) {
|
||||||
|
let review = getReviewFromStorage(specific_tagged_reviews[i]);
|
||||||
|
assert.strictEqual(review.tags.includes("tag false"), true);
|
||||||
|
assert.strictEqual(review.reviewID >= 37, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag x");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag y");
|
||||||
|
assert.strictEqual(specific_tagged_reviews.length, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("delete all sample data for sort and filter", () => {
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
deleteReviewFromStorage(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test getTopIDsFromStorage end behavior after delete", () => {
|
||||||
|
for (let i = 0; i <= 100; i++) {
|
||||||
|
let top_reviews = getTopIDsFromStorage(i);
|
||||||
|
assert.deepEqual(top_reviews, []);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("test getIDsByTag end behavior after delete", () => {
|
||||||
|
let specific_tagged_reviews = [];
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 0");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 1");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 2");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag 3");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag true");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag false");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag x");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
|
||||||
|
specific_tagged_reviews = getIDsByTag("tag y");
|
||||||
|
assert.deepEqual(specific_tagged_reviews, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {});
|
||||||
});
|
});
|
||||||
|
@@ -1,31 +1,223 @@
|
|||||||
import {strict as assert} from "node:assert";
|
import { strict as assert } from "node:assert";
|
||||||
import {describe, it, beforeEach, afterEach} from "mocha";
|
import { describe, it, before, after } from "mocha";
|
||||||
import puppeteer from "puppeteer-core";
|
import puppeteer from "puppeteer-core";
|
||||||
import { exit } from "node:process";
|
import { setReviewForm, checkCorrectness } from "./appTestHelpers.js";
|
||||||
|
|
||||||
describe("test App end to end", async () => {
|
describe("test App end to end", async () => {
|
||||||
|
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
|
|
||||||
beforeEach(async () => {
|
before(async () => {
|
||||||
browser = await puppeteer.launch();
|
let root;
|
||||||
|
try {
|
||||||
|
root = process.getuid() == 0;
|
||||||
|
} catch (error) {
|
||||||
|
root = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//browser = await puppeteer.launch({headless: false, slowMo: 250, args: root ? ['--no-sandbox'] : undefined});
|
||||||
|
browser = await puppeteer.launch({ args: root ? ["--no-sandbox"] : undefined });
|
||||||
page = await browser.newPage();
|
page = await browser.newPage();
|
||||||
try{
|
try {
|
||||||
await page.goto("http://localhost:8080", {timeout: 1000});
|
await page.goto("http://localhost:8080", { timeout: 2000 });
|
||||||
}
|
await console.log(`✔ connected to localhost webserver as ${root ? "root" : "user"}`);
|
||||||
catch (error) {
|
} catch (error) {
|
||||||
console.log("❌ failed to connect to localhost webserver on port 8080");
|
await console.log("❌ failed to connect to localhost webserver on port 8080");
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("page should have correct title", async () => {
|
describe("test simple properties", async () => {
|
||||||
assert.strictEqual(await page.title(), "Food Journal");
|
it("page should have correct title", async () => {
|
||||||
|
assert.strictEqual(await page.title(), "Food Journal");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async () => {
|
describe("test CRUD on simple inputs and default image", () => {
|
||||||
|
describe("test create 1 new review", async () => {
|
||||||
|
it("create 1 new review", async () => {
|
||||||
|
// Click the button to create a new review
|
||||||
|
let create_btn = await page.$("#create-btn");
|
||||||
|
await create_btn.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
// create a new review
|
||||||
|
let review = {
|
||||||
|
mealName: "sample name",
|
||||||
|
comments: "sample comment",
|
||||||
|
restaurant: "sample restaurant",
|
||||||
|
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
|
||||||
|
rating: 1,
|
||||||
|
};
|
||||||
|
await setReviewForm(page, review);
|
||||||
|
|
||||||
|
// Click the save button to save updates
|
||||||
|
let save_btn = await page.$("#save-btn");
|
||||||
|
await save_btn.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("check details page", async () => {
|
||||||
|
// check the details page for correctness
|
||||||
|
let expected = {
|
||||||
|
imgSrc: "http://localhost:8080/assets/images/default_plate.png",
|
||||||
|
mealName: "sample name",
|
||||||
|
comments: "sample comment",
|
||||||
|
restaurant: "sample restaurant",
|
||||||
|
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
|
||||||
|
rating: "http://localhost:8080/assets/images/1-star.svg",
|
||||||
|
};
|
||||||
|
await checkCorrectness(page, "d", expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("check home page", async () => {
|
||||||
|
// Click the button to return to the home page
|
||||||
|
let home_btn = await page.$("#home-btn");
|
||||||
|
home_btn.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
// Get the review card again and get its shadowRoot
|
||||||
|
let review_card = await page.$("review-card");
|
||||||
|
let shadowRoot = await review_card.getProperty("shadowRoot");
|
||||||
|
|
||||||
|
let expected = {
|
||||||
|
imgSrc: "http://localhost:8080/assets/images/default_plate.png",
|
||||||
|
mealName: "sample name",
|
||||||
|
comments: "sample comment",
|
||||||
|
restaurant: "sample restaurant",
|
||||||
|
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
|
||||||
|
rating: "http://localhost:8080/assets/images/1-star.svg",
|
||||||
|
};
|
||||||
|
await checkCorrectness(shadowRoot, "a", expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test read 1 review after refresh", async () => {
|
||||||
|
it("refresh page", async () => {
|
||||||
|
// Reload the page
|
||||||
|
await page.reload({ waitUntil: ["networkidle0", "domcontentloaded"] });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("check details page", async () => {
|
||||||
|
// click review card
|
||||||
|
let review_card = await page.$("review-card");
|
||||||
|
await review_card.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
// check the details page for correctness
|
||||||
|
let expected = {
|
||||||
|
imgSrc: "http://localhost:8080/assets/images/default_plate.png",
|
||||||
|
mealName: "sample name",
|
||||||
|
comments: "sample comment",
|
||||||
|
restaurant: "sample restaurant",
|
||||||
|
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
|
||||||
|
rating: "http://localhost:8080/assets/images/1-star.svg",
|
||||||
|
};
|
||||||
|
await checkCorrectness(page, "d", expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("check home page", async () => {
|
||||||
|
// Click the button to return to the home page
|
||||||
|
let home_btn = await page.$("#home-btn");
|
||||||
|
home_btn.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
// Get the review card again and get its shadowRoot
|
||||||
|
let review_card = await page.$("review-card");
|
||||||
|
let shadowRoot = await review_card.getProperty("shadowRoot");
|
||||||
|
|
||||||
|
// check the details page for correctness
|
||||||
|
let expected = {
|
||||||
|
imgSrc: "http://localhost:8080/assets/images/default_plate.png",
|
||||||
|
mealName: "sample name",
|
||||||
|
comments: "sample comment",
|
||||||
|
restaurant: "sample restaurant",
|
||||||
|
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
|
||||||
|
rating: "http://localhost:8080/assets/images/1-star.svg",
|
||||||
|
};
|
||||||
|
await checkCorrectness(shadowRoot, "a", expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test update 1 review", async () => {
|
||||||
|
it("update 1 review", async () => {
|
||||||
|
// Get the only review card and click it
|
||||||
|
let review_card = await page.$("review-card");
|
||||||
|
await review_card.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
// Click the button to show update form
|
||||||
|
let update_btn = await page.$("#update-btn");
|
||||||
|
await update_btn.click();
|
||||||
|
|
||||||
|
// create a new review
|
||||||
|
let review = {
|
||||||
|
mealName: "updated name",
|
||||||
|
comments: "updated comment",
|
||||||
|
restaurant: "updated restaurant",
|
||||||
|
tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"],
|
||||||
|
rating: 5,
|
||||||
|
};
|
||||||
|
await setReviewForm(page, review);
|
||||||
|
|
||||||
|
// Click the save button to save updates
|
||||||
|
let save_btn = await page.$("#save-btn");
|
||||||
|
await save_btn.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
}).timeout(10000);
|
||||||
|
|
||||||
|
it("check details page", async () => {
|
||||||
|
// check the details page for correctness
|
||||||
|
let expected = {
|
||||||
|
imgSrc: "http://localhost:8080/assets/images/default_plate.png",
|
||||||
|
mealName: "updated name",
|
||||||
|
comments: "updated comment",
|
||||||
|
restaurant: "updated restaurant",
|
||||||
|
tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"],
|
||||||
|
rating: "http://localhost:8080/assets/images/5-star.svg",
|
||||||
|
};
|
||||||
|
await checkCorrectness(page, "d", expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("check home page", async () => {
|
||||||
|
// Click the button to return to the home page
|
||||||
|
let home_btn = await page.$("#home-btn");
|
||||||
|
home_btn.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
// Get the review card again and get its shadowRoot
|
||||||
|
let review_card = await page.$("review-card");
|
||||||
|
let shadowRoot = await review_card.getProperty("shadowRoot");
|
||||||
|
|
||||||
|
// check the details page for correctness
|
||||||
|
let expected = {
|
||||||
|
imgSrc: "http://localhost:8080/assets/images/default_plate.png",
|
||||||
|
mealName: "updated name",
|
||||||
|
comments: "updated comment",
|
||||||
|
restaurant: "updated restaurant",
|
||||||
|
tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"],
|
||||||
|
rating: "http://localhost:8080/assets/images/5-star.svg",
|
||||||
|
};
|
||||||
|
await checkCorrectness(shadowRoot, "a", expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test delete 1 review", async () => {
|
||||||
|
it("delete 1 review", async () => {
|
||||||
|
// Get the only review card and click it
|
||||||
|
let review_card = await page.$("review-card");
|
||||||
|
await review_card.click();
|
||||||
|
await page.waitForNavigation();
|
||||||
|
|
||||||
|
page.on("dialog", async (dialog) => {
|
||||||
|
console.log(dialog.message());
|
||||||
|
await dialog.accept();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
await page.close();
|
await page.close();
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,123 +1,156 @@
|
|||||||
// main.js
|
// main.js
|
||||||
import {getReviewsFromStorage, saveReviewsToStorage} from "./localStorage.js";
|
import { getIDsByTag, getIDsFromStorage, getReviewFromStorage, getTopIDsFromStorage } from "./localStorage.js";
|
||||||
|
|
||||||
// Run the init() function when the page has loaded
|
// Run the init() function when the page has loaded
|
||||||
window.addEventListener("DOMContentLoaded", init);
|
window.addEventListener("DOMContentLoaded", init);
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
// Get the reviews from localStorage
|
//initial population of review container
|
||||||
let reviews = getReviewsFromStorage();
|
sortAndFilter(false, null);
|
||||||
// Add each reviews to the <main> element
|
//Add the event listeners to dropdown and search bar
|
||||||
addReviewsToDocument(reviews);
|
|
||||||
// Add the event listeners to the form elements
|
|
||||||
initFormHandler();
|
initFormHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<Object>} reviews An array of reviews
|
* @param {Array<Object>} reviews An array of reviews
|
||||||
*/
|
*/
|
||||||
function addReviewsToDocument(reviews) {
|
function addReviewsToDocument(reviews) {
|
||||||
let mainEl = document.querySelector("main");
|
let reviewBox = document.getElementById("review-container");
|
||||||
reviews.forEach(review => {
|
reviews.forEach((review) => {
|
||||||
let newReview = document.createElement("review-card");
|
let newReview = document.createElement("review-card");
|
||||||
newReview.data = review;
|
newReview.data = review;
|
||||||
//TODO: want to append it to whatever the box is in layout
|
reviewBox.append(newReview);
|
||||||
mainEl.append(newReview);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the necessary event handlers to <form> and the clear storage
|
* Adds the necessary event handlers to search-btn and sort
|
||||||
* <button>.
|
|
||||||
*/
|
*/
|
||||||
function initFormHandler() {
|
function initFormHandler() {
|
||||||
|
//grabbing search field
|
||||||
//btn to create form (could be its own function?)
|
let searchField = document.getElementById("search-bar");
|
||||||
let createBtn = document.getElementById("create-btn");
|
let searchBtn = document.getElementById("search-btn");
|
||||||
createBtn.addEventListener("click", function(){
|
let searchTag = null;
|
||||||
window.location.assign("./CreatePage.html");
|
//adding search functionality
|
||||||
});
|
//TODO: Add ability to enter without refresh of search bar
|
||||||
|
//filter by selected tag when button clicked
|
||||||
//accessing form components
|
searchBtn.addEventListener("click", function () {
|
||||||
/*
|
searchTag = searchField.value;
|
||||||
let tagContainer = document.getElementById("tag-container-form");
|
sortAndFilter(searchTag);
|
||||||
let form = document.querySelector("form");
|
|
||||||
|
|
||||||
form.addEventListener("submit", function(){
|
|
||||||
/*
|
|
||||||
* User submits the form for their review.
|
|
||||||
* We create reviewCard and put in storage
|
|
||||||
let formData = new FormData(form);
|
|
||||||
let reviewObject = {};
|
|
||||||
for (let [key, value] of formData) {
|
|
||||||
console.log(`${key}`);
|
|
||||||
console.log(`${value}`);
|
|
||||||
if (`${key}` !== "tag-form") {
|
|
||||||
reviewObject[`${key}`] = `${value}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reviewObject["tags"] = [];
|
|
||||||
|
|
||||||
let tags = document.querySelectorAll(".tag");
|
|
||||||
for(let i = 0; i < tags.length; i ++) {
|
|
||||||
reviewObject["tags"].push(tags[i].innerHTML);
|
|
||||||
tagContainer.removeChild(tags[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
let newReview = document.createElement("review-card");
|
|
||||||
newReview.data = reviewObject;
|
|
||||||
|
|
||||||
//TODO: want to append it to whatever the box is in layout
|
|
||||||
let mainEl = document.querySelector("main");
|
|
||||||
mainEl.append(newReview);
|
|
||||||
|
|
||||||
// TODO: assign an ID to be used for referencing this object form the activeIDs array and the tag arrays
|
|
||||||
let ID = localStorage.nextID;
|
|
||||||
|
|
||||||
let storedReviews = getReviewsFromStorage();
|
|
||||||
storedReviews.push(reviewObject);
|
|
||||||
saveReviewsToStorage(storedReviews);
|
|
||||||
document.getElementById("new-food-entry").reset();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// DEV-MODE: for testing purposes
|
//for clearing tag filter
|
||||||
let clearBtn = document.querySelector(".danger");
|
let clearSearchBtn = document.getElementById("clear-search");
|
||||||
clearBtn.addEventListener("click", function() {
|
clearSearchBtn.addEventListener("click", function () {
|
||||||
localStorage.clear();
|
searchTag = null;
|
||||||
let mainEl = document.querySelector("main");
|
searchField.value = "";
|
||||||
while (mainEl.firstChild) {
|
sortAndFilter(searchTag);
|
||||||
mainEl.removeChild(mainEl.firstChild);
|
|
||||||
}
|
|
||||||
let deleteTags = document.querySelectorAll(".tag");
|
|
||||||
for(let i = 0; i < deleteTags.length; i ++) {
|
|
||||||
tagContainer.removeChild(deleteTags[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//clears reviews AS WELL as resets form
|
|
||||||
document.getElementById("new-food-entry").reset();
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let tagAddBtn = document.getElementById("tagAdd");
|
//sort by selected method
|
||||||
tagAddBtn.addEventListener("click", ()=> {
|
let sortMethod = document.getElementById("sort");
|
||||||
let tagField = document.getElementById("tag-form");
|
sortMethod.addEventListener("input", function () {
|
||||||
if (tagField.value.length > 0) {
|
sortAndFilter(searchTag);
|
||||||
let tagLabel = document.createElement("label");
|
|
||||||
tagLabel.innerHTML = tagField.value;
|
|
||||||
tagLabel.setAttribute("class","tag");
|
|
||||||
tagLabel.addEventListener("click",()=> {
|
|
||||||
tagContainer.removeChild(tagLabel);
|
|
||||||
});
|
|
||||||
|
|
||||||
tagContainer.append(tagLabel);
|
|
||||||
tagField.value = "";
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deciphers sort and filter to populate the review-container
|
||||||
|
* @param {string} searchTag tag name to filter by
|
||||||
|
*/
|
||||||
|
function sortAndFilter(searchTag) {
|
||||||
|
let reviewBox = document.getElementById("review-container");
|
||||||
|
let sortMethod = document.getElementById("sort");
|
||||||
|
//clear review container
|
||||||
|
while (reviewBox.firstChild) {
|
||||||
|
reviewBox.removeChild(reviewBox.firstChild);
|
||||||
|
}
|
||||||
|
let reviewIDs = [];
|
||||||
|
//sort method: most recent
|
||||||
|
if (sortMethod.value == "recent") {
|
||||||
|
//tag filtered most recent
|
||||||
|
if (searchTag) {
|
||||||
|
reviewIDs = getIDsByTag(searchTag);
|
||||||
|
}
|
||||||
|
//most recent
|
||||||
|
else {
|
||||||
|
reviewIDs = getIDsFromStorage();
|
||||||
|
}
|
||||||
|
//reversed for recency
|
||||||
|
loadReviews(0, reviewIDs);
|
||||||
|
}
|
||||||
|
//sort method: top rated
|
||||||
|
else if (sortMethod.value == "top") {
|
||||||
|
//tag filtered top rated
|
||||||
|
if (searchTag) {
|
||||||
|
//intersection of top ids list and ids by tag in top ids order
|
||||||
|
reviewIDs = getTopIDsFromStorage().filter((x) => getIDsByTag(searchTag).includes(x));
|
||||||
|
}
|
||||||
|
//top rated
|
||||||
|
else {
|
||||||
|
reviewIDs = getTopIDsFromStorage();
|
||||||
|
}
|
||||||
|
loadReviews(0, reviewIDs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate review-container with 9 more reviews
|
||||||
|
* @param {number} index review index to begin with
|
||||||
|
* @param {number[]} reviewIDs ordered array of reviews
|
||||||
|
*/
|
||||||
|
function loadReviews(index, reviewIDs) {
|
||||||
|
let reviewBox = document.getElementById("review-container");
|
||||||
|
// label if there are no reviews to display
|
||||||
|
if (reviewIDs.length == 0) {
|
||||||
|
let emptyLabel = document.createElement("label");
|
||||||
|
emptyLabel.setAttribute("id", "empty");
|
||||||
|
emptyLabel.innerText = "No Reviews To Display";
|
||||||
|
reviewBox.append(emptyLabel);
|
||||||
|
} else {
|
||||||
|
let emptyLabel = document.getElementById("empty");
|
||||||
|
if (emptyLabel) {
|
||||||
|
reviewBox.removeChild(emptyLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let moreBtn = document.getElementById("more-btn");
|
||||||
|
//delete load more button if exists
|
||||||
|
if (moreBtn) {
|
||||||
|
reviewBox.removeChild(moreBtn);
|
||||||
|
}
|
||||||
|
let reviewArr = [];
|
||||||
|
//check if there are more than 9 reviews left
|
||||||
|
if (index + 9 > reviewIDs.length - 1) {
|
||||||
|
//add remaining reviews to review container
|
||||||
|
for (let i = index; i < reviewIDs.length; i++) {
|
||||||
|
reviewArr.push(getReviewFromStorage(reviewIDs[i]));
|
||||||
|
}
|
||||||
|
addReviewsToDocument(reviewArr);
|
||||||
|
} else {
|
||||||
|
//add 9 more reviews to container
|
||||||
|
for (let i = index; i < index + 9; i++) {
|
||||||
|
reviewArr.push(getReviewFromStorage(reviewIDs[i]));
|
||||||
|
}
|
||||||
|
addReviewsToDocument(reviewArr);
|
||||||
|
//create and add load more button
|
||||||
|
moreBtn = document.createElement("button");
|
||||||
|
moreBtn.setAttribute("id", "more-btn");
|
||||||
|
moreBtn.innerText = "Load More";
|
||||||
|
//if load more clicked, load 9 more
|
||||||
|
moreBtn.addEventListener("click", function () {
|
||||||
|
loadReviews(index + 9, reviewIDs);
|
||||||
|
});
|
||||||
|
reviewBox.append(moreBtn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerServiceWorker = async () => {
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
try {
|
||||||
|
await navigator.serviceWorker.register("./sw.js", { scope: "./" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Registration failed with ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
registerServiceWorker();
|
||||||
|
@@ -1,79 +1,65 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Food Journal</title>
|
<title>Food Journal</title>
|
||||||
|
|
||||||
<!-- Recipe Card Custom Element -->
|
<!--Add Favicon-->
|
||||||
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico" />
|
||||||
|
|
||||||
|
<!-- Recipe Card Custom Element -->
|
||||||
|
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
||||||
|
|
||||||
<!-- Main Stylesheets & Scripts -->
|
<!-- Main Stylesheets & Scripts -->
|
||||||
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
|
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
|
||||||
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
|
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
|
||||||
<link rel="stylesheet" href="./static/ReviewCard.css" />
|
<link rel="stylesheet" href="./static/homepage.css" />
|
||||||
<script src="assets/scripts/main.js" type="module"></script>
|
<script src="assets/scripts/main.js" type="module"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
</head>
|
<body>
|
||||||
<body>
|
<header>
|
||||||
<main>
|
<div class="top-bar">
|
||||||
<!-- Add Food Entries Here -->
|
<img src="./assets/images/Logo.png" alt="logo" />
|
||||||
</main>
|
<h1>Food Journal</h1>
|
||||||
<button type="button" id="create-btn"><a href='./CreatePage.html'></a>CREATE</button>
|
<img src="./assets/images/Logo.png" alt="logo" />
|
||||||
<!-- <form id="new-food-entry">
|
</div>
|
||||||
<fieldset>
|
</header>
|
||||||
<legend>Pic:</legend>
|
<main>
|
||||||
<label for="mealImage">
|
<div class="body-container">
|
||||||
Source:
|
<div style="width: 20%"></div>
|
||||||
<input type="text" id="mealImg" name="mealImg">
|
<div style="width: 60%">
|
||||||
</label>
|
<div class="search-bar">
|
||||||
<label for="image-alt">
|
<form id="form">
|
||||||
Alt Text:
|
<label for="sort">Sorting Method:</label>
|
||||||
<input type="text" id="imgAlt" name="imgAlt">
|
<select id="sort">
|
||||||
</label>
|
<option value="recent">Most Recent</option>
|
||||||
</fieldset>
|
<option value="top">Top Rated</option>
|
||||||
<fieldset>
|
</select>
|
||||||
|
<input type="search" id="search-bar" name="searchBar" placeholder="Search tags..." />
|
||||||
|
<button id="clear-search">Clear Search</button>
|
||||||
|
</form>
|
||||||
|
<img src="./assets/images/search_button.png" alt="SEARCH BTN" id="search-btn" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<legend> Meal: </legend>
|
<div class="center-display">
|
||||||
<label for="Meal: ">Meal:
|
<img
|
||||||
<input type="text" id="mealName" name="mealName" required>
|
src="./assets/images/create_button.png"
|
||||||
</label>
|
alt="CREATE"
|
||||||
<label for="comments">Comments:
|
id="create-btn"
|
||||||
<br>
|
title="Add an entry!"
|
||||||
<textarea name="comments" id="comments"></textarea>
|
onclick="window.location.assign('./CreatePage.html')"
|
||||||
</label>
|
/>
|
||||||
</fieldset>
|
<h2 id="recent-reviews-text">Recent Reviews</h2>
|
||||||
|
<img src="./assets/images/create_button.png" id="create-btn-invis" draggable="false" />
|
||||||
<fieldset class="rating">
|
</div>
|
||||||
<legend> Rating: </legend>
|
|
||||||
<input type="radio" id="s5" name="rating" value="5"/> <label for="s5"> 5 stars </label>
|
|
||||||
<input type="radio" id="s4" name="rating" value="4"/> <label for="s4"> 4 stars </label>
|
|
||||||
<input type="radio" id="s3" name="rating" value="3"/> <label for="s3"> 3 stars </label>
|
|
||||||
<input type="radio" id="s2" name="rating" value="2"/> <label for="s2"> 2 stars </label>
|
|
||||||
<input type="radio" id="s1" name="rating" value="1"/> <label for="s1"> 1 star </label>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
<div class="review-container" id="review-container"></div>
|
||||||
<legend>Other Info:</legend>
|
</div>
|
||||||
<label for="restaurant">
|
<div style="width: 20%"></div>
|
||||||
Restaurant:
|
</div>
|
||||||
<input type="text" id="restaurant" name="restaurant" required>
|
</main>
|
||||||
</label>
|
</body>
|
||||||
<label for="tag-form">
|
|
||||||
Tags:
|
|
||||||
<input type="text" id="tag-form" name="tag-form">
|
|
||||||
<div class='tag-container' id="tag-container-form">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<button type="button" id="tagAdd">Add Tag</button>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
</fieldset>
|
|
||||||
<button type="submit" value="Submit">Add Review</button>
|
|
||||||
<button type="button" class="danger">Clear Review Journal</button>
|
|
||||||
</form> -->
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Food Journal</title>
|
|
||||||
|
|
||||||
<script src="assets/scripts/reviewpage.js" type="module"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Current Review:</h1>
|
|
||||||
<main>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@@ -1,19 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"imgSrc": "https://cdn.vox-cdn.com/thumbor/Cj5J-5WqSCjlC2tWCOXEB536CJY=/0x0:1810x1182/1200x800/filters:focal(761x447:1049x735)/cdn.vox-cdn.com/uploads/chorus_image/image/69422966/Tacos_Lined_Up.0.png",
|
|
||||||
"imgAlt": "tacos pic",
|
|
||||||
"mealName": "Birria Tacos",
|
|
||||||
"restaurant": "Mike's Red Tacos",
|
|
||||||
"rating": 5,
|
|
||||||
"tags": ["delicious", "#worthit","omg"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"imgSrc": "https://www.redwormcomposting.com/images/worm-burrito.JPG",
|
|
||||||
"imgAlt": "wolftown pic",
|
|
||||||
"mealName": "Carnitas Burrito",
|
|
||||||
"restaurant": "Wolftown UCSD",
|
|
||||||
"rating": 0,
|
|
||||||
"tags": ["gross", "why","no"]
|
|
||||||
|
|
||||||
}
|
|
||||||
]
|
|
BIN
source/static/CoveredByYourGrace-Regular.ttf
Normal file
@@ -1,83 +1,30 @@
|
|||||||
/* CreatePage.css */
|
/* CreatePage.css */
|
||||||
|
|
||||||
* {
|
@font-face {
|
||||||
font-family: sans-serif;
|
font-family: testFont;
|
||||||
|
src: url("CoveredByYourGrace-Regular.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
background-color: #f8f3f1;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
.top-bar {
|
||||||
border: 2px solid rgb(214 214 214);
|
display: flex;
|
||||||
box-sizing: border-box;
|
justify-content: center;
|
||||||
display: block;
|
|
||||||
width: max-content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form button {
|
.top-bar > img {
|
||||||
display: block;
|
position: relative;
|
||||||
margin-top: 5px;
|
align-self: center;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
label[for="ingredients"] p {
|
.top-bar > h1 {
|
||||||
margin: 0;
|
position: relative;
|
||||||
}
|
text-align: center;
|
||||||
|
color: #516754;
|
||||||
label[for="numRatings"] {
|
font-size: 6rem;
|
||||||
margin: 10px 0 0;
|
font-family: testFont, sans-serif;
|
||||||
}
|
|
||||||
|
|
||||||
label[for^="rating"] {
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
label:not([for^="rating"]) {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
column-gap: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
height: auto;
|
|
||||||
max-width: 660px;
|
|
||||||
row-gap: 10px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-container {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag {
|
|
||||||
background-color: grey;
|
|
||||||
border-radius: 7px;
|
|
||||||
color: white;
|
|
||||||
padding-right: 7px;
|
|
||||||
padding-left: 7px;
|
|
||||||
margin: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag::before {
|
|
||||||
display: inline-block;
|
|
||||||
content: "x";
|
|
||||||
height: 15px;
|
|
||||||
width: 15px;
|
|
||||||
margin-right: 4px;
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag:hover::before {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.danger {
|
|
||||||
background-color: rgb(254 171 171);
|
|
||||||
border-color: red;
|
|
||||||
}
|
}
|
||||||
|
160
source/static/Form.css
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: testFont;
|
||||||
|
src: url("CoveredByYourGrace-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-form h1 {
|
||||||
|
font-family: testFont, sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-form {
|
||||||
|
font-size: 120%;
|
||||||
|
font-family: "Century Gothic", sans-serif;
|
||||||
|
width: 50%;
|
||||||
|
margin: auto;
|
||||||
|
color: #516754;
|
||||||
|
border: 2px solid rgb(31 41 32);
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f7dfd5;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
#d-meal-img {
|
||||||
|
border: 2px solid rgb(31 41 32);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #f7dfd5;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid rgb(0 0 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"]:focus {
|
||||||
|
outline: none;
|
||||||
|
border-bottom: 1px solid rgb(0 0 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: nowrap row-reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden,
|
||||||
|
.rating:not(:checked) > input {
|
||||||
|
/* Hide radio circles while star rating */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unchecked stars */
|
||||||
|
.rating:not(:checked) > label {
|
||||||
|
/* Make stars line up sideways and not vertically */
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
/* Hide label text */
|
||||||
|
width: 1em;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
/* Star default color and size */
|
||||||
|
font-size: 200%;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: #b3b3cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating > label:active {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating:not(:checked) > label::before {
|
||||||
|
content: "★";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checked star color */
|
||||||
|
.rating > input:checked ~ label {
|
||||||
|
color: #ffbf00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating:not(:checked) > label:hover,
|
||||||
|
.rating:not(:checked) > label:hover ~ label {
|
||||||
|
color: orangered;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rating > input:checked + label:hover,
|
||||||
|
.rating > input:checked ~ label:hover,
|
||||||
|
.rating > input:checked + label:hover ~ label,
|
||||||
|
.rating > input:checked ~ label:hover ~ label,
|
||||||
|
.rating > label:hover ~ input:checked ~ label {
|
||||||
|
color: orangered;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-container {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: wrap row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
background-color: grey;
|
||||||
|
border-radius: 7px;
|
||||||
|
color: white;
|
||||||
|
padding-right: 7px;
|
||||||
|
padding-left: 7px;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag::before {
|
||||||
|
display: inline-block;
|
||||||
|
content: "x";
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
margin-right: 4px;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag:hover::before {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tag-add-btn {
|
||||||
|
background-color: #94da97; /* Green */
|
||||||
|
border: round;
|
||||||
|
color: rgb(206 83 179);
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 10%;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tag-add-btn:hover {
|
||||||
|
background-color: rgb(206 83 179); /* Green */
|
||||||
|
border: round;
|
||||||
|
color: #94da97;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 10%;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-container * {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
93
source/static/OFL.txt
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright (c) 2010, Kimberly Geswein (kimberlygeswein.com)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
@@ -1,130 +0,0 @@
|
|||||||
/* main.css */
|
|
||||||
|
|
||||||
* {
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
border: 2px solid rgb(214 214 214);
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: block;
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
form button {
|
|
||||||
display: block;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="ingredients"] p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for="numRatings"] {
|
|
||||||
margin: 10px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
label[for^="rating"] {
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
label:not([for^="rating"]) {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
column-gap: 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
height: auto;
|
|
||||||
max-width: 660px;
|
|
||||||
row-gap: 10px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag-container {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag {
|
|
||||||
background-color: grey;
|
|
||||||
border-radius: 7px;
|
|
||||||
color: white;
|
|
||||||
padding-right: 7px;
|
|
||||||
padding-left: 7px;
|
|
||||||
margin: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag::before {
|
|
||||||
display: inline-block;
|
|
||||||
content: "x";
|
|
||||||
height: 15px;
|
|
||||||
width: 15px;
|
|
||||||
margin-right: 4px;
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag:hover::before {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.danger {
|
|
||||||
background-color: rgb(254 171 171);
|
|
||||||
border-color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden,
|
|
||||||
.rating:not(:checked) > input { /* Hide radio circles while star rating */
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unchecked stars */
|
|
||||||
.rating:not(:checked) > label {
|
|
||||||
/* Make stars line up sideways and not vertically */
|
|
||||||
float: right;
|
|
||||||
|
|
||||||
/* Hide label text */
|
|
||||||
width: 1em;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
/* Star default color and size */
|
|
||||||
font-size: 200%;
|
|
||||||
line-height: 1.2;
|
|
||||||
color: #b3b3cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rating > label:active {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rating:not(:checked) > label::before {
|
|
||||||
content: "★";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checked star color */
|
|
||||||
.rating > input:checked ~ label {
|
|
||||||
color: #ffbf00;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rating:not(:checked) > label:hover,
|
|
||||||
.rating:not(:checked) > label:hover ~ label {
|
|
||||||
color: orangered;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rating > input:checked + label:hover,
|
|
||||||
.rating > input:checked ~ label:hover,
|
|
||||||
.rating > input:checked + label:hover ~ label,
|
|
||||||
.rating > input:checked ~ label:hover ~ label,
|
|
||||||
.rating > label:hover ~ input:checked ~ label {
|
|
||||||
color: orangered;
|
|
||||||
}
|
|
45
source/static/ReviewDetails.css
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* ReviewDetails.css */
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: testFont;
|
||||||
|
src: url("CoveredByYourGrace-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f8f3f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar > img {
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar > h1 {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
/* color: #e4c3d2; */
|
||||||
|
color: #516754;
|
||||||
|
font-size: 6rem;
|
||||||
|
font-family: testFont, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.d-tag {
|
||||||
|
background-color: grey;
|
||||||
|
border-radius: 7px;
|
||||||
|
color: white;
|
||||||
|
padding-right: 7px;
|
||||||
|
padding-left: 7px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
120
source/static/homepage.css
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/* homepage.css */
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: testFont;
|
||||||
|
src: url("CoveredByYourGrace-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color */
|
||||||
|
body {
|
||||||
|
/* background-color: #97a5bd */
|
||||||
|
|
||||||
|
/* background-color: #E3E3EC; */
|
||||||
|
background-color: #f8f3f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar > img {
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar > h1 {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
/* color: #e4c3d2; */
|
||||||
|
|
||||||
|
/* color: rgb(145, 124, 175); */
|
||||||
|
color: #516754;
|
||||||
|
font-size: 6rem;
|
||||||
|
font-family: testFont, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-container {
|
||||||
|
display: flex;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-display {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: "Century Gothic", sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #516754;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sort {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar > form {
|
||||||
|
float: right;
|
||||||
|
padding: 6px 10px;
|
||||||
|
|
||||||
|
/*
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-right: 16px;
|
||||||
|
*/
|
||||||
|
background: rgb(239 183 183);
|
||||||
|
font-size: 17px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-btn {
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#recent-reviews-text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 4rem;
|
||||||
|
color: #516754;
|
||||||
|
font-family: testFont, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#create-btn {
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 10%;
|
||||||
|
height: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#create-btn-invis {
|
||||||
|
opacity: 0;
|
||||||
|
padding-left: 2.5%;
|
||||||
|
padding-right: 2.5%;
|
||||||
|
width: 10%;
|
||||||
|
height: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-container {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-container > div {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
@@ -1,158 +0,0 @@
|
|||||||
/* This is a generic CSS file that sets preliminary rules for content that should be the same across pages */
|
|
||||||
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
div,
|
|
||||||
span,
|
|
||||||
object,
|
|
||||||
iframe,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6,
|
|
||||||
p,
|
|
||||||
blockquote,
|
|
||||||
pre,
|
|
||||||
abbr,
|
|
||||||
address,
|
|
||||||
cite,
|
|
||||||
code,
|
|
||||||
del,
|
|
||||||
dfn,
|
|
||||||
em,
|
|
||||||
img,
|
|
||||||
ins,
|
|
||||||
kbd,
|
|
||||||
q,
|
|
||||||
samp,
|
|
||||||
small,
|
|
||||||
strong,
|
|
||||||
sub,
|
|
||||||
sup,
|
|
||||||
var,
|
|
||||||
b,
|
|
||||||
i,
|
|
||||||
dl,
|
|
||||||
dt,
|
|
||||||
dd,
|
|
||||||
ol,
|
|
||||||
ul,
|
|
||||||
li,
|
|
||||||
fieldset,
|
|
||||||
form,
|
|
||||||
label,
|
|
||||||
legend,
|
|
||||||
table,
|
|
||||||
caption,
|
|
||||||
tbody,
|
|
||||||
tfoot,
|
|
||||||
thead,
|
|
||||||
tr,
|
|
||||||
th,
|
|
||||||
td,
|
|
||||||
article,
|
|
||||||
aside,
|
|
||||||
canvas,
|
|
||||||
details,
|
|
||||||
figcaption,
|
|
||||||
figure,
|
|
||||||
footer,
|
|
||||||
header,
|
|
||||||
hgroup,
|
|
||||||
menu,
|
|
||||||
nav,
|
|
||||||
section,
|
|
||||||
summary,
|
|
||||||
time,
|
|
||||||
mark,
|
|
||||||
audio,
|
|
||||||
video {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
outline: 0;
|
|
||||||
font-size: 100%;
|
|
||||||
vertical-align: baseline;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
article,
|
|
||||||
aside,
|
|
||||||
details,
|
|
||||||
figcaption,
|
|
||||||
figure,
|
|
||||||
footer,
|
|
||||||
header,
|
|
||||||
hgroup,
|
|
||||||
menu,
|
|
||||||
nav,
|
|
||||||
section {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav ul {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote,
|
|
||||||
q {
|
|
||||||
quotes: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote::before,
|
|
||||||
blockquote::after,
|
|
||||||
q::before,
|
|
||||||
q::after {
|
|
||||||
content: "";
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-size: 100%;
|
|
||||||
vertical-align: baseline;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
select {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
img,
|
|
||||||
fieldset,
|
|
||||||
object {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::after,
|
|
||||||
*::before {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
label {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
border: solid;
|
|
||||||
}
|
|
67
source/sw.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
const CACHE_NAME = "food-journal-v1";
|
||||||
|
const ASSETS = [
|
||||||
|
"index.html",
|
||||||
|
"ReviewDetails.html",
|
||||||
|
"CreatePage.html",
|
||||||
|
"static/CoveredByYourGrace-Regular.ttf",
|
||||||
|
"static/CreatePage.css",
|
||||||
|
"static/Form.css",
|
||||||
|
"static/homepage.css",
|
||||||
|
"static/ReviewDetails.css",
|
||||||
|
"assets/images/0-star.svg",
|
||||||
|
"assets/images/1-star.svg",
|
||||||
|
"assets/images/2-star.svg",
|
||||||
|
"assets/images/3-star.svg",
|
||||||
|
"assets/images/4-star.svg",
|
||||||
|
"assets/images/5-star.svg",
|
||||||
|
"assets/images/create_button.png",
|
||||||
|
"assets/images/default_plate.png",
|
||||||
|
"assets/images/delete_icon_for_interface.png",
|
||||||
|
"assets/images/edit_button_for_interface.png",
|
||||||
|
"assets/images/home_button_for_interface.png",
|
||||||
|
"assets/images/favicon.ico",
|
||||||
|
"assets/images/Logo.png",
|
||||||
|
"assets/images/search_button.png",
|
||||||
|
"assets/scripts/CreatePage.js",
|
||||||
|
"assets/scripts/localStorage.js",
|
||||||
|
"assets/scripts/main.js",
|
||||||
|
"assets/scripts/ReviewCard.js",
|
||||||
|
"assets/scripts/ReviewDetails.js",
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the install listener where the app assets are added to the cache
|
||||||
|
*/
|
||||||
|
self.addEventListener("install", async () => {
|
||||||
|
// open the cace
|
||||||
|
const cache = await caches.open(CACHE_NAME);
|
||||||
|
// add all elements in ASSETS to the cache, these are all the files requried for the app to run
|
||||||
|
await cache.addAll(ASSETS);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an event listener on fetch events to serve cached resources while offline
|
||||||
|
* Uses a network first structure to prioritize fetching from network in case of app updates.
|
||||||
|
* If there are important updates, we want the user to get those if possible.
|
||||||
|
*/
|
||||||
|
self.addEventListener("fetch", (event) => {
|
||||||
|
// add a response to the fetch event
|
||||||
|
event.respondWith(
|
||||||
|
caches.open(CACHE_NAME).then((cache) => {
|
||||||
|
// try to return a network fetch response
|
||||||
|
return fetch(event.request)
|
||||||
|
.then((fetchedResponse) => {
|
||||||
|
// if there is a response, add it to the cache
|
||||||
|
cache.put(event.request, fetchedResponse.clone());
|
||||||
|
// return the network response
|
||||||
|
return fetchedResponse;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// If there is not a network response, return the cached response
|
||||||
|
// The ignoreVary option is used here to fix an issue where the service worker
|
||||||
|
// would not serve certain requests unless the page was refreshed at least once
|
||||||
|
return cache.match(event.request, { ignoreVary: true, ignoreSearch: true });
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
@@ -1,16 +1,20 @@
|
|||||||
# Final Project Topic Decision
|
# Final Project Topic Decision
|
||||||
- Status: accept
|
|
||||||
- Deciders: team members and TA
|
- Status: accept
|
||||||
- Date: 10 / 27 / 22
|
- Deciders: team members and TA
|
||||||
|
- Date: 10 / 27 / 22
|
||||||
|
|
||||||
## Decision Drivers
|
## Decision Drivers
|
||||||
- Needed to develop a local-first, CRUD application that would be simple enough to implement in the next few weeks
|
|
||||||
|
- Needed to develop a local-first, CRUD application that would be simple enough to implement in the next few weeks
|
||||||
|
|
||||||
## Considered Options:
|
## Considered Options:
|
||||||
- Social Media Archive
|
|
||||||
- Resume Builder
|
- Social Media Archive
|
||||||
- Copy/Paste
|
- Resume Builder
|
||||||
- Food Journal
|
- Copy/Paste
|
||||||
|
- Food Journal
|
||||||
|
|
||||||
## Decision Outcome
|
## Decision Outcome
|
||||||
|
|
||||||
Chosen Option: Food Journal, which allows users to hold their thoughts and ratings on meals and restaurants that they have been to. It is local-first, CRUD app, and fun. Therefore, we decided to choose this.
|
Chosen Option: Food Journal, which allows users to hold their thoughts and ratings on meals and restaurants that they have been to. It is local-first, CRUD app, and fun. Therefore, we decided to choose this.
|
||||||
|
@@ -1,15 +1,19 @@
|
|||||||
# Finalized App Design on Figma
|
# Finalized App Design on Figma
|
||||||
- Status: accept
|
|
||||||
- Deciders: Isaac Otero
|
- Status: accept
|
||||||
- Date: 11 / 08 / 22
|
- Deciders: Isaac Otero
|
||||||
|
- Date: 11 / 08 / 22
|
||||||
|
|
||||||
## Decision Drivers:
|
## Decision Drivers:
|
||||||
- Needed to figure out the wireframe and flow of our app
|
|
||||||
- Needed to visualize the different features
|
- Needed to figure out the wireframe and flow of our app
|
||||||
|
- Needed to visualize the different features
|
||||||
|
|
||||||
## Considered Option:
|
## Considered Option:
|
||||||
- Different feature option
|
|
||||||
- Color Scheme, font, spacing, and other design options were discussed
|
- Different feature option
|
||||||
|
- Color Scheme, font, spacing, and other design options were discussed
|
||||||
|
|
||||||
## Decision Outcome:
|
## Decision Outcome:
|
||||||
- Chosen Option: Design can be found at this link: https://www.figma.com/file/Qhugp1Dd0gPnJTbmmUIvsa/Wireframe?node-id=36%3A2
|
|
||||||
|
- Chosen Option: Design can be found at this link: https://www.figma.com/file/Qhugp1Dd0gPnJTbmmUIvsa/Wireframe?node-id=36%3A2
|
||||||
|
@@ -1,19 +1,19 @@
|
|||||||
# Use multiple CI/CD pipelines in parallel
|
# Use multiple CI/CD pipelines in parallel
|
||||||
|
|
||||||
- Status: accept
|
- Status: accept
|
||||||
- Deciders: Arthur Lu, Marc Reta
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
- Date: 11 / 12 / 22
|
- Date: 11 / 12 / 22
|
||||||
|
|
||||||
## Decision Drivers
|
## Decision Drivers
|
||||||
|
|
||||||
- Need to perform many different CI/CD tasks
|
- Need to perform many different CI/CD tasks
|
||||||
- Need pipeline to be durable against any single failure
|
- Need pipeline to be durable against any single failure
|
||||||
|
|
||||||
## Considered Options
|
## Considered Options
|
||||||
|
|
||||||
- Single deep pipeline
|
- Single deep pipeline
|
||||||
- Multiple short pipelines in parallel
|
- Multiple short pipelines in parallel
|
||||||
|
|
||||||
## Decision Outcone
|
## Decision Outcone
|
||||||
|
|
||||||
Chosen Option: Multiple short pipelines in parallel as any one failure will not prevent code from being developed and deployed.
|
Chosen Option: Multiple short pipelines in parallel as any one failure will not prevent code from being developed and deployed.
|
||||||
|
@@ -1,19 +1,19 @@
|
|||||||
# Use eslint for JS linting framework
|
# Use eslint for JS linting framework
|
||||||
|
|
||||||
- Status: accept
|
- Status: accept
|
||||||
- Deciders: Arthur Lu, Marc Reta
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
- Date: 11 / 12 / 22
|
- Date: 11 / 12 / 22
|
||||||
|
|
||||||
## Decision Drivers
|
## Decision Drivers
|
||||||
|
|
||||||
- Need linting to work with multiple style standards
|
- Need linting to work with multiple style standards
|
||||||
- Need linting to be fast and informative
|
- Need linting to be fast and informative
|
||||||
|
|
||||||
## Considered Options
|
## Considered Options
|
||||||
|
|
||||||
- JSLint
|
- JSLint
|
||||||
- eslint
|
- eslint
|
||||||
|
|
||||||
## Decision Outcome
|
## Decision Outcome
|
||||||
|
|
||||||
Chosen Option: eslint for its low configuration complexity.
|
Chosen Option: eslint for its low configuration complexity.
|
||||||
|
@@ -1,19 +1,20 @@
|
|||||||
# Use mocha for JS unit testing framework
|
# Use mocha for JS unit testing framework
|
||||||
|
|
||||||
- Status: accept
|
- Status: accept
|
||||||
- Deciders: Arthur Lu, Marc Reta
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
- Date: 11 / 12 / 22
|
- Date: 11 / 12 / 22
|
||||||
|
|
||||||
## Decision Drivers
|
## Decision Drivers
|
||||||
|
|
||||||
- Need specification on how to write unit testing assertion statements
|
- Need specification on how to write unit testing assertion statements
|
||||||
- Need framework to perform unit testing quickly for immediate code feedback
|
- Need framework to perform unit testing quickly for immediate code feedback
|
||||||
|
|
||||||
## Considered Options
|
## Considered Options
|
||||||
- JUnit5
|
|
||||||
- Jest
|
- JUnit5
|
||||||
- Mocha
|
- Jest
|
||||||
|
- Mocha
|
||||||
|
|
||||||
## Decision Outcome
|
## Decision Outcome
|
||||||
|
|
||||||
Chosen Option: Mocha because it was significantly faster to run than Jest (1s vs 30s), and can use a variety of assertion styles unlike JUnit5.
|
Chosen Option: Mocha because it was significantly faster to run than Jest (1s vs 30s), and can use a variety of assertion styles unlike JUnit5.
|
||||||
|
19
specs/adrs/111422-csslinting-stylelint.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Use Stylelint for CSS linting framework
|
||||||
|
|
||||||
|
- Status: accept
|
||||||
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
|
- Date: 11 / 14 / 22
|
||||||
|
|
||||||
|
## Decision Drivers
|
||||||
|
|
||||||
|
- Need linting to work with multiple style standards
|
||||||
|
- Need linting to be fast and informative
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
- Stylelint
|
||||||
|
- Prettier
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
Chosen Option: Stylelint for its easy installation and unopinionated.
|
19
specs/adrs/111422-htmllinting-htmlhint.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Use HTMLhint for HTML linting framework
|
||||||
|
|
||||||
|
- Status: accept
|
||||||
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
|
- Date: 11 / 14 / 22
|
||||||
|
|
||||||
|
## Decision Drivers
|
||||||
|
|
||||||
|
- Need linting to work with multiple style standards
|
||||||
|
- Need linting to be fast and informative
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
- HTMLhint
|
||||||
|
- HTML-validate
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
Chosen Option: HTMLhint for its low configuration complexity.
|
@@ -1,19 +1,20 @@
|
|||||||
# Use puppeteer for JS unit testing framework
|
# Use puppeteer for JS unit testing framework
|
||||||
|
|
||||||
- Status: accept
|
- Status: accept
|
||||||
- Deciders: Arthur Lu, Marc Reta
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
- Date: 11 / 16 / 22
|
- Date: 11 / 16 / 22
|
||||||
|
|
||||||
## Decision Drivers
|
## Decision Drivers
|
||||||
|
|
||||||
- Need end to end testing framework which runs headlessly and quickly
|
- Need end to end testing framework which runs headlessly and quickly
|
||||||
- Framework should integrate well with Mocha, the existing unit testing framework
|
- Framework should integrate well with Mocha, the existing unit testing framework
|
||||||
- Framework should be easy to implement end to end tests with
|
- Framework should be easy to implement end to end tests with
|
||||||
|
|
||||||
## Considered Options
|
## Considered Options
|
||||||
- puppeteer
|
|
||||||
- selenium-webdriver
|
- puppeteer
|
||||||
|
- selenium-webdriver
|
||||||
## Decision Outcome
|
|
||||||
|
## Decision Outcome
|
||||||
Chosen Option: Puppeteer for its ease of use with mocha.
|
|
||||||
|
Chosen Option: Puppeteer for its ease of use with mocha.
|
||||||
|
18
specs/adrs/112922-documentation-jsdoc.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Use JSDoc for JS documentation
|
||||||
|
|
||||||
|
- Status: accept
|
||||||
|
- Deciders: Arthur Lu, Marc Reta
|
||||||
|
- Date: 11 / 29 / 22
|
||||||
|
|
||||||
|
## Decision Drivers
|
||||||
|
|
||||||
|
- Need simple way to publish documentation for code
|
||||||
|
- Already documentating infile using JSDoc style
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
- JSDoc
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
Chosen Option: JSDoc. Will run by generating docs in /source/docs/ before publishing /source/ so users can enter the URI /docs/ to see documentation.
|