-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add ability to add and remove speakers from teams in admin interface #2838
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
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| # Generated by Django 5.2.7 on 2026-03-20 23:08 | ||
|
|
||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('actionlog', '0013_actionlogentry_agent_alter_actionlogentry_type'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| 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.del', 'Deleted 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'), ('qu.crea', 'Created question'), ('qu.edit', 'Edited question'), ('inst.reg', 'Registered institution'), ('te.reg', 'Registered team'), ('aj.reg', 'Registered adjudicator'), ('sp.reg', 'Registered speaker'), ('re.conf', 'Confirmed registration'), ('sc.crea', 'Created schedule event'), ('sc.edit', 'Edited schedule event')], max_length=10, verbose_name='type'), | ||
| ), | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from django import forms | ||
| from django.utils.translation import gettext as _ | ||
|
|
||
|
|
||
| class ConfirmSpeakerDeletionForm(forms.Form): | ||
| speaker_name = forms.CharField(label=_("Speaker's full name"), required=True) | ||
|
|
||
| def __init__(self, *args, speaker=None, **kwargs): | ||
| self.speaker = speaker | ||
| super().__init__(*args, **kwargs) | ||
|
|
||
| def clean_speaker_name(self): | ||
| if self.cleaned_data['speaker_name'] != self.speaker.name: | ||
| raise forms.ValidationError( | ||
| _("You must type '%(name)s' exactly to confirm deletion.") % {'name': self.speaker.name}, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| {% extends "base.html" %} | ||
| {% load debate_tags i18n %} | ||
|
|
||
| {% block head-title %}<span class="emoji">🗑</span> {% trans "Confirm Speaker Deletion" %}{% endblock %} | ||
| {% block page-title %}{% trans "Confirm Speaker Deletion" %}{% endblock %} | ||
|
|
||
| {% block page-subnav-sections %} | ||
| <a class="btn btn-outline-primary" href="{% tournamenturl 'participants-team-record' pk=team.pk %}"> | ||
| <i data-feather="chevron-left"></i>{% trans "Back to Team Record" %} | ||
| </a> | ||
| {% endblock %} | ||
|
|
||
| {% block page-alerts %} | ||
|
|
||
| <div class="alert alert-danger"> | ||
| {% blocktrans trimmed with name=speaker.name team=team.short_name %} | ||
| Do you really want to delete <strong>{{ name }}</strong> from {{ team }}? | ||
| This will permanently remove the speaker and <strong>cannot be undone</strong>. | ||
| Any ballot scores attributed to this speaker will also be deleted. | ||
| {% endblocktrans %} | ||
| </div> | ||
|
|
||
| <form method="POST" action=""> | ||
| {% csrf_token %} | ||
| {% include "components/form-main.html" %} | ||
|
|
||
| {% blocktrans trimmed with name=speaker.name asvar title %} | ||
| Yes, delete {{ name }} | ||
| {% endblocktrans %} | ||
| {% include "components/form-submit.html" with type='danger' %} | ||
| </form> | ||
|
|
||
| {% endblock %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| {% extends "base.html" %} | ||
| {% load i18n %} | ||
|
|
||
| {% block head-title %}<span class="emoji">👤</span> {% trans "Add Speaker" %}{% endblock %} | ||
| {% block page-title %}{% trans "Add Speaker" %}{% endblock %} | ||
| {% block page-subtitle %}{% blocktrans trimmed with name=team.short_name %}for {{ name }}{% endblocktrans %}{% endblock %} | ||
|
|
||
| {% block page-subnav-sections %} | ||
| {% include "participants_subnav.html" %} | ||
| {% endblock %} | ||
|
|
||
| {% block content %} | ||
|
|
||
| <form action="" method="POST"> | ||
| {% csrf_token %} | ||
| <div class="card"> | ||
| <div class="list-group list-group-flush"> | ||
| {% include "components/form-main.html" %} | ||
| {% trans "Add Speaker" as save_text %} | ||
| {% include "components/form-submit.html" with title=save_text suburl=team_record_url subtitle=cancel_text %} | ||
| </div> | ||
| </div> | ||
| </form> | ||
|
|
||
| {% endblock content %} |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small things, but we should use Also, for creation, I'm not sure the registration form would be the best, as a lot of fields may be missing, and admins may not want to answer the custom fields.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will do, good catch.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense, I'll swap it out for a plain ModelForm on Speaker instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an idea, but maybe add an "Edit" button to the top of the registration card to send the user to the team's "Edit DB" page?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I'll add that.