Description:
prob manage
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r882:50181c2869eb - - The requested commit is too big and content was truncated. 7 files changed. Show full diff
@@ -0,0 +1,290 | |||||
|
|
1 | + /*! | ||
|
|
2 | + * Tempus Dominus v6.2.4 (https://getdatepicker.com/) | ||
|
|
3 | + * Copyright 2013-2022 Jonathan Peterson | ||
|
|
4 | + * Licensed under MIT (https://github.com/Eonasdan/tempus-dominus/blob/master/LICENSE) | ||
|
|
5 | + */ | ||
|
|
6 | + (function(g,f){typeof exports==='object'&&typeof module!=='undefined'?module.exports=f():typeof define==='function'&&define.amd?define(f):(g=typeof globalThis!=='undefined'?globalThis:g||self,(g.tempusDominus=g.tempusDominus||{},g.tempusDominus.plugins=g.tempusDominus.plugins||{},g.tempusDominus.plugins.customDateFormat=f()));})(this,(function(){'use strict';class CustomDateFormat { | ||
|
|
7 | + constructor(dateTime, errorMessages) { | ||
|
|
8 | + this.REGEX_FORMAT = /\[([^\]]+)]|y{1,4}|M{1,4}|d{1,4}|H{1,2}|h{1,2}|t|T|m{1,2}|s{1,2}|Z{1,2}/g; | ||
|
|
9 | + // noinspection SpellCheckingInspection | ||
|
|
10 | + this.englishFormats = { | ||
|
|
11 | + LTS: 'h:mm:ss T', | ||
|
|
12 | + LT: 'h:mm T', | ||
|
|
13 | + L: 'MM/dd/yyyy', | ||
|
|
14 | + LL: 'MMMM d, yyyy', | ||
|
|
15 | + LLL: 'MMMM d, yyyy h:mm T', | ||
|
|
16 | + LLLL: 'dddd, MMMM d, yyyy h:mm T', | ||
|
|
17 | + }; | ||
|
|
18 | + this.formattingTokens = /(\[[^[]*])|([-_:/.,()\s]+)|(T|t|yyyy|yy?|MM?M?M?|Do|dd?|hh?|HH?|mm?|ss?|z|ZZ?)/g; | ||
|
|
19 | + this.match1 = /\d/; // 0 - 9 | ||
|
|
20 | + this.match2 = /\d\d/; // 00 - 99 | ||
|
|
21 | + this.match3 = /\d{3}/; // 000 - 999 | ||
|
|
22 | + this.match4 = /\d{4}/; // 0000 - 9999 | ||
|
|
23 | + this.match1to2 = /\d\d?/; // 0 - 99 | ||
|
|
24 | + this.matchSigned = /[+-]?\d+/; // -inf - inf | ||
|
|
25 | + this.matchOffset = /[+-]\d\d:?(\d\d)?|Z/; // +00:00 -00:00 +0000 or -0000 +00 or Z | ||
|
|
26 | + this.matchWord = /\d*[^-_:/,()\s\d]+/; // Word | ||
|
|
27 | + this.zoneExpressions = [ | ||
|
|
28 | + this.matchOffset, | ||
|
|
29 | + (obj, input) => { | ||
|
|
30 | + obj.offset = this.offsetFromString(input); | ||
|
|
31 | + }, | ||
|
|
32 | + ]; | ||
|
|
33 | + this.expressions = { | ||
|
|
34 | + t: [ | ||
|
|
35 | + this.matchWord, | ||
|
|
36 | + (ojb, input) => { | ||
|
|
37 | + ojb.afternoon = this.meridiemMatch(input); | ||
|
|
38 | + }, | ||
|
|
39 | + ], | ||
|
|
40 | + T: [ | ||
|
|
41 | + this.matchWord, | ||
|
|
42 | + (ojb, input) => { | ||
|
|
43 | + ojb.afternoon = this.meridiemMatch(input); | ||
|
|
44 | + }, | ||
|
|
45 | + ], | ||
|
|
46 | + fff: [ | ||
|
|
47 | + this.match3, | ||
|
|
48 | + (ojb, input) => { | ||
|
|
49 | + ojb.milliseconds = +input; | ||
|
|
50 | + }, | ||
|
|
51 | + ], | ||
|
|
52 | + s: [this.match1to2, this.addInput('seconds')], | ||
|
|
53 | + ss: [this.match1to2, this.addInput('seconds')], | ||
|
|
54 | + m: [this.match1to2, this.addInput('minutes')], | ||
|
|
55 | + mm: [this.match1to2, this.addInput('minutes')], | ||
|
|
56 | + H: [this.match1to2, this.addInput('hours')], | ||
|
|
57 | + h: [this.match1to2, this.addInput('hours')], | ||
|
|
58 | + HH: [this.match1to2, this.addInput('hours')], | ||
|
|
59 | + hh: [this.match1to2, this.addInput('hours')], | ||
|
|
60 | + d: [this.match1to2, this.addInput('day')], | ||
|
|
61 | + dd: [this.match2, this.addInput('day')], | ||
|
|
62 | + Do: [ | ||
|
|
63 | + this.matchWord, | ||
|
|
64 | + (ojb, input) => { | ||
|
|
65 | + [ojb.day] = input.match(/\d+/); | ||
|
|
66 | + if (!this.localization.ordinal) | ||
|
|
67 | + return; | ||
|
|
68 | + for (let i = 1; i <= 31; i += 1) { | ||
|
|
69 | + if (this.localization.ordinal(i).replace(/[\[\]]/g, '') === input) { | ||
|
|
70 | + ojb.day = i; | ||
|
|
71 | + } | ||
|
|
72 | + } | ||
|
|
73 | + }, | ||
|
|
74 | + ], | ||
|
|
75 | + M: [this.match1to2, this.addInput('month')], | ||
|
|
76 | + MM: [this.match2, this.addInput('month')], | ||
|
|
77 | + MMM: [ | ||
|
|
78 | + this.matchWord, | ||
|
|
79 | + (obj, input) => { | ||
|
|
80 | + const months = this.getAllMonths(); | ||
|
|
81 | + const monthsShort = this.getAllMonths('short'); | ||
|
|
82 | + const matchIndex = (monthsShort || months.map((_) => _.slice(0, 3))).indexOf(input) + 1; | ||
|
|
83 | + if (matchIndex < 1) { | ||
|
|
84 | + throw new Error(); | ||
|
|
85 | + } | ||
|
|
86 | + obj.month = matchIndex % 12 || matchIndex; | ||
|
|
87 | + }, | ||
|
|
88 | + ], | ||
|
|
89 | + MMMM: [ | ||
|
|
90 | + this.matchWord, | ||
|
|
91 | + (obj, input) => { | ||
|
|
92 | + const months = this.getAllMonths(); | ||
|
|
93 | + const matchIndex = months.indexOf(input) + 1; | ||
|
|
94 | + if (matchIndex < 1) { | ||
|
|
95 | + throw new Error(); | ||
|
|
96 | + } | ||
|
|
97 | + obj.month = matchIndex % 12 || matchIndex; | ||
|
|
98 | + }, | ||
|
|
99 | + ], | ||
|
|
100 | + y: [this.matchSigned, this.addInput('year')], | ||
|
|
101 | + yy: [ | ||
|
|
102 | + this.match2, | ||
|
|
103 | + (obj, input) => { | ||
|
|
104 | + obj.year = this.parseTwoDigitYear(input); | ||
|
|
105 | + }, | ||
|
|
106 | + ], | ||
|
|
107 | + yyyy: [this.match4, this.addInput('year')], | ||
|
|
108 | + Z: this.zoneExpressions, | ||
|
|
109 | + ZZ: this.zoneExpressions, | ||
|
|
110 | + }; | ||
|
|
111 | + this.parseFormattedInput = (input) => { | ||
|
|
112 | + if (!this.localization.format) { | ||
|
|
113 | + this.errorMessages.customDateFormatError('No format was provided'); | ||
|
|
114 | + } | ||
|
|
115 | + try { | ||
|
|
116 | + if (['x', 'X'].indexOf(this.localization.format) > -1) | ||
|
|
117 | + return new this.DateTime((this.localization.format === 'X' ? 1000 : 1) * input); | ||
|
|
118 | + const parser = this.makeParser(this.localization.format); | ||
|
|
119 | + const { year, month, day, hours, minutes, seconds, milliseconds, zone } = parser(input); | ||
|
|
120 | + const now = new this.DateTime(); | ||
|
|
121 | + const d = day || (!year && !month ? now.getDate() : 1); | ||
|
|
122 | + const y = year || now.getFullYear(); | ||
|
|
123 | + let M = 0; | ||
|
|
124 | + if (!(year && !month)) { | ||
|
|
125 | + M = month > 0 ? month - 1 : now.getMonth(); | ||
|
|
126 | + } | ||
|
|
127 | + const h = hours || 0; | ||
|
|
128 | + const m = minutes || 0; | ||
|
|
129 | + const s = seconds || 0; | ||
|
|
130 | + const ms = milliseconds || 0; | ||
|
|
131 | + if (zone) { | ||
|
|
132 | + return new this.DateTime(Date.UTC(y, M, d, h, m, s, ms + zone.offset * 60 * 1000)); | ||
|
|
133 | + } | ||
|
|
134 | + return new this.DateTime(y, M, d, h, m, s, ms); | ||
|
|
135 | + } | ||
|
|
136 | + catch (e) { | ||
|
|
137 | + this.errorMessages.customDateFormatError(`Unable to parse provided input: ${input}, format: ${this.localization.format}`); | ||
|
|
138 | + return new this.DateTime(''); // Invalid Date | ||
|
|
139 | + } | ||
|
|
140 | + }; | ||
|
|
141 | + this.DateTime = dateTime; | ||
|
|
142 | + this.errorMessages = errorMessages; | ||
|
|
143 | + } | ||
|
|
144 | + getAllMonths(format = 'long') { | ||
|
|
145 | + const applyFormat = new Intl.DateTimeFormat(this.localization.locale, { month: format }).format; | ||
|
|
146 | + return [...Array(12).keys()].map((m) => applyFormat(new Date(2021, m))); | ||
|
|
147 | + } | ||
|
|
148 | + replaceExtendedTokens(format) { | ||
|
|
149 | + return format.replace(/(\[[^\]]+])|(MMMM|MM|dd|dddd)/g, (_, a, b) => a || b.slice(1)); | ||
|
|
150 | + } | ||
|
|
151 | + replaceTokens(formatStr, formats) { | ||
|
|
152 | + return formatStr.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (_, a, b) => { | ||
|
|
153 | + const B = b && b.toUpperCase(); | ||
|
|
154 | + return a || this.englishFormats[b] || this.replaceExtendedTokens(formats[B]); | ||
|
|
155 | + }); | ||
|
|
156 | + } | ||
|
|
157 | + parseTwoDigitYear(input) { | ||
|
|
158 | + input = +input; | ||
|
|
159 | + return input + (input > 68 ? 1900 : 2000); | ||
|
|
160 | + } | ||
|
|
161 | + ; | ||
|
|
162 | + offsetFromString(string) { | ||
|
|
163 | + if (!string) | ||
|
|
164 | + return 0; | ||
|
|
165 | + if (string === 'Z') | ||
|
|
166 | + return 0; | ||
|
|
167 | + const parts = string.match(/([+-]|\d\d)/g); | ||
|
|
168 | + const minutes = +(parts[1] * 60) + (+parts[2] || 0); | ||
|
|
169 | + return minutes === 0 ? 0 : parts[0] === '+' ? -minutes : minutes; // eslint-disable-line no-nested-ternary | ||
|
|
170 | + } | ||
|
|
171 | + addInput(property) { | ||
|
|
172 | + return (time, input) => { | ||
|
|
173 | + time[property] = +input; | ||
|
|
174 | + }; | ||
|
|
175 | + } | ||
|
|
176 | + ; | ||
|
|
177 | + meridiemMatch(input) { | ||
|
|
178 | + const meridiem = new Intl.DateTimeFormat(this.localization.locale, { | ||
|
|
179 | + hour: 'numeric', | ||
|
|
180 | + hour12: true, | ||
|
|
181 | + }) | ||
|
|
182 | + .formatToParts(new Date(2022, 3, 4, 13)) | ||
|
|
183 | + .find((p) => p.type === 'dayPeriod')?.value; | ||
|
|
184 | + return input.toLowerCase() === meridiem.toLowerCase(); | ||
|
|
185 | + } | ||
|
|
186 | + ; | ||
|
|
187 | + correctHours(time) { | ||
|
|
188 | + const { afternoon } = time; | ||
|
|
189 | + if (afternoon !== undefined) { | ||
|
|
190 | + const { hours } = time; | ||
|
|
191 | + if (afternoon) { | ||
|
|
192 | + if (hours < 12) { | ||
|
|
193 | + time.hours += 12; | ||
|
|
194 | + } | ||
|
|
195 | + } | ||
|
|
196 | + else if (hours === 12) { | ||
|
|
197 | + time.hours = 0; | ||
|
|
198 | + } | ||
|
|
199 | + delete time.afternoon; | ||
|
|
200 | + } | ||
|
|
201 | + } | ||
|
|
202 | + makeParser(format) { | ||
|
|
203 | + format = this.replaceTokens(format, this.localization.dateFormats); | ||
|
|
204 | + const array = format.match(this.formattingTokens); | ||
|
|
205 | + const { length } = array; | ||
|
|
206 | + for (let i = 0; i < length; i += 1) { | ||
|
|
207 | + const token = array[i]; | ||
|
|
208 | + const parseTo = this.expressions[token]; | ||
|
|
209 | + const regex = parseTo && parseTo[0]; | ||
|
|
210 | + const parser = parseTo && parseTo[1]; | ||
|
|
211 | + if (parser) { | ||
|
|
212 | + array[i] = { regex, parser }; | ||
|
|
213 | + } | ||
|
|
214 | + else { | ||
|
|
215 | + array[i] = token.replace(/^\[|]$/g, ''); | ||
|
|
216 | + } | ||
|
|
217 | + } | ||
|
|
218 | + return (input) => { | ||
|
|
219 | + const time = {}; | ||
|
|
220 | + for (let i = 0, start = 0; i < length; i += 1) { | ||
|
|
221 | + const token = array[i]; | ||
|
|
222 | + if (typeof token === 'string') { | ||
|
|
223 | + start += token.length; | ||
|
|
224 | + } | ||
|
|
225 | + else { | ||
|
|
226 | + const { regex, parser } = token; | ||
|
|
227 | + const part = input.slice(start); | ||
|
|
228 | + const match = regex.exec(part); | ||
|
|
229 | + const value = match[0]; | ||
|
|
230 | + parser.call(this, time, value); | ||
|
|
231 | + input = input.replace(value, ''); | ||
|
|
232 | + } | ||
|
|
233 | + } | ||
|
|
234 | + this.correctHours(time); | ||
|
|
235 | + return time; | ||
|
|
236 | + }; | ||
|
|
237 | + } | ||
|
|
238 | + format(dateTime) { | ||
|
|
239 | + if (!dateTime) | ||
|
|
240 | + return dateTime; | ||
|
|
241 | + if (JSON.stringify(dateTime) === 'null') | ||
|
|
242 | + return 'Invalid Date'; | ||
|
|
243 | + const format = this.replaceTokens(this.localization.format || `${this.englishFormats.L}, ${this.englishFormats.LT}`, this.localization.dateFormats); | ||
|
|
244 | + const formatter = (template) => new Intl.DateTimeFormat(this.localization.locale, template).format(dateTime); | ||
|
|
245 | + const matches = { | ||
|
|
246 | + yy: formatter({ year: '2-digit' }), | ||
|
|
247 | + yyyy: dateTime.year, | ||
|
|
248 | + M: formatter({ month: 'numeric' }), | ||
|
|
249 | + MM: dateTime.monthFormatted, | ||
|
|
250 | + MMM: this.getAllMonths('short')[dateTime.getMonth()], | ||
|
|
251 | + MMMM: this.getAllMonths()[dateTime.getMonth()], | ||
|
|
252 | + d: dateTime.date, | ||
|
|
253 | + dd: dateTime.dateFormatted, | ||
|
|
254 | + ddd: formatter({ weekday: "short" }), | ||
|
|
255 | + dddd: formatter({ weekday: "long" }), | ||
|
|
256 | + H: dateTime.getHours(), | ||
|
|
257 | + HH: dateTime.hoursFormatted, | ||
|
|
258 | + h: dateTime.hours > 12 ? dateTime.hours - 12 : dateTime.hours, | ||
|
|
259 | + hh: dateTime.twelveHoursFormatted, | ||
|
|
260 | + t: dateTime.meridiem(), | ||
|
|
261 | + T: dateTime.meridiem().toUpperCase(), | ||
|
|
262 | + m: dateTime.minutes, | ||
|
|
263 | + mm: dateTime.minutesFormatted, | ||
|
|
264 | + s: dateTime.seconds, | ||
|
|
265 | + ss: dateTime.secondsFormatted, | ||
|
|
266 | + fff: dateTime.getMilliseconds(), | ||
|
|
267 | + //z: dateTime.getTimezoneOffset() todo zones are stupid | ||
|
|
268 | + }; | ||
|
|
269 | + return format.replace(this.REGEX_FORMAT, (match, $1) => { | ||
|
|
270 | + return $1 || matches[match]; | ||
|
|
271 | + }); | ||
|
|
272 | + } | ||
|
|
273 | + } | ||
|
|
274 | + var index = (_, tdClasses, __) => { | ||
|
|
275 | + const customDateFormat = new CustomDateFormat(tdClasses.DateTime, tdClasses.ErrorMessages); | ||
|
|
276 | + // noinspection JSUnusedGlobalSymbols | ||
|
|
277 | + tdClasses.Dates.prototype.formatInput = function (date) { | ||
|
|
278 | + customDateFormat.localization = this.optionsStore.options.localization; | ||
|
|
279 | + return customDateFormat.format(date); | ||
|
|
280 | + }; | ||
|
|
281 | + // noinspection JSUnusedGlobalSymbols | ||
|
|
282 | + tdClasses.Dates.prototype.parseInput = function (input) { | ||
|
|
283 | + customDateFormat.localization = this.optionsStore.options.localization; | ||
|
|
284 | + return customDateFormat.parseFormattedInput(input); | ||
|
|
285 | + }; | ||
|
|
286 | + tdClasses.DateTime.fromString = function (input, localization) { | ||
|
|
287 | + customDateFormat.localization = localization; | ||
|
|
288 | + return customDateFormat.parseFormattedInput(input); | ||
|
|
289 | + }; | ||
|
|
290 | + };return index;})); |
new file 100644 |
@@ -154,19 +154,14 | |||||
|
154 | end |
|
154 | end |
|
155 |
|
155 | ||
|
156 | def manage |
|
156 | def manage |
|
157 | - @problems = Problem.order(date_added: :desc) |
|
157 | + @problems = Problem.order(date_added: :desc).includes(:tags) |
|
158 | end |
|
158 | end |
|
159 |
|
159 | ||
|
160 | def do_manage |
|
160 | def do_manage |
|
161 |
- if params |
|
161 | + change_date_added if params[:change_date_added] == '1' && params[:date_added].strip.empty? == false |
|
162 | - change_date_added |
|
162 | + add_to_contest if params.has_key? 'add_to_contest' |
|
163 | - elsif params.has_key? 'add_to_contest' |
|
163 | + set_available(params[:enable] == 'yes') if params[:change_enable] == '1' |
|
164 | - add_to_contest |
|
164 | + if params[:add_group] == '1' |
|
165 | - elsif params.has_key? 'enable_problem' |
|
||
|
166 | - set_available(true) |
|
||
|
167 | - elsif params.has_key? 'disable_problem' |
|
||
|
168 | - set_available(false) |
|
||
|
169 | - elsif params.has_key? 'add_group' |
|
||
|
170 | group = Group.find(params[:group_id]) |
|
165 | group = Group.find(params[:group_id]) |
|
171 | ok = [] |
|
166 | ok = [] |
|
172 | failed = [] |
|
167 | failed = [] |
@@ -180,10 +175,10 | |||||
|
180 | end |
|
175 | end |
|
181 | flash[:success] = "The following problems are added to the group #{group.name}: " + ok.join(', ') if ok.count > 0 |
|
176 | flash[:success] = "The following problems are added to the group #{group.name}: " + ok.join(', ') if ok.count > 0 |
|
182 | flash[:alert] = "The following problems are already in the group #{group.name}: " + failed.join(', ') if failed.count > 0 |
|
177 | flash[:alert] = "The following problems are already in the group #{group.name}: " + failed.join(', ') if failed.count > 0 |
|
183 | - elsif params.has_key? 'add_tags' |
|
178 | + end |
|
184 | - get_problems_from_params.each do |p| |
|
179 | + |
|
185 | - p.tag_ids += params[:tag_ids] |
|
180 | + if params[:add_tags] == '1' |
|
186 | - end |
|
181 | + get_problems_from_params.each { |p| p.tag_ids += params[:tag_ids] } |
|
187 | end |
|
182 | end |
|
188 |
|
183 | ||
|
189 | redirect_to :action => 'manage' |
|
184 | redirect_to :action => 'manage' |
@@ -45,8 +45,14 | |||||
|
45 |
|
45 | ||
|
46 | import "select2" |
|
46 | import "select2" |
|
47 | import "chart" |
|
47 | import "chart" |
|
|
48 | + | ||
|
|
49 | + //tempus dominus | ||
|
48 | import { TempusDominus } from "@eonasdan/tempus-dominus" |
|
50 | import { TempusDominus } from "@eonasdan/tempus-dominus" |
|
|
51 | + import * as TD from "@eonasdan/tempus-dominus-esm" | ||
|
|
52 | + import * as customDateFormat from '@eonasdan/tempus-dominus/customDateFormat' | ||
|
|
53 | + window.TD = TD | ||
|
49 | window.TempusDominus = TempusDominus |
|
54 | window.TempusDominus = TempusDominus |
|
|
55 | + window.customDateFormat = customDateFormat | ||
|
50 |
|
56 | ||
|
51 | //my own customization |
|
57 | //my own customization |
|
52 | import 'custom' |
|
58 | import 'custom' |
@@ -36,7 +36,7 | |||||
|
36 | = f.label :add_group, 'Add selected problems to user group' |
|
36 | = f.label :add_group, 'Add selected problems to user group' |
|
37 | = f.check_box :add_group, class: 'form-check-input' |
|
37 | = f.check_box :add_group, class: 'form-check-input' |
|
38 | .col-md-auto |
|
38 | .col-md-auto |
|
39 | - = f.select "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), {}, class: 'select2 form-control' |
|
39 | + = f.select "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), {}, class: 'select2 form-control', data: {width: "400px"} |
|
40 | .col-md-6 |
|
40 | .col-md-6 |
|
41 | .row.mb-3.align-items-center |
|
41 | .row.mb-3.align-items-center |
|
42 | .col-md-auto |
|
42 | .col-md-auto |
@@ -57,37 +57,6 | |||||
|
57 | .col-auto |
|
57 | .col-auto |
|
58 | = f.submit :go, class: 'btn btn-primary' |
|
58 | = f.submit :go, class: 'btn btn-primary' |
|
59 |
|
59 | ||
|
60 | - |
|
||
|
61 | - -# |
|
||
|
62 | - %ul.form-inline |
|
||
|
63 | - %li |
|
||
|
64 | - Change "Date added" to |
|
||
|
65 | - .input-group.date |
|
||
|
66 | - = text_field_tag :date_added, class: 'form-control' |
|
||
|
67 | - %span.input-group-addon |
|
||
|
68 | - %span.glyphicon.glyphicon-calendar |
|
||
|
69 | - -# = select_date Date.current, :prefix => 'date_added' |
|
||
|
70 | - |
|
||
|
71 | - = submit_tag 'Change', :name => 'change_date_added', class: 'btn btn-primary btn-sm' |
|
||
|
72 | - %li |
|
||
|
73 | - Set "Available" to |
|
||
|
74 | - = submit_tag 'True', :name => 'enable_problem', class: 'btn btn-primary btn-sm' |
|
||
|
75 | - = submit_tag 'False', :name => 'disable_problem', class: 'btn btn-primary btn-sm' |
|
||
|
76 | - |
|
||
|
77 | - - if GraderConfiguration.multicontests? |
|
||
|
78 | - %li |
|
||
|
79 | - Add selected problems to contest |
|
||
|
80 | - = select("contest","id",Contest.all.collect {|c| [c.title, c.id]}) |
|
||
|
81 | - = submit_tag 'Add', :name => 'add_to_contest', class: 'btn btn-primary btn-sm' |
|
||
|
82 | - %li |
|
||
|
83 | - Add selected problems to user group |
|
||
|
84 | - = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2' |
|
||
|
85 | - = submit_tag 'Add', name: 'add_group', class: 'btn btn-primary' |
|
||
|
86 | - %li |
|
||
|
87 | - Add the following tags to the selected problems |
|
||
|
88 | - = select_tag "tag_ids", options_from_collection_for_select( Tag.all, 'id','name'), id: 'tags_name',class: 'select2', multiple: true, data: {placeholder: 'Select tags by clicking', width: "200px"} |
|
||
|
89 | - = submit_tag 'Add', name: 'add_tags', class: 'btn btn-primary' |
|
||
|
90 | - |
|
||
|
91 | %table.table.table-hover.datatable |
|
60 | %table.table.table-hover.datatable |
|
92 | %thead |
|
61 | %thead |
|
93 | %tr{style: "text-align: left;"} |
|
62 | %tr{style: "text-align: left;"} |
@@ -110,7 +79,7 | |||||
|
110 | %td= problem.full_name |
|
79 | %td= problem.full_name |
|
111 | %td |
|
80 | %td |
|
112 | - problem.tags.each do |t| |
|
81 | - problem.tags.each do |t| |
|
113 |
- %span. |
|
82 | + %span.badge.text-bg-secondary= t.name |
|
114 | %td= problem.available |
|
83 | %td= problem.available |
|
115 | %td= problem.date_added |
|
84 | %td= problem.date_added |
|
116 | - if GraderConfiguration.multicontests? |
|
85 | - if GraderConfiguration.multicontests? |
@@ -149,33 +118,34 | |||||
|
149 | } |
|
118 | } |
|
150 | }); |
|
119 | }); |
|
151 |
|
120 | ||
|
152 | - $('.input-group.date').datetimepicker({ |
|
||
|
153 | - format: 'DD/MMM/YYYY', |
|
||
|
154 | - showTodayButton: true, |
|
||
|
155 | - locale: 'en', |
|
||
|
156 | - widgetPositioning: {horizontal: 'auto', vertical: 'bottom'}, |
|
||
|
157 | - |
|
||
|
158 | - }); |
|
||
|
159 | - |
|
||
|
160 | $('.datatable').DataTable({ |
|
121 | $('.datatable').DataTable({ |
|
161 | paging: false |
|
122 | paging: false |
|
162 | }); |
|
123 | }); |
|
163 | $('.select2').select2(); |
|
124 | $('.select2').select2(); |
|
164 |
|
125 | ||
|
165 |
|
126 | ||
|
166 | - new TempusDominus(document.getElementById('date_added'), { |
|
127 | + td = new TempusDominus(document.getElementById('date_added'), { |
|
167 | display: { |
|
128 | display: { |
|
168 | icons: { |
|
129 | icons: { |
|
169 | time: 'mi mi-td-time', |
|
130 | time: 'mi mi-td-time', |
|
170 | date: 'mi mi-td-date', |
|
131 | date: 'mi mi-td-date', |
|
171 | up: 'mi mi-td-up', |
|
132 | up: 'mi mi-td-up', |
|
172 | down: 'mi mi-td-down', |
|
133 | down: 'mi mi-td-down', |
|
173 |
- previous: ' |
|
134 | + previous: 'mi mi-td-previous', |
|
174 |
- next: ' |
|
135 | + next: 'mi mi-td-next', |
|
175 |
- today: ' |
|
136 | + today: 'mi mi-td-today', |
|
176 |
- clear: ' |
|
137 | + clear: 'mi mi-td-clear', |
|
177 |
- close: ' |
|
138 | + close: 'mi mi-td-close', |
|
178 | }, |
|
139 | }, |
|
|
140 | + components: { | ||
|
|
141 | + hours: false, | ||
|
|
142 | + minutes: false, | ||
|
|
143 | + seconds: false | ||
|
|
144 | + } | ||
|
|
145 | + }, | ||
|
|
146 | + localization: { | ||
|
|
147 | + locale: 'en-uk', | ||
|
|
148 | + format: 'dd/MMM/yyyy', | ||
|
179 | } |
|
149 | } |
|
180 | }); |
|
150 | }); |
|
181 |
|
151 |
@@ -56,4 +56,6 | |||||
|
56 |
|
56 | ||
|
57 | #pin "ace-rails-ap" |
|
57 | #pin "ace-rails-ap" |
|
58 | pin "chart", to: 'chart.js' # @3.9.1 |
|
58 | pin "chart", to: 'chart.js' # @3.9.1 |
|
59 | - pin "@eonasdan/tempus-dominus", to: "@eonasdan--tempus-dominus.js" # @6.2.4 |
|
59 | + pin "@eonasdan/tempus-dominus", to: "tempus-dominus/@eonasdan--tempus-dominus.js" # @6.2.4 |
|
|
60 | + pin "@eonasdan/tempus-dominus-esm", to: "tempus-dominus/tempus-dominus.esm.js" # @6.2.4 | ||
|
|
61 | + pin "@eonasdan/tempus-dominus/customDateFormat", to: "tempus-dominus/customDateFormat.js" # @6.2.4 |
file renamed from vendor/javascript/@eonasdan--tempus-dominus.js to vendor/javascript/tempus-dominus/@eonasdan--tempus-dominus.js |
You need to be logged in to leave comments.
Login now