diff --git a/docs/source/contact.md b/docs/source/contact.md index eebe583d4b8df2d21638761816c05dfe83795e6e..8fc5ed576a140a500c94c6baa1330e5f10682a74 100644 --- a/docs/source/contact.md +++ b/docs/source/contact.md @@ -3,15 +3,13 @@ The people involved in the project, their email, their role in the project, what they worked on generally and, if anything, they worked on most will be described below. Please feel free to contact us if you have any questions. -| Namn | Email | Roll | Generellt | Speciellt | -| ------------------ | ----------------------- | ---------------------- | --------- | ---------------------- | -| Albin Henriksson | albhe428@student.liu.se | Testledare | Frontend | | -| Sebastian Karlsson | sebka991@student.liu.se | Arkitekt | Frontend | | -| Victor Löfgren | viclo211@student.liu.se | Konfigurationsansvarig | Backend | Dokumentation, Sockets | -| Björn Modée | bjomo323@student.liu.se | Kvalitetsamordnare | Frontend | Redux | -| Josef Olsson | josol381@student.liu.se | Teamledare | Backend | | -| Max Rüdiger | maxru105@student.liu.se | Dokumentansvarig | Frontend | | -| Carl Schönfelder | carsc272@student.liu.se | Utvecklingsledare | Backend | Databas | -| Emil Wahlqvist | emiwa210@student.liu.se | Analysansvarig | Frontend | Presentationseditor | - -[comment]: # (Should this really be in swedish?) \ No newline at end of file +| Name | Email | Role | Generally | Especially | +| ------------------ | ----------------------- | ------------------------ | --------- | ------------------------------ | +| Albin Henriksson | albhe428@student.liu.se | Test Leader | Front end | Presentations, Editor, Testing | +| Sebastian Karlsson | sebka991@student.liu.se | Architect | Front end | Editor, Uploading pictures | +| Victor Löfgren | viclo211@student.liu.se | Configuration Management | Back end | Documentation, Sockets, API | +| Björn Modée | bjomo323@student.liu.se | Quality Assurance | Front end | Redux | +| Josef Olsson | josol381@student.liu.se | Team Leader | Back end | Database, Testing | +| Max Rüdiger | maxru105@student.liu.se | Document Management | Front end | | +| Carl Schönfelder | carsc272@student.liu.se | Development Leader | Back end | Database, Uploading pictures | +| Emil Wahlqvist | emiwa210@student.liu.se | Analyst | Front end | Editor | diff --git a/docs/source/development/client.md b/docs/source/development/client.md index c868be7420b0a94cfa9cb6e2379cf9789d4cb18a..3cef7f4041f992ea836ea6910842f043ee23dcd7 100644 --- a/docs/source/development/client.md +++ b/docs/source/development/client.md @@ -1,10 +1,10 @@ # Frontend -[comment]: # (TODO) +Here it is described how to work with the frontend in the system. ## Working with TypeScript -[comment]: # (TODO) +The main programming languange used for the front end is TypeScript. ### npm diff --git a/docs/source/development/external.md b/docs/source/development/external.md index ee8c3b358bf0c8bea21575bf161d4450ae05f39e..83d02ad542760b90d0aa48145e816adc98065e0a 100644 --- a/docs/source/development/external.md +++ b/docs/source/development/external.md @@ -12,5 +12,3 @@ It's very helpful when developing APIs. [DB Browser for SQlite](https://sqlitebrowser.org/) is used to see what is currently stored in the database. You can even edit values. - -[comment]: # (Add VS CODE?) \ No newline at end of file diff --git a/docs/source/development/further.md b/docs/source/development/further.md index 543de426d0f437292596246684b5aff10ca3ceb3..8b6d8b7dfa37d42c25f2378cba52832a739d3f15 100644 --- a/docs/source/development/further.md +++ b/docs/source/development/further.md @@ -20,15 +20,3 @@ A list of all the questions that needs to be supported (and more) can be found o Here we will give a list of things we think will improve the system. It is not certain that they are a better solutions but definitely something to look into. - -### Replace Flask-RESTX with flask-smorest - -[comment]: # (This is already implemented) - -We currently use [Flask-RESTX](https://flask-restx.readthedocs.io/en/latest/) to define our endpoints and parse the arguments they take, either as a query string or in the body. -But when responding we use [Marshmallow](https://flask-smorest.readthedocs.io/en/latest/) to generate the JSON objects to return. -We believe that [flask-smorest](https://flask-smorest.readthedocs.io/en/latest/) would integrate a lot better with Marshmallow. -This would give us the ability to more easily show the expected arguments and the return values for our endpoints using Swagger (when visiting `localhost:5000`). -Currently we only show the route. -The work required also seems to be rather small because they look quite similar. -This would also remove the deprecated [reqparse](https://flask-restx.readthedocs.io/en/latest/parsing.html) part from Flask-RESTX, which is desirable. diff --git a/docs/source/development/vscode.md b/docs/source/development/vscode.md index 86c4a97fd13e0b0320a0cecb7894ff77c078feda..be5e7ed961473a1f29f3747a25e13a07b3950160 100644 --- a/docs/source/development/vscode.md +++ b/docs/source/development/vscode.md @@ -13,8 +13,6 @@ The Python and Pylance extensions help with linting Python code, auto imports, s Prettier is an extension used to format JavaScript and TypeScript. ESLint is used to lint JavaScript and TypeScript code. -[comment]: # ("is used to lint JavaScript" what is lint? It's not explained) - Live Share is an extension that is used to write code together at the same time, much like a Google Docs document. There were however a few issues with the Python extension that made Live Share hard to work with. diff --git a/docs/source/documentation/client.md b/docs/source/documentation/client.md index fe424fe59115b82fd2ac7ed865a7958f226e48d9..ca1dcfe8f4edf2280b636384ba5b6dcf148a60d1 100644 --- a/docs/source/documentation/client.md +++ b/docs/source/documentation/client.md @@ -16,5 +16,3 @@ start ./docs/index.html ``` If you want to include the documentation from the tests, go to the file `client/tsconfig.json` and comment out the line `"exlude": "**/*.test.*"`. - -[comment]: # (There should be a task for this, or does one exist already?) \ No newline at end of file diff --git a/docs/source/installation/client.md b/docs/source/installation/client.md index e5768e9c7a1eb0c658b3ecc4e66d2f5122ec776e..f7a886525bad9cf6655b8a972f013b235455a4d9 100644 --- a/docs/source/installation/client.md +++ b/docs/source/installation/client.md @@ -19,5 +19,4 @@ npm install You should now be ready to start the client. Try it by running `npm run start`. A web page should open where you can see the [login page](../user_manual/login.md). - -[comment]: # (Should we mention the task for starting the client?) +If you are using VS Code you can also start the client with the [task](../development/vscode.md) `start client`. diff --git a/docs/source/installation/server.md b/docs/source/installation/server.md index 3c867f43d7a90f49ea21720df224770d2372c27c..889c2465904a75dd53e19c1c5e83b149b3d05eb6 100644 --- a/docs/source/installation/server.md +++ b/docs/source/installation/server.md @@ -41,5 +41,4 @@ pip install -r requirements.txt You should now be ready to start the server. Try it by running `python main.py` and navigate to `localhost:5000`. If everything worked as it should you should see a list of all available API calls. - -[comment]: # (Should we mention the task for starting the server?) +If you are using VS Code you can also start the server with the [task](../development/vscode.md) `start server`. diff --git a/docs/source/overview/overview.md b/docs/source/overview/overview.md index 5a46ed1975d8835380c5dc403edefe0bd6caf9c1..fec1ff24ffe7eb9c11e7fee42e46484f4b9ef264 100644 --- a/docs/source/overview/overview.md +++ b/docs/source/overview/overview.md @@ -16,10 +16,8 @@ This is to make sure that whoever tries to communicate has the correct level of ### API -[comment]: # (What does "that will proxy the request to the main Python server" mean?) - API calls are used for simple functions that the client wants to perform, such as getting, editing, and saving data. -These are sent from the client to the backend Node server that will proxy the request to the main Python server. +These are sent from the client to the backend Node server that will forward the request to the main Python server. The request will then be handled there and the response will be sent back. The Node server will then send them back to the client. diff --git a/docs/source/overview/server.md b/docs/source/overview/server.md index 9f322c4e2d43843f8126ac9539a5ef2a88d9e0ff..73b56dbaad7ee5c7fb174172bc9e2d1dfd997ca6 100644 --- a/docs/source/overview/server.md +++ b/docs/source/overview/server.md @@ -6,6 +6,17 @@ It also needs to make sure that only authorized people can access these. The other responsibility is to sync slides, timer and answers between clients in an active competition. Both of these will be described in more detail below. +## Libraries + +The server is built in [Flask](https://flask.palletsprojects.com/en/2.0.x/). +A few extensions to Flask are also used. +[flask-smorest](https://flask-smorest.readthedocs.io/en/latest/) is used to defined the API routes. +It is this libray that automatically documents the API on `localhost:5000` using Swagger. +[marshmallow](https://marshmallow.readthedocs.io/en/stable/) is used to convert database objects in JSON and to parse JSON back into Python objects. +[SQLAlchemy](https://www.sqlalchemy.org/) is used to interface with the SQL database that is used. +More specifically [Flask-SQLAlchemy](https://flask-sqlalchemy.palletsprojects.com/en/2.x/) is used to integrate it with Flask. +[Flask-Bcrypt](https://flask-bcrypt.readthedocs.io/en/latest/) is used to encrypt passwords. + ## Receiving API calls An API call is a way for the client to communicate with the server. @@ -26,7 +37,7 @@ When the server receives an API call it will first check that the call is author The authorization is done using JSON Web Tokens (JWT) by comparing the contents of them with what is expected. Whenever a client logs into an account or joins a competition, it is given a JWT generated by the server, and the client will need to use this token in every subsequent request sent to the server in order to authenticate itself. -The needed authorization is specified by the `@protect_route()` decorator. +The needed authorization is specified by the `ExtendedBlueprint.authorization()` decorator. This decorator specifies who is allowed to access this route, which can either be users with specific roles, or people that have joined competitions with specific views. If the route is not decorated everyone is allowed to access it, and the only routes currently like that is, by necessity, logging in as a user and joining a competition. @@ -42,9 +53,9 @@ This is why the server can simply read the contents of the JWT to be sure that t ### Parsing request -After the request is authorized the server will need to parse the contents of the request. -The parsing is done with [reqparse](https://flask-restx.readthedocs.io/en/latest/parsing.html) from RestX (this module is deprecated and should be replaced). -Each API call expects different parameters in different places and this is specified in each of the files in `app/apis/` folder, together with the route. +The server receives data in three ways: In the query string, body and header. +The data in the body and header is sent in JSON format and needs to be converted into Python dictionaries. +What data a route needs is specified by a marshmallow schema and blueprint from flask-smorest. ### Handling request @@ -56,7 +67,7 @@ Everything related to the database is located in the `app/database/` folder. ### Responding When the server har processed the request it usually responds with an item from the database. -Converting a database object to json is done with [Marsmallow](https://marshmallow.readthedocs.io/en/stable/). +Converting a database object to json is done with marshmallow. This conversion is specified in two files in the folder `app/core/`. The file `schemas.py` converts a record in the database field by field. The file `rich_schemas.py` on the other hand converts an `id` in one table to an entire object in the another table, thus the name rich. @@ -65,18 +76,18 @@ In this way, for example, an entire competition with its teams, codes, slides an ## Active competitions Slides, timers, and answers needs to be synced during an active presentation. -This is done using SocketIO together with flask_socketio. +This is done using SocketIO together with flask-socketio. Sent events are also authorized via JWT, basically the same way as the for the API calls. -But for socket events, the decorator that is used to authenticate them is `@authorize_user()`. +But for socket events, the decorator that is used to authenticate them is `sockets.authorization()`. Whenever a client joins a competition they will connect via sockets. A single competition cannot be active more than once at the same time. This means that you will need to make a copy of a competition if you want to run the same competition at several locations at the same time. All of the functionality related to an active competition and sockets can be found in the file `app/core/sockets.py`. -The terms *active competition* and *presentation* are equivalent. +The terms _active competition_ and _presentation_ are equivalent. ### Starting and joing presentations -Whenever a code is typed in to the client it will be checked via the `api/auth/login/code` API call. +Whenever a code is typed in to the client it will be checked via the `api/auth/code` API call. If there is such a code and it was an operator code, the client will receive the JWT it will need to use to authenticate itself. If there is such a code and the associated competition is active, the client will also receive a JWT for its corresponding role. Both of these cases will be handled by the default `connect` event, using the JWT received from the API call. @@ -84,10 +95,9 @@ The server can see what is stored in the JWT and do different things depending o ### Syncing between clients -[comment]: # (What does `sync` mean? It isn't explained) - -The operator will emit the `sync` event and provide either a slide or a timer to update it on the server. -The server will then send `sync` to all connected clients with the updated values, regardless of what was actually updated. -The server will also store the timer and active slide in order to `sync` clients when they join. -The operator can also emit `end_presentation` to disconnect all clients from its competitions. +There are two other events that is used. +The operator will emit the `sync` event to syncronise some values to all other clients connected to the same competition. +The server will then send `sync` to all connected clients with the values that was updated. +The server will also store these values and will syncronise these when a client joins a presentation. +The operator can also emit `end_presentation` to disconnect all clients from its presentation. This will also end the presentation. diff --git a/docs/source/testing/client.md b/docs/source/testing/client.md index b0201a485b067be1dd57a7ca0fd48712d543cf31..367eee00a5e661f63761926c62b10768cbabc262 100644 --- a/docs/source/testing/client.md +++ b/docs/source/testing/client.md @@ -1,3 +1,5 @@ # Testing the client -[comment]: # (TODO) \ No newline at end of file +The clients tests are the files named `<name>.test.ts`. +They test the file called `<name>.ts`. +They are run using the [VS Code task](../development/vscode.md) `Unit tests`. diff --git a/docs/source/testing/e2e.md b/docs/source/testing/e2e.md index 62d7038664f24151e4fcc1a45849f337e9636770..2fdffa7a7038cd9acaefcc2580dad5d9be38afb9 100644 --- a/docs/source/testing/e2e.md +++ b/docs/source/testing/e2e.md @@ -1,3 +1,6 @@ # End to end tests -[comment]: # (TODO) \ No newline at end of file +The end to end tests are tests that test the entire system, both the server and the client. +They are stored in the folder `/client/src/e2e/`. +Both the client and the server need to be running for the end to end tests to work. +The tests are run using the [VS Code task](../development/vscode.md) `Run e2e tests`. diff --git a/docs/source/user_manual/editor.md b/docs/source/user_manual/editor.md index 7091cce61b74daabd5bbdc476d3dce7fc6186aa2..c3c99901c3e4b01c4a1a27d7827e009036ed831a 100644 --- a/docs/source/user_manual/editor.md +++ b/docs/source/user_manual/editor.md @@ -1,7 +1,6 @@ # Editor -[comment]: # 'Explain where to find the competition name. Perhaps an image or link to Admin?' - +The [competition manager](./admin.md) will list all competitions. After clicking on a competition name you will enter the editor and will be able to edit it. The Teknikåttan logo in the top left corner will take you back to the Admin page and right under that all slides are shown. A newly created competition will have one empty default slide. @@ -9,6 +8,7 @@ Switch to a different slide by clicking on it. In the bottom left corner you will be able to add a new slide using the "Ny sida" button. Delete or copy a slide simply by right clicking on it and choosing the appropriate option. In the top right corner you will be able to change which view you see and edit. +By right clicking on a component you will be able to delete it or copy it to the same or a different view.  @@ -31,5 +31,3 @@ Below that you will be able to add and remove text and image components as well The background image for the competition can be overridden by explicitly setting it on a specific page.  - -[comment]: # 'Perhaps mention right clicking a component to make a copy to another view?' diff --git a/docs/source/user_manual/presentation.md b/docs/source/user_manual/presentation.md index 2bb125a59fafad25d5787524a4212e4377b0e789..03845fa4f4ff590a53a844f121a6d8dfbdfd3b48 100644 --- a/docs/source/user_manual/presentation.md +++ b/docs/source/user_manual/presentation.md @@ -1,13 +1,12 @@ -[comment]: # "Why is this file named 'presentation' but the main headline is 'Active competitions'?" +# Presentations -# Active competitions - -There are many different views during a competition. -Below it is described how to start a competition, how to join a competition, and how the different kinds of views work. +An active (i.e. started) competition is for simplicity's sake called a presentation. +There are many different views during a presentation. +Below it is described how to start a competition, how to join a presentation, and how the different kinds of views work. ## Competition codes -You can join a competition with codes. +You can join a presentation with codes. This can either be done by pasting the link that can be copied when listing the codes or can be typed by hand in the login page. All the views have different purposes and therefore looks a little bit different from one another. @@ -16,17 +15,16 @@ All the views have different purposes and therefore looks a little bit different There are two ways to start a competition. The first way is to navigate to the competition manager, press the three dots "..." and press "Starta". You will then enter the operator view. -From there you will be able to go between slides with the "<" and ">" buttons or start the timer, both will be synced between all clients connected to that competition. -You will also be able to view the scores for the teams and view all codes to the competition. +From there you will be able to go between slides with the "<" and ">" buttons and start the timer, both will be synced between all clients connected to that presentation. +You will also be able to view all codes to the competition. +You can also show the current score for all teams to the audience.  ## Team -[comment]: # 'What is meant with "(or the code for one of the teams)"? Doesnt a team have to log in using a code?' - -The team view (or the code for one of the teams) will be used by teams. -It shows the current slide (that the operator has decided) and allows the user to answer questions on the slide that will be saved. +The team view will be used by teams. +It shows the current slide (that the operator has decided) and allows the user to answer questions on the slide, which will be saved.  @@ -38,10 +36,8 @@ The audience view will look like the operator view but without the buttons. ## Judge -[comment]: # 'Update image to show that the current slide is highlighted.' - The judge view will show show the same slide as team view. -To the left you will be able to move between different slides without affecting the other clients and will be shown och which slide the operator currently is. +To the left you will be able to move between different slides without affecting the other clients and will be shown on which slide the operator currently is. To the right you will see what the teams have answered on every question, what score each team got on each question, their total score and be able to set the score of a team on any and all questions. In the bottom right you will see instructions for how to grade the current question. diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py index 92e6dc8eff7a09ed2dbef788238693e5dde51190..4e6c7df6993d34ff4d1c98fb89f4908438a98863 100644 --- a/server/app/database/__init__.py +++ b/server/app/database/__init__.py @@ -6,8 +6,6 @@ database. It can add, get, delete, edit, search and copy items. from app.apis import http_codes from flask_smorest import abort from flask_smorest.pagination import PaginationParameters - -# from flask_restx import abort from flask_sqlalchemy import BaseQuery from flask_sqlalchemy.model import Model from sqlalchemy import Column, DateTime diff --git a/server/app/database/controller/delete.py b/server/app/database/controller/delete.py index 3a617d3c7df5d0b96fee21261f0694cd6bb9b27c..d85228cf5eb82fad02ddeb219f46fb91ff06212f 100644 --- a/server/app/database/controller/delete.py +++ b/server/app/database/controller/delete.py @@ -7,8 +7,6 @@ from app.apis import http_codes from app.core import db from app.database.models import QuestionAlternativeAnswer, QuestionScore, Whitelist from flask_smorest import abort - -# from flask_restx import abort from sqlalchemy.exc import IntegrityError diff --git a/server/app/database/controller/edit.py b/server/app/database/controller/edit.py index a5e35352163b04729851b53f62ed839dacdb93f7..d9930633490bd2f22c4a6b3fbb082352a5fa193c 100644 --- a/server/app/database/controller/edit.py +++ b/server/app/database/controller/edit.py @@ -5,8 +5,6 @@ This file contains functionality to get data from the database. from app.apis import http_codes from app.core import db from flask_smorest import abort - -# from flask_restx.errors import abort from sqlalchemy import exc diff --git a/server/app/database/controller/utils.py b/server/app/database/controller/utils.py index acfddc136a3e4c58135dede0839885ee1c93974c..9c321cdc936392c1e428d0acfc7554840a0ca73c 100644 --- a/server/app/database/controller/utils.py +++ b/server/app/database/controller/utils.py @@ -8,8 +8,6 @@ from app.core.codes import generate_code_string from app.database.models import Code from flask_smorest import abort -# from flask_restx import abort - def move_order(orders, order_key, from_order, to_order): """