2
0
mirror of https://github.com/frappe/books.git synced 2024-11-10 07:40:55 +00:00

feat(ui): add a loading element

This commit is contained in:
18alantom 2022-03-01 14:16:12 +05:30 committed by Alan
parent e1389184ed
commit 3d175f1730
3 changed files with 111 additions and 7 deletions

View File

@ -0,0 +1,63 @@
<template>
<div
class="absolute bottom-0 flex justify-end pb-6 pr-6"
style="width: calc(100% - 12rem)"
v-if="open && !close"
>
<div
class="
text-gray-900
shadow-lg
px-3
py-3
items-center
w-96
z-10
bg-white
rounded-lg
"
v-if="true"
>
<p class="text-base text-gray-600 pb-2" v-if="message.length">{{ message }}</p>
<div class="w-full flex flex-row items-center">
<div class="w-full bg-gray-200 h-3 mr-2 rounded">
<div
class="h-3 rounded bg-blue-400"
:style="{ width: `${percent * 100}%` }"
></div>
</div>
<feather-icon
name="x"
class="
w-4
h-4
ml-auto
text-gray-600
cursor-pointer
hover:text-gray-800
"
@click="closeToast"
/>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
open: { type: Boolean, default: false },
percent: { type: Number, default: 0.5 },
message: { type: String, default: '' },
},
data() {
return {
close: false,
};
},
methods: {
closeToast() {
this.close = true;
},
},
};
</script>

View File

@ -35,6 +35,12 @@ type LabelTemplateFieldMap = {
[key: string]: TemplateField;
};
type LoadingStatusCallback = (
isMakingEntries: boolean,
entriesMade: number,
totalEntries: number
) => void;
interface TemplateField {
label: string;
fieldname: string;
@ -354,11 +360,15 @@ export class Importer {
return Object.keys(docMap).map((k) => docMap[k]);
}
async importData(): Promise<Status> {
async importData(setLoadingStatus: LoadingStatusCallback): Promise<Status> {
const status: Status = { success: false, names: [], message: '' };
const shouldDeleteName = await isNameAutoSet(this.doctype);
const docObjs = this.getDocs();
for (const docObj of this.getDocs()) {
let entriesMade = 0;
setLoadingStatus(true, 0, docObjs.length);
for (const docObj of docObjs) {
if (shouldDeleteName) {
delete docObj.name;
}
@ -378,7 +388,10 @@ export class Importer {
if (this.shouldSubmit) {
await doc.submit();
}
entriesMade += 1;
setLoadingStatus(true, entriesMade, docObjs.length);
} catch (err) {
setLoadingStatus(false, entriesMade, docObjs.length);
const messages = [
frappe.t`Could not import ${this.doctype} ${doc.name}.`,
];
@ -405,6 +418,7 @@ export class Importer {
status.names.push(doc.name);
}
setLoadingStatus(false, entriesMade, docObjs.length);
status.success = true;
return status;
}

View File

@ -1,5 +1,5 @@
<template>
<div class="flex flex-col overflow-hidden">
<div class="flex flex-col overflow-hidden w-full">
<PageHeader>
<template #title>
<h1 class="text-2xl font-bold">
@ -212,7 +212,14 @@
:key="'matrix-row-' + i"
>
<button
class="w-4 h-4 text-gray-600 hover:text-gray-900 cursor-pointer outline-none"
class="
w-4
h-4
text-gray-600
hover:text-gray-900
cursor-pointer
outline-none
"
@click="
() => {
importer.dropRow(i);
@ -306,12 +313,18 @@
</div>
<div
v-if="!importType"
class="flex justify-center h-full items-center mb-16"
class="flex justify-center h-full w-full items-center mb-16"
>
<HowTo link="https://youtu.be/ukHAgcnVxTQ">
{{ t`How to Use Data Import?` }}
</HowTo>
</div>
<Loading
v-if="openLoading"
:open="openLoading"
:percent="percentLoading"
:message="messageLoading"
/>
</div>
</template>
<script>
@ -326,6 +339,7 @@ import { IPC_ACTIONS } from '@/messages';
import { getSavePath, saveData, showMessageDialog } from '@/utils';
import { ipcRenderer } from 'electron';
import frappe from 'frappe';
import Loading from '../components/Loading.vue';
export default {
components: {
PageHeader,
@ -334,6 +348,7 @@ export default {
DropdownWithActions,
FeatherIcon,
HowTo,
Loading,
},
data() {
return {
@ -343,6 +358,9 @@ export default {
file: null,
importer: null,
importType: '',
openLoading: false,
percentLoading: 0,
messageLoading: '',
};
},
computed: {
@ -446,7 +464,7 @@ export default {
if (!this.complete) {
return;
}
this.clear();
},
methods: {
@ -533,7 +551,9 @@ export default {
return;
}
const { success, names, message } = await this.importer.importData();
const { success, names, message } = await this.importer.importData(
this.setLoadingStatus
);
if (!success) {
showMessageDialog({
message: this.t`Import Failed`,
@ -552,6 +572,13 @@ export default {
this.importType = importType;
this.importer = new Importer(this.labelDoctypeMap[this.importType]);
},
setLoadingStatus(isMakingEntries, entriesMade, totalEntries) {
this.openLoading = isMakingEntries;
this.percentLoading = entriesMade / totalEntries;
this.messageLoading = isMakingEntries
? `${entriesMade} entries made out of ${totalEntries}...`
: '';
},
async selectFile() {
const options = {
title: this.t`Select File`,