get app ready for heroku

This commit is contained in:
2017-02-07 22:26:44 -05:00
parent ae5250e688
commit 537795bf16
36 changed files with 33 additions and 0 deletions

View File

@@ -1,5 +0,0 @@
from django.contrib import admin
from models import Committee
# Register your models here.
admin.site.register(Committee)

View File

@@ -1,7 +0,0 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class CommitteeConfig(AppConfig):
name = 'committee'

View File

@@ -1,11 +0,0 @@
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
class Committee(models.Model):
name = models.CharField(max_length=100, unique=True)
chair = models.ForeignKey(User, null=True)
def __str__(self):
return self.name

View File

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

View File

@@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.

View File

@@ -1,5 +0,0 @@
from django.contrib import admin
from models import Item
# Register your models here.
admin.site.register(Item)

View File

@@ -1,7 +0,0 @@
from __future__ import unicode_literals
from django.apps import AppConfig
class ItemsConfig(AppConfig):
name = 'items'

View File

@@ -1,179 +0,0 @@
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.core.mail import send_mail
from storages.backends.s3boto3 import S3Boto3Storage
from stdimage.models import StdImageField
from datetime import datetime, date
from committee.models import Committee
from django.db import models
class Item(models.Model):
S3 = S3Boto3Storage()
NEW = 'N'
PREAPPROVED = 'C'
PROCESSED = 'P'
REJECTED = 'R'
STATUS = (
(NEW, 'New'),
(PREAPPROVED, 'Committee Approved'),
(PROCESSED, 'Processed'),
(REJECTED, 'Rejected'),
)
desc = models.CharField(max_length=200)
event = models.CharField(max_length=200)
committee = models.ForeignKey(Committee)
details = models.TextField()
cost = models.DecimalField(max_digits=7, decimal_places=2)
date_purchased = models.DateField('date purchased')
image = StdImageField(upload_to='images/%Y/%m/%d',
variations={'thumbnail': (600, 600)}
)
created_by = models.ForeignKey(User, related_name='created_by')
approved_by = models.ManyToManyField(User, blank=True, related_name='approved_by')
date_filed = models.DateTimeField('date filed')
status = models.CharField(max_length=2, choices=STATUS)
def approved(self):
return self.status == Item.PREAPPROVED
def processed(self):
return self.status == Item.PROCESSED
def rejected(self):
return self.status == Item.REJECTED
def new(self):
return self.status == Item.NEW
def statusText(self):
return dict(Item.STATUS)[self.status]
def comName(self):
return self.committee.name
def __str__(self):
return self.committee.name + ": " + self.event + " " + self.desc
def mail_com_chair(self):
send_mail(
'New Reimbursement - ' + self.event + ': ' + self.desc,
'Hey ' + self.committee.chair.first_name + ',\n\n' + \
'Please take a moment to review http://fincom.delt.space/items/' + \
str(self.pk) + ' and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'. If you have any questions, contact the treasurer.\n\n' + \
'Have a fiscally responsible day,\n Fincom Bot',
'fincom.bot@gmail.com',
[self.committee.chair.email],
html_message='Hey ' + self.committee.chair.first_name+',<br><br>' +\
'Please take a moment to review ' + \
'<a href="http://fincom.delt.space/items/' + \
str(self.pk) + '">http://fincom.delt.space/items/' + str(self.pk) +\
'</a> and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'. If you have any questions, contact the treasurer.<br><br>' + \
'Have a fiscally responsible day,<br><br><em>Fincom Bot</em>'
)
def mail_fincom(self):
emails = [s.email for s in User.objects.filter(groups__name='Fincom')]
send_mail(
'Preapproved Reimbursement - ' + self.event + ': ' + self.desc,
'Hey Fincom,\n\n' + \
'Please take a moment to review http://fincom.delt.space/items/' + \
str(self.pk) + ' and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'.\n\nHave a fiscally responsible day,\n Fincom Bot',
'fincom.bot@gmail.com',
emails,
html_message='Hey Fincom,<br><br>' + \
'Please take a moment to review ' + \
'<a href="http://fincom.delt.space/items/' + \
str(self.pk) + '">http://fincom.delt.space/items/' + str(self.pk) +\
'</a> and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'.<br><br>' + \
'Have a fiscally responsible day,<br><br> <em>Fincom Bot</em>'
)
@staticmethod
def parseDate(date_str):
try:
return datetime.strptime(date_str, "%m/%d/%y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%m/%d/%Y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%m-%d-%y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%m-%d-%Y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%m %d %y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%m %d %Y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%y %m %d").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%Y %m %d").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%y-%m-%d").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%Y-%m-%d").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%y/%m/%d").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%Y/%m/%d").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%d %m %y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%d %m %Y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%d/%m/%y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%d/%m/%Y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%d-%m-%y").date().isoformat()
except ValueError:
pass
try:
return datetime.strptime(date_str, "%d-%m-%Y").date().isoformat()
except ValueError:
return date.today().isoformat()

View File

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

View File

@@ -1,12 +0,0 @@
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.list, name='list'),
url(r'^(?P<item_id>\d+)/$', views.details, name='details'),
url(r'^(?P<item_id>\d+)/approve$', views.approve, name='approve'),
url(r'^(?P<item_id>\d+)/reject$', views.reject, name='reject'),
url(r'^(?P<item_id>\d+)/edit$', views.edit, name='edit'),
url(r'^(?P<item_id>\d+)/delete$', views.delete, name='delete'),
url(r'^new$', views.new_form, name='new_form'),
]

View File

@@ -1,181 +0,0 @@
from django.shortcuts import HttpResponse, HttpResponseRedirect
from django.template import loader
from django.utils import timezone
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from models import Item
from committee.models import Committee
def isAuthorised(request, item):
return (request.user == item.committee.chair
or request.user.groups.filter(name='Fincom').exists())
def authError():
return HttpResponseRedirect('/items')
def myItems(user):
if (user.groups.filter(name='Fincom').exists()):
return Item.objects.order_by('-date_filed', 'desc')
comms = []
for c in Committee.objects.all():
if (c.chair == user):
comms.append(c)
return Item.objects.filter(Q(created_by=user) | Q(committee__in=comms)) \
.order_by('-date_filed', 'desc')
def pageItems(request, items, status):
if status != 'M':
p = Paginator(items.filter(status=status), 8)
else:
p = Paginator(items, 8)
page = request.GET.get(status)
try:
return p.page(page)
except PageNotAnInteger:
return p.page(1)
except EmptyPage:
return p.page(p.num_pages)
@login_required
def list(request):
template = loader.get_template('items/list.html')
items = myItems(request.user)
mine = Item.objects.filter(created_by=request.user).order_by('-date_filed')
context = {
'preapproved': pageItems(request, items, Item.PREAPPROVED),
'processed': pageItems(request, items, Item.PROCESSED),
'newitems': pageItems(request, items, Item.NEW),
'rejected': pageItems(request, items, Item.REJECTED),
'mine': pageItems(request, mine, 'M'),
}
return HttpResponse(template.render(context, request))
@login_required
def details(request, item_id):
I = Item.objects.get(pk=item_id)
if (not isAuthorised(request, I)
and request.user != I.created_by):
return authError()
template = loader.get_template('items/details.html')
context = {
'I': I,
'approve': isAuthorised(request, I),
}
return HttpResponse(template.render(context, request))
def approve(request, item_id):
I = Item.objects.get(pk=item_id)
if (not isAuthorised(request, I)):
return authError()
I.approved_by.add(request.user)
if (I.committee.chair == request.user and
I.status == Item.NEW):
I.status = Item.PREAPPROVED
I.mail_fincom()
elif (request.user.groups.filter(name='Fincom').exists()):
I.status = Item.PROCESSED
I.save()
return HttpResponseRedirect('/items')
def reject(request, item_id):
I = Item.objects.get(pk=item_id)
if (not isAuthorised(request, I)):
return authError()
I.status = Item.REJECTED
I.save()
return HttpResponseRedirect('/items')
def delete(request, item_id):
I = Item.objects.get(pk=item_id)
if (not isAuthorised(request, I)):
return authError()
I.delete()
return HttpResponseRedirect('/items')
def edit(request, item_id):
I = Item.objects.get(pk=item_id)
if (not isAuthorised(request, I)
and request.user != I.created_by):
return authError()
if request.method == 'POST':
if (request.POST.get('desc', None)):
I.desc = request.POST['desc']
if (request.POST.get('event', None)):
I.event = request.POST['event']
if (request.POST.get('committee', None)):
I.committee = Committee.objects.get(name=request.POST['committee'])
if (request.POST.get('cost', None)):
I.cost = request.POST['cost']
if (request.POST.get('date', None)):
I.date_purchased = Item.parseDate(request.POST['date']),
if (request.POST.get('details', None)):
I.details = request.POST['details']
I.save()
return HttpResponseRedirect('/items/' + str(item_id))
else:
template = loader.get_template('items/edit.html')
context = {
'I': I,
'committees': Committee.objects.order_by('name'),
}
return HttpResponse(template.render(context, request))
def new_form(request):
if request.method == 'POST':
if request.FILES['image'].size > 10 * (1 << 20):
template = loader.get_template('items/new.html')
context = {
'committees': Committee.objects.order_by('name'),
'error': 'Your image file is too large. Maximum size is 20MB',
}
return HttpResponse(template.render(context, request))
item = Item(
desc = request.POST['desc'],
event = request.POST['event'],
committee = Committee.objects.get(name=request.POST['committee']),
cost = request.POST['cost'],
date_purchased = Item.parseDate(request.POST['date']),
details = request.POST['details'],
date_filed = timezone.now(),
created_by = request.user,
status = Item.NEW,
image = request.FILES['image'],
)
item.save()
item.mail_com_chair()
return HttpResponseRedirect('/items')
else:
template = loader.get_template('items/new.html')
context = {
'committees': Committee.objects.order_by('name'),
}
return HttpResponse(template.render(context, request))

View File

@@ -1,22 +0,0 @@
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fincom.settings")
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(sys.argv)

View File

@@ -159,6 +159,7 @@ USE_TZ = True
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)

View File

@@ -1,4 +0,0 @@
SRC=$(wildcard *.scss)
all: $(SRC)
sass include.scss ../css/site.css

View File

@@ -1,42 +0,0 @@
.approve {
padding: $pad-xl;
.status {
font-size: 16px;
color: $midgray;
font-weight: lighter;
span {
color: $text;
}
}
img {
border: 1px solid $midgray;
max-width: 100%;
}
}
.actions {
margin: $pad-m 0;
a {
text-decoration: none;
font-size: 12px;
font-weight: normal;
}
}
.details {
color: $text;
font-size: 12px;
font-weight: normal;
margin: $pad-m 0;
padding: $pad-l;
border-radius: $pad-s;
border: 1px solid $midgray;
span {
color: $midgray;
}
}

View File

@@ -1,85 +0,0 @@
$purple: #563d7c;
$gold: #fdd017;
$lightgray: #f8f8f8;
$midgray: #969499;
$darkgray: #4b4a4d;
$text: #252526;
$shadowgray: rgba(0, 0, 0, .8);
// size constants
$pad-s: 2px;
$pad-m: 8px;
$pad-l: 16px;
$pad-xl: 36;
body {
color: $text;
font-family: sans-serif;
background-color: $lightgray;
padding-bottom: 0px;
margin: 0px $pad-l;
}
.nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 50px;;
box-sizing: border-box;
padding: 16px;
background-color: $purple;
color: $gold;
box-shadow: 0px 3px 12px $shadowgray;
z-index: 10;
h3 {
font-weight: lighter;
font-size: 16px;
margin: 0;
}
a {
float: right;
color: $gold;
text-decoration: none;
font-size: 16px;
}
}
.pull-right {
float: right;
margin: $pad-l;
}
.container {
margin-bottom: $pad-xl;
& > div {
margin-left: auto;
margin-right: auto;
margin-top: 64px;
max-width: 960;
background-color: #fff;
border: solid 1px $midgray;
box-shadow: 0px 3px 9px lighten($shadowgray, 20%);
}
}
.btn {
border-radius: $pad-s;
border: 1px solid $midgray;
color: $purple;
display: inline-block;
padding: $pad-m $pad-l;
text-decoration: none;
vertical-align: middle;
white-space: nowrap;
&:hover {
background-color: lighten($purple, 35%);
}
}

View File

@@ -1,5 +0,0 @@
@import 'globals';
@import 'details';
@import 'items';
@import 'login';
@import 'new';

View File

@@ -1,144 +0,0 @@
section {
color: $midgray;
font-weight: lighter;
font-size: 16px;
margin-top: 2*$pad-xl;
margin-bottom: -2*$pad-xl + $pad-l;
max-width: 960px;
margin-right: auto;
margin-left: auto;
}
.items {
a.page {
display: inline-block;
margin: $pad-m;
text-decoration: none;
color: $midgray;
font-size: 12px;
float: right;
}
a.page:hover {
text-decoration: underline;
color: $purple;
}
a.page.empty:hover {
color: $midgray;
text-decoration: none;
}
}
.item {
padding: $pad-m $pad-xl;
margin: 0px;
border-bottom: 1px solid $midgray;
box-sizing: border-box;
width: 100%;
.committee {
color: $midgray;
font-size: 12px;
font-weight: bold;
margin: 0px;
}
a {
text-decoration: none;
}
.details-row {
margin: $pad-m 0;
font-size: 16px;
font-weight: lighter;
color: $text;
padding: 0px;
b {
color: $darkgray;
}
em {
color: $midgray;
margin: 0 $pad-s;
}
}
.status {
color: $midgray;
font-size: 12px;
margin: 0px;
}
.cost {
display: inline-block;
text-align: center;
width: 120px;
height: 24px;
font-size: 12px;
color: $midgray;
border-radius: $pad-s;
border: 1px solid $midgray;
box-sizing: border-box;
padding: 2*$pad-s;
margin: 2*$pad-s 0;
}
.approved {
background-color: #ffd9d9;
}
.processed {
background-color: #d9ffd9;
}
.rejected {
background-color: $midgray;
color: $lightgray;
}
.newItem {
background-color: #fff7d9;
}
}
@media (min-width: 800px) {
.item .cost {
float: right;
}
}
.empty {
margin: $pad-l;
color: $midgray;
font-weight: lighter;
font-size: 16px;
text-align: center;
}
$button-size: 24px;
.btn-floating {
position: fixed;
bottom: $button-size;
right: $button-size;
padding: $button-size/2;
color: $gold;
background-color: $purple;
text-decoration: none;
font-weight: bold;
z-index: 1000;
border-radius: 50%;
text-align: center;
box-shadow: 0 0 6px rgba(0,0,0,.16),0 6px 12px rgba(0,0,0,.32);
span {
display: block;
width: 36;
height: 36;
font-size: 28;
}
}

View File

@@ -1,33 +0,0 @@
body.login {
background-color: $purple;
color: $gold;
}
.login {
text-align: center;
color: $gold;
div {
margin-top: 30%;
}
h3 {
font-size: 24px;
margin-bottom: $pad-m;
}
h2 {
font-size: 28px;
margin-top: -$pad-l;
}
.btn {
background-color: $gold;
color: $purple;
&:hover {
background-color: darken($gold, 15%);
}
}
}

View File

@@ -1,74 +0,0 @@
h1 {
font-size: 18px;
font-weight: lighter;
color: $purple;
margin: $pad-l;
}
hr {
margin: $pad-l;
color: $midgray;
}
form {
div {
margin: $pad-l;
* {
display: inline-block;
}
label {
width: 180px;
color: $text;
vertical-align: top;
}
input, select, textarea {
width: 180px;
}
&.clear {
margin: -$pad-l 0;
width: 180px;
}
&.clear:after {
content: "";
display: table;
clear: both;
}
}
}
.rcol {
margin: $pad-l;
color: $midgray;
font-weight: lighter;
}
@media (min-width: 430px) {
form {
div {
width: 376px;
label {
text-align: right;
}
input, select, textarea {
width: 180px;
float: right;
}
}
}
}
@media (min-width: 800px) {
.rcol {
float: right;
width: 40%;
}
}

View File

@@ -1,29 +0,0 @@
<html>
<head>
<title>{% block title %}Fincom Webapp{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{% load staticfiles %}
<link href="{% static "css/site.css" %}" rel="stylesheet" />
</head>
<body>
<div class="nav">
<a href="/logout">logout</a>
<h3>Fincom Web App</h3>
</div>
<div class="container">
{% block main %}
{% endblock %}
</div>
{% block bottom %}
{% endblock %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62761470-2', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@@ -1,31 +0,0 @@
<html>
<head>
<title>Login - Fincom</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% load staticfiles %}
<link href="{% static "css/site.css" %}" rel="stylesheet">
</head>
<body class="login">
<div>
<h3>Delta Beta Chapter</h3>
<h2>Fincom Webapp</h2>
{% if error %}
<p>{{ error }}</p>
{% endif %}
<a class="btn btn-info btn-lg"
href="/login/google-oauth2/?next={{ next }}">
Login with your AndrewID
</a>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62761470-2', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@@ -1,30 +0,0 @@
{% extends "../boilerplate.html" %}
{% block main %}
<div>
{% include "./item.html" %}
<div class="approve">
{% if I.details %}
<div class="details">
<span>Details:</span><br>
{{ I.details }}</div>
{% endif %}
<div class="status">Status: <span>{{ I.statusText }}</span></div>
<div class="actions">
{% if approve %}
<a href="/items/{{ I.pk }}/approve" class="btn">Approve</a>
<a href="/items/{{ I.pk }}/reject" class="btn">Reject</a>
{% endif %}
<a href="/items/{{ I.pk }}/delete" class="btn">Delete</a>
<a href="/items/{{ I.pk }}/edit" class="btn">Edit</a>
<a href="/items" class="btn">Back</a>
</div>
<a href="{{ I.image.url }}"><img src="{{ I.image.thumbnail.url }}"></a>
</div>
</div>
{% endblock %}

View File

@@ -1,66 +0,0 @@
{% extends "../boilerplate.html" %}
{% block title %}Edit Reimbursement{% endblock %}
{% block main %}
<div>
<a href="/items" class="btn pull-right">Back</a>
<h1>Edit Reimbursements</h1>
<hr>
<form action="/items/{{ I.pk }}/edit" method="post">
{% csrf_token %}
<div>
<label for="desc">Item</label>
<input id="desc" type="text" name="desc" placeholder="What you bought"
value="{{ I.desc }}">
</div>
<div>
<label for="event">Event</label>
<input id="event" type="text" name="event" placeholder="When we need it"
value="{{ I.event }}">
</div>
<div>
<label for="committee">Committee or Budget</label>
<select name="committee" id="committee">
{% for C in committees %}
{% if I.committee == C %}
<option selected>{{ C.name }}</option>
{% else %}
<option>{{ C.name }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div>
<label for="cost">Cost</label>
<input id="cost" type="text" name="cost" placeholder="15.00"
value="{{ I.cost }}">
</div>
<div>
<label for="date">Date Purchased</label>
<input id="date" type="date" name="date" placeholder="mm/dd/yyyy"
value="{{ I.date_purchased }}">
</div>
<div class="clear">
<div>
<label for="details">Details</label>
<textarea id="details" name="details" rows="4" class="clear">{{ I.details }}</textarea>
</div>
</div>
<div class="clear">
<div>
<input type="submit">
</div>
</div>
</form>
</div>
{% endblock %}

View File

@@ -1,38 +0,0 @@
<div class="item">
<div class="committee">
{{ I.comName }}
</div>
{% if I.approved %}
<div class="cost approved">
{% elif I.processed %}
<div class="cost processed">
{% elif I.rejected %}
<div class="cost rejected">
{% else %}
<div class="cost newItem">
{% endif %}
${{ I.cost|floatformat:"2" }}
</div>
<a href="/items/{{ I.pk }}">
<div class="details-row">
<b>{{ I.event }}:</b>
{{ I.desc }}
<em>by</em>
{{ I.created_by.first_name }} {{ I.created_by.last_name }}
<em>on</em> {{ I.date_purchased }}
<em>(filed {{ I.date_filed }})</em>
</div>
</a>
<div class="status">
{% if I.approved or I.processed %}
Approved By:
{% for u in I.approved_by.all %}
{{ u.first_name }} {{ u.last_name }}
{% endfor %}
{% elif I.rejected %}
Reimbursement Declined
{% else %}
Needs Approval
{% endif %}
</div>
</div>

View File

@@ -1,45 +0,0 @@
{% extends "../boilerplate.html" %}
{% block main %}
{% if error %}
<div>
<span class="error">{{ error }}</span>
</div>
{% endif %}
{% if preapproved %}
{% with items=preapproved pagination_key="C" name="Pre-Approved" %}
{% include "./section.html" %}
{% endwith %}
{% endif %}
{% if newitems %}
{% with items=newitems pagination_key="N" name="New Items" %}
{% include "./section.html" %}
{% endwith %}
{% endif %}
{% if processed %}
{% with items=processed pagination_key="P" name="Approved" %}
{% include "./section.html" %}
{% endwith %}
{% endif %}
{% if rejected %}
{% with items=rejected pagination_key="R" name="Rejected" %}
{% include "./section.html" %}
{% endwith %}
{% endif %}
{% with items=mine pagination_key="M" name="My Reimbursements" %}
{% include "./section.html" %}
{% endwith %}
{% endblock %}
{% block bottom %}
<a href="/items/new" title="Submit new item" class="btn-floating">
<span>+</span>
</a>
{% endblock %}

View File

@@ -1,68 +0,0 @@
{% extends "../boilerplate.html" %}
{% block title %}New Reimbursement{% endblock %}
{% block main %}
<div>
<h1>Add New Reimbursements</h1>
<hr>
<div class="rcol">
Make sure all information is accurate, you submit an itemized receipt, and
you select the correct committee.
</div>
<form action="/items/new" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
<label for="desc">Item</label>
<input id="desc" type="text" name="desc" placeholder="What you bought">
</div>
<div>
<label for="event">Event</label>
<input id="event" type="text" name="event" placeholder="When we need it">
</div>
<div>
<label for="committee">Committee or Budget</label>
<select name="committee" id="committee">
<option disabled selected>Select a committee</option>
{% for C in committees %}
<option>{{ C.name }}</option>
{% endfor %}
</select>
</div>
<div>
<label for="cost">Cost</label>
<input id="cost" type="text" name="cost" placeholder="15.00">
</div>
<div>
<label for="date">Date Purchased</label>
<input id="date" type="date" name="date" placeholder="mm/dd/yyyy">
</div>
<div class="clear">
<div>
<label for="details">Details</label>
<textarea id="details" name="details" rows="4" class="clear"></textarea>
</div>
</div>
<div>
<label for="image">Receipt</label>
<input type="file" name="image" id="image" accept="image/*">
</div>
<div class="clear">
<div>
<input type="submit">
</div>
</div>
</form>
</div>
{% endblock %}

View File

@@ -1,22 +0,0 @@
<section>{{ name }}</section>
<div class="items">
{% for I in items %}
{% include "./item.html" %}
{% empty %}
<div class="empty">No Reimbursements</div>
{% endfor %}
{% if items.has_next %}
<a class="page" href="?{{ pagination_key }}={{ items.next_page_number }}">
Older &rarr;
</a>
{% else %}
<a class="page empty" href="#">Older &rarr;</a>
{% endif %}
{% if items.has_previous %}
<a class="page" href="?{{ pagination_key }}={{ items.previous_page_number }}">
&larr; Newer
</a>
{% else %}
<a class="page empty" href="#">&larr; Newer</a>
{% endif %}
</div>

View File

@@ -10,7 +10,9 @@ https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
import os
from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fincom.settings")
application = get_wsgi_application()
application = DjangoWhiteNoise(application)