aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Bobrov <breton@cynicmansion.ru>2016-02-05 04:33:05 +0300
committerBoris Bobrov <breton@cynicmansion.ru>2016-02-05 04:33:05 +0300
commit3b6b009077955c94e76cd2248e16a32dde1d90cf (patch)
treefd4db259e709217fbc557dc82dd7948fc3ba4727
parentf13225fa6dc2b4537300e5bed4b587619de9cf26 (diff)
parent41076dc96bbf273c5a04978e2046ea8738b1eee0 (diff)
downloadmediagoblin-3b6b009077955c94e76cd2248e16a32dde1d90cf.tar.lz
mediagoblin-3b6b009077955c94e76cd2248e16a32dde1d90cf.tar.xz
mediagoblin-3b6b009077955c94e76cd2248e16a32dde1d90cf.zip
Merge branch 'media_panel'
-rw-r--r--mediagoblin.example.ini1
-rw-r--r--mediagoblin/plugins/processing_info/README.rst5
-rw-r--r--mediagoblin/plugins/processing_info/__init__.py50
-rw-r--r--mediagoblin/plugins/processing_info/templates/mediagoblin/processing_info/header_left.html32
-rw-r--r--mediagoblin/processing/__init__.py16
-rw-r--r--mediagoblin/static/css/base.css56
-rw-r--r--mediagoblin/templates/mediagoblin/base.html1
-rw-r--r--mediagoblin/templates/mediagoblin/moderation/media_panel.html12
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/processing_panel.html106
-rw-r--r--mediagoblin/user_pages/routing.py5
-rw-r--r--mediagoblin/user_pages/views.py36
11 files changed, 233 insertions, 87 deletions
diff --git a/mediagoblin.example.ini b/mediagoblin.example.ini
index 52331d82..7b528359 100644
--- a/mediagoblin.example.ini
+++ b/mediagoblin.example.ini
@@ -57,4 +57,5 @@ base_url = /mgoblin_media/
[plugins]
[[mediagoblin.plugins.geolocation]]
[[mediagoblin.plugins.basic_auth]]
+[[mediagoblin.plugins.processing_info]]
[[mediagoblin.media_types.image]]
diff --git a/mediagoblin/plugins/processing_info/README.rst b/mediagoblin/plugins/processing_info/README.rst
new file mode 100644
index 00000000..3bacbf50
--- /dev/null
+++ b/mediagoblin/plugins/processing_info/README.rst
@@ -0,0 +1,5 @@
+==============
+ sampleplugin
+==============
+
+A plugin to insert some useful information about processing to templates
diff --git a/mediagoblin/plugins/processing_info/__init__.py b/mediagoblin/plugins/processing_info/__init__.py
new file mode 100644
index 00000000..e5ce0a1c
--- /dev/null
+++ b/mediagoblin/plugins/processing_info/__init__.py
@@ -0,0 +1,50 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+import logging
+import os
+
+from mediagoblin.tools.pluginapi import get_config
+from mediagoblin.db.models import MediaEntry
+from mediagoblin.tools import pluginapi
+
+_log = logging.getLogger(__name__)
+
+PLUGIN_DIR = os.path.dirname(__file__)
+
+def setup_plugin():
+ pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates'))
+ pluginapi.register_template_hooks(
+ {'header_left': 'mediagoblin/processing_info/header_left.html'})
+ return
+
+def make_stats(context):
+ request = context['request']
+ user = request.user
+ num_queued = MediaEntry.query.filter_by(
+ actor=user.id, state=u'processing').count()
+ context['num_queued'] = num_queued
+ num_failed = MediaEntry.query.filter_by(
+ actor=user.id, state=u'failed').count()
+ context['num_failed'] = num_failed
+ return context
+
+
+hooks = {
+ 'setup': setup_plugin,
+ 'template_context_prerender': make_stats
+ }
diff --git a/mediagoblin/plugins/processing_info/templates/mediagoblin/processing_info/header_left.html b/mediagoblin/plugins/processing_info/templates/mediagoblin/processing_info/header_left.html
new file mode 100644
index 00000000..1d5e724d
--- /dev/null
+++ b/mediagoblin/plugins/processing_info/templates/mediagoblin/processing_info/header_left.html
@@ -0,0 +1,32 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#}
+{#This injects some information about entries in processing #}
+{% if request.user and request.user.has_privilege('active') %}
+{% if num_queued is defined and num_queued != 0 %}
+<span class="num_queued status_icon">
+ <a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel',
+ user=request.user.username, state="processing") }}">&#9203; {{ num_queued }}</a>
+</span>
+{% endif %}
+{% if num_failed is defined and num_failed != 0 %}
+<span class="num_failed status_icon">
+ <a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel',
+ user=request.user.username, state="failed") }}">&#9785; {{ num_failed }}</a>
+</span>
+{% endif %}
+{% endif %}
diff --git a/mediagoblin/processing/__init__.py b/mediagoblin/processing/__init__.py
index aa8f1447..29345227 100644
--- a/mediagoblin/processing/__init__.py
+++ b/mediagoblin/processing/__init__.py
@@ -325,14 +325,13 @@ def mark_entry_failed(entry_id, exc):
u'fail_metadata': exc.metadata})
else:
_log.warn("No idea what happened here, but it failed: %r", exc)
- # Looks like no, so just mark it as failed and don't record a
- # failure_error (we'll assume it wasn't handled) and don't record
- # metadata (in fact overwrite it if somehow it had previous info
- # here)
+ # Looks like no, let's record it so that admin could ask us about the
+ # reason
atomic_update(mgg.database.MediaEntry,
{'id': entry_id},
{u'state': u'failed',
- u'fail_error': None,
+ u'fail_error': u'Unhandled exception: {0}'.format(
+ six.text_type(exc)),
u'fail_metadata': {}})
@@ -410,8 +409,11 @@ class BaseProcessingFail(Exception):
return u"%s:%s" % (
self.__class__.__module__, self.__class__.__name__)
- def __init__(self, **metadata):
- self.metadata = metadata or {}
+ def __init__(self, message=None, **metadata):
+ if message is not None:
+ super(BaseProcessingFail, self).__init__(message)
+ metadata['message'] = message
+ self.metadata = metadata
class BadMediaFail(BaseProcessingFail):
"""
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index f8726708..52c1f2dc 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -171,6 +171,26 @@ header {
a.logo {
color: #fff;
font-weight: bold;
+ text-decoration: none;
+}
+
+.status_icon {
+ border-radius: 2px;
+ padding: 4px;
+ margin: 0px 4px;
+}
+
+.num_queued {
+ background: #56446F;
+}
+
+.num_failed {
+ background: #87453B;
+}
+
+.status_icon a {
+ display: inline-block;
+ color: #C3C3C3;
}
.logo img {
@@ -754,6 +774,42 @@ table.media_panel th {
padding-bottom: 4px;
text-align: left;
}
+.thumb-overlay-status {
+ position: absolute;
+ margin: auto;
+ top: 0; bottom: 0; left: 0; right: 0;
+ width: 180px;
+ height: 20px;
+ display: inline;
+ text-align: center;
+ background-color: rgba(255, 255, 255, 0.8);
+}
+
+.thumb-processing {
+ color: black;
+ font-weight: bold;
+}
+
+.thumb-failed {
+ color: red;
+ font-weight: bold;
+}
+
+.thumb-wrapper {
+ position: relative;
+/* for proportional thumb resizing */
+ width: auto;
+ height: auto;
+ display: inline-block;
+}
+
+.thumb-wrapper img {
+ max-height: 180px;
+ max-width: 180px;
+}
+.media_panel td {
+ vertical-align: middle;
+}
/* moderator panels */
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 778cc3f9..9b0b7168 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -72,6 +72,7 @@
<div class="row foot">
<div class="header_left">
{%- include "mediagoblin/bits/logo.html" -%}
+ {% template_hook("header_left") %}
{% block mediagoblin_header_title %}{% endblock %}
</div>
<div class="header_right">
diff --git a/mediagoblin/templates/mediagoblin/moderation/media_panel.html b/mediagoblin/templates/mediagoblin/moderation/media_panel.html
index 888e4feb..94d4a1a0 100644
--- a/mediagoblin/templates/mediagoblin/moderation/media_panel.html
+++ b/mediagoblin/templates/mediagoblin/moderation/media_panel.html
@@ -43,8 +43,18 @@
</tr>
{% for media_entry in processing_entries %}
<tr>
+ <td>
+ <div class="thumb-wrapper">
+ <img src="{{ media_entry.thumb_url }}" alt="{{ media_entry.title }}" />
+ <div class="thumb-overlay-status thumb-processing">Processing...</div>
+ </div>
+ </td>
<td>{{ media_entry.id }}</td>
- <td>{{ media_entry.get_actor.username }}</td>
+ <td>
+ <a href="{{ request.urlgen('mediagoblin.moderation.users_detail', user=media_entry.get_actor.username) }}">
+ {{ media_entry.get_actor.username }}
+ </a>
+ </td>
<td>{{ media_entry.title }}</td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
{% if media_entry.transcoding_progress %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
index 2a449d45..96786937 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/processing_panel.html
@@ -17,6 +17,8 @@
#}
{% extends "mediagoblin/base.html" %}
+{% from "mediagoblin/utils/pagination.html" import render_pagination %}
+
{% block title -%}
{% trans %}Media processing panel{% endtrans %} &mdash; {{ super() }}
{%- endblock %}
@@ -28,20 +30,53 @@
<p>
{% trans %}You can track the state of media being processed for your gallery here.{% endtrans %}
</p>
-
-<h2>{% trans %}Media in-processing{% endtrans %}</h2>
-{% if processing_entries.count() %}
+<p>
+Show:
+<a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel',
+ user=request.user.username) }}">All</a>,
+<a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel',
+ user=request.user.username, state="processing") }}">In processing</a>,
+<a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel',
+ user=request.user.username, state="failed") }}">Failed</a>,
+<a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel',
+ user=request.user.username, state="processed") }}">Succesful</a>
+</p>
+
+{% if entries.count() %}
+ {{ render_pagination(request, pagination) }}
<table class="media_panel processing">
<tr>
- <th>ID</th>
+ <th width="210">Thumbnail</th>
<th>Title</th>
- <th>When submitted</th>
- <th>Transcoding progress</th>
+ <th width="20%">When submitted</th>
+ <th width="200">Transcoding progress</th>
</tr>
- {% for media_entry in processing_entries %}
+ {% for media_entry in entries %}
<tr>
- <td>{{ media_entry.id }}</td>
+ {% if media_entry.state == 'processed' %}
+ {% set entry_url = media_entry.url_for_self(request.urlgen) %}
+ <td>
+ <div class="thumb-wrapper">
+ <a href="{{ entry_url }}">
+ <img src="{{ media_entry.thumb_url }}" alt="{{ media_entry.title }}" />
+ </a>
+ </div>
+ </td>
+ <td><a href="{{ entry_url }}">{{ media_entry.title }}</a></td>
+ <td>{{ media_entry.created.strftime("%F %R") }}</td>
+ <td>Ready</td>
+ {% else %}
+ <td>
+ <div class="thumb-wrapper">
+ <img src="{{ media_entry.thumb_url }}" alt="{{ media_entry.title }}" />
+ {% if media_entry.state == 'processing' %}
+ <div class="thumb-overlay-status thumb-processing">Processing...</div>
+ {% elif media_entry.state == 'failed' %}
+ <div class="thumb-overlay-status thumb-failed">Failed!</div>
+ {% endif %}
+ </div>
+ </td>
<td>{{ media_entry.title }}</td>
<td>{{ media_entry.created.strftime("%F %R") }}</td>
{% if media_entry.transcoding_progress %}
@@ -49,61 +84,12 @@
{% else %}
<td>Unknown</td>
{% endif %}
+ {% endif %}
</tr>
{% endfor %}
</table>
+ {{ render_pagination(request, pagination) }}
{% else %}
- <p><em>{% trans %}No media in-processing{% endtrans %}</em></p>
+ <p><em>{% trans %}You have not uploaded anything yet!{% endtrans %}</em></p>
{% endif %}
-
-<h2>{% trans %}These uploads failed to process:{% endtrans %}</h2>
-{% if failed_entries.count() %}
-
- <table class="media_panel failed">
- <tr>
- <th>ID</th>
- <th>Title</th>
- <th>When submitted</th>
- <th>Reason for failure</th>
- <th>Failure metadata</th>
- </tr>
- {% for media_entry in failed_entries %}
- <tr>
- <td>{{ media_entry.id }}</td>
- <td>{{ media_entry.title }}</td>
- <td>{{ media_entry.created.strftime("%F %R") }}</td>
- {% if media_entry.get_fail_exception() %}
- <td>{{ media_entry.get_fail_exception().general_message }}</td>
- <td>{{ media_entry.fail_metadata }}</td>
- {% else %}
- <td>&nbsp;</td>
- <td>&nbsp;</td>
- {% endif %}
- </tr>
- {% endfor %}
- </table>
-{% else %}
- <p><em>{% trans %}No failed entries!{% endtrans %}</em></p>
-{% endif %}
-
-<h2>{% trans %}Your last 10 successful uploads{% endtrans %}</h2>
-{% if processed_entries.count() %}
-
- <table class="media_panel processed">
- <tr>
- <th>ID</th>
- <th>Title</th>
- <th>Submitted</th>
- </tr>
- {% for entry in processed_entries %}
- <tr>
- <td>{{ entry.id }}</td>
- <td><a href="{{ entry.url_for_self(request.urlgen) }}">{{ entry.title }}</a></td>
- <td>{{ entry.created.strftime("%F %R") }}</td>
- </tr>
- {% endfor %}
- </table>
-{% else %}
- <p><em>{% trans %}No processed entries, yet!{% endtrans %}</em></p>
-{% endif %}
{% endblock %}
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 1a1d4139..68cb0a3b 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -97,6 +97,11 @@ add_route('mediagoblin.user_pages.processing_panel',
'/u/<string:user>/panel/',
'mediagoblin.user_pages.views:processing_panel')
+add_route('mediagoblin.user_pages.processing_panel',
+ '/u/<string:user>/panel/<any(processed, processing, failed):state>/',
+ 'mediagoblin.user_pages.views:processing_panel')
+
+
# Stray edit routes
add_route('mediagoblin.edit.edit_media',
'/u/<string:user>/m/<int:media_id>/edit/',
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 88e077d4..547048d6 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -637,8 +637,10 @@ def collection_atom_feed(request):
return feed.get_response()
+@active_user_from_url
+@uses_pagination
@require_active_login
-def processing_panel(request):
+def processing_panel(request, page, url_user):
"""
Show to the user what media is still in conversion/processing...
and what failed, and why!
@@ -653,33 +655,29 @@ def processing_panel(request):
return redirect(
request, 'mediagoblin.user_pages.user_home',
user=user.username)
-
# Get media entries which are in-processing
- processing_entries = MediaEntry.query.\
- filter_by(actor = user.id,
- state = u'processing').\
- order_by(MediaEntry.created.desc())
+ entries = (MediaEntry.query.filter_by(actor=user.id)
+ .order_by(MediaEntry.created.desc()))
- # Get media entries which have failed to process
- failed_entries = MediaEntry.query.\
- filter_by(actor = user.id,
- state = u'failed').\
- order_by(MediaEntry.created.desc())
+ try:
+ state = request.matchdict['state']
+ # no exception was thrown, filter entries by state
+ entries = entries.filter_by(state=state)
+ except KeyError:
+ # show all entries
+ pass
- processed_entries = MediaEntry.query.\
- filter_by(actor = user.id,
- state = u'processed').\
- order_by(MediaEntry.created.desc()).\
- limit(10)
+ pagination = Pagination(page, entries)
+ pagination.per_page = 30
+ entries_on_a_page = pagination()
# Render to response
return render_to_response(
request,
'mediagoblin/user_pages/processing_panel.html',
{'user': user,
- 'processing_entries': processing_entries,
- 'failed_entries': failed_entries,
- 'processed_entries': processed_entries})
+ 'entries': entries_on_a_page,
+ 'pagination': pagination})
@allow_reporting
@get_user_media_entry