Multimedia support - Commiting from a not yet finished state - Details below
[mediagoblin.git] / mediagoblin / user_pages / views.py
CommitLineData
01c75c7e 1# MediaGoblin -- federated, autonomous media hosting
12a100e4 2# Copyright (C) 2011 MediaGoblin contributors. See AUTHORS.
9a16e16f
SS
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
1c63ad5d 17from webob import exc
52359e91 18
3a8c3a38 19from mediagoblin import messages, mg_globals
9074ee7c 20from mediagoblin.db.util import DESCENDING, ObjectId
95e6da02 21from mediagoblin.util import (
de12b4e7 22 Pagination, render_to_response, redirect, cleaned_markdown_conversion,
502073f2 23 render_404, delete_media_files)
7a4c0126 24from mediagoblin.util import pass_to_ugettext as _
9074ee7c 25from mediagoblin.user_pages import forms as user_forms
f6249408 26
50854db0 27from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
502073f2 28 require_active_login, user_may_delete_media)
9a16e16f 29
00c39256 30from werkzeug.contrib.atom import AtomFeed
1301a8ad 31
93bdab9d
JW
32from mediagoblin.media_types import get_media_manager
33
9074ee7c 34
3eb6fc4f 35@uses_pagination
1301a8ad 36def user_home(request, page):
9a16e16f 37 """'Homepage' of a User()"""
7acdbfd3 38 user = request.db.User.find_one({
990d3b69 39 'username': request.matchdict['user']})
7acdbfd3 40 if not user:
de12b4e7 41 return render_404(request)
990d3b69
CAW
42 elif user['status'] != u'active':
43 return render_to_response(
44 request,
45 'mediagoblin/user_pages/user.html',
46 {'user': user})
9a16e16f 47
434b3221 48 cursor = request.db.MediaEntry.find(
16509be1 49 {'uploader': user['_id'],
434b3221 50 'state': 'processed'}).sort('created', DESCENDING)
9a16e16f 51
1301a8ad 52 pagination = Pagination(page, cursor)
ca3ca51c 53 media_entries = pagination()
44e3e917 54
ae85ed0f
BK
55 #if no data is available, return NotFound
56 if media_entries == None:
de12b4e7 57 return render_404(request)
ae85ed0f 58
5949be9a
CAW
59 user_gallery_url = request.urlgen(
60 'mediagoblin.user_pages.user_gallery',
61 user=user['username'])
62
9038c9f9
CAW
63 return render_to_response(
64 request,
c9c24934
E
65 'mediagoblin/user_pages/user.html',
66 {'user': user,
5949be9a 67 'user_gallery_url': user_gallery_url,
c9c24934
E
68 'media_entries': media_entries,
69 'pagination': pagination})
f6249408 70
184f2240 71@uses_pagination
72def user_gallery(request, page):
73 """'Gallery' of a User()"""
74 user = request.db.User.find_one({
75 'username': request.matchdict['user'],
76 'status': 'active'})
77 if not user:
de12b4e7 78 return render_404(request)
184f2240 79
80 cursor = request.db.MediaEntry.find(
81 {'uploader': user['_id'],
82 'state': 'processed'}).sort('created', DESCENDING)
83
84 pagination = Pagination(page, cursor)
85 media_entries = pagination()
86
87 #if no data is available, return NotFound
88 if media_entries == None:
de12b4e7 89 return render_404(request)
184f2240 90
4b5f5a08 91 return render_to_response(
92 request,
93 'mediagoblin/user_pages/gallery.html',
94 {'user': user,
95 'media_entries': media_entries,
96 'pagination': pagination})
184f2240 97
6f59a3a3 98MEDIA_COMMENTS_PER_PAGE = 50
434b3221 99
01674e10 100@get_user_media_entry
9074ee7c 101@uses_pagination
6f59a3a3 102def media_home(request, media, page, **kwargs):
9074ee7c
JW
103 """
104 'Homepage' of a MediaEntry()
105 """
af2fcba5
JW
106 if ObjectId(request.matchdict.get('comment')):
107 pagination = Pagination(
108 page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE,
109 ObjectId(request.matchdict.get('comment')))
110 else:
111 pagination = Pagination(
112 page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE)
9074ee7c 113
6f59a3a3 114 comments = pagination()
9074ee7c 115
6f59a3a3 116 comment_form = user_forms.MediaCommentForm(request.POST)
9074ee7c 117
93bdab9d
JW
118 media_template_name = get_media_manager(media['media_type'])['display_template']
119
9038c9f9
CAW
120 return render_to_response(
121 request,
93bdab9d 122 media_template_name,
9074ee7c
JW
123 {'media': media,
124 'comments': comments,
125 'pagination': pagination,
3a8c3a38
JW
126 'comment_form': comment_form,
127 'app_config': mg_globals.app_config})
9074ee7c 128
95e6da02 129
9074ee7c
JW
130@require_active_login
131def media_post_comment(request):
132 """
133 recieves POST from a MediaEntry() comment form, saves the comment.
134 """
135 comment = request.db.MediaComment()
136 comment['media_entry'] = ObjectId(request.matchdict['media'])
137 comment['author'] = request.user['_id']
08750772 138 comment['content'] = unicode(request.POST['comment_content'])
9074ee7c 139
95e6da02 140 comment['content_html'] = cleaned_markdown_conversion(comment['content'])
9074ee7c
JW
141
142 comment.save()
b5d3aec6 143
52359e91
CAW
144 messages.add_message(
145 request, messages.SUCCESS,
146 'Comment posted!')
147
9074ee7c
JW
148 return redirect(request, 'mediagoblin.user_pages.media_home',
149 media = request.matchdict['media'],
150 user = request.matchdict['user'])
00c39256 151
95e6da02 152
502073f2
JW
153@get_user_media_entry
154@require_active_login
155@user_may_delete_media
156def media_confirm_delete(request, media):
157
158 form = user_forms.ConfirmDeleteForm(request.POST)
159
160 if request.method == 'POST' and form.validate():
8daef28d 161 if form.confirm.data is True:
502073f2
JW
162 username = media.uploader()['username']
163
164 # Delete all files on the public storage
165 delete_media_files(media)
166
167 media.delete()
168
169 return redirect(request, "mediagoblin.user_pages.user_home",
170 user=username)
171 else:
8d7b549b
E
172 return exc.HTTPFound(
173 location=media.url_for_self(request.urlgen))
502073f2 174
7a4c0126
CAW
175 if ((request.user[u'is_admin'] and
176 request.user[u'_id'] != media.uploader()[u'_id'])):
177 messages.add_message(
178 request, messages.WARNING,
179 _("You are about to delete another user's media. "
180 "Proceed with caution."))
181
502073f2
JW
182 return render_to_response(
183 request,
184 'mediagoblin/user_pages/media_confirm_delete.html',
185 {'media': media,
186 'form': form})
187
188
a5303e47 189ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 15
00c39256
BK
190
191def atom_feed(request):
192 """
193 generates the atom feed with the newest images
194 """
195
196 user = request.db.User.find_one({
197 'username': request.matchdict['user'],
198 'status': 'active'})
199 if not user:
de12b4e7 200 return render_404(request)
00c39256
BK
201
202 cursor = request.db.MediaEntry.find({
203 'uploader': user['_id'],
204 'state': 'processed'}) \
205 .sort('created', DESCENDING) \
206 .limit(ATOM_DEFAULT_NR_OF_UPDATED_ITEMS)
207
208 feed = AtomFeed(request.matchdict['user'],
209 feed_url=request.url,
210 url=request.host_url)
44e2da2f 211
00c39256
BK
212 for entry in cursor:
213 feed.add(entry.get('title'),
44e2da2f 214 entry.get('description_html'),
00c39256
BK
215 content_type='html',
216 author=request.matchdict['user'],
217 updated=entry.get('created'),
218 url=entry.url_for_self(request.urlgen))
219
9074ee7c 220 return feed.get_response()
01c75c7e
CAW
221
222
223@require_active_login
224def processing_panel(request):
225 """
226 Show to the user what media is still in conversion/processing...
227 and what failed, and why!
228 """
229 # Get the user
230 user = request.db.User.find_one(
231 {'username': request.matchdict['user'],
232 'status': 'active'})
233
234 # Make sure the user exists and is active
235 if not user:
de12b4e7 236 return render_404(request)
01c75c7e
CAW
237 elif user['status'] != u'active':
238 return render_to_response(
239 request,
240 'mediagoblin/user_pages/user.html',
241 {'user': user})
242
243 # XXX: Should this be a decorator?
244 #
245 # Make sure we have permission to access this user's panel. Only
246 # admins and this user herself should be able to do so.
247 if not (user[u'_id'] == request.user[u'_id']
248 or request.user.is_admin):
249 # No? Let's simply redirect to this user's homepage then.
250 return redirect(
251 request, 'mediagoblin.user_pages.user_home',
252 user=request.matchdict['user'])
253
254 # Get media entries which are in-processing
255 processing_entries = request.db.MediaEntry.find(
256 {'uploader': user['_id'],
257 'state': 'processing'}).sort('created', DESCENDING)
258
259 # Get media entries which have failed to process
260 failed_entries = request.db.MediaEntry.find(
261 {'uploader': user['_id'],
262 'state': 'failed'}).sort('created', DESCENDING)
263
264 # Render to response
265 return render_to_response(
266 request,
267 'mediagoblin/user_pages/processing_panel.html',
268 {'user': user,
269 'processing_entries': processing_entries,
270 'failed_entries': failed_entries})