Skip to content
Snippets Groups Projects
Commit ea66679f authored by Albin Henriksson's avatar Albin Henriksson
Browse files

#14: Pulled dev

parents 1f49da58 186d707a
No related branches found
No related tags found
1 merge request!21Resolve "Add admin-view"
......@@ -2,4 +2,5 @@ __pycache__
*.db
*/env
*.coverage
htmlcov
.pytest_cache
\ No newline at end of file
......@@ -2,7 +2,7 @@
"version": "2.0.0",
"tasks": [
{
"label": "Client",
"label": "Start client",
"type": "npm",
"script": "start",
"path": "client/",
......@@ -13,7 +13,26 @@
}
},
{
"label": "Server",
"label": "Test client",
"type": "npm",
"script": "test:coverage:html",
"path": "client/",
"group": "test",
"problemMatcher": [],
},
{
"label": "Open client coverage",
"type": "shell",
"group": "build",
"command": "start ./output/coverage/jest/index.html",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/client"
},
},
{
"label": "Start server",
"type": "shell",
"group": "build",
"command": "env/Scripts/python main.py",
......@@ -26,10 +45,20 @@
}
},
{
"label": "Test Server",
"label": "Test server",
"type": "shell",
"group": "build",
"command": "env/Scripts/pytest.exe --cov-report html --cov app tests/",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/server"
},
},
{
"label": "Open server coverage",
"type": "shell",
"group": "build",
"command": "env/Scripts/pytest.exe --cov app tests/",
"command": "start ./htmlcov/index.html",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/server"
......@@ -37,11 +66,11 @@
},
{
"label": "Client + Server",
"label": "Start client and server",
"group": "build",
"dependsOn": [
"Server",
"Client"
"Start server",
"Start client"
],
"problemMatcher": []
}
......
![coverage report](https://gitlab.liu.se/tddd96-grupp11/teknikattan-scoring-system/badges/dev/coverage.svg?job=client:test&key_text=Client+Coverage&key_width=110)
![coverage report](https://gitlab.liu.se/tddd96-grupp11/teknikattan-scoring-system/badges/dev/coverage.svg?job=server:test&key_text=Server+Coverage&key_width=115)
# Scoring system for Teknikåttan
This is the scoring system for Teknikåttan!
......@@ -13,6 +12,65 @@ To install the client and server needed to run the application, look in their re
## Using
After installing both the client and the server, you are ready to run the application.
This is done in VSCode by pressing `ctrl+shift+b` and running the `Client + Server` task.
This is done in VSCode by pressing `ctrl+shift+b` and running the `Start client and server` task.
The terminals for the client and server will now be seen on the right and left, respectively.
After making a change to either the client or the server while they are running, they will auto reload and you will see the changes immediately.
After making a change to either the client or the server while they are running, simply reload the page to see the changes immediately.
## Workflow
### Working on an issue
This following steps describe how you choose an issue and create a branch and merge request from it.
1. See all issues by going to `Issues->Boards`.
2. The issues no one has started on yet are showed in the `Open` tab. Choose one of these by dragging it into the `In progress` tab and opening it.
3. Add yourself as an asignee (in top right corner).
4. Add the current week as a milestone to the issue (to the right).
5. Press the little green downarrow on the right of the `Create merge request` button and select and press `Create branch`.
6. Open the project in VSCode.
7. Type `git pull`. This will fetch the new branch you just created and you should see it in the log (Example: `* [new branch] 5-add-login-api -> origin/5-add-login-api`)
8. Switch to it by running `git checkout <issue>-<name>`. (Example: `git checkout 5-add-login-api`)
You are now ready to start working on your issue.
### Creating a merge request
When you have solved the issue and are ready to merge them into the `dev` will have to create a merge request.
1. On GitLab open `Repository->Branches`.
2. Find your branch and press `Merge request`.
You have now create a merge request for your branch.
The next step is to prepare your branch to be merged.
1. Open the project in VSCode.
2. Checkout your branch, if you are not already on it (`git checkout <branch>`).
3. Run `git pull origin dev`. This will try to merge the latest changes from `dev` into your branch. This can have a few different results:
- There will be no changes, which is fine.
- There will be no conflicting changes, which is also fine.
- There will be conflicting changes, in which case you will need to merge it manually (see Merge conflicts) before continuing to the next step.
4. Run `git push`.
5. Go to GitLab and press `Merge Requests`, open your merge request and press the green `Mark as ready` button (in the top righ corner).
The test will then run on your changes in the merge request on GitLab.
You will be allowed to merge once the pipelines have passed and another person has approved your merge request.
When this is done, simply press the `Merge` button.
### Merge conflicts
You will need to manually merge if there is a merge conflict between your branch and another.
This is simply done by opening the project in VSCode and going to the Git tab on the left (git symbol).
You will then see som files marked with `C`, which means that there are conflicts in these files.
Open them one by one and choose if you want to keep incoming changes (from `dev`), current changes (from your branch) or both.
The only thing you really need to do is removing the `<<<`, `===` and `>>>` symbols from the document, although you don't have to do it by hand.
A merge typically looks like the following picture in plain (try opening this in VSCode and see how it looks).
Simply solve all the merge conflicts in every file, run the tests to make sure it still works.
When you are done, simply commit and push your changes.
```
<<<<<<< file.txt
<Your changes>
=======
<Changes from dev>
>>>>>>> 123456789:file.txt
```
......@@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
output
......@@ -24,32 +24,33 @@ npm install
## Using
After you have done every step described in setup, you are ready to start the client.
You can either start the client using tasks (recommended) or start it directly in the terminal.
To see the tasks described in the following steps, press `ctrl+shift+b`.
### Tasks
### Starting
You can run the client using Visual Studio Code tasks.
This is done by pressing `ctrl+shift+b` and running the `Client` task.
Start the server by running the `Start client` task.
### Terminal
### Testing
Run the client tests running the `Test client` task.
After it has finished, you can view a coverage report.
This is done by running the `Open client coverage` task.
### Adding and removing new modules
You can also run the client directly from the terminal.
All of the following snippets assume you are in the `client` folder.
Running the client:
Installing new module:
```bash
npm run start
npm install <module>
```
Installing new modules:
Uninstalling module:
```bash
npm install new_module
npm uninstall <module>
```
Whenever a new module is installed, commited and pushed to git, everyone else needs to run `npm install` after pulling to install it as well.
Author: Victor Löfgren
Last updated: 11 February 2020
......@@ -4,7 +4,10 @@
"private": true,
"dependencies": {
"@material-ui/core": "^4.11.3",
<<<<<<< HEAD
"@material-ui/icons": "^4.11.2",
=======
>>>>>>> 186d707ace54d27ff8913eff2be29026e64afb43
"@material-ui/lab": "^4.0.0-alpha.57",
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.5",
......@@ -45,7 +48,8 @@
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint \"./src/**/*.{js,ts,tsx}\"",
"test:coverage": "react-scripts test --coverage --coverageDirectory=output/coverage/jest"
"test:coverage": "react-scripts test --coverage --coverageDirectory=output/coverage/jest",
"test:coverage:html": "npm test -- --coverage --watchAll=false --coverageDirectory=output/coverage/jest"
},
"browserslist": {
"production": [
......
......@@ -9,7 +9,19 @@ const App: React.FC = () => {
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/>
<<<<<<< HEAD
<Main />
=======
<h1>Application</h1>
<TestConnection />
<BrowserRouter>
<Switch>
<Route path="/">
<LoginForm />
</Route>
</Switch>
</BrowserRouter>
>>>>>>> 186d707ace54d27ff8913eff2be29026e64afb43
</div>
)
}
......
......@@ -11,7 +11,7 @@ You will need to do the following things to install the server:
3. Clone this repository if you haven't done so already.
4. Open the project folder in VSCode.
5. Open the integrated terminal by pressing `ctrl+ö`.
6. Type the following commands (or if you are on Windows, simply paste them) into your terminal:
6. Type the following commands into your terminal:
```bash
# Install virtualenv package. You may need to open as administrator if you get
......@@ -29,12 +29,13 @@ py -m venv env
# This step is different depending on your operating system.
# Windows
# You migt to run the following before activating the virtual environment.
Set-ExecutionPolicy Unrestricted -Scope Process
./env/Scripts/activate
# =====
# Linux/Mac
# source env/bin/activate
source env/bin/activate
# =====
# Install all the required packages into your virtual environment.
pip install -r requirements.txt
......@@ -42,35 +43,40 @@ pip install -r requirements.txt
## Using
After you have done every step described in setup, you are ready to run the server.
You can either run the server using tasks (recommended) or run it directly in the terminal.
After you have done every step described in setup, you are ready to start the server.
To see the tasks described in the following steps, press `ctrl+shift+b`.
### Tasks
### Starting
You can run the server using Visual Studio Code tasks.
This is done by pressing `ctrl+shift+b` and running the `Server` task.
Start the server by running the `Start server` task.
### Terminal
### Testing
You can also run the server and tests directly from the terminal.
Before doing anything in the terminal, you need to activate the Python virtual environment (see Setup).
All of the following snippets assume you are in the `server` folder.
Run the client tests running the `Test server` task.
Running the server:
After it has finished, you can view a coverage report.
This is done by running the `Open server coverage` task.
### Adding and removing new packages
All of the following snippets assume you are in the `server` folder and have activated the virtual environment (see Setup).
Installing new package:
```bash
python main.py
pip install <package>
```
Running the tests:
Uninstalling package:
```bash
python test.py
pip uninstall <package>
```
Adding new packages:
If you have added or removed a package from the repository, you will also have to run the following before commiting it to git:
```bash
pip install new_package
pip freeze > requirements.txt
```
Whenever a new package is installed, commited and pushed to git, everyone else needs to run `pip install -r requirements.txt` after pulling to install it as well.
......@@ -5,6 +5,7 @@ from app.api import api_blueprint
from app.database.models import Blacklist, User
from app.utils.validator import edit_user_schema, login_schema, register_schema, validateObject
from flask import request
from flask.globals import session
from flask_jwt_extended import (
create_access_token,
create_refresh_token,
......
from flask_sqlalchemy.model import Model
import sqlalchemy as sa
from flask_sqlalchemy.model import Model
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.sql import func
class Base(Model):
@declared_attr
def __tablename__(self):
return self.__class__.__name__.replace("Model", "s").lower()
__abstract__ = True
created = sa.Column(sa.DateTime(timezone=True), server_default=func.now())
updated = sa.Column(sa.DateTime(timezone=True), onupdate=func.now())
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
from app import bcrypt, db
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property
from app import bcrypt, db
from app.database import Base
STRING_SIZE = 254
class Blacklist(db.Model):
id = db.Column(db.Integer, primary_key=True)
jti = db.Column(db.String, unique=True, nullable=False)
@declared_attr
def __tablename__(self):
return "blacklist"
def __init__(self, jti):
self.jti = jti
class Role(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
users = db.relationship("User", backref="role")
def __init__(self, name):
self.name = name
class City(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
users = db.relationship("User", backref="city")
def __init__(self, name):
self.name = name
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(254), unique=True, nullable=False)
......@@ -28,9 +44,16 @@ class User(db.Model):
twoAuthConfirmed = db.Column(db.Boolean, default=True) # Change to false for Two factor authen
twoAuthCode = db.Column(db.String(100), nullable=True)
def __init__(self, email, plaintext_password, name=""):
role_id = db.Column(db.Integer, db.ForeignKey("role.id"), nullable=True) # Change to false
city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=True) # Change to false
media = db.relationship("Media", backref="upload_by")
def __init__(self, email, plaintext_password, role_id=None, city_id=None, name=None):
self._password = bcrypt.generate_password_hash(plaintext_password)
self.email = email
self.role_id = role_id
self.city_id = city_id
self.name = name
self.authenticated = False
......@@ -48,3 +71,164 @@ class User(db.Model):
@hybrid_method
def is_correct_password(self, plaintext_password):
return bcrypt.check_password_hash(self._password, plaintext_password)
class Media(db.Model):
id = db.Column(db.Integer, primary_key=True)
filename = db.Column(db.String(STRING_SIZE), unique=True)
type = db.Column(db.String(STRING_SIZE), nullable=False)
upload_by_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
def __init__(self, filename, type, upload_by_id):
self.filename = filename
self.type = type
self.upload_by_id = upload_by_id
class Style(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
css = db.Column(db.Text, nullable=True)
bg_image_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=True)
bg_image = db.relationship("Media", foreign_keys=[bg_image_id], uselist=False)
def __init__(self, name, css=None, bg_image_id=None):
self.name = name
self.css = css
self.bg_image_id = bg_image_id
class Competition(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
style_id = db.Column(db.Integer, db.ForeignKey("style.id"), nullable=False)
city_id = db.Column(db.Integer, db.ForeignKey("city.id"), nullable=False)
style = db.relationship("Style", foreign_keys=[style_id], uselist=False)
city = db.relationship("City", foreign_keys=[city_id], uselist=False)
def __init__(self, name, style_id, city_id):
self.name = name
self.style_id = style_id
self.city_id = city_id
class Team(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
competition = db.relationship("Competition", foreign_keys=[competition_id], uselist=False)
def __init__(self, name, competition_id):
self.name = name
self.competition_id = competition_id
class Slide(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
order = db.Column(db.Integer, nullable=False)
tweak_settings = db.Column(db.Text, nullable=True)
competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=False)
competition = db.relationship("Competition", foreign_keys=[competition_id], uselist=False)
def __init__(self, name, order, competition_id, tweak_settings=None):
self.name = name
self.order = order
self.competition_id = competition_id
self.tweak_settings = tweak_settings
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(STRING_SIZE), unique=True)
title = db.Column(db.String(STRING_SIZE), nullable=False)
timer = db.Column(db.Integer, nullable=False)
slide_id = db.Column(db.Integer, db.ForeignKey("slide.id"), nullable=False)
slide = db.relationship("Slide", foreign_keys=[slide_id], uselist=False)
def __init__(self, name, title, timer, slide_id):
self.name = name
self.title = title
self.timer = timer
self.slide_id = slide_id
class TrueFalseQuestion(db.Model):
id = db.Column(db.Integer, primary_key=True)
true_false = db.Column(db.Boolean, nullable=False, default=False)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
def __init__(self, true_false, question_id):
self.true_false = true_false
self.question_id = question_id
class TextQuestion(db.Model):
id = db.Column(db.Integer, primary_key=True)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
def __init__(self, question_id):
self.question_id = question_id
class TextQuestionAlternative(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(STRING_SIZE), nullable=False)
text_question_id = db.Column(db.Integer, db.ForeignKey("text_question.id"), nullable=False)
text_question = db.relationship("TextQuestion", foreign_keys=[text_question_id], uselist=False)
def __init__(self, text, text_question_id):
self.text = text
self.text_question_id = text_question_id
class MCQuestion(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(STRING_SIZE), nullable=False)
timer = db.Column(db.Integer, nullable=False)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
def __init__(self, title, timer, slide_id):
self.title = title
self.timer = timer
self.slide_id = slide_id
class MCQuestionAlternative(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(STRING_SIZE), nullable=False)
true_false = db.Column(db.Boolean, nullable=False, default=False)
mc_id = db.Column(db.Integer, db.ForeignKey("mc_question.id"), nullable=False)
mc = db.relationship("MCQuestion", foreign_keys=[mc_id], uselist=False)
def __init__(self, text, true_false, mc_id):
self.text = text
self.true_false = true_false
self.mc_id = mc_id
class AnsweredQuestion(db.Model):
id = db.Column(db.Integer, primary_key=True)
data = db.Column(db.Text, nullable=False)
score = db.Column(db.Integer, nullable=False)
question_id = db.Column(db.Integer, db.ForeignKey("question.id"), nullable=False)
team_id = db.Column(db.Integer, db.ForeignKey("team.id"), nullable=False)
question = db.relationship("Question", foreign_keys=[question_id], uselist=False)
team = db.relationship("Team", foreign_keys=[team_id], uselist=False)
def __init__(self, data, score, question_id, team_id):
self.data = data
self.score = score
self.question_id = question_id
self.team_id = team_id
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment