add versioning

This commit is contained in:
Edward Betts 2017-04-07 15:43:46 +01:00
parent 956dbadabd
commit 2f37577aaa
5 changed files with 90 additions and 11 deletions

View file

@ -5,15 +5,19 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, ForeignKey
from sqlalchemy.types import String, Unicode, Integer, DateTime, Boolean, UnicodeText, Enum
from sqlalchemy import func
from sqlalchemy.orm import relationship, validates, synonym
from sqlalchemy.orm import relationship, validates, synonym, configure_mappers
from sqlalchemy.sql import exists
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy_continuum import make_versioned
from sqlalchemy_continuum.plugins import FlaskPlugin, ActivityPlugin
import re
from hashids import Hashids
activity_plugin = ActivityPlugin()
make_versioned(plugins=[FlaskPlugin(), activity_plugin])
doc_hashids = Hashids(min_length=8)
Base = declarative_base()
@ -119,7 +123,9 @@ class User(TimeStampedModel, UserMixin):
return user
class Item(TimeStampedModel):
__versioned__ = {}
__tablename__ = 'item'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('user.id'))
published = Column(DateTime)
@ -148,7 +154,19 @@ class Item(TimeStampedModel):
@property
def url(self):
return url_for('.view_item', username=self.user.username, hashid=self.hashid)
return url_for('.view_item',
username=self.user.username,
hashid=self.hashid)
def version_url(self, version):
return url_for('.view_item',
username=self.user.username,
hashid=self.hashid,
v=version.transaction_id)
@property
def history_url(self):
return url_for('.history', username=self.user.username, hashid=self.hashid)
@property
def external_url(self):
@ -245,3 +263,6 @@ class SourceDoc(Item):
return self.db_price_per_character or self.db_document_price / len(self.text)
__mapper_args__ = {'polymorphic_identity': 'sourcedoc'}
configure_mappers()

View file

@ -21,7 +21,7 @@
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="#">History</a>
<a class="nav-link" href="{{ doc.history_url }}">History</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="{{ doc.edit_url }}">Edit</a>

View file

@ -0,0 +1,35 @@
{% extends "base.html" %}
{% block title %}{{ doc.title() }}{% endblock %}
{% block content %}
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link" href="{{ doc.url }}">View</a>
</li>
{% if doc.type == 'xanadoc' %}
<li class="nav-item">
<a class="nav-link" href="{{ doc.url }}/fulfil">Fulfil</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link active" href="{{ doc.history_url }}">History</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ doc.edit_url }}">Edit</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ request.url }}/raw">Raw</a>
</li>
</ul>
<h1 class="mt-3">{{ self.title() }}</h1>
<ul>
{% for v in doc.versions %}
<li><a href="{{ doc.version_url(v) }}">{{ v.modified.strftime('%H:%M:%S, %d %B %Y') }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View file

@ -14,7 +14,7 @@
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="#">History</a>
<a class="nav-link" href="{{ doc.history_url }}">History</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ doc.edit_url }}">Edit</a>
@ -25,11 +25,15 @@
</ul>
<h1 class="mt-3">{{ self.title() }}</h1>
{% if version %}
<p>Revision as of {{ version.modified.strftime('%H:%M, %d %B %Y') }}</p>
{% endif %}
<div id="text">
<div class="card mb-2" id="text">
<div class="card-block">
{% if span_length %}
{%- for start, line in add_highlight(doc.text, span_start, span_length) if line -%}
<p data-start="{{ start }}">
{%- for start, line in add_highlight(text, span_start, span_length) if line -%}
<p class="card-text" data-start="{{ start }}">
{% for i in line %}
{%- if i.highlight -%}
{%- if i.highlight != '\n' and i.highlight != '\r\n' -%}
@ -42,15 +46,16 @@
</p>
{%- endfor -%}
{% else %}
{%- for start, line in iter_lines(doc.text) if line -%}
{%- for start, line in iter_lines(text) if line -%}
{# <p data-start="{{ start }}">{% if line != "\n" and line != "\r\n" %}{{ line }}{% else %}&nbsp;{% endif
%}</p>#}
<p data-start="{{ start }}">{{ nbsp_at_start(line) }}</p>
{%- endfor -%}
{% endif %}
</div>
</div>
{% if doc.type == 'sourcedoc' and not span_length %}
{% if not version and doc.type == 'sourcedoc' and not span_length %}
<button id="show-span-selector" class="btn btn-primary">show span selector</button>
<button id="select-all" class="btn btn-primary">get entire document span</button>
<p id="span-selector" class="d-none">span: <span id="span"></span></p>
@ -60,7 +65,7 @@
{% block scripts %}
<script>
var doc_url = '{{ doc.external_url }}';
var doc_length = {{ doc.text | length }};
var doc_length = {{ text | length }};
</script>
<script src="{{ url_for('static', filename='js/sourcedoc.js') }}"></script>
{% endblock %}

View file

@ -16,6 +16,7 @@ from jinja2 import evalcontextfilter, Markup
from functools import wraps
from .utils import nbsp_at_start
from itsdangerous import URLSafeTimedSerializer
from sqlalchemy_continuum import version_class
import re
@ -212,14 +213,31 @@ def view_item(username, hashid, raw=False):
if raw:
return Response(item.text, mimetype='text/plain')
if 'v' in request.args and request.args['v'].isdigit():
ItemVersion = version_class(Item)
version = (session.query(ItemVersion)
.filter_by(transaction_id=int(request.args['v']))
.first())
text = version.text
else:
version = None
text = item.text
return render_template('view.html',
doc=item,
version=version,
text=text,
span_start=start,
span_length=length,
add_highlight=add_highlight,
nbsp_at_start=nbsp_at_start,
iter_lines=iter_lines)
@bp.route('/<username>/<hashid>/history')
def history(username, hashid):
item = get_item(username, hashid)
return render_template('history.html', doc=item)
@bp.route('/<username>/<hashid>/edit', methods=['GET', 'POST'])
def edit_item(username, hashid):
obj = get_item(username, hashid)