Skip to content

Commit b3e72f0

Browse files
authored
Merge from docusealco/wip
2 parents 9011e3f + 700ebc4 commit b3e72f0

28 files changed

+1925
-157
lines changed

Dockerfile

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ FROM ruby:3.4.2-alpine AS app
4747
ENV RAILS_ENV=production
4848
ENV BUNDLE_WITHOUT="development:test"
4949
ENV LD_PRELOAD=/lib/libgcompat.so.0
50-
ENV OPENSSL_CONF=/app/openssl_legacy.cnf
50+
ENV OPENSSL_CONF=/etc/openssl_legacy.cnf
5151

5252
WORKDIR /app
5353

@@ -65,36 +65,35 @@ legacy = legacy_sect\n\
6565
activate = 1\n\
6666
\n\
6767
[legacy_sect]\n\
68-
activate = 1' >> /app/openssl_legacy.cnf
68+
activate = 1' >> /etc/openssl_legacy.cnf
6969

70-
COPY ./Gemfile ./Gemfile.lock ./
70+
COPY --chown=docuseal:docuseal ./Gemfile ./Gemfile.lock ./
7171

7272
RUN apk add --no-cache build-base && bundle install && apk del --no-cache build-base && rm -rf ~/.bundle /usr/local/bundle/cache && ruby -e "puts Dir['/usr/local/bundle/**/{spec,rdoc,resources/shared,resources/collation,resources/locales}']" | xargs rm -rf && ln -sf /usr/lib/libonnxruntime.so.1 $(ruby -e "print Dir[Gem::Specification.find_by_name('onnxruntime').gem_dir + '/vendor/*.so'].first")
7373

7474
RUN echo 'https://dl-cdn.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories && echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache onnxruntime
7575

76-
COPY ./bin ./bin
77-
COPY ./app ./app
78-
COPY ./config ./config
79-
COPY ./db/migrate ./db/migrate
80-
COPY ./log ./log
81-
COPY ./lib ./lib
82-
COPY ./public ./public
83-
COPY ./tmp ./tmp
84-
COPY LICENSE README.md Rakefile config.ru .version ./
85-
COPY .version ./public/version
86-
87-
COPY --from=download /fonts/GoNotoKurrent-Regular.ttf /fonts/GoNotoKurrent-Bold.ttf /fonts/DancingScript-Regular.otf /fonts/OFL.txt /fonts
76+
COPY --chown=docuseal:docuseal ./bin ./bin
77+
COPY --chown=docuseal:docuseal ./app ./app
78+
COPY --chown=docuseal:docuseal ./config ./config
79+
COPY --chown=docuseal:docuseal ./db/migrate ./db/migrate
80+
COPY --chown=docuseal:docuseal ./log ./log
81+
COPY --chown=docuseal:docuseal ./lib ./lib
82+
COPY --chown=docuseal:docuseal ./public ./public
83+
COPY --chown=docuseal:docuseal ./tmp ./tmp
84+
COPY --chown=docuseal:docuseal LICENSE README.md Rakefile config.ru .version ./
85+
COPY --chown=docuseal:docuseal .version ./public/version
86+
87+
COPY --chown=docuseal:docuseal --from=download /fonts/GoNotoKurrent-Regular.ttf /fonts/GoNotoKurrent-Bold.ttf /fonts/DancingScript-Regular.otf /fonts/OFL.txt /fonts
8888
COPY --from=download /fonts/FreeSans.ttf /usr/share/fonts/freefont
8989
COPY --from=download /pdfium-linux/lib/libpdfium.so /usr/lib/libpdfium.so
9090
COPY --from=download /pdfium-linux/licenses/pdfium.txt /usr/lib/libpdfium-LICENSE.txt
91-
COPY --from=download /model.onnx /app/tmp/model.onnx
92-
COPY --from=webpack /app/public/packs ./public/packs
91+
COPY --chown=docuseal:docuseal --from=download /model.onnx /app/tmp/model.onnx
92+
COPY --chown=docuseal:docuseal --from=webpack /app/public/packs ./public/packs
9393

94-
RUN ln -s /fonts /app/public/fonts
95-
RUN bundle exec bootsnap precompile -j 1 --gemfile app/ lib/
96-
97-
RUN chown -R docuseal:docuseal /app
94+
RUN ln -s /fonts /app/public/fonts && \
95+
bundle exec bootsnap precompile -j 1 --gemfile app/ lib/ && \
96+
chown -R docuseal:docuseal /app/tmp/cache
9897

9998
WORKDIR /data/docuseal
10099
ENV HOME=/home/docuseal

app/controllers/templates_detect_fields_controller.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ def create
1111
sse = SSE.new(response.stream)
1212

1313
documents = @template.schema_documents.preload(:blob)
14+
documents = documents.where(uuid: params[:attachment_uuid]) if params[:attachment_uuid].present?
15+
16+
page_number = params[:page].present? ? params[:page].to_i : nil
1417

1518
documents.each do |document|
1619
io = StringIO.new(document.download)
1720

18-
Templates::DetectFields.call(io, attachment: document) do |(attachment_uuid, page, fields)|
21+
Templates::DetectFields.call(io, attachment: document, page_number:) do |(attachment_uuid, page, fields)|
1922
sse.write({ attachment_uuid:, page:, fields: })
2023
end
2124
end

app/javascript/submission_form/form.vue

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,17 +1244,31 @@ export default {
12441244
} else if (['equal', 'contains'].includes(condition.action) && field) {
12451245
if (field.options) {
12461246
const option = field.options.find((o) => o.uuid === condition.value)
1247-
const values = [this.values[condition.field_uuid] ?? defaultValue].flat()
12481247
1249-
return values.includes(this.optionValue(option, field.options.indexOf(option)))
1248+
if (option) {
1249+
const values = [this.values[condition.field_uuid] ?? defaultValue].flat()
1250+
1251+
return values.includes(this.optionValue(option, field.options.indexOf(option)))
1252+
} else {
1253+
return false
1254+
}
12501255
} else {
12511256
return [this.values[condition.field_uuid] ?? defaultValue].flat().includes(condition.value)
12521257
}
12531258
} else if (['not_equal', 'does_not_contain'].includes(condition.action) && field) {
1254-
const option = field.options.find((o) => o.uuid === condition.value)
1255-
const values = [this.values[condition.field_uuid] ?? defaultValue].flat()
1259+
if (field.options) {
1260+
const option = field.options.find((o) => o.uuid === condition.value)
12561261
1257-
return !values.includes(this.optionValue(option, field.options.indexOf(option)))
1262+
if (option) {
1263+
const values = [this.values[condition.field_uuid] ?? defaultValue].flat()
1264+
1265+
return !values.includes(this.optionValue(option, field.options.indexOf(option)))
1266+
} else {
1267+
return false
1268+
}
1269+
} else {
1270+
return false
1271+
}
12581272
} else {
12591273
return true
12601274
}

app/javascript/template_builder/area.vue

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
@touchstart="startTouchDrag"
99
>
1010
<div
11-
v-if="isSelected || isDraw"
11+
v-if="isSelected || isDraw || isInMultiSelection"
1212
class="top-0 bottom-0 right-0 left-0 absolute border border-1.5 pointer-events-none"
1313
:class="activeBorderClasses"
1414
/>
@@ -24,15 +24,15 @@
2424
:style="{ left: (cellW / area.w * 100) + '%' }"
2525
>
2626
<span
27-
v-if="index === 0 && editable"
27+
v-if="index === 0 && editable && !isInMultiSelection"
2828
class="h-2.5 w-2.5 rounded-full -bottom-1 border-gray-400 bg-white shadow-md border absolute cursor-ew-resize z-10"
2929
style="left: -4px"
3030
@mousedown.stop="startResizeCell"
3131
/>
3232
</div>
3333
</div>
3434
<div
35-
v-if="field?.type && (isSelected || isNameFocus)"
35+
v-if="field?.type && (isSelected || isNameFocus) && !isInMultiSelection"
3636
class="absolute bg-white rounded-t border overflow-visible whitespace-nowrap flex z-10 field-area-controls"
3737
style="top: -25px; height: 25px"
3838
@mousedown.stop
@@ -48,7 +48,7 @@
4848
:menu-classes="'dropdown-content bg-white menu menu-xs p-2 shadow rounded-box w-52 rounded-t-none -left-[1px] mt-[1px]'"
4949
:submitters="template.submitters"
5050
@update:model-value="save"
51-
@click="selectedAreaRef.value = area"
51+
@click="selectedAreasRef.value = [area]"
5252
/>
5353
<FieldType
5454
v-model="field.type"
@@ -57,7 +57,7 @@
5757
:button-classes="'px-1'"
5858
:menu-classes="'bg-white rounded-t-none'"
5959
@update:model-value="[maybeUpdateOptions(), save()]"
60-
@click="selectedAreaRef.value = area"
60+
@click="selectedAreasRef.value = [area]"
6161
/>
6262
<span
6363
v-if="field.type !== 'checkbox' || field.name"
@@ -146,7 +146,7 @@
146146
@click-font="isShowFontModal = true"
147147
@click-description="isShowDescriptionModal = true"
148148
@click-condition="isShowConditionsModal = true"
149-
@scroll-to="[selectedAreaRef.value = $event, $emit('scroll-to', $event)]"
149+
@scroll-to="[selectedAreasRef.value = [$event], $emit('scroll-to', $event)]"
150150
/>
151151
</ul>
152152
</span>
@@ -266,7 +266,7 @@
266266
ref="defaultValueSelect"
267267
class="bg-transparent outline-none focus:outline-none w-full"
268268
@change="[field.default_value = $event.target.value, field.readonly = !!field.default_value?.length, save()]"
269-
@focus="selectedAreaRef.value = area"
269+
@focus="selectedAreasRef.value = [area]"
270270
@keydown.enter="onDefaultValueEnter"
271271
>
272272
<option
@@ -293,7 +293,7 @@
293293
:class="{ 'cursor-text': isValueInput }"
294294
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : (field.type === 'date' ? field.preferences?.format || t('type_value') : t('type_value'))"
295295
@blur="onDefaultValueBlur"
296-
@focus="selectedAreaRef.value = area"
296+
@focus="selectedAreasRef.value = [area]"
297297
@paste.prevent="onPaste"
298298
@keydown.enter="onDefaultValueEnter"
299299
>{{ field.default_value }}</span>
@@ -319,6 +319,7 @@
319319
<span
320320
v-if="field?.type && editable"
321321
class="h-4 w-4 lg:h-2.5 lg:w-2.5 -right-1 rounded-full -bottom-1 border-gray-400 bg-white shadow-md border absolute cursor-nwse-resize"
322+
:class="{ 'z-30': isInMultiSelection }"
322323
@mousedown.stop="startResize"
323324
@touchstart="startTouchResize"
324325
/>
@@ -398,7 +399,7 @@ export default {
398399
FieldSubmitter,
399400
IconX
400401
},
401-
inject: ['template', 'selectedAreaRef', 'save', 't', 'isInlineSize'],
402+
inject: ['template', 'save', 't', 'isInlineSize', 'selectedAreasRef', 'isCmdKeyRef'],
402403
props: {
403404
area: {
404405
type: Object,
@@ -463,6 +464,11 @@ export default {
463464
type: Object,
464465
required: false,
465466
default: null
467+
},
468+
isSelectMode: {
469+
type: Boolean,
470+
required: false,
471+
default: false
466472
}
467473
},
468474
emits: ['start-resize', 'stop-resize', 'start-drag', 'stop-drag', 'remove', 'scroll-to'],
@@ -646,7 +652,10 @@ export default {
646652
]
647653
},
648654
isSelected () {
649-
return this.selectedAreaRef.value === this.area
655+
return this.selectedAreasRef.value.includes(this.area)
656+
},
657+
isInMultiSelection () {
658+
return this.selectedAreasRef.value.length >= 2 && this.isSelected
650659
},
651660
positionStyle () {
652661
const { x, y, w, h } = this.area
@@ -683,10 +692,10 @@ export default {
683692
buildAreaOptionValue (area) {
684693
const option = this.optionsUuidIndex[area.option_uuid]
685694
686-
return option.value || `${this.t('option')} ${this.field.options.indexOf(option) + 1}`
695+
return option?.value || `${this.t('option')} ${this.field.options.indexOf(option) + 1}`
687696
},
688697
maybeToggleDefaultValue () {
689-
if (!this.editable) {
698+
if (!this.editable || this.isCmdKeyRef.value) {
690699
return
691700
}
692701
@@ -770,7 +779,7 @@ export default {
770779
}
771780
},
772781
onNameFocus (e) {
773-
this.selectedAreaRef.value = this.area
782+
this.selectedAreasRef.value = [this.area]
774783
775784
this.isNameFocus = true
776785
this.$refs.name.style.minWidth = this.$refs.name.clientWidth + 'px'
@@ -906,6 +915,15 @@ export default {
906915
if (e.target.id === 'mask') {
907916
this.area.w = e.offsetX / e.target.clientWidth - this.area.x
908917
this.area.h = e.offsetY / e.target.clientHeight - this.area.y
918+
919+
if (this.isInMultiSelection) {
920+
this.selectedAreasRef.value.forEach((area) => {
921+
if (area !== this.area) {
922+
area.w = this.area.w
923+
area.h = this.area.h
924+
}
925+
})
926+
}
909927
}
910928
},
911929
drag (e) {
@@ -931,7 +949,7 @@ export default {
931949
932950
const rect = e.target.getBoundingClientRect()
933951
934-
this.selectedAreaRef.value = this.area
952+
this.selectedAreasRef.value = [this.area]
935953
936954
this.dragFrom = { x: rect.left - e.touches[0].clientX, y: rect.top - e.touches[0].clientY }
937955
@@ -980,13 +998,23 @@ export default {
980998
981999
e.preventDefault()
9821000
1001+
if (e.metaKey || e.ctrlKey) {
1002+
if (!this.selectedAreasRef.value.includes(this.area)) {
1003+
this.selectedAreasRef.value.push(this.area)
1004+
} else {
1005+
this.selectedAreasRef.value.splice(this.selectedAreasRef.value.indexOf(this.area), 1)
1006+
}
1007+
1008+
return
1009+
}
1010+
9831011
if (this.editable) {
9841012
this.isDragged = true
9851013
}
9861014
9871015
const rect = e.target.getBoundingClientRect()
9881016
989-
this.selectedAreaRef.value = this.area
1017+
this.selectedAreasRef.value = [this.area]
9901018
9911019
this.dragFrom = { x: rect.left - e.clientX, y: rect.top - e.clientY }
9921020
@@ -1055,7 +1083,9 @@ export default {
10551083
this.$emit('stop-drag')
10561084
},
10571085
startResize () {
1058-
this.selectedAreaRef.value = this.area
1086+
if (!this.selectedAreasRef.value.includes(this.area)) {
1087+
this.selectedAreasRef.value = [this.area]
1088+
}
10591089
10601090
this.$el.getRootNode().addEventListener('mousemove', this.resize)
10611091
this.$el.getRootNode().addEventListener('mouseup', this.stopResize)
@@ -1071,7 +1101,9 @@ export default {
10711101
this.save()
10721102
},
10731103
startTouchResize (e) {
1074-
this.selectedAreaRef.value = this.area
1104+
if (!this.selectedAreasRef.value.includes(this.area)) {
1105+
this.selectedAreasRef.value = [this.area]
1106+
}
10751107
10761108
this.$refs?.name?.blur()
10771109
@@ -1088,6 +1120,15 @@ export default {
10881120
10891121
this.area.w = (e.touches[0].clientX - rect.left) / rect.width - this.area.x
10901122
this.area.h = (e.touches[0].clientY - rect.top) / rect.height - this.area.y
1123+
1124+
if (this.isInMultiSelection) {
1125+
this.selectedAreasRef.value.forEach((area) => {
1126+
if (area !== this.area) {
1127+
area.w = this.area.w
1128+
area.h = this.area.h
1129+
}
1130+
})
1131+
}
10911132
},
10921133
stopTouchResize () {
10931134
this.$el.getRootNode().removeEventListener('touchmove', this.touchResize)

0 commit comments

Comments
 (0)