Mercurial > public > sg101
comparison gpp/messages/views2.py @ 425:76ba9478ebbd
Initial beta-test commit of a revamped, jquery ui tab-based PM system. This is for #211.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Tue, 26 Apr 2011 00:16:35 +0000 |
parents | |
children | 77b3b01843b5 |
comparison
equal
deleted
inserted
replaced
424:8df6e9edac22 | 425:76ba9478ebbd |
---|---|
1 """ | |
2 Views for the messages application. | |
3 | |
4 """ | |
5 import datetime | |
6 | |
7 from django.contrib.auth.decorators import login_required | |
8 from django.contrib import messages | |
9 from django.core.paginator import Paginator, EmptyPage, InvalidPage | |
10 from django.core.urlresolvers import reverse | |
11 from django.http import HttpResponse | |
12 from django.http import HttpResponseForbidden | |
13 from django.http import HttpResponseNotAllowed | |
14 from django.http import HttpResponseRedirect | |
15 from django.shortcuts import get_object_or_404 | |
16 from django.shortcuts import render | |
17 import django.utils.simplejson as json | |
18 | |
19 from messages.models import Message, Options | |
20 from messages.forms import OptionsForm, ComposeForm | |
21 from messages.utils import reply_subject, quote_message | |
22 | |
23 | |
24 MSGS_PER_PAGE = 20 | |
25 | |
26 TAB_INDICES = { | |
27 'inbox': 0, | |
28 'compose': 1, | |
29 'outbox': 2, | |
30 'trash': 3, | |
31 'options': 4, | |
32 } | |
33 | |
34 | |
35 def _get_page(request): | |
36 try: | |
37 n = int(request.GET.get('page', '1')) | |
38 except ValueError: | |
39 n = 1 | |
40 return n | |
41 | |
42 | |
43 @login_required | |
44 def index(request, tab=None): | |
45 """ | |
46 This function displays the base tabbed private messages view. | |
47 | |
48 """ | |
49 tab_index = TAB_INDICES[tab] if tab else 0 | |
50 return render(request, 'messages/tabbed_base.html', { | |
51 'tab': tab_index, | |
52 }) | |
53 | |
54 | |
55 def inbox(request): | |
56 """ | |
57 Returns the inbox for the user. | |
58 | |
59 """ | |
60 if not request.user.is_authenticated(): | |
61 return HttpResponseForbidden() | |
62 | |
63 msg_list = Message.objects.inbox(request.user) | |
64 paginator = Paginator(msg_list, MSGS_PER_PAGE) | |
65 try: | |
66 msgs = paginator.page(_get_page(request)) | |
67 except EmptyPage, InvalidPage: | |
68 msgs = paginator.page(paginator.num_pages) | |
69 | |
70 return render(request, 'messages/inbox_tab.html', { | |
71 'msgs': msgs, | |
72 'url': reverse('messages-beta_inbox'), | |
73 }) | |
74 | |
75 | |
76 def outbox(request): | |
77 """ | |
78 Returns the outbox for the user. | |
79 | |
80 """ | |
81 if not request.user.is_authenticated(): | |
82 return HttpResponseForbidden() | |
83 | |
84 msg_list = Message.objects.outbox(request.user) | |
85 paginator = Paginator(msg_list, MSGS_PER_PAGE) | |
86 try: | |
87 msgs = paginator.page(_get_page(request)) | |
88 except EmptyPage, InvalidPage: | |
89 msgs = paginator.page(paginator.num_pages) | |
90 | |
91 return render(request, 'messages/outbox_tab.html', { | |
92 'msgs': msgs, | |
93 'url': reverse('messages-beta_outbox'), | |
94 }) | |
95 | |
96 | |
97 def trash(request): | |
98 """ | |
99 Returns the trash for the user. | |
100 | |
101 """ | |
102 if not request.user.is_authenticated(): | |
103 return HttpResponseForbidden() | |
104 | |
105 msg_list = Message.objects.trash(request.user) | |
106 paginator = Paginator(msg_list, MSGS_PER_PAGE) | |
107 try: | |
108 msgs = paginator.page(_get_page(request)) | |
109 except EmptyPage, InvalidPage: | |
110 msgs = paginator.page(paginator.num_pages) | |
111 | |
112 return render(request, 'messages/trash_tab.html', { | |
113 'msgs': msgs, | |
114 'url': reverse('messages-beta_trash'), | |
115 }) | |
116 | |
117 | |
118 def message(request): | |
119 """ | |
120 This view function retrieves a message and returns it as a JSON object. | |
121 | |
122 """ | |
123 if not request.user.is_authenticated(): | |
124 return HttpResponseForbidden() | |
125 if request.method != 'POST': | |
126 return HttpResponseNotAllowed(['POST']) | |
127 | |
128 msg_id = request.POST.get('msg_id') | |
129 msg = get_object_or_404(Message.objects.select_related(), pk=msg_id) | |
130 if msg.sender != request.user and msg.receiver != request.user: | |
131 return HttpResponseForbidden() | |
132 | |
133 if msg.receiver == request.user and msg.read_date is None: | |
134 msg.read_date = datetime.datetime.now() | |
135 msg.save() | |
136 | |
137 msg_dict = dict(subject=msg.subject, | |
138 sender=msg.sender.username, | |
139 receiver=msg.receiver.username, | |
140 content=msg.html, | |
141 re_subject=reply_subject(msg.subject), | |
142 re_content=quote_message(msg.sender.username, msg.send_date, | |
143 msg.message)) | |
144 | |
145 result = json.dumps(msg_dict, ensure_ascii=False) | |
146 return HttpResponse(result, content_type='application/json') | |
147 | |
148 | |
149 def options(request): | |
150 """ | |
151 This view handles the displaying and changing of private message options. | |
152 | |
153 """ | |
154 if not request.user.is_authenticated(): | |
155 return HttpResponseForbidden() | |
156 | |
157 if request.method == "POST": | |
158 options = Options.objects.for_user(request.user) | |
159 form = OptionsForm(request.POST, instance=options, prefix='opts') | |
160 if form.is_valid(): | |
161 form.save() | |
162 messages.success(request, 'Options saved.') | |
163 else: | |
164 options = Options.objects.for_user(request.user) | |
165 form = OptionsForm(instance=options, prefix='opts') | |
166 | |
167 return render(request, 'messages/options_tab.html', { | |
168 'form': form, | |
169 }) | |
170 | |
171 | |
172 def compose(request, receiver=None): | |
173 """ | |
174 Process or prepare the compose form to create a new private message. | |
175 | |
176 """ | |
177 if not request.user.is_authenticated(): | |
178 return HttpResponseForbidden() | |
179 | |
180 if request.method == "POST": | |
181 compose_form = ComposeForm(request.user, request.POST) | |
182 if compose_form.is_valid(): | |
183 compose_form.save(sender=request.user) | |
184 messages.success(request, 'Message sent.') | |
185 return HttpResponseRedirect(reverse('messages-beta_index_named', args=['compose'])) | |
186 else: | |
187 if receiver is not None: | |
188 form_data = {'receiver': receiver} | |
189 compose_form = ComposeForm(request.user, initial=form_data) | |
190 else: | |
191 compose_form = ComposeForm(request.user) | |
192 | |
193 return render(request, 'messages/compose_tab.html', { | |
194 'compose_form': compose_form, | |
195 }) | |
196 | |
197 | |
198 def _only_integers(slist): | |
199 """ | |
200 Accepts a list of strings. Returns a list of integers consisting of only | |
201 those elements from the original list that could be converted to integers | |
202 | |
203 """ | |
204 result = [] | |
205 for s in slist: | |
206 try: | |
207 n = int(s) | |
208 except ValueError: | |
209 pass | |
210 else: | |
211 result.append(n) | |
212 return result | |
213 | |
214 | |
215 def _delete_msgs(user, msg_ids): | |
216 """ | |
217 Deletes the messages given by the list of msg_ids. For this to succeed, the | |
218 user has to be either the sender or receiver on each message. | |
219 | |
220 """ | |
221 msg_ids = _only_integers(msg_ids) | |
222 msgs = Message.objects.filter(id__in=msg_ids) | |
223 | |
224 for msg in msgs: | |
225 if msg.sender == user: | |
226 if (msg.receiver_delete_date is not None or | |
227 msg.read_date is None): | |
228 # Both parties deleted the message or receiver hasn't read it | |
229 # yet, we can delete it now | |
230 msg.delete() | |
231 else: | |
232 # receiver still has it in inbox | |
233 msg.sender_delete_date = datetime.datetime.now() | |
234 msg.save() | |
235 | |
236 elif msg.receiver == user: | |
237 if msg.sender_delete_date is not None: | |
238 # both parties deleted the message, we can delete it now | |
239 msg.delete() | |
240 else: | |
241 # sender still has it in the outbox | |
242 msg.receiver_delete_date = datetime.datetime.now() | |
243 msg.save() | |
244 | |
245 | |
246 def _undelete_msgs(user, msg_ids): | |
247 """ | |
248 Attempts to "undelete" the messages given by the msg_ids list. | |
249 This will only succeed if the user is either the sender or receiver. | |
250 | |
251 """ | |
252 msg_ids = _only_integers(msg_ids) | |
253 msgs = Message.objects.filter(id__in=msg_ids) | |
254 for msg in msgs: | |
255 if msg.sender == user: | |
256 msg.sender_delete_date = None | |
257 msg.save() | |
258 elif msg.receiver == user: | |
259 msg.receiver_delete_date = None | |
260 msg.save() | |
261 | |
262 | |
263 def bulk(request): | |
264 """ | |
265 This view processes messages in bulk. Arrays of message ids are expected in | |
266 the POST query dict: inbox_ids and outbox_ids will be deleted; trash_ids will | |
267 be undeleted. | |
268 | |
269 """ | |
270 if not request.user.is_authenticated(): | |
271 return HttpResponseForbidden() | |
272 if request.method != 'POST': | |
273 return HttpResponseNotAllowed(['POST']) | |
274 | |
275 delete_ids = [] | |
276 if 'inbox_ids' in request.POST: | |
277 delete_ids.extend(request.POST.getlist('inbox_ids')) | |
278 if 'outbox_ids' in request.POST: | |
279 delete_ids.extend(request.POST.getlist('outbox_ids')) | |
280 | |
281 if len(delete_ids): | |
282 _delete_msgs(request.user, delete_ids) | |
283 | |
284 if 'trash_ids' in request.POST: | |
285 _undelete_msgs(request.user, request.POST.getlist('trash_ids')) | |
286 | |
287 return HttpResponse(''); |