Description:
start update to 5.2
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r751:01b657de42d9 - - 29 files changed: 765 inserted, 140 deleted

@@ -0,0 +1,14
1 + %h1 New announcement
2 + = error_messages_for :announcement
3 + = simple_form_for(@announcement) do |f|
4 + .row
5 + .col-md-6
6 + = f.input :title
7 + = f.input :notes, label: 'Notes (shown internally, used to organize announcements)'
8 + = f.input :body
9 + = f.input :author
10 + = f.input :published
11 + = f.input :frontpage, label: 'Display in the front page only?'
12 + = f.input :contest_only, label: 'Display in contest only?'
13 + = f.button :submit, "Create", class: 'btn btn-primary'
14 + = link_to 'Back', announcements_path, class: 'btn btn-default'
@@ -0,0 +1,24
1 + %p
2 + %b Author:
3 + = h @announcement.author
4 + %p
5 + %b Title:
6 + = h @announcement.title
7 + %p
8 + %b Notes:
9 + = h @announcement.notes
10 + %p
11 + %b Body:
12 + = h markdown(@announcement.body)
13 + %p
14 + %b Published:
15 + = h @announcement.published
16 + %p
17 + %b Show on front page:
18 + = h @announcement.frontpage
19 + %p
20 + %b Show only in contest:
21 + = h @announcement.contest_only
22 + = link_to 'Edit', edit_announcement_path(@announcement)
23 + |
24 + = link_to 'Back', announcements_path
@@ -0,0 +1,179
1 + # frozen_string_literal: true
2 + #
3 + # Uncomment this and change the path if necessary to include your own
4 + # components.
5 + # See https://github.com/plataformatec/simple_form#custom-components to know
6 + # more about custom components.
7 + # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8 + #
9 + # Use this setup block to configure all options available in SimpleForm.
10 + SimpleForm.setup do |config|
11 + # Wrappers are used by the form builder to generate a
12 + # complete input. You can remove any component from the
13 + # wrapper, change the order or even add your own to the
14 + # stack. The options given below are used to wrap the
15 + # whole input.
16 + config.wrappers :default, class: :input,
17 + hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
18 + ## Extensions enabled by default
19 + # Any of these extensions can be disabled for a
20 + # given input by passing: `f.input EXTENSION_NAME => false`.
21 + # You can make any of these extensions optional by
22 + # renaming `b.use` to `b.optional`.
23 +
24 + # Determines whether to use HTML5 (:email, :url, ...)
25 + # and required attributes
26 + b.use :html5
27 +
28 + # Calculates placeholders automatically from I18n
29 + # You can also pass a string as f.input placeholder: "Placeholder"
30 + b.use :placeholder
31 +
32 + ## Optional extensions
33 + # They are disabled unless you pass `f.input EXTENSION_NAME => true`
34 + # to the input. If so, they will retrieve the values from the model
35 + # if any exists. If you want to enable any of those
36 + # extensions by default, you can change `b.optional` to `b.use`.
37 +
38 + # Calculates maxlength from length validations for string inputs
39 + # and/or database column lengths
40 + b.optional :maxlength
41 +
42 + # Calculate minlength from length validations for string inputs
43 + b.optional :minlength
44 +
45 + # Calculates pattern from format validations for string inputs
46 + b.optional :pattern
47 +
48 + # Calculates min and max from length validations for numeric inputs
49 + b.optional :min_max
50 +
51 + # Calculates readonly automatically from readonly attributes
52 + b.optional :readonly
53 +
54 + ## Inputs
55 + # b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
56 + b.use :label_input
57 + b.use :hint, wrap_with: { tag: :span, class: :hint }
58 + b.use :error, wrap_with: { tag: :span, class: :error }
59 +
60 + ## full_messages_for
61 + # If you want to display the full error message for the attribute, you can
62 + # use the component :full_error, like:
63 + #
64 + # b.use :full_error, wrap_with: { tag: :span, class: :error }
65 + end
66 +
67 + # The default wrapper to be used by the FormBuilder.
68 + config.default_wrapper = :default
69 +
70 + # Define the way to render check boxes / radio buttons with labels.
71 + # Defaults to :nested for bootstrap config.
72 + # inline: input + label
73 + # nested: label > input
74 + config.boolean_style = :nested
75 +
76 + # Default class for buttons
77 + config.button_class = 'btn'
78 +
79 + # Method used to tidy up errors. Specify any Rails Array method.
80 + # :first lists the first message for each field.
81 + # Use :to_sentence to list all errors for each field.
82 + # config.error_method = :first
83 +
84 + # Default tag used for error notification helper.
85 + config.error_notification_tag = :div
86 +
87 + # CSS class to add for error notification helper.
88 + config.error_notification_class = 'error_notification'
89 +
90 + # Series of attempts to detect a default label method for collection.
91 + # config.collection_label_methods = [ :to_label, :name, :title, :to_s ]
92 +
93 + # Series of attempts to detect a default value method for collection.
94 + # config.collection_value_methods = [ :id, :to_s ]
95 +
96 + # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
97 + # config.collection_wrapper_tag = nil
98 +
99 + # You can define the class to use on all collection wrappers. Defaulting to none.
100 + # config.collection_wrapper_class = nil
101 +
102 + # You can wrap each item in a collection of radio/check boxes with a tag,
103 + # defaulting to :span.
104 + # config.item_wrapper_tag = :span
105 +
106 + # You can define a class to use in all item wrappers. Defaulting to none.
107 + # config.item_wrapper_class = nil
108 +
109 + # How the label text should be generated altogether with the required text.
110 + # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
111 +
112 + # You can define the class to use on all labels. Default is nil.
113 + # config.label_class = nil
114 +
115 + # You can define the default class to be used on forms. Can be overriden
116 + # with `html: { :class }`. Defaulting to none.
117 + # config.default_form_class = nil
118 +
119 + # You can define which elements should obtain additional classes
120 + # config.generate_additional_classes_for = [:wrapper, :label, :input]
121 +
122 + # Whether attributes are required by default (or not). Default is true.
123 + # config.required_by_default = true
124 +
125 + # Tell browsers whether to use the native HTML5 validations (novalidate form option).
126 + # These validations are enabled in SimpleForm's internal config but disabled by default
127 + # in this configuration, which is recommended due to some quirks from different browsers.
128 + # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
129 + # change this configuration to true.
130 + config.browser_validations = false
131 +
132 + # Collection of methods to detect if a file type was given.
133 + # config.file_methods = [ :mounted_as, :file?, :public_filename, :attached? ]
134 +
135 + # Custom mappings for input types. This should be a hash containing a regexp
136 + # to match as key, and the input type that will be used when the field name
137 + # matches the regexp as value.
138 + # config.input_mappings = { /count/ => :integer }
139 +
140 + # Custom wrappers for input types. This should be a hash containing an input
141 + # type as key and the wrapper that will be used for all inputs with specified type.
142 + # config.wrapper_mappings = { string: :prepend }
143 +
144 + # Namespaces where SimpleForm should look for custom input classes that
145 + # override default inputs.
146 + # config.custom_inputs_namespaces << "CustomInputs"
147 +
148 + # Default priority for time_zone inputs.
149 + # config.time_zone_priority = nil
150 +
151 + # Default priority for country inputs.
152 + # config.country_priority = nil
153 +
154 + # When false, do not use translations for labels.
155 + # config.translate_labels = true
156 +
157 + # Automatically discover new inputs in Rails' autoload path.
158 + # config.inputs_discovery = true
159 +
160 + # Cache SimpleForm inputs discovery
161 + # config.cache_discovery = !Rails.env.development?
162 +
163 + # Default class for inputs
164 + # config.input_class = nil
165 +
166 + # Define the default class of the input wrapper of the boolean input.
167 + config.boolean_label_class = 'checkbox'
168 +
169 + # Defines if the default input wrapper class should be included in radio
170 + # collection wrappers.
171 + # config.include_default_input_wrapper_class = true
172 +
173 + # Defines which i18n scope will be used in Simple Form.
174 + # config.i18n_scope = 'simple_form'
175 +
176 + # Defines validation classes to the input_field. By default it's nil.
177 + # config.input_field_valid_class = 'is-valid'
178 + # config.input_field_error_class = 'is-invalid'
179 + end
@@ -0,0 +1,439
1 + # frozen_string_literal: true
2 +
3 + # Please do not make direct changes to this file!
4 + # This generator is maintained by the community around simple_form-bootstrap:
5 + # https://github.com/rafaelfranca/simple_form-bootstrap
6 + # All future development, tests, and organization should happen there.
7 + # Background history: https://github.com/plataformatec/simple_form/issues/1561
8 +
9 + # Uncomment this and change the path if necessary to include your own
10 + # components.
11 + # See https://github.com/plataformatec/simple_form#custom-components
12 + # to know more about custom components.
13 + # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
14 +
15 + # Use this setup block to configure all options available in SimpleForm.
16 + SimpleForm.setup do |config|
17 + # Default class for buttons
18 + config.button_class = 'btn'
19 +
20 + # Define the default class of the input wrapper of the boolean input.
21 + config.boolean_label_class = 'form-check-label'
22 +
23 + # How the label text should be generated altogether with the required text.
24 + config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }
25 +
26 + # Define the way to render check boxes / radio buttons with labels.
27 + config.boolean_style = :inline
28 +
29 + # You can wrap each item in a collection of radio/check boxes with a tag
30 + config.item_wrapper_tag = :div
31 +
32 + # Defines if the default input wrapper class should be included in radio
33 + # collection wrappers.
34 + config.include_default_input_wrapper_class = false
35 +
36 + # CSS class to add for error notification helper.
37 + config.error_notification_class = 'alert alert-danger'
38 +
39 + # Method used to tidy up errors. Specify any Rails Array method.
40 + # :first lists the first message for each field.
41 + # :to_sentence to list all errors for each field.
42 + config.error_method = :to_sentence
43 +
44 + # add validation classes to `input_field`
45 + config.input_field_error_class = 'is-invalid'
46 + config.input_field_valid_class = 'is-valid'
47 +
48 +
49 + # vertical forms
50 + #
51 + # vertical default_wrapper
52 + config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
53 + b.use :html5
54 + b.use :placeholder
55 + b.optional :maxlength
56 + b.optional :minlength
57 + b.optional :pattern
58 + b.optional :min_max
59 + b.optional :readonly
60 + b.use :label, class: 'form-control-label'
61 + b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
62 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
63 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
64 + end
65 +
66 + # vertical input for boolean
67 + config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
68 + b.use :html5
69 + b.optional :readonly
70 + b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
71 + bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
72 + bb.use :label, class: 'form-check-label'
73 + bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
74 + bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
75 + end
76 + end
77 +
78 + # vertical input for radio buttons and check boxes
79 + config.wrappers :vertical_collection, item_wrapper_class: 'form-check', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
80 + b.use :html5
81 + b.optional :readonly
82 + b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
83 + ba.use :label_text
84 + end
85 + b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
86 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
87 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
88 + end
89 +
90 + # vertical input for inline radio buttons and check boxes
91 + config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
92 + b.use :html5
93 + b.optional :readonly
94 + b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
95 + ba.use :label_text
96 + end
97 + b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
98 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
99 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
100 + end
101 +
102 + # vertical file input
103 + config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
104 + b.use :html5
105 + b.use :placeholder
106 + b.optional :maxlength
107 + b.optional :minlength
108 + b.optional :readonly
109 + b.use :label
110 + b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid'
111 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
112 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
113 + end
114 +
115 + # vertical multi select
116 + config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
117 + b.use :html5
118 + b.optional :readonly
119 + b.use :label, class: 'form-control-label'
120 + b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
121 + ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
122 + end
123 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
124 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
125 + end
126 +
127 + # vertical range input
128 + config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
129 + b.use :html5
130 + b.use :placeholder
131 + b.optional :readonly
132 + b.optional :step
133 + b.use :label
134 + b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
135 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
136 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
137 + end
138 +
139 +
140 + # horizontal forms
141 + #
142 + # horizontal default_wrapper
143 + config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
144 + b.use :html5
145 + b.use :placeholder
146 + b.optional :maxlength
147 + b.optional :minlength
148 + b.optional :pattern
149 + b.optional :min_max
150 + b.optional :readonly
151 + b.use :label, class: 'col-sm-3 col-form-label'
152 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
153 + ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
154 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
155 + ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
156 + end
157 + end
158 +
159 + # horizontal input for boolean
160 + config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
161 + b.use :html5
162 + b.optional :readonly
163 + b.wrapper tag: 'label', class: 'col-sm-3' do |ba|
164 + ba.use :label_text
165 + end
166 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr|
167 + wr.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
168 + bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
169 + bb.use :label, class: 'form-check-label'
170 + bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
171 + bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
172 + end
173 + end
174 + end
175 +
176 + # horizontal input for radio buttons and check boxes
177 + config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
178 + b.use :html5
179 + b.optional :readonly
180 + b.use :label, class: 'col-sm-3 form-control-label'
181 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
182 + ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
183 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
184 + ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
185 + end
186 + end
187 +
188 + # horizontal input for inline radio buttons and check boxes
189 + config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
190 + b.use :html5
191 + b.optional :readonly
192 + b.use :label, class: 'col-sm-3 form-control-label'
193 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
194 + ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
195 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
196 + ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
197 + end
198 + end
199 +
200 + # horizontal file input
201 + config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
202 + b.use :html5
203 + b.use :placeholder
204 + b.optional :maxlength
205 + b.optional :minlength
206 + b.optional :readonly
207 + b.use :label, class: 'col-sm-3 form-control-label'
208 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
209 + ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
210 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
211 + ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
212 + end
213 + end
214 +
215 + # horizontal multi select
216 + config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
217 + b.use :html5
218 + b.optional :readonly
219 + b.use :label, class: 'col-sm-3 control-label'
220 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
221 + ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
222 + bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
223 + end
224 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
225 + ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
226 + end
227 + end
228 +
229 + # horizontal range input
230 + config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
231 + b.use :html5
232 + b.use :placeholder
233 + b.optional :readonly
234 + b.optional :step
235 + b.use :label, class: 'col-sm-3 form-control-label'
236 + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
237 + ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
238 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
239 + ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
240 + end
241 + end
242 +
243 +
244 + # inline forms
245 + #
246 + # inline default_wrapper
247 + config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
248 + b.use :html5
249 + b.use :placeholder
250 + b.optional :maxlength
251 + b.optional :minlength
252 + b.optional :pattern
253 + b.optional :min_max
254 + b.optional :readonly
255 + b.use :label, class: 'sr-only'
256 +
257 + b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
258 + b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
259 + b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
260 + end
261 +
262 + # inline input for boolean
263 + config.wrappers :inline_boolean, tag: 'span', class: 'form-check flex-wrap justify-content-start mr-sm-2', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
264 + b.use :html5
265 + b.optional :readonly
266 + b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
267 + b.use :label, class: 'form-check-label'
268 + b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
269 + b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
270 + end
271 +
272 +
273 + # bootstrap custom forms
274 + #
275 + # custom input for boolean
276 + config.wrappers :custom_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
277 + b.use :html5
278 + b.optional :readonly
279 + b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb|
280 + bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
281 + bb.use :label, class: 'custom-control-label'
282 + bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
283 + bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
284 + end
285 + end
286 +
287 + config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
288 + b.use :html5
289 + b.optional :readonly
290 + b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox-switch' do |bb|
291 + bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
292 + bb.use :label, class: 'custom-control-label'
293 + bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
294 + bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
295 + end
296 + end
297 +
298 + # custom input for radio buttons and check boxes
299 + config.wrappers :custom_collection, item_wrapper_class: 'custom-control', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
300 + b.use :html5
301 + b.optional :readonly
302 + b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
303 + ba.use :label_text
304 + end
305 + b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
306 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
307 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
308 + end
309 +
310 + # custom input for inline radio buttons and check boxes
311 + config.wrappers :custom_collection_inline, item_wrapper_class: 'custom-control custom-control-inline', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
312 + b.use :html5
313 + b.optional :readonly
314 + b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
315 + ba.use :label_text
316 + end
317 + b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
318 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
319 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
320 + end
321 +
322 + # custom file input
323 + config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
324 + b.use :html5
325 + b.use :placeholder
326 + b.optional :maxlength
327 + b.optional :minlength
328 + b.optional :readonly
329 + b.use :label, class: 'form-control-label'
330 + b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
331 + ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
332 + ba.use :label, class: 'custom-file-label'
333 + ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
334 + end
335 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
336 + end
337 +
338 + # custom multi select
339 + config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
340 + b.use :html5
341 + b.optional :readonly
342 + b.use :label, class: 'form-control-label'
343 + b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
344 + ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
345 + end
346 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
347 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
348 + end
349 +
350 + # custom range input
351 + config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
352 + b.use :html5
353 + b.use :placeholder
354 + b.optional :readonly
355 + b.optional :step
356 + b.use :label, class: 'form-control-label'
357 + b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
358 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
359 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
360 + end
361 +
362 +
363 + # Input Group - custom component
364 + # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
365 + # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
366 + # b.use :html5
367 + # b.use :placeholder
368 + # b.optional :maxlength
369 + # b.optional :minlength
370 + # b.optional :pattern
371 + # b.optional :min_max
372 + # b.optional :readonly
373 + # b.use :label, class: 'form-control-label'
374 + # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
375 + # ba.optional :prepend
376 + # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
377 + # ba.optional :append
378 + # end
379 + # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
380 + # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
381 + # end
382 +
383 +
384 + # Floating Labels form
385 + #
386 + # floating labels default_wrapper
387 + config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
388 + b.use :html5
389 + b.use :placeholder
390 + b.optional :maxlength
391 + b.optional :minlength
392 + b.optional :pattern
393 + b.optional :min_max
394 + b.optional :readonly
395 + b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
396 + b.use :label, class: 'form-control-label'
397 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
398 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
399 + end
400 +
401 + # custom multi select
402 + config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
403 + b.use :html5
404 + b.optional :readonly
405 + b.use :input, class: 'custom-select custom-select-lg', error_class: 'is-invalid', valid_class: 'is-valid'
406 + b.use :label, class: 'form-control-label'
407 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
408 + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
409 + end
410 +
411 +
412 + # The default wrapper to be used by the FormBuilder.
413 + config.default_wrapper = :vertical_form
414 +
415 + # Custom wrappers for input types. This should be a hash containing an input
416 + # type as key and the wrapper that will be used for all inputs with specified type.
417 + config.wrapper_mappings = {
418 + boolean: :vertical_boolean,
419 + check_boxes: :vertical_collection,
420 + date: :vertical_multi_select,
421 + datetime: :vertical_multi_select,
422 + file: :vertical_file,
423 + radio_buttons: :vertical_collection,
424 + range: :vertical_range,
425 + time: :vertical_multi_select
426 + }
427 +
428 + # enable custom form wrappers
429 + # config.wrapper_mappings = {
430 + # boolean: :custom_boolean,
431 + # check_boxes: :custom_collection,
432 + # date: :custom_multi_select,
433 + # datetime: :custom_multi_select,
434 + # file: :custom_file,
435 + # radio_buttons: :custom_collection,
436 + # range: :custom_range,
437 + # time: :custom_multi_select
438 + # }
439 + end
@@ -0,0 +1,31
1 + en:
2 + simple_form:
3 + "yes": 'Yes'
4 + "no": 'No'
5 + required:
6 + text: 'required'
7 + mark: '*'
8 + # You can uncomment the line below if you need to overwrite the whole required html.
9 + # When using html, text and mark won't be used.
10 + # html: '<abbr title="required">*</abbr>'
11 + error_notification:
12 + default_message: "Please review the problems below:"
13 + # Examples
14 + # labels:
15 + # defaults:
16 + # password: 'Password'
17 + # user:
18 + # new:
19 + # email: 'E-mail to sign in.'
20 + # edit:
21 + # email: 'E-mail.'
22 + # hints:
23 + # defaults:
24 + # username: 'User name to sign in.'
25 + # password: 'No special characters, please.'
26 + # include_blanks:
27 + # defaults:
28 + # age: 'Rather not say'
29 + # prompts:
30 + # defaults:
31 + # age: 'Select your age'
@@ -0,0 +1,12
1 + -# frozen_string_literal: true
2 + = simple_form_for(@<%= singular_table_name %>) do |f|
3 + = f.error_notification
4 + = f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
5 +
6 + .form-inputs
7 + <%- attributes.each do |attribute| -%>
8 + = f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %>
9 + <%- end -%>
10 +
11 + .form-actions
12 + = f.button :submit
@@ -0,0 +1,5
1 + require "test_helper"
2 +
3 + class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4 + driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
5 + end
@@ -0,0 +1,37
1 + require "application_system_test_case"
2 +
3 + class AnnouncementsTest < ApplicationSystemTestCase
4 + test "add new announcement" do
5 + visit root_path
6 + fill_in "Login", with: "admin"
7 + fill_in "Password", with: "admin"
8 + click_on "Login"
9 +
10 + assert_text "MAIN"
11 + assert_text "Submission"
12 +
13 + within :css, 'header' do
14 + click_on "Manage"
15 + click_on "Announcements"
16 + end
17 + assert_text "+ Add announcement"
18 +
19 + click_on "Add announcement", match: :first
20 +
21 + fill_in 'Title', with: 'test'
22 + fill_in 'Body', with: 'test body 12345'
23 + check 'Published'
24 +
25 + click_on 'Create'
26 +
27 + visit list_main_path
28 +
29 + assert_text "test body 12345"
30 +
31 + end
32 + # test "visiting the index" do
33 + # visit announcements_url
34 + #
35 + # assert_selector "h1", text: "Announcement"
36 + # end
37 + end
@@ -1,115 +1,116
1 source 'https://rubygems.org'
1 source 'https://rubygems.org'
2 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
2 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
3
4 #rails
4 #rails
5 gem 'rails', '~>5.2'
5 gem 'rails', '~>5.2'
6 gem 'activerecord-session_store'
6 gem 'activerecord-session_store'
7 gem 'puma'
7 gem 'puma'
8
8
9 # Reduces boot times through caching; required in config/boot.rb
9 # Reduces boot times through caching; required in config/boot.rb
10 gem 'bootsnap', '>= 1.1.0', require: false
10 gem 'bootsnap', '>= 1.1.0', require: false
11
11
12 # Bundle edge Rails instead:
12 # Bundle edge Rails instead:
13 # gem 'rails', :git => 'git://github.com/rails/rails.git'
13 # gem 'rails', :git => 'git://github.com/rails/rails.git'
14
14
15 #---------------- database ---------------------
15 #---------------- database ---------------------
16 #the database
16 #the database
17 gem 'mysql2'
17 gem 'mysql2'
18 #for testing
18 #for testing
19 gem 'sqlite3'
19 gem 'sqlite3'
20 gem 'rails-controller-testing'
20 gem 'rails-controller-testing'
21 #for dumping database into yaml
21 #for dumping database into yaml
22 gem 'yaml_db'
22 gem 'yaml_db'
23
23
24
24
25 #------------- assset pipeline -----------------
25 #------------- assset pipeline -----------------
26 # Gems used only for assets and not required
26 # Gems used only for assets and not required
27 # in production environments by default.
27 # in production environments by default.
28 #sass-rails is depricated
28 #sass-rails is depricated
29 #gem 'sass-rails'
29 #gem 'sass-rails'
30 gem 'sassc-rails'
30 gem 'sassc-rails'
31 gem 'coffee-rails'
31 gem 'coffee-rails'
32
32
33 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
33 # See https://github.com/sstephenson/execjs#readme for more supported runtimes
34 # gem 'therubyracer', :platforms => :ruby
34 # gem 'therubyracer', :platforms => :ruby
35
35
36 gem 'uglifier'
36 gem 'uglifier'
37
37
38 gem 'haml'
38 gem 'haml'
39 gem 'haml-rails'
39 gem 'haml-rails'
40
40
41 # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
41 # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
42 #gem 'turbolinks', '~> 5'
42 #gem 'turbolinks', '~> 5'
43 # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
43 # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
44 gem 'jbuilder', '~> 2.5'
44 gem 'jbuilder', '~> 2.5'
45
45
46
46
47 #in-place editor
47 #in-place editor
48 gem 'best_in_place', '~> 3.0.1'
48 gem 'best_in_place', '~> 3.0.1'
49
49
50 # jquery addition
50 # jquery addition
51 gem 'jquery-rails'
51 gem 'jquery-rails'
52 gem 'jquery-ui-rails'
52 gem 'jquery-ui-rails'
53 gem 'jquery-timepicker-addon-rails'
53 gem 'jquery-timepicker-addon-rails'
54 gem 'jquery-tablesorter'
54 gem 'jquery-tablesorter'
55 gem 'jquery-countdown-rails'
55 gem 'jquery-countdown-rails'
56
56
57 #syntax highlighter
57 #syntax highlighter
58 gem 'rouge'
58 gem 'rouge'
59
59
60 #bootstrap add-ons
60 #bootstrap add-ons
61 gem 'bootstrap-sass', '~> 3.4.1'
61 gem 'bootstrap-sass', '~> 3.4.1'
62 gem 'bootstrap-switch-rails'
62 gem 'bootstrap-switch-rails'
63 gem 'bootstrap-toggle-rails'
63 gem 'bootstrap-toggle-rails'
64 gem 'autoprefixer-rails'
64 gem 'autoprefixer-rails'
65 gem 'momentjs-rails'
65 gem 'momentjs-rails'
66 gem 'rails_bootstrap_sortable'
66 gem 'rails_bootstrap_sortable'
67 gem 'bootstrap-datepicker-rails'
67 gem 'bootstrap-datepicker-rails'
68 gem 'bootstrap3-datetimepicker-rails'
68 gem 'bootstrap3-datetimepicker-rails'
69 gem 'jquery-datatables-rails'
69 gem 'jquery-datatables-rails'
70
70
71 #----------- user interface -----------------
71 #----------- user interface -----------------
72 + gem 'simple_form'
72 #select 2
73 #select 2
73 gem 'select2-rails'
74 gem 'select2-rails'
74 #ace editor
75 #ace editor
75 gem 'ace-rails-ap'
76 gem 'ace-rails-ap'
76 #paginator
77 #paginator
77 gem 'will_paginate', '~> 3.0.7'
78 gem 'will_paginate', '~> 3.0.7'
78
79
79 gem 'mail'
80 gem 'mail'
80 gem 'rdiscount'
81 gem 'rdiscount'
81 gem 'dynamic_form'
82 gem 'dynamic_form'
82 gem 'in_place_editing'
83 gem 'in_place_editing'
83 #gem 'verification', :git => 'https://github.com/sikachu/verification.git'
84 #gem 'verification', :git => 'https://github.com/sikachu/verification.git'
84
85
85
86
86 #---------------- testiing -----------------------
87 #---------------- testiing -----------------------
87 gem 'minitest-reporters'
88 gem 'minitest-reporters'
88
89
89 #---------------- for console --------------------
90 #---------------- for console --------------------
90 gem 'fuzzy-string-match'
91 gem 'fuzzy-string-match'
91
92
92
93
93 group :development, :test do
94 group :development, :test do
94 # Call 'byebug' anywhere in the code to stop execution and get a debugger console
95 # Call 'byebug' anywhere in the code to stop execution and get a debugger console
95 gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
96 gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
96 end
97 end
97
98
98 group :development do
99 group :development do
99 # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
100 # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
100 gem 'web-console', '>= 3.3.0'
101 gem 'web-console', '>= 3.3.0'
101 gem 'listen', '>= 3.0.5', '< 3.2'
102 gem 'listen', '>= 3.0.5', '< 3.2'
102 # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
103 # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
103 gem 'spring'
104 gem 'spring'
104 gem 'spring-watcher-listen', '~> 2.0.0'
105 gem 'spring-watcher-listen', '~> 2.0.0'
105 end
106 end
106
107
107 group :test do
108 group :test do
108 # Adds support for Capybara system testing and selenium driver
109 # Adds support for Capybara system testing and selenium driver
109 gem 'capybara', '>= 2.15'
110 gem 'capybara', '>= 2.15'
110 gem 'selenium-webdriver'
111 gem 'selenium-webdriver'
111 # Easy installation and use of chromedriver to run system tests with Chrome
112 # Easy installation and use of chromedriver to run system tests with Chrome
112 #gem 'chromedriver-helper'
113 #gem 'chromedriver-helper'
113 gem 'webdriver'
114 gem 'webdriver'
114 end
115 end
115
116
@@ -148,186 +148,190
148 mail (2.7.1)
148 mail (2.7.1)
149 mini_mime (>= 0.1.1)
149 mini_mime (>= 0.1.1)
150 marcel (0.3.3)
150 marcel (0.3.3)
151 mimemagic (~> 0.3.2)
151 mimemagic (~> 0.3.2)
152 method_source (0.9.2)
152 method_source (0.9.2)
153 mimemagic (0.3.3)
153 mimemagic (0.3.3)
154 mini_mime (1.0.1)
154 mini_mime (1.0.1)
155 mini_portile2 (2.4.0)
155 mini_portile2 (2.4.0)
156 minitest (5.11.3)
156 minitest (5.11.3)
157 minitest-reporters (1.3.6)
157 minitest-reporters (1.3.6)
158 ansi
158 ansi
159 builder
159 builder
160 minitest (>= 5.0)
160 minitest (>= 5.0)
161 ruby-progressbar
161 ruby-progressbar
162 momentjs-rails (2.20.1)
162 momentjs-rails (2.20.1)
163 railties (>= 3.1)
163 railties (>= 3.1)
164 msgpack (1.3.0)
164 msgpack (1.3.0)
165 multi_json (1.13.1)
165 multi_json (1.13.1)
166 mysql2 (0.5.2)
166 mysql2 (0.5.2)
167 nio4r (2.3.1)
167 nio4r (2.3.1)
168 nokogiri (1.10.3)
168 nokogiri (1.10.3)
169 mini_portile2 (~> 2.4.0)
169 mini_portile2 (~> 2.4.0)
170 public_suffix (3.1.1)
170 public_suffix (3.1.1)
171 puma (4.0.0)
171 puma (4.0.0)
172 nio4r (~> 2.0)
172 nio4r (~> 2.0)
173 rack (2.0.7)
173 rack (2.0.7)
174 rack-test (1.1.0)
174 rack-test (1.1.0)
175 rack (>= 1.0, < 3)
175 rack (>= 1.0, < 3)
176 rails (5.2.3)
176 rails (5.2.3)
177 actioncable (= 5.2.3)
177 actioncable (= 5.2.3)
178 actionmailer (= 5.2.3)
178 actionmailer (= 5.2.3)
179 actionpack (= 5.2.3)
179 actionpack (= 5.2.3)
180 actionview (= 5.2.3)
180 actionview (= 5.2.3)
181 activejob (= 5.2.3)
181 activejob (= 5.2.3)
182 activemodel (= 5.2.3)
182 activemodel (= 5.2.3)
183 activerecord (= 5.2.3)
183 activerecord (= 5.2.3)
184 activestorage (= 5.2.3)
184 activestorage (= 5.2.3)
185 activesupport (= 5.2.3)
185 activesupport (= 5.2.3)
186 bundler (>= 1.3.0)
186 bundler (>= 1.3.0)
187 railties (= 5.2.3)
187 railties (= 5.2.3)
188 sprockets-rails (>= 2.0.0)
188 sprockets-rails (>= 2.0.0)
189 rails-controller-testing (1.0.4)
189 rails-controller-testing (1.0.4)
190 actionpack (>= 5.0.1.x)
190 actionpack (>= 5.0.1.x)
191 actionview (>= 5.0.1.x)
191 actionview (>= 5.0.1.x)
192 activesupport (>= 5.0.1.x)
192 activesupport (>= 5.0.1.x)
193 rails-dom-testing (2.0.3)
193 rails-dom-testing (2.0.3)
194 activesupport (>= 4.2.0)
194 activesupport (>= 4.2.0)
195 nokogiri (>= 1.6)
195 nokogiri (>= 1.6)
196 rails-html-sanitizer (1.0.4)
196 rails-html-sanitizer (1.0.4)
197 loofah (~> 2.2, >= 2.2.2)
197 loofah (~> 2.2, >= 2.2.2)
198 rails_bootstrap_sortable (2.0.6)
198 rails_bootstrap_sortable (2.0.6)
199 momentjs-rails (>= 2.8.3)
199 momentjs-rails (>= 2.8.3)
200 railties (5.2.3)
200 railties (5.2.3)
201 actionpack (= 5.2.3)
201 actionpack (= 5.2.3)
202 activesupport (= 5.2.3)
202 activesupport (= 5.2.3)
203 method_source
203 method_source
204 rake (>= 0.8.7)
204 rake (>= 0.8.7)
205 thor (>= 0.19.0, < 2.0)
205 thor (>= 0.19.0, < 2.0)
206 rake (12.3.2)
206 rake (12.3.2)
207 rb-fsevent (0.10.3)
207 rb-fsevent (0.10.3)
208 rb-inotify (0.10.0)
208 rb-inotify (0.10.0)
209 ffi (~> 1.0)
209 ffi (~> 1.0)
210 rdiscount (2.2.0.1)
210 rdiscount (2.2.0.1)
211 regexp_parser (1.5.1)
211 regexp_parser (1.5.1)
212 rouge (3.3.0)
212 rouge (3.3.0)
213 ruby-progressbar (1.10.0)
213 ruby-progressbar (1.10.0)
214 ruby_dep (1.5.0)
214 ruby_dep (1.5.0)
215 ruby_parser (3.13.1)
215 ruby_parser (3.13.1)
216 sexp_processor (~> 4.9)
216 sexp_processor (~> 4.9)
217 rubyzip (1.2.3)
217 rubyzip (1.2.3)
218 sass (3.7.4)
218 sass (3.7.4)
219 sass-listen (~> 4.0.0)
219 sass-listen (~> 4.0.0)
220 sass-listen (4.0.0)
220 sass-listen (4.0.0)
221 rb-fsevent (~> 0.9, >= 0.9.4)
221 rb-fsevent (~> 0.9, >= 0.9.4)
222 rb-inotify (~> 0.9, >= 0.9.7)
222 rb-inotify (~> 0.9, >= 0.9.7)
223 sass-rails (5.0.7)
223 sass-rails (5.0.7)
224 railties (>= 4.0.0, < 6)
224 railties (>= 4.0.0, < 6)
225 sass (~> 3.1)
225 sass (~> 3.1)
226 sprockets (>= 2.8, < 4.0)
226 sprockets (>= 2.8, < 4.0)
227 sprockets-rails (>= 2.0, < 4.0)
227 sprockets-rails (>= 2.0, < 4.0)
228 tilt (>= 1.1, < 3)
228 tilt (>= 1.1, < 3)
229 sassc (2.0.1)
229 sassc (2.0.1)
230 ffi (~> 1.9)
230 ffi (~> 1.9)
231 rake
231 rake
232 sassc-rails (2.1.1)
232 sassc-rails (2.1.1)
233 railties (>= 4.0.0)
233 railties (>= 4.0.0)
234 sassc (>= 2.0)
234 sassc (>= 2.0)
235 sprockets (> 3.0)
235 sprockets (> 3.0)
236 sprockets-rails
236 sprockets-rails
237 tilt
237 tilt
238 select2-rails (4.0.3)
238 select2-rails (4.0.3)
239 thor (~> 0.14)
239 thor (~> 0.14)
240 selenium-webdriver (3.142.3)
240 selenium-webdriver (3.142.3)
241 childprocess (>= 0.5, < 2.0)
241 childprocess (>= 0.5, < 2.0)
242 rubyzip (~> 1.2, >= 1.2.2)
242 rubyzip (~> 1.2, >= 1.2.2)
243 sexp_processor (4.12.0)
243 sexp_processor (4.12.0)
244 + simple_form (4.1.0)
245 + actionpack (>= 5.0)
246 + activemodel (>= 5.0)
244 spring (2.1.0)
247 spring (2.1.0)
245 spring-watcher-listen (2.0.1)
248 spring-watcher-listen (2.0.1)
246 listen (>= 2.7, < 4.0)
249 listen (>= 2.7, < 4.0)
247 spring (>= 1.2, < 3.0)
250 spring (>= 1.2, < 3.0)
248 sprockets (3.7.2)
251 sprockets (3.7.2)
249 concurrent-ruby (~> 1.0)
252 concurrent-ruby (~> 1.0)
250 rack (> 1, < 3)
253 rack (> 1, < 3)
251 sprockets-rails (3.2.1)
254 sprockets-rails (3.2.1)
252 actionpack (>= 4.0)
255 actionpack (>= 4.0)
253 activesupport (>= 4.0)
256 activesupport (>= 4.0)
254 sprockets (>= 3.0.0)
257 sprockets (>= 3.0.0)
255 sqlite3 (1.4.1)
258 sqlite3 (1.4.1)
256 temple (0.8.1)
259 temple (0.8.1)
257 thor (0.20.3)
260 thor (0.20.3)
258 thread_safe (0.3.6)
261 thread_safe (0.3.6)
259 tilt (2.0.9)
262 tilt (2.0.9)
260 tzinfo (1.2.5)
263 tzinfo (1.2.5)
261 thread_safe (~> 0.1)
264 thread_safe (~> 0.1)
262 uglifier (4.1.20)
265 uglifier (4.1.20)
263 execjs (>= 0.3.0, < 3)
266 execjs (>= 0.3.0, < 3)
264 web-console (3.7.0)
267 web-console (3.7.0)
265 actionview (>= 5.0)
268 actionview (>= 5.0)
266 activemodel (>= 5.0)
269 activemodel (>= 5.0)
267 bindex (>= 0.4.0)
270 bindex (>= 0.4.0)
268 railties (>= 5.0)
271 railties (>= 5.0)
269 webdriver (0.1.0)
272 webdriver (0.1.0)
270 websocket-driver (0.7.1)
273 websocket-driver (0.7.1)
271 websocket-extensions (>= 0.1.0)
274 websocket-extensions (>= 0.1.0)
272 websocket-extensions (0.1.4)
275 websocket-extensions (0.1.4)
273 will_paginate (3.0.12)
276 will_paginate (3.0.12)
274 xpath (3.2.0)
277 xpath (3.2.0)
275 nokogiri (~> 1.8)
278 nokogiri (~> 1.8)
276 yaml_db (0.7.0)
279 yaml_db (0.7.0)
277 rails (>= 3.0)
280 rails (>= 3.0)
278 rake (>= 0.8.7)
281 rake (>= 0.8.7)
279
282
280 PLATFORMS
283 PLATFORMS
281 ruby
284 ruby
282
285
283 DEPENDENCIES
286 DEPENDENCIES
284 ace-rails-ap
287 ace-rails-ap
285 activerecord-session_store
288 activerecord-session_store
286 autoprefixer-rails
289 autoprefixer-rails
287 best_in_place (~> 3.0.1)
290 best_in_place (~> 3.0.1)
288 bootsnap (>= 1.1.0)
291 bootsnap (>= 1.1.0)
289 bootstrap-datepicker-rails
292 bootstrap-datepicker-rails
290 bootstrap-sass (~> 3.4.1)
293 bootstrap-sass (~> 3.4.1)
291 bootstrap-switch-rails
294 bootstrap-switch-rails
292 bootstrap-toggle-rails
295 bootstrap-toggle-rails
293 bootstrap3-datetimepicker-rails
296 bootstrap3-datetimepicker-rails
294 byebug
297 byebug
295 capybara (>= 2.15)
298 capybara (>= 2.15)
296 coffee-rails
299 coffee-rails
297 dynamic_form
300 dynamic_form
298 fuzzy-string-match
301 fuzzy-string-match
299 haml
302 haml
300 haml-rails
303 haml-rails
301 in_place_editing
304 in_place_editing
302 jbuilder (~> 2.5)
305 jbuilder (~> 2.5)
303 jquery-countdown-rails
306 jquery-countdown-rails
304 jquery-datatables-rails
307 jquery-datatables-rails
305 jquery-rails
308 jquery-rails
306 jquery-tablesorter
309 jquery-tablesorter
307 jquery-timepicker-addon-rails
310 jquery-timepicker-addon-rails
308 jquery-ui-rails
311 jquery-ui-rails
309 listen (>= 3.0.5, < 3.2)
312 listen (>= 3.0.5, < 3.2)
310 mail
313 mail
311 minitest-reporters
314 minitest-reporters
312 momentjs-rails
315 momentjs-rails
313 mysql2
316 mysql2
314 puma
317 puma
315 rails (~> 5.2)
318 rails (~> 5.2)
316 rails-controller-testing
319 rails-controller-testing
317 rails_bootstrap_sortable
320 rails_bootstrap_sortable
318 rdiscount
321 rdiscount
319 rouge
322 rouge
320 sassc-rails
323 sassc-rails
321 select2-rails
324 select2-rails
322 selenium-webdriver
325 selenium-webdriver
326 + simple_form
323 spring
327 spring
324 spring-watcher-listen (~> 2.0.0)
328 spring-watcher-listen (~> 2.0.0)
325 sqlite3
329 sqlite3
326 uglifier
330 uglifier
327 web-console (>= 3.3.0)
331 web-console (>= 3.3.0)
328 webdriver
332 webdriver
329 will_paginate (~> 3.0.7)
333 will_paginate (~> 3.0.7)
330 yaml_db
334 yaml_db
331
335
332 BUNDLED WITH
336 BUNDLED WITH
333 1.17.2
337 1.17.2
@@ -1,93 +1,86
1 class GradersController < ApplicationController
1 class GradersController < ApplicationController
2
2
3 before_action :admin_authorization
3 before_action :admin_authorization
4
4
5 - verify :method => :post, :only => ['clear_all',
6 - 'start_exam',
7 - 'start_grading',
8 - 'stop_all',
9 - 'clear_terminated'],
10 - :redirect_to => {:action => 'index'}
11 -
12 def index
5 def index
13 redirect_to :action => 'list'
6 redirect_to :action => 'list'
14 end
7 end
15
8
16 def list
9 def list
17 @grader_processes = GraderProcess.find_running_graders
10 @grader_processes = GraderProcess.find_running_graders
18 @stalled_processes = GraderProcess.find_stalled_process
11 @stalled_processes = GraderProcess.find_stalled_process
19
12
20 @terminated_processes = GraderProcess.find_terminated_graders
13 @terminated_processes = GraderProcess.find_terminated_graders
21
14
22 @last_task = Task.last
15 @last_task = Task.last
23 @last_test_request = TestRequest.last
16 @last_test_request = TestRequest.last
24 @submission = Submission.order("id desc").limit(20)
17 @submission = Submission.order("id desc").limit(20)
25 @backlog_submission = Submission.where('graded_at is null')
18 @backlog_submission = Submission.where('graded_at is null')
26 end
19 end
27
20
28 def clear
21 def clear
29 grader_proc = GraderProcess.find(params[:id])
22 grader_proc = GraderProcess.find(params[:id])
30 grader_proc.destroy if grader_proc!=nil
23 grader_proc.destroy if grader_proc!=nil
31 redirect_to :action => 'list'
24 redirect_to :action => 'list'
32 end
25 end
33
26
34 def clear_terminated
27 def clear_terminated
35 GraderProcess.find_terminated_graders.each do |p|
28 GraderProcess.find_terminated_graders.each do |p|
36 p.destroy
29 p.destroy
37 end
30 end
38 redirect_to :action => 'list'
31 redirect_to :action => 'list'
39 end
32 end
40
33
41 def clear_all
34 def clear_all
42 GraderProcess.all.each do |p|
35 GraderProcess.all.each do |p|
43 p.destroy
36 p.destroy
44 end
37 end
45 redirect_to :action => 'list'
38 redirect_to :action => 'list'
46 end
39 end
47
40
48 def view
41 def view
49 if params[:type]=='Task'
42 if params[:type]=='Task'
50 redirect_to :action => 'task', :id => params[:id]
43 redirect_to :action => 'task', :id => params[:id]
51 else
44 else
52 redirect_to :action => 'test_request', :id => params[:id]
45 redirect_to :action => 'test_request', :id => params[:id]
53 end
46 end
54 end
47 end
55
48
56 def test_request
49 def test_request
57 @test_request = TestRequest.find(params[:id])
50 @test_request = TestRequest.find(params[:id])
58 end
51 end
59
52
60 def task
53 def task
61 @task = Task.find(params[:id])
54 @task = Task.find(params[:id])
62 end
55 end
63
56
64
57
65 # various grader controls
58 # various grader controls
66
59
67 def stop
60 def stop
68 grader_proc = GraderProcess.find(params[:id])
61 grader_proc = GraderProcess.find(params[:id])
69 GraderScript.stop_grader(grader_proc.pid)
62 GraderScript.stop_grader(grader_proc.pid)
70 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
63 flash[:notice] = 'Grader stopped. It may not disappear now, but it should disappear shortly.'
71 redirect_to :action => 'list'
64 redirect_to :action => 'list'
72 end
65 end
73
66
74 def stop_all
67 def stop_all
75 GraderScript.stop_graders(GraderProcess.find_running_graders +
68 GraderScript.stop_graders(GraderProcess.find_running_graders +
76 GraderProcess.find_stalled_process)
69 GraderProcess.find_stalled_process)
77 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
70 flash[:notice] = 'Graders stopped. They may not disappear now, but they should disappear shortly.'
78 redirect_to :action => 'list'
71 redirect_to :action => 'list'
79 end
72 end
80
73
81 def start_grading
74 def start_grading
82 GraderScript.start_grader('grading')
75 GraderScript.start_grader('grading')
83 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
76 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
84 redirect_to :action => 'list'
77 redirect_to :action => 'list'
85 end
78 end
86
79
87 def start_exam
80 def start_exam
88 GraderScript.start_grader('exam')
81 GraderScript.start_grader('exam')
89 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
82 flash[:notice] = '2 graders in grading env started, one for grading queue tasks, another for grading test request'
90 redirect_to :action => 'list'
83 redirect_to :action => 'list'
91 end
84 end
92
85
93 end
86 end
@@ -1,122 +1,113
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_action :authenticate, :except => [:index, :login]
3 before_action :authenticate, :except => [:index, :login]
4 before_action :check_viewability, :except => [:index, :login]
4 before_action :check_viewability, :except => [:index, :login]
5
5
6 append_before_action :confirm_and_update_start_time,
6 append_before_action :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
13 prepend_before_action :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 before_action :authenticate_by_ip_address, :only => [:list]
16 before_action :authenticate_by_ip_address, :only => [:list]
17
17
18 - # COMMENTED OUT: filter in each action instead
19 - # before_filter :verify_time_limit, :only => [:submit]
20 -
21 - verify :method => :post, :only => [:submit],
22 - :redirect_to => { :action => :index }
23 -
24 - # COMMENT OUT: only need when having high load
25 - # caches_action :index, :login
26 -
27 # NOTE: This method is not actually needed, 'config/routes.rb' has
18 # NOTE: This method is not actually needed, 'config/routes.rb' has
28 # assigned action login as a default action.
19 # assigned action login as a default action.
29 def index
20 def index
30 redirect_to :action => 'login'
21 redirect_to :action => 'login'
31 end
22 end
32
23
33 def login
24 def login
34 saved_notice = flash[:notice]
25 saved_notice = flash[:notice]
35 reset_session
26 reset_session
36 flash.now[:notice] = saved_notice
27 flash.now[:notice] = saved_notice
37
28
38 # EXPERIMENT:
29 # EXPERIMENT:
39 # Hide login if in single user mode and the url does not
30 # Hide login if in single user mode and the url does not
40 # explicitly specify /login
31 # explicitly specify /login
41 #
32 #
42 # logger.info "PATH: #{request.path}"
33 # logger.info "PATH: #{request.path}"
43 # if GraderConfiguration['system.single_user_mode'] and
34 # if GraderConfiguration['system.single_user_mode'] and
44 # request.path!='/main/login'
35 # request.path!='/main/login'
45 # @hidelogin = true
36 # @hidelogin = true
46 # end
37 # end
47
38
48 @announcements = Announcement.frontpage
39 @announcements = Announcement.frontpage
49 render :action => 'login', :layout => 'empty'
40 render :action => 'login', :layout => 'empty'
50 end
41 end
51
42
52 def list
43 def list
53 prepare_list_information
44 prepare_list_information
54 end
45 end
55
46
56 def help
47 def help
57 @user = User.find(session[:user_id])
48 @user = User.find(session[:user_id])
58 end
49 end
59
50
60 def submit
51 def submit
61 user = User.find(session[:user_id])
52 user = User.find(session[:user_id])
62
53
63 @submission = Submission.new
54 @submission = Submission.new
64 @submission.problem_id = params[:submission][:problem_id]
55 @submission.problem_id = params[:submission][:problem_id]
65 @submission.user = user
56 @submission.user = user
66 @submission.language_id = 0
57 @submission.language_id = 0
67 if (params['file']) and (params['file']!='')
58 if (params['file']) and (params['file']!='')
68 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
59 @submission.source = File.open(params['file'].path,'r:UTF-8',&:read)
69 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
60 @submission.source.encode!('UTF-8','UTF-8',invalid: :replace, replace: '')
70 @submission.source_filename = params['file'].original_filename
61 @submission.source_filename = params['file'].original_filename
71 end
62 end
72
63
73 if (params[:editor_text])
64 if (params[:editor_text])
74 language = Language.find_by_id(params[:language_id])
65 language = Language.find_by_id(params[:language_id])
75 @submission.source = params[:editor_text]
66 @submission.source = params[:editor_text]
76 @submission.source_filename = "live_edit.#{language.ext}"
67 @submission.source_filename = "live_edit.#{language.ext}"
77 @submission.language = language
68 @submission.language = language
78 end
69 end
79
70
80 @submission.submitted_at = Time.new.gmtime
71 @submission.submitted_at = Time.new.gmtime
81 @submission.ip_address = request.remote_ip
72 @submission.ip_address = request.remote_ip
82
73
83 if GraderConfiguration.time_limit_mode? and user.contest_finished?
74 if GraderConfiguration.time_limit_mode? and user.contest_finished?
84 @submission.errors.add(:base,"The contest is over.")
75 @submission.errors.add(:base,"The contest is over.")
85 prepare_list_information
76 prepare_list_information
86 render :action => 'list' and return
77 render :action => 'list' and return
87 end
78 end
88
79
89 if @submission.valid?(@current_user)
80 if @submission.valid?(@current_user)
90 if @submission.save == false
81 if @submission.save == false
91 flash[:notice] = 'Error saving your submission'
82 flash[:notice] = 'Error saving your submission'
92 elsif Task.create(:submission_id => @submission.id,
83 elsif Task.create(:submission_id => @submission.id,
93 :status => Task::STATUS_INQUEUE) == false
84 :status => Task::STATUS_INQUEUE) == false
94 flash[:notice] = 'Error adding your submission to task queue'
85 flash[:notice] = 'Error adding your submission to task queue'
95 end
86 end
96 else
87 else
97 prepare_list_information
88 prepare_list_information
98 render :action => 'list' and return
89 render :action => 'list' and return
99 end
90 end
100 redirect_to edit_submission_path(@submission)
91 redirect_to edit_submission_path(@submission)
101 end
92 end
102
93
103 def source
94 def source
104 submission = Submission.find(params[:id])
95 submission = Submission.find(params[:id])
105 if ((submission.user_id == session[:user_id]) and
96 if ((submission.user_id == session[:user_id]) and
106 (submission.problem != nil) and
97 (submission.problem != nil) and
107 (submission.problem.available))
98 (submission.problem.available))
108 send_data(submission.source,
99 send_data(submission.source,
109 {:filename => submission.download_filename,
100 {:filename => submission.download_filename,
110 :type => 'text/plain'})
101 :type => 'text/plain'})
111 else
102 else
112 flash[:notice] = 'Error viewing source'
103 flash[:notice] = 'Error viewing source'
113 redirect_to :action => 'list'
104 redirect_to :action => 'list'
114 end
105 end
115 end
106 end
116
107
117 def compiler_msg
108 def compiler_msg
118 @submission = Submission.find(params[:id])
109 @submission = Submission.find(params[:id])
119 if @submission.user_id == session[:user_id]
110 if @submission.user_id == session[:user_id]
120 render :action => 'compiler_msg', :layout => 'empty'
111 render :action => 'compiler_msg', :layout => 'empty'
121 else
112 else
122 flash[:notice] = 'Error viewing source'
113 flash[:notice] = 'Error viewing source'
@@ -1,86 +1,84
1 class MessagesController < ApplicationController
1 class MessagesController < ApplicationController
2
2
3 before_action :authenticate
3 before_action :authenticate
4
4
5 - verify :method => :post, :only => ['create'],
6 - :redirect_to => { :action => 'list' }
7
5
8 before_filter :admin_authorization, :only => ['console','show',
6 before_filter :admin_authorization, :only => ['console','show',
9 'reply','hide','list_all']
7 'reply','hide','list_all']
10
8
11 def list
9 def list
12 @user = User.find(session[:user_id])
10 @user = User.find(session[:user_id])
13 @messages = Message.find_all_sent_by_user(@user)
11 @messages = Message.find_all_sent_by_user(@user)
14 end
12 end
15
13
16 def console
14 def console
17 @user = User.find(session[:user_id])
15 @user = User.find(session[:user_id])
18 @messages = Message.find_all_system_unreplied_messages
16 @messages = Message.find_all_system_unreplied_messages
19 end
17 end
20
18
21 def show
19 def show
22 @message = Message.find(params[:id])
20 @message = Message.find(params[:id])
23 end
21 end
24
22
25 def list_all
23 def list_all
26 @user = User.find(session[:user_id])
24 @user = User.find(session[:user_id])
27 @messages = Message.where(receiver_id: nil).order(:created_at)
25 @messages = Message.where(receiver_id: nil).order(:created_at)
28 end
26 end
29
27
30 def create
28 def create
31 user = User.find(session[:user_id])
29 user = User.find(session[:user_id])
32 @message = Message.new(params[:message])
30 @message = Message.new(params[:message])
33 @message.sender = user
31 @message.sender = user
34 if @message.body == '' or !@message.save
32 if @message.body == '' or !@message.save
35 flash[:notice] = 'An error occurred'
33 flash[:notice] = 'An error occurred'
36 else
34 else
37 flash[:notice] = 'New message posted'
35 flash[:notice] = 'New message posted'
38 end
36 end
39 redirect_to :action => 'list'
37 redirect_to :action => 'list'
40 end
38 end
41
39
42 def reply
40 def reply
43 user = User.find(session[:user_id])
41 user = User.find(session[:user_id])
44 @message = Message.new(params[:r_message])
42 @message = Message.new(params[:r_message])
45 @message.sender = user
43 @message.sender = user
46 if @message.body == '' or !@message.save
44 if @message.body == '' or !@message.save
47 flash[:notice] = 'An error occurred'
45 flash[:notice] = 'An error occurred'
48 redirect_to :action => 'show', :id => @message.replying_message_id
46 redirect_to :action => 'show', :id => @message.replying_message_id
49 else
47 else
50 flash[:notice] = 'Message replied'
48 flash[:notice] = 'Message replied'
51 rep_msg = @message.replying_message
49 rep_msg = @message.replying_message
52 rep_msg.replied = true
50 rep_msg.replied = true
53 rep_msg.save
51 rep_msg.save
54 redirect_to :action => 'console'
52 redirect_to :action => 'console'
55 end
53 end
56 end
54 end
57
55
58 def hide
56 def hide
59 message = Message.find(params[:id])
57 message = Message.find(params[:id])
60 message.replied = true
58 message.replied = true
61 message.save
59 message.save
62 flash[:notice] = 'Message hidden (just marked replied)'
60 flash[:notice] = 'Message hidden (just marked replied)'
63 redirect_to :action => 'console'
61 redirect_to :action => 'console'
64 end
62 end
65
63
66 protected
64 protected
67 def build_replying_message_hierarchy(user)
65 def build_replying_message_hierarchy(user)
68 @all_messages = {}
66 @all_messages = {}
69
67
70
68
71 # manually build replies hierarchy (to improve efficiency)
69 # manually build replies hierarchy (to improve efficiency)
72 [@messages, @replied_messages].each do |collection|
70 [@messages, @replied_messages].each do |collection|
73 collection.each do |m|
71 collection.each do |m|
74 @all_messages[m.id] = {:msg => m, :replies => []}
72 @all_messages[m.id] = {:msg => m, :replies => []}
75 end
73 end
76 end
74 end
77
75
78 @all_messages.each do |m|
76 @all_messages.each do |m|
79 rep_id = m.replying_message_id
77 rep_id = m.replying_message_id
80 if @all_messages[rep_id]!=nil
78 if @all_messages[rep_id]!=nil
81 @all_messages[rep_id][:replies] << m
79 @all_messages[rep_id][:replies] << m
82 end
80 end
83 end
81 end
84 end
82 end
85
83
86 end
84 end
@@ -1,128 +1,122
1 class ProblemsController < ApplicationController
1 class ProblemsController < ApplicationController
2
2
3 before_action :authenticate, :authorization
3 before_action :authenticate, :authorization
4 before_action :testcase_authorization, only: [:show_testcase]
4 before_action :testcase_authorization, only: [:show_testcase]
5
5
6 in_place_edit_for :problem, :name
6 in_place_edit_for :problem, :name
7 in_place_edit_for :problem, :full_name
7 in_place_edit_for :problem, :full_name
8 in_place_edit_for :problem, :full_score
8 in_place_edit_for :problem, :full_score
9
9
10 def index
10 def index
11 @problems = Problem.order(date_added: :desc)
11 @problems = Problem.order(date_added: :desc)
12 end
12 end
13
13
14 - # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
15 - verify :method => :post, :only => [ :create, :quick_create,
16 - :do_manage,
17 - :do_import,
18 - ],
19 - :redirect_to => { :action => :index }
20
14
21 def show
15 def show
22 @problem = Problem.find(params[:id])
16 @problem = Problem.find(params[:id])
23 end
17 end
24
18
25 def new
19 def new
26 @problem = Problem.new
20 @problem = Problem.new
27 @description = nil
21 @description = nil
28 end
22 end
29
23
30 def create
24 def create
31 @problem = Problem.new(problem_params)
25 @problem = Problem.new(problem_params)
32 - @description = Description.new(params[:description])
26 + @description = Description.new(problem_params[:description])
33 if @description.body!=''
27 if @description.body!=''
34 if !@description.save
28 if !@description.save
35 render :action => new and return
29 render :action => new and return
36 end
30 end
37 else
31 else
38 @description = nil
32 @description = nil
39 end
33 end
40 @problem.description = @description
34 @problem.description = @description
41 if @problem.save
35 if @problem.save
42 flash[:notice] = 'Problem was successfully created.'
36 flash[:notice] = 'Problem was successfully created.'
43 redirect_to action: :index
37 redirect_to action: :index
44 else
38 else
45 render :action => 'new'
39 render :action => 'new'
46 end
40 end
47 end
41 end
48
42
49 def quick_create
43 def quick_create
50 @problem = Problem.new(problem_params)
44 @problem = Problem.new(problem_params)
51 @problem.full_name = @problem.name if @problem.full_name == ''
45 @problem.full_name = @problem.name if @problem.full_name == ''
52 @problem.full_score = 100
46 @problem.full_score = 100
53 @problem.available = false
47 @problem.available = false
54 @problem.test_allowed = true
48 @problem.test_allowed = true
55 @problem.output_only = false
49 @problem.output_only = false
56 @problem.date_added = Time.new
50 @problem.date_added = Time.new
57 if @problem.save
51 if @problem.save
58 flash[:notice] = 'Problem was successfully created.'
52 flash[:notice] = 'Problem was successfully created.'
59 redirect_to action: :index
53 redirect_to action: :index
60 else
54 else
61 flash[:notice] = 'Error saving problem'
55 flash[:notice] = 'Error saving problem'
62 redirect_to action: :index
56 redirect_to action: :index
63 end
57 end
64 end
58 end
65
59
66 def edit
60 def edit
67 @problem = Problem.find(params[:id])
61 @problem = Problem.find(params[:id])
68 @description = @problem.description
62 @description = @problem.description
69 end
63 end
70
64
71 def update
65 def update
72 @problem = Problem.find(params[:id])
66 @problem = Problem.find(params[:id])
73 @description = @problem.description
67 @description = @problem.description
74 if @description.nil? and params[:description][:body]!=''
68 if @description.nil? and params[:description][:body]!=''
75 @description = Description.new(params[:description])
69 @description = Description.new(params[:description])
76 if !@description.save
70 if !@description.save
77 flash[:notice] = 'Error saving description'
71 flash[:notice] = 'Error saving description'
78 render :action => 'edit' and return
72 render :action => 'edit' and return
79 end
73 end
80 @problem.description = @description
74 @problem.description = @description
81 elsif @description
75 elsif @description
82 if !@description.update_attributes(params[:description])
76 if !@description.update_attributes(params[:description])
83 flash[:notice] = 'Error saving description'
77 flash[:notice] = 'Error saving description'
84 render :action => 'edit' and return
78 render :action => 'edit' and return
85 end
79 end
86 end
80 end
87 if params[:file] and params[:file].content_type != 'application/pdf'
81 if params[:file] and params[:file].content_type != 'application/pdf'
88 flash[:notice] = 'Error: Uploaded file is not PDF'
82 flash[:notice] = 'Error: Uploaded file is not PDF'
89 render :action => 'edit' and return
83 render :action => 'edit' and return
90 end
84 end
91 if @problem.update_attributes(problem_params)
85 if @problem.update_attributes(problem_params)
92 flash[:notice] = 'Problem was successfully updated.'
86 flash[:notice] = 'Problem was successfully updated.'
93 unless params[:file] == nil or params[:file] == ''
87 unless params[:file] == nil or params[:file] == ''
94 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
88 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
95 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
89 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
96 if not FileTest.exists? out_dirname
90 if not FileTest.exists? out_dirname
97 Dir.mkdir out_dirname
91 Dir.mkdir out_dirname
98 end
92 end
99
93
100 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
94 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
101 if FileTest.exists? out_filename
95 if FileTest.exists? out_filename
102 File.delete out_filename
96 File.delete out_filename
103 end
97 end
104
98
105 File.open(out_filename,"wb") do |file|
99 File.open(out_filename,"wb") do |file|
106 file.write(params[:file].read)
100 file.write(params[:file].read)
107 end
101 end
108 @problem.description_filename = "#{@problem.name}.pdf"
102 @problem.description_filename = "#{@problem.name}.pdf"
109 @problem.save
103 @problem.save
110 end
104 end
111 redirect_to :action => 'show', :id => @problem
105 redirect_to :action => 'show', :id => @problem
112 else
106 else
113 render :action => 'edit'
107 render :action => 'edit'
114 end
108 end
115 end
109 end
116
110
117 def destroy
111 def destroy
118 p = Problem.find(params[:id]).destroy
112 p = Problem.find(params[:id]).destroy
119 redirect_to action: :index
113 redirect_to action: :index
120 end
114 end
121
115
122 def toggle
116 def toggle
123 @problem = Problem.find(params[:id])
117 @problem = Problem.find(params[:id])
124 @problem.update_attributes(available: !(@problem.available) )
118 @problem.update_attributes(available: !(@problem.available) )
125 respond_to do |format|
119 respond_to do |format|
126 format.js { }
120 format.js { }
127 end
121 end
128 end
122 end
@@ -1,107 +1,100
1 class TestController < ApplicationController
1 class TestController < ApplicationController
2
2
3 before_action :authenticate, :check_viewability
3 before_action :authenticate, :check_viewability
4
4
5 - #
6 - # COMMENT OUT: filter in each action instead
7 - #
8 - # before_filter :verify_time_limit, :only => [:submit]
9 -
10 - verify :method => :post, :only => [:submit],
11 - :redirect_to => { :action => :index }
12
5
13 def index
6 def index
14 prepare_index_information
7 prepare_index_information
15 end
8 end
16
9
17 def submit
10 def submit
18 @user = User.find(session[:user_id])
11 @user = User.find(session[:user_id])
19
12
20 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
13 @submitted_test_request = TestRequest.new_from_form_params(@user,params[:test_request])
21
14
22 if ! @submitted_test_request.errors.empty?
15 if ! @submitted_test_request.errors.empty?
23 prepare_index_information
16 prepare_index_information
24 render :action => 'index' and return
17 render :action => 'index' and return
25 end
18 end
26
19
27 if GraderConfiguration.time_limit_mode?
20 if GraderConfiguration.time_limit_mode?
28 if @user.contest_finished?
21 if @user.contest_finished?
29 @submitted_test_request.errors.add(:base,'Contest is over.')
22 @submitted_test_request.errors.add(:base,'Contest is over.')
30 prepare_index_information
23 prepare_index_information
31 render :action => 'index' and return
24 render :action => 'index' and return
32 end
25 end
33
26
34 if !GraderConfiguration.allow_test_request(@user)
27 if !GraderConfiguration.allow_test_request(@user)
35 prepare_index_information
28 prepare_index_information
36 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
29 flash[:notice] = 'Test request is not allowed during the last 30 minutes'
37 redirect_to :action => 'index' and return
30 redirect_to :action => 'index' and return
38 end
31 end
39 end
32 end
40
33
41 if @submitted_test_request.save
34 if @submitted_test_request.save
42 redirect_to :action => 'index'
35 redirect_to :action => 'index'
43 else
36 else
44 prepare_index_information
37 prepare_index_information
45 render :action => 'index'
38 render :action => 'index'
46 end
39 end
47 end
40 end
48
41
49 def read
42 def read
50 user = User.find(session[:user_id])
43 user = User.find(session[:user_id])
51 begin
44 begin
52 test_request = TestRequest.find(params[:id])
45 test_request = TestRequest.find(params[:id])
53 rescue
46 rescue
54 test_request = nil
47 test_request = nil
55 end
48 end
56 if test_request==nil or test_request.user_id != user.id
49 if test_request==nil or test_request.user_id != user.id
57 flash[:notice] = 'Invalid output'
50 flash[:notice] = 'Invalid output'
58 redirect_to :action => 'index'
51 redirect_to :action => 'index'
59 return
52 return
60 end
53 end
61 if test_request.output_file_name!=nil
54 if test_request.output_file_name!=nil
62 data = File.open(test_request.output_file_name).read(2048)
55 data = File.open(test_request.output_file_name).read(2048)
63 if data==nil
56 if data==nil
64 data=""
57 data=""
65 end
58 end
66 send_data(data,
59 send_data(data,
67 {:filename => 'output.txt',
60 {:filename => 'output.txt',
68 :type => 'text/plain'})
61 :type => 'text/plain'})
69 return
62 return
70 end
63 end
71 redirect_to :action => 'index'
64 redirect_to :action => 'index'
72 end
65 end
73
66
74 def result
67 def result
75 @user = User.find(session[:user_id])
68 @user = User.find(session[:user_id])
76 begin
69 begin
77 @test_request = TestRequest.find(params[:id])
70 @test_request = TestRequest.find(params[:id])
78 rescue
71 rescue
79 @test_request = nil
72 @test_request = nil
80 end
73 end
81 if @test_request==nil or @test_request.user_id != @user.id
74 if @test_request==nil or @test_request.user_id != @user.id
82 flash[:notice] = 'Invalid request'
75 flash[:notice] = 'Invalid request'
83 redirect_to :action => 'index'
76 redirect_to :action => 'index'
84 return
77 return
85 end
78 end
86 end
79 end
87
80
88 protected
81 protected
89
82
90 def prepare_index_information
83 def prepare_index_information
91 @user = User.find(session[:user_id])
84 @user = User.find(session[:user_id])
92 @submissions = Submission.find_last_for_all_available_problems(@user.id)
85 @submissions = Submission.find_last_for_all_available_problems(@user.id)
93 all_problems = @submissions.collect { |submission| submission.problem }
86 all_problems = @submissions.collect { |submission| submission.problem }
94 @problems = []
87 @problems = []
95 all_problems.each do |problem|
88 all_problems.each do |problem|
96 if problem.test_allowed
89 if problem.test_allowed
97 @problems << problem
90 @problems << problem
98 end
91 end
99 end
92 end
100 @test_requests = []
93 @test_requests = []
101 @user.test_requests.each do |ts|
94 @user.test_requests.each do |ts|
102 if ts.problem and ts.problem.available
95 if ts.problem and ts.problem.available
103 @test_requests << ts
96 @test_requests << ts
104 end
97 end
105 end
98 end
106 end
99 end
107
100
@@ -1,113 +1,104
1 require 'csv'
1 require 'csv'
2
2
3 class UserAdminController < ApplicationController
3 class UserAdminController < ApplicationController
4
4
5 include MailHelperMethods
5 include MailHelperMethods
6
6
7 before_action :admin_authorization
7 before_action :admin_authorization
8
8
9 - # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
10 - verify :method => :post, :only => [
11 - :create, :create_from_list,
12 - :update,
13 - :manage_contest,
14 - :bulk_mail
15 - ],
16 - :redirect_to => { :action => :list }
17 -
18 def index
9 def index
19 @user_count = User.count
10 @user_count = User.count
20 if params[:page] == 'all'
11 if params[:page] == 'all'
21 @users = User.all
12 @users = User.all
22 @paginated = false
13 @paginated = false
23 else
14 else
24 @users = User.paginate :page => params[:page]
15 @users = User.paginate :page => params[:page]
25 @paginated = true
16 @paginated = true
26 end
17 end
27 @users = User.all
18 @users = User.all
28 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
19 @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at']
29 @contests = Contest.enabled
20 @contests = Contest.enabled
30 end
21 end
31
22
32 def active
23 def active
33 sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago)
24 sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago)
34 @users = []
25 @users = []
35 sessions.each do |session|
26 sessions.each do |session|
36 if session.data[:user_id]
27 if session.data[:user_id]
37 @users << User.find(session.data[:user_id])
28 @users << User.find(session.data[:user_id])
38 end
29 end
39 end
30 end
40 end
31 end
41
32
42 def show
33 def show
43 @user = User.find(params[:id])
34 @user = User.find(params[:id])
44 end
35 end
45
36
46 def new
37 def new
47 @user = User.new
38 @user = User.new
48 end
39 end
49
40
50 def create
41 def create
51 @user = User.new(user_params)
42 @user = User.new(user_params)
52 @user.activated = true
43 @user.activated = true
53 if @user.save
44 if @user.save
54 flash[:notice] = 'User was successfully created.'
45 flash[:notice] = 'User was successfully created.'
55 redirect_to :action => 'index'
46 redirect_to :action => 'index'
56 else
47 else
57 render :action => 'new'
48 render :action => 'new'
58 end
49 end
59 end
50 end
60
51
61 def clear_last_ip
52 def clear_last_ip
62 @user = User.find(params[:id])
53 @user = User.find(params[:id])
63 @user.last_ip = nil
54 @user.last_ip = nil
64 @user.save
55 @user.save
65 redirect_to action: 'index', page: params[:page]
56 redirect_to action: 'index', page: params[:page]
66 end
57 end
67
58
68 def create_from_list
59 def create_from_list
69 lines = params[:user_list]
60 lines = params[:user_list]
70
61
71 note = []
62 note = []
72
63
73 lines.split("\n").each do |line|
64 lines.split("\n").each do |line|
74 items = line.chomp.split(',')
65 items = line.chomp.split(',')
75 if items.length>=2
66 if items.length>=2
76 login = items[0]
67 login = items[0]
77 full_name = items[1]
68 full_name = items[1]
78 remark =''
69 remark =''
79 user_alias = ''
70 user_alias = ''
80
71
81 added_random_password = false
72 added_random_password = false
82 if items.length >= 3 and items[2].chomp(" ").length > 0;
73 if items.length >= 3 and items[2].chomp(" ").length > 0;
83 password = items[2].chomp(" ")
74 password = items[2].chomp(" ")
84 else
75 else
85 password = random_password
76 password = random_password
86 add_random_password=true;
77 add_random_password=true;
87 end
78 end
88
79
89 if items.length>= 4 and items[3].chomp(" ").length > 0;
80 if items.length>= 4 and items[3].chomp(" ").length > 0;
90 user_alias = items[3].chomp(" ")
81 user_alias = items[3].chomp(" ")
91 else
82 else
92 user_alias = login
83 user_alias = login
93 end
84 end
94
85
95 if items.length>=5
86 if items.length>=5
96 remark = items[4].strip;
87 remark = items[4].strip;
97 end
88 end
98
89
99 user = User.find_by_login(login)
90 user = User.find_by_login(login)
100 if (user)
91 if (user)
101 user.full_name = full_name
92 user.full_name = full_name
102 user.password = password
93 user.password = password
103 user.remark = remark
94 user.remark = remark
104 else
95 else
105 user = User.new({:login => login,
96 user = User.new({:login => login,
106 :full_name => full_name,
97 :full_name => full_name,
107 :password => password,
98 :password => password,
108 :password_confirmation => password,
99 :password_confirmation => password,
109 :alias => user_alias,
100 :alias => user_alias,
110 :remark => remark})
101 :remark => remark})
111 end
102 end
112 user.activated = true
103 user.activated = true
113 user.save
104 user.save
@@ -1,120 +1,117
1 require 'net/smtp'
1 require 'net/smtp'
2
2
3 class UsersController < ApplicationController
3 class UsersController < ApplicationController
4
4
5 include MailHelperMethods
5 include MailHelperMethods
6
6
7 before_action :authenticate, :except => [:new,
7 before_action :authenticate, :except => [:new,
8 :register,
8 :register,
9 :confirm,
9 :confirm,
10 :forget,
10 :forget,
11 :retrieve_password]
11 :retrieve_password]
12
12
13 before_action :verify_online_registration, :only => [:new,
13 before_action :verify_online_registration, :only => [:new,
14 :register,
14 :register,
15 :forget,
15 :forget,
16 :retrieve_password]
16 :retrieve_password]
17 before_action :authenticate, :profile_authorization, only: [:profile]
17 before_action :authenticate, :profile_authorization, only: [:profile]
18
18
19 before_action :admin_authorization, only: [:stat, :toggle_activate, :toggle_enable]
19 before_action :admin_authorization, only: [:stat, :toggle_activate, :toggle_enable]
20
20
21
21
22 - verify :method => :post, :only => [:chg_passwd],
23 - :redirect_to => { :action => :index }
24 -
25 #in_place_edit_for :user, :alias_for_editing
22 #in_place_edit_for :user, :alias_for_editing
26 #in_place_edit_for :user, :email_for_editing
23 #in_place_edit_for :user, :email_for_editing
27
24
28 def index
25 def index
29 if !GraderConfiguration['system.user_setting_enabled']
26 if !GraderConfiguration['system.user_setting_enabled']
30 redirect_to :controller => 'main', :action => 'list'
27 redirect_to :controller => 'main', :action => 'list'
31 else
28 else
32 @user = User.find(session[:user_id])
29 @user = User.find(session[:user_id])
33 end
30 end
34 end
31 end
35
32
36 def chg_passwd
33 def chg_passwd
37 user = User.find(session[:user_id])
34 user = User.find(session[:user_id])
38 user.password = params[:passwd]
35 user.password = params[:passwd]
39 user.password_confirmation = params[:passwd_verify]
36 user.password_confirmation = params[:passwd_verify]
40 if user.save
37 if user.save
41 flash[:notice] = 'password changed'
38 flash[:notice] = 'password changed'
42 else
39 else
43 flash[:notice] = 'Error: password changing failed'
40 flash[:notice] = 'Error: password changing failed'
44 end
41 end
45 redirect_to :action => 'index'
42 redirect_to :action => 'index'
46 end
43 end
47
44
48 def new
45 def new
49 @user = User.new
46 @user = User.new
50 render :action => 'new', :layout => 'empty'
47 render :action => 'new', :layout => 'empty'
51 end
48 end
52
49
53 def register
50 def register
54 if(params[:cancel])
51 if(params[:cancel])
55 redirect_to :controller => 'main', :action => 'login'
52 redirect_to :controller => 'main', :action => 'login'
56 return
53 return
57 end
54 end
58 @user = User.new(user_params)
55 @user = User.new(user_params)
59 @user.password_confirmation = @user.password = User.random_password
56 @user.password_confirmation = @user.password = User.random_password
60 @user.activated = false
57 @user.activated = false
61 if (@user.valid?) and (@user.save)
58 if (@user.valid?) and (@user.save)
62 if send_confirmation_email(@user)
59 if send_confirmation_email(@user)
63 render :action => 'new_splash', :layout => 'empty'
60 render :action => 'new_splash', :layout => 'empty'
64 else
61 else
65 @admin_email = GraderConfiguration['system.admin_email']
62 @admin_email = GraderConfiguration['system.admin_email']
66 render :action => 'email_error', :layout => 'empty'
63 render :action => 'email_error', :layout => 'empty'
67 end
64 end
68 else
65 else
69 @user.errors.add(:base,"Email cannot be blank") if @user.email==''
66 @user.errors.add(:base,"Email cannot be blank") if @user.email==''
70 render :action => 'new', :layout => 'empty'
67 render :action => 'new', :layout => 'empty'
71 end
68 end
72 end
69 end
73
70
74 def confirm
71 def confirm
75 login = params[:login]
72 login = params[:login]
76 key = params[:activation]
73 key = params[:activation]
77 @user = User.find_by_login(login)
74 @user = User.find_by_login(login)
78 if (@user) and (@user.verify_activation_key(key))
75 if (@user) and (@user.verify_activation_key(key))
79 if @user.valid? # check uniquenss of email
76 if @user.valid? # check uniquenss of email
80 @user.activated = true
77 @user.activated = true
81 @user.save
78 @user.save
82 @result = :successful
79 @result = :successful
83 else
80 else
84 @result = :email_used
81 @result = :email_used
85 end
82 end
86 else
83 else
87 @result = :failed
84 @result = :failed
88 end
85 end
89 render :action => 'confirm', :layout => 'empty'
86 render :action => 'confirm', :layout => 'empty'
90 end
87 end
91
88
92 def forget
89 def forget
93 render :action => 'forget', :layout => 'empty'
90 render :action => 'forget', :layout => 'empty'
94 end
91 end
95
92
96 def retrieve_password
93 def retrieve_password
97 email = params[:email]
94 email = params[:email]
98 user = User.find_by_email(email)
95 user = User.find_by_email(email)
99 if user
96 if user
100 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
101 if last_updated_time > Time.now.gmtime - 5.minutes
98 if last_updated_time > Time.now.gmtime - 5.minutes
102 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
103 else
100 else
104 user.password = user.password_confirmation = User.random_password
101 user.password = user.password_confirmation = User.random_password
105 user.save
102 user.save
106 send_new_password_email(user)
103 send_new_password_email(user)
107 flash[:notice] = 'New password has been mailed to you.'
104 flash[:notice] = 'New password has been mailed to you.'
108 end
105 end
109 else
106 else
110 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
111 end
108 end
112 redirect_to :action => 'forget'
109 redirect_to :action => 'forget'
113 end
110 end
114
111
115 def stat
112 def stat
116 @user = User.find(params[:id])
113 @user = User.find(params[:id])
117 @submission = Submission.joins(:problem).where(user_id: params[:id])
114 @submission = Submission.joins(:problem).where(user_id: params[:id])
118 @submission = @submission.where('problems.available = true') unless current_user.admin?
115 @submission = @submission.where('problems.available = true') unless current_user.admin?
119
116
120 range = 120
117 range = 120
@@ -1,13 +1,13
1 class Group < ActiveRecord::Base
1 class Group < ActiveRecord::Base
2 - has_many :groups_problems, class_name: GroupProblem
2 + has_many :groups_problems, class_name: 'GroupProblem'
3 has_many :problems, :through => :groups_problems
3 has_many :problems, :through => :groups_problems
4
4
5 - has_many :groups_users, class_name: GroupUser
5 + has_many :groups_users, class_name: 'GroupUser'
6 has_many :users, :through => :groups_users
6 has_many :users, :through => :groups_users
7
7
8 #has_and_belongs_to_many :problems
8 #has_and_belongs_to_many :problems
9 #has_and_belongs_to_many :users
9 #has_and_belongs_to_many :users
10
10
11
11
12 end
12 end
13
13
@@ -1,106 +1,106
1 class Problem < ActiveRecord::Base
1 class Problem < ActiveRecord::Base
2
2
3 belongs_to :description
3 belongs_to :description
4 has_and_belongs_to_many :contests, :uniq => true
4 has_and_belongs_to_many :contests, :uniq => true
5
5
6 #has_and_belongs_to_many :groups
6 #has_and_belongs_to_many :groups
7 - has_many :groups_problems, class_name: GroupProblem
7 + has_many :groups_problems, class_name: 'GroupProblem'
8 has_many :groups, :through => :groups_problems
8 has_many :groups, :through => :groups_problems
9
9
10 - has_many :problems_tags, class_name: ProblemTag
10 + has_many :problems_tags, class_name: 'ProblemTag'
11 has_many :tags, through: :problems_tags
11 has_many :tags, through: :problems_tags
12
12
13 has_many :test_pairs, :dependent => :delete_all
13 has_many :test_pairs, :dependent => :delete_all
14 has_many :testcases, :dependent => :destroy
14 has_many :testcases, :dependent => :destroy
15
15
16 has_many :submissions
16 has_many :submissions
17
17
18 validates_presence_of :name
18 validates_presence_of :name
19 validates_format_of :name, :with => /\A\w+\z/
19 validates_format_of :name, :with => /\A\w+\z/
20 validates_presence_of :full_name
20 validates_presence_of :full_name
21
21
22 scope :available, -> { where(available: true) }
22 scope :available, -> { where(available: true) }
23
23
24 DEFAULT_TIME_LIMIT = 1
24 DEFAULT_TIME_LIMIT = 1
25 DEFAULT_MEMORY_LIMIT = 32
25 DEFAULT_MEMORY_LIMIT = 32
26
26
27 def self.available_problems
27 def self.available_problems
28 available.order(date_added: :desc).order(:name)
28 available.order(date_added: :desc).order(:name)
29 #Problem.available.all(:order => "date_added DESC, name ASC")
29 #Problem.available.all(:order => "date_added DESC, name ASC")
30 end
30 end
31
31
32 def self.create_from_import_form_params(params, old_problem=nil)
32 def self.create_from_import_form_params(params, old_problem=nil)
33 org_problem = old_problem || Problem.new
33 org_problem = old_problem || Problem.new
34 import_params, problem = Problem.extract_params_and_check(params,
34 import_params, problem = Problem.extract_params_and_check(params,
35 org_problem)
35 org_problem)
36
36
37 if !problem.errors.empty?
37 if !problem.errors.empty?
38 return problem, 'Error importing'
38 return problem, 'Error importing'
39 end
39 end
40
40
41 problem.full_score = 100
41 problem.full_score = 100
42 problem.date_added = Time.new
42 problem.date_added = Time.new
43 problem.test_allowed = true
43 problem.test_allowed = true
44 problem.output_only = false
44 problem.output_only = false
45 problem.available = false
45 problem.available = false
46
46
47 if not problem.save
47 if not problem.save
48 return problem, 'Error importing'
48 return problem, 'Error importing'
49 end
49 end
50
50
51 import_to_db = params.has_key? :import_to_db
51 import_to_db = params.has_key? :import_to_db
52
52
53 importer = TestdataImporter.new(problem)
53 importer = TestdataImporter.new(problem)
54
54
55 if not importer.import_from_file(import_params[:file],
55 if not importer.import_from_file(import_params[:file],
56 import_params[:time_limit],
56 import_params[:time_limit],
57 import_params[:memory_limit],
57 import_params[:memory_limit],
58 import_params[:checker_name],
58 import_params[:checker_name],
59 import_to_db)
59 import_to_db)
60 problem.errors.add(:base,'Import error.')
60 problem.errors.add(:base,'Import error.')
61 end
61 end
62
62
63 return problem, importer.log_msg
63 return problem, importer.log_msg
64 end
64 end
65
65
66 def self.download_file_basedir
66 def self.download_file_basedir
67 return "#{Rails.root}/data/tasks"
67 return "#{Rails.root}/data/tasks"
68 end
68 end
69
69
70 def get_submission_stat
70 def get_submission_stat
71 result = Hash.new
71 result = Hash.new
72 #total number of submission
72 #total number of submission
73 result[:total_sub] = Submission.where(problem_id: self.id).count
73 result[:total_sub] = Submission.where(problem_id: self.id).count
74 result[:attempted_user] = Submission.where(problem_id: self.id).group(:user_id)
74 result[:attempted_user] = Submission.where(problem_id: self.id).group(:user_id)
75 result[:pass] = Submission.where(problem_id: self.id).where("points >= ?",self.full_score).count
75 result[:pass] = Submission.where(problem_id: self.id).where("points >= ?",self.full_score).count
76 return result
76 return result
77 end
77 end
78
78
79 def long_name
79 def long_name
80 "[#{name}] #{full_name}"
80 "[#{name}] #{full_name}"
81 end
81 end
82
82
83 protected
83 protected
84
84
85 def self.to_i_or_default(st, default)
85 def self.to_i_or_default(st, default)
86 if st!=''
86 if st!=''
87 result = st.to_i
87 result = st.to_i
88 end
88 end
89 result ||= default
89 result ||= default
90 end
90 end
91
91
92 def self.to_f_or_default(st, default)
92 def self.to_f_or_default(st, default)
93 if st!=''
93 if st!=''
94 result = st.to_f
94 result = st.to_f
95 end
95 end
96 result ||= default
96 result ||= default
97 end
97 end
98
98
99 def self.extract_params_and_check(params, problem)
99 def self.extract_params_and_check(params, problem)
100 time_limit = Problem.to_f_or_default(params[:time_limit],
100 time_limit = Problem.to_f_or_default(params[:time_limit],
101 DEFAULT_TIME_LIMIT)
101 DEFAULT_TIME_LIMIT)
102 memory_limit = Problem.to_i_or_default(params[:memory_limit],
102 memory_limit = Problem.to_i_or_default(params[:memory_limit],
103 DEFAULT_MEMORY_LIMIT)
103 DEFAULT_MEMORY_LIMIT)
104
104
105 if time_limit<=0 or time_limit >60
105 if time_limit<=0 or time_limit >60
106 problem.errors.add(:base,'Time limit out of range.')
106 problem.errors.add(:base,'Time limit out of range.')
@@ -1,4 +1,4
1 class Tag < ActiveRecord::Base
1 class Tag < ActiveRecord::Base
2 - has_many :problems_tags, class_name: ProblemTag
2 + has_many :problems_tags, class_name: 'ProblemTag'
3 has_many :problems, through: :problems_tags
3 has_many :problems, through: :problems_tags
4 end
4 end
@@ -1,108 +1,108
1 require 'digest/sha1'
1 require 'digest/sha1'
2 require 'net/pop'
2 require 'net/pop'
3 require 'net/https'
3 require 'net/https'
4 require 'net/http'
4 require 'net/http'
5 require 'json'
5 require 'json'
6
6
7 class User < ActiveRecord::Base
7 class User < ActiveRecord::Base
8
8
9 has_and_belongs_to_many :roles
9 has_and_belongs_to_many :roles
10
10
11 #has_and_belongs_to_many :groups
11 #has_and_belongs_to_many :groups
12 - has_many :groups_users, class_name: GroupUser
12 + has_many :groups_users, class_name: 'GroupUser'
13 has_many :groups, :through => :groups_users
13 has_many :groups, :through => :groups_users
14
14
15 has_many :test_requests, -> {order(submitted_at: :desc)}
15 has_many :test_requests, -> {order(submitted_at: :desc)}
16
16
17 has_many :messages, -> { order(created_at: :desc) },
17 has_many :messages, -> { order(created_at: :desc) },
18 :class_name => "Message",
18 :class_name => "Message",
19 :foreign_key => "sender_id"
19 :foreign_key => "sender_id"
20
20
21 has_many :replied_messages, -> { order(created_at: :desc) },
21 has_many :replied_messages, -> { order(created_at: :desc) },
22 :class_name => "Message",
22 :class_name => "Message",
23 :foreign_key => "receiver_id"
23 :foreign_key => "receiver_id"
24
24
25 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
25 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
26
26
27 belongs_to :site
27 belongs_to :site
28 belongs_to :country
28 belongs_to :country
29
29
30 has_and_belongs_to_many :contests, -> { order(:name); uniq}
30 has_and_belongs_to_many :contests, -> { order(:name); uniq}
31
31
32 scope :activated_users, -> {where activated: true}
32 scope :activated_users, -> {where activated: true}
33
33
34 validates_presence_of :login
34 validates_presence_of :login
35 validates_uniqueness_of :login
35 validates_uniqueness_of :login
36 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
36 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
37 validates_length_of :login, :within => 3..30
37 validates_length_of :login, :within => 3..30
38
38
39 validates_presence_of :full_name
39 validates_presence_of :full_name
40 validates_length_of :full_name, :minimum => 1
40 validates_length_of :full_name, :minimum => 1
41
41
42 validates_presence_of :password, :if => :password_required?
42 validates_presence_of :password, :if => :password_required?
43 validates_length_of :password, :within => 4..20, :if => :password_required?
43 validates_length_of :password, :within => 4..20, :if => :password_required?
44 validates_confirmation_of :password, :if => :password_required?
44 validates_confirmation_of :password, :if => :password_required?
45
45
46 validates_format_of :email,
46 validates_format_of :email,
47 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
47 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
48 :if => :email_validation?
48 :if => :email_validation?
49 validate :uniqueness_of_email_from_activated_users,
49 validate :uniqueness_of_email_from_activated_users,
50 :if => :email_validation?
50 :if => :email_validation?
51 validate :enough_time_interval_between_same_email_registrations,
51 validate :enough_time_interval_between_same_email_registrations,
52 :if => :email_validation?
52 :if => :email_validation?
53
53
54 # these are for ytopc
54 # these are for ytopc
55 # disable for now
55 # disable for now
56 #validates_presence_of :province
56 #validates_presence_of :province
57
57
58 attr_accessor :password
58 attr_accessor :password
59
59
60 before_save :encrypt_new_password
60 before_save :encrypt_new_password
61 before_save :assign_default_site
61 before_save :assign_default_site
62 before_save :assign_default_contest
62 before_save :assign_default_contest
63
63
64 # this is for will_paginate
64 # this is for will_paginate
65 cattr_reader :per_page
65 cattr_reader :per_page
66 @@per_page = 50
66 @@per_page = 50
67
67
68 def self.authenticate(login, password)
68 def self.authenticate(login, password)
69 user = find_by_login(login)
69 user = find_by_login(login)
70 if user
70 if user
71 return user if user.authenticated?(password)
71 return user if user.authenticated?(password)
72 end
72 end
73 end
73 end
74
74
75 def authenticated?(password)
75 def authenticated?(password)
76 if self.activated
76 if self.activated
77 hashed_password == User.encrypt(password,self.salt)
77 hashed_password == User.encrypt(password,self.salt)
78 else
78 else
79 false
79 false
80 end
80 end
81 end
81 end
82
82
83 def admin?
83 def admin?
84 self.roles.detect {|r| r.name == 'admin' }
84 self.roles.detect {|r| r.name == 'admin' }
85 end
85 end
86
86
87 def email_for_editing
87 def email_for_editing
88 if self.email==nil
88 if self.email==nil
89 "(unknown)"
89 "(unknown)"
90 elsif self.email==''
90 elsif self.email==''
91 "(blank)"
91 "(blank)"
92 else
92 else
93 self.email
93 self.email
94 end
94 end
95 end
95 end
96
96
97 def email_for_editing=(e)
97 def email_for_editing=(e)
98 self.email=e
98 self.email=e
99 end
99 end
100
100
101 def alias_for_editing
101 def alias_for_editing
102 if self.alias==nil
102 if self.alias==nil
103 "(unknown)"
103 "(unknown)"
104 elsif self.alias==''
104 elsif self.alias==''
105 "(blank)"
105 "(blank)"
106 else
106 else
107 self.alias
107 self.alias
108 end
108 end
@@ -1,65 +1,65
1 - content_for :head do
1 - content_for :head do
2 = stylesheet_link_tag 'problems'
2 = stylesheet_link_tag 'problems'
3 %h1 Problems
3 %h1 Problems
4 %p
4 %p
5 = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-success btn-sm'
5 = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-success btn-sm'
6 = link_to 'New problem', new_problem_path, class: 'btn btn-success btn-sm'
6 = link_to 'New problem', new_problem_path, class: 'btn btn-success btn-sm'
7 = link_to 'Bulk Manage', { action: 'manage'}, class: 'btn btn-info btn-sm'
7 = link_to 'Bulk Manage', { action: 'manage'}, class: 'btn btn-info btn-sm'
8 = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm'
8 = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm'
9 = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm'
9 = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm'
10 .submitbox
10 .submitbox
11 - = form_tag :action => 'quick_create' do
11 + = form_tag action: 'quick_create', controller: 'problems' do
12 %b Quick New:
12 %b Quick New:
13 %label{:for => "problem_name"} Name
13 %label{:for => "problem_name"} Name
14 = text_field 'problem', 'name'
14 = text_field 'problem', 'name'
15 |
15 |
16 %label{:for => "problem_full_name"} Full name
16 %label{:for => "problem_full_name"} Full name
17 = text_field 'problem', 'full_name'
17 = text_field 'problem', 'full_name'
18 = submit_tag "Create"
18 = submit_tag "Create"
19 %table.table.table-condense.table-hover
19 %table.table.table-condense.table-hover
20 %thead
20 %thead
21 %th Name
21 %th Name
22 %th Full name
22 %th Full name
23 %th.text-right Full score
23 %th.text-right Full score
24 %th Tags
24 %th Tags
25 %th
25 %th
26 Submit
26 Submit
27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Admin can always submit to any problem' } [?]
27 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Admin can always submit to any problem' } [?]
28 %th Date added
28 %th Date added
29 %th.text-center
29 %th.text-center
30 Avail?
30 Avail?
31 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
31 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?]
32 %th.text-center
32 %th.text-center
33 View Data?
33 View Data?
34 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
34 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?]
35 %th.text-center
35 %th.text-center
36 Test?
36 Test?
37 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
37 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
38 - if GraderConfiguration.multicontests?
38 - if GraderConfiguration.multicontests?
39 %th Contests
39 %th Contests
40 - for problem in @problems
40 - for problem in @problems
41 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
41 %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
42 - @problem=problem
42 - @problem=problem
43 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
43 %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1
44 %td
44 %td
45 = problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
45 = problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1
46 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
46 = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem
47 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
47 %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1
48 %td
48 %td
49 - problem.tags.each do |t|
49 - problem.tags.each do |t|
50 - #%button.btn.btn-default.btn-xs= t.name
50 - #%button.btn.btn-default.btn-xs= t.name
51 %span.label.label-default= t.name
51 %span.label.label-default= t.name
52 %td= link_to "Submit", direct_edit_problem_submissions_path(problem,@current_user.id), class: 'btn btn-xs btn-primary'
52 %td= link_to "Submit", direct_edit_problem_submissions_path(problem,@current_user.id), class: 'btn btn-xs btn-primary'
53 %td= problem.date_added
53 %td= problem.date_added
54 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
54 %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}")
55 %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
55 %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}")
56 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
56 %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}")
57 - if GraderConfiguration.multicontests?
57 - if GraderConfiguration.multicontests?
58 %td
58 %td
59 = problem.contests.collect { |c| c.name }.join(', ')
59 = problem.contests.collect { |c| c.name }.join(', ')
60 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
60 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block'
61 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
61 %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block'
62 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
62 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block'
63 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
63 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block'
64 %br/
64 %br/
65 = link_to '[New problem]', :action => 'new'
65 = link_to '[New problem]', :action => 'new'
@@ -1,8 +1,8
1 <h1>New problem</h1>
1 <h1>New problem</h1>
2
2
3 <%= form_tag :action => 'create' do %>
3 <%= form_tag :action => 'create' do %>
4 <%= render :partial => 'form' %>
4 <%= render :partial => 'form' %>
5 <%= submit_tag "Create" %>
5 <%= submit_tag "Create" %>
6 <% end %>
6 <% end %>
7
7
8 - <%= link_to 'Back', :action => 'list' %>
8 + <%= link_to 'Back', problems_path %>
@@ -1,13 +1,13
1 %h1 Editing user
1 %h1 Editing user
2
2
3 = form_tag( {:action => 'update', :id => @user}, {class: 'form-horizontal'}) do
3 = form_tag( {:action => 'update', :id => @user}, {class: 'form-horizontal'}) do
4 = error_messages_for 'user'
4 = error_messages_for 'user'
5 = render partial: "form"
5 = render partial: "form"
6 .form-group
6 .form-group
7 .col-md-offset-2.col-md-4
7 .col-md-offset-2.col-md-4
8 = submit_tag "Edit", class: 'btn btn-primary'
8 = submit_tag "Edit", class: 'btn btn-primary'
9
9
10
10
11 = link_to 'Show', :action => 'show', :id => @user
11 = link_to 'Show', :action => 'show', :id => @user
12 |
12 |
13 - = link_to 'Back', :action => 'list'
13 + = link_to 'Back', :action => 'index'
@@ -1,25 +1,25
1 # Be sure to restart your server when you modify this file.
1 # Be sure to restart your server when you modify this file.
2 #
2 #
3 # This file contains migration options to ease your Rails 5.0 upgrade.
3 # This file contains migration options to ease your Rails 5.0 upgrade.
4 #
4 #
5 # Once upgraded flip defaults one by one to migrate to the new default.
5 # Once upgraded flip defaults one by one to migrate to the new default.
6 #
6 #
7 # Read the Guide for Upgrading Ruby on Rails for more info on each option.
7 # Read the Guide for Upgrading Ruby on Rails for more info on each option.
8
8
9 Rails.application.config.action_controller.raise_on_unfiltered_parameters = true
9 Rails.application.config.action_controller.raise_on_unfiltered_parameters = true
10
10
11 # Enable per-form CSRF tokens. Previous versions had false.
11 # Enable per-form CSRF tokens. Previous versions had false.
12 Rails.application.config.action_controller.per_form_csrf_tokens = false
12 Rails.application.config.action_controller.per_form_csrf_tokens = false
13
13
14 # Enable origin-checking CSRF mitigation. Previous versions had false.
14 # Enable origin-checking CSRF mitigation. Previous versions had false.
15 Rails.application.config.action_controller.forgery_protection_origin_check = false
15 Rails.application.config.action_controller.forgery_protection_origin_check = false
16
16
17 # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
17 # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`.
18 # Previous versions had false.
18 # Previous versions had false.
19 ActiveSupport.to_time_preserves_timezone = false
19 ActiveSupport.to_time_preserves_timezone = false
20
20
21 # Require `belongs_to` associations by default. Previous versions had false.
21 # Require `belongs_to` associations by default. Previous versions had false.
22 Rails.application.config.active_record.belongs_to_required_by_default = false
22 Rails.application.config.active_record.belongs_to_required_by_default = false
23
23
24 # Do not halt callback chains when a callback returns false. Previous versions had true.
24 # Do not halt callback chains when a callback returns false. Previous versions had true.
25 - ActiveSupport.halt_callback_chains_on_return_false = true
25 + # ActiveSupport.halt_callback_chains_on_return_false = true
@@ -1,167 +1,171
1 Rails.application.routes.draw do
1 Rails.application.routes.draw do
2 resources :tags
2 resources :tags
3 get "sources/direct_edit"
3 get "sources/direct_edit"
4
4
5 root :to => 'main#login'
5 root :to => 'main#login'
6
6
7 #logins
7 #logins
8 match 'login/login', to: 'login#login', via: [:get,:post]
8 match 'login/login', to: 'login#login', via: [:get,:post]
9
9
10
10
11 resources :contests
11 resources :contests
12
12
13 resources :sites
13 resources :sites
14
14
15 resources :test
15 resources :test
16
16
17 resources :messages do
17 resources :messages do
18 collection do
18 collection do
19 get 'console'
19 get 'console'
20 end
20 end
21 end
21 end
22
22
23 resources :announcements do
23 resources :announcements do
24 member do
24 member do
25 get 'toggle','toggle_front'
25 get 'toggle','toggle_front'
26 end
26 end
27 end
27 end
28
28
29 resources :problems do
29 resources :problems do
30 member do
30 member do
31 get 'toggle'
31 get 'toggle'
32 get 'toggle_test'
32 get 'toggle_test'
33 get 'toggle_view_testcase'
33 get 'toggle_view_testcase'
34 get 'stat'
34 get 'stat'
35 end
35 end
36 collection do
36 collection do
37 get 'turn_all_off'
37 get 'turn_all_off'
38 get 'turn_all_on'
38 get 'turn_all_on'
39 get 'import'
39 get 'import'
40 get 'manage'
40 get 'manage'
41 + get 'quick_create'
42 + post 'do_manage'
41 end
43 end
42 end
44 end
43
45
44 resources :groups do
46 resources :groups do
45 member do
47 member do
46 post 'add_user', to: 'groups#add_user', as: 'add_user'
48 post 'add_user', to: 'groups#add_user', as: 'add_user'
47 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
49 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
48 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
50 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
49 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
51 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
50 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
52 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
51 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
53 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
52 end
54 end
53 collection do
55 collection do
54
56
55 end
57 end
56 end
58 end
57
59
58 resources :testcases, only: [] do
60 resources :testcases, only: [] do
59 member do
61 member do
60 get 'download_input'
62 get 'download_input'
61 get 'download_sol'
63 get 'download_sol'
62 end
64 end
63 collection do
65 collection do
64 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
66 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
65 end
67 end
66 end
68 end
67
69
68 resources :grader_configuration, controller: 'configurations'
70 resources :grader_configuration, controller: 'configurations'
69
71
70 resources :users do
72 resources :users do
71 member do
73 member do
72 get 'toggle_activate', 'toggle_enable'
74 get 'toggle_activate', 'toggle_enable'
73 get 'stat'
75 get 'stat'
74 end
76 end
75 end
77 end
76
78
77 resources :submissions do
79 resources :submissions do
78 member do
80 member do
79 get 'download'
81 get 'download'
80 get 'compiler_msg'
82 get 'compiler_msg'
81 get 'rejudge'
83 get 'rejudge'
82 end
84 end
83 collection do
85 collection do
84 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
86 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
85 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
87 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
86 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
88 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
87 end
89 end
88 end
90 end
89
91
90
92
91 #user admin
93 #user admin
92 resources :user_admin do
94 resources :user_admin do
93 collection do
95 collection do
94 match 'bulk_manage', via: [:get, :post]
96 match 'bulk_manage', via: [:get, :post]
97 + get 'bulk_mail'
95 get 'user_stat'
98 get 'user_stat'
96 get 'import'
99 get 'import'
97 get 'new_list'
100 get 'new_list'
98 get 'admin'
101 get 'admin'
99 get 'random_all_passwords'
102 get 'random_all_passwords'
100 get 'active'
103 get 'active'
101 get 'mass_mailing'
104 get 'mass_mailing'
102 match 'create_from_list', via: [:get, :post]
105 match 'create_from_list', via: [:get, :post]
106 + post 'grant_admin'
103 end
107 end
104 member do
108 member do
105 get 'clear_last_ip'
109 get 'clear_last_ip'
106 end
110 end
107 end
111 end
108
112
109 resources :contest_management, only: [:index] do
113 resources :contest_management, only: [:index] do
110 collection do
114 collection do
111 get 'user_stat'
115 get 'user_stat'
112 get 'clear_stat'
116 get 'clear_stat'
113 get 'clear_all_stat'
117 get 'clear_all_stat'
114 end
118 end
115 end
119 end
116
120
117 #get 'user_admin', to: 'user_admin#index'
121 #get 'user_admin', to: 'user_admin#index'
118 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
122 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
119 #post 'user_admin', to: 'user_admin#create'
123 #post 'user_admin', to: 'user_admin#create'
120 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
124 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
121
125
122 #singular resource
126 #singular resource
123 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
127 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
124 #report
128 #report
125 resource :report, only: [], controller: 'report' do
129 resource :report, only: [], controller: 'report' do
126 get 'login'
130 get 'login'
127 get 'multiple_login'
131 get 'multiple_login'
128 get 'problem_hof/:id', action: 'problem_hof'
132 get 'problem_hof/:id', action: 'problem_hof'
129 get 'current_score'
133 get 'current_score'
130 get 'max_score'
134 get 'max_score'
131 post 'show_max_score'
135 post 'show_max_score'
132 end
136 end
133 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
137 #get 'report/current_score', to: 'report#current_score', as: 'report_current_score'
134 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
138 #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof'
135 #get "report/login"
139 #get "report/login"
136 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
140 #get 'report/max_score', to: 'report#max_score', as: 'report_max_score'
137 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
141 #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score'
138
142
139 resource :main, only: [], controller: 'main' do
143 resource :main, only: [], controller: 'main' do
140 get 'list'
144 get 'list'
141 get 'submission(/:id)', action: 'submission', as: 'main_submission'
145 get 'submission(/:id)', action: 'submission', as: 'main_submission'
142 post 'submit'
146 post 'submit'
143 get 'announcements'
147 get 'announcements'
144 get 'help'
148 get 'help'
145 end
149 end
146 #main
150 #main
147 #get "main/list"
151 #get "main/list"
148 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
152 #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission'
149 #post 'main/submit', to: 'main#submit'
153 #post 'main/submit', to: 'main#submit'
150 #get 'main/announcements', to: 'main#announcements'
154 #get 'main/announcements', to: 'main#announcements'
151
155
152
156
153 #
157 #
154 get 'tasks/view/:file.:ext' => 'tasks#view'
158 get 'tasks/view/:file.:ext' => 'tasks#view'
155 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
159 get 'tasks/download/:id/:file.:ext' => 'tasks#download'
156 get 'heartbeat/:id/edit' => 'heartbeat#edit'
160 get 'heartbeat/:id/edit' => 'heartbeat#edit'
157
161
158 #grader
162 #grader
159 get 'graders/list', to: 'graders#list', as: 'grader_list'
163 get 'graders/list', to: 'graders#list', as: 'grader_list'
160
164
161
165
162 # See how all your routes lay out with "rake routes"
166 # See how all your routes lay out with "rake routes"
163
167
164 # This is a legacy wild controller route that's not recommended for RESTful applications.
168 # This is a legacy wild controller route that's not recommended for RESTful applications.
165 # Note: This route will make all actions in every controller accessible via GET requests.
169 # Note: This route will make all actions in every controller accessible via GET requests.
166 # match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
170 # match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
167 end
171 end
@@ -1,27 +1,28
1 - ENV["RAILS_ENV"] = "test"
1 + ENV['RAILS_ENV'] ||= 'test'
2 - require File.expand_path('../../config/environment', __FILE__)
2 + require_relative '../config/environment'
3 require 'rails/test_help'
3 require 'rails/test_help'
4
4
5 #reporter for beautiful result
5 #reporter for beautiful result
6 require "minitest/reporters"
6 require "minitest/reporters"
7 Minitest::Reporters.use!
7 Minitest::Reporters.use!
8
8
9 module SignInHelper
9 module SignInHelper
10 def sign_in_as(user,password)
10 def sign_in_as(user,password)
11 post login_login_path, {login: user, password: password }
11 post login_login_path, {login: user, password: password }
12 end
12 end
13 end
13 end
14
14
15 class ActiveSupport::TestCase
15 class ActiveSupport::TestCase
16 include SignInHelper
16 include SignInHelper
17 # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
17 # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
18 #
18 #
19 # Note: You'll currently still have to declare fixtures explicitly in integration tests
19 # Note: You'll currently still have to declare fixtures explicitly in integration tests
20 # -- they do not yet inherit this setting
20 # -- they do not yet inherit this setting
21 fixtures :all
21 fixtures :all
22
22
23 # Add more helper methods to be used by all tests here...
23 # Add more helper methods to be used by all tests here...
24
24
25 - self.use_transactional_fixtures = true
25 + self.use_transactional_tests = true
26 + #self.use_instantiated_fixtures = false
26 self.use_instantiated_fixtures = false
27 self.use_instantiated_fixtures = false
27 end
28 end
deleted file
deleted file
You need to be logged in to leave comments. Login now