Cleanup
This commit is contained in:
parent
3900075ab4
commit
4ba10fb739
|
@ -14,38 +14,11 @@ import math
|
||||||
APPROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
|
APPROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
|
||||||
|
|
||||||
|
|
||||||
class PhotosWeb(object):
|
def auth():
|
||||||
def __init__(self, library, template_dir):
|
return cherrypy.session.get('authed', None)
|
||||||
self.library = library
|
|
||||||
self.tpl = Environment(loader=FileSystemLoader(template_dir),
|
|
||||||
autoescape=select_autoescape(['html', 'xml']))
|
|
||||||
self.tpl.globals.update(mime2ext=self.mime2ext)
|
|
||||||
self.tpl.filters['basename'] = os.path.basename
|
|
||||||
self.tpl.filters['ceil'] = math.ceil
|
|
||||||
self.thumb = ThumbnailView(self)
|
|
||||||
self.photo = PhotoView(self)
|
|
||||||
self.download = DownloadView(self)
|
|
||||||
self.date = DateView(self)
|
|
||||||
self.tag = TagView(self)
|
|
||||||
self.album = self.tag
|
|
||||||
|
|
||||||
def render(self, template, **kwargs):
|
|
||||||
return self.tpl.get_template(template).render(**kwargs, **self.get_default_vars())
|
|
||||||
|
|
||||||
def get_default_vars(self):
|
def mime2ext(mime):
|
||||||
s = self.session()
|
|
||||||
ret = {
|
|
||||||
"all_tags": s.query(Tag).order_by(Tag.title).all(),
|
|
||||||
"all_albums": s.query(Tag).filter(Tag.is_album == True).order_by(Tag.title).all(),
|
|
||||||
"path": cherrypy.request.path_info
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def session(self):
|
|
||||||
return self.library.session()
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def mime2ext(mime):
|
|
||||||
return {"image/png": "png",
|
return {"image/png": "png",
|
||||||
"image/jpeg": "jpg",
|
"image/jpeg": "jpg",
|
||||||
"image/gif": "gif",
|
"image/gif": "gif",
|
||||||
|
@ -54,12 +27,62 @@ class PhotosWeb(object):
|
||||||
"video/mp4": "mp4",
|
"video/mp4": "mp4",
|
||||||
"video/quicktime": "mov"}[mime]
|
"video/quicktime": "mov"}[mime]
|
||||||
|
|
||||||
|
|
||||||
|
class PhotosWeb(object):
|
||||||
|
def __init__(self, library, template_dir):
|
||||||
|
self.library = library
|
||||||
|
|
||||||
|
self.tpl = Environment(loader=FileSystemLoader(template_dir),
|
||||||
|
autoescape=select_autoescape(['html', 'xml']))
|
||||||
|
self.tpl.filters['mime2ext'] = mime2ext
|
||||||
|
self.tpl.filters['basename'] = os.path.basename
|
||||||
|
self.tpl.filters['ceil'] = math.ceil
|
||||||
|
self.tpl.filters['statusstr'] = lambda x: str(x).split(".")[-1]
|
||||||
|
|
||||||
|
self.thumb = ThumbnailView(self)
|
||||||
|
self.photo = PhotoView(self)
|
||||||
|
self.download = DownloadView(self)
|
||||||
|
self.date = DateView(self)
|
||||||
|
self.tag = TagView(self)
|
||||||
|
self.album = self.tag
|
||||||
|
|
||||||
|
def render(self, template, **kwargs):
|
||||||
|
"""
|
||||||
|
Render a template
|
||||||
|
"""
|
||||||
|
return self.tpl.get_template(template).render(**kwargs, **self.get_default_vars())
|
||||||
|
|
||||||
|
def get_default_vars(self):
|
||||||
|
"""
|
||||||
|
Return a dict containing variables expected to be on every page
|
||||||
|
"""
|
||||||
|
s = self.session()
|
||||||
|
ret = {
|
||||||
|
"all_tags": s.query(Tag).order_by(Tag.title).all(),
|
||||||
|
"all_albums": s.query(Tag).filter(Tag.is_album == True).order_by(Tag.title).all(),
|
||||||
|
"path": cherrypy.request.path_info
|
||||||
|
}
|
||||||
|
s.close()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def session(self):
|
||||||
|
"""
|
||||||
|
Get a database session
|
||||||
|
"""
|
||||||
|
return self.library.session()
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def index(self):
|
def index(self):
|
||||||
|
"""
|
||||||
|
Home page - redirect to the photo feed
|
||||||
|
"""
|
||||||
raise cherrypy.HTTPRedirect('feed', 302)
|
raise cherrypy.HTTPRedirect('feed', 302)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def feed(self, page=0, pgsize=25):
|
def feed(self, page=0, pgsize=25):
|
||||||
|
"""
|
||||||
|
/feed - main photo feed - show photos sorted by date, newest first
|
||||||
|
"""
|
||||||
s = self.session()
|
s = self.session()
|
||||||
page, pgsize = int(page), int(pgsize)
|
page, pgsize = int(page), int(pgsize)
|
||||||
total_sets = s.query(func.count(PhotoSet.id)).first()[0]
|
total_sets = s.query(func.count(PhotoSet.id)).first()[0]
|
||||||
|
@ -67,7 +90,10 @@ class PhotosWeb(object):
|
||||||
yield self.render("feed.html", images=[i for i in images], page=page, pgsize=int(pgsize), total_sets=total_sets)
|
yield self.render("feed.html", images=[i for i in images], page=page, pgsize=int(pgsize), total_sets=total_sets)
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def monthly(self):
|
def stats(self):
|
||||||
|
"""
|
||||||
|
/stats - show server statistics
|
||||||
|
"""
|
||||||
s = self.session()
|
s = self.session()
|
||||||
images = s.query(func.count(PhotoSet.uuid),
|
images = s.query(func.count(PhotoSet.uuid),
|
||||||
func.strftime('%Y', PhotoSet.date).label('year'),
|
func.strftime('%Y', PhotoSet.date).label('year'),
|
||||||
|
@ -78,6 +104,10 @@ class PhotosWeb(object):
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
def map(self, i=None, zoom=3):
|
def map(self, i=None, zoom=3):
|
||||||
|
"""
|
||||||
|
/map - show all photos on the a map, or a single point if $i is passed
|
||||||
|
TODO using so many coordinates is slow in the browser. dedupe them somehow.
|
||||||
|
"""
|
||||||
s = self.session()
|
s = self.session()
|
||||||
query = s.query(PhotoSet).filter(PhotoSet.lat != 0, PhotoSet.lon != 0)
|
query = s.query(PhotoSet).filter(PhotoSet.lat != 0, PhotoSet.lon != 0)
|
||||||
if i:
|
if i:
|
||||||
|
@ -153,20 +183,12 @@ class DateView(object):
|
||||||
group_by('gdate').order_by(desc('year'), 'month', 'day').all()
|
group_by('gdate').order_by(desc('year'), 'month', 'day').all()
|
||||||
yield self.master.render("dates.html", images=images)
|
yield self.master.render("dates.html", images=images)
|
||||||
|
|
||||||
@cherrypy.expose
|
|
||||||
def tag(self, date):
|
|
||||||
raise Exception("Who am i")
|
|
||||||
s = self.master.session()
|
|
||||||
dt = datetime.strptime(date, "%Y-%m-%d")
|
|
||||||
dt_end = dt + timedelta(days=1)
|
|
||||||
photos = s.query(PhotoSet).filter(and_(PhotoSet.date >= dt,
|
|
||||||
PhotoSet.date < dt_end)).order_by(PhotoSet.date).all()
|
|
||||||
alltags = s.query(Tag).order_by(Tag.title).all()
|
|
||||||
yield self.master.render("create_tags.html", images=photos, alltags=alltags)
|
|
||||||
|
|
||||||
|
|
||||||
@cherrypy.popargs('item_type', 'thumb_size', 'uuid')
|
@cherrypy.popargs('item_type', 'thumb_size', 'uuid')
|
||||||
class ThumbnailView(object):
|
class ThumbnailView(object):
|
||||||
|
"""
|
||||||
|
Generate and serve thumbnails on-demand
|
||||||
|
"""
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
self.master = master
|
self.master = master
|
||||||
self._cp_config = {"tools.trailing_slash.on": False}
|
self._cp_config = {"tools.trailing_slash.on": False}
|
||||||
|
@ -202,6 +224,9 @@ class ThumbnailView(object):
|
||||||
|
|
||||||
@cherrypy.popargs('item_type', 'uuid')
|
@cherrypy.popargs('item_type', 'uuid')
|
||||||
class DownloadView(object):
|
class DownloadView(object):
|
||||||
|
"""
|
||||||
|
View original files or force-download them
|
||||||
|
"""
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
self.master = master
|
self.master = master
|
||||||
self._cp_config = {"tools.trailing_slash.on": False}
|
self._cp_config = {"tools.trailing_slash.on": False}
|
||||||
|
@ -225,6 +250,9 @@ class DownloadView(object):
|
||||||
|
|
||||||
@cherrypy.popargs('uuid')
|
@cherrypy.popargs('uuid')
|
||||||
class PhotoView(object):
|
class PhotoView(object):
|
||||||
|
"""
|
||||||
|
View a single photo
|
||||||
|
"""
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
self.master = master
|
self.master = master
|
||||||
self._cp_config = {"tools.trailing_slash.on": False}
|
self._cp_config = {"tools.trailing_slash.on": False}
|
||||||
|
|
|
@ -27,28 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<br style="clear:both" />
|
<br style="clear:both" />
|
||||||
<div class="pager">
|
{% include "pager.html" %}
|
||||||
<h6>Page</h6>
|
|
||||||
{% if page > 0 %}
|
|
||||||
<div class="nav-prev">
|
|
||||||
<a href="{{path}}?page={{ page - 1 }}">Previous</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="pages">
|
|
||||||
<ul class="pager">
|
|
||||||
{% for pgnum in range(0, total_pages) %}
|
|
||||||
<li{% if pgnum == page %} class="current"{% endif %}>
|
|
||||||
<a href="{{path}}?page={{ pgnum }}">{{ pgnum }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% if page + 1 < total_pages %}
|
|
||||||
<div class="nav-next">
|
|
||||||
<a href="{{path}}?page={{ page + 1 }}">Next</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
<li class="pure-menu-item"><a href="/date" class="pure-menu-link">Dates</a></li>
|
<li class="pure-menu-item"><a href="/date" class="pure-menu-link">Dates</a></li>
|
||||||
<li class="pure-menu-item"><a href="/monthly" class="pure-menu-link">Stats</a></li>
|
<li class="pure-menu-item"><a href="/monthly" class="pure-menu-link">Stats</a></li>
|
||||||
<li class="pure-menu-item"><a href="/map" class="pure-menu-link">Map</a></li>
|
<li class="pure-menu-item"><a href="/map" class="pure-menu-link">Map</a></li>
|
||||||
|
<li class="pure-menu-item"><a href="/tag/untagged" class="pure-menu-link">Untagged</a></li>
|
||||||
<li class="pure-menu-item"><a href="/admin/trash" class="pure-menu-link">Trash</a></li>
|
<li class="pure-menu-item"><a href="/admin/trash" class="pure-menu-link">Trash</a></li>
|
||||||
<li class="pure-menu-heading">Albums</li>
|
<li class="pure-menu-heading">Albums</li>
|
||||||
{% for tag in all_albums %}
|
{% for tag in all_albums %}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<div class="pager">
|
||||||
|
<h6>Page</h6>
|
||||||
|
{% if page > 0 %}
|
||||||
|
<div class="nav-prev">
|
||||||
|
<a href="{{path}}?page={{ page - 1 }}">Previous</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="pages">
|
||||||
|
<ul class="pager">
|
||||||
|
{% for pgnum in range(0, total_pages) %}
|
||||||
|
<li{% if pgnum == page %} class="current"{% endif %}>
|
||||||
|
<a href="{{path}}?page={{ pgnum }}">{{ pgnum }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% if page + 1 < total_pages %}
|
||||||
|
<div class="nav-next">
|
||||||
|
<a href="{{path}}?page={{ page + 1 }}">Next</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
|
@ -18,10 +18,27 @@
|
||||||
<div class="photo-metadata">
|
<div class="photo-metadata">
|
||||||
<h2>Information</h2>
|
<h2>Information</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Date:</strong> {{ image.date }} </li>
|
<li>
|
||||||
<li><strong>Versions:</strong> {{ image.files|length }}</li>
|
<strong>Date:</strong> {{ image.date }}
|
||||||
|
</li>
|
||||||
|
{% if image.date_offset %}
|
||||||
|
<li>
|
||||||
|
<strong>Time offset: </strong> {{ image.date_offset }}m
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Embedded date: </strong>{{ image.date_real }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<strong>Status: </strong>{{ image.status | statusstr }}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Versions:</strong> {{ image.files|length }}
|
||||||
|
</li>
|
||||||
{% if image.lat != 0 %}
|
{% if image.lat != 0 %}
|
||||||
<li><strong>Coordinates:</strong> <a href="/map?zoom=13&i={{ image.uuid }}">{{ image.lat }}, {{ image.lon }}</a></li>
|
<li>
|
||||||
|
<strong>Coordinates:</strong> <a href="/map?zoom=13&i={{ image.uuid }}">{{ image.lat }}, {{ image.lon }}</a>
|
||||||
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,7 +70,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="/download/one/{{ img.uuid }}">download</a>
|
<a href="/download/one/{{ img.uuid }}">download</a>
|
||||||
<a href="/download/one/{{ img.uuid }}.{{ mime2ext(img.format) }}?preview=true">preview</a>
|
<a href="/download/one/{{ img.uuid }}.{{ img.format | mime2ext }}?preview=true">preview</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -61,7 +78,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="photo-tags">
|
<div class="photo-tags">
|
||||||
<h2>Tags <a href="/photo/{{ image.uuid }}/tag">add</a></h2>
|
<h2>Tags{% if auth %} <a href="/create_tags?uuid={{ image.uuid }}">add</a>{% endif %}</h2>
|
||||||
<ul class="tags-picker">
|
<ul class="tags-picker">
|
||||||
{% for tagi in image.tags %}
|
{% for tagi in image.tags %}
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
{% extends "page.html" %}
|
|
||||||
|
|
||||||
{% set title = "Placeholder Title" %}
|
|
||||||
{% set subtitle = image.uuid %}
|
|
||||||
|
|
||||||
{% block buttons %}
|
|
||||||
xxx
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
|
|
||||||
<div class="photo-tagging pure-g">
|
|
||||||
<div class="current-tags pure-u-1-3">
|
|
||||||
<h2>Current Tags</h2>
|
|
||||||
<a href="/photo/{{ image.uuid }}">
|
|
||||||
<img src="/thumb/set/small/{{ image.uuid }}.jpg" />
|
|
||||||
</a>
|
|
||||||
<ul class="tags-picker">
|
|
||||||
{% for tagi in image.tags %}
|
|
||||||
<li>
|
|
||||||
<a href="/tag/{{ tagi.tag.uuid }}">{{ tagi.tag.title }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="all-tags pure-u-1-3">
|
|
||||||
<h2>All tags</h2>
|
|
||||||
<ul class="tags-picker">
|
|
||||||
{% for tag in alltags %}
|
|
||||||
<li>
|
|
||||||
<form action="/photo/{{ image.uuid }}/tag_add" method="post">
|
|
||||||
<input type="hidden" name="tag" value="{{ tag.uuid }}" />
|
|
||||||
<input class="submit-link" type="submit" value="{{ tag.title }}" />
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="add-tags pure-u-1-3">
|
|
||||||
<h2>Add tag</h2>
|
|
||||||
<form action="/photo/{{ image.uuid }}/tag_create" method="post" class="pure-form">
|
|
||||||
<input type="text" name="tag" placeholder="new tag name" />
|
|
||||||
<input type="submit" value="Add" class="pure-button pure-button-primary" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
{% extends "page.html" %}
|
||||||
|
{% set title = "Untagged photos" %}
|
||||||
|
{% set subtitle = "By date, descending" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
{% set locals = namespace() %}
|
||||||
|
{% set total_pages = (total_items/pgsize)|ceil %}
|
||||||
|
|
||||||
|
<div class="photo-feed">
|
||||||
|
{% set locals.im_date = "" %}
|
||||||
|
{% for item in images %}
|
||||||
|
{% set newdate = item.date.strftime("%b %d, %Y") %}
|
||||||
|
{% if newdate != locals.im_date %}
|
||||||
|
{% set locals.im_date = newdate %}
|
||||||
|
<div class="feed-divider year"><h4><a href="/date/{{ item.date.strftime("%Y-%m-%d") }}">{{ locals.im_date }}</a></h4></div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="photo">
|
||||||
|
<a href="/photo/{{ item.uuid }}">
|
||||||
|
<img src="/thumb/set/feed/{{ item.uuid }}.jpg" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<br style="clear:both" />
|
||||||
|
{% include "pager.html" %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue