Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-26 11:00:28 +01:00
Merge pull request #49 from paviliondev/add_date_time_inputs
Add date time inputs
Dieser Commit ist enthalten in:
Commit
f70170abf7
19 geänderte Dateien mit 156 neuen und 8 gelöschten Zeilen
|
@ -25,6 +25,11 @@ export default Component.extend(UndoChanges, {
|
|||
showAdvanced: alias('field.type'),
|
||||
messageUrl: 'https://thepavilion.io/t/2809',
|
||||
|
||||
@discourseComputed('field.type')
|
||||
isDateTime(type) {
|
||||
return ['date_time', 'date', 'time'].indexOf(type) > -1;
|
||||
},
|
||||
|
||||
@discourseComputed('field.type')
|
||||
messageKey(type) {
|
||||
let key = 'type';
|
||||
|
|
|
@ -110,6 +110,19 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if isDateTime}}
|
||||
<div class="setting">
|
||||
<div class="setting-label">
|
||||
<label>{{{i18n 'admin.wizard.field.date_time_format.label'}}}</label>
|
||||
</div>
|
||||
|
||||
<div class="setting-value">
|
||||
{{input value=field.format class="medium"}}
|
||||
<label>{{{i18n 'admin.wizard.field.date_time_format.instructions'}}}</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if showPrefill}}
|
||||
<div class="setting full field-mapper-setting">
|
||||
<div class="setting-label">
|
||||
|
|
|
@ -89,6 +89,9 @@
|
|||
//= require discourse/app/components/emoji-picker
|
||||
//= require discourse/app/components/input-tip
|
||||
//= require discourse/app/components/date-picker
|
||||
//= require discourse/app/components/time-input
|
||||
//= require discourse/app/components/date-input
|
||||
//= require discourse/app/components/date-time-input
|
||||
//= require discourse/app/components/text-field
|
||||
//= require discourse/app/components/d-textarea
|
||||
|
||||
|
@ -96,6 +99,9 @@
|
|||
//= require discourse/app/templates/components/d-button
|
||||
//= require discourse/app/templates/components/d-editor
|
||||
//= require discourse/app/templates/components/date-picker
|
||||
//= require discourse/app/templates/components/date-input
|
||||
//= require discourse/app/templates/components/time-input
|
||||
//= require discourse/app/templates/components/date-time-input
|
||||
//= require discourse/app/templates/components/emoji-picker
|
||||
//= require discourse/app/templates/components/popup-input-tip
|
||||
//= require discourse/app/templates/category-tag-autocomplete
|
||||
|
|
15
assets/javascripts/wizard/components/wizard-field-date-time.js.es6
Normale Datei
15
assets/javascripts/wizard/components/wizard-field-date-time.js.es6
Normale Datei
|
@ -0,0 +1,15 @@
|
|||
import Component from "@ember/component";
|
||||
import { observes } from 'discourse-common/utils/decorators';
|
||||
|
||||
export default Component.extend({
|
||||
@observes('dateTime')
|
||||
setValue() {
|
||||
this.set('field.value', this.dateTime.format(this.field.format));
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChange(value) {
|
||||
this.set('dateTime', moment(value));
|
||||
}
|
||||
}
|
||||
});
|
15
assets/javascripts/wizard/components/wizard-field-date.js.es6
Normale Datei
15
assets/javascripts/wizard/components/wizard-field-date.js.es6
Normale Datei
|
@ -0,0 +1,15 @@
|
|||
import Component from "@ember/component";
|
||||
import { observes } from 'discourse-common/utils/decorators';
|
||||
|
||||
export default Component.extend({
|
||||
@observes('date')
|
||||
setValue() {
|
||||
this.set('field.value', this.date.format(this.field.format));
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChange(value) {
|
||||
this.set('date', moment(value));
|
||||
}
|
||||
}
|
||||
});
|
20
assets/javascripts/wizard/components/wizard-field-time.js.es6
Normale Datei
20
assets/javascripts/wizard/components/wizard-field-time.js.es6
Normale Datei
|
@ -0,0 +1,20 @@
|
|||
import Component from "@ember/component";
|
||||
import { observes } from 'discourse-common/utils/decorators';
|
||||
|
||||
export default Component.extend({
|
||||
@observes('time')
|
||||
setValue() {
|
||||
this.set('field.value', this.time.format(this.field.format));
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChange(value) {
|
||||
this.set('time',
|
||||
moment({
|
||||
hours: value.hours,
|
||||
minutes: value.minutes
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
|
@ -241,7 +241,10 @@ export default {
|
|||
'text_only',
|
||||
'composer',
|
||||
'category',
|
||||
'group'
|
||||
'group',
|
||||
'date',
|
||||
'time',
|
||||
'date_time'
|
||||
];
|
||||
|
||||
FieldModel.reopen({
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{{date-time-input
|
||||
date=dateTime
|
||||
onChange=(action "onChange")
|
||||
}}
|
|
@ -1,4 +1,4 @@
|
|||
{{date-picker
|
||||
value=field.value
|
||||
id=field.id
|
||||
{{date-input
|
||||
date=date
|
||||
onChange=(action "onChange")
|
||||
}}
|
|
@ -0,0 +1,4 @@
|
|||
{{time-input
|
||||
date=time
|
||||
onChange=(action "onChange")
|
||||
}}
|
|
@ -300,6 +300,27 @@
|
|||
}
|
||||
}
|
||||
|
||||
input.date-picker {
|
||||
font-size: 1.1487em;
|
||||
padding: 6px;
|
||||
border: 1px solid $primary;
|
||||
transition: border-color 0.5s;
|
||||
}
|
||||
|
||||
.pika-single.is-bound {
|
||||
width: fit-content;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
.d-time-input .select-kit.combo-box .select-kit-header {
|
||||
font-size: 1.1487em;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.d-date-time-input {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.step-message {
|
||||
text-align: center;
|
||||
transition: all .2s;
|
||||
|
|
|
@ -150,6 +150,9 @@ en:
|
|||
property: "Property"
|
||||
prefill: "Prefill"
|
||||
content: "Content"
|
||||
date_time_format:
|
||||
label: "Format"
|
||||
instructions: "<a href='https://momentjs.com/docs/#/displaying/format/' target='_blank'>Moment.js format</a>"
|
||||
|
||||
type:
|
||||
text: "Text"
|
||||
|
@ -166,6 +169,8 @@ en:
|
|||
group: Group
|
||||
user_selector: User Selector
|
||||
date: Date
|
||||
time: Time
|
||||
date_time: Date & Time
|
||||
|
||||
connector:
|
||||
and: "and"
|
||||
|
|
|
@ -11,6 +11,8 @@ en:
|
|||
required: "%{label} is required."
|
||||
not_url: "%{label} must be a valid url"
|
||||
invalid_file: "%{label} must be a %{types}"
|
||||
invalid_date: "Invalid date"
|
||||
invalid_time: "Invalid time"
|
||||
|
||||
none: "We couldn't find a wizard at that address."
|
||||
no_skip: "Wizard can't be skipped"
|
||||
|
|
|
@ -101,6 +101,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
|||
:type,
|
||||
:min_length,
|
||||
:file_types,
|
||||
:format,
|
||||
:limit,
|
||||
:property,
|
||||
prefill: mapped_params,
|
||||
|
|
|
@ -5,6 +5,7 @@ module CustomWizardFieldExtension
|
|||
:key,
|
||||
:min_length,
|
||||
:file_types,
|
||||
:format,
|
||||
:limit,
|
||||
:property,
|
||||
:content
|
||||
|
@ -17,6 +18,7 @@ module CustomWizardFieldExtension
|
|||
@key = attrs[:key]
|
||||
@min_length = attrs[:min_length]
|
||||
@file_types = attrs[:file_types]
|
||||
@format = attrs[:format]
|
||||
@limit = attrs[:limit]
|
||||
@property = attrs[:property]
|
||||
@content = attrs[:content]
|
||||
|
|
|
@ -232,6 +232,10 @@ class CustomWizard::Builder
|
|||
params[:file_types] = field_template['file_types']
|
||||
end
|
||||
|
||||
if ['date', 'time', 'date_time'].include?(field_template['type'])
|
||||
params[:format] = field_template['format']
|
||||
end
|
||||
|
||||
if field_template['type'] === 'category' || field_template['type'] === 'tag'
|
||||
params[:limit] = field_template['limit']
|
||||
end
|
||||
|
@ -306,6 +310,7 @@ class CustomWizard::Builder
|
|||
id = field['id'].to_s
|
||||
min_length = field['min_length'] if is_text_type(field)
|
||||
file_types = field['file_types']
|
||||
format = field['format']
|
||||
|
||||
if required && !value
|
||||
updater.errors.add(id, I18n.t('wizard.field.required', label: label))
|
||||
|
@ -327,10 +332,14 @@ class CustomWizard::Builder
|
|||
updater.errors.add(id, I18n.t('wizard.field.invalid_file', label: label, types: file_types))
|
||||
end
|
||||
|
||||
if type === 'date' && value.present? && !validate_date(value)
|
||||
if ['date', 'date_time'].include?(type) && value.present? && !validate_date(value)
|
||||
updater.errors.add(id, I18n.t('wizard.field.invalid_date'))
|
||||
end
|
||||
|
||||
if type === 'time' && value.present? && !validate_time(value)
|
||||
updater.errors.add(id, I18n.t('wizard.field.invalid_time'))
|
||||
end
|
||||
|
||||
CustomWizard::Builder.field_validators.each do |validator|
|
||||
if type === validator[:type]
|
||||
validator[:block].call(field, updater, step_template)
|
||||
|
@ -353,6 +362,15 @@ class CustomWizard::Builder
|
|||
end
|
||||
end
|
||||
|
||||
def validate_time(value)
|
||||
begin
|
||||
Time.parse(value)
|
||||
true
|
||||
rescue ArgumentError
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def is_text_type(field)
|
||||
['text', 'textarea'].include? field['type']
|
||||
end
|
||||
|
|
|
@ -13,7 +13,15 @@ class CustomWizard::Field
|
|||
min_length: nil
|
||||
},
|
||||
text_only: {},
|
||||
date: {},
|
||||
date: {
|
||||
format: "YYYY-MM-DD"
|
||||
},
|
||||
time: {
|
||||
format: "HH:mm"
|
||||
},
|
||||
date_time: {
|
||||
format: ""
|
||||
},
|
||||
number: {},
|
||||
checkbox: {},
|
||||
url: {
|
||||
|
|
|
@ -249,6 +249,7 @@ class CustomWizard::Mapper
|
|||
end
|
||||
|
||||
def recurse(data, keys)
|
||||
return nil if data.nil?
|
||||
k = keys.shift
|
||||
result = data[k]
|
||||
keys.empty? ? result : self.recurse(result, keys)
|
||||
|
|
|
@ -4,6 +4,7 @@ class CustomWizard::FieldSerializer < ::WizardFieldSerializer
|
|||
|
||||
attributes :image,
|
||||
:file_types,
|
||||
:format,
|
||||
:limit,
|
||||
:property,
|
||||
:content
|
||||
|
@ -34,6 +35,10 @@ class CustomWizard::FieldSerializer < ::WizardFieldSerializer
|
|||
object.file_types
|
||||
end
|
||||
|
||||
def format
|
||||
object.format
|
||||
end
|
||||
|
||||
def limit
|
||||
object.limit
|
||||
end
|
||||
|
|
Laden …
In neuem Issue referenzieren