Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend with accounts and province ranking system #50

Open
wants to merge 77 commits into
base: backend+accounts+rankings
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
b07895d
initial docker-compose
AlexandreOndet Apr 28, 2023
b0a59ba
added nginx and mysql
AlexandreOndet Apr 28, 2023
f9edbce
small fix depends_on
AlexandreOndet Apr 28, 2023
18eb34c
two new empty pages for the future
AlexandreOndet Apr 28, 2023
44ca464
Merge branch 'main' into docker
AlexandreOndet May 23, 2023
bf2292a
root gitignore
AlexandreOndet May 23, 2023
3c68d0a
fix docker-compose new project structure
AlexandreOndet May 23, 2023
c1d7f23
update readme for docker-compose
AlexandreOndet May 23, 2023
f53e1fc
starting auth based on what scramble-matcher is doing
AlexandreOndet May 23, 2023
5d20075
update in how the environment variables are used
AlexandreOndet May 24, 2023
5cd2e20
fix env
AlexandreOndet May 24, 2023
b1e207e
start db connection
AlexandreOndet May 24, 2023
bb6a234
from wcaid to id to match everyone
AlexandreOndet May 24, 2023
4251a4e
Merge branch 'main' of github.com:AlexandreOndet/speedcubing-canada-w…
AlexandreOndet Jun 23, 2023
b185ed2
update in how environment variable are dealt with
AlexandreOndet Jun 23, 2023
cbea314
oauth does not nork and I don't kown why
AlexandreOndet Jun 25, 2023
3e5881c
start backend python (merci cubingUSA :D)
AlexandreOndet Jun 27, 2023
a82644a
the backend is running
AlexandreOndet Jun 28, 2023
bef4eed
the start of the login works but it crashes during callback
AlexandreOndet Jun 28, 2023
8a5cc5c
oauth is working :)
AlexandreOndet Jul 2, 2023
8bffbb9
Can log in and out from the frontend
AlexandreOndet Jul 3, 2023
d03fcbd
province storing is working
AlexandreOndet Jul 4, 2023
1386347
some frontend, it's not much but it's honest work
AlexandreOndet Jul 4, 2023
bf48664
frenchc translations for the new pages
AlexandreOndet Jul 4, 2023
06e79b1
db load updated for this project
AlexandreOndet Jul 4, 2023
053a6f8
fix path
AlexandreOndet Jul 5, 2023
68448ab
loi 101
AlexandreOndet Jul 6, 2023
bb142b0
fix startup script
AlexandreOndet Jul 18, 2023
68f70cf
update comput vm scripts
AlexandreOndet Jul 18, 2023
66425d0
Revert "update comput vm scripts"
AlexandreOndet Jul 18, 2023
832b109
moved requirements ouside package
AlexandreOndet Jul 18, 2023
b7726ad
fix path
AlexandreOndet Jul 18, 2023
972164f
fix legacy env variable name + switch state to province in rank model
AlexandreOndet Jul 19, 2023
c4c3537
fix env for staging
AlexandreOndet Jul 20, 2023
fc0ec71
fix staging env, again
AlexandreOndet Jul 20, 2023
506a2ef
logs in db loading
AlexandreOndet Jul 20, 2023
9127c76
vm setup and start of ranking api
AlexandreOndet Jul 21, 2023
6ccfe0b
staging website is norw working
AlexandreOndet Jul 29, 2023
1d37df1
more info on the profile
AlexandreOndet Aug 2, 2023
f967606
api for province rankings is now working
AlexandreOndet Aug 2, 2023
94c718b
profile with all the info (but still ugly)
AlexandreOndet Aug 3, 2023
658c87e
start of the ranking page
AlexandreOndet Aug 3, 2023
a432c65
alert to confirm update of the profile
AlexandreOndet Aug 3, 2023
e4dbc49
update readme and .env.dev
AlexandreOndet Aug 4, 2023
7e7dead
loading screen on profile
AlexandreOndet Aug 4, 2023
539b002
translation everywhere, even in Autocomplete :)
AlexandreOndet Aug 4, 2023
631f4cb
province rankings without event selection
AlexandreOndet Aug 9, 2023
921af77
no display when no Province selected
AlexandreOndet Aug 9, 2023
f11a539
fix forgotten translation
AlexandreOndet Aug 9, 2023
3e527bb
minor visual fixes
AlexandreOndet Aug 9, 2023
33acfe2
fixes from Kevin's suggestions
AlexandreOndet Aug 13, 2023
2d06d06
roles translations
AlexandreOndet Aug 13, 2023
2bc5811
2nd of Kevin's suggestion + small fix in french translation to be mov…
AlexandreOndet Aug 13, 2023
ec47999
removed unused default file
AlexandreOndet Aug 13, 2023
c60a5e1
if simplification
AlexandreOndet Aug 13, 2023
db8642c
changes since last code review: admin section, load db auto, frontend…
AlexandreOndet Sep 2, 2023
bf49653
Merge branch 'main' into account
AlexandreOndet Sep 2, 2023
db92c54
renaming frontend directory to app to ease the merging process
AlexandreOndet Sep 6, 2023
95932b4
removed axios from the project
AlexandreOndet Sep 6, 2023
26e151f
updated deploy script to reflect change in dir name
AlexandreOndet Sep 6, 2023
d9f3408
fixed error when not logged in
AlexandreOndet Sep 7, 2023
91f87ba
Merge branch 'main' into account
AlexandreOndet Sep 9, 2023
c6697c1
formatting with prettier
AlexandreOndet Sep 9, 2023
9a33b78
removing web-vitals package (already removed from the code a while ago)
AlexandreOndet Sep 9, 2023
9786fcb
changes from review (front part)
AlexandreOndet Sep 9, 2023
cf11637
method renaming
AlexandreOndet Sep 9, 2023
23002c5
better requirements
AlexandreOndet Sep 9, 2023
9da98ea
review changes part 1
AlexandreOndet Sep 10, 2023
079985f
review changes part 2
AlexandreOndet Sep 10, 2023
9bd2b48
update project name in deploy script
AlexandreOndet Sep 10, 2023
8d46357
better URL handling
AlexandreOndet Sep 13, 2023
73b9ee9
renamed round property
AlexandreOndet Sep 13, 2023
74d41b6
fix display bug in case of tie
AlexandreOndet Sep 20, 2023
1af8cbd
fixes and improvements from Kevin's review
AlexandreOndet Sep 26, 2023
8b29af8
Merge branch 'main' into account
AlexandreOndet Nov 8, 2023
b2189c9
fix variable name after merge
AlexandreOndet Nov 8, 2023
757d071
small docker config changes
AlexandreOndet Dec 29, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
app/node_modules
app/npm-debug.log
app/build
node_modules
npm-debug.log
back/venv
19 changes: 19 additions & 0 deletions .env.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
NODE_LOCAL_PORT=2003
NODE_DOCKER_PORT=2003

FLASK_LOCAL_PORT=8083
FLASK_DOCKER_PORT=8083
FRONT_ADDRESS=http://localhost
API_BASE_URL=http://localhost:8003

NODE_ENV=DEV
ENV=DEV

WCA_CLIENT_ID=example-id
WCA_CLIENT_SECRET=example-secret
WCA_HOST=https://staging.worldcubeassociation.org
SESSION_SECRET_KEY=12340987
DATASTORE_EMULATOR_HOST=localhost:8081
GOOGLE_CLOUD_PROJECT=scc-staging-391105

ADMIN_WCA_ID=2017ONDE01
29 changes: 29 additions & 0 deletions .gcloudignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This file specifies files that are *not* uploaded to Google Cloud
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).

^(.*/)?#.*#$
^(.*/)?.*~$
^(.*/)?.*\.py[co]$
^(.*/)?\..*$
external/bootstrap
__pycache__/
/src/
/lib/
.git/
.gitignore
env/
back/venv/
frontend/node_modules/

# Ignore other unnecessary files
*.pyc
*.pyo
*.pyd
*.pyc
*.egg-info/
*.egg
*.bak
*.swp
*.DS_Store
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM node:16-alpine AS development
ENV NODE_ENV development

WORKDIR /
COPY app/package.json ./
COPY package-lock.json ./
RUN npm install

COPY . .
WORKDIR /app

EXPOSE 3000
CMD ["npm", "start"]
62 changes: 50 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
# speedcubingcanada.org

## Running the app locally
In order to run the app locally, you will need three independant services running at the same time:
- The frontend
- The backend
- The datastore emulator

The quickest way to get all three running is to use docker-compose for the frontend and backend, and the gcloud client for the datastore emulator.
Right now, the python part is commented in the docker-compose file, so you can either uncomment it or run it locally (useful if you want to use a debugger for example).
## Frontend
First option, in the project root directory, you can run:

First, please move into the `app` directory.
### `docker-compose up`
Runs the app and an nginx server. The app is available at [http://localhost/](http://localhost/).

In the project directory, you can run:
Second option:
Move into the `frontend` directory.

### `npm start`

Expand All @@ -14,21 +25,48 @@ Open [http://localhost:2003](http://localhost:2003) to view it in the browser.
The page will reload if you make edits.\
You will also see any lint errors in the console.

### `npm test`

Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.

Currently, there are no tests.

### `npm run build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
Currently, this step is handled deploy script described bellow.

## Backend
As mentioned above you can either use docker-compose or run the app locally.

To run the app locally, you will need to move the `back` folder first and install the dependencies (I recommend using a virtual environment):

```shell
cd back
pip install -r requirements.txt
```

Then you can run the flask app with:
```shell
gunicorn -b :8083 backend:app
```
If you use pycharm, you can also create a flask configuration and run it from there. Keep in mind the target folder is `back/backend`.

## Datastore emulator

```shell
gcloud beta emulators datastore start
```

## Deployment

To deploy the app use the script `deploy.sh` in the root directory. It will build the frontend and deploy the backend and frontend.
Here are the options available (you must choose prod or staging at least):

Currently, this step is handled automatically by an AWS build pipeline.
```sh
./deploy.sh
# Arguments:
# -p: deploy to prod
# -s: deploy to staging
# -f: frontend only
# -b: backend only
# -v <app version>: On staging, the name of the app version to upload.
```
17 changes: 17 additions & 0 deletions app/.gcloudignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This file specifies files that are *not* uploaded to Google Cloud
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore

# Node.js dependencies:
node_modules/
2 changes: 2 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.fuse_hidden*

12 changes: 12 additions & 0 deletions app/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
runtime: nodejs16

handlers:
# Serve all static files with url ending with a file extension
- url: /(.*\..+)$
static_files: build/\1
upload: build/(.*\..+)$

# Catch all handler to index.html
- url: /.*
static_files: build/index.html
upload: build/index.html
9 changes: 7 additions & 2 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,26 @@
"@mui/icons-material": "^5.6.2",
"@mui/material": "^5.6.2",
"@mui/styles": "^5.8.4",
"@mui/x-data-grid": "^6.11.0",
"@mui/x-date-pickers": "^6.10.2",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.4.0",
"@types/node": "^16.11.22",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"dayjs": "^1.11.9",
"i18next": "^21.6.16",
"ra-data-simple-rest": "^4.12.2",
"ra-language-french": "^4.13.0",
"react": "^17.0.2",
"react-admin": "^4.12.3",
"react-dom": "^17.0.2",
"react-i18next": "^11.16.7",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"typescript": "^4.5.5",
"web-vitals": "^2.1.4"
"typescript": "^4.5.5"
},
"scripts": {
"start": "PORT=2003 react-scripts start",
Expand Down
1 change: 1 addition & 0 deletions app/public/robots.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
/admin/*
17 changes: 16 additions & 1 deletion app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { Home } from "./pages/Home";
import { About } from "./pages/About";
import { Organization } from "./pages/Organization";
import { FAQ } from "./pages/FAQ";
import { Rankings } from "./pages/Rankings";
import { Account } from "./pages/Account";
import { AdminPage } from "./pages/AdminPage";
import * as React from "react";
import { Quebec } from "./pages/Quebec";

i18n.use(initReactI18next).init({
Expand Down Expand Up @@ -38,16 +42,27 @@ const App = () => {
<ThemeProvider theme={theme}>
<BrowserRouter>
<Routes>
{/* Admin page without the navigation bar */}
<Route path="/admin/*" element={<AdminPage />} />
{/* Normal pages */}
<Route element={<Base />}>
<Route path=":locale/">
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="organization" element={<Organization />} />
<Route path="faq" element={<FAQ />} />
<Route path="rankings" element={<Rankings />} />
<Route path="account" element={<Account />} />
<Route path="quebec" element={<Quebec />} />
</Route>
{["about", "organization", "faq", "quebec"].map((route) => (
{[
"about",
"organization",
"faq",
"rankings",
"account",
"quebec",
].map((route) => (
AlexandreOndet marked this conversation as resolved.
Show resolved Hide resolved
<Route
key={route}
path={route}
Expand Down
12 changes: 12 additions & 0 deletions app/src/components/AdminDashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Card, CardContent, CardHeader } from "@mui/material";
import { useTranslate } from "react-admin";

export const AdminDashboard = () => {
const t = useTranslate();
return (
<Card>
<CardHeader title={t("admin.title")} />
<CardContent>{t("admin.body")}</CardContent>
</Card>
);
};
22 changes: 20 additions & 2 deletions app/src/components/Base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,42 @@ import {
BottomNavigation,
BottomNavigationAction,
} from "@mui/material";
import { Home, Info, CorporateFare, QuestionAnswer } from "@mui/icons-material";
import {
Home,
Info,
CorporateFare,
QuestionAnswer,
AccountCircle,
Leaderboard,
} from "@mui/icons-material";
import { Link, Outlet, useLocation, useParams } from "react-router-dom";
import { getLocaleOrFallback, SAVED_LOCALE } from "../locale";

const ROUTES = ["home", "about", "organization", "faq"] as const;
const ROUTES = [
"home",
"about",
"organization",
"faq",
"rankings",
"account",
] as const;

const ICONS = {
home: Home,
about: Info,
organization: CorporateFare,
faq: QuestionAnswer,
account: AccountCircle,
rankings: Leaderboard,
} as const;

const ROUTE_NAME_TO_ROUTE = {
home: "",
about: "about",
organization: "organization",
faq: "faq",
rankings: "rankings",
account: "account",
} as const;

export const Base = () => {
Expand Down
28 changes: 28 additions & 0 deletions app/src/components/MyCubingIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import "../cubingicon.css";
import React from "react";
import { Icon, Tooltip } from "@mui/material";
import { useTranslation } from "react-i18next";
import { eventID, IconSize } from "./Types";

export const MyCubingIcon: React.FC<{
event: eventID;
selected: boolean;
size?: IconSize;
}> = (data) => {
const { t } = useTranslation();
AlexandreOndet marked this conversation as resolved.
Show resolved Hide resolved

const { event, selected, size = "medium" } = data;

return (
<Tooltip title={t("events._" + event)} arrow>
<Icon
baseClassName={`icon cubing-icon event-${event} cubing-icon-${size} ${
selected ? "cubing-icon-selected" : "cubing-icon-unselected"
}`}
sx={{
height: 40,
}}
/>
</Tooltip>
);
};
Loading