11 from logilab.mtconverter import html_escape |
11 from logilab.mtconverter import html_escape |
12 |
12 |
13 from cubicweb import NoSelectableObject, role |
13 from cubicweb import NoSelectableObject, role |
14 from cubicweb.selectors import partial_has_related_entities |
14 from cubicweb.selectors import partial_has_related_entities |
15 from cubicweb.common.view import EntityView |
15 from cubicweb.common.view import EntityView |
|
16 from cubicweb.common.selectors import has_related_entities |
16 from cubicweb.common.utils import HTMLHead |
17 from cubicweb.common.utils import HTMLHead |
17 from cubicweb.common.uilib import rql_for_eid |
18 from cubicweb.common.uilib import rql_for_eid |
18 |
19 |
19 from cubicweb.web.views.basecontrollers import JSonController |
20 from cubicweb.web.views.basecontrollers import JSonController |
20 |
21 |
31 jQuery('#lazy-%(vid)s').bind('%(event)s', function(event) { |
32 jQuery('#lazy-%(vid)s').bind('%(event)s', function(event) { |
32 load_now('#lazy-%(vid)s', '#%(vid)s-hole', %(reloadable)s); |
33 load_now('#lazy-%(vid)s', '#%(vid)s-hole', %(reloadable)s); |
33 });""" % {'event': 'load_%s' % vid, 'vid': vid, |
34 });""" % {'event': 'load_%s' % vid, 'vid': vid, |
34 'reloadable' : str(reloadable).lower()}) |
35 'reloadable' : str(reloadable).lower()}) |
35 |
36 |
36 def lazyview(self, vid, eid=None, reloadable=False, show_spinbox=True, w=None): |
37 def lazyview(self, vid, rql=None, eid=None, rset=None, static=False, |
|
38 reloadable=False, show_spinbox=True, w=None): |
37 """a lazy version of wview |
39 """a lazy version of wview |
38 first version only support lazy viewing for an entity at a time |
40 first version only support lazy viewing for an entity at a time |
39 """ |
41 """ |
|
42 assert rql or eid or rset or static, \ |
|
43 'lazyview wants at least : rql, or an eid, or an rset -- or call it with static=True' |
40 w = w or self.w |
44 w = w or self.w |
41 self.req.add_js('cubicweb.lazy.js') |
45 self.req.add_js('cubicweb.lazy.js') |
42 urlparams = {'vid' : vid, 'mode' : 'html'} |
46 urlparams = {'vid' : vid, 'mode' : 'html'} |
43 if eid: |
47 if rql: |
|
48 urlparams['rql'] = rql |
|
49 elif eid: |
44 urlparams['rql'] = rql_for_eid(eid) |
50 urlparams['rql'] = rql_for_eid(eid) |
|
51 elif rset: |
|
52 urlparams['rql'] = rset.printable_rql() |
45 w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % ( |
53 w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % ( |
46 vid, html_escape(self.build_url('json', **urlparams)))) |
54 vid, html_escape(self.build_url('json', **urlparams)))) |
47 if show_spinbox: |
55 if show_spinbox: |
48 w(u'<img src="data/loading.gif" id="%s-hole" alt="%s"/>' |
56 w(u'<img src="data/loading.gif" id="%s-hole" alt="%s"/>' |
49 % (vid, self.req._('loading'))) |
57 % (vid, self.req._('loading'))) |
63 @property |
71 @property |
64 def cookie_name(self): |
72 def cookie_name(self): |
65 return str('%s_active_tab' % self.config.appid) |
73 return str('%s_active_tab' % self.config.appid) |
66 |
74 |
67 def active_tab(self, tabs, default): |
75 def active_tab(self, tabs, default): |
68 cookie = self.req.get_cookie() |
76 cookies = self.req.get_cookie() |
69 cookiename = self.cookie_name |
77 cookiename = self.cookie_name |
70 activetab = cookie.get(cookiename) |
78 activetab = cookies.get(cookiename) |
71 if activetab is None: |
79 if activetab is None: |
72 cookie[cookiename] = default |
80 cookies[cookiename] = default |
73 self.req.set_cookie(cookie, cookiename) |
81 self.req.set_cookie(cookies, cookiename) |
74 tab = default |
82 tab = default |
75 else: |
83 else: |
76 tab = activetab.value |
84 tab = activetab.value |
77 return tab in tabs and tab or default |
85 return tab in tabs and tab or default |
78 |
86 |
94 tabs = self.prune_tabs(tabs) |
102 tabs = self.prune_tabs(tabs) |
95 # select a tab |
103 # select a tab |
96 active_tab = self.active_tab(tabs, default) |
104 active_tab = self.active_tab(tabs, default) |
97 # build the html structure |
105 # build the html structure |
98 w = self.w |
106 w = self.w |
99 w(u'<div id="entity-tabs">') |
107 w(u'<div id="entity-tabs-%s">' % entity.eid) |
100 w(u'<ul>') |
108 w(u'<ul>') |
101 for tab in tabs: |
109 for tab in tabs: |
102 w(u'<li>') |
110 w(u'<li>') |
103 w(u'<a href="#as-%s">' % tab) |
111 w(u'<a href="#as-%s">' % tab) |
104 w(u'<span onclick="set_tab(\'%s\', \'%s\')">' % (tab, self.cookie_name)) |
112 w(u'<span onclick="set_tab(\'%s\', \'%s\')">' % (tab, self.cookie_name)) |
108 w(u'</li>') |
116 w(u'</li>') |
109 w(u'</ul>') |
117 w(u'</ul>') |
110 w(u'</div>') |
118 w(u'</div>') |
111 for tab in tabs: |
119 for tab in tabs: |
112 w(u'<div id="as-%s">' % tab) |
120 w(u'<div id="as-%s">' % tab) |
113 self.lazyview(tab, entity.eid) |
121 self.lazyview(tab, eid=entity.eid) |
114 w(u'</div>') |
122 w(u'</div>') |
115 # call the set_tab() JS function *after* each tab is generated |
123 # call the set_tab() JS function *after* each tab is generated |
116 # because the callback binding needs to be done before |
124 # because the callback binding needs to be done before |
117 self.req.html_headers.add_onload(u""" |
125 self.req.html_headers.add_onload(u""" |
118 jQuery('#entity-tabs > ul').tabs( { selected: %(tabindex)s }); |
126 jQuery('#entity-tabs-%(eeid)s > ul').tabs( { selected: %(tabindex)s }); |
119 set_tab('%(vid)s', '%(cookiename)s'); |
127 set_tab('%(vid)s', '%(cookiename)s'); |
120 """ % {'tabindex' : tabs.index(active_tab), |
128 """ % {'tabindex' : tabs.index(active_tab), |
121 'vid' : active_tab, |
129 'vid' : active_tab, |
|
130 'eeid' : entity.eid, |
122 'cookiename' : self.cookie_name}) |
131 'cookiename' : self.cookie_name}) |
123 |
132 |
124 |
133 |
125 |
134 class EntityRelatedTab(EntityView): |
126 class EntityRelationView(EntityView): |
135 """A view you should inherit from leftmost, |
127 """view displaying entity related stuff. Such a view _must_ provide rtype |
136 to wrap another actual view displaying entity related stuff. |
128 and target attributes |
137 Such a view _must_ provide the rtype, target and vid attributes : |
129 |
138 |
130 Example : |
139 Example : |
131 |
140 |
132 class ProjectScreenshotsView(EntityRelationView): |
141 class ProjectScreenshotsView(EntityRelationView): |
133 '''display project's screenshots''' |
142 '''display project's screenshots''' |
134 id = title = _('projectscreenshots') |
143 id = title = _('projectscreenshots') |
135 __select__ = implements('Project') |
144 accepts = ('Project',) |
136 rtype = 'screenshot' |
145 rtype = 'screenshot' |
137 target = 'object' |
146 target = 'object' |
|
147 vid = 'gallery' |
|
148 __selectors__ = EntityRelationView.__selectors__ + (one_line_rset,) |
|
149 |
|
150 |
|
151 This is the view we want to have in a tab, only if there is something to show. |
|
152 Then, just define as below, and declare this being the tab content : |
|
153 |
|
154 class ProjectScreenshotTab(EntityRelatedTab, ProjectScreenshotsView): |
|
155 id = 'screenshots_tab' |
138 """ |
156 """ |
139 __select__ = EntityView.__select__ & partial_has_related_entities() |
157 __select__ = EntityView.__select__ & partial_has_related_entities() |
140 vid = 'list' |
158 vid = 'list' |
141 |
159 |
142 def cell_call(self, row, col): |
160 def cell_call(self, row, col): |
143 rset = self.rset.get_entity(row, col).related(self.rtype, role(self)) |
161 rset = self.entity(row, col).related(self.rtype, role(self)) |
144 self.w(u'<h1>%s</h1>' % self.req._(self.title).capitalize()) |
|
145 self.w(u'<div class="mainInfo">') |
162 self.w(u'<div class="mainInfo">') |
146 self.wview(self.vid, rset, 'noresult') |
163 self.wview(self.vid, rset, 'noresult') |
147 self.w(u'</div>') |
164 self.w(u'</div>') |