photo editing and misc template refactor

This commit is contained in:
dave 2018-09-23 15:02:03 -07:00
parent fcfa7005d6
commit b81cad8b71
14 changed files with 112 additions and 69 deletions

View File

@ -6,7 +6,7 @@ from photoapp.library import PhotoLibrary
from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus
from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2 import Environment, FileSystemLoader, select_autoescape
from sqlalchemy import desc from sqlalchemy import desc
from sqlalchemy import func, and_ from sqlalchemy import func, and_, or_
import math import math
from urllib.parse import urlparse from urllib.parse import urlparse
@ -342,22 +342,34 @@ class PhotoView(object):
@cherrypy.expose @cherrypy.expose
def index(self, uuid): def index(self, uuid):
uuid = uuid.split(".")[0] # uuid = uuid.split(".")[0]
s = self.master.session() s = self.master.session()
photo = photo_auth_filter(s.query(PhotoSet)).filter(PhotoSet.uuid == uuid).first() photo = photo_auth_filter(s.query(PhotoSet)).filter(or_(PhotoSet.uuid == uuid, PhotoSet.slug == uuid)).first()
yield self.master.render("photo.html", image=photo) yield self.master.render("photo.html", image=photo)
@cherrypy.expose @cherrypy.expose
@require_auth @require_auth
def op(self, uuid, op): def op(self, uuid, op, title=None, description=None, offset=None):
s = self.master.session() s = self.master.session()
photo = s.query(PhotoSet).filter(PhotoSet.uuid == uuid).first() photo = s.query(PhotoSet).filter(PhotoSet.uuid == uuid).first()
if op == "Make public": if op == "Make public":
photo.status = PhotoStatus.public photo.status = PhotoStatus.public
elif op == "Make private": elif op == "Make private":
photo.status = PhotoStatus.private photo.status = PhotoStatus.private
elif op == "Save":
photo.title = title
photo.description = description
photo.slug = slugify(title) or None
photo.date_offset = int(offset) if offset else 0
s.commit() s.commit()
raise cherrypy.HTTPRedirect('/photo/{}'.format(photo.uuid), 302) raise cherrypy.HTTPRedirect('/photo/{}'.format(photo.slug or photo.uuid), 302)
@cherrypy.expose
@require_auth
def edit(self, uuid):
s = self.master.session()
photo = photo_auth_filter(s.query(PhotoSet)).filter(PhotoSet.uuid == uuid).first()
yield self.master.render("photo_edit.html", image=photo)
@cherrypy.popargs('uuid') @cherrypy.popargs('uuid')
@ -379,14 +391,18 @@ class TagView(object):
numphotos = photo_auth_filter(s.query(func.count(PhotoSet.id))). \ numphotos = photo_auth_filter(s.query(func.count(PhotoSet.id))). \
filter(~PhotoSet.id.in_(s.query(TagItem.set_id))).scalar() filter(~PhotoSet.id.in_(s.query(TagItem.set_id))).scalar()
photos = photo_auth_filter(s.query(PhotoSet)).filter(~PhotoSet.id.in_(s.query(TagItem.set_id))).\ photos = photo_auth_filter(s.query(PhotoSet)).filter(~PhotoSet.id.in_(s.query(TagItem.set_id))).\
offset(page * pgsize).limit(pgsize).all() offset(page * pgsize). \
limit(pgsize).all()
yield self.master.render("untagged.html", images=photos, total_items=numphotos, pgsize=pgsize, page=page) yield self.master.render("untagged.html", images=photos, total_items=numphotos, pgsize=pgsize, page=page)
else: else:
tag = s.query(Tag).filter(Tag.uuid == uuid).first() tag = s.query(Tag).filter(or_(Tag.uuid == uuid, Tag.slug == uuid)).first()
numphotos = photo_auth_filter(s.query(func.count(Tag.id)).join(TagItem).join(PhotoSet)). \ numphotos = photo_auth_filter(s.query(func.count(Tag.id)).join(TagItem).join(PhotoSet)). \
filter(Tag.uuid == uuid).scalar() filter(Tag.id == tag.id).scalar()
photos = photo_auth_filter(s.query(PhotoSet)).join(TagItem).join(Tag).filter(Tag.uuid == uuid). \ photos = photo_auth_filter(s.query(PhotoSet)).join(TagItem).join(Tag). \
order_by(PhotoSet.date.desc()).offset(page * pgsize).limit(pgsize).all() filter(Tag.id == tag.id). \
order_by(PhotoSet.date.desc()). \
offset(page * pgsize). \
limit(pgsize).all()
yield self.master.render("album.html", tag=tag, images=photos, yield self.master.render("album.html", tag=tag, images=photos,
total_items=numphotos, pgsize=pgsize, page=page) total_items=numphotos, pgsize=pgsize, page=page)
@ -402,7 +418,7 @@ class TagView(object):
- Make all private: mark all photos under this tag as private - Make all private: mark all photos under this tag as private
""" """
s = self.master.session() s = self.master.session()
tag = s.query(Tag).filter(Tag.uuid == uuid).first() tag = s.query(Tag).filter(or_(Tag.uuid == uuid, Tag.slug == uuid)).first()
if op == "Demote to tag": if op == "Demote to tag":
tag.is_album = 0 tag.is_album = 0
elif op == "Promote to album": elif op == "Promote to album":
@ -414,11 +430,11 @@ class TagView(object):
raise cherrypy.HTTPRedirect('/', 302) raise cherrypy.HTTPRedirect('/', 302)
elif op == "Make all public": elif op == "Make all public":
# TODO smarter query # TODO smarter query
for photo in s.query(PhotoSet).join(TagItem).join(Tag).filter(Tag.uuid == uuid).all(): for photo in s.query(PhotoSet).join(TagItem).join(Tag).filter(Tag.id == tag.id).all():
photo.status = PhotoStatus.public photo.status = PhotoStatus.public
elif op == "Make all private": elif op == "Make all private":
# TODO smarter query # TODO smarter query
for photo in s.query(PhotoSet).join(TagItem).join(Tag).filter(Tag.uuid == uuid).all(): for photo in s.query(PhotoSet).join(TagItem).join(Tag).filter(Tag.id == tag.id).all():
photo.status = PhotoStatus.private photo.status = PhotoStatus.private
else: else:
raise Exception("Invalid op: '{}'".format(op)) raise Exception("Invalid op: '{}'".format(op))

View File

@ -25,5 +25,6 @@ setup(name='photoapp',
}, },
include_package_data=True, include_package_data=True,
package_data={'photoapp': ['../templates/*.html', package_data={'photoapp': ['../templates/*.html',
'../templates/fragments/*.html',
'../styles/dist/*']}, '../styles/dist/*']},
zip_safe=False) zip_safe=False)

View File

@ -124,9 +124,12 @@ a {
.email-content-controls { .email-content-controls {
margin-top: 2em; margin-top: 2em;
text-align: right; text-align: right;
} .secondary-button {
.email-content-controls .secondary-button { margin-bottom: 0.3em;
margin-bottom: 0.3em; }
form {
display: inline-block;
}
} }
.email-avatar { .email-avatar {

View File

@ -1,6 +1,6 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Photos by date" %} {% block title %}{{ tag.title or tag.name }}{% endblock %}
{% set subtitle = "By date, descending" %} {% block subtitle %}{{ tag.description }}{% endblock %}
{% block buttons %} {% block buttons %}
<form action="/tag/{{ tag.uuid }}/op" method="post"> <form action="/tag/{{ tag.uuid }}/op" method="post">
@ -25,11 +25,7 @@
{% set locals.im_date = newdate %} {% set locals.im_date = newdate %}
<div class="feed-divider year"><h4>{{ locals.im_date }}</h4></div> <div class="feed-divider year"><h4>{{ locals.im_date }}</h4></div>
{% endif %} {% endif %}
<div class="photo"> {% include "fragments/feed-photo.html" %}
<a href="/photo/{{ item.uuid }}">
<img src="/thumb/set/feed/{{ item.uuid }}.jpg" />
</a>
</div>
{% endfor %} {% endfor %}
<br style="clear:both" /> <br style="clear:both" />
<div class="pager"> <div class="pager">

View File

@ -1,6 +1,6 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Photos on {}".format(date.strftime("%b %d, %Y")) %} {% block title %}{{ "Photos on {}".format(date.strftime("%b %d, %Y")) }}{% endblock %}
{% set subtitle = "By date, descending" %} {% block subtitle %}{% endblock %}
{% block buttons %} {% block buttons %}
<form action="/create_tags" method="post"> <form action="/create_tags" method="post">
@ -25,11 +25,7 @@
{% set locals.im_date = newdate %} {% set locals.im_date = newdate %}
<div class="feed-divider year"><h4>{{ locals.im_date }}</h4></div> <div class="feed-divider year"><h4>{{ locals.im_date }}</h4></div>
{% endif %} {% endif %}
<div class="photo"> {% include "fragments/feed-photo.html" %}
<a href="/photo/{{ item.uuid }}">
<img src="/thumb/set/feed/{{ item.uuid }}.jpg" />
</a>
</div>
{% endfor %} {% endfor %}
<br style="clear:both" /> <br style="clear:both" />
<div class="pager"> <div class="pager">

View File

@ -1,6 +1,6 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "All photos" %} {% block title %}Photo Dates{% endblock %}
{% set subtitle = "By date, descending" %} {% block subtitle %}Count per day{% endblock %}
{% block buttons %} {% block buttons %}
xxx xxx

View File

@ -1,10 +1,7 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Photos by date" %} {% block title %}Photos by date{% endblock %}
{% set subtitle = "By date, descending" %} {% block subtitle %}By date, descending{% endblock %}
{% block buttons %}{% endblock %}
{% block buttons %}
xxx
{% endblock %}
{% block body %} {% block body %}
@ -20,11 +17,7 @@
{% set locals.im_date = newdate %} {% set locals.im_date = newdate %}
<div class="feed-divider year"><h4>{{ locals.im_date }}</h4></div> <div class="feed-divider year"><h4>{{ locals.im_date }}</h4></div>
{% endif %} {% endif %}
<div class="photo"> {% include "fragments/feed-photo.html" %}
<a href="/photo/{{ item.uuid }}">
<img src="/thumb/set/feed/{{ item.uuid }}.jpg" />
</a>
</div>
{% endfor %} {% endfor %}
<br style="clear:both" /> <br style="clear:both" />
{% include "pager.html" %} {% include "pager.html" %}

View File

@ -0,0 +1,5 @@
<div class="photo">
<a href="/photo/{{ item.slug or item.uuid }}">
<img src="/thumb/set/feed/{{ item.uuid }}.jpg" />
</a>
</div>

View File

@ -1,10 +1,7 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Photo map" %} {% block title %}Photo map{% endblock %}
{% set subtitle = "GPS data" %} {% block subtitle %}GPS data{% endblock %}
{% block buttons %}{% endblock %}
{% block buttons %}
xxx
{% endblock %}
{% block body %} {% block body %}

View File

@ -1,10 +1,7 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Server statistics" %} {% block title %}Server statistics{% endblock %}
{% set subtitle = "Placeholder" %} {% block subtitle %}{% endblock %}
{% block buttons %}{% endblock %}
{% block buttons %}
xxx
{% endblock %}
{% block body %} {% block body %}

View File

@ -22,11 +22,11 @@
<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 %}
<li class="pure-menu-item"><a href="/album/{{ tag.uuid }}" class="pure-menu-link"><span class="tag-icon tag-icon-mod-6-{{ tag.id % 6 }}"></span>{{ tag.title }}</a></li> <li class="pure-menu-item"><a href="/album/{{ tag.slug }}" class="pure-menu-link"><span class="tag-icon tag-icon-mod-6-{{ tag.id % 6 }}"></span>{{ tag.name }}</a></li>
{% endfor %} {% endfor %}
<li class="pure-menu-heading">Tags</li> <li class="pure-menu-heading">Tags</li>
{% for tag in all_tags %} {% for tag in all_tags %}
<li class="pure-menu-item"><a href="/tag/{{ tag.uuid }}" class="pure-menu-link"><span class="tag-icon tag-icon-mod-6-{{ tag.id % 6 }}"></span>{{ tag.title }}</a></li> <li class="pure-menu-item"><a href="/tag/{{ tag.slug }}" class="pure-menu-link"><span class="tag-icon tag-icon-mod-6-{{ tag.id % 6 }}"></span>{{ tag.name }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>
@ -45,9 +45,9 @@
<div class="email-content"> <div class="email-content">
<div class="email-content-header pure-g"> <div class="email-content-header pure-g">
<div class="pure-u-1-2"> <div class="pure-u-1-2">
<h1 class="email-content-title">{{ title }}</h1> <h1 class="email-content-title">{% block title %}DEFAULT TITLE{% endblock %}</h1>
<p class="email-content-subtitle"> <p class="email-content-subtitle">
{{ subtitle }} {% block subtitle %}DEFAULT SUBTITLE{% endblock %}
</p> </p>
</div> </div>
{% if auth %} {% if auth %}

View File

@ -1,6 +1,6 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Placeholder Title" %} {% block title %}{{ image.title or image.uuid }}{% endblock %}
{% set subtitle = image.uuid %} {% block subtitle %}{{ image.date }}{% endblock %}
{% block buttons %} {% block buttons %}
<form action="/photo/{{ image.uuid }}/op" method="post"> <form action="/photo/{{ image.uuid }}/op" method="post">
@ -10,6 +10,7 @@
<input type="submit" class="secondary-button pure-button" name="op" value="Make private" /> <input type="submit" class="secondary-button pure-button" name="op" value="Make private" />
{% endif %} {% endif %}
</form> </form>
<a href="/photo/{{ image.uuid }}/edit"><button class="secondary-button pure-button">Edit</button></a>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
@ -21,6 +22,12 @@
</a> </a>
</div> </div>
<div class="photo-info pure-u-1-3"> <div class="photo-info pure-u-1-3">
{% if image.description %}
<div class="photo-description">
<h2>Description</h2>
<p>{{ image.description }}</p>
</div>
{% endif %}
<div class="photo-metadata"> <div class="photo-metadata">
<h2>Information</h2> <h2>Information</h2>
<ul> <ul>
@ -88,7 +95,7 @@
<ul class="tags-picker"> <ul class="tags-picker">
{% for tagi in image.tags %} {% for tagi in image.tags %}
<li> <li>
<a href="/tag/{{ tagi.tag.uuid }}">{{ tagi.tag.title }}</a> <a href="/tag/{{ tagi.tag.slug }}">{{ tagi.tag.name }}</a>
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>

36
templates/photo_edit.html Normal file
View File

@ -0,0 +1,36 @@
{% extends "page.html" %}
{% block title %}Editing {{ image.uuid }}{% endblock %}
{% block subtitle %}{{ image.date }}{% endblock %}
{% block buttons %}
<a href="/photo/{{ image.uuid }}"><button class="secondary-button pure-button">Back</button></a>
{% endblock %}
{% block body %}
<div class="photo-view pure-g">
<div class="photo-form pure-u-2-3">
<form action="/photo/{{ image.uuid }}/op" method="post" class="pure-form pure-form-stacked">
<fieldset>
<fieldset class="pure-group pure-u-1">
<input name="title" type="text" class="pure-input-1" placeholder="Image title" value="{{ image.title or "" }}" />
<textarea name="description" class="pure-input-1" placeholder="Description" rows="15">{{ image.description or "" }}</textarea>
</fieldset>
<div class="pure-u-1">
<label for="offset">Offset (minutes)</label>
<input id="offset" class="pure-u-1-2" type="text" name="offset" value="{{ image.date_offset }}" />
</div>
<div class="pure-u-1">
<input type="submit" class="pure-button pure-button-primary" name="op" value="Save" />
</div>
</fieldset>
</form>
</div>
<div class="photo-info pure-u-1-3">
<a href="/photo/{{ image.uuid }}" class="pure-g-1-4">
<img src="/thumb/set/feed/{{ image.uuid }}.jpg" />
</a>
</div>
</div>
{% endblock %}

View File

@ -1,6 +1,6 @@
{% extends "page.html" %} {% extends "page.html" %}
{% set title = "Untagged photos" %} {% block title %}Untagged photos{% endblock %}
{% set subtitle = "By date, descending" %} {% block subtitle %}By date, descending{% endblock %}
{% block body %} {% block body %}
@ -15,11 +15,7 @@
{% set locals.im_date = newdate %} {% 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> <div class="feed-divider year"><h4><a href="/date/{{ item.date.strftime("%Y-%m-%d") }}">{{ locals.im_date }}</a></h4></div>
{% endif %} {% endif %}
<div class="photo"> {% include "fragments/feed-photo.html" %}
<a href="/photo/{{ item.uuid }}">
<img src="/thumb/set/feed/{{ item.uuid }}.jpg" />
</a>
</div>
{% endfor %} {% endfor %}
<br style="clear:both" /> <br style="clear:both" />
{% include "pager.html" %} {% include "pager.html" %}