add ability to set date field format
This commit is contained in:
@@ -273,9 +273,15 @@ export default {
|
||||
return null
|
||||
}
|
||||
},
|
||||
locale () {
|
||||
return Intl.DateTimeFormat().resolvedOptions()?.locale
|
||||
},
|
||||
formattedDate () {
|
||||
if (this.field.type === 'date' && this.modelValue) {
|
||||
return new Intl.DateTimeFormat([], { year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' }).format(new Date(this.modelValue))
|
||||
return this.formatDate(
|
||||
new Date(this.modelValue),
|
||||
this.field.preferences?.format || (this.locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY')
|
||||
)
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
@@ -315,6 +321,36 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatDate (date, format) {
|
||||
const monthFormats = {
|
||||
M: 'numeric',
|
||||
MM: '2-digit',
|
||||
MMM: 'short',
|
||||
MMMM: 'long'
|
||||
}
|
||||
|
||||
const dayFormats = {
|
||||
D: 'numeric',
|
||||
DD: '2-digit'
|
||||
}
|
||||
|
||||
const yearFormats = {
|
||||
YYYY: 'numeric',
|
||||
YY: '2-digit'
|
||||
}
|
||||
|
||||
const parts = new Intl.DateTimeFormat([], {
|
||||
day: dayFormats[format.match(/D+/)],
|
||||
month: monthFormats[format.match(/M+/)],
|
||||
year: yearFormats[format.match(/Y+/)],
|
||||
timeZone: 'UTC'
|
||||
}).formatToParts(date)
|
||||
|
||||
return format
|
||||
.replace(/D+/, parts.find((p) => p.type === 'day').value)
|
||||
.replace(/M+/, parts.find((p) => p.type === 'month').value)
|
||||
.replace(/Y+/, parts.find((p) => p.type === 'year').value)
|
||||
},
|
||||
updateMultipleSelectValue (value) {
|
||||
if (this.modelValue?.includes(value)) {
|
||||
const newValue = [...this.modelValue]
|
||||
|
||||
@@ -474,6 +474,12 @@ export default {
|
||||
field.options = [{ value: '', uuid: v4() }]
|
||||
}
|
||||
|
||||
if (type === 'date') {
|
||||
field.preferences = {
|
||||
format: Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY'
|
||||
}
|
||||
}
|
||||
|
||||
this.drawField = field
|
||||
this.drawOption = null
|
||||
},
|
||||
@@ -650,6 +656,12 @@ export default {
|
||||
field.options = [{ value: '', uuid: v4() }]
|
||||
}
|
||||
|
||||
if (field.type === 'date') {
|
||||
field.preferences = {
|
||||
format: Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY'
|
||||
}
|
||||
}
|
||||
|
||||
const fieldArea = {
|
||||
x: (area.x - 6) / area.maskW,
|
||||
y: area.y / area.maskH,
|
||||
|
||||
@@ -111,6 +111,33 @@
|
||||
Default value
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="field.type === 'date'"
|
||||
class="py-1.5 px-1 relative"
|
||||
@click.stop
|
||||
>
|
||||
<select
|
||||
v-model="field.preferences.format"
|
||||
placeholder="Format"
|
||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0"
|
||||
@change="save"
|
||||
>
|
||||
<option
|
||||
v-for="format in dateFormats"
|
||||
:key="format"
|
||||
:value="format"
|
||||
>
|
||||
{{ formatDate(new Date(), format) }}
|
||||
</option>
|
||||
</select>
|
||||
<label
|
||||
:style="{ backgroundColor: backgroundColor }"
|
||||
class="absolute -top-1 left-2.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
Format
|
||||
</label>
|
||||
</div>
|
||||
<li
|
||||
v-if="field.type != 'phone'"
|
||||
@click.stop
|
||||
@@ -307,6 +334,19 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
fieldNames: FieldType.computed.fieldNames,
|
||||
dateFormats () {
|
||||
return [
|
||||
'MM/DD/YYYY',
|
||||
'DD/MM/YYYY',
|
||||
'YYYY-MM-DD',
|
||||
'DD-MM-YYYY',
|
||||
'DD.MM.YYYY',
|
||||
'MMM D, YYYY',
|
||||
'MMMM D, YYYY',
|
||||
'D MMM YYYY',
|
||||
'D MMMM YYYY'
|
||||
]
|
||||
},
|
||||
defaultName () {
|
||||
if (this.field.type === 'payment' && this.field.preferences?.price) {
|
||||
const { price, currency } = this.field.preferences || {}
|
||||
@@ -329,7 +369,44 @@ export default {
|
||||
return this.field.areas || []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.field.preferences ||= {}
|
||||
|
||||
if (this.field.type === 'date') {
|
||||
this.field.preferences.format ||=
|
||||
(Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
formatDate (date, format) {
|
||||
const monthFormats = {
|
||||
M: 'numeric',
|
||||
MM: '2-digit',
|
||||
MMM: 'short',
|
||||
MMMM: 'long'
|
||||
}
|
||||
|
||||
const dayFormats = {
|
||||
D: 'numeric',
|
||||
DD: '2-digit'
|
||||
}
|
||||
|
||||
const yearFormats = {
|
||||
YYYY: 'numeric',
|
||||
YY: '2-digit'
|
||||
}
|
||||
|
||||
const parts = new Intl.DateTimeFormat([], {
|
||||
day: dayFormats[format.match(/D+/)],
|
||||
month: monthFormats[format.match(/M+/)],
|
||||
year: yearFormats[format.match(/Y+/)]
|
||||
}).formatToParts(date)
|
||||
|
||||
return format
|
||||
.replace(/D+/, parts.find((p) => p.type === 'day').value)
|
||||
.replace(/M+/, parts.find((p) => p.type === 'month').value)
|
||||
.replace(/Y+/, parts.find((p) => p.type === 'year').value)
|
||||
},
|
||||
copyToAllPages (field) {
|
||||
const areaString = JSON.stringify(field.areas[0])
|
||||
|
||||
|
||||
@@ -261,6 +261,12 @@ export default {
|
||||
field.options = [{ value: '', uuid: v4() }]
|
||||
}
|
||||
|
||||
if (type === 'date') {
|
||||
field.preferences = {
|
||||
format: Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY'
|
||||
}
|
||||
}
|
||||
|
||||
this.fields.push(field)
|
||||
|
||||
if (['signature', 'initials', 'cells'].includes(type)) {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<% elsif field['type'] == 'date' %>
|
||||
<autosize-field></autosize-field>
|
||||
<div class="flex items-center px-0.5">
|
||||
<%= l(Date.parse(value), format: :long, locale: local_assigns[:locale]) %>
|
||||
<%= TimeUtils.format_date_string(value, field.dig('preferences', 'format'), local_assigns[:locale]) %>
|
||||
</div>
|
||||
<% else %>
|
||||
<autosize-field></autosize-field>
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
<% elsif field['type'] == 'checkbox' %>
|
||||
<%= svg_icon('check', class: 'w-6 h-6') %>
|
||||
<% elsif field['type'] == 'date' %>
|
||||
<%= l(Date.parse(value), locale: @submission.template.account.locale, format: :long) %>
|
||||
<%= TimeUtils.format_date_string(value, field.dig('preferences', 'format'), @submission.template.account.locale) %>
|
||||
<% else %>
|
||||
<%= Array.wrap(value).join(', ') %>
|
||||
<% end %>
|
||||
|
||||
@@ -228,7 +228,10 @@ module Submissions
|
||||
elsif field['type'] == 'checkbox'
|
||||
composer.formatted_text_box([{ text: value.to_s.titleize }], padding: [0, 0, 10, 0])
|
||||
else
|
||||
value = I18n.l(Date.parse(value), format: :long, locale: account.locale) if field['type'] == 'date'
|
||||
if field['type'] == 'date'
|
||||
value = TimeUtils.format_date_string(value, field.dig('preferences', 'format'), account.locale)
|
||||
end
|
||||
|
||||
value = value.join(', ') if value.is_a?(Array)
|
||||
|
||||
composer.formatted_text_box([{ text: value.to_s.presence || 'n/a' }], padding: [0, 0, 10, 0])
|
||||
|
||||
@@ -164,7 +164,9 @@ module Submissions
|
||||
height - (area['y'] * height))
|
||||
end
|
||||
else
|
||||
value = I18n.l(Date.parse(value), format: :default, locale: account.locale) if field['type'] == 'date'
|
||||
if field['type'] == 'date'
|
||||
value = TimeUtils.format_date_string(value, field.dig('preferences', 'format'), account.locale)
|
||||
end
|
||||
|
||||
text = HexaPDF::Layout::TextFragment.create(Array.wrap(value).join(', '), font: pdf.fonts.add(FONT_NAME),
|
||||
font_size:)
|
||||
@@ -268,7 +270,7 @@ module Submissions
|
||||
Submissions::EnsureResultGenerated.call(latest_submitter) if latest_submitter
|
||||
|
||||
documents = latest_submitter&.documents&.preload(:blob).to_a.presence
|
||||
documents ||= submitter.submission.template.schema_documents.preload(:blob)
|
||||
documents ||= submitter.submission.template_schema_documents.preload(:blob)
|
||||
|
||||
documents.to_h do |attachment|
|
||||
pdf =
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module TimeUtils
|
||||
MONTH_FORMATS = {
|
||||
'M' => '%-m',
|
||||
'MM' => '%m',
|
||||
'MMM' => '%b',
|
||||
'MMMM' => '%B'
|
||||
}.freeze
|
||||
|
||||
DAY_FORMATS = {
|
||||
'D' => '%-d',
|
||||
'DD' => '%d'
|
||||
}.freeze
|
||||
|
||||
YEAR_FORMATS = {
|
||||
'YYYY' => '%Y',
|
||||
'YY' => '%y'
|
||||
}.freeze
|
||||
|
||||
DEFAULT_DATE_FORMAT_US = 'MM/DD/YYYY'
|
||||
DEFAULT_DATE_FORMAT = 'DD/MM/YYYY'
|
||||
|
||||
module_function
|
||||
|
||||
def timezone_abbr(timezone, time = Time.current)
|
||||
@@ -10,4 +30,20 @@ module TimeUtils
|
||||
|
||||
tz_info.abbreviation(time)
|
||||
end
|
||||
|
||||
def format_date_string(string, format, locale)
|
||||
date = Date.parse(string)
|
||||
|
||||
format ||= locale.to_s.ends_with?('US') ? DEFAULT_DATE_FORMAT_US : DEFAULT_DATE_FORMAT
|
||||
|
||||
i18n_format = format.sub(/D+/, DAY_FORMATS[format[/D+/]])
|
||||
.sub(/M+/, MONTH_FORMATS[format[/M+/]])
|
||||
.sub(/Y+/, YEAR_FORMATS[format[/Y+/]])
|
||||
|
||||
I18n.l(date, format: i18n_format, locale:)
|
||||
rescue Date::Error => e
|
||||
Rollbar.error(e) if defined?(Rollbar)
|
||||
|
||||
string
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user