Compare commits

...

3 Commits

Author SHA1 Message Date
4d0624324e hide_chat setting is remembered and used by session cookie 2018-09-21 09:30:40 -04:00
708513039a chat pane is hideable 2018-09-20 13:09:24 -04:00
52b6ba01e4 refactor css layout 2018-09-19 15:56:59 -04:00
9 changed files with 275 additions and 241 deletions

View File

@ -4,46 +4,29 @@
<meta charset="utf-8">
<title>{% block title %}{% endblock %} - Titivillus</title>
<link rel="stylesheet" type="text/css" href="{{ static('base.css') }}">
<script type="text/javascript" src="{{ static('base.js') }}"></script>
<script>
function toggleHeaderCookie(state) {
let xhr = new XMLHttpRequest();
xhr.open('POST', '{{ url("set_session:index") }}', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-CSRFToken', '{{ csrf_token }}');
xhr.send('hide_header=' + state);
}
function toggleHeader() {
if (document.getElementById('header').style.display == 'initial') {
document.getElementById('header').style.display = 'none';
document.getElementById('headerHidden').style.display = 'initial';
toggleHeaderCookie('on');
}
else {
document.getElementById('header').style.display = 'initial';
document.getElementById('headerHidden').style.display = 'none';
toggleHeaderCookie('off');
}
}
const set_session_url = '{{ url("set_session:index") }}';
const csrf_token = '{{ csrf_token }}';
</script>
{% block head %}{% endblock %}
</head>
<body>
<div id="globalWrapper">
<ul id="header" class="header" style="{% if request.session.get("hide_header") == True %}display:none;{% else %}display:initial;{% endif %}">
<li><a onclick="toggleHeader();" href="javascript:void(0);"></a></li>
<li><a onclick="toggle_header();" href="javascript:void(0);"></a></li>
<li><a href="{{ url('homepage:index') }}">Home</a></li>
{% block header %}{% endblock %}
</ul>
<ul id="headerHidden" class="header" style="{% if request.session.get("hide_header") == True %}display:initial;{% else %}display:none;{% endif %}">
<li><a onclick="toggleHeader();" href="javascript:void(0);"></a></li>
<li><a onclick="toggle_header();" href="javascript:void(0);"></a></li>
</ul>
{#<br /> <!-- TODO: make this more exact. -->#}
<div id="pageMessages">
<ul class="pageMessages">
<ul id="alerts">
{% for message in get_messages(request) %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
</div>
<div id="content">{% block content %}{% endblock %}</div>
</div>
</body>
</html>

View File

@ -2,6 +2,9 @@
{% block title %}{{ quest.title }}{% endblock %}
{% block head %}
<link rel="stylesheet" type="text/css" href="{{ static('quest.css') }}">
{% if request.user == quest.owner %}
<link rel="stylesheet" type="text/css" href="{{ static('questQM.css') }}">
{% endif %}
<script>
const quest_id = {{ quest.id }};
const page_num = {{ page_num }};
@ -24,10 +27,10 @@
{% endfor %}
</select>
</li>
<li id="toggleChat"><a onclick="toggle_chat()" href="javascript:void(0);">{% if request.session.get("hide_chat") == True %}←{% else %}→{% endif %}</a></li>
{% endblock %}
{% block content %}
<div id="questContainer">
<div id="questPane">
<div id="questPane" style="width:{% if request.session.get("hide_chat") == True %}100%{% else %}70%{% endif %};">
<center><h1>{{ quest.title }}</h1></center>
<div id="questPosts">
{% for post in posts %}
@ -87,7 +90,7 @@
{% endif %}
{% endif %}
</div>
</div><br />
</div><br>
{% endfor %}
</div>
{% if request.user == quest.owner %}
@ -138,9 +141,7 @@
</div>
{% endif %}
</div>
<br />
<br />
<div id="chatPane">
<div id="chatPane" style="display:{% if request.session.get("hide_chat") == True %}none{% else %}flex{% endif %};">
<h1>Chat</h1>
<div id="chatWindow">
{% autoescape false %}
@ -159,6 +160,5 @@
</div>
<div id="messageTextDiv"><textarea id="messageTextArea"></textarea></div>
</div>
</div>
<div id="preview" style="display:none;"></div>
{% endblock %}

View File

@ -8,14 +8,12 @@ h3 {
margin-bottom: 0.5em;
}
#questContainer {
display: flex;
overflow: auto;
}
#questPane {
float: left;
box-sizing: border-box;
padding-left: 5%;
width: 65%;
padding-right: 5%;
width: 70%;
}
.questPost {
@ -33,60 +31,6 @@ h3 {
width: 100%;
}
#QMPostPane {
display: flex;
}
.editPostText {
width: 100%;
box-sizing: border-box;
}
#QMPostTabs {
display: inline-block;
list-style-type: none;
padding: 0;
margin: 0;
background-color: #f1f1f1;
height: 100%;
}
.QMPostTab {
display: block;
padding: 8px 16px;
text-decoration: none;
}
.QMPostTab:hover {
background-color: #555;
color: white;
}
.QMPostTab.active {
background-color: #555;
color: white;
}
.QMPostTabContent {
flex: auto;
padding: 0px 12px;
border: 1px solid #ccc;
border-left: none;
width: 100px;
}
#postTextArea {
max-width: 100%;
}
.tooltip {
border-bottom: 1px dotted black;
}
#QMPollPostForm a {
text-decoration: none;
}
.pollOption {
width: 100%;
margin: 0.1em;
@ -153,7 +97,7 @@ h3 {
}
#chatPane {
height: 100%;
height: calc(100% - var(--header-height));
width: 30%;
right: 0;
position: fixed;
@ -165,7 +109,7 @@ h3 {
border: 1px solid #ccc;
padding: 0.25em;
overflow: auto;
flex: 1;
flex: auto;
}
.messageContent {
@ -184,16 +128,15 @@ h3 {
}
#messageTextDiv {
padding-bottom: 1em;
width: 100%;
display: flex;
flex-direction: column;
padding-bottom: 0.25em;
}
#messageTextArea {
resize: none;
box-sizing: border-box;
height: 5em;
width: 100%;
padding: 0;
}
#preview {

View File

@ -247,3 +247,17 @@ function open_post(post_id) {
}
}
}
function toggle_chat() {
if (document.getElementById('chatPane').style.display == 'flex') {
document.getElementById('chatPane').style.display = 'none';
document.getElementById('questPane').style.width = '100%';
document.getElementById('toggleChat').firstChild.innerText = '←';
toggle_cookie('hide_chat', 'on');
}
else {
document.getElementById('chatPane').style.display = 'flex';
document.getElementById('questPane').style.width = '70%';
document.getElementById('toggleChat').firstChild.innerText = '→';
toggle_cookie('hide_chat', 'off');
}
}

53
quest/static/questQM.css Normal file
View File

@ -0,0 +1,53 @@
#QMPostPane {
display: flex;
}
.editPostText {
width: 100%;
box-sizing: border-box;
}
#QMPostTabs {
display: inline-block;
list-style-type: none;
padding: 0;
margin: 0;
background-color: #f1f1f1;
height: 100%;
}
.QMPostTab {
display: block;
padding: 8px 16px;
text-decoration: none;
}
.QMPostTab:hover {
background-color: #555;
color: white;
}
.QMPostTab.active {
background-color: #555;
color: white;
}
.QMPostTabContent {
flex: auto;
padding: 0px 12px;
border: 1px solid #ccc;
border-left: none;
width: 100px;
}
#postTextArea {
max-width: 100%;
}
.tooltip {
border-bottom: 1px dotted black;
}
#QMPollPostForm a {
text-decoration: none;
}

View File

@ -8,8 +8,12 @@ def index(request):
"""
A simple API endpoint for setting certain values in the users session.
"""
if request.POST.get('hide_header') == 'on':
request.session['hide_header'] = True
elif request.POST.get('hide_header') == 'off':
request.session['hide_header'] = False
for key, value in request.POST.items():
if key not in ['hide_header', 'hide_chat']:
continue
if value == 'on':
request.session[key] = True
elif value == 'off':
request.session[key] = False
return HttpResponse('true')

View File

@ -1,11 +1,25 @@
:root {
--header-height: 1.25em;
}
body {
margin: 0;
}
#globalWrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.header {
position: fixed;
position: sticky;
top: 0;
left: 0;
width: 100%;
list-style-type: none;
margin: 0;
padding: 0;
width: 100%;
height: var(--header-height);
list-style-type: none;
background-color: #dddddd;
}
@ -18,5 +32,14 @@
}
#headerHidden {
width: auto;
width: 1em;
}
#alerts {
margin: 0;
}
#content {
flex: auto;
overflow: auto;
}

19
static/base.js Normal file
View File

@ -0,0 +1,19 @@
function toggle_cookie(cookie, state) {
let xhr = new XMLHttpRequest();
xhr.open('POST', set_session_url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-CSRFToken', csrf_token);
xhr.send(cookie + '=' + state);
}
function toggle_header() {
if (document.getElementById('header').style.display == 'initial') {
document.getElementById('header').style.display = 'none';
document.getElementById('headerHidden').style.display = 'initial';
toggle_cookie('hide_header', 'on');
}
else {
document.getElementById('header').style.display = 'initial';
document.getElementById('headerHidden').style.display = 'none';
toggle_cookie('hide_header', 'off');
}
}

5
todo
View File

@ -19,14 +19,9 @@ Improvements:
More options for text posts (lists and so on)
More rigorous input checking in events.py
New post displays chat message
Record email on signup
Change urls
Poll vote highlights entire option
Poll vote doesn't disappear checkbox
Total voters per poll
Chat archives
Only last 100 (50?) chat messages are loaded on page load
Adjust quote preview postioning
Port from old code:
Images