Skip to content

Commit

Permalink
Merge pull request #61 from WomenPlusPlus/docs
Browse files Browse the repository at this point in the history
change reposotory structure, add documentation and test scenarios
  • Loading branch information
daczczcz1 authored Oct 29, 2023
2 parents 8ef686f + cd4099c commit aac0ac5
Show file tree
Hide file tree
Showing 83 changed files with 227 additions and 5 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/migrate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ on:
branches:
- main
paths:
- "migrations/**"
- "src/migrations/**"

jobs:
migrate-database:
name: Run Flyway migrations
runs-on: ubuntu-20.04
env:
SUPABASE_HOST: db.fwmiurdtauuyrqhzuwpg.supabase.co
SUPABASE_PORT: 5432
SUPABASE_USER: postgres
SUPABASE_DB: postgres
Expand All @@ -21,9 +20,9 @@ jobs:
- uses: actions/checkout@v2
- run: >-
docker run --rm
--volume ${{ github.workspace }}/migrations:/flyway/sql:ro
--volume ${{ github.workspace }}/src/migrations:/flyway/sql:ro
flyway/flyway:latest
-url="jdbc:postgresql://${{ env.SUPABASE_HOST }}:${{ env.SUPABASE_PORT }}/${{ env.SUPABASE_DB }}?sslmode=require"
-url="jdbc:postgresql://${{ secrets.SUPABASE_DB_HOST }}:${{ env.SUPABASE_PORT }}/${{ env.SUPABASE_DB }}?sslmode=require"
-user="${{ env.SUPABASE_USER }}"
-password="${{ secrets.SUPABASE_PASS }}"
migrate
78 changes: 77 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,77 @@
# deploy-impact-23-kpi-1
# KPI Monitor

## Objectives:

The main goal of this application is to provide [Pro Juventute](https://www.projuventute.ch) members an easy and
standardized way to collect and visualize KPIs.

## Setup:

### 1. Prerequisites:

- [Docker](https://www.docker.com/get-started/)
- [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)

### 2. Run locally:

1. run [local Supabase instance](https://supabase.com/docs/guides/self-hosting/docker)

```shell
cd ~/dev # or another location where you want to store the Supabase repository
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .env
docker compose pull
docker compose up -d
grep 'ANON_KEY=' .env | awk -F'=' '{print $2}' # this is the key required to connect the webapp to the backend
```

- add a user who will be used for accessing the app:
- go to http://localhost:8000/project/default/auth/users
- click "Add user" > "Create user"
- enter email and password (save them for later use)

2. run database migrations:

```shell
docker run --rm --network supabase_default --volume $(pwd)/migrations:/flyway/sql:ro flyway/flyway:latest -url="jdbc:postgresql://supabase-db:5432/postgres" -user="postgres" -password="your-super-secret-a
nd-long-postgres-password" migrate

```

3. run webapp

```shell
cd KPI-team1-frontend
touch .env.local
echo "VITE_PUBLIC_SUPABASE_URL=http://localhost:8000" | tee -a .env.local
echo "VITE_PUBLIC_SUPABASE_ANON_KEY=<<ANON_KEY_FROM_POINT_1>>" | tee -a .env.local
npm run dev
```

- open localhost:3000 in you browser
- you should now be able to log in using the user created previously in the Supabase UI

### 3. Considerations for production deployment

The project heavily relies on Supabase. The deployment could be done using a self-hosted Supabase instance, which should
be [secured](https://supabase.com/docs/guides/self-hosting/docker#securing-your-services). An alternative approach is to
create a Supabase account. Current GitHub setup allows applying the database migrations automatically:
- go to https://github.com/WomenPlusPlus/deploy-impact-23-kpi-1/settings/secrets/actions
- setup two secrets: SUPABASE_DB_HOST and SUPABASE_PASS - those are the credentials to the Postgres database

The frontend application uses [Vite](https://vitejs.dev/guide/build.html) which allows
different [deployment](https://vitejs.dev/guide/static-deploy.html) options out of the box.

### 4. Tools used:
- [Supabase](https://supabase.com/)
- [React](https://react.dev/)
- [Flyway](https://flywaydb.org/)
- [Flowbite](https://flowbite.com/)
- [Material UI](https://mui.com/)
- [Vite](https://vitejs.dev/)

### 5. Documentation
- the general architecture of the project is described [here](/docs/arch.md)
- the database schema and instructions for management of the application by the Gatekeeper is [here](/docs/db.md)

61 changes: 61 additions & 0 deletions docs/arch.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<mxfile host="app.diagrams.net" modified="2023-10-29T16:13:20.948Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0" etag="cWDFXSOucl6UHoPB8p54" version="22.0.0" type="device">
<diagram name="Strona-1" id="oetVzceQHpRXCima8oXP">
<mxGraphModel dx="1434" dy="782" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="r8XdS0BeGojSjV3rh1AG-1" value="" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;" vertex="1" parent="1">
<mxGeometry x="400" y="160" width="560" height="340" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-2" value="&lt;font size=&quot;1&quot;&gt;&lt;b style=&quot;font-size: 15px;&quot;&gt;Supabase&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="640" y="170" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-4" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="420" y="270" width="150" height="150" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-5" value="&lt;b&gt;PostgREST Web Server&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="457.5" y="320" width="75" height="60" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-6" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="600" y="210" width="340" height="270" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-7" value="&lt;b&gt;PostgreSQL database&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="680" y="220" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-8" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="620" y="370" width="300" height="65" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-9" value="Tables" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="730" y="387.5" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-10" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="620" y="267.5" width="300" height="75" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-11" value="Database functions and views " style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="680" y="290" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-12" value="&lt;b&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;React web application&lt;/font&gt;&lt;/b&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="110" y="255" width="220" height="180" as="geometry" />
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-13" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="r8XdS0BeGojSjV3rh1AG-12" target="r8XdS0BeGojSjV3rh1AG-4">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="420" as="sourcePoint" />
<mxPoint x="440" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-14" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="r8XdS0BeGojSjV3rh1AG-4" target="r8XdS0BeGojSjV3rh1AG-10">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="420" as="sourcePoint" />
<mxPoint x="440" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="r8XdS0BeGojSjV3rh1AG-17" value="" style="endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="r8XdS0BeGojSjV3rh1AG-4" target="r8XdS0BeGojSjV3rh1AG-8">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="390" y="420" as="sourcePoint" />
<mxPoint x="440" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
8 changes: 8 additions & 0 deletions docs/arch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Architecture

This project consists of two major elements: a database schema and API provided by [Supabase](https://supabase.com/) and built on top of a [PostgreSQL](https://www.postgresql.org/) database and [PostgREST server](https://postgrest.org/en/stable/) and a web application built with [React](https://react.dev/).

![Architecture diagram](arch.png)
(this diagram was created and can be edited with [draw.io](https://app.diagrams.net/) - the xml version is [here](arch.drawio))

Authentication is handled by Supabase and is ready for integration with e.g. Azure AD. The data is secured using PostgreSQL [row level security policies](https://www.postgresql.org/docs/current/ddl-rowsecurity.html). The database migrations are handled using Flyway, they are accessible [here](/migrations).
Binary file added docs/arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions docs/db.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Database schema

The table containing the KPI values is `public.kpi_values_history`. It is actually a historical log of changes made to a
particular KPI and the latest (currently valid) values can be retrieved using
the `public.kpi_definitions_with_latest_values` view.

## Manual KPI and user management

Adding new KPI definition requires adding a new entry in `public.kpi_definition` table. KPI definitions can be used by
multiple circles, thus allowing a particular circle to start recording values for this KPI requires inserting a record
to `public.circle_kpi_definition`. End users can also propose new KPIs from the UI - doing so will create the required entries but in
order to be usable from the UI they need the flag `public.kpi_definition.is_approved` to be set to true.

Onboarding a new user requires creating his account in the Supabase dashboard and creating an entry in `public.kpi_user` that references the newly created row in `auth.users`. Assigning a user to a circle is done by adding a row in `public.circle_user`.

![Database schema](schema.png)
Binary file added docs/schema.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?

. DS_Store
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
60 changes: 60 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## Test scenarios

The project was tested using a set of manual tests scenarios which are provided here. The list is non-exhaustive, mostly used for regression testing. Exploratory testing was performed by the team members as well.

1. **Existing user login**

*Given* a user exists
*When* I log using Log in with Email/Password on the login page
*Then* I get redirected to the main page


2. **Display KPI definitions**

*Given* a user is logged in
*And* there exist KPI definitions
*When* I type in a KPI definition name fragment in the top search bar
*Then* a list of matching KPI definitions is displayed


3. **Display KPI values**

*Given* a user is logged in and on the 'KPIs' page
*And* there is a KPI definition with values inserted previously
*When* I click on a KPI name
*Then* a modal is opened
*And* the values are displayed in the table "Previous values"


4. **Insert new KPI value**

*Given* a user is logged in and has the KPI modal open
*And* no values exist for the selected KPI
*When* I fill in the date field with a past date
*And* I fill in the value with a valid numeric value
*And* I click "Save"
*Then* the "Previous values" table is reloaded
*And* the new value is displayed for the matching period


5. **Update of a KPI value**

*Given* a user is logged in and has the KPI modal open
*And* a value exists for the selected KPI
*When* I fill in the date field with a date matching the period
*And* I fill in the value with a valid numeric value, different from the existing one
*And* I click "Save"
*Then* the "Previous values" table is reloaded
*And* the new value is displayed for the matching period


6. **Switch default circle**

*Given* a user is logged in
*And* I open the "Settings" screen
*When* I change the default circle
*And* I click "Save"
*Then* I should be redirected to the new default circle page



0 comments on commit aac0ac5

Please sign in to comment.