39 Commits

Author SHA1 Message Date
Aaron Gutierrez
44cf3cea28 upgrade django 2021-04-10 06:13:10 +00:00
Aaron Gutierrez
1c580648cb upgrade Pillow 2021-04-10 06:10:26 +00:00
Aaron Gutierrez
f586d12fba upgrade some packages 2021-04-10 06:03:10 +00:00
c5ee6a085b Merge branch 'master' into prod 2019-08-20 08:46:01 -07:00
ccbf980a0c upgrade Django 2019-08-20 08:45:43 -07:00
76c402849b Merge branch 'master' into prod 2019-06-12 07:55:50 -07:00
279cfd1b86 update Django and urllib3 2019-06-12 07:55:32 -07:00
091430a24b Merge branch 'master' into prod 2019-04-23 09:16:48 -07:00
b1208f8c4f upgrade django 2019-04-23 09:16:38 -07:00
8254c381fd Merge branch 'master' into prod 2019-01-29 08:40:27 -08:00
23545c3383 upgrade to python3 on heroku 2019-01-29 08:40:21 -08:00
Aaron Gutierrez
b654ccc548 Google+ deprecation 2019-01-29 08:38:32 -08:00
61da19ed00 Merge branch 'prod' of git.frat.tech:aaron/fincom into prod 2019-01-29 08:34:52 -08:00
Aaron Gutierrez
218e76ec13 Google+ deprecation 2019-01-29 16:34:14 +00:00
4a5a20bbe0 Merge branch 'prod' of git.frat.tech:aaron/fincom into prod 2019-01-27 11:01:03 -08:00
Aaron Gutierrez
4a8b07af87 Merge branch 'master' into prod 2019-01-27 18:53:43 +00:00
0b464dfd9c No public ACL 2019-01-26 18:10:19 -08:00
Aaron Gutierrez
ac7afddaab upgrade packages 2019-01-27 00:29:32 +00:00
2dee669507 Merge remote-tracking branch 'frat/master' 2019-01-26 15:06:27 -08:00
Aaron Gutierrez
bb1c63bf14 Fincom on AWS 2019-01-26 23:05:45 +00:00
51481db40e Merge branch 'master' into prod 2018-10-21 13:48:14 -07:00
d85c53c688 fix rotation error 2018-10-21 13:47:59 -07:00
dba41d0ad9 Merge branch 'master' into prod 2018-10-21 10:42:47 -07:00
81661a5aa0 cleanup 2018-10-21 10:42:19 -07:00
3ad6651044 Rotate vertical images 2018-10-21 10:10:56 -07:00
695a4b9af6 Clean up styles woo 2018-10-21 10:10:27 -07:00
083c8b06a3 Merge branch 'master' into prod 2018-09-27 09:14:37 -07:00
0eba3c29a3 upgrade psycopg2 2018-09-27 09:14:24 -07:00
18acddfbc1 Merge branch 'master' into prod 2018-09-27 09:01:36 -07:00
dbbcef6857 Remove google analytics 2018-09-27 09:01:07 -07:00
f689d404ef Merge branch 'master' into prod 2018-06-04 08:45:19 -07:00
d12e1ed2c6 Merge pull request #1 from aarongut/disabled-next-prev
'disabled' newer/older links cannot be interacted with
2018-05-29 11:07:58 -07:00
Zachary Snow
3ed17949c3 'disabled' newer/older links cannot be interacted with 2018-05-29 10:50:28 -07:00
c0d8c01249 debug = false in prod 2018-03-24 10:51:58 -07:00
6df63d4137 Dev changes 2018-03-24 10:51:26 -07:00
66b1a22e09 Update letsencrypt stuff 2017-05-08 21:19:54 -04:00
10abcdd32f Minor style updates 2017-04-11 11:45:33 -04:00
a40ae6bd96 fix email urls to be absolute and https 2017-03-02 18:47:44 -05:00
14bb6559cd update gitignore 2017-02-25 14:23:02 -05:00
35 changed files with 712 additions and 528 deletions

14
.gitignore vendored
View File

@@ -6,6 +6,13 @@ __pycache__/
# vim # vim
*.swp *.swp
# macOS
.DS_Store
# Visual Studio Code
.vscode/
# tags # tags
tags tags
@@ -86,9 +93,16 @@ celerybeat-schedule
# dotenv # dotenv
.env .env
keys.sh keys.sh
server.crt
server.csr
server.key
fullchain.pem
privkey.pem
# sass # sass
.sass-cache .sass-cache
*.css.map
# virtualenv # virtualenv
venv/ venv/

View File

@@ -1,2 +1,2 @@
web: gunicorn fincom.wsgi --log-file - web: gunicorn fincom.wsgi --log-file -
test: gunicorn fincom.wsgi --log-file - --keyfile server.key --certfile server.crt test: gunicorn fincom.wsgi --log-file - --keyfile server.key --certfile server.crt --bind 0.0.0.0:5100

View File

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

View File

@@ -5,7 +5,7 @@ from django.db import models
class Committee(models.Model): class Committee(models.Model):
name = models.CharField(max_length=100, unique=True) name = models.CharField(max_length=100, unique=True)
chair = models.ForeignKey(User, null=True) chair = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return self.name return self.name

View File

@@ -1,10 +1,11 @@
from django.conf.urls import url from django.urls import path
from . import views
from committee import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.edit, name='edit'), path('', views.edit, name='edit'),
url(r'^update/(?P<committee>\d+)/$', views.update, name='update'), path('update/<int:committee>/', views.update, name='update'),
url(r'^fincom/$', views.add_to_fincom, name='add_to_fincom'), path('fincom/', views.add_to_fincom, name='add_to_fincom'),
url(r'^fincom/delete$', views.remove_fincom, name='remove_fincom'), path('fincom/delete', views.remove_fincom, name='remove_fincom'),
url(r'^new$', views.new_committee, name='new_committee'), path('new', views.new_committee, name='new_committee'),
] ]

View File

@@ -2,7 +2,8 @@ from django.shortcuts import HttpResponse, HttpResponseRedirect
from django.template import loader from django.template import loader
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from models import Committee
from committee.models import Committee
@login_required @login_required
def edit(request): def edit(request):
@@ -68,4 +69,4 @@ def remove_fincom(request):
user.groups.remove(Group.objects.filter(name='Fincom')[0]) user.groups.remove(Group.objects.filter(name='Fincom')[0])
user.save() user.save()
return HttpResponseRedirect('/committees') return HttpResponseRedirect('/committees')

View File

@@ -23,12 +23,12 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = os.environ['SECRET_KEY'] SECRET_KEY = os.environ['SECRET_KEY']
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = False
ALLOWED_HOSTS = [ ALLOWED_HOSTS = [
'localhost', 'localhost',
'dtd-fincom.herokuapp.com', 'fincom.frat.tech',
'fincom.delt.space', 'fincom.delt.space',
] ]
@@ -98,10 +98,10 @@ WSGI_APPLICATION = 'fincom.wsgi.application'
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.postgresql', 'ENGINE': 'django.db.backends.postgresql',
'NAME': 'dbu9ujb6cnhc3n', 'NAME': 'fincom',
'USER': 'dexgqmkgoabqyd', 'USER': 'fincom',
'PASSWORD': os.environ['DBPASSWD'], 'PASSWORD': 'fincom',
'HOST': 'ec2-50-19-89-124.compute-1.amazonaws.com', 'HOST': '127.0.0.1',
'PORT': '5432', 'PORT': '5432',
} }
} }
@@ -110,8 +110,8 @@ DATABASES = {
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID=os.environ['AWS_ACCESS_KEY_ID'] AWS_ACCESS_KEY_ID=os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY=os.environ['AWS_SECRET_ACCESS_KEY'] AWS_SECRET_ACCESS_KEY=os.environ['AWS_SECRET_ACCESS_KEY']
AWS_AUTO_CREATE_BUCKET=True
AWS_STORAGE_BUCKET_NAME='fincom' AWS_STORAGE_BUCKET_NAME='fincom'
AWS_DEFAULT_ACL=None
AWS_S3_FILE_OVERWRITE=False AWS_S3_FILE_OVERWRITE=False
@@ -138,8 +138,8 @@ AUTH_PASSWORD_VALIDATORS = [
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.environ['SOCIAL_AUTH_GOOGLE_OAUTH2_KEY'] SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.environ['SOCIAL_AUTH_GOOGLE_OAUTH2_KEY']
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ['SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET'] SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ['SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET']
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = ['andrew.cmu.edu'] SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = ['andrew.cmu.edu', 'alumni.cmu.edu']
SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = {'hd': 'andrew.cmu.edu' } SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = {'hd': '*' }
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/items/' SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/items/'
LOGIN_URL = '/login/google-oauth2/' LOGIN_URL = '/login/google-oauth2/'

View File

@@ -13,16 +13,16 @@ Including another URLconf
1. Import the include() function: from django.conf.urls import url, include 1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
""" """
from django.conf.urls import include, url from django.urls import include, path
from django.contrib import admin from django.contrib import admin
from . import views
from fincom import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.index, name='index'), path('', views.index, name='index'),
url(r'^logout$', views.user_logout, name='logout'), path('logout', views.user_logout, name='logout'),
url(r'^items/', include('items.urls')), path('items/', include('items.urls')),
url(r'^committees/', include('committee.urls')), path('committees/', include('committee.urls')),
url('.well-known/acme-challenge/EJpPgYRpZkFhuxZEpocd9j0Xy58rA1swzbItXAgXV2M', views.encrypt, name='encrypt'), path('', include('social_django.urls', namespace='social')),
url('', include('social_django.urls', namespace='social')), path('admin/', admin.site.urls),
url(r'^admin/', admin.site.urls),
] ]

View File

@@ -3,15 +3,12 @@ from django.contrib.auth import logout
from django.template import loader from django.template import loader
def index(request): def index(request):
if request.user.is_authenticated(): if request.user.is_authenticated:
return HttpResponseRedirect('/items') return HttpResponseRedirect('/items')
template = loader.get_template('fincom/index.html') template = loader.get_template('fincom/index.html')
return HttpResponse(template.render({}, request)) return HttpResponse(template.render({}, request))
def encrypt(request):
return HttpResponse('EJpPgYRpZkFhuxZEpocd9j0Xy58rA1swzbItXAgXV2M.g4Ct3egntTJZl1LOzJH8v9Ri24BQ7blYjcbzPucJVE4', request)
def user_logout(request): def user_logout(request):
logout(request) logout(request)

View File

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

View File

@@ -1,15 +1,62 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from __future__ import with_statement
from datetime import datetime, date
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.files.base import ContentFile
from django.core.mail import send_mail from django.core.mail import send_mail
from django.template import loader from django.template import loader
from io import BytesIO
from PIL import Image
from storages.backends.s3boto3 import S3Boto3Storage from storages.backends.s3boto3 import S3Boto3Storage
from stdimage.models import StdImageField from stdimage.models import StdImageField
from datetime import datetime, date from stdimage.utils import render_variations
from committee.models import Committee from committee.models import Committee
from django.db import models from django.db import models
#EXIF key index for the orientation value
ORIENTATION_KEY = 274
ROTATE_VALUES = {
3: Image.ROTATE_180,
6: Image.ROTATE_270,
8: Image.ROTATE_90,
}
# helper to fix "soft" rotated images
def resizeAndRotate(file_name, variations, storage):
rotated = False
with storage.open(file_name) as f:
try:
image = Image.open(f)
except:
return False
else:
with image:
try:
file_format = image.format
exif = image._getexif()
if exif and ORIENTATION_KEY in exif:
orientation = exif[ORIENTATION_KEY]
if orientation in ROTATE_VALUES:
image = image.transpose(ROTATE_VALUES[orientation])
rotated = True
if rotated:
with BytesIO() as file_buffer:
image.save(file_buffer, file_format)
f = ContentFile(file_buffer.getvalue())
storage.delete(file_name)
storage.save(file_name, f)
except:
return True
render_variations(file_name, variations, storage=storage)
return False
class Item(models.Model): class Item(models.Model):
S3 = S3Boto3Storage() S3 = S3Boto3Storage()
@@ -25,21 +72,24 @@ class Item(models.Model):
(REJECTED, 'Rejected'), (REJECTED, 'Rejected'),
) )
desc = models.CharField(max_length=200) desc = models.CharField(max_length=200)
event = models.CharField(max_length=200) event = models.CharField(max_length=200)
committee = models.ForeignKey(Committee) committee = models.ForeignKey(Committee, on_delete=models.DO_NOTHING)
details = models.TextField() details = models.TextField()
cost = models.DecimalField(max_digits=7, decimal_places=2) cost = models.DecimalField(max_digits=7, decimal_places=2)
date_purchased = models.DateField('date purchased') date_purchased = models.DateField('date purchased')
image = StdImageField(upload_to='images/%Y/%m/%d', image = StdImageField(upload_to='images/%Y/%m/%d',
render_variations=resizeAndRotate,
variations={'thumbnail': (600, 600)} variations={'thumbnail': (600, 600)}
) )
created_by = models.ForeignKey(User, related_name='created_by') created_by = models.ForeignKey(User, related_name='created_by', on_delete=models.DO_NOTHING)
approved_by = models.ManyToManyField(User, blank=True, related_name='approved_by') approved_by = models.ManyToManyField(User, blank=True, related_name='approved_by')
date_filed = models.DateTimeField('date filed') date_filed = models.DateTimeField('date filed')
status = models.CharField(max_length=2, choices=STATUS) status = models.CharField(max_length=2, choices=STATUS)
def approved(self): def approved(self):
return self.status == Item.PREAPPROVED return self.status == Item.PREAPPROVED

View File

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

View File

@@ -4,8 +4,9 @@ from django.utils import timezone
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db.models import Q from django.db.models import Q
from models import Item
from committee.models import Committee from committee.models import Committee
from items.models import Item
def isAuthorised(request, item): def isAuthorised(request, item):
return (request.user == item.committee.chair return (request.user == item.committee.chair

View File

@@ -1,29 +1,39 @@
appdirs==1.4.0 appdirs==1.4.0
boto3==1.4.4 boto3==1.9.86
botocore==1.5.7 botocore==1.12.166
Django==1.10.5 certifi==2018.11.29
chardet==3.0.4
defusedxml==0.5.0
Django==2.2.20
django-cleanup==0.4.2 django-cleanup==0.4.2
django-stdimage==2.4.1 django-stdimage==2.4.1
django-storages==1.5.2 django-storages==1.5.2
docutils==0.13.1 docutils==0.14
futures==3.0.5 futures==3.0.5
gunicorn==19.6.0 gunicorn==19.9.0
jmespath==0.9.1 idna==2.8
oauthlib==2.0.1 jmespath==0.9.3
oauthlib==3.0.1
olefile==0.44 olefile==0.44
packaging==16.8 packaging==16.8
Pillow==4.0.0 Pillow==8.1.1
pkg-resources==0.0.0
progressbar2==3.12.0 progressbar2==3.12.0
psycopg2==2.6.2 psycopg2-binary==2.8.6
PyJWT==1.4.2 PyJWT==1.7.1
pyparsing==2.1.10 pyparsing==2.1.10
python-dateutil==2.6.0 python-dateutil==2.7.5
python-openid==2.2.5 python-openid==2.2.5
python-social-auth==0.3.6
python-utils==2.0.1 python-utils==2.0.1
requests==2.13.0 python3-openid==3.1.0
requests-oauthlib==0.7.0 pytz==2018.9
s3transfer==0.1.10 requests==2.22.0
six==1.10.0 requests-oauthlib==1.2.0
social-auth-app-django==1.0.1 s3transfer==0.1.13
social-auth-core==1.1.0 six==1.12.0
social-auth-app-django==3.1.0
social-auth-core==3.0.0
sqlparse==0.3.0
urllib3==1.25.3
whitenoise==3.3.0 whitenoise==3.3.0

1
runtime.txt Normal file
View File

@@ -0,0 +1 @@
python-3.6.6

4
sass/Makefile Normal file
View File

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

View File

@@ -13,28 +13,30 @@
img { img {
border: 1px solid $midgray; border: 1px solid $midgray;
max-width: 100%; width: 100%;
} }
} }
.actions { .actions {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: $pad-m 0; margin: $pad-m 0;
a { a {
flex: 0 0 auto;
margin-bottom: $pad-m;
margin-right: $pad-m;
text-decoration: none; text-decoration: none;
font-size: 12px;
font-weight: normal;
} }
} }
.details { .details {
color: $text; border: 1px solid $midgray;
border-radius: $pad-s;
font-size: 12px; font-size: 12px;
font-weight: normal;
margin: $pad-m 0; margin: $pad-m 0;
padding: $pad-l; padding: $pad-l;
border-radius: $pad-s;
border: 1px solid $midgray;
span { span {
color: $midgray; color: $midgray;

105
sass/globals.scss Normal file
View File

@@ -0,0 +1,105 @@
$purple: #563d7c;
$gold: #fdd017;
$lightgray: #f8f8f8;
$midgray: #969499;
$darkgray: #4b4a4d;
$text: #252526;
$shadowgray: rgba(0, 0, 0, .8);
$lightshadowgray: rgba(0, 0, 0, 0.2);
// size constants
$pad-s: 2px;
$pad-m: 8px;
$pad-l: 16px;
$pad-xl: 36px;
html,
body {
background-color: $lightgray;
color: $text;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Helvetica,Arial,sans-serif;
height: 100vh;
margin: 0;
padding: 0;
width: 100vw;
}
body {
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.nav {
align-items: center;
box-shadow: 0px 3px 12px $shadowgray;
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
flex: 0 0 auto;
height: 50px;
padding: $pad-l;
background-color: $purple;
color: $gold;
z-index: 10;
h3 {
font-weight: normal;
font-size: 16px;
margin: 0;
}
a {
color: $gold;
text-decoration: none;
font-size: 16px;
margin-left: $pad-m;
&:hover {
color: darken($gold, 20%);
text-decoration: initial;
}
}
}
.content {
align-items: center;
display: flex;
flex: 1 1 auto;
flex-direction: column;
position: relative;
overflow-y: auto;
min-height: 1;
}
.container {
background-color: #fff;
box-shadow: 0px 3px 12px $lightshadowgray;
display: flex;
flex: 0 0 auto;
flex-direction: column;
min-height: 1;
}
.btn {
background-color: #fff;
border-radius: $pad-s;
border: 1px solid $midgray;
box-sizing: border-box;
color: $purple;
cursor: pointer;
display: inline-block;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Helvetica,Arial,sans-serif;
font-size: 12px;
font-weight: normal;
padding: $pad-m $pad-l;
text-decoration: none;
vertical-align: middle;
white-space: nowrap;
&:hover {
background-color: lighten($purple, 35%);
}
}

View File

@@ -1,42 +1,64 @@
section { section {
color: $midgray; color: $midgray;
flex: 0 0 auto;
font-weight: lighter; font-weight: lighter;
font-size: 16px; font-size: 16px;
margin-top: 2*$pad-xl; margin-top: $pad-xl;
margin-bottom: -2*$pad-xl + $pad-l; text-align: center;
max-width: 960px;
margin-right: auto;
margin-left: auto;
} }
.items { .items {
display: flex;
flex-direction: column;
flex: 1 0 auto;
a.page { a.page {
display: inline-block; display: inline-block;
margin: $pad-m; margin: $pad-m;
text-decoration: none; text-decoration: none;
color: $midgray; color: $purple;
font-size: 12px; font-size: 12px;
float: right; float: right;
} }
a.page:hover { a.page:hover {
text-decoration: underline; text-decoration: underline;
color: $purple;
} }
a.page.empty:hover { a.page.empty {
color: $midgray; color: $midgray;
text-decoration: none; text-decoration: none;
cursor: default;
} }
} }
.pagination {
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: $pad-l;
padding: 0 $pad-xl;
width: 100%;
}
.item { .item {
display: flex;
flex-direction: column;
padding: $pad-m $pad-xl; padding: $pad-m $pad-xl;
margin: 0px; margin: 0px;
border-bottom: 1px solid $midgray; border-bottom: 1px solid $midgray;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
.committeeAndCost {
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.committee { .committee {
color: $midgray; color: $midgray;
font-size: 12px; font-size: 12px;
@@ -49,16 +71,17 @@ section {
} }
.details-row { .details-row {
margin: $pad-m 0; color: $text;
font-size: 16px; font-size: 16px;
font-weight: lighter; font-weight: lighter;
color: $text; line-height: 24px;
margin: $pad-m 0;
padding: 0px; padding: 0px;
b { b {
color: $darkgray; color: $darkgray;
} }
em { em {
color: $midgray; color: $midgray;
margin: 0 $pad-s; margin: 0 $pad-s;
@@ -103,17 +126,11 @@ section {
} }
} }
@media (min-width: 800px) { .emptyItems {
.item .cost { margin: $pad-xl;
float: right;
}
}
.empty {
margin: $pad-l;
color: $midgray; color: $midgray;
font-weight: lighter; font-size: 12px;
font-size: 16px; font-style: italic;
text-align: center; text-align: center;
} }
@@ -141,4 +158,9 @@ $button-size: 24px;
height: 36; height: 36;
font-size: 28; font-size: 28;
} }
&:hover {
background-color: darken($purple, 10%);
box-shadow: 0 0 12px rgba(0,0,0,.16),0 12px 12px rgba(0,0,0,.32);
}
} }

View File

@@ -14,17 +14,18 @@ body.login {
h3 { h3 {
font-size: 24px; font-size: 24px;
margin-bottom: $pad-m; margin-bottom: 0;
} }
h2 { h2 {
font-size: 28px; font-size: 28px;
margin-top: -$pad-l; margin: 0 auto;
} }
.btn { .btn {
background-color: $gold; background-color: $gold;
color: $purple; color: $purple;
font-size: 16px;
&:hover { &:hover {
background-color: darken($gold, 15%); background-color: darken($gold, 15%);

54
sass/new.scss Normal file
View File

@@ -0,0 +1,54 @@
h1 {
font-size: 18px;
font-weight: lighter;
color: $purple;
margin: $pad-l;
}
hr {
margin: $pad-l;
color: $midgray;
}
.inputRow {
box-sizing: border-box;
margin-bottom: $pad-l;
padding: 0 $pad-xl;
label {
color: $midgray;
font-weight: bold;
font-size: 12px;
margin-left: $pad-s;
}
input,
select,
textarea {
box-sizing: border-box;
border: 1px solid $midgray;
font-size: 16px;
line-height: 24px;
padding: $pad-s;
width: 100%;
}
textarea {
resize: vertical;
}
}
.editActions {
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 $pad-xl;
width: 100%;
}
.notes {
color: $midgray;
font-size: 12px;
margin: $pad-l $pad-xl;
}

View File

@@ -1,178 +1,254 @@
html,
body { body {
color: #252526;
font-family: sans-serif;
background-color: #f8f8f8; background-color: #f8f8f8;
padding-bottom: 0px; color: #252526;
margin: 0px 16px; } font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Helvetica, Arial, sans-serif;
height: 100vh;
margin: 0;
padding: 0;
width: 100vw;
}
body {
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.nav { .nav {
position: fixed; align-items: center;
top: 0; box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.8);
left: 0;
width: 100%;
height: 50px;
box-sizing: border-box; box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
flex: 0 0 auto;
height: 50px;
padding: 16px; padding: 16px;
background-color: #563d7c; background-color: #563d7c;
color: #fdd017; color: #fdd017;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.8); z-index: 10;
z-index: 10; } }
.nav h3 { .nav h3 {
font-weight: lighter; font-weight: normal;
font-size: 16px; font-size: 16px;
margin: 0; } margin: 0;
.nav a { }
float: right; .nav a {
color: #fdd017; color: #fdd017;
text-decoration: none; text-decoration: none;
font-size: 16px; font-size: 16px;
margin-left: 8px; } margin-left: 8px;
}
.nav a:hover {
color: #ad8b01;
text-decoration: initial;
}
.pull-right { .content {
float: right; align-items: center;
margin: 16px; } display: flex;
flex: 1 1 auto;
flex-direction: column;
position: relative;
overflow-y: auto;
min-height: 1;
}
.container { .container {
margin-bottom: 36; } background-color: #fff;
.container > div { box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.2);
margin-left: auto; display: flex;
margin-right: auto; flex: 0 0 auto;
margin-top: 64px; flex-direction: column;
max-width: 960; min-height: 1;
background-color: #fff; }
border: solid 1px #969499;
box-shadow: 0px 3px 9px rgba(51, 51, 51, 0.8); }
.btn { .btn {
background-color: #fff;
border-radius: 2px; border-radius: 2px;
border: 1px solid #969499; border: 1px solid #969499;
box-sizing: border-box;
color: #563d7c; color: #563d7c;
cursor: pointer;
display: inline-block; display: inline-block;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 12px;
font-weight: normal;
padding: 8px 16px; padding: 8px 16px;
text-decoration: none; text-decoration: none;
vertical-align: middle; vertical-align: middle;
white-space: nowrap; } white-space: nowrap;
.btn:hover { }
background-color: #b19dcf; } .btn:hover {
background-color: #b19dcf;
}
.approve { .approve {
padding: 36; } padding: 36px;
.approve .status { }
font-size: 16px; .approve .status {
color: #969499; font-size: 16px;
font-weight: lighter; } color: #969499;
.approve .status span { font-weight: lighter;
color: #252526; } }
.approve img { .approve .status span {
border: 1px solid #969499; color: #252526;
max-width: 100%; } }
.approve img {
border: 1px solid #969499;
width: 100%;
}
.actions { .actions {
margin: 8px 0; } display: flex;
.actions a { flex-direction: row;
text-decoration: none; flex-wrap: wrap;
font-size: 12px; margin: 8px 0;
font-weight: normal; } }
.actions a {
flex: 0 0 auto;
margin-bottom: 8px;
margin-right: 8px;
text-decoration: none;
}
.details { .details {
color: #252526; border: 1px solid #969499;
border-radius: 2px;
font-size: 12px; font-size: 12px;
font-weight: normal;
margin: 8px 0; margin: 8px 0;
padding: 16px; padding: 16px;
border-radius: 2px; }
border: 1px solid #969499; } .details span {
.details span { color: #969499;
color: #969499; } }
form.committee { form.committee {
border-bottom: 1px solid #969499; border-bottom: 1px solid #969499;
padding: 16px; padding: 16px;
margin-bottom: 0; } margin-bottom: 0;
}
section { section {
color: #969499; color: #969499;
flex: 0 0 auto;
font-weight: lighter; font-weight: lighter;
font-size: 16px; font-size: 16px;
margin-top: 72; margin-top: 36px;
margin-bottom: -56px; text-align: center;
max-width: 960px; }
margin-right: auto;
margin-left: auto; }
.items {
display: flex;
flex-direction: column;
flex: 1 0 auto;
}
.items a.page { .items a.page {
display: inline-block; display: inline-block;
margin: 8px; margin: 8px;
text-decoration: none; text-decoration: none;
color: #969499; color: #563d7c;
font-size: 12px; font-size: 12px;
float: right; } float: right;
}
.items a.page:hover { .items a.page:hover {
text-decoration: underline; text-decoration: underline;
color: #563d7c; } }
.items a.page.empty:hover { .items a.page.empty {
color: #969499; color: #969499;
text-decoration: none; } text-decoration: none;
cursor: default;
}
.pagination {
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 16px;
padding: 0 36px;
width: 100%;
}
.item { .item {
padding: 8px 36; display: flex;
flex-direction: column;
padding: 8px 36px;
margin: 0px; margin: 0px;
border-bottom: 1px solid #969499; border-bottom: 1px solid #969499;
box-sizing: border-box; box-sizing: border-box;
width: 100%; } width: 100%;
.item .committee { }
color: #969499; .item .committeeAndCost {
font-size: 12px; align-items: center;
font-weight: bold; display: flex;
margin: 0px; } flex-direction: row;
.item a { justify-content: space-between;
text-decoration: none; } }
.item .details-row { .item .committee {
margin: 8px 0;
font-size: 16px;
font-weight: lighter;
color: #252526;
padding: 0px; }
.item .details-row b {
color: #4b4a4d; }
.item .details-row em {
color: #969499;
margin: 0 2px; }
.item .status {
color: #969499;
font-size: 12px;
margin: 0px; }
.item .cost {
display: inline-block;
text-align: center;
width: 120px;
height: 24px;
font-size: 12px;
color: #969499;
border-radius: 2px;
border: 1px solid #969499;
box-sizing: border-box;
padding: 4px;
margin: 4px 0; }
.item .approved {
background-color: #ffd9d9; }
.item .processed {
background-color: #d9ffd9; }
.item .rejected {
background-color: #969499;
color: #f8f8f8; }
.item .newItem {
background-color: #fff7d9; }
@media (min-width: 800px) {
.item .cost {
float: right; } }
.empty {
margin: 16px;
color: #969499; color: #969499;
font-weight: lighter; font-size: 12px;
font-weight: bold;
margin: 0px;
}
.item a {
text-decoration: none;
}
.item .details-row {
color: #252526;
font-size: 16px; font-size: 16px;
text-align: center; } font-weight: lighter;
line-height: 24px;
margin: 8px 0;
padding: 0px;
}
.item .details-row b {
color: #4b4a4d;
}
.item .details-row em {
color: #969499;
margin: 0 2px;
}
.item .status {
color: #969499;
font-size: 12px;
margin: 0px;
}
.item .cost {
display: inline-block;
text-align: center;
width: 120px;
height: 24px;
font-size: 12px;
color: #969499;
border-radius: 2px;
border: 1px solid #969499;
box-sizing: border-box;
padding: 4px;
margin: 4px 0;
}
.item .approved {
background-color: #ffd9d9;
}
.item .processed {
background-color: #d9ffd9;
}
.item .rejected {
background-color: #969499;
color: #f8f8f8;
}
.item .newItem {
background-color: #fff7d9;
}
.emptyItems {
margin: 36px;
color: #969499;
font-size: 12px;
font-style: italic;
text-align: center;
}
.btn-floating { .btn-floating {
position: fixed; position: fixed;
@@ -186,78 +262,98 @@ section {
z-index: 1000; z-index: 1000;
border-radius: 50%; border-radius: 50%;
text-align: center; text-align: center;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.16), 0 6px 12px rgba(0, 0, 0, 0.32); } box-shadow: 0 0 6px rgba(0, 0, 0, 0.16), 0 6px 12px rgba(0, 0, 0, 0.32);
.btn-floating span { }
display: block; .btn-floating span {
width: 36; display: block;
height: 36; width: 36;
font-size: 28; } height: 36;
font-size: 28;
}
.btn-floating:hover {
background-color: #3e2c5a;
box-shadow: 0 0 12px rgba(0, 0, 0, 0.16), 0 12px 12px rgba(0, 0, 0, 0.32);
}
body.login { body.login {
background-color: #563d7c; background-color: #563d7c;
color: #fdd017; } color: #fdd017;
}
.login { .login {
text-align: center; text-align: center;
color: #fdd017; } color: #fdd017;
.login div { }
margin-top: 30%; } .login div {
.login h3 { margin-top: 30%;
font-size: 24px; }
margin-bottom: 8px; } .login h3 {
.login h2 { font-size: 24px;
font-size: 28px; margin-bottom: 0;
margin-top: -16px; } }
.login .btn { .login h2 {
background-color: #fdd017; font-size: 28px;
color: #563d7c; } margin: 0 auto;
.login .btn:hover { }
background-color: #c69f02; } .login .btn {
background-color: #fdd017;
color: #563d7c;
font-size: 16px;
}
.login .btn:hover {
background-color: #c69f02;
}
h1 { h1 {
font-size: 18px; font-size: 18px;
font-weight: lighter; font-weight: lighter;
color: #563d7c; color: #563d7c;
margin: 16px; } margin: 16px;
}
hr { hr {
margin: 16px;
color: #969499; }
form div {
margin: 16px; }
form div * {
display: inline-block; }
form div label {
width: 180px;
color: #252526;
vertical-align: top; }
form div input, form div select, form div textarea {
width: 180px; }
form div.clear {
margin: -16px 0;
width: 180px; }
form div.clear:after {
content: "";
display: table;
clear: both; }
.rcol {
margin: 16px; margin: 16px;
color: #969499; color: #969499;
font-weight: lighter; } }
@media (min-width: 430px) { .inputRow {
form div { box-sizing: border-box;
width: 376px; } margin-bottom: 16px;
form div label { padding: 0 36px;
text-align: right; } }
form div input, form div select, form div textarea { .inputRow label {
width: 180px; color: #969499;
float: right; } } font-weight: bold;
@media (min-width: 800px) { font-size: 12px;
.rcol { margin-left: 2px;
float: right; }
width: 40%; } } .inputRow input,
.inputRow select,
.inputRow textarea {
box-sizing: border-box;
border: 1px solid #969499;
font-size: 16px;
line-height: 24px;
padding: 2px;
width: 100%;
}
.inputRow textarea {
resize: vertical;
}
.editActions {
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 0 36px;
width: 100%;
}
.notes {
color: #969499;
font-size: 12px;
margin: 16px 36px;
}
/*# sourceMappingURL=site.css.map */ /*# sourceMappingURL=site.css.map */

View File

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

View File

@@ -1,86 +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;
margin-left: $pad-m;
}
}
.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,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

@@ -5,30 +5,25 @@
{% load staticfiles %} {% load staticfiles %}
<link href="{% static "css/site.css" %}" rel="stylesheet" /> <link href="{% static "css/site.css" %}" rel="stylesheet" />
<link rel="icon" href="{% static "favicon.32.png" %}" sizes="32x32" type="image/png"> <link rel="icon" href="{% static "favicon.32.png" %}" sizes="32x32" type="image/png">
<link rel="icon" href="{% static "/favicon.64.png" %}" sizes="64x64" type="image/png"> <link rel="icon" href="{% static "favicon.64.png" %}" sizes="64x64" type="image/png">
</head> </head>
<body> <body>
<div class="nav"> <div class="nav">
<a href="/logout">logout</a> <h3>The Aaron Gutierrez, '17, Fincom Web App</h3>
{% if fincom %} <div>
<a href="/committees">manage</a> {% if fincom %}
{% endif %} <a href="/committees">manage</a>
<h3>Fincom Web App</h3> {% endif %}
<a href="/logout">logout</a>
</div>
</div> </div>
<div class="container"> <div class="content">
{% block main %} <div class="container">
{% endblock %} {% block main %}
{% endblock %}
</div>
</div> </div>
{% block bottom %} {% block bottom %}
{% endblock %} {% 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> </body>
</html> </html>

View File

@@ -4,28 +4,21 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
{% load staticfiles %} {% load staticfiles %}
<link href="{% static "css/site.css" %}" rel="stylesheet"> <link href="{% static "css/site.css" %}" rel="stylesheet">
<link rel="icon" href="{% static "favicon.32.png" %}" sizes="32x32" type="image/png">
<link rel="icon" href="{% static "favicon.64.png" %}" sizes="64x64" type="image/png">
</head> </head>
<body class="login"> <body class="login">
<div> <div>
<h3>Delta Beta Chapter</h3> <h3>Delta Beta Chapter</h3>
<h2>Fincom Webapp</h2> <h2>Fincom Webapp</h2>
{% if error %} <a class="btn btn-info"
<p>{{ error }}</p>
{% endif %}
<a class="btn btn-info btn-lg"
href="/login/google-oauth2/?next={{ next }}"> href="/login/google-oauth2/?next={{ next }}">
Login with your AndrewID Login with your AndrewID
</a> </a>
{% if error %}
<p>{{ error }}</p>
{% endif %}
</div> </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> </body>
</html> </html>

View File

@@ -8,7 +8,7 @@
<div class="approve"> <div class="approve">
{% if I.details %} {% if I.details %}
<div class="details"> <div class="details">
<span>Details:</span><br> <span>Details</span><br>
{{ I.details }}</div> {{ I.details }}</div>
{% endif %} {% endif %}
<div class="status">Status: <span>{{ I.statusText }}</span></div> <div class="status">Status: <span>{{ I.statusText }}</span></div>
@@ -23,7 +23,9 @@
<a href="/items" class="btn">Back</a> <a href="/items" class="btn">Back</a>
</div> </div>
<a href="{{ I.image.url }}"><img src="{{ I.image.thumbnail.url }}"></a> <a href="{{ I.image.url }}">
<img src="{{ I.image.thumbnail.url }}" alt="Click to view">
</a>
</div> </div>
</div> </div>

View File

@@ -5,25 +5,24 @@
{% block main %} {% block main %}
<div> <div>
<a href="/items" class="btn pull-right">Back</a>
<h1>Edit Reimbursements</h1> <h1>Edit Reimbursements</h1>
<hr> <hr>
<form action="/items/{{ I.pk }}/edit" method="post"> <form action="/items/{{ I.pk }}/edit" method="post">
{% csrf_token %} {% csrf_token %}
<div> <div class="inputRow">
<label for="desc">Item</label> <label for="desc">Item</label>
<input id="desc" type="text" name="desc" placeholder="What you bought" <input id="desc" type="text" name="desc" placeholder="What you bought"
value="{{ I.desc }}"> value="{{ I.desc }}">
</div> </div>
<div> <div class="inputRow">
<label for="event">Event</label> <label for="event">Event</label>
<input id="event" type="text" name="event" placeholder="When we need it" <input id="event" type="text" name="event" placeholder="When we need it"
value="{{ I.event }}"> value="{{ I.event }}">
</div> </div>
<div> <div class="inputRow">
<label for="committee">Committee or Budget</label> <label for="committee">Committee or Budget</label>
<select name="committee" id="committee"> <select name="committee" id="committee">
{% for C in committees %} {% for C in committees %}
@@ -36,29 +35,26 @@
</select> </select>
</div> </div>
<div> <div class="inputRow">
<label for="cost">Cost</label> <label for="cost">Cost</label>
<input id="cost" type="text" name="cost" placeholder="15.00" <input id="cost" type="text" name="cost" placeholder="15.00"
value="{{ I.cost }}"> value="{{ I.cost }}">
</div> </div>
<div> <div class="inputRow">
<label for="date">Date Purchased</label> <label for="date">Date Purchased</label>
<input id="date" type="date" name="date" placeholder="mm/dd/yyyy" <input id="date" type="date" name="date" placeholder="mm/dd/yyyy"
value="{{ I.date_purchased }}"> value="{{ I.date_purchased }}">
</div> </div>
<div class="clear"> <div class="inputRow">
<div>
<label for="details">Details</label> <label for="details">Details</label>
<textarea id="details" name="details" rows="4" class="clear">{{ I.details }}</textarea> <textarea id="details" name="details" rows="4">{{ I.details }}</textarea>
</div>
</div> </div>
<div class="clear"> <div class="editActions">
<div> <a href="/items" class="btn">Back</a>
<input type="submit"> <input type="submit" class="btn">
</div>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -1,6 +1,6 @@
Hey {{ to }}, Hey {{ to }},{% if html %}<br><br>{% endif %}
Please review and then approve or reject the request from {{ submitter }} for {{ I.event }}: {{ I.desc }} by going to {% if html %}<a href="http://fincom.delt.space/items/{{ I.pk }}">{% endif %}http://fincom.delt.space/items/{{ I.pk }}{% if html %}</a>.<br><br>{% endif %} Please review and then approve or reject the request from {{ submitter }} for {{ I.event }}: {{ I.desc }} by going to {% if html %}<a href="https://fincom.delt.space/items/{{ I.pk }}">{% endif %}https://fincom.delt.space/items/{{ I.pk }}{% if html %}</a>.<br><br>{% endif %}
{% if html %} {% if html %}
<div style="padding: 8px 36px; border: 1px solid #969499; box-sizing: border-box; width: 100%;"> <div style="padding: 8px 36px; border: 1px solid #969499; box-sizing: border-box; width: 100%;">
@@ -18,7 +18,7 @@ Please review and then approve or reject the request from {{ submitter }} for {{
{% endif %} {% endif %}
${{ I.cost|floatformat:"2" }} ${{ I.cost|floatformat:"2" }}
</div> </div>
<a href="/items/{{ I.pk }}" style="text-decoration: none;"> <a href="https://fincom.delt.space/items/{{ I.pk }}" style="text-decoration: none;">
<div style="margin: 8px 0; font-size: 16px; font-weight: ligher; color: #252526; padding: 0px;"> <div style="margin: 8px 0; font-size: 16px; font-weight: ligher; color: #252526; padding: 0px;">
<b style="color: #4b4a4d;">{{ I.event }}:</b> <b style="color: #4b4a4d;">{{ I.event }}:</b>
{{ I.desc }} {{ I.desc }}
@@ -30,7 +30,7 @@ Please review and then approve or reject the request from {{ submitter }} for {{
</a> </a>
<div style="color: #969499; font-size: 12px; margin: 0px;"> <div style="color: #969499; font-size: 12px; margin: 0px;">
{% if I.approved or I.processed %} {% if I.approved or I.processed %}
Approved By: Approved By:
{% for u in I.approved_by.all %} {% for u in I.approved_by.all %}
{{ u.first_name }} {{ u.last_name }} {{ u.first_name }} {{ u.last_name }}
{% endfor %} {% endfor %}

View File

@@ -1,18 +1,20 @@
<div class="item"> <div class="item">
<div class="committee"> <div class="committeeAndCost">
{{ I.comName }} <div class="committee">
</div> {{ I.comName }}
{% 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> </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>
</div>
<a href="/items/{{ I.pk }}"> <a href="/items/{{ I.pk }}">
<div class="details-row"> <div class="details-row">
<b>{{ I.event }}:</b> <b>{{ I.event }}:</b>

View File

@@ -5,27 +5,23 @@
{% block main %} {% block main %}
<div> <div>
<h1>Add New Reimbursements</h1> <h1>New Reimbursement</h1>
<hr> <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"> <form action="/items/new" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<div> <div class="inputRow">
<label for="desc">Item</label> <label for="desc">Item</label>
<input id="desc" type="text" name="desc" placeholder="What you bought"> <input id="desc" type="text" name="desc" placeholder="What you bought">
</div> </div>
<div> <div class="inputRow">
<label for="event">Event</label> <label for="event">Event</label>
<input id="event" type="text" name="event" placeholder="When we need it"> <input id="event" type="text" name="event" placeholder="When we need it">
</div> </div>
<div> <div class="inputRow">
<label for="committee">Committee or Budget</label> <label for="committee">Committee or Budget</label>
<select name="committee" id="committee"> <select name="committee" id="committee">
<option disabled selected>Select a committee</option> <option disabled selected>Select a committee</option>
@@ -35,32 +31,34 @@
</select> </select>
</div> </div>
<div> <div class="inputRow">
<label for="cost">Cost</label> <label for="cost">Cost</label>
<input id="cost" type="text" name="cost" placeholder="15.00"> <input id="cost" type="text" name="cost" placeholder="15.00">
</div> </div>
<div> <div class="inputRow">
<label for="date">Date Purchased</label> <label for="date">Date Purchased</label>
<input id="date" type="date" name="date" placeholder="mm/dd/yyyy"> <input id="date" type="date" name="date" placeholder="mm/dd/yyyy">
</div> </div>
<div class="clear"> <div class="inputRow">
<div>
<label for="details">Details</label> <label for="details">Details</label>
<textarea id="details" name="details" rows="4" class="clear"></textarea> <textarea id="details" name="details" rows="4"></textarea>
</div>
</div> </div>
<div> <div class="inputRow">
<label for="image">Receipt</label> <label for="image">Receipt</label>
<input type="file" name="image" id="image" accept="image/*"> <input type="file" name="image" id="image" accept="image/*">
</div> </div>
<div class="clear"> <div class="notes">
<div> Make sure all information is accurate, you submit an itemized receipt, and
<input type="submit"> you select the correct committee.
</div> </div>
<div class="editActions">
<a href="/items" class="btn">Back</a>
<input type="submit" class="btn">
</div> </div>
</form> </form>
</div> </div>

View File

@@ -3,20 +3,22 @@
{% for I in items %} {% for I in items %}
{% include "./item.html" %} {% include "./item.html" %}
{% empty %} {% empty %}
<div class="empty">No Reimbursements</div> <div class="emptyItems">No Reimbursements</div>
{% endfor %} {% endfor %}
{% if items.has_next %} <div class="pagination">
<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 %} {% if items.has_previous %}
<a class="page" href="?{{ pagination_key }}={{ items.previous_page_number }}"> <a class="page" href="?{{ pagination_key }}={{ items.previous_page_number }}">
&larr; Newer &larr; Newer
</a> </a>
{% else %} {% else %}
<a class="page empty" href="#">&larr; Newer</a> <a class="page empty">&larr; Newer</a>
{% endif %} {% endif %}
{% if items.has_next %}
<a class="page" href="?{{ pagination_key }}={{ items.next_page_number }}">
Older &rarr;
</a>
{% else %}
<a class="page empty">Older &rarr;</a>
{% endif %}
</div>
</div> </div>