Restore names of uploaded files on submit/draft restore (#65)
This involved turning the list of file IDs stored in the hidden text field into JSON.
This commit is contained in:
parent
b5ccbf631d
commit
79dffadd14
@ -19,6 +19,9 @@ class BaseFile(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.file.name
|
return self.file.name
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return self.file.name
|
||||||
|
|
||||||
|
|
||||||
class File(BaseFile):
|
class File(BaseFile):
|
||||||
pass
|
pass
|
||||||
|
@ -65,10 +65,25 @@ class MultipleFilesWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rebuildListFromField() {
|
rebuildListFromField() {
|
||||||
let idList = this.element.field.value.split(",")
|
const fieldContents = this.element.field.value
|
||||||
for (let id of idList) {
|
|
||||||
this.addFile(id, `Saved upload (id ${id})`, this.status.DONE)
|
// Nothing to do
|
||||||
|
if (fieldContents === '') {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let list = JSON.parse(fieldContents)
|
||||||
|
for (let file of list) {
|
||||||
|
this.addFile(file.id, file.name, this.status.DONE)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Not JSON, let's parse as CSV
|
||||||
|
for (let id of fieldContents.split(",")) {
|
||||||
|
this.addFile(id, `Saved upload (id ${id})`, this.status.DONE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.viewFileList()
|
this.viewFileList()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +160,13 @@ class MultipleFilesWidget {
|
|||||||
|
|
||||||
updateFormField() {
|
updateFormField() {
|
||||||
let oldVal = this.element.field.value
|
let oldVal = this.element.field.value
|
||||||
this.element.field.value = this.fileList.filter(f => f.id != null)
|
let fileList = this.fileList.filter(f => f.id != null)
|
||||||
.map(f => f.id)
|
.map(f => ({
|
||||||
.toString()
|
id: f.id,
|
||||||
|
name: f.name
|
||||||
|
}))
|
||||||
|
|
||||||
|
this.element.field.value = JSON.stringify(fileList)
|
||||||
|
|
||||||
// Mark form as dirty
|
// Mark form as dirty
|
||||||
if (this.element.field.value !== oldVal) {
|
if (this.element.field.value !== oldVal) {
|
||||||
|
@ -12,7 +12,7 @@ from leaflet.forms.widgets import LeafletWidget
|
|||||||
from apps.files.models import File, ImageFile
|
from apps.files.models import File, ImageFile
|
||||||
|
|
||||||
from .models import CaseStudy, SpatialRefSys
|
from .models import CaseStudy, SpatialRefSys
|
||||||
from .widgets import CommaSeparatedTextInput
|
from .widgets import JSONFileListWidget
|
||||||
|
|
||||||
|
|
||||||
class MinimumZoomWidget(LeafletWidget):
|
class MinimumZoomWidget(LeafletWidget):
|
||||||
@ -94,7 +94,7 @@ class LongCaseStudyForm(BaseCaseStudyForm):
|
|||||||
|
|
||||||
images_files = forms.ModelMultipleChoiceField(
|
images_files = forms.ModelMultipleChoiceField(
|
||||||
queryset=ImageFile.objects.all(),
|
queryset=ImageFile.objects.all(),
|
||||||
widget=CommaSeparatedTextInput(),
|
widget=JSONFileListWidget(),
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ class LongCaseStudyForm(BaseCaseStudyForm):
|
|||||||
|
|
||||||
official_project_documents_files = forms.ModelMultipleChoiceField(
|
official_project_documents_files = forms.ModelMultipleChoiceField(
|
||||||
queryset=File.objects.all(),
|
queryset=File.objects.all(),
|
||||||
widget=CommaSeparatedTextInput(),
|
widget=JSONFileListWidget(),
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ class LongCaseStudyForm(BaseCaseStudyForm):
|
|||||||
|
|
||||||
other_documents_files = forms.ModelMultipleChoiceField(
|
other_documents_files = forms.ModelMultipleChoiceField(
|
||||||
queryset=File.objects.all(),
|
queryset=File.objects.all(),
|
||||||
widget=CommaSeparatedTextInput(),
|
widget=JSONFileListWidget(),
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ class LongCaseStudyForm(BaseCaseStudyForm):
|
|||||||
|
|
||||||
shapefiles_files = forms.ModelMultipleChoiceField(
|
shapefiles_files = forms.ModelMultipleChoiceField(
|
||||||
queryset=File.objects.all(),
|
queryset=File.objects.all(),
|
||||||
widget=CommaSeparatedTextInput(),
|
widget=JSONFileListWidget(),
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class BaseForm(LoginRequiredMixin, CreateView):
|
|||||||
self.object = form.save()
|
self.object = form.save()
|
||||||
|
|
||||||
self.object.official_project_documents = form.cleaned_data.get(
|
self.object.official_project_documents = form.cleaned_data.get(
|
||||||
'official_project_document_files', []
|
'official_project_documents_files', []
|
||||||
)
|
)
|
||||||
self.object.other_documents = form.cleaned_data.get(
|
self.object.other_documents = form.cleaned_data.get(
|
||||||
'other_documents_files', []
|
'other_documents_files', []
|
||||||
@ -76,6 +76,9 @@ class BaseForm(LoginRequiredMixin, CreateView):
|
|||||||
self.object.shapefiles = form.cleaned_data.get(
|
self.object.shapefiles = form.cleaned_data.get(
|
||||||
'shapefiles_files', []
|
'shapefiles_files', []
|
||||||
)
|
)
|
||||||
|
self.object.images = form.cleaned_data.get(
|
||||||
|
'images_files', []
|
||||||
|
)
|
||||||
|
|
||||||
self.object.author = self.request.user
|
self.object.author = self.request.user
|
||||||
self.object.save()
|
self.object.save()
|
||||||
@ -160,37 +163,33 @@ class Drafts(LoginRequiredMixin, View):
|
|||||||
if draft != None:
|
if draft != None:
|
||||||
data = json.loads(draft.data)
|
data = json.loads(draft.data)
|
||||||
|
|
||||||
for k in ['official_project_documents', 'other_documents',
|
for k in [ 'official_project_documents', 'other_documents',
|
||||||
'shapefiles', 'images' ]:
|
'shapefiles', 'images' ]:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Filter the dictionary of form fields in the draft
|
keyname = k + '_files'
|
||||||
# down to just the ones right the right name `k`
|
field = data['data']['form'][keyname]
|
||||||
items = list(filter(
|
|
||||||
lambda x: (
|
|
||||||
x['name'] == '{0}_files'.format(k)
|
|
||||||
and x['value'] != ''
|
|
||||||
), data['data']['form']
|
|
||||||
))
|
|
||||||
except KeyError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Split the comma-separated list of IDs into a list
|
# Ignore empty fields
|
||||||
try:
|
if field['value'] == '':
|
||||||
items = items[0]['value'].split(',')
|
|
||||||
except IndexError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Delete those items
|
|
||||||
for item in items:
|
|
||||||
try:
|
|
||||||
f = File.objects.get(id=item)
|
|
||||||
if f.user != self.request.user:
|
|
||||||
continue
|
|
||||||
f.delete()
|
|
||||||
except File.DoesNotExist:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
file_list = json.loads(field['value'])
|
||||||
|
|
||||||
|
# Delete those items
|
||||||
|
for item in file_list:
|
||||||
|
try:
|
||||||
|
f = File.objects.get(id=item['id'])
|
||||||
|
if f.user != self.request.user:
|
||||||
|
continue
|
||||||
|
f.delete()
|
||||||
|
except File.DoesNotExist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
draft.delete()
|
draft.delete()
|
||||||
|
|
||||||
return HttpResponse(status=204)
|
return HttpResponse(status=204)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
|
from apps.files.models import File
|
||||||
|
|
||||||
|
|
||||||
class CommaSeparatedTextInput(widgets.HiddenInput):
|
class CommaSeparatedTextInput(widgets.HiddenInput):
|
||||||
@ -19,3 +22,34 @@ class CommaSeparatedTextInput(widgets.HiddenInput):
|
|||||||
return value.split(',')
|
return value.split(',')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def idToDict(id):
|
||||||
|
file = File.objects.get(pk=id)
|
||||||
|
return dict(id=id, name=file.name())
|
||||||
|
|
||||||
|
|
||||||
|
# For clarity:
|
||||||
|
# the canonical format is a list of integers (IDs of files)
|
||||||
|
# the input/display format is a string containing a JSON list of {id=x, name=y} objects
|
||||||
|
class JSONFileListWidget(widgets.HiddenInput):
|
||||||
|
|
||||||
|
def format_value(self, value):
|
||||||
|
try:
|
||||||
|
value = [ idToDict(id) for id in value ]
|
||||||
|
value = json.dumps(value)
|
||||||
|
except TypeError:
|
||||||
|
value = ''
|
||||||
|
return super().format_value(value)
|
||||||
|
|
||||||
|
def value_from_datadict(self, data, files, name):
|
||||||
|
value = super().value_from_datadict(data, files, name)
|
||||||
|
|
||||||
|
if value == '':
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
filelist = json.loads(value)
|
||||||
|
return [ file['id'] for file in filelist ]
|
||||||
|
except JSONDecodeError:
|
||||||
|
return None
|
||||||
|
Loading…
Reference in New Issue
Block a user