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 user_entity
= app_entity
.applicant
226 to
= accounts
.denormalizeAccount(user_entity
.account
).email()
228 context
= {'sender': sender
,
230 'sender_name': sender_name
,
231 'to_name': user_entity
.name
,
232 'program_name': app_entity
.scope
.name
,
233 '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 # send out the constructed email
246 mail_dispatcher
.sendMailFromTemplate(template
, context
)
248 @decorators.merge_params
249 @decorators.check_access
250 def bulkAccept(self
, request
, access_type
,
251 page_name
=None, params
=None, **kwargs
):
252 """Returns a HTTP Response containing JSON information needed
256 program_keyname
= kwargs
['scope_path']
257 return self
._bulkReview
(request
, params
, 'pre-accepted', 'accepted',
260 @decorators.merge_params
261 @decorators.check_access
262 def bulkReject(self
, request
, access_type
,
263 page_name
=None, params
=None, **kwargs
):
264 """Returns a HTTP Response containing JSON information needed
268 program_keyname
= kwargs
['scope_path']
269 return self
._bulkReview
(request
, params
, 'pre-rejected', 'rejected',
272 def _bulkReview(self
, request
, params
, from_status
, to_status
,
274 """Returns a HTTP Response containing JSON information needed
275 to bulk-review organization applications.
278 request: Standard Django HTTP Request object
279 params: Params for this view
280 from_status: The status for the applications which should
281 be reviewed (can be a list)
282 to_status: The status to which all applications should be changed to
283 program_keyname: The keyname for the program to which
284 the application belongs
287 # get the program entity from the keyname
288 program_entity
= program_logic
.logic
.getFromKeyName(program_keyname
)
290 # get all the organization applications for the
291 # given program and from_status
292 filter = {'scope': program_entity
,
293 'status': from_status
}
295 org_app_entities
= params
['logic'].getForFields(filter=filter)
297 # convert each application into a dictionary containing only the fields
298 # given by the dict_filter
299 dict_filter
= ['link_id', 'name']
300 org_apps
= [dicts
.filter(i
.toDict(), dict_filter
) for i
in org_app_entities
]
303 'program' : program_entity
.name
,
304 'nr_applications' : len(org_apps
),
305 'application_type' : params
['name_plural'],
306 'applications': org_apps
,
307 'link' : '/%s/review/%s/(link_id)?status=%s' %(
308 params
['url_name'] ,program_entity
.key().name(), to_status
),
311 json
= simplejson
.dumps(to_json
)
313 # use the standard JSON template to return our response
314 context
= {'json': json
}
315 template
= 'soc/json.html'
317 return responses
.respond(request
, template
, context
)
322 admin
= decorators
.view(view
.admin
)
323 bulk_accept
= decorators
.view(view
.bulkAccept
)
324 bulk_reject
= decorators
.view(view
.bulkReject
)
325 create
= decorators
.view(view
.create
)
326 delete
= decorators
.view(view
.delete
)
327 edit
= decorators
.view(view
.edit
)
328 list = decorators
.view(view
.list)
329 list_self
= decorators
.view(view
.listSelf
)
330 public
= decorators
.view(view
.public
)
331 export
= decorators
.view(view
.export
)
332 review
= decorators
.view(view
.review
)
333 review_overview
= decorators
.view(view
.reviewOverview
)