add versioning
This commit is contained in:
parent
956dbadabd
commit
2f37577aaa
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
|
|
35
sourcing/templates/history.html
Normal file
35
sourcing/templates/history.html
Normal 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 %}
|
|
@ -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 %} {% 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 %}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue