1010 class =" proposal-modal__content"
1111 :title =" modalTitle"
1212 :size =" modalSize"
13+ :close-button-contained =" false"
14+ :can-close =" !operationInProgress"
1315 @close =" onModalClose()" >
16+ <!-- Loading overlay -->
17+ <div v-if =" operationInProgress" class =" proposal-editor__loading-overlay" >
18+ <NcLoadingIcon :size =" 64" />
19+ <p >{{ operationMessage }}</p >
20+ </div >
21+
1422 <!-- Show proposal viewer -->
1523 <div v-if =" modalMode === 'view'" class =" proposal-viewer__content" >
1624 <div class =" proposal-viewer__content-title" >
@@ -260,6 +268,7 @@ import DeleteIcon from 'vue-material-design-icons/TrashCanOutline'
260268// components
261269import NcButton from ' @nextcloud/vue/components/NcButton'
262270import NcCheckboxRadioSwitch from ' @nextcloud/vue/components/NcCheckboxRadioSwitch'
271+ import NcLoadingIcon from ' @nextcloud/vue/components/NcLoadingIcon'
263272import NcModal from ' @nextcloud/vue/components/NcModal'
264273import NcTextArea from ' @nextcloud/vue/components/NcTextArea'
265274import NcTextField from ' @nextcloud/vue/components/NcTextField'
@@ -300,6 +309,7 @@ export default {
300309 components: {
301310 NcButton ,
302311 NcCheckboxRadioSwitch ,
312+ NcLoadingIcon ,
303313 NcModal ,
304314 NcTextField ,
305315 NcTextArea ,
@@ -338,6 +348,8 @@ export default {
338348 calendarSpanMin: 1 , // Minimum days that can be shown
339349 calendarSpanDays: 7 , // Currently applied span (derived)
340350 screenWidth: window .innerWidth , // Track screen width
351+ operationInProgress: false , // Lock to prevent concurrent operations
352+ operationMessage: ' ' , // Message to display during operation
341353 }
342354 },
343355
@@ -583,36 +595,60 @@ export default {
583595 },
584596
585597 async onProposalDestroy(proposal : Proposal ) {
598+ if (this .operationInProgress ) {
599+ return
600+ }
601+
586602 if (! confirm (t (' calendar' , ' Are you sure you want to delete "{title}"?' , { title: proposal .title ?? t (' calendar' , ' No title' ) }))) {
587603 return
588604 }
605+
606+ this .operationInProgress = true
607+ this .operationMessage = t (' calendar' , ' Deleting proposal...' )
608+
589609 try {
590- showSuccess (t (' calendar' , ' Deleting proposal "{title}"' , { title: proposal .title ?? t (' calendar' , ' No title' ) }))
591610 await this .proposalStore .destroyProposal (proposal )
592611 showSuccess (t (' calendar' , ' Successfully deleted proposal' ))
593612 this .onModalClose ()
594613 } catch (error ) {
595614 showError (t (' calendar' , ' Failed to delete proposal' ))
596615 console .error (' Failed to delete proposal:' , error )
616+ } finally {
617+ this .operationInProgress = false
618+ this .operationMessage = ' '
597619 }
598620 },
599621
600622 async onProposalSave() {
623+ if (this .operationInProgress ) {
624+ return
625+ }
626+
627+ if (! this .selectedProposal ) {
628+ return console .error (' No proposal selected for this operation' )
629+ }
630+
631+ this .operationInProgress = true
632+ this .operationMessage = t (' calendar' , ' Saving proposal...' )
633+
601634 try {
602- if (! this .selectedProposal ) {
603- return console .error (' No proposal selected for this operation' )
604- }
605- showSuccess (t (' calendar' , ' Saving proposal "{title}"' , { title: this .selectedProposal .title ?? t (' calendar' , ' No title' ) }))
606635 await this .proposalStore .storeProposal (this .selectedProposal )
607636 showSuccess (t (' calendar' , ' Successfully saved proposal' ))
608637 this .onModalClose ()
609638 } catch (error ) {
610639 showError (t (' calendar' , ' Failed to save proposal' ))
611640 console .error (' Failed to save proposal:' , error )
641+ } finally {
642+ this .operationInProgress = false
643+ this .operationMessage = ' '
612644 }
613645 },
614646
615647 async onProposalConvert(date : ProposalDate ) {
648+ if (this .operationInProgress ) {
649+ return
650+ }
651+
616652 if (! this .selectedProposal || ! date .date ) {
617653 return console .error (' No proposal selected or invalid date for meeting conversion' )
618654 }
@@ -623,14 +659,19 @@ export default {
623659 return
624660 }
625661
662+ this .operationInProgress = true
663+ this .operationMessage = t (' calendar' , ' Creating meeting...' )
664+
626665 try {
627- showSuccess (t (' calendar' , ' Creating meeting for {date}' , { date: dateString }))
628666 await this .proposalStore .convertProposal (this .selectedProposal , date , this .userTimezone )
629667 showSuccess (t (' calendar' , ' Successfully created meeting for {date}' , { date: dateString }))
630668 this .onModalClose ()
631669 } catch (error ) {
632670 showError (t (' calendar' , ' Failed to create a meeting for {date}' , { date: dateString }))
633671 console .error (' Failed to create a meeting:' , error )
672+ } finally {
673+ this .operationInProgress = false
674+ this .operationMessage = ' '
634675 }
635676 },
636677
@@ -1220,4 +1261,34 @@ export default {
12201261 /* Override background with striped pattern for better visibility */
12211262 background-image : repeating-linear-gradient (45deg , transparent 0px , transparent calc (var (--default-grid-baseline ) * 1 ), var (--color-background-hover ) calc (var (--default-grid-baseline ) * 1 ), var (--color-background-hover ) calc (var (--default-grid-baseline ) * 4 )) !important ;
12221263}
1264+
1265+ .proposal-editor__loading-overlay {
1266+ position : absolute ;
1267+ top : 0 ;
1268+ left : 0 ;
1269+ right : 0 ;
1270+ bottom : 0 ;
1271+ background-color : rgba (255 , 255 , 255 , 0.95 );
1272+ display : flex ;
1273+ flex-direction : column ;
1274+ align-items : center ;
1275+ justify-content : center ;
1276+ gap : calc (var (--default-grid-baseline ) * 4 );
1277+ z-index : 10000 ;
1278+ border-radius : var (--border-radius-large );
1279+
1280+ p {
1281+ font-size : calc (var (--default-grid-baseline ) * 4 );
1282+ font-weight : 500 ;
1283+ color : var (--color-text-primary );
1284+ margin : 0 ;
1285+ }
1286+ }
1287+
1288+ // Dark mode support
1289+ @media (prefers-color-scheme : dark ) {
1290+ .proposal-editor__loading-overlay {
1291+ background-color : rgba (0 , 0 , 0 , 0.95 );
1292+ }
1293+ }
12231294 </style >
0 commit comments