basic tagging
This commit is contained in:
parent
1ff3e2106b
commit
018faecc3a
@ -138,6 +138,36 @@ class PhotoView(object):
|
||||
|
||||
# yield "viewing {}".format(uuid)
|
||||
|
||||
@cherrypy.expose
|
||||
def tag(self, uuid):
|
||||
s = self.master.session()
|
||||
photo = s.query(PhotoSet).filter(PhotoSet.uuid == uuid).first()
|
||||
alltags = s.query(Tag).order_by(Tag.title).all()
|
||||
yield self.master.tpl.get_template("photo_tag.html").render(image=photo, alltags=alltags)
|
||||
|
||||
@cherrypy.expose
|
||||
def tag_create(self, uuid, tag):
|
||||
# TODO validate uuid ?
|
||||
s = self.master.session()
|
||||
s.add(Tag(title=tag)) # TODO slug
|
||||
# TODO generate slug now or in model?
|
||||
s.commit()
|
||||
raise cherrypy.HTTPRedirect('/photo/{}/tag'.format(uuid), 302)
|
||||
|
||||
@cherrypy.expose
|
||||
def tag_add(self, uuid, tag):
|
||||
# TODO validate uuid ?
|
||||
# TODO validate tag ?
|
||||
s = self.master.session()
|
||||
tag = s.query(Tag).filter(Tag.uuid == tag).first()
|
||||
item = s.query(PhotoSet).filter(PhotoSet.uuid == uuid).first()
|
||||
s.add(TagItem(tag_id=tag.id, set_id=item.id))
|
||||
try:
|
||||
s.commit()
|
||||
except IntegrityError: # tag already applied
|
||||
pass
|
||||
raise cherrypy.HTTPRedirect('/photo/{}/tag'.format(uuid), 302)
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
@ -1,6 +1,8 @@
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Unicode, DECIMAL, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.schema import UniqueConstraint
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from datetime import datetime
|
||||
import uuid
|
||||
|
||||
|
||||
@ -11,12 +13,13 @@ class PhotoSet(Base):
|
||||
__tablename__ = 'photos'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
uuid = Column(Unicode, default=lambda: str(uuid.uuid4()))
|
||||
uuid = Column(Unicode, unique=True, default=lambda: str(uuid.uuid4()))
|
||||
date = Column(DateTime)
|
||||
lat = Column(DECIMAL(precision=11))
|
||||
lon = Column(DECIMAL(precision=11))
|
||||
|
||||
files = relationship("Photo", back_populates="set")
|
||||
tags = relationship("TagItem", back_populates="set")
|
||||
|
||||
title = Column(String)
|
||||
description = Column(String)
|
||||
@ -27,7 +30,7 @@ class Photo(Base):
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
set_id = Column(Integer, ForeignKey("photos.id"))
|
||||
uuid = Column(Unicode, default=lambda: str(uuid.uuid4()))
|
||||
uuid = Column(Unicode, unique=True, default=lambda: str(uuid.uuid4()))
|
||||
|
||||
set = relationship("PhotoSet", back_populates="files", foreign_keys=[set_id])
|
||||
|
||||
@ -44,11 +47,11 @@ class Tag(Base):
|
||||
__tablename__ = 'tags'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
uuid = Column(Unicode, default=lambda: str(uuid.uuid4()))
|
||||
created = Column(DateTime)
|
||||
modified = Column(DateTime)
|
||||
title = Column(String)
|
||||
slug = Column(String)
|
||||
uuid = Column(Unicode, unique=True, default=lambda: str(uuid.uuid4()))
|
||||
created = Column(DateTime, default=lambda: datetime.now())
|
||||
modified = Column(DateTime, default=lambda: datetime.now())
|
||||
title = Column(String, unique=True)
|
||||
slug = Column(String, unique=True)
|
||||
description = Column(String)
|
||||
|
||||
entries = relationship("TagItem", back_populates="tag")
|
||||
@ -59,8 +62,10 @@ class TagItem(Base):
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
tag_id = Column(Integer, ForeignKey("tags.id"))
|
||||
set_id = Column(Integer, ForeignKey("photos.id"))
|
||||
order = Column(Integer, default=0)
|
||||
|
||||
tag = relationship("Tag", back_populates="entries", foreign_keys=[tag_id])
|
||||
set = relationship("PhotoSet", back_populates="tags", foreign_keys=[set_id])
|
||||
|
||||
item_uuid = Column(String, unique=True)
|
||||
order = Column(Integer, default=0)
|
||||
UniqueConstraint(tag_id, set_id)
|
||||
|
@ -2,9 +2,12 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
@linkcolor: #1b98f8;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #1b98f8;
|
||||
color: @linkcolor;
|
||||
}
|
||||
|
||||
#layout, #nav, #list, #main {
|
||||
@ -204,4 +207,35 @@ a {
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
.photo-tags {
|
||||
h2 a {
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.photo-tagging {
|
||||
img {
|
||||
float: left;
|
||||
padding: 0px 20px 20px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.tags-picker {
|
||||
ul {
|
||||
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
padding-right: 15px;
|
||||
}
|
||||
input.submit-link {
|
||||
border: 0;
|
||||
background: none;
|
||||
color: @linkcolor;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,15 @@
|
||||
{{ img.path | basename }}
|
||||
</div>
|
||||
<div>
|
||||
{{ img.size | filesizeformat }} - {{ img.format }}
|
||||
{{ img.size | filesizeformat }} - {{ img.width }} x {{ img.height }}
|
||||
</div>
|
||||
{% if img.orientation > 0 %}
|
||||
<div>
|
||||
Rotation: {{ img.orientation * 90 }}°
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
{{ img.format }}
|
||||
</div>
|
||||
<div>
|
||||
<a href="/download/one/{{ img.uuid }}">download</a>
|
||||
@ -47,6 +55,16 @@
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="photo-tags">
|
||||
<h2>Tags <a href="/photo/{{ image.uuid }}/tag">add</a></h2>
|
||||
<ul class="tags-picker">
|
||||
{% for tagi in image.tags %}
|
||||
<li>
|
||||
<a href="/tags/{{ tagi.tag.uuid }}">{{ tagi.tag.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
43
templates/photo_tag.html
Normal file
43
templates/photo_tag.html
Normal file
@ -0,0 +1,43 @@
|
||||
{% set title = "Placeholder Title" %}
|
||||
{% set subtitle = image.uuid %}
|
||||
|
||||
{% include "page-top.html" %}
|
||||
|
||||
|
||||
<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="/tags/{{ 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>
|
||||
|
||||
{% include "page-bottom.html" %}
|
Loading…
Reference in New Issue
Block a user