diff --git a/puzzles/lacrosse_town_crossword.py b/puzzles/lacrosse_town_crossword.py new file mode 100644 index 0000000..804df2f --- /dev/null +++ b/puzzles/lacrosse_town_crossword.py @@ -0,0 +1,30 @@ +import requests +import json +from django.conf import settings +from puzzles.models import Puzzle, LacrosseTownCrossword + +# returns URL +def create_lacrosse_town_crossword(): + params = { + "type": "new", + } + result = requests.post( + settings.LACROSSE_TOWN_CROSSWORD_DOMAIN + "/api", + data={"params": json.dumps(params)}) + + result = json.loads(result.text) + + if not result["success"]: + raise Exception("crossword api did not return success") + if not result["url"]: + raise Exception("crossword api did not return a URL") + + return result["url"] + +def add_crossword_for_puzzle(puzzle): + url = create_lacrosse_town_crossword() + + LacrosseTownCrossword.objects.create( + puzzle=puzzle, + url=url, + is_deleted=False) diff --git a/puzzles/management/commands/initial_config.py b/puzzles/management/commands/initial_config.py index aa1fc64..6f8a869 100644 --- a/puzzles/management/commands/initial_config.py +++ b/puzzles/management/commands/initial_config.py @@ -45,7 +45,7 @@ def handle(self, *args, **options): testing_taglist.tags = [Tag.objects.get(name='testing')] testing_taglist.save() - default_locations = ['Cambridge', 'remote'] + default_locations = ['Cambridge', 'remote', 'unknown'] Location.objects.all().delete() for location_name in default_locations: Location(name=location_name).save() diff --git a/puzzles/models.py b/puzzles/models.py index ee0d421..0a7f0ff 100644 --- a/puzzles/models.py +++ b/puzzles/models.py @@ -166,6 +166,14 @@ class Location(OrderedModel): def __unicode__(self): return self.name +class LacrosseTownCrossword(OrderedModel): + puzzle = models.ForeignKey('Puzzle') + url = models.CharField(max_length=200) + is_deleted = models.BooleanField() + + def __unicode__(self): + return self.url + class UserProfile(models.Model): user = models.OneToOneField(User) diff --git a/puzzles/static/css/base.css b/puzzles/static/css/base.css index ece9888..3b81ff3 100644 --- a/puzzles/static/css/base.css +++ b/puzzles/static/css/base.css @@ -441,6 +441,29 @@ div#answers a#callinanswer:hover { padding-left: 10px; } +.puzzle-blurb div#add_crossword { + display: inline-block; + padding-left: 10px; +} + +#delete_crossword_form { + padding-left: 200px; +} + +.delete_crossword_form_hidden { + display: none; +} + +input[type=button].collaboration_link_button_sel { + background-color: #66ffff; + border-color: #66ffff; + box-shadow: inset; +} + +input[type=button].collaboration_link_button { + cursor: pointer; +} + span.puzzle-title { font-weight: bold; } diff --git a/puzzles/views.py b/puzzles/views.py index abdf3e3..0ae9407 100644 --- a/puzzles/views.py +++ b/puzzles/views.py @@ -12,10 +12,11 @@ from django.db import IntegrityError from django import forms -from models import Status, Priority, Tag, QueuedAnswer, PuzzleWrongAnswer, Puzzle, TagList, UploadedFile, Location, Config +from models import Status, Priority, Tag, QueuedAnswer, PuzzleWrongAnswer, Puzzle, TagList, UploadedFile, Location, Config, LacrosseTownCrossword from forms import UploadForm, AnswerForm from django.contrib.auth.models import User from django.conf import settings +from lacrosse_town_crossword import add_crossword_for_puzzle def get_motd(): try: @@ -81,6 +82,22 @@ def puzzle_info(request, puzzle_id): queued_answers = puzzle.queuedanswer_set.order_by('-id') wrong_answers = puzzle.puzzlewronganswer_set.order_by('-id') uploaded_files = puzzle.uploadedfile_set.order_by('id') + + crosswords = LacrosseTownCrossword.objects.all().filter(puzzle=puzzle, is_deleted=False) + collaboration_links = ([ + {"selected": False, "text": "Spreadsheet", + "url": reverse("puzzles.views.puzzle_spreadsheet", args=[puzzle_id]), + "id": ""}, + ] + + [ {"selected": False, "text": "Crossword Sheet", "url": crossword.url, + "id": str(crossword.id)} + for crossword in crosswords ]) + if len(collaboration_links) > 1: + # by default, select the first crossword, if there is at least one + collaboration_links[1]["selected"] = True + else: + collaboration_links[0]["selected"] = True + return render_to_response("puzzles/puzzle-info.html", puzzle_context(request, { 'puzzle': puzzle, 'statuses': statuses, @@ -91,7 +108,9 @@ def puzzle_info(request, puzzle_id): 'queued_answers': queued_answers, 'wrong_answers': wrong_answers, 'uploaded_files': uploaded_files, - 'refresh': 30 + 'refresh': 30, + 'collaboration_links': collaboration_links, + 'hide_collaboration_links': len(collaboration_links) == 1, })) @login_required @@ -137,6 +156,25 @@ def puzzle_add_solver(request, puzzle_id): puzzle.save() return redirect(request.POST['continue']) +@login_required +def puzzle_add_crossword(request, puzzle_id): + puzzle = Puzzle.objects.get(id=puzzle_id) + add_crossword_for_puzzle(puzzle) + return redirect(request.POST['continue']) + +@login_required +def puzzle_delete_crossword(request, puzzle_id): + # soft delete: just set the `is_deleted` field to True + crossword_id = int(request.POST['crossword_id']) + crossword = LacrosseTownCrossword.objects.get(id=crossword_id) + if crossword.puzzle.id != int(puzzle_id): + raise Exception( + "puzzle id did not match: crossword_id=%d, puzzle_id=%d, puzzle_id from request=%s" % + (crossword_id, crossword.puzzle.id, puzzle_id)) + crossword.is_deleted = True + crossword.save() + return redirect(request.POST['continue']) + def handle_puzzle_upload(puzzle, name, file): if file.name == '' or file.name[0] == '.' or '/' in file.name: raise ValueError diff --git a/solving/local_settings_template.py b/solving/local_settings_template.py index 02e8e01..5d04593 100644 --- a/solving/local_settings_template.py +++ b/solving/local_settings_template.py @@ -46,3 +46,5 @@ import random ZULIP_HOSTNAME_BALANCING = lambda: 'https://e%d.%s' % ( random.randint(1, 100), ZULIP_SERVER_HOSTNAME) + +LACROSSE_TOWN_CROSSWORD_DOMAIN = 'http://enigmatic-mountain-8851.herokuapp.com' diff --git a/solving/urls.py b/solving/urls.py index a8b7a9b..919c3e7 100644 --- a/solving/urls.py +++ b/solving/urls.py @@ -18,6 +18,8 @@ url(r'^puzzle/set_priority/(\d+)/$', 'puzzles.views.puzzle_set_priority'), url(r'^puzzle/remove_solver/(\d+)/$', 'puzzles.views.puzzle_remove_solver'), url(r'^puzzle/add_solver/(\d+)/$', 'puzzles.views.puzzle_add_solver'), + url(r'^puzzle/add_crossword/(\d+)/$', 'puzzles.views.puzzle_add_crossword'), + url(r'^puzzle/delete_crossword/(\d+)/$', 'puzzles.views.puzzle_delete_crossword'), url(r'^puzzle/upload/(\d+)/$', 'puzzles.views.puzzle_upload'), url(r'^puzzle/call_in_answer/(\d+)/$', 'puzzles.views.puzzle_call_in_answer'), diff --git a/templates/puzzles/puzzle-frames.html b/templates/puzzles/puzzle-frames.html index 3638204..70aa5f8 100644 --- a/templates/puzzles/puzzle-frames.html +++ b/templates/puzzles/puzzle-frames.html @@ -3,11 +3,16 @@