add ability to set date field format
This commit is contained in:
@@ -273,9 +273,15 @@ export default {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
locale () {
|
||||||
|
return Intl.DateTimeFormat().resolvedOptions()?.locale
|
||||||
|
},
|
||||||
formattedDate () {
|
formattedDate () {
|
||||||
if (this.field.type === 'date' && this.modelValue) {
|
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 {
|
} else {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
@@ -315,6 +321,36 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
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) {
|
updateMultipleSelectValue (value) {
|
||||||
if (this.modelValue?.includes(value)) {
|
if (this.modelValue?.includes(value)) {
|
||||||
const newValue = [...this.modelValue]
|
const newValue = [...this.modelValue]
|
||||||
|
|||||||
@@ -474,6 +474,12 @@ export default {
|
|||||||
field.options = [{ value: '', uuid: v4() }]
|
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.drawField = field
|
||||||
this.drawOption = null
|
this.drawOption = null
|
||||||
},
|
},
|
||||||
@@ -650,6 +656,12 @@ export default {
|
|||||||
field.options = [{ value: '', uuid: v4() }]
|
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 = {
|
const fieldArea = {
|
||||||
x: (area.x - 6) / area.maskW,
|
x: (area.x - 6) / area.maskW,
|
||||||
y: area.y / area.maskH,
|
y: area.y / area.maskH,
|
||||||
|
|||||||
@@ -111,6 +111,33 @@
|
|||||||
Default value
|
Default value
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</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
|
<li
|
||||||
v-if="field.type != 'phone'"
|
v-if="field.type != 'phone'"
|
||||||
@click.stop
|
@click.stop
|
||||||
@@ -307,6 +334,19 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
fieldNames: FieldType.computed.fieldNames,
|
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 () {
|
defaultName () {
|
||||||
if (this.field.type === 'payment' && this.field.preferences?.price) {
|
if (this.field.type === 'payment' && this.field.preferences?.price) {
|
||||||
const { price, currency } = this.field.preferences || {}
|
const { price, currency } = this.field.preferences || {}
|
||||||
@@ -329,7 +369,44 @@ export default {
|
|||||||
return this.field.areas || []
|
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: {
|
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) {
|
copyToAllPages (field) {
|
||||||
const areaString = JSON.stringify(field.areas[0])
|
const areaString = JSON.stringify(field.areas[0])
|
||||||
|
|
||||||
|
|||||||
@@ -261,6 +261,12 @@ export default {
|
|||||||
field.options = [{ value: '', uuid: v4() }]
|
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)
|
this.fields.push(field)
|
||||||
|
|
||||||
if (['signature', 'initials', 'cells'].includes(type)) {
|
if (['signature', 'initials', 'cells'].includes(type)) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
<% elsif field['type'] == 'date' %>
|
<% elsif field['type'] == 'date' %>
|
||||||
<autosize-field></autosize-field>
|
<autosize-field></autosize-field>
|
||||||
<div class="flex items-center px-0.5">
|
<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>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<autosize-field></autosize-field>
|
<autosize-field></autosize-field>
|
||||||
|
|||||||
@@ -162,7 +162,7 @@
|
|||||||
<% elsif field['type'] == 'checkbox' %>
|
<% elsif field['type'] == 'checkbox' %>
|
||||||
<%= svg_icon('check', class: 'w-6 h-6') %>
|
<%= svg_icon('check', class: 'w-6 h-6') %>
|
||||||
<% elsif field['type'] == 'date' %>
|
<% 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 %>
|
<% else %>
|
||||||
<%= Array.wrap(value).join(', ') %>
|
<%= Array.wrap(value).join(', ') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -228,7 +228,10 @@ module Submissions
|
|||||||
elsif field['type'] == 'checkbox'
|
elsif field['type'] == 'checkbox'
|
||||||
composer.formatted_text_box([{ text: value.to_s.titleize }], padding: [0, 0, 10, 0])
|
composer.formatted_text_box([{ text: value.to_s.titleize }], padding: [0, 0, 10, 0])
|
||||||
else
|
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)
|
value = value.join(', ') if value.is_a?(Array)
|
||||||
|
|
||||||
composer.formatted_text_box([{ text: value.to_s.presence || 'n/a' }], padding: [0, 0, 10, 0])
|
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))
|
height - (area['y'] * height))
|
||||||
end
|
end
|
||||||
else
|
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),
|
text = HexaPDF::Layout::TextFragment.create(Array.wrap(value).join(', '), font: pdf.fonts.add(FONT_NAME),
|
||||||
font_size:)
|
font_size:)
|
||||||
@@ -268,7 +270,7 @@ module Submissions
|
|||||||
Submissions::EnsureResultGenerated.call(latest_submitter) if latest_submitter
|
Submissions::EnsureResultGenerated.call(latest_submitter) if latest_submitter
|
||||||
|
|
||||||
documents = latest_submitter&.documents&.preload(:blob).to_a.presence
|
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|
|
documents.to_h do |attachment|
|
||||||
pdf =
|
pdf =
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module TimeUtils
|
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
|
module_function
|
||||||
|
|
||||||
def timezone_abbr(timezone, time = Time.current)
|
def timezone_abbr(timezone, time = Time.current)
|
||||||
@@ -10,4 +30,20 @@ module TimeUtils
|
|||||||
|
|
||||||
tz_info.abbreviation(time)
|
tz_info.abbreviation(time)
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user