adding nice loading states
This commit is contained in:
parent
140233960e
commit
3a460429a0
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
import { fade } from "svelte/transition"
|
||||||
import fsort from "fast-sort"
|
import fsort from "fast-sort"
|
||||||
import getOr from "lodash/fp/getOr"
|
import getOr from "lodash/fp/getOr"
|
||||||
import { store, backendUiStore } from "builderStore"
|
import { store, backendUiStore } from "builderStore"
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
import LinkedRecord from "./LinkedRecord.svelte"
|
import LinkedRecord from "./LinkedRecord.svelte"
|
||||||
import AttachmentList from "./AttachmentList.svelte"
|
import AttachmentList from "./AttachmentList.svelte"
|
||||||
import TablePagination from "./TablePagination.svelte"
|
import TablePagination from "./TablePagination.svelte"
|
||||||
|
import Spinner from "components/common/Spinner.svelte"
|
||||||
import { DeleteRecordModal, CreateEditRecordModal } from "./modals"
|
import { DeleteRecordModal, CreateEditRecordModal } from "./modals"
|
||||||
import RowPopover from "./popovers/Row.svelte"
|
import RowPopover from "./popovers/Row.svelte"
|
||||||
import ColumnPopover from "./popovers/Column.svelte"
|
import ColumnPopover from "./popovers/Column.svelte"
|
||||||
|
@ -26,14 +28,17 @@
|
||||||
let headers = []
|
let headers = []
|
||||||
let currentPage = 0
|
let currentPage = 0
|
||||||
let search
|
let search
|
||||||
|
let loading
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if (
|
if (
|
||||||
$backendUiStore.selectedView &&
|
$backendUiStore.selectedView &&
|
||||||
$backendUiStore.selectedView.name.startsWith("all_")
|
$backendUiStore.selectedView.name.startsWith("all_")
|
||||||
) {
|
) {
|
||||||
|
loading = true
|
||||||
api.fetchDataForView($backendUiStore.selectedView).then(records => {
|
api.fetchDataForView($backendUiStore.selectedView).then(records => {
|
||||||
data = records || []
|
data = records || []
|
||||||
|
loading = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +65,14 @@
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="table-controls">
|
<div class="table-controls">
|
||||||
<h2 class="title">{$backendUiStore.selectedModel.name}</h2>
|
<h2 class="title">
|
||||||
|
<span>{$backendUiStore.selectedModel.name}</span>
|
||||||
|
{#if loading}
|
||||||
|
<div transition:fade>
|
||||||
|
<Spinner size="15" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</h2>
|
||||||
<div class="popovers">
|
<div class="popovers">
|
||||||
<ColumnPopover />
|
<ColumnPopover />
|
||||||
{#if Object.keys($backendUiStore.selectedModel.schema).length > 0}
|
{#if Object.keys($backendUiStore.selectedModel.schema).length > 0}
|
||||||
|
@ -123,6 +135,12 @@
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title > span {
|
||||||
|
margin-right: var(--spacing-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { goto } from "@sveltech/routify"
|
import { goto } from "@sveltech/routify"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
import { notifier } from "builderStore/store/notifications"
|
import { notifier } from "builderStore/store/notifications"
|
||||||
|
import Spinner from "components/common/Spinner.svelte"
|
||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
|
@ -20,8 +21,10 @@
|
||||||
let dropdown
|
let dropdown
|
||||||
let name
|
let name
|
||||||
let dataImport
|
let dataImport
|
||||||
|
let loading
|
||||||
|
|
||||||
async function saveTable() {
|
async function saveTable() {
|
||||||
|
loading = true
|
||||||
const model = await backendUiStore.actions.models.save({
|
const model = await backendUiStore.actions.models.save({
|
||||||
name,
|
name,
|
||||||
schema: dataImport.schema || {},
|
schema: dataImport.schema || {},
|
||||||
|
@ -32,6 +35,7 @@
|
||||||
name = ""
|
name = ""
|
||||||
dropdown.hide()
|
dropdown.hide()
|
||||||
analytics.captureEvent("Table Created", { name })
|
analytics.captureEvent("Table Created", { name })
|
||||||
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const onClosed = () => {
|
const onClosed = () => {
|
||||||
|
@ -65,7 +69,10 @@
|
||||||
disabled={!name || !dataImport.valid}
|
disabled={!name || !dataImport.valid}
|
||||||
primary
|
primary
|
||||||
on:click={saveTable}>
|
on:click={saveTable}>
|
||||||
Save
|
<span>Save</span>
|
||||||
|
{#if loading}
|
||||||
|
<Spinner size="10" />
|
||||||
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -73,10 +80,15 @@
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h5 {
|
h5 {
|
||||||
margin-bottom: var(--spacing-l);
|
margin-bottom: var(--spacing-m);
|
||||||
|
margin-top: 0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: var(--spacing-l);
|
padding: var(--spacing-l);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
$: dataImport = {
|
$: dataImport = {
|
||||||
valid,
|
valid,
|
||||||
schema: buildModelSchema(schema),
|
schema: buildModelSchema(schema),
|
||||||
path: files.length && files[0].path,
|
path: files[0] && files[0].path,
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildModelSchema(schema) {
|
function buildModelSchema(schema) {
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
|
|
||||||
<div class="dropzone">
|
<div class="dropzone">
|
||||||
<input id="file-upload" accept=".csv" type="file" on:change={handleFile} />
|
<input id="file-upload" accept=".csv" type="file" on:change={handleFile} />
|
||||||
<label for="file-upload">
|
<label for="file-upload" class:uploaded={files[0]}>
|
||||||
{#if files[0]}{files[0].name}{:else}Upload{/if}
|
{#if files[0]}{files[0].name}{:else}Upload{/if}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -129,11 +129,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.field-status {
|
.field-status {
|
||||||
color: green;
|
color: var(--green);
|
||||||
|
justify-self: center;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
color: var(--red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded {
|
||||||
|
color: var(--blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="file"] {
|
input[type="file"] {
|
||||||
|
@ -169,6 +175,7 @@
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
color: var(--grey-7);
|
color: var(--grey-7);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
justify-self: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field {
|
.field {
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
const Router = require("@koa/router")
|
const Router = require("@koa/router")
|
||||||
const recordController = require("../controllers/record")
|
const recordController = require("../controllers/record")
|
||||||
const authorized = require("../../middleware/authorized")
|
const authorized = require("../../middleware/authorized")
|
||||||
const {
|
const { READ_MODEL, WRITE_MODEL } = require("../../utilities/accessLevels")
|
||||||
READ_MODEL,
|
|
||||||
WRITE_MODEL,
|
|
||||||
BUILDER,
|
|
||||||
} = require("../../utilities/accessLevels")
|
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,8 @@ function parse(path, parsers) {
|
||||||
const validator = VALIDATORS[parsers[key].type]
|
const validator = VALIDATORS[parsers[key].type]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
schema[key].success = !!validator(row[key])
|
// allow null/undefined values
|
||||||
|
schema[key].success = !row[key] || !!validator(row[key])
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
schema[key].success = false
|
schema[key].success = false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue