Skip to content
Snippets Groups Projects
Commit c1bb0cbc authored by Josef Olsson's avatar Josef Olsson
Browse files

Resolve "Duplicate slide and competition api"

parent d3425300
No related branches found
No related tags found
1 merge request!78Resolve "Duplicate slide and competition api"
Pipeline #41561 passed
...@@ -61,3 +61,15 @@ class CompetitionSearch(Resource): ...@@ -61,3 +61,15 @@ class CompetitionSearch(Resource):
args = competition_search_parser.parse_args(strict=True) args = competition_search_parser.parse_args(strict=True)
items, total = dbc.search.competition(**args) items, total = dbc.search.competition(**args)
return list_response(list_schema.dump(items), total) return list_response(list_schema.dump(items), total)
@api.route("/<CID>/copy")
@api.param("CID")
class SlidesOrder(Resource):
@check_jwt(editor=True)
def post(self, CID):
item_competition = dbc.get.competition(CID)
item_competition_copy = dbc.copy.competition(item_competition)
return item_response(schema.dump(item_competition_copy))
...@@ -83,3 +83,15 @@ class SlidesOrder(Resource): ...@@ -83,3 +83,15 @@ class SlidesOrder(Resource):
item_slide = dbc.edit.switch_order(item_slide, item_slide_order) item_slide = dbc.edit.switch_order(item_slide, item_slide_order)
return item_response(schema.dump(item_slide)) return item_response(schema.dump(item_slide))
@api.route("/<SOrder>/copy")
@api.param("CID,SOrder")
class SlidesOrder(Resource):
@check_jwt(editor=True)
def post(self, CID, SOrder):
item_slide = dbc.get.slide(CID, SOrder)
item_slide_copy = dbc.copy.slide(item_slide)
return item_response(schema.dump(item_slide_copy))
# import add, get # import add, get
from app.core import db from app.core import db
from app.database.controller import add, delete, edit, get, search, utils from app.database.controller import add, copy, delete, edit, get, search, utils
...@@ -140,20 +140,36 @@ def slide(item_competition): ...@@ -140,20 +140,36 @@ def slide(item_competition):
def competition(name, year, city_id): def competition(name, year, city_id):
""" Adds a competition to the database using the provided arguments. """ """
Adds a competition to the database using the
provided arguments. Also adds slide and codes.
"""
item_competition = db_add(Competition(name, year, city_id)) item_competition = _competition(name, year, city_id)
# Add one slide for the competition # Add one slide for the competition
slide(item_competition) slide(item_competition)
# TODO: Add two teams
return item_competition
def _competition(name, year, city_id, font=None):
"""
Internal function. Adds a competition to the database
using the provided arguments. Also adds codes.
"""
item_competition = db_add(Competition(name, year, city_id))
if font:
item_competition.font = font
# Add code for Judge view # Add code for Judge view
code(item_competition.id, 2) code(item_competition.id, 2)
# Add code for Audience view # Add code for Audience view
code(item_competition.id, 3) code(item_competition.id, 3)
# TODO: Add two teams
utils.refresh(item_competition) utils.refresh(item_competition)
return item_competition return item_competition
"""
This file contains functionality to copy and duplicate data to the database.
"""
from app.database.controller import add, get, search, utils
from app.database.models import Question
def _question(item_question_old, slide_id):
"""
Internal function. Makes a copy of the provided question item to the
specified slide. Does not copy team, question answers or alternatives.
"""
item_question_new = add.db_add(
Question(
item_question_old.name,
item_question_old.total_score,
item_question_old.type_id,
slide_id,
)
)
# TODO: Add question alternatives
# for item_alternatives in item_question_old.alternatives:
# dbc.add.alternatives()
return item_question_new
def _component(item_component, item_slide_new):
"""
Internal function. Makes a copy of the provided
component item to the specified slide.
"""
add.component(
item_component.type_id,
item_slide_new,
item_component.data,
item_component.x,
item_component.y,
item_component.w,
item_component.h,
)
def slide(item_slide_old):
"""
Deep copies a slide to the same competition.
Does not copy team, question answers or alternatives.
"""
item_competition = get.competition(item_slide_old.competition_id)
return slide_to_competition(item_slide_old, item_competition)
def slide_to_competition(item_slide_old, item_competition):
"""
Deep copies a slide to the provided competition.
Does not copy team, question answers or alternatives.
"""
item_slide_new = add.slide(item_competition)
# Copy all fields
item_slide_new.title = item_slide_old.title
item_slide_new.body = item_slide_old.body
item_slide_new.timer = item_slide_old.timer
item_slide_new.settings = item_slide_old.settings
# TODO: Add background image
for item_component in item_slide_old.components:
_component(item_component, item_slide_new)
for item_question in item_slide_old.questions:
_question(item_question, item_slide_new.id)
utils.commit_and_refresh(item_slide_new)
return item_slide_new
def competition(item_competition_old):
"""
Adds a deep-copy of the provided competition.
Will not copy teams, question answers or alternatives.
"""
name = "Kopia av " + item_competition_old.name
item_competition, total = search.competition(name=name)
if item_competition:
print(f"{item_competition[total-1].name}, {total=}")
name = "Kopia av " + item_competition[total - 1].name
item_competition_new = add._competition(
name,
item_competition_old.year,
item_competition_old.city_id,
item_competition_old.font,
)
# TODO: Add background image
for item_slide in item_competition_old.slides:
slide_to_competition(item_slide, item_competition_new)
return item_competition_new
...@@ -98,6 +98,16 @@ def test_competition_api(client): ...@@ -98,6 +98,16 @@ def test_competition_api(client):
response, body = delete(client, f"/api/competitions/{competition_id}", headers=headers) response, body = delete(client, f"/api/competitions/{competition_id}", headers=headers)
assert response.status_code == codes.OK assert response.status_code == codes.OK
# Get competition
competition_id = 2
response, body = get(client, f"/api/competitions/{competition_id}", headers=headers)
assert response.status_code == codes.OK
# Copies competition
for _ in range(10):
response, _ = post(client, f"/api/competitions/{competition_id}/copy", headers=headers)
assert response.status_code == codes.OK
def test_auth_and_user_api(client): def test_auth_and_user_api(client):
add_default_values() add_default_values()
...@@ -301,6 +311,11 @@ def test_slide_api(client): ...@@ -301,6 +311,11 @@ def test_slide_api(client):
# Changes the order # Changes the order
change_order_test(client, CID, slide_order, slide_order + 1, headers) change_order_test(client, CID, slide_order, slide_order + 1, headers)
# Copies slide
for _ in range(10):
response, _ = post(client, f"/api/competitions/{CID}/slides/{slide_order}/copy", headers=headers)
assert response.status_code == codes.OK
def test_question_api(client): def test_question_api(client):
add_default_values() add_default_values()
......
import app.database.controller as dbc import app.database.controller as dbc
from app.database.models import City, Competition, Media, MediaType, Question, QuestionType, Role, Slide, Team, User from app.database.models import City, Media, MediaType, Role, User
from tests import app, client, db from tests import app, client, db
from tests.test_helpers import add_default_values, assert_exists, assert_insert_fail from tests.test_helpers import add_default_values, assert_exists, assert_insert_fail
...@@ -40,6 +40,80 @@ def test_media(client): ...@@ -40,6 +40,80 @@ def test_media(client):
assert item_media.upload_by.email == "test@test.se" assert item_media.upload_by.email == "test@test.se"
def test_copy(client):
add_default_values()
# Fetches an empty competition
list_item_competitions, _ = dbc.search.competition(name="Tävling 1")
item_competition_original = list_item_competitions[0]
# Fetches the first slide in that competition
num_slides = 3
item_slides, total = dbc.search.slide(competition_id=item_competition_original.id)
assert total == num_slides
item_slide_original = item_slides[0]
# Inserts several copies of the same slide
num_copies = 10
for _ in range(num_copies):
item_slide_copy = dbc.copy.slide(item_slide_original)
num_slides += 1
check_slides_copy(item_slide_original, item_slide_copy, num_slides, num_slides - 1)
assert item_slide_copy.competition_id == item_slide_original.competition_id
# Copies competition
num_copies = 3
for _ in range(num_copies):
item_competition_copy = dbc.copy.competition(item_competition_original)
for order, item_slide in enumerate(item_competition_copy.slides):
item_slide_original = item_competition_original.slides[order]
check_slides_copy(item_slide_original, item_slide, num_slides, order)
assert item_slide.competition_id != item_slide_original.competition_id
def check_slides_copy(item_slide_original, item_slide_copy, num_slides, order):
""" Checks that two slides are correct copies of each other. Looks big but is quite fast. """
assert item_slide_copy.order == order # 0 indexing
assert item_slide_copy.title == item_slide_original.title
assert item_slide_copy.body == item_slide_original.body
assert item_slide_copy.timer == item_slide_original.timer
assert item_slide_copy.settings == item_slide_original.settings
# Checks that all components were correctly copied
assert len(item_slide_copy.components) == len(item_slide_original.components)
for i, c1 in enumerate(item_slide_original.components):
c2 = item_slide_copy.components[i]
assert c1 != c2
assert c1.x == c2.x
assert c1.y == c2.y
assert c1.w == c2.w
assert c1.h == c2.h
assert c1.data == c2.data
assert c1.slide_id == item_slide_original.id
assert c2.slide_id == item_slide_copy.id
assert c1.type_id == c2.type_id
# Checks that all questions were correctly copied
assert len(item_slide_copy.questions) == len(item_slide_original.questions)
for i, q1 in enumerate(item_slide_original.questions):
q2 = item_slide_copy.questions[i]
assert q1 != q2
assert q1.name == q2.name
assert q1.total_score == q2.total_score
assert q1.type_id == q2.type_id
assert q1.slide_id == item_slide_original.id
assert q2.slide_id == item_slide_copy.id
# TODO: Assert alternatives
# Checks that the copy put the slide in the database
item_slides, total = dbc.search.slide(
competition_id=item_slide_copy.competition_id,
# page_size=num_slides + 1, # Use this total > 15
)
assert total == num_slides
assert item_slide_copy == item_slides[order]
""" """
def test_question(client): def test_question(client):
add_default_values() add_default_values()
......
...@@ -47,17 +47,19 @@ def add_default_values(): ...@@ -47,17 +47,19 @@ def add_default_values():
dbc.add.slide(item_comp) dbc.add.slide(item_comp)
# Add slides # Add slides
i = 1 for i, item_slide in enumerate(item_comp.slides):
for item_slide in item_comp.slides:
# Populate slide with data # Populate slide with data
item_slide.title = f"Title {i}" item_slide.title = f"Title {i+1}"
item_slide.body = f"Body {i}" item_slide.body = f"Body {i+1}"
item_slide.timer = 100 + i item_slide.timer = 100 + i + 1
# item_slide.settings = "{}" # item_slide.settings = "{}"
dbc.utils.commit_and_refresh(item_slide) dbc.utils.commit_and_refresh(item_slide)
# Add question to competition # Add question to competition
dbc.add.question(name=f"Q{i}", total_score=i, type_id=1, item_slide=item_slide) dbc.add.question(name=f"Q{i+1}", total_score=i + 1, type_id=1, item_slide=item_slide)
i += 1
# Add text component
dbc.add.component(1, item_slide, {"text": "Text"}, i, 2 * i, 3 * i, 4 * i)
def get_body(response): def get_body(response):
......
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