mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-12-25 10:54:18 +00:00
Move some blueprints and rename routes
This commit is contained in:
parent
ee7f64f5be
commit
a8ab1bee71
@ -104,15 +104,6 @@ def create_app(config: Config = Config) -> Flask:
|
|||||||
from .blueprints.contributions import bp as contributions_blueprint
|
from .blueprints.contributions import bp as contributions_blueprint
|
||||||
app.register_blueprint(contributions_blueprint, url_prefix='/contributions')
|
app.register_blueprint(contributions_blueprint, url_prefix='/contributions')
|
||||||
|
|
||||||
from .blueprints.spacy_nlp_pipeline_models import bp as spacy_nlp_pipeline_models_blueprint
|
|
||||||
app.register_blueprint(spacy_nlp_pipeline_models_blueprint, url_prefix='/contributions/spacy-nlp-pipeline-models')
|
|
||||||
|
|
||||||
from .blueprints.tesseract_ocr_pipeline_models import bp as tesseract_ocr_pipeline_models_blueprint
|
|
||||||
app.register_blueprint(tesseract_ocr_pipeline_models_blueprint, url_prefix='/contributions/tesseract-ocr-pipeline-models')
|
|
||||||
|
|
||||||
from.blueprints.transkribus_htr_pipeline_models import bp as transkribus_htr_pipeline_models_blueprint
|
|
||||||
app.register_blueprint(transkribus_htr_pipeline_models_blueprint, url_prefix='/contributions/transkribus-htr-pipeline-models')
|
|
||||||
|
|
||||||
from .blueprints.corpora import bp as corpora_blueprint
|
from .blueprints.corpora import bp as corpora_blueprint
|
||||||
app.register_blueprint(corpora_blueprint, cli_group='corpus', url_prefix='/corpora')
|
app.register_blueprint(corpora_blueprint, cli_group='corpus', url_prefix='/corpora')
|
||||||
|
|
||||||
|
@ -16,3 +16,10 @@ def before_request():
|
|||||||
|
|
||||||
|
|
||||||
from . import routes
|
from . import routes
|
||||||
|
|
||||||
|
|
||||||
|
from .spacy_nlp_pipeline_models import bp as spacy_nlp_pipeline_models_bp
|
||||||
|
bp.register_blueprint(spacy_nlp_pipeline_models_bp, url_prefix='/spacy-nlp-pipeline-models')
|
||||||
|
|
||||||
|
from .tesseract_ocr_pipeline_models import bp as tesseract_ocr_pipeline_models_bp
|
||||||
|
bp.register_blueprint(tesseract_ocr_pipeline_models_bp, url_prefix='/tesseract-ocr-pipeline-models')
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from flask import redirect, url_for
|
from flask import render_template
|
||||||
from . import bp
|
from . import bp
|
||||||
|
|
||||||
|
|
||||||
@bp.route('')
|
@bp.route('')
|
||||||
def index():
|
def index():
|
||||||
return redirect(url_for('main.dashboard', _anchor='contributions'))
|
return render_template('contributions/index.html.j2', title='Contributions')
|
||||||
|
@ -12,10 +12,7 @@ from .forms import (
|
|||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
@login_required
|
@login_required
|
||||||
def index():
|
def index():
|
||||||
return render_template(
|
return redirect(url_for('contributions.index', _anchor='spacy-nlp-pipeline-models'))
|
||||||
'spacy_nlp_pipeline_models/index.html.j2',
|
|
||||||
title='SpaCy NLP Pipeline Models'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/create', methods=['GET', 'POST'])
|
@bp.route('/create', methods=['GET', 'POST'])
|
||||||
@ -46,7 +43,7 @@ def create():
|
|||||||
flash(f'SpaCy NLP Pipeline model "{snpm.title}" created')
|
flash(f'SpaCy NLP Pipeline model "{snpm.title}" created')
|
||||||
return {}, 201, {'Location': url_for('.index')}
|
return {}, 201, {'Location': url_for('.index')}
|
||||||
return render_template(
|
return render_template(
|
||||||
'spacy_nlp_pipeline_models/create.html.j2',
|
'contributions/spacy_nlp_pipeline_models/create.html.j2',
|
||||||
title='Create SpaCy NLP Pipeline Model',
|
title='Create SpaCy NLP Pipeline Model',
|
||||||
form=form
|
form=form
|
||||||
)
|
)
|
||||||
@ -54,7 +51,7 @@ def create():
|
|||||||
|
|
||||||
@bp.route('/<hashid:spacy_nlp_pipeline_model_id>', methods=['GET', 'POST'])
|
@bp.route('/<hashid:spacy_nlp_pipeline_model_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def spacy_nlp_pipeline_model(spacy_nlp_pipeline_model_id):
|
def entity(spacy_nlp_pipeline_model_id):
|
||||||
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
snpm = SpaCyNLPPipelineModel.query.get_or_404(spacy_nlp_pipeline_model_id)
|
||||||
if not (snpm.user == current_user or current_user.is_administrator):
|
if not (snpm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
@ -66,7 +63,7 @@ def spacy_nlp_pipeline_model(spacy_nlp_pipeline_model_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for('.index'))
|
return redirect(url_for('.index'))
|
||||||
return render_template(
|
return render_template(
|
||||||
'spacy_nlp_pipeline_models/spacy_nlp_pipeline_model.html.j2',
|
'contributions/spacy_nlp_pipeline_models/entity.html.j2',
|
||||||
title=f'{snpm.title} {snpm.version}',
|
title=f'{snpm.title} {snpm.version}',
|
||||||
form=form,
|
form=form,
|
||||||
spacy_nlp_pipeline_model=snpm
|
spacy_nlp_pipeline_model=snpm
|
@ -11,10 +11,7 @@ from .forms import (
|
|||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template(
|
return redirect(url_for('contributions.index', _anchor='tesseract-ocr-pipeline-models'))
|
||||||
'tesseract_ocr_pipeline_models/index.html.j2',
|
|
||||||
title='Tesseract OCR Pipeline Models'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/create', methods=['GET', 'POST'])
|
@bp.route('/create', methods=['GET', 'POST'])
|
||||||
@ -43,14 +40,14 @@ def create():
|
|||||||
flash(f'Tesseract OCR Pipeline model "{topm.title}" created')
|
flash(f'Tesseract OCR Pipeline model "{topm.title}" created')
|
||||||
return {}, 201, {'Location': url_for('.index')}
|
return {}, 201, {'Location': url_for('.index')}
|
||||||
return render_template(
|
return render_template(
|
||||||
'tesseract_ocr_pipeline_models/create.html.j2',
|
'contributions/tesseract_ocr_pipeline_models/create.html.j2',
|
||||||
title='Create Tesseract OCR Pipeline Model',
|
title='Create Tesseract OCR Pipeline Model',
|
||||||
form=form
|
form=form
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/<hashid:tesseract_ocr_pipeline_model_id>', methods=['GET', 'POST'])
|
@bp.route('/<hashid:tesseract_ocr_pipeline_model_id>', methods=['GET', 'POST'])
|
||||||
def tesseract_ocr_pipeline_model(tesseract_ocr_pipeline_model_id):
|
def entity(tesseract_ocr_pipeline_model_id):
|
||||||
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
topm = TesseractOCRPipelineModel.query.get_or_404(tesseract_ocr_pipeline_model_id)
|
||||||
if not (topm.user == current_user or current_user.is_administrator):
|
if not (topm.user == current_user or current_user.is_administrator):
|
||||||
abort(403)
|
abort(403)
|
||||||
@ -62,7 +59,7 @@ def tesseract_ocr_pipeline_model(tesseract_ocr_pipeline_model_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for('.index'))
|
return redirect(url_for('.index'))
|
||||||
return render_template(
|
return render_template(
|
||||||
'tesseract_ocr_pipeline_models/tesseract_ocr_pipeline_model.html.j2',
|
'contributions/tesseract_ocr_pipeline_models/entity.html.j2',
|
||||||
title=f'{topm.title} {topm.version}',
|
title=f'{topm.title} {topm.version}',
|
||||||
form=form,
|
form=form,
|
||||||
tesseract_ocr_pipeline_model=topm
|
tesseract_ocr_pipeline_model=topm
|
@ -72,14 +72,14 @@ def terms_of_use():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/social-area')
|
@bp.route('/social')
|
||||||
@login_required
|
@login_required
|
||||||
def social_area():
|
def social():
|
||||||
corpora = Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
|
corpora = Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
|
||||||
users = User.query.filter(User.is_public == True, User.id != current_user.id).all()
|
users = User.query.filter(User.is_public == True, User.id != current_user.id).all()
|
||||||
return render_template(
|
return render_template(
|
||||||
'main/social_area.html.j2',
|
'main/social.html.j2',
|
||||||
title='Social Area',
|
title='Social',
|
||||||
corpora=corpora,
|
corpora=corpora,
|
||||||
users=users
|
users=users
|
||||||
)
|
)
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
from flask import Blueprint
|
|
||||||
from flask_login import login_required
|
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint('transkribus_htr_pipeline_models', __name__)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.before_request
|
|
||||||
@login_required
|
|
||||||
def before_request():
|
|
||||||
'''
|
|
||||||
Ensures that the routes in this package can only be visited by users that
|
|
||||||
are logged in.
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
from . import routes
|
|
@ -1,7 +0,0 @@
|
|||||||
from flask import abort
|
|
||||||
from . import bp
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/transkribus_htr_pipeline_models')
|
|
||||||
def index():
|
|
||||||
return abort(503)
|
|
@ -41,7 +41,7 @@ class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
return url_for(
|
return url_for(
|
||||||
'contributions.spacy_nlp_pipeline_model',
|
'contributions.spacy_nlp_pipeline_models.entity',
|
||||||
spacy_nlp_pipeline_model_id=self.id
|
spacy_nlp_pipeline_model_id=self.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
|
|||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
return url_for(
|
return url_for(
|
||||||
'contributions.tesseract_ocr_pipeline_model',
|
'contributions.tesseract_ocr_pipeline_models.entity',
|
||||||
tesseract_ocr_pipeline_model_id=self.id
|
tesseract_ocr_pipeline_model_id=self.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
{# social #}
|
{# social #}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('main.social_area') }}">
|
<a href="{{ url_for('main.social') }}">
|
||||||
<i class="material-icons left">groups</i>
|
<i class="material-icons left">groups</i>
|
||||||
Social
|
Social
|
||||||
</a>
|
</a>
|
||||||
|
@ -16,8 +16,14 @@
|
|||||||
<li {% if request.path == url_for('main.dashboard') %}class="active"{% endif %}>
|
<li {% if request.path == url_for('main.dashboard') %}class="active"{% endif %}>
|
||||||
<a class="waves-effect" href="{{ url_for('main.dashboard') }}"><i class="material-icons">dashboard</i>Dashboard</a>
|
<a class="waves-effect" href="{{ url_for('main.dashboard') }}"><i class="material-icons">dashboard</i>Dashboard</a>
|
||||||
</li>
|
</li>
|
||||||
<li {% if request.path == url_for('main.social_area') %}class="active"{% endif %}>
|
<li {% if request.path == url_for('contributions.index') %}class="active"{% endif %}>
|
||||||
<a class="waves-effect" href="{{ url_for('main.social_area') }}"><i class="material-icons">groups</i>Social</a>
|
<a href="{{ url_for('contributions.index') }}">
|
||||||
|
<i class="material-icons left">new_label</i>
|
||||||
|
Contributions
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li {% if request.path == url_for('main.social') %}class="active"{% endif %}>
|
||||||
|
<a class="waves-effect" href="{{ url_for('main.social') }}"><i class="material-icons">groups</i>Social</a>
|
||||||
</li>
|
</li>
|
||||||
<li {% if request.path == url_for('main.manual') %}class="active"{% endif %}>
|
<li {% if request.path == url_for('main.manual') %}class="active"{% endif %}>
|
||||||
<a class="waves-effect" href="{{ url_for('main.manual') }}"><i class="material-icons">help_outline</i>Manual</a>
|
<a class="waves-effect" href="{{ url_for('main.manual') }}"><i class="material-icons">help_outline</i>Manual</a>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
{% extends "base.html.j2" %}
|
{% extends "base.html.j2" %}
|
||||||
{% import "wtf.html.j2" as wtf %}
|
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -9,17 +8,27 @@
|
|||||||
<p>Here you can see and edit the models that you have created. You can also create new models.</p>
|
<p>Here you can see and edit the models that you have created. You can also create new models.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col s12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="spacy-nlp-pipeline-model-list" data-user-id="{{ current_user.hashid }}"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card-action right-align">
|
||||||
|
<a href="{{ url_for('.spacy_nlp_pipeline_models.create') }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Create</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="tesseract-ocr-pipeline-model-list" data-user-id="{{ current_user.hashid }}"></div>
|
<div class="tesseract-ocr-pipeline-model-list" data-user-id="{{ current_user.hashid }}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-action right-align">
|
<div class="card-action right-align">
|
||||||
<a href="{{ url_for('.create') }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Create</a>
|
<a href="{{ url_for('.tesseract_ocr_pipeline_models.create') }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Create</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock page_content %}
|
{% endblock page_content %}
|
@ -41,97 +41,10 @@
|
|||||||
<div class="job-list" data-user-id="{{ current_user.hashid }}"></div>
|
<div class="job-list" data-user-id="{{ current_user.hashid }}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-action right-align">
|
<div class="card-action right-align">
|
||||||
<p><a class="btn modal-trigger waves-effect waves-light" data-target="create-job-modal">Create job<i class="material-icons right">add</i></a></p>
|
<p><a href="#data-processing-and-analysis-modal" class="btn modal-trigger waves-effect waves-light">Create job<i class="material-icons right">add</i></a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col s12" id="contributions">
|
|
||||||
<h2>My Contributions</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col s4">
|
|
||||||
<div class="card extension-selector hoverable service-color" data-service="tesseract-ocr-pipeline">
|
|
||||||
<a href="{{ url_for('tesseract_ocr_pipeline_models.index') }}" style="position: absolute; width: 100%; height: 100%;"></a>
|
|
||||||
<div class="card-content">
|
|
||||||
<span class="card-title">Tesseract OCR Pipeline Models</span>
|
|
||||||
<p>Here you can see and edit the models that you have created. You can also create new models.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col s4">
|
|
||||||
<div class="card extension-selector hoverable service-color" data-service="spacy-nlp-pipeline">
|
|
||||||
<a href="{{ url_for('spacy_nlp_pipeline_models.index') }}" style="position: absolute; width: 100%; height: 100%;"></a>
|
|
||||||
<div class="card-content">
|
|
||||||
<span class="card-title">SpaCy NLP Pipeline Models</span>
|
|
||||||
<p>Here you can see and edit the models that you have created. You can also create new models.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if config.NOPAQUE_TRANSKRIBUS_ENABLED %}
|
|
||||||
<div class="col s4">
|
|
||||||
<div class="card extension-selector hoverable service-color" data-service="transkribus-htr-pipeline">
|
|
||||||
<a href="{{ url_for('transkribus_htr_pipeline_models.index') }}" style="position: absolute; width: 100%; height: 100%;"></a>
|
|
||||||
<div class="card-content">
|
|
||||||
<span class="card-title">Transkribus HTR Pipeline Models</span>
|
|
||||||
<p>Here you can see and edit the models that you have created. You can also create new models.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock page_content %}
|
{% endblock page_content %}
|
||||||
|
|
||||||
{% block modals %}
|
|
||||||
{{ super() }}
|
|
||||||
<div id="create-job-modal" class="modal">
|
|
||||||
<div class="modal-content">
|
|
||||||
<h4>Select a service</h4>
|
|
||||||
<p> </p>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12 m4">
|
|
||||||
<div class="card-panel center-align hoverable">
|
|
||||||
<br>
|
|
||||||
<a href="{{ url_for('services.file_setup_pipeline') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);">
|
|
||||||
<i class="nopaque-icons service-color darken service-icons" data-service="file-setup-pipeline"></i>
|
|
||||||
</a>
|
|
||||||
<br><br>
|
|
||||||
<p class="service-color-text darken" data-service="file-setup-pipeline"><b>File setup</b></p>
|
|
||||||
<p class="light">Digital copies of text based research data (books, letters, etc.) often comprise various files and formats. nopaque converts and merges those files to facilitate further processing.</p>
|
|
||||||
<a href="{{ url_for('services.file_setup_pipeline') }}" class="waves-effect waves-light btn service-color darken" data-service="file-setup-pipeline">Create Job</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m4">
|
|
||||||
<div class="card-panel center-align hoverable">
|
|
||||||
<br>
|
|
||||||
<a href="{{ url_for('services.tesseract_ocr_pipeline') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);">
|
|
||||||
<i class="nopaque-icons service-color darken service-icons" data-service="tesseract-ocr-pipeline" style="font-size: 2.5rem;"></i>
|
|
||||||
</a>
|
|
||||||
<br><br>
|
|
||||||
<p class="service-color-text darken" data-service="tesseract-ocr-pipeline"><b>Optical Character Recognition</b></p>
|
|
||||||
<p class="light">nopaque converts your image data – like photos or scans – into text data through a process called OCR. This step enables you to proceed with further computational analysis of your documents.</p>
|
|
||||||
<a href="{{ url_for('services.tesseract_ocr_pipeline') }}" class="waves-effect waves-light btn service-color darken" data-service="tesseract-ocr-pipeline">Create Job</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col s12 m4">
|
|
||||||
<div class="card-panel center-align hoverable">
|
|
||||||
<br>
|
|
||||||
<a href="{{ url_for('services.spacy_nlp_pipeline') }}" class="btn-floating btn-large waves-effect waves-light" style="transform: scale(2);">
|
|
||||||
<i class="nopaque-icons service-color darken service-icons" data-service="spacy-nlp-pipeline" style="font-size: 2.5rem;"></i>
|
|
||||||
</a>
|
|
||||||
<br><br>
|
|
||||||
<p class="service-color-text darken" data-service="spacy-nlp-pipeline"><b>Natural Language Processing</b></p>
|
|
||||||
<p class="light">By means of computational linguistic data processing (tokenization, lemmatization, part-of-speech tagging and named-entity recognition) nopaque extracts additional information from your text.</p>
|
|
||||||
<a href="{{ url_for('services.spacy_nlp_pipeline') }}" class="waves-effect waves-light btn service-color darken" data-service="spacy-nlp-pipeline">Create Job</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<a class="btn-flat modal-close waves-effect waves-light">Close</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock modals %}
|
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
{% extends "base.html.j2" %}
|
|
||||||
{% import "wtf.html.j2" as wtf %}
|
|
||||||
|
|
||||||
{% block page_content %}
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col s12">
|
|
||||||
<h1 id="title">{{ title }}</h1>
|
|
||||||
<p>Here you can see and edit the models that you have created. You can also create new models.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col s12">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="spacy-nlp-pipeline-model-list" data-user-id="{{ current_user.hashid }}"></div>
|
|
||||||
</div>
|
|
||||||
<div class="card-action right-align">
|
|
||||||
<a href="{{ url_for('.create') }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Create</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock page_content %}
|
|
Loading…
Reference in New Issue
Block a user