d4d0f6dc7964257b2acdac66d056e0759a71af01
[redakcja.git] / apps / explorer / views.py
1 # -*- coding: utf-8 -*-
2 from librarian import html
3 import hg, urllib2, time
4
5 from django.utils import simplejson as json
6
7 from librarian import dcparser, parser
8 from librarian import ParseError, ValidationError
9
10 from django.views.generic.simple import direct_to_template
11
12 from django.conf import settings
13 from django.http import HttpResponseRedirect, HttpResponse
14
15 from django.core.urlresolvers import reverse
16 from django.core.paginator import Paginator, InvalidPage, EmptyPage
17
18 from django.contrib.auth.decorators import login_required, permission_required
19
20 from explorer import forms, models
21
22 #
23 # Some useful decorators
24 #
25 def with_repo(view):
26     """Open a repository for this view"""
27     def view_with_repo(request, *args, **kwargs):          
28         kwargs['repo'] = hg.Repository(settings.REPOSITORY_PATH)
29         return view(request, *args, **kwargs)
30     return view_with_repo
31
32 #
33 def ajax_login_required(view):
34     """Similar ro @login_required, but instead of redirect, 
35     just return some JSON stuff with error."""
36     def view_with_auth(request, *args, **kwargs):
37         if request.user.is_authenticated():
38             return view(request, *args, **kwargs)
39         # not authenticated
40         return HttpResponse( json.dumps({'result': 'access_denied'}) );
41     return view_with_auth
42
43 #
44 # View all files
45 #
46 @with_repo
47 def file_list(request, repo):
48     paginator = Paginator( repo.file_list('default'), 100);
49     bookform = forms.BookUploadForm()
50
51     try:
52         page = int(request.GET.get('page', '1'))
53     except ValueError:
54         page = 1
55
56     try:
57         files = paginator.page(page)
58     except (EmptyPage, InvalidPage):
59         files = paginator.page(paginator.num_pages)
60
61     return direct_to_template(request, 'explorer/file_list.html', extra_context={
62         'files': files, 'page': page, 'bookform': bookform,
63     })
64
65 @permission_required('explorer.can_add_files')
66 @with_repo
67 def file_upload(request, repo):
68     form = forms.BookUploadForm(request.POST, request.FILES)
69     if form.is_valid():
70         f = request.FILES['file']        
71
72         def upload_action():
73             print 'Adding file: %s' % f.name
74             repo._add_file(f.name, f.read().decode('utf-8'))
75             repo._commit(message="File %s uploaded from platform by %s" %
76                 (f.name, request.user.username), user=request.user.username)
77
78         repo.in_branch(upload_action, 'default')
79         return HttpResponseRedirect( reverse('editor_view', kwargs={'path': f.name}) )
80
81     return direct_to_template(request, 'explorer/file_upload.html',
82         extra_context = {'form' : form} )
83    
84 #
85 # Edit the file
86 #
87
88 @ajax_login_required
89 @with_repo
90 def file_xml(request, repo, path):
91     if request.method == 'POST':
92         errors = None
93         form = forms.BookForm(request.POST)
94         if form.is_valid():
95             print 'Saving whole text.', request.user.username
96             def save_action():
97                 print 'In branch: ' + repo.repo[None].branch()
98                 repo._add_file(path, form.cleaned_data['content'])                
99                 repo._commit(message=(form.cleaned_data['commit_message'] or 'Lokalny zapis platformy.'),\
100                      user=request.user.username)
101             try:
102                 # wczytaj dokument z ciągu znaków -> weryfikacja
103                 document = parser.WLDocument.from_string(form.cleaned_data['content'])
104
105                 #  save to user's branch
106                 repo.in_branch(save_action, models.user_branch(request.user) );
107             except (ParseError, ValidationError), e:
108                 errors = [e.message]              
109
110         if not errors:
111             errors = dict( (field[0], field[1].as_text()) for field in form.errors.iteritems() )
112
113         return HttpResponse(json.dumps({'result': errors and 'error' or 'ok', 'errors': errors}));
114
115     form = forms.BookForm()
116     data = repo.get_file(path, models.user_branch(request.user))
117     form.fields['content'].initial = data
118     return HttpResponse( json.dumps({'result': 'ok', 'content': data}) ) 
119
120 @ajax_login_required
121 @with_repo
122 def file_dc(request, path, repo):
123     if request.method == 'POST':
124         form = forms.DublinCoreForm(request.POST)
125         errors = None
126         
127         if form.is_valid():
128             def save_action():
129                 file_contents = repo._get_file(path)
130
131                 # wczytaj dokument z repozytorium
132                 document = parser.WLDocument.from_string(file_contents)
133
134                 rdf_ns = dcparser.BookInfo.RDF
135                 dc_ns = dcparser.BookInfo.DC
136
137                 rdf_attrs = {rdf_ns('about'): form.cleaned_data.pop('about')}
138                 field_dict = {}
139                     
140                 for key, value in form.cleaned_data.items():
141                     field_dict[ dc_ns(key) ] = value if isinstance(value, list) else [value]
142
143                 print field_dict
144
145                 new_info = dcparser.BookInfo(rdf_attrs, field_dict)
146                 document.book_info = new_info
147
148                 print "SAVING DC"
149
150                     # zapisz
151                 repo._add_file(path, document.serialize())
152                 repo._commit( \
153                     message=(form.cleaned_data['commit_message'] or 'Lokalny zapis platformy.'), \
154                     user=request.user.username )
155                 
156             try:
157                 repo.in_branch(save_action, models.user_branch(request.user) )
158             except (ParseError, ValidationError), e:
159                 errors = [e.message]
160
161         if errors is None:
162             errors = dict( (field[0], field[1].as_text()) for field in form.errors.iteritems() )
163
164         return HttpResponse( json.dumps({'result': errors and 'error' or 'ok', 'errors': errors}) );
165     
166     fulltext = repo.get_file(path, models.user_branch(request.user))
167     form = forms.DublinCoreForm(text=fulltext)       
168     return HttpResponse( json.dumps({'result': 'ok', 'content': fulltext}) ) 
169
170 # Display the main editor view
171
172 @login_required
173 def display_editor(request, path):
174     return direct_to_template(request, 'explorer/editor.html', extra_context={
175         'hash': path, 'panel_list': ['lewy', 'prawy'],
176     })
177
178 # ===============
179 # = Panel views =
180 # ===============
181
182 @ajax_login_required
183 @with_repo
184 def xmleditor_panel(request, path, repo):
185     form = forms.BookForm()
186     text = repo.get_file(path, models.user_branch(request.user))
187     
188     return direct_to_template(request, 'explorer/panels/xmleditor.html', extra_context={
189         'fpath': path,
190         'text': text,
191     })
192     
193
194 @ajax_login_required
195 def gallery_panel(request, path):
196     return direct_to_template(request, 'explorer/panels/gallery.html', extra_context={
197         'fpath': path,
198         'form': forms.ImageFoldersForm(),
199     })
200
201 @ajax_login_required
202 @with_repo
203 def htmleditor_panel(request, path, repo):
204     user_branch = models.user_branch(request.user)
205     return direct_to_template(request, 'explorer/panels/htmleditor.html', extra_context={
206         'fpath': path,
207         'html': html.transform(repo.get_file(path, user_branch), is_file=False),
208     })
209  
210
211 @ajax_login_required
212 @with_repo
213 def dceditor_panel(request, path, repo):
214     user_branch = models.user_branch(request.user)
215     doc_text = repo.get_file(path, user_branch)
216
217     document = parser.WLDocument.from_string(doc_text)
218     form = forms.DublinCoreForm(info=document.book_info)       
219
220     return direct_to_template(request, 'explorer/panels/dceditor.html', extra_context={
221         'fpath': path,
222         'form': form,
223     })
224
225
226 # =================
227 # = Utility views =
228 # =================
229 @ajax_login_required
230 def folder_images(request, folder):
231     return direct_to_template(request, 'explorer/folder_images.html', extra_context={
232         'images': models.get_images_from_folder(folder),
233     })
234
235
236 def _add_references(message, issues):
237     return message + " - " + ", ".join(map(lambda issue: "Refs #%d" % issue['id'], issues))
238
239 def _get_issues_for_file(path):
240     if not path.endswith('.xml'):
241         raise ValueError('Path must end with .xml')
242
243     book_id = path[:-4]
244     uf = None
245
246     try:
247         uf = urllib2.urlopen(settings.REDMINE_URL + 'publications/issues/%s.json' % book_id)
248         return json.loads(uf.read())
249     except urllib2.HTTPError:
250         return []
251     finally:
252         if uf: uf.close()
253
254
255 # =================
256 # = Pull requests =
257 # =================
258 def pull_requests(request):
259     return direct_to_template(request, 'manager/pull_request.html', extra_context = {
260         'objects': models.PullRequest.objects.all()} )