1515 @click =" addSigner" >
1616 {{ t('libresign', 'Add signer') }}
1717 </NcButton >
18+ <NcCheckboxRadioSwitch v-if =" showPreserveOrder"
19+ v-model =" preserveOrder"
20+ type =" switch"
21+ @update:checked =" onPreserveOrderChange" >
22+ {{ t('libresign', 'Preserve signing order') }}
23+ </NcCheckboxRadioSwitch >
24+ <NcButton v-if =" showViewOrderButton"
25+ type =" tertiary"
26+ @click =" showOrderDiagram = true" >
27+ <template #icon >
28+ <ChartGantt :size =" 20" />
29+ </template >
30+ {{ t('libresign', 'View signing order') }}
31+ </NcButton >
1832 <Signers event =" libresign:edit-signer"
1933 @signing-order-changed =" debouncedSave" >
2034 <template #actions =" {signer , closeActions } " >
192206 </NcButton >
193207 </template >
194208 </NcDialog >
209+ <NcDialog v-if =" showOrderDiagram"
210+ :name =" t('libresign', 'Signing order diagram')"
211+ size =" large"
212+ @closing =" showOrderDiagram = false" >
213+ <SigningOrderDiagram :signers =" filesStore.getFile()?.signers || []"
214+ :sender-name =" currentUserDisplayName" />
215+ <template #actions >
216+ <NcButton @click =" showOrderDiagram = false" >
217+ {{ t('libresign', 'Close') }}
218+ </NcButton >
219+ </template >
220+ </NcDialog >
195221 </div >
196222</template >
197223<script >
@@ -200,11 +226,13 @@ import debounce from 'debounce'
200226
201227import svgAccount from ' @mdi/svg/svg/account.svg?raw'
202228import svgEmail from ' @mdi/svg/svg/email.svg?raw'
229+ import svgInfo from ' @mdi/svg/svg/information-outline.svg?raw'
203230import svgSms from ' @mdi/svg/svg/message-processing.svg?raw'
204231import svgWhatsapp from ' @mdi/svg/svg/whatsapp.svg?raw'
205232import svgXmpp from ' @mdi/svg/svg/xmpp.svg?raw'
206233
207234import Bell from ' vue-material-design-icons/Bell.vue'
235+ import ChartGantt from ' vue-material-design-icons/ChartGantt.vue'
208236import Delete from ' vue-material-design-icons/Delete.vue'
209237import Draw from ' vue-material-design-icons/Draw.vue'
210238import FileDocument from ' vue-material-design-icons/FileDocument.vue'
@@ -227,15 +255,17 @@ import NcActions from '@nextcloud/vue/components/NcActions'
227255import NcAppSidebar from ' @nextcloud/vue/components/NcAppSidebar'
228256import NcAppSidebarTab from ' @nextcloud/vue/components/NcAppSidebarTab'
229257import NcButton from ' @nextcloud/vue/components/NcButton'
258+ import NcCheckboxRadioSwitch from ' @nextcloud/vue/components/NcCheckboxRadioSwitch'
230259import NcDialog from ' @nextcloud/vue/components/NcDialog'
231260import NcIconSvgWrapper from ' @nextcloud/vue/components/NcIconSvgWrapper'
232261import NcLoadingIcon from ' @nextcloud/vue/components/NcLoadingIcon'
233262import NcModal from ' @nextcloud/vue/components/NcModal'
234263import NcNoteCard from ' @nextcloud/vue/components/NcNoteCard'
235264
236265import IdentifySigner from ' ../Request/IdentifySigner.vue'
237- import VisibleElements from ' ../Request/VisibleElements.vue'
238266import Signers from ' ../Signers/Signers.vue'
267+ import SigningOrderDiagram from ' ../SigningOrder/SigningOrderDiagram.vue'
268+ import VisibleElements from ' ../Request/VisibleElements.vue'
239269
240270import svgSignal from ' ../../../img/logo-signal-app.svg?raw'
241271import svgTelegram from ' ../../../img/logo-telegram-app.svg?raw'
@@ -262,28 +292,31 @@ export default {
262292 name: ' RequestSignatureTab' ,
263293 mixins: [signingOrderMixin],
264294 components: {
295+ Bell,
296+ ChartGantt,
297+ Delete,
298+ Draw,
299+ FileDocument,
300+ IdentifySigner,
301+ Information,
302+ MessageText,
265303 NcActionButton,
266304 NcActionInput,
267305 NcActions,
268306 NcAppSidebar,
269307 NcAppSidebarTab,
270308 NcButton,
309+ NcCheckboxRadioSwitch,
310+ NcDialog,
271311 NcIconSvgWrapper,
272312 NcLoadingIcon,
273313 NcModal,
274314 NcNoteCard,
275- NcDialog,
276- Bell,
277- Delete,
278- Draw,
279- FileDocument,
280- Information,
281- MessageText,
282315 OrderNumericAscending,
283316 Pencil,
284317 Send,
285318 Signers,
286- IdentifySigner ,
319+ SigningOrderDiagram ,
287320 VisibleElements,
288321 },
289322 props: {
@@ -311,23 +344,61 @@ export default {
311344 showConfirmRequestSigner: false ,
312345 selectedSigner: null ,
313346 activeTab: ' ' ,
347+ preserveOrder: false ,
348+ showOrderDiagram: false ,
349+ infoIcon: svgInfo,
350+ adminSignatureFlow: ' ' ,
351+ lastSyncedFileId: null ,
314352 }
315353 },
316354 computed: {
317355 signatureFlow () {
318356 const file = this .filesStore .getFile ()
319- return file? .signatureFlow ?? ' parallel'
357+ let flow = file? .signatureFlow
358+
359+ if (typeof flow === ' number' ) {
360+ const flowMap = { 0 : ' none' , 1 : ' parallel' , 2 : ' ordered_numeric' }
361+ flow = flowMap[flow]
362+ }
363+
364+ if (flow && flow !== ' none' ) {
365+ return flow
366+ }
367+ if (this .adminSignatureFlow && this .adminSignatureFlow !== ' none' ) {
368+ return this .adminSignatureFlow
369+ }
370+ return ' parallel'
371+ },
372+ isAdminFlowForced () {
373+ return this .adminSignatureFlow && this .adminSignatureFlow !== ' none'
320374 },
321375 isOrderedNumeric () {
322376 return this .signatureFlow === ' ordered_numeric'
323377 },
378+ showSigningOrderOptions () {
379+ return this .hasSigners && this .filesStore .canSave () && ! this .isAdminFlowForced
380+ },
381+ showPreserveOrder () {
382+ return this .hasSigners && this .filesStore .canSave () && ! this .isAdminFlowForced
383+ },
384+ showViewOrderButton () {
385+ return this .isOrderedNumeric && this .totalSigners > 1 && this .hasSigners
386+ },
387+ shouldShowOrderedOptions () {
388+ return this .isOrderedNumeric && this .totalSigners > 1
389+ },
390+ currentUserDisplayName () {
391+ return OC .getCurrentUser ()? .displayName || ' '
392+ },
324393 showDocMdpWarning () {
325394 return this .filesStore .isDocMdpNoChangesAllowed () && ! this .filesStore .canAddSigner ()
326395 },
327396 canEditSigningOrder () {
328397 return (signer ) => {
398+ const minSigners = this .isAdminFlowForced ? 1 : 2
399+
329400 return this .isOrderedNumeric
330- && this .totalSigners > 1
401+ && this .totalSigners >= minSigners
331402 && this .filesStore .canSave ()
332403 && ! signer .signed
333404 }
@@ -490,12 +561,25 @@ export default {
490561 signers (signers ) {
491562 this .init (signers)
492563 },
564+ ' filesStore.selectedNodeId' : {
565+ handler (newFileId , oldFileId ) {
566+ if (newFileId && newFileId !== this .lastSyncedFileId ) {
567+ this .syncPreserveOrderWithFile ()
568+ this .lastSyncedFileId = newFileId
569+ }
570+ },
571+ immediate: true ,
572+ },
493573 },
494574 async mounted () {
495575 subscribe (' libresign:edit-signer' , this .editSigner )
496576 this .filesStore .disableIdentifySigner ()
497577
498578 this .activeTab = this .userConfigStore .signer_identify_tab || ' '
579+
580+ this .adminSignatureFlow = loadState (' libresign' , ' signature_flow' , ' none' )
581+
582+ this .syncPreserveOrderWithFile ()
499583 },
500584 beforeUnmount () {
501585 unsubscribe (' libresign:edit-signer' )
@@ -506,7 +590,11 @@ export default {
506590
507591 this .debouncedSave = debounce (async () => {
508592 try {
509- await this .filesStore .saveWithVisibleElements ({ visibleElements: [] })
593+ const file = this .filesStore .getFile ()
594+ await this .filesStore .saveWithVisibleElements ({
595+ visibleElements: [],
596+ signatureFlow: file? .signatureFlow ,
597+ })
510598 } catch (error) {
511599 if (error .response ? .data ? .ocs ? .data ? .message ) {
512600 showError (error .response .data .ocs .data .message )
@@ -521,6 +609,56 @@ export default {
521609 }, 500 )
522610 },
523611 methods: {
612+ onPreserveOrderChange (value ) {
613+ this .preserveOrder = value
614+ const file = this .filesStore .getFile ()
615+
616+ if (value) {
617+ if (file? .signers ) {
618+ file .signers .forEach ((signer , index ) => {
619+ if (! signer .signingOrder ) {
620+ this .$set (signer, ' signingOrder' , index + 1 )
621+ }
622+ })
623+ }
624+ if (file) {
625+ this .$set (file, ' signatureFlow' , ' ordered_numeric' )
626+ }
627+ } else {
628+ if (! this .isAdminFlowForced ) {
629+ if (file? .signers ) {
630+ file .signers .forEach (signer => {
631+ if (! signer .signed ) {
632+ this .$set (signer, ' signingOrder' , 1 )
633+ }
634+ })
635+ }
636+ if (file) {
637+ this .$set (file, ' signatureFlow' , ' parallel' )
638+ }
639+ }
640+ }
641+
642+ this .debouncedSave ()
643+ },
644+
645+ syncPreserveOrderWithFile () {
646+ const file = this .filesStore .getFile ()
647+ if (! file) {
648+ this .preserveOrder = false
649+ return
650+ }
651+
652+ const flow = file .signatureFlow
653+
654+ this .lastSyncedFileId = this .filesStore .selectedNodeId
655+
656+ if ((flow === ' ordered_numeric' || flow === 2 ) && ! this .isAdminFlowForced ) {
657+ this .preserveOrder = true
658+ } else {
659+ this .preserveOrder = false
660+ }
661+ },
524662 getSvgIcon (name ) {
525663 return iconMap[` svg${ name .charAt (0 ).toUpperCase () + name .slice (1 )} ` ] || iconMap .svgAccount
526664 },
@@ -789,6 +927,10 @@ export default {
789927< / script>
790928< style lang= " scss" scoped>
791929
930+ : deep (.checkbox - radio - switch ) {
931+ margin: 8px 0 ;
932+ }
933+
792934.action - buttons {
793935 display: flex;
794936 flex- direction: column;
0 commit comments