diff --git a/assets/javascripts/discourse/templates/admin-wizards-logs.hbs b/assets/javascripts/discourse/templates/admin-wizards-logs.hbs index 18fd3fdb..b0dd3de6 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-logs.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-logs.hbs @@ -3,7 +3,7 @@ {{d-button label="refresh" - icon="refresh" + icon="sync" action="refresh" class="refresh"}} diff --git a/assets/javascripts/wizard/components/wizard-date-input.js.es6 b/assets/javascripts/wizard/components/wizard-date-input.js.es6 index 93c7ed2d..bb11b655 100644 --- a/assets/javascripts/wizard/components/wizard-date-input.js.es6 +++ b/assets/javascripts/wizard/components/wizard-date-input.js.es6 @@ -1,3 +1,42 @@ import DateInput from "discourse/components/date-input"; +import loadScript from "discourse/lib/load-script"; +import discourseComputed from "discourse-common/utils/decorators"; +import I18n from "I18n"; +/* global Pikaday:true */ -export default DateInput.extend(); +export default DateInput.extend({ + useNativePicker: false, + + @discourseComputed() + placeholder() { + return this.format; + }, + + _loadPikadayPicker(container) { + return loadScript("/javascripts/pikaday.js").then(() => { + let defaultOptions = { + field: this.element.querySelector(".date-picker"), + container: container || this.element.querySelector(".picker-container"), + bound: container === null, + format: this.format, + firstDay: 1, + i18n: { + previousMonth: I18n.t("dates.previous_month"), + nextMonth: I18n.t("dates.next_month"), + months: moment.months(), + weekdays: moment.weekdays(), + weekdaysShort: moment.weekdaysShort(), + }, + onSelect: (date) => this._handleSelection(date), + }; + + if (this.relativeDate) { + defaultOptions = Object.assign({}, defaultOptions, { + minDate: moment(this.relativeDate).toDate(), + }); + } + + return new Pikaday(Object.assign({}, defaultOptions, this._opts())); + }); + }, +}); diff --git a/assets/javascripts/wizard/templates/components/wizard-field-date.hbs b/assets/javascripts/wizard/templates/components/wizard-field-date.hbs index 4ac6571b..ed4d14e3 100644 --- a/assets/javascripts/wizard/templates/components/wizard-field-date.hbs +++ b/assets/javascripts/wizard/templates/components/wizard-field-date.hbs @@ -2,4 +2,5 @@ date=date onChange=(action "onChange") tabindex=field.tabindex + format=field.format }} diff --git a/lib/custom_wizard/validators/update.rb b/lib/custom_wizard/validators/update.rb index d84b448a..93d4955f 100644 --- a/lib/custom_wizard/validators/update.rb +++ b/lib/custom_wizard/validators/update.rb @@ -52,7 +52,7 @@ class ::CustomWizard::UpdateValidator @updater.errors.add(field_id, I18n.t('wizard.field.invalid_file', label: label, types: file_types)) end - if ['date', 'date_time'].include?(type) && value.present? && !validate_date(value) + if ['date', 'date_time'].include?(type) && value.present? && !validate_date(value, format) @updater.errors.add(field_id, I18n.t('wizard.field.invalid_date')) end @@ -88,13 +88,8 @@ class ::CustomWizard::UpdateValidator .include?(File.extname(value['original_filename'])[1..-1]) end - def validate_date(value) - begin - Date.parse(value) - true - rescue ArgumentError - false - end + def validate_date(value, format) + v8.eval("moment('#{value}', '#{format}', true).isValid()") end def validate_time(value) @@ -126,4 +121,12 @@ class ::CustomWizard::UpdateValidator def standardise_boolean(value) ActiveRecord::Type::Boolean.new.cast(value) end + + def v8 + return @ctx if @ctx + + @ctx = PrettyText.v8 + PrettyText.ctx_load(@ctx, "#{Rails.root}/vendor/assets/javascripts/moment.js") + @ctx + end end diff --git a/serializers/custom_wizard/wizard_serializer.rb b/serializers/custom_wizard/wizard_serializer.rb index f858c195..7a162ba5 100644 --- a/serializers/custom_wizard/wizard_serializer.rb +++ b/serializers/custom_wizard/wizard_serializer.rb @@ -8,11 +8,11 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer :completed, :required, :permitted, - :uncategorized_category_id + :uncategorized_category_id, + :categories has_many :steps, serializer: ::CustomWizard::StepSerializer, embed: :objects has_one :user, serializer: ::BasicUserSerializer, embed: :objects - has_many :categories, serializer: ::BasicCategorySerializer, embed: :objects has_many :groups, serializer: ::BasicGroupSerializer, embed: :objects def completed @@ -56,4 +56,8 @@ class CustomWizard::WizardSerializer < CustomWizard::BasicWizardSerializer def include_uncategorized_category_id? object.needs_categories end + + def categories + object.categories.map { |c| c.to_h } + end end diff --git a/spec/components/custom_wizard/update_validator_spec.rb b/spec/components/custom_wizard/update_validator_spec.rb index 81212b4b..e7658d8c 100644 --- a/spec/components/custom_wizard/update_validator_spec.rb +++ b/spec/components/custom_wizard/update_validator_spec.rb @@ -132,4 +132,44 @@ describe CustomWizard::UpdateValidator do updater.errors.messages[:step_2_field_6].first ).to eq(nil) end + + it 'validates date fields' do + @template[:steps][1][:fields][0][:format] = "DD-MM-YYYY" + CustomWizard::Template.save(@template) + + updater = perform_validation('step_2', step_2_field_1: '13-11-2021') + expect( + updater.errors.messages[:step_2_field_1].first + ).to eq(nil) + end + + it 'doesn\'t validate date field if the format is not respected' do + @template[:steps][1][:fields][0][:format] = "MM-DD-YYYY" + CustomWizard::Template.save(@template) + + updater = perform_validation('step_2', step_2_field_1: '13-11-2021') + expect( + updater.errors.messages[:step_2_field_1].first + ).to eq(I18n.t('wizard.field.invalid_date')) + end + + it 'validates date time fields' do + @template[:steps][1][:fields][2][:format] = "DD-MM-YYYY HH:mm:ss" + CustomWizard::Template.save(@template) + + updater = perform_validation('step_2', step_2_field_3: '13-11-2021 09:15:00') + expect( + updater.errors.messages[:step_2_field_3].first + ).to eq(nil) + end + + it 'doesn\'t validate date time field if the format is not respected' do + @template[:steps][1][:fields][2][:format] = "MM-DD-YYYY HH:mm:ss" + CustomWizard::Template.save(@template) + + updater = perform_validation('step_2', step_2_field_3: '13-11-2021 09:15') + expect( + updater.errors.messages[:step_2_field_3].first + ).to eq(I18n.t('wizard.field.invalid_date')) + end end