##// END OF EJS Templates
autocomplete for repository managment of users
marcink -
r298:15e96b5a default
parent child Browse files
Show More
@@ -111,6 +111,7 b' class ReposController(BaseController):'
111 111
112 112 except formencode.Invalid as errors:
113 113 c.repo_info = repo_model.get(id)
114 c.users_array = repo_model.get_users_js()
114 115 errors.value.update({'user':c.repo_info.user.username})
115 116 c.form_errors = errors.error_dict
116 117 return htmlfill.render(
@@ -169,6 +170,8 b' class ReposController(BaseController):'
169 170 defaults = c.repo_info.__dict__
170 171 defaults.update({'user':c.repo_info.user.username})
171 172
173 c.users_array = repo_model.get_users_js()
174
172 175 for p in c.repo_info.repo2perm:
173 176 defaults.update({'perm_%s' % p.user.username:
174 177 p.permission.permission_name})
@@ -41,6 +41,15 b' class RepoModel(object):'
41 41 def get(self, id):
42 42 return self.sa.query(Repository).get(id)
43 43
44 def get_users_js(self):
45
46 users = self.sa.query(User).all()
47 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
48 users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
49 u.lastname, u.username)
50 for u in users])
51 return users_array
52
44 53
45 54 def update(self, repo_id, form_data):
46 55 try:
@@ -4,13 +4,16 b''
4 4 background: #DBD4C6;
5 5 font-family: sans-serif;
6 6 }
7
7 8 #mainhtml .breadcrumbs a:HOVER{
8 9 text-decoration: underline;
9 10 }
11
10 12 a {
11 13 color: #556CB5;
12 14 text-decoration: none;
13 15 }
16
14 17 a:HOVER{
15 18 text-decoration: underline;
16 19 }
@@ -44,6 +47,7 b' a:HOVER{'
44 47 border-top: 1px solid #AAAAAA;
45 48 border-bottom: 2px solid #666666;
46 49 }
50
47 51 .table_disp td {
48 52 border-left: 1px solid #AAAAAA;
49 53 padding-left: 4px;
@@ -62,18 +66,17 b' table tr.parity1 {'
62 66 background: #FFFFFF;
63 67 }
64 68
65
66 69 /*** ***/
67 70
68 /** common settings **/
71 /** COMMON SETTINGS **/
69 72 .add_icon{
70 73 background: url("/images/icons/add.png") no-repeat scroll 3px;
71 74 height: 16px;
72 75 padding-left: 20px;
73 76 padding-top: 0px;
74 77 text-align: left;
78 }
75 79
76 }
77 80 .edit_icon{
78 81 background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
79 82 height: 16px;
@@ -88,13 +91,13 b' table tr.parity1 {'
88 91 padding-left: 20px;
89 92 padding-top: 0px;
90 93 text-align: left;
91
92 94 }
93 95
94 96 .action_button{
95 97 border:0px;
96 98 display: block;
97 99 }
100
98 101 .action_button:hover{
99 102 border:0px;
100 103 font-style:italic;
@@ -104,26 +107,29 b' table tr.parity1 {'
104 107 .flash_msg ul{
105 108 margin:0;
106 109 padding:25px 0px 0px 0px;
110 }
107 111
108 }
109 112 .error_msg {
110 113 background-color:#FFCFCF;
111 114 background-image: url("/images/icons/error_msg.png");
112 115 border:1px solid #FF9595;
113 116 color:#CC3300;
114 117 }
118
115 119 .warning_msg {
116 120 background-color:#FFFBCC;
117 121 background-image: url("/images/icons/warning_msg.png");
118 122 border:1px solid #FFF35E;
119 123 color:#C69E00;
120 124 }
125
121 126 .success_msg {
122 127 background-color:#D5FFCF;
123 128 background-image: url("/images/icons/success_msg.png");
124 129 border:1px solid #97FF88;
125 130 color:#009900;
126 131 }
132
127 133 .notice_msg {
128 134 background-color:#DCE3FF;
129 135 background-image: url("/images/icons/notice_msg.png");
@@ -146,7 +152,8 b' table tr.parity1 {'
146 152 }
147 153
148 154 #msg_close {
149 background:transparent url("icons/cross_grey_small.png") no-repeat scroll 0 0;
155 background: transparent url("icons/cross_grey_small.png") no-repeat
156 scroll 0 0;
150 157 cursor:pointer;
151 158 height:16px;
152 159 position:absolute;
@@ -158,9 +165,9 b' table tr.parity1 {'
158 165 .error-message{
159 166 color:#CC3300;
160 167 }
161 /**** Tooltip ****/
162 .yui-overlay,
163 .yui-panel-container {
168
169 /**** TOOLTIP ****/
170 .yui-overlay,.yui-panel-container {
164 171 visibility:hidden;
165 172 position:absolute;
166 173 z-index: 2;
@@ -182,9 +189,90 b' table tr.parity1 {'
182 189 .yui-tt-shadow {
183 190 display: none;
184 191 }
185 /** end of Tooltip **/
192
193 /** END TOOLTIP **/
194
195 /** AUTOCOMPLETE **/
196
197 .ac{
198 vertical-align: top;
199
200 }
201 .ac .match {
202 font-weight:bold;
203 }
204
205 .ac .yui-ac {
206 position: relative;
207 font-family: arial;
208 font-size: 100%;
209 }
210
211 .ac #perm_ac{
212 width:15em;
213 }
214 /* styles for input field */
215 .ac .yui-ac-input {
216 position: absolute;
217 width: 100%;
218 }
219
220 /* styles for results container */
221 .ac .yui-ac-container {
222 position: absolute;
223 top: 1.6em;
224 width: 100%;
225 }
186 226
227 /* styles for header/body/footer wrapper within container */
228 .ac .yui-ac-content {
229 position: absolute;
230 width: 100%;
231 border: 1px solid #808080;
232 background: #fff;
233 overflow: hidden;
234 z-index: 9050;
235 }
187 236
237 /* styles for container shadow */
238 .ac .yui-ac-shadow {
239 position: absolute;
240 margin: .3em;
241 width: 100%;
242 background: #000;
243 -moz-opacity: 0.10;
244 opacity: .10;
245 filter: alpha(opacity = 10);
246 z-index: 9049;
247 }
248
249 /* styles for results list */
250 .ac .yui-ac-content ul {
251 margin: 0;
252 padding: 0;
253 width: 100%;
254 }
255
256 /* styles for result item */
257 .ac .yui-ac-content li {
258 margin: 0;
259 padding: 2px 5px;
260 cursor: default;
261 white-space: nowrap;
262 }
263
264 /* styles for prehighlighted result item */
265 .ac .yui-ac-content li.yui-ac-prehighlight {
266 background: #B3D4FF;
267 }
268
269 /* styles for highlighted result item */
270 .ac .yui-ac-content li.yui-ac-highlight {
271 background: #556CB5;
272 color: #FFF;
273 }
274
275 /** END AUTOCOMPLETE **/
188 276 div#main {
189 277 padding: 5px;
190 278 }
@@ -273,9 +361,11 b' ul.page-nav li.current {'
273 361 padding-right: 5px;
274 362 padding-left: 5px;
275 363 }
364
276 365 ul.page-nav li.current a {
277 366 color: #556CB5;
278 367 }
368
279 369 ul.page-nav li a {
280 370 height: 24px;
281 371 color: #FFF;
@@ -285,9 +375,11 b' ul.page-nav li a {'
285 375 text-decoration: none;
286 376 font-weight: bold;
287 377 }
378
288 379 ul.page-nav li.logout a {
289 380 color: #FDAC9D;
290 381 }
382
291 383 ul.page-nav li a:hover {
292 384 background: #FFF;
293 385 color: #556CB5;
@@ -304,14 +396,15 b' ul.submenu li {'
304 396 font-weight:bold;
305 397 display: inline;
306 398 }
399
307 400 ul.submenu .repos {
308 401 background: url("/images/icons/folder_edit.png") no-repeat scroll 3px;
309 402 height: 16px;
310 403 padding-left: 20px;
311 404 padding-top: 0px;
312 405 text-align: left;
406 }
313 407
314 }
315 408 ul.submenu .users {
316 409 background: url("/images/icons/user_edit.png") no-repeat scroll 3px;
317 410 height: 16px;
@@ -319,6 +412,7 b' ul.submenu .users {'
319 412 padding-top: 0px;
320 413 text-align: left;
321 414 }
415
322 416 ul.submenu .permissions {
323 417 background: url("/images/icons/folder_key.png") no-repeat scroll 3px;
324 418 height: 16px;
@@ -528,9 +622,8 b' dl.overview dt {'
528 622 #clone_url{
529 623 border: 0px;
530 624 }
531 /** end of summary **/
532 625
533 /** chagelog **/
626 /** end of summary **/ /** chagelog **/
534 627 h3.changelog {
535 628 margin: 20px 0 5px 30px;
536 629 padding: 0 0 2px;
@@ -568,18 +661,14 b' ul.changelog-entry li.description {'
568 661 font-size: 1.1em;
569 662 }
570 663
571 /** end of changelog **/
572
573 /** file **/
664 /** end of changelog **/ /** file **/
574 665 p.files {
575 666 margin: 0 0 0 20px;
576 667 font-size: 2.0em;
577 668 font-weight: bold;
578 669 }
579 670
580 /** end of file **/
581
582 /** changeset **/
671 /** end of file **/ /** changeset **/
583 672 #changeset_content{
584 673 width:60%;
585 674 float:left;
@@ -588,6 +677,7 b' p.files {'
588 677 #changeset_content .container .wrapper{
589 678 width: 600px;
590 679 }
680
591 681 #changeset_content .container{
592 682 border:1px solid #CCCCCC;
593 683 height:120px;
@@ -608,9 +698,11 b' p.files {'
608 698 #changeset_content .container .left .date{
609 699 font-weight:bold;
610 700 }
701
611 702 #changeset_content .container .left .author{
612 703
613 704 }
705
614 706 #changeset_content .container .left .message{
615 707 font-style: italic;
616 708 color: #556CB5;
@@ -628,16 +720,20 b' p.files {'
628 720 margin-top: 7px;
629 721 text-align: left;
630 722 }
723
631 724 .cs_files .cs_changed{
632 background: url("/images/icons/page_white_edit.png") no-repeat scroll 3px;
725 background: url("/images/icons/page_white_edit.png") no-repeat scroll
726 3px;
633 727 /*background-color: #FFDD88;*/
634 728 height: 16px;
635 729 padding-left: 20px;
636 730 margin-top: 7px;
637 731 text-align: left;
638 732 }
733
639 734 .cs_files .cs_removed{
640 background: url("/images/icons/page_white_delete.png") no-repeat scroll 3px;
735 background: url("/images/icons/page_white_delete.png") no-repeat scroll
736 3px;
641 737 /*background-color: #FF8888;*/
642 738 height: 16px;
643 739 padding-left: 20px;
@@ -645,16 +741,15 b' p.files {'
645 741 text-align: left;
646 742 }
647 743
648 /** end of changeset **/
649
650 /** canvas **/
744 /** end of changeset **/ /** canvas **/
651 745 #graph_nodes{
652 746 margin-top:8px;
653 747 }
748
654 749 #graph{
655 750 overflow: hidden;
751 }
656 752
657 }
658 753 #graph_nodes{
659 754 width:160px;
660 755 float:left;
@@ -664,16 +759,17 b' p.files {'
664 759 width:800px;
665 760 float:left;
666 761 }
762
667 763 #graph_content .container_header{
668 764 border:1px solid #CCCCCC;
669 765 height:30px;
670 766 background: #EEEEEE;
671 767 }
672 768
673
674 769 #graph_content .container .wrapper{
675 770 width: 600px;
676 771 }
772
677 773 #graph_content .container{
678 774 border-bottom: 1px solid #CCCCCC;
679 775 border-left: 1px solid #CCCCCC;
@@ -692,12 +788,15 b' p.files {'
692 788 width: 25%;
693 789 text-align: right;
694 790 }
791
695 792 #graph_content .container .left .date{
696 793 font-weight:bold;
697 794 }
795
698 796 #graph_content .container .left .author{
699 797
700 798 }
799
701 800 #graph_content .container .left .message{
702 801 font-size: 80%;
703 802 }
@@ -705,6 +804,7 b' p.files {'
705 804 .right div{
706 805 clear: both;
707 806 }
807
708 808 .right .changes .added,.changed,.removed{
709 809 border:1px solid #DDDDDD;
710 810 display:block;
@@ -713,12 +813,15 b' p.files {'
713 813 text-align:center;
714 814 min-width:15px;
715 815 }
816
716 817 .right .changes .added{
717 818 background:#BBFFBB;
718 819 }
820
719 821 .right .changes .changed{
720 822 background: #FFDD88;
721 823 }
824
722 825 .right .changes .removed{
723 826 background: #FF8888;
724 827 }
@@ -728,6 +831,7 b' p.files {'
728 831 font-size: 60%;
729 832 font-weight: bold;
730 833 }
834
731 835 .right .merge img{
732 836 vertical-align: bottom;
733 837 }
@@ -736,9 +840,8 b' p.files {'
736 840 font-size: 90%;
737 841 font-family: monospace;
738 842 }
739 /** end of canvas **/
740 843
741 /* FILE BROWSER */
844 /** end of canvas **/ /* FILE BROWSER */
742 845 div.browserblock {
743 846 overflow: hidden;
744 847 padding: 0px;
@@ -749,16 +852,19 b' div.browserblock {'
749 852 /* new */
750 853 line-height: 125%;
751 854 }
855
752 856 div.browserblock .browser-header{
753 857 border-bottom: 1px solid #CCCCCC;
754 858 background: #EEEEEE;
755 859 color:blue;
756 860 padding:10px 0 10px 0;
757 861 }
862
758 863 div.browserblock .browser-header span{
759 864 margin-left:25px;
760 865 font-weight: bold;
761 866 }
867
762 868 div.browserblock .browser-body{
763 869 background: #EEEEEE;
764 870 }
@@ -767,6 +873,7 b' table.code-browser {'
767 873 border-collapse:collapse;
768 874 width: 100%;
769 875 }
876
770 877 table.code-browser tr{
771 878 margin:3px;
772 879 }
@@ -780,12 +887,12 b' table.code-browser thead th {'
780 887 text-align: left;
781 888 padding-left: 10px;
782 889 }
890
783 891 table.code-browser tbody tr {
784 892
785 893 }
786 894
787 895 table.code-browser tbody td {
788
789 896 padding-left:10px;
790 897 height: 20px;
791 898 }
@@ -811,6 +918,7 b' table.code-browser tbody td {'
811 918 padding-top: 0px;
812 919 text-align: left;
813 920 }
921
814 922 .archive_logo{
815 923 background: url("/images/icons/compress.png") no-repeat scroll 3px;
816 924 height: 16px;
@@ -35,7 +35,12 b''
35 35 </tr>
36 36 <tr>
37 37 <td>${_('Owner')}</td>
38 <td>${h.text('user')}</td>
38 <td class='ac'>
39 <div id="perm_ac">
40 ${h.text('user',class_='yui-ac-input')}
41 <div id="owner_container"></div>
42 </div>
43 </td>
39 44 <td>${self.get_form_error('user')}</td>
40 45 </tr>
41 46 <tr>
@@ -59,10 +64,7 b''
59 64 <td>${r2p.user.username}</td>
60 65 </tr>
61 66 %endfor
62
63
64 67 <%
65
66 68 if not hasattr(c,'form_errors'):
67 69 d = 'display:none;'
68 70 else:
@@ -74,7 +76,12 b''
74 76 <td>${h.radio('perm_new_user','repository.read')}</td>
75 77 <td>${h.radio('perm_new_user','repository.write')}</td>
76 78 <td>${h.radio('perm_new_user','repository.admin')}</td>
77 <td>${h.text('perm_new_user_name',size=10)}</td>
79 <td class='ac'>
80 <div id="perm_ac">
81 ${h.text('perm_new_user_name',class_='yui-ac-input')}
82 <div id="perm_container"></div>
83 </div>
84 </td>
78 85 <td>${self.get_form_error('perm_new_user_name')}</td>
79 86 </tr>
80 87 <tr>
@@ -105,5 +112,114 b''
105 112 });
106 113 });
107 114 </script>
115 <script type="text/javascript">
116 YAHOO.example.FnMultipleFields = function(){
117 var myContacts = ${c.users_array|n}
118
119 // Define a custom search function for the DataSource
120 var matchNames = function(sQuery) {
121 // Case insensitive matching
122 var query = sQuery.toLowerCase(),
123 contact,
124 i=0,
125 l=myContacts.length,
126 matches = [];
127
128 // Match against each name of each contact
129 for(; i<l; i++) {
130 contact = myContacts[i];
131 if((contact.fname.toLowerCase().indexOf(query) > -1) ||
132 (contact.lname.toLowerCase().indexOf(query) > -1) ||
133 (contact.nname && (contact.nname.toLowerCase().indexOf(query) > -1))) {
134 matches[matches.length] = contact;
135 }
136 }
137
138 return matches;
139 };
140
141 // Use a FunctionDataSource
142 var oDS = new YAHOO.util.FunctionDataSource(matchNames);
143 oDS.responseSchema = {
144 fields: ["id", "fname", "lname", "nname"]
145 }
146
147 // Instantiate AutoComplete for perms
148 var oAC_perms = new YAHOO.widget.AutoComplete("perm_new_user_name", "perm_container", oDS);
149 oAC_perms.useShadow = false;
150 oAC_perms.resultTypeList = false;
151
152 // Instantiate AutoComplete for owner
153 var oAC_owner = new YAHOO.widget.AutoComplete("user", "owner_container", oDS);
154 oAC_owner.useShadow = false;
155 oAC_owner.resultTypeList = false;
156
157
158 // Custom formatter to highlight the matching letters
159 var custom_formatter = function(oResultData, sQuery, sResultMatch) {
160 var query = sQuery.toLowerCase(),
161 fname = oResultData.fname,
162 lname = oResultData.lname,
163 nname = oResultData.nname || "", // Guard against null value
164 query = sQuery.toLowerCase(),
165 fnameMatchIndex = fname.toLowerCase().indexOf(query),
166 lnameMatchIndex = lname.toLowerCase().indexOf(query),
167 nnameMatchIndex = nname.toLowerCase().indexOf(query),
168 displayfname, displaylname, displaynname;
169
170 if(fnameMatchIndex > -1) {
171 displayfname = highlightMatch(fname, query, fnameMatchIndex);
172 }
173 else {
174 displayfname = fname;
175 }
176
177 if(lnameMatchIndex > -1) {
178 displaylname = highlightMatch(lname, query, lnameMatchIndex);
179 }
180 else {
181 displaylname = lname;
182 }
183
184 if(nnameMatchIndex > -1) {
185 displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
186 }
187 else {
188 displaynname = nname ? "(" + nname + ")" : "";
189 }
190
191 return displayfname + " " + displaylname + " " + displaynname;
192
193 };
194 oAC_perms.formatResult = custom_formatter;
195 oAC_owner.formatResult = custom_formatter;
196
197 // Helper function for the formatter
198 var highlightMatch = function(full, snippet, matchindex) {
199 return full.substring(0, matchindex) +
200 "<span class='match'>" +
201 full.substr(matchindex, snippet.length) +
202 "</span>" +
203 full.substring(matchindex + snippet.length);
204 };
205
206 var myHandler = function(sType, aArgs) {
207 var myAC = aArgs[0]; // reference back to the AC instance
208 var elLI = aArgs[1]; // reference to the selected LI element
209 var oData = aArgs[2]; // object literal of selected item's result data
210 myAC.getInputEl().value = oData.nname;
211 };
212
213 oAC_perms.itemSelectEvent.subscribe(myHandler);
214 oAC_owner.itemSelectEvent.subscribe(myHandler);
215
216 return {
217 oDS: oDS,
218 oAC_perms: oAC_perms,
219 oAC_owner: oAC_owner,
220 };
221 }();
222
223 </script>
108 224 </div>
109 225 </%def>
@@ -106,6 +106,7 b' def is_current(selected):'
106 106 <li ${is_current('branches')}>${h.link_to(_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
107 107 <li ${is_current('tags')}>${h.link_to(_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
108 108 <li ${is_current('files')}>${h.link_to(_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
109 <li>${h.link_to(_('settings'),h.url('edit_repo',id=c.repo_name))}</li>
109 110 </ul>
110 111 %else:
111 112 ##Root menu
@@ -142,6 +143,8 b' def is_current(selected):'
142 143 <%def name="js()">
143 144 <script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
144 145 <script type="text/javascript" src="/js/yui/container/container-min.js"></script>
146 <script type="text/javascript" src="/js/yui/datasource/datasource-min.js"></script>
147 <script type="text/javascript" src="/js/yui/autocomplete/autocomplete-min.js"></script>
145 148 </%def>
146 149
147 150 <!-- DEFINITION OF FORM ERROR FETCHER -->
@@ -7,12 +7,13 b''
7 7 ${c.repos_prefix} Mercurial Repositories
8 8 </%def>
9 9 <%def name="page_nav()">
10 ${self.menu('home')}
10 &nbsp;
11 </div>
11 12 </%def>
12 13 <%def name="main()">
13 14 <div>
14 15 <br />
15 <h2>${_('Login')}</h2>
16 <h2>${_('Login to hg app')}</h2>
16 17 ${h.form(h.url.current())}
17 18 <table>
18 19 <tr>
General Comments 0
You need to be logged in to leave comments. Login now