Skip to content

Commit

Permalink
add ability to draw areas for radio options
Browse files Browse the repository at this point in the history
  • Loading branch information
omohokcoj committed Nov 13, 2023
1 parent 9aa68fe commit 333a5d6
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 13 deletions.
59 changes: 57 additions & 2 deletions app/javascript/submission_form/area.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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 }"
>
<div
v-if="!isActive && !isValueSet && field.type !== 'checkbox' && submittable"
v-if="!isActive && !isValueSet && field.type !== 'checkbox' && submittable && !area.option_uuid"
class="absolute top-0 bottom-0 right-0 left-0 items-center justify-center h-full w-full"
>
<span
Expand All @@ -21,7 +21,7 @@
</span>
</div>
<div
v-if="isActive && withLabel"
v-if="isActive && withLabel && !area.option_uuid"
class="absolute -top-7 rounded bg-base-content text-base-100 px-2 text-sm whitespace-nowrap"
>
{{ field.name || fieldNames[field.type] }}
Expand Down Expand Up @@ -87,6 +87,44 @@
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
/>
</div>
<div
v-else-if="field.type === 'radio' && area.option_uuid"
class="w-full p-[0.2vw] flex items-center justify-center"
>
<input
v-if="submittable"
type="radio"
:value="false"
class="aspect-square base-radio"
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
:checked="modelValue && modelValue === field.options.find((o) => o.uuid === area.option_uuid)?.value"
@click="$emit('update:model-value', field.options.find((o) => o.uuid === area.option_uuid)?.value)"
>
<IconCheck
v-else-if="modelValue && modelValue === field.options.find((o) => o.uuid === area.option_uuid)?.value"
class="aspect-square"
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
/>
</div>
<div
v-else-if="field.type === 'multiple' && area.option_uuid"
class="w-full p-[0.2vw] flex items-center justify-center"
>
<input
v-if="submittable"
type="checkbox"
:value="false"
class="aspect-square base-checkbox"
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
:checked="modelValue && modelValue.includes(field.options.find((o) => o.uuid === area.option_uuid)?.value)"
@change="updateMultipleSelectValue(field.options.find((o) => o.uuid === area.option_uuid)?.value)"
>
<IconCheck
v-else-if="modelValue && modelValue.includes(field.options.find((o) => o.uuid === area.option_uuid)?.value)"
class="aspect-square"
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
/>
</div>
<div
v-else-if="field.type === 'cells'"
class="w-full flex items-center"
Expand Down Expand Up @@ -271,6 +309,23 @@ export default {
this.textOverflowChars = this.$refs.textContainer.scrollHeight > 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)
}
}
}
}
</script>
9 changes: 8 additions & 1 deletion app/javascript/template_builder/area.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
@keydown.enter.prevent="onNameEnter"
@focus="onNameFocus"
@blur="onNameBlur"
>{{ field.name || defaultName }}</span>
>{{ optionIndexText }} {{ field.name || defaultName }}</span>
<div
v-if="isNameFocus && !['checkbox', 'phone'].includes(field.type)"
class="flex items-center ml-1.5"
Expand Down Expand Up @@ -185,6 +185,13 @@ export default {
defaultName: Field.computed.defaultName,
fieldNames: FieldType.computed.fieldNames,
fieldIcons: FieldType.computed.fieldIcons,
optionIndexText () {
if (this.area.option_uuid && this.field.options) {
return `${this.field.options.findIndex((o) => o.uuid === this.area.option_uuid) + 1}.`
} else {
return ''
}
},
cells () {
const cells = []
Expand Down
20 changes: 17 additions & 3 deletions app/javascript/template_builder/builder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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]"
/>
<FieldType
Expand Down Expand Up @@ -209,7 +209,7 @@
<p>
<button
class="base-button"
@click="drawField = null"
@click="[drawField = null, drawOption = null]"
>
Cancel
</button>
Expand All @@ -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"
Expand Down Expand Up @@ -354,6 +354,7 @@ export default {
isSaving: false,
selectedSubmitter: null,
drawField: null,
drawOption: null,
dragField: null
}
},
Expand Down Expand Up @@ -433,6 +434,7 @@ export default {
}
this.drawField = field
this.drawOption = null
},
undo () {
if (this.undoStack.length > 1) {
Expand Down Expand Up @@ -482,6 +484,7 @@ export default {
onKeyUp (e) {
if (e.code === 'Escape') {
this.drawField = null
this.drawOption = null
this.selectedAreaRef.value = null
}
Expand Down Expand Up @@ -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)
Expand All @@ -536,6 +549,7 @@ export default {
}
this.drawField = null
this.drawOption = null
this.selectedAreaRef.value = area
Expand Down
46 changes: 41 additions & 5 deletions app/javascript/template_builder/field.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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 })"
>
<IconNewSection
:width="18"
Expand Down Expand Up @@ -151,11 +151,11 @@
Page {{ area.page + 1 }}
</a>
</li>
<li>
<li v-if="!field.areas?.length || !['radio', 'multiple'].includes(field.type)">
<a
href="#"
class="text-sm py-1 px-2"
@click.prevent="$emit('set-draw', field)"
@click.prevent="$emit('set-draw', { field })"
>
<IconNewSection
:width="20"
Expand Down Expand Up @@ -205,16 +205,39 @@
<span class="text-sm w-3.5">
{{ index + 1 }}.
</span>
<div
v-if="['radio', 'multiple'].includes(field.type) && (index > 0 || field.areas.find((a) => a.option_uuid)) && !field.areas.find((a) => a.option_uuid === option.uuid)"
class="items-center flex w-full"
>
<input
v-model="option.value"
class="w-full input input-primary input-xs text-sm bg-transparent !pr-7 -mr-6"
type="text"
required
@blur="save"
>
<button
title="Draw"
@click.prevent="$emit('set-draw', { field, option })"
>
<IconNewSection
:width="18"
:stroke-width="1.6"
/>
</button>
</div>
<input
v-else
v-model="option.value"
class="w-full input input-primary input-xs text-sm bg-transparent"
type="text"
required
@focus="maybeFocusOnOptionArea(option)"
@blur="save"
>
<button
class="text-sm w-3.5"
@click="[field.options.splice(index, 1), save()]"
@click="removeOption(option)"
>
&times;
</button>
Expand Down Expand Up @@ -248,7 +271,7 @@ export default {
IconCopy,
FieldType
},
inject: ['template', 'save', 'backgroundColor'],
inject: ['template', 'save', 'backgroundColor', 'selectedAreaRef'],
props: {
field: {
type: Object,
Expand Down Expand Up @@ -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])
},
Expand All @@ -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
Expand Down
9 changes: 8 additions & 1 deletion app/views/submissions/_value.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@
<% end %>
</div>
<% elsif field['type'] == 'checkbox' %>
<div class="w-full p-[0.2vw] flex items-center justify-center">
<div class="w-full flex items-center justify-center">
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
</div>
<% 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']) %>
<div class="w-full flex items-center justify-center">
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
</div>
<% end %>
<% elsif field['type'] == 'cells' %>
<% cell_width = area['cell_w'] / area['w'] * 100 %>
<div class="w-full flex items-center">
Expand Down
8 changes: 7 additions & 1 deletion lib/submissions/generate_result_attachments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 333a5d6

Please sign in to comment.