Merge lp:~sahana-eden-vms/sahana-eden/vms into lp:sahana-eden

Proposed by Pat Tressel
Status: Merged
Merged at revision: 993
Proposed branch: lp:~sahana-eden-vms/sahana-eden/vms
Merge into: lp:sahana-eden
Diff against target: 816 lines (+329/-321)
9 files modified
controllers/msg.py (+2/-54)
controllers/vol.py (+96/-10)
models/msg.py (+66/-0)
models/vol.py (+24/-132)
views/msg/_compose.html (+133/-0)
views/msg/compose.html (+2/-125)
views/vol/compose_group.html (+2/-0)
views/vol/compose_person.html (+2/-0)
views/vol/view_team_map.html (+2/-0)
To merge this branch: bzr merge lp:~sahana-eden-vms/sahana-eden/vms
Reviewer Review Type Date Requested Status
Fran Boon Pending
Review via email: mp+32841@code.launchpad.net

Description of the change

This is Zubair's GSoC version. (It temporarily omits Dominic's vol changes -- we'll recover and merge those separately.) Changes in this version include maps of individual and team member locations, email to individual and team members. Multiselect widget for adding skills to a person has been removed as it's inappropriate for a table with multiple fields. This uses standard crud for skills, so they need to be added one at a time. Should not be a big issue. A skill can be deleted from a person by clicking edit on that skill, then delete skill on the edit page. We'll look into a fancier widget later.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'controllers/msg.py'
2--- controllers/msg.py 2010-08-07 20:12:56 +0000
3+++ controllers/msg.py 2010-08-17 03:20:56 +0000
4@@ -353,60 +353,8 @@
5 return shn_rest_controller(module, resource, deletable=False, listadd=False)
6
7 def compose():
8- """ Form to Compose a Message """
9- resource1 = "log"
10- tablename1 = module + "_" + resource1
11- table1 = db[tablename1]
12- resource2 = "outbox"
13- tablename2 = module + "_" + resource2
14- table2 = db[tablename2]
15-
16- if auth.is_logged_in() or auth.basic():
17- pass
18- else:
19- redirect(URL(r=request, c="default", f="user", args="login",
20- vars={"_next":URL(r=request, c="msg", f="compose")}))
21-
22- # Model options
23- table1.sender.writable = table1.sender.readable = False
24- table1.fromaddress.writable = table1.fromaddress.readable = False
25- table1.pe_id.writable = table1.pe_id.readable = False
26- table1.verified.writable = table1.verified.readable = False
27- table1.verified_comments.writable = table1.verified_comments.readable = False
28- table1.actioned.writable = table1.actioned.readable = False
29- table1.actionable.writable = table1.actionable.readable = False
30- table1.actioned_comments.writable = table1.actioned_comments.readable = False
31-
32- table1.subject.label = T("Subject")
33- table1.message.label = T("Message")
34- table1.priority.label = T("Priority")
35-
36- table2.pe_id.writable = table2.pe_id.readable = True
37- table2.pe_id.label = T("Recipients")
38-
39- def compose_onvalidation(form):
40- """ Set the sender and use msg.send_by_pe_id to route the message """
41- if not request.vars.pe_id:
42- session.error = T("Please enter the recipient")
43- redirect(URL(r=request,c="msg", f="compose"))
44- sender_pe_id = db(db.pr_person.uuid == auth.user.person_uuid).select(db.pr_person.pe_id, limitby=(0, 1)).first().pe_id
45- if msg.send_by_pe_id(request.vars.pe_id,
46- request.vars.subject,
47- request.vars.message,
48- sender_pe_id,
49- request.vars.pr_message_method):
50- session.flash = T("Message sent to outbox")
51- redirect(URL(r=request, c="msg", f="compose"))
52- else:
53- session.error = T("Error in message")
54- redirect(URL(r=request,c="msg", f="compose"))
55-
56-
57- logform = crud.create(table1,
58- onvalidation = compose_onvalidation)
59- outboxform = crud.create(table2)
60-
61- return dict(logform = logform, outboxform = outboxform, title = T("Send Message"))
62+
63+ return shn_msg_compose()
64
65 def outbox():
66 "View the contents of the Outbox"
67
68=== modified file 'controllers/vol.py'
69--- controllers/vol.py 2010-08-13 23:00:35 +0000
70+++ controllers/vol.py 2010-08-17 03:20:56 +0000
71@@ -4,6 +4,8 @@
72 Volunteer Management System
73 """
74
75+from gluon.sql import Rows
76+
77 module = request.controller
78
79 if module not in deployment_settings.modules:
80@@ -33,7 +35,7 @@
81 menu_teams = [
82 [T("Teams"), False, URL(r=request, f="group"),[
83 [T("List"), False, URL(r=request, f="group")],
84- [T("Add"), False, URL(r=request, f="group", args="create", vars={"_next":URL(r=request, args=request.args, vars=request.vars)})],
85+ [T("Add"), False, URL(r=request, f="group", args="create")],
86 ]]
87 ]
88 menu.extend(menu_teams)
89@@ -43,14 +45,17 @@
90 if selection:
91 team_name = shn_pr_group_represent(group_id)
92 menu_teams = [
93- ["%s %s" % (T("Team:"), team_name), False, URL(r=request, f="group", args=[group_id, "read"])],
94+ ["%s %s" % (T("Team:"), team_name), False, URL(r=request, f="group", args=[group_id, "read"]),[
95+ [T("View On Map"), False, URL(r=request, f="view_team_map", args=[group_id])],
96+ [T("Send Mail"), False, URL(r=request, f="compose_group", vars={"group_id":group_id})],
97+ ]],
98 ]
99 menu.extend(menu_teams)
100
101 menu_persons = [
102- [T("Persons"), False, URL(r=request, f="person", args=["search_simple"], vars={"_next":URL(r=request, f="person", args=["[id]", "volunteer"], vars={"vol_tabs":"volunteer"})}),[
103- [T("List"), False, URL(r=request, f="person", vars={"_next":URL(r=request, f="person", args=["[id]", "volunteer"], vars={"vol_tabs":"volunteer"})})],
104- [T("Add"), False, URL(r=request, f="person", args="create", vars={"_next":URL(r=request, f="person", args=["[id]", "volunteer"], vars={"vol_tabs":"volunteer"})})],
105+ [T("Persons"), False, URL(r=request, f="person", args=["search_simple"]),[
106+ [T("List"), False, URL(r=request, f="person")],
107+ [T("Add"), False, URL(r=request, f="person", args="create")],
108 ]]
109 ]
110 menu.extend(menu_persons)
111@@ -68,7 +73,8 @@
112 [T("Volunteer Data"), False, URL(r=request, f="person", args=[person_id, "volunteer"], vars={"vol_tabs":"volunteer"})],
113 # The default tab is pr_person, which is fine here.
114 [T("Person Data"), False, URL(r=request, f="person", args=[person_id], vars={"vol_tabs":"person"})],
115- [T("View Map"), False, URL(r=request, f="view_map", args=[person_id])],
116+ [T("View On Map"), False, URL(r=request, f="view_map", args=[person_id])],
117+ [T("Send Mail"), False, URL(r=request, f="compose_person", vars={"person_id":person_id})],
118 ]],
119 ]
120 menu.extend(menu_person)
121@@ -78,7 +84,7 @@
122 menu.extend(menu_skills)
123 if auth.user is not None:
124 menu_user = [
125- [T("My Tasks"), False, URL(r=request, f="task", args="")]
126+ [T("My Tasks"), False, URL(r=request, f="task", args="")],
127 ]
128 menu.extend(menu_user)
129 response.menu_options = menu
130@@ -237,13 +243,13 @@
131
132 person_id = request.args(0)
133
134- presence_query = (db.pr_person.id == person_id) and (db.pr_presence.pe_id == db.pr_person.pe_id) and (db.gis_location.id == db.pr_presence.location_id)
135+ presence_query = (db.pr_person.id == person_id) & (db.pr_presence.pe_id == db.pr_person.pe_id) & (db.gis_location.id == db.pr_presence.location_id)
136
137 # Need sql.Rows object for show_map, so don't extract individual row.
138- location = db(presence_query).select(db.gis_location.ALL, orderby=~db.pr_presence.time, limitby=(0, 1))
139+ location = db(presence_query).select(db.gis_location.ALL, orderby=~db.pr_presence.datetime, limitby=(0, 1))
140
141 if not location:
142- address_query = (db.pr_person.id == person_id) and (db.pr_address.pe_id == db.pr_person.pe_id) and (db.gis_location.id == db.pr_address.location_id)
143+ address_query = (db.pr_person.id == person_id) & (db.pr_address.pe_id == db.pr_person.pe_id) & (db.gis_location.id == db.pr_address.location_id)
144 # TODO: If there are multiple addresses, which should we choose?
145 # For now, take whichever address is supplied first.
146 location = db(address_query).select(db.gis_location.ALL, limitby=(0, 1))
147@@ -371,6 +377,86 @@
148
149
150 # -----------------------------------------------------------------------------
151+def view_team_map():
152+ """
153+ Map Location of Volunteer in a Team.
154+ Use most recent presence if available, else any address that's available.
155+ """
156+
157+ group_id = request.args(0)
158+
159+ members_query = (db.pr_group_membership.group_id == group_id)
160+ members = db(members_query).select(db.pr_group_membership.person_id) #members of a team aka group
161+ member_person_ids = [ x.person_id for x in members ] #list of members
162+
163+ #Presence Data of the members with Presence Logs
164+ presence_rows = db(db.pr_person.id.belongs(member_person_ids) & (db.pr_presence.pe_id == db.pr_person.pe_id) & (db.gis_location.id == db.pr_presence.location_id)).select(db.gis_location.ALL, db.pr_person.id, orderby=~db.pr_presence.datetime)
165+ #Get Latest Presence Data
166+ person_location_sort = presence_rows.sort(lambda row:row.pr_person.id)
167+ previous_person_id = None
168+ locations_list = []
169+ for row in person_location_sort:
170+ if row.pr_person.id != previous_person_id:
171+ locations_list.append(row["gis_location"])
172+ member_person_ids.remove(row.pr_person.id)
173+ previous_person_id = row.pr_person.id
174+
175+ #Address of those members without Presence data
176+ address = db(db.pr_person.id.belongs(member_person_ids) & (db.pr_address.pe_id == db.pr_person.pe_id) & (db.gis_location.id == db.pr_address.location_id)).select(db.gis_location.ALL)
177+
178+ locations_list.extend(address)
179+
180+ if locations_list:
181+
182+ bounds = gis.get_bounds(features=locations_list)
183+
184+ volunteer = {"feature_group" : "People"}
185+ html = gis.show_map(
186+ feature_queries = [{"name" : "Volunteer", "query" : locations_list, "active" : True, "marker" : db(db.gis_marker.name == "volunteer").select().first().id}],
187+ feature_groups = [volunteer],
188+ wms_browser = {"name" : "Risk Maps", "url" : "http://preview.grid.unep.ch:8080/geoserver/ows?service=WMS&request=GetCapabilities"},
189+ catalogue_overlays = True,
190+ catalogue_toolbar = True,
191+ toolbar = True,
192+ search = True,
193+ bbox = bounds,
194+ window = True,
195+ )
196+ return dict(map=html)
197+
198+ # TODO: What is an appropriate response if no location is available?
199+ return None
200+
201+
202+# -----------------------------------------------------------------------------
203+def compose_person():
204+ "Send message to volunteer"
205+
206+ person_pe_id_query = (db.pr_person.id == request.vars.person_id)
207+ pe_id_row = db(person_pe_id_query).select(db.pr_person.pe_id).first()
208+ request.vars.pe_id = pe_id_row["pe_id"]
209+
210+ return shn_msg_compose( redirect_module=module,
211+ redirect_function="compose_person",
212+ redirect_vars={"person_id":request.vars.person_id},
213+ title_name="Send a message to a volunteer" )
214+
215+
216+# -----------------------------------------------------------------------------
217+def compose_group():
218+ "Send message to members of a team"
219+
220+ group_pe_id_query = (db.pr_group.id == request.vars.group_id)
221+ pe_id_row = db(group_pe_id_query).select(db.pr_group.pe_id).first()
222+ request.vars.pe_id = pe_id_row["pe_id"]
223+
224+ return shn_msg_compose( redirect_module=module,
225+ redirect_function="compose_group",
226+ redirect_vars={"group_id":request.vars.group_id},
227+ title_name="Send a message to a team of volunteers" )
228+
229+
230+# -----------------------------------------------------------------------------
231 # TODO: Is resource a bad name, due to possible confusion with other usage?
232 def resource():
233 "Select resources a volunteer has."
234
235=== modified file 'models/msg.py'
236--- models/msg.py 2010-08-11 22:48:49 +0000
237+++ models/msg.py 2010-08-17 03:20:56 +0000
238@@ -270,3 +270,69 @@
239 Field("url", requires=IS_NULL_OR(IS_URL())),
240 migrate=migrate)
241 table.uuid.requires = IS_NOT_IN_DB(db, "%s.uuid" % tablename)
242+
243+def shn_msg_compose( redirect_module = "msg",
244+ redirect_function = "compose",
245+ redirect_vars = None,
246+ title_name = "Send Message" ):
247+ """
248+ Form to Compose a Message
249+
250+ @param redirect_module: Redirect to the specified module's url after login.
251+ @param redirect_function: Redirect to the specified function
252+ @param redirect_vars: Dict with vars to include in redirects
253+ @param title_name: Title of the page
254+ """
255+
256+ resource1 = "log"
257+ tablename1 = "msg" + "_" + resource1
258+ table1 = db[tablename1]
259+ resource2 = "outbox"
260+ tablename2 = "msg" + "_" + resource2
261+ table2 = db[tablename2]
262+
263+ if auth.is_logged_in() or auth.basic():
264+ pass
265+ else:
266+ redirect(URL(r=request, c="default", f="user", args="login",
267+ vars={"_next":URL(r=request, c=redirect_module, f=redirect_function, vars=redirect_vars)}))
268+
269+ # Model options
270+ table1.sender.writable = table1.sender.readable = False
271+ table1.fromaddress.writable = table1.fromaddress.readable = False
272+ table1.pe_id.writable = table1.pe_id.readable = False
273+ table1.verified.writable = table1.verified.readable = False
274+ table1.verified_comments.writable = table1.verified_comments.readable = False
275+ table1.actioned.writable = table1.actioned.readable = False
276+ table1.actionable.writable = table1.actionable.readable = False
277+ table1.actioned_comments.writable = table1.actioned_comments.readable = False
278+
279+ table1.subject.label = T("Subject")
280+ table1.message.label = T("Message")
281+ table1.priority.label = T("Priority")
282+
283+ table2.pe_id.writable = table2.pe_id.readable = True
284+ table2.pe_id.label = T("Recipients")
285+
286+ def compose_onvalidation(form):
287+ """ Set the sender and use msg.send_by_pe_id to route the message """
288+ if not request.vars.pe_id:
289+ session.error = T("Please enter the recipient")
290+ redirect(URL(r=request,c=redirect_module, f=redirect_function, vars=redirect_vars))
291+ sender_pe_id = db(db.pr_person.uuid == auth.user.person_uuid).select(db.pr_person.pe_id, limitby=(0, 1)).first().pe_id
292+ if msg.send_by_pe_id(request.vars.pe_id,
293+ request.vars.subject,
294+ request.vars.message,
295+ sender_pe_id,
296+ request.vars.pr_message_method):
297+ session.flash = T("Message sent to outbox")
298+ redirect(URL(r=request, c=redirect_module, f=redirect_function, vars=redirect_vars))
299+ else:
300+ session.error = T("Error in message")
301+ redirect(URL(r=request,c=redirect_module, f=redirect_function, vars=redirect_vars))
302+
303+ logform = crud.create(table1,
304+ onvalidation = compose_onvalidation)
305+ outboxform = crud.create(table2)
306+
307+ return dict(logform = logform, outboxform = outboxform, title = T(title_name))
308
309=== modified file 'models/vol.py'
310--- models/vol.py 2010-08-16 21:08:38 +0000
311+++ models/vol.py 2010-08-17 03:20:56 +0000
312@@ -19,9 +19,6 @@
313 migrate=migrate)
314
315 # -------------------------------------------------------------------------
316- # Person components which are specifically volunteer data:
317- shn_vol_volunteer_data = ("volunteer", "group_membership", "skill")
318- # -------------------------------------------------------------------------
319 # pr_volunteer (Component of pr_person)
320 # describes a person's availability as a volunteer
321
322@@ -399,11 +396,11 @@
323 s3.crud_strings[tablename] = Storage(
324 title_create = T("Add Skill Type"),
325 title_display = T("Skill Type Details"),
326- title_list = T("Skill Type"),
327+ title_list = T("Skill Types"),
328 title_update = T("Edit Skill Type"),
329- title_search = T("Search Skill Type"),
330+ title_search = T("Search Skill Types"),
331 subtitle_create = T("Add New Skill Type"),
332- subtitle_list = T("Skill Type"),
333+ subtitle_list = T("Skill Types"),
334 label_list_button = T("List Skill Types"),
335 label_create_button = T("Add Skill Types"),
336 label_delete_button = T("Delete Skill Type"),
337@@ -412,22 +409,6 @@
338 msg_record_deleted = T("Skill Type deleted"),
339 msg_list_empty = T("No Skill Types currently set"))
340
341- field_settings = S3CheckboxesWidget(db = db,
342- lookup_table_name = "vol_skill_types",
343- lookup_field_name = "name",
344- multiple = True,
345- num_column=3
346- )
347-
348- # Reusable field
349- skill_ids = db.Table(None, "skill_ids",
350- FieldS3("skill_ids",
351- requires = field_settings.requires,
352- widget = field_settings.widget,
353- represent = field_settings.represent,
354- label = T("skills"),
355- ondelete = "RESTRICT"))
356-
357 # Representation function
358 def vol_skill_types_represent(id):
359 if id:
360@@ -441,47 +422,31 @@
361 else:
362 return None
363
364+ skill_types_id = db.Table(None, "skill_types_id",
365+ FieldS3("skill_types_id", db.vol_skill_types,
366+ sortby = ["category", "name"],
367+ requires = IS_ONE_OF(db, "vol_skill_types.id", vol_skill_types_represent),
368+ represent = vol_skill_types_represent,
369+ label = T("Skill"),
370+ ondelete = "RESTRICT"))
371+
372
373 # -------------------------------------------------------------------------
374 # vol_skill
375 # A volunteer's skills (component of pr)
376 #
377
378- def multiselect_widget(f, v):
379- import uuid
380- d_id = "multiselect-" + str(uuid.uuid4())[:8]
381- wrapper = DIV(_id=d_id)
382- inp = SQLFORM.widgets.options.widget(f, v)
383- inp["_multiple"] = "multiple"
384- inp["_style"] = "min-width: %spx;" % (len(f.name) * 20 + 50)
385- if v:
386- if not isinstance(v,list): v = str(v).split("|")
387- opts = inp.elements("option")
388- for op in opts:
389- if op["_value"] in v:
390- op["_selected"] = "selected"
391- scr = SCRIPT('jQuery("#%s select").multiSelect({'\
392- 'noneSelected:"Select %ss"});' % (d_id, f.name))
393- wrapper.append(inp)
394- wrapper.append(scr)
395- if request.vars.get(inp["_id"] + "[]", None):
396- var = request.vars[inp["_id"] + "[]"]
397- if not isinstance(var,list): var = [var]
398- request.vars[f.name] = "|".join(var)
399- del request.vars[inp["_id"] + "[]"]
400- return wrapper
401-
402 resource = "skill"
403 tablename = module + "_" + resource
404- table = db.define_table(tablename, timestamp, uuidstamp, deletion_status,
405- person_id,
406- Field("skill_types_id"),
407- Field("status", requires=IS_IN_SET(["approved", "unapproved", "denied"]), label=T("status"), notnull=True, default="unapproved"),
408- migrate=migrate)
409-
410- db.vol_skill.skill_types_id.widget = multiselect_widget
411- db.vol_skill.skill_types_id.requires = IS_ONE_OF(db, "vol_skill_types.id", vol_skill_types_represent, multiple=True)
412- #db.vol_skill.skill_types_id.represent = vol_skill_types_represent
413+ table = db.define_table(
414+ tablename, timestamp, uuidstamp, deletion_status,
415+ person_id, skill_types_id,
416+ Field("status",
417+ requires=IS_IN_SET(["approved","unapproved","denied"]),
418+ label=T("Status"),
419+ notnull=True,
420+ default="unapproved"),
421+ migrate=migrate)
422
423 s3xrc.model.add_component(module, resource,
424 multiple=True,
425@@ -502,17 +467,18 @@
426 title_display = T("Skill Details"),
427 title_list = SKILL,
428 title_update = T("Edit Skill"),
429- title_search = T("Search Skill"),
430+ title_search = T("Search Skills"),
431 subtitle_create = T("Add New Skill"),
432 subtitle_list = SKILL,
433- label_list_button = T("List Skill"),
434+ label_list_button = T("List Skills"),
435 label_create_button = ADD_SKILL,
436+ label_delete_button = T("Delete Skill"),
437 msg_record_created = T("Skill added"),
438 msg_record_modified = T("Skill updated"),
439 msg_record_deleted = T("Skill deleted"),
440 msg_list_empty = T("No skills currently set"))
441
442- # shn_pr_group_represent -----------------------------------------------------
443+ # shn_pr_group_represent -------------------------------------------------
444 #
445 def teamname(record):
446 """
447@@ -536,77 +502,3 @@
448
449 name = cache.ram("pr_group_%s" % id, lambda: _represent(id))
450 return name
451-
452- # -----------------------------------------------------------------------------
453- def shn_vol_view_map(jr, **attr):
454- """
455- Map Location of Volunteer.
456- Use most recent presence if available, else any address that's available.
457- """
458-
459- response.view = "vol/view_map.html"
460- rheader = shn_vol_rheader(jr)
461-
462- output = dict(title=T("Volunteer location"), rheader=rheader)
463-
464- if jr.id:
465- person_id = jr.id
466-
467- presence_query = (db.pr_person.id == person_id) & \
468- (db.pr_presence.pe_id == db.pr_person.pe_id) & \
469- (db.gis_location.id == db.pr_presence.location_id)
470-
471- # Need sql.Rows object for show_map, so don't extract individual row.
472- location = db(presence_query).select(db.gis_location.ALL,
473- orderby=~db.pr_presence.time,
474- limitby=(0, 1))
475-
476- if not location:
477- address_query = (db.pr_person.id == person_id) & \
478- (db.pr_address.pe_id == db.pr_person.pe_id) & \
479- (db.gis_location.id == db.pr_address.location_id)
480-
481- # TODO: If there are multiple addresses, which should we choose?
482- # For now, take whichever address is supplied first.
483- location = db(address_query).select(db.gis_location.ALL, limitby=(0, 1))
484-
485- if location:
486- # Center and zoom the map.
487- location_row = location.first() # location is a sql.Rows
488- lat = location_row.lat
489- lon = location_row.lon
490- bounds = gis.get_bounds(features=location)
491-
492- marker = db(db.gis_marker.name == "volunteer").select().first()
493- if marker:
494- marker = marker.id
495- else:
496- marker = None
497-
498- volunteer = {"feature_group" : "People"}
499- html = gis.show_map(
500- feature_queries = [{"name" : "Volunteer",
501- "query" : location,
502- "active" : True,
503- "marker" : marker}],
504- feature_groups = [volunteer],
505- catalogue_overlays = True,
506- catalogue_toolbar = False,
507- toolbar = True,
508- search = True,
509- lat = lat,
510- lon = lon,
511- bbox = bounds,
512- window = True,
513- )
514- output.update(map=html)
515-
516- else:
517- # TODO: What is an appropriate response if no location is available?
518- html = T("No location known of this person.")
519- output.update(map=html)
520-
521- return output
522-
523- s3xrc.model.set_method("pr", "person", method="view_map", action=shn_vol_view_map)
524-
525
526=== added file 'views/msg/_compose.html'
527--- views/msg/_compose.html 1970-01-01 00:00:00 +0000
528+++ views/msg/_compose.html 2010-08-17 03:20:56 +0000
529@@ -0,0 +1,133 @@
530+{{try:}}
531+ {{=H2(title)}}
532+{{except:}}
533+{{pass}}
534+<script type="text/javascript">//<![CDATA[
535+$(function() {
536+ // Hide the real Input Field
537+ $('#msg_outbox_pe_id').hide();
538+ // Autocomplete-enable the Dummy Input
539+ $('#dummy').autocomplete('{{=URL(r=request, c="msg", f="search")}}', {
540+ minChars: 2,
541+ //mustMatch: true,
542+ // TODO : Should get multiple working
543+ multiple: false,
544+ matchContains: true,
545+ autofill: true,
546+ dataType: 'json',
547+ parse: function(data) {
548+ var rows = new Array();
549+ for(var i=0; i<data.length; i++){
550+ rows[i] = { data:data[i], value:data[i].id, result:data[i].name };
551+ }
552+ return rows;
553+ },
554+ formatItem: function(row, i, n) {
555+ return row.name;
556+ }
557+ });
558+ // Populate the real Input when the Dummy is selected
559+ $('#dummy').result(function(event, data, formatted) {
560+ var newvalue = data.id;
561+ $('#msg_outbox_pe_id').val(newvalue);
562+ });
563+// $('#dummy_submit').click(function(){
564+// return true;
565+// });
566+$('#msg_outbox_pr_message_method').change(function() {
567+ if ($(this).val() == 1){//Dependent on pr_message_method
568+ $('#msg_log_subject__row').show();
569+ }
570+ else{
571+ $('#msg_log_subject__row').hide();
572+ }
573+ });
574+});
575+//]]></script>
576+
577+<div class='form-container'>
578+{{try:}}
579+ {{=logform.custom.begin}}
580+ <table>
581+ <tbody>
582+ <tr id='msg_outbox_pr_message_method__row'>
583+ <td>
584+ <label>{{=outboxform.custom.label.pr_message_method}}</label>
585+ </td>
586+ <td>
587+ {{=outboxform.custom.widget.pr_message_method}}
588+ </td>
589+ <td>
590+ {{=outboxform.custom.comment.pr_message_method}}
591+ </td>
592+ </tr>
593+ <tr id='msg_outbox_pe_id__row'>
594+ <td>
595+ <label>{{=outboxform.custom.label.pe_id}}</label>
596+ </td>
597+ {{if 'pe_id' in request.vars:}}
598+ <script type="text/javascript">//<![CDATA[
599+ $('#msg_outbox_pe_id').val({{=request.vars.pe_id}})
600+ //]]></script>
601+ <td>
602+ {{=shn_pentity_represent(request.vars.pe_id)}}
603+ </td>
604+ {{else:}}
605+ <td>
606+ {{=INPUT(_id="dummy", _class="ac_input", _size="50")}}
607+ {{=outboxform.custom.widget.pe_id}}
608+ </td>
609+ <td>
610+ {{=outboxform.custom.comment.pe_id}}
611+ </td>
612+ {{pass}}
613+ </tr>
614+ <tr id='msg_log_subject__row'>
615+ <td>
616+ <label>{{=logform.custom.label.subject}}</label>
617+ </td>
618+ <td>
619+ {{=logform.custom.widget.subject}}
620+ </td>
621+ <td>
622+ {{=logform.custom.comment.subject}}
623+ </td>
624+ </tr>
625+ <tr id='msg_log_message__row'>
626+ <td>
627+ <label>{{=logform.custom.label.message}}</label>
628+ </td>
629+ <td>
630+ {{=logform.custom.widget.message}}
631+ </td>
632+ <td>
633+ {{=logform.custom.comment.message}}
634+ </td>
635+ </tr>
636+ <tr id='msg_log_priority__row'>
637+ <td>
638+ <label>{{=logform.custom.label.priority}}</label>
639+ </td>
640+ <td>
641+ {{=logform.custom.widget.priority}}
642+ </td>
643+ <td>
644+ {{=logform.custom.comment.priority}}
645+ </td>
646+ </tr>
647+ <tr id='submit_record__row'>
648+ <td>
649+ </td>
650+ <td>
651+ {{=INPUT(_type="submit", _value=T("Send message"), _id="dummy_submit")}}
652+ </td>
653+ </tr>
654+ <td>
655+ </td>
656+ </tbody>
657+ </table>
658+ {{=logform.custom.end}}
659+{{except:}}
660+{{pass}}
661+</div>
662+<p>&nbsp;</p>
663
664=== modified file 'views/msg/compose.html'
665--- views/msg/compose.html 2010-07-24 16:05:47 +0000
666+++ views/msg/compose.html 2010-08-17 03:20:56 +0000
667@@ -1,125 +1,2 @@
668-{{extend "layout.html"}}
669-{{try:}}
670- {{=H2(title)}}
671-{{except:}}
672-{{pass}}
673-<script type="text/javascript">//<![CDATA[
674-$(function() {
675- // Hide the real Input Field
676- $('#msg_outbox_pe_id').hide();
677- // Autocomplete-enable the Dummy Input
678- $('#dummy').autocomplete('{{=URL(r=request, c="msg", f="search")}}', {
679- minChars: 2,
680- //mustMatch: true,
681- // TODO : Should get multiple working
682- multiple: false,
683- matchContains: true,
684- autofill: true,
685- dataType: 'json',
686- parse: function(data) {
687- var rows = new Array();
688- for(var i=0; i<data.length; i++){
689- rows[i] = { data:data[i], value:data[i].id, result:data[i].name };
690- }
691- return rows;
692- },
693- formatItem: function(row, i, n) {
694- return row.name;
695- }
696- });
697- // Populate the real Input when the Dummy is selected
698- $('#dummy').result(function(event, data, formatted) {
699- var newvalue = data.id;
700- $('#msg_outbox_pe_id').val(newvalue);
701- });
702-// $('#dummy_submit').click(function(){
703-// return true;
704-// });
705-$('#msg_outbox_pr_message_method').change(function() {
706- if ($(this).val() == 1){//Dependent on pr_message_method
707- $('#msg_log_subject__row').show();
708- }
709- else{
710- $('#msg_log_subject__row').hide();
711- }
712- });
713-});
714-//]]></script>
715-
716-<div class='form-container'>
717-{{try:}}
718- {{=logform.custom.begin}}
719- <table>
720- <tbody>
721- <tr id='msg_outbox_pr_message_method__row'>
722- <td>
723- <label>{{=outboxform.custom.label.pr_message_method}}</label>
724- </td>
725- <td>
726- {{=outboxform.custom.widget.pr_message_method}}
727- </td>
728- <td>
729- {{=outboxform.custom.comment.pr_message_method}}
730- </td>
731- </tr>
732- <tr id='msg_outbox_pe_id__row'>
733- <td>
734- <label>{{=outboxform.custom.label.pe_id}}</label>
735- </td>
736- <td>
737- {{=INPUT(_id="dummy", _class="ac_input", _size="50")}}
738- {{=outboxform.custom.widget.pe_id}}
739- </td>
740- <td>
741- {{=outboxform.custom.comment.pe_id}}
742- </td>
743-</tr>
744- <tr id='msg_log_subject__row'>
745- <td>
746- <label>{{=logform.custom.label.subject}}</label>
747- </td>
748- <td>
749- {{=logform.custom.widget.subject}}
750- </td>
751- <td>
752- {{=logform.custom.comment.subject}}
753- </td>
754- </tr>
755- <tr id='msg_log_message__row'>
756- <td>
757- <label>{{=logform.custom.label.message}}</label>
758- </td>
759- <td>
760- {{=logform.custom.widget.message}}
761- </td>
762- <td>
763- {{=logform.custom.comment.message}}
764- </td>
765- </tr>
766- <tr id='msg_log_priority__row'>
767- <td>
768- <label>{{=logform.custom.label.priority}}</label>
769- </td>
770- <td>
771- {{=logform.custom.widget.priority}}
772- </td>
773- <td>
774- {{=logform.custom.comment.priority}}
775- </td>
776- </tr>
777- <tr id='submit_record__row'>
778- <td>
779- </td>
780- <td>
781- {{=INPUT(_type="submit", _value=T("Send message"), _id="dummy_submit")}}
782- </td>
783- </tr>
784- <td>
785- </td>
786- </tbody>
787- </table>
788- {{=logform.custom.end}}
789-{{except:}}
790-{{pass}}
791-</div>
792-<p>&nbsp;</p>
793+{{extend 'layout.html'}}
794+{{include 'msg/_compose.html'}}
795
796=== added file 'views/vol/compose_group.html'
797--- views/vol/compose_group.html 1970-01-01 00:00:00 +0000
798+++ views/vol/compose_group.html 2010-08-17 03:20:56 +0000
799@@ -0,0 +1,2 @@
800+{{extend 'layout.html'}}
801+{{include 'msg/_compose.html'}}
802
803=== added file 'views/vol/compose_person.html'
804--- views/vol/compose_person.html 1970-01-01 00:00:00 +0000
805+++ views/vol/compose_person.html 2010-08-17 03:20:56 +0000
806@@ -0,0 +1,2 @@
807+{{extend 'layout.html'}}
808+{{include 'msg/_compose.html'}}
809
810=== added file 'views/vol/view_team_map.html'
811--- views/vol/view_team_map.html 1970-01-01 00:00:00 +0000
812+++ views/vol/view_team_map.html 2010-08-17 03:20:56 +0000
813@@ -0,0 +1,2 @@
814+{{extend 'layout.html'}}
815+{{=XML(map)}}
816\ No newline at end of file