blob: 139c4f588f50d4f2c9a39317b13c1c6957729a59 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2018 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6"""A servlet for project owners to create a new template"""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import collections
12import logging
13import time
14
15import ezt
16
17from framework import authdata
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020018from framework import flaskservlet
Copybara854996b2021-09-07 19:36:02 +000019from framework import framework_bizobj
20from framework import framework_helpers
21from framework import servlet
22from framework import urls
23from framework import permissions
24from tracker import field_helpers
25from tracker import template_helpers
26from tracker import tracker_bizobj
27from tracker import tracker_helpers
28from tracker import tracker_views
29from services import user_svc
30from proto import tracker_pb2
31
32
33class TemplateCreate(servlet.Servlet):
34 """Servlet allowing project owners to create an issue template."""
35
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020036 _MAIN_TAB_MODE = flaskservlet.FlaskServlet.MAIN_TAB_PROCESS
Copybara854996b2021-09-07 19:36:02 +000037 _PAGE_TEMPLATE = 'tracker/template-detail-page.ezt'
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +020038 _PROCESS_SUBTAB = flaskservlet.FlaskServlet.PROCESS_TAB_TEMPLATES
Copybara854996b2021-09-07 19:36:02 +000039
40 def AssertBasePermission(self, mr):
41 """Check whether the user has any permission to visit this page.
42
43 Args:
44 mr: commonly used info parsed from the request
45 """
46 super(TemplateCreate, self).AssertBasePermission(mr)
47 if not self.CheckPerm(mr, permissions.EDIT_PROJECT):
48 raise permissions.PermissionException(
49 'User is not allowed to administer this project')
50
51 def GatherPageData(self, mr):
52 """Build up a dictionary of data values to use when rendering the page.
53
54 Args:
55 mr: commonly used info parsed from the request.
56
57 Returns:
58 Dict of values used by EZT for rendering the page.
59 """
60
61 config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
62 field_views = tracker_views.MakeAllFieldValueViews(
63 config, [], [], [], {})
64 approval_subfields_present = any(
65 fv.field_def.is_approval_subfield for fv in field_views)
66
67 initial_phases = [tracker_pb2.Phase()] * template_helpers.MAX_NUM_PHASES
68 return {
69 'admin_tab_mode':
70 self._PROCESS_SUBTAB,
71 'allow_edit':
72 ezt.boolean(True),
73 'uneditable_fields':
74 ezt.boolean(False),
75 'new_template_form':
76 ezt.boolean(True),
77 'initial_members_only':
78 ezt.boolean(False),
79 'template_name':
80 '',
81 'initial_content':
82 '',
83 'initial_must_edit_summary':
84 ezt.boolean(False),
85 'initial_summary':
86 '',
87 'initial_status':
88 '',
89 'initial_owner':
90 '',
91 'initial_owner_defaults_to_member':
92 ezt.boolean(False),
93 'initial_components':
94 '',
95 'initial_component_required':
96 ezt.boolean(False),
97 'initial_admins':
98 '',
99 'fields':
100 [
101 view for view in field_views
102 if view.field_def.type_name is not "APPROVAL_TYPE"
103 ],
104 'initial_add_approvals':
105 ezt.boolean(False),
106 'initial_phases':
107 initial_phases,
108 'approvals':
109 [
110 view for view in field_views
111 if view.field_def.type_name is "APPROVAL_TYPE"
112 ],
113 'prechecked_approvals': [],
114 'required_approval_ids': [],
115 'approval_subfields_present':
116 ezt.boolean(approval_subfields_present),
117 # We do not support setting phase field values during template creation.
118 'phase_fields_present':
119 ezt.boolean(False),
120 }
121
122 def ProcessFormData(self, mr, post_data):
123 """Validate and store the contents of the issues tracker admin page.
124
125 Args:
126 mr: commonly used info parsed from the request.
127 post_data: HTML form data from the request.
128
129 Returns:
130 String URL to redirect the user to, or None if response was already sent.
131 """
132
133 config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id)
134 parsed = template_helpers.ParseTemplateRequest(post_data, config)
135 field_helpers.ShiftEnumFieldsIntoLabels(
136 parsed.labels, [], parsed.field_val_strs, [], config)
137
138 if not parsed.name:
139 mr.errors.name = 'Please provide a template name'
140 if self.services.template.GetTemplateByName(mr.cnxn, parsed.name,
141 mr.project_id):
142 mr.errors.name = 'Template with name %s already exists' % parsed.name
143
144 (admin_ids, owner_id, component_ids,
145 field_values, phases,
146 approvals) = template_helpers.GetTemplateInfoFromParsed(
147 mr, self.services, parsed, config)
148
149 labels = [label for label in parsed.labels if label]
150 field_helpers.AssertCustomFieldsEditPerms(
151 mr, config, field_values, [], [], labels, [])
152
153 if mr.errors.AnyErrors():
154 field_views = tracker_views.MakeAllFieldValueViews(
155 config, [], [], field_values, {})
156 prechecked_approvals = template_helpers.GetCheckedApprovalsFromParsed(
157 parsed.approvals_to_phase_idx)
158
159 self.PleaseCorrect(
160 mr,
161 initial_members_only=ezt.boolean(parsed.members_only),
162 template_name=parsed.name,
163 initial_content=parsed.summary,
164 initial_must_edit_summary=ezt.boolean(parsed.summary_must_be_edited),
165 initial_description=parsed.content,
166 initial_status=parsed.status,
167 initial_owner=parsed.owner_str,
168 initial_owner_defaults_to_member=ezt.boolean(
169 parsed.owner_defaults_to_member),
170 initial_components=', '.join(parsed.component_paths),
171 initial_component_required=ezt.boolean(parsed.component_required),
172 initial_admins=parsed.admin_str,
173 labels=parsed.labels,
174 fields=[view for view in field_views
175 if view.field_def.type_name is not 'APPROVAL_TYPE'],
176 initial_add_approvals=ezt.boolean(parsed.add_approvals),
177 initial_phases=[tracker_pb2.Phase(name=name) for name in
178 parsed.phase_names],
179 approvals=[view for view in field_views
180 if view.field_def.type_name is 'APPROVAL_TYPE'],
181 prechecked_approvals=prechecked_approvals,
182 required_approval_ids=parsed.required_approval_ids
183 )
184 return
185
186 self.services.template.CreateIssueTemplateDef(
187 mr.cnxn, mr.project_id, parsed.name, parsed.content, parsed.summary,
188 parsed.summary_must_be_edited, parsed.status, parsed.members_only,
189 parsed.owner_defaults_to_member, parsed.component_required,
190 owner_id, labels, component_ids, admin_ids, field_values, phases=phases,
191 approval_values=approvals)
192
193 return framework_helpers.FormatAbsoluteURL(
194 mr, urls.ADMIN_TEMPLATES, saved=1, ts=int(time.time()))
Adrià Vilanova Martínezde942802022-07-15 14:06:55 +0200195
196 # def GetTemplateCreate(self, **kwargs):
197 # return self.handler(**kwargs)
198
199 # def PostTemplateCreate(self, **kwargs):
200 # return self.handler(**kwargs)