Basic promotions logic

This commit is contained in:
Yingtong Li 2018-12-07 15:53:46 +11:00
parent 4339f568f9
commit f0e53b56a5
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
20 changed files with 2105 additions and 19 deletions

View File

@ -2,3 +2,5 @@ Django==2.0.6
Jinja2==2.10
social-auth-app-django==2.1.0
jsonfield==2.0.2
Pillow==3.5.0
Markdown==3.0.1

View File

@ -1,25 +1,27 @@
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import markdown
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from django.utils import timezone
from jinja2 import Environment
from jinja2 import Environment, Markup
import importlib
@ -31,4 +33,7 @@ def environment(**options):
'static': staticfiles_storage.url,
'url': reverse,
})
env.filters.update({
'markdown': lambda x: Markup(markdown.markdown(x))
})
return env

View File

@ -21,5 +21,6 @@ urlpatterns = [
path('admin/', admin.site.urls),
path('auth/', include('social_django.urls', namespace='social')),
path('treasury/', include('sstreasury.urls')),
path('promotions/', include('sspromotions.urls')),
path('', include('ssmain.urls')),
]

View File

@ -70,7 +70,8 @@
<div class="ui large secondary inverted pointing menu">
</a>
<a class="{% if request.resolver_match.func.__module__.startswith('ssmain.') %}active {% endif %}item" href="{{ url('index') }}">Society Self-Service</a>
<a class="{% if request.resolver_match.func.__module__.startswith('sstreasury.') %}active {% endif %}item" href="{{ url('treasury') }}">Treasury Connect</a>
<a class="{% if request.resolver_match.func.__module__.startswith('sstreasury.') %}active {% endif %}item" href="{{ url('treasury') }}">Treasury</a>
<a class="{% if request.resolver_match.func.__module__.startswith('sspromotions.') %}active {% endif %}item" href="{{ url('promotions') }}">Promotions</a>
<div class="right menu">
{% if request.user.is_authenticated %}
<div class="item"><i class="user circle icon"></i>{{ request.user.first_name }} {{ request.user.last_name }}</div>

View File

@ -53,5 +53,15 @@
</div>
</a>
#}
<a class="ui card" href="{{ url('promotions') }}">
<div class="content">
<div class="header">Promotions Hub</div>
<div class="description">Create bulletin items. Add calendar events.</div>
</div>
<div class="ui bottom attached primary button">
<i class="chevron right icon" style="margin: 0 .42857143em 0 -.21428571em;"></i>
Enter
</div>
</a>
</div>
{% endblock %}

View File

@ -1,3 +1,24 @@
from django.db import models
# Create your models here.
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from django.contrib.auth.models import User
from django.db import models
from jsonfield import JSONField
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
delegates = JSONField(default=[])

0
sspromotions/__init__.py Normal file
View File

21
sspromotions/admin.py Normal file
View File

@ -0,0 +1,21 @@
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from django.contrib import admin
from . import models
admin.site.register(models.Group)

5
sspromotions/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class SspromotionsConfig(AppConfig):
name = 'sspromotions'

View File

@ -0,0 +1,49 @@
{% extends 'ssmain/base.html' %}
{#
Society Self-Service
Copyright © 2018 Yingtong Li (RunasSudo)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block content %}
<div class="ui grid">
{# side menu #}
<div class="four wide column">
<div class="ui vertical fluid menu">
<div class="item">
Bulletin
<div class="menu">
<a class="{% if request.resolver_match.url_name == 'bulletin_list' %}active {% endif %}item" href="{{ url('bulletin_list') }}">Your bulletin items</a>
<a class="{% if request.resolver_match.url_name == 'bulletin_new' %}active {% endif %}item" href="{{ url('bulletin_new') }}">Create new bulletin item</a>
<a class="{% if request.resolver_match.url_name == 'bulletin_preview' %}active {% endif %}item" href="{{ url('bulletin_preview') }}">Preview the bulletin</a>
</div>
</div>
<div class="item">
Calendar
<div class="menu">
<a class="item">Your calendar events</a>
<a class="item">Create new calendar event</a>
<a class="item">Preview the calendar</a>
</div>
</div>
</div>
</div>
<div class="twelve wide column">
{% block maincontent %}{% endblock %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,121 @@
{% extends 'sspromotions/base.html' %}
{#
Society Self-Service
Copyright © 2018 Yingtong Li (RunasSudo)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}{% if request.resolver_match.url_name == 'bulletin_new' %}New{% else %}Edit{% endif %} bulletin item{% endblock %}
{% block maincontent %}
<h1>{% if request.resolver_match.url_name == 'bulletin_new' %}New{% else %}Edit{% endif %} bulletin item</h1>
<form class="ui form" method="POST">
<div class="ui disabled inline grid field">
<label class="three wide column">ID</label>
<input class="eleven wide column" type="text" name="id" value="{{ item.id if item.id != None else '' }}">
</div>
<div class="ui required inline grid field">
<label class="three wide column">Title</label>
<input class="eleven wide column" type="text" name="title" value="{{ item.title }}">
</div>
<div class="ui required inline grid field">
<label class="three wide column">Date</label>
<div class="ten wide column">
<div class="ui calendar" id="cal_date">
<div class="ui input left icon grid">
<i class="calendar icon" style="z-index: 999;"></i>
<input class="twelve wide column" type="text" name="date" value="{{ item.date or '' }}">
</div>
</div>
<div style="margin-top: 1.5em;">The item will be scheduled for the first bulletin post on or after this date.</div>
</div>
</div>
<div class="ui required inline grid field">
<label class="three wide column">Group</label>
<select class="ui dropdown eleven wide column" name="group">
<option value="">Group</option>
{% for group in groups %}
<option value="{{ group.id }}">{{ group.name }}</option>
{% endfor %}
</select>
</div>
<div class="ui divider"></div>
<div class="ui required inline grid field">
<label class="three wide column">Content</label>
<textarea class="eleven wide column" rows="6" name="content">{{ item.content }}</textarea>
</div>
<div class="ui inline grid field">
<label class="three wide column">Link</label>
<input class="eleven wide column" type="text" name="link" value="{{ item.link or '' }}">
</div>
<div class="ui inline grid field">
<label class="three wide column">Image</label>
<input class="eleven wide column" type="file" name="image" value="{{ item.image or '' }}">
</div>
<div class="ui divider"></div>
<div class="ui inline grid field">
<label class="three wide column">Also limit to</label>
<div class="eleven wide column">
{% for group in all_groups %}
<div class="field" style="display: inline; margin-right: 1em;">
<div class="ui checkbox">
<input type="checkbox" name="also_limit_{{ group.id }}"{% if group.id in item.also_limit %} checked{% endif %}>
<label>{{ group.name }}</label>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="ui divider"></div>
<div class="ui error message"></div>
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
<input class="ui primary button" type="submit" name='submit' value="Save">
<input class="ui button" type="submit" name='submit' value="Save and continue editing">
</form>
{% endblock %}
{% block head %}
{{ super() }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui-calendar@0.0.8/dist/calendar.min.css" integrity="sha256-KCHiPtYk/vfF5/6lDXpz5r5FuIYchVdai0fepwGft80=" crossorigin="anonymous">
{% endblock %}
{% block script %}
{{ super() }}
<script src="https://cdn.jsdelivr.net/npm/semantic-ui-calendar@0.0.8/dist/calendar.min.js" integrity="sha256-Pnz4CK94A8tUiYWCfg/Ko25YZrHqOKeMS4JDXVTcVA0=" crossorigin="anonymous"></script>
<script>
function leftpad(n) {
if (n < 10)
return '0' + n;
return '' + n;
}
$('#cal_date').calendar({
type: 'date',
formatter: {
date: function(date, settings) {
return date.getFullYear() + '-' + leftpad(date.getMonth() + 1) + '-' + leftpad(date.getDate());
}
}
});
$('.ui.dropdown').dropdown();
{% if item.group %}
$('.ui.dropdown').dropdown('set selected', {{ item.group.id }});
{% endif %}
</script>
{% endblock script %}

View File

@ -0,0 +1,75 @@
{% extends 'sspromotions/base.html' %}
{#
Society Self-Service
Copyright © 2018 Yingtong Li (RunasSudo)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Your bulletin items{% endblock %}
{% macro listitems(items) %}
<table class="ui selectable celled table">
<thead>
<tr>
<th class="four wide">Title</th>
<th class="ten wide">Content</th>
<th class="two wide">Actions</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td class="selectable"><a href="{{ url('bulletin_edit', kwargs={'id': item.id}) }}">{{ item.title }}</a></td>
<td class="selectable"><a href="{{ url('bulletin_edit', kwargs={'id': item.id}) }}">{{ item.content }}</a></td>
<td class="selectable">
<a href="{{ url('bulletin_edit', kwargs={'id': item.id}) }}" class="ui tiny primary icon button" style="margin: 0.8em 0 0.8em 0.8em;"><i class="edit icon"></i></a>
<a href="{{ url('bulletin_delete', kwargs={'id': item.id}) }}" onclick="return confirm('Are you sure you want to delete this bulletin item?');" class="ui tiny red icon button" style="margin: 0.8em 0 0.8em 0.8em;"><i class="trash icon"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endmacro %}
{% block maincontent %}
<h1>Your bulletin items</h1>
{% if not items_past and not items_upcoming and not items_future %}
<p>You have no bulletin items to view. To create a bulletin item, click <a href="{{ url('bulletin_new') }}">Create new bulletin item</a>.</p>
{% endif %}
{% if items_upcoming %}
<h2>Upcoming bulletin items (this week)</h2>
{{ listitems(items_upcoming) }}
{% endif %}
{% if items_future %}
<h2>Future bulletin items</h2>
{{ listitems(items_future) }}
{% endif %}
{% if items_past %}
<h2>Past bulletin items</h2>
{{ listitems(items_past) }}
{% endif %}
{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
{% extends 'sspromotions/email/base.html' %}
{#
Society Self-Service
Copyright © 2018 Yingtong Li (RunasSudo)
Design by SendWithUs (Apache 2.0 licence)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block content %}
<table class="row masthead"><tbody><tr> <!-- Masthead -->
<th class="small-12 large-12 columns first last" style="padding: 0;">
<table>
<tr>
<th>
<center data-parsed="">
<img src="http://placehold.it/1280x720" valign="bottom" alt="Calendar" align="center" class="text-center">
</center>
</th>
<th class="expander"></th>
</tr>
</table>
</th>
</tr></tbody></table>
{% for group in groups %}
{% if not loop.first %}
{{ gap }}
{% endif %}
<table class="row heading"><tbody><tr> <!-- Section heading -->
<th class="small-12 large-12 columns first last">
<table>
<tr>
<th>
<h2 class="text-center">{{ group.name }}</h2>
<th class="expander"></th>
</th>
</tr>
</table>
</th>
</tr></tbody></table>
{{ gap }}
{% for item in group.bulletinitem_set.all() %}
<table class="row"><tbody><tr> <!-- Main Digest content -->
{% if item.image %}
<th class="small-12 large-3 columns first">
<table>
<tr>
<th>
<a href="#"><img src="{{ item.image }}" alt="{{ item.title }}"></a>
</th>
</tr>
</table>
</th>
{% endif %}
<th class="small-12 large-{% if item.image %}8{% else %}12 first{% endif %} columns last">
<table>
<tr>
<th>
<b><h5>{{ item.title }}</h5></b>
<p>{{ item.content | markdown }}</p>
{% if item.link %}<p><a href="{{ item.link }}">Click Here &#x203A;</a></p>{% endif %}
</th>
</tr>
</table>
</th>
</tr></tbody></table>
{% if not loop.last %}<hr>{% endif %}
{% endfor %}
{% endfor %}
{% if more %}
<table class="row heading"><tbody><tr>
<th class="small-12 large-12 columns first last">
<table>
<tr>
<th>
<p>More from MUMUS:</p>
</th>
</tr>
</table>
</th>
</tr></tbody></table>
{{ gap }}
<table class="row"><tbody><tr> <!-- Digest Content 2 columns-->
{% for item in more %}
<th class="small-12 large-4 columns{% if loop.first %} first{% endif %}{% if loop.last %} last{% endif %}">
<table>
<tr>
<th>
{% if item.image %}{% if item.link %}<a href="{{ item.link }}">{% endif %}<img src="{{ item.image }}" alt="{{ item.title }}">{% if item.link %}</a>{% endif %}<br>{% endif %}
<b><h5>{{ item.title }}</h5></b>
<p>{{ item.content }}</p>
{% if item.link %}<p><a href="{{ item.link }}">Click Here &#x203A;</a></p>{% endif %}
</th>
</tr>
</table>
</th>
{% endfor %}
</table>
{% endif %}
{% endblock content %}

View File

@ -0,0 +1,25 @@
{% extends 'sspromotions/base.html' %}
{#
Society Self-Service
Copyright © 2018 Yingtong Li (RunasSudo)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
#}
{% block title %}Promotions{% endblock %}
{% block maincontent %}
<p>Welcome to the Promotions Hub. Select an option from the side menu to begin.</p>
{% endblock %}

53
sspromotions/models.py Normal file
View File

@ -0,0 +1,53 @@
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from django.contrib.auth.models import User
from django.db import models
from jsonfield import JSONField
class Group(models.Model):
name = models.CharField(max_length=100)
subscribable = models.BooleanField()
order = models.IntegerField(null=True, blank=True)
managers = JSONField(default=[])
def __str__(self):
return self.name
def can_user_access(self, user):
if user.is_superuser:
return True
if user.email in self.managers:
return True
for email in self.managers:
manager = User.objects.get(email=email)
if user.email in manager.delegates:
return True
return False
class Meta:
ordering = ['order', 'id']
class BulletinItem(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
also_limit = JSONField(default=[])
title = models.CharField(max_length=100)
link = models.CharField(max_length=100, null=True)
image = models.ImageField(upload_to='promo_uploads/%Y/%m/%d/', null=True)
content = models.TextField()
date = models.DateField()

3
sspromotions/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

28
sspromotions/urls.py Normal file
View File

@ -0,0 +1,28 @@
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from django.urls import path
from . import views
urlpatterns = [
path('bulletin/', views.bulletin_list, name='bulletin_list'),
path('bulletin/new/', views.bulletin_new, name='bulletin_new'),
path('bulletin/edit/<int:id>', views.bulletin_edit, name='bulletin_edit'),
path('bulletin/delete/<int:id>', views.bulletin_delete, name='bulletin_delete'),
path('bulletin/preview/', views.bulletin_preview, name='bulletin_preview'),
path('', views.index, name='promotions'),
]

122
sspromotions/views.py Normal file
View File

@ -0,0 +1,122 @@
# Society Self-Service
# Copyright © 2018 Yingtong Li (RunasSudo)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.utils import timezone
from . import models
@login_required
def index(request):
return render(request, 'sspromotions/index.html')
@login_required
def bulletin_list(request):
items_past = []
items_upcoming = []
items_future = []
for item in models.BulletinItem.objects.all():
if not item.group.can_user_access(request.user):
continue
# TODO
items_upcoming.append(item)
return render(request, 'sspromotions/bulletin_list.html', {
'items_past': items_past,
'items_upcoming': items_upcoming,
'items_future': items_future
})
@login_required
def bulletin_preview(request):
return render(request, 'sspromotions/email/bulletin.html', {
'groups': [group for group in models.Group.objects.all() if group.bulletinitem_set.count() > 0],
'more': []
})
@login_required
def bulletin_new(request):
if request.method == 'POST':
item = models.BulletinItem()
item.group = models.Group.objects.get(id=int(request.POST['group']))
if not item.group.can_user_access(request.user):
return HttpResponse('Unauthorized', status=401)
item.title = request.POST['title']
item.date = request.POST['date']
item.content = request.POST['content']
item.link = request.POST['link']
if request.FILES:
item.image = request.FILES['image']
item.also_limit = [int(k[11:]) for k, v in request.POST.items() if k.startswith('also_limit_') and v]
item.save()
if request.POST['submit'] == 'Save':
return redirect(reverse('bulletin_list'))
else:
return redirect(reverse('bulletin_edit', kwargs={'id': item.id}))
else:
item = models.BulletinItem()
item.date = timezone.now()
return render(request, 'sspromotions/bulletin_edit.html', {
'item': item,
'groups': [group for group in models.Group.objects.all() if group.can_user_access(request.user)],
'all_groups': models.Group.objects.all()
})
@login_required
def bulletin_edit(request, id):
if request.method == 'POST':
item = models.BulletinItem.objects.get(id=id)
item.group = models.Group.objects.get(id=int(request.POST['group']))
if not item.group.can_user_access(request.user):
return HttpResponse('Unauthorized', status=401)
item.title = request.POST['title']
item.date = request.POST['date']
item.content = request.POST['content']
item.link = request.POST['link']
if request.FILES:
item.image = request.FILES['image']
item.also_limit = [int(k[11:]) for k, v in request.POST.items() if k.startswith('also_limit_') and v]
item.save()
if request.POST['submit'] == 'Save':
return redirect(reverse('bulletin_list'))
else:
return redirect(reverse('bulletin_edit', kwargs={'id': item.id}))
else:
item = models.BulletinItem.objects.get(id=id)
if not item.group.can_user_access(request.user):
return HttpResponse('Unauthorized', status=401)
return render(request, 'sspromotions/bulletin_edit.html', {
'item': item,
'groups': [group for group in models.Group.objects.all() if group.can_user_access(request.user)],
'all_groups': models.Group.objects.all()
})
@login_required
def bulletin_delete(request, id):
item = models.BulletinItem.objects.get(id=id)
if not item.group.can_user_access(request.user):
return HttpResponse('Unauthorized', status=401)
item.delete()
return redirect(reverse('bulletin_list'))

View File

@ -114,7 +114,7 @@ def budget_new(request):
revision.time = timezone.now()
revision = revision_from_form(budget, revision, request.POST)
if request.POST['submit'] == 'Submit':
if request.POST['submit'] == 'Save':
return redirect(reverse('budget_view', kwargs={'id': budget.id}))
else:
return redirect(reverse('budget_edit', kwargs={'id': budget.id}))
@ -143,7 +143,7 @@ def budget_edit(request, id):
revision.time = timezone.now()
revision = revision_from_form(budget, revision, request.POST)
if request.POST['submit'] == 'Submit':
if request.POST['submit'] == 'Save':
return redirect(reverse('budget_view', kwargs={'id': budget.id}))
else:
return redirect(reverse('budget_edit', kwargs={'id': budget.id}))