##// END OF EJS Templates
helper-blocks: fix pre formatting only for auth plugin helper texts....
marcink -
r1470:337b0a05 default
parent child Browse files
Show More
@@ -1,383 +1,385 b''
1
1
2 // Contains the style definitions used for .main-content
2 // Contains the style definitions used for .main-content
3 // elements which are mainly around the admin settings.
3 // elements which are mainly around the admin settings.
4
4
5
5
6 // TODO: johbo: Integrate in a better way, this is for "main content" which
6 // TODO: johbo: Integrate in a better way, this is for "main content" which
7 // should not have a limit on the width.
7 // should not have a limit on the width.
8 .main-content-full {
8 .main-content-full {
9 clear: both;
9 clear: both;
10 }
10 }
11
11
12
12
13 .main-content {
13 .main-content {
14 max-width: @maincontent-maxwidth;
14 max-width: @maincontent-maxwidth;
15
15
16 h3,
16 h3,
17 // TODO: johbo: Change templates to use h3 instead of h4 here
17 // TODO: johbo: Change templates to use h3 instead of h4 here
18 h4 {
18 h4 {
19 line-height: 1em;
19 line-height: 1em;
20 }
20 }
21
21
22 // TODO: johbo: Check if we can do that on a global level
22 // TODO: johbo: Check if we can do that on a global level
23 table {
23 table {
24 th {
24 th {
25 padding: 0;
25 padding: 0;
26 }
26 }
27 td.field{
27 td.field{
28 .help-block{
28 .help-block{
29 margin-left: 0;
29 margin-left: 0;
30 }
30 }
31 }
31 }
32 }
32 }
33
33
34 // TODO: johbo: Tweak this into the general styling, for a full width
34 // TODO: johbo: Tweak this into the general styling, for a full width
35 // textarea
35 // textarea
36 .textarea-full {
36 .textarea-full {
37 // 2x 10px padding and 2x 1px border
37 // 2x 10px padding and 2x 1px border
38 margin-right: 22px;
38 margin-right: 22px;
39 }
39 }
40
40
41 }
41 }
42
42
43
43
44 // TODO: johbo: duplicated, think about a mixins.less
44 // TODO: johbo: duplicated, think about a mixins.less
45 .block-left{
45 .block-left{
46 float: left;
46 float: left;
47 }
47 }
48
48
49 .form {
49 .form {
50 .checkboxes {
50 .checkboxes {
51 // TODO: johbo: Should be changed in .checkboxes already
51 // TODO: johbo: Should be changed in .checkboxes already
52 width: auto;
52 width: auto;
53 }
53 }
54
54
55 // TODO: johbo: some settings pages are broken and don't have the .buttons
55 // TODO: johbo: some settings pages are broken and don't have the .buttons
56 // inside the .fields, tweak those templates and remove this.
56 // inside the .fields, tweak those templates and remove this.
57 .buttons {
57 .buttons {
58 margin-top: @textmargin;
58 margin-top: @textmargin;
59 }
59 }
60
60
61 .help-block {
61 .help-block {
62 display: block;
62 display: block;
63 margin-left: @label-width;
63 margin-left: @label-width;
64 white-space: pre;
64 &.pre-formatting {
65 white-space: pre;
66 }
65 }
67 }
66
68
67 .action_button {
69 .action_button {
68 color: @grey4;
70 color: @grey4;
69 }
71 }
70 }
72 }
71
73
72 .main-content-full-width {
74 .main-content-full-width {
73 .main-content;
75 .main-content;
74 width: 100%;
76 width: 100%;
75 min-width: 100%;
77 min-width: 100%;
76 }
78 }
77
79
78 .field {
80 .field {
79 clear: left;
81 clear: left;
80 margin-bottom: @padding;
82 margin-bottom: @padding;
81
83
82 }
84 }
83
85
84 .input-monospace {
86 .input-monospace {
85 font-family: @font-family-monospace;
87 font-family: @font-family-monospace;
86 }
88 }
87
89
88 .fields {
90 .fields {
89 label {
91 label {
90 color: @grey2;
92 color: @grey2;
91 }
93 }
92
94
93 .field {
95 .field {
94 clear: right;
96 clear: right;
95 margin-bottom: @textmargin;
97 margin-bottom: @textmargin;
96 width: 100%;
98 width: 100%;
97
99
98 .label {
100 .label {
99 float: left;
101 float: left;
100 margin-right: @form-vertical-margin;
102 margin-right: @form-vertical-margin;
101 margin-top: 0;
103 margin-top: 0;
102 padding-top: @input-padding-px + @border-thickness-inputs;
104 padding-top: @input-padding-px + @border-thickness-inputs;
103 width: @label-width - @form-vertical-margin;
105 width: @label-width - @form-vertical-margin;
104 }
106 }
105 // used in forms for fields that show just text
107 // used in forms for fields that show just text
106 .label-text {
108 .label-text {
107 .label;
109 .label;
108 padding-top: 5px;
110 padding-top: 5px;
109 }
111 }
110 // Used to position content on the right side of a .label
112 // Used to position content on the right side of a .label
111 .content,
113 .content,
112 .side-by-side-selector {
114 .side-by-side-selector {
113 padding-top: @input-padding-px + @input-border-thickness;
115 padding-top: @input-padding-px + @input-border-thickness;
114 }
116 }
115
117
116 .checkboxes,
118 .checkboxes,
117 .input,
119 .input,
118 .select,
120 .select,
119 .textarea,
121 .textarea,
120 .content {
122 .content {
121 float: none;
123 float: none;
122 margin-left: @label-width;
124 margin-left: @label-width;
123
125
124 .help-block {
126 .help-block {
125 margin-left: 0;
127 margin-left: 0;
126 }
128 }
127 }
129 }
128
130
129 .checkboxes,
131 .checkboxes,
130 .input,
132 .input,
131 .select {
133 .select {
132 .help-block {
134 .help-block {
133 display: block;
135 display: block;
134 }
136 }
135 }
137 }
136
138
137 .checkboxes,
139 .checkboxes,
138 .radios {
140 .radios {
139 // TODO: johbo: We get a 4px margin from the from-bootstrap,
141 // TODO: johbo: We get a 4px margin from the from-bootstrap,
140 // compensating here to align well with labels on the left.
142 // compensating here to align well with labels on the left.
141 padding-top: @input-padding-px + @input-border-thickness - 3px;
143 padding-top: @input-padding-px + @input-border-thickness - 3px;
142 }
144 }
143
145
144 .checkbox,
146 .checkbox,
145 .radio {
147 .radio {
146 display: block;
148 display: block;
147 width: auto;
149 width: auto;
148 }
150 }
149
151
150 .checkbox + .checkbox {
152 .checkbox + .checkbox {
151 display: block;
153 display: block;
152 }
154 }
153
155
154 .input,
156 .input,
155 .select {
157 .select {
156 .help-block,
158 .help-block,
157 .info-block {
159 .info-block {
158 margin-top: @form-vertical-margin / 2;
160 margin-top: @form-vertical-margin / 2;
159 }
161 }
160 }
162 }
161
163
162 .input {
164 .input {
163 .medium {
165 .medium {
164 width: @fields-input-m;
166 width: @fields-input-m;
165 }
167 }
166 .large {
168 .large {
167 width: @fields-input-l;
169 width: @fields-input-l;
168 }
170 }
169
171
170 .text-as-placeholder {
172 .text-as-placeholder {
171 padding-top: @input-padding-px + @border-thickness-inputs;
173 padding-top: @input-padding-px + @border-thickness-inputs;
172 }
174 }
173 }
175 }
174
176
175 // TODO: johbo: Try to find a better integration of this bit.
177 // TODO: johbo: Try to find a better integration of this bit.
176 // When using a select2 inside of a field, it should not have the
178 // When using a select2 inside of a field, it should not have the
177 // top margin.
179 // top margin.
178 .select .drop-menu {
180 .select .drop-menu {
179 margin-top: 0;
181 margin-top: 0;
180 }
182 }
181
183
182 .textarea {
184 .textarea {
183 float: none;
185 float: none;
184
186
185 textarea {
187 textarea {
186 // TODO: johbo: From somewhere we get a clear which does
188 // TODO: johbo: From somewhere we get a clear which does
187 // more harm than good here.
189 // more harm than good here.
188 clear: none;
190 clear: none;
189 }
191 }
190
192
191 .CodeMirror {
193 .CodeMirror {
192 // TODO: johbo: Tweak to position the .help-block nicer,
194 // TODO: johbo: Tweak to position the .help-block nicer,
193 // figure out how to apply for .text-block instead.
195 // figure out how to apply for .text-block instead.
194 margin-bottom: 10px;
196 margin-bottom: 10px;
195 }
197 }
196
198
197 // TODO: johbo: Check if we can remove the grey background on
199 // TODO: johbo: Check if we can remove the grey background on
198 // the global level and remove this if possible.
200 // the global level and remove this if possible.
199 .help-block {
201 .help-block {
200 background: transparent;
202 background: transparent;
201 padding: 0;
203 padding: 0;
202 }
204 }
203 }
205 }
204
206
205 &.tag_patterns,
207 &.tag_patterns,
206 &.branch_patterns {
208 &.branch_patterns {
207
209
208 input {
210 input {
209 max-width: 430px;
211 max-width: 430px;
210 }
212 }
211 }
213 }
212 }
214 }
213
215
214 .field-sm {
216 .field-sm {
215 .label {
217 .label {
216 padding-top: @input-padding-px / 2 + @input-border-thickness;
218 padding-top: @input-padding-px / 2 + @input-border-thickness;
217 }
219 }
218 .checkboxes,
220 .checkboxes,
219 .radios {
221 .radios {
220 // TODO: johbo: We get a 4px margin from the from-bootstrap,
222 // TODO: johbo: We get a 4px margin from the from-bootstrap,
221 // compensating here to align well with labels on the left.
223 // compensating here to align well with labels on the left.
222 padding-top: @input-padding-px / 2 + @input-border-thickness - 3px;
224 padding-top: @input-padding-px / 2 + @input-border-thickness - 3px;
223 }
225 }
224 }
226 }
225
227
226 .field.customhooks {
228 .field.customhooks {
227 .label {
229 .label {
228 padding-top: 0;
230 padding-top: 0;
229 }
231 }
230 .input-wrapper {
232 .input-wrapper {
231 padding-right: 25px;
233 padding-right: 25px;
232
234
233 input {
235 input {
234 width: 100%;
236 width: 100%;
235 }
237 }
236 }
238 }
237 .input {
239 .input {
238 padding-right: 25px;
240 padding-right: 25px;
239 }
241 }
240 }
242 }
241
243
242 .buttons {
244 .buttons {
243 // TODO: johbo: define variable for this value.
245 // TODO: johbo: define variable for this value.
244 // Note that this should be 40px but since most elements add some
246 // Note that this should be 40px but since most elements add some
245 // space in the bottom, we are with 20 closer to 40.
247 // space in the bottom, we are with 20 closer to 40.
246 margin-top: 20px;
248 margin-top: 20px;
247 clear: both;
249 clear: both;
248 margin-bottom: @padding;
250 margin-bottom: @padding;
249 }
251 }
250
252
251 .desc{
253 .desc{
252 margin-right: @textmargin;
254 margin-right: @textmargin;
253 }
255 }
254
256
255 input,
257 input,
256 .drop-menu {
258 .drop-menu {
257 margin-right: @padding/3;
259 margin-right: @padding/3;
258 }
260 }
259
261
260 }
262 }
261
263
262 .form-vertical .fields .field {
264 .form-vertical .fields .field {
263
265
264 .label {
266 .label {
265 float: none;
267 float: none;
266 width: auto;
268 width: auto;
267 }
269 }
268
270
269 .checkboxes,
271 .checkboxes,
270 .input,
272 .input,
271 .select,
273 .select,
272 .textarea {
274 .textarea {
273 margin-left: 0;
275 margin-left: 0;
274 }
276 }
275
277
276 // TODO: johbo: had to tweak the width here to make it big enough for
278 // TODO: johbo: had to tweak the width here to make it big enough for
277 // the license.
279 // the license.
278 .textarea.editor {
280 .textarea.editor {
279 max-width: none;
281 max-width: none;
280 }
282 }
281
283
282 .textarea.large textarea {
284 .textarea.large textarea {
283 min-height: 200px;
285 min-height: 200px;
284 }
286 }
285
287
286 .help-block {
288 .help-block {
287 margin-left: 0;
289 margin-left: 0;
288 }
290 }
289 }
291 }
290
292
291
293
292
294
293
295
294 .main-content {
296 .main-content {
295 .block-left;
297 .block-left;
296
298
297 .section {
299 .section {
298 margin-bottom: @space;
300 margin-bottom: @space;
299 }
301 }
300
302
301
303
302 // Table aligning same way as forms in admin section, e.g.
304 // Table aligning same way as forms in admin section, e.g.
303 // python packages table
305 // python packages table
304 table.formalign {
306 table.formalign {
305 float: left;
307 float: left;
306 width: auto;
308 width: auto;
307
309
308 .label {
310 .label {
309 width: @label-width;
311 width: @label-width;
310 }
312 }
311
313
312 }
314 }
313
315
314
316
315 table.issuetracker {
317 table.issuetracker {
316
318
317 color: @text-color;
319 color: @text-color;
318
320
319 .issue-tracker-example {
321 .issue-tracker-example {
320 color: @grey4;
322 color: @grey4;
321 }
323 }
322 }
324 }
323
325
324 .side-by-side-selector{
326 .side-by-side-selector{
325 .left-group,
327 .left-group,
326 .middle-group,
328 .middle-group,
327 .right-group{
329 .right-group{
328 float: left;
330 float: left;
329 }
331 }
330
332
331 .left-group,
333 .left-group,
332 .right-group{
334 .right-group{
333 width: 45%;
335 width: 45%;
334 text-align: center;
336 text-align: center;
335
337
336 label{
338 label{
337 width: 100%;
339 width: 100%;
338 text-align: left;
340 text-align: left;
339 }
341 }
340
342
341 select{
343 select{
342 width: 100%;
344 width: 100%;
343 background: none;
345 background: none;
344 border-color: @border-highlight-color;
346 border-color: @border-highlight-color;
345 color: @text-color;
347 color: @text-color;
346 font-family: @text-light;
348 font-family: @text-light;
347 font-size: @basefontsize;
349 font-size: @basefontsize;
348 color: @grey1;
350 color: @grey1;
349 padding: @textmargin/2;
351 padding: @textmargin/2;
350 }
352 }
351
353
352 select:after{
354 select:after{
353 content: "";
355 content: "";
354 }
356 }
355
357
356 }
358 }
357
359
358 .middle-group{
360 .middle-group{
359 width: 10%;
361 width: 10%;
360 text-align: center;
362 text-align: center;
361 padding-top: 4em;
363 padding-top: 4em;
362 i {
364 i {
363 font-size: 18px;
365 font-size: 18px;
364 cursor: pointer;
366 cursor: pointer;
365 line-height: 2em;
367 line-height: 2em;
366 }
368 }
367 }
369 }
368
370
369 }
371 }
370
372
371 .permissions_boxes{
373 .permissions_boxes{
372 label, .label{
374 label, .label{
373 margin-right: @textmargin/2;
375 margin-right: @textmargin/2;
374 }
376 }
375 }
377 }
376
378
377 .radios{
379 .radios{
378 label{
380 label{
379 margin-right: @textmargin;
381 margin-right: @textmargin;
380 }
382 }
381 }
383 }
382 }
384 }
383
385
@@ -1,118 +1,118 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.mako"/>
2 <%inherit file="/base/base.mako"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Authentication Settings')}
5 ${_('Authentication Settings')}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}}
7 &middot; ${h.branding(c.rhodecode_name)}}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 ${h.link_to(_('Admin'),h.url('admin_home'))}
12 ${h.link_to(_('Admin'),h.url('admin_home'))}
13 &raquo;
13 &raquo;
14 ${h.link_to(_('Authentication Plugins'),request.resource_path(resource.__parent__, route_name='auth_home'))}
14 ${h.link_to(_('Authentication Plugins'),request.resource_path(resource.__parent__, route_name='auth_home'))}
15 &raquo;
15 &raquo;
16 ${resource.display_name}
16 ${resource.display_name}
17 </%def>
17 </%def>
18
18
19 <%def name="menu_bar_nav()">
19 <%def name="menu_bar_nav()">
20 ${self.menu_items(active='admin')}
20 ${self.menu_items(active='admin')}
21 </%def>
21 </%def>
22
22
23 <%def name="main()">
23 <%def name="main()">
24 <div class="box">
24 <div class="box">
25 <div class="title">
25 <div class="title">
26 ${self.breadcrumbs()}
26 ${self.breadcrumbs()}
27 </div>
27 </div>
28 <div class='sidebar-col-wrapper'>
28 <div class='sidebar-col-wrapper'>
29
29
30 ## TODO: This is repeated in the auth root template and should be merged
30 ## TODO: This is repeated in the auth root template and should be merged
31 ## into a single solution.
31 ## into a single solution.
32 <div class="sidebar">
32 <div class="sidebar">
33 <ul class="nav nav-pills nav-stacked">
33 <ul class="nav nav-pills nav-stacked">
34 % for item in resource.get_root().get_nav_list():
34 % for item in resource.get_root().get_nav_list():
35 <li ${'class=active' if item == resource else ''}>
35 <li ${'class=active' if item == resource else ''}>
36 <a href="${request.resource_path(item, route_name='auth_home')}">${item.display_name}</a>
36 <a href="${request.resource_path(item, route_name='auth_home')}">${item.display_name}</a>
37 </li>
37 </li>
38 % endfor
38 % endfor
39 </ul>
39 </ul>
40 </div>
40 </div>
41
41
42 <div class="main-content-full-width">
42 <div class="main-content-full-width">
43 <div class="panel panel-default">
43 <div class="panel panel-default">
44 <div class="panel-heading">
44 <div class="panel-heading">
45 <h3 class="panel-title">${_('Plugin')}: ${resource.display_name}</h3>
45 <h3 class="panel-title">${_('Plugin')}: ${resource.display_name}</h3>
46 </div>
46 </div>
47 <div class="panel-body">
47 <div class="panel-body">
48 <div class="plugin_form">
48 <div class="plugin_form">
49 <div class="fields">
49 <div class="fields">
50 ${h.secure_form(request.resource_path(resource, route_name='auth_home'))}
50 ${h.secure_form(request.resource_path(resource, route_name='auth_home'))}
51 <div class="form">
51 <div class="form">
52
52
53 %for node in plugin.get_settings_schema():
53 %for node in plugin.get_settings_schema():
54 <% label_css_class = ("label-checkbox" if (node.widget == "bool") else "") %>
54 <% label_css_class = ("label-checkbox" if (node.widget == "bool") else "") %>
55 <div class="field">
55 <div class="field">
56 <div class="label ${label_css_class}"><label for="${node.name}">${node.title}</label></div>
56 <div class="label ${label_css_class}"><label for="${node.name}">${node.title}</label></div>
57 <div class="input">
57 <div class="input">
58 %if node.widget in ["string", "int", "unicode"]:
58 %if node.widget in ["string", "int", "unicode"]:
59 ${h.text(node.name, defaults.get(node.name), class_="medium")}
59 ${h.text(node.name, defaults.get(node.name), class_="medium")}
60 %elif node.widget == "password":
60 %elif node.widget == "password":
61 ${h.password(node.name, defaults.get(node.name), class_="medium")}
61 ${h.password(node.name, defaults.get(node.name), class_="medium")}
62 %elif node.widget == "bool":
62 %elif node.widget == "bool":
63 <div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div>
63 <div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div>
64 %elif node.widget == "select":
64 %elif node.widget == "select":
65 ${h.select(node.name, defaults.get(node.name), node.validator.choices)}
65 ${h.select(node.name, defaults.get(node.name), node.validator.choices)}
66 %elif node.widget == "readonly":
66 %elif node.widget == "readonly":
67 ${node.default}
67 ${node.default}
68 %else:
68 %else:
69 This field is of type ${node.typ}, which cannot be displayed. Must be one of [string|int|bool|select].
69 This field is of type ${node.typ}, which cannot be displayed. Must be one of [string|int|bool|select].
70 %endif
70 %endif
71 %if node.name in errors:
71 %if node.name in errors:
72 <span class="error-message">${errors.get(node.name)}</span>
72 <span class="error-message">${errors.get(node.name)}</span>
73 <br />
73 <br />
74 %endif
74 %endif
75 <p class="help-block">${node.description}</p>
75 <p class="help-block pre-formatting">${node.description}</p>
76 </div>
76 </div>
77 </div>
77 </div>
78 %endfor
78 %endfor
79
79
80 ## Allow derived templates to add something below the form
80 ## Allow derived templates to add something below the form
81 ## input fields
81 ## input fields
82 %if hasattr(next, 'below_form_fields'):
82 %if hasattr(next, 'below_form_fields'):
83 ${next.below_form_fields()}
83 ${next.below_form_fields()}
84 %endif
84 %endif
85
85
86 <div class="buttons">
86 <div class="buttons">
87 ${h.submit('save',_('Save'),class_="btn")}
87 ${h.submit('save',_('Save'),class_="btn")}
88 </div>
88 </div>
89
89
90 </div>
90 </div>
91 ${h.end_form()}
91 ${h.end_form()}
92 </div>
92 </div>
93 </div>
93 </div>
94 </div>
94 </div>
95 </div>
95 </div>
96 </div>
96 </div>
97
97
98 </div>
98 </div>
99 </div>
99 </div>
100
100
101 ## TODO: Ugly hack to get ldap select elements to work.
101 ## TODO: Ugly hack to get ldap select elements to work.
102 ## Find a solution to integrate this nicely.
102 ## Find a solution to integrate this nicely.
103 <script>
103 <script>
104 $(document).ready(function() {
104 $(document).ready(function() {
105 var select2Options = {
105 var select2Options = {
106 containerCssClass: 'drop-menu',
106 containerCssClass: 'drop-menu',
107 dropdownCssClass: 'drop-menu-dropdown',
107 dropdownCssClass: 'drop-menu-dropdown',
108 dropdownAutoWidth: true,
108 dropdownAutoWidth: true,
109 minimumResultsForSearch: -1
109 minimumResultsForSearch: -1
110 };
110 };
111 $("#tls_kind").select2(select2Options);
111 $("#tls_kind").select2(select2Options);
112 $("#tls_reqcert").select2(select2Options);
112 $("#tls_reqcert").select2(select2Options);
113 $("#search_scope").select2(select2Options);
113 $("#search_scope").select2(select2Options);
114 $("#group_extraction_type").select2(select2Options);
114 $("#group_extraction_type").select2(select2Options);
115 $("#admin_groups_sync").select2(select2Options);
115 $("#admin_groups_sync").select2(select2Options);
116 });
116 });
117 </script>
117 </script>
118 </%def>
118 </%def>
@@ -1,76 +1,74 b''
1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
1 <%namespace name="vcss" file="/base/vcs_settings.mako"/>
2
2
3 <div id="repo_vcs_settings" class="${'inherited' if c.inherit_global_settings else ''}">
3 <div id="repo_vcs_settings" class="${'inherited' if c.inherit_global_settings else ''}">
4 ${h.secure_form(url('repo_vcs_settings', repo_name=c.repo_info.repo_name), method='post')}
4 ${h.secure_form(url('repo_vcs_settings', repo_name=c.repo_info.repo_name), method='post')}
5 <div class="form panel panel-default">
5 <div class="form panel panel-default">
6 <div class="fields panel-body">
6 <div class="fields panel-body">
7 <div class="field">
7 <div class="field">
8 <div class="label label-checkbox">
8 <div class="label label-checkbox">
9 <label for="inherit_global_settings">${_('Inherit from global settings')}:</label>
9 <label for="inherit_global_settings">${_('Inherit from global settings')}:</label>
10 </div>
10 </div>
11 <div class="checkboxes">
11 <div class="checkboxes">
12 ${h.checkbox('inherit_global_settings',value=True)}
12 ${h.checkbox('inherit_global_settings',value=True)}
13 <span class="help-block">
13 <span class="help-block">${h.literal(_('Select to inherit global vcs settings.'))}</span>
14 ${h.literal(_('Select to inherit global vcs settings.'))}
15 </span>
16 </div>
14 </div>
17 </div>
15 </div>
18 </div>
16 </div>
19 </div>
17 </div>
20
18
21 <div id="inherit_overlay_vcs_default">
19 <div id="inherit_overlay_vcs_default">
22 <div>
20 <div>
23 ${vcss.vcs_settings_fields(
21 ${vcss.vcs_settings_fields(
24 suffix='_inherited',
22 suffix='_inherited',
25 svn_tag_patterns=c.global_svn_tag_patterns,
23 svn_tag_patterns=c.global_svn_tag_patterns,
26 svn_branch_patterns=c.global_svn_branch_patterns,
24 svn_branch_patterns=c.global_svn_branch_patterns,
27 repo_type=c.repo_info.repo_type,
25 repo_type=c.repo_info.repo_type,
28 disabled='disabled'
26 disabled='disabled'
29 )}
27 )}
30 </div>
28 </div>
31 </div>
29 </div>
32
30
33 <div id="inherit_overlay_vcs_custom">
31 <div id="inherit_overlay_vcs_custom">
34 <div>
32 <div>
35 ${vcss.vcs_settings_fields(
33 ${vcss.vcs_settings_fields(
36 suffix='',
34 suffix='',
37 svn_tag_patterns=c.svn_tag_patterns,
35 svn_tag_patterns=c.svn_tag_patterns,
38 svn_branch_patterns=c.svn_branch_patterns,
36 svn_branch_patterns=c.svn_branch_patterns,
39 repo_type=c.repo_info.repo_type
37 repo_type=c.repo_info.repo_type
40 )}
38 )}
41 </div>
39 </div>
42 </div>
40 </div>
43
41
44 <div class="buttons">
42 <div class="buttons">
45 ${h.submit('save',_('Save settings'),class_="btn")}
43 ${h.submit('save',_('Save settings'),class_="btn")}
46 ${h.reset('reset',_('Reset'),class_="btn")}
44 ${h.reset('reset',_('Reset'),class_="btn")}
47 </div>
45 </div>
48
46
49 ${h.end_form()}
47 ${h.end_form()}
50 </div>
48 </div>
51
49
52 <script type="text/javascript">
50 <script type="text/javascript">
53
51
54 function ajaxDeletePattern(pattern_id, field_id) {
52 function ajaxDeletePattern(pattern_id, field_id) {
55 var sUrl = "${h.url('repo_vcs_settings', repo_name=c.repo_info.repo_name)}";
53 var sUrl = "${h.url('repo_vcs_settings', repo_name=c.repo_info.repo_name)}";
56 var callback = function (o) {
54 var callback = function (o) {
57 var elem = $("#"+field_id);
55 var elem = $("#"+field_id);
58 elem.remove();
56 elem.remove();
59 };
57 };
60 var postData = {
58 var postData = {
61 '_method': 'delete',
59 '_method': 'delete',
62 'delete_svn_pattern': pattern_id,
60 'delete_svn_pattern': pattern_id,
63 'csrf_token': CSRF_TOKEN
61 'csrf_token': CSRF_TOKEN
64 };
62 };
65 var request = $.post(sUrl, postData)
63 var request = $.post(sUrl, postData)
66 .done(callback)
64 .done(callback)
67 .fail(function (data, textStatus, errorThrown) {
65 .fail(function (data, textStatus, errorThrown) {
68 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
66 alert("Error while deleting hooks.\nError code {0} ({1}). URL: {2}".format(data.status,data.statusText,$(this)[0].url));
69 });
67 });
70 }
68 }
71
69
72 $('#inherit_global_settings').on('change', function(e){
70 $('#inherit_global_settings').on('change', function(e){
73 $('#repo_vcs_settings').toggleClass('inherited', this.checked);
71 $('#repo_vcs_settings').toggleClass('inherited', this.checked);
74 });
72 });
75
73
76 </script>
74 </script>
@@ -1,88 +1,87 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="base/root.mako"/>
2 <%inherit file="base/root.mako"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Sign In')}
5 ${_('Sign In')}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <style>body{background-color:#eeeeee;}</style>
11 <style>body{background-color:#eeeeee;}</style>
12 <div class="loginbox">
12 <div class="loginbox">
13 <div class="header">
13 <div class="header">
14 <div id="header-inner" class="title">
14 <div id="header-inner" class="title">
15 <div id="logo">
15 <div id="logo">
16 <div class="logo-wrapper">
16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 </div>
18 </div>
19 %if c.rhodecode_name:
19 %if c.rhodecode_name:
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 %endif
21 %endif
22 </div>
22 </div>
23 </div>
23 </div>
24 </div>
24 </div>
25
25
26 <div class="loginwrapper">
26 <div class="loginwrapper">
27 <div class="left-column">
27 <div class="left-column">
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 </div>
29 </div>
30 <%block name="above_login_button" />
30 <%block name="above_login_button" />
31 <div id="login" class="right-column">
31 <div id="login" class="right-column">
32 <!-- login -->
32 <!-- login -->
33 <div class="sign-in-title">
33 <div class="sign-in-title">
34 <h1>${_('Sign In')}</h1>
34 <h1>${_('Sign In')}</h1>
35 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
35 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
36 <h4>${h.link_to(_("Go to the registration page to create a new account."), request.route_path('register'))}</h4>
36 <h4>${h.link_to(_("Go to the registration page to create a new account."), request.route_path('register'))}</h4>
37 %endif
37 %endif
38 </div>
38 </div>
39 <div class="inner form">
39 <div class="inner form">
40 ${h.form(request.route_path('login', _query={'came_from': came_from}), needs_csrf_token=False)}
40 ${h.form(request.route_path('login', _query={'came_from': came_from}), needs_csrf_token=False)}
41
41
42 <label for="username">${_('Username')}:</label>
42 <label for="username">${_('Username')}:</label>
43 ${h.text('username', class_='focus', value=defaults.get('username'))}
43 ${h.text('username', class_='focus', value=defaults.get('username'))}
44 %if 'username' in errors:
44 %if 'username' in errors:
45 <span class="error-message">${errors.get('username')}</span>
45 <span class="error-message">${errors.get('username')}</span>
46 <br />
46 <br />
47 %endif
47 %endif
48
48
49 <label for="password">${_('Password')}:</label>
49 <label for="password">${_('Password')}:</label>
50 ${h.password('password', class_='focus')}
50 ${h.password('password', class_='focus')}
51 %if 'password' in errors:
51 %if 'password' in errors:
52 <span class="error-message">${errors.get('password')}</span>
52 <span class="error-message">${errors.get('password')}</span>
53 <br />
53 <br />
54 %endif
54 %endif
55
55
56 ${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
56 ${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
57 <label class="checkbox" for="remember">${_('Remember me')}</label>
57 <label class="checkbox" for="remember">${_('Remember me')}</label>
58
58
59 %if h.HasPermissionAny('hg.password_reset.enabled')():
59 %if h.HasPermissionAny('hg.password_reset.enabled')():
60 <p class="links">
60 <p class="links">
61 ${h.link_to(_('Forgot your password?'), h.route_path('reset_password'), class_='pwd_reset')}
61 ${h.link_to(_('Forgot your password?'), h.route_path('reset_password'), class_='pwd_reset')}
62 </p>
62 </p>
63 %elif h.HasPermissionAny('hg.password_reset.hidden')():
63 %elif h.HasPermissionAny('hg.password_reset.hidden')():
64 <p class="help-block">
64 <p class="help-block">
65 ${_('Password reset is disabled. Please contact ')}
65 ${_('Password reset is disabled. Please contact ')}
66 % if c.visual.rhodecode_support_url:
66 % if c.visual.rhodecode_support_url:
67 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
67 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
68 ${_('or')}
68 ${_('or')}
69 % endif
69 % endif
70 ${_('an administrator if you need help.')}
70 ${_('an administrator if you need help.')}
71 </p>
71 </p>
72 %endif
72 %endif
73
74
73
75 ${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}
74 ${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}
76
75
77 ${h.end_form()}
76 ${h.end_form()}
78 <script type="text/javascript">
77 <script type="text/javascript">
79 $(document).ready(function(){
78 $(document).ready(function(){
80 $('#username').focus();
79 $('#username').focus();
81 })
80 })
82 </script>
81 </script>
83 </div>
82 </div>
84 <!-- end login -->
83 <!-- end login -->
85 <%block name="below_login_button" />
84 <%block name="below_login_button" />
86 </div>
85 </div>
87 </div>
86 </div>
88 </div>
87 </div>
@@ -1,593 +1,591 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('New pull request')}
4 ${c.repo_name} ${_('New pull request')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${_('New pull request')}
8 ${_('New pull request')}
9 </%def>
9 </%def>
10
10
11 <%def name="menu_bar_nav()">
11 <%def name="menu_bar_nav()">
12 ${self.menu_items(active='repositories')}
12 ${self.menu_items(active='repositories')}
13 </%def>
13 </%def>
14
14
15 <%def name="menu_bar_subnav()">
15 <%def name="menu_bar_subnav()">
16 ${self.repo_menu(active='showpullrequest')}
16 ${self.repo_menu(active='showpullrequest')}
17 </%def>
17 </%def>
18
18
19 <%def name="main()">
19 <%def name="main()">
20 <div class="box">
20 <div class="box">
21 <div class="title">
21 <div class="title">
22 ${self.repo_page_title(c.rhodecode_db_repo)}
22 ${self.repo_page_title(c.rhodecode_db_repo)}
23 ${self.breadcrumbs()}
23 ${self.breadcrumbs()}
24 </div>
24 </div>
25
25
26 ${h.secure_form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
26 ${h.secure_form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
27 <div class="box pr-summary">
27 <div class="box pr-summary">
28
28
29 <div class="summary-details block-left">
29 <div class="summary-details block-left">
30
30
31 <div class="form">
31 <div class="form">
32 <!-- fields -->
32 <!-- fields -->
33
33
34 <div class="fields" >
34 <div class="fields" >
35
35
36 <div class="field">
36 <div class="field">
37 <div class="label">
37 <div class="label">
38 <label for="pullrequest_title">${_('Title')}:</label>
38 <label for="pullrequest_title">${_('Title')}:</label>
39 </div>
39 </div>
40 <div class="input">
40 <div class="input">
41 ${h.text('pullrequest_title', c.default_title, class_="medium autogenerated-title")}
41 ${h.text('pullrequest_title', c.default_title, class_="medium autogenerated-title")}
42 </div>
42 </div>
43 </div>
43 </div>
44
44
45 <div class="field">
45 <div class="field">
46 <div class="label label-textarea">
46 <div class="label label-textarea">
47 <label for="pullrequest_desc">${_('Description')}:</label>
47 <label for="pullrequest_desc">${_('Description')}:</label>
48 </div>
48 </div>
49 <div class="textarea text-area editor">
49 <div class="textarea text-area editor">
50 ${h.textarea('pullrequest_desc',size=30, )}
50 ${h.textarea('pullrequest_desc',size=30, )}
51 <span class="help-block">
51 <span class="help-block">${_('Write a short description on this pull request')}</span>
52 ${_('Write a short description on this pull request')}
53 </span>
54 </div>
52 </div>
55 </div>
53 </div>
56
54
57 <div class="field">
55 <div class="field">
58 <div class="label label-textarea">
56 <div class="label label-textarea">
59 <label for="pullrequest_desc">${_('Commit flow')}:</label>
57 <label for="pullrequest_desc">${_('Commit flow')}:</label>
60 </div>
58 </div>
61
59
62 ## TODO: johbo: Abusing the "content" class here to get the
60 ## TODO: johbo: Abusing the "content" class here to get the
63 ## desired effect. Should be replaced by a proper solution.
61 ## desired effect. Should be replaced by a proper solution.
64
62
65 ##ORG
63 ##ORG
66 <div class="content">
64 <div class="content">
67 <strong>${_('Origin repository')}:</strong>
65 <strong>${_('Origin repository')}:</strong>
68 ${c.rhodecode_db_repo.description}
66 ${c.rhodecode_db_repo.description}
69 </div>
67 </div>
70 <div class="content">
68 <div class="content">
71 ${h.hidden('source_repo')}
69 ${h.hidden('source_repo')}
72 ${h.hidden('source_ref')}
70 ${h.hidden('source_ref')}
73 </div>
71 </div>
74
72
75 ##OTHER, most Probably the PARENT OF THIS FORK
73 ##OTHER, most Probably the PARENT OF THIS FORK
76 <div class="content">
74 <div class="content">
77 ## filled with JS
75 ## filled with JS
78 <div id="target_repo_desc"></div>
76 <div id="target_repo_desc"></div>
79 </div>
77 </div>
80
78
81 <div class="content">
79 <div class="content">
82 ${h.hidden('target_repo')}
80 ${h.hidden('target_repo')}
83 ${h.hidden('target_ref')}
81 ${h.hidden('target_ref')}
84 <span id="target_ref_loading" style="display: none">
82 <span id="target_ref_loading" style="display: none">
85 ${_('Loading refs...')}
83 ${_('Loading refs...')}
86 </span>
84 </span>
87 </div>
85 </div>
88 </div>
86 </div>
89
87
90 <div class="field">
88 <div class="field">
91 <div class="label label-textarea">
89 <div class="label label-textarea">
92 <label for="pullrequest_submit"></label>
90 <label for="pullrequest_submit"></label>
93 </div>
91 </div>
94 <div class="input">
92 <div class="input">
95 <div class="pr-submit-button">
93 <div class="pr-submit-button">
96 ${h.submit('save',_('Submit Pull Request'),class_="btn")}
94 ${h.submit('save',_('Submit Pull Request'),class_="btn")}
97 </div>
95 </div>
98 <div id="pr_open_message"></div>
96 <div id="pr_open_message"></div>
99 </div>
97 </div>
100 </div>
98 </div>
101
99
102 <div class="pr-spacing-container"></div>
100 <div class="pr-spacing-container"></div>
103 </div>
101 </div>
104 </div>
102 </div>
105 </div>
103 </div>
106 <div>
104 <div>
107 <div class="reviewers-title block-right">
105 <div class="reviewers-title block-right">
108 <div class="pr-details-title">
106 <div class="pr-details-title">
109 ${_('Pull request reviewers')}
107 ${_('Pull request reviewers')}
110 <span class="calculate-reviewers"> - ${_('loading...')}</span>
108 <span class="calculate-reviewers"> - ${_('loading...')}</span>
111 </div>
109 </div>
112 </div>
110 </div>
113 <div id="reviewers" class="block-right pr-details-content reviewers">
111 <div id="reviewers" class="block-right pr-details-content reviewers">
114 ## members goes here, filled via JS based on initial selection !
112 ## members goes here, filled via JS based on initial selection !
115 <input type="hidden" name="__start__" value="review_members:sequence">
113 <input type="hidden" name="__start__" value="review_members:sequence">
116 <ul id="review_members" class="group_members"></ul>
114 <ul id="review_members" class="group_members"></ul>
117 <input type="hidden" name="__end__" value="review_members:sequence">
115 <input type="hidden" name="__end__" value="review_members:sequence">
118 <div id="add_reviewer_input" class='ac'>
116 <div id="add_reviewer_input" class='ac'>
119 <div class="reviewer_ac">
117 <div class="reviewer_ac">
120 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer'))}
118 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer'))}
121 <div id="reviewers_container"></div>
119 <div id="reviewers_container"></div>
122 </div>
120 </div>
123 </div>
121 </div>
124 </div>
122 </div>
125 </div>
123 </div>
126 </div>
124 </div>
127 <div class="box">
125 <div class="box">
128 <div>
126 <div>
129 ## overview pulled by ajax
127 ## overview pulled by ajax
130 <div id="pull_request_overview"></div>
128 <div id="pull_request_overview"></div>
131 </div>
129 </div>
132 </div>
130 </div>
133 ${h.end_form()}
131 ${h.end_form()}
134 </div>
132 </div>
135
133
136 <script type="text/javascript">
134 <script type="text/javascript">
137 $(function(){
135 $(function(){
138 var defaultSourceRepo = '${c.default_repo_data['source_repo_name']}';
136 var defaultSourceRepo = '${c.default_repo_data['source_repo_name']}';
139 var defaultSourceRepoData = ${c.default_repo_data['source_refs_json']|n};
137 var defaultSourceRepoData = ${c.default_repo_data['source_refs_json']|n};
140 var defaultTargetRepo = '${c.default_repo_data['target_repo_name']}';
138 var defaultTargetRepo = '${c.default_repo_data['target_repo_name']}';
141 var defaultTargetRepoData = ${c.default_repo_data['target_refs_json']|n};
139 var defaultTargetRepoData = ${c.default_repo_data['target_refs_json']|n};
142 var targetRepoName = '${c.repo_name}';
140 var targetRepoName = '${c.repo_name}';
143
141
144 var $pullRequestForm = $('#pull_request_form');
142 var $pullRequestForm = $('#pull_request_form');
145 var $sourceRepo = $('#source_repo', $pullRequestForm);
143 var $sourceRepo = $('#source_repo', $pullRequestForm);
146 var $targetRepo = $('#target_repo', $pullRequestForm);
144 var $targetRepo = $('#target_repo', $pullRequestForm);
147 var $sourceRef = $('#source_ref', $pullRequestForm);
145 var $sourceRef = $('#source_ref', $pullRequestForm);
148 var $targetRef = $('#target_ref', $pullRequestForm);
146 var $targetRef = $('#target_ref', $pullRequestForm);
149
147
150 var calculateContainerWidth = function() {
148 var calculateContainerWidth = function() {
151 var maxWidth = 0;
149 var maxWidth = 0;
152 var repoSelect2Containers = ['#source_repo', '#target_repo'];
150 var repoSelect2Containers = ['#source_repo', '#target_repo'];
153 $.each(repoSelect2Containers, function(idx, value) {
151 $.each(repoSelect2Containers, function(idx, value) {
154 $(value).select2('container').width('auto');
152 $(value).select2('container').width('auto');
155 var curWidth = $(value).select2('container').width();
153 var curWidth = $(value).select2('container').width();
156 if (maxWidth <= curWidth) {
154 if (maxWidth <= curWidth) {
157 maxWidth = curWidth;
155 maxWidth = curWidth;
158 }
156 }
159 $.each(repoSelect2Containers, function(idx, value) {
157 $.each(repoSelect2Containers, function(idx, value) {
160 $(value).select2('container').width(maxWidth + 10);
158 $(value).select2('container').width(maxWidth + 10);
161 });
159 });
162 });
160 });
163 };
161 };
164
162
165 var initRefSelection = function(selectedRef) {
163 var initRefSelection = function(selectedRef) {
166 return function(element, callback) {
164 return function(element, callback) {
167 // translate our select2 id into a text, it's a mapping to show
165 // translate our select2 id into a text, it's a mapping to show
168 // simple label when selecting by internal ID.
166 // simple label when selecting by internal ID.
169 var id, refData;
167 var id, refData;
170 if (selectedRef === undefined) {
168 if (selectedRef === undefined) {
171 id = element.val();
169 id = element.val();
172 refData = element.val().split(':');
170 refData = element.val().split(':');
173 } else {
171 } else {
174 id = selectedRef;
172 id = selectedRef;
175 refData = selectedRef.split(':');
173 refData = selectedRef.split(':');
176 }
174 }
177
175
178 var text = refData[1];
176 var text = refData[1];
179 if (refData[0] === 'rev') {
177 if (refData[0] === 'rev') {
180 text = text.substring(0, 12);
178 text = text.substring(0, 12);
181 }
179 }
182
180
183 var data = {id: id, text: text};
181 var data = {id: id, text: text};
184
182
185 callback(data);
183 callback(data);
186 };
184 };
187 };
185 };
188
186
189 var formatRefSelection = function(item) {
187 var formatRefSelection = function(item) {
190 var prefix = '';
188 var prefix = '';
191 var refData = item.id.split(':');
189 var refData = item.id.split(':');
192 if (refData[0] === 'branch') {
190 if (refData[0] === 'branch') {
193 prefix = '<i class="icon-branch"></i>';
191 prefix = '<i class="icon-branch"></i>';
194 }
192 }
195 else if (refData[0] === 'book') {
193 else if (refData[0] === 'book') {
196 prefix = '<i class="icon-bookmark"></i>';
194 prefix = '<i class="icon-bookmark"></i>';
197 }
195 }
198 else if (refData[0] === 'tag') {
196 else if (refData[0] === 'tag') {
199 prefix = '<i class="icon-tag"></i>';
197 prefix = '<i class="icon-tag"></i>';
200 }
198 }
201
199
202 var originalOption = item.element;
200 var originalOption = item.element;
203 return prefix + item.text;
201 return prefix + item.text;
204 };
202 };
205
203
206 // custom code mirror
204 // custom code mirror
207 var codeMirrorInstance = initPullRequestsCodeMirror('#pullrequest_desc');
205 var codeMirrorInstance = initPullRequestsCodeMirror('#pullrequest_desc');
208
206
209 var queryTargetRepo = function(self, query) {
207 var queryTargetRepo = function(self, query) {
210 // cache ALL results if query is empty
208 // cache ALL results if query is empty
211 var cacheKey = query.term || '__';
209 var cacheKey = query.term || '__';
212 var cachedData = self.cachedDataSource[cacheKey];
210 var cachedData = self.cachedDataSource[cacheKey];
213
211
214 if (cachedData) {
212 if (cachedData) {
215 query.callback({results: cachedData.results});
213 query.callback({results: cachedData.results});
216 } else {
214 } else {
217 $.ajax({
215 $.ajax({
218 url: pyroutes.url('pullrequest_repo_destinations', {'repo_name': targetRepoName}),
216 url: pyroutes.url('pullrequest_repo_destinations', {'repo_name': targetRepoName}),
219 data: {query: query.term},
217 data: {query: query.term},
220 dataType: 'json',
218 dataType: 'json',
221 type: 'GET',
219 type: 'GET',
222 success: function(data) {
220 success: function(data) {
223 self.cachedDataSource[cacheKey] = data;
221 self.cachedDataSource[cacheKey] = data;
224 query.callback({results: data.results});
222 query.callback({results: data.results});
225 },
223 },
226 error: function(data, textStatus, errorThrown) {
224 error: function(data, textStatus, errorThrown) {
227 alert(
225 alert(
228 "Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
226 "Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
229 }
227 }
230 });
228 });
231 }
229 }
232 };
230 };
233
231
234 var queryTargetRefs = function(initialData, query) {
232 var queryTargetRefs = function(initialData, query) {
235 var data = {results: []};
233 var data = {results: []};
236 // filter initialData
234 // filter initialData
237 $.each(initialData, function() {
235 $.each(initialData, function() {
238 var section = this.text;
236 var section = this.text;
239 var children = [];
237 var children = [];
240 $.each(this.children, function() {
238 $.each(this.children, function() {
241 if (query.term.length === 0 ||
239 if (query.term.length === 0 ||
242 this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ) {
240 this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ) {
243 children.push({'id': this.id, 'text': this.text})
241 children.push({'id': this.id, 'text': this.text})
244 }
242 }
245 });
243 });
246 data.results.push({'text': section, 'children': children})
244 data.results.push({'text': section, 'children': children})
247 });
245 });
248 query.callback({results: data.results});
246 query.callback({results: data.results});
249 };
247 };
250
248
251
249
252 var prButtonLockChecks = {
250 var prButtonLockChecks = {
253 'compare': false,
251 'compare': false,
254 'reviewers': false
252 'reviewers': false
255 };
253 };
256
254
257 var prButtonLock = function(lockEnabled, msg, scope) {
255 var prButtonLock = function(lockEnabled, msg, scope) {
258 scope = scope || 'all';
256 scope = scope || 'all';
259 if (scope == 'all'){
257 if (scope == 'all'){
260 prButtonLockChecks['compare'] = !lockEnabled;
258 prButtonLockChecks['compare'] = !lockEnabled;
261 prButtonLockChecks['reviewers'] = !lockEnabled;
259 prButtonLockChecks['reviewers'] = !lockEnabled;
262 } else if (scope == 'compare') {
260 } else if (scope == 'compare') {
263 prButtonLockChecks['compare'] = !lockEnabled;
261 prButtonLockChecks['compare'] = !lockEnabled;
264 } else if (scope == 'reviewers'){
262 } else if (scope == 'reviewers'){
265 prButtonLockChecks['reviewers'] = !lockEnabled;
263 prButtonLockChecks['reviewers'] = !lockEnabled;
266 }
264 }
267 var checksMeet = prButtonLockChecks.compare && prButtonLockChecks.reviewers;
265 var checksMeet = prButtonLockChecks.compare && prButtonLockChecks.reviewers;
268 if (lockEnabled) {
266 if (lockEnabled) {
269 $('#save').attr('disabled', 'disabled');
267 $('#save').attr('disabled', 'disabled');
270 }
268 }
271 else if (checksMeet) {
269 else if (checksMeet) {
272 $('#save').removeAttr('disabled');
270 $('#save').removeAttr('disabled');
273 }
271 }
274
272
275 if (msg) {
273 if (msg) {
276 $('#pr_open_message').html(msg);
274 $('#pr_open_message').html(msg);
277 }
275 }
278 };
276 };
279
277
280 var loadRepoRefDiffPreview = function() {
278 var loadRepoRefDiffPreview = function() {
281 var sourceRepo = $sourceRepo.eq(0).val();
279 var sourceRepo = $sourceRepo.eq(0).val();
282 var sourceRef = $sourceRef.eq(0).val().split(':');
280 var sourceRef = $sourceRef.eq(0).val().split(':');
283
281
284 var targetRepo = $targetRepo.eq(0).val();
282 var targetRepo = $targetRepo.eq(0).val();
285 var targetRef = $targetRef.eq(0).val().split(':');
283 var targetRef = $targetRef.eq(0).val().split(':');
286
284
287 var url_data = {
285 var url_data = {
288 'repo_name': targetRepo,
286 'repo_name': targetRepo,
289 'target_repo': sourceRepo,
287 'target_repo': sourceRepo,
290 'source_ref': targetRef[2],
288 'source_ref': targetRef[2],
291 'source_ref_type': 'rev',
289 'source_ref_type': 'rev',
292 'target_ref': sourceRef[2],
290 'target_ref': sourceRef[2],
293 'target_ref_type': 'rev',
291 'target_ref_type': 'rev',
294 'merge': true,
292 'merge': true,
295 '_': Date.now() // bypass browser caching
293 '_': Date.now() // bypass browser caching
296 }; // gather the source/target ref and repo here
294 }; // gather the source/target ref and repo here
297
295
298 if (sourceRef.length !== 3 || targetRef.length !== 3) {
296 if (sourceRef.length !== 3 || targetRef.length !== 3) {
299 prButtonLock(true, "${_('Please select origin and destination')}");
297 prButtonLock(true, "${_('Please select origin and destination')}");
300 return;
298 return;
301 }
299 }
302 var url = pyroutes.url('compare_url', url_data);
300 var url = pyroutes.url('compare_url', url_data);
303
301
304 // lock PR button, so we cannot send PR before it's calculated
302 // lock PR button, so we cannot send PR before it's calculated
305 prButtonLock(true, "${_('Loading compare ...')}", 'compare');
303 prButtonLock(true, "${_('Loading compare ...')}", 'compare');
306
304
307 if (loadRepoRefDiffPreview._currentRequest) {
305 if (loadRepoRefDiffPreview._currentRequest) {
308 loadRepoRefDiffPreview._currentRequest.abort();
306 loadRepoRefDiffPreview._currentRequest.abort();
309 }
307 }
310
308
311 loadRepoRefDiffPreview._currentRequest = $.get(url)
309 loadRepoRefDiffPreview._currentRequest = $.get(url)
312 .error(function(data, textStatus, errorThrown) {
310 .error(function(data, textStatus, errorThrown) {
313 alert(
311 alert(
314 "Error while processing request.\nError code {0} ({1}).".format(
312 "Error while processing request.\nError code {0} ({1}).".format(
315 data.status, data.statusText));
313 data.status, data.statusText));
316 })
314 })
317 .done(function(data) {
315 .done(function(data) {
318 loadRepoRefDiffPreview._currentRequest = null;
316 loadRepoRefDiffPreview._currentRequest = null;
319 $('#pull_request_overview').html(data);
317 $('#pull_request_overview').html(data);
320 var commitElements = $(data).find('tr[commit_id]');
318 var commitElements = $(data).find('tr[commit_id]');
321
319
322 var prTitleAndDesc = getTitleAndDescription(sourceRef[1],
320 var prTitleAndDesc = getTitleAndDescription(sourceRef[1],
323 commitElements, 5);
321 commitElements, 5);
324
322
325 var title = prTitleAndDesc[0];
323 var title = prTitleAndDesc[0];
326 var proposedDescription = prTitleAndDesc[1];
324 var proposedDescription = prTitleAndDesc[1];
327
325
328 var useGeneratedTitle = (
326 var useGeneratedTitle = (
329 $('#pullrequest_title').hasClass('autogenerated-title') ||
327 $('#pullrequest_title').hasClass('autogenerated-title') ||
330 $('#pullrequest_title').val() === "");
328 $('#pullrequest_title').val() === "");
331
329
332 if (title && useGeneratedTitle) {
330 if (title && useGeneratedTitle) {
333 // use generated title if we haven't specified our own
331 // use generated title if we haven't specified our own
334 $('#pullrequest_title').val(title);
332 $('#pullrequest_title').val(title);
335 $('#pullrequest_title').addClass('autogenerated-title');
333 $('#pullrequest_title').addClass('autogenerated-title');
336
334
337 }
335 }
338
336
339 var useGeneratedDescription = (
337 var useGeneratedDescription = (
340 !codeMirrorInstance._userDefinedDesc ||
338 !codeMirrorInstance._userDefinedDesc ||
341 codeMirrorInstance.getValue() === "");
339 codeMirrorInstance.getValue() === "");
342
340
343 if (proposedDescription && useGeneratedDescription) {
341 if (proposedDescription && useGeneratedDescription) {
344 // set proposed content, if we haven't defined our own,
342 // set proposed content, if we haven't defined our own,
345 // or we don't have description written
343 // or we don't have description written
346 codeMirrorInstance._userDefinedDesc = false; // reset state
344 codeMirrorInstance._userDefinedDesc = false; // reset state
347 codeMirrorInstance.setValue(proposedDescription);
345 codeMirrorInstance.setValue(proposedDescription);
348 }
346 }
349
347
350 var msg = '';
348 var msg = '';
351 if (commitElements.length === 1) {
349 if (commitElements.length === 1) {
352 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 1)}";
350 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 1)}";
353 } else {
351 } else {
354 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 2)}";
352 msg = "${ungettext('This pull request will consist of __COMMITS__ commit.', 'This pull request will consist of __COMMITS__ commits.', 2)}";
355 }
353 }
356
354
357 msg += ' <a id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url);
355 msg += ' <a id="pull_request_overview_url" href="{0}" target="_blank">${_('Show detailed compare.')}</a>'.format(url);
358
356
359 if (commitElements.length) {
357 if (commitElements.length) {
360 var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length);
358 var commitsLink = '<a href="#pull_request_overview"><strong>{0}</strong></a>'.format(commitElements.length);
361 prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare');
359 prButtonLock(false, msg.replace('__COMMITS__', commitsLink), 'compare');
362 }
360 }
363 else {
361 else {
364 prButtonLock(true, "${_('There are no commits to merge.')}", 'compare');
362 prButtonLock(true, "${_('There are no commits to merge.')}", 'compare');
365 }
363 }
366
364
367
365
368 });
366 });
369 };
367 };
370
368
371 /**
369 /**
372 Generate Title and Description for a PullRequest.
370 Generate Title and Description for a PullRequest.
373 In case of 1 commits, the title and description is that one commit
371 In case of 1 commits, the title and description is that one commit
374 in case of multiple commits, we iterate on them with max N number of commits,
372 in case of multiple commits, we iterate on them with max N number of commits,
375 and build description in a form
373 and build description in a form
376 - commitN
374 - commitN
377 - commitN+1
375 - commitN+1
378 ...
376 ...
379
377
380 Title is then constructed from branch names, or other references,
378 Title is then constructed from branch names, or other references,
381 replacing '-' and '_' into spaces
379 replacing '-' and '_' into spaces
382
380
383 * @param sourceRef
381 * @param sourceRef
384 * @param elements
382 * @param elements
385 * @param limit
383 * @param limit
386 * @returns {*[]}
384 * @returns {*[]}
387 */
385 */
388 var getTitleAndDescription = function(sourceRef, elements, limit) {
386 var getTitleAndDescription = function(sourceRef, elements, limit) {
389 var title = '';
387 var title = '';
390 var desc = '';
388 var desc = '';
391
389
392 $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
390 $.each($(elements).get().reverse().slice(0, limit), function(idx, value) {
393 var rawMessage = $(value).find('td.td-description .message').data('messageRaw');
391 var rawMessage = $(value).find('td.td-description .message').data('messageRaw');
394 desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
392 desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n';
395 });
393 });
396 // only 1 commit, use commit message as title
394 // only 1 commit, use commit message as title
397 if (elements.length == 1) {
395 if (elements.length == 1) {
398 title = $(elements[0]).find('td.td-description .message').data('messageRaw').split('\n')[0];
396 title = $(elements[0]).find('td.td-description .message').data('messageRaw').split('\n')[0];
399 }
397 }
400 else {
398 else {
401 // use reference name
399 // use reference name
402 title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
400 title = sourceRef.replace(/-/g, ' ').replace(/_/g, ' ').capitalizeFirstLetter();
403 }
401 }
404
402
405 return [title, desc]
403 return [title, desc]
406 };
404 };
407
405
408 var Select2Box = function(element, overrides) {
406 var Select2Box = function(element, overrides) {
409 var globalDefaults = {
407 var globalDefaults = {
410 dropdownAutoWidth: true,
408 dropdownAutoWidth: true,
411 containerCssClass: "drop-menu",
409 containerCssClass: "drop-menu",
412 dropdownCssClass: "drop-menu-dropdown"
410 dropdownCssClass: "drop-menu-dropdown"
413 };
411 };
414
412
415 var initSelect2 = function(defaultOptions) {
413 var initSelect2 = function(defaultOptions) {
416 var options = jQuery.extend(globalDefaults, defaultOptions, overrides);
414 var options = jQuery.extend(globalDefaults, defaultOptions, overrides);
417 element.select2(options);
415 element.select2(options);
418 };
416 };
419
417
420 return {
418 return {
421 initRef: function() {
419 initRef: function() {
422 var defaultOptions = {
420 var defaultOptions = {
423 minimumResultsForSearch: 5,
421 minimumResultsForSearch: 5,
424 formatSelection: formatRefSelection
422 formatSelection: formatRefSelection
425 };
423 };
426
424
427 initSelect2(defaultOptions);
425 initSelect2(defaultOptions);
428 },
426 },
429
427
430 initRepo: function(defaultValue, readOnly) {
428 initRepo: function(defaultValue, readOnly) {
431 var defaultOptions = {
429 var defaultOptions = {
432 initSelection : function (element, callback) {
430 initSelection : function (element, callback) {
433 var data = {id: defaultValue, text: defaultValue};
431 var data = {id: defaultValue, text: defaultValue};
434 callback(data);
432 callback(data);
435 }
433 }
436 };
434 };
437
435
438 initSelect2(defaultOptions);
436 initSelect2(defaultOptions);
439
437
440 element.select2('val', defaultSourceRepo);
438 element.select2('val', defaultSourceRepo);
441 if (readOnly === true) {
439 if (readOnly === true) {
442 element.select2('readonly', true);
440 element.select2('readonly', true);
443 }
441 }
444 }
442 }
445 };
443 };
446 };
444 };
447
445
448 var initTargetRefs = function(refsData, selectedRef){
446 var initTargetRefs = function(refsData, selectedRef){
449 Select2Box($targetRef, {
447 Select2Box($targetRef, {
450 query: function(query) {
448 query: function(query) {
451 queryTargetRefs(refsData, query);
449 queryTargetRefs(refsData, query);
452 },
450 },
453 initSelection : initRefSelection(selectedRef)
451 initSelection : initRefSelection(selectedRef)
454 }).initRef();
452 }).initRef();
455
453
456 if (!(selectedRef === undefined)) {
454 if (!(selectedRef === undefined)) {
457 $targetRef.select2('val', selectedRef);
455 $targetRef.select2('val', selectedRef);
458 }
456 }
459 };
457 };
460
458
461 var targetRepoChanged = function(repoData) {
459 var targetRepoChanged = function(repoData) {
462 // generate new DESC of target repo displayed next to select
460 // generate new DESC of target repo displayed next to select
463 $('#target_repo_desc').html(
461 $('#target_repo_desc').html(
464 "<strong>${_('Destination repository')}</strong>: {0}".format(repoData['description'])
462 "<strong>${_('Destination repository')}</strong>: {0}".format(repoData['description'])
465 );
463 );
466
464
467 // generate dynamic select2 for refs.
465 // generate dynamic select2 for refs.
468 initTargetRefs(repoData['refs']['select2_refs'],
466 initTargetRefs(repoData['refs']['select2_refs'],
469 repoData['refs']['selected_ref']);
467 repoData['refs']['selected_ref']);
470
468
471 };
469 };
472
470
473 var sourceRefSelect2 = Select2Box(
471 var sourceRefSelect2 = Select2Box(
474 $sourceRef, {
472 $sourceRef, {
475 placeholder: "${_('Select commit reference')}",
473 placeholder: "${_('Select commit reference')}",
476 query: function(query) {
474 query: function(query) {
477 var initialData = defaultSourceRepoData['refs']['select2_refs'];
475 var initialData = defaultSourceRepoData['refs']['select2_refs'];
478 queryTargetRefs(initialData, query)
476 queryTargetRefs(initialData, query)
479 },
477 },
480 initSelection: initRefSelection()
478 initSelection: initRefSelection()
481 }
479 }
482 );
480 );
483
481
484 var sourceRepoSelect2 = Select2Box($sourceRepo, {
482 var sourceRepoSelect2 = Select2Box($sourceRepo, {
485 query: function(query) {}
483 query: function(query) {}
486 });
484 });
487
485
488 var targetRepoSelect2 = Select2Box($targetRepo, {
486 var targetRepoSelect2 = Select2Box($targetRepo, {
489 cachedDataSource: {},
487 cachedDataSource: {},
490 query: $.debounce(250, function(query) {
488 query: $.debounce(250, function(query) {
491 queryTargetRepo(this, query);
489 queryTargetRepo(this, query);
492 }),
490 }),
493 formatResult: formatResult
491 formatResult: formatResult
494 });
492 });
495
493
496 sourceRefSelect2.initRef();
494 sourceRefSelect2.initRef();
497
495
498 sourceRepoSelect2.initRepo(defaultSourceRepo, true);
496 sourceRepoSelect2.initRepo(defaultSourceRepo, true);
499
497
500 targetRepoSelect2.initRepo(defaultTargetRepo, false);
498 targetRepoSelect2.initRepo(defaultTargetRepo, false);
501
499
502 $sourceRef.on('change', function(e){
500 $sourceRef.on('change', function(e){
503 loadRepoRefDiffPreview();
501 loadRepoRefDiffPreview();
504 loadDefaultReviewers();
502 loadDefaultReviewers();
505 });
503 });
506
504
507 $targetRef.on('change', function(e){
505 $targetRef.on('change', function(e){
508 loadRepoRefDiffPreview();
506 loadRepoRefDiffPreview();
509 loadDefaultReviewers();
507 loadDefaultReviewers();
510 });
508 });
511
509
512 $targetRepo.on('change', function(e){
510 $targetRepo.on('change', function(e){
513 var repoName = $(this).val();
511 var repoName = $(this).val();
514 calculateContainerWidth();
512 calculateContainerWidth();
515 $targetRef.select2('destroy');
513 $targetRef.select2('destroy');
516 $('#target_ref_loading').show();
514 $('#target_ref_loading').show();
517
515
518 $.ajax({
516 $.ajax({
519 url: pyroutes.url('pullrequest_repo_refs',
517 url: pyroutes.url('pullrequest_repo_refs',
520 {'repo_name': targetRepoName, 'target_repo_name':repoName}),
518 {'repo_name': targetRepoName, 'target_repo_name':repoName}),
521 data: {},
519 data: {},
522 dataType: 'json',
520 dataType: 'json',
523 type: 'GET',
521 type: 'GET',
524 success: function(data) {
522 success: function(data) {
525 $('#target_ref_loading').hide();
523 $('#target_ref_loading').hide();
526 targetRepoChanged(data);
524 targetRepoChanged(data);
527 loadRepoRefDiffPreview();
525 loadRepoRefDiffPreview();
528 },
526 },
529 error: function(data, textStatus, errorThrown) {
527 error: function(data, textStatus, errorThrown) {
530 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
528 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
531 }
529 }
532 })
530 })
533
531
534 });
532 });
535
533
536 var loadDefaultReviewers = function() {
534 var loadDefaultReviewers = function() {
537 if (loadDefaultReviewers._currentRequest) {
535 if (loadDefaultReviewers._currentRequest) {
538 loadDefaultReviewers._currentRequest.abort();
536 loadDefaultReviewers._currentRequest.abort();
539 }
537 }
540 $('.calculate-reviewers').show();
538 $('.calculate-reviewers').show();
541 prButtonLock(true, null, 'reviewers');
539 prButtonLock(true, null, 'reviewers');
542
540
543 var url = pyroutes.url('repo_default_reviewers_data', {'repo_name': targetRepoName});
541 var url = pyroutes.url('repo_default_reviewers_data', {'repo_name': targetRepoName});
544
542
545 var sourceRepo = $sourceRepo.eq(0).val();
543 var sourceRepo = $sourceRepo.eq(0).val();
546 var sourceRef = $sourceRef.eq(0).val().split(':');
544 var sourceRef = $sourceRef.eq(0).val().split(':');
547 var targetRepo = $targetRepo.eq(0).val();
545 var targetRepo = $targetRepo.eq(0).val();
548 var targetRef = $targetRef.eq(0).val().split(':');
546 var targetRef = $targetRef.eq(0).val().split(':');
549 url += '?source_repo=' + sourceRepo;
547 url += '?source_repo=' + sourceRepo;
550 url += '&source_ref=' + sourceRef[2];
548 url += '&source_ref=' + sourceRef[2];
551 url += '&target_repo=' + targetRepo;
549 url += '&target_repo=' + targetRepo;
552 url += '&target_ref=' + targetRef[2];
550 url += '&target_ref=' + targetRef[2];
553
551
554 loadDefaultReviewers._currentRequest = $.get(url)
552 loadDefaultReviewers._currentRequest = $.get(url)
555 .done(function(data) {
553 .done(function(data) {
556 loadDefaultReviewers._currentRequest = null;
554 loadDefaultReviewers._currentRequest = null;
557
555
558 // reset && add the reviewer based on selected repo
556 // reset && add the reviewer based on selected repo
559 $('#review_members').html('');
557 $('#review_members').html('');
560 for (var i = 0; i < data.reviewers.length; i++) {
558 for (var i = 0; i < data.reviewers.length; i++) {
561 var reviewer = data.reviewers[i];
559 var reviewer = data.reviewers[i];
562 addReviewMember(
560 addReviewMember(
563 reviewer.user_id, reviewer.firstname,
561 reviewer.user_id, reviewer.firstname,
564 reviewer.lastname, reviewer.username,
562 reviewer.lastname, reviewer.username,
565 reviewer.gravatar_link, reviewer.reasons);
563 reviewer.gravatar_link, reviewer.reasons);
566 }
564 }
567 $('.calculate-reviewers').hide();
565 $('.calculate-reviewers').hide();
568 prButtonLock(false, null, 'reviewers');
566 prButtonLock(false, null, 'reviewers');
569 });
567 });
570 };
568 };
571
569
572 prButtonLock(true, "${_('Please select origin and destination')}", 'all');
570 prButtonLock(true, "${_('Please select origin and destination')}", 'all');
573
571
574 // auto-load on init, the target refs select2
572 // auto-load on init, the target refs select2
575 calculateContainerWidth();
573 calculateContainerWidth();
576 targetRepoChanged(defaultTargetRepoData);
574 targetRepoChanged(defaultTargetRepoData);
577
575
578 $('#pullrequest_title').on('keyup', function(e){
576 $('#pullrequest_title').on('keyup', function(e){
579 $(this).removeClass('autogenerated-title');
577 $(this).removeClass('autogenerated-title');
580 });
578 });
581
579
582 % if c.default_source_ref:
580 % if c.default_source_ref:
583 // in case we have a pre-selected value, use it now
581 // in case we have a pre-selected value, use it now
584 $sourceRef.select2('val', '${c.default_source_ref}');
582 $sourceRef.select2('val', '${c.default_source_ref}');
585 loadRepoRefDiffPreview();
583 loadRepoRefDiffPreview();
586 loadDefaultReviewers();
584 loadDefaultReviewers();
587 % endif
585 % endif
588
586
589 ReviewerAutoComplete('user');
587 ReviewerAutoComplete('user');
590 });
588 });
591 </script>
589 </script>
592
590
593 </%def>
591 </%def>
General Comments 0
You need to be logged in to leave comments. Login now