##// END OF EJS Templates
templates: switched most of confirm dialogs to sweetalert2
ergo -
r4313:4bf03e9f default
parent child Browse files
Show More
@@ -1,1371 +1,1371 b''
1 .swal2-popup.swal2-toast {
1 .swal2-popup.swal2-toast {
2 flex-direction: row;
2 flex-direction: row;
3 align-items: center;
3 align-items: center;
4 width: auto;
4 width: auto;
5 padding: 0.625em;
5 padding: 0.625em;
6 overflow-y: hidden;
6 overflow-y: hidden;
7 background: #fff;
7 background: #fff;
8 box-shadow: 0 0 0.625em #d9d9d9;
8 box-shadow: 0 0 0.625em #d9d9d9;
9 }
9 }
10 .swal2-popup.swal2-toast .swal2-header {
10 .swal2-popup.swal2-toast .swal2-header {
11 flex-direction: row;
11 flex-direction: row;
12 }
12 }
13 .swal2-popup.swal2-toast .swal2-title {
13 .swal2-popup.swal2-toast .swal2-title {
14 flex-grow: 1;
14 flex-grow: 1;
15 justify-content: flex-start;
15 justify-content: flex-start;
16 margin: 0 0.6em;
16 margin: 0 0.6em;
17 font-size: 1em;
17 font-size: 1em;
18 }
18 }
19 .swal2-popup.swal2-toast .swal2-footer {
19 .swal2-popup.swal2-toast .swal2-footer {
20 margin: 0.5em 0 0;
20 margin: 0.5em 0 0;
21 padding: 0.5em 0 0;
21 padding: 0.5em 0 0;
22 font-size: 0.8em;
22 font-size: 0.8em;
23 }
23 }
24 .swal2-popup.swal2-toast .swal2-close {
24 .swal2-popup.swal2-toast .swal2-close {
25 position: static;
25 position: static;
26 width: 0.8em;
26 width: 0.8em;
27 height: 0.8em;
27 height: 0.8em;
28 line-height: 0.8;
28 line-height: 0.8;
29 }
29 }
30 .swal2-popup.swal2-toast .swal2-content {
30 .swal2-popup.swal2-toast .swal2-content {
31 justify-content: flex-start;
31 justify-content: flex-start;
32 font-size: 1em;
32 font-size: 1em;
33 }
33 }
34 .swal2-popup.swal2-toast .swal2-icon {
34 .swal2-popup.swal2-toast .swal2-icon {
35 width: 2em;
35 width: 2em;
36 min-width: 2em;
36 min-width: 2em;
37 height: 2em;
37 height: 2em;
38 margin: 0;
38 margin: 0;
39 }
39 }
40 .swal2-popup.swal2-toast .swal2-icon .swal2-icon-content {
40 .swal2-popup.swal2-toast .swal2-icon .swal2-icon-content {
41 display: flex;
41 display: flex;
42 align-items: center;
42 align-items: center;
43 font-size: 1.8em;
43 font-size: 1.8em;
44 font-weight: bold;
44 font-weight: bold;
45 }
45 }
46 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
46 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
47 .swal2-popup.swal2-toast .swal2-icon .swal2-icon-content {
47 .swal2-popup.swal2-toast .swal2-icon .swal2-icon-content {
48 font-size: 0.25em;
48 font-size: 0.25em;
49 }
49 }
50 }
50 }
51 .swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring {
51 .swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring {
52 width: 2em;
52 width: 2em;
53 height: 2em;
53 height: 2em;
54 }
54 }
55 .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line] {
55 .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line] {
56 top: 0.875em;
56 top: 0.875em;
57 width: 1.375em;
57 width: 1.375em;
58 }
58 }
59 .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
59 .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
60 left: 0.3125em;
60 left: 0.3125em;
61 }
61 }
62 .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
62 .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
63 right: 0.3125em;
63 right: 0.3125em;
64 }
64 }
65 .swal2-popup.swal2-toast .swal2-actions {
65 .swal2-popup.swal2-toast .swal2-actions {
66 flex-basis: auto !important;
66 flex-basis: auto !important;
67 width: auto;
67 width: auto;
68 height: auto;
68 height: auto;
69 margin: 0 0.3125em;
69 margin: 0 0.3125em;
70 }
70 }
71 .swal2-popup.swal2-toast .swal2-styled {
71 .swal2-popup.swal2-toast .swal2-styled {
72 margin: 0 0.3125em;
72 margin: 0 0.3125em;
73 padding: 0.3125em 0.625em;
73 padding: 0.3125em 0.625em;
74 font-size: 1em;
74 font-size: 1em;
75 }
75 }
76 .swal2-popup.swal2-toast .swal2-styled:focus {
76 .swal2-popup.swal2-toast .swal2-styled:focus {
77 box-shadow: 0 0 0 1px #fff, 0 0 0 3px rgba(50, 100, 150, 0.4);
77 box-shadow: 0 0 0 1px #fff, 0 0 0 3px rgba(50, 100, 150, 0.4);
78 }
78 }
79 .swal2-popup.swal2-toast .swal2-success {
79 .swal2-popup.swal2-toast .swal2-success {
80 border-color: @alert1;
80 border-color: @alert1;
81 }
81 }
82 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line] {
82 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line] {
83 position: absolute;
83 position: absolute;
84 width: 1.6em;
84 width: 1.6em;
85 height: 3em;
85 height: 3em;
86 transform: rotate(45deg);
86 transform: rotate(45deg);
87 border-radius: 50%;
87 border-radius: 50%;
88 }
88 }
89 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left] {
89 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=left] {
90 top: -0.8em;
90 top: -0.8em;
91 left: -0.5em;
91 left: -0.5em;
92 transform: rotate(-45deg);
92 transform: rotate(-45deg);
93 transform-origin: 2em 2em;
93 transform-origin: 2em 2em;
94 border-radius: 4em 0 0 4em;
94 border-radius: 4em 0 0 4em;
95 }
95 }
96 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right] {
96 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-circular-line][class$=right] {
97 top: -0.25em;
97 top: -0.25em;
98 left: 0.9375em;
98 left: 0.9375em;
99 transform-origin: 0 1.5em;
99 transform-origin: 0 1.5em;
100 border-radius: 0 4em 4em 0;
100 border-radius: 0 4em 4em 0;
101 }
101 }
102 .swal2-popup.swal2-toast .swal2-success .swal2-success-ring {
102 .swal2-popup.swal2-toast .swal2-success .swal2-success-ring {
103 width: 2em;
103 width: 2em;
104 height: 2em;
104 height: 2em;
105 }
105 }
106 .swal2-popup.swal2-toast .swal2-success .swal2-success-fix {
106 .swal2-popup.swal2-toast .swal2-success .swal2-success-fix {
107 top: 0;
107 top: 0;
108 left: 0.4375em;
108 left: 0.4375em;
109 width: 0.4375em;
109 width: 0.4375em;
110 height: 2.6875em;
110 height: 2.6875em;
111 }
111 }
112 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line] {
112 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line] {
113 height: 0.3125em;
113 height: 0.3125em;
114 }
114 }
115 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip] {
115 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=tip] {
116 top: 1.125em;
116 top: 1.125em;
117 left: 0.1875em;
117 left: 0.1875em;
118 width: 0.75em;
118 width: 0.75em;
119 }
119 }
120 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long] {
120 .swal2-popup.swal2-toast .swal2-success [class^=swal2-success-line][class$=long] {
121 top: 0.9375em;
121 top: 0.9375em;
122 right: 0.1875em;
122 right: 0.1875em;
123 width: 1.375em;
123 width: 1.375em;
124 }
124 }
125 .swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip {
125 .swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-tip {
126 -webkit-animation: swal2-toast-animate-success-line-tip 0.75s;
126 -webkit-animation: swal2-toast-animate-success-line-tip 0.75s;
127 animation: swal2-toast-animate-success-line-tip 0.75s;
127 animation: swal2-toast-animate-success-line-tip 0.75s;
128 }
128 }
129 .swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long {
129 .swal2-popup.swal2-toast .swal2-success.swal2-icon-show .swal2-success-line-long {
130 -webkit-animation: swal2-toast-animate-success-line-long 0.75s;
130 -webkit-animation: swal2-toast-animate-success-line-long 0.75s;
131 animation: swal2-toast-animate-success-line-long 0.75s;
131 animation: swal2-toast-animate-success-line-long 0.75s;
132 }
132 }
133 .swal2-popup.swal2-toast.swal2-show {
133 .swal2-popup.swal2-toast.swal2-show {
134 -webkit-animation: swal2-toast-show 0.5s;
134 -webkit-animation: swal2-toast-show 0.5s;
135 animation: swal2-toast-show 0.5s;
135 animation: swal2-toast-show 0.5s;
136 }
136 }
137 .swal2-popup.swal2-toast.swal2-hide {
137 .swal2-popup.swal2-toast.swal2-hide {
138 -webkit-animation: swal2-toast-hide 0.1s forwards;
138 -webkit-animation: swal2-toast-hide 0.1s forwards;
139 animation: swal2-toast-hide 0.1s forwards;
139 animation: swal2-toast-hide 0.1s forwards;
140 }
140 }
141
141
142 .swal2-container {
142 .swal2-container {
143 display: flex;
143 display: flex;
144 position: fixed;
144 position: fixed;
145 z-index: 1060;
145 z-index: 1060;
146 top: 0;
146 top: 0;
147 right: 0;
147 right: 0;
148 bottom: 0;
148 bottom: 0;
149 left: 0;
149 left: 0;
150 flex-direction: row;
150 flex-direction: row;
151 align-items: center;
151 align-items: center;
152 justify-content: center;
152 justify-content: center;
153 padding: 0.625em;
153 padding: 0.625em;
154 overflow-x: hidden;
154 overflow-x: hidden;
155 transition: background-color 0.1s;
155 transition: background-color 0.1s;
156 -webkit-overflow-scrolling: touch;
156 -webkit-overflow-scrolling: touch;
157 }
157 }
158 .swal2-container.swal2-backdrop-show, .swal2-container.swal2-noanimation {
158 .swal2-container.swal2-backdrop-show, .swal2-container.swal2-noanimation {
159 background: rgba(0, 0, 0, 0.4);
159 background: rgba(0, 0, 0, 0.4);
160 }
160 }
161 .swal2-container.swal2-backdrop-hide {
161 .swal2-container.swal2-backdrop-hide {
162 background: transparent !important;
162 background: transparent !important;
163 }
163 }
164 .swal2-container.swal2-top {
164 .swal2-container.swal2-top {
165 align-items: flex-start;
165 align-items: flex-start;
166 }
166 }
167 .swal2-container.swal2-top-start, .swal2-container.swal2-top-left {
167 .swal2-container.swal2-top-start, .swal2-container.swal2-top-left {
168 align-items: flex-start;
168 align-items: flex-start;
169 justify-content: flex-start;
169 justify-content: flex-start;
170 }
170 }
171 .swal2-container.swal2-top-end, .swal2-container.swal2-top-right {
171 .swal2-container.swal2-top-end, .swal2-container.swal2-top-right {
172 align-items: flex-start;
172 align-items: flex-start;
173 justify-content: flex-end;
173 justify-content: flex-end;
174 }
174 }
175 .swal2-container.swal2-center {
175 .swal2-container.swal2-center {
176 align-items: center;
176 align-items: center;
177 }
177 }
178 .swal2-container.swal2-center-start, .swal2-container.swal2-center-left {
178 .swal2-container.swal2-center-start, .swal2-container.swal2-center-left {
179 align-items: center;
179 align-items: center;
180 justify-content: flex-start;
180 justify-content: flex-start;
181 }
181 }
182 .swal2-container.swal2-center-end, .swal2-container.swal2-center-right {
182 .swal2-container.swal2-center-end, .swal2-container.swal2-center-right {
183 align-items: center;
183 align-items: center;
184 justify-content: flex-end;
184 justify-content: flex-end;
185 }
185 }
186 .swal2-container.swal2-bottom {
186 .swal2-container.swal2-bottom {
187 align-items: flex-end;
187 align-items: flex-end;
188 }
188 }
189 .swal2-container.swal2-bottom-start, .swal2-container.swal2-bottom-left {
189 .swal2-container.swal2-bottom-start, .swal2-container.swal2-bottom-left {
190 align-items: flex-end;
190 align-items: flex-end;
191 justify-content: flex-start;
191 justify-content: flex-start;
192 }
192 }
193 .swal2-container.swal2-bottom-end, .swal2-container.swal2-bottom-right {
193 .swal2-container.swal2-bottom-end, .swal2-container.swal2-bottom-right {
194 align-items: flex-end;
194 align-items: flex-end;
195 justify-content: flex-end;
195 justify-content: flex-end;
196 }
196 }
197 .swal2-container.swal2-bottom > :first-child, .swal2-container.swal2-bottom-start > :first-child, .swal2-container.swal2-bottom-left > :first-child, .swal2-container.swal2-bottom-end > :first-child, .swal2-container.swal2-bottom-right > :first-child {
197 .swal2-container.swal2-bottom > :first-child, .swal2-container.swal2-bottom-start > :first-child, .swal2-container.swal2-bottom-left > :first-child, .swal2-container.swal2-bottom-end > :first-child, .swal2-container.swal2-bottom-right > :first-child {
198 margin-top: auto;
198 margin-top: auto;
199 }
199 }
200 .swal2-container.swal2-grow-fullscreen > .swal2-modal {
200 .swal2-container.swal2-grow-fullscreen > .swal2-modal {
201 display: flex !important;
201 display: flex !important;
202 flex: 1;
202 flex: 1;
203 align-self: stretch;
203 align-self: stretch;
204 justify-content: center;
204 justify-content: center;
205 }
205 }
206 .swal2-container.swal2-grow-row > .swal2-modal {
206 .swal2-container.swal2-grow-row > .swal2-modal {
207 display: flex !important;
207 display: flex !important;
208 flex: 1;
208 flex: 1;
209 align-content: center;
209 align-content: center;
210 justify-content: center;
210 justify-content: center;
211 }
211 }
212 .swal2-container.swal2-grow-column {
212 .swal2-container.swal2-grow-column {
213 flex: 1;
213 flex: 1;
214 flex-direction: column;
214 flex-direction: column;
215 }
215 }
216 .swal2-container.swal2-grow-column.swal2-top, .swal2-container.swal2-grow-column.swal2-center, .swal2-container.swal2-grow-column.swal2-bottom {
216 .swal2-container.swal2-grow-column.swal2-top, .swal2-container.swal2-grow-column.swal2-center, .swal2-container.swal2-grow-column.swal2-bottom {
217 align-items: center;
217 align-items: center;
218 }
218 }
219 .swal2-container.swal2-grow-column.swal2-top-start, .swal2-container.swal2-grow-column.swal2-center-start, .swal2-container.swal2-grow-column.swal2-bottom-start, .swal2-container.swal2-grow-column.swal2-top-left, .swal2-container.swal2-grow-column.swal2-center-left, .swal2-container.swal2-grow-column.swal2-bottom-left {
219 .swal2-container.swal2-grow-column.swal2-top-start, .swal2-container.swal2-grow-column.swal2-center-start, .swal2-container.swal2-grow-column.swal2-bottom-start, .swal2-container.swal2-grow-column.swal2-top-left, .swal2-container.swal2-grow-column.swal2-center-left, .swal2-container.swal2-grow-column.swal2-bottom-left {
220 align-items: flex-start;
220 align-items: flex-start;
221 }
221 }
222 .swal2-container.swal2-grow-column.swal2-top-end, .swal2-container.swal2-grow-column.swal2-center-end, .swal2-container.swal2-grow-column.swal2-bottom-end, .swal2-container.swal2-grow-column.swal2-top-right, .swal2-container.swal2-grow-column.swal2-center-right, .swal2-container.swal2-grow-column.swal2-bottom-right {
222 .swal2-container.swal2-grow-column.swal2-top-end, .swal2-container.swal2-grow-column.swal2-center-end, .swal2-container.swal2-grow-column.swal2-bottom-end, .swal2-container.swal2-grow-column.swal2-top-right, .swal2-container.swal2-grow-column.swal2-center-right, .swal2-container.swal2-grow-column.swal2-bottom-right {
223 align-items: flex-end;
223 align-items: flex-end;
224 }
224 }
225 .swal2-container.swal2-grow-column > .swal2-modal {
225 .swal2-container.swal2-grow-column > .swal2-modal {
226 display: flex !important;
226 display: flex !important;
227 flex: 1;
227 flex: 1;
228 align-content: center;
228 align-content: center;
229 justify-content: center;
229 justify-content: center;
230 }
230 }
231 .swal2-container.swal2-no-transition {
231 .swal2-container.swal2-no-transition {
232 transition: none !important;
232 transition: none !important;
233 }
233 }
234 .swal2-container:not(.swal2-top):not(.swal2-top-start):not(.swal2-top-end):not(.swal2-top-left):not(.swal2-top-right):not(.swal2-center-start):not(.swal2-center-end):not(.swal2-center-left):not(.swal2-center-right):not(.swal2-bottom):not(.swal2-bottom-start):not(.swal2-bottom-end):not(.swal2-bottom-left):not(.swal2-bottom-right):not(.swal2-grow-fullscreen) > .swal2-modal {
234 .swal2-container:not(.swal2-top):not(.swal2-top-start):not(.swal2-top-end):not(.swal2-top-left):not(.swal2-top-right):not(.swal2-center-start):not(.swal2-center-end):not(.swal2-center-left):not(.swal2-center-right):not(.swal2-bottom):not(.swal2-bottom-start):not(.swal2-bottom-end):not(.swal2-bottom-left):not(.swal2-bottom-right):not(.swal2-grow-fullscreen) > .swal2-modal {
235 margin: auto;
235 margin: auto;
236 }
236 }
237 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
237 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
238 .swal2-container .swal2-modal {
238 .swal2-container .swal2-modal {
239 margin: 0 !important;
239 margin: 0 !important;
240 }
240 }
241 }
241 }
242
242
243 .swal2-popup {
243 .swal2-popup {
244 display: none;
244 display: none;
245 position: relative;
245 position: relative;
246 box-sizing: border-box;
246 box-sizing: border-box;
247 flex-direction: column;
247 flex-direction: column;
248 justify-content: center;
248 justify-content: center;
249 width: 32em;
249 width: 38em;
250 max-width: 100%;
250 max-width: 100%;
251 padding: 1.25em;
251 padding: 1.25em;
252 border: none;
252 border: none;
253 border-radius: 0.3125em;
253 border-radius: 0.3125em;
254 background: #fff;
254 background: #fff;
255 font-family: inherit;
255 font-family: inherit;
256 font-size: 1rem;
256 font-size: 1rem;
257 }
257 }
258 .swal2-popup:focus {
258 .swal2-popup:focus {
259 outline: none;
259 outline: none;
260 }
260 }
261 .swal2-popup.swal2-loading {
261 .swal2-popup.swal2-loading {
262 overflow-y: hidden;
262 overflow-y: hidden;
263 }
263 }
264
264
265 .swal2-header {
265 .swal2-header {
266 display: flex;
266 display: flex;
267 flex-direction: column;
267 flex-direction: column;
268 align-items: center;
268 align-items: center;
269 }
269 }
270
270
271 .swal2-title {
271 .swal2-title {
272 position: relative;
272 position: relative;
273 max-width: 100%;
273 max-width: 100%;
274 margin: 0 0 0.4em;
274 margin: 0 0 0.4em;
275 padding: 0;
275 padding: 0;
276 color: #595959;
276 color: #595959;
277 font-size: 1.875em;
277 font-size: 1.875em;
278 font-weight: 600;
278 font-weight: 600;
279 text-align: center;
279 text-align: center;
280 text-transform: none;
280 text-transform: none;
281 word-wrap: break-word;
281 word-wrap: break-word;
282 }
282 }
283
283
284 .swal2-actions {
284 .swal2-actions {
285 display: flex;
285 display: flex;
286 z-index: 1;
286 z-index: 1;
287 flex-wrap: wrap;
287 flex-wrap: wrap;
288 align-items: center;
288 align-items: center;
289 justify-content: center;
289 justify-content: center;
290 width: 100%;
290 width: 100%;
291 margin: 1.25em auto 0;
291 margin: 1.25em auto 0;
292 }
292 }
293 .swal2-actions:not(.swal2-loading) .swal2-styled[disabled] {
293 .swal2-actions:not(.swal2-loading) .swal2-styled[disabled] {
294 opacity: 0.4;
294 opacity: 0.4;
295 }
295 }
296 .swal2-actions:not(.swal2-loading) .swal2-styled:hover {
296 .swal2-actions:not(.swal2-loading) .swal2-styled:hover {
297 background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
297 background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1));
298 }
298 }
299 .swal2-actions:not(.swal2-loading) .swal2-styled:active {
299 .swal2-actions:not(.swal2-loading) .swal2-styled:active {
300 background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
300 background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2));
301 }
301 }
302 .swal2-actions.swal2-loading .swal2-styled.swal2-confirm {
302 .swal2-actions.swal2-loading .swal2-styled.swal2-confirm {
303 box-sizing: border-box;
303 box-sizing: border-box;
304 width: 2.5em;
304 width: 2.5em;
305 height: 2.5em;
305 height: 2.5em;
306 margin: 0.46875em;
306 margin: 0.46875em;
307 padding: 0;
307 padding: 0;
308 -webkit-animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
308 -webkit-animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
309 animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
309 animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
310 border: 0.25em solid transparent;
310 border: 0.25em solid transparent;
311 border-radius: 100%;
311 border-radius: 100%;
312 border-color: transparent;
312 border-color: transparent;
313 background-color: transparent !important;
313 background-color: transparent !important;
314 color: transparent !important;
314 color: transparent !important;
315 cursor: default;
315 cursor: default;
316 -webkit-user-select: none;
316 -webkit-user-select: none;
317 -moz-user-select: none;
317 -moz-user-select: none;
318 -ms-user-select: none;
318 -ms-user-select: none;
319 user-select: none;
319 user-select: none;
320 }
320 }
321 .swal2-actions.swal2-loading .swal2-styled.swal2-cancel {
321 .swal2-actions.swal2-loading .swal2-styled.swal2-cancel {
322 margin-right: 30px;
322 margin-right: 30px;
323 margin-left: 30px;
323 margin-left: 30px;
324 }
324 }
325 .swal2-actions.swal2-loading :not(.swal2-styled).swal2-confirm::after {
325 .swal2-actions.swal2-loading :not(.swal2-styled).swal2-confirm::after {
326 content: "";
326 content: "";
327 display: inline-block;
327 display: inline-block;
328 width: 15px;
328 width: 15px;
329 height: 15px;
329 height: 15px;
330 margin-left: 5px;
330 margin-left: 5px;
331 -webkit-animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
331 -webkit-animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
332 animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
332 animation: swal2-rotate-loading 1.5s linear 0s infinite normal;
333 border: 3px solid #999999;
333 border: 3px solid #999999;
334 border-radius: 50%;
334 border-radius: 50%;
335 border-right-color: transparent;
335 border-right-color: transparent;
336 box-shadow: 1px 1px 1px #fff;
336 box-shadow: 1px 1px 1px #fff;
337 }
337 }
338
338
339 .swal2-styled {
339 .swal2-styled {
340 margin: 0.3125em;
340 margin: 0.3125em;
341 padding: 0.625em 2em;
341 padding: 0.625em 2em;
342 box-shadow: none;
342 box-shadow: none;
343 font-weight: 500;
343 font-weight: 500;
344 }
344 }
345 .swal2-styled:not([disabled]) {
345 .swal2-styled:not([disabled]) {
346 cursor: pointer;
346 cursor: pointer;
347 }
347 }
348 .swal2-styled.swal2-confirm {
348 .swal2-styled.swal2-confirm {
349 border: 0;
349 border: 0;
350 border-radius: 0.25em;
350 border-radius: 0.25em;
351 background: initial;
351 background: initial;
352 background-color: @alert4;
352 background-color: @alert4;
353 color: #fff;
353 color: #fff;
354 font-size: 1.0625em;
354 font-size: 1.0625em;
355 }
355 }
356 .swal2-styled.swal2-cancel {
356 .swal2-styled.swal2-cancel {
357 border: 0;
357 border: 0;
358 border-radius: 0.25em;
358 border-radius: 0.25em;
359 background: initial;
359 background: initial;
360 background-color: #aaa;
360 background-color: #aaa;
361 color: #fff;
361 color: #fff;
362 font-size: 1.0625em;
362 font-size: 1.0625em;
363 }
363 }
364 .swal2-styled:focus {
364 .swal2-styled:focus {
365 outline: none;
365 outline: none;
366 box-shadow: 0 0 0 1px #fff, 0 0 0 3px rgba(50, 100, 150, 0.4);
366 box-shadow: 0 0 0 1px #fff, 0 0 0 3px rgba(50, 100, 150, 0.4);
367 }
367 }
368 .swal2-styled::-moz-focus-inner {
368 .swal2-styled::-moz-focus-inner {
369 border: 0;
369 border: 0;
370 }
370 }
371
371
372 .swal2-footer {
372 .swal2-footer {
373 justify-content: center;
373 justify-content: center;
374 margin: 1.25em 0 0;
374 margin: 1.25em 0 0;
375 padding: 1em 0 0;
375 padding: 1em 0 0;
376 border-top: 1px solid #eee;
376 border-top: 1px solid #eee;
377 color: #545454;
377 color: #545454;
378 font-size: 1em;
378 font-size: 1em;
379 }
379 }
380
380
381 .swal2-timer-progress-bar-container {
381 .swal2-timer-progress-bar-container {
382 position: absolute;
382 position: absolute;
383 right: 0;
383 right: 0;
384 bottom: 0;
384 bottom: 0;
385 left: 0;
385 left: 0;
386 height: 0.25em;
386 height: 0.25em;
387 overflow: hidden;
387 overflow: hidden;
388 border-bottom-right-radius: 0.3125em;
388 border-bottom-right-radius: 0.3125em;
389 border-bottom-left-radius: 0.3125em;
389 border-bottom-left-radius: 0.3125em;
390 }
390 }
391
391
392 .swal2-timer-progress-bar {
392 .swal2-timer-progress-bar {
393 width: 100%;
393 width: 100%;
394 height: 0.25em;
394 height: 0.25em;
395 background: rgba(0, 0, 0, 0.2);
395 background: rgba(0, 0, 0, 0.2);
396 }
396 }
397
397
398 .swal2-image {
398 .swal2-image {
399 max-width: 100%;
399 max-width: 100%;
400 margin: 1.25em auto;
400 margin: 1.25em auto;
401 }
401 }
402
402
403 .swal2-close {
403 .swal2-close {
404 position: absolute;
404 position: absolute;
405 z-index: 2;
405 z-index: 2;
406 top: 0;
406 top: 0;
407 right: 0;
407 right: 0;
408 align-items: center;
408 align-items: center;
409 justify-content: center;
409 justify-content: center;
410 width: 1.2em;
410 width: 1.2em;
411 height: 1.2em;
411 height: 1.2em;
412 padding: 0;
412 padding: 0;
413 overflow: hidden;
413 overflow: hidden;
414 transition: color 0.1s ease-out;
414 transition: color 0.1s ease-out;
415 border: none;
415 border: none;
416 border-radius: 0;
416 border-radius: 0;
417 background: transparent;
417 background: transparent;
418 color: #cccccc;
418 color: #cccccc;
419 font-family: serif;
419 font-family: serif;
420 font-size: 2.5em;
420 font-size: 2.5em;
421 line-height: 1.2;
421 line-height: 1.2;
422 cursor: pointer;
422 cursor: pointer;
423 }
423 }
424 .swal2-close:hover {
424 .swal2-close:hover {
425 transform: none;
425 transform: none;
426 background: transparent;
426 background: transparent;
427 color: #f27474;
427 color: #f27474;
428 }
428 }
429 .swal2-close::-moz-focus-inner {
429 .swal2-close::-moz-focus-inner {
430 border: 0;
430 border: 0;
431 }
431 }
432
432
433 .swal2-content {
433 .swal2-content {
434 z-index: 1;
434 z-index: 1;
435 justify-content: center;
435 justify-content: center;
436 margin: 0;
436 margin: 0;
437 padding: 0;
437 padding: 0;
438 color: #545454;
438 color: #545454;
439 font-size: 1.125em;
439 font-size: 1.125em;
440 font-weight: normal;
440 font-weight: normal;
441 line-height: normal;
441 line-height: normal;
442 text-align: center;
442 text-align: center;
443 word-wrap: break-word;
443 word-wrap: break-word;
444 }
444 }
445
445
446 .swal2-input,
446 .swal2-input,
447 .swal2-file,
447 .swal2-file,
448 .swal2-textarea,
448 .swal2-textarea,
449 .swal2-select,
449 .swal2-select,
450 .swal2-radio,
450 .swal2-radio,
451 .swal2-checkbox {
451 .swal2-checkbox {
452 margin: 1em auto;
452 margin: 1em auto;
453 }
453 }
454
454
455 .swal2-input,
455 .swal2-input,
456 .swal2-file,
456 .swal2-file,
457 .swal2-textarea {
457 .swal2-textarea {
458 box-sizing: border-box;
458 box-sizing: border-box;
459 width: 100%;
459 width: 100%;
460 transition: border-color 0.3s, box-shadow 0.3s;
460 transition: border-color 0.3s, box-shadow 0.3s;
461 border: 1px solid #d9d9d9;
461 border: 1px solid #d9d9d9;
462 border-radius: 0.1875em;
462 border-radius: 0.1875em;
463 background: inherit;
463 background: inherit;
464 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);
464 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);
465 color: inherit;
465 color: inherit;
466 font-size: 1.125em;
466 font-size: 1.125em;
467 }
467 }
468 .swal2-input.swal2-inputerror,
468 .swal2-input.swal2-inputerror,
469 .swal2-file.swal2-inputerror,
469 .swal2-file.swal2-inputerror,
470 .swal2-textarea.swal2-inputerror {
470 .swal2-textarea.swal2-inputerror {
471 border-color: #f27474 !important;
471 border-color: #f27474 !important;
472 box-shadow: 0 0 2px #f27474 !important;
472 box-shadow: 0 0 2px #f27474 !important;
473 }
473 }
474 .swal2-input:focus,
474 .swal2-input:focus,
475 .swal2-file:focus,
475 .swal2-file:focus,
476 .swal2-textarea:focus {
476 .swal2-textarea:focus {
477 border: 1px solid #b4dbed;
477 border: 1px solid #b4dbed;
478 outline: none;
478 outline: none;
479 box-shadow: 0 0 3px #c4e6f5;
479 box-shadow: 0 0 3px #c4e6f5;
480 }
480 }
481 .swal2-input::-webkit-input-placeholder, .swal2-file::-webkit-input-placeholder, .swal2-textarea::-webkit-input-placeholder {
481 .swal2-input::-webkit-input-placeholder, .swal2-file::-webkit-input-placeholder, .swal2-textarea::-webkit-input-placeholder {
482 color: #cccccc;
482 color: #cccccc;
483 }
483 }
484 .swal2-input::-moz-placeholder, .swal2-file::-moz-placeholder, .swal2-textarea::-moz-placeholder {
484 .swal2-input::-moz-placeholder, .swal2-file::-moz-placeholder, .swal2-textarea::-moz-placeholder {
485 color: #cccccc;
485 color: #cccccc;
486 }
486 }
487 .swal2-input:-ms-input-placeholder, .swal2-file:-ms-input-placeholder, .swal2-textarea:-ms-input-placeholder {
487 .swal2-input:-ms-input-placeholder, .swal2-file:-ms-input-placeholder, .swal2-textarea:-ms-input-placeholder {
488 color: #cccccc;
488 color: #cccccc;
489 }
489 }
490 .swal2-input::-ms-input-placeholder, .swal2-file::-ms-input-placeholder, .swal2-textarea::-ms-input-placeholder {
490 .swal2-input::-ms-input-placeholder, .swal2-file::-ms-input-placeholder, .swal2-textarea::-ms-input-placeholder {
491 color: #cccccc;
491 color: #cccccc;
492 }
492 }
493 .swal2-input::placeholder,
493 .swal2-input::placeholder,
494 .swal2-file::placeholder,
494 .swal2-file::placeholder,
495 .swal2-textarea::placeholder {
495 .swal2-textarea::placeholder {
496 color: #cccccc;
496 color: #cccccc;
497 }
497 }
498
498
499 .swal2-range {
499 .swal2-range {
500 margin: 1em auto;
500 margin: 1em auto;
501 background: #fff;
501 background: #fff;
502 }
502 }
503 .swal2-range input {
503 .swal2-range input {
504 width: 80%;
504 width: 80%;
505 }
505 }
506 .swal2-range output {
506 .swal2-range output {
507 width: 20%;
507 width: 20%;
508 color: inherit;
508 color: inherit;
509 font-weight: 600;
509 font-weight: 600;
510 text-align: center;
510 text-align: center;
511 }
511 }
512 .swal2-range input,
512 .swal2-range input,
513 .swal2-range output {
513 .swal2-range output {
514 height: 2.625em;
514 height: 2.625em;
515 padding: 0;
515 padding: 0;
516 font-size: 1.125em;
516 font-size: 1.125em;
517 line-height: 2.625em;
517 line-height: 2.625em;
518 }
518 }
519
519
520 .swal2-input {
520 .swal2-input {
521 height: 2.625em;
521 height: 2.625em;
522 padding: 0 0.75em;
522 padding: 0 0.75em;
523 }
523 }
524 .swal2-input[type=number] {
524 .swal2-input[type=number] {
525 max-width: 10em;
525 max-width: 10em;
526 }
526 }
527
527
528 .swal2-file {
528 .swal2-file {
529 background: inherit;
529 background: inherit;
530 font-size: 1.125em;
530 font-size: 1.125em;
531 }
531 }
532
532
533 .swal2-textarea {
533 .swal2-textarea {
534 height: 6.75em;
534 height: 6.75em;
535 padding: 0.75em;
535 padding: 0.75em;
536 }
536 }
537
537
538 .swal2-select {
538 .swal2-select {
539 min-width: 50%;
539 min-width: 50%;
540 max-width: 100%;
540 max-width: 100%;
541 padding: 0.375em 0.625em;
541 padding: 0.375em 0.625em;
542 background: inherit;
542 background: inherit;
543 color: inherit;
543 color: inherit;
544 font-size: 1.125em;
544 font-size: 1.125em;
545 }
545 }
546
546
547 .swal2-radio,
547 .swal2-radio,
548 .swal2-checkbox {
548 .swal2-checkbox {
549 align-items: center;
549 align-items: center;
550 justify-content: center;
550 justify-content: center;
551 background: #fff;
551 background: #fff;
552 color: inherit;
552 color: inherit;
553 }
553 }
554 .swal2-radio label,
554 .swal2-radio label,
555 .swal2-checkbox label {
555 .swal2-checkbox label {
556 margin: 0 0.6em;
556 margin: 0 0.6em;
557 font-size: 1.125em;
557 font-size: 1.125em;
558 }
558 }
559 .swal2-radio input,
559 .swal2-radio input,
560 .swal2-checkbox input {
560 .swal2-checkbox input {
561 margin: 0 0.4em;
561 margin: 0 0.4em;
562 }
562 }
563
563
564 .swal2-validation-message {
564 .swal2-validation-message {
565 display: none;
565 display: none;
566 align-items: center;
566 align-items: center;
567 justify-content: center;
567 justify-content: center;
568 padding: 0.625em;
568 padding: 0.625em;
569 overflow: hidden;
569 overflow: hidden;
570 background: #f0f0f0;
570 background: #f0f0f0;
571 color: #666666;
571 color: #666666;
572 font-size: 1em;
572 font-size: 1em;
573 font-weight: 300;
573 font-weight: 300;
574 }
574 }
575 .swal2-validation-message::before {
575 .swal2-validation-message::before {
576 content: "!";
576 content: "!";
577 display: inline-block;
577 display: inline-block;
578 width: 1.5em;
578 width: 1.5em;
579 min-width: 1.5em;
579 min-width: 1.5em;
580 height: 1.5em;
580 height: 1.5em;
581 margin: 0 0.625em;
581 margin: 0 0.625em;
582 border-radius: 50%;
582 border-radius: 50%;
583 background-color: #f27474;
583 background-color: #f27474;
584 color: #fff;
584 color: #fff;
585 font-weight: 600;
585 font-weight: 600;
586 line-height: 1.5em;
586 line-height: 1.5em;
587 text-align: center;
587 text-align: center;
588 }
588 }
589
589
590 .swal2-icon {
590 .swal2-icon {
591 position: relative;
591 position: relative;
592 box-sizing: content-box;
592 box-sizing: content-box;
593 justify-content: center;
593 justify-content: center;
594 width: 5em;
594 width: 5em;
595 height: 5em;
595 height: 5em;
596 margin: 1.25em auto 1.875em;
596 margin: 1.25em auto 1.875em;
597 border: 0.25em solid transparent;
597 border: 0.25em solid transparent;
598 border-radius: 50%;
598 border-radius: 50%;
599 font-family: inherit;
599 font-family: inherit;
600 line-height: 5em;
600 line-height: 5em;
601 cursor: default;
601 cursor: default;
602 -webkit-user-select: none;
602 -webkit-user-select: none;
603 -moz-user-select: none;
603 -moz-user-select: none;
604 -ms-user-select: none;
604 -ms-user-select: none;
605 user-select: none;
605 user-select: none;
606 }
606 }
607 .swal2-icon .swal2-icon-content {
607 .swal2-icon .swal2-icon-content {
608 display: flex;
608 display: flex;
609 align-items: center;
609 align-items: center;
610 font-size: 3.75em;
610 font-size: 3.75em;
611 }
611 }
612 .swal2-icon.swal2-error {
612 .swal2-icon.swal2-error {
613 border-color: @alert2;
613 border-color: @alert2;
614 color: @alert2;
614 color: @alert2;
615 }
615 }
616 .swal2-icon.swal2-error .swal2-x-mark {
616 .swal2-icon.swal2-error .swal2-x-mark {
617 position: relative;
617 position: relative;
618 flex-grow: 1;
618 flex-grow: 1;
619 }
619 }
620 .swal2-icon.swal2-error [class^=swal2-x-mark-line] {
620 .swal2-icon.swal2-error [class^=swal2-x-mark-line] {
621 display: block;
621 display: block;
622 position: absolute;
622 position: absolute;
623 top: 2.3125em;
623 top: 2.3125em;
624 width: 2.9375em;
624 width: 2.9375em;
625 height: 0.3125em;
625 height: 0.3125em;
626 border-radius: 0.125em;
626 border-radius: 0.125em;
627 background-color: @alert2;
627 background-color: @alert2;
628 }
628 }
629 .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
629 .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
630 left: 1.0625em;
630 left: 1.0625em;
631 transform: rotate(45deg);
631 transform: rotate(45deg);
632 }
632 }
633 .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
633 .swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
634 right: 1em;
634 right: 1em;
635 transform: rotate(-45deg);
635 transform: rotate(-45deg);
636 }
636 }
637 .swal2-icon.swal2-error.swal2-icon-show {
637 .swal2-icon.swal2-error.swal2-icon-show {
638 //-webkit-animation: swal2-animate-error-icon 0.5s;
638 //-webkit-animation: swal2-animate-error-icon 0.5s;
639 // animation: swal2-animate-error-icon 0.5s;
639 // animation: swal2-animate-error-icon 0.5s;
640 }
640 }
641 .swal2-icon.swal2-error.swal2-icon-show .swal2-x-mark {
641 .swal2-icon.swal2-error.swal2-icon-show .swal2-x-mark {
642 //-webkit-animation: swal2-animate-error-x-mark 0.5s;
642 //-webkit-animation: swal2-animate-error-x-mark 0.5s;
643 // animation: swal2-animate-error-x-mark 0.5s;
643 // animation: swal2-animate-error-x-mark 0.5s;
644 }
644 }
645 .swal2-icon.swal2-warning {
645 .swal2-icon.swal2-warning {
646 border-color: @alert3;
646 border-color: @alert3;
647 color: @alert3;
647 color: @alert3;
648 }
648 }
649 .swal2-icon.swal2-info {
649 .swal2-icon.swal2-info {
650 border-color: #9de0f6;
650 border-color: #9de0f6;
651 color: #3fc3ee;
651 color: #3fc3ee;
652 }
652 }
653 .swal2-icon.swal2-question {
653 .swal2-icon.swal2-question {
654 border-color: #c9dae1;
654 border-color: #c9dae1;
655 color: #87adbd;
655 color: #87adbd;
656 }
656 }
657 .swal2-icon.swal2-success {
657 .swal2-icon.swal2-success {
658 border-color: @alert1;
658 border-color: @alert1;
659 color: @alert1;
659 color: @alert1;
660 }
660 }
661 .swal2-icon.swal2-success [class^=swal2-success-circular-line] {
661 .swal2-icon.swal2-success [class^=swal2-success-circular-line] {
662 position: absolute;
662 position: absolute;
663 width: 3.75em;
663 width: 3.75em;
664 height: 7.5em;
664 height: 7.5em;
665 transform: rotate(45deg);
665 transform: rotate(45deg);
666 border-radius: 50%;
666 border-radius: 50%;
667 }
667 }
668 .swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left] {
668 .swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left] {
669 top: -0.4375em;
669 top: -0.4375em;
670 left: -2.0635em;
670 left: -2.0635em;
671 transform: rotate(-45deg);
671 transform: rotate(-45deg);
672 transform-origin: 3.75em 3.75em;
672 transform-origin: 3.75em 3.75em;
673 border-radius: 7.5em 0 0 7.5em;
673 border-radius: 7.5em 0 0 7.5em;
674 }
674 }
675 .swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right] {
675 .swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right] {
676 top: -0.6875em;
676 top: -0.6875em;
677 left: 1.875em;
677 left: 1.875em;
678 transform: rotate(-45deg);
678 transform: rotate(-45deg);
679 transform-origin: 0 3.75em;
679 transform-origin: 0 3.75em;
680 border-radius: 0 7.5em 7.5em 0;
680 border-radius: 0 7.5em 7.5em 0;
681 }
681 }
682 .swal2-icon.swal2-success .swal2-success-ring {
682 .swal2-icon.swal2-success .swal2-success-ring {
683 position: absolute;
683 position: absolute;
684 z-index: 2;
684 z-index: 2;
685 top: -0.25em;
685 top: -0.25em;
686 left: -0.25em;
686 left: -0.25em;
687 box-sizing: content-box;
687 box-sizing: content-box;
688 width: 100%;
688 width: 100%;
689 height: 100%;
689 height: 100%;
690 border: 0.25em solid rgba(165, 220, 134, 0.3);
690 border: 0.25em solid rgba(165, 220, 134, 0.3);
691 border-radius: 50%;
691 border-radius: 50%;
692 }
692 }
693 .swal2-icon.swal2-success .swal2-success-fix {
693 .swal2-icon.swal2-success .swal2-success-fix {
694 position: absolute;
694 position: absolute;
695 z-index: 1;
695 z-index: 1;
696 top: 0.5em;
696 top: 0.5em;
697 left: 1.625em;
697 left: 1.625em;
698 width: 0.4375em;
698 width: 0.4375em;
699 height: 5.625em;
699 height: 5.625em;
700 transform: rotate(-45deg);
700 transform: rotate(-45deg);
701 }
701 }
702 .swal2-icon.swal2-success [class^=swal2-success-line] {
702 .swal2-icon.swal2-success [class^=swal2-success-line] {
703 display: block;
703 display: block;
704 position: absolute;
704 position: absolute;
705 z-index: 2;
705 z-index: 2;
706 height: 0.3125em;
706 height: 0.3125em;
707 border-radius: 0.125em;
707 border-radius: 0.125em;
708 background-color: @alert1;
708 background-color: @alert1;
709 }
709 }
710 .swal2-icon.swal2-success [class^=swal2-success-line][class$=tip] {
710 .swal2-icon.swal2-success [class^=swal2-success-line][class$=tip] {
711 top: 2.875em;
711 top: 2.875em;
712 left: 0.8125em;
712 left: 0.8125em;
713 width: 1.5625em;
713 width: 1.5625em;
714 transform: rotate(45deg);
714 transform: rotate(45deg);
715 }
715 }
716 .swal2-icon.swal2-success [class^=swal2-success-line][class$=long] {
716 .swal2-icon.swal2-success [class^=swal2-success-line][class$=long] {
717 top: 2.375em;
717 top: 2.375em;
718 right: 0.5em;
718 right: 0.5em;
719 width: 2.9375em;
719 width: 2.9375em;
720 transform: rotate(-45deg);
720 transform: rotate(-45deg);
721 }
721 }
722 .swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-tip {
722 .swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-tip {
723 -webkit-animation: swal2-animate-success-line-tip 0.75s;
723 -webkit-animation: swal2-animate-success-line-tip 0.75s;
724 animation: swal2-animate-success-line-tip 0.75s;
724 animation: swal2-animate-success-line-tip 0.75s;
725 }
725 }
726 .swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-long {
726 .swal2-icon.swal2-success.swal2-icon-show .swal2-success-line-long {
727 -webkit-animation: swal2-animate-success-line-long 0.75s;
727 -webkit-animation: swal2-animate-success-line-long 0.75s;
728 animation: swal2-animate-success-line-long 0.75s;
728 animation: swal2-animate-success-line-long 0.75s;
729 }
729 }
730 .swal2-icon.swal2-success.swal2-icon-show .swal2-success-circular-line-right {
730 .swal2-icon.swal2-success.swal2-icon-show .swal2-success-circular-line-right {
731 -webkit-animation: swal2-rotate-success-circular-line 4.25s ease-in;
731 -webkit-animation: swal2-rotate-success-circular-line 4.25s ease-in;
732 animation: swal2-rotate-success-circular-line 4.25s ease-in;
732 animation: swal2-rotate-success-circular-line 4.25s ease-in;
733 }
733 }
734
734
735 .swal2-progress-steps {
735 .swal2-progress-steps {
736 align-items: center;
736 align-items: center;
737 margin: 0 0 1.25em;
737 margin: 0 0 1.25em;
738 padding: 0;
738 padding: 0;
739 background: inherit;
739 background: inherit;
740 font-weight: 600;
740 font-weight: 600;
741 }
741 }
742 .swal2-progress-steps li {
742 .swal2-progress-steps li {
743 display: inline-block;
743 display: inline-block;
744 position: relative;
744 position: relative;
745 }
745 }
746 .swal2-progress-steps .swal2-progress-step {
746 .swal2-progress-steps .swal2-progress-step {
747 z-index: 20;
747 z-index: 20;
748 width: 2em;
748 width: 2em;
749 height: 2em;
749 height: 2em;
750 border-radius: 2em;
750 border-radius: 2em;
751 background: #3085d6;
751 background: #3085d6;
752 color: #fff;
752 color: #fff;
753 line-height: 2em;
753 line-height: 2em;
754 text-align: center;
754 text-align: center;
755 }
755 }
756 .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step {
756 .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step {
757 background: #3085d6;
757 background: #3085d6;
758 }
758 }
759 .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step ~ .swal2-progress-step {
759 .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step ~ .swal2-progress-step {
760 background: #add8e6;
760 background: #add8e6;
761 color: #fff;
761 color: #fff;
762 }
762 }
763 .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step ~ .swal2-progress-step-line {
763 .swal2-progress-steps .swal2-progress-step.swal2-active-progress-step ~ .swal2-progress-step-line {
764 background: #add8e6;
764 background: #add8e6;
765 }
765 }
766 .swal2-progress-steps .swal2-progress-step-line {
766 .swal2-progress-steps .swal2-progress-step-line {
767 z-index: 10;
767 z-index: 10;
768 width: 2.5em;
768 width: 2.5em;
769 height: 0.4em;
769 height: 0.4em;
770 margin: 0 -1px;
770 margin: 0 -1px;
771 background: #3085d6;
771 background: #3085d6;
772 }
772 }
773
773
774 [class^=swal2] {
774 [class^=swal2] {
775 -webkit-tap-highlight-color: transparent;
775 -webkit-tap-highlight-color: transparent;
776 }
776 }
777
777
778 .swal2-show {
778 .swal2-show {
779 -webkit-animation: swal2-show 0.3s;
779 -webkit-animation: swal2-show 0.3s;
780 animation: swal2-show 0.3s;
780 animation: swal2-show 0.3s;
781 }
781 }
782
782
783 .swal2-hide {
783 .swal2-hide {
784 -webkit-animation: swal2-hide 0.15s forwards;
784 -webkit-animation: swal2-hide 0.15s forwards;
785 animation: swal2-hide 0.15s forwards;
785 animation: swal2-hide 0.15s forwards;
786 }
786 }
787
787
788 .swal2-noanimation {
788 .swal2-noanimation {
789 transition: none;
789 transition: none;
790 }
790 }
791
791
792 .swal2-scrollbar-measure {
792 .swal2-scrollbar-measure {
793 position: absolute;
793 position: absolute;
794 top: -9999px;
794 top: -9999px;
795 width: 50px;
795 width: 50px;
796 height: 50px;
796 height: 50px;
797 overflow: scroll;
797 overflow: scroll;
798 }
798 }
799
799
800 .swal2-rtl .swal2-close {
800 .swal2-rtl .swal2-close {
801 right: auto;
801 right: auto;
802 left: 0;
802 left: 0;
803 }
803 }
804 .swal2-rtl .swal2-timer-progress-bar {
804 .swal2-rtl .swal2-timer-progress-bar {
805 right: 0;
805 right: 0;
806 left: auto;
806 left: auto;
807 }
807 }
808
808
809 @supports (-ms-accelerator: true) {
809 @supports (-ms-accelerator: true) {
810 .swal2-range input {
810 .swal2-range input {
811 width: 100% !important;
811 width: 100% !important;
812 }
812 }
813 .swal2-range output {
813 .swal2-range output {
814 display: none;
814 display: none;
815 }
815 }
816 }
816 }
817 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
817 @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
818 .swal2-range input {
818 .swal2-range input {
819 width: 100% !important;
819 width: 100% !important;
820 }
820 }
821 .swal2-range output {
821 .swal2-range output {
822 display: none;
822 display: none;
823 }
823 }
824 }
824 }
825 @-moz-document url-prefix() {
825 @-moz-document url-prefix() {
826 .swal2-close:focus {
826 .swal2-close:focus {
827 outline: 2px solid rgba(50, 100, 150, 0.4);
827 outline: 2px solid rgba(50, 100, 150, 0.4);
828 }
828 }
829 }
829 }
830 @-webkit-keyframes swal2-toast-show {
830 @-webkit-keyframes swal2-toast-show {
831 0% {
831 0% {
832 transform: translateY(-0.625em) rotateZ(2deg);
832 transform: translateY(-0.625em) rotateZ(2deg);
833 }
833 }
834 33% {
834 33% {
835 transform: translateY(0) rotateZ(-2deg);
835 transform: translateY(0) rotateZ(-2deg);
836 }
836 }
837 66% {
837 66% {
838 transform: translateY(0.3125em) rotateZ(2deg);
838 transform: translateY(0.3125em) rotateZ(2deg);
839 }
839 }
840 100% {
840 100% {
841 transform: translateY(0) rotateZ(0deg);
841 transform: translateY(0) rotateZ(0deg);
842 }
842 }
843 }
843 }
844 @keyframes swal2-toast-show {
844 @keyframes swal2-toast-show {
845 0% {
845 0% {
846 transform: translateY(-0.625em) rotateZ(2deg);
846 transform: translateY(-0.625em) rotateZ(2deg);
847 }
847 }
848 33% {
848 33% {
849 transform: translateY(0) rotateZ(-2deg);
849 transform: translateY(0) rotateZ(-2deg);
850 }
850 }
851 66% {
851 66% {
852 transform: translateY(0.3125em) rotateZ(2deg);
852 transform: translateY(0.3125em) rotateZ(2deg);
853 }
853 }
854 100% {
854 100% {
855 transform: translateY(0) rotateZ(0deg);
855 transform: translateY(0) rotateZ(0deg);
856 }
856 }
857 }
857 }
858 @-webkit-keyframes swal2-toast-hide {
858 @-webkit-keyframes swal2-toast-hide {
859 100% {
859 100% {
860 transform: rotateZ(1deg);
860 transform: rotateZ(1deg);
861 opacity: 0;
861 opacity: 0;
862 }
862 }
863 }
863 }
864 @keyframes swal2-toast-hide {
864 @keyframes swal2-toast-hide {
865 100% {
865 100% {
866 transform: rotateZ(1deg);
866 transform: rotateZ(1deg);
867 opacity: 0;
867 opacity: 0;
868 }
868 }
869 }
869 }
870 @-webkit-keyframes swal2-toast-animate-success-line-tip {
870 @-webkit-keyframes swal2-toast-animate-success-line-tip {
871 0% {
871 0% {
872 top: 0.5625em;
872 top: 0.5625em;
873 left: 0.0625em;
873 left: 0.0625em;
874 width: 0;
874 width: 0;
875 }
875 }
876 54% {
876 54% {
877 top: 0.125em;
877 top: 0.125em;
878 left: 0.125em;
878 left: 0.125em;
879 width: 0;
879 width: 0;
880 }
880 }
881 70% {
881 70% {
882 top: 0.625em;
882 top: 0.625em;
883 left: -0.25em;
883 left: -0.25em;
884 width: 1.625em;
884 width: 1.625em;
885 }
885 }
886 84% {
886 84% {
887 top: 1.0625em;
887 top: 1.0625em;
888 left: 0.75em;
888 left: 0.75em;
889 width: 0.5em;
889 width: 0.5em;
890 }
890 }
891 100% {
891 100% {
892 top: 1.125em;
892 top: 1.125em;
893 left: 0.1875em;
893 left: 0.1875em;
894 width: 0.75em;
894 width: 0.75em;
895 }
895 }
896 }
896 }
897 @keyframes swal2-toast-animate-success-line-tip {
897 @keyframes swal2-toast-animate-success-line-tip {
898 0% {
898 0% {
899 top: 0.5625em;
899 top: 0.5625em;
900 left: 0.0625em;
900 left: 0.0625em;
901 width: 0;
901 width: 0;
902 }
902 }
903 54% {
903 54% {
904 top: 0.125em;
904 top: 0.125em;
905 left: 0.125em;
905 left: 0.125em;
906 width: 0;
906 width: 0;
907 }
907 }
908 70% {
908 70% {
909 top: 0.625em;
909 top: 0.625em;
910 left: -0.25em;
910 left: -0.25em;
911 width: 1.625em;
911 width: 1.625em;
912 }
912 }
913 84% {
913 84% {
914 top: 1.0625em;
914 top: 1.0625em;
915 left: 0.75em;
915 left: 0.75em;
916 width: 0.5em;
916 width: 0.5em;
917 }
917 }
918 100% {
918 100% {
919 top: 1.125em;
919 top: 1.125em;
920 left: 0.1875em;
920 left: 0.1875em;
921 width: 0.75em;
921 width: 0.75em;
922 }
922 }
923 }
923 }
924 @-webkit-keyframes swal2-toast-animate-success-line-long {
924 @-webkit-keyframes swal2-toast-animate-success-line-long {
925 0% {
925 0% {
926 top: 1.625em;
926 top: 1.625em;
927 right: 1.375em;
927 right: 1.375em;
928 width: 0;
928 width: 0;
929 }
929 }
930 65% {
930 65% {
931 top: 1.25em;
931 top: 1.25em;
932 right: 0.9375em;
932 right: 0.9375em;
933 width: 0;
933 width: 0;
934 }
934 }
935 84% {
935 84% {
936 top: 0.9375em;
936 top: 0.9375em;
937 right: 0;
937 right: 0;
938 width: 1.125em;
938 width: 1.125em;
939 }
939 }
940 100% {
940 100% {
941 top: 0.9375em;
941 top: 0.9375em;
942 right: 0.1875em;
942 right: 0.1875em;
943 width: 1.375em;
943 width: 1.375em;
944 }
944 }
945 }
945 }
946 @keyframes swal2-toast-animate-success-line-long {
946 @keyframes swal2-toast-animate-success-line-long {
947 0% {
947 0% {
948 top: 1.625em;
948 top: 1.625em;
949 right: 1.375em;
949 right: 1.375em;
950 width: 0;
950 width: 0;
951 }
951 }
952 65% {
952 65% {
953 top: 1.25em;
953 top: 1.25em;
954 right: 0.9375em;
954 right: 0.9375em;
955 width: 0;
955 width: 0;
956 }
956 }
957 84% {
957 84% {
958 top: 0.9375em;
958 top: 0.9375em;
959 right: 0;
959 right: 0;
960 width: 1.125em;
960 width: 1.125em;
961 }
961 }
962 100% {
962 100% {
963 top: 0.9375em;
963 top: 0.9375em;
964 right: 0.1875em;
964 right: 0.1875em;
965 width: 1.375em;
965 width: 1.375em;
966 }
966 }
967 }
967 }
968 @-webkit-keyframes swal2-show {
968 @-webkit-keyframes swal2-show {
969 0% {
969 0% {
970 transform: scale(0.7);
970 transform: scale(0.7);
971 }
971 }
972 45% {
972 45% {
973 transform: scale(1.05);
973 transform: scale(1.05);
974 }
974 }
975 80% {
975 80% {
976 transform: scale(0.95);
976 transform: scale(0.95);
977 }
977 }
978 100% {
978 100% {
979 transform: scale(1);
979 transform: scale(1);
980 }
980 }
981 }
981 }
982 @keyframes swal2-show {
982 @keyframes swal2-show {
983 0% {
983 0% {
984 transform: scale(0.7);
984 transform: scale(0.7);
985 }
985 }
986 45% {
986 45% {
987 transform: scale(1.05);
987 transform: scale(1.05);
988 }
988 }
989 80% {
989 80% {
990 transform: scale(0.95);
990 transform: scale(0.95);
991 }
991 }
992 100% {
992 100% {
993 transform: scale(1);
993 transform: scale(1);
994 }
994 }
995 }
995 }
996 @-webkit-keyframes swal2-hide {
996 @-webkit-keyframes swal2-hide {
997 0% {
997 0% {
998 transform: scale(1);
998 transform: scale(1);
999 opacity: 1;
999 opacity: 1;
1000 }
1000 }
1001 100% {
1001 100% {
1002 transform: scale(0.5);
1002 transform: scale(0.5);
1003 opacity: 0;
1003 opacity: 0;
1004 }
1004 }
1005 }
1005 }
1006 @keyframes swal2-hide {
1006 @keyframes swal2-hide {
1007 0% {
1007 0% {
1008 transform: scale(1);
1008 transform: scale(1);
1009 opacity: 1;
1009 opacity: 1;
1010 }
1010 }
1011 100% {
1011 100% {
1012 transform: scale(0.5);
1012 transform: scale(0.5);
1013 opacity: 0;
1013 opacity: 0;
1014 }
1014 }
1015 }
1015 }
1016 @-webkit-keyframes swal2-animate-success-line-tip {
1016 @-webkit-keyframes swal2-animate-success-line-tip {
1017 0% {
1017 0% {
1018 top: 1.1875em;
1018 top: 1.1875em;
1019 left: 0.0625em;
1019 left: 0.0625em;
1020 width: 0;
1020 width: 0;
1021 }
1021 }
1022 54% {
1022 54% {
1023 top: 1.0625em;
1023 top: 1.0625em;
1024 left: 0.125em;
1024 left: 0.125em;
1025 width: 0;
1025 width: 0;
1026 }
1026 }
1027 70% {
1027 70% {
1028 top: 2.1875em;
1028 top: 2.1875em;
1029 left: -0.375em;
1029 left: -0.375em;
1030 width: 3.125em;
1030 width: 3.125em;
1031 }
1031 }
1032 84% {
1032 84% {
1033 top: 3em;
1033 top: 3em;
1034 left: 1.3125em;
1034 left: 1.3125em;
1035 width: 1.0625em;
1035 width: 1.0625em;
1036 }
1036 }
1037 100% {
1037 100% {
1038 top: 2.8125em;
1038 top: 2.8125em;
1039 left: 0.8125em;
1039 left: 0.8125em;
1040 width: 1.5625em;
1040 width: 1.5625em;
1041 }
1041 }
1042 }
1042 }
1043 @keyframes swal2-animate-success-line-tip {
1043 @keyframes swal2-animate-success-line-tip {
1044 0% {
1044 0% {
1045 top: 1.1875em;
1045 top: 1.1875em;
1046 left: 0.0625em;
1046 left: 0.0625em;
1047 width: 0;
1047 width: 0;
1048 }
1048 }
1049 54% {
1049 54% {
1050 top: 1.0625em;
1050 top: 1.0625em;
1051 left: 0.125em;
1051 left: 0.125em;
1052 width: 0;
1052 width: 0;
1053 }
1053 }
1054 70% {
1054 70% {
1055 top: 2.1875em;
1055 top: 2.1875em;
1056 left: -0.375em;
1056 left: -0.375em;
1057 width: 3.125em;
1057 width: 3.125em;
1058 }
1058 }
1059 84% {
1059 84% {
1060 top: 3em;
1060 top: 3em;
1061 left: 1.3125em;
1061 left: 1.3125em;
1062 width: 1.0625em;
1062 width: 1.0625em;
1063 }
1063 }
1064 100% {
1064 100% {
1065 top: 2.8125em;
1065 top: 2.8125em;
1066 left: 0.8125em;
1066 left: 0.8125em;
1067 width: 1.5625em;
1067 width: 1.5625em;
1068 }
1068 }
1069 }
1069 }
1070 @-webkit-keyframes swal2-animate-success-line-long {
1070 @-webkit-keyframes swal2-animate-success-line-long {
1071 0% {
1071 0% {
1072 top: 3.375em;
1072 top: 3.375em;
1073 right: 2.875em;
1073 right: 2.875em;
1074 width: 0;
1074 width: 0;
1075 }
1075 }
1076 65% {
1076 65% {
1077 top: 3.375em;
1077 top: 3.375em;
1078 right: 2.875em;
1078 right: 2.875em;
1079 width: 0;
1079 width: 0;
1080 }
1080 }
1081 84% {
1081 84% {
1082 top: 2.1875em;
1082 top: 2.1875em;
1083 right: 0;
1083 right: 0;
1084 width: 3.4375em;
1084 width: 3.4375em;
1085 }
1085 }
1086 100% {
1086 100% {
1087 top: 2.375em;
1087 top: 2.375em;
1088 right: 0.5em;
1088 right: 0.5em;
1089 width: 2.9375em;
1089 width: 2.9375em;
1090 }
1090 }
1091 }
1091 }
1092 @keyframes swal2-animate-success-line-long {
1092 @keyframes swal2-animate-success-line-long {
1093 0% {
1093 0% {
1094 top: 3.375em;
1094 top: 3.375em;
1095 right: 2.875em;
1095 right: 2.875em;
1096 width: 0;
1096 width: 0;
1097 }
1097 }
1098 65% {
1098 65% {
1099 top: 3.375em;
1099 top: 3.375em;
1100 right: 2.875em;
1100 right: 2.875em;
1101 width: 0;
1101 width: 0;
1102 }
1102 }
1103 84% {
1103 84% {
1104 top: 2.1875em;
1104 top: 2.1875em;
1105 right: 0;
1105 right: 0;
1106 width: 3.4375em;
1106 width: 3.4375em;
1107 }
1107 }
1108 100% {
1108 100% {
1109 top: 2.375em;
1109 top: 2.375em;
1110 right: 0.5em;
1110 right: 0.5em;
1111 width: 2.9375em;
1111 width: 2.9375em;
1112 }
1112 }
1113 }
1113 }
1114 @-webkit-keyframes swal2-rotate-success-circular-line {
1114 @-webkit-keyframes swal2-rotate-success-circular-line {
1115 0% {
1115 0% {
1116 transform: rotate(-45deg);
1116 transform: rotate(-45deg);
1117 }
1117 }
1118 5% {
1118 5% {
1119 transform: rotate(-45deg);
1119 transform: rotate(-45deg);
1120 }
1120 }
1121 12% {
1121 12% {
1122 transform: rotate(-405deg);
1122 transform: rotate(-405deg);
1123 }
1123 }
1124 100% {
1124 100% {
1125 transform: rotate(-405deg);
1125 transform: rotate(-405deg);
1126 }
1126 }
1127 }
1127 }
1128 @keyframes swal2-rotate-success-circular-line {
1128 @keyframes swal2-rotate-success-circular-line {
1129 0% {
1129 0% {
1130 transform: rotate(-45deg);
1130 transform: rotate(-45deg);
1131 }
1131 }
1132 5% {
1132 5% {
1133 transform: rotate(-45deg);
1133 transform: rotate(-45deg);
1134 }
1134 }
1135 12% {
1135 12% {
1136 transform: rotate(-405deg);
1136 transform: rotate(-405deg);
1137 }
1137 }
1138 100% {
1138 100% {
1139 transform: rotate(-405deg);
1139 transform: rotate(-405deg);
1140 }
1140 }
1141 }
1141 }
1142 @-webkit-keyframes swal2-animate-error-x-mark {
1142 @-webkit-keyframes swal2-animate-error-x-mark {
1143 0% {
1143 0% {
1144 margin-top: 1.625em;
1144 margin-top: 1.625em;
1145 transform: scale(0.4);
1145 transform: scale(0.4);
1146 opacity: 0;
1146 opacity: 0;
1147 }
1147 }
1148 50% {
1148 50% {
1149 margin-top: 1.625em;
1149 margin-top: 1.625em;
1150 transform: scale(0.4);
1150 transform: scale(0.4);
1151 opacity: 0;
1151 opacity: 0;
1152 }
1152 }
1153 80% {
1153 80% {
1154 margin-top: -0.375em;
1154 margin-top: -0.375em;
1155 transform: scale(1.15);
1155 transform: scale(1.15);
1156 }
1156 }
1157 100% {
1157 100% {
1158 margin-top: 0;
1158 margin-top: 0;
1159 transform: scale(1);
1159 transform: scale(1);
1160 opacity: 1;
1160 opacity: 1;
1161 }
1161 }
1162 }
1162 }
1163 @keyframes swal2-animate-error-x-mark {
1163 @keyframes swal2-animate-error-x-mark {
1164 0% {
1164 0% {
1165 margin-top: 1.625em;
1165 margin-top: 1.625em;
1166 transform: scale(0.4);
1166 transform: scale(0.4);
1167 opacity: 0;
1167 opacity: 0;
1168 }
1168 }
1169 50% {
1169 50% {
1170 margin-top: 1.625em;
1170 margin-top: 1.625em;
1171 transform: scale(0.4);
1171 transform: scale(0.4);
1172 opacity: 0;
1172 opacity: 0;
1173 }
1173 }
1174 80% {
1174 80% {
1175 margin-top: -0.375em;
1175 margin-top: -0.375em;
1176 transform: scale(1.15);
1176 transform: scale(1.15);
1177 }
1177 }
1178 100% {
1178 100% {
1179 margin-top: 0;
1179 margin-top: 0;
1180 transform: scale(1);
1180 transform: scale(1);
1181 opacity: 1;
1181 opacity: 1;
1182 }
1182 }
1183 }
1183 }
1184 @-webkit-keyframes swal2-animate-error-icon {
1184 @-webkit-keyframes swal2-animate-error-icon {
1185 0% {
1185 0% {
1186 transform: rotateX(100deg);
1186 transform: rotateX(100deg);
1187 opacity: 0;
1187 opacity: 0;
1188 }
1188 }
1189 100% {
1189 100% {
1190 transform: rotateX(0deg);
1190 transform: rotateX(0deg);
1191 opacity: 1;
1191 opacity: 1;
1192 }
1192 }
1193 }
1193 }
1194 @keyframes swal2-animate-error-icon {
1194 @keyframes swal2-animate-error-icon {
1195 0% {
1195 0% {
1196 transform: rotateX(100deg);
1196 transform: rotateX(100deg);
1197 opacity: 0;
1197 opacity: 0;
1198 }
1198 }
1199 100% {
1199 100% {
1200 transform: rotateX(0deg);
1200 transform: rotateX(0deg);
1201 opacity: 1;
1201 opacity: 1;
1202 }
1202 }
1203 }
1203 }
1204 @-webkit-keyframes swal2-rotate-loading {
1204 @-webkit-keyframes swal2-rotate-loading {
1205 0% {
1205 0% {
1206 transform: rotate(0deg);
1206 transform: rotate(0deg);
1207 }
1207 }
1208 100% {
1208 100% {
1209 transform: rotate(360deg);
1209 transform: rotate(360deg);
1210 }
1210 }
1211 }
1211 }
1212 @keyframes swal2-rotate-loading {
1212 @keyframes swal2-rotate-loading {
1213 0% {
1213 0% {
1214 transform: rotate(0deg);
1214 transform: rotate(0deg);
1215 }
1215 }
1216 100% {
1216 100% {
1217 transform: rotate(360deg);
1217 transform: rotate(360deg);
1218 }
1218 }
1219 }
1219 }
1220 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {
1220 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {
1221 overflow: hidden;
1221 overflow: hidden;
1222 }
1222 }
1223 body.swal2-height-auto {
1223 body.swal2-height-auto {
1224 height: auto !important;
1224 height: auto !important;
1225 }
1225 }
1226 body.swal2-no-backdrop .swal2-container {
1226 body.swal2-no-backdrop .swal2-container {
1227 top: auto;
1227 top: auto;
1228 right: auto;
1228 right: auto;
1229 bottom: auto;
1229 bottom: auto;
1230 left: auto;
1230 left: auto;
1231 max-width: calc(100% - 0.625em * 2);
1231 max-width: calc(100% - 0.625em * 2);
1232 background-color: transparent !important;
1232 background-color: transparent !important;
1233 }
1233 }
1234 body.swal2-no-backdrop .swal2-container > .swal2-modal {
1234 body.swal2-no-backdrop .swal2-container > .swal2-modal {
1235 box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
1235 box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
1236 }
1236 }
1237 body.swal2-no-backdrop .swal2-container.swal2-top {
1237 body.swal2-no-backdrop .swal2-container.swal2-top {
1238 top: 0;
1238 top: 0;
1239 left: 50%;
1239 left: 50%;
1240 transform: translateX(-50%);
1240 transform: translateX(-50%);
1241 }
1241 }
1242 body.swal2-no-backdrop .swal2-container.swal2-top-start, body.swal2-no-backdrop .swal2-container.swal2-top-left {
1242 body.swal2-no-backdrop .swal2-container.swal2-top-start, body.swal2-no-backdrop .swal2-container.swal2-top-left {
1243 top: 0;
1243 top: 0;
1244 left: 0;
1244 left: 0;
1245 }
1245 }
1246 body.swal2-no-backdrop .swal2-container.swal2-top-end, body.swal2-no-backdrop .swal2-container.swal2-top-right {
1246 body.swal2-no-backdrop .swal2-container.swal2-top-end, body.swal2-no-backdrop .swal2-container.swal2-top-right {
1247 top: 0;
1247 top: 0;
1248 right: 0;
1248 right: 0;
1249 }
1249 }
1250 body.swal2-no-backdrop .swal2-container.swal2-center {
1250 body.swal2-no-backdrop .swal2-container.swal2-center {
1251 top: 50%;
1251 top: 50%;
1252 left: 50%;
1252 left: 50%;
1253 transform: translate(-50%, -50%);
1253 transform: translate(-50%, -50%);
1254 }
1254 }
1255 body.swal2-no-backdrop .swal2-container.swal2-center-start, body.swal2-no-backdrop .swal2-container.swal2-center-left {
1255 body.swal2-no-backdrop .swal2-container.swal2-center-start, body.swal2-no-backdrop .swal2-container.swal2-center-left {
1256 top: 50%;
1256 top: 50%;
1257 left: 0;
1257 left: 0;
1258 transform: translateY(-50%);
1258 transform: translateY(-50%);
1259 }
1259 }
1260 body.swal2-no-backdrop .swal2-container.swal2-center-end, body.swal2-no-backdrop .swal2-container.swal2-center-right {
1260 body.swal2-no-backdrop .swal2-container.swal2-center-end, body.swal2-no-backdrop .swal2-container.swal2-center-right {
1261 top: 50%;
1261 top: 50%;
1262 right: 0;
1262 right: 0;
1263 transform: translateY(-50%);
1263 transform: translateY(-50%);
1264 }
1264 }
1265 body.swal2-no-backdrop .swal2-container.swal2-bottom {
1265 body.swal2-no-backdrop .swal2-container.swal2-bottom {
1266 bottom: 0;
1266 bottom: 0;
1267 left: 50%;
1267 left: 50%;
1268 transform: translateX(-50%);
1268 transform: translateX(-50%);
1269 }
1269 }
1270 body.swal2-no-backdrop .swal2-container.swal2-bottom-start, body.swal2-no-backdrop .swal2-container.swal2-bottom-left {
1270 body.swal2-no-backdrop .swal2-container.swal2-bottom-start, body.swal2-no-backdrop .swal2-container.swal2-bottom-left {
1271 bottom: 0;
1271 bottom: 0;
1272 left: 0;
1272 left: 0;
1273 }
1273 }
1274 body.swal2-no-backdrop .swal2-container.swal2-bottom-end, body.swal2-no-backdrop .swal2-container.swal2-bottom-right {
1274 body.swal2-no-backdrop .swal2-container.swal2-bottom-end, body.swal2-no-backdrop .swal2-container.swal2-bottom-right {
1275 right: 0;
1275 right: 0;
1276 bottom: 0;
1276 bottom: 0;
1277 }
1277 }
1278 @media print {
1278 @media print {
1279 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {
1279 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {
1280 overflow-y: scroll !important;
1280 overflow-y: scroll !important;
1281 }
1281 }
1282 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) > [aria-hidden=true] {
1282 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) > [aria-hidden=true] {
1283 display: none;
1283 display: none;
1284 }
1284 }
1285 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container {
1285 body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) .swal2-container {
1286 position: static !important;
1286 position: static !important;
1287 }
1287 }
1288 }
1288 }
1289 body.swal2-toast-shown .swal2-container {
1289 body.swal2-toast-shown .swal2-container {
1290 background-color: transparent;
1290 background-color: transparent;
1291 }
1291 }
1292 body.swal2-toast-shown .swal2-container.swal2-top {
1292 body.swal2-toast-shown .swal2-container.swal2-top {
1293 top: 0;
1293 top: 0;
1294 right: auto;
1294 right: auto;
1295 bottom: auto;
1295 bottom: auto;
1296 left: 50%;
1296 left: 50%;
1297 transform: translateX(-50%);
1297 transform: translateX(-50%);
1298 }
1298 }
1299 body.swal2-toast-shown .swal2-container.swal2-top-end, body.swal2-toast-shown .swal2-container.swal2-top-right {
1299 body.swal2-toast-shown .swal2-container.swal2-top-end, body.swal2-toast-shown .swal2-container.swal2-top-right {
1300 top: 0;
1300 top: 0;
1301 right: 0;
1301 right: 0;
1302 bottom: auto;
1302 bottom: auto;
1303 left: auto;
1303 left: auto;
1304 }
1304 }
1305 body.swal2-toast-shown .swal2-container.swal2-top-start, body.swal2-toast-shown .swal2-container.swal2-top-left {
1305 body.swal2-toast-shown .swal2-container.swal2-top-start, body.swal2-toast-shown .swal2-container.swal2-top-left {
1306 top: 0;
1306 top: 0;
1307 right: auto;
1307 right: auto;
1308 bottom: auto;
1308 bottom: auto;
1309 left: 0;
1309 left: 0;
1310 }
1310 }
1311 body.swal2-toast-shown .swal2-container.swal2-center-start, body.swal2-toast-shown .swal2-container.swal2-center-left {
1311 body.swal2-toast-shown .swal2-container.swal2-center-start, body.swal2-toast-shown .swal2-container.swal2-center-left {
1312 top: 50%;
1312 top: 50%;
1313 right: auto;
1313 right: auto;
1314 bottom: auto;
1314 bottom: auto;
1315 left: 0;
1315 left: 0;
1316 transform: translateY(-50%);
1316 transform: translateY(-50%);
1317 }
1317 }
1318 body.swal2-toast-shown .swal2-container.swal2-center {
1318 body.swal2-toast-shown .swal2-container.swal2-center {
1319 top: 50%;
1319 top: 50%;
1320 right: auto;
1320 right: auto;
1321 bottom: auto;
1321 bottom: auto;
1322 left: 50%;
1322 left: 50%;
1323 transform: translate(-50%, -50%);
1323 transform: translate(-50%, -50%);
1324 }
1324 }
1325 body.swal2-toast-shown .swal2-container.swal2-center-end, body.swal2-toast-shown .swal2-container.swal2-center-right {
1325 body.swal2-toast-shown .swal2-container.swal2-center-end, body.swal2-toast-shown .swal2-container.swal2-center-right {
1326 top: 50%;
1326 top: 50%;
1327 right: 0;
1327 right: 0;
1328 bottom: auto;
1328 bottom: auto;
1329 left: auto;
1329 left: auto;
1330 transform: translateY(-50%);
1330 transform: translateY(-50%);
1331 }
1331 }
1332 body.swal2-toast-shown .swal2-container.swal2-bottom-start, body.swal2-toast-shown .swal2-container.swal2-bottom-left {
1332 body.swal2-toast-shown .swal2-container.swal2-bottom-start, body.swal2-toast-shown .swal2-container.swal2-bottom-left {
1333 top: auto;
1333 top: auto;
1334 right: auto;
1334 right: auto;
1335 bottom: 0;
1335 bottom: 0;
1336 left: 0;
1336 left: 0;
1337 }
1337 }
1338 body.swal2-toast-shown .swal2-container.swal2-bottom {
1338 body.swal2-toast-shown .swal2-container.swal2-bottom {
1339 top: auto;
1339 top: auto;
1340 right: auto;
1340 right: auto;
1341 bottom: 0;
1341 bottom: 0;
1342 left: 50%;
1342 left: 50%;
1343 transform: translateX(-50%);
1343 transform: translateX(-50%);
1344 }
1344 }
1345 body.swal2-toast-shown .swal2-container.swal2-bottom-end, body.swal2-toast-shown .swal2-container.swal2-bottom-right {
1345 body.swal2-toast-shown .swal2-container.swal2-bottom-end, body.swal2-toast-shown .swal2-container.swal2-bottom-right {
1346 top: auto;
1346 top: auto;
1347 right: 0;
1347 right: 0;
1348 bottom: 0;
1348 bottom: 0;
1349 left: auto;
1349 left: auto;
1350 }
1350 }
1351 body.swal2-toast-column .swal2-toast {
1351 body.swal2-toast-column .swal2-toast {
1352 flex-direction: column;
1352 flex-direction: column;
1353 align-items: stretch;
1353 align-items: stretch;
1354 }
1354 }
1355 body.swal2-toast-column .swal2-toast .swal2-actions {
1355 body.swal2-toast-column .swal2-toast .swal2-actions {
1356 flex: 1;
1356 flex: 1;
1357 align-self: stretch;
1357 align-self: stretch;
1358 height: 2.2em;
1358 height: 2.2em;
1359 margin-top: 0.3125em;
1359 margin-top: 0.3125em;
1360 }
1360 }
1361 body.swal2-toast-column .swal2-toast .swal2-loading {
1361 body.swal2-toast-column .swal2-toast .swal2-loading {
1362 justify-content: center;
1362 justify-content: center;
1363 }
1363 }
1364 body.swal2-toast-column .swal2-toast .swal2-input {
1364 body.swal2-toast-column .swal2-toast .swal2-input {
1365 height: 2em;
1365 height: 2em;
1366 margin: 0.3125em auto;
1366 margin: 0.3125em auto;
1367 font-size: 1em;
1367 font-size: 1em;
1368 }
1368 }
1369 body.swal2-toast-column .swal2-toast .swal2-validation-message {
1369 body.swal2-toast-column .swal2-toast .swal2-validation-message {
1370 font-size: 1em;
1370 font-size: 1em;
1371 } No newline at end of file
1371 }
@@ -1,947 +1,955 b''
1 // # Copyright (C) 2010-2020 RhodeCode GmbH
1 // # Copyright (C) 2010-2020 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 var firefoxAnchorFix = function() {
19 var firefoxAnchorFix = function() {
20 // hack to make anchor links behave properly on firefox, in our inline
20 // hack to make anchor links behave properly on firefox, in our inline
21 // comments generation when comments are injected firefox is misbehaving
21 // comments generation when comments are injected firefox is misbehaving
22 // when jumping to anchor links
22 // when jumping to anchor links
23 if (location.href.indexOf('#') > -1) {
23 if (location.href.indexOf('#') > -1) {
24 location.href += '';
24 location.href += '';
25 }
25 }
26 };
26 };
27
27
28 var linkifyComments = function(comments) {
28 var linkifyComments = function(comments) {
29 var firstCommentId = null;
29 var firstCommentId = null;
30 if (comments) {
30 if (comments) {
31 firstCommentId = $(comments[0]).data('comment-id');
31 firstCommentId = $(comments[0]).data('comment-id');
32 }
32 }
33
33
34 if (firstCommentId){
34 if (firstCommentId){
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
35 $('#inline-comments-counter').attr('href', '#comment-' + firstCommentId);
36 }
36 }
37 };
37 };
38
38
39 var bindToggleButtons = function() {
39 var bindToggleButtons = function() {
40 $('.comment-toggle').on('click', function() {
40 $('.comment-toggle').on('click', function() {
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
41 $(this).parent().nextUntil('tr.line').toggle('inline-comments');
42 });
42 });
43 };
43 };
44
44
45
45
46
46
47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
47 var _submitAjaxPOST = function(url, postData, successHandler, failHandler) {
48 failHandler = failHandler || function() {};
48 failHandler = failHandler || function() {};
49 postData = toQueryString(postData);
49 postData = toQueryString(postData);
50 var request = $.ajax({
50 var request = $.ajax({
51 url: url,
51 url: url,
52 type: 'POST',
52 type: 'POST',
53 data: postData,
53 data: postData,
54 headers: {'X-PARTIAL-XHR': true}
54 headers: {'X-PARTIAL-XHR': true}
55 })
55 })
56 .done(function (data) {
56 .done(function (data) {
57 successHandler(data);
57 successHandler(data);
58 })
58 })
59 .fail(function (data, textStatus, errorThrown) {
59 .fail(function (data, textStatus, errorThrown) {
60 failHandler(data, textStatus, errorThrown)
60 failHandler(data, textStatus, errorThrown)
61 });
61 });
62 return request;
62 return request;
63 };
63 };
64
64
65
65
66
66
67
67
68 /* Comment form for main and inline comments */
68 /* Comment form for main and inline comments */
69 (function(mod) {
69 (function(mod) {
70
70
71 if (typeof exports == "object" && typeof module == "object") {
71 if (typeof exports == "object" && typeof module == "object") {
72 // CommonJS
72 // CommonJS
73 module.exports = mod();
73 module.exports = mod();
74 }
74 }
75 else {
75 else {
76 // Plain browser env
76 // Plain browser env
77 (this || window).CommentForm = mod();
77 (this || window).CommentForm = mod();
78 }
78 }
79
79
80 })(function() {
80 })(function() {
81 "use strict";
81 "use strict";
82
82
83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
83 function CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId) {
84 if (!(this instanceof CommentForm)) {
84 if (!(this instanceof CommentForm)) {
85 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
85 return new CommentForm(formElement, commitId, pullRequestId, lineNo, initAutocompleteActions, resolvesCommentId);
86 }
86 }
87
87
88 // bind the element instance to our Form
88 // bind the element instance to our Form
89 $(formElement).get(0).CommentForm = this;
89 $(formElement).get(0).CommentForm = this;
90
90
91 this.withLineNo = function(selector) {
91 this.withLineNo = function(selector) {
92 var lineNo = this.lineNo;
92 var lineNo = this.lineNo;
93 if (lineNo === undefined) {
93 if (lineNo === undefined) {
94 return selector
94 return selector
95 } else {
95 } else {
96 return selector + '_' + lineNo;
96 return selector + '_' + lineNo;
97 }
97 }
98 };
98 };
99
99
100 this.commitId = commitId;
100 this.commitId = commitId;
101 this.pullRequestId = pullRequestId;
101 this.pullRequestId = pullRequestId;
102 this.lineNo = lineNo;
102 this.lineNo = lineNo;
103 this.initAutocompleteActions = initAutocompleteActions;
103 this.initAutocompleteActions = initAutocompleteActions;
104
104
105 this.previewButton = this.withLineNo('#preview-btn');
105 this.previewButton = this.withLineNo('#preview-btn');
106 this.previewContainer = this.withLineNo('#preview-container');
106 this.previewContainer = this.withLineNo('#preview-container');
107
107
108 this.previewBoxSelector = this.withLineNo('#preview-box');
108 this.previewBoxSelector = this.withLineNo('#preview-box');
109
109
110 this.editButton = this.withLineNo('#edit-btn');
110 this.editButton = this.withLineNo('#edit-btn');
111 this.editContainer = this.withLineNo('#edit-container');
111 this.editContainer = this.withLineNo('#edit-container');
112 this.cancelButton = this.withLineNo('#cancel-btn');
112 this.cancelButton = this.withLineNo('#cancel-btn');
113 this.commentType = this.withLineNo('#comment_type');
113 this.commentType = this.withLineNo('#comment_type');
114
114
115 this.resolvesId = null;
115 this.resolvesId = null;
116 this.resolvesActionId = null;
116 this.resolvesActionId = null;
117
117
118 this.closesPr = '#close_pull_request';
118 this.closesPr = '#close_pull_request';
119
119
120 this.cmBox = this.withLineNo('#text');
120 this.cmBox = this.withLineNo('#text');
121 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
121 this.cm = initCommentBoxCodeMirror(this, this.cmBox, this.initAutocompleteActions);
122
122
123 this.statusChange = this.withLineNo('#change_status');
123 this.statusChange = this.withLineNo('#change_status');
124
124
125 this.submitForm = formElement;
125 this.submitForm = formElement;
126 this.submitButton = $(this.submitForm).find('input[type="submit"]');
126 this.submitButton = $(this.submitForm).find('input[type="submit"]');
127 this.submitButtonText = this.submitButton.val();
127 this.submitButtonText = this.submitButton.val();
128
128
129 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
129 this.previewUrl = pyroutes.url('repo_commit_comment_preview',
130 {'repo_name': templateContext.repo_name,
130 {'repo_name': templateContext.repo_name,
131 'commit_id': templateContext.commit_data.commit_id});
131 'commit_id': templateContext.commit_data.commit_id});
132
132
133 if (resolvesCommentId){
133 if (resolvesCommentId){
134 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
134 this.resolvesId = '#resolve_comment_{0}'.format(resolvesCommentId);
135 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
135 this.resolvesActionId = '#resolve_comment_action_{0}'.format(resolvesCommentId);
136 $(this.commentType).prop('disabled', true);
136 $(this.commentType).prop('disabled', true);
137 $(this.commentType).addClass('disabled');
137 $(this.commentType).addClass('disabled');
138
138
139 // disable select
139 // disable select
140 setTimeout(function() {
140 setTimeout(function() {
141 $(self.statusChange).select2('readonly', true);
141 $(self.statusChange).select2('readonly', true);
142 }, 10);
142 }, 10);
143
143
144 var resolvedInfo = (
144 var resolvedInfo = (
145 '<li class="resolve-action">' +
145 '<li class="resolve-action">' +
146 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
146 '<input type="hidden" id="resolve_comment_{0}" name="resolve_comment_{0}" value="{0}">' +
147 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
147 '<button id="resolve_comment_action_{0}" class="resolve-text btn btn-sm" onclick="return Rhodecode.comments.submitResolution({0})">{1} #{0}</button>' +
148 '</li>'
148 '</li>'
149 ).format(resolvesCommentId, _gettext('resolve comment'));
149 ).format(resolvesCommentId, _gettext('resolve comment'));
150 $(resolvedInfo).insertAfter($(this.commentType).parent());
150 $(resolvedInfo).insertAfter($(this.commentType).parent());
151 }
151 }
152
152
153 // based on commitId, or pullRequestId decide where do we submit
153 // based on commitId, or pullRequestId decide where do we submit
154 // out data
154 // out data
155 if (this.commitId){
155 if (this.commitId){
156 this.submitUrl = pyroutes.url('repo_commit_comment_create',
156 this.submitUrl = pyroutes.url('repo_commit_comment_create',
157 {'repo_name': templateContext.repo_name,
157 {'repo_name': templateContext.repo_name,
158 'commit_id': this.commitId});
158 'commit_id': this.commitId});
159 this.selfUrl = pyroutes.url('repo_commit',
159 this.selfUrl = pyroutes.url('repo_commit',
160 {'repo_name': templateContext.repo_name,
160 {'repo_name': templateContext.repo_name,
161 'commit_id': this.commitId});
161 'commit_id': this.commitId});
162
162
163 } else if (this.pullRequestId) {
163 } else if (this.pullRequestId) {
164 this.submitUrl = pyroutes.url('pullrequest_comment_create',
164 this.submitUrl = pyroutes.url('pullrequest_comment_create',
165 {'repo_name': templateContext.repo_name,
165 {'repo_name': templateContext.repo_name,
166 'pull_request_id': this.pullRequestId});
166 'pull_request_id': this.pullRequestId});
167 this.selfUrl = pyroutes.url('pullrequest_show',
167 this.selfUrl = pyroutes.url('pullrequest_show',
168 {'repo_name': templateContext.repo_name,
168 {'repo_name': templateContext.repo_name,
169 'pull_request_id': this.pullRequestId});
169 'pull_request_id': this.pullRequestId});
170
170
171 } else {
171 } else {
172 throw new Error(
172 throw new Error(
173 'CommentForm requires pullRequestId, or commitId to be specified.')
173 'CommentForm requires pullRequestId, or commitId to be specified.')
174 }
174 }
175
175
176 // FUNCTIONS and helpers
176 // FUNCTIONS and helpers
177 var self = this;
177 var self = this;
178
178
179 this.isInline = function(){
179 this.isInline = function(){
180 return this.lineNo && this.lineNo != 'general';
180 return this.lineNo && this.lineNo != 'general';
181 };
181 };
182
182
183 this.getCmInstance = function(){
183 this.getCmInstance = function(){
184 return this.cm
184 return this.cm
185 };
185 };
186
186
187 this.setPlaceholder = function(placeholder) {
187 this.setPlaceholder = function(placeholder) {
188 var cm = this.getCmInstance();
188 var cm = this.getCmInstance();
189 if (cm){
189 if (cm){
190 cm.setOption('placeholder', placeholder);
190 cm.setOption('placeholder', placeholder);
191 }
191 }
192 };
192 };
193
193
194 this.getCommentStatus = function() {
194 this.getCommentStatus = function() {
195 return $(this.submitForm).find(this.statusChange).val();
195 return $(this.submitForm).find(this.statusChange).val();
196 };
196 };
197 this.getCommentType = function() {
197 this.getCommentType = function() {
198 return $(this.submitForm).find(this.commentType).val();
198 return $(this.submitForm).find(this.commentType).val();
199 };
199 };
200
200
201 this.getResolvesId = function() {
201 this.getResolvesId = function() {
202 return $(this.submitForm).find(this.resolvesId).val() || null;
202 return $(this.submitForm).find(this.resolvesId).val() || null;
203 };
203 };
204
204
205 this.getClosePr = function() {
205 this.getClosePr = function() {
206 return $(this.submitForm).find(this.closesPr).val() || null;
206 return $(this.submitForm).find(this.closesPr).val() || null;
207 };
207 };
208
208
209 this.markCommentResolved = function(resolvedCommentId){
209 this.markCommentResolved = function(resolvedCommentId){
210 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
210 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolved').show();
211 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
211 $('#comment-label-{0}'.format(resolvedCommentId)).find('.resolve').hide();
212 };
212 };
213
213
214 this.isAllowedToSubmit = function() {
214 this.isAllowedToSubmit = function() {
215 return !$(this.submitButton).prop('disabled');
215 return !$(this.submitButton).prop('disabled');
216 };
216 };
217
217
218 this.initStatusChangeSelector = function(){
218 this.initStatusChangeSelector = function(){
219 var formatChangeStatus = function(state, escapeMarkup) {
219 var formatChangeStatus = function(state, escapeMarkup) {
220 var originalOption = state.element;
220 var originalOption = state.element;
221 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
221 var tmpl = '<i class="icon-circle review-status-{0}"></i><span>{1}</span>'.format($(originalOption).data('status'), escapeMarkup(state.text));
222 return tmpl
222 return tmpl
223 };
223 };
224 var formatResult = function(result, container, query, escapeMarkup) {
224 var formatResult = function(result, container, query, escapeMarkup) {
225 return formatChangeStatus(result, escapeMarkup);
225 return formatChangeStatus(result, escapeMarkup);
226 };
226 };
227
227
228 var formatSelection = function(data, container, escapeMarkup) {
228 var formatSelection = function(data, container, escapeMarkup) {
229 return formatChangeStatus(data, escapeMarkup);
229 return formatChangeStatus(data, escapeMarkup);
230 };
230 };
231
231
232 $(this.submitForm).find(this.statusChange).select2({
232 $(this.submitForm).find(this.statusChange).select2({
233 placeholder: _gettext('Status Review'),
233 placeholder: _gettext('Status Review'),
234 formatResult: formatResult,
234 formatResult: formatResult,
235 formatSelection: formatSelection,
235 formatSelection: formatSelection,
236 containerCssClass: "drop-menu status_box_menu",
236 containerCssClass: "drop-menu status_box_menu",
237 dropdownCssClass: "drop-menu-dropdown",
237 dropdownCssClass: "drop-menu-dropdown",
238 dropdownAutoWidth: true,
238 dropdownAutoWidth: true,
239 minimumResultsForSearch: -1
239 minimumResultsForSearch: -1
240 });
240 });
241 $(this.submitForm).find(this.statusChange).on('change', function() {
241 $(this.submitForm).find(this.statusChange).on('change', function() {
242 var status = self.getCommentStatus();
242 var status = self.getCommentStatus();
243
243
244 if (status && !self.isInline()) {
244 if (status && !self.isInline()) {
245 $(self.submitButton).prop('disabled', false);
245 $(self.submitButton).prop('disabled', false);
246 }
246 }
247
247
248 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
248 var placeholderText = _gettext('Comment text will be set automatically based on currently selected status ({0}) ...').format(status);
249 self.setPlaceholder(placeholderText)
249 self.setPlaceholder(placeholderText)
250 })
250 })
251 };
251 };
252
252
253 // reset the comment form into it's original state
253 // reset the comment form into it's original state
254 this.resetCommentFormState = function(content) {
254 this.resetCommentFormState = function(content) {
255 content = content || '';
255 content = content || '';
256
256
257 $(this.editContainer).show();
257 $(this.editContainer).show();
258 $(this.editButton).parent().addClass('active');
258 $(this.editButton).parent().addClass('active');
259
259
260 $(this.previewContainer).hide();
260 $(this.previewContainer).hide();
261 $(this.previewButton).parent().removeClass('active');
261 $(this.previewButton).parent().removeClass('active');
262
262
263 this.setActionButtonsDisabled(true);
263 this.setActionButtonsDisabled(true);
264 self.cm.setValue(content);
264 self.cm.setValue(content);
265 self.cm.setOption("readOnly", false);
265 self.cm.setOption("readOnly", false);
266
266
267 if (this.resolvesId) {
267 if (this.resolvesId) {
268 // destroy the resolve action
268 // destroy the resolve action
269 $(this.resolvesId).parent().remove();
269 $(this.resolvesId).parent().remove();
270 }
270 }
271 // reset closingPR flag
271 // reset closingPR flag
272 $('.close-pr-input').remove();
272 $('.close-pr-input').remove();
273
273
274 $(this.statusChange).select2('readonly', false);
274 $(this.statusChange).select2('readonly', false);
275 };
275 };
276
276
277 this.globalSubmitSuccessCallback = function(){
277 this.globalSubmitSuccessCallback = function(){
278 // default behaviour is to call GLOBAL hook, if it's registered.
278 // default behaviour is to call GLOBAL hook, if it's registered.
279 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
279 if (window.commentFormGlobalSubmitSuccessCallback !== undefined){
280 commentFormGlobalSubmitSuccessCallback()
280 commentFormGlobalSubmitSuccessCallback()
281 }
281 }
282 };
282 };
283
283
284 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
284 this.submitAjaxPOST = function(url, postData, successHandler, failHandler) {
285 return _submitAjaxPOST(url, postData, successHandler, failHandler);
285 return _submitAjaxPOST(url, postData, successHandler, failHandler);
286 };
286 };
287
287
288 // overwrite a submitHandler, we need to do it for inline comments
288 // overwrite a submitHandler, we need to do it for inline comments
289 this.setHandleFormSubmit = function(callback) {
289 this.setHandleFormSubmit = function(callback) {
290 this.handleFormSubmit = callback;
290 this.handleFormSubmit = callback;
291 };
291 };
292
292
293 // overwrite a submitSuccessHandler
293 // overwrite a submitSuccessHandler
294 this.setGlobalSubmitSuccessCallback = function(callback) {
294 this.setGlobalSubmitSuccessCallback = function(callback) {
295 this.globalSubmitSuccessCallback = callback;
295 this.globalSubmitSuccessCallback = callback;
296 };
296 };
297
297
298 // default handler for for submit for main comments
298 // default handler for for submit for main comments
299 this.handleFormSubmit = function() {
299 this.handleFormSubmit = function() {
300 var text = self.cm.getValue();
300 var text = self.cm.getValue();
301 var status = self.getCommentStatus();
301 var status = self.getCommentStatus();
302 var commentType = self.getCommentType();
302 var commentType = self.getCommentType();
303 var resolvesCommentId = self.getResolvesId();
303 var resolvesCommentId = self.getResolvesId();
304 var closePullRequest = self.getClosePr();
304 var closePullRequest = self.getClosePr();
305
305
306 if (text === "" && !status) {
306 if (text === "" && !status) {
307 return;
307 return;
308 }
308 }
309
309
310 var excludeCancelBtn = false;
310 var excludeCancelBtn = false;
311 var submitEvent = true;
311 var submitEvent = true;
312 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
312 self.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
313 self.cm.setOption("readOnly", true);
313 self.cm.setOption("readOnly", true);
314
314
315 var postData = {
315 var postData = {
316 'text': text,
316 'text': text,
317 'changeset_status': status,
317 'changeset_status': status,
318 'comment_type': commentType,
318 'comment_type': commentType,
319 'csrf_token': CSRF_TOKEN
319 'csrf_token': CSRF_TOKEN
320 };
320 };
321
321
322 if (resolvesCommentId) {
322 if (resolvesCommentId) {
323 postData['resolves_comment_id'] = resolvesCommentId;
323 postData['resolves_comment_id'] = resolvesCommentId;
324 }
324 }
325
325
326 if (closePullRequest) {
326 if (closePullRequest) {
327 postData['close_pull_request'] = true;
327 postData['close_pull_request'] = true;
328 }
328 }
329
329
330 var submitSuccessCallback = function(o) {
330 var submitSuccessCallback = function(o) {
331 // reload page if we change status for single commit.
331 // reload page if we change status for single commit.
332 if (status && self.commitId) {
332 if (status && self.commitId) {
333 location.reload(true);
333 location.reload(true);
334 } else {
334 } else {
335 $('#injected_page_comments').append(o.rendered_text);
335 $('#injected_page_comments').append(o.rendered_text);
336 self.resetCommentFormState();
336 self.resetCommentFormState();
337 timeagoActivate();
337 timeagoActivate();
338 tooltipActivate();
338 tooltipActivate();
339
339
340 // mark visually which comment was resolved
340 // mark visually which comment was resolved
341 if (resolvesCommentId) {
341 if (resolvesCommentId) {
342 self.markCommentResolved(resolvesCommentId);
342 self.markCommentResolved(resolvesCommentId);
343 }
343 }
344 }
344 }
345
345
346 // run global callback on submit
346 // run global callback on submit
347 self.globalSubmitSuccessCallback();
347 self.globalSubmitSuccessCallback();
348
348
349 };
349 };
350 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
350 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
351 var prefix = "Error while submitting comment.\n"
351 var prefix = "Error while submitting comment.\n"
352 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
352 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
353 ajaxErrorSwal(message);
353 ajaxErrorSwal(message);
354 self.resetCommentFormState(text);
354 self.resetCommentFormState(text);
355 };
355 };
356 self.submitAjaxPOST(
356 self.submitAjaxPOST(
357 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
357 self.submitUrl, postData, submitSuccessCallback, submitFailCallback);
358 };
358 };
359
359
360 this.previewSuccessCallback = function(o) {
360 this.previewSuccessCallback = function(o) {
361 $(self.previewBoxSelector).html(o);
361 $(self.previewBoxSelector).html(o);
362 $(self.previewBoxSelector).removeClass('unloaded');
362 $(self.previewBoxSelector).removeClass('unloaded');
363
363
364 // swap buttons, making preview active
364 // swap buttons, making preview active
365 $(self.previewButton).parent().addClass('active');
365 $(self.previewButton).parent().addClass('active');
366 $(self.editButton).parent().removeClass('active');
366 $(self.editButton).parent().removeClass('active');
367
367
368 // unlock buttons
368 // unlock buttons
369 self.setActionButtonsDisabled(false);
369 self.setActionButtonsDisabled(false);
370 };
370 };
371
371
372 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
372 this.setActionButtonsDisabled = function(state, excludeCancelBtn, submitEvent) {
373 excludeCancelBtn = excludeCancelBtn || false;
373 excludeCancelBtn = excludeCancelBtn || false;
374 submitEvent = submitEvent || false;
374 submitEvent = submitEvent || false;
375
375
376 $(this.editButton).prop('disabled', state);
376 $(this.editButton).prop('disabled', state);
377 $(this.previewButton).prop('disabled', state);
377 $(this.previewButton).prop('disabled', state);
378
378
379 if (!excludeCancelBtn) {
379 if (!excludeCancelBtn) {
380 $(this.cancelButton).prop('disabled', state);
380 $(this.cancelButton).prop('disabled', state);
381 }
381 }
382
382
383 var submitState = state;
383 var submitState = state;
384 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
384 if (!submitEvent && this.getCommentStatus() && !self.isInline()) {
385 // if the value of commit review status is set, we allow
385 // if the value of commit review status is set, we allow
386 // submit button, but only on Main form, isInline means inline
386 // submit button, but only on Main form, isInline means inline
387 submitState = false
387 submitState = false
388 }
388 }
389
389
390 $(this.submitButton).prop('disabled', submitState);
390 $(this.submitButton).prop('disabled', submitState);
391 if (submitEvent) {
391 if (submitEvent) {
392 $(this.submitButton).val(_gettext('Submitting...'));
392 $(this.submitButton).val(_gettext('Submitting...'));
393 } else {
393 } else {
394 $(this.submitButton).val(this.submitButtonText);
394 $(this.submitButton).val(this.submitButtonText);
395 }
395 }
396
396
397 };
397 };
398
398
399 // lock preview/edit/submit buttons on load, but exclude cancel button
399 // lock preview/edit/submit buttons on load, but exclude cancel button
400 var excludeCancelBtn = true;
400 var excludeCancelBtn = true;
401 this.setActionButtonsDisabled(true, excludeCancelBtn);
401 this.setActionButtonsDisabled(true, excludeCancelBtn);
402
402
403 // anonymous users don't have access to initialized CM instance
403 // anonymous users don't have access to initialized CM instance
404 if (this.cm !== undefined){
404 if (this.cm !== undefined){
405 this.cm.on('change', function(cMirror) {
405 this.cm.on('change', function(cMirror) {
406 if (cMirror.getValue() === "") {
406 if (cMirror.getValue() === "") {
407 self.setActionButtonsDisabled(true, excludeCancelBtn)
407 self.setActionButtonsDisabled(true, excludeCancelBtn)
408 } else {
408 } else {
409 self.setActionButtonsDisabled(false, excludeCancelBtn)
409 self.setActionButtonsDisabled(false, excludeCancelBtn)
410 }
410 }
411 });
411 });
412 }
412 }
413
413
414 $(this.editButton).on('click', function(e) {
414 $(this.editButton).on('click', function(e) {
415 e.preventDefault();
415 e.preventDefault();
416
416
417 $(self.previewButton).parent().removeClass('active');
417 $(self.previewButton).parent().removeClass('active');
418 $(self.previewContainer).hide();
418 $(self.previewContainer).hide();
419
419
420 $(self.editButton).parent().addClass('active');
420 $(self.editButton).parent().addClass('active');
421 $(self.editContainer).show();
421 $(self.editContainer).show();
422
422
423 });
423 });
424
424
425 $(this.previewButton).on('click', function(e) {
425 $(this.previewButton).on('click', function(e) {
426 e.preventDefault();
426 e.preventDefault();
427 var text = self.cm.getValue();
427 var text = self.cm.getValue();
428
428
429 if (text === "") {
429 if (text === "") {
430 return;
430 return;
431 }
431 }
432
432
433 var postData = {
433 var postData = {
434 'text': text,
434 'text': text,
435 'renderer': templateContext.visual.default_renderer,
435 'renderer': templateContext.visual.default_renderer,
436 'csrf_token': CSRF_TOKEN
436 'csrf_token': CSRF_TOKEN
437 };
437 };
438
438
439 // lock ALL buttons on preview
439 // lock ALL buttons on preview
440 self.setActionButtonsDisabled(true);
440 self.setActionButtonsDisabled(true);
441
441
442 $(self.previewBoxSelector).addClass('unloaded');
442 $(self.previewBoxSelector).addClass('unloaded');
443 $(self.previewBoxSelector).html(_gettext('Loading ...'));
443 $(self.previewBoxSelector).html(_gettext('Loading ...'));
444
444
445 $(self.editContainer).hide();
445 $(self.editContainer).hide();
446 $(self.previewContainer).show();
446 $(self.previewContainer).show();
447
447
448 // by default we reset state of comment preserving the text
448 // by default we reset state of comment preserving the text
449 var previewFailCallback = function(jqXHR, textStatus, errorThrown) {
449 var previewFailCallback = function(jqXHR, textStatus, errorThrown) {
450 var prefix = "Error while preview of comment.\n"
450 var prefix = "Error while preview of comment.\n"
451 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
451 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
452 ajaxErrorSwal(message);
452 ajaxErrorSwal(message);
453
453
454 self.resetCommentFormState(text)
454 self.resetCommentFormState(text)
455 };
455 };
456 self.submitAjaxPOST(
456 self.submitAjaxPOST(
457 self.previewUrl, postData, self.previewSuccessCallback,
457 self.previewUrl, postData, self.previewSuccessCallback,
458 previewFailCallback);
458 previewFailCallback);
459
459
460 $(self.previewButton).parent().addClass('active');
460 $(self.previewButton).parent().addClass('active');
461 $(self.editButton).parent().removeClass('active');
461 $(self.editButton).parent().removeClass('active');
462 });
462 });
463
463
464 $(this.submitForm).submit(function(e) {
464 $(this.submitForm).submit(function(e) {
465 e.preventDefault();
465 e.preventDefault();
466 var allowedToSubmit = self.isAllowedToSubmit();
466 var allowedToSubmit = self.isAllowedToSubmit();
467 if (!allowedToSubmit){
467 if (!allowedToSubmit){
468 return false;
468 return false;
469 }
469 }
470 self.handleFormSubmit();
470 self.handleFormSubmit();
471 });
471 });
472
472
473 }
473 }
474
474
475 return CommentForm;
475 return CommentForm;
476 });
476 });
477
477
478 /* comments controller */
478 /* comments controller */
479 var CommentsController = function() {
479 var CommentsController = function() {
480 var mainComment = '#text';
480 var mainComment = '#text';
481 var self = this;
481 var self = this;
482
482
483 this.cancelComment = function(node) {
483 this.cancelComment = function(node) {
484 var $node = $(node);
484 var $node = $(node);
485 var $td = $node.closest('td');
485 var $td = $node.closest('td');
486 $node.closest('.comment-inline-form').remove();
486 $node.closest('.comment-inline-form').remove();
487 return false;
487 return false;
488 };
488 };
489
489
490 this.getLineNumber = function(node) {
490 this.getLineNumber = function(node) {
491 var $node = $(node);
491 var $node = $(node);
492 var lineNo = $node.closest('td').attr('data-line-no');
492 var lineNo = $node.closest('td').attr('data-line-no');
493 if (lineNo === undefined && $node.data('commentInline')){
493 if (lineNo === undefined && $node.data('commentInline')){
494 lineNo = $node.data('commentLineNo')
494 lineNo = $node.data('commentLineNo')
495 }
495 }
496
496
497 return lineNo
497 return lineNo
498 };
498 };
499
499
500 this.scrollToComment = function(node, offset, outdated) {
500 this.scrollToComment = function(node, offset, outdated) {
501 if (offset === undefined) {
501 if (offset === undefined) {
502 offset = 0;
502 offset = 0;
503 }
503 }
504 var outdated = outdated || false;
504 var outdated = outdated || false;
505 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
505 var klass = outdated ? 'div.comment-outdated' : 'div.comment-current';
506
506
507 if (!node) {
507 if (!node) {
508 node = $('.comment-selected');
508 node = $('.comment-selected');
509 if (!node.length) {
509 if (!node.length) {
510 node = $('comment-current')
510 node = $('comment-current')
511 }
511 }
512 }
512 }
513
513
514 $wrapper = $(node).closest('div.comment');
514 $wrapper = $(node).closest('div.comment');
515
515
516 // show hidden comment when referenced.
516 // show hidden comment when referenced.
517 if (!$wrapper.is(':visible')){
517 if (!$wrapper.is(':visible')){
518 $wrapper.show();
518 $wrapper.show();
519 }
519 }
520
520
521 $comment = $(node).closest(klass);
521 $comment = $(node).closest(klass);
522 $comments = $(klass);
522 $comments = $(klass);
523
523
524 $('.comment-selected').removeClass('comment-selected');
524 $('.comment-selected').removeClass('comment-selected');
525
525
526 var nextIdx = $(klass).index($comment) + offset;
526 var nextIdx = $(klass).index($comment) + offset;
527 if (nextIdx >= $comments.length) {
527 if (nextIdx >= $comments.length) {
528 nextIdx = 0;
528 nextIdx = 0;
529 }
529 }
530 var $next = $(klass).eq(nextIdx);
530 var $next = $(klass).eq(nextIdx);
531
531
532 var $cb = $next.closest('.cb');
532 var $cb = $next.closest('.cb');
533 $cb.removeClass('cb-collapsed');
533 $cb.removeClass('cb-collapsed');
534
534
535 var $filediffCollapseState = $cb.closest('.filediff').prev();
535 var $filediffCollapseState = $cb.closest('.filediff').prev();
536 $filediffCollapseState.prop('checked', false);
536 $filediffCollapseState.prop('checked', false);
537 $next.addClass('comment-selected');
537 $next.addClass('comment-selected');
538 scrollToElement($next);
538 scrollToElement($next);
539 return false;
539 return false;
540 };
540 };
541
541
542 this.nextComment = function(node) {
542 this.nextComment = function(node) {
543 return self.scrollToComment(node, 1);
543 return self.scrollToComment(node, 1);
544 };
544 };
545
545
546 this.prevComment = function(node) {
546 this.prevComment = function(node) {
547 return self.scrollToComment(node, -1);
547 return self.scrollToComment(node, -1);
548 };
548 };
549
549
550 this.nextOutdatedComment = function(node) {
550 this.nextOutdatedComment = function(node) {
551 return self.scrollToComment(node, 1, true);
551 return self.scrollToComment(node, 1, true);
552 };
552 };
553
553
554 this.prevOutdatedComment = function(node) {
554 this.prevOutdatedComment = function(node) {
555 return self.scrollToComment(node, -1, true);
555 return self.scrollToComment(node, -1, true);
556 };
556 };
557
557
558 this._deleteComment = function(node) {
558 this._deleteComment = function(node) {
559 var $node = $(node);
559 var $node = $(node);
560 var $td = $node.closest('td');
560 var $td = $node.closest('td');
561 var $comment = $node.closest('.comment');
561 var $comment = $node.closest('.comment');
562 var comment_id = $comment.attr('data-comment-id');
562 var comment_id = $comment.attr('data-comment-id');
563 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
563 var url = AJAX_COMMENT_DELETE_URL.replace('__COMMENT_ID__', comment_id);
564 var postData = {
564 var postData = {
565 'csrf_token': CSRF_TOKEN
565 'csrf_token': CSRF_TOKEN
566 };
566 };
567
567
568 $comment.addClass('comment-deleting');
568 $comment.addClass('comment-deleting');
569 $comment.hide('fast');
569 $comment.hide('fast');
570
570
571 var success = function(response) {
571 var success = function(response) {
572 $comment.remove();
572 $comment.remove();
573 return false;
573 return false;
574 };
574 };
575 var failure = function(jqXHR, textStatus, errorThrown) {
575 var failure = function(jqXHR, textStatus, errorThrown) {
576 var prefix = "Error while deleting this comment.\n"
576 var prefix = "Error while deleting this comment.\n"
577 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
577 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
578 ajaxErrorSwal(message);
578 ajaxErrorSwal(message);
579
579
580 $comment.show('fast');
580 $comment.show('fast');
581 $comment.removeClass('comment-deleting');
581 $comment.removeClass('comment-deleting');
582 return false;
582 return false;
583 };
583 };
584 ajaxPOST(url, postData, success, failure);
584 ajaxPOST(url, postData, success, failure);
585 }
585 }
586
586
587 this.deleteComment = function(node) {
587 this.deleteComment = function(node) {
588 var $comment = $(node).closest('.comment');
588 var $comment = $(node).closest('.comment');
589 var comment_id = $comment.attr('data-comment-id');
589 var comment_id = $comment.attr('data-comment-id');
590
590
591 Swal.fire({
591 Swal.fire({
592 title: 'Delete this comment?',
592 title: 'Delete this comment?',
593 icon: 'warning',
593 icon: 'warning',
594 showCancelButton: true,
594 showCancelButton: true,
595 confirmButtonColor: '#84a5d2',
595 confirmButtonColor: '#84a5d2',
596 cancelButtonColor: '#e85e4d',
596 cancelButtonColor: '#e85e4d',
597 confirmButtonText: _gettext('Yes, delete comment #{0}!').format(comment_id)
597 confirmButtonText: _gettext('Yes, delete comment #{0}!').format(comment_id),
598 showClass: {
599 popup: 'swal2-noanimation',
600 backdrop: 'swal2-noanimation'
601 },
602 hideClass: {
603 popup: '',
604 backdrop: ''
605 }
598 }).then(function(result) {
606 }).then(function(result) {
599 if (result.value) {
607 if (result.value) {
600 self._deleteComment(node);
608 self._deleteComment(node);
601 }
609 }
602 })
610 })
603 };
611 };
604
612
605 this.toggleWideMode = function (node) {
613 this.toggleWideMode = function (node) {
606 if ($('#content').hasClass('wrapper')) {
614 if ($('#content').hasClass('wrapper')) {
607 $('#content').removeClass("wrapper");
615 $('#content').removeClass("wrapper");
608 $('#content').addClass("wide-mode-wrapper");
616 $('#content').addClass("wide-mode-wrapper");
609 $(node).addClass('btn-success');
617 $(node).addClass('btn-success');
610 return true
618 return true
611 } else {
619 } else {
612 $('#content').removeClass("wide-mode-wrapper");
620 $('#content').removeClass("wide-mode-wrapper");
613 $('#content').addClass("wrapper");
621 $('#content').addClass("wrapper");
614 $(node).removeClass('btn-success');
622 $(node).removeClass('btn-success');
615 return false
623 return false
616 }
624 }
617
625
618 };
626 };
619
627
620 this.toggleComments = function(node, show) {
628 this.toggleComments = function(node, show) {
621 var $filediff = $(node).closest('.filediff');
629 var $filediff = $(node).closest('.filediff');
622 if (show === true) {
630 if (show === true) {
623 $filediff.removeClass('hide-comments');
631 $filediff.removeClass('hide-comments');
624 } else if (show === false) {
632 } else if (show === false) {
625 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
633 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
626 $filediff.addClass('hide-comments');
634 $filediff.addClass('hide-comments');
627 } else {
635 } else {
628 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
636 $filediff.find('.hide-line-comments').removeClass('hide-line-comments');
629 $filediff.toggleClass('hide-comments');
637 $filediff.toggleClass('hide-comments');
630 }
638 }
631 return false;
639 return false;
632 };
640 };
633
641
634 this.toggleLineComments = function(node) {
642 this.toggleLineComments = function(node) {
635 self.toggleComments(node, true);
643 self.toggleComments(node, true);
636 var $node = $(node);
644 var $node = $(node);
637 // mark outdated comments as visible before the toggle;
645 // mark outdated comments as visible before the toggle;
638 $(node.closest('tr')).find('.comment-outdated').show();
646 $(node.closest('tr')).find('.comment-outdated').show();
639 $node.closest('tr').toggleClass('hide-line-comments');
647 $node.closest('tr').toggleClass('hide-line-comments');
640 };
648 };
641
649
642 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
650 this.createCommentForm = function(formElement, lineno, placeholderText, initAutocompleteActions, resolvesCommentId){
643 var pullRequestId = templateContext.pull_request_data.pull_request_id;
651 var pullRequestId = templateContext.pull_request_data.pull_request_id;
644 var commitId = templateContext.commit_data.commit_id;
652 var commitId = templateContext.commit_data.commit_id;
645
653
646 var commentForm = new CommentForm(
654 var commentForm = new CommentForm(
647 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
655 formElement, commitId, pullRequestId, lineno, initAutocompleteActions, resolvesCommentId);
648 var cm = commentForm.getCmInstance();
656 var cm = commentForm.getCmInstance();
649
657
650 if (resolvesCommentId){
658 if (resolvesCommentId){
651 var placeholderText = _gettext('Leave a resolution comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
659 var placeholderText = _gettext('Leave a resolution comment, or click resolve button to resolve TODO comment #{0}').format(resolvesCommentId);
652 }
660 }
653
661
654 setTimeout(function() {
662 setTimeout(function() {
655 // callbacks
663 // callbacks
656 if (cm !== undefined) {
664 if (cm !== undefined) {
657 commentForm.setPlaceholder(placeholderText);
665 commentForm.setPlaceholder(placeholderText);
658 if (commentForm.isInline()) {
666 if (commentForm.isInline()) {
659 cm.focus();
667 cm.focus();
660 cm.refresh();
668 cm.refresh();
661 }
669 }
662 }
670 }
663 }, 10);
671 }, 10);
664
672
665 // trigger scrolldown to the resolve comment, since it might be away
673 // trigger scrolldown to the resolve comment, since it might be away
666 // from the clicked
674 // from the clicked
667 if (resolvesCommentId){
675 if (resolvesCommentId){
668 var actionNode = $(commentForm.resolvesActionId).offset();
676 var actionNode = $(commentForm.resolvesActionId).offset();
669
677
670 setTimeout(function() {
678 setTimeout(function() {
671 if (actionNode) {
679 if (actionNode) {
672 $('body, html').animate({scrollTop: actionNode.top}, 10);
680 $('body, html').animate({scrollTop: actionNode.top}, 10);
673 }
681 }
674 }, 100);
682 }, 100);
675 }
683 }
676
684
677 // add dropzone support
685 // add dropzone support
678 var insertAttachmentText = function (cm, attachmentName, attachmentStoreUrl, isRendered) {
686 var insertAttachmentText = function (cm, attachmentName, attachmentStoreUrl, isRendered) {
679 var renderer = templateContext.visual.default_renderer;
687 var renderer = templateContext.visual.default_renderer;
680 if (renderer == 'rst') {
688 if (renderer == 'rst') {
681 var attachmentUrl = '`#{0} <{1}>`_'.format(attachmentName, attachmentStoreUrl);
689 var attachmentUrl = '`#{0} <{1}>`_'.format(attachmentName, attachmentStoreUrl);
682 if (isRendered){
690 if (isRendered){
683 attachmentUrl = '\n.. image:: {0}'.format(attachmentStoreUrl);
691 attachmentUrl = '\n.. image:: {0}'.format(attachmentStoreUrl);
684 }
692 }
685 } else if (renderer == 'markdown') {
693 } else if (renderer == 'markdown') {
686 var attachmentUrl = '[{0}]({1})'.format(attachmentName, attachmentStoreUrl);
694 var attachmentUrl = '[{0}]({1})'.format(attachmentName, attachmentStoreUrl);
687 if (isRendered){
695 if (isRendered){
688 attachmentUrl = '!' + attachmentUrl;
696 attachmentUrl = '!' + attachmentUrl;
689 }
697 }
690 } else {
698 } else {
691 var attachmentUrl = '{}'.format(attachmentStoreUrl);
699 var attachmentUrl = '{}'.format(attachmentStoreUrl);
692 }
700 }
693 cm.replaceRange(attachmentUrl+'\n', CodeMirror.Pos(cm.lastLine()));
701 cm.replaceRange(attachmentUrl+'\n', CodeMirror.Pos(cm.lastLine()));
694
702
695 return false;
703 return false;
696 };
704 };
697
705
698 //see: https://www.dropzonejs.com/#configuration
706 //see: https://www.dropzonejs.com/#configuration
699 var storeUrl = pyroutes.url('repo_commit_comment_attachment_upload',
707 var storeUrl = pyroutes.url('repo_commit_comment_attachment_upload',
700 {'repo_name': templateContext.repo_name,
708 {'repo_name': templateContext.repo_name,
701 'commit_id': templateContext.commit_data.commit_id})
709 'commit_id': templateContext.commit_data.commit_id})
702
710
703 var previewTmpl = $(formElement).find('.comment-attachment-uploader-template').get(0);
711 var previewTmpl = $(formElement).find('.comment-attachment-uploader-template').get(0);
704 if (previewTmpl !== undefined){
712 if (previewTmpl !== undefined){
705 var selectLink = $(formElement).find('.pick-attachment').get(0);
713 var selectLink = $(formElement).find('.pick-attachment').get(0);
706 $(formElement).find('.comment-attachment-uploader').dropzone({
714 $(formElement).find('.comment-attachment-uploader').dropzone({
707 url: storeUrl,
715 url: storeUrl,
708 headers: {"X-CSRF-Token": CSRF_TOKEN},
716 headers: {"X-CSRF-Token": CSRF_TOKEN},
709 paramName: function () {
717 paramName: function () {
710 return "attachment"
718 return "attachment"
711 }, // The name that will be used to transfer the file
719 }, // The name that will be used to transfer the file
712 clickable: selectLink,
720 clickable: selectLink,
713 parallelUploads: 1,
721 parallelUploads: 1,
714 maxFiles: 10,
722 maxFiles: 10,
715 maxFilesize: templateContext.attachment_store.max_file_size_mb,
723 maxFilesize: templateContext.attachment_store.max_file_size_mb,
716 uploadMultiple: false,
724 uploadMultiple: false,
717 autoProcessQueue: true, // if false queue will not be processed automatically.
725 autoProcessQueue: true, // if false queue will not be processed automatically.
718 createImageThumbnails: false,
726 createImageThumbnails: false,
719 previewTemplate: previewTmpl.innerHTML,
727 previewTemplate: previewTmpl.innerHTML,
720
728
721 accept: function (file, done) {
729 accept: function (file, done) {
722 done();
730 done();
723 },
731 },
724 init: function () {
732 init: function () {
725
733
726 this.on("sending", function (file, xhr, formData) {
734 this.on("sending", function (file, xhr, formData) {
727 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').hide();
735 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').hide();
728 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').show();
736 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').show();
729 });
737 });
730
738
731 this.on("success", function (file, response) {
739 this.on("success", function (file, response) {
732 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').show();
740 $(formElement).find('.comment-attachment-uploader').find('.dropzone-text').show();
733 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
741 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
734
742
735 var isRendered = false;
743 var isRendered = false;
736 var ext = file.name.split('.').pop();
744 var ext = file.name.split('.').pop();
737 var imageExts = templateContext.attachment_store.image_ext;
745 var imageExts = templateContext.attachment_store.image_ext;
738 if (imageExts.indexOf(ext) !== -1){
746 if (imageExts.indexOf(ext) !== -1){
739 isRendered = true;
747 isRendered = true;
740 }
748 }
741
749
742 insertAttachmentText(cm, file.name, response.repo_fqn_access_path, isRendered)
750 insertAttachmentText(cm, file.name, response.repo_fqn_access_path, isRendered)
743 });
751 });
744
752
745 this.on("error", function (file, errorMessage, xhr) {
753 this.on("error", function (file, errorMessage, xhr) {
746 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
754 $(formElement).find('.comment-attachment-uploader').find('.dropzone-upload').hide();
747
755
748 var error = null;
756 var error = null;
749
757
750 if (xhr !== undefined){
758 if (xhr !== undefined){
751 var httpStatus = xhr.status + " " + xhr.statusText;
759 var httpStatus = xhr.status + " " + xhr.statusText;
752 if (xhr !== undefined && xhr.status >= 500) {
760 if (xhr !== undefined && xhr.status >= 500) {
753 error = httpStatus;
761 error = httpStatus;
754 }
762 }
755 }
763 }
756
764
757 if (error === null) {
765 if (error === null) {
758 error = errorMessage.error || errorMessage || httpStatus;
766 error = errorMessage.error || errorMessage || httpStatus;
759 }
767 }
760 $(file.previewElement).find('.dz-error-message').html('ERROR: {0}'.format(error));
768 $(file.previewElement).find('.dz-error-message').html('ERROR: {0}'.format(error));
761
769
762 });
770 });
763 }
771 }
764 });
772 });
765 }
773 }
766 return commentForm;
774 return commentForm;
767 };
775 };
768
776
769 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
777 this.createGeneralComment = function (lineNo, placeholderText, resolvesCommentId) {
770
778
771 var tmpl = $('#cb-comment-general-form-template').html();
779 var tmpl = $('#cb-comment-general-form-template').html();
772 tmpl = tmpl.format(null, 'general');
780 tmpl = tmpl.format(null, 'general');
773 var $form = $(tmpl);
781 var $form = $(tmpl);
774
782
775 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
783 var $formPlaceholder = $('#cb-comment-general-form-placeholder');
776 var curForm = $formPlaceholder.find('form');
784 var curForm = $formPlaceholder.find('form');
777 if (curForm){
785 if (curForm){
778 curForm.remove();
786 curForm.remove();
779 }
787 }
780 $formPlaceholder.append($form);
788 $formPlaceholder.append($form);
781
789
782 var _form = $($form[0]);
790 var _form = $($form[0]);
783 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
791 var autocompleteActions = ['approve', 'reject', 'as_note', 'as_todo'];
784 var commentForm = this.createCommentForm(
792 var commentForm = this.createCommentForm(
785 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId);
793 _form, lineNo, placeholderText, autocompleteActions, resolvesCommentId);
786 commentForm.initStatusChangeSelector();
794 commentForm.initStatusChangeSelector();
787
795
788 return commentForm;
796 return commentForm;
789 };
797 };
790
798
791 this.createComment = function(node, resolutionComment) {
799 this.createComment = function(node, resolutionComment) {
792 var resolvesCommentId = resolutionComment || null;
800 var resolvesCommentId = resolutionComment || null;
793 var $node = $(node);
801 var $node = $(node);
794 var $td = $node.closest('td');
802 var $td = $node.closest('td');
795 var $form = $td.find('.comment-inline-form');
803 var $form = $td.find('.comment-inline-form');
796
804
797 if (!$form.length) {
805 if (!$form.length) {
798
806
799 var $filediff = $node.closest('.filediff');
807 var $filediff = $node.closest('.filediff');
800 $filediff.removeClass('hide-comments');
808 $filediff.removeClass('hide-comments');
801 var f_path = $filediff.attr('data-f-path');
809 var f_path = $filediff.attr('data-f-path');
802 var lineno = self.getLineNumber(node);
810 var lineno = self.getLineNumber(node);
803 // create a new HTML from template
811 // create a new HTML from template
804 var tmpl = $('#cb-comment-inline-form-template').html();
812 var tmpl = $('#cb-comment-inline-form-template').html();
805 tmpl = tmpl.format(escapeHtml(f_path), lineno);
813 tmpl = tmpl.format(escapeHtml(f_path), lineno);
806 $form = $(tmpl);
814 $form = $(tmpl);
807
815
808 var $comments = $td.find('.inline-comments');
816 var $comments = $td.find('.inline-comments');
809 if (!$comments.length) {
817 if (!$comments.length) {
810 $comments = $(
818 $comments = $(
811 $('#cb-comments-inline-container-template').html());
819 $('#cb-comments-inline-container-template').html());
812 $td.append($comments);
820 $td.append($comments);
813 }
821 }
814
822
815 $td.find('.cb-comment-add-button').before($form);
823 $td.find('.cb-comment-add-button').before($form);
816
824
817 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
825 var placeholderText = _gettext('Leave a comment on line {0}.').format(lineno);
818 var _form = $($form[0]).find('form');
826 var _form = $($form[0]).find('form');
819 var autocompleteActions = ['as_note', 'as_todo'];
827 var autocompleteActions = ['as_note', 'as_todo'];
820 var commentForm = this.createCommentForm(
828 var commentForm = this.createCommentForm(
821 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId);
829 _form, lineno, placeholderText, autocompleteActions, resolvesCommentId);
822
830
823 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
831 $.Topic('/ui/plugins/code/comment_form_built').prepareOrPublish({
824 form: _form,
832 form: _form,
825 parent: $td[0],
833 parent: $td[0],
826 lineno: lineno,
834 lineno: lineno,
827 f_path: f_path}
835 f_path: f_path}
828 );
836 );
829
837
830 // set a CUSTOM submit handler for inline comments.
838 // set a CUSTOM submit handler for inline comments.
831 commentForm.setHandleFormSubmit(function(o) {
839 commentForm.setHandleFormSubmit(function(o) {
832 var text = commentForm.cm.getValue();
840 var text = commentForm.cm.getValue();
833 var commentType = commentForm.getCommentType();
841 var commentType = commentForm.getCommentType();
834 var resolvesCommentId = commentForm.getResolvesId();
842 var resolvesCommentId = commentForm.getResolvesId();
835
843
836 if (text === "") {
844 if (text === "") {
837 return;
845 return;
838 }
846 }
839
847
840 if (lineno === undefined) {
848 if (lineno === undefined) {
841 alert('missing line !');
849 alert('missing line !');
842 return;
850 return;
843 }
851 }
844 if (f_path === undefined) {
852 if (f_path === undefined) {
845 alert('missing file path !');
853 alert('missing file path !');
846 return;
854 return;
847 }
855 }
848
856
849 var excludeCancelBtn = false;
857 var excludeCancelBtn = false;
850 var submitEvent = true;
858 var submitEvent = true;
851 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
859 commentForm.setActionButtonsDisabled(true, excludeCancelBtn, submitEvent);
852 commentForm.cm.setOption("readOnly", true);
860 commentForm.cm.setOption("readOnly", true);
853 var postData = {
861 var postData = {
854 'text': text,
862 'text': text,
855 'f_path': f_path,
863 'f_path': f_path,
856 'line': lineno,
864 'line': lineno,
857 'comment_type': commentType,
865 'comment_type': commentType,
858 'csrf_token': CSRF_TOKEN
866 'csrf_token': CSRF_TOKEN
859 };
867 };
860 if (resolvesCommentId){
868 if (resolvesCommentId){
861 postData['resolves_comment_id'] = resolvesCommentId;
869 postData['resolves_comment_id'] = resolvesCommentId;
862 }
870 }
863
871
864 var submitSuccessCallback = function(json_data) {
872 var submitSuccessCallback = function(json_data) {
865 $form.remove();
873 $form.remove();
866 try {
874 try {
867 var html = json_data.rendered_text;
875 var html = json_data.rendered_text;
868 var lineno = json_data.line_no;
876 var lineno = json_data.line_no;
869 var target_id = json_data.target_id;
877 var target_id = json_data.target_id;
870
878
871 $comments.find('.cb-comment-add-button').before(html);
879 $comments.find('.cb-comment-add-button').before(html);
872
880
873 //mark visually which comment was resolved
881 //mark visually which comment was resolved
874 if (resolvesCommentId) {
882 if (resolvesCommentId) {
875 commentForm.markCommentResolved(resolvesCommentId);
883 commentForm.markCommentResolved(resolvesCommentId);
876 }
884 }
877
885
878 // run global callback on submit
886 // run global callback on submit
879 commentForm.globalSubmitSuccessCallback();
887 commentForm.globalSubmitSuccessCallback();
880
888
881 } catch (e) {
889 } catch (e) {
882 console.error(e);
890 console.error(e);
883 }
891 }
884
892
885 // re trigger the linkification of next/prev navigation
893 // re trigger the linkification of next/prev navigation
886 linkifyComments($('.inline-comment-injected'));
894 linkifyComments($('.inline-comment-injected'));
887 timeagoActivate();
895 timeagoActivate();
888 tooltipActivate();
896 tooltipActivate();
889
897
890 if (window.updateSticky !== undefined) {
898 if (window.updateSticky !== undefined) {
891 // potentially our comments change the active window size, so we
899 // potentially our comments change the active window size, so we
892 // notify sticky elements
900 // notify sticky elements
893 updateSticky()
901 updateSticky()
894 }
902 }
895
903
896 commentForm.setActionButtonsDisabled(false);
904 commentForm.setActionButtonsDisabled(false);
897
905
898 };
906 };
899 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
907 var submitFailCallback = function(jqXHR, textStatus, errorThrown) {
900 var prefix = "Error while submitting comment.\n"
908 var prefix = "Error while submitting comment.\n"
901 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
909 var message = formatErrorMessage(jqXHR, textStatus, errorThrown, prefix);
902 ajaxErrorSwal(message);
910 ajaxErrorSwal(message);
903 commentForm.resetCommentFormState(text)
911 commentForm.resetCommentFormState(text)
904 };
912 };
905 commentForm.submitAjaxPOST(
913 commentForm.submitAjaxPOST(
906 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
914 commentForm.submitUrl, postData, submitSuccessCallback, submitFailCallback);
907 });
915 });
908 }
916 }
909
917
910 $form.addClass('comment-inline-form-open');
918 $form.addClass('comment-inline-form-open');
911 };
919 };
912
920
913 this.createResolutionComment = function(commentId){
921 this.createResolutionComment = function(commentId){
914 // hide the trigger text
922 // hide the trigger text
915 $('#resolve-comment-{0}'.format(commentId)).hide();
923 $('#resolve-comment-{0}'.format(commentId)).hide();
916
924
917 var comment = $('#comment-'+commentId);
925 var comment = $('#comment-'+commentId);
918 var commentData = comment.data();
926 var commentData = comment.data();
919 if (commentData.commentInline) {
927 if (commentData.commentInline) {
920 this.createComment(comment, commentId)
928 this.createComment(comment, commentId)
921 } else {
929 } else {
922 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
930 Rhodecode.comments.createGeneralComment('general', "$placeholder", commentId)
923 }
931 }
924
932
925 return false;
933 return false;
926 };
934 };
927
935
928 this.submitResolution = function(commentId){
936 this.submitResolution = function(commentId){
929 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
937 var form = $('#resolve_comment_{0}'.format(commentId)).closest('form');
930 var commentForm = form.get(0).CommentForm;
938 var commentForm = form.get(0).CommentForm;
931
939
932 var cm = commentForm.getCmInstance();
940 var cm = commentForm.getCmInstance();
933 var renderer = templateContext.visual.default_renderer;
941 var renderer = templateContext.visual.default_renderer;
934 if (renderer == 'rst'){
942 if (renderer == 'rst'){
935 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
943 var commentUrl = '`#{0} <{1}#comment-{0}>`_'.format(commentId, commentForm.selfUrl);
936 } else if (renderer == 'markdown') {
944 } else if (renderer == 'markdown') {
937 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
945 var commentUrl = '[#{0}]({1}#comment-{0})'.format(commentId, commentForm.selfUrl);
938 } else {
946 } else {
939 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
947 var commentUrl = '{1}#comment-{0}'.format(commentId, commentForm.selfUrl);
940 }
948 }
941
949
942 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
950 cm.setValue(_gettext('TODO from comment {0} was fixed.').format(commentUrl));
943 form.submit();
951 form.submit();
944 return false;
952 return false;
945 };
953 };
946
954
947 };
955 };
@@ -1,123 +1,159 b''
1 // # Copyright (C) 2010-2020 RhodeCode GmbH
1 // # Copyright (C) 2010-2020 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 /**
19 /**
20 * turns objects into GET query string
20 * turns objects into GET query string
21 */
21 */
22 var toQueryString = function(o) {
22 var toQueryString = function(o) {
23 if(typeof o === 'string') {
23 if(typeof o === 'string') {
24 return o;
24 return o;
25 }
25 }
26 if(typeof o !== 'object') {
26 if(typeof o !== 'object') {
27 return false;
27 return false;
28 }
28 }
29 var _p, _qs = [];
29 var _p, _qs = [];
30 for(_p in o) {
30 for(_p in o) {
31 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
31 _qs.push(encodeURIComponent(_p) + '=' + encodeURIComponent(o[_p]));
32 }
32 }
33 return _qs.join('&');
33 return _qs.join('&');
34 };
34 };
35
35
36 /**
36 /**
37 * ajax call wrappers
37 * ajax call wrappers
38 */
38 */
39
39
40 var ajaxGET = function (url, success, failure) {
40 var ajaxGET = function (url, success, failure) {
41 var sUrl = url;
41 var sUrl = url;
42 var request = $.ajax({
42 var request = $.ajax({
43 url: sUrl,
43 url: sUrl,
44 headers: {'X-PARTIAL-XHR': true}
44 headers: {'X-PARTIAL-XHR': true}
45 })
45 })
46 .done(function (data) {
46 .done(function (data) {
47 success(data);
47 success(data);
48 })
48 })
49 .fail(function (jqXHR, textStatus, errorThrown) {
49 .fail(function (jqXHR, textStatus, errorThrown) {
50 if (failure) {
50 if (failure) {
51 failure(jqXHR, textStatus, errorThrown);
51 failure(jqXHR, textStatus, errorThrown);
52 } else {
52 } else {
53 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
53 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
54 ajaxErrorSwal(message);
54 ajaxErrorSwal(message);
55 }
55 }
56 });
56 });
57 return request;
57 return request;
58 };
58 };
59
59
60 var ajaxPOST = function (url, postData, success, failure) {
60 var ajaxPOST = function (url, postData, success, failure) {
61 var sUrl = url;
61 var sUrl = url;
62 var postData = toQueryString(postData);
62 var postData = toQueryString(postData);
63 var request = $.ajax({
63 var request = $.ajax({
64 type: 'POST',
64 type: 'POST',
65 url: sUrl,
65 url: sUrl,
66 data: postData,
66 data: postData,
67 headers: {'X-PARTIAL-XHR': true}
67 headers: {'X-PARTIAL-XHR': true}
68 })
68 })
69 .done(function (data) {
69 .done(function (data) {
70 success(data);
70 success(data);
71 })
71 })
72 .fail(function (jqXHR, textStatus, errorThrown) {
72 .fail(function (jqXHR, textStatus, errorThrown) {
73 if (failure) {
73 if (failure) {
74 failure(jqXHR, textStatus, errorThrown);
74 failure(jqXHR, textStatus, errorThrown);
75 } else {
75 } else {
76 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
76 var message = formatErrorMessage(jqXHR, textStatus, errorThrown);
77 ajaxErrorSwal(message);
77 ajaxErrorSwal(message);
78 }
78 }
79 });
79 });
80 return request;
80 return request;
81 };
81 };
82
82
83 function formatErrorMessage(jqXHR, textStatus, errorThrown, prefix) {
83 function formatErrorMessage(jqXHR, textStatus, errorThrown, prefix) {
84 if(typeof prefix === "undefined") {
84 if(typeof prefix === "undefined") {
85 prefix = ''
85 prefix = ''
86 }
86 }
87
87
88 if (jqXHR.status === 0) {
88 if (jqXHR.status === 0) {
89 return (prefix + 'Not connected.\nPlease verify your network connection.');
89 return (prefix + 'Not connected.\nPlease verify your network connection.');
90 } else if (jqXHR.status == 401) {
90 } else if (jqXHR.status == 401) {
91 return (prefix + 'Unauthorized access. [401]');
91 return (prefix + 'Unauthorized access. [401]');
92 } else if (jqXHR.status == 404) {
92 } else if (jqXHR.status == 404) {
93 return (prefix + 'The requested page not found. [404]');
93 return (prefix + 'The requested page not found. [404]');
94 } else if (jqXHR.status == 500) {
94 } else if (jqXHR.status == 500) {
95 return (prefix + 'Internal Server Error [500].');
95 return (prefix + 'Internal Server Error [500].');
96 } else if (jqXHR.status == 503) {
96 } else if (jqXHR.status == 503) {
97 return (prefix + 'Service unavailable [503].');
97 return (prefix + 'Service unavailable [503].');
98 } else if (errorThrown === 'parsererror') {
98 } else if (errorThrown === 'parsererror') {
99 return (prefix + 'Requested JSON parse failed.');
99 return (prefix + 'Requested JSON parse failed.');
100 } else if (errorThrown === 'timeout') {
100 } else if (errorThrown === 'timeout') {
101 return (prefix + 'Time out error.');
101 return (prefix + 'Time out error.');
102 } else if (errorThrown === 'abort') {
102 } else if (errorThrown === 'abort') {
103 return (prefix + 'Ajax request aborted.');
103 return (prefix + 'Ajax request aborted.');
104 } else {
104 } else {
105 return (prefix + 'Uncaught Error.\n' + jqXHR.responseText);
105 return (prefix + 'Uncaught Error.\n' + jqXHR.responseText);
106 }
106 }
107 }
107 }
108
108
109 function ajaxErrorSwal(message) {
109 function ajaxErrorSwal(message) {
110 Swal.fire({
110 Swal.fire({
111 icon: 'error',
111 icon: 'error',
112 title: _gettext('Ajax Error'),
112 title: _gettext('Ajax Error'),
113 html: '<span style="white-space: pre-line">{0}</span>'.format(message),
113 html: '<span style="white-space: pre-line">{0}</span>'.format(message),
114 showClass: {
114 showClass: {
115 popup: 'swal2-noanimation',
115 popup: 'swal2-noanimation',
116 backdrop: 'swal2-noanimation'
116 backdrop: 'swal2-noanimation'
117 },
117 },
118 hideClass: {
118 hideClass: {
119 popup: '',
119 popup: '',
120 backdrop: ''
120 backdrop: ''
121 }
121 }
122 })
122 })
123 }
124
125 /*
126 * use in onclick attributes e.g
127 * onclick="submitConfirm(event, this, _gettext('Confirm to delete '), _gettext('Confirm Delete'), 'what we delete')">
128 * */
129 function submitConfirm(event, self, question, confirmText, htmlText) {
130 if (htmlText === "undefined") {
131 htmlText = null;
132 }
133 if (confirmText === "undefined") {
134 confirmText = _gettext('Delete')
135 }
136 event.preventDefault();
137
138 Swal.fire({
139 title: question,
140 icon: 'warning',
141 html: htmlText,
142 showClass: {
143 popup: 'swal2-noanimation',
144 backdrop: 'swal2-noanimation'
145 },
146 hideClass: {
147 popup: '',
148 backdrop: ''
149 },
150 showCancelButton: true,
151 confirmButtonColor: '#84a5d2',
152 cancelButtonColor: '#e85e4d',
153 confirmButtonText: confirmText
154 }).then(function(result) {
155 if (result.value) {
156 $(self).closest("form").submit();
157 }
158 })
123 } No newline at end of file
159 }
@@ -1,110 +1,113 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.mako"/>
2 <%inherit file="/base/base.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4
4
5 <%def name="robots()">
5 <%def name="robots()">
6 %if c.gist.gist_type != 'public':
6 %if c.gist.gist_type != 'public':
7 <meta name="robots" content="noindex, nofollow">
7 <meta name="robots" content="noindex, nofollow">
8 %else:
8 %else:
9 ${parent.robots()}
9 ${parent.robots()}
10 %endif
10 %endif
11 </%def>
11 </%def>
12
12
13 <%def name="title()">
13 <%def name="title()">
14 ${_('Gist')} &middot; ${c.gist.gist_access_id}
14 ${_('Gist')} &middot; ${c.gist.gist_access_id}
15 %if c.rhodecode_name:
15 %if c.rhodecode_name:
16 &middot; ${h.branding(c.rhodecode_name)}
16 &middot; ${h.branding(c.rhodecode_name)}
17 %endif
17 %endif
18 </%def>
18 </%def>
19
19
20 <%def name="breadcrumbs_links()">
20 <%def name="breadcrumbs_links()">
21 ${_('Gist')} &middot; ${c.gist.gist_access_id}
21 ${_('Gist')} &middot; ${c.gist.gist_access_id}
22 </%def>
22 </%def>
23
23
24 <%def name="menu_bar_nav()">
24 <%def name="menu_bar_nav()">
25 ${self.menu_items(active='gists')}
25 ${self.menu_items(active='gists')}
26 </%def>
26 </%def>
27
27
28 <%def name="main()">
28 <%def name="main()">
29 <div class="box">
29 <div class="box">
30 <!-- box / title -->
30 <!-- box / title -->
31
31
32 <div class="table">
32 <div class="table">
33 <div id="files_data">
33 <div id="files_data">
34 <div id="codeblock" class="codeblock">
34 <div id="codeblock" class="codeblock">
35 <div class="code-header">
35 <div class="code-header">
36 <div class="gist_url">
36 <div class="gist_url">
37 <div class="pull-left">
37 <div class="pull-left">
38 <code>
38 <code>
39 ${dt.gist_type(c.gist.gist_type)}
39 ${dt.gist_type(c.gist.gist_type)}
40 <span class="tag disabled">${c.gist.gist_access_id}</span>
40 <span class="tag disabled">${c.gist.gist_access_id}</span>
41 ${c.gist.gist_url()} <span class="icon-clipboard clipboard-action" data-clipboard-text="${c.gist.gist_url()}" title="${_('Copy the url')}"></span>
41 ${c.gist.gist_url()} <span class="icon-clipboard clipboard-action" data-clipboard-text="${c.gist.gist_url()}" title="${_('Copy the url')}"></span>
42 </code>
42 </code>
43 </div>
43 </div>
44
44
45 <div class="pull-right buttons">
45 <div class="pull-right buttons">
46 ## only owner should see that
46 ## only owner should see that
47 <a href="#copySource" onclick="return false;" class="btn btn-mini icon-clipboard no-grey clipboard-action" data-clipboard-text="${c.files[0].content}">${_('Copy content')}</a>
47 <a href="#copySource" onclick="return false;" class="btn btn-mini icon-clipboard no-grey clipboard-action" data-clipboard-text="${c.files[0].content}">${_('Copy content')}</a>
48
48
49 %if c.is_super_admin or c.gist.gist_owner == c.rhodecode_user.user_id:
49 %if c.is_super_admin or c.gist.gist_owner == c.rhodecode_user.user_id:
50 ${h.link_to(_('Edit'), h.route_path('gist_edit', gist_id=c.gist.gist_access_id), class_="btn btn-mini")}
50 ${h.link_to(_('Edit'), h.route_path('gist_edit', gist_id=c.gist.gist_access_id), class_="btn btn-mini")}
51 %endif
51 %endif
52 ${h.link_to(_('Show as Raw'), h.route_path('gist_show_formatted', gist_id=c.gist.gist_access_id, revision='tip', format='raw'), class_="btn btn-mini")}
52 ${h.link_to(_('Show as Raw'), h.route_path('gist_show_formatted', gist_id=c.gist.gist_access_id, revision='tip', format='raw'), class_="btn btn-mini")}
53
53
54 %if c.is_super_admin or c.gist.gist_owner == c.rhodecode_user.user_id:
54 %if c.is_super_admin or c.gist.gist_owner == c.rhodecode_user.user_id:
55 <div class="pull-right remove_gist">
55 <div class="pull-right remove_gist">
56 ${h.secure_form(h.route_path('gist_delete', gist_id=c.gist.gist_access_id), request=request)}
56 ${h.secure_form(h.route_path('gist_delete', gist_id=c.gist.gist_access_id), request=request)}
57 ${h.submit('remove_gist', _('Delete'),class_="btn btn-mini btn-danger",onclick="return confirm('"+_('Confirm to delete this Gist')+"');")}
57 <input class="btn btn-mini btn-danger" id="remove_gist" name="remove_gist"
58 onclick="submitConfirm(event, this, _gettext('Confirm to delete this gist'), _gettext('Delete'), '${c.gist.gist_access_id}')"
59 type="submit" value="${_('Delete')}"
60 >
58 ${h.end_form()}
61 ${h.end_form()}
59 </div>
62 </div>
60 %endif
63 %endif
61 </div>
64 </div>
62 </div>
65 </div>
63
66
64 <div class="gist-desc">
67 <div class="gist-desc">
65 <code>${c.gist.gist_description}</code>
68 <code>${c.gist.gist_description}</code>
66 </div>
69 </div>
67
70
68 <div class="author">
71 <div class="author">
69 <div title="${h.tooltip(c.file_last_commit.author)}">
72 <div title="${h.tooltip(c.file_last_commit.author)}">
70 ${self.gravatar_with_user(c.file_last_commit.author, 16, tooltip=True)} - ${_('created')} ${h.age_component(c.file_last_commit.date)},
73 ${self.gravatar_with_user(c.file_last_commit.author, 16, tooltip=True)} - ${_('created')} ${h.age_component(c.file_last_commit.date)},
71 ${_('expires')}:
74 ${_('expires')}:
72 %if c.gist.gist_expires == -1:
75 %if c.gist.gist_expires == -1:
73 ${_('never')}
76 ${_('never')}
74 %else:
77 %else:
75 ${h.age_component(h.time_to_utcdatetime(c.gist.gist_expires))}
78 ${h.age_component(h.time_to_utcdatetime(c.gist.gist_expires))}
76 %endif
79 %endif
77 </span>
80 </span>
78 </div>
81 </div>
79
82
80 </div>
83 </div>
81 <div class="commit">${h.urlify_commit_message(c.file_last_commit.message, None)}</div>
84 <div class="commit">${h.urlify_commit_message(c.file_last_commit.message, None)}</div>
82 </div>
85 </div>
83
86
84 ## iterate over the files
87 ## iterate over the files
85 % for gist_file in c.files:
88 % for gist_file in c.files:
86 <% renderer = c.render and h.renderer_from_filename(gist_file.path, exclude=['.txt', '.TXT'])%>
89 <% renderer = c.render and h.renderer_from_filename(gist_file.path, exclude=['.txt', '.TXT'])%>
87 <!--
90 <!--
88 <div id="${h.FID('G', gist_file.path)}" class="stats" >
91 <div id="${h.FID('G', gist_file.path)}" class="stats" >
89 <a href="${c.gist.gist_url()}">ΒΆ</a>
92 <a href="${c.gist.gist_url()}">ΒΆ</a>
90 <b >${gist_file.path}</b>
93 <b >${gist_file.path}</b>
91 <div>
94 <div>
92 ${h.link_to(_('Show as raw'), h.route_path('gist_show_formatted_path', gist_id=c.gist.gist_access_id, revision=gist_file.commit.raw_id, format='raw', f_path=gist_file.path), class_="btn btn-mini")}
95 ${h.link_to(_('Show as raw'), h.route_path('gist_show_formatted_path', gist_id=c.gist.gist_access_id, revision=gist_file.commit.raw_id, format='raw', f_path=gist_file.path), class_="btn btn-mini")}
93 </div>
96 </div>
94 </div>
97 </div>
95 -->
98 -->
96 <div class="code-body textarea text-area editor">
99 <div class="code-body textarea text-area editor">
97 %if renderer:
100 %if renderer:
98 ${h.render(gist_file.content, renderer=renderer)}
101 ${h.render(gist_file.content, renderer=renderer)}
99 %else:
102 %else:
100 ${h.pygmentize(gist_file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
103 ${h.pygmentize(gist_file,linenos=True,anchorlinenos=True,lineanchors='L',cssclass="code-highlight")}
101 %endif
104 %endif
102 </div>
105 </div>
103 %endfor
106 %endfor
104 </div>
107 </div>
105 </div>
108 </div>
106 </div>
109 </div>
107
110
108
111
109 </div>
112 </div>
110 </%def>
113 </%def>
@@ -1,190 +1,191 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Authentication Tokens')}</h3>
3 <h3 class="panel-title">${_('Authentication Tokens')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 <div class="apikeys_wrap">
6 <div class="apikeys_wrap">
7 <p>
7 <p>
8 ${_('Authentication tokens can be used to interact with the API, or VCS-over-http. '
8 ${_('Authentication tokens can be used to interact with the API, or VCS-over-http. '
9 'Each token can have a role. Token with a role can be used only in given context, '
9 'Each token can have a role. Token with a role can be used only in given context, '
10 'e.g. VCS tokens can be used together with the authtoken auth plugin for git/hg/svn operations only.')}
10 'e.g. VCS tokens can be used together with the authtoken auth plugin for git/hg/svn operations only.')}
11 </p>
11 </p>
12 <table class="rctable auth_tokens">
12 <table class="rctable auth_tokens">
13 <tr>
13 <tr>
14 <th>${_('Token')}</th>
14 <th>${_('Token')}</th>
15 <th>${_('Description')}</th>
15 <th>${_('Description')}</th>
16 <th>${_('Role')}</th>
16 <th>${_('Role')}</th>
17 <th>${_('Repository Scope')}</th>
17 <th>${_('Repository Scope')}</th>
18 <th>${_('Expiration')}</th>
18 <th>${_('Expiration')}</th>
19 <th>${_('Action')}</th>
19 <th>${_('Action')}</th>
20 </tr>
20 </tr>
21 %if c.user_auth_tokens:
21 %if c.user_auth_tokens:
22 %for auth_token in c.user_auth_tokens:
22 %for auth_token in c.user_auth_tokens:
23 <tr class="${('expired' if auth_token.expired else '')}">
23 <tr class="${('expired' if auth_token.expired else '')}">
24 <td class="truncate-wrap td-authtoken">
24 <td class="truncate-wrap td-authtoken">
25 <div class="user_auth_tokens truncate autoexpand">
25 <div class="user_auth_tokens truncate autoexpand">
26 <code>${auth_token.api_key}</code>
26 <code>${auth_token.api_key}</code>
27 </div>
27 </div>
28 </td>
28 </td>
29 <td class="td-wrap">${auth_token.description}</td>
29 <td class="td-wrap">${auth_token.description}</td>
30 <td class="td-tags">
30 <td class="td-tags">
31 <span class="tag disabled">${auth_token.role_humanized}</span>
31 <span class="tag disabled">${auth_token.role_humanized}</span>
32 </td>
32 </td>
33 <td class="td">${auth_token.scope_humanized}</td>
33 <td class="td">${auth_token.scope_humanized}</td>
34 <td class="td-exp">
34 <td class="td-exp">
35 %if auth_token.expires == -1:
35 %if auth_token.expires == -1:
36 ${_('never')}
36 ${_('never')}
37 %else:
37 %else:
38 %if auth_token.expired:
38 %if auth_token.expired:
39 <span style="text-decoration: line-through">${h.age_component(h.time_to_utcdatetime(auth_token.expires))}</span>
39 <span style="text-decoration: line-through">${h.age_component(h.time_to_utcdatetime(auth_token.expires))}</span>
40 %else:
40 %else:
41 ${h.age_component(h.time_to_utcdatetime(auth_token.expires))}
41 ${h.age_component(h.time_to_utcdatetime(auth_token.expires))}
42 %endif
42 %endif
43 %endif
43 %endif
44 </td>
44 </td>
45 <td class="td-action">
45 <td class="td-action">
46 ${h.secure_form(h.route_path('my_account_auth_tokens_delete'), request=request)}
46 ${h.secure_form(h.route_path('my_account_auth_tokens_delete'), request=request)}
47 ${h.hidden('del_auth_token', auth_token.user_api_key_id)}
47 ${h.hidden('del_auth_token', auth_token.user_api_key_id)}
48 <button class="btn btn-link btn-danger" type="submit"
48 <button class="btn btn-link btn-danger" type="submit"
49 onclick="return confirm('${_('Confirm to remove this auth token: %s') % auth_token.token_obfuscated}');">
49 onclick="submitConfirm(event, this, _gettext('Confirm to delete this auth token'), _gettext('Delete'), '${auth_token.token_obfuscated}')"
50 >
50 ${_('Delete')}
51 ${_('Delete')}
51 </button>
52 </button>
52 ${h.end_form()}
53 ${h.end_form()}
53 </td>
54 </td>
54 </tr>
55 </tr>
55 %endfor
56 %endfor
56 %else:
57 %else:
57 <tr><td><div class="ip">${_('No additional auth tokens specified')}</div></td></tr>
58 <tr><td><div class="ip">${_('No additional auth tokens specified')}</div></td></tr>
58 %endif
59 %endif
59 </table>
60 </table>
60 </div>
61 </div>
61
62
62 <div class="user_auth_tokens">
63 <div class="user_auth_tokens">
63 ${h.secure_form(h.route_path('my_account_auth_tokens_add'), request=request)}
64 ${h.secure_form(h.route_path('my_account_auth_tokens_add'), request=request)}
64 <div class="form form-vertical">
65 <div class="form form-vertical">
65 <!-- fields -->
66 <!-- fields -->
66 <div class="fields">
67 <div class="fields">
67 <div class="field">
68 <div class="field">
68 <div class="label">
69 <div class="label">
69 <label for="new_email">${_('New authentication token')}:</label>
70 <label for="new_email">${_('New authentication token')}:</label>
70 </div>
71 </div>
71 <div class="input">
72 <div class="input">
72 ${h.text('description', class_='medium', placeholder=_('Description'))}
73 ${h.text('description', class_='medium', placeholder=_('Description'))}
73 ${h.hidden('lifetime')}
74 ${h.hidden('lifetime')}
74 ${h.select('role', request.GET.get('token_role', ''), c.role_options)}
75 ${h.select('role', request.GET.get('token_role', ''), c.role_options)}
75
76
76 % if c.allow_scoped_tokens:
77 % if c.allow_scoped_tokens:
77 ${h.hidden('scope_repo_id')}
78 ${h.hidden('scope_repo_id')}
78 % else:
79 % else:
79 ${h.select('scope_repo_id_disabled', '', ['Scopes available in EE edition'], disabled='disabled')}
80 ${h.select('scope_repo_id_disabled', '', ['Scopes available in EE edition'], disabled='disabled')}
80 % endif
81 % endif
81 </div>
82 </div>
82 <p class="help-block">
83 <p class="help-block">
83 ${_('Repository scope works only with tokens with VCS type.')}
84 ${_('Repository scope works only with tokens with VCS type.')}
84 </p>
85 </p>
85 </div>
86 </div>
86 <div class="buttons">
87 <div class="buttons">
87 ${h.submit('save',_('Add'),class_="btn")}
88 ${h.submit('save',_('Add'),class_="btn")}
88 ${h.reset('reset',_('Reset'),class_="btn")}
89 ${h.reset('reset',_('Reset'),class_="btn")}
89 </div>
90 </div>
90 </div>
91 </div>
91 </div>
92 </div>
92 ${h.end_form()}
93 ${h.end_form()}
93 </div>
94 </div>
94 </div>
95 </div>
95 </div>
96 </div>
96
97
97 <script>
98 <script>
98 $(document).ready(function(){
99 $(document).ready(function(){
99
100
100 var select2Options = {
101 var select2Options = {
101 'containerCssClass': "drop-menu",
102 'containerCssClass': "drop-menu",
102 'dropdownCssClass': "drop-menu-dropdown",
103 'dropdownCssClass': "drop-menu-dropdown",
103 'dropdownAutoWidth': true
104 'dropdownAutoWidth': true
104 };
105 };
105 $("#role").select2(select2Options);
106 $("#role").select2(select2Options);
106
107
107 var preloadData = {
108 var preloadData = {
108 results: [
109 results: [
109 % for entry in c.lifetime_values:
110 % for entry in c.lifetime_values:
110 {id:${entry[0]}, text:"${entry[1]}"}${'' if loop.last else ','}
111 {id:${entry[0]}, text:"${entry[1]}"}${'' if loop.last else ','}
111 % endfor
112 % endfor
112 ]
113 ]
113 };
114 };
114
115
115 $("#lifetime").select2({
116 $("#lifetime").select2({
116 containerCssClass: "drop-menu",
117 containerCssClass: "drop-menu",
117 dropdownCssClass: "drop-menu-dropdown",
118 dropdownCssClass: "drop-menu-dropdown",
118 dropdownAutoWidth: true,
119 dropdownAutoWidth: true,
119 data: preloadData,
120 data: preloadData,
120 placeholder: "${_('Select or enter expiration date')}",
121 placeholder: "${_('Select or enter expiration date')}",
121 query: function(query) {
122 query: function(query) {
122 feedLifetimeOptions(query, preloadData);
123 feedLifetimeOptions(query, preloadData);
123 }
124 }
124 });
125 });
125
126
126
127
127 var repoFilter = function(data) {
128 var repoFilter = function(data) {
128 var results = [];
129 var results = [];
129
130
130 if (!data.results[0]) {
131 if (!data.results[0]) {
131 return data
132 return data
132 }
133 }
133
134
134 $.each(data.results[0].children, function() {
135 $.each(data.results[0].children, function() {
135 // replace name to ID for submision
136 // replace name to ID for submision
136 this.id = this.repo_id;
137 this.id = this.repo_id;
137 results.push(this);
138 results.push(this);
138 });
139 });
139
140
140 data.results[0].children = results;
141 data.results[0].children = results;
141 return data;
142 return data;
142 };
143 };
143
144
144 $("#scope_repo_id_disabled").select2(select2Options);
145 $("#scope_repo_id_disabled").select2(select2Options);
145
146
146 var selectVcsScope = function() {
147 var selectVcsScope = function() {
147 // select vcs scope and disable input
148 // select vcs scope and disable input
148 $("#role").select2("val", "${c.role_vcs}").trigger('change');
149 $("#role").select2("val", "${c.role_vcs}").trigger('change');
149 $("#role").select2("readonly", true)
150 $("#role").select2("readonly", true)
150 };
151 };
151
152
152 $("#scope_repo_id").select2({
153 $("#scope_repo_id").select2({
153 cachedDataSource: {},
154 cachedDataSource: {},
154 minimumInputLength: 2,
155 minimumInputLength: 2,
155 placeholder: "${_('repository scope')}",
156 placeholder: "${_('repository scope')}",
156 dropdownAutoWidth: true,
157 dropdownAutoWidth: true,
157 containerCssClass: "drop-menu",
158 containerCssClass: "drop-menu",
158 dropdownCssClass: "drop-menu-dropdown",
159 dropdownCssClass: "drop-menu-dropdown",
159 formatResult: formatRepoResult,
160 formatResult: formatRepoResult,
160 query: $.debounce(250, function(query){
161 query: $.debounce(250, function(query){
161 self = this;
162 self = this;
162 var cacheKey = query.term;
163 var cacheKey = query.term;
163 var cachedData = self.cachedDataSource[cacheKey];
164 var cachedData = self.cachedDataSource[cacheKey];
164
165
165 if (cachedData) {
166 if (cachedData) {
166 query.callback({results: cachedData.results});
167 query.callback({results: cachedData.results});
167 } else {
168 } else {
168 $.ajax({
169 $.ajax({
169 url: pyroutes.url('repo_list_data'),
170 url: pyroutes.url('repo_list_data'),
170 data: {'query': query.term},
171 data: {'query': query.term},
171 dataType: 'json',
172 dataType: 'json',
172 type: 'GET',
173 type: 'GET',
173 success: function(data) {
174 success: function(data) {
174 data = repoFilter(data);
175 data = repoFilter(data);
175 self.cachedDataSource[cacheKey] = data;
176 self.cachedDataSource[cacheKey] = data;
176 query.callback({results: data.results});
177 query.callback({results: data.results});
177 },
178 },
178 error: function(data, textStatus, errorThrown) {
179 error: function(data, textStatus, errorThrown) {
179 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
180 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
180 }
181 }
181 })
182 })
182 }
183 }
183 })
184 })
184 });
185 });
185 $("#scope_repo_id").on('select2-selecting', function(e){
186 $("#scope_repo_id").on('select2-selecting', function(e){
186 selectVcsScope()
187 selectVcsScope()
187 });
188 });
188
189
189 });
190 });
190 </script>
191 </script>
@@ -1,60 +1,61 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <div class="panel panel-default">
3 <div class="panel panel-default">
4 <div class="panel-heading">
4 <div class="panel-heading">
5 <h3 class="panel-title">${_('Account Emails')}</h3>
5 <h3 class="panel-title">${_('Account Emails')}</h3>
6 </div>
6 </div>
7
7
8 <div class="panel-body">
8 <div class="panel-body">
9 <div class="emails_wrap">
9 <div class="emails_wrap">
10 <table class="rctable account_emails">
10 <table class="rctable account_emails">
11 <tr>
11 <tr>
12 <td class="td-user">
12 <td class="td-user">
13 ${base.gravatar(c.user.email, 16)}
13 ${base.gravatar(c.user.email, 16)}
14 <span class="user email">${c.user.email}</span>
14 <span class="user email">${c.user.email}</span>
15 </td>
15 </td>
16 <td class="td-tags">
16 <td class="td-tags">
17 <span class="tag tag1">${_('Primary')}</span>
17 <span class="tag tag1">${_('Primary')}</span>
18 </td>
18 </td>
19 </tr>
19 </tr>
20 %if c.user_email_map:
20 %if c.user_email_map:
21 %for em in c.user_email_map:
21 %for em in c.user_email_map:
22 <tr>
22 <tr>
23 <td class="td-user">
23 <td class="td-user">
24 ${base.gravatar(em.email, 16)}
24 ${base.gravatar(em.email, 16)}
25 <span class="user email">${em.email}</span>
25 <span class="user email">${em.email}</span>
26 </td>
26 </td>
27 <td class="td-action">
27 <td class="td-action">
28 ${h.secure_form(h.route_path('my_account_emails_delete'), request=request)}
28 ${h.secure_form(h.route_path('my_account_emails_delete'), request=request)}
29 ${h.hidden('del_email_id',em.email_id)}
29 ${h.hidden('del_email_id',em.email_id)}
30 <button class="btn btn-link btn-danger" type="submit" id="${'remove_email_%s'.format(em.email_id)}"
30 <button class="btn btn-link btn-danger" type="submit" id="${'remove_email_%s'.format(em.email_id)}"
31 onclick="return confirm('${_('Confirm to delete this email: {}').format(em.email)}');">
31 onclick="submitConfirm(event, this, _gettext('Confirm to delete this email'), _gettext('Delete'), '${em.email}')"
32 >
32 ${_('Delete')}
33 ${_('Delete')}
33 </button>
34 </button>
34 ${h.end_form()}
35 ${h.end_form()}
35 </td>
36 </td>
36 </tr>
37 </tr>
37 %endfor
38 %endfor
38 %else:
39 %else:
39 <tr class="noborder">
40 <tr class="noborder">
40 <td colspan="3">
41 <td colspan="3">
41 <div class="td-email">
42 <div class="td-email">
42 ${_('No additional emails specified')}
43 ${_('No additional emails specified')}
43 </div>
44 </div>
44 </td>
45 </td>
45 </tr>
46 </tr>
46 %endif
47 %endif
47 </table>
48 </table>
48 </div>
49 </div>
49
50
50 % if c.user.extern_type != 'rhodecode':
51 % if c.user.extern_type != 'rhodecode':
51 <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')}
52 <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')}
52 <br/>${_('Source type')}: <strong>${c.user.extern_type}</strong>
53 <br/>${_('Source type')}: <strong>${c.user.extern_type}</strong>
53 </p>
54 </p>
54 % else:
55 % else:
55 <div>
56 <div>
56 ${c.form.render() | n}
57 ${c.form.render() | n}
57 </div>
58 </div>
58 % endif
59 % endif
59 </div>
60 </div>
60 </div>
61 </div>
@@ -1,91 +1,92 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('SSH Keys')}</h3>
3 <h3 class="panel-title">${_('SSH Keys')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 <div class="sshkeys_wrap">
6 <div class="sshkeys_wrap">
7 <table class="rctable ssh_keys">
7 <table class="rctable ssh_keys">
8 <tr>
8 <tr>
9 <th>${_('Fingerprint')}</th>
9 <th>${_('Fingerprint')}</th>
10 <th>${_('Description')}</th>
10 <th>${_('Description')}</th>
11 <th>${_('Created on')}</th>
11 <th>${_('Created on')}</th>
12 <th>${_('Accessed on')}</th>
12 <th>${_('Accessed on')}</th>
13 <th>${_('Action')}</th>
13 <th>${_('Action')}</th>
14 </tr>
14 </tr>
15 % if not c.ssh_enabled:
15 % if not c.ssh_enabled:
16 <tr><td colspan="4"><div class="">${_('SSH Keys usage is currently disabled, please ask your administrator to enable them.')}</div></td></tr>
16 <tr><td colspan="4"><div class="">${_('SSH Keys usage is currently disabled, please ask your administrator to enable them.')}</div></td></tr>
17 % else:
17 % else:
18 %if c.user_ssh_keys:
18 %if c.user_ssh_keys:
19 %for ssh_key in c.user_ssh_keys:
19 %for ssh_key in c.user_ssh_keys:
20 <tr class="">
20 <tr class="">
21 <td class="">
21 <td class="">
22 <code>${ssh_key.ssh_key_fingerprint}</code>
22 <code>${ssh_key.ssh_key_fingerprint}</code>
23 </td>
23 </td>
24 <td class="td-wrap">${ssh_key.description}</td>
24 <td class="td-wrap">${ssh_key.description}</td>
25 <td class="td-tags">${h.format_date(ssh_key.created_on)}</td>
25 <td class="td-tags">${h.format_date(ssh_key.created_on)}</td>
26 <td class="td-tags">${h.format_date(ssh_key.accessed_on)}</td>
26 <td class="td-tags">${h.format_date(ssh_key.accessed_on)}</td>
27
27
28 <td class="td-action">
28 <td class="td-action">
29 ${h.secure_form(h.route_path('my_account_ssh_keys_delete'), request=request)}
29 ${h.secure_form(h.route_path('my_account_ssh_keys_delete'), request=request)}
30 ${h.hidden('del_ssh_key', ssh_key.ssh_key_id)}
30 ${h.hidden('del_ssh_key', ssh_key.ssh_key_id)}
31 <button class="btn btn-link btn-danger" type="submit"
31 <button class="btn btn-link btn-danger" type="submit"
32 onclick="return confirm('${_('Confirm to remove ssh key %s') % ssh_key.ssh_key_fingerprint}');">
32 onclick="submitConfirm(event, this, _gettext('Confirm to delete this ssh key'), _gettext('Delete'), '${ssh_key.ssh_key_fingerprint}')"
33 >
33 ${_('Delete')}
34 ${_('Delete')}
34 </button>
35 </button>
35 ${h.end_form()}
36 ${h.end_form()}
36 </td>
37 </td>
37 </tr>
38 </tr>
38 %endfor
39 %endfor
39 %else:
40 %else:
40 <tr><td colspan="4"><div class="">${_('No additional ssh keys specified')}</div></td></tr>
41 <tr><td colspan="4"><div class="">${_('No additional ssh keys specified')}</div></td></tr>
41 %endif
42 %endif
42 % endif
43 % endif
43 </table>
44 </table>
44 </div>
45 </div>
45
46
46 % if c.ssh_enabled:
47 % if c.ssh_enabled:
47 <div class="user_ssh_keys">
48 <div class="user_ssh_keys">
48 ${h.secure_form(h.route_path('my_account_ssh_keys_add'), request=request)}
49 ${h.secure_form(h.route_path('my_account_ssh_keys_add'), request=request)}
49 <div class="form form-vertical">
50 <div class="form form-vertical">
50 <!-- fields -->
51 <!-- fields -->
51 <div class="fields">
52 <div class="fields">
52 <div class="field">
53 <div class="field">
53 <div class="label">
54 <div class="label">
54 <label for="new_email">${_('New ssh key')}:</label>
55 <label for="new_email">${_('New ssh key')}:</label>
55 </div>
56 </div>
56 <div class="input">
57 <div class="input">
57 ${h.text('description', class_='medium', placeholder=_('Description'))}
58 ${h.text('description', class_='medium', placeholder=_('Description'))}
58 % if c.ssh_key_generator_enabled:
59 % if c.ssh_key_generator_enabled:
59 <a href="${h.route_path('my_account_ssh_keys_generate')}">${_('Generate random RSA key')}</a>
60 <a href="${h.route_path('my_account_ssh_keys_generate')}">${_('Generate random RSA key')}</a>
60 % endif
61 % endif
61 </div>
62 </div>
62 </div>
63 </div>
63
64
64 <div class="field">
65 <div class="field">
65 <div class="textarea text-area editor">
66 <div class="textarea text-area editor">
66 ${h.textarea('key_data',c.default_key, size=30, placeholder=_("Public key, begins with 'ssh-rsa', 'ssh-dss', 'ssh-ed25519', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', or 'ecdsa-sha2-nistp521'"))}
67 ${h.textarea('key_data',c.default_key, size=30, placeholder=_("Public key, begins with 'ssh-rsa', 'ssh-dss', 'ssh-ed25519', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', or 'ecdsa-sha2-nistp521'"))}
67 </div>
68 </div>
68 </div>
69 </div>
69
70
70 <div class="buttons">
71 <div class="buttons">
71 ${h.submit('save',_('Add'),class_="btn")}
72 ${h.submit('save',_('Add'),class_="btn")}
72 ${h.reset('reset',_('Reset'),class_="btn")}
73 ${h.reset('reset',_('Reset'),class_="btn")}
73 </div>
74 </div>
74 % if c.default_key:
75 % if c.default_key:
75 ${_('Click add to use this generated SSH key')}
76 ${_('Click add to use this generated SSH key')}
76 % endif
77 % endif
77 </div>
78 </div>
78 </div>
79 </div>
79 ${h.end_form()}
80 ${h.end_form()}
80 </div>
81 </div>
81 % endif
82 % endif
82 </div>
83 </div>
83 </div>
84 </div>
84
85
85 <script>
86 <script>
86
87
87 $(document).ready(function(){
88 $(document).ready(function(){
88
89
89
90
90 });
91 });
91 </script>
92 </script>
@@ -1,295 +1,299 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <%
3 <%
4 elems = [
4 elems = [
5 (_('Repository ID'), c.rhodecode_db_repo.repo_id, '', ''),
5 (_('Repository ID'), c.rhodecode_db_repo.repo_id, '', ''),
6 (_('Owner'), lambda:base.gravatar_with_user(c.rhodecode_db_repo.user.email, tooltip=True), '', ''),
6 (_('Owner'), lambda:base.gravatar_with_user(c.rhodecode_db_repo.user.email, tooltip=True), '', ''),
7 (_('Created on'), h.format_date(c.rhodecode_db_repo.created_on), '', ''),
7 (_('Created on'), h.format_date(c.rhodecode_db_repo.created_on), '', ''),
8 (_('Updated on'), h.format_date(c.rhodecode_db_repo.updated_on), '', ''),
8 (_('Updated on'), h.format_date(c.rhodecode_db_repo.updated_on), '', ''),
9 (_('Cached Commit id'), lambda: h.link_to(c.rhodecode_db_repo.changeset_cache.get('short_id'), h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.rhodecode_db_repo.changeset_cache.get('raw_id'))), '', ''),
9 (_('Cached Commit id'), lambda: h.link_to(c.rhodecode_db_repo.changeset_cache.get('short_id'), h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.rhodecode_db_repo.changeset_cache.get('raw_id'))), '', ''),
10 (_('Cached Commit date'), c.rhodecode_db_repo.changeset_cache.get('date'), '', ''),
10 (_('Cached Commit date'), c.rhodecode_db_repo.changeset_cache.get('date'), '', ''),
11 (_('Cached Commit data'), lambda: h.link_to('refresh now', h.current_route_path(request, update_commit_cache=1)), '', ''),
11 (_('Cached Commit data'), lambda: h.link_to('refresh now', h.current_route_path(request, update_commit_cache=1)), '', ''),
12 (_('Attached scoped tokens'), len(c.rhodecode_db_repo.scoped_tokens), '', [x.user for x in c.rhodecode_db_repo.scoped_tokens]),
12 (_('Attached scoped tokens'), len(c.rhodecode_db_repo.scoped_tokens), '', [x.user for x in c.rhodecode_db_repo.scoped_tokens]),
13 (_('Pull requests source'), len(c.rhodecode_db_repo.pull_requests_source), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.source_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_source]),
13 (_('Pull requests source'), len(c.rhodecode_db_repo.pull_requests_source), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.source_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_source]),
14 (_('Pull requests target'), len(c.rhodecode_db_repo.pull_requests_target), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.target_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_target]),
14 (_('Pull requests target'), len(c.rhodecode_db_repo.pull_requests_target), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.target_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_target]),
15 (_('Attached Artifacts'), len(c.rhodecode_db_repo.artifacts), '', ''),
15 (_('Attached Artifacts'), len(c.rhodecode_db_repo.artifacts), '', ''),
16 ]
16 ]
17 %>
17 %>
18
18
19 <div class="panel panel-default">
19 <div class="panel panel-default">
20 <div class="panel-heading" id="advanced-info" >
20 <div class="panel-heading" id="advanced-info" >
21 <h3 class="panel-title">${_('Repository: %s') % c.rhodecode_db_repo.repo_name} <a class="permalink" href="#advanced-info"> ΒΆ</a></h3>
21 <h3 class="panel-title">${_('Repository: %s') % c.rhodecode_db_repo.repo_name} <a class="permalink" href="#advanced-info"> ΒΆ</a></h3>
22 </div>
22 </div>
23 <div class="panel-body">
23 <div class="panel-body">
24 ${base.dt_info_panel(elems)}
24 ${base.dt_info_panel(elems)}
25 </div>
25 </div>
26 </div>
26 </div>
27
27
28
28
29 <div class="panel panel-default">
29 <div class="panel panel-default">
30 <div class="panel-heading" id="advanced-fork">
30 <div class="panel-heading" id="advanced-fork">
31 <h3 class="panel-title">${_('Fork Reference')} <a class="permalink" href="#advanced-fork"> ΒΆ</a></h3>
31 <h3 class="panel-title">${_('Fork Reference')} <a class="permalink" href="#advanced-fork"> ΒΆ</a></h3>
32 </div>
32 </div>
33 <div class="panel-body">
33 <div class="panel-body">
34 ${h.secure_form(h.route_path('edit_repo_advanced_fork', repo_name=c.rhodecode_db_repo.repo_name), request=request)}
34 ${h.secure_form(h.route_path('edit_repo_advanced_fork', repo_name=c.rhodecode_db_repo.repo_name), request=request)}
35
35
36 % if c.rhodecode_db_repo.fork:
36 % if c.rhodecode_db_repo.fork:
37 <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.rhodecode_db_repo.fork.repo_name, h.route_path('repo_summary', repo_name=c.rhodecode_db_repo.fork.repo_name))})}
37 <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.rhodecode_db_repo.fork.repo_name, h.route_path('repo_summary', repo_name=c.rhodecode_db_repo.fork.repo_name))})}
38 | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div>
38 | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div>
39 % endif
39 % endif
40
40
41 <div class="field">
41 <div class="field">
42 ${h.hidden('id_fork_of')}
42 ${h.hidden('id_fork_of')}
43 ${h.submit('set_as_fork_%s' % c.rhodecode_db_repo.repo_name,_('Set'),class_="btn btn-small",)}
43 ${h.submit('set_as_fork_%s' % c.rhodecode_db_repo.repo_name,_('Set'),class_="btn btn-small",)}
44 </div>
44 </div>
45 <div class="field">
45 <div class="field">
46 <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span>
46 <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span>
47 </div>
47 </div>
48 ${h.end_form()}
48 ${h.end_form()}
49 </div>
49 </div>
50 </div>
50 </div>
51
51
52
52
53 <div class="panel panel-default">
53 <div class="panel panel-default">
54 <div class="panel-heading" id="advanced-journal">
54 <div class="panel-heading" id="advanced-journal">
55 <h3 class="panel-title">${_('Public Journal Visibility')} <a class="permalink" href="#advanced-journal"> ΒΆ</a></h3>
55 <h3 class="panel-title">${_('Public Journal Visibility')} <a class="permalink" href="#advanced-journal"> ΒΆ</a></h3>
56 </div>
56 </div>
57 <div class="panel-body">
57 <div class="panel-body">
58 ${h.secure_form(h.route_path('edit_repo_advanced_journal', repo_name=c.rhodecode_db_repo.repo_name), request=request)}
58 ${h.secure_form(h.route_path('edit_repo_advanced_journal', repo_name=c.rhodecode_db_repo.repo_name), request=request)}
59 <div class="field">
59 <div class="field">
60 %if c.in_public_journal:
60 %if c.in_public_journal:
61 <button class="btn btn-small" type="submit">
61 <button class="btn btn-small" type="submit">
62 ${_('Remove from Public Journal')}
62 ${_('Remove from Public Journal')}
63 </button>
63 </button>
64 %else:
64 %else:
65 <button class="btn btn-small" type="submit">
65 <button class="btn btn-small" type="submit">
66 ${_('Add to Public Journal')}
66 ${_('Add to Public Journal')}
67 </button>
67 </button>
68 %endif
68 %endif
69 </div>
69 </div>
70 <div class="field" >
70 <div class="field" >
71 <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span>
71 <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span>
72 </div>
72 </div>
73 ${h.end_form()}
73 ${h.end_form()}
74 </div>
74 </div>
75 </div>
75 </div>
76
76
77
77
78 <div class="panel panel-default">
78 <div class="panel panel-default">
79 <div class="panel-heading" id="advanced-locking">
79 <div class="panel-heading" id="advanced-locking">
80 <h3 class="panel-title">${_('Locking state')} <a class="permalink" href="#advanced-locking"> ΒΆ</a></h3>
80 <h3 class="panel-title">${_('Locking state')} <a class="permalink" href="#advanced-locking"> ΒΆ</a></h3>
81 </div>
81 </div>
82 <div class="panel-body">
82 <div class="panel-body">
83 ${h.secure_form(h.route_path('edit_repo_advanced_locking', repo_name=c.rhodecode_db_repo.repo_name), request=request)}
83 ${h.secure_form(h.route_path('edit_repo_advanced_locking', repo_name=c.rhodecode_db_repo.repo_name), request=request)}
84
84
85 %if c.rhodecode_db_repo.locked[0]:
85 %if c.rhodecode_db_repo.locked[0]:
86 <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.rhodecode_db_repo.locked[0]),
86 <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.rhodecode_db_repo.locked[0]),
87 h.format_date(h. time_to_datetime(c.rhodecode_db_repo.locked[1])), c.rhodecode_db_repo.locked[2])}</div>
87 h.format_date(h. time_to_datetime(c.rhodecode_db_repo.locked[1])), c.rhodecode_db_repo.locked[2])}</div>
88 %else:
88 %else:
89 <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div>
89 <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div>
90 %endif
90 %endif
91
91
92 <div class="field" >
92 <div class="field" >
93 %if c.rhodecode_db_repo.locked[0]:
93 %if c.rhodecode_db_repo.locked[0]:
94 ${h.hidden('set_unlock', '1')}
94 ${h.hidden('set_unlock', '1')}
95 <button class="btn btn-small" type="submit"
95 <button class="btn btn-small" type="submit"
96 onclick="return confirm('${_('Confirm to unlock repository.')}');">
96 onclick="submitConfirm(event, this, _gettext('Confirm to unlock this repository'), _gettext('Unlock'), '${c.rhodecode_db_repo.repo_name}')"
97 >
97 <i class="icon-unlock"></i>
98 <i class="icon-unlock"></i>
98 ${_('Unlock repository')}
99 ${_('Unlock repository')}
99 </button>
100 </button>
100 %else:
101 %else:
101 ${h.hidden('set_lock', '1')}
102 ${h.hidden('set_lock', '1')}
102 <button class="btn btn-small" type="submit"
103 <button class="btn btn-small" type="submit"
103 onclick="return confirm('${_('Confirm to lock repository.')}');">
104 onclick="submitConfirm(event, this, _gettext('Confirm to lock this repository'), _gettext('lock'), '${c.rhodecode_db_repo.repo_name}')"
105 >
104 <i class="icon-lock"></i>
106 <i class="icon-lock"></i>
105 ${_('Lock repository')}
107 ${_('Lock repository')}
106 </button>
108 </button>
107 %endif
109 %endif
108 </div>
110 </div>
109 <div class="field" >
111 <div class="field" >
110 <span class="help-block">
112 <span class="help-block">
111 ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')}
113 ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')}
112 </span>
114 </span>
113 </div>
115 </div>
114 ${h.end_form()}
116 ${h.end_form()}
115 </div>
117 </div>
116 </div>
118 </div>
117
119
118
120
119 <div class="panel panel-default">
121 <div class="panel panel-default">
120 <div class="panel-heading" id="advanced-hooks">
122 <div class="panel-heading" id="advanced-hooks">
121 <h3 class="panel-title">${_('Hooks')} <a class="permalink" href="#advanced-hooks"> ΒΆ</a></h3>
123 <h3 class="panel-title">${_('Hooks')} <a class="permalink" href="#advanced-hooks"> ΒΆ</a></h3>
122 </div>
124 </div>
123 <div class="panel-body">
125 <div class="panel-body">
124 <table class="rctable">
126 <table class="rctable">
125 <th>${_('Hook type')}</th>
127 <th>${_('Hook type')}</th>
126 <th>${_('Hook version')}</th>
128 <th>${_('Hook version')}</th>
127 <th>${_('Current version')}</th>
129 <th>${_('Current version')}</th>
128 % if c.ver_info_dict:
130 % if c.ver_info_dict:
129 <tr>
131 <tr>
130 <td>${_('PRE HOOK')}</td>
132 <td>${_('PRE HOOK')}</td>
131 <td>${c.ver_info_dict['pre_version']}</td>
133 <td>${c.ver_info_dict['pre_version']}</td>
132 <td>${c.rhodecode_version}</td>
134 <td>${c.rhodecode_version}</td>
133 </tr>
135 </tr>
134 <tr>
136 <tr>
135 <td>${_('POST HOOK')}</td>
137 <td>${_('POST HOOK')}</td>
136 <td>${c.ver_info_dict['post_version']}</td>
138 <td>${c.ver_info_dict['post_version']}</td>
137 <td>${c.rhodecode_version}</td>
139 <td>${c.rhodecode_version}</td>
138 </tr>
140 </tr>
139 % else:
141 % else:
140 <tr>
142 <tr>
141 <td>${_('Unable to read hook information from VCS Server')}</td>
143 <td>${_('Unable to read hook information from VCS Server')}</td>
142 </tr>
144 </tr>
143 % endif
145 % endif
144 </table>
146 </table>
145
147
146 <a class="btn btn-primary" href="${h.route_path('edit_repo_advanced_hooks', repo_name=c.repo_name)}"
148 <a class="btn btn-primary" href="${h.route_path('edit_repo_advanced_hooks', repo_name=c.repo_name)}"
147 onclick="return confirm('${_('Confirm to reinstall hooks for this repository.')}');">
149 onclick="return confirm('${_('Confirm to reinstall hooks for this repository.')}');">
148 ${_('Update Hooks')}
150 ${_('Update Hooks')}
149 </a>
151 </a>
150 % if c.hooks_outdated:
152 % if c.hooks_outdated:
151 <span class="alert-error" style="padding: 10px">
153 <span class="alert-error" style="padding: 10px">
152 ${_('Outdated hooks detected, please update hooks using `Update Hooks` action.')}
154 ${_('Outdated hooks detected, please update hooks using `Update Hooks` action.')}
153 </span>
155 </span>
154 % endif
156 % endif
155 </div>
157 </div>
156 </div>
158 </div>
157
159
158 <div class="panel panel-warning">
160 <div class="panel panel-warning">
159 <div class="panel-heading" id="advanced-archive">
161 <div class="panel-heading" id="advanced-archive">
160 <h3 class="panel-title">${_('Archive repository')} <a class="permalink" href="#advanced-archive"> ΒΆ</a></h3>
162 <h3 class="panel-title">${_('Archive repository')} <a class="permalink" href="#advanced-archive"> ΒΆ</a></h3>
161 </div>
163 </div>
162 <div class="panel-body">
164 <div class="panel-body">
163 ${h.secure_form(h.route_path('edit_repo_advanced_archive', repo_name=c.repo_name), request=request)}
165 ${h.secure_form(h.route_path('edit_repo_advanced_archive', repo_name=c.repo_name), request=request)}
164
166
165 <div style="margin: 0 0 20px 0" class="fake-space"></div>
167 <div style="margin: 0 0 20px 0" class="fake-space"></div>
166
168
167 <div class="field">
169 <div class="field">
168 <button class="btn btn-small btn-warning" type="submit"
170 <button class="btn btn-small btn-warning" type="submit"
169 onclick="return confirm('${_('Confirm to archive this repository: %s') % c.repo_name}');">
171 onclick="submitConfirm(event, this, _gettext('Confirm to archive this repository'), _gettext('Archive'), '${c.rhodecode_db_repo.repo_name}')"
172 >
170 ${_('Archive this repository')}
173 ${_('Archive this repository')}
171 </button>
174 </button>
172 </div>
175 </div>
173 <div class="field">
176 <div class="field">
174 <span class="help-block">
177 <span class="help-block">
175 ${_('Archiving the repository will make it entirely read-only. The repository cannot be committed to.'
178 ${_('Archiving the repository will make it entirely read-only. The repository cannot be committed to.'
176 'It is hidden from the search results and dashboard. ')}
179 'It is hidden from the search results and dashboard. ')}
177 </span>
180 </span>
178 </div>
181 </div>
179
182
180 ${h.end_form()}
183 ${h.end_form()}
181 </div>
184 </div>
182 </div>
185 </div>
183
186
184
187
185 <div class="panel panel-danger">
188 <div class="panel panel-danger">
186 <div class="panel-heading" id="advanced-delete">
189 <div class="panel-heading" id="advanced-delete">
187 <h3 class="panel-title">${_('Delete repository')} <a class="permalink" href="#advanced-delete"> ΒΆ</a></h3>
190 <h3 class="panel-title">${_('Delete repository')} <a class="permalink" href="#advanced-delete"> ΒΆ</a></h3>
188 </div>
191 </div>
189 <div class="panel-body">
192 <div class="panel-body">
190 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=c.repo_name), request=request)}
193 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=c.repo_name), request=request)}
191 <table class="display">
194 <table class="display">
192 <tr>
195 <tr>
193 <td>
196 <td>
194 ${_ungettext('This repository has %s fork.', 'This repository has %s forks.', c.rhodecode_db_repo.forks.count()) % c.rhodecode_db_repo.forks.count()}
197 ${_ungettext('This repository has %s fork.', 'This repository has %s forks.', c.rhodecode_db_repo.forks.count()) % c.rhodecode_db_repo.forks.count()}
195 </td>
198 </td>
196 <td>
199 <td>
197 %if c.rhodecode_db_repo.forks.count():
200 %if c.rhodecode_db_repo.forks.count():
198 <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label>
201 <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label>
199 %endif
202 %endif
200 </td>
203 </td>
201 <td>
204 <td>
202 %if c.rhodecode_db_repo.forks.count():
205 %if c.rhodecode_db_repo.forks.count():
203 <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label>
206 <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label>
204 %endif
207 %endif
205 </td>
208 </td>
206 </tr>
209 </tr>
207 <% attached_prs = len(c.rhodecode_db_repo.pull_requests_source + c.rhodecode_db_repo.pull_requests_target) %>
210 <% attached_prs = len(c.rhodecode_db_repo.pull_requests_source + c.rhodecode_db_repo.pull_requests_target) %>
208 % if c.rhodecode_db_repo.pull_requests_source or c.rhodecode_db_repo.pull_requests_target:
211 % if c.rhodecode_db_repo.pull_requests_source or c.rhodecode_db_repo.pull_requests_target:
209 <tr>
212 <tr>
210 <td>
213 <td>
211 ${_ungettext('This repository has %s attached pull request.', 'This repository has %s attached pull requests.', attached_prs) % attached_prs}
214 ${_ungettext('This repository has %s attached pull request.', 'This repository has %s attached pull requests.', attached_prs) % attached_prs}
212 <br/>
215 <br/>
213 ${_('Consider to archive this repository instead.')}
216 ${_('Consider to archive this repository instead.')}
214 </td>
217 </td>
215 <td></td>
218 <td></td>
216 <td></td>
219 <td></td>
217 </tr>
220 </tr>
218 % endif
221 % endif
219 </table>
222 </table>
220 <div style="margin: 0 0 20px 0" class="fake-space"></div>
223 <div style="margin: 0 0 20px 0" class="fake-space"></div>
221
224
222 <div class="field">
225 <div class="field">
223 <button class="btn btn-small btn-danger" type="submit"
226 <button class="btn btn-small btn-danger" type="submit"
224 onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');">
227 onclick="submitConfirm(event, this, _gettext('Confirm to delete this repository'), _gettext('Delete'), '${c.rhodecode_db_repo.repo_name}')"
228 >
225 ${_('Delete this repository')}
229 ${_('Delete this repository')}
226 </button>
230 </button>
227 </div>
231 </div>
228 <div class="field">
232 <div class="field">
229 <span class="help-block">
233 <span class="help-block">
230 ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command available in rhodecode-tools.')}
234 ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command available in rhodecode-tools.')}
231 </span>
235 </span>
232 </div>
236 </div>
233
237
234 ${h.end_form()}
238 ${h.end_form()}
235 </div>
239 </div>
236 </div>
240 </div>
237
241
238
242
239 <script>
243 <script>
240
244
241 var currentRepoId = ${c.rhodecode_db_repo.repo_id};
245 var currentRepoId = ${c.rhodecode_db_repo.repo_id};
242
246
243 var repoTypeFilter = function(data) {
247 var repoTypeFilter = function(data) {
244 var results = [];
248 var results = [];
245
249
246 if (!data.results[0]) {
250 if (!data.results[0]) {
247 return data
251 return data
248 }
252 }
249
253
250 $.each(data.results[0].children, function() {
254 $.each(data.results[0].children, function() {
251 // filter out the SAME repo, it cannot be used as fork of itself
255 // filter out the SAME repo, it cannot be used as fork of itself
252 if (this.repo_id != currentRepoId) {
256 if (this.repo_id != currentRepoId) {
253 this.id = this.repo_id;
257 this.id = this.repo_id;
254 results.push(this)
258 results.push(this)
255 }
259 }
256 });
260 });
257 data.results[0].children = results;
261 data.results[0].children = results;
258 return data;
262 return data;
259 };
263 };
260
264
261 $("#id_fork_of").select2({
265 $("#id_fork_of").select2({
262 cachedDataSource: {},
266 cachedDataSource: {},
263 minimumInputLength: 2,
267 minimumInputLength: 2,
264 placeholder: "${_('Change repository') if c.rhodecode_db_repo.fork else _('Pick repository')}",
268 placeholder: "${_('Change repository') if c.rhodecode_db_repo.fork else _('Pick repository')}",
265 dropdownAutoWidth: true,
269 dropdownAutoWidth: true,
266 containerCssClass: "drop-menu",
270 containerCssClass: "drop-menu",
267 dropdownCssClass: "drop-menu-dropdown",
271 dropdownCssClass: "drop-menu-dropdown",
268 formatResult: formatRepoResult,
272 formatResult: formatRepoResult,
269 query: $.debounce(250, function(query){
273 query: $.debounce(250, function(query){
270 self = this;
274 self = this;
271 var cacheKey = query.term;
275 var cacheKey = query.term;
272 var cachedData = self.cachedDataSource[cacheKey];
276 var cachedData = self.cachedDataSource[cacheKey];
273
277
274 if (cachedData) {
278 if (cachedData) {
275 query.callback({results: cachedData.results});
279 query.callback({results: cachedData.results});
276 } else {
280 } else {
277 $.ajax({
281 $.ajax({
278 url: pyroutes.url('repo_list_data'),
282 url: pyroutes.url('repo_list_data'),
279 data: {'query': query.term, repo_type: '${c.rhodecode_db_repo.repo_type}'},
283 data: {'query': query.term, repo_type: '${c.rhodecode_db_repo.repo_type}'},
280 dataType: 'json',
284 dataType: 'json',
281 type: 'GET',
285 type: 'GET',
282 success: function(data) {
286 success: function(data) {
283 data = repoTypeFilter(data);
287 data = repoTypeFilter(data);
284 self.cachedDataSource[cacheKey] = data;
288 self.cachedDataSource[cacheKey] = data;
285 query.callback({results: data.results});
289 query.callback({results: data.results});
286 },
290 },
287 error: function(data, textStatus, errorThrown) {
291 error: function(data, textStatus, errorThrown) {
288 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
292 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
289 }
293 }
290 })
294 })
291 }
295 }
292 })
296 })
293 });
297 });
294 </script>
298 </script>
295
299
@@ -1,154 +1,158 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Invalidate Cache for Repository')}</h3>
3 <h3 class="panel-title">${_('Invalidate Cache for Repository')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6
6
7 <h4>${_('Manually invalidate the repository cache. On the next access a repository cache will be recreated.')}</h4>
7 <h4>${_('Manually invalidate the repository cache. On the next access a repository cache will be recreated.')}</h4>
8
8
9 <p>
9 <p>
10 ${_('Cache purge can be automated by such api call. Can be called periodically in crontab etc.')}
10 ${_('Cache purge can be automated by such api call. Can be called periodically in crontab etc.')}
11 <br/>
11 <br/>
12 <code>
12 <code>
13 ${h.api_call_example(method='invalidate_cache', args={"repoid": c.rhodecode_db_repo.repo_name})}
13 ${h.api_call_example(method='invalidate_cache', args={"repoid": c.rhodecode_db_repo.repo_name})}
14 </code>
14 </code>
15 </p>
15 </p>
16
16
17 ${h.secure_form(h.route_path('edit_repo_caches', repo_name=c.repo_name), request=request)}
17 ${h.secure_form(h.route_path('edit_repo_caches', repo_name=c.repo_name), request=request)}
18 <div class="form">
18 <div class="form">
19 <div class="fields">
19 <div class="fields">
20 ${h.submit('reset_cache_%s' % c.rhodecode_db_repo.repo_name,_('Invalidate repository cache'),class_="btn btn-small",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")}
20 <input class="btn btn-small" id="reset_cache_${c.rhodecode_db_repo.repo_id}"
21 name="reset_cache_${c.rhodecode_db_repo.repo_id}"
22 onclick="submitConfirm(event, this, _gettext('Confirm to invalidate repository cache'), _gettext('Invalidate Cache'), '${c.rhodecode_db_repo.repo_name}')"
23 type="submit" value="${_('Invalidate repository cache')}"
24 >
21 </div>
25 </div>
22 </div>
26 </div>
23 ${h.end_form()}
27 ${h.end_form()}
24
28
25 </div>
29 </div>
26 </div>
30 </div>
27
31
28
32
29 <div class="panel panel-default">
33 <div class="panel panel-default">
30 <div class="panel-heading">
34 <div class="panel-heading">
31 <h3 class="panel-title">
35 <h3 class="panel-title">
32 ${_('Invalidation keys')}
36 ${_('Invalidation keys')}
33 </h3>
37 </h3>
34 </div>
38 </div>
35 <div class="panel-body">
39 <div class="panel-body">
36 <p>
40 <p>
37 Cache keys used to signal repository state changes after operations such as push, strip etc.
41 Cache keys used to signal repository state changes after operations such as push, strip etc.
38 </p>
42 </p>
39 <div class="field">
43 <div class="field">
40 <a href="#showKeys" onclick="$('#signal-keys').toggle()">${_('Show all')} ${len(c.rhodecode_db_repo.cache_keys)}</a>
44 <a href="#showKeys" onclick="$('#signal-keys').toggle()">${_('Show all')} ${len(c.rhodecode_db_repo.cache_keys)}</a>
41
45
42 <table class="rctable edit_cache" id="signal-keys" style="display: none">
46 <table class="rctable edit_cache" id="signal-keys" style="display: none">
43 <tr>
47 <tr>
44 <th>${_('Key')}</th>
48 <th>${_('Key')}</th>
45 <th>${_('State UID')}</th>
49 <th>${_('State UID')}</th>
46 <th>${_('Namespace')}</th>
50 <th>${_('Namespace')}</th>
47 <th>${_('Active')}</th>
51 <th>${_('Active')}</th>
48 </tr>
52 </tr>
49 %for cache in c.rhodecode_db_repo.cache_keys:
53 %for cache in c.rhodecode_db_repo.cache_keys:
50 <tr>
54 <tr>
51 <td class="td-prefix"><code>${cache.cache_key}</code></td>
55 <td class="td-prefix"><code>${cache.cache_key}</code></td>
52 <td class="td-cachekey"><code>${cache.cache_state_uid}</code></td>
56 <td class="td-cachekey"><code>${cache.cache_state_uid}</code></td>
53 <td class="td-cachekey"><code>${cache.cache_args}</code></td>
57 <td class="td-cachekey"><code>${cache.cache_args}</code></td>
54 <td class="td-active">${h.bool2icon(cache.cache_active)}</td>
58 <td class="td-active">${h.bool2icon(cache.cache_active)}</td>
55 </tr>
59 </tr>
56 %endfor
60 %endfor
57 </table>
61 </table>
58 </div>
62 </div>
59 </div>
63 </div>
60 </div>
64 </div>
61
65
62 <div class="panel panel-default">
66 <div class="panel panel-default">
63 <div class="panel-heading">
67 <div class="panel-heading">
64 <h3 class="panel-title">
68 <h3 class="panel-title">
65 ${_('Cache keys')}
69 ${_('Cache keys')}
66 </h3>
70 </h3>
67 </div>
71 </div>
68 <div class="panel-body">
72 <div class="panel-body">
69 <p>
73 <p>
70 Cache keys used for storing cached values of repository stats,
74 Cache keys used for storing cached values of repository stats,
71 file tree history and file tree search.
75 file tree history and file tree search.
72 Invalidating the cache will remove those entries.
76 Invalidating the cache will remove those entries.
73 </p>
77 </p>
74 <pre>
78 <pre>
75 backend: ${c.region.actual_backend.__class__}
79 backend: ${c.region.actual_backend.__class__}
76 % if c.rhodecode_user.is_admin:
80 % if c.rhodecode_user.is_admin:
77 store: ${c.region.actual_backend.get_store()}
81 store: ${c.region.actual_backend.get_store()}
78 % else:
82 % else:
79 store: ${c.region.actual_backend.get_store().__class__}
83 store: ${c.region.actual_backend.get_store().__class__}
80 % endif
84 % endif
81 </pre>
85 </pre>
82
86
83 <div class="field">
87 <div class="field">
84 <a href="#showKeys" onclick="$('#cache-keys').toggle()">${_('Show all')} ${len(c.repo_keys)}</a>
88 <a href="#showKeys" onclick="$('#cache-keys').toggle()">${_('Show all')} ${len(c.repo_keys)}</a>
85
89
86 <table class="rctable edit_cache" id="cache-keys" style="display: none">
90 <table class="rctable edit_cache" id="cache-keys" style="display: none">
87 <tr>
91 <tr>
88 <th>${_('Key')}</th>
92 <th>${_('Key')}</th>
89 <th>${_('Region')}</th>
93 <th>${_('Region')}</th>
90 </tr>
94 </tr>
91 %for cache_key in c.repo_keys:
95 %for cache_key in c.repo_keys:
92 <tr>
96 <tr>
93 <td class="td-prefix"><code>${cache_key}</code></td>
97 <td class="td-prefix"><code>${cache_key}</code></td>
94 <td class="td-cachekey">${c.region.name}</td>
98 <td class="td-cachekey">${c.region.name}</td>
95 </tr>
99 </tr>
96 %endfor
100 %endfor
97 </table>
101 </table>
98 </div>
102 </div>
99
103
100 </div>
104 </div>
101 </div>
105 </div>
102
106
103
107
104 <div class="panel panel-default">
108 <div class="panel panel-default">
105 <div class="panel-heading">
109 <div class="panel-heading">
106 <h3 class="panel-title">${_('Shadow Repositories')}</h3>
110 <h3 class="panel-title">${_('Shadow Repositories')}</h3>
107 </div>
111 </div>
108 <div class="panel-body">
112 <div class="panel-body">
109 <table class="rctable edit_cache">
113 <table class="rctable edit_cache">
110 % if c.shadow_repos:
114 % if c.shadow_repos:
111 % for shadow_repo in c.shadow_repos:
115 % for shadow_repo in c.shadow_repos:
112 <tr>
116 <tr>
113 <td>${shadow_repo}</td>
117 <td>${shadow_repo}</td>
114 </tr>
118 </tr>
115 % endfor
119 % endfor
116 % else:
120 % else:
117 <tr>
121 <tr>
118 <td>${_('No Shadow repositories exist for this repository.')}</td>
122 <td>${_('No Shadow repositories exist for this repository.')}</td>
119 </tr>
123 </tr>
120 % endif
124 % endif
121
125
122 </table>
126 </table>
123 </div>
127 </div>
124 </div>
128 </div>
125
129
126
130
127 <div class="panel panel-default">
131 <div class="panel panel-default">
128 <div class="panel-heading">
132 <div class="panel-heading">
129 <h3 class="panel-title">${_('Diff Caches')}</h3>
133 <h3 class="panel-title">${_('Diff Caches')}</h3>
130 </div>
134 </div>
131 <div class="panel-body">
135 <div class="panel-body">
132 <p>
136 <p>
133 Number and size of stored cached diff for commits and pull requests.
137 Number and size of stored cached diff for commits and pull requests.
134 </p>
138 </p>
135 <table class="rctable edit_cache">
139 <table class="rctable edit_cache">
136 <tr>
140 <tr>
137 <td>${_('Cached diff name')}:</td>
141 <td>${_('Cached diff name')}:</td>
138 % if c.rhodecode_user.is_admin:
142 % if c.rhodecode_user.is_admin:
139 <td>${c.rhodecode_db_repo.cached_diffs_dir}</td>
143 <td>${c.rhodecode_db_repo.cached_diffs_dir}</td>
140 % else:
144 % else:
141 <td>${c.rhodecode_db_repo.cached_diffs_relative_dir}</td>
145 <td>${c.rhodecode_db_repo.cached_diffs_relative_dir}</td>
142 % endif
146 % endif
143 </tr>
147 </tr>
144 <tr>
148 <tr>
145 <td>${_('Cached diff files')}:</td>
149 <td>${_('Cached diff files')}:</td>
146 <td>${c.cached_diff_count}</td>
150 <td>${c.cached_diff_count}</td>
147 </tr>
151 </tr>
148 <tr>
152 <tr>
149 <td>${_('Cached diff size')}:</td>
153 <td>${_('Cached diff size')}:</td>
150 <td>${h.format_byte_size(c.cached_diff_size)}</td>
154 <td>${h.format_byte_size(c.cached_diff_size)}</td>
151 </tr>
155 </tr>
152 </table>
156 </table>
153 </div>
157 </div>
154 </div>
158 </div>
@@ -1,68 +1,73 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Remote Sync')}</h3>
3 <h3 class="panel-title">${_('Remote Sync')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6
6
7 <h4>${_('Manually pull/push changes from/to external URLs.')}</h4>
7 <h4>${_('Manually pull/push changes from/to external URLs.')}</h4>
8
8
9 <table>
9 <table>
10 <tr>
10 <tr>
11 <td><div style="min-width: 80px"><strong>${_('Pull url')}</strong></div></td>
11 <td><div style="min-width: 80px"><strong>${_('Pull url')}</strong></div></td>
12 <td>
12 <td>
13 % if c.rhodecode_db_repo.clone_uri:
13 % if c.rhodecode_db_repo.clone_uri:
14 <a href="${c.rhodecode_db_repo.clone_uri}">${c.rhodecode_db_repo.clone_uri_hidden}</a>
14 <a href="${c.rhodecode_db_repo.clone_uri}">${c.rhodecode_db_repo.clone_uri_hidden}</a>
15 % else:
15 % else:
16 ${_('This repository does not have any pull url set.')}
16 ${_('This repository does not have any pull url set.')}
17 <a href="${h.route_path('edit_repo', repo_name=c.rhodecode_db_repo.repo_name)}">${_('Set remote url.')}</a>
17 <a href="${h.route_path('edit_repo', repo_name=c.rhodecode_db_repo.repo_name)}">${_('Set remote url.')}</a>
18 % endif
18 % endif
19 </td>
19 </td>
20 </tr>
20 </tr>
21 % if c.rhodecode_db_repo.clone_uri:
21 % if c.rhodecode_db_repo.clone_uri:
22 <tr>
22 <tr>
23 <td></td>
23 <td></td>
24 <td>
24 <td>
25 <p>
25 <p>
26 ${_('Pull can be automated by such api call. Can be called periodically in crontab etc.')}
26 ${_('Pull can be automated by such api call. Can be called periodically in crontab etc.')}
27 <br/>
27 <br/>
28 <code>
28 <code>
29 ${h.api_call_example(method='pull', args={"repoid": c.rhodecode_db_repo.repo_name})}
29 ${h.api_call_example(method='pull', args={"repoid": c.rhodecode_db_repo.repo_name})}
30 </code>
30 </code>
31 </p>
31 </p>
32 </td>
32 </td>
33 </tr>
33 </tr>
34 <tr>
34 <tr>
35 <td></td>
35 <td></td>
36 <td>
36 <td>
37 ${h.secure_form(h.route_path('edit_repo_remote_pull', repo_name=c.repo_name), request=request)}
37 ${h.secure_form(h.route_path('edit_repo_remote_pull', repo_name=c.repo_name), request=request)}
38 <div class="form">
38 <div class="form">
39 <div class="fields">
39 <div class="fields">
40 ${h.submit('remote_pull_%s' % c.rhodecode_db_repo.repo_name,_('Pull changes from remote location'),class_="btn btn-small",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
40 <input class="btn btn-small"
41 id="remote_pull_${c.rhodecode_db_repo.repo_id}"
42 name="remote_pull_${c.rhodecode_db_repo.repo_id}"
43 onclick="submitConfirm(event, this, _gettext('Confirm pull changes from remote side'), _gettext('Pull changes'), '${c.rhodecode_db_repo.clone_uri_hidden}')"
44 type="submit" value="${_('Pull changes from remote location')}"
45 >
41 </div>
46 </div>
42 </div>
47 </div>
43 ${h.end_form()}
48 ${h.end_form()}
44 </td>
49 </td>
45 </tr>
50 </tr>
46 % endif
51 % endif
47
52
48 <tr>
53 <tr>
49 <td><div style="min-width: 80px"><strong>${_('Push url')}</strong></div></td>
54 <td><div style="min-width: 80px"><strong>${_('Push url')}</strong></div></td>
50 <td>
55 <td>
51 % if c.rhodecode_db_repo.push_uri:
56 % if c.rhodecode_db_repo.push_uri:
52 <a href="${c.rhodecode_db_repo.push_uri_hidden}">${c.rhodecode_db_repo.push_uri_hidden}</a>
57 <a href="${c.rhodecode_db_repo.push_uri_hidden}">${c.rhodecode_db_repo.push_uri_hidden}</a>
53 % else:
58 % else:
54 ${_('This repository does not have any push url set.')}
59 ${_('This repository does not have any push url set.')}
55 <a href="${h.route_path('edit_repo', repo_name=c.rhodecode_db_repo.repo_name)}">${_('Set remote url.')}</a>
60 <a href="${h.route_path('edit_repo', repo_name=c.rhodecode_db_repo.repo_name)}">${_('Set remote url.')}</a>
56 % endif
61 % endif
57 </td>
62 </td>
58 </tr>
63 </tr>
59 <tr>
64 <tr>
60 <td></td>
65 <td></td>
61 <td>
66 <td>
62 ${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}
67 ${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}
63 </td>
68 </td>
64 </tr>
69 </tr>
65
70
66 </table>
71 </table>
67 </div>
72 </div>
68 </div>
73 </div>
@@ -1,47 +1,47 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Exceptions Tracker - Exception ID')}: ${c.exception_id}</h3>
3 <h3 class="panel-title">${_('Exceptions Tracker - Exception ID')}: ${c.exception_id}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 % if c.traceback:
6 % if c.traceback:
7
7
8 <h4>${_('Exception `{}` generated on UTC date: {}').format(c.traceback.get('exc_type', 'NO_TYPE'), c.traceback.get('exc_utc_date', 'NO_DATE'))}</h4>
8 <h4>${_('Exception `{}` generated on UTC date: {}').format(c.traceback.get('exc_type', 'NO_TYPE'), c.traceback.get('exc_utc_date', 'NO_DATE'))}</h4>
9 % if c.traceback.get('url'):
9 % if c.traceback.get('url'):
10 Request:
10 Request:
11 <code>${c.traceback.get('method')} ${c.traceback.get('url')}</code><br/>
11 <code>${c.traceback.get('method')} ${c.traceback.get('url')}</code><br/>
12 <code>${c.traceback.get('client_address')} ${c.traceback.get('user_agent')}</code>
12 <code>${c.traceback.get('client_address')} ${c.traceback.get('user_agent')}</code>
13 <br/>
13 <br/>
14 <br/>
14 <br/>
15 % endif
15 % endif
16
16
17 <pre>${c.traceback.get('exc_message', 'NO_MESSAGE')}</pre>
17 <pre>${c.traceback.get('exc_message', 'NO_MESSAGE')}</pre>
18
18
19
19
20 % else:
20 % else:
21 ${_('Unable to Read Exception. It might be removed or non-existing.')}
21 ${_('Unable to Read Exception. It might be removed or non-existing.')}
22 % endif
22 % endif
23 </div>
23 </div>
24 </div>
24 </div>
25
25
26
26
27 % if c.traceback:
27 % if c.traceback:
28 <div class="panel panel-danger">
28 <div class="panel panel-danger">
29 <div class="panel-heading" id="advanced-delete">
29 <div class="panel-heading" id="advanced-delete">
30 <h3 class="panel-title">${_('Delete this Exception')}</h3>
30 <h3 class="panel-title">${_('Delete this Exception')}</h3>
31 </div>
31 </div>
32 <div class="panel-body">
32 <div class="panel-body">
33 ${h.secure_form(h.route_path('admin_settings_exception_tracker_delete', exception_id=c.exception_id), request=request)}
33 ${h.secure_form(h.route_path('admin_settings_exception_tracker_delete', exception_id=c.exception_id), request=request)}
34 <div style="margin: 0 0 20px 0" class="fake-space"></div>
34 <div style="margin: 0 0 20px 0" class="fake-space"></div>
35
35
36 <div class="field">
36 <div class="field">
37 <button class="btn btn-small btn-danger" type="submit"
37 <button class="btn btn-small btn-danger" type="submit"
38 onclick="return confirm('${_('Confirm to delete this exception')}');">
38 onclick="submitConfirm(event, this, _gettext('Confirm to delete this exception'), _gettext('Delete'), ${c.exception_id})">
39 <i class="icon-remove"></i>
39 <i class="icon-remove"></i>
40 ${_('Delete This Exception')}
40 ${_('Delete This Exception')}
41 </button>
41 </button>
42 </div>
42 </div>
43
43
44 ${h.end_form()}
44 ${h.end_form()}
45 </div>
45 </div>
46 </div>
46 </div>
47 % endif
47 % endif
@@ -1,65 +1,66 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Exceptions Tracker ')}</h3>
3 <h3 class="panel-title">${_('Exceptions Tracker ')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 % if c.exception_list_count == 1:
6 % if c.exception_list_count == 1:
7 ${_('There is {} stored exception.').format(c.exception_list_count)}
7 ${_('There is {} stored exception.').format(c.exception_list_count)}
8 % else:
8 % else:
9 ${_('There are total {} stored exceptions.').format(c.exception_list_count)}
9 ${_('There are total {} stored exceptions.').format(c.exception_list_count)}
10 % endif
10 % endif
11 <br/>
11 <br/>
12 ${_('Store directory')}: ${c.exception_store_dir}
12 ${_('Store directory')}: ${c.exception_store_dir}
13
13
14 ${h.secure_form(h.route_path('admin_settings_exception_tracker_delete_all'), request=request)}
14 ${h.secure_form(h.route_path('admin_settings_exception_tracker_delete_all'), request=request)}
15 <div style="margin: 0 0 20px 0" class="fake-space"></div>
15 <div style="margin: 0 0 20px 0" class="fake-space"></div>
16 <input type="hidden" name="type_filter", value="${c.type_filter}">
16 <input type="hidden" name="type_filter", value="${c.type_filter}">
17 <div class="field">
17 <div class="field">
18 <button class="btn btn-small btn-danger" type="submit"
18 <button class="btn btn-small btn-danger" type="submit"
19 onclick="return confirm('${_('Confirm to delete all exceptions')}');">
19 onclick="submitConfirm(event, this, _gettext('Confirm to delete all exceptions'), _gettext('Delete'), '${'total:{}'.format(c.exception_list_count)}')"
20 >
20 <i class="icon-remove"></i>
21 <i class="icon-remove"></i>
21 % if c.type_filter:
22 % if c.type_filter:
22 ${_('Delete All `{}`').format(c.type_filter)}
23 ${_('Delete All `{}`').format(c.type_filter)}
23 % else:
24 % else:
24 ${_('Delete All')}
25 ${_('Delete All')}
25 % endif
26 % endif
26
27
27 </button>
28 </button>
28 </div>
29 </div>
29
30
30 ${h.end_form()}
31 ${h.end_form()}
31
32
32 </div>
33 </div>
33 </div>
34 </div>
34
35
35
36
36 <div class="panel panel-default">
37 <div class="panel panel-default">
37 <div class="panel-heading">
38 <div class="panel-heading">
38 <h3 class="panel-title">${_('Exceptions Tracker - Showing the last {} Exceptions').format(c.limit)}.</h3>
39 <h3 class="panel-title">${_('Exceptions Tracker - Showing the last {} Exceptions').format(c.limit)}.</h3>
39 <a class="panel-edit" href="${h.current_route_path(request, limit=c.next_limit)}">${_('Show more')}</a>
40 <a class="panel-edit" href="${h.current_route_path(request, limit=c.next_limit)}">${_('Show more')}</a>
40 </div>
41 </div>
41 <div class="panel-body">
42 <div class="panel-body">
42 <table class="rctable">
43 <table class="rctable">
43 <tr>
44 <tr>
44 <th>#</th>
45 <th>#</th>
45 <th>Exception ID</th>
46 <th>Exception ID</th>
46 <th>Date</th>
47 <th>Date</th>
47 <th>App Type</th>
48 <th>App Type</th>
48 <th>Exc Type</th>
49 <th>Exc Type</th>
49 </tr>
50 </tr>
50 <% cnt = len(c.exception_list)%>
51 <% cnt = len(c.exception_list)%>
51 % for tb in c.exception_list:
52 % for tb in c.exception_list:
52 <tr>
53 <tr>
53 <td>${cnt}</td>
54 <td>${cnt}</td>
54 <td><a href="${h.route_path('admin_settings_exception_tracker_show', exception_id=tb['exc_id'])}"><code>${tb['exc_id']}</code></a></td>
55 <td><a href="${h.route_path('admin_settings_exception_tracker_show', exception_id=tb['exc_id'])}"><code>${tb['exc_id']}</code></a></td>
55 <td>${h.format_date(tb['exc_utc_date'])}</td>
56 <td>${h.format_date(tb['exc_utc_date'])}</td>
56 <td>${tb['app_type']}</td>
57 <td>${tb['app_type']}</td>
57 <td>
58 <td>
58 <a href="${h.current_route_path(request, type_filter=tb['exc_type'])}">${tb['exc_type']}</a>
59 <a href="${h.current_route_path(request, type_filter=tb['exc_type'])}">${tb['exc_type']}</a>
59 </td>
60 </td>
60 </tr>
61 </tr>
61 <% cnt -=1 %>
62 <% cnt -=1 %>
62 % endfor
63 % endfor
63 </table>
64 </table>
64 </div>
65 </div>
65 </div>
66 </div>
@@ -1,479 +1,489 b''
1 ## DATA TABLE RE USABLE ELEMENTS
1 ## DATA TABLE RE USABLE ELEMENTS
2 ## usage:
2 ## usage:
3 ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 ## <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4 <%namespace name="base" file="/base/base.mako"/>
4 <%namespace name="base" file="/base/base.mako"/>
5
5
6 <%def name="metatags_help()">
6 <%def name="metatags_help()">
7 <table>
7 <table>
8 <%
8 <%
9 example_tags = [
9 example_tags = [
10 ('state','[stable]'),
10 ('state','[stable]'),
11 ('state','[stale]'),
11 ('state','[stale]'),
12 ('state','[featured]'),
12 ('state','[featured]'),
13 ('state','[dev]'),
13 ('state','[dev]'),
14 ('state','[dead]'),
14 ('state','[dead]'),
15 ('state','[deprecated]'),
15 ('state','[deprecated]'),
16
16
17 ('label','[personal]'),
17 ('label','[personal]'),
18 ('generic','[v2.0.0]'),
18 ('generic','[v2.0.0]'),
19
19
20 ('lang','[lang =&gt; JavaScript]'),
20 ('lang','[lang =&gt; JavaScript]'),
21 ('license','[license =&gt; LicenseName]'),
21 ('license','[license =&gt; LicenseName]'),
22
22
23 ('ref','[requires =&gt; RepoName]'),
23 ('ref','[requires =&gt; RepoName]'),
24 ('ref','[recommends =&gt; GroupName]'),
24 ('ref','[recommends =&gt; GroupName]'),
25 ('ref','[conflicts =&gt; SomeName]'),
25 ('ref','[conflicts =&gt; SomeName]'),
26 ('ref','[base =&gt; SomeName]'),
26 ('ref','[base =&gt; SomeName]'),
27 ('url','[url =&gt; [linkName](https://rhodecode.com)]'),
27 ('url','[url =&gt; [linkName](https://rhodecode.com)]'),
28 ('see','[see =&gt; http://rhodecode.com]'),
28 ('see','[see =&gt; http://rhodecode.com]'),
29 ]
29 ]
30 %>
30 %>
31 % for tag_type, tag in example_tags:
31 % for tag_type, tag in example_tags:
32 <tr>
32 <tr>
33 <td>${tag|n}</td>
33 <td>${tag|n}</td>
34 <td>${h.style_metatag(tag_type, tag)|n}</td>
34 <td>${h.style_metatag(tag_type, tag)|n}</td>
35 </tr>
35 </tr>
36 % endfor
36 % endfor
37 </table>
37 </table>
38 </%def>
38 </%def>
39
39
40 <%def name="render_description(description, stylify_metatags)">
40 <%def name="render_description(description, stylify_metatags)">
41 <%
41 <%
42 tags = []
42 tags = []
43 if stylify_metatags:
43 if stylify_metatags:
44 tags, description = h.extract_metatags(description)
44 tags, description = h.extract_metatags(description)
45 %>
45 %>
46 % for tag_type, tag in tags:
46 % for tag_type, tag in tags:
47 ${h.style_metatag(tag_type, tag)|n,trim}
47 ${h.style_metatag(tag_type, tag)|n,trim}
48 % endfor
48 % endfor
49 <code style="white-space: pre-wrap">${description}</code>
49 <code style="white-space: pre-wrap">${description}</code>
50 </%def>
50 </%def>
51
51
52 ## REPOSITORY RENDERERS
52 ## REPOSITORY RENDERERS
53 <%def name="quick_menu(repo_name)">
53 <%def name="quick_menu(repo_name)">
54 <i class="icon-more"></i>
54 <i class="icon-more"></i>
55 <div class="menu_items_container hidden">
55 <div class="menu_items_container hidden">
56 <ul class="menu_items">
56 <ul class="menu_items">
57 <li>
57 <li>
58 <a title="${_('Summary')}" href="${h.route_path('repo_summary',repo_name=repo_name)}">
58 <a title="${_('Summary')}" href="${h.route_path('repo_summary',repo_name=repo_name)}">
59 <span>${_('Summary')}</span>
59 <span>${_('Summary')}</span>
60 </a>
60 </a>
61 </li>
61 </li>
62 <li>
62 <li>
63 <a title="${_('Commits')}" href="${h.route_path('repo_commits',repo_name=repo_name)}">
63 <a title="${_('Commits')}" href="${h.route_path('repo_commits',repo_name=repo_name)}">
64 <span>${_('Commits')}</span>
64 <span>${_('Commits')}</span>
65 </a>
65 </a>
66 </li>
66 </li>
67 <li>
67 <li>
68 <a title="${_('Files')}" href="${h.route_path('repo_files:default_commit',repo_name=repo_name)}">
68 <a title="${_('Files')}" href="${h.route_path('repo_files:default_commit',repo_name=repo_name)}">
69 <span>${_('Files')}</span>
69 <span>${_('Files')}</span>
70 </a>
70 </a>
71 </li>
71 </li>
72 <li>
72 <li>
73 <a title="${_('Fork')}" href="${h.route_path('repo_fork_new',repo_name=repo_name)}">
73 <a title="${_('Fork')}" href="${h.route_path('repo_fork_new',repo_name=repo_name)}">
74 <span>${_('Fork')}</span>
74 <span>${_('Fork')}</span>
75 </a>
75 </a>
76 </li>
76 </li>
77 </ul>
77 </ul>
78 </div>
78 </div>
79 </%def>
79 </%def>
80
80
81 <%def name="repo_name(name,rtype,rstate,private,archived,fork_of,short_name=False,admin=False)">
81 <%def name="repo_name(name,rtype,rstate,private,archived,fork_of,short_name=False,admin=False)">
82 <%
82 <%
83 def get_name(name,short_name=short_name):
83 def get_name(name,short_name=short_name):
84 if short_name:
84 if short_name:
85 return name.split('/')[-1]
85 return name.split('/')[-1]
86 else:
86 else:
87 return name
87 return name
88 %>
88 %>
89 <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate">
89 <div class="${'repo_state_pending' if rstate == 'repo_state_pending' else ''} truncate">
90 ##NAME
90 ##NAME
91 <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.route_path('repo_summary',repo_name=name)}">
91 <a href="${h.route_path('edit_repo',repo_name=name) if admin else h.route_path('repo_summary',repo_name=name)}">
92
92
93 ##TYPE OF REPO
93 ##TYPE OF REPO
94 %if h.is_hg(rtype):
94 %if h.is_hg(rtype):
95 <span title="${_('Mercurial repository')}"><i class="icon-hg" style="font-size: 14px;"></i></span>
95 <span title="${_('Mercurial repository')}"><i class="icon-hg" style="font-size: 14px;"></i></span>
96 %elif h.is_git(rtype):
96 %elif h.is_git(rtype):
97 <span title="${_('Git repository')}"><i class="icon-git" style="font-size: 14px"></i></span>
97 <span title="${_('Git repository')}"><i class="icon-git" style="font-size: 14px"></i></span>
98 %elif h.is_svn(rtype):
98 %elif h.is_svn(rtype):
99 <span title="${_('Subversion repository')}"><i class="icon-svn" style="font-size: 14px"></i></span>
99 <span title="${_('Subversion repository')}"><i class="icon-svn" style="font-size: 14px"></i></span>
100 %endif
100 %endif
101
101
102 ##PRIVATE/PUBLIC
102 ##PRIVATE/PUBLIC
103 %if private is True and c.visual.show_private_icon:
103 %if private is True and c.visual.show_private_icon:
104 <i class="icon-lock" title="${_('Private repository')}"></i>
104 <i class="icon-lock" title="${_('Private repository')}"></i>
105 %elif private is False and c.visual.show_public_icon:
105 %elif private is False and c.visual.show_public_icon:
106 <i class="icon-unlock-alt" title="${_('Public repository')}"></i>
106 <i class="icon-unlock-alt" title="${_('Public repository')}"></i>
107 %else:
107 %else:
108 <span></span>
108 <span></span>
109 %endif
109 %endif
110 ${get_name(name)}
110 ${get_name(name)}
111 </a>
111 </a>
112 %if fork_of:
112 %if fork_of:
113 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
113 <a href="${h.route_path('repo_summary',repo_name=fork_of.repo_name)}"><i class="icon-code-fork"></i></a>
114 %endif
114 %endif
115 %if rstate == 'repo_state_pending':
115 %if rstate == 'repo_state_pending':
116 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
116 <span class="creation_in_progress tooltip" title="${_('This repository is being created in a background task')}">
117 (${_('creating...')})
117 (${_('creating...')})
118 </span>
118 </span>
119 %endif
119 %endif
120
120
121 </div>
121 </div>
122 </%def>
122 </%def>
123
123
124 <%def name="repo_desc(description, stylify_metatags)">
124 <%def name="repo_desc(description, stylify_metatags)">
125 <%
125 <%
126 tags, description = h.extract_metatags(description)
126 tags, description = h.extract_metatags(description)
127 %>
127 %>
128
128
129 <div class="truncate-wrap">
129 <div class="truncate-wrap">
130 % if stylify_metatags:
130 % if stylify_metatags:
131 % for tag_type, tag in tags:
131 % for tag_type, tag in tags:
132 ${h.style_metatag(tag_type, tag)|n}
132 ${h.style_metatag(tag_type, tag)|n}
133 % endfor
133 % endfor
134 % endif
134 % endif
135 ${description}
135 ${description}
136 </div>
136 </div>
137
137
138 </%def>
138 </%def>
139
139
140 <%def name="last_change(last_change)">
140 <%def name="last_change(last_change)">
141 ${h.age_component(last_change, time_is_local=True)}
141 ${h.age_component(last_change, time_is_local=True)}
142 </%def>
142 </%def>
143
143
144 <%def name="revision(repo_name, rev, commit_id, author, last_msg, commit_date)">
144 <%def name="revision(repo_name, rev, commit_id, author, last_msg, commit_date)">
145 <div>
145 <div>
146 %if rev >= 0:
146 %if rev >= 0:
147 <code><a class="tooltip-hovercard" data-hovercard-alt=${h.tooltip(last_msg)} data-hovercard-url="${h.route_path('hovercard_repo_commit', repo_name=repo_name, commit_id=commit_id)}" href="${h.route_path('repo_commit',repo_name=repo_name,commit_id=commit_id)}">${'r{}:{}'.format(rev,h.short_id(commit_id))}</a></code>
147 <code><a class="tooltip-hovercard" data-hovercard-alt=${h.tooltip(last_msg)} data-hovercard-url="${h.route_path('hovercard_repo_commit', repo_name=repo_name, commit_id=commit_id)}" href="${h.route_path('repo_commit',repo_name=repo_name,commit_id=commit_id)}">${'r{}:{}'.format(rev,h.short_id(commit_id))}</a></code>
148 %else:
148 %else:
149 ${_('No commits yet')}
149 ${_('No commits yet')}
150 %endif
150 %endif
151 </div>
151 </div>
152 </%def>
152 </%def>
153
153
154 <%def name="rss(name)">
154 <%def name="rss(name)">
155 %if c.rhodecode_user.username != h.DEFAULT_USER:
155 %if c.rhodecode_user.username != h.DEFAULT_USER:
156 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
156 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
157 %else:
157 %else:
158 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
158 <a title="${h.tooltip(_('Subscribe to %s rss feed')% name)}" href="${h.route_path('rss_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
159 %endif
159 %endif
160 </%def>
160 </%def>
161
161
162 <%def name="atom(name)">
162 <%def name="atom(name)">
163 %if c.rhodecode_user.username != h.DEFAULT_USER:
163 %if c.rhodecode_user.username != h.DEFAULT_USER:
164 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
164 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name, _query=dict(auth_token=c.rhodecode_user.feed_token))}"><i class="icon-rss-sign"></i></a>
165 %else:
165 %else:
166 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
166 <a title="${h.tooltip(_('Subscribe to %s atom feed')% name)}" href="${h.route_path('atom_feed_home', repo_name=name)}"><i class="icon-rss-sign"></i></a>
167 %endif
167 %endif
168 </%def>
168 </%def>
169
169
170 <%def name="repo_actions(repo_name, super_user=True)">
170 <%def name="repo_actions(repo_name, super_user=True)">
171 <div>
171 <div>
172 <div class="grid_edit">
172 <div class="grid_edit">
173 <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
173 <a href="${h.route_path('edit_repo',repo_name=repo_name)}" title="${_('Edit')}">
174 Edit
174 Edit
175 </a>
175 </a>
176 </div>
176 </div>
177 <div class="grid_delete">
177 <div class="grid_delete">
178 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), request=request)}
178 ${h.secure_form(h.route_path('edit_repo_advanced_delete', repo_name=repo_name), request=request)}
179 ${h.submit('remove_%s' % repo_name,_('Delete'),class_="btn btn-link btn-danger",
179 <input class="btn btn-link btn-danger" id="remove_${repo_name}" name="remove_${repo_name}"
180 onclick="return confirm('"+_('Confirm to delete this repository: %s') % repo_name+"');")}
180 onclick="submitConfirm(event, this, _gettext('Confirm to delete this repository'), _gettext('Delete'), '${repo_name}')"
181 type="submit" value="Delete"
182 >
181 ${h.end_form()}
183 ${h.end_form()}
182 </div>
184 </div>
183 </div>
185 </div>
184 </%def>
186 </%def>
185
187
186 <%def name="repo_state(repo_state)">
188 <%def name="repo_state(repo_state)">
187 <div>
189 <div>
188 %if repo_state == 'repo_state_pending':
190 %if repo_state == 'repo_state_pending':
189 <div class="tag tag4">${_('Creating')}</div>
191 <div class="tag tag4">${_('Creating')}</div>
190 %elif repo_state == 'repo_state_created':
192 %elif repo_state == 'repo_state_created':
191 <div class="tag tag1">${_('Created')}</div>
193 <div class="tag tag1">${_('Created')}</div>
192 %else:
194 %else:
193 <div class="tag alert2" title="${h.tooltip(repo_state)}">invalid</div>
195 <div class="tag alert2" title="${h.tooltip(repo_state)}">invalid</div>
194 %endif
196 %endif
195 </div>
197 </div>
196 </%def>
198 </%def>
197
199
198
200
199 ## REPO GROUP RENDERERS
201 ## REPO GROUP RENDERERS
200 <%def name="quick_repo_group_menu(repo_group_name)">
202 <%def name="quick_repo_group_menu(repo_group_name)">
201 <i class="icon-more"></i>
203 <i class="icon-more"></i>
202 <div class="menu_items_container hidden">
204 <div class="menu_items_container hidden">
203 <ul class="menu_items">
205 <ul class="menu_items">
204 <li>
206 <li>
205 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">${_('Summary')}</a>
207 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">${_('Summary')}</a>
206 </li>
208 </li>
207
209
208 </ul>
210 </ul>
209 </div>
211 </div>
210 </%def>
212 </%def>
211
213
212 <%def name="repo_group_name(repo_group_name, children_groups=None)">
214 <%def name="repo_group_name(repo_group_name, children_groups=None)">
213 <div>
215 <div>
214 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">
216 <a href="${h.route_path('repo_group_home', repo_group_name=repo_group_name)}">
215 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
217 <i class="icon-repo-group" title="${_('Repository group')}" style="font-size: 14px"></i>
216 %if children_groups:
218 %if children_groups:
217 ${h.literal(' &raquo; '.join(children_groups))}
219 ${h.literal(' &raquo; '.join(children_groups))}
218 %else:
220 %else:
219 ${repo_group_name}
221 ${repo_group_name}
220 %endif
222 %endif
221 </a>
223 </a>
222 </div>
224 </div>
223 </%def>
225 </%def>
224
226
225 <%def name="repo_group_desc(description, personal, stylify_metatags)">
227 <%def name="repo_group_desc(description, personal, stylify_metatags)">
226
228
227 <%
229 <%
228 if stylify_metatags:
230 if stylify_metatags:
229 tags, description = h.extract_metatags(description)
231 tags, description = h.extract_metatags(description)
230 %>
232 %>
231
233
232 <div class="truncate-wrap">
234 <div class="truncate-wrap">
233 % if personal:
235 % if personal:
234 <div class="metatag" tag="personal">${_('personal')}</div>
236 <div class="metatag" tag="personal">${_('personal')}</div>
235 % endif
237 % endif
236
238
237 % if stylify_metatags:
239 % if stylify_metatags:
238 % for tag_type, tag in tags:
240 % for tag_type, tag in tags:
239 ${h.style_metatag(tag_type, tag)|n}
241 ${h.style_metatag(tag_type, tag)|n}
240 % endfor
242 % endfor
241 % endif
243 % endif
242 ${description}
244 ${description}
243 </div>
245 </div>
244
246
245 </%def>
247 </%def>
246
248
247 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
249 <%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
248 <div class="grid_edit">
250 <div class="grid_edit">
249 <a href="${h.route_path('edit_repo_group',repo_group_name=repo_group_name)}" title="${_('Edit')}">Edit</a>
251 <a href="${h.route_path('edit_repo_group',repo_group_name=repo_group_name)}" title="${_('Edit')}">Edit</a>
250 </div>
252 </div>
251 <div class="grid_delete">
253 <div class="grid_delete">
252 ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=repo_group_name), request=request)}
254 ${h.secure_form(h.route_path('edit_repo_group_advanced_delete', repo_group_name=repo_group_name), request=request)}
253 ${h.submit('remove_%s' % repo_group_name,_('Delete'),class_="btn btn-link btn-danger",
255 <input class="btn btn-link btn-danger" id="remove_${repo_group_name}" name="remove_${repo_group_name}"
254 onclick="return confirm('"+_ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)+"');")}
256 onclick="submitConfirm(event, this, _gettext('Confirm to delete this repository group'), _gettext('Delete'), '${_ungettext('`{}` with {} repository','`{}` with {} repositories',gr_count).format(repo_group_name, gr_count)}')"
257 type="submit" value="Delete"
258 >
255 ${h.end_form()}
259 ${h.end_form()}
256 </div>
260 </div>
257 </%def>
261 </%def>
258
262
259
263
260 <%def name="user_actions(user_id, username)">
264 <%def name="user_actions(user_id, username)">
261 <div class="grid_edit">
265 <div class="grid_edit">
262 <a href="${h.route_path('user_edit',user_id=user_id)}" title="${_('Edit')}">
266 <a href="${h.route_path('user_edit',user_id=user_id)}" title="${_('Edit')}">
263 ${_('Edit')}
267 ${_('Edit')}
264 </a>
268 </a>
265 </div>
269 </div>
266 <div class="grid_delete">
270 <div class="grid_delete">
267 ${h.secure_form(h.route_path('user_delete', user_id=user_id), request=request)}
271 ${h.secure_form(h.route_path('user_delete', user_id=user_id), request=request)}
268 ${h.submit('remove_',_('Delete'),id="remove_user_%s" % user_id, class_="btn btn-link btn-danger",
272 <input class="btn btn-link btn-danger" id="remove_user_${user_id}" name="remove_user_${user_id}"
269 onclick="return confirm('"+_('Confirm to delete this user: %s') % username+"');")}
273 onclick="submitConfirm(event, this, _gettext('Confirm to delete this user'), _gettext('Delete'), '${username}')"
274 type="submit" value="Delete"
275 >
270 ${h.end_form()}
276 ${h.end_form()}
271 </div>
277 </div>
272 </%def>
278 </%def>
273
279
274 <%def name="user_group_actions(user_group_id, user_group_name)">
280 <%def name="user_group_actions(user_group_id, user_group_name)">
275 <div class="grid_edit">
281 <div class="grid_edit">
276 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
282 <a href="${h.route_path('edit_user_group', user_group_id=user_group_id)}" title="${_('Edit')}">Edit</a>
277 </div>
283 </div>
278 <div class="grid_delete">
284 <div class="grid_delete">
279 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), request=request)}
285 ${h.secure_form(h.route_path('user_groups_delete', user_group_id=user_group_id), request=request)}
280 ${h.submit('remove_',_('Delete'),id="remove_group_%s" % user_group_id, class_="btn btn-link btn-danger",
286 <input class="btn btn-link btn-danger" id="remove_group_${user_group_id}" name="remove_group_${user_group_id}"
281 onclick="return confirm('"+_('Confirm to delete this user group: %s') % user_group_name+"');")}
287 onclick="submitConfirm(event, this, _gettext('Confirm to delete this user group'), _gettext('Delete'), '${user_group_name}')"
288 type="submit" value="Delete"
289 >
282 ${h.end_form()}
290 ${h.end_form()}
283 </div>
291 </div>
284 </%def>
292 </%def>
285
293
286
294
287 <%def name="user_name(user_id, username)">
295 <%def name="user_name(user_id, username)">
288 ${h.link_to(h.person(username, 'username_or_name_or_email'), h.route_path('user_edit', user_id=user_id))}
296 ${h.link_to(h.person(username, 'username_or_name_or_email'), h.route_path('user_edit', user_id=user_id))}
289 </%def>
297 </%def>
290
298
291 <%def name="user_profile(username)">
299 <%def name="user_profile(username)">
292 ${base.gravatar_with_user(username, 16, tooltip=True)}
300 ${base.gravatar_with_user(username, 16, tooltip=True)}
293 </%def>
301 </%def>
294
302
295 <%def name="user_group_name(user_group_name)">
303 <%def name="user_group_name(user_group_name)">
296 <div>
304 <div>
297 <i class="icon-user-group" title="${_('User group')}"></i>
305 <i class="icon-user-group" title="${_('User group')}"></i>
298 ${h.link_to_group(user_group_name)}
306 ${h.link_to_group(user_group_name)}
299 </div>
307 </div>
300 </%def>
308 </%def>
301
309
302
310
303 ## GISTS
311 ## GISTS
304
312
305 <%def name="gist_gravatar(full_contact)">
313 <%def name="gist_gravatar(full_contact)">
306 <div class="gist_gravatar">
314 <div class="gist_gravatar">
307 ${base.gravatar(full_contact, 30)}
315 ${base.gravatar(full_contact, 30)}
308 </div>
316 </div>
309 </%def>
317 </%def>
310
318
311 <%def name="gist_access_id(gist_access_id, full_contact)">
319 <%def name="gist_access_id(gist_access_id, full_contact)">
312 <div>
320 <div>
313 <code>
321 <code>
314 <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">${gist_access_id}</a>
322 <a href="${h.route_path('gist_show', gist_id=gist_access_id)}">${gist_access_id}</a>
315 </code>
323 </code>
316 </div>
324 </div>
317 </%def>
325 </%def>
318
326
319 <%def name="gist_author(full_contact, created_on, expires)">
327 <%def name="gist_author(full_contact, created_on, expires)">
320 ${base.gravatar_with_user(full_contact, 16, tooltip=True)}
328 ${base.gravatar_with_user(full_contact, 16, tooltip=True)}
321 </%def>
329 </%def>
322
330
323
331
324 <%def name="gist_created(created_on)">
332 <%def name="gist_created(created_on)">
325 <div class="created">
333 <div class="created">
326 ${h.age_component(created_on, time_is_local=True)}
334 ${h.age_component(created_on, time_is_local=True)}
327 </div>
335 </div>
328 </%def>
336 </%def>
329
337
330 <%def name="gist_expires(expires)">
338 <%def name="gist_expires(expires)">
331 <div class="created">
339 <div class="created">
332 %if expires == -1:
340 %if expires == -1:
333 ${_('never')}
341 ${_('never')}
334 %else:
342 %else:
335 ${h.age_component(h.time_to_utcdatetime(expires))}
343 ${h.age_component(h.time_to_utcdatetime(expires))}
336 %endif
344 %endif
337 </div>
345 </div>
338 </%def>
346 </%def>
339
347
340 <%def name="gist_type(gist_type)">
348 <%def name="gist_type(gist_type)">
341 %if gist_type == 'public':
349 %if gist_type == 'public':
342 <span class="tag tag-gist-public disabled">${_('Public Gist')}</span>
350 <span class="tag tag-gist-public disabled">${_('Public Gist')}</span>
343 %else:
351 %else:
344 <span class="tag tag-gist-private disabled">${_('Private Gist')}</span>
352 <span class="tag tag-gist-private disabled">${_('Private Gist')}</span>
345 %endif
353 %endif
346 </%def>
354 </%def>
347
355
348 <%def name="gist_description(gist_description)">
356 <%def name="gist_description(gist_description)">
349 ${gist_description}
357 ${gist_description}
350 </%def>
358 </%def>
351
359
352
360
353 ## PULL REQUESTS GRID RENDERERS
361 ## PULL REQUESTS GRID RENDERERS
354
362
355 <%def name="pullrequest_target_repo(repo_name)">
363 <%def name="pullrequest_target_repo(repo_name)">
356 <div class="truncate">
364 <div class="truncate">
357 ${h.link_to(repo_name,h.route_path('repo_summary',repo_name=repo_name))}
365 ${h.link_to(repo_name,h.route_path('repo_summary',repo_name=repo_name))}
358 </div>
366 </div>
359 </%def>
367 </%def>
360
368
361 <%def name="pullrequest_status(status)">
369 <%def name="pullrequest_status(status)">
362 <i class="icon-circle review-status-${status}"></i>
370 <i class="icon-circle review-status-${status}"></i>
363 </%def>
371 </%def>
364
372
365 <%def name="pullrequest_title(title, description)">
373 <%def name="pullrequest_title(title, description)">
366 ${title}
374 ${title}
367 </%def>
375 </%def>
368
376
369 <%def name="pullrequest_comments(comments_nr)">
377 <%def name="pullrequest_comments(comments_nr)">
370 <i class="icon-comment"></i> ${comments_nr}
378 <i class="icon-comment"></i> ${comments_nr}
371 </%def>
379 </%def>
372
380
373 <%def name="pullrequest_name(pull_request_id, state, is_wip, target_repo_name, short=False)">
381 <%def name="pullrequest_name(pull_request_id, state, is_wip, target_repo_name, short=False)">
374 <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}">
382 <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}">
375
383
376 % if short:
384 % if short:
377 !${pull_request_id}
385 !${pull_request_id}
378 % else:
386 % else:
379 ${_('Pull request !{}').format(pull_request_id)}
387 ${_('Pull request !{}').format(pull_request_id)}
380 % endif
388 % endif
381
389
382 % if state not in ['created']:
390 % if state not in ['created']:
383 <span class="tag tag-merge-state-${state} tooltip" title="Pull request state is changing">${state}</span>
391 <span class="tag tag-merge-state-${state} tooltip" title="Pull request state is changing">${state}</span>
384 % endif
392 % endif
385
393
386 % if is_wip:
394 % if is_wip:
387 <span class="tag tooltip" title="${_('Work in progress')}">wip</span>
395 <span class="tag tooltip" title="${_('Work in progress')}">wip</span>
388 % endif
396 % endif
389 </a>
397 </a>
390 </%def>
398 </%def>
391
399
392 <%def name="pullrequest_updated_on(updated_on)">
400 <%def name="pullrequest_updated_on(updated_on)">
393 ${h.age_component(h.time_to_utcdatetime(updated_on))}
401 ${h.age_component(h.time_to_utcdatetime(updated_on))}
394 </%def>
402 </%def>
395
403
396 <%def name="pullrequest_author(full_contact)">
404 <%def name="pullrequest_author(full_contact)">
397 ${base.gravatar_with_user(full_contact, 16, tooltip=True)}
405 ${base.gravatar_with_user(full_contact, 16, tooltip=True)}
398 </%def>
406 </%def>
399
407
400
408
401 ## ARTIFACT RENDERERS
409 ## ARTIFACT RENDERERS
402 <%def name="repo_artifact_name(repo_name, file_uid, artifact_display_name)">
410 <%def name="repo_artifact_name(repo_name, file_uid, artifact_display_name)">
403 <a href="${h.route_path('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}">
411 <a href="${h.route_path('repo_artifacts_get', repo_name=repo_name, uid=file_uid)}">
404 ${artifact_display_name or '_EMPTY_NAME_'}
412 ${artifact_display_name or '_EMPTY_NAME_'}
405 </a>
413 </a>
406 </%def>
414 </%def>
407
415
408 <%def name="repo_artifact_uid(repo_name, file_uid)">
416 <%def name="repo_artifact_uid(repo_name, file_uid)">
409 <code>${h.shorter(file_uid, size=24, prefix=True)}</code>
417 <code>${h.shorter(file_uid, size=24, prefix=True)}</code>
410 </%def>
418 </%def>
411
419
412 <%def name="repo_artifact_sha256(artifact_sha256)">
420 <%def name="repo_artifact_sha256(artifact_sha256)">
413 <div class="code">${h.shorter(artifact_sha256, 12)}</div>
421 <div class="code">${h.shorter(artifact_sha256, 12)}</div>
414 </%def>
422 </%def>
415
423
416 <%def name="repo_artifact_actions(repo_name, file_store_id, file_uid)">
424 <%def name="repo_artifact_actions(repo_name, file_store_id, file_uid)">
417 ## <div class="grid_edit">
425 ## <div class="grid_edit">
418 ## <a href="#Edit" title="${_('Edit')}">${_('Edit')}</a>
426 ## <a href="#Edit" title="${_('Edit')}">${_('Edit')}</a>
419 ## </div>
427 ## </div>
420 <div class="grid_edit">
428 <div class="grid_edit">
421 <a href="${h.route_path('repo_artifacts_info', repo_name=repo_name, uid=file_store_id)}" title="${_('Info')}">${_('Info')}</a>
429 <a href="${h.route_path('repo_artifacts_info', repo_name=repo_name, uid=file_store_id)}" title="${_('Info')}">${_('Info')}</a>
422 </div>
430 </div>
423 % if h.HasRepoPermissionAny('repository.admin')(c.repo_name):
431 % if h.HasRepoPermissionAny('repository.admin')(c.repo_name):
424 <div class="grid_delete">
432 <div class="grid_delete">
425 ${h.secure_form(h.route_path('repo_artifacts_delete', repo_name=repo_name, uid=file_store_id), request=request)}
433 ${h.secure_form(h.route_path('repo_artifacts_delete', repo_name=repo_name, uid=file_store_id), request=request)}
426 ${h.submit('remove_',_('Delete'),id="remove_artifact_%s" % file_store_id, class_="btn btn-link btn-danger",
434 <input class="btn btn-link btn-danger" id="remove_artifact_${file_store_id}" name="remove_artifact_${file_store_id}"
427 onclick="return confirm('"+_('Confirm to delete this artifact: %s') % file_uid+"');")}
435 onclick="submitConfirm(event, this, _gettext('Confirm to delete this artifact'), _gettext('Delete'), '${file_uid}')"
436 type="submit" value="${_('Delete')}"
437 >
428 ${h.end_form()}
438 ${h.end_form()}
429 </div>
439 </div>
430 % endif
440 % endif
431 </%def>
441 </%def>
432
442
433 <%def name="markup_form(form_id, form_text='', help_text=None)">
443 <%def name="markup_form(form_id, form_text='', help_text=None)">
434
444
435 <div class="markup-form">
445 <div class="markup-form">
436 <div class="markup-form-area">
446 <div class="markup-form-area">
437 <div class="markup-form-area-header">
447 <div class="markup-form-area-header">
438 <ul class="nav-links clearfix">
448 <ul class="nav-links clearfix">
439 <li class="active">
449 <li class="active">
440 <a href="#edit-text" tabindex="-1" id="edit-btn_${form_id}">${_('Write')}</a>
450 <a href="#edit-text" tabindex="-1" id="edit-btn_${form_id}">${_('Write')}</a>
441 </li>
451 </li>
442 <li class="">
452 <li class="">
443 <a href="#preview-text" tabindex="-1" id="preview-btn_${form_id}">${_('Preview')}</a>
453 <a href="#preview-text" tabindex="-1" id="preview-btn_${form_id}">${_('Preview')}</a>
444 </li>
454 </li>
445 </ul>
455 </ul>
446 </div>
456 </div>
447
457
448 <div class="markup-form-area-write" style="display: block;">
458 <div class="markup-form-area-write" style="display: block;">
449 <div id="edit-container_${form_id}">
459 <div id="edit-container_${form_id}">
450 <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea>
460 <textarea id="${form_id}" name="${form_id}" class="comment-block-ta ac-input">${form_text if form_text else ''}</textarea>
451 </div>
461 </div>
452 <div id="preview-container_${form_id}" class="clearfix" style="display: none;">
462 <div id="preview-container_${form_id}" class="clearfix" style="display: none;">
453 <div id="preview-box_${form_id}" class="preview-box"></div>
463 <div id="preview-box_${form_id}" class="preview-box"></div>
454 </div>
464 </div>
455 </div>
465 </div>
456
466
457 <div class="markup-form-area-footer">
467 <div class="markup-form-area-footer">
458 <div class="toolbar">
468 <div class="toolbar">
459 <div class="toolbar-text">
469 <div class="toolbar-text">
460 ${(_('Parsed using %s syntax') % (
470 ${(_('Parsed using %s syntax') % (
461 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
471 ('<a href="%s">%s</a>' % (h.route_url('%s_help' % c.visual.default_renderer), c.visual.default_renderer.upper())),
462 )
472 )
463 )|n}
473 )|n}
464 </div>
474 </div>
465 </div>
475 </div>
466 </div>
476 </div>
467 </div>
477 </div>
468
478
469 <div class="markup-form-footer">
479 <div class="markup-form-footer">
470 % if help_text:
480 % if help_text:
471 <span class="help-block">${help_text}</span>
481 <span class="help-block">${help_text}</span>
472 % endif
482 % endif
473 </div>
483 </div>
474 </div>
484 </div>
475 <script type="text/javascript">
485 <script type="text/javascript">
476 new MarkupForm('${form_id}');
486 new MarkupForm('${form_id}');
477 </script>
487 </script>
478
488
479 </%def>
489 </%def>
@@ -1,911 +1,912 b''
1 <%inherit file="/base/base.mako"/>
1 <%inherit file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
3 <%namespace name="dt" file="/data_table/_dt_elements.mako"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)}
6 ${_('{} Pull Request !{}').format(c.repo_name, c.pull_request.pull_request_id)}
7 %if c.rhodecode_name:
7 %if c.rhodecode_name:
8 &middot; ${h.branding(c.rhodecode_name)}
8 &middot; ${h.branding(c.rhodecode_name)}
9 %endif
9 %endif
10 </%def>
10 </%def>
11
11
12 <%def name="breadcrumbs_links()">
12 <%def name="breadcrumbs_links()">
13
13
14 </%def>
14 </%def>
15
15
16 <%def name="menu_bar_nav()">
16 <%def name="menu_bar_nav()">
17 ${self.menu_items(active='repositories')}
17 ${self.menu_items(active='repositories')}
18 </%def>
18 </%def>
19
19
20 <%def name="menu_bar_subnav()">
20 <%def name="menu_bar_subnav()">
21 ${self.repo_menu(active='showpullrequest')}
21 ${self.repo_menu(active='showpullrequest')}
22 </%def>
22 </%def>
23
23
24 <%def name="main()">
24 <%def name="main()">
25
25
26 <script type="text/javascript">
26 <script type="text/javascript">
27 // TODO: marcink switch this to pyroutes
27 // TODO: marcink switch this to pyroutes
28 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
28 AJAX_COMMENT_DELETE_URL = "${h.route_path('pullrequest_comment_delete',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id,comment_id='__COMMENT_ID__')}";
29 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
29 templateContext.pull_request_data.pull_request_id = ${c.pull_request.pull_request_id};
30 </script>
30 </script>
31
31
32 <div class="box">
32 <div class="box">
33
33
34 <div class="box pr-summary">
34 <div class="box pr-summary">
35
35
36 <div class="summary-details block-left">
36 <div class="summary-details block-left">
37 <div id="pr-title">
37 <div id="pr-title">
38 % if c.pull_request.is_closed():
38 % if c.pull_request.is_closed():
39 <span class="pr-title-closed-tag tag">${_('Closed')}</span>
39 <span class="pr-title-closed-tag tag">${_('Closed')}</span>
40 % endif
40 % endif
41 <input class="pr-title-input large disabled" disabled="disabled" name="pullrequest_title" type="text" value="${c.pull_request.title}">
41 <input class="pr-title-input large disabled" disabled="disabled" name="pullrequest_title" type="text" value="${c.pull_request.title}">
42 </div>
42 </div>
43 <div id="pr-title-edit" class="input" style="display: none;">
43 <div id="pr-title-edit" class="input" style="display: none;">
44 <input class="pr-title-input large" id="pr-title-input" name="pullrequest_title" type="text" value="${c.pull_request.title}">
44 <input class="pr-title-input large" id="pr-title-input" name="pullrequest_title" type="text" value="${c.pull_request.title}">
45 </div>
45 </div>
46
46
47 <% summary = lambda n:{False:'summary-short'}.get(n) %>
47 <% summary = lambda n:{False:'summary-short'}.get(n) %>
48 <div class="pr-details-title">
48 <div class="pr-details-title">
49 <div class="pull-left">
49 <div class="pull-left">
50 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request !{}').format(c.pull_request.pull_request_id)}</a>
50 <a href="${h.route_path('pull_requests_global', pull_request_id=c.pull_request.pull_request_id)}">${_('Pull request !{}').format(c.pull_request.pull_request_id)}</a>
51 ${_('Created on')}
51 ${_('Created on')}
52 <span class="tooltip" title="${_('Last updated on')} ${h.format_date(c.pull_request.updated_on)}">${h.format_date(c.pull_request.created_on)},</span>
52 <span class="tooltip" title="${_('Last updated on')} ${h.format_date(c.pull_request.updated_on)}">${h.format_date(c.pull_request.created_on)},</span>
53 <span class="pr-details-title-author-pref">${_('by')}</span>
53 <span class="pr-details-title-author-pref">${_('by')}</span>
54 </div>
54 </div>
55
55
56 <div class="pull-left">
56 <div class="pull-left">
57 ${self.gravatar_with_user(c.pull_request.author.email, 16, tooltip=True)}
57 ${self.gravatar_with_user(c.pull_request.author.email, 16, tooltip=True)}
58 </div>
58 </div>
59
59
60 %if c.allowed_to_update:
60 %if c.allowed_to_update:
61 <div class="pull-right">
61 <div class="pull-right">
62 <div id="edit_pull_request" class="action_button pr-save" style="display: none;">${_('Update title & description')}</div>
62 <div id="edit_pull_request" class="action_button pr-save" style="display: none;">${_('Update title & description')}</div>
63 <div id="delete_pullrequest" class="action_button pr-save ${('' if c.allowed_to_delete else 'disabled' )}" style="display: none;">
63 <div id="delete_pullrequest" class="action_button pr-save ${('' if c.allowed_to_delete else 'disabled' )}" style="display: none;">
64 % if c.allowed_to_delete:
64 % if c.allowed_to_delete:
65 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
65 ${h.secure_form(h.route_path('pullrequest_delete', repo_name=c.pull_request.target_repo.repo_name, pull_request_id=c.pull_request.pull_request_id), request=request)}
66 ${h.submit('remove_%s' % c.pull_request.pull_request_id, _('Delete pull request'),
66 <input class="btn btn-link btn-danger no-margin" id="remove_${c.pull_request.pull_request_id}" name="remove_${c.pull_request.pull_request_id}"
67 class_="btn btn-link btn-danger no-margin",onclick="return confirm('"+_('Confirm to delete this pull request')+"');")}
67 onclick="submitConfirm(event, this, _gettext('Confirm to delete this pull request'), _gettext('Delete'), '${'!{}'.format(c.pull_request.pull_request_id)}')"
68 type="submit" value="${_('Delete pull request')}">
68 ${h.end_form()}
69 ${h.end_form()}
69 % else:
70 % else:
70 <span class="tooltip" title="${_('Not allowed to delete this pull request')}">${_('Delete pull request')}</span>
71 <span class="tooltip" title="${_('Not allowed to delete this pull request')}">${_('Delete pull request')}</span>
71 % endif
72 % endif
72 </div>
73 </div>
73 <div id="open_edit_pullrequest" class="action_button">${_('Edit')}</div>
74 <div id="open_edit_pullrequest" class="action_button">${_('Edit')}</div>
74 <div id="close_edit_pullrequest" class="action_button" style="display: none;">${_('Cancel')}</div>
75 <div id="close_edit_pullrequest" class="action_button" style="display: none;">${_('Cancel')}</div>
75 </div>
76 </div>
76
77
77 %endif
78 %endif
78 </div>
79 </div>
79
80
80 <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}">
81 <div id="pr-desc" class="input" title="${_('Rendered using {} renderer').format(c.renderer)}">
81 ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)}
82 ${h.render(c.pull_request.description, renderer=c.renderer, repo_name=c.repo_name)}
82 </div>
83 </div>
83
84
84 <div id="pr-desc-edit" class="input textarea" style="display: none;">
85 <div id="pr-desc-edit" class="input textarea" style="display: none;">
85 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
86 <input id="pr-renderer-input" type="hidden" name="description_renderer" value="${c.visual.default_renderer}">
86 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
87 ${dt.markup_form('pr-description-input', form_text=c.pull_request.description)}
87 </div>
88 </div>
88
89
89 <div id="summary" class="fields pr-details-content">
90 <div id="summary" class="fields pr-details-content">
90
91
91 ## review
92 ## review
92 <div class="field">
93 <div class="field">
93 <div class="label-pr-detail">
94 <div class="label-pr-detail">
94 <label>${_('Review status')}:</label>
95 <label>${_('Review status')}:</label>
95 </div>
96 </div>
96 <div class="input">
97 <div class="input">
97 %if c.pull_request_review_status:
98 %if c.pull_request_review_status:
98 <div class="tag status-tag-${c.pull_request_review_status}">
99 <div class="tag status-tag-${c.pull_request_review_status}">
99 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
100 <i class="icon-circle review-status-${c.pull_request_review_status}"></i>
100 <span class="changeset-status-lbl">
101 <span class="changeset-status-lbl">
101 %if c.pull_request.is_closed():
102 %if c.pull_request.is_closed():
102 ${_('Closed')},
103 ${_('Closed')},
103 %endif
104 %endif
104
105
105 ${h.commit_status_lbl(c.pull_request_review_status)}
106 ${h.commit_status_lbl(c.pull_request_review_status)}
106
107
107 </span>
108 </span>
108 </div>
109 </div>
109 - ${_ungettext('calculated based on {} reviewer vote', 'calculated based on {} reviewers votes', len(c.pull_request_reviewers)).format(len(c.pull_request_reviewers))}
110 - ${_ungettext('calculated based on {} reviewer vote', 'calculated based on {} reviewers votes', len(c.pull_request_reviewers)).format(len(c.pull_request_reviewers))}
110 %endif
111 %endif
111 </div>
112 </div>
112 </div>
113 </div>
113
114
114 ## source
115 ## source
115 <div class="field">
116 <div class="field">
116 <div class="label-pr-detail">
117 <div class="label-pr-detail">
117 <label>${_('Commit flow')}:</label>
118 <label>${_('Commit flow')}:</label>
118 </div>
119 </div>
119 <div class="input">
120 <div class="input">
120 <div class="pr-commit-flow">
121 <div class="pr-commit-flow">
121 ## Source
122 ## Source
122 %if c.pull_request.source_ref_parts.type == 'branch':
123 %if c.pull_request.source_ref_parts.type == 'branch':
123 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}"><code class="pr-source-info">${c.pull_request.source_ref_parts.type}:${c.pull_request.source_ref_parts.name}</code></a>
124 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.source_repo.repo_name, _query=dict(branch=c.pull_request.source_ref_parts.name))}"><code class="pr-source-info">${c.pull_request.source_ref_parts.type}:${c.pull_request.source_ref_parts.name}</code></a>
124 %else:
125 %else:
125 <code class="pr-source-info">${'{}:{}'.format(c.pull_request.source_ref_parts.type, c.pull_request.source_ref_parts.name)}</code>
126 <code class="pr-source-info">${'{}:{}'.format(c.pull_request.source_ref_parts.type, c.pull_request.source_ref_parts.name)}</code>
126 %endif
127 %endif
127 ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.repo_name}</a>
128 ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.source_repo.repo_name)}">${c.pull_request.source_repo.repo_name}</a>
128 &rarr;
129 &rarr;
129 ## Target
130 ## Target
130 %if c.pull_request.target_ref_parts.type == 'branch':
131 %if c.pull_request.target_ref_parts.type == 'branch':
131 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}"><code class="pr-target-info">${c.pull_request.target_ref_parts.type}:${c.pull_request.target_ref_parts.name}</code></a>
132 <a href="${h.route_path('repo_commits', repo_name=c.pull_request.target_repo.repo_name, _query=dict(branch=c.pull_request.target_ref_parts.name))}"><code class="pr-target-info">${c.pull_request.target_ref_parts.type}:${c.pull_request.target_ref_parts.name}</code></a>
132 %else:
133 %else:
133 <code class="pr-target-info">${'{}:{}'.format(c.pull_request.target_ref_parts.type, c.pull_request.target_ref_parts.name)}</code>
134 <code class="pr-target-info">${'{}:{}'.format(c.pull_request.target_ref_parts.type, c.pull_request.target_ref_parts.name)}</code>
134 %endif
135 %endif
135
136
136 ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.repo_name}</a>
137 ${_('of')} <a href="${h.route_path('repo_summary', repo_name=c.pull_request.target_repo.repo_name)}">${c.pull_request.target_repo.repo_name}</a>
137
138
138 <a class="source-details-action" href="#expand-source-details" onclick="return versionController.toggleElement(this, '.source-details')" data-toggle-on='<i class="icon-angle-down">more details</i>' data-toggle-off='<i class="icon-angle-up">less details</i>'>
139 <a class="source-details-action" href="#expand-source-details" onclick="return versionController.toggleElement(this, '.source-details')" data-toggle-on='<i class="icon-angle-down">more details</i>' data-toggle-off='<i class="icon-angle-up">less details</i>'>
139 <i class="icon-angle-down">more details</i>
140 <i class="icon-angle-down">more details</i>
140 </a>
141 </a>
141
142
142 </div>
143 </div>
143
144
144 <div class="source-details" style="display: none">
145 <div class="source-details" style="display: none">
145
146
146 <ul>
147 <ul>
147
148
148 ## common ancestor
149 ## common ancestor
149 <li>
150 <li>
150 ${_('Common ancestor')}:
151 ${_('Common ancestor')}:
151 % if c.ancestor_commit:
152 % if c.ancestor_commit:
152 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a>
153 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=c.ancestor_commit.raw_id)}">${h.show_id(c.ancestor_commit)}</a>
153 % else:
154 % else:
154 ${_('not available')}
155 ${_('not available')}
155 % endif
156 % endif
156 </li>
157 </li>
157
158
158 ## pull url
159 ## pull url
159 <li>
160 <li>
160 %if h.is_hg(c.pull_request.source_repo):
161 %if h.is_hg(c.pull_request.source_repo):
161 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
162 <% clone_url = 'hg pull -r {} {}'.format(h.short_id(c.source_ref), c.pull_request.source_repo.clone_url()) %>
162 %elif h.is_git(c.pull_request.source_repo):
163 %elif h.is_git(c.pull_request.source_repo):
163 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
164 <% clone_url = 'git pull {} {}'.format(c.pull_request.source_repo.clone_url(), c.pull_request.source_ref_parts.name) %>
164 %endif
165 %endif
165
166
166 <span>${_('Pull changes from source')}</span>: <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
167 <span>${_('Pull changes from source')}</span>: <input type="text" class="input-monospace pr-pullinfo" value="${clone_url}" readonly="readonly">
167 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
168 <i class="tooltip icon-clipboard clipboard-action pull-right pr-pullinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the pull url')}"></i>
168 </li>
169 </li>
169
170
170 ## Shadow repo
171 ## Shadow repo
171 <li>
172 <li>
172 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
173 % if not c.pull_request.is_closed() and c.pull_request.shadow_merge_ref:
173 %if h.is_hg(c.pull_request.target_repo):
174 %if h.is_hg(c.pull_request.target_repo):
174 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
175 <% clone_url = 'hg clone --update {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
175 %elif h.is_git(c.pull_request.target_repo):
176 %elif h.is_git(c.pull_request.target_repo):
176 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
177 <% clone_url = 'git clone --branch {} {} pull-request-{}'.format(c.pull_request.shadow_merge_ref.name, c.shadow_clone_url, c.pull_request.pull_request_id) %>
177 %endif
178 %endif
178
179
179 <span class="tooltip" title="${_('Clone repository in its merged state using shadow repository')}">${_('Clone from shadow repository')}</span>: <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
180 <span class="tooltip" title="${_('Clone repository in its merged state using shadow repository')}">${_('Clone from shadow repository')}</span>: <input type="text" class="input-monospace pr-mergeinfo" value="${clone_url}" readonly="readonly">
180 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
181 <i class="tooltip icon-clipboard clipboard-action pull-right pr-mergeinfo-copy" data-clipboard-text="${clone_url}" title="${_('Copy the clone url')}"></i>
181
182
182 % else:
183 % else:
183 <div class="">
184 <div class="">
184 ${_('Shadow repository data not available')}.
185 ${_('Shadow repository data not available')}.
185 </div>
186 </div>
186 % endif
187 % endif
187 </li>
188 </li>
188
189
189 </ul>
190 </ul>
190
191
191 </div>
192 </div>
192
193
193 </div>
194 </div>
194
195
195 </div>
196 </div>
196
197
197 ## versions
198 ## versions
198 <div class="field">
199 <div class="field">
199 <div class="label-pr-detail">
200 <div class="label-pr-detail">
200 <label>${_('Versions')}:</label>
201 <label>${_('Versions')}:</label>
201 </div>
202 </div>
202
203
203 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
204 <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %>
204 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
205 <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %>
205
206
206 <div class="pr-versions">
207 <div class="pr-versions">
207 % if c.show_version_changes:
208 % if c.show_version_changes:
208 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
209 <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %>
209 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
210 <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %>
210 ${_ungettext('{} version available for this pull request, ', '{} versions available for this pull request, ', len(c.versions)).format(len(c.versions))}
211 ${_ungettext('{} version available for this pull request, ', '{} versions available for this pull request, ', len(c.versions)).format(len(c.versions))}
211 <a id="show-pr-versions" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
212 <a id="show-pr-versions" onclick="return versionController.toggleVersionView(this)" href="#show-pr-versions"
212 data-toggle-on="${_('show versions')}."
213 data-toggle-on="${_('show versions')}."
213 data-toggle-off="${_('hide versions')}.">
214 data-toggle-off="${_('hide versions')}.">
214 ${_('show versions')}.
215 ${_('show versions')}.
215 </a>
216 </a>
216 <table>
217 <table>
217 ## SHOW ALL VERSIONS OF PR
218 ## SHOW ALL VERSIONS OF PR
218 <% ver_pr = None %>
219 <% ver_pr = None %>
219
220
220 % for data in reversed(list(enumerate(c.versions, 1))):
221 % for data in reversed(list(enumerate(c.versions, 1))):
221 <% ver_pos = data[0] %>
222 <% ver_pos = data[0] %>
222 <% ver = data[1] %>
223 <% ver = data[1] %>
223 <% ver_pr = ver.pull_request_version_id %>
224 <% ver_pr = ver.pull_request_version_id %>
224 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
225 <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %>
225
226
226 <tr class="version-pr" style="display: ${display_row}">
227 <tr class="version-pr" style="display: ${display_row}">
227 <td>
228 <td>
228 <code>
229 <code>
229 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
230 <a href="${request.current_route_path(_query=dict(version=ver_pr or 'latest'))}">v${ver_pos}</a>
230 </code>
231 </code>
231 </td>
232 </td>
232 <td>
233 <td>
233 <input ${('checked="checked"' if c.from_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
234 <input ${('checked="checked"' if c.from_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
234 <input ${('checked="checked"' if c.at_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
235 <input ${('checked="checked"' if c.at_version_num == ver_pr else '')} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/>
235 </td>
236 </td>
236 <td>
237 <td>
237 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
238 <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %>
238 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
239 <i class="tooltip icon-circle review-status-${review_status}" title="${_('Your review status at this version')}"></i>
239
240
240 </td>
241 </td>
241 <td>
242 <td>
242 % if c.at_version_num != ver_pr:
243 % if c.at_version_num != ver_pr:
243 <i class="tooltip icon-comment" title="${_('Comments from pull request version v{0}').format(ver_pos)}"></i>
244 <i class="tooltip icon-comment" title="${_('Comments from pull request version v{0}').format(ver_pos)}"></i>
244 <code>
245 <code>
245 General:${len(c.comment_versions[ver_pr]['at'])} / Inline:${len(c.inline_versions[ver_pr]['at'])}
246 General:${len(c.comment_versions[ver_pr]['at'])} / Inline:${len(c.inline_versions[ver_pr]['at'])}
246 </code>
247 </code>
247 % endif
248 % endif
248 </td>
249 </td>
249 <td>
250 <td>
250 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
251 ##<code>${ver.source_ref_parts.commit_id[:6]}</code>
251 </td>
252 </td>
252 <td>
253 <td>
253 <code>${h.age_component(ver.updated_on, time_is_local=True, tooltip=False)}</code>
254 <code>${h.age_component(ver.updated_on, time_is_local=True, tooltip=False)}</code>
254 </td>
255 </td>
255 </tr>
256 </tr>
256 % endfor
257 % endfor
257
258
258 <tr>
259 <tr>
259 <td colspan="6">
260 <td colspan="6">
260 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
261 <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none"
261 data-label-text-locked="${_('select versions to show changes')}"
262 data-label-text-locked="${_('select versions to show changes')}"
262 data-label-text-diff="${_('show changes between versions')}"
263 data-label-text-diff="${_('show changes between versions')}"
263 data-label-text-show="${_('show pull request for this version')}"
264 data-label-text-show="${_('show pull request for this version')}"
264 >
265 >
265 ${_('select versions to show changes')}
266 ${_('select versions to show changes')}
266 </button>
267 </button>
267 </td>
268 </td>
268 </tr>
269 </tr>
269 </table>
270 </table>
270 % else:
271 % else:
271 <div>
272 <div>
272 ${_('Pull request versions not available')}.
273 ${_('Pull request versions not available')}.
273 </div>
274 </div>
274 % endif
275 % endif
275 </div>
276 </div>
276 </div>
277 </div>
277
278
278 </div>
279 </div>
279
280
280 </div>
281 </div>
281
282
282 ## REVIEW RULES
283 ## REVIEW RULES
283 <div id="review_rules" style="display: none" class="reviewers-title block-right">
284 <div id="review_rules" style="display: none" class="reviewers-title block-right">
284 <div class="pr-details-title">
285 <div class="pr-details-title">
285 ${_('Reviewer rules')}
286 ${_('Reviewer rules')}
286 %if c.allowed_to_update:
287 %if c.allowed_to_update:
287 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
288 <span id="close_edit_reviewers" class="block-right action_button last-item" style="display: none;">${_('Close')}</span>
288 %endif
289 %endif
289 </div>
290 </div>
290 <div class="pr-reviewer-rules">
291 <div class="pr-reviewer-rules">
291 ## review rules will be appended here, by default reviewers logic
292 ## review rules will be appended here, by default reviewers logic
292 </div>
293 </div>
293 <input id="review_data" type="hidden" name="review_data" value="">
294 <input id="review_data" type="hidden" name="review_data" value="">
294 </div>
295 </div>
295
296
296 ## REVIEWERS
297 ## REVIEWERS
297 <div class="reviewers-title first-panel block-right">
298 <div class="reviewers-title first-panel block-right">
298 <div class="pr-details-title">
299 <div class="pr-details-title">
299 ${_('Pull request reviewers')}
300 ${_('Pull request reviewers')}
300 %if c.allowed_to_update:
301 %if c.allowed_to_update:
301 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
302 <span id="open_edit_reviewers" class="block-right action_button last-item">${_('Edit')}</span>
302 %endif
303 %endif
303 </div>
304 </div>
304 </div>
305 </div>
305 <div id="reviewers" class="block-right pr-details-content reviewers">
306 <div id="reviewers" class="block-right pr-details-content reviewers">
306
307
307 ## members redering block
308 ## members redering block
308 <input type="hidden" name="__start__" value="review_members:sequence">
309 <input type="hidden" name="__start__" value="review_members:sequence">
309 <ul id="review_members" class="group_members">
310 <ul id="review_members" class="group_members">
310
311
311 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
312 % for review_obj, member, reasons, mandatory, status in c.pull_request_reviewers:
312 <script>
313 <script>
313 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
314 var member = ${h.json.dumps(h.reviewer_as_json(member, reasons=reasons, mandatory=mandatory, user_group=review_obj.rule_user_group_data()))|n};
314 var status = "${(status[0][1].status if status else 'not_reviewed')}";
315 var status = "${(status[0][1].status if status else 'not_reviewed')}";
315 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
316 var status_lbl = "${h.commit_status_lbl(status[0][1].status if status else 'not_reviewed')}";
316 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
317 var allowed_to_update = ${h.json.dumps(c.allowed_to_update)};
317
318
318 var entry = renderTemplate('reviewMemberEntry', {
319 var entry = renderTemplate('reviewMemberEntry', {
319 'member': member,
320 'member': member,
320 'mandatory': member.mandatory,
321 'mandatory': member.mandatory,
321 'reasons': member.reasons,
322 'reasons': member.reasons,
322 'allowed_to_update': allowed_to_update,
323 'allowed_to_update': allowed_to_update,
323 'review_status': status,
324 'review_status': status,
324 'review_status_label': status_lbl,
325 'review_status_label': status_lbl,
325 'user_group': member.user_group,
326 'user_group': member.user_group,
326 'create': false
327 'create': false
327 });
328 });
328 $('#review_members').append(entry)
329 $('#review_members').append(entry)
329 </script>
330 </script>
330
331
331 % endfor
332 % endfor
332
333
333 </ul>
334 </ul>
334
335
335 <input type="hidden" name="__end__" value="review_members:sequence">
336 <input type="hidden" name="__end__" value="review_members:sequence">
336 ## end members redering block
337 ## end members redering block
337
338
338 %if not c.pull_request.is_closed():
339 %if not c.pull_request.is_closed():
339 <div id="add_reviewer" class="ac" style="display: none;">
340 <div id="add_reviewer" class="ac" style="display: none;">
340 %if c.allowed_to_update:
341 %if c.allowed_to_update:
341 % if not c.forbid_adding_reviewers:
342 % if not c.forbid_adding_reviewers:
342 <div id="add_reviewer_input" class="reviewer_ac">
343 <div id="add_reviewer_input" class="reviewer_ac">
343 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
344 ${h.text('user', class_='ac-input', placeholder=_('Add reviewer or reviewer group'))}
344 <div id="reviewers_container"></div>
345 <div id="reviewers_container"></div>
345 </div>
346 </div>
346 % endif
347 % endif
347 <div class="pull-right">
348 <div class="pull-right">
348 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
349 <button id="update_pull_request" class="btn btn-small no-margin">${_('Save Changes')}</button>
349 </div>
350 </div>
350 %endif
351 %endif
351 </div>
352 </div>
352 %endif
353 %endif
353 </div>
354 </div>
354
355
355 ## TODOs will be listed here
356 ## TODOs will be listed here
356 <div class="reviewers-title block-right">
357 <div class="reviewers-title block-right">
357 <div class="pr-details-title">
358 <div class="pr-details-title">
358 ## Only show unresolved, that is only what matters
359 ## Only show unresolved, that is only what matters
359 TODO Comments - ${len(c.unresolved_comments)} / ${(len(c.unresolved_comments) + len(c.resolved_comments))}
360 TODO Comments - ${len(c.unresolved_comments)} / ${(len(c.unresolved_comments) + len(c.resolved_comments))}
360
361
361 % if not c.at_version:
362 % if not c.at_version:
362 % if c.resolved_comments:
363 % if c.resolved_comments:
363 <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return versionController.toggleElement(this, '.unresolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span>
364 <span class="block-right action_button last-item noselect" onclick="$('.unresolved-todo-text').toggle(); return versionController.toggleElement(this, '.unresolved-todo');" data-toggle-on="Show resolved" data-toggle-off="Hide resolved">Show resolved</span>
364 % else:
365 % else:
365 <span class="block-right last-item noselect">Show resolved</span>
366 <span class="block-right last-item noselect">Show resolved</span>
366 % endif
367 % endif
367 % endif
368 % endif
368 </div>
369 </div>
369 </div>
370 </div>
370 <div class="block-right pr-details-content reviewers">
371 <div class="block-right pr-details-content reviewers">
371
372
372 <table class="todo-table">
373 <table class="todo-table">
373 <%
374 <%
374 def sorter(entry):
375 def sorter(entry):
375 user_id = entry.author.user_id
376 user_id = entry.author.user_id
376 resolved = '1' if entry.resolved else '0'
377 resolved = '1' if entry.resolved else '0'
377 if user_id == c.rhodecode_user.user_id:
378 if user_id == c.rhodecode_user.user_id:
378 # own comments first
379 # own comments first
379 user_id = 0
380 user_id = 0
380 return '{}_{}_{}'.format(resolved, user_id, str(entry.comment_id).zfill(100))
381 return '{}_{}_{}'.format(resolved, user_id, str(entry.comment_id).zfill(100))
381 %>
382 %>
382
383
383 % if c.at_version:
384 % if c.at_version:
384 <tr>
385 <tr>
385 <td class="unresolved-todo-text">${_('unresolved TODOs unavailable in this view')}.</td>
386 <td class="unresolved-todo-text">${_('unresolved TODOs unavailable in this view')}.</td>
386 </tr>
387 </tr>
387 % else:
388 % else:
388 % for todo_comment in sorted(c.unresolved_comments + c.resolved_comments, key=sorter):
389 % for todo_comment in sorted(c.unresolved_comments + c.resolved_comments, key=sorter):
389 <% resolved = todo_comment.resolved %>
390 <% resolved = todo_comment.resolved %>
390 % if inline:
391 % if inline:
391 <% outdated_at_ver = todo_comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
392 <% outdated_at_ver = todo_comment.outdated_at_version(getattr(c, 'at_version_num', None)) %>
392 % else:
393 % else:
393 <% outdated_at_ver = todo_comment.older_than_version(getattr(c, 'at_version_num', None)) %>
394 <% outdated_at_ver = todo_comment.older_than_version(getattr(c, 'at_version_num', None)) %>
394 % endif
395 % endif
395
396
396 <tr ${('class="unresolved-todo" style="display: none"' if resolved else '') |n}>
397 <tr ${('class="unresolved-todo" style="display: none"' if resolved else '') |n}>
397
398
398 <td class="td-todo-number">
399 <td class="td-todo-number">
399 % if resolved:
400 % if resolved:
400 <a class="permalink todo-resolved tooltip" title="${_('Resolved by comment #{}').format(todo_comment.resolved.comment_id)}" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
401 <a class="permalink todo-resolved tooltip" title="${_('Resolved by comment #{}').format(todo_comment.resolved.comment_id)}" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
401 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
402 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
402 % else:
403 % else:
403 <a class="permalink" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
404 <a class="permalink" href="#comment-${todo_comment.comment_id}" onclick="return Rhodecode.comments.scrollToComment($('#comment-${todo_comment.comment_id}'), 0, ${h.json.dumps(outdated_at_ver)})">
404 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
405 <i class="icon-flag-filled"></i> ${todo_comment.comment_id}</a>
405 % endif
406 % endif
406 </td>
407 </td>
407 <td class="td-todo-gravatar">
408 <td class="td-todo-gravatar">
408 ${base.gravatar(todo_comment.author.email, 16, user=todo_comment.author, tooltip=True, extra_class=['no-margin'])}
409 ${base.gravatar(todo_comment.author.email, 16, user=todo_comment.author, tooltip=True, extra_class=['no-margin'])}
409 </td>
410 </td>
410 <td class="todo-comment-text-wrapper">
411 <td class="todo-comment-text-wrapper">
411 <div class="todo-comment-text">
412 <div class="todo-comment-text">
412 <code>${h.chop_at_smart(todo_comment.text, '\n', suffix_if_chopped='...')}</code>
413 <code>${h.chop_at_smart(todo_comment.text, '\n', suffix_if_chopped='...')}</code>
413 </div>
414 </div>
414 </td>
415 </td>
415
416
416 </tr>
417 </tr>
417 % endfor
418 % endfor
418
419
419 % if len(c.unresolved_comments) == 0:
420 % if len(c.unresolved_comments) == 0:
420 <tr>
421 <tr>
421 <td class="unresolved-todo-text">${_('No unresolved TODOs')}.</td>
422 <td class="unresolved-todo-text">${_('No unresolved TODOs')}.</td>
422 </tr>
423 </tr>
423 % endif
424 % endif
424
425
425 % endif
426 % endif
426
427
427 </table>
428 </table>
428
429
429 </div>
430 </div>
430 </div>
431 </div>
431
432
432 </div>
433 </div>
433
434
434 <div class="box">
435 <div class="box">
435
436
436 % if c.state_progressing:
437 % if c.state_progressing:
437
438
438 <h2 style="text-align: center">
439 <h2 style="text-align: center">
439 ${_('Cannot show diff when pull request state is changing. Current progress state')}: <span class="tag tag-merge-state-${c.pull_request.state}">${c.pull_request.state}</span>
440 ${_('Cannot show diff when pull request state is changing. Current progress state')}: <span class="tag tag-merge-state-${c.pull_request.state}">${c.pull_request.state}</span>
440
441
441 % if c.is_super_admin:
442 % if c.is_super_admin:
442 <br/>
443 <br/>
443 If you think this is an error try <a href="${h.current_route_path(request, force_state='created')}">forced state reset</a> to <span class="tag tag-merge-state-created">created</span> state.
444 If you think this is an error try <a href="${h.current_route_path(request, force_state='created')}">forced state reset</a> to <span class="tag tag-merge-state-created">created</span> state.
444 % endif
445 % endif
445 </h2>
446 </h2>
446
447
447 % else:
448 % else:
448
449
449 ## Diffs rendered here
450 ## Diffs rendered here
450 <div class="table" >
451 <div class="table" >
451 <div id="changeset_compare_view_content">
452 <div id="changeset_compare_view_content">
452 ##CS
453 ##CS
453 % if c.missing_requirements:
454 % if c.missing_requirements:
454 <div class="box">
455 <div class="box">
455 <div class="alert alert-warning">
456 <div class="alert alert-warning">
456 <div>
457 <div>
457 <strong>${_('Missing requirements:')}</strong>
458 <strong>${_('Missing requirements:')}</strong>
458 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
459 ${_('These commits cannot be displayed, because this repository uses the Mercurial largefiles extension, which was not enabled.')}
459 </div>
460 </div>
460 </div>
461 </div>
461 </div>
462 </div>
462 % elif c.missing_commits:
463 % elif c.missing_commits:
463 <div class="box">
464 <div class="box">
464 <div class="alert alert-warning">
465 <div class="alert alert-warning">
465 <div>
466 <div>
466 <strong>${_('Missing commits')}:</strong>
467 <strong>${_('Missing commits')}:</strong>
467 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
468 ${_('This pull request cannot be displayed, because one or more commits no longer exist in the source repository.')}
468 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
469 ${_('Please update this pull request, push the commits back into the source repository, or consider closing this pull request.')}
469 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
470 ${_('Consider doing a {force_refresh_url} in case you think this is an error.').format(force_refresh_url=h.link_to('force refresh', h.current_route_path(request, force_refresh='1')))|n}
470 </div>
471 </div>
471 </div>
472 </div>
472 </div>
473 </div>
473 % endif
474 % endif
474
475
475 <div class="compare_view_commits_title">
476 <div class="compare_view_commits_title">
476 % if not c.compare_mode:
477 % if not c.compare_mode:
477
478
478 % if c.at_version_pos:
479 % if c.at_version_pos:
479 <h4>
480 <h4>
480 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
481 ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos}
481 </h4>
482 </h4>
482 % endif
483 % endif
483
484
484 <div class="pull-left">
485 <div class="pull-left">
485 <div class="btn-group">
486 <div class="btn-group">
486 <a class="${('collapsed' if c.collapse_all_commits else '')}" href="#expand-commits" onclick="toggleCommitExpand(this); return false" data-toggle-commits-cnt=${len(c.commit_ranges)} >
487 <a class="${('collapsed' if c.collapse_all_commits else '')}" href="#expand-commits" onclick="toggleCommitExpand(this); return false" data-toggle-commits-cnt=${len(c.commit_ranges)} >
487 % if c.collapse_all_commits:
488 % if c.collapse_all_commits:
488 <i class="icon-plus-squared-alt icon-no-margin"></i>
489 <i class="icon-plus-squared-alt icon-no-margin"></i>
489 ${_ungettext('Expand {} commit', 'Expand {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
490 ${_ungettext('Expand {} commit', 'Expand {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
490 % else:
491 % else:
491 <i class="icon-minus-squared-alt icon-no-margin"></i>
492 <i class="icon-minus-squared-alt icon-no-margin"></i>
492 ${_ungettext('Collapse {} commit', 'Collapse {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
493 ${_ungettext('Collapse {} commit', 'Collapse {} commits', len(c.commit_ranges)).format(len(c.commit_ranges))}
493 % endif
494 % endif
494 </a>
495 </a>
495 </div>
496 </div>
496 </div>
497 </div>
497
498
498 <div class="pull-right">
499 <div class="pull-right">
499 % if c.allowed_to_update and not c.pull_request.is_closed():
500 % if c.allowed_to_update and not c.pull_request.is_closed():
500
501
501 <div class="btn-group btn-group-actions">
502 <div class="btn-group btn-group-actions">
502 <a id="update_commits" class="btn btn-primary no-margin" onclick="updateController.updateCommits(this); return false">
503 <a id="update_commits" class="btn btn-primary no-margin" onclick="updateController.updateCommits(this); return false">
503 ${_('Update commits')}
504 ${_('Update commits')}
504 </a>
505 </a>
505
506
506 <a id="update_commits_switcher" class="tooltip btn btn-primary" style="margin-left: -1px" data-toggle="dropdown" aria-pressed="false" role="button" title="${_('more update options')}">
507 <a id="update_commits_switcher" class="tooltip btn btn-primary" style="margin-left: -1px" data-toggle="dropdown" aria-pressed="false" role="button" title="${_('more update options')}">
507 <i class="icon-down"></i>
508 <i class="icon-down"></i>
508 </a>
509 </a>
509
510
510 <div class="btn-action-switcher-container" id="update-commits-switcher">
511 <div class="btn-action-switcher-container" id="update-commits-switcher">
511 <ul class="btn-action-switcher" role="menu">
512 <ul class="btn-action-switcher" role="menu">
512 <li>
513 <li>
513 <a href="#forceUpdate" onclick="updateController.forceUpdateCommits(this); return false">
514 <a href="#forceUpdate" onclick="updateController.forceUpdateCommits(this); return false">
514 ${_('Force update commits')}
515 ${_('Force update commits')}
515 </a>
516 </a>
516 <div class="action-help-block">
517 <div class="action-help-block">
517 ${_('Update commits and force refresh this pull request.')}
518 ${_('Update commits and force refresh this pull request.')}
518 </div>
519 </div>
519 </li>
520 </li>
520 </ul>
521 </ul>
521 </div>
522 </div>
522 </div>
523 </div>
523
524
524 % else:
525 % else:
525 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
526 <a class="tooltip btn disabled pull-right" disabled="disabled" title="${_('Update is disabled for current view')}">${_('Update commits')}</a>
526 % endif
527 % endif
527
528
528 </div>
529 </div>
529 % endif
530 % endif
530 </div>
531 </div>
531
532
532 % if not c.missing_commits:
533 % if not c.missing_commits:
533 % if c.compare_mode:
534 % if c.compare_mode:
534 % if c.at_version:
535 % if c.at_version:
535 <h4>
536 <h4>
536 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
537 ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}:
537 </h4>
538 </h4>
538
539
539 <div class="subtitle-compare">
540 <div class="subtitle-compare">
540 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
541 ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))}
541 </div>
542 </div>
542
543
543 <div class="container">
544 <div class="container">
544 <table class="rctable compare_view_commits">
545 <table class="rctable compare_view_commits">
545 <tr>
546 <tr>
546 <th></th>
547 <th></th>
547 <th>${_('Time')}</th>
548 <th>${_('Time')}</th>
548 <th>${_('Author')}</th>
549 <th>${_('Author')}</th>
549 <th>${_('Commit')}</th>
550 <th>${_('Commit')}</th>
550 <th></th>
551 <th></th>
551 <th>${_('Description')}</th>
552 <th>${_('Description')}</th>
552 </tr>
553 </tr>
553
554
554 % for c_type, commit in c.commit_changes:
555 % for c_type, commit in c.commit_changes:
555 % if c_type in ['a', 'r']:
556 % if c_type in ['a', 'r']:
556 <%
557 <%
557 if c_type == 'a':
558 if c_type == 'a':
558 cc_title = _('Commit added in displayed changes')
559 cc_title = _('Commit added in displayed changes')
559 elif c_type == 'r':
560 elif c_type == 'r':
560 cc_title = _('Commit removed in displayed changes')
561 cc_title = _('Commit removed in displayed changes')
561 else:
562 else:
562 cc_title = ''
563 cc_title = ''
563 %>
564 %>
564 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
565 <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select">
565 <td>
566 <td>
566 <div class="commit-change-indicator color-${c_type}-border">
567 <div class="commit-change-indicator color-${c_type}-border">
567 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
568 <div class="commit-change-content color-${c_type} tooltip" title="${h.tooltip(cc_title)}">
568 ${c_type.upper()}
569 ${c_type.upper()}
569 </div>
570 </div>
570 </div>
571 </div>
571 </td>
572 </td>
572 <td class="td-time">
573 <td class="td-time">
573 ${h.age_component(commit.date)}
574 ${h.age_component(commit.date)}
574 </td>
575 </td>
575 <td class="td-user">
576 <td class="td-user">
576 ${base.gravatar_with_user(commit.author, 16, tooltip=True)}
577 ${base.gravatar_with_user(commit.author, 16, tooltip=True)}
577 </td>
578 </td>
578 <td class="td-hash">
579 <td class="td-hash">
579 <code>
580 <code>
580 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
581 <a href="${h.route_path('repo_commit', repo_name=c.target_repo.repo_name, commit_id=commit.raw_id)}">
581 r${commit.idx}:${h.short_id(commit.raw_id)}
582 r${commit.idx}:${h.short_id(commit.raw_id)}
582 </a>
583 </a>
583 ${h.hidden('revisions', commit.raw_id)}
584 ${h.hidden('revisions', commit.raw_id)}
584 </code>
585 </code>
585 </td>
586 </td>
586 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
587 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
587 <i class="icon-expand-linked"></i>
588 <i class="icon-expand-linked"></i>
588 </td>
589 </td>
589 <td class="mid td-description">
590 <td class="mid td-description">
590 <div class="log-container truncate-wrap">
591 <div class="log-container truncate-wrap">
591 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
592 <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
592 </div>
593 </div>
593 </td>
594 </td>
594 </tr>
595 </tr>
595 % endif
596 % endif
596 % endfor
597 % endfor
597 </table>
598 </table>
598 </div>
599 </div>
599
600
600 % endif
601 % endif
601
602
602 % else:
603 % else:
603 <%include file="/compare/compare_commits.mako" />
604 <%include file="/compare/compare_commits.mako" />
604 % endif
605 % endif
605
606
606 <div class="cs_files">
607 <div class="cs_files">
607 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
608 <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/>
608 % if c.at_version:
609 % if c.at_version:
609 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['display']) %>
610 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['display']) %>
610 <% c.comments = c.comment_versions[c.at_version_num]['display'] %>
611 <% c.comments = c.comment_versions[c.at_version_num]['display'] %>
611 % else:
612 % else:
612 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['until']) %>
613 <% c.inline_cnt = len(c.inline_versions[c.at_version_num]['until']) %>
613 <% c.comments = c.comment_versions[c.at_version_num]['until'] %>
614 <% c.comments = c.comment_versions[c.at_version_num]['until'] %>
614 % endif
615 % endif
615
616
616 <%
617 <%
617 pr_menu_data = {
618 pr_menu_data = {
618 'outdated_comm_count_ver': outdated_comm_count_ver
619 'outdated_comm_count_ver': outdated_comm_count_ver
619 }
620 }
620 %>
621 %>
621
622
622 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
623 ${cbdiffs.render_diffset_menu(c.diffset, range_diff_on=c.range_diff_on)}
623
624
624 % if c.range_diff_on:
625 % if c.range_diff_on:
625 % for commit in c.commit_ranges:
626 % for commit in c.commit_ranges:
626 ${cbdiffs.render_diffset(
627 ${cbdiffs.render_diffset(
627 c.changes[commit.raw_id],
628 c.changes[commit.raw_id],
628 commit=commit, use_comments=True,
629 commit=commit, use_comments=True,
629 collapse_when_files_over=5,
630 collapse_when_files_over=5,
630 disable_new_comments=True,
631 disable_new_comments=True,
631 deleted_files_comments=c.deleted_files_comments,
632 deleted_files_comments=c.deleted_files_comments,
632 inline_comments=c.inline_comments,
633 inline_comments=c.inline_comments,
633 pull_request_menu=pr_menu_data, show_todos=False)}
634 pull_request_menu=pr_menu_data, show_todos=False)}
634 % endfor
635 % endfor
635 % else:
636 % else:
636 ${cbdiffs.render_diffset(
637 ${cbdiffs.render_diffset(
637 c.diffset, use_comments=True,
638 c.diffset, use_comments=True,
638 collapse_when_files_over=30,
639 collapse_when_files_over=30,
639 disable_new_comments=not c.allowed_to_comment,
640 disable_new_comments=not c.allowed_to_comment,
640 deleted_files_comments=c.deleted_files_comments,
641 deleted_files_comments=c.deleted_files_comments,
641 inline_comments=c.inline_comments,
642 inline_comments=c.inline_comments,
642 pull_request_menu=pr_menu_data, show_todos=False)}
643 pull_request_menu=pr_menu_data, show_todos=False)}
643 % endif
644 % endif
644
645
645 </div>
646 </div>
646 % else:
647 % else:
647 ## skipping commits we need to clear the view for missing commits
648 ## skipping commits we need to clear the view for missing commits
648 <div style="clear:both;"></div>
649 <div style="clear:both;"></div>
649 % endif
650 % endif
650
651
651 </div>
652 </div>
652 </div>
653 </div>
653
654
654 ## template for inline comment form
655 ## template for inline comment form
655 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
656 <%namespace name="comment" file="/changeset/changeset_file_comment.mako"/>
656
657
657 ## comments heading with count
658 ## comments heading with count
658 <div class="comments-heading">
659 <div class="comments-heading">
659 <i class="icon-comment"></i>
660 <i class="icon-comment"></i>
660 ${_('Comments')} ${len(c.comments)}
661 ${_('Comments')} ${len(c.comments)}
661 </div>
662 </div>
662
663
663 ## render general comments
664 ## render general comments
664 <div id="comment-tr-show">
665 <div id="comment-tr-show">
665 % if general_outdated_comm_count_ver:
666 % if general_outdated_comm_count_ver:
666 <div class="info-box">
667 <div class="info-box">
667 % if general_outdated_comm_count_ver == 1:
668 % if general_outdated_comm_count_ver == 1:
668 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
669 ${_('there is {num} general comment from older versions').format(num=general_outdated_comm_count_ver)},
669 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
670 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show it')}</a>
670 % else:
671 % else:
671 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
672 ${_('there are {num} general comments from older versions').format(num=general_outdated_comm_count_ver)},
672 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
673 <a href="#show-hidden-comments" onclick="$('.comment-general.comment-outdated').show(); $(this).parent().hide(); return false;">${_('show them')}</a>
673 % endif
674 % endif
674 </div>
675 </div>
675 % endif
676 % endif
676 </div>
677 </div>
677
678
678 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
679 ${comment.generate_comments(c.comments, include_pull_request=True, is_pull_request=True)}
679
680
680 % if not c.pull_request.is_closed():
681 % if not c.pull_request.is_closed():
681 ## main comment form and it status
682 ## main comment form and it status
682 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
683 ${comment.comments(h.route_path('pullrequest_comment_create', repo_name=c.repo_name,
683 pull_request_id=c.pull_request.pull_request_id),
684 pull_request_id=c.pull_request.pull_request_id),
684 c.pull_request_review_status,
685 c.pull_request_review_status,
685 is_pull_request=True, change_status=c.allowed_to_change_status)}
686 is_pull_request=True, change_status=c.allowed_to_change_status)}
686
687
687 ## merge status, and merge action
688 ## merge status, and merge action
688 <div class="pull-request-merge">
689 <div class="pull-request-merge">
689 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
690 <%include file="/pullrequests/pullrequest_merge_checks.mako"/>
690 </div>
691 </div>
691
692
692 %endif
693 %endif
693
694
694 % endif
695 % endif
695 </div>
696 </div>
696
697
697 <script type="text/javascript">
698 <script type="text/javascript">
698
699
699 versionController = new VersionController();
700 versionController = new VersionController();
700 versionController.init();
701 versionController.init();
701
702
702 reviewersController = new ReviewersController();
703 reviewersController = new ReviewersController();
703 commitsController = new CommitsController();
704 commitsController = new CommitsController();
704
705
705 updateController = new UpdatePrController();
706 updateController = new UpdatePrController();
706
707
707 $(function () {
708 $(function () {
708
709
709 // custom code mirror
710 // custom code mirror
710 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
711 var codeMirrorInstance = $('#pr-description-input').get(0).MarkupForm.cm;
711
712
712 var PRDetails = {
713 var PRDetails = {
713 editButton: $('#open_edit_pullrequest'),
714 editButton: $('#open_edit_pullrequest'),
714 closeButton: $('#close_edit_pullrequest'),
715 closeButton: $('#close_edit_pullrequest'),
715 deleteButton: $('#delete_pullrequest'),
716 deleteButton: $('#delete_pullrequest'),
716 viewFields: $('#pr-desc, #pr-title'),
717 viewFields: $('#pr-desc, #pr-title'),
717 editFields: $('#pr-desc-edit, #pr-title-edit, .pr-save'),
718 editFields: $('#pr-desc-edit, #pr-title-edit, .pr-save'),
718
719
719 init: function () {
720 init: function () {
720 var that = this;
721 var that = this;
721 this.editButton.on('click', function (e) {
722 this.editButton.on('click', function (e) {
722 that.edit();
723 that.edit();
723 });
724 });
724 this.closeButton.on('click', function (e) {
725 this.closeButton.on('click', function (e) {
725 that.view();
726 that.view();
726 });
727 });
727 },
728 },
728
729
729 edit: function (event) {
730 edit: function (event) {
730 this.viewFields.hide();
731 this.viewFields.hide();
731 this.editButton.hide();
732 this.editButton.hide();
732 this.deleteButton.hide();
733 this.deleteButton.hide();
733 this.closeButton.show();
734 this.closeButton.show();
734 this.editFields.show();
735 this.editFields.show();
735 codeMirrorInstance.refresh();
736 codeMirrorInstance.refresh();
736 },
737 },
737
738
738 view: function (event) {
739 view: function (event) {
739 this.editButton.show();
740 this.editButton.show();
740 this.deleteButton.show();
741 this.deleteButton.show();
741 this.editFields.hide();
742 this.editFields.hide();
742 this.closeButton.hide();
743 this.closeButton.hide();
743 this.viewFields.show();
744 this.viewFields.show();
744 }
745 }
745 };
746 };
746
747
747 var ReviewersPanel = {
748 var ReviewersPanel = {
748 editButton: $('#open_edit_reviewers'),
749 editButton: $('#open_edit_reviewers'),
749 closeButton: $('#close_edit_reviewers'),
750 closeButton: $('#close_edit_reviewers'),
750 addButton: $('#add_reviewer'),
751 addButton: $('#add_reviewer'),
751 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
752 removeButtons: $('.reviewer_member_remove,.reviewer_member_mandatory_remove'),
752
753
753 init: function () {
754 init: function () {
754 var self = this;
755 var self = this;
755 this.editButton.on('click', function (e) {
756 this.editButton.on('click', function (e) {
756 self.edit();
757 self.edit();
757 });
758 });
758 this.closeButton.on('click', function (e) {
759 this.closeButton.on('click', function (e) {
759 self.close();
760 self.close();
760 });
761 });
761 },
762 },
762
763
763 edit: function (event) {
764 edit: function (event) {
764 this.editButton.hide();
765 this.editButton.hide();
765 this.closeButton.show();
766 this.closeButton.show();
766 this.addButton.show();
767 this.addButton.show();
767 this.removeButtons.css('visibility', 'visible');
768 this.removeButtons.css('visibility', 'visible');
768 // review rules
769 // review rules
769 reviewersController.loadReviewRules(
770 reviewersController.loadReviewRules(
770 ${c.pull_request.reviewer_data_json | n});
771 ${c.pull_request.reviewer_data_json | n});
771 },
772 },
772
773
773 close: function (event) {
774 close: function (event) {
774 this.editButton.show();
775 this.editButton.show();
775 this.closeButton.hide();
776 this.closeButton.hide();
776 this.addButton.hide();
777 this.addButton.hide();
777 this.removeButtons.css('visibility', 'hidden');
778 this.removeButtons.css('visibility', 'hidden');
778 // hide review rules
779 // hide review rules
779 reviewersController.hideReviewRules()
780 reviewersController.hideReviewRules()
780 }
781 }
781 };
782 };
782
783
783 PRDetails.init();
784 PRDetails.init();
784 ReviewersPanel.init();
785 ReviewersPanel.init();
785
786
786 showOutdated = function (self) {
787 showOutdated = function (self) {
787 $('.comment-inline.comment-outdated').show();
788 $('.comment-inline.comment-outdated').show();
788 $('.filediff-outdated').show();
789 $('.filediff-outdated').show();
789 $('.showOutdatedComments').hide();
790 $('.showOutdatedComments').hide();
790 $('.hideOutdatedComments').show();
791 $('.hideOutdatedComments').show();
791 };
792 };
792
793
793 hideOutdated = function (self) {
794 hideOutdated = function (self) {
794 $('.comment-inline.comment-outdated').hide();
795 $('.comment-inline.comment-outdated').hide();
795 $('.filediff-outdated').hide();
796 $('.filediff-outdated').hide();
796 $('.hideOutdatedComments').hide();
797 $('.hideOutdatedComments').hide();
797 $('.showOutdatedComments').show();
798 $('.showOutdatedComments').show();
798 };
799 };
799
800
800 refreshMergeChecks = function () {
801 refreshMergeChecks = function () {
801 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
802 var loadUrl = "${request.current_route_path(_query=dict(merge_checks=1))}";
802 $('.pull-request-merge').css('opacity', 0.3);
803 $('.pull-request-merge').css('opacity', 0.3);
803 $('.action-buttons-extra').css('opacity', 0.3);
804 $('.action-buttons-extra').css('opacity', 0.3);
804
805
805 $('.pull-request-merge').load(
806 $('.pull-request-merge').load(
806 loadUrl, function () {
807 loadUrl, function () {
807 $('.pull-request-merge').css('opacity', 1);
808 $('.pull-request-merge').css('opacity', 1);
808
809
809 $('.action-buttons-extra').css('opacity', 1);
810 $('.action-buttons-extra').css('opacity', 1);
810 }
811 }
811 );
812 );
812 };
813 };
813
814
814 closePullRequest = function (status) {
815 closePullRequest = function (status) {
815 if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) {
816 if (!confirm(_gettext('Are you sure to close this pull request without merging?'))) {
816 return false;
817 return false;
817 }
818 }
818 // inject closing flag
819 // inject closing flag
819 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
820 $('.action-buttons-extra').append('<input type="hidden" class="close-pr-input" id="close_pull_request" value="1">');
820 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
821 $(generalCommentForm.statusChange).select2("val", status).trigger('change');
821 $(generalCommentForm.submitForm).submit();
822 $(generalCommentForm.submitForm).submit();
822 };
823 };
823
824
824 $('#show-outdated-comments').on('click', function (e) {
825 $('#show-outdated-comments').on('click', function (e) {
825 var button = $(this);
826 var button = $(this);
826 var outdated = $('.comment-outdated');
827 var outdated = $('.comment-outdated');
827
828
828 if (button.html() === "(Show)") {
829 if (button.html() === "(Show)") {
829 button.html("(Hide)");
830 button.html("(Hide)");
830 outdated.show();
831 outdated.show();
831 } else {
832 } else {
832 button.html("(Show)");
833 button.html("(Show)");
833 outdated.hide();
834 outdated.hide();
834 }
835 }
835 });
836 });
836
837
837 $('.show-inline-comments').on('change', function (e) {
838 $('.show-inline-comments').on('change', function (e) {
838 var show = 'none';
839 var show = 'none';
839 var target = e.currentTarget;
840 var target = e.currentTarget;
840 if (target.checked) {
841 if (target.checked) {
841 show = ''
842 show = ''
842 }
843 }
843 var boxid = $(target).attr('id_for');
844 var boxid = $(target).attr('id_for');
844 var comments = $('#{0} .inline-comments'.format(boxid));
845 var comments = $('#{0} .inline-comments'.format(boxid));
845 var fn_display = function (idx) {
846 var fn_display = function (idx) {
846 $(this).css('display', show);
847 $(this).css('display', show);
847 };
848 };
848 $(comments).each(fn_display);
849 $(comments).each(fn_display);
849 var btns = $('#{0} .inline-comments-button'.format(boxid));
850 var btns = $('#{0} .inline-comments-button'.format(boxid));
850 $(btns).each(fn_display);
851 $(btns).each(fn_display);
851 });
852 });
852
853
853 $('#merge_pull_request_form').submit(function () {
854 $('#merge_pull_request_form').submit(function () {
854 if (!$('#merge_pull_request').attr('disabled')) {
855 if (!$('#merge_pull_request').attr('disabled')) {
855 $('#merge_pull_request').attr('disabled', 'disabled');
856 $('#merge_pull_request').attr('disabled', 'disabled');
856 }
857 }
857 return true;
858 return true;
858 });
859 });
859
860
860 $('#edit_pull_request').on('click', function (e) {
861 $('#edit_pull_request').on('click', function (e) {
861 var title = $('#pr-title-input').val();
862 var title = $('#pr-title-input').val();
862 var description = codeMirrorInstance.getValue();
863 var description = codeMirrorInstance.getValue();
863 var renderer = $('#pr-renderer-input').val();
864 var renderer = $('#pr-renderer-input').val();
864 editPullRequest(
865 editPullRequest(
865 "${c.repo_name}", "${c.pull_request.pull_request_id}",
866 "${c.repo_name}", "${c.pull_request.pull_request_id}",
866 title, description, renderer);
867 title, description, renderer);
867 });
868 });
868
869
869 $('#update_pull_request').on('click', function (e) {
870 $('#update_pull_request').on('click', function (e) {
870 $(this).attr('disabled', 'disabled');
871 $(this).attr('disabled', 'disabled');
871 $(this).addClass('disabled');
872 $(this).addClass('disabled');
872 $(this).html(_gettext('Saving...'));
873 $(this).html(_gettext('Saving...'));
873 reviewersController.updateReviewers(
874 reviewersController.updateReviewers(
874 "${c.repo_name}", "${c.pull_request.pull_request_id}");
875 "${c.repo_name}", "${c.pull_request.pull_request_id}");
875 });
876 });
876
877
877
878
878 // fixing issue with caches on firefox
879 // fixing issue with caches on firefox
879 $('#update_commits').removeAttr("disabled");
880 $('#update_commits').removeAttr("disabled");
880
881
881 $('.show-inline-comments').on('click', function (e) {
882 $('.show-inline-comments').on('click', function (e) {
882 var boxid = $(this).attr('data-comment-id');
883 var boxid = $(this).attr('data-comment-id');
883 var button = $(this);
884 var button = $(this);
884
885
885 if (button.hasClass("comments-visible")) {
886 if (button.hasClass("comments-visible")) {
886 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
887 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
887 $(this).hide();
888 $(this).hide();
888 });
889 });
889 button.removeClass("comments-visible");
890 button.removeClass("comments-visible");
890 } else {
891 } else {
891 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
892 $('#{0} .inline-comments'.format(boxid)).each(function (index) {
892 $(this).show();
893 $(this).show();
893 });
894 });
894 button.addClass("comments-visible");
895 button.addClass("comments-visible");
895 }
896 }
896 });
897 });
897
898
898 // register submit callback on commentForm form to track TODOs
899 // register submit callback on commentForm form to track TODOs
899 window.commentFormGlobalSubmitSuccessCallback = function () {
900 window.commentFormGlobalSubmitSuccessCallback = function () {
900 refreshMergeChecks();
901 refreshMergeChecks();
901 };
902 };
902
903
903 ReviewerAutoComplete('#user');
904 ReviewerAutoComplete('#user');
904
905
905 })
906 })
906
907
907 </script>
908 </script>
908
909
909 </div>
910 </div>
910
911
911 </%def>
912 </%def>
General Comments 0
You need to be logged in to leave comments. Login now