diff --git a/app/javascript/submission_form/area.vue b/app/javascript/submission_form/area.vue index 8e4a2ae3c..e363e8009 100644 --- a/app/javascript/submission_form/area.vue +++ b/app/javascript/submission_form/area.vue @@ -5,7 +5,7 @@ :class="{ 'text-[1.5vw] lg:text-base': !textOverflowChars, 'text-[1.0vw] lg:text-xs': textOverflowChars, 'cursor-default': !submittable, 'bg-red-100 border cursor-pointer ': submittable, 'border-red-100': !isActive && submittable, 'bg-opacity-70': !isActive && !isValueSet && submittable, 'border-red-500 border-dashed z-10': isActive && submittable, 'bg-opacity-30': (isActive || isValueSet) && submittable }" >
{{ field.name || fieldNames[field.type] }} @@ -87,6 +87,44 @@ :class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }" />
+
+ + +
+
+ + +
this.$refs.textContainer.clientHeight ? this.modelValue.length : 0 }) } + }, + methods: { + updateMultipleSelectValue (value) { + if (this.modelValue?.includes(value)) { + const newValue = [...this.modelValue] + + newValue.splice(newValue.indexOf(value), 1) + + this.$emit('update:model-value', newValue) + } else { + const newValue = this.modelValue ? [...this.modelValue] : [] + + newValue.push(value) + + this.$emit('update:model-value', newValue) + } + } } } diff --git a/app/javascript/template_builder/area.vue b/app/javascript/template_builder/area.vue index c5a1cfc45..a405c2742 100644 --- a/app/javascript/template_builder/area.vue +++ b/app/javascript/template_builder/area.vue @@ -66,7 +66,7 @@ @keydown.enter.prevent="onNameEnter" @focus="onNameFocus" @blur="onNameBlur" - >{{ field.name || defaultName }} + >{{ optionIndexText }} {{ field.name || defaultName }}
o.uuid === this.area.option_uuid) + 1}.` + } else { + return '' + } + }, cells () { const cells = [] diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index 248e3122a..d85582eff 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -168,7 +168,7 @@ :selected-submitter="selectedSubmitter" class="md:hidden" :editable="editable" - @cancel="drawField = null" + @cancel="[drawField = null, drawOption = null]" @change-submitter="[selectedSubmitter = $event, drawField.submitter_uuid = $event.uuid]" /> @@ -225,7 +225,7 @@ :default-fields="defaultFields" :with-sticky-submitters="withStickySubmitters" :editable="editable" - @set-draw="drawField = $event" + @set-draw="[drawField = $event.field, drawOption = $event.option]" @set-drag="dragField = $event" @change-submitter="selectedSubmitter = $event" @drag-end="dragField = null" @@ -354,6 +354,7 @@ export default { isSaving: false, selectedSubmitter: null, drawField: null, + drawOption: null, dragField: null } }, @@ -433,6 +434,7 @@ export default { } this.drawField = field + this.drawOption = null }, undo () { if (this.undoStack.length > 1) { @@ -482,6 +484,7 @@ export default { onKeyUp (e) { if (e.code === 'Escape') { this.drawField = null + this.drawOption = null this.selectedAreaRef.value = null } @@ -528,6 +531,16 @@ export default { }, onDraw (area) { if (this.drawField) { + if (this.drawOption) { + const areaWithoutOption = this.drawField.areas?.find((a) => !a.option_uuid) + + if (areaWithoutOption && !this.drawField.areas.find((a) => a.option_uuid === this.drawField.options[0].uuid)) { + areaWithoutOption.option_uuid = this.drawField.options[0].uuid + } + + area.option_uuid = this.drawOption.uuid + } + this.drawField.areas ||= [] this.drawField.areas.push(area) @@ -536,6 +549,7 @@ export default { } this.drawField = null + this.drawOption = null this.selectedAreaRef.value = area diff --git a/app/javascript/template_builder/field.vue b/app/javascript/template_builder/field.vue index 3fa0abf7a..00a713457 100644 --- a/app/javascript/template_builder/field.vue +++ b/app/javascript/template_builder/field.vue @@ -58,7 +58,7 @@ v-if="field && !field.areas.length" title="Draw" class="relative cursor-pointer text-transparent group-hover:text-base-content" - @click="$emit('set-draw', field)" + @click="$emit('set-draw', { field })" > -
  • +
  • {{ index + 1 }}. +
    + + +
    @@ -248,7 +271,7 @@ export default { IconCopy, FieldType }, - inject: ['template', 'save', 'backgroundColor'], + inject: ['template', 'save', 'backgroundColor', 'selectedAreaRef'], props: { field: { type: Object, @@ -306,6 +329,13 @@ export default { }, 1) } }, + maybeFocusOnOptionArea (option) { + const area = this.field.areas.find((a) => a.option_uuid === option.uuid) + + if (area) { + this.selectedAreaRef.value = area + } + }, scrollToFirstArea () { return this.field.areas?.[0] && this.$emit('scroll-to', this.field.areas[0]) }, @@ -317,6 +347,12 @@ export default { this.save() }, + removeOption (option) { + this.field.options.splice(this.field.options.indexOf(option), 1) + this.field.areas.splice(this.field.areas.findIndex((a) => a.option_uuid === option.uuid), 1) + + this.save() + }, maybeUpdateOptions () { delete this.field.default_value diff --git a/app/views/submissions/_value.html.erb b/app/views/submissions/_value.html.erb index 11ef194ce..9306f2371 100644 --- a/app/views/submissions/_value.html.erb +++ b/app/views/submissions/_value.html.erb @@ -11,9 +11,16 @@ <% end %>
  • <% elsif field['type'] == 'checkbox' %> -
    +
    <%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
    + <% elsif field['type'].in?(%w[multiple radio]) && area['option_uuid'] %> + <% option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] } %> + <% if option && Array.wrap(value).include?(option['value']) %> +
    + <%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %> +
    + <% end %> <% elsif field['type'] == 'cells' %> <% cell_width = area['cell_w'] / area['w'] * 100 %>
    diff --git a/lib/submissions/generate_result_attachments.rb b/lib/submissions/generate_result_attachments.rb index 4c8344b57..f26a28dc8 100644 --- a/lib/submissions/generate_result_attachments.rb +++ b/lib/submissions/generate_result_attachments.rb @@ -124,7 +124,13 @@ def call(submitter) layouter.fit(items, area['w'] * width, height_diff.positive? ? box_height : area['h'] * height) .draw(canvas, (area['x'] * width) + TEXT_LEFT_MARGIN, height - (area['y'] * height) + height_diff - TEXT_TOP_MARGIN) - when 'checkbox' + when ->(type) { type == 'checkbox' || (type.in?(%w[multiple radio]) && area['option_uuid'].present?) } + if field['type'].in?(%w[multiple radio]) + option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] } + + value = Array.wrap(value).include?(option['value']) + end + next unless value == true scale = [(area['w'] * width) / PdfIcons::WIDTH, (area['h'] * height) / PdfIcons::HEIGHT].min