Edit import excel
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
UiPagination,
|
||||
} from '@/components/ui';
|
||||
import UiIcon from '@/components/UiIcon.vue';
|
||||
import ExcelImportFlow from '@/components/ExcelImportFlow.vue';
|
||||
import ActivityFormView from '@/views/ActivityFormView.vue';
|
||||
import type {
|
||||
ActivityDto,
|
||||
@@ -78,7 +79,6 @@ const activityModal = ref<{
|
||||
const menuId = ref<string | null>(null);
|
||||
const busy = ref(false);
|
||||
const importMsg = ref('');
|
||||
const fileInput = ref<HTMLInputElement | null>(null);
|
||||
const counts = ref<Record<ActivityFilter, number>>({
|
||||
today: 0,
|
||||
overdue: 0,
|
||||
@@ -286,44 +286,31 @@ async function exportExcel() {
|
||||
}
|
||||
}
|
||||
|
||||
function pickImportFile() {
|
||||
fileInput.value?.click();
|
||||
}
|
||||
|
||||
async function onImportFile(ev: Event) {
|
||||
const input = ev.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
input.value = '';
|
||||
if (!file) return;
|
||||
function onImportStart() {
|
||||
busy.value = true;
|
||||
importMsg.value = '';
|
||||
error.value = '';
|
||||
try {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const { data } = await api.post<ImportContactsResult>('/activities/import', form, {
|
||||
headers: { 'Content-Type': undefined },
|
||||
});
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
await Promise.all([load(), loadCounts()]);
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
const msg = (e.response?.data as { message?: string | string[] })?.message;
|
||||
error.value = Array.isArray(msg) ? msg.join('، ') : (msg ?? 'ایمپورت ناموفق بود');
|
||||
} else {
|
||||
error.value = 'ایمپورت ناموفق بود';
|
||||
}
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
async function onImportDone(data: ImportContactsResult) {
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
await Promise.all([load(), loadCounts()]);
|
||||
}
|
||||
|
||||
function onImportFail(message: string) {
|
||||
error.value = message;
|
||||
}
|
||||
|
||||
function onImportSettled() {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -357,17 +344,20 @@ onMounted(() => {
|
||||
<span class="btn-full">خروجی اکسل</span>
|
||||
<span class="btn-short">خروجی</span>
|
||||
</UiButton>
|
||||
<UiButton variant="ghost" type="button" :disabled="busy" @click.stop="pickImportFile">
|
||||
<span class="btn-full">ورود از اکسل</span>
|
||||
<span class="btn-short">ورود</span>
|
||||
</UiButton>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
hidden
|
||||
@change="onImportFile"
|
||||
/>
|
||||
<ExcelImportFlow
|
||||
preview-path="/activities/import/preview"
|
||||
import-path="/activities/import"
|
||||
:disabled="busy"
|
||||
@start="onImportStart"
|
||||
@done="onImportDone"
|
||||
@fail="onImportFail"
|
||||
@settled="onImportSettled"
|
||||
>
|
||||
<UiButton variant="ghost" type="button" :disabled="busy">
|
||||
<span class="btn-full">ورود از اکسل</span>
|
||||
<span class="btn-short">ورود</span>
|
||||
</UiButton>
|
||||
</ExcelImportFlow>
|
||||
<UiButton variant="primary" @click="activityModal = {}">
|
||||
<UiIcon name="plus" :size="16" />
|
||||
فعالیت جدید
|
||||
|
||||
@@ -5,6 +5,7 @@ import axios from 'axios';
|
||||
import { api } from '@/lib/api';
|
||||
import { formatJalaliNumeric, toFaDigits } from '@/lib/jalali';
|
||||
import CustomerMoodFace from '@/components/CustomerMoodFace.vue';
|
||||
import ExcelImportFlow from '@/components/ExcelImportFlow.vue';
|
||||
import {
|
||||
UiButton,
|
||||
UiModal,
|
||||
@@ -52,7 +53,6 @@ const error = ref('');
|
||||
const importMsg = ref('');
|
||||
const people = ref<PaginatedResponse<PersonDto> | null>(null);
|
||||
const companies = ref<PaginatedResponse<CompanyDto> | null>(null);
|
||||
const fileInput = ref<HTMLInputElement | null>(null);
|
||||
const menuId = ref<string | null>(null);
|
||||
const sortOpen = ref(false);
|
||||
const filterOpen = ref(false);
|
||||
@@ -187,46 +187,38 @@ async function exportExcel() {
|
||||
}
|
||||
}
|
||||
|
||||
function pickImportFile() {
|
||||
fileInput.value?.click();
|
||||
}
|
||||
const importPreviewPath = computed(() =>
|
||||
tab.value === 'people' ? '/people/import/preview' : '/companies/import/preview',
|
||||
);
|
||||
const importPath = computed(() =>
|
||||
tab.value === 'people' ? '/people/import' : '/companies/import',
|
||||
);
|
||||
|
||||
async function onImportFile(ev: Event) {
|
||||
const input = ev.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
input.value = '';
|
||||
if (!file) return;
|
||||
function onImportStart() {
|
||||
busy.value = true;
|
||||
importMsg.value = '';
|
||||
error.value = '';
|
||||
try {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const path = tab.value === 'people' ? '/people/import' : '/companies/import';
|
||||
const { data } = await api.post<ImportContactsResult>(path, form, {
|
||||
headers: { 'Content-Type': undefined },
|
||||
});
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}`;
|
||||
if (data.errors.length) {
|
||||
const sample = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
error.value = sample;
|
||||
}
|
||||
await load();
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
const msg = (e.response?.data as { message?: string | string[] })?.message;
|
||||
error.value = Array.isArray(msg) ? msg.join('، ') : (msg ?? 'ایمپورت ناموفق بود');
|
||||
} else {
|
||||
error.value = 'ایمپورت ناموفق بود';
|
||||
}
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
async function onImportDone(data: ImportContactsResult) {
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
await load();
|
||||
}
|
||||
|
||||
function onImportFail(message: string) {
|
||||
error.value = message;
|
||||
}
|
||||
|
||||
function onImportSettled() {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
watch(
|
||||
@@ -251,17 +243,20 @@ onMounted(load);
|
||||
<span class="btn-full">خروجی اکسل</span>
|
||||
<span class="btn-short">خروجی</span>
|
||||
</UiButton>
|
||||
<UiButton variant="ghost" size="sm" :disabled="busy" @click.stop="pickImportFile">
|
||||
<span class="btn-full">ورود از اکسل</span>
|
||||
<span class="btn-short">ورود</span>
|
||||
</UiButton>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
hidden
|
||||
@change="onImportFile"
|
||||
/>
|
||||
<ExcelImportFlow
|
||||
:preview-path="importPreviewPath"
|
||||
:import-path="importPath"
|
||||
:disabled="busy"
|
||||
@start="onImportStart"
|
||||
@done="onImportDone"
|
||||
@fail="onImportFail"
|
||||
@settled="onImportSettled"
|
||||
>
|
||||
<UiButton variant="ghost" size="sm" :disabled="busy">
|
||||
<span class="btn-full">ورود از اکسل</span>
|
||||
<span class="btn-short">ورود</span>
|
||||
</UiButton>
|
||||
</ExcelImportFlow>
|
||||
<UiButton
|
||||
variant="primary"
|
||||
@click="contactModal = tab === 'companies' ? 'company' : 'person'"
|
||||
|
||||
@@ -196,12 +196,12 @@ onMounted(load);
|
||||
<form v-else class="crm-form" @submit.prevent="submit">
|
||||
<UiCard>
|
||||
<div class="crm-form-grid-2">
|
||||
<UiField label="نام" required for-id="firstName">
|
||||
<UiInput id="firstName" v-model="firstName" required />
|
||||
<UiField label="نام" for-id="firstName">
|
||||
<UiInput id="firstName" v-model="firstName" />
|
||||
</UiField>
|
||||
|
||||
<UiField label="نام خانوادگی" required for-id="lastName">
|
||||
<UiInput id="lastName" v-model="lastName" required />
|
||||
<UiField label="نام خانوادگی" for-id="lastName">
|
||||
<UiInput id="lastName" v-model="lastName" />
|
||||
</UiField>
|
||||
|
||||
<UiField label="موبایل" for-id="mobile">
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
moveStageToIndex,
|
||||
updateDealStage,
|
||||
} from '@/lib/pipeline-board';
|
||||
import ExcelImportFlow from '@/components/ExcelImportFlow.vue';
|
||||
import UiButton from '@/components/ui/UiButton.vue';
|
||||
import UiInput from '@/components/ui/UiInput.vue';
|
||||
import UiModal from '@/components/ui/UiModal.vue';
|
||||
@@ -47,7 +48,6 @@ const deleteStageId = ref<string | null>(null);
|
||||
const stageBusy = ref(false);
|
||||
const busy = ref(false);
|
||||
const importMsg = ref('');
|
||||
const fileInput = ref<HTMLInputElement | null>(null);
|
||||
|
||||
const draggingId = ref<string | null>(null);
|
||||
const draggingColumnId = ref<string | null>(null);
|
||||
@@ -390,43 +390,35 @@ async function exportExcel() {
|
||||
}
|
||||
}
|
||||
|
||||
function pickImportFile() {
|
||||
fileInput.value?.click();
|
||||
}
|
||||
|
||||
async function onImportFile(ev: Event) {
|
||||
const input = ev.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
input.value = '';
|
||||
if (!file) return;
|
||||
function onImportStart() {
|
||||
busy.value = true;
|
||||
importMsg.value = '';
|
||||
error.value = '';
|
||||
try {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const { data } = await api.post<ImportContactsResult>('/deals/import', form, {
|
||||
headers: { 'Content-Type': undefined },
|
||||
});
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}${data.boards?.length ? ` · کاریز: ${data.boards.join('، ')}` : ''}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
if (data.boardId && data.boardId !== selectedPipelineId.value) {
|
||||
await router.replace({ name: 'pipeline', query: { pipelineId: data.boardId } });
|
||||
} else {
|
||||
await load();
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = apiMessage(e, 'ایمپورت ناموفق بود');
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
async function onImportDone(data: ImportContactsResult) {
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}${data.boards?.length ? ` · کاریز: ${data.boards.join('، ')}` : ''}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
if (data.boardId && data.boardId !== selectedPipelineId.value) {
|
||||
await router.replace({ name: 'pipeline', query: { pipelineId: data.boardId } });
|
||||
} else {
|
||||
await load();
|
||||
}
|
||||
}
|
||||
|
||||
function onImportFail(message: string) {
|
||||
error.value = message;
|
||||
}
|
||||
|
||||
function onImportSettled() {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
function onMenuDeal(dealId: string) {
|
||||
@@ -472,16 +464,19 @@ defineExpose({ updateDealStage: applyUpdateDealStage });
|
||||
<button class="btn-ghost-sm" type="button" :disabled="loading || busy" @click="exportExcel">
|
||||
خروجی اکسل
|
||||
</button>
|
||||
<button class="btn-ghost-sm" type="button" :disabled="loading || busy" @click="pickImportFile">
|
||||
ورود از اکسل
|
||||
</button>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
hidden
|
||||
@change="onImportFile"
|
||||
/>
|
||||
<ExcelImportFlow
|
||||
preview-path="/deals/import/preview"
|
||||
import-path="/deals/import"
|
||||
:disabled="loading || busy"
|
||||
@start="onImportStart"
|
||||
@done="onImportDone"
|
||||
@fail="onImportFail"
|
||||
@settled="onImportSettled"
|
||||
>
|
||||
<button class="btn-ghost-sm" type="button" :disabled="loading || busy">
|
||||
ورود از اکسل
|
||||
</button>
|
||||
</ExcelImportFlow>
|
||||
</template>
|
||||
</PipelineToolbar>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
UiPagination,
|
||||
UiSelect,
|
||||
} from '@/components/ui';
|
||||
import ExcelImportFlow from '@/components/ExcelImportFlow.vue';
|
||||
import UiIcon from '@/components/UiIcon.vue';
|
||||
import ProductFormView from '@/views/ProductFormView.vue';
|
||||
import type { ImportContactsResult, ProductDto } from '@mento/shared';
|
||||
@@ -41,7 +42,6 @@ const moreOpen = ref(false);
|
||||
const productModal = ref(false);
|
||||
const busy = ref(false);
|
||||
const importMsg = ref('');
|
||||
const fileInput = ref<HTMLInputElement | null>(null);
|
||||
|
||||
const categories = computed(() => {
|
||||
const set = new Set<string>();
|
||||
@@ -187,45 +187,32 @@ async function exportExcel() {
|
||||
}
|
||||
}
|
||||
|
||||
function pickImportFile() {
|
||||
function onImportStart() {
|
||||
closeMenus();
|
||||
fileInput.value?.click();
|
||||
}
|
||||
|
||||
async function onImportFile(ev: Event) {
|
||||
const input = ev.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
input.value = '';
|
||||
if (!file) return;
|
||||
busy.value = true;
|
||||
importMsg.value = '';
|
||||
error.value = '';
|
||||
try {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const { data } = await api.post<ImportContactsResult>('/products/import', form, {
|
||||
headers: { 'Content-Type': undefined },
|
||||
});
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
await load();
|
||||
} catch (e) {
|
||||
error.value = axios.isAxiosError(e)
|
||||
? String(
|
||||
(e.response?.data as { message?: string | string[] })?.message ??
|
||||
'ایمپورت ناموفق بود',
|
||||
)
|
||||
: 'ایمپورت ناموفق بود';
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
async function onImportDone(data: ImportContactsResult) {
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
await load();
|
||||
}
|
||||
|
||||
function onImportFail(message: string) {
|
||||
error.value = message;
|
||||
}
|
||||
|
||||
function onImportSettled() {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
async function toggleActive(product: ProductDto) {
|
||||
@@ -270,16 +257,17 @@ onMounted(load);
|
||||
<UiButton variant="ghost" type="button" :disabled="busy" @click="exportExcel">
|
||||
خروجی اکسل
|
||||
</UiButton>
|
||||
<UiButton variant="ghost" type="button" :disabled="busy" @click="pickImportFile">
|
||||
ورود از اکسل
|
||||
</UiButton>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
hidden
|
||||
@change="onImportFile"
|
||||
/>
|
||||
<ExcelImportFlow
|
||||
preview-path="/products/import/preview"
|
||||
import-path="/products/import"
|
||||
:disabled="busy"
|
||||
@start="onImportStart"
|
||||
@done="onImportDone"
|
||||
@fail="onImportFail"
|
||||
@settled="onImportSettled"
|
||||
>
|
||||
<UiButton variant="ghost" type="button" :disabled="busy">ورود از اکسل</UiButton>
|
||||
</ExcelImportFlow>
|
||||
<UiButton variant="primary" @click="productModal = true">
|
||||
<UiIcon name="plus" :size="16" />
|
||||
محصول جدید
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
moveStageToIndex,
|
||||
updateDealStage,
|
||||
} from '@/lib/pipeline-board';
|
||||
import ExcelImportFlow from '@/components/ExcelImportFlow.vue';
|
||||
import UiButton from '@/components/ui/UiButton.vue';
|
||||
import UiInput from '@/components/ui/UiInput.vue';
|
||||
import UiModal from '@/components/ui/UiModal.vue';
|
||||
@@ -50,7 +51,6 @@ const deleteStageId = ref<string | null>(null);
|
||||
const stageBusy = ref(false);
|
||||
const busy = ref(false);
|
||||
const importMsg = ref('');
|
||||
const fileInput = ref<HTMLInputElement | null>(null);
|
||||
|
||||
const draggingId = ref<string | null>(null);
|
||||
const draggingColumnId = ref<string | null>(null);
|
||||
@@ -387,45 +387,35 @@ async function exportExcel() {
|
||||
}
|
||||
}
|
||||
|
||||
function pickImportFile() {
|
||||
fileInput.value?.click();
|
||||
}
|
||||
|
||||
async function onImportFile(ev: Event) {
|
||||
const input = ev.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
input.value = '';
|
||||
if (!file) return;
|
||||
function onImportStart() {
|
||||
busy.value = true;
|
||||
importMsg.value = '';
|
||||
error.value = '';
|
||||
try {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
const { data } = await api.post<ImportContactsResult>(
|
||||
'/project-cards/import',
|
||||
form,
|
||||
{ headers: { 'Content-Type': undefined } },
|
||||
);
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}${data.boards?.length ? ` · برد: ${data.boards.join('، ')}` : ''}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
if (data.boardId && data.boardId !== selectedBoardId.value) {
|
||||
await router.replace({ name: 'projects', query: { boardId: data.boardId } });
|
||||
} else {
|
||||
await load();
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = apiMessage(e, 'ایمپورت ناموفق بود');
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
async function onImportDone(data: ImportContactsResult) {
|
||||
importMsg.value = `وارد شد: ${data.created} · تکراری رد شد: ${data.skipped}${
|
||||
data.errors.length ? ` · خطا: ${data.errors.length}` : ''
|
||||
}${data.boards?.length ? ` · برد: ${data.boards.join('، ')}` : ''}`;
|
||||
if (data.errors.length) {
|
||||
error.value = data.errors
|
||||
.slice(0, 3)
|
||||
.map((e) => `ردیف ${e.row}: ${e.message}`)
|
||||
.join(' | ');
|
||||
}
|
||||
if (data.boardId && data.boardId !== selectedBoardId.value) {
|
||||
await router.replace({ name: 'projects', query: { boardId: data.boardId } });
|
||||
} else {
|
||||
await load();
|
||||
}
|
||||
}
|
||||
|
||||
function onImportFail(message: string) {
|
||||
error.value = message;
|
||||
}
|
||||
|
||||
function onImportSettled() {
|
||||
busy.value = false;
|
||||
}
|
||||
|
||||
function onMenuCard(cardId: string) {
|
||||
@@ -470,16 +460,19 @@ onBeforeUnmount(() => {
|
||||
<button class="btn-ghost-sm" type="button" :disabled="loading || busy" @click="exportExcel">
|
||||
خروجی اکسل
|
||||
</button>
|
||||
<button class="btn-ghost-sm" type="button" :disabled="loading || busy" @click="pickImportFile">
|
||||
ورود از اکسل
|
||||
</button>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
hidden
|
||||
@change="onImportFile"
|
||||
/>
|
||||
<ExcelImportFlow
|
||||
preview-path="/project-cards/import/preview"
|
||||
import-path="/project-cards/import"
|
||||
:disabled="loading || busy"
|
||||
@start="onImportStart"
|
||||
@done="onImportDone"
|
||||
@fail="onImportFail"
|
||||
@settled="onImportSettled"
|
||||
>
|
||||
<button class="btn-ghost-sm" type="button" :disabled="loading || busy">
|
||||
ورود از اکسل
|
||||
</button>
|
||||
</ExcelImportFlow>
|
||||
</template>
|
||||
</PipelineToolbar>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user