Restructure upload.html and edit.html as well as route logic

Rename variables and reformats user/admin logic
Add an is_trusted field to upload and edit forms

Restructure fields on upload and edit pages
Add simple styling for checkboxes
Add titles (mouseover) for checkboxes with crude explanations
Show Anonymous checkbox during upload and check & disable it for guests
Show Trusted checkbox for users at or above Trusted level
Adjust description field rendering to show field label above it

Add title (mouseover) for edit icon on torrent page
Show uploader for admins on anonymous torrents
Show uploader for admins when editing others' torrents
This commit is contained in:
TheAMM 2017-05-20 22:00:45 +03:00
parent 2ccf23a1f3
commit b9d88e8960
6 changed files with 149 additions and 143 deletions

View File

@ -153,6 +153,7 @@ class EditForm(FlaskForm):
is_remake = BooleanField('Remake') is_remake = BooleanField('Remake')
is_anonymous = BooleanField('Anonymous') is_anonymous = BooleanField('Anonymous')
is_complete = BooleanField('Complete') is_complete = BooleanField('Complete')
is_trusted = BooleanField('Trusted')
information = StringField('Information', [ information = StringField('Information', [
Length(max=255, message='Information must be at most %(max)d characters long.') Length(max=255, message='Information must be at most %(max)d characters long.')
@ -200,6 +201,7 @@ class UploadForm(FlaskForm):
is_remake = BooleanField('Remake') is_remake = BooleanField('Remake')
is_anonymous = BooleanField('Anonymous') is_anonymous = BooleanField('Anonymous')
is_complete = BooleanField('Complete') is_complete = BooleanField('Complete')
is_trusted = BooleanField('Trusted')
information = StringField('Information', [ information = StringField('Information', [
Length(max=255, message='Information must be at most %(max)d characters long.') Length(max=255, message='Information must be at most %(max)d characters long.')

View File

@ -275,7 +275,7 @@ def view_user(user_name):
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
return flask.redirect('/user/' + user.username) return flask.redirect(flask.url_for('view_user', user_name=user.username))
user_level = ['Regular', 'Trusted', 'Moderator', 'Administrator'][user.level] user_level = ['Regular', 'Trusted', 'Moderator', 'Administrator'][user.level]
@ -579,16 +579,17 @@ def upload():
def view_torrent(torrent_id): def view_torrent(torrent_id):
torrent = models.Torrent.by_id(torrent_id) torrent = models.Torrent.by_id(torrent_id)
viewer = flask.g.user
if not torrent: if not torrent:
flask.abort(404) flask.abort(404)
if torrent.deleted and (not flask.g.user or not flask.g.user.is_admin): # Only allow admins see deleted torrents
if torrent.deleted and not (viewer and viewer.is_admin):
flask.abort(404) flask.abort(404)
if flask.g.user: # Only allow owners and admins to edit torrents
can_edit = flask.g.user is torrent.user or flask.g.user.is_admin can_edit = viewer and (viewer is torrent.user or viewer.is_admin)
else:
can_edit = False
files = None files = None
if torrent.filelist: if torrent.filelist:
@ -596,6 +597,7 @@ def view_torrent(torrent_id):
return flask.render_template('view.html', torrent=torrent, return flask.render_template('view.html', torrent=torrent,
files=files, files=files,
viewer=viewer,
can_edit=can_edit) can_edit=can_edit)
@ -604,15 +606,18 @@ def edit_torrent(torrent_id):
torrent = models.Torrent.by_id(torrent_id) torrent = models.Torrent.by_id(torrent_id)
form = forms.EditForm(flask.request.form) form = forms.EditForm(flask.request.form)
form.category.choices = _create_upload_category_choices() form.category.choices = _create_upload_category_choices()
category = str(torrent.main_category_id) + "_" + str(torrent.sub_category_id)
editor = flask.g.user
if not torrent: if not torrent:
flask.abort(404) flask.abort(404)
if torrent.deleted and (not flask.g.user or not flask.g.user.is_admin): # Only allow admins edit deleted torrents
if torrent.deleted and not (editor and editor.is_admin):
flask.abort(404) flask.abort(404)
if not flask.g.user or (flask.g.user is not torrent.user and not flask.g.user.is_admin): # Only allow torrent owners or admins edit torrents
if not editor or not (editor is torrent.user or editor.is_admin):
flask.abort(403) flask.abort(403)
if flask.request.method == 'POST' and form.validate(): if flask.request.method == 'POST' and form.validate():
@ -622,36 +627,43 @@ def edit_torrent(torrent_id):
torrent.display_name = (form.display_name.data or '').strip() torrent.display_name = (form.display_name.data or '').strip()
torrent.information = (form.information.data or '').strip() torrent.information = (form.information.data or '').strip()
torrent.description = (form.description.data or '').strip() torrent.description = (form.description.data or '').strip()
if flask.g.user.is_admin:
torrent.deleted = form.is_deleted.data
torrent.hidden = form.is_hidden.data torrent.hidden = form.is_hidden.data
torrent.remake = form.is_remake.data torrent.remake = form.is_remake.data
torrent.complete = form.is_complete.data torrent.complete = form.is_complete.data
torrent.anonymous = form.is_anonymous.data torrent.anonymous = form.is_anonymous.data
if editor.is_trusted:
torrent.trusted = form.is_trusted.data
if editor.is_admin:
torrent.deleted = form.is_deleted.data
db.session.commit() db.session.commit()
flask.flash(flask.Markup( flask.flash(flask.Markup(
'Torrent has been successfully edited! Changes might take a few minutes to show up.'), 'info') 'Torrent has been successfully edited! Changes might take a few minutes to show up.'), 'info')
return flask.redirect('/view/' + str(torrent_id)) return flask.redirect(flask.url_for('view_torrent', torrent_id=torrent.id))
else: else:
# Setup form with pre-formatted form. if flask.request.method != 'POST':
form.category.data = category # Fill form data only if the POST didn't fail
form.display_name.data = torrent.display_name form.category.data = torrent.sub_category.id_as_string
form.information.data = torrent.information form.display_name.data = torrent.display_name
form.description.data = torrent.description form.information.data = torrent.information
form.is_hidden.data = torrent.hidden form.description.data = torrent.description
if flask.g.user.is_admin:
form.is_hidden.data = torrent.hidden
form.is_remake.data = torrent.remake
form.is_complete.data = torrent.complete
form.is_anonymous.data = torrent.anonymous
form.is_trusted.data = torrent.trusted
form.is_deleted.data = torrent.deleted form.is_deleted.data = torrent.deleted
form.is_remake.data = torrent.remake
form.is_complete.data = torrent.complete
form.is_anonymous.data = torrent.anonymous
return flask.render_template('edit.html', return flask.render_template('edit.html',
form=form, form=form,
torrent=torrent, torrent=torrent,
admin=flask.g.user.is_admin) editor=editor)
@app.route('/view/<int:torrent_id>/magnet') @app.route('/view/<int:torrent_id>/magnet')

View File

@ -1,10 +1,12 @@
{% macro render_field(field) %} {% macro render_field(field, render_label=True) %}
{% if field.errors %} {% if field.errors %}
<div class="form-group has-error"> <div class="form-group has-error">
{% else %} {% else %}
<div class="form-group"> <div class="form-group">
{% endif %} {% endif %}
{% if render_label %}
{{ field.label(class='control-label') }} {{ field.label(class='control-label') }}
{% endif %}
{{ field(title=field.description,**kwargs) | safe }} {{ field(title=field.description,**kwargs) | safe }}
{% if field.errors %} {% if field.errors %}
<div class="help-block"> <div class="help-block">
@ -27,33 +29,33 @@
{% macro render_markdown_editor(field, field_name='') %} {% macro render_markdown_editor(field, field_name='') %}
{% if field.errors %} {% if field.errors %}
<div class="form-group has-error"> <div class="form-group has-error">
{% else %} {% else %}
<div class="form-group"> <div class="form-group">
{% endif %} {% endif %}
<div class="markdown-editor" id="{{ field_name }}-markdown-editor" data-field-name="{{ field_name }}"> <div class="markdown-editor" id="{{ field_name }}-markdown-editor" data-field-name="{{ field_name }}">
<ul class="nav nav-tabs" role="tablist"> {{ field.label(class='control-label') }}
<li role="presentation" class="active"> <ul class="nav nav-tabs" role="tablist">
<a href="#{{ field_name }}-tab" aria-controls="" role="tab" data-toggle="tab"> <li role="presentation" class="active">
Write <a href="#{{ field_name }}-tab" aria-controls="" role="tab" data-toggle="tab">
</a> Write
</li> </a>
<li role="presentation"> </li>
<a href="#{{ field_name }}-preview" id="{{ field_name }}-preview-tab" aria-controls="preview" role="tab" data-toggle="tab"> <li role="presentation">
Preview <a href="#{{ field_name }}-preview" id="{{ field_name }}-preview-tab" aria-controls="preview" role="tab" data-toggle="tab">
</a> Preview
</li> </a>
</ul> </li>
<div class="tab-content"> </ul>
<div role="tabpanel" class="tab-pane active" id="{{ field_name }}-tab" data-markdown-target="#{{ field_name }}-markdown-target"> <div class="tab-content">
{{ render_field(field, class_='form-control markdown-source') }} <div role="tabpanel" class="tab-pane active" id="{{ field_name }}-tab" data-markdown-target="#{{ field_name }}-markdown-target">
</div> {{ render_field(field, False, class_='form-control markdown-source') }}
<div role="tabpanel" class="tab-pane" id="{{ field_name }}-preview"> </div>
{{ field.label(class='control-label') }} <div role="tabpanel" class="tab-pane" id="{{ field_name }}-preview">
<div class="well" id="{{ field_name }}-markdown-target"></div> <div class="well" id="{{ field_name }}-markdown-target"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endmacro %} {% endmacro %}

View File

@ -4,79 +4,73 @@
{% from "_formhelpers.html" import render_field %} {% from "_formhelpers.html" import render_field %}
{% from "_formhelpers.html" import render_markdown_editor %} {% from "_formhelpers.html" import render_markdown_editor %}
<h1>Edit Torrent</h1> {% set torrent_url = url_for('view_torrent', torrent_id=torrent.id) %}
<h1>
Edit Torrent <a href="{{ torrent_url }}">#{{torrent.id}}</a>
{% if (torrent.user != None) and (torrent.user != editor) %}
(by <a href="{{ url_for('view_user', user_name=torrent.user.username) }}">{{ torrent.user.username }}</a>)
{% endif %}
</h1>
<form method="POST" enctype="multipart/form-data"> <form method="POST" enctype="multipart/form-data">
{{ form.csrf_token }} {{ form.csrf_token }}
<div class="row"> <div class="row">
<div class="form-group col-md-6"> <div class="col-md-6">
{{ render_field(form.category, class_='form-control')}} {{ render_field(form.display_name, class_='form-control', placeholder='Display name') }}
</div>
<div class="col-md-4">
{{ render_field(form.category, class_='form-control')}}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-md-6"> <div class="col-md-4">
{{ render_field(form.display_name, class_='form-control', placeholder='Display name') }} {{ render_field(form.information, class_='form-control', placeholder='Your website or IRC channel') }}
</div> </div>
</div> <div class="col-md-8">
<label class="control-label">Torrent flags</label>
<div>
{% if editor.is_admin %}
<label class="btn btn-primary">
{{ form.is_deleted }}
Deleted
</label>
{% endif %}
<div class="row"> <label class="btn btn-default" style="background-color: darkgray; border-color: #ccc;" title="Hide torrent from listing">
<div class="form-group col-md-6">
{{ render_field(form.information, class_='form-control', placeholder='Your website or IRC channel') }}
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
{{ render_markdown_editor(form.description, field_name='description') }}
</div>
</div>
{% if admin %}
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_deleted }}
Deleted
</label>
</div>
</div>
{% endif %}
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_hidden }} {{ form.is_hidden }}
Hidden Hidden
</label> </label>
</div> <label class="btn btn-danger" title="This torrent is derived from another release">
</div>
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_remake }} {{ form.is_remake }}
Remake Remake
</label> </label>
</div> <label class="btn btn-primary" title="This torrent is a complete batch (eg. season)">
</div>
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_complete }} {{ form.is_complete }}
Complete Complete
</label> </label>
{# Only allow changing anonymous status when an uploader exists #}
{% if torrent.uploader_id %}
<label class="btn btn-primary" title="Upload torrent anonymously (don't display your username)">
{{ form.is_anonymous }}
Anonymous
</label>
{% endif %}
{% if editor.is_trusted %}
<label class="btn btn-success" title="Mark torrent trusted">
{{ form.is_trusted }}
Trusted
</label>
{% endif %}
</div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-md-6"> <div class="col-md-12">
<label> {{ render_markdown_editor(form.description, field_name='description') }}
{{ form.is_anonymous }}
Anonymous
</label>
</div> </div>
</div> </div>

View File

@ -16,68 +16,57 @@
<form method="POST" enctype="multipart/form-data"> <form method="POST" enctype="multipart/form-data">
{% if config.ENFORCE_MAIN_ANNOUNCE_URL %}<p><strong>Important:</strong> Please include <kbd>{{config.MAIN_ANNOUNCE_URL}}</kbd> in your trackers</p>{% endif %} {% if config.ENFORCE_MAIN_ANNOUNCE_URL %}<p><strong>Important:</strong> Please include <kbd>{{config.MAIN_ANNOUNCE_URL}}</kbd> in your trackers</p>{% endif %}
<div class="row"> <div class="row">
<div class="form-group col-md-6"> <div class="col-md-6">
{{ render_upload(form.torrent_file, accept=".torrent") }} {{ render_upload(form.torrent_file, accept=".torrent") }}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-md-6"> <div class="col-md-6">
{{ render_field(form.category, class_='form-control')}} {{ render_field(form.display_name, class_='form-control', placeholder='Display name') }}
</div>
<div class="col-md-4">
{{ render_field(form.category, class_='form-control')}}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="form-group col-md-6">
{{ render_field(form.display_name, class_='form-control', placeholder='Display name') }}
</div>
</div> </div>
<div class="row form-group">
<div class="row"> <div class="col-md-4">
<div class="form-group col-md-6">
{{ render_field(form.information, class_='form-control', placeholder='Your website or IRC channel') }} {{ render_field(form.information, class_='form-control', placeholder='Your website or IRC channel') }}
</div> </div>
</div> <div class="col-md-8">
<label class="control-label">Torrent flags</label>
<div class="row"> <div>
<div class="form-group col-md-6"> <label class="btn btn-default" style="background-color: darkgray; border-color: #ccc;" title="Hide torrent from listing">
{{ render_markdown_editor(form.description, field_name='description') }}
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_hidden }} {{ form.is_hidden }}
Hidden Hidden
</label> </label>
</div> <label class="btn btn-danger" title="This torrent is derived from another release">
</div>
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_remake }} {{ form.is_remake }}
Remake Remake
</label> </label>
</div> <label class="btn btn-primary" title="This torrent is a complete batch (eg. season)">
</div>
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_complete }} {{ form.is_complete }}
Complete Complete
</label> </label>
</div> <label class="btn btn-primary" title="Upload torrent anonymously (don't display your username)">
</div> {{ form.is_anonymous(disabled=(False if user else ""), checked=(False if user else "")) }}
<div class="row">
<div class="form-group col-md-6">
<label>
{{ form.is_anonymous }}
Anonymous Anonymous
</label> </label>
{% if user.is_trusted %}
<label class="btn btn-success" title="Mark torrent trusted">
{{ form.is_trusted(checked="") }}
Trusted
</label>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{{ render_markdown_editor(form.description, field_name='description') }}
</div> </div>
</div> </div>

View File

@ -5,7 +5,7 @@
<div class="panel-heading"{% if torrent.hidden %} style="background-color: darkgray;"{% endif %}> <div class="panel-heading"{% if torrent.hidden %} style="background-color: darkgray;"{% endif %}>
<h3 class="panel-title"> <h3 class="panel-title">
{% if can_edit %} {% if can_edit %}
<a href="{{ request.url }}/edit"><i class="fa fa-fw fa-pencil"></i></a> <a href="{{ request.url }}/edit" title="Edit torrent"><i class="fa fa-fw fa-pencil"></i></a>
{% endif %} {% endif %}
{{ torrent.display_name }} {{ torrent.display_name }}
</h3> </h3>
@ -23,7 +23,14 @@
<div class="row"> <div class="row">
<div class="col-md-1">Submitter:</div> <div class="col-md-1">Submitter:</div>
<div class="col-md-5">{% if not torrent.anonymous and torrent.user %}<a href="{{ url_for('view_user', user_name=torrent.user.username) }}">{{ torrent.user.username }}</a>{% else %}Anonymous{% endif %}</div> <div class="col-md-5">
{% set user_url = torrent.user and url_for('view_user', user_name=torrent.user.username) %}
{%- if not torrent.anonymous and torrent.user -%}
<a href="{{ user_url }}">{{ torrent.user.username }}</a>
{%- else -%}
Anonymous {% if torrent.user and (viewer == torrent.user or viewer.is_admin) %}(<a href="{{ user_url }}">{{ torrent.user.username }}</a>){% endif %}
{%- endif -%}
</div>
<div class="col-md-1">Seeders:</div> <div class="col-md-1">Seeders:</div>
<div class="col-md-5"><span style="color: green;">{% if config.ENABLE_SHOW_STATS %}{{ torrent.stats.seed_count }}{% else %}Coming soon{% endif %}</span></div> <div class="col-md-5"><span style="color: green;">{% if config.ENABLE_SHOW_STATS %}{{ torrent.stats.seed_count }}{% else %}Coming soon{% endif %}</span></div>