diff --git a/Dockerfile.prod b/Dockerfile.prod index c5f0ddc8..9c5244c6 100644 --- a/Dockerfile.prod +++ b/Dockerfile.prod @@ -1,10 +1,9 @@ -# This image runs the production server, with nginx ########### # BUILDER # ########### # pull official base image -FROM python:3.11.4-slim-buster as python_builder +FROM python:3.11.4-slim-buster as builder # set work directory WORKDIR /usr/src/app @@ -49,8 +48,8 @@ WORKDIR $APP_HOME # install dependencies RUN apt-get update && apt-get install -y --no-install-recommends netcat -COPY --from=python_builder /usr/src/app/wheels /wheels -COPY --from=python_builder /usr/src/app/requirements.txt . +COPY --from=builder /usr/src/app/wheels /wheels +COPY --from=builder /usr/src/app/requirements.txt . RUN pip install --upgrade pip RUN pip install --no-cache /wheels/* @@ -69,11 +68,4 @@ RUN chown -R app:app $APP_HOME USER app # run entrypoint.prod.sh -<<<<<<< HEAD:Dockerfile.prod -ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"] - - -# TODO: gunicorn stuff -======= -ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"] ->>>>>>> ac68347c12ced724206112843623ee8c515bd3ad:server/Dockerfile.prod +ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 54d673e5..29aa7256 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,29 @@ You can view the current [build of the website here](https://balancertestsite.co ![image](https://github.com/CodeForPhilly/balancer-main/assets/26842253/92c5d6e3-2aaf-4d28-9095-0ea22fa87791) -Likewise, you can view the very first iteration [build of the website here](https://64861cae18fa9449694ad5ef--deft-tapioca-dd7777.netlify.app/). +Likewise, you can view the first iteration [build of the website here](https://64861cae18fa9449694ad5ef--deft-tapioca-dd7777.netlify.app/). ## Project Updates +[Release V1.02272024] + +1) Updated Help Page. Thank you @kristo_baricevic +2) Make 'Contact us' a mailto link. Thank you @greggaleg +3) Improve Chat Response Formatting in UI. Thank you @greggaleg ## Current Tasks +1) Official Deployment System: @joshgerstein. +2) Prompt Creations: @erinc. +3) Additional Business Logic for New Patient Form: @tomdoan. +4) Backend for Feedback Form: @dattali. +5) Redesign of AI Architecture. +6) Add logging to the backend for debugging. +7) Documentations of Forking and merging branches. ## Languages/Frameworks +Django, React, PostGres ## Contribution diff --git a/config/env/env.dev b/config/env/env.dev index 47ff5783..92f51aee 100644 --- a/config/env/env.dev +++ b/config/env/env.dev @@ -1,4 +1,4 @@ -DEBUG=1 +DEBUG=True SECRET_KEY=foo DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1] SQL_ENGINE=django.db.backends.postgresql @@ -9,5 +9,7 @@ SQL_HOST=db SQL_PORT=5432 DATABASE=postgres LOGIN_REDIRECT_URL= -OPENAI_API_KEY= -PINECONE_API_KEY= \ No newline at end of file +OPENAI_API_KEY= +PINECONE_API_KEY= +EMAIL_HOST_USER= +EMAIL_HOST_PASSWORD= \ No newline at end of file diff --git a/config/env/env.prod b/config/env/env.prod index a82573f0..12b3491a 100644 --- a/config/env/env.prod +++ b/config/env/env.prod @@ -9,4 +9,6 @@ SQL_PASSWORD=set_me SQL_HOST=db SQL_PORT=5432 DATABASE=postgres -LOGIN_REDIRECT_URL= \ No newline at end of file +LOGIN_REDIRECT_URL= +EMAIL_HOST_USER= +EMAIL_HOST_PASSWORD= \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 578e2669..2eb6e187 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -4,31 +4,40 @@ services: image: postgres:15 volumes: - postgres_data:/var/lib/postgresql/data/ - env_file: -<<<<<<< HEAD - - ./config/env/env.prod.db -======= - - ./config/env/.env.prod.db ->>>>>>> ac68347c12ced724206112843623ee8c515bd3ad + environment: + - POSTGRES_USER=balancer + - POSTGRES_PASSWORD=balancer + - POSTGRES_DB=balancer_dev + ports: + - "5432:5432" backend: - build: - context: ./server - dockerfile: Dockerfile.prod - command: gunicorn balancer_backend.wsgi:application --bind 0.0.0.0:8000 + image: balancer-backend + build: + context: server + dockerfile: Dockerfile.prod ports: - - 8000:8000 + - "8000:8000" env_file: - - ./config/env/env.prod + - ./config/env/env.dev depends_on: - db <<<<<<< HEAD ======= frontend: + image: balancer-frontend build: - context: ./frontend - dockerfile: Dockerfile.prod + context: frontend + dockerfile: Dockerfile + args: + - IMAGE_NAME=balancer-frontend ports: - - "3000:80" + - "3000:3000" + environment: + - CHOKIDAR_USEPOLLING=true + # - VITE_API_BASE_URL=https://balancertestsite.com/ + volumes: + - "./frontend:/usr/src/app:delegated" + - "/usr/src/app/node_modules/" depends_on: - backend >>>>>>> ac68347c12ced724206112843623ee8c515bd3ad diff --git a/docker-compose.prodBackup.yml b/docker-compose.prodBackup.yml new file mode 100644 index 00000000..a7f0ae12 --- /dev/null +++ b/docker-compose.prodBackup.yml @@ -0,0 +1,30 @@ +version: '3.8' +services: + db: + image: postgres:15 + volumes: + - postgres_data:/var/lib/postgresql/data/ + env_file: + - ./config/env/.env.prod.db + backend: + build: + context: ./server + dockerfile: Dockerfile.prod + command: gunicorn balancer_backend.wsgi:application --bind 0.0.0.0:8000 + ports: + - 8000:8000 + env_file: + - ./config/env/.env.prod + depends_on: + - db + frontend: + build: + context: ./frontend + dockerfile: Dockerfile.prod + ports: + - "3000:80" + depends_on: + - backend + +volumes: + postgres_data: \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 79cafa89..ae60363a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,9 +8,11 @@ "name": "balancer", "version": "0.0.0", "dependencies": { - "@reduxjs/toolkit": "https://pkg.csb.dev/reduxjs/redux-toolkit/commit/933aa4a1/@reduxjs/toolkit", + "@redux-devtools/extension": "^3.3.0", "axios": "^1.4.0", "formik": "^2.4.2", + "jsonwebtoken": "^9.0.2", + "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^5.0.1", @@ -24,6 +26,8 @@ }, "devDependencies": { "@types/axios": "^0.14.0", + "@types/jsonwebtoken": "^9.0.6", + "@types/jwt-decode": "^3.1.0", "@types/node": "^20.10.6", "@types/react": "^18.2.14", "@types/react-dom": "^18.0.11", @@ -371,11 +375,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", - "integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", "dependencies": { - "regenerator-runtime": "^0.13.11" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -997,18 +1001,16 @@ "node": ">= 8" } }, - "node_modules/@reduxjs/toolkit": { - "version": "1.2.3", - "resolved": "https://pkg.csb.dev/reduxjs/redux-toolkit/commit/933aa4a1/@reduxjs/toolkit", - "integrity": "sha512-9Eyplfq7iVInelDP1oUHug6qyMILsQcedhcYE39TAYgXxHFB8513h2fUl7upcmWEqIvu4CH+q4YQ04nU1oNF1A==", - "license": "MIT", + "node_modules/@redux-devtools/extension": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.3.0.tgz", + "integrity": "sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==", "dependencies": { - "immer": "^4.0.1", - "redux": "^4.0.0", - "redux-devtools-extension": "^2.13.8", - "redux-immutable-state-invariant": "^2.1.0", - "redux-thunk": "^2.3.0", - "reselect": "^4.0.0" + "@babel/runtime": "^7.23.2", + "immutable": "^4.3.4" + }, + "peerDependencies": { + "redux": "^3.1.0 || ^4.0.0 || ^5.0.0" } }, "node_modules/@remix-run/router": { @@ -1050,6 +1052,25 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", + "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jwt-decode": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/jwt-decode/-/jwt-decode-3.1.0.tgz", + "integrity": "sha512-tthwik7TKkou3mVnBnvVuHnHElbjtdbM63pdBCbZTirCt3WAdM73Y79mOri7+ljsS99ZVwUFZHLMxJuJnv/z1w==", + "deprecated": "This is a stub types definition. jwt-decode provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "jwt-decode": "*" + } + }, "node_modules/@types/node": { "version": "20.10.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", @@ -1667,6 +1688,11 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -1944,6 +1970,14 @@ "node": ">=6.0.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.438", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.438.tgz", @@ -3007,10 +3041,10 @@ "node": ">= 4" } }, - "node_modules/immer": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/immer/-/immer-4.0.2.tgz", - "integrity": "sha512-Q/tm+yKqnKy4RIBmmtISBlhXuSDrB69e9EKTYiIenIKQkXBQir43w+kN/eGiax3wt1J0O1b2fYcNqLSbEcXA7w==" + "node_modules/immutable": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -3388,11 +3422,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -3405,6 +3434,59 @@ "node": ">=6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3463,6 +3545,11 @@ "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", "integrity": "sha512-6bc3b8grkpMgDcVJv9JYZAk/mHgcqMljzm7OsbmcE2FGUMmmLQTPHlh/dFqR8LA0GQ7z4K67JSotVKu5058v1A==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, "node_modules/lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -3473,6 +3560,21 @@ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==" }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, "node_modules/lodash.isplainobject": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz", @@ -3483,6 +3585,11 @@ "lodash.keysin": "^3.0.0" } }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.keysin": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz", @@ -3498,6 +3605,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3596,8 +3708,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mz": { "version": "2.7.0", @@ -4354,32 +4465,16 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "peer": true, "dependencies": { "@babel/runtime": "^7.9.2" } }, - "node_modules/redux-devtools-extension": { - "version": "2.13.9", - "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz", - "integrity": "sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==", - "deprecated": "Package moved to @redux-devtools/extension.", - "peerDependencies": { - "redux": "^3.1.0 || ^4.0.0" - } - }, - "node_modules/redux-immutable-state-invariant": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/redux-immutable-state-invariant/-/redux-immutable-state-invariant-2.1.0.tgz", - "integrity": "sha512-3czbDKs35FwiBRsx/3KabUk5zSOoTXC+cgVofGkpBNv3jQcqIe5JrHcF5AmVt7B/4hyJ8MijBIpCJ8cife6yJg==", - "dependencies": { - "invariant": "^2.1.0", - "json-stringify-safe": "^5.0.1" - } - }, "node_modules/redux-thunk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", + "dev": true, "peerDependencies": { "redux": "^4" } @@ -4409,9 +4504,9 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.0", @@ -4435,11 +4530,6 @@ "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" }, - "node_modules/reselect": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", - "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" - }, "node_modules/resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", @@ -4547,6 +4637,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -4570,10 +4679,9 @@ } }, "node_modules/semver": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", - "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", - "dev": true, + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -4588,7 +4696,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4599,8 +4706,7 @@ "node_modules/semver/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -5145,9 +5251,9 @@ } }, "node_modules/vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dev": true, "dependencies": { "esbuild": "^0.18.10", diff --git a/frontend/package.json b/frontend/package.json index 74f04a4f..09d561a9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,9 +10,11 @@ "preview": "vite preview" }, "dependencies": { - "@reduxjs/toolkit": "https://pkg.csb.dev/reduxjs/redux-toolkit/commit/933aa4a1/@reduxjs/toolkit", + "@redux-devtools/extension": "^3.3.0", "axios": "^1.4.0", "formik": "^2.4.2", + "jsonwebtoken": "^9.0.2", + "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^5.0.1", @@ -26,6 +28,8 @@ }, "devDependencies": { "@types/axios": "^0.14.0", + "@types/jsonwebtoken": "^9.0.6", + "@types/jwt-decode": "^3.1.0", "@types/node": "^20.10.6", "@types/react": "^18.2.14", "@types/react-dom": "^18.0.11", diff --git a/frontend/src/components/Footer/Footer.tsx b/frontend/src/components/Footer/Footer.tsx index 08345c0e..6a60e3e9 100644 --- a/frontend/src/components/Footer/Footer.tsx +++ b/frontend/src/components/Footer/Footer.tsx @@ -24,7 +24,11 @@ function Footer() { Home { + window.location.href = 'mailto:balancerteam@codeforphilly.org'; + e.preventDefault(); + }} className="flex justify-center text-black hover:border-blue-600 hover:text-blue-600 hover:no-underline" > Contact us diff --git a/frontend/src/components/Header/Chat.tsx b/frontend/src/components/Header/Chat.tsx index 895e6075..b64db23f 100644 --- a/frontend/src/components/Header/Chat.tsx +++ b/frontend/src/components/Header/Chat.tsx @@ -113,8 +113,8 @@ const Chat: React.FC = ({ showChat, setShowChat }) => { ...prevChatLog, { type: "bot", - message: response.data.message.choices[0].message.content, - }, + message: response.data.message.choices[0].message.content + } ]); setIsLoading(false); }) @@ -193,15 +193,22 @@ const Chat: React.FC = ({ showChat, setShowChat }) => { message.type === "user" ? "justify-end" : "justify-start" }`} > -
- {message.message} -
+ )) )} diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx index 4f144894..e5e0cb27 100644 --- a/frontend/src/components/Header/Header.tsx +++ b/frontend/src/components/Header/Header.tsx @@ -1,26 +1,29 @@ -import { useState, useRef, useEffect, Fragment } from "react"; +// import { useState, useRef, useEffect, Fragment } from "react"; +import { useState, Fragment } from "react"; import accountLogo from "../../assets/account.svg"; import { Link, useNavigate } from "react-router-dom"; import LoginMenuDropDown from "./LoginMenuDropDown"; import "../../components/Header/header.css"; import Chat from "./Chat"; -import { FeatureMenuDropDown } from "./FeatureMenuDropDown"; +// import { FeatureMenuDropDown } from "./FeatureMenuDropDown"; import MdNavBar from "./MdNavBar"; import { connect, useDispatch } from "react-redux"; import { RootState } from "../../services/actions/types"; import { logout, AppDispatch } from "../../services/actions/auth"; -import { HiChevronDown } from "react-icons/hi"; +// import { HiChevronDown } from "react-icons/hi"; interface LoginFormProps { isAuthenticated: boolean; + isSuperuser: boolean; } const Header = (props: LoginFormProps) => { const { isAuthenticated } = props; + const { isSuperuser } = props; const navigate = useNavigate(); - const [showFeaturesMenu, setShowFeaturesMenu] = useState(false); - const dropdownRef = useRef(null); - let delayTimeout: number | null = null; + // const [showFeaturesMenu, setShowFeaturesMenu] = useState(false); + // const dropdownRef = useRef(null); + // let delayTimeout: number | null = null; const [showChat, setShowChat] = useState(false); const [showLoginMenu, setShowLoginMenu] = useState(false); const [redirect, setRedirect] = useState(false); @@ -54,26 +57,26 @@ const Header = (props: LoginFormProps) => { setShowLoginMenu(!showLoginMenu); }; - const handleMouseEnter = () => { - if (delayTimeout !== null) { - clearTimeout(delayTimeout); - } - setShowFeaturesMenu(true); - }; + // const handleMouseEnter = () => { + // if (delayTimeout !== null) { + // clearTimeout(delayTimeout); + // } + // setShowFeaturesMenu(true); + // }; - const handleMouseLeave = () => { - delayTimeout = setTimeout(() => { - setShowFeaturesMenu(false); - }, 300) as unknown as number; // Adjust the delay time as needed - }; + // const handleMouseLeave = () => { + // delayTimeout = setTimeout(() => { + // setShowFeaturesMenu(false); + // }, 300) as unknown as number; // Adjust the delay time as needed + // }; - useEffect(() => { - return () => { - if (delayTimeout !== null) { - clearTimeout(delayTimeout); - } - }; - }, [delayTimeout]); + // useEffect(() => { + // return () => { + // if (delayTimeout !== null) { + // clearTimeout(delayTimeout); + // } + // }; + // }, [delayTimeout]); return (
@@ -99,7 +102,7 @@ const Header = (props: LoginFormProps) => { @@ -164,6 +181,7 @@ const Header = (props: LoginFormProps) => { const mapStateToProps = (state: RootState) => ({ isAuthenticated: state.auth.isAuthenticated, + isSuperuser: state.auth.isSuperuser, }); const ConnectedLayout = connect(mapStateToProps)(Header); diff --git a/frontend/src/pages/AdminPortal/AdminPortal.tsx b/frontend/src/pages/AdminPortal/AdminPortal.tsx new file mode 100644 index 00000000..57f39527 --- /dev/null +++ b/frontend/src/pages/AdminPortal/AdminPortal.tsx @@ -0,0 +1,13 @@ +//import Welcome from "../../components/Welcome/Welcome.tsx"; +import Layout from "../Layout/Layout"; +// import image from "./OIP.jpeg"; + +function About() { + return ( + +
+
+ ); +} + +export default About; diff --git a/frontend/src/pages/Feedback/Feedback.tsx b/frontend/src/pages/Feedback/Feedback.tsx index 4497c821..d4e61e40 100644 --- a/frontend/src/pages/Feedback/Feedback.tsx +++ b/frontend/src/pages/Feedback/Feedback.tsx @@ -10,7 +10,7 @@ function Feedback() {

Feedback

- Leave Feedback for the Balancer Team. + Leave feedback for the Balancer Team.

diff --git a/frontend/src/pages/Feedback/FeedbackForm.tsx b/frontend/src/pages/Feedback/FeedbackForm.tsx index 769cf0c7..68a3b2a1 100644 --- a/frontend/src/pages/Feedback/FeedbackForm.tsx +++ b/frontend/src/pages/Feedback/FeedbackForm.tsx @@ -187,7 +187,7 @@ const FeedbackForm = () => { className="block text-sm font-medium leading-6 text-gray-900" htmlFor="psychotic-yes" > - Feature Request + Feature request { className="block text-sm font-medium leading-6 text-gray-900" htmlFor="psychotic-no" > - Bug + Issue { className="block text-sm font-medium leading-6 text-gray-900" htmlFor="psychotic-no" > - General Improvements + General feedback diff --git a/frontend/src/pages/Help/DataSources.tsx b/frontend/src/pages/Help/DataSources.tsx index 66dd7379..fe54f89b 100644 --- a/frontend/src/pages/Help/DataSources.tsx +++ b/frontend/src/pages/Help/DataSources.tsx @@ -9,10 +9,13 @@ interface DataProps { const data: DataProps = { title: "How Do We Get Our Data?", paragraph: [ - "Balancer gets it data from publicly available peer-reviewed research "+ - "as well as through extensive interviews with prescribers. ", - "Check back soon for more comprehensive information." + "Balancer is a free and open-source tool that utilizes data from " + + "publicly available peer-reviewed medical research, as well as " + + "through extensive interviews with physicians and medical professionals " + + "who treat patients with bipolar disorder.", + "Check back soon for more comprehensive information on our data sources." ], + }; function HowTo() { diff --git a/frontend/src/pages/Help/Help.tsx b/frontend/src/pages/Help/Help.tsx index 3c050a4f..52c2b015 100644 --- a/frontend/src/pages/Help/Help.tsx +++ b/frontend/src/pages/Help/Help.tsx @@ -4,24 +4,20 @@ import HelpCard from "./HelpCard"; import { Link } from "react-router-dom"; interface HelpData { - link: string[]; - icon: string[]; - title: string[]; - paragraph: string[]; + link: string[]; + icon: string[]; + title: string[]; + paragraph: string[]; } const HelpCardData: HelpData = { - link: [ - "/how-to", - "/feedback", - "/data-sources" - ], + link: ["/how-to", "/feedback", "/data-sources"], icon: ["UserDoctor", "FeedbackIcon", "MagnifyingGlassChart"], - title: ["How To Use this Site", "Submit Feedback", "How We Get Our Data"], + title: ["How To Use This Site", "Submit Feedback", "How We Get Our Data"], paragraph: [ - "Visit this page to learn how to use the Balancer App!", + "Visit this page to learn how to use the Balancer App.", "Give the Balancer team feedback on your experience.", - "Learn where the Balancer team gets our data!", + "Learn about how the Balancer team gets our data.", ], }; @@ -48,24 +44,27 @@ function Help() {
-

+

Help & Support Page -

+
-
+

- Let us help you in your Balancer experience! + Get help and support for improving your Balancer experience.

{data.icon.map((icon, index) => ( - - + + +
+ +
))}
diff --git a/frontend/src/pages/Help/HowTo.tsx b/frontend/src/pages/Help/HowTo.tsx index cd35153a..93a51e3b 100644 --- a/frontend/src/pages/Help/HowTo.tsx +++ b/frontend/src/pages/Help/HowTo.tsx @@ -9,28 +9,72 @@ interface HowToProps { const howToData: HowToProps = { title: "How To Use the Balancer App", paragraph: [ - "Balancer's Medication Suggester feature provides medication decision support by " + + "Balancer's Medication Suggestion Tool feature provides medication decision support by " + "offering tailored medication recommendations and comprehensive risk-benefit assessments " + "based on a patient's diagnosis and individual characteristics. ", - "Here is how to use it: ", + "How to use the Balancer App: ", ], instructions: [ - "1. Navigate to the Medication Suggester.", - "2. Select the patient's current state.", - "3. Answer 'yes' or 'no' to the questions related to patient characteristics.", - "4. Check off any relevant reproductive status information.", - "5. Type out a list of the patient's current medications. You can separate medications " + - "with commas. It doesn't matter if you use the generic or brand name of the medication; " + + "Navigate to the Medication Suggestion Tool.", + "Select the patient's current state.", + "Answer 'yes' or 'no' to the questions related to patient " + + "characteristics.", + "Reproductive status: check off any relevant reproductive status " + + "information.", + "Current medications: enter all of the patient's current medications. " + + "You can separate medications with commas. It doesn't matter if you " + + "use the generic or brand name of the medication; " + "Balancer will understand.", - "6. Type out a list of any medications you want Balancer to exclude from the recommended " + - "medications list. (For example, if a patient has already tried a particular medication " + - "without success, enter the name of that medication and Balancer will be sure not to " + - "suggest it in the results page.) You can separate medications with commas. Again, " + - "it doesn't matter if you use the generic or brand name of the medication; Balancer will " + - "understand.", + "Prior medications to exclude: type out a list of any medications you " + + "want Balancer to exclude from the recommended medications list." ], }; +function createList(list: string[]) { + return ( +
    + {list.map((text, index) => { + if (index !== 5) { + return ( +
  1. + {`${index + 1}. ${text}`} +
  2. + ); + } else { // Custom sublist + return ( +
  3. + {`${index + 1}. ${text}`} +
      +
    1. {"a. For example, if a patient has already tried a particular medication " + + "without success, enter the name of that medication and Balancer will " + + "be sure not to suggest it in the results page."} +
    2. +
    3. {"b. You can separate medications with commas. " + + "Again, it doesn't matter if you use the generic or " + + "brand name of the medication; Balancer will understand."} +
    4. +
    +
  4. + ); + } + })} +
+ ) +} + function HowTo() { return ( @@ -40,26 +84,15 @@ function HowTo() {
-

+

{howToData.paragraph[0]}

-

+

{howToData.paragraph[1]}

-
    - {howToData.instructions.map((text, index) => { - return ( -
  1. - {text} -
  2. - ); - })} -
+ {createList(howToData.instructions)}
@@ -67,4 +100,4 @@ function HowTo() { ); } -export default HowTo; +export default HowTo; \ No newline at end of file diff --git a/frontend/src/pages/PatientManager/NewPatientForm.tsx b/frontend/src/pages/PatientManager/NewPatientForm.tsx index a167492e..b56c6652 100644 --- a/frontend/src/pages/PatientManager/NewPatientForm.tsx +++ b/frontend/src/pages/PatientManager/NewPatientForm.tsx @@ -734,7 +734,6 @@ const NewPatientForm = ({ CurrentMedications: String(e.target.value), }) } - required placeholder="Separate medications with commas" className={ isLoading @@ -769,7 +768,6 @@ const NewPatientForm = ({ PriorMedications: String(e.target.value), }) } - required placeholder="Separate medications with commas" className={ isLoading @@ -792,14 +790,12 @@ const NewPatientForm = ({