added appendices, refactored pages

This commit is contained in:
iou1name 2018-09-25 11:58:07 -04:00
parent cb487f231e
commit ba28cb94e1
15 changed files with 108 additions and 112 deletions

View File

@ -4,7 +4,7 @@ Form(s) for the create_quest page.
""" """
from django import forms from django import forms
from quest.models import Quest, Post, PageTitle from quest.models import Quest, Post
class QuestForm(forms.ModelForm): class QuestForm(forms.ModelForm):
""" """

View File

@ -6,7 +6,7 @@ from django.contrib import messages
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from .forms import QuestForm, PostForm from .forms import QuestForm, PostForm
from quest.models import Quest, Post, PageTitle from quest.models import Quest, Post, Page
def index(request): def index(request):
""" """
@ -16,18 +16,19 @@ def index(request):
# TODO: clean the post body # TODO: clean the post body
quest = Quest(owner=request.user) quest = Quest(owner=request.user)
quest_form = QuestForm(request.POST, instance=quest) quest_form = QuestForm(request.POST, instance=quest)
post = Post(post_type='text', page_num=1) post = Post(post_type='text')
post_form = PostForm(request.POST, instance=post) post_form = PostForm(request.POST, instance=post)
if all((quest_form.is_valid(), post_form.is_valid())): if all((quest_form.is_valid(), post_form.is_valid())):
quest.save() quest.save()
post.quest = quest page = Page(
post.save()
page = PageTitle(
quest=quest, quest=quest,
page_num=1, page_num=1,
title="Page 1" title="Page 1"
) )
page.save() page.save()
post.quest = quest
post.page = page
post.save()
return redirect('quest:quest', quest_id=quest.id) return redirect('quest:quest', quest_id=quest.id)
else: else:
quest_form = QuestForm() quest_form = QuestForm()

View File

@ -1,3 +1,4 @@
{% set vars = {} %}
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

View File

@ -154,9 +154,10 @@ def text_post(socket, data):
# handle image # handle image
quest = Quest.objects.get(id=socket.quest_id)
p = Post( p = Post(
quest=Quest.objects.get(id=socket.quest_id), quest=quest,
page_num=page_num, page=Page.objects.get(quest=quest, page_num=page_num),
post_type='text', post_type='text',
post_text=post_text) post_text=post_text)
p.save() p.save()
@ -197,9 +198,10 @@ def dice_post(socket, data):
if form['diceChal']: if form['diceChal']:
post_text += " vs DC" + str(form['diceChal']) post_text += " vs DC" + str(form['diceChal'])
quest = Quest.objects.get(id=socket.quest_id)
p = Post( p = Post(
quest=Quest.objects.get(id=socket.quest_id), quest=quest,
page_num=page_num, page=Page.objects.get(quest=quest, page_num=page_num),
post_type='dice', post_type='dice',
post_text=post_text post_text=post_text
) )
@ -232,9 +234,10 @@ def poll_post(socket, data):
return # error message? return # error message?
form = form.cleaned_data form = form.cleaned_data
quest=Quest.objects.get(id=socket.quest_id)
p = Post( p = Post(
quest=Quest.objects.get(id=socket.quest_id), quest=quest,
page_num=page_num, page=Page.objects.get(quest=quest, page_num=page_num),
post_type='poll', post_type='poll',
post_text="Poll" post_text="Poll"
) )
@ -412,19 +415,39 @@ def new_page(socket, data):
Called when the QM creates a new page. Called when the QM creates a new page.
""" """
title = data.get('page_title') title = data.get('page_title')
appendix = bool(data.get('appendix'))
quest = Quest.objects.get(id=socket.quest_id) quest = Quest.objects.get(id=socket.quest_id)
p = PageTitle( if appendix:
page = Page.objects.filter(
quest=quest,
appendix=True
).order_by('page_num').last()
if page:
page_num = chr(ord(page.page_num)+1)
else:
page_num = 'a'
else:
page_num = Page.objects.filter(
quest=quest,
appendix=False
).order_by('page_num').last().page_num + 1
p = Page(
quest=quest, quest=quest,
page_num=PageTitle.objects.filter(quest=quest).count() + 1, page_num=page_num,
title=title, title=title,
appendix=appendix,
) )
p.save() p.save()
data = {} data = {}
data['page_num'] = p.page_num data['page_num'] = p.page_num
data['title'] = title data['title'] = title
data['url'] = reverse('quest:quest', args=[socket.quest_id, p.page_num]) if appendix:
data['appendix'] = True
else:
data['appendix'] = False
data['url'] = reverse('quest:quest', args=[socket.quest_id, p.page_num])
socket.send('new_page', data) socket.send('new_page', data)

View File

@ -23,9 +23,18 @@
{% endif %} {% endif %}
<li> <li>
<select onChange="window.location.href=this.value"> <select onChange="window.location.href=this.value">
{% for page in pages %} <optgroup label="Pages">
<option value="{{ url('quest:quest', args=[quest_id, page.page_num]) }}"{% if page.page_num == page_num %} selected="yes"{% endif %}>{{ page.title }}</option> {% for page in pages %}
{% endfor %} <option value="{{ url('quest:quest', args=[quest_id, page.page_num]) }}"{% if page.page_num == page_num %} selected="yes" {% if vars.update({'next_page': loop.nextitem}) %}{% endif %}{% endif %}>{{ page.title }}</option>
{% endfor %}
</optgroup>
{% if appendices %}
<optgroup label="Appendices">
{% for appendix in appendices %}
<option value="{{ url('quest:quest', args=[quest_id, appendix.page_num]) }}"{% if appendix.page_num == page_num %} selected="yes"{% endif %}>{{ appendix.title }}</option>
{% endfor %}
</optgroup>
{% endif %}
</select> </select>
</li> </li>
<li id="toggleChat"><a onclick="toggle_chat()" href="javascript:void(0);">{% if request.session.get("hide_chat") == True %}←{% else %}→{% endif %}</a></li> <li id="toggleChat"><a onclick="toggle_chat()" href="javascript:void(0);">{% if request.session.get("hide_chat") == True %}←{% else %}→{% endif %}</a></li>
@ -143,14 +152,15 @@
<div id="QMPage" class="QMPostTabContent" style="display:none;"> <div id="QMPage" class="QMPostTabContent" style="display:none;">
<form id="QMPageForm" action="javascript:void(0);" onsubmit="form_post('QMPageForm', 'new_page');"> <form id="QMPageForm" action="javascript:void(0);" onsubmit="form_post('QMPageForm', 'new_page');">
New Page: <input type="text" name="page_title" maxlength="200" value="Page {{ pages.count() + 1 }}"><br> New Page: <input type="text" name="page_title" maxlength="200" value="Page {{ pages.count() + 1 }}"><br>
Appendix: <input type="checkbox" name="appendix"><br>
<input type="submit" name="submit" value="Submit"> <input type="submit" name="submit" value="Submit">
</form> </form>
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if page_num != pages.reverse()[0].page_num %} {% if vars['next_page'] %}
<div id="nextPageContainer"> <div id="nextPageContainer">
<input type="button" id="nextPage" value="Next Page: {{ pages[page_num].title }}" onclick="window.location.href='{{ url('quest:quest', args=[quest_id, page_num+1]) }}'"> <input type="button" id="nextPage" value="Next Page: {{ vars['next_page'].title }}" onclick="window.location.href='{{ url('quest:quest', args=[quest_id, vars['next_page'].page_num]) }}'">
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -158,7 +168,7 @@
<h1>Chat</h1> <h1>Chat</h1>
<div id="chatWindow"> <div id="chatWindow">
{% autoescape false %} {% autoescape false %}
{% for message in messages %} {% for message in chat_messages %}
<div id="msg-{{ message.id }}" class="message"> <div id="msg-{{ message.id }}" class="message">
<div class="messageHeader"> <div class="messageHeader">
<span class="messageName">{{ message.user.username or quest.anon_name }}</span> <span class="messageName">{{ message.user.username or quest.anon_name }}</span>

View File

@ -1,4 +1,4 @@
# Generated by Django 2.1.1 on 2018-09-05 17:44 # Generated by Django 2.1.1 on 2018-09-25 13:36
import django.core.validators import django.core.validators
from django.db import migrations, models from django.db import migrations, models
@ -22,11 +22,12 @@ class Migration(migrations.Migration):
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='PageTitle', name='Page',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('page_num', models.IntegerField()), ('page_num', models.CharField(max_length=4)),
('title', models.CharField(max_length=200)), ('title', models.CharField(max_length=200)),
('appendix', models.BooleanField(default=False)),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
@ -47,7 +48,6 @@ class Migration(migrations.Migration):
name='Post', name='Post',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('page_num', models.IntegerField(default=1)),
('post_type', models.CharField(choices=[('text', 'Text'), ('dice', 'Dice'), ('poll', 'Poll')], max_length=4)), ('post_type', models.CharField(choices=[('text', 'Text'), ('dice', 'Dice'), ('poll', 'Poll')], max_length=4)),
('post_text', models.TextField()), ('post_text', models.TextField()),
('timestamp', models.DateTimeField(auto_now=True)), ('timestamp', models.DateTimeField(auto_now=True)),
@ -58,16 +58,17 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)), ('title', models.CharField(max_length=200)),
('anon_name', models.CharField(default='Anonymous', max_length=20)),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='DiceCall', name='DiceCall',
fields=[ fields=[
('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')), ('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')),
('dice_roll', models.CharField(max_length=9)), ('dice_roll', models.CharField(max_length=16)),
('strict', models.BooleanField()), ('strict', models.BooleanField()),
('dice_challenge', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(999), django.core.validators.MinValueValidator(1)])), ('dice_challenge', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65536)])),
('rolls_taken', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(99), django.core.validators.MinValueValidator(1)])), ('rolls_taken', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(256)])),
('open', models.BooleanField()), ('open', models.BooleanField()),
], ],
), ),
@ -75,7 +76,7 @@ class Migration(migrations.Migration):
name='DiceRoll', name='DiceRoll',
fields=[ fields=[
('message', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Message')), ('message', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Message')),
('roll', models.CharField(max_length=9)), ('roll', models.CharField(max_length=16)),
('results', models.TextField()), ('results', models.TextField()),
('total', models.IntegerField()), ('total', models.IntegerField()),
], ],

View File

@ -1,4 +1,4 @@
# Generated by Django 2.1.1 on 2018-09-05 17:44 # Generated by Django 2.1.1 on 2018-09-25 13:36
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
@ -10,8 +10,8 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('quest', '0001_initial'), ('quest', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ operations = [
@ -20,6 +20,11 @@ class Migration(migrations.Migration):
name='owner', name='owner',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
), ),
migrations.AddField(
model_name='post',
name='page',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Page'),
),
migrations.AddField( migrations.AddField(
model_name='post', model_name='post',
name='quest', name='quest',
@ -36,7 +41,7 @@ class Migration(migrations.Migration):
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
), ),
migrations.AddField( migrations.AddField(
model_name='pagetitle', model_name='page',
name='quest', name='quest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'),
), ),

View File

@ -1,18 +0,0 @@
# Generated by Django 2.1.1 on 2018-09-21 16:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('quest', '0002_auto_20180905_1344'),
]
operations = [
migrations.AddField(
model_name='quest',
name='anon_name',
field=models.CharField(default='Anonymous', max_length=20),
),
]

View File

@ -1,34 +0,0 @@
# Generated by Django 2.1.1 on 2018-09-24 13:31
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('quest', '0003_quest_anon_name'),
]
operations = [
migrations.AlterField(
model_name='dicecall',
name='dice_challenge',
field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65536)]),
),
migrations.AlterField(
model_name='dicecall',
name='dice_roll',
field=models.CharField(max_length=16),
),
migrations.AlterField(
model_name='dicecall',
name='rolls_taken',
field=models.IntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(256)]),
),
migrations.AlterField(
model_name='diceroll',
name='roll',
field=models.CharField(max_length=16),
),
]

View File

@ -31,12 +31,25 @@ class Message(models.Model):
message = models.TextField(max_length=512) message = models.TextField(max_length=512)
class Page(models.Model):
"""
Represents the title of a quest page.
"""
quest = models.ForeignKey(Quest, on_delete=models.CASCADE)
page_num = models.CharField(max_length=4)
title = models.CharField(max_length=200)
appendix = models.BooleanField(default=False)
def __str__(self):
return self.title
class Post(models.Model): class Post(models.Model):
""" """
An object for arbituary posts. Contains all post data, type, etc. An object for arbituary posts. Contains all post data, type, etc.
""" """
quest = models.ForeignKey(Quest, on_delete=models.CASCADE) quest = models.ForeignKey(Quest, on_delete=models.CASCADE)
page_num = models.IntegerField(default=1) page = models.ForeignKey(Page, on_delete=models.CASCADE)
POST_TYPES = ( POST_TYPES = (
('text', 'Text'), ('text', 'Text'),
('dice', 'Dice'), ('dice', 'Dice'),
@ -129,15 +142,3 @@ class PollVote(models.Model):
class Meta: class Meta:
unique_together = ('option', 'ip_address') unique_together = ('option', 'ip_address')
class PageTitle(models.Model):
"""
Represents the title of a quest page.
"""
quest = models.ForeignKey(Quest, on_delete=models.CASCADE)
page_num = models.IntegerField()
title = models.CharField(max_length=200)
def __str__(self):
return self.title

View File

@ -156,7 +156,7 @@ socket.events['set_option_box'] = function(data) {
} }
socket.events['new_page'] = function(data) { socket.events['new_page'] = function(data) {
if (page_num != data.page_num-1) { return; } if (page_num != data.page_num-1) { return; }
let html_str = '<div id="nextPageContainer"><input type="button" id="nextPage" value="Next Page: ' + data.title + '" onclick="window.location.href=\'' + SCRIPT_NAME + data.url + '\'"></div>'; let html_str = '<div id="nextPageContainer"><input type="button" id="nextPage" value="Next Page: ' + data.title + '" onclick="window.location.href=\'' + data.url + '\'"></div>';
document.getElementById('questPane').innerHTML = document.getElementById('questPane').innerHTML + html_str; document.getElementById('questPane').innerHTML = document.getElementById('questPane').innerHTML + html_str;
} }

View File

@ -10,7 +10,7 @@ app_name = 'quest'
urlpatterns = [ urlpatterns = [
path('', views.index, name='index'), path('', views.index, name='index'),
path('<int:quest_id>', views.quest, name='quest'), path('<int:quest_id>', views.quest, name='quest'),
path('<int:quest_id>/<int:page_num>', views.quest, name='quest'), path('<int:quest_id>/<page_num>', views.quest, name='quest'),
path('<int:quest_id>/edit_quest', views.edit_quest, name='edit_quest'), path('<int:quest_id>/edit_quest', views.edit_quest, name='edit_quest'),
path('<int:quest_id>/<int:page_num>/edit_quest', views.edit_quest, name='edit_quest'), path('<int:quest_id>/<page_num>/edit_quest', views.edit_quest, name='edit_quest'),
] ]

View File

@ -2,10 +2,11 @@
""" """
Quest and quest accessory views. Quest and quest accessory views.
""" """
from django.shortcuts import render, redirect from django.contrib import messages
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import render, redirect
from .models import Quest, DiceRoll, PollOption, PollVote, PageTitle from .models import Quest, DiceRoll, PollOption, PollVote, Page
from .forms import EditQuestForm from .forms import EditQuestForm
def index(request): def index(request):
@ -15,17 +16,23 @@ def index(request):
return HttpResponse("Hello, world. You're at the quest index.") return HttpResponse("Hello, world. You're at the quest index.")
def quest(request, quest_id, page_num=1): def quest(request, quest_id, page_num='1'):
""" """
Arbituary quest page view. Arbituary quest page view.
""" """
# TODO: 404 quest not found
quest = Quest.objects.get(id=quest_id) quest = Quest.objects.get(id=quest_id)
pages = PageTitle.objects.filter(quest=quest).order_by('page_num') pages = Page.objects.filter(
if page_num > pages.reverse()[0].page_num: quest=quest, appendix=False).order_by('page_num')
page_num = pages.reverse()[0].page_num appendices = Page.objects.filter(
return redirect('quest:quest', quest_id=quest.id, page_num=page_num) quest=quest, appendix=True).order_by('title')
messages = quest.message_set.all() chat_messages = quest.message_set.all()
posts = quest.post_set.filter(page_num=page_num) try:
page = Page.objects.get(quest=quest, page_num=page_num)
except Page.DoesNotExist:
messages.error(request, "Page not found, redirecting you.")
return redirect('quest:quest', quest_id=quest.id, page_num='1')
posts = quest.post_set.filter(page=page)
# TODO: filter by page_num as well # TODO: filter by page_num as well
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest=quest) dice_rolls = DiceRoll.objects.filter(dicecall__post__quest=quest)
poll_options = PollOption.objects.filter(poll__post__quest=quest) poll_options = PollOption.objects.filter(poll__post__quest=quest)

1
todo
View File

@ -1,5 +1,4 @@
New Features: New Features:
Pages/appendixes
Live indicator/countdown Live indicator/countdown
Notifications Notifications
Banner images Banner images

View File

@ -1,4 +1,4 @@
# Generated by Django 2.1.1 on 2018-09-05 17:44 # Generated by Django 2.1.1 on 2018-09-25 13:36
import django.contrib.auth.models import django.contrib.auth.models
import django.core.validators import django.core.validators