Skip to content

Commit 03d74fa

Browse files
authored
Merge pull request #6068 from LibreSign/backport/6066/stable32
[stable32] feat: improve signature request workflow
2 parents fc77a48 + 8bc42ad commit 03d74fa

3 files changed

Lines changed: 163 additions & 89 deletions

File tree

src/Components/Request/VisibleElements.vue

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@
4040
</Signer>
4141
</ul>
4242
<NcButton v-if="canSave"
43-
:variant="variantOfRequestButton"
43+
:variant="variantOfSaveButton"
4444
:wide="true"
4545
:class="{ disabled: signerSelected }"
46-
@click="showConfirm = true">
47-
{{ t('libresign', 'Request') }}
46+
@click="isDraft ? save() : showConfirm = true">
47+
{{ isDraft ? t('libresign', 'Save') : t('libresign', 'Send') }}
4848
</NcButton>
4949

5050
<NcButton v-if="canSign"
@@ -66,7 +66,7 @@
6666
:open.sync="showConfirm"
6767
:name="t('libresign', 'Confirm')"
6868
:no-close="loading"
69-
:message="t('libresign', 'Request signatures?')">
69+
:message="t('libresign', 'Send signature request?')">
7070
<NcNoteCard v-if="errorConfirmRequest.length > 0"
7171
type="error">
7272
{{ errorConfirmRequest }}
@@ -78,11 +78,12 @@
7878
</NcButton>
7979
<NcButton variant="primary"
8080
:disabled="loading"
81-
@click="save">
81+
@click="request">
8282
<template #icon>
8383
<NcLoadingIcon v-if="loading" :size="20" name="Loading" />
84+
<Send v-else :size="20" />
8485
</template>
85-
{{ t('libresign', 'Request') }}
86+
{{ t('libresign', 'Send') }}
8687
</NcButton>
8788
</template>
8889
</NcDialog>
@@ -92,7 +93,7 @@
9293
<script>
9394
import axios from '@nextcloud/axios'
9495
import { getCapabilities } from '@nextcloud/capabilities'
95-
import { showSuccess } from '@nextcloud/dialogs'
96+
import { showSuccess, showError } from '@nextcloud/dialogs'
9697
import { subscribe, unsubscribe, emit } from '@nextcloud/event-bus'
9798
import { loadState } from '@nextcloud/initial-state'
9899
import { generateOcsUrl } from '@nextcloud/router'
@@ -102,6 +103,8 @@ import NcDialog from '@nextcloud/vue/components/NcDialog'
102103
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
103104
import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
104105
106+
import Send from 'vue-material-design-icons/Send.vue'
107+
105108
import Chip from '../Chip.vue'
106109
import PdfEditor from '../PdfEditor/PdfEditor.vue'
107110
import Signer from '../Signers/Signer.vue'
@@ -119,6 +122,7 @@ export default {
119122
NcButton,
120123
NcLoadingIcon,
121124
PdfEditor,
125+
Send,
122126
},
123127
setup() {
124128
const filesStore = useFilesStore()
@@ -137,7 +141,7 @@ export default {
137141
}
138142
},
139143
computed: {
140-
variantOfRequestButton() {
144+
variantOfSaveButton() {
141145
if (this.canSave) {
142146
return 'primary'
143147
}
@@ -281,17 +285,50 @@ export default {
281285
}))
282286
},
283287
async goToSign() {
284-
// after save, the document is no more acessible by this way,
285-
// this is the reason to retain the UUID before save action
286288
const uuid = this.document.settings.signerFileUuid
287289
if (await this.save()) {
288290
const route = this.$router.resolve({ name: 'SignPDF', params: { uuid } })
289291
window.location.href = route.href
290292
}
291293
},
292294
async save() {
295+
this.loading = true
296+
const visibleElements = this.buildVisibleElements()
297+
298+
try {
299+
const response = await this.filesStore.saveWithVisibleElements({ visibleElements })
300+
showSuccess(t('libresign', response.message))
301+
this.closeModal()
302+
emit('libresign:visible-elements-saved')
303+
this.loading = false
304+
return true
305+
} catch (error) {
306+
showError(error.response?.data?.ocs?.data?.message || t('libresign', 'An error occurred'))
307+
this.loading = false
308+
return false
309+
}
310+
},
311+
async request() {
293312
this.loading = true
294313
this.errorConfirmRequest = ''
314+
const visibleElements = this.buildVisibleElements()
315+
316+
try {
317+
const response = await this.filesStore.requestSignaturesWithVisibleElements({ visibleElements })
318+
this.filesStore.addFile(response.data)
319+
this.showConfirm = false
320+
showSuccess(t('libresign', response.message))
321+
this.closeModal()
322+
emit('libresign:visible-elements-saved')
323+
this.loading = false
324+
return true
325+
} catch (error) {
326+
this.errorConfirmRequest = error.response?.data?.ocs?.data?.message || t('libresign', 'An error occurred')
327+
this.loading = false
328+
return false
329+
}
330+
},
331+
buildVisibleElements() {
295332
const visibleElements = []
296333
const scale = this.$refs.pdfEditor.$refs.vuePdfEditor.scale || 1
297334
Object.entries(this.$refs.pdfEditor.$refs.vuePdfEditor.allObjects).forEach(entry => {
@@ -315,28 +352,7 @@ export default {
315352
})
316353
})
317354
}, this)
318-
return await axios.patch(generateOcsUrl('/apps/libresign/api/v1/request-signature'), {
319-
users: this.filesStore.getFile().signers,
320-
// Only add to array if not empty
321-
...(this.filesStore.getFile().uuid && { uuid: this.filesStore.getFile().uuid }),
322-
...(this.filesStore.getFile().nodeId && { file: { fileId: this.filesStore.getFile().nodeId } }),
323-
visibleElements,
324-
status: 1,
325-
})
326-
.then(({ data }) => {
327-
this.filesStore.addFile(data.ocs.data.data)
328-
this.showConfirm = false
329-
showSuccess(t('libresign', data.ocs.data.message))
330-
this.closeModal()
331-
emit('libresign:visible-elements-saved')
332-
this.loading = false
333-
return true
334-
})
335-
.catch(({ response }) => {
336-
this.errorConfirmRequest = response?.data?.ocs?.data?.message || 'An error occurred'
337-
this.loading = false
338-
return false
339-
})
355+
return visibleElements
340356
},
341357
},
342358
}

src/Components/RightSidebar/RequestSignatureTab.vue

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,33 @@
3030
</template>
3131
</Signers>
3232
<div class="action-buttons">
33-
<NcButton v-if="filesStore.canSave()"
33+
<NcButton v-if="showSaveButton"
3434
:variant="filesStore.canSign() ? 'secondary' : 'primary'"
3535
:disabled="hasLoading"
3636
@click="save()">
3737
<template #icon>
3838
<NcLoadingIcon v-if="hasLoading" :size="20" />
39+
<Pencil v-else-if="isSignElementsAvailable()" :size="20" />
3940
</template>
40-
{{ labelOfSaveButton }}
41+
{{ isSignElementsAvailable() ? t('libresign', 'Edit visible signatures') : t('libresign', 'Save') }}
42+
</NcButton>
43+
<NcButton v-if="showRequestButton"
44+
:variant="filesStore.canSign() ? 'secondary' : 'primary'"
45+
:disabled="hasLoading"
46+
@click="request()">
47+
<template #icon>
48+
<NcLoadingIcon v-if="hasLoading" :size="20" />
49+
<Send v-else :size="20" />
50+
</template>
51+
{{ t('libresign', 'Send') }}
4152
</NcButton>
4253
<NcButton v-if="filesStore.canSign()"
4354
variant="primary"
4455
:disabled="hasLoading"
4556
@click="sign()">
4657
<template #icon>
4758
<NcLoadingIcon v-if="hasLoading" :size="20" />
59+
<Draw v-else :size="20" />
4860
</template>
4961
{{ t('libresign', 'Sign') }}
5062
</NcButton>
@@ -54,6 +66,9 @@
5466
{{ t('libresign', 'Validate') }}
5567
</NcButton>
5668
<NcButton @click="openFile()">
69+
<template #icon>
70+
<FileDocument :size="20" />
71+
</template>
5772
{{ t('libresign', 'Open file') }}
5873
</NcButton>
5974
</div>
@@ -97,6 +112,10 @@ import svgWhatsapp from '@mdi/svg/svg/whatsapp.svg?raw'
97112
import svgXmpp from '@mdi/svg/svg/xmpp.svg?raw'
98113
99114
import Delete from 'vue-material-design-icons/Delete.vue'
115+
import Draw from 'vue-material-design-icons/Draw.vue'
116+
import FileDocument from 'vue-material-design-icons/FileDocument.vue'
117+
import Pencil from 'vue-material-design-icons/Pencil.vue'
118+
import Send from 'vue-material-design-icons/Send.vue'
100119
101120
import axios from '@nextcloud/axios'
102121
import { getCapabilities } from '@nextcloud/capabilities'
@@ -120,6 +139,7 @@ import Signers from '../Signers/Signers.vue'
120139
121140
import svgSignal from '../../../img/logo-signal-app.svg?raw'
122141
import svgTelegram from '../../../img/logo-telegram-app.svg?raw'
142+
import { SIGN_STATUS } from '../../domains/sign/enum.js'
123143
import router from '../../router/router.js'
124144
import { useFilesStore } from '../../store/files.js'
125145
import { useSidebarStore } from '../../store/sidebar.js'
@@ -147,6 +167,10 @@ export default {
147167
NcModal,
148168
NcDialog,
149169
Delete,
170+
Draw,
171+
FileDocument,
172+
Pencil,
173+
Send,
150174
Signers,
151175
IdentifySigner,
152176
VisibleElements,
@@ -174,15 +198,28 @@ export default {
174198
}
175199
},
176200
computed: {
177-
labelOfSaveButton() {
201+
showSaveButton() {
202+
if (!this.filesStore.canSave()) {
203+
return false
204+
}
178205
179-
if (this.filesStore.canSign()) {
180-
return t('libresign', 'Edit visible signatures')
206+
if (!this.isSignElementsAvailable()) {
207+
return false
181208
}
182-
if (this.isSignElementsAvailable()) {
183-
return t('libresign', 'Next')
209+
210+
const file = this.filesStore.getFile()
211+
212+
if (file.status === SIGN_STATUS.PARTIAL_SIGNED || file.status === SIGN_STATUS.SIGNED) {
213+
return false
214+
}
215+
216+
return true
217+
},
218+
showRequestButton() {
219+
if (!this.filesStore.canSave()) {
220+
return false
184221
}
185-
return t('libresign', 'Request')
222+
return this.hasSigners
186223
},
187224
hasSigners() {
188225
return this.filesStore.hasSigners(this.filesStore.getFile())
@@ -274,59 +311,30 @@ export default {
274311
},
275312
async save() {
276313
this.hasLoading = true
277-
const config = {
278-
url: generateOcsUrl('/apps/libresign/api/v1/request-signature'),
279-
data: {
280-
name: this.filesStore.getFile()?.name,
281-
users: [],
282-
},
283-
};
284-
(this.filesStore.getFile()?.signers ?? []).forEach(signer => {
285-
const user = {
286-
displayName: signer.displayName,
287-
identify: {},
314+
try {
315+
await this.filesStore.saveWithVisibleElements({ visibleElements: [] })
316+
emit('libresign:show-visible-elements')
317+
} catch (error) {
318+
if (error.response?.data?.ocs?.data?.message) {
319+
showError(error.response.data.ocs.data.message)
320+
} else if (error.response?.data?.ocs?.data?.errors) {
321+
error.response.data.ocs.data.errors.forEach(error => showError(error.message))
288322
}
289-
signer.identifyMethods.forEach(method => {
290-
user.notify = false
291-
if (method.method === 'account') {
292-
user.identify.account = method?.value?.id ?? method?.value ?? signer.uid
293-
} else if (method.method === 'email') {
294-
user.identify.email = method?.value?.id ?? method?.value ?? signer.email
295-
} else {
296-
user.identify[method.method] = method.value
297-
}
298-
})
299-
config.data.users.push(user)
300-
})
301-
if (this.filesStore.getFile()?.status) {
302-
config.data.status = this.filesStore.getFile()?.status
303-
} else if (!this.isSignElementsAvailable()) {
304-
config.data.status = 1
305-
} else {
306-
config.data.status = 0
307323
}
308-
309-
if (this.filesStore.getFile().uuid) {
310-
config.data.uuid = this.filesStore.getFile().uuid
311-
config.method = 'patch'
312-
} else {
313-
config.data.file = {
314-
fileId: this.filesStore.selectedNodeId,
324+
this.hasLoading = false
325+
},
326+
async request() {
327+
this.hasLoading = true
328+
try {
329+
const response = await this.filesStore.requestSignaturesWithVisibleElements({ visibleElements: [] })
330+
showSuccess(t('libresign', response.message))
331+
} catch (error) {
332+
if (error.response?.data?.ocs?.data?.message) {
333+
showError(error.response.data.ocs.data.message)
334+
} else if (error.response?.data?.ocs?.data?.errors) {
335+
error.response.data.ocs.data.errors.forEach(error => showError(error.message))
315336
}
316-
config.method = 'post'
317337
}
318-
await axios(config)
319-
.then(({ data }) => {
320-
this.filesStore.addFile(data.ocs.data.data)
321-
emit('libresign:show-visible-elements')
322-
})
323-
.catch(({ response }) => {
324-
if (response?.data?.ocs?.data?.message) {
325-
showError(response.data.ocs.data.message)
326-
} else if (response?.data?.ocs?.data?.errors) {
327-
response.data.ocs.data.errors.forEach(error => showError(error.message))
328-
}
329-
})
330338
this.hasLoading = false
331339
},
332340
openFile() {

0 commit comments

Comments
 (0)