Show More
@@ -0,0 +1,91 b'' | |||
|
1 | .deform { | |
|
2 | ||
|
3 | * { | |
|
4 | box-sizing: border-box; | |
|
5 | } | |
|
6 | ||
|
7 | .required:after { | |
|
8 | color: #e32; | |
|
9 | content: '*'; | |
|
10 | display:inline; | |
|
11 | } | |
|
12 | ||
|
13 | .control-label { | |
|
14 | width: 200px; | |
|
15 | float: left; | |
|
16 | } | |
|
17 | .control-inputs { | |
|
18 | width: 400px; | |
|
19 | float: left; | |
|
20 | } | |
|
21 | .form-group .radio, .form-group .checkbox { | |
|
22 | position: relative; | |
|
23 | display: block; | |
|
24 | /* margin-bottom: 10px; */ | |
|
25 | } | |
|
26 | ||
|
27 | .form-group { | |
|
28 | clear: left; | |
|
29 | } | |
|
30 | ||
|
31 | .form-control { | |
|
32 | width: 100%; | |
|
33 | } | |
|
34 | ||
|
35 | .error-block { | |
|
36 | color: red; | |
|
37 | } | |
|
38 | ||
|
39 | .deform-seq-container .control-inputs { | |
|
40 | width: 100%; | |
|
41 | } | |
|
42 | ||
|
43 | .deform-seq-container .deform-seq-item-handle { | |
|
44 | width: 8.3%; | |
|
45 | float: left; | |
|
46 | } | |
|
47 | ||
|
48 | .deform-seq-container .deform-seq-item-group { | |
|
49 | width: 91.6%; | |
|
50 | float: left; | |
|
51 | } | |
|
52 | ||
|
53 | .form-control { | |
|
54 | input { | |
|
55 | height: 40px; | |
|
56 | } | |
|
57 | input[type=checkbox], input[type=radio] { | |
|
58 | height: auto; | |
|
59 | } | |
|
60 | select { | |
|
61 | height: 40px; | |
|
62 | } | |
|
63 | } | |
|
64 | ||
|
65 | .form-control.select2-container { height: 40px; } | |
|
66 | ||
|
67 | .deform-two-field-sequence .deform-seq-container .deform-seq-item label { | |
|
68 | display: none; | |
|
69 | } | |
|
70 | .deform-two-field-sequence .deform-seq-container .deform-seq-item:first-child label { | |
|
71 | display: block; | |
|
72 | } | |
|
73 | .deform-two-field-sequence .deform-seq-container .deform-seq-item .panel-heading { | |
|
74 | display: none; | |
|
75 | } | |
|
76 | .deform-two-field-sequence .deform-seq-container .deform-seq-item.form-group { | |
|
77 | background: red; | |
|
78 | } | |
|
79 | .deform-two-field-sequence .deform-seq-container .deform-seq-item .deform-seq-item-group .form-group { | |
|
80 | width: 45%; padding: 0 2px; float: left; clear: none; | |
|
81 | } | |
|
82 | .deform-two-field-sequence .deform-seq-container .deform-seq-item .deform-seq-item-group > .panel { | |
|
83 | padding: 0; | |
|
84 | margin: 5px 0; | |
|
85 | border: none; | |
|
86 | } | |
|
87 | .deform-two-field-sequence .deform-seq-container .deform-seq-item .deform-seq-item-group > .panel > .panel-body { | |
|
88 | padding: 0; | |
|
89 | } | |
|
90 | ||
|
91 | } |
@@ -0,0 +1,20 b'' | |||
|
1 | <div class="checkbox"> | |
|
2 | <input tal:define="name name|field.name; | |
|
3 | true_val true_val|field.widget.true_val; | |
|
4 | css_class css_class|field.widget.css_class; | |
|
5 | style style|field.widget.style; | |
|
6 | oid oid|field.oid" | |
|
7 | type="checkbox" | |
|
8 | name="${name}" value="${true_val}" | |
|
9 | id="${oid}" | |
|
10 | tal:attributes="checked cstruct == true_val; | |
|
11 | class css_class; | |
|
12 | style style;" /> | |
|
13 | ||
|
14 | <label for="${field.oid}"> | |
|
15 | <span tal:condition="hasattr(field, 'schema') and hasattr(field.schema, 'label')" | |
|
16 | tal:replace="field.schema.label" class="checkbox-label" > | |
|
17 | </span> | |
|
18 | ||
|
19 | </label> | |
|
20 | </div> No newline at end of file |
@@ -0,0 +1,25 b'' | |||
|
1 | <div tal:define="css_class css_class|field.widget.css_class; | |
|
2 | style style|field.widget.style; | |
|
3 | oid oid|field.oid; | |
|
4 | inline getattr(field.widget, 'inline', False)" | |
|
5 | tal:omit-tag="not inline"> | |
|
6 | ${field.start_sequence()} | |
|
7 | <div tal:repeat="choice values | field.widget.values" | |
|
8 | tal:omit-tag="inline" | |
|
9 | class="checkbox"> | |
|
10 | <div tal:define="(value, title) choice"> | |
|
11 | <input tal:attributes="checked value in cstruct; | |
|
12 | class css_class; | |
|
13 | style style" | |
|
14 | type="checkbox" | |
|
15 | name="checkbox" | |
|
16 | value="${value}" | |
|
17 | id="${oid}-${repeat.choice.index}"/> | |
|
18 | <label for="${oid}-${repeat.choice.index}" | |
|
19 | tal:attributes="class inline and 'checkbox-inline'"> | |
|
20 | ${title} | |
|
21 | </label> | |
|
22 | </div> | |
|
23 | </div> | |
|
24 | ${field.end_sequence()} | |
|
25 | </div> No newline at end of file |
@@ -0,0 +1,100 b'' | |||
|
1 | <form | |
|
2 | tal:define="style style|field.widget.style; | |
|
3 | css_class css_class|string:${field.widget.css_class or field.css_class or ''}; | |
|
4 | item_template item_template|field.widget.item_template; | |
|
5 | autocomplete autocomplete|field.autocomplete; | |
|
6 | title title|field.title; | |
|
7 | errormsg errormsg|field.errormsg; | |
|
8 | description description|field.description; | |
|
9 | buttons buttons|field.buttons; | |
|
10 | use_ajax use_ajax|field.use_ajax; | |
|
11 | ajax_options ajax_options|field.ajax_options; | |
|
12 | formid formid|field.formid; | |
|
13 | action action|field.action or None; | |
|
14 | method method|field.method;" | |
|
15 | tal:attributes="autocomplete autocomplete; | |
|
16 | style style; | |
|
17 | class css_class; | |
|
18 | action action;" | |
|
19 | id="${formid}" | |
|
20 | method="${method}" | |
|
21 | enctype="multipart/form-data" | |
|
22 | accept-charset="utf-8" | |
|
23 | i18n:domain="deform" | |
|
24 | > | |
|
25 | ||
|
26 | <fieldset class="deform-form-fieldset"> | |
|
27 | ||
|
28 | <legend tal:condition="title">${title}</legend> | |
|
29 | ||
|
30 | <input type="hidden" name="${h.csrf_token_key}" value="${h.get_csrf_token()}" /> | |
|
31 | <input type="hidden" name="_charset_" /> | |
|
32 | <input type="hidden" name="__formid__" value="${formid}"/> | |
|
33 | ||
|
34 | <!-- | |
|
35 | <div class="alert alert-danger" tal:condition="field.error"> | |
|
36 | <div class="error-msg-lbl" i18n:translate="" | |
|
37 | >There was a problem with your submission</div> | |
|
38 | <div class="error-msg-detail" i18n:translate="" | |
|
39 | >Errors have been highlighted below</div> | |
|
40 | <p class="error-msg">${field.errormsg}</p> | |
|
41 | </div> | |
|
42 | --> | |
|
43 | ||
|
44 | <p class="section first" tal:condition="description"> | |
|
45 | ${description} | |
|
46 | </p> | |
|
47 | ||
|
48 | <div tal:repeat="child field" | |
|
49 | tal:replace="structure child.render_template(item_template)"/> | |
|
50 | ||
|
51 | <div class="form-group"> | |
|
52 | <tal:loop tal:repeat="button buttons"> | |
|
53 | <button | |
|
54 | tal:define="btn_disposition repeat.button.start and 'btn-primary' or (button.name == 'delete' and 'btn-danger' or 'btn-default'); | |
|
55 | btn_icon button.icon|None" | |
|
56 | tal:attributes="disabled button.disabled if button.disabled else None" | |
|
57 | id="${formid+button.name}" | |
|
58 | name="${button.name}" | |
|
59 | type="${button.type}" | |
|
60 | class="btn ${button.css_class or btn_disposition}" | |
|
61 | value="${button.value}"> | |
|
62 | <i tal:condition="btn_icon" class="${btn_icon}"> </i> | |
|
63 | ${button.title} | |
|
64 | </button> | |
|
65 | </tal:loop> | |
|
66 | </div> | |
|
67 | ||
|
68 | </fieldset> | |
|
69 | ||
|
70 | <script type="text/javascript" tal:condition="use_ajax"> | |
|
71 | deform.addCallback( | |
|
72 | '${formid}', | |
|
73 | function(oid) { | |
|
74 | var target = '#' + oid; | |
|
75 | var options = { | |
|
76 | target: target, | |
|
77 | replaceTarget: true, | |
|
78 | success: function() { | |
|
79 | deform.processCallbacks(); | |
|
80 | deform.focusFirstInput(target); | |
|
81 | }, | |
|
82 | beforeSerialize: function() { | |
|
83 | // See http://bit.ly/1agBs9Z (hack to fix tinymce-related ajax bug) | |
|
84 | if ('tinymce' in window) { | |
|
85 | $(tinymce.get()).each( | |
|
86 | function(i, el) { | |
|
87 | var content = el.getContent(); | |
|
88 | var editor_input = document.getElementById(el.id); | |
|
89 | editor_input.value = content; | |
|
90 | }); | |
|
91 | } | |
|
92 | } | |
|
93 | }; | |
|
94 | var extra_options = ${ajax_options} || {}; | |
|
95 | $('#' + oid).ajaxForm($.extend(options, extra_options)); | |
|
96 | } | |
|
97 | ); | |
|
98 | </script> | |
|
99 | ||
|
100 | </form> No newline at end of file |
@@ -0,0 +1,33 b'' | |||
|
1 | <tal:def tal:define="title title|field.title; | |
|
2 | description description|field.description; | |
|
3 | errormsg errormsg|field.errormsg; | |
|
4 | item_template item_template|field.widget.item_template" | |
|
5 | i18n:domain="deform"> | |
|
6 | ||
|
7 | <div class="panel panel-default"> | |
|
8 | <div class="panel-heading">${title}</div> | |
|
9 | <div class="panel-body"> | |
|
10 | ||
|
11 | <div tal:condition="errormsg" | |
|
12 | class="clearfix alert alert-danger"> | |
|
13 | <p i18n:translate=""> | |
|
14 | There was a problem with this section | |
|
15 | </p> | |
|
16 | <p>${errormsg}</p> | |
|
17 | </div> | |
|
18 | ||
|
19 | <div tal:condition="description"> | |
|
20 | ${description} | |
|
21 | </div> | |
|
22 | ||
|
23 | ${field.start_mapping()} | |
|
24 | <div tal:repeat="child field.children" | |
|
25 | tal:replace="structure child.render_template(item_template)" > | |
|
26 | </div> | |
|
27 | ${field.end_mapping()} | |
|
28 | ||
|
29 | <div style="clear: both"></div> | |
|
30 | </div> | |
|
31 | </div> | |
|
32 | ||
|
33 | </tal:def> No newline at end of file |
@@ -0,0 +1,47 b'' | |||
|
1 | <div tal:define="error_class error_class|field.widget.error_class; | |
|
2 | description description|field.description; | |
|
3 | title title|field.title; | |
|
4 | oid oid|field.oid; | |
|
5 | hidden hidden|field.widget.hidden; | |
|
6 | category category|field.widget.category; | |
|
7 | structural hidden or category == 'structural'; | |
|
8 | required required|field.required;" | |
|
9 | class="form-group ${field.error and 'has-error' or ''} ${field.widget.item_css_class or ''}" | |
|
10 | id="item-${oid}" | |
|
11 | tal:omit-tag="structural" | |
|
12 | i18n:domain="deform"> | |
|
13 | ||
|
14 | <label for="${oid}" | |
|
15 | class="control-label ${required and 'required' or ''}" | |
|
16 | tal:condition="not structural" | |
|
17 | id="req-${oid}" | |
|
18 | > | |
|
19 | ${title} | |
|
20 | </label> | |
|
21 | <div class="control-inputs"> | |
|
22 | <div tal:define="input_prepend field.widget.input_prepend | None; | |
|
23 | input_append field.widget.input_append | None" | |
|
24 | tal:omit-tag="not (input_prepend or input_append)" | |
|
25 | class="input-group"> | |
|
26 | <span class="input-group-addon" | |
|
27 | tal:condition="input_prepend">${input_prepend}</span | |
|
28 | ><span tal:replace="structure field.serialize(cstruct).strip()" | |
|
29 | /><span class="input-group-addon" | |
|
30 | tal:condition="input_append">${input_append}</span> | |
|
31 | </div> | |
|
32 | <p class="help-block error-block" | |
|
33 | tal:define="errstr 'error-%s' % field.oid" | |
|
34 | tal:repeat="msg field.error.messages()" | |
|
35 | i18n:translate="" | |
|
36 | tal:attributes="id repeat.msg.index==0 and errstr or | |
|
37 | ('%s-%s' % (errstr, repeat.msg.index))" | |
|
38 | tal:condition="field.error and not field.widget.hidden and not field.typ.__class__.__name__=='Mapping'"> | |
|
39 | ${msg} | |
|
40 | </p> | |
|
41 | ||
|
42 | <p tal:condition="field.description and not field.widget.hidden" | |
|
43 | class="help-block" > | |
|
44 | ${field.description} | |
|
45 | </p> | |
|
46 | </div> | |
|
47 | </div> No newline at end of file |
@@ -0,0 +1,24 b'' | |||
|
1 | <div tal:define=" | |
|
2 | item_tmpl item_template|field.widget.readonly_item_template; | |
|
3 | oid oid|field.oid; | |
|
4 | name name|field.name; | |
|
5 | title title|field.title;" | |
|
6 | class="deform-seq" | |
|
7 | id="${oid}"> | |
|
8 | ||
|
9 | <div class="panel panel-default"> | |
|
10 | <div class="panel-heading">${title}</div> | |
|
11 | <div class="panel-body"> | |
|
12 | ||
|
13 | <div class="deform-seq-container"> | |
|
14 | <div tal:define="subfields [ x[1] for x in subfields ]" | |
|
15 | tal:repeat="subfield subfields" | |
|
16 | tal:replace="structure subfield.render_template(item_tmpl, | |
|
17 | parent=field)" /> | |
|
18 | </div> | |
|
19 | ||
|
20 | <div style="clear: both"></div> | |
|
21 | </div> | |
|
22 | ||
|
23 | </div> | |
|
24 | </div> No newline at end of file |
@@ -0,0 +1,11 b'' | |||
|
1 | <div tal:omit-tag="field.widget.hidden" | |
|
2 | tal:define=" | |
|
3 | hidden hidden|field.widget.hidden; | |
|
4 | description description|field.description;" | |
|
5 | title="${description}" | |
|
6 | class="form-group row deform-seq-item ${field.error and error_class or ''} ${field.widget.item_css_class or ''}" | |
|
7 | i18n:domain="deform"> | |
|
8 | <div class="deform-seq-item-group"> | |
|
9 | <span tal:replace="structure field.serialize(cstruct, readonly=True)"/> | |
|
10 | </div> | |
|
11 | </div> |
@@ -0,0 +1,55 b'' | |||
|
1 | <div tal:define=" | |
|
2 | name name|field.name; | |
|
3 | style field.widget.style; | |
|
4 | oid oid|field.oid; | |
|
5 | css_class css_class|field.widget.css_class; | |
|
6 | optgroup_class optgroup_class|field.widget.optgroup_class; | |
|
7 | multiple multiple|field.widget.multiple;" | |
|
8 | tal:omit-tag=""> | |
|
9 | <input type="hidden" name="__start__" value="${name}:sequence" | |
|
10 | tal:condition="multiple" /> | |
|
11 | ||
|
12 | <select tal:attributes=" | |
|
13 | name name; | |
|
14 | id oid; | |
|
15 | class string: form-control ${css_class or ''}; | |
|
16 | data-placeholder field.widget.placeholder|None; | |
|
17 | multiple multiple; | |
|
18 | style style;"> | |
|
19 | <tal:loop tal:repeat="item values"> | |
|
20 | <optgroup tal:condition="isinstance(item, optgroup_class)" | |
|
21 | tal:attributes="label item.label"> | |
|
22 | <option tal:repeat="(value, description) item.options" | |
|
23 | tal:attributes=" | |
|
24 | selected (multiple and value in list(map(unicode, cstruct)) or value == list(map(unicode, cstruct))) and 'selected'; | |
|
25 | class css_class; | |
|
26 | label field.widget.long_label_generator and description; | |
|
27 | value value" | |
|
28 | tal:content="field.widget.long_label_generator and field.widget.long_label_generator(item.label, description) or description"/> | |
|
29 | </optgroup> | |
|
30 | <option tal:condition="not isinstance(item, optgroup_class)" | |
|
31 | tal:attributes=" | |
|
32 | selected (multiple and item[0] in list(map(unicode, cstruct)) or item[0] == unicode(cstruct)) and 'selected'; | |
|
33 | class css_class; | |
|
34 | value item[0]">${item[1]}</option> | |
|
35 | </tal:loop> | |
|
36 | </select> | |
|
37 | ||
|
38 | <script type="text/javascript"> | |
|
39 | deform.addCallback( | |
|
40 | '${field.oid}', | |
|
41 | function(oid) { | |
|
42 | $('#' + oid).select2({ | |
|
43 | containerCssClass: 'form-control drop-menu', | |
|
44 | dropdownCssClass: 'drop-menu-dropdown', | |
|
45 | dropdownAutoWidth: true, | |
|
46 | placeholder: "${str(field.widget.placeholder).replace('"','\\"')|""}", | |
|
47 | allowClear: true | |
|
48 | }); | |
|
49 | } | |
|
50 | ); | |
|
51 | </script> | |
|
52 | ||
|
53 | <input type="hidden" name="__end__" value="${name}:sequence" | |
|
54 | tal:condition="multiple" /> | |
|
55 | </div> No newline at end of file |
@@ -0,0 +1,105 b'' | |||
|
1 | <div tal:define="item_tmpl item_template|field.widget.item_template; | |
|
2 | oid oid|field.oid; | |
|
3 | name name|field.name; | |
|
4 | min_len min_len|field.widget.min_len; | |
|
5 | min_len min_len or 0; | |
|
6 | max_len max_len|field.widget.max_len; | |
|
7 | max_len max_len or 100000; | |
|
8 | now_len len(subfields); | |
|
9 | orderable orderable|field.widget.orderable; | |
|
10 | orderable orderable and 1 or 0; | |
|
11 | prototype field.widget.prototype(field); | |
|
12 | title title|field.title;" | |
|
13 | class="deform-seq" | |
|
14 | id="${oid}"> | |
|
15 | ||
|
16 | <style> | |
|
17 | body.dragging, body.dragging * { | |
|
18 | cursor: move !important; | |
|
19 | } | |
|
20 | ||
|
21 | .dragged { | |
|
22 | position: absolute; | |
|
23 | opacity: 0.5; | |
|
24 | z-index: 2000; | |
|
25 | } | |
|
26 | </style> | |
|
27 | ||
|
28 | <!-- sequence --> | |
|
29 | <input type="hidden" name="__start__" | |
|
30 | value="${field.name}:sequence" | |
|
31 | class="deform-proto" | |
|
32 | tal:attributes="prototype prototype"/> | |
|
33 | ||
|
34 | <div class="panel panel-default"> | |
|
35 | <div class="panel-heading">${title}</div> | |
|
36 | <div class="panel-body"> | |
|
37 | ||
|
38 | <div class="deform-seq-container" | |
|
39 | id="${oid}-orderable"> | |
|
40 | <div tal:define="subfields [ x[1] for x in subfields ]" | |
|
41 | tal:repeat="subfield subfields" | |
|
42 | tal:replace="structure subfield.render_template(item_tmpl, | |
|
43 | parent=field)" /> | |
|
44 | <span class="deform-insert-before" | |
|
45 | tal:attributes=" | |
|
46 | min_len min_len; | |
|
47 | max_len max_len; | |
|
48 | now_len now_len; | |
|
49 | orderable orderable;"></span> | |
|
50 | </div> | |
|
51 | ||
|
52 | <div style="clear: both"></div> | |
|
53 | </div> | |
|
54 | ||
|
55 | <div class="panel-footer"> | |
|
56 | <a href="#" | |
|
57 | class="btn deform-seq-add" | |
|
58 | id="${field.oid}-seqAdd" | |
|
59 | onclick="javascript: return deform.appendSequenceItem(this);"> | |
|
60 | <small id="${field.oid}-addtext">${add_subitem_text}</small> | |
|
61 | </a> | |
|
62 | ||
|
63 | <script type="text/javascript"> | |
|
64 | deform.addCallback( | |
|
65 | '${field.oid}', | |
|
66 | function(oid) { | |
|
67 | oid_node = $('#'+ oid); | |
|
68 | deform.processSequenceButtons(oid_node, ${min_len}, | |
|
69 | ${max_len}, ${now_len}, | |
|
70 | ${orderable}); | |
|
71 | } | |
|
72 | ) | |
|
73 | <tal:block condition="orderable"> | |
|
74 | $( "#${oid}-orderable" ).sortable({ | |
|
75 | handle: ".deform-order-button, .panel-heading", | |
|
76 | containerSelector: "#${oid}-orderable", | |
|
77 | itemSelector: ".deform-seq-item", | |
|
78 | placeholder: '<span class="glyphicon glyphicon-arrow-right placeholder"></span>', | |
|
79 | onDragStart: function ($item, container, _super) { | |
|
80 | var offset = $item.offset(), | |
|
81 | pointer = container.rootGroup.pointer | |
|
82 | ||
|
83 | adjustment = { | |
|
84 | left: pointer.left - offset.left, | |
|
85 | top: pointer.top - offset.top | |
|
86 | } | |
|
87 | ||
|
88 | _super($item, container) | |
|
89 | }, | |
|
90 | onDrag: function ($item, position) { | |
|
91 | $item.css({ | |
|
92 | left: position.left - adjustment.left, | |
|
93 | top: position.top - adjustment.top | |
|
94 | }) | |
|
95 | } | |
|
96 | }); | |
|
97 | </tal:block> | |
|
98 | </script> | |
|
99 | ||
|
100 | <input type="hidden" name="__end__" value="${field.name}:sequence"/> | |
|
101 | <!-- /sequence --> | |
|
102 | </div> | |
|
103 | ||
|
104 | </div> | |
|
105 | </div> No newline at end of file |
@@ -0,0 +1,35 b'' | |||
|
1 | <div tal:omit-tag="field.widget.hidden" | |
|
2 | tal:define="hidden hidden|field.widget.hidden; | |
|
3 | error_class error_class|field.widget.error_class; | |
|
4 | description description|field.description; | |
|
5 | title title|field.title; | |
|
6 | oid oid|field.oid" | |
|
7 | class="form-group row deform-seq-item ${field.error and error_class or ''} ${field.widget.item_css_class or ''}" | |
|
8 | i18n:domain="deform"> | |
|
9 | <div class="deform-seq-item-group"> | |
|
10 | <span tal:replace="structure field.serialize(cstruct)"/> | |
|
11 | <tal:errors condition="field.error and not hidden" | |
|
12 | define="errstr 'error-%s' % oid" | |
|
13 | repeat="msg field.error.messages()"> | |
|
14 | <p tal:condition="msg" | |
|
15 | id="${errstr if repeat.msg.index==0 else '%s-%s' % (errstr, repeat.msg.index)}" | |
|
16 | class="${error_class} help-block" | |
|
17 | i18n:translate="">${msg}</p> | |
|
18 | </tal:errors> | |
|
19 | </div> | |
|
20 | <div class="deform-seq-item-handle" style="padding:0"> | |
|
21 | <!-- sequence_item --> | |
|
22 | <span class="deform-order-button close glyphicon glyphicon-resize-vertical" | |
|
23 | id="${oid}-order" | |
|
24 | tal:condition="not hidden" | |
|
25 | title="Reorder (via drag and drop)" | |
|
26 | i18n:attributes="title"></span> | |
|
27 | <a class="deform-close-button close" | |
|
28 | id="${oid}-close" | |
|
29 | tal:condition="not field.widget.hidden" | |
|
30 | title="Remove" | |
|
31 | i18n:attributes="title" | |
|
32 | onclick="javascript:deform.removeSequenceItem(this);">×</a> | |
|
33 | </div> | |
|
34 | <!-- /sequence_item --> | |
|
35 | </div> |
@@ -0,0 +1,23 b'' | |||
|
1 | <span tal:define="name name|field.name; | |
|
2 | css_class css_class|field.widget.css_class; | |
|
3 | oid oid|field.oid; | |
|
4 | mask mask|field.widget.mask; | |
|
5 | placeholder placeholder|field.widget.placeholder|field.placeholder|''; | |
|
6 | mask_placeholder mask_placeholder|field.widget.mask_placeholder; | |
|
7 | style style|field.widget.style; | |
|
8 | " | |
|
9 | tal:omit-tag=""> | |
|
10 | <input type="text" name="${name}" value="${cstruct}" | |
|
11 | tal:attributes="class string: form-control ${css_class or ''}; | |
|
12 | style style" | |
|
13 | placeholder="${placeholder}" | |
|
14 | id="${oid}"/> | |
|
15 | <script tal:condition="mask" type="text/javascript"> | |
|
16 | deform.addCallback( | |
|
17 | '${oid}', | |
|
18 | function (oid) { | |
|
19 | $("#" + oid).mask("${mask}", | |
|
20 | {placeholder:"${mask_placeholder}"}); | |
|
21 | }); | |
|
22 | </script> | |
|
23 | </span> No newline at end of file |
@@ -38,6 +38,19 b'' | |||
|
38 | 38 | license = [ pkgs.lib.licenses.mit ]; |
|
39 | 39 | }; |
|
40 | 40 | }; |
|
41 | Chameleon = super.buildPythonPackage { | |
|
42 | name = "Chameleon-2.24"; | |
|
43 | buildInputs = with self; []; | |
|
44 | doCheck = false; | |
|
45 | propagatedBuildInputs = with self; []; | |
|
46 | src = fetchurl { | |
|
47 | url = "https://pypi.python.org/packages/5a/9e/637379ffa13c5172b5c0e704833ffea6bf51cec7567f93fd6e903d53ed74/Chameleon-2.24.tar.gz"; | |
|
48 | md5 = "1b01f1f6533a8a11d0d2f2366dec5342"; | |
|
49 | }; | |
|
50 | meta = { | |
|
51 | license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; | |
|
52 | }; | |
|
53 | }; | |
|
41 | 54 | Fabric = super.buildPythonPackage { |
|
42 | 55 | name = "Fabric-1.10.0"; |
|
43 | 56 | buildInputs = with self; []; |
@@ -558,6 +571,20 b'' | |||
|
558 | 571 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
559 | 572 | }; |
|
560 | 573 | }; |
|
574 | deform = super.buildPythonPackage { | |
|
575 | name = "deform-2.0a3.dev0"; | |
|
576 | buildInputs = with self; []; | |
|
577 | doCheck = false; | |
|
578 | propagatedBuildInputs = with self; [Chameleon colander iso8601 peppercorn translationstring zope.deprecation]; | |
|
579 | src = fetchgit { | |
|
580 | url = "https://github.com/Pylons/deform"; | |
|
581 | rev = "08fb9de077c76951f6e70e28d4bf060a209d3d39"; | |
|
582 | sha256 = "0nmhajc4pfgp4lbwhs5szqfzswpij1qyr69m7qkyhncl2g2d759r"; | |
|
583 | }; | |
|
584 | meta = { | |
|
585 | license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ]; | |
|
586 | }; | |
|
587 | }; | |
|
561 | 588 | docutils = super.buildPythonPackage { |
|
562 | 589 | name = "docutils-0.12"; |
|
563 | 590 | buildInputs = with self; []; |
@@ -1355,7 +1382,7 b'' | |||
|
1355 | 1382 | name = "rhodecode-enterprise-ce-4.3.0"; |
|
1356 | 1383 | buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner]; |
|
1357 | 1384 | doCheck = true; |
|
1358 | propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt]; | |
|
1385 | propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator deform docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt]; | |
|
1359 | 1386 | src = ./.; |
|
1360 | 1387 | meta = { |
|
1361 | 1388 | license = [ { fullName = "AGPLv3, and Commercial License"; } ]; |
@@ -60,6 +60,7 b' cov-core==1.15.0' | |||
|
60 | 60 | coverage==3.7.1 |
|
61 | 61 | cssselect==0.9.1 |
|
62 | 62 | decorator==3.4.2 |
|
63 | git+https://github.com/Pylons/deform@08fb9de077c76951f6e70e28d4bf060a209d3d39#egg=deform | |
|
63 | 64 | docutils==0.12 |
|
64 | 65 | dogpile.cache==0.6.1 |
|
65 | 66 | dogpile.core==0.4.1 |
@@ -316,9 +316,10 b' def includeme_first(config):' | |||
|
316 | 316 | config.add_route('favicon', '/favicon.ico') |
|
317 | 317 | |
|
318 | 318 | config.add_static_view( |
|
319 | '_static/deform', 'deform:static') | |
|
320 | config.add_static_view( | |
|
319 | 321 | '_static', path='rhodecode:public', cache_max_age=3600 * 24) |
|
320 | 322 | |
|
321 | ||
|
322 | 323 | def wrap_app_in_wsgi_middlewares(pyramid_app, config): |
|
323 | 324 | """ |
|
324 | 325 | Apply outer WSGI middlewares around the application. |
@@ -19,6 +19,7 b'' | |||
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | import logging |
|
22 | ||
|
22 | 23 | from rhodecode.integrations.registry import IntegrationTypeRegistry |
|
23 | 24 | from rhodecode.integrations.types import webhook, slack |
|
24 | 25 |
@@ -35,7 +35,6 b' class IntegrationSettingsSchemaBase(cola' | |||
|
35 | 35 | description=lazy_ugettext('Enable or disable this integration.'), |
|
36 | 36 | missing=False, |
|
37 | 37 | title=lazy_ugettext('Enabled'), |
|
38 | widget='bool', | |
|
39 | 38 | ) |
|
40 | 39 | |
|
41 | 40 | name = colander.SchemaNode( |
@@ -43,6 +42,4 b' class IntegrationSettingsSchemaBase(cola' | |||
|
43 | 42 | description=lazy_ugettext('Short name for this integration.'), |
|
44 | 43 | missing=colander.required, |
|
45 | 44 | title=lazy_ugettext('Integration name'), |
|
46 | widget='string', | |
|
47 | 45 | ) |
|
48 |
@@ -31,8 +31,7 b' class IntegrationTypeBase(object):' | |||
|
31 | 31 | self.settings = settings |
|
32 | 32 | |
|
33 | 33 | |
|
34 | @classmethod | |
|
35 | def settings_schema(cls): | |
|
34 | def settings_schema(self): | |
|
36 | 35 | """ |
|
37 | 36 | A colander schema of settings for the integration type |
|
38 | 37 |
@@ -19,7 +19,7 b'' | |||
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | from __future__ import unicode_literals |
|
22 | ||
|
22 | import deform | |
|
23 | 23 | import re |
|
24 | 24 | import logging |
|
25 | 25 | import requests |
@@ -48,10 +48,11 b' class SlackSettingsSchema(IntegrationSet' | |||
|
48 | 48 | '<a href="https://my.slack.com/services/new/incoming-webhook/">' |
|
49 | 49 | 'slack app manager</a>')), |
|
50 | 50 | default='', |
|
51 | placeholder='https://hooks.slack.com/services/...', | |
|
52 | 51 | preparer=strip_whitespace, |
|
53 | 52 | validator=colander.url, |
|
54 | widget='string' | |
|
53 | widget=deform.widget.TextInputWidget( | |
|
54 | placeholder='https://hooks.slack.com/services/...', | |
|
55 | ), | |
|
55 | 56 | ) |
|
56 | 57 | username = colander.SchemaNode( |
|
57 | 58 | colander.String(), |
@@ -59,8 +60,9 b' class SlackSettingsSchema(IntegrationSet' | |||
|
59 | 60 | description=lazy_ugettext('Username to show notifications coming from.'), |
|
60 | 61 | missing='Rhodecode', |
|
61 | 62 | preparer=strip_whitespace, |
|
62 | widget='string', | |
|
63 | placeholder='Rhodecode' | |
|
63 | widget=deform.widget.TextInputWidget( | |
|
64 | placeholder='Rhodecode' | |
|
65 | ), | |
|
64 | 66 | ) |
|
65 | 67 | channel = colander.SchemaNode( |
|
66 | 68 | colander.String(), |
@@ -68,8 +70,9 b' class SlackSettingsSchema(IntegrationSet' | |||
|
68 | 70 | description=lazy_ugettext('Channel to send notifications to.'), |
|
69 | 71 | missing='', |
|
70 | 72 | preparer=strip_whitespace, |
|
71 | widget='string', | |
|
72 | placeholder='#general' | |
|
73 | widget=deform.widget.TextInputWidget( | |
|
74 | placeholder='#general' | |
|
75 | ), | |
|
73 | 76 | ) |
|
74 | 77 | icon_emoji = colander.SchemaNode( |
|
75 | 78 | colander.String(), |
@@ -77,8 +80,9 b' class SlackSettingsSchema(IntegrationSet' | |||
|
77 | 80 | description=lazy_ugettext('Emoji to use eg. :studio_microphone:'), |
|
78 | 81 | missing='', |
|
79 | 82 | preparer=strip_whitespace, |
|
80 | widget='string', | |
|
81 | placeholder=':studio_microphone:' | |
|
83 | widget=deform.widget.TextInputWidget( | |
|
84 | placeholder=':studio_microphone:' | |
|
85 | ), | |
|
82 | 86 | ) |
|
83 | 87 | |
|
84 | 88 | |
@@ -144,16 +148,19 b' class SlackIntegrationType(IntegrationTy' | |||
|
144 | 148 | |
|
145 | 149 | run_task(post_text_to_slack, self.settings, text) |
|
146 | 150 | |
|
147 | @classmethod | |
|
148 | def settings_schema(cls): | |
|
151 | def settings_schema(self): | |
|
149 | 152 | schema = SlackSettingsSchema() |
|
150 | 153 | schema.add(colander.SchemaNode( |
|
151 | 154 | colander.Set(), |
|
152 |
widget= |
|
|
153 | choices=sorted([e.name for e in cls.valid_events]), | |
|
155 | widget=deform.widget.CheckboxChoiceWidget( | |
|
156 | values=sorted( | |
|
157 | [(e.name, e.display_name) for e in self.valid_events] | |
|
158 | ) | |
|
159 | ), | |
|
154 | 160 | description="Events activated for this integration", |
|
155 | 161 | name='events' |
|
156 | 162 | )) |
|
163 | ||
|
157 | 164 | return schema |
|
158 | 165 | |
|
159 | 166 | def format_pull_request_comment_event(self, event, data): |
@@ -20,6 +20,7 b'' | |||
|
20 | 20 | |
|
21 | 21 | from __future__ import unicode_literals |
|
22 | 22 | |
|
23 | import deform | |
|
23 | 24 | import logging |
|
24 | 25 | import requests |
|
25 | 26 | import colander |
@@ -41,16 +42,18 b' class WebhookSettingsSchema(IntegrationS' | |||
|
41 | 42 | description=lazy_ugettext('URL of the webhook to receive POST event.'), |
|
42 | 43 | default='', |
|
43 | 44 | validator=colander.url, |
|
44 | placeholder='https://www.example.com/webhook', | |
|
45 | widget='string' | |
|
45 | widget=deform.widget.TextInputWidget( | |
|
46 | placeholder='https://www.example.com/webhook' | |
|
47 | ), | |
|
46 | 48 | ) |
|
47 | 49 | secret_token = colander.SchemaNode( |
|
48 | 50 | colander.String(), |
|
49 | 51 | title=lazy_ugettext('Secret Token'), |
|
50 | 52 | description=lazy_ugettext('String used to validate received payloads.'), |
|
51 | 53 | default='', |
|
52 | placeholder='secret_token', | |
|
53 | widget='string' | |
|
54 | widget=deform.widget.TextInputWidget( | |
|
55 | placeholder='secret_token' | |
|
56 | ), | |
|
54 | 57 | ) |
|
55 | 58 | |
|
56 | 59 | |
@@ -68,13 +71,15 b' class WebhookIntegrationType(Integration' | |||
|
68 | 71 | events.RepoCreateEvent, |
|
69 | 72 | ] |
|
70 | 73 | |
|
71 | @classmethod | |
|
72 | def settings_schema(cls): | |
|
74 | def settings_schema(self): | |
|
73 | 75 | schema = WebhookSettingsSchema() |
|
74 | 76 | schema.add(colander.SchemaNode( |
|
75 | 77 | colander.Set(), |
|
76 |
widget= |
|
|
77 | choices=sorted([e.name for e in cls.valid_events]), | |
|
78 | widget=deform.widget.CheckboxChoiceWidget( | |
|
79 | values=sorted( | |
|
80 | [(e.name, e.display_name) for e in self.valid_events] | |
|
81 | ) | |
|
82 | ), | |
|
78 | 83 | description="Events activated for this integration", |
|
79 | 84 | name='events' |
|
80 | 85 | )) |
@@ -21,6 +21,7 b'' | |||
|
21 | 21 | import colander |
|
22 | 22 | import logging |
|
23 | 23 | import pylons |
|
24 | import deform | |
|
24 | 25 | |
|
25 | 26 | from pyramid.httpexceptions import HTTPFound, HTTPForbidden |
|
26 | 27 | from pyramid.renderers import render |
@@ -101,30 +102,41 b' class IntegrationSettingsViewBase(object' | |||
|
101 | 102 | return c |
|
102 | 103 | |
|
103 | 104 | def _form_schema(self): |
|
104 | return self.IntegrationType.settings_schema() | |
|
105 | if self.integration: | |
|
106 | settings = self.integration.settings | |
|
107 | else: | |
|
108 | settings = {} | |
|
109 | return self.IntegrationType(settings=settings).settings_schema() | |
|
105 | 110 | |
|
106 | def settings_get(self, defaults=None, errors=None): | |
|
111 | def settings_get(self, defaults=None, errors=None, form=None): | |
|
107 | 112 | """ |
|
108 | 113 | View that displays the plugin settings as a form. |
|
109 | 114 | """ |
|
110 | 115 | defaults = defaults or {} |
|
111 | 116 | errors = errors or {} |
|
112 | 117 | |
|
113 | schema = self._form_schema() | |
|
114 | ||
|
115 | if not defaults: | |
|
116 |
|
|
|
117 | defaults['enabled'] = self.integration.enabled | |
|
118 | defaults['name'] = self.integration.name | |
|
118 | if self.integration: | |
|
119 | defaults = self.integration.settings or {} | |
|
120 | defaults['name'] = self.integration.name | |
|
121 | defaults['enabled'] = self.integration.enabled | |
|
122 | else: | |
|
123 | if self.repo: | |
|
124 | scope = self.repo.repo_name | |
|
119 | 125 | else: |
|
120 | if self.repo: | |
|
121 | scope = self.repo.repo_name | |
|
122 | else: | |
|
123 | scope = _('Global') | |
|
126 | scope = _('Global') | |
|
127 | ||
|
128 | defaults['name'] = '{} {} integration'.format(scope, | |
|
129 | self.IntegrationType.display_name) | |
|
130 | defaults['enabled'] = True | |
|
124 | 131 | |
|
125 | defaults['name'] = '{} {} integration'.format(scope, | |
|
126 | self.IntegrationType.display_name) | |
|
127 | defaults['enabled'] = True | |
|
132 | schema = self._form_schema().bind(request=self.request) | |
|
133 | ||
|
134 | if self.integration: | |
|
135 | buttons = ('submit', 'delete') | |
|
136 | else: | |
|
137 | buttons = ('submit',) | |
|
138 | ||
|
139 | form = form or deform.Form(schema, appstruct=defaults, buttons=buttons) | |
|
128 | 140 | |
|
129 | 141 | for node in schema: |
|
130 | 142 | setting = self.settings.get(node.name) |
@@ -135,6 +147,7 b' class IntegrationSettingsViewBase(object' | |||
|
135 | 147 | defaults.setdefault(node.name, node.default) |
|
136 | 148 | |
|
137 | 149 | template_context = { |
|
150 | 'form': form, | |
|
138 | 151 | 'defaults': defaults, |
|
139 | 152 | 'errors': errors, |
|
140 | 153 | 'schema': schema, |
@@ -166,7 +179,9 b' class IntegrationSettingsViewBase(object' | |||
|
166 | 179 | redirect_to = self.request.route_url('global_integrations_home') |
|
167 | 180 | raise HTTPFound(redirect_to) |
|
168 | 181 | |
|
169 | schema = self._form_schema() | |
|
182 | schema = self._form_schema().bind(request=self.request) | |
|
183 | ||
|
184 | form = deform.Form(schema, buttons=('submit', 'delete')) | |
|
170 | 185 | |
|
171 | 186 | params = {} |
|
172 | 187 | for node in schema.children: |
@@ -177,15 +192,15 b' class IntegrationSettingsViewBase(object' | |||
|
177 | 192 | if val: |
|
178 | 193 | params[node.name] = val |
|
179 | 194 | |
|
195 | controls = self.request.POST.items() | |
|
180 | 196 | try: |
|
181 |
valid_data = |
|
|
182 |
except |
|
|
183 | # Display error message and display form again. | |
|
197 | valid_data = form.validate(controls) | |
|
198 | except deform.ValidationFailure as e: | |
|
184 | 199 | self.request.session.flash( |
|
185 |
_('Errors exist when saving |
|
|
200 | _('Errors exist when saving integration settings. ' | |
|
186 | 201 | 'Please check the form inputs.'), |
|
187 | 202 | queue='error') |
|
188 |
return self.settings_get(errors= |
|
|
203 | return self.settings_get(errors={}, defaults=params, form=e) | |
|
189 | 204 | |
|
190 | 205 | if not self.integration: |
|
191 | 206 | self.integration = Integration() |
@@ -230,7 +245,6 b' class IntegrationSettingsViewBase(object' | |||
|
230 | 245 | template_context = { |
|
231 | 246 | 'current_IntegrationType': self.IntegrationType, |
|
232 | 247 | 'current_integrations': current_integrations, |
|
233 | 'current_integration': 'none', | |
|
234 | 248 | 'available_integrations': integration_type_registry, |
|
235 | 249 | 'c': self._template_c_context() |
|
236 | 250 | } |
@@ -950,7 +950,8 b' def bool2icon(value):' | |||
|
950 | 950 | #============================================================================== |
|
951 | 951 | from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \ |
|
952 | 952 | HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \ |
|
953 | HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token | |
|
953 | HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token, \ | |
|
954 | csrf_token_key | |
|
954 | 955 | |
|
955 | 956 | |
|
956 | 957 | #============================================================================== |
@@ -1877,11 +1878,15 b' def secure_form(url, method="POST", mult' | |||
|
1877 | 1878 | |
|
1878 | 1879 | """ |
|
1879 | 1880 | from webhelpers.pylonslib.secure_form import insecure_form |
|
1880 | from rhodecode.lib.auth import get_csrf_token, csrf_token_key | |
|
1881 | 1881 | form = insecure_form(url, method, multipart, **attrs) |
|
1882 | token = HTML.div(hidden(csrf_token_key, get_csrf_token()), style="display: none;") | |
|
1882 | token = csrf_input() | |
|
1883 | 1883 | return literal("%s\n%s" % (form, token)) |
|
1884 | 1884 | |
|
1885 | def csrf_input(): | |
|
1886 | return literal( | |
|
1887 | '<input type="hidden" id="{}" name="{}" value="{}">'.format( | |
|
1888 | csrf_token_key, csrf_token_key, get_csrf_token())) | |
|
1889 | ||
|
1885 | 1890 | def dropdownmenu(name, selected, options, enable_filter=False, **attrs): |
|
1886 | 1891 | select_html = select(name, selected, options, **attrs) |
|
1887 | 1892 | select2 = """ |
@@ -1937,6 +1942,16 b' def route_path(*args, **kwds):' | |||
|
1937 | 1942 | return req.route_path(*args, **kwds) |
|
1938 | 1943 | |
|
1939 | 1944 | |
|
1945 | def static_url(*args, **kwds): | |
|
1946 | """ | |
|
1947 | Wrapper around pyramids `route_path` function. It is used to generate | |
|
1948 | URLs from within pylons views or templates. This will be removed when | |
|
1949 | pyramid migration if finished. | |
|
1950 | """ | |
|
1951 | req = get_current_request() | |
|
1952 | return req.static_url(*args, **kwds) | |
|
1953 | ||
|
1954 | ||
|
1940 | 1955 | def resource_path(*args, **kwds): |
|
1941 | 1956 | """ |
|
1942 | 1957 | Wrapper around pyramids `route_path` function. It is used to generate |
@@ -41,6 +41,16 b' for SELECT use formencode.All(OneOf(list' | |||
|
41 | 41 | |
|
42 | 42 | """ |
|
43 | 43 | |
|
44 | import deform | |
|
45 | from pkg_resources import resource_filename | |
|
46 | ||
|
47 | deform_templates = resource_filename('deform', 'templates') | |
|
48 | rhodecode_templates = resource_filename('rhodecode', 'templates/forms') | |
|
49 | search_path = (rhodecode_templates, deform_templates) | |
|
50 | ||
|
51 | deform.Form.set_zpt_renderer(search_path) | |
|
52 | ||
|
53 | ||
|
44 | 54 | import logging |
|
45 | 55 | |
|
46 | 56 | import formencode |
@@ -25,6 +25,7 b'' | |||
|
25 | 25 | @import 'comments'; |
|
26 | 26 | @import 'panels-bootstrap'; |
|
27 | 27 | @import 'panels'; |
|
28 | @import 'deform'; | |
|
28 | 29 | |
|
29 | 30 | |
|
30 | 31 | //--- BASE ------------------// |
@@ -141,7 +142,7 b' input.inline[type="file"] {' | |||
|
141 | 142 | h1 { |
|
142 | 143 | color: @grey2; |
|
143 | 144 | } |
|
144 | ||
|
145 | ||
|
145 | 146 | .error-branding { |
|
146 | 147 | font-family: @text-semibold; |
|
147 | 148 | color: @grey4; |
@@ -1022,9 +1023,9 b' label {' | |||
|
1022 | 1023 | padding: .9em; |
|
1023 | 1024 | color: @grey3; |
|
1024 | 1025 | background-color: @grey7; |
|
1025 |
border-right: @border-thickness solid @border-default-color; |
|
|
1026 |
border-bottom: @border-thickness solid @border-default-color; |
|
|
1027 |
border-left: @border-thickness solid @border-default-color; |
|
|
1026 | border-right: @border-thickness solid @border-default-color; | |
|
1027 | border-bottom: @border-thickness solid @border-default-color; | |
|
1028 | border-left: @border-thickness solid @border-default-color; | |
|
1028 | 1029 | } |
|
1029 | 1030 | |
|
1030 | 1031 | #repo_vcs_settings { |
@@ -1953,7 +1954,7 b' div.search-feedback-items {' | |||
|
1953 | 1954 | padding:0px 0px 0px 96px; |
|
1954 | 1955 | } |
|
1955 | 1956 | |
|
1956 |
div.search-code-body { |
|
|
1957 | div.search-code-body { | |
|
1957 | 1958 | background-color: #ffffff; padding: 5px 0 5px 10px; |
|
1958 | 1959 | pre { |
|
1959 | 1960 | .match { background-color: #faffa6;} |
@@ -27,8 +27,6 b'' | |||
|
27 | 27 | ${integration.name} |
|
28 | 28 | %endif |
|
29 | 29 | </%def> |
|
30 | ||
|
31 | ||
|
32 | 30 | <div class="panel panel-default"> |
|
33 | 31 | <div class="panel-heading"> |
|
34 | 32 | <h2 class="panel-title"> |
@@ -39,70 +37,8 b'' | |||
|
39 | 37 | %endif |
|
40 | 38 | </h2> |
|
41 | 39 | </div> |
|
42 |
<div class=" |
|
|
43 | ${h.secure_form(request.url)} | |
|
44 | <div class="form"> | |
|
45 | %for node in schema: | |
|
46 | <% label_css_class = ("label-checkbox" if (node.widget == "bool") else "") %> | |
|
47 | <div class="field"> | |
|
48 | <div class="label ${label_css_class}"><label for="${node.name}">${node.title}</label></div> | |
|
49 | <div class="input"> | |
|
50 | %if node.widget in ["string", "int", "unicode"]: | |
|
51 | ${h.text(node.name, defaults.get(node.name), class_="medium", placeholder=hasattr(node, 'placeholder') and node.placeholder or '')} | |
|
52 | %elif node.widget in ["text"]: | |
|
53 | ${h.textarea(node.name, defaults.get(node.name), class_="medium", placeholder=hasattr(node, 'placeholder') and node.placeholder or '')} | |
|
54 | %elif node.widget == "password": | |
|
55 | ${h.password(node.name, defaults.get(node.name), class_="medium")} | |
|
56 | %elif node.widget == "bool": | |
|
57 | <div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div> | |
|
58 | %elif node.widget == "select": | |
|
59 | ${h.select(node.name, defaults.get(node.name), node.choices)} | |
|
60 | %elif node.widget == "checkbox_list": | |
|
61 | %for i, choice in enumerate(node.choices): | |
|
62 | <% | |
|
63 | name, value = choice, choice | |
|
64 | if isinstance(choice, tuple): | |
|
65 | choice, name = choice | |
|
66 | %> | |
|
67 | <div> | |
|
68 | <input id="${node.name}-${choice}" | |
|
69 | name="${node.name}" | |
|
70 | value="${value}" | |
|
71 | type="checkbox" | |
|
72 | ${value in defaults.get(node.name, []) and 'checked' or ''}> | |
|
73 | <label for="${node.name}-${value}"> | |
|
74 | ${name} | |
|
75 | </label> | |
|
76 | </div> | |
|
77 | %endfor | |
|
78 | %elif node.widget == "readonly": | |
|
79 | ${node.default} | |
|
80 | %else: | |
|
81 | This field is of type ${node.typ}, which cannot be displayed. Must be one of [string|int|bool|select|password|text|checkbox_list]. | |
|
82 | %endif | |
|
83 | %if node.name in errors: | |
|
84 | <span class="error-message">${errors.get(node.name)}</span> | |
|
85 | <br /> | |
|
86 | %endif | |
|
87 | <p class="help-block">${node.description}</p> | |
|
88 | </div> | |
|
89 | </div> | |
|
90 | %endfor | |
|
91 | ||
|
92 | ## Allow derived templates to add something below the form | |
|
93 | ## input fields | |
|
94 | %if hasattr(next, 'below_form_fields'): | |
|
95 | ${next.below_form_fields()} | |
|
96 | %endif | |
|
97 | ||
|
98 | <div class="buttons"> | |
|
99 | ${h.submit('save',_('Save'),class_="btn")} | |
|
100 | %if integration: | |
|
101 | ${h.submit('delete',_('Delete'),class_="btn btn-danger")} | |
|
102 | %endif | |
|
103 | </div> | |
|
104 | ||
|
105 | </div> | |
|
106 | ${h.end_form()} | |
|
40 | <div class="panel-body"> | |
|
41 | ## TODO: dan: find way to put h in the deform context properly | |
|
42 | ${form.render(h=h) | n} | |
|
107 | 43 | </div> |
|
108 | </div> No newline at end of file | |
|
44 | </div> |
@@ -83,9 +83,11 b" c.template_context['visual']['default_re" | |||
|
83 | 83 | <![endif]--> |
|
84 | 84 | <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script> |
|
85 | 85 | <script language="javascript" type="text/javascript" src="${h.asset('js/scripts.js', ver=c.rhodecode_version_hash)}"></script> |
|
86 | <script language="javascript" type="text/javascript" src="${h.static_url('deform:static/scripts/deform.js')}"></script> | |
|
86 | 87 | ## avoide esaping the %N |
|
87 | 88 | <script>CodeMirror.modeURL = "${h.asset('') + 'js/mode/%N/%N.js'}";</script> |
|
88 | 89 | |
|
90 | ||
|
89 | 91 | ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates |
|
90 | 92 | ${self.js_extra()} |
|
91 | 93 |
General Comments 0
You need to be logged in to leave comments.
Login now