Merge lp:~mwhudson/launchpad/filter-code-imports-by-type-bug-513182 into lp:launchpad
- filter-code-imports-by-type-bug-513182
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Gavin Panella | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~mwhudson/launchpad/filter-code-imports-by-type-bug-513182 | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
318 lines (+117/-53) 6 files modified
lib/lp/code/browser/codeimport.py (+19/-14) lib/lp/code/doc/codeimport.txt (+35/-13) lib/lp/code/interfaces/codeimport.py (+5/-6) lib/lp/code/model/codeimport.py (+8/-6) lib/lp/code/stories/codeimport/xx-codeimport-view.txt (+28/-12) lib/lp/code/templates/codeimport-list.pt (+22/-2) |
||||
To merge this branch: | bzr merge lp:~mwhudson/launchpad/filter-code-imports-by-type-bug-513182 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gavin Panella (community) | code | Approve | |
Review via email: mp+20719@code.launchpad.net |
Commit message
Allow filtering the +code-imports view by type and show more useful information in the table.
Description of the change
Hi,
This branch adds the option to filter the https:/
Screenshot at: http://
Cheers,
mwh
Michael Hudson-Doyle (mwhudson) wrote : | # |
Gavin Panella wrote:
> Review: Needs Fixing code
> Hi Michael,
>
> Nice feature :) A few tiny comments, but also a possible security hole
> later on, so Needs Fixing.
Hi Gavin, thanks for the review. I think I've addressed your comments
-- diff attached -- so please have another look.
>> === modified file 'lib/lp/
>> --- lib/lp/
>> +++ lib/lp/
>> @@ -67,7 +67,7 @@
>> text = u'Code Import System'
>>
>>
>> -class ReviewStatusDro
>> +class DropdownWidgetW
>> """A <select> widget with a more appropriate 'no value' message.
>>
>> By default `LaunchpadDropd
>> @@ -88,9 +88,15 @@
>> status_field = Choice(
>> __name__='status', title=_("Review Status"),
>> vocabulary=
>> - self.status_widget = CustomWidgetFac
>> + self.status_widget = CustomWidgetFac
>> setUpWidget(self, 'status', status_field, IInputWidget)
>>
>> + type_field = Choice(
>
> This is referred to as rcs_type later in initialize() and as an arg to
> self.context.
>
>> + __name__='type', title=_("Review Status"),
>
> s/Review Status/Revision Control System/ ?
Actually, I think it's much clearer to use copy_field instead of what I
was doing there for both fields, so I did that, and renamed everything
to be hopefully more consistent.
>> + vocabulary=
>> + self.type_widget = CustomWidgetFac
>> + setUpWidget(self, 'type', type_field, IInputWidget)
>> +
>> # status should be None if either (a) there were no query arguments
>> # supplied, i.e. the user browsed directly to this page (this is when
>> # hasValidInput returns False) or (b) the user chose 'Any' in the
>> @@ -99,11 +105,12 @@
>> status = None
>> if self.status_
>> status = self.status_
>> + # Similar for 'type'
>> + rcs_type = None
>> + if self.type_
>> + rcs_type = self.type_
>>
>> - if status is not None:
>> - imports = self.context.
>> - else:
>> - imports = self.context.
>> + imports = self.context.
>>
>> self.batchnav = BatchNavigator(
>>
>> === modified file 'lib/lp/
>> --- lib/lp/
>> +++ lib/lp/
>> @@ -35,9 +35,9 @@
>> Filtering the code import list
>> =======
>>
>> -The code import listing is filterable, though o...
1 | === modified file 'lib/lp/code/browser/codeimport.py' |
2 | --- lib/lp/code/browser/codeimport.py 2010-03-05 04:16:37 +0000 |
3 | +++ lib/lp/code/browser/codeimport.py 2010-03-08 01:15:46 +0000 |
4 | @@ -23,7 +23,6 @@ |
5 | from zope.component import getUtility |
6 | from zope.formlib import form |
7 | from zope.interface import Interface |
8 | -from zope.schema import Choice |
9 | |
10 | from canonical.cachedproperty import cachedproperty |
11 | from canonical.launchpad import _ |
12 | @@ -85,32 +84,31 @@ |
13 | |
14 | def initialize(self): |
15 | """See `LaunchpadView.initialize`.""" |
16 | - status_field = Choice( |
17 | - __name__='status', title=_("Review Status"), |
18 | - vocabulary=CodeImportReviewStatus, required=False) |
19 | - self.status_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
20 | - setUpWidget(self, 'status', status_field, IInputWidget) |
21 | + review_status_field = copy_field( |
22 | + ICodeImport['review_status'], required=False, default=None) |
23 | + self.review_status_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
24 | + setUpWidget(self, 'review_status', review_status_field, IInputWidget) |
25 | |
26 | - type_field = Choice( |
27 | - __name__='type', title=_("Review Status"), |
28 | - vocabulary=RevisionControlSystems, required=False) |
29 | - self.type_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
30 | - setUpWidget(self, 'type', type_field, IInputWidget) |
31 | + rcs_type_field = copy_field( |
32 | + ICodeImport['rcs_type'], required=False, default=None) |
33 | + self.rcs_type_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
34 | + setUpWidget(self, 'rcs_type', rcs_type_field, IInputWidget) |
35 | |
36 | # status should be None if either (a) there were no query arguments |
37 | # supplied, i.e. the user browsed directly to this page (this is when |
38 | # hasValidInput returns False) or (b) the user chose 'Any' in the |
39 | # status widget (this is when hasValidInput returns True but |
40 | # getInputValue returns None). |
41 | - status = None |
42 | - if self.status_widget.hasValidInput(): |
43 | - status = self.status_widget.getInputValue() |
44 | + review_status = None |
45 | + if self.review_status_widget.hasValidInput(): |
46 | + review_status = self.review_status_widget.getInputValue() |
47 | # Similar for 'type' |
48 | rcs_type = None |
49 | - if self.type_widget.hasValidInput(): |
50 | - rcs_type = self.type_widget.getInputValue() |
51 | + if self.rcs_type_widget.hasValidInput(): |
52 | + rcs_type = self.rcs_type_widget.getInputValue() |
53 | |
54 | - imports = self.context.search(review_status=status, rcs_type=rcs_type) |
55 | + imports = self.context.search( |
56 | + review_status=review_status, rcs_type=rcs_type) |
57 | |
58 | self.batchnav = BatchNavigator(imports, self.request) |
59 | |
60 | |
61 | === modified file 'lib/lp/code/stories/codeimport/xx-codeimport-view.txt' |
62 | --- lib/lp/code/stories/codeimport/xx-codeimport-view.txt 2010-03-05 04:19:48 +0000 |
63 | +++ lib/lp/code/stories/codeimport/xx-codeimport-view.txt 2010-03-08 01:15:46 +0000 |
64 | @@ -43,7 +43,7 @@ |
65 | internals a bit. |
66 | |
67 | >>> browser.open('http://code.launchpad.dev/+code-imports') |
68 | - >>> control = browser.getControl(name="field.status") |
69 | + >>> control = browser.getControl(name="field.review_status") |
70 | >>> control.displayValue |
71 | ['Any'] |
72 | >>> control.displayValue = ["Invalid"] |
73 | @@ -55,24 +55,30 @@ |
74 | Of course selecting the "Any" filtering option ensures that all |
75 | imports appear again. |
76 | |
77 | - >>> browser.getControl(name="field.status").displayValue = ["Any"] |
78 | + >>> browser.getControl(name="field.review_status").displayValue = ["Any"] |
79 | >>> browser.getControl(name="submit").click() |
80 | >>> table = find_tag_by_id(browser.contents, 'code-import-listing') |
81 | - >>> names = [extract_text(tr.td) for tr in table.tbody('tr')] |
82 | - >>> for name in names: |
83 | - ... print name |
84 | - gnome-terminal/import |
85 | - evolution/import |
86 | + >>> rows = [extract_text(tr) for tr in table('tr')] |
87 | + >>> for row in rows: |
88 | + ... print row |
89 | + Import Created Type Location Status |
90 | + gnome-terminal/import 2007-... Subversion via ... http://sv... Reviewed |
91 | + evolution/import 2007-... Concurrent Vers... :pserver:... Pending Review |
92 | |
93 | We can also filter by type. |
94 | |
95 | - >>> browser.getControl(name="field.type").displayValue = ["Concurrent Versions System"] |
96 | + >>> control = browser.getControl(name="field.rcs_type") |
97 | + >>> control.displayValue |
98 | + ['Any'] |
99 | + >>> browser.getControl(name="field.rcs_type").displayValue = [ |
100 | + ... "Concurrent Versions System"] |
101 | >>> browser.getControl(name="submit").click() |
102 | >>> table = find_tag_by_id(browser.contents, 'code-import-listing') |
103 | - >>> names = [extract_text(tr.td) for tr in table.tbody('tr')] |
104 | - >>> for name in names: |
105 | - ... print name |
106 | - evolution/import |
107 | + >>> rows = [extract_text(tr) for tr in table('tr')] |
108 | + >>> for row in rows: |
109 | + ... print row |
110 | + Import Created Type Location Status |
111 | + evolution/import 2007-... Concurrent Vers... :pserver:... Pending Review |
112 | |
113 | If we create a lot of imports, the listing view will be batched. |
114 | |
115 | |
116 | === modified file 'lib/lp/code/templates/codeimport-list.pt' |
117 | --- lib/lp/code/templates/codeimport-list.pt 2010-03-05 04:16:37 +0000 |
118 | +++ lib/lp/code/templates/codeimport-list.pt 2010-03-08 01:15:46 +0000 |
119 | @@ -14,12 +14,12 @@ |
120 | tal:define="codeimports view/batchnav/currentBatch"> |
121 | |
122 | <form action="" method="GET"> |
123 | - <select name="review_status" tal:replace="structure view/status_widget"> |
124 | + <select name="review_status" tal:replace="structure view/review_status_widget"> |
125 | <option label="">Any</option> |
126 | <option label="NEW">New</option> |
127 | <option label="REVIEWED">Reviewed</option> |
128 | </select> |
129 | - <select name="rcs_type" tal:replace="structure view/type_widget"> |
130 | + <select name="rcs_type" tal:replace="structure view/rcs_type_widget"> |
131 | <option label="">Any</option> |
132 | <option label="GIT">Git</option> |
133 | <option label="BZR_SVN">Subversion</option> |
134 | @@ -68,15 +68,15 @@ |
135 | </a> |
136 | </td> |
137 | |
138 | - <td tal:content="structure codeimport/date_created/fmt:datetime"> |
139 | + <td tal:content="codeimport/date_created/fmt:datetime"> |
140 | some date |
141 | </td> |
142 | |
143 | - <td tal:content="structure codeimport/rcs_type/title"> |
144 | + <td tal:content="codeimport/rcs_type/title"> |
145 | some type |
146 | </td> |
147 | |
148 | - <td tal:content="structure codeimport/getImportDetailsForDisplay"> |
149 | + <td tal:content="codeimport/getImportDetailsForDisplay"> |
150 | some details |
151 | </td> |
152 |
Gavin Panella (allenap) wrote : | # |
This all looks great!
Preview Diff
1 | === modified file 'lib/lp/code/browser/codeimport.py' |
2 | --- lib/lp/code/browser/codeimport.py 2010-03-05 03:46:53 +0000 |
3 | +++ lib/lp/code/browser/codeimport.py 2010-03-08 19:30:44 +0000 |
4 | @@ -23,7 +23,6 @@ |
5 | from zope.component import getUtility |
6 | from zope.formlib import form |
7 | from zope.interface import Interface |
8 | -from zope.schema import Choice |
9 | |
10 | from canonical.cachedproperty import cachedproperty |
11 | from canonical.launchpad import _ |
12 | @@ -67,7 +66,7 @@ |
13 | text = u'Code Import System' |
14 | |
15 | |
16 | -class ReviewStatusDropdownWidget(LaunchpadDropdownWidget): |
17 | +class DropdownWidgetWithAny(LaunchpadDropdownWidget): |
18 | """A <select> widget with a more appropriate 'no value' message. |
19 | |
20 | By default `LaunchpadDropdownWidget` displays 'no value' when the |
21 | @@ -85,25 +84,31 @@ |
22 | |
23 | def initialize(self): |
24 | """See `LaunchpadView.initialize`.""" |
25 | - status_field = Choice( |
26 | - __name__='status', title=_("Review Status"), |
27 | - vocabulary=CodeImportReviewStatus, required=False) |
28 | - self.status_widget = CustomWidgetFactory(ReviewStatusDropdownWidget) |
29 | - setUpWidget(self, 'status', status_field, IInputWidget) |
30 | + review_status_field = copy_field( |
31 | + ICodeImport['review_status'], required=False, default=None) |
32 | + self.review_status_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
33 | + setUpWidget(self, 'review_status', review_status_field, IInputWidget) |
34 | + |
35 | + rcs_type_field = copy_field( |
36 | + ICodeImport['rcs_type'], required=False, default=None) |
37 | + self.rcs_type_widget = CustomWidgetFactory(DropdownWidgetWithAny) |
38 | + setUpWidget(self, 'rcs_type', rcs_type_field, IInputWidget) |
39 | |
40 | # status should be None if either (a) there were no query arguments |
41 | # supplied, i.e. the user browsed directly to this page (this is when |
42 | # hasValidInput returns False) or (b) the user chose 'Any' in the |
43 | # status widget (this is when hasValidInput returns True but |
44 | # getInputValue returns None). |
45 | - status = None |
46 | - if self.status_widget.hasValidInput(): |
47 | - status = self.status_widget.getInputValue() |
48 | + review_status = None |
49 | + if self.review_status_widget.hasValidInput(): |
50 | + review_status = self.review_status_widget.getInputValue() |
51 | + # Similar for 'type' |
52 | + rcs_type = None |
53 | + if self.rcs_type_widget.hasValidInput(): |
54 | + rcs_type = self.rcs_type_widget.getInputValue() |
55 | |
56 | - if status is not None: |
57 | - imports = self.context.search(review_status=status) |
58 | - else: |
59 | - imports = self.context.getAll() |
60 | + imports = self.context.search( |
61 | + review_status=review_status, rcs_type=rcs_type) |
62 | |
63 | self.batchnav = BatchNavigator(imports, self.request) |
64 | |
65 | |
66 | === modified file 'lib/lp/code/doc/codeimport.txt' |
67 | --- lib/lp/code/doc/codeimport.txt 2010-01-12 03:46:21 +0000 |
68 | +++ lib/lp/code/doc/codeimport.txt 2010-03-08 19:30:44 +0000 |
69 | @@ -399,22 +399,15 @@ |
70 | Retrieving CodeImports |
71 | ---------------------- |
72 | |
73 | -You can retrieve all imports with the `getAll` method of ICodeImport. |
74 | +You can retrive subsets of code imports with the `search` method of |
75 | +ICodeImportSet. Passing no arguments returns all code imports. |
76 | |
77 | - >>> svn_import in code_import_set.getAll() |
78 | + >>> svn_import in code_import_set.search() |
79 | True |
80 | |
81 | -You can also retrive an import by id, which will be used to present the |
82 | -object view for an import and also by branch, which will be used to |
83 | -present the import's details on the page of the branch. |
84 | - |
85 | - >>> code_import_set.get(svn_import.id).url |
86 | - u'svn://svn.example.com/trunk' |
87 | - >>> code_import_set.getByBranch(cvs_import.branch).cvs_root |
88 | - u':pserver:anonymous@cvs.example.com:/cvsroot' |
89 | - |
90 | -Finally, you can search for imports by review status. For instance, |
91 | -there is a single sample CodeImport with the "REVIEWED" status: |
92 | +You can filter the results by review status and by type. For |
93 | +instance, there is a single sample CodeImport with the "REVIEWED" |
94 | +status: |
95 | |
96 | >>> reviewed_imports = list(code_import_set.search( |
97 | ... review_status=CodeImportReviewStatus.REVIEWED)) |
98 | @@ -423,6 +416,35 @@ |
99 | >>> reviewed_imports[0].review_status.name |
100 | 'REVIEWED' |
101 | |
102 | +And a single Git import. |
103 | + |
104 | + >>> git_imports = list(code_import_set.search( |
105 | + ... rcs_type=RevisionControlSystems.GIT)) |
106 | + >>> git_imports |
107 | + [<...CodeImport...>] |
108 | + >>> git_imports[0].rcs_type.name |
109 | + 'GIT' |
110 | + |
111 | +Passing both paramters is combined as "and". |
112 | + |
113 | + >>> reviewed_git_imports = list(code_import_set.search( |
114 | + ... review_status=CodeImportReviewStatus.REVIEWED, |
115 | + ... rcs_type=RevisionControlSystems.GIT)) |
116 | + >>> reviewed_git_imports |
117 | + [<...CodeImport...>] |
118 | + >>> reviewed_git_imports[0].rcs_type.name |
119 | + 'GIT' |
120 | + >>> reviewed_git_imports[0].review_status.name |
121 | + 'REVIEWED' |
122 | + |
123 | +You can also retrive an import by id and by branch, which will be used |
124 | +to present the import's details on the page of the branch. |
125 | + |
126 | + >>> code_import_set.get(svn_import.id).url |
127 | + u'svn://svn.example.com/trunk' |
128 | + >>> code_import_set.getByBranch(cvs_import.branch).cvs_root |
129 | + u':pserver:anonymous@cvs.example.com:/cvsroot' |
130 | + |
131 | When you ask for an id that is not present ICodeImportSet.get() raises |
132 | canonical.launchpad.interfaces.NotFoundError, rather than some |
133 | internal database exception. |
134 | |
135 | === modified file 'lib/lp/code/interfaces/codeimport.py' |
136 | --- lib/lp/code/interfaces/codeimport.py 2010-01-12 02:07:38 +0000 |
137 | +++ lib/lp/code/interfaces/codeimport.py 2010-03-08 19:30:44 +0000 |
138 | @@ -191,9 +191,6 @@ |
139 | cvs_root=None, cvs_module=None, review_status=None): |
140 | """Create a new CodeImport.""" |
141 | |
142 | - def getAll(): |
143 | - """Return an iterable of all CodeImport objects.""" |
144 | - |
145 | def getActiveImports(text=None): |
146 | """Return an iterable of all 'active' CodeImport objects. |
147 | |
148 | @@ -222,9 +219,11 @@ |
149 | def delete(id): |
150 | """Delete a CodeImport given its id.""" |
151 | |
152 | - def search(review_status): |
153 | - """Find the CodeImports of the given status. |
154 | + def search(review_status=None, rcs_type=None): |
155 | + """Find the CodeImports of the given status and type. |
156 | |
157 | :param review_status: An entry from the `CodeImportReviewStatus` |
158 | - schema. |
159 | + schema, or None, which signifies 'any status'. |
160 | + :param rcs_type: An entry from the `RevisionControlSystems` |
161 | + schema, or None, which signifies 'any type'. |
162 | """ |
163 | |
164 | === modified file 'lib/lp/code/model/codeimport.py' |
165 | --- lib/lp/code/model/codeimport.py 2010-01-31 23:48:38 +0000 |
166 | +++ lib/lp/code/model/codeimport.py 2010-03-08 19:30:44 +0000 |
167 | @@ -31,6 +31,7 @@ |
168 | from canonical.database.datetimecol import UtcDateTimeCol |
169 | from canonical.database.enumcol import EnumCol |
170 | from canonical.database.sqlbase import SQLBase, quote, sqlvalues |
171 | +from canonical.launchpad.interfaces import IStore |
172 | from lp.code.model.codeimportjob import CodeImportJobWorkflow |
173 | from lp.registry.model.productseries import ProductSeries |
174 | from canonical.launchpad.webapp.interfaces import NotFoundError |
175 | @@ -265,10 +266,6 @@ |
176 | CodeImportJob.delete(code_import.import_job.id) |
177 | CodeImport.delete(code_import.id) |
178 | |
179 | - def getAll(self): |
180 | - """See `ICodeImportSet`.""" |
181 | - return CodeImport.select() |
182 | - |
183 | def getActiveImports(self, text=None): |
184 | """See `ICodeImportSet`.""" |
185 | query = self.composeQueryString(text) |
186 | @@ -334,6 +331,11 @@ |
187 | """See `ICodeImportSet`.""" |
188 | return CodeImport.selectOneBy(branch=branch) |
189 | |
190 | - def search(self, review_status): |
191 | + def search(self, review_status=None, rcs_type=None): |
192 | """See `ICodeImportSet`.""" |
193 | - return CodeImport.selectBy(review_status=review_status) |
194 | + clauses = [] |
195 | + if review_status is not None: |
196 | + clauses.append(CodeImport.review_status == review_status) |
197 | + if rcs_type is not None: |
198 | + clauses.append(CodeImport.rcs_type == rcs_type) |
199 | + return IStore(CodeImport).find(CodeImport, *clauses) |
200 | |
201 | === modified file 'lib/lp/code/stories/codeimport/xx-codeimport-view.txt' |
202 | --- lib/lp/code/stories/codeimport/xx-codeimport-view.txt 2009-12-07 08:57:49 +0000 |
203 | +++ lib/lp/code/stories/codeimport/xx-codeimport-view.txt 2010-03-08 19:30:44 +0000 |
204 | @@ -35,15 +35,15 @@ |
205 | Filtering the code import list |
206 | ============================== |
207 | |
208 | -The code import listing is filterable, though only on review status so |
209 | -far. There are no invalid imports in the sample data, so if we filter |
210 | -just on them we'll see the "no imports found" message. It is worth |
211 | +The code import listing is filterable, on review status and type. |
212 | +There are no invalid imports in the sample data, so if we filter just |
213 | +on them we'll see the "no imports found" message. It is worth |
214 | ensuring that the control for filtering on review status reads "Any" |
215 | by default, as the code that ensures this is poking at Zope 3 |
216 | internals a bit. |
217 | |
218 | >>> browser.open('http://code.launchpad.dev/+code-imports') |
219 | - >>> control = browser.getControl(name="field.status") |
220 | + >>> control = browser.getControl(name="field.review_status") |
221 | >>> control.displayValue |
222 | ['Any'] |
223 | >>> control.displayValue = ["Invalid"] |
224 | @@ -55,14 +55,30 @@ |
225 | Of course selecting the "Any" filtering option ensures that all |
226 | imports appear again. |
227 | |
228 | - >>> browser.getControl(name="field.status").displayValue = ["Any"] |
229 | - >>> browser.getControl(name="submit").click() |
230 | - >>> table = find_tag_by_id(browser.contents, 'code-import-listing') |
231 | - >>> names = [extract_text(tr.td) for tr in table.tbody('tr')] |
232 | - >>> for name in names: |
233 | - ... print name |
234 | - gnome-terminal/import |
235 | - evolution/import |
236 | + >>> browser.getControl(name="field.review_status").displayValue = ["Any"] |
237 | + >>> browser.getControl(name="submit").click() |
238 | + >>> table = find_tag_by_id(browser.contents, 'code-import-listing') |
239 | + >>> rows = [extract_text(tr) for tr in table('tr')] |
240 | + >>> for row in rows: |
241 | + ... print row |
242 | + Import Created Type Location Status |
243 | + gnome-terminal/import 2007-... Subversion via ... http://sv... Reviewed |
244 | + evolution/import 2007-... Concurrent Vers... :pserver:... Pending Review |
245 | + |
246 | +We can also filter by type. |
247 | + |
248 | + >>> control = browser.getControl(name="field.rcs_type") |
249 | + >>> control.displayValue |
250 | + ['Any'] |
251 | + >>> browser.getControl(name="field.rcs_type").displayValue = [ |
252 | + ... "Concurrent Versions System"] |
253 | + >>> browser.getControl(name="submit").click() |
254 | + >>> table = find_tag_by_id(browser.contents, 'code-import-listing') |
255 | + >>> rows = [extract_text(tr) for tr in table('tr')] |
256 | + >>> for row in rows: |
257 | + ... print row |
258 | + Import Created Type Location Status |
259 | + evolution/import 2007-... Concurrent Vers... :pserver:... Pending Review |
260 | |
261 | If we create a lot of imports, the listing view will be batched. |
262 | |
263 | |
264 | === modified file 'lib/lp/code/templates/codeimport-list.pt' |
265 | --- lib/lp/code/templates/codeimport-list.pt 2009-08-18 00:19:52 +0000 |
266 | +++ lib/lp/code/templates/codeimport-list.pt 2010-03-08 19:30:44 +0000 |
267 | @@ -14,11 +14,17 @@ |
268 | tal:define="codeimports view/batchnav/currentBatch"> |
269 | |
270 | <form action="" method="GET"> |
271 | - <select name="review_status" tal:replace="structure view/status_widget"> |
272 | + <select name="review_status" tal:replace="structure view/review_status_widget"> |
273 | <option label="">Any</option> |
274 | <option label="NEW">New</option> |
275 | <option label="REVIEWED">Reviewed</option> |
276 | </select> |
277 | + <select name="rcs_type" tal:replace="structure view/rcs_type_widget"> |
278 | + <option label="">Any</option> |
279 | + <option label="GIT">Git</option> |
280 | + <option label="BZR_SVN">Subversion</option> |
281 | + <option label="SVN">Subversion (legacy)</option> |
282 | + </select> |
283 | <input type="submit" name="submit"/> |
284 | </form> |
285 | |
286 | @@ -38,6 +44,12 @@ |
287 | Created |
288 | </th> |
289 | <th> |
290 | + Type |
291 | + </th> |
292 | + <th> |
293 | + Location |
294 | + </th> |
295 | + <th> |
296 | Status |
297 | </th> |
298 | </tr> |
299 | @@ -56,10 +68,18 @@ |
300 | </a> |
301 | </td> |
302 | |
303 | - <td tal:content="structure codeimport/date_created/fmt:datetime"> |
304 | + <td tal:content="codeimport/date_created/fmt:datetime"> |
305 | some date |
306 | </td> |
307 | |
308 | + <td tal:content="codeimport/rcs_type/title"> |
309 | + some type |
310 | + </td> |
311 | + |
312 | + <td tal:content="codeimport/getImportDetailsForDisplay"> |
313 | + some details |
314 | + </td> |
315 | + |
316 | <td tal:content="codeimport/review_status/title"> |
317 | status |
318 | </td> |
Hi Michael,
Nice feature :) A few tiny comments, but also a possible security hole
later on, so Needs Fixing.
Gavin.
> === modified file 'lib/lp/ code/browser/ codeimport. py' code/browser/ codeimport. py 2010-01-20 03:19:44 +0000 code/browser/ codeimport. py 2010-03-05 13:53:19 +0000 pdownWidget( LaunchpadDropdo wnWidget) : ithAny( LaunchpadDropdo wnWidget) : ownWidget` displays 'no value' when the CodeImportRevie wStatus, required=False) tory(ReviewStat usDropdownWidge t) tory(DropdownWi dgetWithAny)
> --- lib/lp/
> +++ lib/lp/
> @@ -67,7 +67,7 @@
> text = u'Code Import System'
>
>
> -class ReviewStatusDro
> +class DropdownWidgetW
> """A <select> widget with a more appropriate 'no value' message.
>
> By default `LaunchpadDropd
> @@ -88,9 +88,15 @@
> status_field = Choice(
> __name__='status', title=_("Review Status"),
> vocabulary=
> - self.status_widget = CustomWidgetFac
> + self.status_widget = CustomWidgetFac
> setUpWidget(self, 'status', status_field, IInputWidget)
>
> + type_field = Choice(
This is referred to as rcs_type later in initialize() and as an arg to search( ), so perhaps rename this to rcs_type_field?
self.context.
> + __name__='type', title=_("Review Status"),
s/Review Status/Revision Control System/ ?
> + vocabulary= RevisionControl Systems, required=False) tory(DropdownWi dgetWithAny) widget. hasValidInput( ): widget. getInputValue( ) widget. hasValidInput( ): widget. getInputValue( ) search( review_ status= status) getAll( ) search( review_ status= status, rcs_type=rcs_type) imports, self.request) code/doc/ codeimport. txt' code/doc/ codeimport. txt 2010-01-12 03:46:21 +0000 code/doc/ codeimport. txt 2010-03-05 13:53:19 +0000 ------- ------- - set.getAll( ) set.search( )
> + self.type_widget = CustomWidgetFac
> + setUpWidget(self, 'type', type_field, IInputWidget)
> +
> # status should be None if either (a) there were no query arguments
> # supplied, i.e. the user browsed directly to this page (this is when
> # hasValidInput returns False) or (b) the user chose 'Any' in the
> @@ -99,11 +105,12 @@
> status = None
> if self.status_
> status = self.status_
> + # Similar for 'type'
> + rcs_type = None
> + if self.type_
> + rcs_type = self.type_
>
> - if status is not None:
> - imports = self.context.
> - else:
> - imports = self.context.
> + imports = self.context.
>
> self.batchnav = BatchNavigator(
>
>
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -399,22 +399,15 @@
> Retrieving CodeImports
> -------
>
> -You can retrieve all imports with the `getAll` method of ICodeImport.
> +You can retrive subsets of code imports with the `search` method of
> +ICodeImportSet. Passing no arguments returns all code imports.
>
> - >>> svn_import in code_import_
> + >>> svn_import in code_import_
> True
>
> -You can also retrive an import by id, which will be used to present the
> -object view for an import and also by branch, which will be used to
> -present the import's details on the page of the branch.
> -
> - ...