Tidy up import data modal and change to be a detail popover
This commit is contained in:
parent
c110cb628d
commit
dae550c21e
|
@ -1,17 +1,91 @@
|
|||
<script>
|
||||
import { ActionButton, Modal } from "@budibase/bbui"
|
||||
import ImportModal from "../modals/ImportModal.svelte"
|
||||
import {
|
||||
ActionButton,
|
||||
Label,
|
||||
Button,
|
||||
Body,
|
||||
Layout,
|
||||
notifications,
|
||||
} from "@budibase/bbui"
|
||||
import DetailPopover from "components/common/DetailPopover.svelte"
|
||||
import TableDataImport from "components/backend/TableNavigator/TableDataImport.svelte"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { API } from "api"
|
||||
|
||||
export let tableId
|
||||
export let tableType
|
||||
export let disabled
|
||||
|
||||
let modal
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let popover
|
||||
let rows = []
|
||||
let allValid = false
|
||||
let displayColumn = null
|
||||
let identifierFields = []
|
||||
let loading = false
|
||||
|
||||
const openPopover = () => {
|
||||
rows = []
|
||||
allValid = false
|
||||
displayColumn = null
|
||||
identifierFields = []
|
||||
loading = false
|
||||
popover.show()
|
||||
}
|
||||
|
||||
const importData = async () => {
|
||||
try {
|
||||
loading = true
|
||||
await API.importTableData({
|
||||
tableId,
|
||||
rows,
|
||||
identifierFields,
|
||||
})
|
||||
notifications.success("Rows successfully imported")
|
||||
popover.hide()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
notifications.error("Unable to import data")
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
|
||||
// Always refresh rows just to be sure
|
||||
dispatch("importrows")
|
||||
}
|
||||
</script>
|
||||
|
||||
<ActionButton icon="DataUpload" quiet on:click={modal.show} {disabled}>
|
||||
Import
|
||||
</ActionButton>
|
||||
<Modal bind:this={modal}>
|
||||
<ImportModal {tableId} {tableType} on:importrows />
|
||||
</Modal>
|
||||
<DetailPopover title="Import data" bind:this={popover}>
|
||||
<svelte:fragment slot="anchor" let:open>
|
||||
<ActionButton
|
||||
icon="DataUpload"
|
||||
quiet
|
||||
on:click={openPopover}
|
||||
{disabled}
|
||||
selected={open}
|
||||
>
|
||||
Import
|
||||
</ActionButton>
|
||||
</svelte:fragment>
|
||||
<Body size="S">
|
||||
Import rows to an existing table from a CSV or JSON file. Only columns from
|
||||
the file which exist in the table will be imported.
|
||||
</Body>
|
||||
<Layout gap="XS" noPadding>
|
||||
<Label grey extraSmall>CSV or JSON file to import</Label>
|
||||
<TableDataImport
|
||||
{tableId}
|
||||
{tableType}
|
||||
bind:rows
|
||||
bind:allValid
|
||||
bind:displayColumn
|
||||
bind:identifierFields
|
||||
/>
|
||||
</Layout>
|
||||
<div>
|
||||
<Button cta disabled={loading || !allValid} on:click={importData}>
|
||||
Import
|
||||
</Button>
|
||||
</div>
|
||||
</DetailPopover>
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
<script>
|
||||
import {
|
||||
ModalContent,
|
||||
Label,
|
||||
notifications,
|
||||
Body,
|
||||
Layout,
|
||||
} from "@budibase/bbui"
|
||||
import TableDataImport from "../../TableNavigator/ExistingTableDataImport.svelte"
|
||||
import { API } from "api"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
export let tableId
|
||||
export let tableType
|
||||
|
||||
let rows = []
|
||||
let allValid = false
|
||||
let displayColumn = null
|
||||
let identifierFields = []
|
||||
|
||||
async function importData() {
|
||||
try {
|
||||
await API.importTableData({
|
||||
tableId,
|
||||
rows,
|
||||
identifierFields,
|
||||
})
|
||||
notifications.success("Rows successfully imported")
|
||||
} catch (error) {
|
||||
notifications.error("Unable to import data")
|
||||
}
|
||||
|
||||
// Always refresh rows just to be sure
|
||||
dispatch("importrows")
|
||||
}
|
||||
</script>
|
||||
|
||||
<ModalContent
|
||||
title="Import Data"
|
||||
confirmText="Import"
|
||||
onConfirm={importData}
|
||||
disabled={!allValid}
|
||||
>
|
||||
<Body size="S">
|
||||
Import rows to an existing table from a CSV or JSON file. Only columns from
|
||||
the file which exist in the table will be imported.
|
||||
</Body>
|
||||
<Layout gap="XS" noPadding>
|
||||
<Label grey extraSmall>CSV or JSON file to import</Label>
|
||||
<TableDataImport
|
||||
{tableId}
|
||||
{tableType}
|
||||
bind:rows
|
||||
bind:allValid
|
||||
bind:displayColumn
|
||||
bind:identifierFields
|
||||
/>
|
||||
</Layout>
|
||||
</ModalContent>
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Select, Icon } from "@budibase/bbui"
|
||||
import { Select, Icon, Layout } from "@budibase/bbui"
|
||||
import { FIELDS } from "constants/backend"
|
||||
import { utils } from "@budibase/shared-core"
|
||||
import { canBeDisplayColumn } from "@budibase/frontend-core"
|
||||
|
@ -184,70 +184,71 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="dropzone">
|
||||
<input
|
||||
bind:this={fileInput}
|
||||
disabled={loading}
|
||||
id="file-upload"
|
||||
accept="text/csv,application/json"
|
||||
type="file"
|
||||
on:change={handleFile}
|
||||
/>
|
||||
<label for="file-upload" class:uploaded={rawRows.length > 0}>
|
||||
{#if error}
|
||||
Error: {error}
|
||||
{:else if fileName}
|
||||
{fileName}
|
||||
{:else}
|
||||
Upload
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
{#if rawRows.length > 0 && !error}
|
||||
<div class="schema-fields">
|
||||
{#each Object.entries(schema) as [name, column]}
|
||||
<div class="field">
|
||||
<span>{column.name}</span>
|
||||
<Select
|
||||
bind:value={selectedColumnTypes[column.name]}
|
||||
on:change={e => handleChange(name, e)}
|
||||
options={Object.values(typeOptions)}
|
||||
placeholder={null}
|
||||
getOptionLabel={option => option.label}
|
||||
getOptionValue={option => option.value}
|
||||
/>
|
||||
<span
|
||||
class={validation[column.name]
|
||||
? "fieldStatusSuccess"
|
||||
: "fieldStatusFailure"}
|
||||
>
|
||||
{#if validation[column.name]}
|
||||
Success
|
||||
{:else}
|
||||
Failure
|
||||
{#if errors[column.name]}
|
||||
<Icon name="Help" tooltip={errors[column.name]} />
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
<Icon
|
||||
size="S"
|
||||
name="Close"
|
||||
hoverable
|
||||
on:click={() => deleteColumn(column.name)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
<Layout noPadding gap="S">
|
||||
<div class="dropzone">
|
||||
<input
|
||||
bind:this={fileInput}
|
||||
disabled={loading}
|
||||
id="file-upload"
|
||||
accept="text/csv,application/json"
|
||||
type="file"
|
||||
on:change={handleFile}
|
||||
/>
|
||||
<label for="file-upload" class:uploaded={rawRows.length > 0}>
|
||||
{#if error}
|
||||
Error: {error}
|
||||
{:else if fileName}
|
||||
{fileName}
|
||||
{:else}
|
||||
Upload
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
<div class="display-column">
|
||||
|
||||
{#if rawRows.length > 0 && !error}
|
||||
<div>
|
||||
{#each Object.entries(schema) as [name, column]}
|
||||
<div class="field">
|
||||
<span>{column.name}</span>
|
||||
<Select
|
||||
bind:value={selectedColumnTypes[column.name]}
|
||||
on:change={e => handleChange(name, e)}
|
||||
options={Object.values(typeOptions)}
|
||||
placeholder={null}
|
||||
getOptionLabel={option => option.label}
|
||||
getOptionValue={option => option.value}
|
||||
/>
|
||||
<span
|
||||
class={validation[column.name]
|
||||
? "fieldStatusSuccess"
|
||||
: "fieldStatusFailure"}
|
||||
>
|
||||
{#if validation[column.name]}
|
||||
Success
|
||||
{:else}
|
||||
Failure
|
||||
{#if errors[column.name]}
|
||||
<Icon name="Help" tooltip={errors[column.name]} />
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
<Icon
|
||||
size="S"
|
||||
name="Close"
|
||||
hoverable
|
||||
on:click={() => deleteColumn(column.name)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<Select
|
||||
label="Display Column"
|
||||
bind:value={displayColumn}
|
||||
options={displayColumnOptions}
|
||||
sort
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.dropzone {
|
||||
|
@ -269,7 +270,6 @@
|
|||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
border-radius: var(--border-radius-s);
|
||||
color: var(--ink);
|
||||
padding: var(--spacing-m) var(--spacing-l);
|
||||
transition: all 0.2s ease 0s;
|
||||
display: inline-flex;
|
||||
|
@ -283,20 +283,14 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
background-color: var(--grey-2);
|
||||
font-size: var(--font-size-xs);
|
||||
background-color: var(--spectrum-global-color-gray-300);
|
||||
font-size: var(--font-size-s);
|
||||
line-height: normal;
|
||||
border: var(--border-transparent);
|
||||
}
|
||||
|
||||
.uploaded {
|
||||
color: var(--blue);
|
||||
color: var(--spectrum-global-color-blue-600);
|
||||
}
|
||||
|
||||
.schema-fields {
|
||||
margin-top: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.field {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 2fr 1fr auto;
|
||||
|
@ -322,8 +316,4 @@
|
|||
.fieldStatusFailure :global(.spectrum-Icon) {
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.display-column {
|
||||
margin-top: var(--spacing-xl);
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue