1
2
3 """ Resource Summary Pages
4
5 @copyright: 2013-2019 (c) Sahana Software Foundation
6 @license: MIT
7
8 @requires: U{B{I{gluon}} <http://web2py.com>}
9
10 Permission is hereby granted, free of charge, to any person
11 obtaining a copy of this software and associated documentation
12 files (the "Software"), to deal in the Software without
13 restriction, including without limitation the rights to use,
14 copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the
16 Software is furnished to do so, subject to the following
17 conditions:
18
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
24 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 OTHER DEALINGS IN THE SOFTWARE.
30 """
31
32 from gluon import current, A, DIV, LI, UL
33
34 from s3filter import S3FilterForm
35 from s3gis import MAP
36 from s3rest import S3Method
40 """ Resource Summary Pages """
41
42
44 """
45 Entry point for REST interface
46
47 @param r: the S3Request
48 @param attr: controller attributes
49 """
50
51 if "w" in r.get_vars:
52
53 return self.ajax(r, **attr)
54 else:
55
56 return self.summary(r, **attr)
57
58
60 """
61 Render the summary page
62
63 @param r: the S3Request
64 @param attr: controller attributes
65 """
66
67 output = {}
68 response = current.response
69 resource = self.resource
70 get_config = resource.get_config
71
72
73 config = self._get_config(resource)
74
75
76 crud_string = self.crud_string
77 title = crud_string(self.tablename, "title_list")
78 output["title"] = title
79
80
81 tablist = UL()
82 sections = []
83 commons = []
84
85
86 if "t" in r.get_vars:
87 active_tab = int(r.get_vars["t"])
88 else:
89 active_tab = 0
90 active_map = None
91
92 show_filter_form = False
93 filter_widgets = get_config("filter_widgets")
94 if filter_widgets and not self.hide_filter:
95
96 show_filter_form = True
97 S3FilterForm.apply_filter_defaults(r, resource)
98
99
100 tab_idx = 0
101 widget_idx = 0
102 targets = []
103 pending = []
104
105
106 attr["filter_form"] = form_id = "summary-filter-form"
107
108 for section in config:
109
110 common = section.get("common")
111
112
113 section_id = section["name"]
114 s = DIV(_class="section-container", _id=section_id)
115
116 if not common:
117
118 label = section["label"]
119 translate = section.get("translate", True)
120 if isinstance(label, basestring) and translate:
121 label = current.T(label)
122
123
124 tablist.append(LI(A(label, _href="#%s" % section_id)))
125
126 if common or active_tab == tab_idx:
127 visible = True
128 else:
129 visible = False
130
131
132 widgets = section.get("widgets", [])
133 for widget in widgets:
134
135
136 widget_id = "summary-%s" % widget_idx
137
138
139
140 r.get_vars["w"] = r.vars["w"] = widget_id
141
142
143 filterable = widget.get("filterable", True)
144 if filterable:
145 targets.append(widget_id)
146 if not visible and widget.get("ajax_init"):
147 pending.append(widget_id)
148
149
150 method = widget.get("method")
151 if callable(method):
152 content = method(r,
153 widget_id=widget_id,
154 visible=visible,
155 **attr)
156 else:
157 handler = r.get_widget_handler(method)
158 if handler is None:
159
160 handler = resource.crud
161 if handler is not None:
162 if method == "datatable":
163
164 dtargs = attr.get("dtargs", {})
165 dtargs["dt_searching"] = "false"
166 attr["dtargs"] = dtargs
167 content = handler(r,
168 method=method,
169 widget_id=widget_id,
170 visible=visible,
171 **attr)
172 else:
173 r.error(405, current.ERROR.BAD_METHOD)
174
175
176 if isinstance(content, dict):
177 if r.http == "POST" and content.get("success"):
178
179
180 next_url = content.get("next")
181 if next_url:
182 self.next = next_url
183 return content
184 for k, v in content.items():
185 if k not in ("tabs", "sections", "widget"):
186 output[k] = v
187 content = content.get("widget", "EMPTY")
188 elif isinstance(content, MAP) and (common or active_tab == tab_idx):
189 active_map = content
190 s.append(DIV(content,
191 _id="%s-container" % widget_id,
192 _class="widget-container",
193 ))
194 widget_idx += 1
195
196 if common:
197 commons.append(s)
198 else:
199 sections.append(s)
200 tab_idx += 1
201
202
203 r.get_vars.pop("w", None)
204
205
206 if len(sections) > 1:
207 output["tabs"] = tablist
208
209
210 for s in sections:
211 s.add_class("hide")
212 else:
213
214
215 output["tabs"] = ""
216 output["sections"] = sections
217
218
219 output["common"] = commons
220
221
222 target = " ".join(targets)
223
224
225 filter_ajax = True
226 if show_filter_form:
227
228
229 if active_tab != 0:
230 submit_url_vars = {"t": active_tab}
231 else:
232 submit_url_vars = {}
233 filter_submit_url = attr.get("filter_submit_url")
234 if not filter_submit_url:
235 _vars = self._remove_filters(r.get_vars)
236 _vars.update(submit_url_vars)
237 filter_submit_url = r.url(vars=_vars)
238
239
240 filter_ajax_url = attr.get("filter_ajax_url",
241 r.url(method="filter",
242 vars={},
243 representation="options"))
244
245 filter_clear = get_config("filter_clear",
246 current.deployment_settings.get_ui_filter_clear())
247 filter_formstyle = get_config("filter_formstyle")
248 filter_submit = get_config("filter_submit", True)
249 filter_form = S3FilterForm(filter_widgets,
250 clear=filter_clear,
251 formstyle=filter_formstyle,
252 submit=filter_submit,
253 ajax=filter_ajax,
254 url=filter_submit_url,
255 ajaxurl=filter_ajax_url,
256 _class="filter-form",
257 _id=form_id)
258 fresource = current.s3db.resource(resource.tablename)
259
260 alias = resource.alias if r.component else None
261 output["filter_form"] = filter_form.html(fresource,
262 r.get_vars,
263 target=target,
264 alias=alias)
265 else:
266
267 output["filter_form"] = ""
268
269
270 response.view = self._view(r, "summary.html")
271
272 if len(sections) > 1:
273
274
275
276 pending = ",".join(pending) if pending else "null"
277
278
279 script = '''S3.search.summary_tabs("%s",%s,"%s")''' % \
280 (form_id, active_tab, pending)
281 else:
282
283 script = '''S3.search.summary_tabs("%s")''' % form_id
284
285 response.s3.jquery_ready.append(script)
286
287 if active_map:
288
289
290 active_map.callback = '''S3.search.summary_maps("%s")''' % form_id
291
292 return output
293
294
295 - def ajax(self, r, **attr):
296 """
297 Render a specific widget for pulling-in via AJAX
298
299 @param r: the S3Request
300 @param attr: controller attributes
301 """
302
303
304 config = self._get_config(self.resource)
305
306 widget_id = r.get_vars.get("w")
307 i = 0
308 for section in config:
309 widgets = section.get("widgets", [])
310 for widget in widgets:
311 if widget_id == "summary-%s" % i:
312 method = widget.get("method", None)
313 output = None
314 if callable(method):
315 output = method(r, widget_id=widget_id, **attr)
316 else:
317 handler = r.get_widget_handler(method)
318 if handler is not None:
319 output = handler(r,
320 method=method,
321 widget_id=widget_id,
322 **attr)
323 else:
324 r.error(405, current.ERROR.BAD_METHOD)
325 return output
326 i += 1
327
328
329 return None
330
331
332 @staticmethod
334 """
335 Get the summary page configuration
336
337 @param resource: the target S3Resource
338 """
339
340 get_config = resource.get_config
341 config = get_config("summary",
342 current.deployment_settings.get_ui_summary())
343 if not config:
344 config = [{"name": "table",
345 "label": "Table",
346 "widgets": [{"name": "datatable",
347 "method": "datatable",
348 }]
349 }]
350 return config
351
352
353