3 # Copyright 2009 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Views for Organization App profiles.
21 '"Lennard de Rijk" <ljvderijk@gmail.com>',
27 from django
import forms
28 from django
.utils
import simplejson
30 from soc
.logic
import accounts
31 from soc
.logic
import cleaning
32 from soc
.logic
import dicts
33 from soc
.logic
import mail_dispatcher
34 from soc
.logic
import models
as model_logic
35 from soc
.logic
.models
import program
as program_logic
36 from soc
.logic
.models
import org_app
as org_app_logic
37 from soc
.views
import helper
38 from soc
.views
.helper
import access
39 from soc
.views
.helper
import decorators
40 from soc
.views
.helper
import redirects
41 from soc
.views
.helper
import responses
42 from soc
.views
.helper
import widgets
43 from soc
.views
.models
import group_app
44 from soc
.views
.models
import program
as program_view
47 class View(group_app
.View
):
48 """View methods for the Organization Application model.
51 def __init__(self
, params
=None):
52 """Defines the fields and methods required for the base View class
53 to provide the user with list, public, create, edit and delete views.
56 params: a dict with params for this View
59 rights
= access
.Checker(params
)
60 rights
['create'] = ['checkIsDeveloper']
61 rights
['delete'] = [('checkCanEditGroupApp',
62 [org_app_logic
.logic
]),
63 ('checkIsActivePeriod', ['org_signup', 'scope_path'])]
64 rights
['edit'] = [('checkCanEditGroupApp',
65 [org_app_logic
.logic
]),
66 ('checkIsActivePeriod', ['org_signup', 'scope_path'])]
67 rights
['list'] = ['checkIsDeveloper']
68 rights
['list_self'] = ['checkIsUser']
69 rights
['show'] = ['allow']
70 rights
['review'] = ['checkIsHostForProgramInScope',
71 ('checkCanReviewGroupApp', [org_app_logic
.logic
])]
72 rights
['review_overview'] = ['checkIsHostForProgramInScope']
73 rights
['bulk_accept'] = ['checkIsHostForProgramInScope']
74 rights
['bulk_reject'] = ['checkIsHostForProgramInScope']
75 rights
['apply'] = ['checkIsUser',
76 ('checkCanCreateOrgApp', ['org_signup']),
77 'checkIsNotStudentForProgramInScope']
81 new_params
['rights'] = rights
82 new_params
['logic'] = org_app_logic
.logic
84 new_params
['scope_view'] = program_view
85 new_params
['scope_redirect'] = redirects
.getCreateRedirect
87 new_params
['sidebar_grouping'] = 'Organizations'
89 new_params
['list_key_order'] = [
90 'link_id', 'scope_path', 'name', 'home_page', 'email',
91 'description', 'why_applying','pub_mailing_list','irc_channel',
92 'member_criteria', 'prior_participation', 'prior_application',
93 'license_name', 'ideas', 'dev_mailing_list', 'contrib_template',
94 'contrib_disappears', 'member_disappears', 'encourage_contribs',
97 patterns
= [(r
'^%(url_name)s/(?P<access_type>apply)/%(scope)s$',
98 'soc.views.models.%(module_name)s.create',
99 'Create an %(name_plural)s'),
100 (r
'^%(url_name)s/(?P<access_type>bulk_accept)/%(scope)s$',
101 'soc.views.models.%(module_name)s.bulk_accept',
102 'Bulk Acceptation of %(name_plural)s'),
103 (r
'^%(url_name)s/(?P<access_type>bulk_reject)/%(scope)s$',
104 'soc.views.models.%(module_name)s.bulk_reject',
105 'Bulk Rejection of %(name_plural)s'),]
107 new_params
['extra_django_patterns'] = patterns
108 new_params
['extra_key_order'] = ['admin_agreement',
109 'agreed_to_admin_agreement']
111 new_params
['extra_dynaexclude'] = ['applicant', 'backup_admin', 'status',
112 'created_on', 'last_modified_on']
114 new_params
['create_dynafields'] = [
116 'base': forms
.fields
.CharField
,
117 'label': 'Organization Link ID',
121 new_params
['create_extra_dynaproperties'] = {
122 'scope_path': forms
.fields
.CharField(widget
=forms
.HiddenInput
,
124 'contrib_template': forms
.fields
.CharField(
125 widget
=helper
.widgets
.FullTinyMCE(
126 attrs
={'rows': 25, 'cols': 100})),
127 'description': forms
.fields
.CharField(
128 widget
=helper
.widgets
.FullTinyMCE(
129 attrs
={'rows': 25, 'cols': 100})),
130 'admin_agreement': forms
.fields
.Field(required
=False,
131 widget
=widgets
.AgreementField
),
132 'agreed_to_admin_agreement': forms
.fields
.BooleanField(
133 initial
=False, required
=True),
135 'clean_description': cleaning
.clean_html_content('description'),
136 'clean_contrib_template': cleaning
.clean_html_content(
138 'clean_ideas': cleaning
.clean_url('ideas'),
139 'clean': cleaning
.validate_new_group('link_id', 'scope_path',
140 model_logic
.organization
, org_app_logic
)}
142 # get rid of the clean method
143 new_params
['edit_extra_dynaproperties'] = {
144 'clean': (lambda x
: x
.cleaned_data
)}
146 new_params
['name'] = "Organization Application"
147 new_params
['name_plural'] = "Organization Applications"
148 new_params
['name_short'] = "Org App"
149 new_params
['url_name'] = "org_app"
150 new_params
['group_name'] = "Organization"
151 new_params
['group_url_name'] = 'org'
153 new_params
['review_template'] = 'soc/org_app/review.html'
154 # TODO use a proper template that works for each program
155 new_params
['accepted_mail_template'] = \
156 'soc/org_app/mail/accepted_gsoc2009.html'
157 new_params
['rejected_mail_template'] = 'soc/org_app/mail/rejected.html'
159 params
= dicts
.merge(params
, new_params
)
161 super(View
, self
).__init
__(params
=params
)
163 @ decorators
.merge_params
164 def reviewOverview(self
, request
, access_type
,
165 page_name
=None, params
=None, **kwargs
):
166 """View that allows to see organization application review overview.
168 For Args see base.View.public().
171 params
['list_template'] = 'soc/org_app/review_overview.html'
173 'bulk_accept_link': '/org_app/bulk_accept/%(scope_path)s' % (kwargs
),
174 'bulk_reject_link': '/org_app/bulk_reject/%(scope_path)s' % (kwargs
),}
176 return super(View
, self
).reviewOverview(request
, access_type
,
177 page_name
=page_name
, params
=params
, context
=context
, **kwargs
)
179 def _editContext(self
, request
, context
):
180 """See base.View._editContext.
183 entity
= context
['entity']
184 form
= context
['form']
186 if 'scope_path' in form
.initial
:
187 scope_path
= form
.initial
['scope_path']
188 elif 'scope_path' in request
.POST
:
189 scope_path
= request
.POST
['scope_path']
191 del form
.fields
['admin_agreement']
194 entity
= program_logic
.logic
.getFromKeyName(scope_path
)
196 if not (entity
and entity
.org_admin_agreement
):
199 agreement
= entity
.org_admin_agreement
201 content
= agreement
.content
202 params
= {'url_name': 'document'}
204 widget
= form
.fields
['admin_agreement'].widget
205 widget
.text
= content
206 widget
.url
= redirects
.getPublicRedirect(agreement
, params
)
208 def _review(self
, request
, params
, app_entity
, status
, **kwargs
):
209 """Sends out an email if an org_app has been accepted or rejected.
211 For params see group_app.View._review().
214 if status
== 'accepted' or status
== 'rejected':
216 default_sender
= mail_dispatcher
.getDefaultMailSender()
218 if not default_sender
:
219 # no default sender abort
222 (sender_name
, sender
) = default_sender
224 # construct the contents of the email
225 admin_entity
= app_entity
.applicant
226 backup_entity
= app_entity
.backup_admin
230 'sender_name': sender_name
,
231 'program_name': app_entity
.scope
.name
,
232 'org_app_name': app_entity
.name
235 if status
== 'accepted':
236 # use the accepted template and subject
237 template
= params
['accepted_mail_template']
238 context
['subject'] = 'Congratulations!'
239 context
['HTTP_host'] = 'http://%s' % (os
.environ
['HTTP_HOST'])
240 elif status
== 'rejected':
241 # use the rejected template and subject
242 template
= params
['rejected_mail_template']
243 context
['subject'] = 'Thank you for your application'
245 for to
in [admin_entity
, backup_entity
]:
249 email
= accounts
.denormalizeAccount(to
.account
).email()
250 context
['to'] = email
251 context
['to_name'] = to
.name
253 # send out the constructed email
254 mail_dispatcher
.sendMailFromTemplate(template
, context
)
256 @decorators.merge_params
257 @decorators.check_access
258 def bulkAccept(self
, request
, access_type
,
259 page_name
=None, params
=None, **kwargs
):
260 """Returns a HTTP Response containing JSON information needed
264 program_keyname
= kwargs
['scope_path']
265 return self
._bulkReview
(request
, params
, 'pre-accepted', 'accepted',
268 @decorators.merge_params
269 @decorators.check_access
270 def bulkReject(self
, request
, access_type
,
271 page_name
=None, params
=None, **kwargs
):
272 """Returns a HTTP Response containing JSON information needed
276 program_keyname
= kwargs
['scope_path']
277 return self
._bulkReview
(request
, params
, 'pre-rejected', 'rejected',
280 def _bulkReview(self
, request
, params
, from_status
, to_status
,
282 """Returns a HTTP Response containing JSON information needed
283 to bulk-review organization applications.
286 request: Standard Django HTTP Request object
287 params: Params for this view
288 from_status: The status for the applications which should
289 be reviewed (can be a list)
290 to_status: The status to which all applications should be changed to
291 program_keyname: The keyname for the program to which
292 the application belongs
295 # get the program entity from the keyname
296 program_entity
= program_logic
.logic
.getFromKeyName(program_keyname
)
298 # get all the organization applications for the
299 # given program and from_status
300 filter = {'scope': program_entity
,
301 'status': from_status
}
303 org_app_entities
= params
['logic'].getForFields(filter=filter)
305 # convert each application into a dictionary containing only the fields
306 # given by the dict_filter
307 dict_filter
= ['link_id', 'name']
308 org_apps
= [dicts
.filter(i
.toDict(), dict_filter
) for i
in org_app_entities
]
311 'program' : program_entity
.name
,
312 'nr_applications' : len(org_apps
),
313 'application_type' : params
['name_plural'],
314 'applications': org_apps
,
315 'link' : '/%s/review/%s/(link_id)?status=%s' %(
316 params
['url_name'] ,program_entity
.key().id_or_name(), to_status
),
319 json
= simplejson
.dumps(to_json
)
321 # use the standard JSON template to return our response
322 context
= {'json': json
}
323 template
= 'soc/json.html'
325 return responses
.respond(request
, template
, context
)
330 admin
= decorators
.view(view
.admin
)
331 bulk_accept
= decorators
.view(view
.bulkAccept
)
332 bulk_reject
= decorators
.view(view
.bulkReject
)
333 create
= decorators
.view(view
.create
)
334 delete
= decorators
.view(view
.delete
)
335 edit
= decorators
.view(view
.edit
)
336 list = decorators
.view(view
.list)
337 list_self
= decorators
.view(view
.listSelf
)
338 public
= decorators
.view(view
.public
)
339 export
= decorators
.view(view
.export
)
340 review
= decorators
.view(view
.review
)
341 review_overview
= decorators
.view(view
.reviewOverview
)