1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from __future__
import unicode_literals
19 from flask
import flash
, request
, session
20 from werkzeug
.utils
import secure_filename
22 from indico
.core
.db
import db
23 from indico
.modules
.attachments
.controllers
.util
import SpecificAttachmentMixin
, SpecificFolderMixin
24 from indico
.modules
.attachments
.forms
import (AddAttachmentFilesForm
, AttachmentLinkForm
, AttachmentFolderForm
,
25 EditAttachmentFileForm
)
26 from indico
.modules
.attachments
.models
.folders
import AttachmentFolder
27 from indico
.modules
.attachments
.models
.attachments
import Attachment
, AttachmentFile
, AttachmentType
28 from indico
.modules
.attachments
.util
import get_attached_items
29 from indico
.util
.i18n
import _
, ngettext
30 from indico
.web
.flask
.templating
import get_template_module
31 from indico
.web
.flask
.util
import url_for
32 from indico
.web
.forms
.base
import FormDefaults
33 from indico
.web
.util
import jsonify_template
, jsonify_data
36 def _render_attachment_list(linked_object
):
37 tpl
= get_template_module('attachments/_attachments.html')
38 return tpl
.render_attachments(attachments
=get_attached_items(linked_object
), linked_object
=linked_object
)
41 class ManageAttachmentsMixin
:
42 """Shows the attachment management page"""
46 return self
.wp
.render_template('attachments.html', self
.base_object
, linked_object
=self
.object,
47 linked_object_type
=self
.object_type
, attachments
=get_attached_items(self
.object))
50 class AddAttachmentFilesMixin
:
51 """Upload file attachments"""
54 form
= AddAttachmentFilesForm(linked_object
=self
.object)
55 if form
.validate_on_submit():
56 files
= request
.files
.getlist('file')
57 folder
= form
.folder
.data
or AttachmentFolder
.get_or_create_default(linked_object
=self
.object)
59 filename
= secure_filename(f
.filename
) or 'attachment'
60 attachment
= Attachment(folder
=folder
, user
=session
.user
, title
=f
.filename
, type=AttachmentType
.file,
61 protection_mode
=form
.protection_mode
.data
)
62 attachment
.file = AttachmentFile(user
=session
.user
, filename
=filename
, content_type
=f
.mimetype
)
63 attachment
.file.save(f
.file)
64 db
.session
.add(attachment
)
65 flash(ngettext("The attachment has been uploaded", "%(num)d attachments have been uploaded", len(files
)),
67 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))
68 return jsonify_template('attachments/upload.html', form
=form
, action
=url_for('.upload', self
.object))
71 class AddAttachmentLinkMixin
:
72 """Add link attachment"""
75 form
= AttachmentLinkForm(linked_object
=self
.object)
76 if form
.validate_on_submit():
77 folder
= form
.folder
.data
or AttachmentFolder
.get_or_create_default(linked_object
=self
.object)
78 link
= Attachment(user
=session
.user
, type=AttachmentType
.link
)
79 form
.populate_obj(link
, skip
={'acl'})
82 link
.acl
= form
.acl
.data
83 flash(_("The link has been added"), 'success')
84 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))
85 return jsonify_template('attachments/add_link.html', form
=form
)
88 class EditAttachmentMixin(SpecificAttachmentMixin
):
89 """Edit an attachment"""
92 defaults
= FormDefaults(self
.attachment
, protected
=self
.attachment
.is_protected
)
93 form_cls
= EditAttachmentFileForm
if self
.attachment
.type == AttachmentType
.file else AttachmentLinkForm
94 form
= form_cls(linked_object
=self
.object, obj
=defaults
)
95 if form
.validate_on_submit():
96 folder
= form
.folder
.data
or AttachmentFolder
.get_or_create_default(linked_object
=self
.object)
97 form
.populate_obj(self
.attachment
, skip
={'acl'})
98 self
.attachment
.folder
= folder
99 if self
.attachment
.is_protected
:
100 self
.attachment
.acl
= form
.acl
.data
101 # files need special handling; links are already updated in `populate_obj`
102 if self
.attachment
.type == AttachmentType
.file:
103 file = request
.files
['file'] if request
.files
else None
105 self
.attachment
.file = AttachmentFile(user
=session
.user
, filename
=secure_filename(file.filename
),
106 content_type
=file.mimetype
)
107 self
.attachment
.file.save(file.file)
109 flash(_("The attachment has been updated"), 'success')
110 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))
112 template
= ('attachments/upload.html' if self
.attachment
.type == AttachmentType
.file else
113 'attachments/add_link.html')
114 return jsonify_template(template
, form
=form
, existing_attachment
=self
.attachment
,
115 action
=url_for('.modify_attachment', self
.attachment
))
118 class CreateFolderMixin
:
119 """Create a new empty folder"""
122 form
= AttachmentFolderForm()
123 if form
.validate_on_submit():
124 folder
= AttachmentFolder(linked_object
=self
.object)
125 form
.populate_obj(folder
, skip
={'acl'})
126 if folder
.is_protected
:
127 folder
.acl
= form
.acl
.data
128 db
.session
.add(folder
)
129 flash(_("Folder \"{name}\" created").format(name
=folder
.title
), 'success')
130 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))
131 return jsonify_template('attachments/create_folder.html', form
=form
)
134 class EditFolderMixin(SpecificFolderMixin
):
138 defaults
= FormDefaults(self
.folder
, protected
=self
.folder
.is_protected
)
139 form
= AttachmentFolderForm(obj
=defaults
)
140 if form
.validate_on_submit():
141 form
.populate_obj(self
.folder
, skip
={'acl'})
142 if self
.folder
.is_protected
:
143 self
.folder
.acl
= form
.acl
.data
144 flash(_("Folder \"{name}\" updated").format(name
=self
.folder
.title
), 'success')
145 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))
146 return jsonify_template('attachments/create_folder.html', form
=form
)
149 class DeleteFolderMixin(SpecificFolderMixin
):
150 """Delete a folder"""
153 self
.folder
.is_deleted
= True
154 flash(_("Folder \"{name}\" deleted").format(name
=self
.folder
.title
), 'success')
155 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))
158 class DeleteAttachmentMixin(SpecificAttachmentMixin
):
159 """Delete an attachment"""
162 self
.attachment
= Attachment
.get_one(request
.view_args
['attachment_id'])
163 self
.attachment
.is_deleted
= True
164 flash(_("Attachment \"{name}\" deleted").format(name
=self
.attachment
.title
), 'success')
165 return jsonify_data(attachment_list
=_render_attachment_list(self
.object))