11<template >
2- <div @click =" importCsv" class =" cursor-pointer flex gap-2 items-center" >
2+ <div @click =" handleImportClick"
3+ :class =" [
4+ 'cursor-pointer flex gap-2 items-center',
5+ checkProgress ? 'opacity-50 pointer-events-none' : ''
6+ ]" >
37 {{$t('Import from CSV')}}
4-
5- <svg v-if =" inProgress"
6- aria-hidden="true" class="w-4 h-4 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/><path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/></svg>
8+ </div >
9+ <div v-if =" checkProgress" class =" fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-20" >
10+ <div class =" flex flex-col items-center bg-white dark:bg-gray-800 p-6 rounded-lg shadow-lg" >
11+ <p class =" text-gray-700 dark:text-gray-300 text-sm" >{{ $t('Checking data...') }}</p >
12+ <svg aria-hidden="true" class="w-4 h-4 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/><path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/></svg>
13+ </div >
714 </div >
815 <Dialog ref =" confirmDialog" :header =" t('Import Confirmation')" :buttons =" computedButtons" >
916 <div v-if =" importStats" >
2936 <p >{{ $t('Would you like to proceed?') }}</p >
3037 </template >
3138 </div >
39+ <div v-if =" importProgress" class =" fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-20" >
40+ <div class =" flex flex-col items-center bg-white dark:bg-gray-800 p-6 rounded-lg shadow-lg" >
41+ <p class =" text-gray-700 dark:text-gray-300 text-sm" >{{ $t('Importing...') }}</p >
42+ <svg aria-hidden="true" class="w-4 h-4 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/><path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/></svg>
43+ </div >
44+ </div >
3245</Dialog >
3346</template >
3447
3548<script setup lang="ts">
36- import { ref , Ref , computed } from ' vue' ;
49+ import { ref , Ref , computed , watch } from ' vue' ;
3750import { callAdminForthApi } from ' @/utils' ;
3851import adminforth from ' @/adminforth' ;
3952import Papa from ' papaparse' ;
@@ -42,7 +55,8 @@ import { useI18n } from 'vue-i18n';
4255
4356const { t } = useI18n ();
4457
45- const inProgress: Ref <boolean > = ref (false );
58+ const importProgress: Ref <boolean > = ref (false );
59+ const checkProgress: Ref <boolean > = ref (false );
4660const confirmDialog = ref (null );
4761const importStats = ref (null );
4862const pendingData = ref (null );
@@ -64,33 +78,35 @@ const computedButtons = computed(() => {
6478 return buttons .filter (button => button .visible !== false );
6579});
6680async function confirmImport(dialog ) {
67- dialog .hide ();
6881 await postData (pendingData .value );
82+ dialog .hide ();
6983}
7084
7185async function checkRecords(data : Record <string , string []>) {
86+ checkProgress .value = true ;
7287 const resp = await callAdminForthApi ({
7388 path: ` /plugin/${props .meta .pluginInstanceId }/check-records ` ,
7489 method: ' POST' ,
7590 body: { data }
7691 });
77-
92+ checkProgress . value = false ;
7893 return resp ;
7994}
8095
8196async function confirmImportNewOnly(dialog ) {
82- dialog .hide ();
8397 await postDataNewOnly (pendingData .value );
98+ dialog .hide ();
8499}
85100
86101async function postData(data : Record <string , string []>, skipDuplicates : boolean = false ) {
102+ importProgress .value = true ;
87103 const resp = await callAdminForthApi ({
88104 path: ` /plugin/${props .meta .pluginInstanceId }/import-csv ` ,
89105 method: ' POST' ,
90106 body: { data }
91107 });
92108
93- inProgress .value = false ;
109+ importProgress .value = false ;
94110
95111 if (resp .importedCount > 0 || resp .updatedCount > 0 ) {
96112 adminforth .list .refresh ();
@@ -106,13 +122,14 @@ async function postData(data: Record<string, string[]>, skipDuplicates: boolean
106122}
107123
108124async function postDataNewOnly(data : Record <string , string []>) {
125+ importProgress .value = true ;
109126 const resp = await callAdminForthApi ({
110127 path: ` /plugin/${props .meta .pluginInstanceId }/import-csv-new-only ` ,
111128 method: ' POST' ,
112129 body: { data }
113130 });
114131
115- inProgress .value = false ;
132+ importProgress .value = false ;
116133 if (resp .importedCount > 0 ) {
117134 adminforth .list .refresh ();
118135 }
@@ -125,18 +142,15 @@ async function postDataNewOnly(data: Record<string, string[]>) {
125142}
126143
127144async function importCsv() {
128- inProgress .value = false ;
129145 const fileInput = document .createElement (' input' );
130146
131147 fileInput .type = ' file' ;
132148 fileInput .accept = ' .csv' ;
133149 fileInput .click ();
134150 fileInput .onchange = async (e ) => {
135- inProgress .value = true ;
136151
137152 const file = (e .target as HTMLInputElement ).files ?.[0 ];
138153 if (! file ) {
139- inProgress .value = false ;
140154 return ;
141155 }
142156 const reader = new FileReader ();
@@ -177,7 +191,6 @@ async function importCsv() {
177191 const stats = await checkRecords (data );
178192 importStats .value = stats ;
179193 confirmDialog .value ?.open ();
180- inProgress .value = false ;
181194 },
182195 error : (error ) => {
183196 adminforth .alert ({
@@ -188,7 +201,6 @@ async function importCsv() {
188201 }
189202 });
190203 } catch (error ) {
191- inProgress .value = false ;
192204 adminforth .alert ({
193205 message: ` Error processing CSV: ${error .message } ` ,
194206 variant: ' danger'
@@ -198,4 +210,10 @@ async function importCsv() {
198210 reader .readAsText (file );
199211 };
200212}
213+ function handleImportClick() {
214+ console .log (' handleImportClick' , checkProgress .value );
215+ if (! checkProgress .value ) {
216+ importCsv ();
217+ }
218+ }
201219 </script >
0 commit comments