Skip to content

Commit

Permalink
Merge branch 'develop' into user-permissions
Browse files Browse the repository at this point in the history
# Conflicts:
#	tabbycat/adjallocation/views.py
#	tabbycat/adjfeedback/views.py
#	tabbycat/api/serializers.py
#	tabbycat/api/views.py
#	tabbycat/breakqual/views.py
#	tabbycat/draw/views.py
#	tabbycat/motions/views.py
  • Loading branch information
tienne-B committed May 3, 2024
2 parents 398344e + dd86433 commit dafb8e3
Show file tree
Hide file tree
Showing 68 changed files with 808 additions and 469 deletions.
55 changes: 44 additions & 11 deletions .github/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,61 @@
Change Log
==========

2.8.0 (Quokka)
2.9.0 (Ragdoll)
---------
*Release date: TBD*

- Added a setting to expect no feedback from teams or adjudicators. Thanks Daan Koning!
- Allowed scores to be given in any increments.
- Actions taken through the API are now logged.
- Participants' private URLs now show their barcode for checkin. Thank you to Miha Frangež!
- The API includes participants' barcode numbers on participant endpoints.


2.8.1
-----
*Release date: 27 January 2024*

- Fixed failing draw generation with byes (BACKEND-BWA)
- Avoided showing points in private URL table for uncredited rounds (BACKEND-BVY)
- Corrected ordering of ballots in private URL tables (#2369)
- Fixed draw strength metrics counting unconfirmed ballots
- API: Re-added ``seq`` for motions in Round endpoint
- Hid real names from ballot forms if code names used
- Fixed break category form showing general error


2.8.0 (Quokka)
---------
*Release date: 28 November 2023*

- The term "iron person" is now used throughout the platform for consistency and inclusivity. Thanks to @dcorks for the pull request!
- The number of times a team has had an iron-speaker is now tracked as a team metric.
- Added new emoji from Unicode 12 and 13. Thank you to Daan Koning for the pull request! (`#2143 <https://github.com/TabbycatDebate/tabbycat/issues/2143>`_)
- Info Slides can now use rich-text formatting (e.g. bold, links, etc). Thanks to Trần Trang Linh for adding this feature!
- Speaker and break category forms have better validation and fewer fields.
- The number of times a team has had an iron-speaker is now tracked.
- Tournaments can be created specifying private URL use directly. Thanks to Sébastien Dunne Fulmer!
- Implemented support for APDA-style tournaments with:
- Avoidance for a team to repeatedly meet pulled-up teams,
- A new two-team draw generator to minimize penalties globally within brackets,
- Team seeding for the first round,
- The ability to give ranks to speeches in addition to speaker scores, and
- A preset to enable these options.
- Avoidance for a team to repeatedly meet pulled-up teams,
- A new two-team draw generator to minimize penalties globally within brackets,
- Team seeding for the first round,
- The ability to give ranks to speeches in addition to speaker scores, and
- A preset to enable these options.
- API Updates:
- Documentation is now automatically generated and available under the ``/api/schema/redoc/`` path on all sites.
- Preformed panels are now accessible using the API.
- Team and speaker scores by round has a new endpoint. Thanks to Ido Wolf for the feature!
- The site's timezone is shown in the root endpoint.
- Documentation is now automatically generated and available under the ``/api/schema/redoc/`` path on all sites.
- Preformed panels are now accessible using the API.
- Team and speaker scores by round has a new endpoint. Thanks to Ido Wolf for the feature!
- The site's timezone is shown in the root endpoint. Thanks to Daan Koning!
- \+ so many more little improvements and fixes!


2.7.8
-----
*Release date: 13 August 2023*

- Fixed some issues with Docker-based deployments.


2.7.7
-----
*Release date: 23 April 2023*
Expand Down
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

# Grab a python image
FROM python:3.9
SHELL ["/bin/bash", "--login", "-c"]

# Just needed for all things python (note this is setting an env variable)
ENV PYTHONUNBUFFERED 1
Expand All @@ -12,14 +13,13 @@ ENV IN_DOCKER 1
# Setup Node/NPM
RUN apt-get update
RUN apt-get install -y curl nginx
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash -
RUN apt-get install -y nodejs npm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Copy all our files into the baseimage and cd to that directory
RUN mkdir /tcd
WORKDIR /tcd
# Can this be skipped? Takes ages
ADD . /tcd/
COPY . /tcd/

RUN nvm install && nvm use

# Set git to use HTTPS (SSH is often blocked by firewalls)
RUN git config --global url."https://".insteadOf git://
Expand Down
8 changes: 3 additions & 5 deletions config/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
# This is customised from https://github.com/heroku/heroku-buildpack-nginx.git
# Done so in order to properly proxy to both and asgi and wasgi server
# Super useful template:
# https://github.com/CLClark/fcc-stock-trading-app/blob/9017f001255718c2e0fd24eb8267df02267d6cd8/config/nginx.conf.erb
# Done so in order to properly proxy to both and asgi and wsgi server

daemon off;
# Heroku dynos have at least 4 cores.
worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>;
worker_processes 4;

events {
use epoll;
accept_mutex on;
worker_connections <%= ENV['NGINX_WORKER_CONNECTIONS'] || 1024 %>;
worker_connections 1024;
}

http {
Expand Down
2 changes: 1 addition & 1 deletion config/nginx.conf.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This is customised from https://github.com/heroku/heroku-buildpack-nginx.git
# Done so in order to properly proxy to both and asgi and wasgi server
# Done so in order to properly proxy to both and asgi and wsgi server
# Super useful template:
# https://github.com/CLClark/fcc-stock-trading-app/blob/9017f001255718c2e0fd24eb8267df02267d6cd8/config/nginx.conf.erb

Expand Down
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ services:
- DOCKER_REDIS=1
- USING_NGINX=1
ports:
- "127.0.0.1:8000:8000"
- "8000:8000"
volumes:
- ./tabbycat/settings:/tcd/tabbycat/settings
- .:/tcd
working_dir: /tcd

worker:
Expand All @@ -60,7 +60,7 @@ services:
- DOCKER_REDIS=1
- USING_NGINX=1
volumes:
- ./tabbycat/settings:/tcd/tabbycat/settings
- .:/tcd
working_dir: /tcd

volumes:
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
# built documents.
#
# The short X.Y version.
version = '2.8'
version = '2.9'
# The full version, including alpha/beta/rc tags.
release = '2.8.0-dev'
release = '2.9.0-dev'

rst_epilog = """
.. |vrelease| replace:: v{release}
Expand Down
26 changes: 13 additions & 13 deletions tabbycat/actionlog/management/commands/keytimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,35 +38,35 @@ def handle_tournament(self, tournament, **options):
queryset = round.actionlogentry_set.order_by('timestamp')

# Find the last adj save before venue allocation
venues_last_allocated = queryset.filter(type=ActionLogEntry.ACTION_TYPE_VENUES_AUTOALLOCATE).last()
adj_saves = queryset.filter(type=ActionLogEntry.ACTION_TYPE_ADJUDICATORS_SAVE)
venues_last_allocated = queryset.filter(type=ActionLogEntry.ActionType.VENUES_AUTOALLOCATE).last()
adj_saves = queryset.filter(type=ActionLogEntry.ActionType.ADJUDICATORS_SAVE)
if venues_last_allocated:
adj_saves = adj_saves.filter(timestamp__lte=venues_last_allocated.timestamp)
last_adj_save = adj_saves.last()

entries = [
queryset.filter(type=ActionLogEntry.ACTION_TYPE_DRAW_CREATE).first(),
queryset.filter(type=ActionLogEntry.ActionType.DRAW_CREATE).first(),
queryset.filter(type__in=[
ActionLogEntry.ACTION_TYPE_DEBATE_IMPORTANCE_EDIT,
ActionLogEntry.ACTION_TYPE_DEBATE_IMPORTANCE_AUTO,
ActionLogEntry.ActionType.DEBATE_IMPORTANCE_EDIT,
ActionLogEntry.ActionType.DEBATE_IMPORTANCE_AUTO,
]).first(),
queryset.filter(type__in=[
ActionLogEntry.ACTION_TYPE_ADJUDICATORS_AUTO,
ActionLogEntry.ACTION_TYPE_PREFORMED_PANELS_DEBATES_AUTO,
ActionLogEntry.ActionType.ADJUDICATORS_AUTO,
ActionLogEntry.ActionType.PREFORMED_PANELS_DEBATES_AUTO,
]).first(),
last_adj_save,
venues_last_allocated,
# "start at" times goes here
queryset.filter(type__in=[
ActionLogEntry.ACTION_TYPE_BALLOT_CREATE,
ActionLogEntry.ACTION_TYPE_BALLOT_SUBMIT,
ActionLogEntry.ActionType.BALLOT_CREATE,
ActionLogEntry.ActionType.BALLOT_SUBMIT,
]).first(),
queryset.filter(type=ActionLogEntry.ACTION_TYPE_BALLOT_CONFIRM).first(),
queryset.filter(type=ActionLogEntry.ActionType.BALLOT_CONFIRM).first(),
queryset.filter(type__in=[
ActionLogEntry.ACTION_TYPE_BALLOT_CREATE,
ActionLogEntry.ACTION_TYPE_BALLOT_SUBMIT,
ActionLogEntry.ActionType.BALLOT_CREATE,
ActionLogEntry.ActionType.BALLOT_SUBMIT,
]).last(),
queryset.filter(type=ActionLogEntry.ACTION_TYPE_BALLOT_CONFIRM).last(),
queryset.filter(type=ActionLogEntry.ActionType.BALLOT_CONFIRM).last(),
]
times = [timezone.localtime(entry.timestamp) if entry else None for entry in entries]
date = next((t for t in times[:5][::-1] if t is not None), None)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Generated by Django 4.1.7 on 2024-01-11 17:27

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("actionlog", "0012_auto_20200705_1317"),
]

operations = [
migrations.AddField(
model_name="actionlogentry",
name="agent",
field=models.CharField(
choices=[("a", "API"), ("w", "Web")],
default="w",
max_length=1,
verbose_name="agent",
),
),
migrations.AlterField(
model_name="actionlogentry",
name="type",
field=models.CharField(
choices=[
("br.aj.set", "Changed adjudicator breaking status"),
("aj.crea", "Created adjudicator"),
("aj.edit", "Edited adjudicator"),
("aj.note", "Set adjudicator note"),
("aa.auto", "Auto-allocated adjudicators"),
("aa.save", "Saved adjudicator allocation"),
("av.aj.save", "Edited adjudicators availability"),
("av.save", "Edited availability"),
("av.tm.save", "Edited teams availability"),
("av.ve.save", "Edited room availability"),
("ba.ckin", "Checked in ballot set"),
("ba.conf", "Confirmed ballot set"),
("ba.crea", "Created ballot set"),
("ba.disc", "Discarded ballot set"),
("ba.edit", "Edited ballot set"),
("ba.subm", "Submitted ballot set from the public form"),
("br.ca.edit", "Edited break categories"),
("br.del", "Deleted team break for category"),
("br.rm.edit", "Edited breaking team remarks"),
("br.el.edit", "Edited break eligibility"),
("br.gene", "Generated the team break for all categories"),
("br.gen1", "Generated the team break for one category"),
(
"br.upda",
"Edited breaking team remarks and updated all team breaks",
),
(
"br.upd1",
"Edited breaking team remarks and updated this team break",
),
("ch.aj.gene", "Generated check in identifiers for adjudicators"),
("ch.sp.gene", "Generated check in identifiers for speakers"),
("ch.ve.gene", "Generated check in identifiers for rooms"),
("ac.aa.edit", "Edited adjudicator-adjudicator conflicts"),
("ac.ai.edit", "Edited adjudicator-institution conflicts"),
("ac.at.edit", "Edited adjudicator-team conflicts"),
("ac.ti.edit", "Edited team-institution conflicts"),
("db.crea", "Created debate"),
("db.edit", "Edited debate"),
("db.im.auto", "Auto-prioritized debate importance"),
("db.im.edit", "Edited debate importance"),
("dv.save", "Saved divisions"),
("dr.conf", "Confirmed draw"),
("dr.crea", "Created draw"),
("dr.rege", "Regenerated draw"),
("dr.rele", "Released draw"),
("dr.unre", "Unreleased draw"),
("fq.crea", "Created feedback question"),
("fq.edit", "Edited feedback question"),
("fb.save", "Saved feedback"),
("fb.subm", "Submitted feedback from the public form"),
("in.crea", "Created institution"),
("in.edit", "Edited institution"),
("mu.save", "Saved a matchup manual edit"),
("mo.edit", "Added/edited motion"),
("mo.rele", "Released motions"),
("mo.unre", "Unreleased motions"),
("op.edit", "Edited tournament options"),
("pp.aj.auto", "Auto-allocated adjudicators to preformed panels"),
("pp.aj.edit", "Edited preformed panel adjudicator"),
("pp.crea", "Created preformed panels"),
("pp.db.auto", "Auto-allocated preformed panels to debates"),
("pp.del", "Deleted preformed panels"),
("pp.im.auto", "Auto-prioritized preformed panels"),
("pp.im.edit", "Edited preformed panel importance"),
("rd.adva", "Advanced the current round to"),
("rd.comp", "Marked round as completed"),
("rd.crea", "Created round"),
("rd.edit", "Edited round"),
("rd.st.set", "Set start time"),
("ms.save", "Saved the sides status of a matchup"),
("si.adju", "Imported adjudicators using the simple importer"),
("si.inst", "Imported institutions using the simple importer"),
("si.team", "Imported teams using the simple importer"),
("si.venu", "Imported rooms using the simple importer"),
("se.ca.edit", "Edited speaker categories"),
("sp.crea", "Created speaker"),
("sp.edit", "Edited speaker"),
("se.edit", "Edited speaker category eligibility"),
("te.crea", "Created team"),
("te.edit", "Edited team"),
("ts.edit", "Edited adjudicator base score"),
("to.crea", "Created tournament"),
("to.edit", "Edited tournament"),
("aj.sc.upda", "Updated adjudicator scores in bulk"),
("ur.inv", "Invited user to the instance"),
("ve.ca.edit", "Edited room categories"),
("ve.ca.crea", "Created room category"),
("ve.co.edit", "Edited room constraints"),
("ve.crea", "Created room"),
("ve.edit", "Edited room"),
("ve.auto", "Auto-allocated rooms"),
("ve.save", "Saved a room manual edit"),
],
max_length=10,
verbose_name="type",
),
),
]
4 changes: 2 additions & 2 deletions tabbycat/actionlog/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ def log_action(self, **kwargs):
log = ActionLogEntry.objects.log(ip_address=ip_address, **action_log_fields)

# Notify the actionlog consumer to broadcast the event
if self.tournament:
if tournament := action_log_fields.get('tournament'):
print('Broadcasting notification of ActionLogEntryConsumer')
group_name = ActionLogEntryConsumer.group_prefix + "_" + self.tournament.slug
group_name = ActionLogEntryConsumer.group_prefix + "_" + tournament.slug
async_to_sync(get_channel_layer().group_send)(group_name, {
"type": "send_json",
"data": log.serialize,
Expand Down
Loading

0 comments on commit dafb8e3

Please sign in to comment.