forked from adamlaska/datatracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathviews_material.py
More file actions
220 lines (171 loc) · 8.61 KB
/
views_material.py
File metadata and controls
220 lines (171 loc) · 8.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# Copyright The IETF Trust 2014-2020, All Rights Reserved
# -*- coding: utf-8 -*-
# views for managing group materials (slides, ...)
import io
import os
import re
from django import forms
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.shortcuts import render, get_object_or_404, redirect
from django.utils.html import mark_safe # type:ignore
from django.urls import reverse as urlreverse
import debug # pyflakes:ignore
from ietf.doc.models import Document, DocAlias, DocTypeName, DocEvent, State
from ietf.doc.models import NewRevisionDocEvent
from ietf.doc.utils import add_state_change_event, check_common_doc_name_rules
from ietf.group.models import Group
from ietf.group.utils import can_manage_materials
from ietf.utils.response import permission_denied
@login_required
def choose_material_type(request, acronym):
group = get_object_or_404(Group, acronym=acronym)
if not group.features.has_nonsession_materials:
raise Http404
return render(request, 'doc/material/choose_material_type.html', {
'group': group,
'material_types': DocTypeName.objects.filter(slug__in=group.features.material_types),
})
class UploadMaterialForm(forms.Form):
title = forms.CharField(max_length=Document._meta.get_field("title").max_length)
name = forms.CharField(max_length=Document._meta.get_field("name").max_length)
abstract = forms.CharField(max_length=Document._meta.get_field("abstract").max_length,widget=forms.Textarea, strip=False)
state = forms.ModelChoiceField(State.objects.all(), empty_label=None)
material = forms.FileField(label='File')
def __init__(self, doc_type, action, group, doc, *args, **kwargs):
super(UploadMaterialForm, self).__init__(*args, **kwargs)
self.fields["state"].queryset = self.fields["state"].queryset.filter(type__slug=doc_type.slug)
self.doc_type = doc_type
self.action = action
self.group = group
if action == "new":
self.fields["state"].widget = forms.HiddenInput()
self.fields["state"].queryset = self.fields["state"].queryset.filter(slug="active")
self.fields["state"].initial = self.fields["state"].queryset[0].pk
self.fields["name"].initial = self._default_name()
else:
del self.fields["name"]
self.fields["title"].initial = doc.title
self.fields["abstract"].initial = doc.abstract
self.fields["state"].initial = doc.get_state().pk if doc.get_state() else None
if doc.get_state_slug() == "deleted":
self.fields["state"].help_text = "Note: If you wish to revise this document, you may wish to change the state so it's not deleted."
if action in ["title","state","abstract"]:
for fieldname in ["title","state","material","abstract"]:
if fieldname != action:
del self.fields[fieldname]
if doc_type.slug == 'procmaterials' and 'abstract' in self.fields:
del self.fields['abstract']
def _default_name(self):
return "%s-%s-" % (self.doc_type.slug, self.group.acronym)
def clean_name(self):
name = self.cleaned_data["name"].strip().rstrip("-")
check_common_doc_name_rules(name)
if not re.search("^%s-%s-[a-z0-9]+" % (self.doc_type.slug, self.group.acronym), name):
raise forms.ValidationError("The name must start with %s-%s- followed by descriptive dash-separated words." % (self.doc_type.slug, self.group.acronym))
existing = Document.objects.filter(type=self.doc_type, name=name)
if existing:
url = urlreverse('ietf.doc.views_material.edit_material', kwargs={ 'name': existing[0].name, 'action': 'revise' })
raise forms.ValidationError(mark_safe("Can't upload: %s with name %s already exists. Choose another title and name for what you're uploading or <a href=\"%s\">revise the existing %s</a>." % (self.doc_type.name, name, url, name)))
return name
@login_required
def edit_material(request, name=None, acronym=None, action=None, doc_type=None):
# the materials process is not very developed, so at the moment we
# handle everything through the same view/form
if action == "new":
group = get_object_or_404(Group, acronym=acronym)
if not group.features.has_nonsession_materials:
raise Http404
doc = None
document_type = get_object_or_404(DocTypeName, slug=doc_type)
else:
doc = get_object_or_404(Document, name=name)
group = doc.group
document_type = doc.type
valid_doctypes = ['procmaterials']
if group is not None:
valid_doctypes.extend(['minutes','agenda','bluesheets'])
valid_doctypes.extend(group.features.material_types)
if document_type.slug not in valid_doctypes:
raise Http404
if not can_manage_materials(request.user, group):
permission_denied(request, "You don't have permission to access this view")
if request.method == 'POST':
form = UploadMaterialForm(document_type, action, group, doc, request.POST, request.FILES)
if form.is_valid():
events = []
if action == "new":
doc = Document.objects.create(
type=document_type,
group=group,
rev="00",
name=form.cleaned_data["name"])
prev_rev = None
else:
prev_rev = doc.rev
prev_title = doc.title
prev_state = doc.get_state()
prev_abstract = doc.abstract
if "title" in form.cleaned_data:
doc.title = form.cleaned_data["title"]
if "abstract" in form.cleaned_data:
doc.abstract = form.cleaned_data["abstract"]
if "material" in form.fields:
if action != "new":
doc.rev = "%02d" % (int(doc.rev) + 1)
f = form.cleaned_data["material"]
file_ext = os.path.splitext(f.name)[1]
with io.open(os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + file_ext), 'wb+') as dest:
for chunk in f.chunks():
dest.write(chunk)
if action == "new":
alias, __ = DocAlias.objects.get_or_create(name=doc.name)
alias.docs.add(doc)
if prev_rev != doc.rev:
e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev)
e.by = request.user.person
e.desc = "New version available: <b>%s-%s</b>" % (doc.name, doc.rev)
e.save()
events.append(e)
if prev_title != doc.title:
e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document')
e.desc = "Changed title to <b>%s</b>" % doc.title
if prev_title:
e.desc += " from %s" % prev_title
e.save()
events.append(e)
if prev_abstract != doc.abstract:
e = DocEvent(doc=doc, rev=doc.rev, by=request.user.person, type='changed_document')
e.desc = "Changed abstract to <b>%s</b>" % doc.abstract
if prev_abstract:
e.desc += " from %s" % prev_abstract
e.save()
events.append(e)
if "state" in form.cleaned_data and form.cleaned_data["state"] != prev_state:
doc.set_state(form.cleaned_data["state"])
e = add_state_change_event(doc, request.user.person, prev_state, form.cleaned_data["state"])
events.append(e)
if events:
doc.save_with_history(events)
return redirect("ietf.doc.views_doc.document_main", name=doc.name)
else:
form = UploadMaterialForm(document_type, action, group, doc)
# decide where to go if upload is canceled
if doc:
back_href = urlreverse('ietf.doc.views_doc.document_main', kwargs={'name': doc.name})
else:
back_href = urlreverse('ietf.group.views.materials', kwargs={'acronym': group.acronym})
if document_type.slug == 'procmaterials':
name_prefix = 'proceedings-'
else:
name_prefix = f'{document_type.slug}-{group.acronym}-'
return render(request, 'doc/material/edit_material.html', {
'group': group,
'form': form,
'action': action,
'material_type': document_type,
'name_prefix': name_prefix,
'doc': doc,
'doc_name': doc.name if doc else "",
'back_href': back_href,
})