Skip to content

Commit

Permalink
Merge branch 'main' of github.com:CityConnect-TQS/control-room
Browse files Browse the repository at this point in the history
  • Loading branch information
Barb02 committed Jun 1, 2024
2 parents bfa540a + a66725e commit 3bdbac2
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 85 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
on:
push:
branches:
- main
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
deploy:
runs-on: self-hosted
name: Deploy to DETI machine
env:
PRODUCTION: true
CURRENCY_API_KEY: ${{secrets.CURRENCY_API_KEY}}
JWT_PRIVATE: ${{secrets.JWT_PRIVATE}}
JWT_PUBLIC: ${{secrets.JWT_PUBLIC}}
POSTGRES_PASSWORD: ${{secrets.POSTGRES_PASSWORD}}
HOST_URL: deti-tqs-16.ua.pt
steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Login to GitHub Packages
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Deploy with Docker Compose
run: |
docker compose -f compose.prod.yaml pull
docker compose -f compose.prod.yaml up -d --remove-orphans
docker container prune -f
docker image prune -af
docker builder prune -af
90 changes: 34 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,52 @@
# CityConnect

This project is undertaken as part of the TQS course, with the goal of developing a MVP product while applying software enterprise architecture patterns, specifying and enforcing a Software Quality Assurance (SQA) strategy and applying Continuous Testing, Continuous Integration and Continuous Delivery practices. The chosen theme was a bus service, like the ones you found in common transportation terminals. This is a digital service which includes a customer portal, tools for staff to edit bus and trips information and a digital signage system.
![example workflow](https://github.com/CityConnect-TQS/control-room/actions/workflows/deploy.yaml/badge.svg)

Our project aligns with these goals by focusing on the development of a user-centered online system for a public bus service, with the advantage of unifying these digital services into one.
This project is undertaken as part of the TQS course, with the goal of developing an MVP product while applying software
enterprise architecture patterns, specifying and enforcing a Software Quality Assurance (SQA) strategy and applying
Continuous Testing, Continuous Integration and Continuous Delivery practices.
The chosen theme was a bus service, like the ones you found in common transportation terminals.
This is a digital service that includes a customer portal,
tools for staff to edit bus and trip information and a digital signage system.

## Keep repo and submodules up-to-date
Our project aligns with these goals by focusing on the development of a user-centered online system for a public bus
service, with the advantage of unifying these digital services into one.

Do these commands every time you start working:

```bash
git pull
git submodule foreach git pull
```

If everything works right, all submodules will hopefully be updated.

There is no need to commit submodule changes to this repo, since GitHub Actions does it by itself.

### Full fetch & pull

In the case where a full pull is needed, do the following:

```bash
git pull --recurse-submodules
git submodule foreach git checkout main
```

**WARNING: All local changes will be discarded!**

## Git tips

### Check current branch

Run this code to get the current branch of all submodules:

```bash
git submodule foreach git rev-parse --abbrev-ref HEAD
```

### Cherry-picking commits
## Credentials for testing

If you need to cherry-pick commits from another branch or repo, do the following:
- <b>Email</b>: [email protected]
- <b>Password</b>: admin123

```bash
# Add other repo, if applicable
git remote add cherry [email protected]:CityConnect-TQS/client-portal.git
git fetch cherry
## Project Resources

# Cherry-pick one commit
git cherry-pick commit_hash
#### Jira
- [Project (might need permission)](https://cityconnect-tqs.atlassian.net/jira/software/projects/CC/boards/1)
- [Jira List](https://cityconnect-tqs.atlassian.net/jira/software/projects/CC/list?atlOrigin=eyJpIjoiZDYyYTU1NDI5MDFkNGJiM2E3ZDYwMTkxNjA4YmUyYmMiLCJwIjoiaiJ9)
- [Jira Timeline](https://cityconnect-tqs.atlassian.net/jira/software/projects/CC/boards/1/timeline?shared=&atlOrigin=eyJpIjoiZTdjMmZiMWY0YjU1NDk3N2IzZWRiNTAxMWRiYWE1OWMiLCJwIjoiaiJ9)

# Cherry-pick several commits
git cherry-pick <commit_hash1>^..<commit_hash2>
#### CI/CD Pipeline
- [Link to actions workflow files on backend](https://github.com/CityConnect-TQS/staff-portal/tree/main/.github/workflows)
- [Link to actions workflow files on staff portal](https://github.com/CityConnect-TQS/client-portal/tree/main/.github/workflows)
- [Link to actions workflow files on client portal](https://github.com/CityConnect-TQS/digital-signage/tree/main/.github/workflows)
- [Link to actions workflow files on digital signage](https://github.com/CityConnect-TQS/digital-signage/tree/main/.github/workflows)

# Remove other repo, if applicable
git remote remove cherry
```
#### SonarCloud

## Project Bookmarks
- [Backend](https://sonarcloud.io/summary/overall?id=CityConnect-TQS_backend)
- [Staff Portal](https://sonarcloud.io/summary/overall?id=CityConnect-TQS_staff-portal)
- [Client Portal](https://sonarcloud.io/summary/overall?id=CityConnect-TQS_client-portal)
- [Digital Signage](https://sonarcloud.io/summary/overall?id=CityConnect-TQS_digital-signage)

- [Project Backlog](https://cityconnect-tqs.atlassian.net/jira/software/projects/CC/boards/1/backlog)
- [API Documentation](http://api.localhost/api/docs/swagger-ui/index.html)
- [Static Analysis](https://sonarcloud.io/project/overview?id=CityConnect-TQS_backend)
#### Deployment

- CI/CD enviroment: Check the [backend](https://github.com/CityConnect-TQS/backend) submodule on how CI/CD is used for testing and Sonar analysis
- [Staff Portal](http://deti-tqs-16.ua.pt/staff/)
- [Client Portal](http://deti-tqs-16.ua.pt)
- [Digital Signage](http://deti-tqs-16.ua.pt/digital/)
- [API Documentation](http://deti-tqs-16.ua.pt/api/docs/swagger-ui/index.html)

## Credentials for testing
#### Demo

- <b>Email</b>: [email protected]
- <b>Password</b>: admin123
- [Videos](https://github.com/CityConnect-TQS/control-room/tree/main/docs/demo)

## Project Team

Expand Down
2 changes: 1 addition & 1 deletion backend
Submodule backend updated 20 files
+32 −1 .github/workflows/submodule.yaml
+1 −1 .github/workflows/test_frontend.yaml
+3 −3 src/main/java/pt/ua/deti/tqs/backend/configurations/AuthConfig.java
+1 −1 src/main/java/pt/ua/deti/tqs/backend/configurations/WebSocketConfig.java
+3 −2 src/main/resources/db/migration/V002__DATA.sql
+2 −2 src/test/java/pt/ua/deti/tqs/backend/functional/client/BookReservationSteps.java
+90 −0 src/test/java/pt/ua/deti/tqs/backend/functional/client/CheckInSteps.java
+2 −1 src/test/java/pt/ua/deti/tqs/backend/functional/client/LoginSteps.java
+100 −0 src/test/java/pt/ua/deti/tqs/backend/functional/staff/ManageBusSteps.java
+6 −0 src/test/java/pt/ua/deti/tqs/backend/functional/staff/UpdateTripSteps.java
+84 −0 src/test/java/pt/ua/deti/tqs/backend/functional/staff/createTripSteps.java
+3 −3 src/test/resources/pt/ua/deti/tqs/backend/functional/client/bookReservation.feature
+1 −1 src/test/resources/pt/ua/deti/tqs/backend/functional/client/checkTrips.feature
+23 −0 src/test/resources/pt/ua/deti/tqs/backend/functional/client/checkin.feature
+49 −0 src/test/resources/pt/ua/deti/tqs/backend/functional/staff/createTrip.feature
+4 −3 src/test/resources/pt/ua/deti/tqs/backend/functional/staff/deleteTrip.feature
+1 −1 src/test/resources/pt/ua/deti/tqs/backend/functional/staff/login.feature
+73 −0 src/test/resources/pt/ua/deti/tqs/backend/functional/staff/manageBus.feature
+7 −5 src/test/resources/pt/ua/deti/tqs/backend/functional/staff/updateTrip.feature
+1 −1 src/test/resources/pt/ua/deti/tqs/backend/functional/staff/viewTrips.feature
43 changes: 26 additions & 17 deletions compose.prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
environment:
# Default user is postgres
POSTGRES_DB: cityconnect
POSTGRES_PASSWORD: cityconnect
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-cityconnect}
healthcheck:
test: [ "CMD", "pg_isready", "-U", "postgres" ]
interval: 10s
Expand All @@ -20,6 +20,7 @@ services:
depends_on:
database:
condition: service_healthy
image: ghcr.io/cityconnect-tqs/backend:${TAG:-latest}
build:
context: ./backend
dockerfile: Dockerfile.prod
Expand All @@ -30,16 +31,15 @@ services:
retries: 100
start_period: 2s
environment:
CURRENCY_API_KEY: ${CURRENCY_API_KEY}
SPRING_APPLICATION_JSON: '{
"spring.datasource.url" : "jdbc:postgresql://database:5432/cityconnect",
"spring.datasource.username" : "postgres",
"spring.datasource.password" : "cityconnect",
"spring.jpa.hibernate.ddl-auto" : "update",
"spring.datasource.url": "jdbc:postgresql://database:5432/cityconnect",
"spring.datasource.username": "postgres",
"spring.datasource.password": "${POSTGRES_PASSWORD:-cityconnect}",
"spring.jpa.hibernate.ddl-auto": "update",
"management.influx.metrics.export.enabled": "false",
"currencyapi.apikey": "${CURRENCY_API_KEY}",
"cityconnect.app.jwtPublicKey" : "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyzULMNYfytz32pr/fxkWmpSIA0tQYFY0UBjvHeY2F3tgGht6+dRBenIyAcPkwotmiWAINYbdZ1JqWVDKKnYVOjCvuh8c1biouzZHIwUpwVAHobkzrIGAHEyLDmKbRTW3anuE20pqYucf5RfIE2vvFnGp1x93mEP0Rokl/l8alE/hdWqFKeabtUIE3dgQNYukyUMunOLQsGOfRm5CbIevW+7mSxHFEn54lCHJKfUsJiLTU0xcpF5238Xt56qO0gRP2+w5yA/wcQSwgCxLi8WlLX9mPaYSWcs3pboTcGBY3duyoGokQh2ymiAP+G9pw6McV+1V0/uUgeCnJyduINkh7QIDAQAB",
"cityconnect.app.jwtPrivateKey" : "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLNQsw1h/K3Pfamv9/GRaalIgDS1BgVjRQGO8d5jYXe2AaG3r51EF6cjIBw+TCi2aJYAg1ht1nUmpZUMoqdhU6MK+6HxzVuKi7NkcjBSnBUAehuTOsgYAcTIsOYptFNbdqe4TbSmpi5x/lF8gTa+8WcanXH3eYQ/RGiSX+XxqUT+F1aoUp5pu1QgTd2BA1i6TJQy6c4tCwY59GbkJsh69b7uZLEcUSfniUIckp9SwmItNTTFykXnbfxe3nqo7SBE/b7DnID/BxBLCALEuLxaUtf2Y9phJZyzeluhNwYFjd27KgaiRCHbKaIA/4b2nDoxxX7VXT+5SB4KcnJ24g2SHtAgMBAAECggEAAYPBNBl8fi4ceNgr7F4bAYb25pNio30xAaHV8nKbV5x3UGqBBaiz3j5IqiO0KlEQsBhzpzZ8ov8FxOmpwBxGNztSq//8Xol0VITojdXFhGfczrNLM895TXyykqZggukOF3CZQmsxFNClN7dwKdjlnNS3D9/vq8Zh5T6zdkxuLcnRO7KFYjbNkePYX9laKwmo+cti/tv/p3X7FqcAI85MKRTnBfrr9B39whe55RbALdO+fzHRYNVjJrwP01A75/9gB0pY5XZ9D3I2ahGmic3zHXEUxdX7tQmkqx8IhMCuMGQj4l/JOYkj9FiHJrAZnQog5g7Q6poV0uaM++buKM6sXwKBgQDzCN48uBqvkQy+XVacnc+v00taauIwWENRz9txBPZB8OCXoha+yuLemiTpuuwuzO0pHaMbx5xwbIKVxnh9RCZpXAE40jfQFYX/HU1vq9KU4VeCVqzM4trg0uiv4Gp3NplU/tvb3PsUcn8p+EsTAPDzt4KsmYaaFnWBpIwOI3qsywKBgQDWDEBAuPhRcc/+mtoB7ksELqNN6KNWeVU0w0z3POP7wxBZM+Iqrlnl65WkDPX7vEvEccMn4/SasYOCYZ97B4/NhTlAeGTSkdp5sGV7/yMOhSzBnsg/83rX3TF6u51Y1oN3TVsiwbOGDjidC0cH0T4c//GeRCar0ay2sppLbVeNJwKBgEam0VR9gOSBGl9M6xzkk7fdiQ5j/BVp00g5UOXuN1i8Gc57BHm6qXFlBk4cVQTV9iv5va0ZvlTAdsXryKNB6JjAcmp+UlNfrnCXqCdKoBE/4Ry27c0yNcceCR738nttl+2pmWi1ORicoHMnB0wi/ekb9BURHJw24zopB74kekk5AoGAM7ssQDg0E4L9MNx9+d98k9strqOd7kVOuXzF+i7mLq+bIOPwMj6HDZFdThOv05JTgXu5HcfzEvv5+6XaZGKUd6hOCO3P+DA17BkcvdYQw+6dvYHBheszcj5MOgxj39egWFICx6im2axQNGxIU3RXnayh2Y1BB1+abWFG9xnLAhsCgYBTlSisyDe5pfqmDLSoenT8KZQ1oGMU959riAm0cs7SkhDpARhMK+oLIZtigHbHeJK+GXZ/wNNCQBDPDYgXssmi3xJX1Ru75rG8zfFK3S5w9H3NGNRVr+8g4HnPPjpnhaNOjNaAGlrTxMRB9wwLskxs/M+YhX0Otxjgb6PuUKxVjQ==",
"cityconnect.app.jwtPublicKey": "${JWT_PUBLIC:-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyzULMNYfytz32pr/fxkWmpSIA0tQYFY0UBjvHeY2F3tgGht6+dRBenIyAcPkwotmiWAINYbdZ1JqWVDKKnYVOjCvuh8c1biouzZHIwUpwVAHobkzrIGAHEyLDmKbRTW3anuE20pqYucf5RfIE2vvFnGp1x93mEP0Rokl/l8alE/hdWqFKeabtUIE3dgQNYukyUMunOLQsGOfRm5CbIevW+7mSxHFEn54lCHJKfUsJiLTU0xcpF5238Xt56qO0gRP2+w5yA/wcQSwgCxLi8WlLX9mPaYSWcs3pboTcGBY3duyoGokQh2ymiAP+G9pw6McV+1V0/uUgeCnJyduINkh7QIDAQAB}",
"cityconnect.app.jwtPrivateKey": "${JWT_PRIVATE:-MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLNQsw1h/K3Pfamv9/GRaalIgDS1BgVjRQGO8d5jYXe2AaG3r51EF6cjIBw+TCi2aJYAg1ht1nUmpZUMoqdhU6MK+6HxzVuKi7NkcjBSnBUAehuTOsgYAcTIsOYptFNbdqe4TbSmpi5x/lF8gTa+8WcanXH3eYQ/RGiSX+XxqUT+F1aoUp5pu1QgTd2BA1i6TJQy6c4tCwY59GbkJsh69b7uZLEcUSfniUIckp9SwmItNTTFykXnbfxe3nqo7SBE/b7DnID/BxBLCALEuLxaUtf2Y9phJZyzeluhNwYFjd27KgaiRCHbKaIA/4b2nDoxxX7VXT+5SB4KcnJ24g2SHtAgMBAAECggEAAYPBNBl8fi4ceNgr7F4bAYb25pNio30xAaHV8nKbV5x3UGqBBaiz3j5IqiO0KlEQsBhzpzZ8ov8FxOmpwBxGNztSq//8Xol0VITojdXFhGfczrNLM895TXyykqZggukOF3CZQmsxFNClN7dwKdjlnNS3D9/vq8Zh5T6zdkxuLcnRO7KFYjbNkePYX9laKwmo+cti/tv/p3X7FqcAI85MKRTnBfrr9B39whe55RbALdO+fzHRYNVjJrwP01A75/9gB0pY5XZ9D3I2ahGmic3zHXEUxdX7tQmkqx8IhMCuMGQj4l/JOYkj9FiHJrAZnQog5g7Q6poV0uaM++buKM6sXwKBgQDzCN48uBqvkQy+XVacnc+v00taauIwWENRz9txBPZB8OCXoha+yuLemiTpuuwuzO0pHaMbx5xwbIKVxnh9RCZpXAE40jfQFYX/HU1vq9KU4VeCVqzM4trg0uiv4Gp3NplU/tvb3PsUcn8p+EsTAPDzt4KsmYaaFnWBpIwOI3qsywKBgQDWDEBAuPhRcc/+mtoB7ksELqNN6KNWeVU0w0z3POP7wxBZM+Iqrlnl65WkDPX7vEvEccMn4/SasYOCYZ97B4/NhTlAeGTSkdp5sGV7/yMOhSzBnsg/83rX3TF6u51Y1oN3TVsiwbOGDjidC0cH0T4c//GeRCar0ay2sppLbVeNJwKBgEam0VR9gOSBGl9M6xzkk7fdiQ5j/BVp00g5UOXuN1i8Gc57BHm6qXFlBk4cVQTV9iv5va0ZvlTAdsXryKNB6JjAcmp+UlNfrnCXqCdKoBE/4Ry27c0yNcceCR738nttl+2pmWi1ORicoHMnB0wi/ekb9BURHJw24zopB74kekk5AoGAM7ssQDg0E4L9MNx9+d98k9strqOd7kVOuXzF+i7mLq+bIOPwMj6HDZFdThOv05JTgXu5HcfzEvv5+6XaZGKUd6hOCO3P+DA17BkcvdYQw+6dvYHBheszcj5MOgxj39egWFICx6im2axQNGxIU3RXnayh2Y1BB1+abWFG9xnLAhsCgYBTlSisyDe5pfqmDLSoenT8KZQ1oGMU959riAm0cs7SkhDpARhMK+oLIZtigHbHeJK+GXZ/wNNCQBDPDYgXssmi3xJX1Ru75rG8zfFK3S5w9H3NGNRVr+8g4HnPPjpnhaNOjNaAGlrTxMRB9wwLskxs/M+YhX0Otxjgb6PuUKxVjQ==}",
"cityconnect.app.jwtExpirationMs": "86400000",
"springdoc.api-docs.path": "/api/docs-config",
"springdoc.swagger-ui.url": "/api/docs-config",
Expand All @@ -53,66 +53,75 @@ services:
- maven_data:/root/.m2
labels:
- traefik.enable=true
- traefik.http.routers.backend.rule=Host(`api.localhost`)
- traefik.http.routers.backend.rule=PathPrefix(`/api`)
- traefik.http.services.backend.loadbalancer.server.port=8080
- traefik.http.routers.backend.entrypoints=web

client-portal:
depends_on:
backend:
condition: service_healthy
image: ghcr.io/cityconnect-tqs/client-portal:${TAG:-latest}
build:
context: ./client-portal
dockerfile: Dockerfile.prod
args:
- VITE_HOST_URL=${HOST_URL:-localhost}
volumes:
- bun_cache:/root/.bun/install/cache
networks:
- frontend
labels:
- traefik.enable=true
- traefik.http.routers.client-portal.rule=Host(`localhost`)
- traefik.http.routers.client-portal.rule=PathPrefix(`/`)
- traefik.http.services.client-portal.loadbalancer.server.port=5173
- traefik.http.routers.client-portal.entrypoints=web

staff-portal:
depends_on:
backend:
condition: service_healthy
image: ghcr.io/cityconnect-tqs/staff-portal:${TAG:-latest}
build:
context: ./staff-portal
dockerfile: Dockerfile.prod
args:
- VITE_HOST_URL=${HOST_URL:-localhost}
volumes:
- bun_cache:/root/.bun/install/cache
networks:
- frontend
labels:
- traefik.enable=true
- traefik.http.routers.staff-portal.rule=Host(`staff.localhost`)
- traefik.http.services.staff-portal.loadbalancer.server.port=5173
- traefik.http.routers.staff-portal.rule=PathPrefix(`/staff`)
- traefik.http.services.staff-portal.loadbalancer.server.port=80
- traefik.http.routers.staff-portal.entrypoints=web

digital-signage:
depends_on:
backend:
condition: service_healthy
image: ghcr.io/cityconnect-tqs/digital-signage:${TAG:-latest}
build:
context: ./digital-signage
dockerfile: Dockerfile.prod
args:
- VITE_HOST_URL=${HOST_URL:-localhost}
volumes:
- bun_cache:/root/.bun/install/cache
networks:
- frontend
labels:
- traefik.enable=true
- traefik.http.routers.digital-signage.rule=Host(`digital.localhost`)
- traefik.http.services.digital-signage.loadbalancer.server.port=5173
- traefik.http.routers.digital-signage.rule=PathPrefix(`/digital`)
- traefik.http.services.digital-signage.loadbalancer.server.port=80
- traefik.http.routers.digital-signage.entrypoints=web

traefik:
image: traefik:v2.11
ports:
- 80:80
- 8080:8080
- "80:80"
- "443:443"
depends_on:
backend:
condition: service_healthy
Expand Down
21 changes: 13 additions & 8 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ services:
- maven_data:/root/.m2
labels:
- traefik.enable=true
- traefik.http.routers.backend.rule=Host(`api.localhost`)
- traefik.http.routers.backend.rule=PathPrefix(`/api`)
- traefik.http.services.backend.loadbalancer.server.port=8080
- traefik.http.routers.backend.entrypoints=web

Expand All @@ -71,12 +71,14 @@ services:
- bun_cache:/root/.bun/install/cache
networks:
- frontend
environment:
- VITE_HOST_URL=localhost
labels:
- traefik.enable=true
- traefik.http.routers.client-portal.rule=Host(`localhost`)
- traefik.http.routers.client-portal.rule=PathPrefix(`/`)
- traefik.http.services.client-portal.loadbalancer.server.port=5173
- traefik.http.routers.client-portal.entrypoints=web

staff-portal:
depends_on:
backend:
Expand All @@ -90,9 +92,11 @@ services:
- bun_cache:/root/.bun/install/cache
networks:
- frontend
environment:
- VITE_HOST_URL=localhost
labels:
- traefik.enable=true
- traefik.http.routers.staff-portal.rule=Host(`staff.localhost`)
- traefik.http.routers.staff-portal.rule=PathPrefix(`/staff`)
- traefik.http.services.staff-portal.loadbalancer.server.port=5173
- traefik.http.routers.staff-portal.entrypoints=web

Expand All @@ -109,18 +113,19 @@ services:
- bun_cache:/root/.bun/install/cache
networks:
- frontend
environment:
- VITE_HOST_URL=localhost
labels:
- traefik.enable=true
- traefik.http.routers.digital-signage.rule=Host(`digital.localhost`)
- traefik.http.routers.digital-signage.rule=PathPrefix(`/digital`)
- traefik.http.services.digital-signage.loadbalancer.server.port=5173
- traefik.http.routers.digital-signage.entrypoints=web

traefik:
image: traefik:v2.11
ports:
- 80:80
- 8080:8080
- 443:443
- "80:80"
- "8080:8080"
depends_on:
backend:
condition: service_healthy
Expand Down
Binary file added docs/CityConnect_Presentation.pdf
Binary file not shown.
Binary file added docs/demo/client.mp4
Binary file not shown.
Binary file added docs/demo/digital.mp4
Binary file not shown.
Binary file added docs/demo/staff.mp4
Binary file not shown.

0 comments on commit 3bdbac2

Please sign in to comment.