summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2019-01-13 11:51:02 -0600
committerluxagraf <sng@luxagraf.net>2019-01-13 11:51:02 -0600
commitc4da428fc9ec439389b7473ba5638d9f82085475 (patch)
tree2c135804e201b3008fe56db25d993881a49da686
parent120021d565eefa0318c487f0ff5707c7b9893b43 (diff)
updated income and resume apps
-rw-r--r--app/income/models.py13
-rw-r--r--app/income/parser.py42
-rw-r--r--app/income/views.py14
-rw-r--r--app/resume/admin.py18
-rw-r--r--app/resume/migrations/0004_job_resume.py37
-rw-r--r--app/resume/migrations/0005_job_slug.py18
-rw-r--r--app/resume/migrations/0006_auto_20190112_1257.py22
-rw-r--r--app/resume/migrations/0007_auto_20190113_1128.py18
-rw-r--r--app/resume/migrations/0008_auto_20190113_1139.py24
-rw-r--r--app/resume/migrations/0009_job_body_html.py18
-rw-r--r--app/resume/migrations/0010_auto_20190113_1147.py25
-rw-r--r--app/resume/models.py37
-rw-r--r--app/resume/urls.py29
-rw-r--r--app/resume/views.py10
-rw-r--r--app/utils/util.py11
-rw-r--r--design/sass/pdf_gen.scss140
-rw-r--r--design/templates/archives/notes.html6
-rw-r--r--design/templates/details/invoice.html97
-rw-r--r--design/templates/details/pubs.html23
-rw-r--r--design/templates/details/resume.html163
20 files changed, 700 insertions, 65 deletions
diff --git a/app/income/models.py b/app/income/models.py
index 688d1d7..e5a351b 100644
--- a/app/income/models.py
+++ b/app/income/models.py
@@ -69,6 +69,9 @@ class InvoiceItem(models.Model):
time_end = models.DateTimeField(null=True, blank=True)
work_done = models.TextField(null=True, blank=True)
+ class Meta:
+ ordering = ('time_start',)
+
def __str__(self):
return str(self.time_start)
@@ -89,6 +92,12 @@ class InvoiceItem(models.Model):
half_period_seconds = period_seconds / 2
remainder = td.total_seconds() % period_seconds
if remainder >= half_period_seconds:
- return timedelta(seconds=td.total_seconds() + (period_seconds - remainder))
+ tdr = timedelta(seconds=td.total_seconds() + (period_seconds - remainder))
+ hours, remainder = divmod(tdr.total_seconds(), 3600)
+ r = remainder/3600
+ return float(hours)+r
else:
- return timedelta(seconds=td.total_seconds() - remainder)
+ tdr = timedelta(seconds=td.total_seconds() - remainder)
+ hours, remainder = divmod(tdr.total_seconds(), 3600)
+ r = remainder/3600
+ return float(hours)+r
diff --git a/app/income/parser.py b/app/income/parser.py
index 9524902..b19d039 100644
--- a/app/income/parser.py
+++ b/app/income/parser.py
@@ -1,19 +1,23 @@
-with open('timesheet.csv', newline='') as csvfile:
- reader = csv.reader(csvfile, delimiter=';')
- counter = 0
- f = "%Y-%m-%d %H:%M:%S"
- for row in reader:
- if counter > 0:
- timer = row[0]+' '+row[1]
- timerer = row[0]+' '+row[2]
- time_start = datetime.datetime.strptime(timer, f)
- time_end = datetime.datetime.strptime(timerer, f)
- print(row[4])
- print(timerer, time_end)
- InvoiceItem.objects.get_or_create(
- time_start=time_start,
- time_end=time_end,
- work_done=row[4]
- )
- counter = counter +1
-f = "%Y-%m-%d %H:%M:%S"
+import csv
+import datetime
+from .models import InvoiceItem
+
+
+def read_timesheet():
+ with open('timesheet.csv', newline='') as csvfile:
+ reader = csv.reader(csvfile, delimiter=';')
+ counter = 0
+ f = "%Y-%m-%d %H:%M:%S"
+ for row in reader:
+ if counter > 0:
+ print(row[4])
+ timer = row[0]+' '+row[1]
+ timerer = row[0]+' '+row[2]
+ time_start = datetime.datetime.strptime(timer, f)
+ time_end = datetime.datetime.strptime(timerer, f)
+ InvoiceItem.objects.get_or_create(
+ time_start=time_start,
+ time_end=time_end,
+ work_done=row[4]
+ )
+ counter = counter + 1
diff --git a/app/income/views.py b/app/income/views.py
index 2c3e34a..fc22c0d 100644
--- a/app/income/views.py
+++ b/app/income/views.py
@@ -20,8 +20,7 @@ class MonthlyInvoiceView(DetailView):
total_time = []
for item in context['object_list']:
total_time.append(item.rounded_total)
- duration = (sum(total_time, datetime.timedelta()))
- hours = duration.total_seconds() // 3600
+ hours = (sum(total_time))
context['total_hours'] = hours
context['total_billed'] = int(hours * 100)
context['invoice_number'] = self.object.id+21
@@ -37,10 +36,17 @@ class DownloadMonthlyInvoiceView(MonthlyInvoiceView):
logger = logging.getLogger('weasyprint')
logger.addHandler(logging.FileHandler('weasyprint.log'))
self.object = self.get_object() # assign the object to the view
- c = {'object': self.object}
+ context = self.get_context_data()
+ c = {
+ 'object': self.object,
+ 'object_list': context['object_list'],
+ 'total_hours': context['total_hours'],
+ 'total_billed': context['total_billed'],
+ 'invoice_number': self.object.id+23
+ }
t = render_to_string('details/invoice.html', c).encode('utf-8')
html = HTML(string=t, base_url=self.request.build_absolute_uri())
- pdf = html.write_pdf(stylesheets=[CSS(settings.MEDIA_ROOT + 'site/media/pdf_gen.css')], presentational_hints=True)
+ pdf = html.write_pdf(stylesheets=[CSS(settings.MEDIA_ROOT + '/pdf_gen.css')], presentational_hints=True)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'inline; filename="invoice.pdf"'
return response
diff --git a/app/resume/admin.py b/app/resume/admin.py
index 93b186e..0a7594d 100644
--- a/app/resume/admin.py
+++ b/app/resume/admin.py
@@ -1,15 +1,23 @@
from django.contrib import admin
-from .models import Publisher, PubItem
+from .models import Publisher, PubItem, Job, Resume
-class PublisherAdmin(admin.ModelAdmin):
+@admin.register(Job)
+class JobAdmin(admin.ModelAdmin):
+ pass
+
+
+@admin.register(Resume)
+class ResumeAdmin(admin.ModelAdmin):
pass
+@admin.register(Publisher)
+class PublisherAdmin(admin.ModelAdmin):
+ pass
+
+@admin.register(PubItem)
class PubItemAdmin(admin.ModelAdmin):
list_display = ('title', 'pub_date', 'publisher', 'admin_link')
pass
-
-admin.site.register(Publisher, PublisherAdmin)
-admin.site.register(PubItem, PubItemAdmin)
diff --git a/app/resume/migrations/0004_job_resume.py b/app/resume/migrations/0004_job_resume.py
new file mode 100644
index 0000000..e056fec
--- /dev/null
+++ b/app/resume/migrations/0004_job_resume.py
@@ -0,0 +1,37 @@
+# Generated by Django 2.1.1 on 2019-01-12 12:45
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0003_auto_20151211_1925'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Job',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=200)),
+ ('employer', models.CharField(max_length=200)),
+ ('date_start', models.DateField(verbose_name='Date Start')),
+ ('date_end', models.DateField(blank=True, null=True, verbose_name='Date End')),
+ ('body_markdown', models.TextField(blank=True, null=True)),
+ ],
+ options={
+ 'ordering': ('-date_end',),
+ },
+ ),
+ migrations.CreateModel(
+ name='Resume',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=200)),
+ ('profile', models.TextField()),
+ ('skills', models.TextField()),
+ ('experience', models.ManyToManyField(to='resume.Job')),
+ ],
+ ),
+ ]
diff --git a/app/resume/migrations/0005_job_slug.py b/app/resume/migrations/0005_job_slug.py
new file mode 100644
index 0000000..d18baeb
--- /dev/null
+++ b/app/resume/migrations/0005_job_slug.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.1 on 2019-01-12 12:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0004_job_resume'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='job',
+ name='slug',
+ field=models.CharField(blank=True, max_length=50),
+ ),
+ ]
diff --git a/app/resume/migrations/0006_auto_20190112_1257.py b/app/resume/migrations/0006_auto_20190112_1257.py
new file mode 100644
index 0000000..9ee8f1b
--- /dev/null
+++ b/app/resume/migrations/0006_auto_20190112_1257.py
@@ -0,0 +1,22 @@
+# Generated by Django 2.1.1 on 2019-01-12 12:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0005_job_slug'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='job',
+ name='slug',
+ ),
+ migrations.AddField(
+ model_name='resume',
+ name='slug',
+ field=models.CharField(blank=True, max_length=50),
+ ),
+ ]
diff --git a/app/resume/migrations/0007_auto_20190113_1128.py b/app/resume/migrations/0007_auto_20190113_1128.py
new file mode 100644
index 0000000..a635258
--- /dev/null
+++ b/app/resume/migrations/0007_auto_20190113_1128.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.1 on 2019-01-13 11:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0006_auto_20190112_1257'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='job',
+ name='employer',
+ field=models.CharField(max_length=200, null=True),
+ ),
+ ]
diff --git a/app/resume/migrations/0008_auto_20190113_1139.py b/app/resume/migrations/0008_auto_20190113_1139.py
new file mode 100644
index 0000000..29d975d
--- /dev/null
+++ b/app/resume/migrations/0008_auto_20190113_1139.py
@@ -0,0 +1,24 @@
+# Generated by Django 2.1.1 on 2019-01-13 11:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0007_auto_20190113_1128'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='resume',
+ old_name='experience',
+ new_name='jobs',
+ ),
+ migrations.AlterField(
+ model_name='job',
+ name='employer',
+ field=models.CharField(blank=True, default='', max_length=200),
+ preserve_default=False,
+ ),
+ ]
diff --git a/app/resume/migrations/0009_job_body_html.py b/app/resume/migrations/0009_job_body_html.py
new file mode 100644
index 0000000..fdeea15
--- /dev/null
+++ b/app/resume/migrations/0009_job_body_html.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.1.1 on 2019-01-13 11:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0008_auto_20190113_1139'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='job',
+ name='body_html',
+ field=models.TextField(blank=True, null=True),
+ ),
+ ]
diff --git a/app/resume/migrations/0010_auto_20190113_1147.py b/app/resume/migrations/0010_auto_20190113_1147.py
new file mode 100644
index 0000000..879bd55
--- /dev/null
+++ b/app/resume/migrations/0010_auto_20190113_1147.py
@@ -0,0 +1,25 @@
+# Generated by Django 2.1.1 on 2019-01-13 11:47
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('resume', '0009_job_body_html'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='job',
+ name='body_html',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ migrations.AlterField(
+ model_name='job',
+ name='body_markdown',
+ field=models.TextField(blank=True, default=''),
+ preserve_default=False,
+ ),
+ ]
diff --git a/app/resume/models.py b/app/resume/models.py
index 68f9a7e..390a277 100644
--- a/app/resume/models.py
+++ b/app/resume/models.py
@@ -1,6 +1,7 @@
from django.db import models
from django.utils.encoding import force_text
from django.urls import reverse
+from django.template.defaultfilters import slugify
from utils.util import markdown_to_html
@@ -53,3 +54,39 @@ class PubItem(models.Model):
if self.body_markdown:
self.body_html = markdown_to_html(self.body_markdown)
super(PubItem, self).save()
+
+
+class Job(models.Model):
+ title = models.CharField(max_length=200)
+ employer = models.CharField(max_length=200, blank=True)
+ date_start = models.DateField('Date Start')
+ date_end = models.DateField('Date End', null=True, blank=True)
+ body_markdown = models.TextField(blank=True)
+ body_html = models.TextField(blank=True)
+
+ class Meta:
+ ordering = ('-date_end',)
+
+ def __str__(self):
+ return '{} - {}'.format(self.title, self.employer) # py3.1+ only
+
+ def save(self, *args, **kwargs):
+ if self.body_markdown:
+ self.body_html = markdown_to_html(self.body_markdown)
+ super(Job, self).save()
+
+
+class Resume(models.Model):
+ title = models.CharField(max_length=200)
+ slug = models.CharField(max_length=50, blank=True)
+ profile = models.TextField()
+ skills = models.TextField()
+ jobs = models.ManyToManyField(Job)
+
+ def __str__(self):
+ return self.title
+
+ def save(self, *args, **kwargs):
+ if self._state.adding and not self.slug:
+ self.slug = slugify(self.title)
+ super(Resume, self).save()
diff --git a/app/resume/urls.py b/app/resume/urls.py
index 0d8b40a..47e07ad 100644
--- a/app/resume/urls.py
+++ b/app/resume/urls.py
@@ -1,4 +1,4 @@
-from django.conf.urls import url
+from django.urls import path, re_path
from django.views.generic.base import RedirectView
from . import views
@@ -6,34 +6,39 @@ from . import views
app_name = "resume"
urlpatterns = [
- url(
- r'pubs/(?P<page>\d+)/$',
+ path(
+ r'<str:slug>',
+ views.ResumeView.as_view(),
+ name='resume',
+ ),
+ path(
+ r'pubs/<str:page>/',
views.PublisherListView.as_view(),
name='list',
),
- url(
- r'pubs/(?P<publisher>[-\w]+)/(?P<page>\d+)/$',
+ path(
+ r'pubs/<str:publisher>/<str:page>/',
views.ByPublisherListView.as_view(),
name='list_by_publisher',
),
- url(
- r'pubs/(?P<publisher>[-\w]+)/(?P<slug>[-\w]+)$',
+ path(
+ r'pubs/<str:publisher>/<str:slug>',
views.PubItemDetailView.as_view(),
name='detail',
),
# redirect /slug/ to /slug/1/ for live server
- url(
+ path(
r'pubs/(?P<publisher>[-\w]+)/$',
RedirectView.as_view(url="/resume/pubs/%(publisher)s/1/", permanent=False),
name="live_publisher_redirect"
),
- url(
- r'pubs/$',
+ path(
+ r'pubs/',
RedirectView.as_view(url="/resume/pubs/1/", permanent=False),
name="live_redirect"
),
- url(
- r'^(?P<path>[-\w]+)(?:/(?P<slug>[-\w]+))$',
+ path(
+ r'<str:path>/<str:slug>',
views.PageView.as_view(),
name="pages"
),
diff --git a/app/resume/views.py b/app/resume/views.py
index 15acf14..9cdd8e7 100644
--- a/app/resume/views.py
+++ b/app/resume/views.py
@@ -2,7 +2,7 @@ from django.views.generic.detail import DetailView
from django.views.generic.base import TemplateView
from utils.views import PaginatedListView
-from .models import PubItem, Publisher
+from .models import PubItem, Publisher, Resume
from pages.models import Page
@@ -32,9 +32,10 @@ class ByPublisherListView(PaginatedListView):
context['publisher'] = Publisher.objects.get(slug=self.kwargs['publisher'])
return context
+
class PubItemDetailView(DetailView):
model = PubItem
- template_name = "details/resume.html"
+ template_name = "details/pubs.html"
slug_field = "slug"
@@ -51,3 +52,8 @@ class PageView(DetailView):
def get_template_names(self):
return ["details/%s.html" % self.object.slug, 'details/page.html']
+
+
+class ResumeView(DetailView):
+ model = Resume
+ template_name = "details/resume.html"
diff --git a/app/utils/util.py b/app/utils/util.py
index 6678fc9..714403b 100644
--- a/app/utils/util.py
+++ b/app/utils/util.py
@@ -110,3 +110,14 @@ def parse_video(s):
if soup.find('video'):
return True
return False
+
+def parse_reg_bio_page():
+ content = requests.get("https://www.theregister.co.uk/Author/Scott-Gilbertson/")
+ soup = BeautifulSoup(content, 'html.parser')
+ try:
+ image = soup.find_all('img')[0]['id']
+ img_pk = image.split('image-')[1]
+ return apps.get_model('photos', 'LuxImage').objects.get(pk=img_pk)
+ except IndexError:
+ return None
+
diff --git a/design/sass/pdf_gen.scss b/design/sass/pdf_gen.scss
new file mode 100644
index 0000000..b5072cd
--- /dev/null
+++ b/design/sass/pdf_gen.scss
@@ -0,0 +1,140 @@
+@import "_fonts.scss";
+@import "_mixins.scss";
+
+body {
+ @include fancy_sans;
+}
+.subhead {
+ text-align: right;
+ width: 4cm;
+ float: right;
+ @extend %clearfix;
+ > * {
+ margin: 0;
+ font-weight: 400;
+ }
+}
+header, .row {
+ @extend %clearfix;
+ margin-top: 1cm;
+}
+.print-box {
+ width: 49%;
+ float: left;
+ > * {
+ padding: .125cm;
+ margin: 0;
+ }
+ h5, h4 {
+ @include smcaps;
+ font-size: 9pt;
+ line-height: .5;
+ }
+ h4 {
+ margin-top: -10pt;
+ font-size: 16pt;
+ line-height: 1.5;
+ }
+}
+#bill-from, #bill {
+ border: none;
+ width: 47%;
+ float: left;
+}
+#bill {
+ float: right;
+}
+#bill-to {
+ width: 47%;
+ float: right;
+}
+table {
+ font-family: "Open Sans", sans-serif;
+ line-height: 1;
+ border: 1px solid #ccc;
+ border-collapse: collapse;
+ margin: 1cm 0 0 0;
+ padding: 0;
+ width: 625px;
+}
+table caption {
+ text-align: left;
+ font-size: 10pt;
+ text-transform: uppercase;
+ font-weight: 600;
+ margin: .5em 0 .75em;
+ &:after {
+ content: ":";
+ }
+}
+table tr {
+ border: 1px solid #ddd;
+ padding: .35em;
+}
+table tr.odd { background: #f6f4f4cc;}
+thead {display: table-header-group; }
+table th,
+table td {
+ padding: .625em .625em .625em 1em;
+ text-align: left;
+ border-right: 1px solid #ddd;
+}
+table td {
+ white-space: -o-pre-wrap;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ white-space: -moz-pre-wrap;
+ white-space: -pre-wrap;
+ font-size: 8pt;
+}
+table th {
+ font-size: 7pt;
+ letter-spacing: .1em;
+ text-transform: uppercase;
+ background: #f6f4f4;
+}
+
+table .blank {
+ white-space: normal;
+ td {
+ padding: 1rem;
+ white-space: normal;
+ &:last-of-type {
+ text-align: left;
+ min-width: 1.2cm;
+ }
+ }
+}
+table .right {
+ text-align: right;
+}
+table th a {
+ text-decoration: none;
+ position: relative;
+ span {
+ position: absolute;
+ top: -2px;
+ }
+}
+.smfield { min-width: 50pt;}
+table .total { font-size: 9pt !important;}
+.thanks {
+ margin-top: 40pt;
+ font-family: times, times new roman;
+ font-style: italic;
+ font-weight: 300;
+ text-align: center;
+ color: #333;
+}
+
+@page {
+ @bottom-right{
+ @include fancy_sans;
+ @include smcaps;
+ content: "Page " counter(page) " of " counter(pages);
+ font-size: 6pt;
+ color: #666;
+ width: 2cm;
+ }
+}
+
diff --git a/design/templates/archives/notes.html b/design/templates/archives/notes.html
index 998546f..8dc168e 100644
--- a/design/templates/archives/notes.html
+++ b/design/templates/archives/notes.html
@@ -1,6 +1,7 @@
{% extends 'base.html' %}
{% load typogrify_tags %}
{% load html5_datetime %}
+{% load pagination_tags %}
{% block pagetitle %} Field Notes | luxagraf {% endblock %}
{% block metadescription %} Rough notes and sketches from the field {% endblock %}
{%block bodyid%}class="notes" id="notes-archive"{%endblock%}
@@ -13,7 +14,7 @@
<main role="main">
<h1>Field Notes</h1>
<h4 class="subhead divide-after">Quick notes and images from the road</h4>
- {% for object in object_list %}
+ {% autopaginate object_list 2 %}{% for object in object_list %}
<article class="h-entry">
<h2 class="p-name note--title hide">{{object.title|safe|amp|smartypants}}</h2>
<h5 class="note--date-hed"><a class="u-url" href="{{object.get_absolute_url}}" rel="bookmark"><time class="dt-published" datetime="{{object.pub_date|html5_datetime}}">{{object.pub_date|date:"F j, Y"}}</time></a></h5>
@@ -56,6 +57,9 @@
</article>
{% endfor %}
</main>
+ <nav class="pagination">
+ {% paginate %}
+ </nav>
{% endblock %}
diff --git a/design/templates/details/invoice.html b/design/templates/details/invoice.html
new file mode 100644
index 0000000..1a812c8
--- /dev/null
+++ b/design/templates/details/invoice.html
@@ -0,0 +1,97 @@
+{% load typogrify_tags %}
+
+<!DOCTYPE html>
+<html dir="ltr" lang="en-US">
+<head>
+ <title>Invoice for {{object.title}}</title>
+ <meta charset="utf-8">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="description"
+ content="">
+<style>
+ @page {
+ @bottom-left {
+ content: "";
+ }
+ }
+</style>
+</head>
+ {% load static %}
+<body id="quote">
+ <div class="row">
+ <div class="print-box" id="bill-from">
+ <h5>Bill From:</h5>
+ <p>Scott Gilbertson <br />
+ 1806 Dover Dr. <br />
+ Newport Beach, CA 92660<br />
+ 706-438-4297</p>
+ </div>
+ <div class="print-box" id="bill">
+ <h4>Invoice {{invoice_number}}</h4>
+ <h5>Invoice For: {{object.title}}</h5>
+ <h5>Amount Due: ${{total_billed}}</h5>
+ <h5>Sent on: {% now "M j, Y"%}</h5>
+ </div>
+ </div>
+ <div class="row">
+ <div class="print-box" id="bill-to">
+ <h5>Bill To:</h5>
+ <p>Enterprise Data Resources, Inc.<br />
+ 1089 Culpepper Drive <br />
+ Conyers, GA 30094 <br />
+ 707-973-2862</p>
+ </div>
+ </div>
+ </div>
+<table class="quote-table" id="items_list">
+<thead>
+ <caption>Items</caption>
+<tr>
+<th scope="col" class="sortable column-status">
+ <div class="text">Date</div>
+</th>
+<th scope="col" class="sortable column-created_at sorted descending">
+ <div class="text">Time</div>
+</th>
+<th scope="col" class="sortable column-repair_state">
+ <div class="text">Hours</div>
+</th>
+<th scope="col" class="sortable column-order_id">
+ <div class="text">Tasks</div>
+</th>
+</tr>
+</thead>
+<tbody>
+ {% for obj in object_list %}
+ <tr class="row{{forloop.counter}} {% cycle 'odd' 'even' %}">
+ <td class="smfield" data-label="">{{obj.time_start|date:"m/d/y"}}</td>
+ <td class="smfield" data-label="Serial" >{{obj.time_start|date:"g:i"}} - {{obj.time_end|date:"g:i"}}</td>
+ <td class="smfield" data-label="Serial" >{{obj.rounded_total}}</td>
+ <td class="field" data-label="Issue" >{{obj.work_done|capfirst}}</td>
+ </tr>
+ {%endfor%}
+ <tr class="row gap">
+ </tr>
+ <tr class="row2">
+ <td class="field-payment_status"></td>
+ <td class="field-pub_date nowrap"></td>
+ <th class="field-title">Total Hours:</th>
+ <td class="field-status">{{total_hours}}</td>
+ </tr>
+ <tr class="row2">
+ <td class="field-payment_status"></td>
+ <td class="field-pub_date nowrap"></td>
+ <th class="field-title">Rate:</th>
+ <td class="field-status">$100/hr</td>
+ </tr>
+ <tr class="row2">
+ <td class="field-payment_status"></td>
+ <td class="field-pub_date nowrap"></td>
+ <th class="field-title total">Total for Invoice:</th>
+ <td class="field-status total"><b>${{total_billed}}</b></td>
+ </tr>
+</tbody>
+</table>
+<p class="thanks">Thank you for your prompt payment</p>
+</body>
diff --git a/design/templates/details/pubs.html b/design/templates/details/pubs.html
new file mode 100644
index 0000000..ff16bbe
--- /dev/null
+++ b/design/templates/details/pubs.html
@@ -0,0 +1,23 @@
+{% extends 'base.html' %}
+{% load typogrify_tags %}
+
+{% block pagetitle %}{% endblock %}
+{% block metadescription %}{% endblock %}
+
+{%block htmlclass%}class="detail{%endblock%}
+
+{% block primary %}<ul class="bl" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
+ <li><a href="/" title="luxagraf homepage" itemprop="url"><span itemprop="title">Home</span></a> &rarr; </li>
+ <li><a href="/resume">Resume</a>{% if object.title != "Resume" %} &rarr; {%endif%}</li>
+ {% if object.title != "Resume" %}<li><a href="/resume/pubs/">Publications</a></li>{%endif%}
+ </ul>
+ <main>
+ <article>
+ {% if object.title != "Resume" %}<h1 class="post-header">{{object.title|safe|smartypants|widont}}</h1>{% endif %}
+ {% if object.publisher %}<p><i>This article was published in {{object.publisher}}, you can view <a href="{{object.url}}">the original</a> there, complete with graphics, comments and other fun stuff.</i></p>{% endif %}
+ <div class="post-article" style="margin-top: 3em">
+ {{object.body_html|safe|smartypants|widont}}
+ </div>
+ </article>
+ </main>
+ {%endblock%}
diff --git a/design/templates/details/resume.html b/design/templates/details/resume.html
index ff16bbe..611765c 100644
--- a/design/templates/details/resume.html
+++ b/design/templates/details/resume.html
@@ -1,23 +1,146 @@
{% extends 'base.html' %}
{% load typogrify_tags %}
+{% block pagetitle %}Scott Gilbertson - Curriculum Vitæ{%endblock%}
+{% block extrahead%}
+ <meta name="twitter:card" content="summary">
+ <meta name="twitter:title" content="Curriculum Vitæ">
+ <meta name="twitter:description" content="luxagraf.net is the personal web site of Scott gilbertson.">
+ <meta name="twitter:site:id" content="9469062">
+ <meta name="twitter:creator:id" content="9469062">
+ <meta property="og:type" content="article"/>
+ <meta property="og:title" content="Scott Gilbertson - Curriculum Vitæ"/>
+ <meta property="og:url" content="http://luxagraf.net/resume/cv"/>
+ <meta property="og:description" content="luxagraf.net is the personal web site of Scott gilbertson.">
+ <meta property="article:author" content="Scott Gilbertson"/>
+ <meta property="og:site_name" content="luxagraf.net"/>
+ <meta property="og:locale" content="en_US"/>
+<style>
+</style>{%endblock%}
+{%block bodyid%}class="resume"{%endblock%}
+{%block htmlclass %}class="detail"{%endblock%}
+{% block primary %}
+<main role="main" id="content">
+<article class="h-resume">
+ <div class="h-card head">
+ <header>
+ <h1 class="p-name">
+ <span class="p-given-name">Scott</span>
+ <span class="p-additional-name hide">Nathan</span>
+ <span class="p-family-name">Gilbertson</span>
+ </h1>
+ <h2>Writer, Photographer, Web Developer</h2>
+ </header>
+ <ul class="contact">
+ <li>
+ <h6>Phone</h6>
+ <span><a class="u-tel" href="tel:706-438-4297">706-438-4297</a></span>
+ </li>
+ <li>
+ <h6>Email</h6>
+ <a class="u-email" href="mailto:sng@luxagraf.net">sng@luxagraf.net</a>
+ </li>
+ <li>
+ <h6>Web</h6>
+ <span><a class="u-url" href="https://luxagraf.net/" rel="me">https://luxagraf.net/</a></span>
+ </li>
+ <li>
+ <h6>LinkedIn</h6>
+ <span><a class="u-url" href="https://www.linkedin.com/in/luxagraf" rel="me">luxagraf</a></span>
+ </li>
+ </ul>
+ </div>
+ <div class="profile">
+ <h3>Profile</h3>
+ <p class="p-summary">I am a writer, producer and web developer based in Athens, GA. Clients include Wired, Webmonkey, Ars Technica, Pioneer and Boost Mobile, among others. I wrote for Wired.com&#8217;s Webmonkey.com for 13 years and served as head editor for three. I&#8217;ve been developing on the web and writing about web development for nearly two decades. For an up-to-date list of recent articles, please browse <a href="/resume/pubs/">the publications list</a>.</p>
+ </div>
-{% block pagetitle %}{% endblock %}
-{% block metadescription %}{% endblock %}
-
-{%block htmlclass%}class="detail{%endblock%}
-
-{% block primary %}<ul class="bl" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
- <li><a href="/" title="luxagraf homepage" itemprop="url"><span itemprop="title">Home</span></a> &rarr; </li>
- <li><a href="/resume">Resume</a>{% if object.title != "Resume" %} &rarr; {%endif%}</li>
- {% if object.title != "Resume" %}<li><a href="/resume/pubs/">Publications</a></li>{%endif%}
- </ul>
- <main>
- <article>
- {% if object.title != "Resume" %}<h1 class="post-header">{{object.title|safe|smartypants|widont}}</h1>{% endif %}
- {% if object.publisher %}<p><i>This article was published in {{object.publisher}}, you can view <a href="{{object.url}}">the original</a> there, complete with graphics, comments and other fun stuff.</i></p>{% endif %}
- <div class="post-article" style="margin-top: 3em">
- {{object.body_html|safe|smartypants|widont}}
- </div>
- </article>
- </main>
- {%endblock%}
+ <div id="skills">
+ <h3>Skills</h3>
+
+ <h2><a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Writing">Writing</a></h2>
+ <p>Freelance writer, producer, journalist, editor and hand model at places like Wired, Ars Technica, Budget Travel. I&#8217;ve written blogs, features, news items, ad copy, technical documentation, tutorials, how-tos, wikis and probably other things I&#8217;ve forgotten about. I also served as editor-in-chief of Webmonkey.com.</p>
+
+ <h2><a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Web_development">Web Development</a></h2>
+ <p>Expert front-end engineer in <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Web_standards">standards-based web development</a> using <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/HTML"><abbr title="Hypertext Markup Language">HTML</abbr></a>, <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets"><abbr title="Cascading Style Sheets">CSS</abbr></a>, and high performance <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/JavaScript">JavaScript</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Responsive_web_design">responsive design</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Progressive_enhancement">progressive enhancement</a>, <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Microformats">microformats</a>, <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/ARIA">ARIA</a> and more. </p>
+ <p>Experience maintaining large-scale web applications and tools with <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a> and <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/PHP">PHP</a> in conjunction with databases like <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/PostgreSQL">PostgreSQL</a> (including numerous PostGIS, geographic database projects), <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/MySQL">MySQL</a>, <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Sqlite">Sqlite</a>. Experience administering <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Linux">Linux </a> servers and running web servers like <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Apache_HTTP_Server">Apache</a>, and <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Nginx">Nginx</a>.</p>
+ <p>Advocate and evangelist for free software and open web standards technologies such as <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/HTML5">HTML5</a>, related APIs, <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Cascading_Style_Sheets">CSS3</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Responsive_web_design">responsive design</a> (including <a href="https://longhandpixels.net/books/responsive-web-design">a 350 page book on the subject</a>) and <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Progressive_enhancement">progressive enhancement</a>.</p>
+
+ <h2><a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Graphic_design">Photography/Video/Design</a></h2>
+ <p>Good design eye specializing in fluid, clean layouts with strong <a class="p-skill" rel="tag" href="http://en.wikipedia.org/wiki/Typography">typographic style</a>. </p>
+ <p>Photo and video editing using <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Adobe_Photoshop">Photoshop</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/GIMP">GIMP</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Adobe_Photoshop_Lightroom">Lightroom</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Darktable">Darktable</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Final_Cut_Pro">Final Cut Pro</a>, and <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Kdenlive">Kdenlive</a>.</p>
+
+ </div>
+
+ <div class="h-calendar" id="experience">
+ <h3>Experience</h3>{% for job in object.jobs.all %}
+ <div class="p-experience h-event">
+ <h2 class="p-name">{{job.title}}</h2>
+ <ul class="meta">
+ <li>(<time class="dt-start" datetime="{{job.date_start}}">{{job.date_start|date:"M Y"}}</time>–{% if job.date_end %}<time class="dt-end" datetime="{{job.date_end}}">{{job.date_end|date:"M Y"}}</time>{%else%}<span class="dt-end">present</span>{%endif%})</li>
+ </ul>
+ <p class="e-description">{{job.body_html|safe}}</p>
+ </div>{% endfor %}
+
+ {%comment%}
+ <div class="p-experience h-event">
+ <h2 class="p-name">Web Developer</h2>
+ <ul class="meta">
+ <li>(<time class="dt-start" datetime="2004-06-01">June 2004</time>–Present)
+ </li>
+ </ul>
+ <p class="e-description">Co-founded a small design company where I serve as front-end web developer. I work closely with my co-founder (lead UI/UX), transforming visual designs into valid, semantic HTML/CSS/JavaScript. We specialize in responsive designs and mobile-friendly content that works across browsers and devices. Clients included Wired, Pioneer Entertainment, Boost Mobile, Co-op Credit Union and others.</p>
+ </div>
+
+ <div class="p-experience h-event">
+ <h2 class="p-name">Founder, LongHandPixels Press</h2>
+ <ul class="meta">
+ <li>(<time class="dt-start" datetime="2013-09-01">September 2013</time>–Present)
+ </li>
+ </ul>
+ <p class="e-description">Founded an ebook publishing company, <a href="http://longhandpixels.net/" class="p-organization-name">LongHandPixels Press</a> and launched my first book, <em><a href="https://longhandpixels.net/books/responsive-web-design">Build a Better Web with Responsive Web Design</a></em>. The book covers responsive design, mobile-first web development, progressive enhancement and how modern tools like Sass, Grunt, Node, the Chrome developer tools and more can speed up workflows.
+ </p>
+ </div>
+
+ <div class="p-experience h-event">
+ <h2 class="p-name">Writer/Editor Webmonkey.com</h2>
+ <ul class="meta">
+ <li class="h-location h-card">
+ <a class="u-url p-name" href="http://webmonkey.com">
+ <span class="p-organization-name">Wired.com</span>/
+ <span class="p-organization-unit">Webmonkey.com</span></a>
+ </li>
+ <li>(<time class="dt-start" datetime="2006-06-01">June 2006</time>
+ –<time class="dt-end" datetime="2013-04-31">April 2013</time>)
+ </li>
+ </ul>
+ <p class="e-description">I started contributing tutorials to Wired.com&#8217;s Webmonkey.com in 1999, became a full time employee in 2006 and served as editor-in-chief from 2010 to 2013. I was in charge of creating resources for web developers, including how-to guides on the latest in web standards, code libraries, server technologies and authoring resources. Wrote roughly 3 million words on various web development tools. I also helped cultivate and manage a global team of freelance contributors.</p>
+ </div>
+
+ <div class="p-experience h-event">
+ <h2 class="p-name">Photography and Video Editing</h2>
+ <ul class="meta">
+ <li class="h-location h-card"><a class="u-url p-name" href="http://barrelmanproductions.com"><span class="p-organization-name">barrelmanproductions.com</span></a></li>
+ <li>(<time class="dt-start" datetime="2006-06-01">June 2014</time> - Present)</li>
+ </ul>
+ <p class="e-description">Co-founded a video editing company, Barrelman Productions, specializing in HD aerial video. Portfolio and highlights reel available at <a href="http://www.barrelmanproductions.com/">http://www.barrelmanproductions.com/</a>. Skills include editing in <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Final_Cut_Pro">Final Cut Pro</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Adobe_Photoshop">Photoshop</a>, <a class="p-skill" rel="tag" href="https://en.wikipedia.org/wiki/Adobe_Photoshop_Lightroom">Lightroom</a> and production of web-optimized video.</p>
+ </div>
+ {%endcomment%}
+
+ </div>
+ <div class="h-calendar" id="education">
+ <h3>Education</h3>
+
+ <div class="p-education h-event">
+ <h2 class="p-name">Bachelor of Arts, English</h2>
+ <ul class="meta">
+ <li>Undergraduate degree from <a class="p-location h-card" href="http://uga.edu/">The University of <span class="p-locality">Georgia</span>.</a></li>
+ <li>(<time class="dt-start" title="2001-08-01">2001</time>–<time class="dt-end" title="2003-12-16">2003</time>)</li>
+ </ul>
+ </div>
+
+ </div>
+
+</article>
+
+</main>
+{%endblock%}