Merge lp:~milo/linaro-ci-dashboard/linkify-next-loop into lp:linaro-ci-dashboard
- linkify-next-loop
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 46 |
Proposed branch: | lp:~milo/linaro-ci-dashboard/linkify-next-loop |
Merge into: | lp:linaro-ci-dashboard |
Diff against target: |
440 lines (+127/-77) 22 files modified
dashboard/frontend/android_build/models/android_loop.py (+12/-0) dashboard/frontend/android_build/templates/android_loop_detail.html (+0/-7) dashboard/frontend/android_build/tests/test_android_build_clientresponse.py (+1/-2) dashboard/frontend/android_build/tests/test_android_build_views.py (+2/-0) dashboard/frontend/android_build/views/android_loop_detail_view.py (+0/-2) dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py (+13/-0) dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html (+0/-7) dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py (+1/-2) dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py (+1/-2) dashboard/frontend/integration_loop/models/integration_loop.py (+13/-2) dashboard/frontend/integration_loop/templates/integration_loop_detail.html (+0/-7) dashboard/frontend/integration_loop/views/integration_loop_detail_view.py (+0/-2) dashboard/frontend/kernel_build/models/kernel_loop.py (+12/-0) dashboard/frontend/kernel_build/templates/kernel_loop_detail.html (+0/-7) dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py (+1/-2) dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py (+0/-2) dashboard/frontend/models/loop.py (+15/-2) dashboard/frontend/models/textfield_loop.py (+1/-1) dashboard/frontend/templates/loop_detail.html (+21/-2) dashboard/frontend/templates/textfield_loop_detail.html (+2/-21) dashboard/frontend/tests/test_clientresponse.py (+1/-2) dashboard/frontend/views/loop_detail_view.py (+31/-5) |
To merge this branch: | bzr merge lp:~milo/linaro-ci-dashboard/linkify-next-loop |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stevan Radaković | Approve | ||
Review via email: mp+123800@code.launchpad.net |
Commit message
Description of the change
Thsi is a tentative implementation of the final detail of the detail view.
At the moment it works only for the textfield-based views, but if the implementation looks good enough, it can be extended to the others too.
The code added is commented, so should be clear what has been done.
Basically, I resolved this using the @permalink annotation in the model, and retrieving the correct instance from the generic Loop model from the fields.
The same approach might be used also in the JavaScript that creates the link for the 'build' path in the detail view.
- 45. By Milo Casagrande
-
Fixed problem with link.
- 46. By Milo Casagrande
-
Added permaling method, simplified templates, removed not necessary ones.
- 47. By Milo Casagrande
-
Moved get_next_loop function in the view.
- 48. By Milo Casagrande
-
Fixed part of the tests.
Stevan Radaković (stevanr) wrote : | # |
Looks good.
Thanks.
Approve +1
- 49. By Milo Casagrande
-
Fixed test failing, added note.
Preview Diff
1 | === modified file 'dashboard/frontend/android_build/models/android_loop.py' | |||
2 | --- dashboard/frontend/android_build/models/android_loop.py 2012-09-11 14:34:59 +0000 | |||
3 | +++ dashboard/frontend/android_build/models/android_loop.py 2012-09-12 14:34:19 +0000 | |||
4 | @@ -139,3 +139,15 @@ | |||
5 | 139 | exclude=exclude, | 139 | exclude=exclude, |
6 | 140 | capitalize=capitalize, | 140 | capitalize=capitalize, |
7 | 141 | upper=True) | 141 | upper=True) |
8 | 142 | |||
9 | 143 | @models.permalink | ||
10 | 144 | def get_detail_url(self): | ||
11 | 145 | return 'AndroidLoopDetail', (), {'slug': self.name} | ||
12 | 146 | |||
13 | 147 | @models.permalink | ||
14 | 148 | def get_build_url(self): | ||
15 | 149 | return 'AndroidLoopBuild', (), {'slug': self.name} | ||
16 | 150 | |||
17 | 151 | @models.permalink | ||
18 | 152 | def get_update_url(self): | ||
19 | 153 | return 'AndroidLoopUpdate', (), {'slug': self.name} | ||
20 | 142 | 154 | ||
21 | === removed file 'dashboard/frontend/android_build/templates/android_loop_detail.html' | |||
22 | --- dashboard/frontend/android_build/templates/android_loop_detail.html 2012-09-07 15:36:09 +0000 | |||
23 | +++ dashboard/frontend/android_build/templates/android_loop_detail.html 1970-01-01 00:00:00 +0000 | |||
24 | @@ -1,7 +0,0 @@ | |||
25 | 1 | {% extends "loop_detail.html" %} | ||
26 | 2 | {% block scripts %} | ||
27 | 3 | {{ block.super }} | ||
28 | 4 | $("#update_button").click(function() { | ||
29 | 5 | window.location.href = "{% url AndroidLoopUpdate loop_detail.name %}"; | ||
30 | 6 | }); | ||
31 | 7 | {% endblock scripts %} | ||
32 | 8 | 0 | ||
33 | === modified file 'dashboard/frontend/android_build/tests/test_android_build_clientresponse.py' | |||
34 | --- dashboard/frontend/android_build/tests/test_android_build_clientresponse.py 2012-09-10 08:04:06 +0000 | |||
35 | +++ dashboard/frontend/android_build/tests/test_android_build_clientresponse.py 2012-09-12 14:34:19 +0000 | |||
36 | @@ -66,8 +66,7 @@ | |||
37 | 66 | # Assert template names for detail page. | 66 | # Assert template names for detail page. |
38 | 67 | template_names = [template.name for template in | 67 | template_names = [template.name for template in |
39 | 68 | response.templates] | 68 | response.templates] |
42 | 69 | self.assertEquals(template_names, ["android_loop_detail.html", | 69 | self.assertEquals(template_names, ["loop_detail.html", |
41 | 70 | "loop_detail.html", | ||
43 | 71 | "base.html", | 70 | "base.html", |
44 | 72 | "login.html", | 71 | "login.html", |
45 | 73 | ]) | 72 | ]) |
46 | 74 | 73 | ||
47 | === modified file 'dashboard/frontend/android_build/tests/test_android_build_views.py' | |||
48 | --- dashboard/frontend/android_build/tests/test_android_build_views.py 2012-09-10 08:04:06 +0000 | |||
49 | +++ dashboard/frontend/android_build/tests/test_android_build_views.py 2012-09-12 14:34:19 +0000 | |||
50 | @@ -33,6 +33,8 @@ | |||
51 | 33 | self.mock_loop.loop_ptr.id = 0 | 33 | self.mock_loop.loop_ptr.id = 0 |
52 | 34 | self.mock_loop.loop_ptr.loopbuild_set = MagicMock() | 34 | self.mock_loop.loop_ptr.loopbuild_set = MagicMock() |
53 | 35 | self.mock_loop.loop_ptr.loopbuild_set.all = MagicMock() | 35 | self.mock_loop.loop_ptr.loopbuild_set.all = MagicMock() |
54 | 36 | self.mock_loop.next_loop = MagicMock() | ||
55 | 37 | self.mock_loop.next_loop.id = 1 | ||
56 | 36 | 38 | ||
57 | 37 | def test_create_view_get_context_data(self): | 39 | def test_create_view_get_context_data(self): |
58 | 38 | android_loop_create_view = AndroidLoopCreateView() | 40 | android_loop_create_view = AndroidLoopCreateView() |
59 | 39 | 41 | ||
60 | === modified file 'dashboard/frontend/android_build/views/android_loop_detail_view.py' | |||
61 | --- dashboard/frontend/android_build/views/android_loop_detail_view.py 2012-09-07 15:08:52 +0000 | |||
62 | +++ dashboard/frontend/android_build/views/android_loop_detail_view.py 2012-09-12 14:34:19 +0000 | |||
63 | @@ -22,5 +22,3 @@ | |||
64 | 22 | class AndroidLoopDetailView(LoopDetailView): | 22 | class AndroidLoopDetailView(LoopDetailView): |
65 | 23 | 23 | ||
66 | 24 | model = AndroidLoop | 24 | model = AndroidLoop |
67 | 25 | template_name = "android_loop_detail.html" | ||
68 | 26 | build_path = 'android' | ||
69 | 27 | 25 | ||
70 | === modified file 'dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py' | |||
71 | --- dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py 2012-09-07 12:49:10 +0000 | |||
72 | +++ dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py 2012-09-12 14:34:19 +0000 | |||
73 | @@ -17,6 +17,7 @@ | |||
74 | 17 | 17 | ||
75 | 18 | from frontend.models.textfield_loop import TextFieldLoop | 18 | from frontend.models.textfield_loop import TextFieldLoop |
76 | 19 | from frontend.models.loop_reference import ANDROID_LOOP | 19 | from frontend.models.loop_reference import ANDROID_LOOP |
77 | 20 | from django.db.models import permalink | ||
78 | 20 | 21 | ||
79 | 21 | 22 | ||
80 | 22 | class AndroidTextFieldLoop(TextFieldLoop): | 23 | class AndroidTextFieldLoop(TextFieldLoop): |
81 | @@ -34,3 +35,15 @@ | |||
82 | 34 | def can_chain_into(): | 35 | def can_chain_into(): |
83 | 35 | chain = [ANDROID_LOOP] | 36 | chain = [ANDROID_LOOP] |
84 | 36 | return chain | 37 | return chain |
85 | 38 | |||
86 | 39 | @permalink | ||
87 | 40 | def get_detail_url(self): | ||
88 | 41 | return 'AndroidTextFieldLoopDetail', (), {'slug': self.name} | ||
89 | 42 | |||
90 | 43 | @permalink | ||
91 | 44 | def get_build_url(self): | ||
92 | 45 | return 'AndroidTextFieldLoopBuild', (), {'slug': self.name} | ||
93 | 46 | |||
94 | 47 | @permalink | ||
95 | 48 | def get_update_url(self): | ||
96 | 49 | return 'AndroidTextFieldLoopUpdate', (), {'slug': self.name} | ||
97 | 37 | 50 | ||
98 | === removed file 'dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html' | |||
99 | --- dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html 2012-09-10 13:30:37 +0000 | |||
100 | +++ dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html 1970-01-01 00:00:00 +0000 | |||
101 | @@ -1,7 +0,0 @@ | |||
102 | 1 | {% extends "textfield_loop_detail.html" %} | ||
103 | 2 | {% block scripts %} | ||
104 | 3 | {{ block.super }} | ||
105 | 4 | $("#update_button").click(function() { | ||
106 | 5 | window.location.href = "{% url AndroidTextFieldLoopUpdate loop_detail.name %}"; | ||
107 | 6 | }); | ||
108 | 7 | {% endblock scripts %} | ||
109 | 8 | 0 | ||
110 | === modified file 'dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py' | |||
111 | --- dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py 2012-09-10 13:30:37 +0000 | |||
112 | +++ dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py 2012-09-12 14:34:19 +0000 | |||
113 | @@ -65,8 +65,7 @@ | |||
114 | 65 | template_names = [template.name for template in | 65 | template_names = [template.name for template in |
115 | 66 | response.templates] | 66 | response.templates] |
116 | 67 | self.assertEquals(template_names, | 67 | self.assertEquals(template_names, |
119 | 68 | ["android_textfield_loop_detail.html", | 68 | ["textfield_loop_detail.html", |
118 | 69 | "textfield_loop_detail.html", | ||
120 | 70 | "loop_detail.html", | 69 | "loop_detail.html", |
121 | 71 | "base.html", | 70 | "base.html", |
122 | 72 | "login.html", | 71 | "login.html", |
123 | 73 | 72 | ||
124 | === modified file 'dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py' | |||
125 | --- dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py 2012-09-10 13:30:37 +0000 | |||
126 | +++ dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py 2012-09-12 14:34:19 +0000 | |||
127 | @@ -23,5 +23,4 @@ | |||
128 | 23 | class AndroidTextFieldLoopDetailView(LoopDetailView): | 23 | class AndroidTextFieldLoopDetailView(LoopDetailView): |
129 | 24 | 24 | ||
130 | 25 | model = AndroidTextFieldLoop | 25 | model = AndroidTextFieldLoop |
133 | 26 | template_name = 'android_textfield_loop_detail.html' | 26 | template_name = 'textfield_loop_detail.html' |
132 | 27 | build_path = 'android-text' | ||
134 | 28 | 27 | ||
135 | === modified file 'dashboard/frontend/integration_loop/models/integration_loop.py' | |||
136 | --- dashboard/frontend/integration_loop/models/integration_loop.py 2012-08-31 13:34:41 +0000 | |||
137 | +++ dashboard/frontend/integration_loop/models/integration_loop.py 2012-09-12 14:34:19 +0000 | |||
138 | @@ -42,5 +42,16 @@ | |||
139 | 42 | pass | 42 | pass |
140 | 43 | 43 | ||
141 | 44 | def __repr__(self): | 44 | def __repr__(self): |
144 | 45 | return "IntegrationLoop(id=%d, branch=%s, ...)" % (self.id, | 45 | return "IntegrationLoop(id=%d, branch=%s)" % (self.id, self.branch) |
145 | 46 | self.branch) | 46 | |
146 | 47 | @models.permalink | ||
147 | 48 | def get_detail_url(self): | ||
148 | 49 | return 'IntegrationLoopDetail', (), {'slug': self.name} | ||
149 | 50 | |||
150 | 51 | @models.permalink | ||
151 | 52 | def get_build_url(self): | ||
152 | 53 | return 'IntegrationLoopBuild', (), {'slug': self.name} | ||
153 | 54 | |||
154 | 55 | @models.permalink | ||
155 | 56 | def get_update_url(self): | ||
156 | 57 | return 'IntegrationLoopUpdate', (), {'slug': self.name} | ||
157 | 47 | 58 | ||
158 | === removed file 'dashboard/frontend/integration_loop/templates/integration_loop_detail.html' | |||
159 | --- dashboard/frontend/integration_loop/templates/integration_loop_detail.html 2012-09-07 15:40:57 +0000 | |||
160 | +++ dashboard/frontend/integration_loop/templates/integration_loop_detail.html 1970-01-01 00:00:00 +0000 | |||
161 | @@ -1,7 +0,0 @@ | |||
162 | 1 | {% extends "loop_detail.html" %} | ||
163 | 2 | {% block scripts %} | ||
164 | 3 | {{ block.super }} | ||
165 | 4 | $("#update_button").click(function() { | ||
166 | 5 | window.location.href = "{% url IntegrationLoopUpdate loop_detail.name %}"; | ||
167 | 6 | }); | ||
168 | 7 | {% endblock scripts %} | ||
169 | 8 | 0 | ||
170 | === modified file 'dashboard/frontend/integration_loop/views/integration_loop_detail_view.py' | |||
171 | --- dashboard/frontend/integration_loop/views/integration_loop_detail_view.py 2012-09-07 15:40:57 +0000 | |||
172 | +++ dashboard/frontend/integration_loop/views/integration_loop_detail_view.py 2012-09-12 14:34:19 +0000 | |||
173 | @@ -22,5 +22,3 @@ | |||
174 | 22 | class IntegrationLoopDetailView(LoopDetailView): | 22 | class IntegrationLoopDetailView(LoopDetailView): |
175 | 23 | 23 | ||
176 | 24 | model = IntegrationLoop | 24 | model = IntegrationLoop |
177 | 25 | template_name = "integration_loop_detail.html" | ||
178 | 26 | build_path = 'integration_loop' | ||
179 | 27 | 25 | ||
180 | === modified file 'dashboard/frontend/kernel_build/models/kernel_loop.py' | |||
181 | --- dashboard/frontend/kernel_build/models/kernel_loop.py 2012-08-30 21:49:13 +0000 | |||
182 | +++ dashboard/frontend/kernel_build/models/kernel_loop.py 2012-09-12 14:34:19 +0000 | |||
183 | @@ -123,3 +123,15 @@ | |||
184 | 123 | except: | 123 | except: |
185 | 124 | # TODO: Log error. | 124 | # TODO: Log error. |
186 | 125 | pass | 125 | pass |
187 | 126 | |||
188 | 127 | @models.permalink | ||
189 | 128 | def get_detail_url(self): | ||
190 | 129 | return 'KernelLoopDetail', (), {'slug': self.name} | ||
191 | 130 | |||
192 | 131 | @models.permalink | ||
193 | 132 | def get_build_url(self): | ||
194 | 133 | return 'KernelLoopBuild', (), {'slug': self.name} | ||
195 | 134 | |||
196 | 135 | @models.permalink | ||
197 | 136 | def get_update_url(self): | ||
198 | 137 | return 'KernelLoopUpdate', (), {'slug': self.name} | ||
199 | 126 | 138 | ||
200 | === removed file 'dashboard/frontend/kernel_build/templates/kernel_loop_detail.html' | |||
201 | --- dashboard/frontend/kernel_build/templates/kernel_loop_detail.html 2012-09-11 12:36:18 +0000 | |||
202 | +++ dashboard/frontend/kernel_build/templates/kernel_loop_detail.html 1970-01-01 00:00:00 +0000 | |||
203 | @@ -1,7 +0,0 @@ | |||
204 | 1 | {% extends "loop_detail.html" %} | ||
205 | 2 | {% block scripts %} | ||
206 | 3 | {{ block.super }} | ||
207 | 4 | $("#update_button").click(function() { | ||
208 | 5 | window.location.href = "{% url KernelLoopUpdate loop_detail.name %}"; | ||
209 | 6 | }); | ||
210 | 7 | {% endblock scripts %} | ||
211 | 8 | 0 | ||
212 | === modified file 'dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py' | |||
213 | --- dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py 2012-09-10 07:43:51 +0000 | |||
214 | +++ dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py 2012-09-12 14:34:19 +0000 | |||
215 | @@ -70,8 +70,7 @@ | |||
216 | 70 | # Assert template names for detail page. | 70 | # Assert template names for detail page. |
217 | 71 | template_names = [template.name for template in | 71 | template_names = [template.name for template in |
218 | 72 | response.templates] | 72 | response.templates] |
221 | 73 | self.assertEquals(template_names, ["kernel_loop_detail.html", | 73 | self.assertEquals(template_names, ["loop_detail.html", |
220 | 74 | "loop_detail.html", | ||
222 | 75 | "base.html", | 74 | "base.html", |
223 | 76 | "login.html", | 75 | "login.html", |
224 | 77 | ]) | 76 | ]) |
225 | 78 | 77 | ||
226 | === modified file 'dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py' | |||
227 | --- dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py 2012-09-07 15:43:36 +0000 | |||
228 | +++ dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py 2012-09-12 14:34:19 +0000 | |||
229 | @@ -22,5 +22,3 @@ | |||
230 | 22 | class KernelLoopDetailView(LoopDetailView): | 22 | class KernelLoopDetailView(LoopDetailView): |
231 | 23 | 23 | ||
232 | 24 | model = KernelLoop | 24 | model = KernelLoop |
233 | 25 | template_name = 'kernel_loop_detail.html' | ||
234 | 26 | build_path = 'kernel' | ||
235 | 27 | 25 | ||
236 | === modified file 'dashboard/frontend/models/loop.py' | |||
237 | --- dashboard/frontend/models/loop.py 2012-09-11 14:34:59 +0000 | |||
238 | +++ dashboard/frontend/models/loop.py 2012-09-12 14:34:19 +0000 | |||
239 | @@ -39,7 +39,7 @@ | |||
240 | 39 | next_loop = models.OneToOneField('self', blank=True, null=True, | 39 | next_loop = models.OneToOneField('self', blank=True, null=True, |
241 | 40 | unique=True, on_delete=models.SET_NULL, | 40 | unique=True, on_delete=models.SET_NULL, |
242 | 41 | related_name='previous_loop', | 41 | related_name='previous_loop', |
244 | 42 | verbose_name='Next loop in chain') | 42 | verbose_name='Next loop') |
245 | 43 | 43 | ||
246 | 44 | def __init__(self, *args, **kwargs): | 44 | def __init__(self, *args, **kwargs): |
247 | 45 | self.log = Logger.getClassLogger(self) | 45 | self.log = Logger.getClassLogger(self) |
248 | @@ -237,7 +237,8 @@ | |||
249 | 237 | 237 | ||
250 | 238 | :return A list of tuples. | 238 | :return A list of tuples. |
251 | 239 | """ | 239 | """ |
253 | 240 | excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr'] | 240 | excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr', |
254 | 241 | 'next_loop'] | ||
255 | 241 | return self._get_wanted_fields(exclude=excluded_fields, | 242 | return self._get_wanted_fields(exclude=excluded_fields, |
256 | 242 | verbose_name=True, | 243 | verbose_name=True, |
257 | 243 | capitalize=True) | 244 | capitalize=True) |
258 | @@ -259,3 +260,15 @@ | |||
259 | 259 | This method should be overridden by subclasses. | 260 | This method should be overridden by subclasses. |
260 | 260 | """ | 261 | """ |
261 | 261 | return configuration | 262 | return configuration |
262 | 263 | |||
263 | 264 | @models.permalink | ||
264 | 265 | def get_detail_url(self): | ||
265 | 266 | return () | ||
266 | 267 | |||
267 | 268 | @models.permalink | ||
268 | 269 | def get_build_url(self): | ||
269 | 270 | return () | ||
270 | 271 | |||
271 | 272 | @models.permalink | ||
272 | 273 | def get_update_url(self): | ||
273 | 274 | return () | ||
274 | 262 | 275 | ||
275 | === modified file 'dashboard/frontend/models/textfield_loop.py' | |||
276 | --- dashboard/frontend/models/textfield_loop.py 2012-09-11 07:29:13 +0000 | |||
277 | +++ dashboard/frontend/models/textfield_loop.py 2012-09-12 14:34:19 +0000 | |||
278 | @@ -155,7 +155,7 @@ | |||
279 | 155 | # and define a separate functions to retrieve the lines from the | 155 | # and define a separate functions to retrieve the lines from the |
280 | 156 | # HTML template. | 156 | # HTML template. |
281 | 157 | excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr', | 157 | excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr', |
283 | 158 | 'values'] | 158 | 'values', 'next_loop'] |
284 | 159 | return self._get_wanted_fields(exclude=excluded_fields, | 159 | return self._get_wanted_fields(exclude=excluded_fields, |
285 | 160 | verbose_name=True, | 160 | verbose_name=True, |
286 | 161 | capitalize=True) | 161 | capitalize=True) |
287 | 162 | 162 | ||
288 | === modified file 'dashboard/frontend/templates/loop_detail.html' | |||
289 | --- dashboard/frontend/templates/loop_detail.html 2012-09-10 13:30:37 +0000 | |||
290 | +++ dashboard/frontend/templates/loop_detail.html 2012-09-12 14:34:19 +0000 | |||
291 | @@ -9,7 +9,23 @@ | |||
292 | 9 | {% for name, value in loop_detail.get_details %} | 9 | {% for name, value in loop_detail.get_details %} |
293 | 10 | <div>{{ name }}: {{ value }}</div> | 10 | <div>{{ name }}: {{ value }}</div> |
294 | 11 | {% endfor %} | 11 | {% endfor %} |
295 | 12 | {% for verbose_name, name, obj in next_loop %} | ||
296 | 13 | <div> | ||
297 | 14 | {% if name == None %} | ||
298 | 15 | {{ verbose_name }}: {{ name }} | ||
299 | 16 | {% else %} | ||
300 | 17 | {{ verbose_name }}: <a href="{{ obj.get_detail_url }}">{{ name }}</a> | ||
301 | 18 | {% endif %} | ||
302 | 19 | </div> | ||
303 | 20 | {% endfor %} | ||
304 | 12 | </div> | 21 | </div> |
305 | 22 | {% block values %} | ||
306 | 23 | {% comment %} | ||
307 | 24 | This is used in the textfield detail views, to give a spece | ||
308 | 25 | to represent the key<>value values inserte by the user in a better | ||
309 | 26 | way. | ||
310 | 27 | {% endcomment %} | ||
311 | 28 | {% endblock values %} | ||
312 | 13 | <div> | 29 | <div> |
313 | 14 | <button type="button" id="update_button">Update loop configuration</button> | 30 | <button type="button" id="update_button">Update loop configuration</button> |
314 | 15 | </div> | 31 | </div> |
315 | @@ -25,8 +41,11 @@ | |||
316 | 25 | {% endblock content %} | 41 | {% endblock content %} |
317 | 26 | {% block scripts %} | 42 | {% block scripts %} |
318 | 27 | $("#schedule_button").click(function() { | 43 | $("#schedule_button").click(function() { |
320 | 28 | $.get("{% if request.is_secure %}https{% else %}http{% endif %}://{{ request.get_host }}/{{ build_path }}/build/{{ loop_detail.name }}/", function(data) { | 44 | $.get("{% if request.is_secure %}https{% else %}http{% endif %}://{{ request.get_host }}/{{ loop_detail.get_build_url }}", function(data) { |
321 | 29 | $(data).prependTo($("#builds")); | 45 | $(data).prependTo($("#builds")); |
322 | 30 | }); | 46 | }); |
323 | 31 | }); | 47 | }); |
324 | 32 | {% endblock scripts %} | ||
325 | 33 | \ No newline at end of file | 48 | \ No newline at end of file |
326 | 49 | $("#update_button").click(function() { | ||
327 | 50 | window.location.href = "{{ loop_detail.get_update_url }}"; | ||
328 | 51 | }); | ||
329 | 52 | {% endblock scripts %} | ||
330 | 34 | 53 | ||
331 | === modified file 'dashboard/frontend/templates/textfield_loop_detail.html' | |||
332 | --- dashboard/frontend/templates/textfield_loop_detail.html 2012-09-10 13:30:37 +0000 | |||
333 | +++ dashboard/frontend/templates/textfield_loop_detail.html 2012-09-12 14:34:19 +0000 | |||
334 | @@ -1,28 +1,9 @@ | |||
335 | 1 | {% extends "loop_detail.html" %} | 1 | {% extends "loop_detail.html" %} |
344 | 2 | {% block content %} | 2 | {% block values %} |
337 | 3 | <div class="header"><h2>Loop {{ loop_detail.name }}</h2></div> | ||
338 | 4 | <div class="header"><h4>Details</h4></div> | ||
339 | 5 | <div> | ||
340 | 6 | {% for name, value in loop_detail.get_details %} | ||
341 | 7 | <div>{{ name }}: {{ value }}</div> | ||
342 | 8 | {% endfor %} | ||
343 | 9 | </div> | ||
345 | 10 | <div class="header"><h4>Values</h4></div> | 3 | <div class="header"><h4>Values</h4></div> |
346 | 11 | <div class="textfield"> | 4 | <div class="textfield"> |
347 | 12 | {% for value in loop_detail.get_values %} | 5 | {% for value in loop_detail.get_values %} |
348 | 13 | <div>{{ value }}</div> | 6 | <div>{{ value }}</div> |
349 | 14 | {% endfor %} | 7 | {% endfor %} |
350 | 15 | </div> | 8 | </div> |
364 | 16 | <div> | 9 | {% endblock values %} |
352 | 17 | <button type="button" id="update_button">Update loop configuration</button> | ||
353 | 18 | </div> | ||
354 | 19 | <div class="header"><h4>Builds</h4></div> | ||
355 | 20 | <div id="builds"> | ||
356 | 21 | {% for build in builds %} | ||
357 | 22 | {% include "build.html" %} | ||
358 | 23 | {% endfor %} | ||
359 | 24 | </div> | ||
360 | 25 | <div> | ||
361 | 26 | <button type="button" id="schedule_button">Schedule new build</button> | ||
362 | 27 | </div> | ||
363 | 28 | {% endblock content %} | ||
365 | 29 | 10 | ||
366 | === modified file 'dashboard/frontend/tests/test_clientresponse.py' | |||
367 | --- dashboard/frontend/tests/test_clientresponse.py 2012-09-10 08:21:41 +0000 | |||
368 | +++ dashboard/frontend/tests/test_clientresponse.py 2012-09-12 14:34:19 +0000 | |||
369 | @@ -108,8 +108,7 @@ | |||
370 | 108 | # Assert template names for detail page. | 108 | # Assert template names for detail page. |
371 | 109 | template_names = [template.name for template in | 109 | template_names = [template.name for template in |
372 | 110 | response.templates] | 110 | response.templates] |
375 | 111 | self.assertEquals(template_names, ["integration_loop_detail.html", | 111 | self.assertEquals(template_names, ["loop_detail.html", |
374 | 112 | "loop_detail.html", | ||
376 | 113 | "base.html", | 112 | "base.html", |
377 | 114 | "login.html", | 113 | "login.html", |
378 | 115 | ]) | 114 | ]) |
379 | 116 | 115 | ||
380 | === modified file 'dashboard/frontend/views/loop_detail_view.py' | |||
381 | --- dashboard/frontend/views/loop_detail_view.py 2012-09-10 07:36:24 +0000 | |||
382 | +++ dashboard/frontend/views/loop_detail_view.py 2012-09-12 14:34:19 +0000 | |||
383 | @@ -20,6 +20,7 @@ | |||
384 | 20 | from django.utils.decorators import method_decorator | 20 | from django.utils.decorators import method_decorator |
385 | 21 | from frontend.models.loop import Loop | 21 | from frontend.models.loop import Loop |
386 | 22 | 22 | ||
387 | 23 | |||
388 | 23 | class LoopDetailView(DetailView): | 24 | class LoopDetailView(DetailView): |
389 | 24 | 25 | ||
390 | 25 | # These two fields should *never* be overridden. | 26 | # These two fields should *never* be overridden. |
391 | @@ -28,19 +29,44 @@ | |||
392 | 28 | # The following fields have to be overridden in each sub-class. | 29 | # The following fields have to be overridden in each sub-class. |
393 | 29 | model = Loop | 30 | model = Loop |
394 | 30 | template_name = 'loop_detail.html' | 31 | template_name = 'loop_detail.html' |
395 | 31 | # This is necessary for each loop to define the URL path for the build | ||
396 | 32 | # view. This must be overridden. | ||
397 | 33 | build_path = 'loop' | ||
398 | 34 | 32 | ||
399 | 35 | @method_decorator(login_required) | 33 | @method_decorator(login_required) |
400 | 36 | def dispatch(self, *args, **kwargs): | 34 | def dispatch(self, *args, **kwargs): |
401 | 37 | return super(LoopDetailView, self).dispatch(*args, **kwargs) | 35 | return super(LoopDetailView, self).dispatch(*args, **kwargs) |
402 | 38 | 36 | ||
403 | 39 | def get_context_data(self, **kwargs): | 37 | def get_context_data(self, **kwargs): |
405 | 40 | '''Get the context data passed to template.''' | 38 | """Get the context data passed to template.""" |
406 | 41 | context = super(LoopDetailView, self).get_context_data(**kwargs) | 39 | context = super(LoopDetailView, self).get_context_data(**kwargs) |
407 | 42 | loop_pointer = self.object.loop_ptr | 40 | loop_pointer = self.object.loop_ptr |
408 | 43 | context['request'] = self.request | 41 | context['request'] = self.request |
409 | 44 | context['builds'] = loop_pointer.loopbuild_set.all() | 42 | context['builds'] = loop_pointer.loopbuild_set.all() |
411 | 45 | context['build_path'] = self.build_path | 43 | context['next_loop'] = self._get_next_loop() |
412 | 46 | return context | 44 | return context |
413 | 45 | |||
414 | 46 | def _get_next_loop(self): | ||
415 | 47 | """ | ||
416 | 48 | Retrieves all the necessary information to visualize the next loop as | ||
417 | 49 | a link. | ||
418 | 50 | |||
419 | 51 | :return A list with a three-element tuple containing the verbose name | ||
420 | 52 | of the field, the name of the pointed loop, and the actual instance of | ||
421 | 53 | the pointed loop. | ||
422 | 54 | """ | ||
423 | 55 | field = self.object._meta.get_field('next_loop') | ||
424 | 56 | pk = self.object.next_loop_id | ||
425 | 57 | verbose_name = field.verbose_name.capitalize() | ||
426 | 58 | # XXX changed to isinstance, since tests were failing: we need to | ||
427 | 59 | # mock Loop, not the model variable, in a better way in our tests. | ||
428 | 60 | if isinstance(pk, int): | ||
429 | 61 | # Get the pointer to the object we want to retrieve, and retrieve | ||
430 | 62 | # the actual instance. We can do this since all our loops inherits | ||
431 | 63 | # from the same base class (Loop), and we have the information | ||
432 | 64 | # about the loop type (in type). Django has a feature to retrieve | ||
433 | 65 | # the correct object using the lower-case version of the class | ||
434 | 66 | # name. | ||
435 | 67 | ptr = Loop.objects.get(pk=pk) | ||
436 | 68 | obj = getattr(ptr, ptr.type.lower()) | ||
437 | 69 | other_loop = [(verbose_name, ptr.name, obj)] | ||
438 | 70 | else: | ||
439 | 71 | other_loop = [(verbose_name, None, None)] | ||
440 | 72 | return other_loop |
Hey Milo, looks nice!
Is there anyway we can move the get_next_loop model in the view tho?
Also, since we don't need any of the other permalink methods except detail and build, let's remove them.
And as we've spoken on IRC, let's remove everything related to the build_path now...