Fix prettier and fix crash when using certain views as data sources

This commit is contained in:
Andrew Kingston 2021-05-04 11:04:42 +01:00
parent d465fd8893
commit c010eeb314
229 changed files with 1752 additions and 1204 deletions

View File

@ -4,5 +4,5 @@
"singleQuote": false,
"trailingComma": "es5",
"plugins": ["prettier-plugin-svelte"],
"svelteSortOrder" : "scripts-markup-styles"
"svelteSortOrder" : "options-scripts-markup-styles"
}

View File

@ -14,7 +14,7 @@
"prettier-plugin-svelte": "^2.2.0",
"rimraf": "^3.0.2",
"rollup-plugin-replace": "^2.2.0",
"svelte": "^3.30.0"
"svelte": "^3.37.0"
},
"scripts": {
"bootstrap": "lerna link && lerna bootstrap",

View File

@ -42,12 +42,14 @@
class="spectrum-ActionButton spectrum-ActionButton--size{size}"
{disabled}
on:longPress
on:click|preventDefault>
on:click|preventDefault
>
{#if longPressable}
<svg
class="spectrum-Icon spectrum-UIIcon-CornerTriangle100 spectrum-ActionButton-hold"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-CornerTriangle100" />
</svg>
{/if}
@ -56,7 +58,8 @@
class="spectrum-Icon spectrum-Icon--size{size}"
focusable="false"
aria-hidden="true"
aria-label={icon}>
aria-label={icon}
>
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}

View File

@ -23,13 +23,15 @@
class:active
class="spectrum-Button spectrum-Button--size{size.toUpperCase()}"
{disabled}
on:click|preventDefault>
on:click|preventDefault
>
{#if icon}
<svg
class="spectrum-Icon spectrum-Icon--size{size.toUpperCase()}"
focusable="false"
aria-hidden="true"
aria-label={icon}>
aria-label={icon}
>
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}

View File

@ -3,13 +3,17 @@
export let vertical = false
function group(element) {
const buttons = Array.from(element.getElementsByTagName('button'))
buttons.forEach(button => {
button.classList.add('spectrum-ButtonGroup-item')
const buttons = Array.from(element.getElementsByTagName("button"))
buttons.forEach((button) => {
button.classList.add("spectrum-ButtonGroup-item")
})
}
</script>
<div use:group class="spectrum-ButtonGroup" class:spectrum-ButtonGroup--vertical={vertical}>
<div
use:group
class="spectrum-ButtonGroup"
class:spectrum-ButtonGroup--vertical={vertical}
>
<slot />
</div>

View File

@ -11,7 +11,7 @@
export let error = null
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}

View File

@ -10,11 +10,11 @@
export let error = null
export let placeholder = "Choose an option"
export let options = []
export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value")
export let getOptionLabel = (option) => extractProperty(option, "label")
export let getOptionValue = (option) => extractProperty(option, "value")
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -35,5 +35,6 @@
{placeholder}
{getOptionLabel}
{getOptionValue}
on:change={onChange} />
on:change={onChange}
/>
</Field>

View File

@ -10,34 +10,38 @@
export let disabled = false
const dispatch = createEventDispatcher()
const onChange = event => {
const onChange = (event) => {
dispatch("change", event.target.checked)
}
</script>
<label
class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-Checkbox--emphasized"
class:is-invalid={!!error}>
class:is-invalid={!!error}
>
<input
checked={value}
{disabled}
on:change={onChange}
type="checkbox"
class="spectrum-Checkbox-input"
{id} />
{id}
/>
<span class="spectrum-Checkbox-box">
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Checkbox-checkmark"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
<svg
class="spectrum-Icon spectrum-UIIcon-Dash100 spectrum-Checkbox-partialCheckmark"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Dash100" />
</svg>
</span>
<span class="spectrum-Checkbox-label">{text || ''}</span>
<span class="spectrum-Checkbox-label">{text || ""}</span>
</label>

View File

@ -11,8 +11,8 @@
export let disabled = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let getOptionLabel = (option) => option
export let getOptionValue = (option) => option
const dispatch = createEventDispatcher()
let open = false
@ -31,16 +31,16 @@
}
// Render the label if the selected option is found, otherwise raw value
const selected = options.find(option => getOptionValue(option) === value)
const selected = options.find((option) => getOptionValue(option) === value)
return selected ? getOptionLabel(selected) : value
}
const selectOption = value => {
const selectOption = (value) => {
dispatch("change", value)
open = false
}
const onChange = e => {
const onChange = (e) => {
selectOption(e.target.value)
}
</script>
@ -49,7 +49,8 @@
<div
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-disabled={!!error}
class:is-focused={open || focus}>
class:is-focused={open || focus}
>
<input
type="text"
on:focus={() => (focus = true)}
@ -57,18 +58,21 @@
on:change={onChange}
{value}
{placeholder}
class="spectrum-Textfield-input spectrum-InputGroup-input" />
class="spectrum-Textfield-input spectrum-InputGroup-input"
/>
</div>
<button
class="spectrum-Picker spectrum-Picker--sizeM spectrum-InputGroup-button"
tabindex="-1"
aria-haspopup="true"
disabled={!!error}
on:click={() => (open = true)}>
on:click={() => (open = true)}
>
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon spectrum-InputGroup-icon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Chevron100" />
</svg>
</button>
@ -76,7 +80,8 @@
<div class="overlay" on:mousedown|self={() => (open = false)} />
<div
transition:fly={{ y: -20, duration: 200 }}
class="spectrum-Popover spectrum-Popover--bottom is-open">
class="spectrum-Popover spectrum-Popover--bottom is-open"
>
<ul class="spectrum-Menu" role="listbox">
{#if options && Array.isArray(options)}
{#each options as option}
@ -86,13 +91,16 @@
role="option"
aria-selected="true"
tabindex="0"
on:click={() => selectOption(getOptionValue(option))}>
<span
class="spectrum-Menu-itemLabel">{getOptionLabel(option)}</span>
on:click={() => selectOption(getOptionValue(option))}
>
<span class="spectrum-Menu-itemLabel"
>{getOptionLabel(option)}</span
>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</li>

View File

@ -27,12 +27,12 @@
wrap: true,
}
const handleChange = event => {
const handleChange = (event) => {
const [dates] = event.detail
dispatch("change", dates[0])
}
const clearDateOnBackspace = event => {
const clearDateOnBackspace = (event) => {
if (["Backspace", "Clear", "Delete"].includes(event.key)) {
dispatch("change", null)
flatpickr.close()
@ -53,7 +53,7 @@
// We need to blur both because the focus styling does not get properly
// applied.
const els = document.querySelectorAll(`#${flatpickrId} input`)
els.forEach(el => el.blur())
els.forEach((el) => el.blur())
}
</script>
@ -64,7 +64,8 @@
on:close={onClose}
options={flatpickrOptions}
on:change={handleChange}
element={`#${flatpickrId}`}>
element={`#${flatpickrId}`}
>
<div
id={flatpickrId}
class:is-disabled={disabled}
@ -73,17 +74,20 @@
class:is-focused={open}
aria-readonly="false"
aria-required="false"
aria-haspopup="true">
aria-haspopup="true"
>
<div
on:click={flatpickr?.open}
class="spectrum-Textfield spectrum-InputGroup-textfield"
class:is-disabled={disabled}
class:is-invalid={!!error}>
class:is-invalid={!!error}
>
{#if !!error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
@ -94,7 +98,8 @@
class="spectrum-Textfield-input spectrum-InputGroup-input"
{placeholder}
{id}
{value} />
{value}
/>
</div>
<button
type="button"
@ -102,12 +107,14 @@
tabindex="-1"
{disabled}
class:is-invalid={!!error}
on:click={flatpickr?.open}>
on:click={flatpickr?.open}
>
<svg
class="spectrum-Icon spectrum-Icon--sizeM"
focusable="false"
aria-hidden="true"
aria-label="Calendar">
aria-label="Calendar"
>
<use xlink:href="#spectrum-icon-18-Calendar" />
</svg>
</button>

View File

@ -28,7 +28,7 @@
"bmp",
"jfif",
]
const onChange = event => {
const onChange = (event) => {
dispatch("change", event.target.checked)
}
@ -42,7 +42,7 @@
async function processFileList(fileList) {
if (
handleFileTooLarge &&
Array.from(fileList).some(file => file.size >= fileSizeLimit)
Array.from(fileList).some((file) => file.size >= fileSizeLimit)
) {
handleFileTooLarge(fileSizeLimit, value)
return
@ -119,13 +119,15 @@
<div
class="nav left"
class:visible={selectedImageIdx > 0}
on:click={navigateLeft}>
on:click={navigateLeft}
>
<Icon name="ChevronLeft" />
</div>
<div
class="nav right"
class:visible={selectedImageIdx < fileCount - 1}
on:click={navigateRight}>
on:click={navigateRight}
>
<Icon name="ChevronRight" />
</div>
<div class="footer">File {selectedImageIdx + 1} of {fileCount}</div>
@ -140,19 +142,22 @@
on:dragleave={handleDragLeave}
on:dragenter={handleDragOver}
on:drop={handleDrop}
class:is-dragged={fileDragged}>
class:is-dragged={fileDragged}
>
<div class="spectrum-IllustratedMessage spectrum-IllustratedMessage--cta">
<input
id={fieldId}
{disabled}
type="file"
multiple
on:change={handleFile} />
on:change={handleFile}
/>
<svg
class="spectrum-IllustratedMessage-illustration"
width="125"
height="60"
viewBox="0 0 199 97.7"><defs>
viewBox="0 0 199 97.7"
><defs>
<style>
.cls-1,
.cls-2 {
@ -170,25 +175,31 @@
</defs>
<path
class="cls-1"
d="M110.53,85.66,100.26,95.89a1.09,1.09,0,0,1-1.52,0L88.47,85.66" />
d="M110.53,85.66,100.26,95.89a1.09,1.09,0,0,1-1.52,0L88.47,85.66"
/>
<line class="cls-1" x1="99.5" y1="95.5" x2="99.5" y2="58.5" />
<path class="cls-1" d="M105.5,73.5h19a2,2,0,0,0,2-2v-43" />
<path
class="cls-1"
d="M126.5,22.5h-19a2,2,0,0,1-2-2V1.5h-31a2,2,0,0,0-2,2v68a2,2,0,0,0,2,2h19" />
d="M126.5,22.5h-19a2,2,0,0,1-2-2V1.5h-31a2,2,0,0,0-2,2v68a2,2,0,0,0,2,2h19"
/>
<line class="cls-1" x1="105.5" y1="1.5" x2="126.5" y2="22.5" />
<path
class="cls-2"
d="M47.93,50.49a5,5,0,1,0-4.83-5A4.93,4.93,0,0,0,47.93,50.49Z" />
d="M47.93,50.49a5,5,0,1,0-4.83-5A4.93,4.93,0,0,0,47.93,50.49Z"
/>
<path
class="cls-2"
d="M36.6,65.93,42.05,60A2.06,2.06,0,0,1,45,60l12.68,13.2" />
d="M36.6,65.93,42.05,60A2.06,2.06,0,0,1,45,60l12.68,13.2"
/>
<path
class="cls-2"
d="M3.14,73.23,22.42,53.76a1.65,1.65,0,0,1,2.38,0l19.05,19.7" />
d="M3.14,73.23,22.42,53.76a1.65,1.65,0,0,1,2.38,0l19.05,19.7"
/>
<path
class="cls-1"
d="M139.5,36.5H196A1.49,1.49,0,0,1,197.5,38V72A1.49,1.49,0,0,1,196,73.5H141A1.49,1.49,0,0,1,139.5,72V32A1.49,1.49,0,0,1,141,30.5H154a2.43,2.43,0,0,1,1.67.66l6,5.66" />
d="M139.5,36.5H196A1.49,1.49,0,0,1,197.5,38V72A1.49,1.49,0,0,1,196,73.5H141A1.49,1.49,0,0,1,139.5,72V32A1.49,1.49,0,0,1,141,30.5H154a2.43,2.43,0,0,1,1.67.66l6,5.66"
/>
<rect
class="cls-1"
x="1.5"
@ -196,16 +207,21 @@
width="58"
height="39"
rx="2"
ry="2" />
ry="2"
/>
</svg>
<h2
class="spectrum-Heading spectrum-Heading--sizeL spectrum-Heading--light spectrum-IllustratedMessage-heading">
class="spectrum-Heading spectrum-Heading--sizeL spectrum-Heading--light spectrum-IllustratedMessage-heading"
>
Drag and drop your file
</h2>
{#if !disabled}
<p
class="spectrum-Body spectrum-Body--sizeS spectrum-IllustratedMessage-description">
<label for={fieldId} class="spectrum-Link">Select a file to upload</label>
class="spectrum-Body spectrum-Body--sizeS spectrum-IllustratedMessage-description"
>
<label for={fieldId} class="spectrum-Link"
>Select a file to upload</label
>
<br />
from your computer
</p>

View File

@ -8,14 +8,14 @@
export let disabled = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let getOptionLabel = (option) => option
export let getOptionValue = (option) => option
const dispatch = createEventDispatcher()
$: selectedLookupMap = getSelectedLookupMap(value)
$: optionLookupMap = getOptionLookupMap(options)
$: fieldText = getFieldText(value, optionLookupMap, placeholder)
$: isOptionSelected = optionValue => selectedLookupMap[optionValue] === true
$: isOptionSelected = (optionValue) => selectedLookupMap[optionValue] === true
$: toggleOption = makeToggleOption(selectedLookupMap, value)
const getFieldText = (value, map, placeholder) => {
@ -23,17 +23,17 @@
if (!map) {
return ""
}
const vals = value.map(option => map[option] || option).join(", ")
const vals = value.map((option) => map[option] || option).join(", ")
return `(${value.length}) ${vals}`
} else {
return placeholder || "Choose some options"
}
}
const getSelectedLookupMap = value => {
const getSelectedLookupMap = (value) => {
let map = {}
if (value?.length) {
value.forEach(option => {
value.forEach((option) => {
if (option) {
map[option] = true
}
@ -42,7 +42,7 @@
return map
}
const getOptionLookupMap = options => {
const getOptionLookupMap = (options) => {
let map = null
if (options?.length) {
map = {}
@ -57,9 +57,9 @@
}
const makeToggleOption = (map, value) => {
return optionValue => {
return (optionValue) => {
if (map[optionValue]) {
const filtered = value.filter(option => option !== optionValue)
const filtered = value.filter((option) => option !== optionValue)
dispatch("change", filtered)
} else {
dispatch("change", [...value, optionValue])
@ -78,4 +78,5 @@
{isOptionSelected}
{getOptionLabel}
{getOptionValue}
onSelectOption={toggleOption} />
onSelectOption={toggleOption}
/>

View File

@ -15,13 +15,13 @@
export let options = []
export let isOptionSelected = () => false
export let onSelectOption = () => {}
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let getOptionLabel = (option) => option
export let getOptionValue = (option) => option
export let open = false
export let readonly = false
const dispatch = createEventDispatcher()
const onClick = e => {
const onClick = (e) => {
dispatch("click")
if (readonly) {
return
@ -37,7 +37,8 @@
class:is-invalid={!!error}
class:is-open={open}
aria-haspopup="listbox"
on:mousedown={onClick}>
on:mousedown={onClick}
>
<span class="spectrum-Picker-label" class:is-placeholder={isPlaceholder}>
{fieldText}
</span>
@ -46,14 +47,16 @@
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
focusable="false"
aria-hidden="true"
aria-label="Folder">
aria-label="Folder"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Chevron100" />
</svg>
</button>
@ -61,7 +64,8 @@
<div
use:clickOutside={() => (open = false)}
transition:fly={{ y: -20, duration: 200 }}
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open">
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
>
<ul class="spectrum-Menu" role="listbox">
{#if placeholderOption}
<li
@ -70,12 +74,14 @@
role="option"
aria-selected="true"
tabindex="0"
on:click={() => onSelectOption(null)}>
on:click={() => onSelectOption(null)}
>
<span class="spectrum-Menu-itemLabel">{placeholderOption}</span>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</li>
@ -88,13 +94,16 @@
role="option"
aria-selected="true"
tabindex="0"
on:click={() => onSelectOption(getOptionValue(option, idx))}>
<span
class="spectrum-Menu-itemLabel">{getOptionLabel(option, idx)}</span>
on:click={() => onSelectOption(getOptionValue(option, idx))}
>
<span class="spectrum-Menu-itemLabel"
>{getOptionLabel(option, idx)}</span
>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</li>

View File

@ -8,11 +8,11 @@
export let options = []
export let error = null
export let disabled = false
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let getOptionLabel = (option) => option
export let getOptionValue = (option) => option
const dispatch = createEventDispatcher()
const onChange = e => dispatch("change", e.target.value)
const onChange = (e) => dispatch("change", e.target.value)
</script>
<div class={`spectrum-FieldGroup spectrum-FieldGroup--${direction}`}>
@ -21,14 +21,16 @@
<div
title={getOptionLabel(option)}
class="spectrum-Radio spectrum-FieldGroup-item spectrum-Radio--emphasized"
class:is-invalid={!!error}>
class:is-invalid={!!error}
>
<input
on:change={onChange}
bind:group={value}
value={getOptionValue(option)}
type="radio"
class="spectrum-Radio-input"
{disabled} />
{disabled}
/>
<span class="spectrum-Radio-button" />
<label class="spectrum-Radio-label">{getOptionLabel(option)}</label>
</div>

View File

@ -10,7 +10,7 @@
const dispatch = createEventDispatcher()
let focus = false
const updateValue = value => {
const updateValue = (value) => {
dispatch("change", value)
}
@ -18,12 +18,12 @@
focus = true
}
const onBlur = event => {
const onBlur = (event) => {
focus = false
updateValue(event.target.value)
}
const updateValueOnEnter = event => {
const updateValueOnEnter = (event) => {
if (event.key === "Enter") {
updateValue(event.target.value)
}
@ -34,11 +34,13 @@
<div
class="spectrum-Textfield"
class:is-focused={focus}
class:is-disabled={disabled}>
class:is-disabled={disabled}
>
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-icon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Magnify" />
</svg>
<input
@ -46,23 +48,26 @@
on:keyup={updateValueOnEnter}
{disabled}
{id}
value={value || ''}
placeholder={placeholder || ''}
value={value || ""}
placeholder={placeholder || ""}
on:blur={onBlur}
on:focus={onFocus}
on:input
type="search"
class="spectrum-Textfield-input spectrum-Search-input"
autocomplete="off" />
autocomplete="off"
/>
</div>
<button
on:click={() => updateValue('')}
on:click={() => updateValue("")}
type="reset"
class="spectrum-ClearButton spectrum-Search-clearButton">
class="spectrum-ClearButton spectrum-Search-clearButton"
>
<svg
class="spectrum-Icon spectrum-UIIcon-Cross75"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Cross75" />
</svg>
</button>

View File

@ -8,8 +8,8 @@
export let disabled = false
export let error = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let getOptionLabel = (option) => option
export let getOptionValue = (option) => option
export let readonly = false
const dispatch = createEventDispatcher()
@ -34,7 +34,7 @@
return index !== -1 ? getOptionLabel(options[index], index) : value
}
const selectOption = value => {
const selectOption = (value) => {
dispatch("change", value)
open = false
}
@ -51,7 +51,8 @@
{options}
{getOptionLabel}
{getOptionValue}
isPlaceholder={value == null || value === ''}
isPlaceholder={value == null || value === ""}
placeholderOption={placeholder}
isOptionSelected={option => option === value}
onSelectOption={selectOption} />
isOptionSelected={(option) => option === value}
onSelectOption={selectOption}
/>

View File

@ -9,7 +9,7 @@
export let disabled = false
const dispatch = createEventDispatcher()
const onChange = event => {
const onChange = (event) => {
dispatch("change", event.target.checked)
}
</script>
@ -21,7 +21,8 @@
on:change={onChange}
{id}
type="checkbox"
class="spectrum-Switch-input" />
class="spectrum-Switch-input"
/>
<span class="spectrum-Switch-switch" />
<label class="spectrum-Switch-label" for={id}>{text}</label>
</div>

View File

@ -15,7 +15,7 @@
let focus = false
let textarea
const dispatch = createEventDispatcher()
const onChange = event => {
const onChange = (event) => {
dispatch("change", event.target.value)
focus = false
}
@ -25,23 +25,28 @@
class="spectrum-Textfield spectrum-Textfield--multiline"
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}>
class:is-focused={focus}
>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
<textarea
bind:this={textarea}
placeholder={placeholder || ''}
placeholder={placeholder || ""}
class="spectrum-Textfield-input"
{disabled}
{id}
on:focus={() => (focus = true)}
on:blur={onChange}>{value || ''}</textarea>
on:blur={onChange}
>
{value || ""}
</textarea>
</div>
<style>

View File

@ -13,7 +13,7 @@
const dispatch = createEventDispatcher()
let focus = false
const updateValue = value => {
const updateValue = (value) => {
if (readonly) {
return
}
@ -31,7 +31,7 @@
focus = true
}
const onBlur = event => {
const onBlur = (event) => {
if (readonly) {
return
}
@ -39,7 +39,7 @@
updateValue(event.target.value)
}
const updateValueOnEnter = event => {
const updateValueOnEnter = (event) => {
if (readonly) {
return
}
@ -53,12 +53,14 @@
class="spectrum-Textfield"
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}>
class:is-focused={focus}
>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
@ -68,13 +70,14 @@
{disabled}
{readonly}
{id}
value={value || ''}
placeholder={placeholder || ''}
value={value || ""}
placeholder={placeholder || ""}
on:blur={onBlur}
on:focus={onFocus}
on:input
{type}
class="spectrum-Textfield-input" />
class="spectrum-Textfield-input"
/>
</div>
<style>

View File

@ -12,7 +12,7 @@
export let placeholder = null
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -25,5 +25,6 @@
{value}
{placeholder}
{enableTime}
on:change={onChange} />
on:change={onChange}
/>
</Field>

View File

@ -13,7 +13,7 @@
export let handleFileTooLarge = undefined
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -27,5 +27,6 @@
{fileSizeLimit}
{processFiles}
{handleFileTooLarge}
on:change={onChange} />
on:change={onChange}
/>
</Field>

View File

@ -9,7 +9,7 @@
export let error = null
</script>
<div class="spectrum-Form-item" class:above={labelPosition === 'above'}>
<div class="spectrum-Form-item" class:above={labelPosition === "above"}>
{#if label}
<FieldLabel forId={id} {label} position={labelPosition} />
{/if}

View File

@ -10,8 +10,9 @@
<label
for={forId}
class={`spectrum-FieldLabel spectrum-FieldLabel--sizeM spectrum-Form-itemLabel ${className}`}>
{label || ''}
class={`spectrum-FieldLabel spectrum-FieldLabel--sizeM spectrum-Form-itemLabel ${className}`}
>
{label || ""}
</label>
<style>

View File

@ -13,7 +13,7 @@
export let error = null
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -29,5 +29,6 @@
{type}
on:change={onChange}
on:click
on:input />
on:input
/>
</Field>

View File

@ -11,11 +11,11 @@
export let error = null
export let placeholder = null
export let options = []
export let getOptionLabel = option => option
export let getOptionValue = option => option
export let getOptionLabel = (option) => option
export let getOptionValue = (option) => option
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -31,5 +31,6 @@
{getOptionLabel}
{getOptionValue}
on:change={onChange}
on:click />
on:click
/>
</Field>

View File

@ -9,11 +9,11 @@
export let labelPosition = "above"
export let error = null
export let options = []
export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value")
export let getOptionLabel = (option) => extractProperty(option, "label")
export let getOptionValue = (option) => extractProperty(option, "value")
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -33,5 +33,6 @@
{options}
{getOptionLabel}
{getOptionValue}
on:change={onChange} />
on:change={onChange}
/>
</Field>

View File

@ -10,7 +10,7 @@
export let disabled = false
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -23,5 +23,6 @@
{placeholder}
on:change={onChange}
on:click
on:input />
on:input
/>
</Field>

View File

@ -11,11 +11,11 @@
export let error = null
export let placeholder = "Choose an option"
export let options = []
export let getOptionLabel = option => extractProperty(option, "label")
export let getOptionValue = option => extractProperty(option, "value")
export let getOptionLabel = (option) => extractProperty(option, "label")
export let getOptionValue = (option) => extractProperty(option, "value")
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -38,5 +38,6 @@
{getOptionLabel}
{getOptionValue}
on:change={onChange}
on:click />
on:click
/>
</Field>

View File

@ -12,7 +12,7 @@
export let getCaretPosition = null
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}
@ -25,5 +25,6 @@
{disabled}
{value}
{placeholder}
on:change={onChange} />
on:change={onChange}
/>
</Field>

View File

@ -11,7 +11,7 @@
export let error = null
const dispatch = createEventDispatcher()
const onChange = e => {
const onChange = (e) => {
value = e.detail
dispatch("change", e.detail)
}

View File

@ -17,4 +17,5 @@
class:spectrum-Link--secondary={secondary}
class:spectrum-Link--overBackground={overBackground}
class:spectrum-Link--quiet={quiet}
class="spectrum-Link spectrum-Link--size{size}"><slot /></a>
class="spectrum-Link spectrum-Link--size{size}"><slot /></a
>

View File

@ -1,8 +1,9 @@
<script>
export let heading
</script>
<li role="presentation">
<span class="spectrum-Menu-sectionHeading">{heading}</span>
<span class="spectrum-Menu-sectionHeading">{heading}</span>
<ul class="spectrum-Menu" role="group">
<slot />
</ul>

View File

@ -1 +1 @@
<li class="spectrum-Menu-divider" role="separator"></li>
<li class="spectrum-Menu-divider" role="separator" />

View File

@ -17,7 +17,7 @@
<div on:click={increment}>
Click me
{remaining}
more time{remaining === 1 ? '' : 's'}
more time{remaining === 1 ? "" : "s"}
to close this modal!
</div>

View File

@ -50,13 +50,15 @@
<div
class="spectrum-Underlay is-open"
transition:fade={{ duration: 200 }}
on:mousedown|self={hide}>
on:mousedown|self={hide}
>
<div class="modal-wrapper" on:mousedown|self={hide}>
<div class="modal-inner-wrapper" on:mousedown|self={hide}>
<div
use:focusFirstInput
class="spectrum-Modal is-open"
transition:fly={{ y: 30, duration: 200 }}>
transition:fly={{ y: 30, duration: 200 }}
>
<slot />
</div>
</div>

View File

@ -34,7 +34,8 @@
style="position: relative;"
role="dialog"
tabindex="-1"
aria-modal="true">
aria-modal="true"
>
<div class="spectrum-Dialog-grid">
<h1 class="spectrum-Dialog-heading spectrum-Dialog-heading--noHeader">
{title}
@ -47,7 +48,8 @@
</section>
{#if showCancelButton || showConfirmButton}
<div
class="spectrum-ButtonGroup spectrum-Dialog-buttonGroup spectrum-Dialog-buttonGroup--noFooter">
class="spectrum-ButtonGroup spectrum-Dialog-buttonGroup spectrum-Dialog-buttonGroup--noFooter"
>
<slot name="footer" />
{#if showCancelButton}
<Button group secondary on:click={hide}>{cancelText}</Button>
@ -58,7 +60,8 @@
cta
{...$$restProps}
disabled={confirmDisabled}
on:click={confirm}>
on:click={confirm}
>
{confirmText}
</Button>
{/if}
@ -73,6 +76,9 @@
</div>
<style>
.spectrum-Dialog--XL {
width: 1200px;
}
.content-grid {
display: grid;
position: relative;

View File

@ -31,7 +31,8 @@
bind:this={modal}
confirmText="Submit"
onConfirm={answerQuiz}
on:show={resetState}>
on:show={resetState}
>
{#if error}
<p class="error">Wrong answer! Try again.</p>
{/if}

View File

@ -3,15 +3,23 @@
import Portal from "svelte-portal"
import { flip } from "svelte/animate"
import { fly } from "svelte/transition"
import { notifications } from '../Stores/notifications'
import { notifications } from "../Stores/notifications"
</script>
<Portal target=".modal-container">
<Portal target=".modal-container">
<div class="notifications">
{#each $notifications as {type, icon, message, id} (id)}
<div animate:flip transition:fly={{ y: -30 }} class="spectrum-Toast spectrum-Toast--{type} notification-offset">
{#each $notifications as { type, icon, message, id } (id)}
<div
animate:flip
transition:fly={{ y: -30 }}
class="spectrum-Toast spectrum-Toast--{type} notification-offset"
>
{#if icon}
<svg class="spectrum-Icon spectrum-Icon--sizeM spectrum-Toast-typeIcon" focusable="false" aria-hidden="true">
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Toast-typeIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}
@ -21,8 +29,9 @@
</div>
{/each}
</div>
</Portal>
<style>
</Portal>
<style>
.notifications {
position: fixed;
top: 10px;
@ -40,5 +49,4 @@
.notification-offset {
margin-bottom: 10px;
}
</style>
</style>

View File

@ -37,7 +37,8 @@
use:clickOutside={hide}
on:keydown={handleEscape}
class="spectrum-Popover is-open"
role="presentation">
role="presentation"
>
<slot />
</div>
</Portal>

View File

@ -1,29 +1,33 @@
<script>
// WIP! Does not yet work.
import "@spectrum-css/progresscircle/dist/index-vars.css"
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
import { tweened } from "svelte/motion"
import { cubicOut } from "svelte/easing"
export let value = false
export let small;
export let large;
export let small
export let large
export let overBackground;
export let overBackground
</script>
<div class:spectrum-ProgressBar--indeterminate={!value} class:spectrum-ProgressCircle--small={small} class:spectrum-ProgressCircle--large={large} class="spectrum-ProgressCircle">
<div class="spectrum-ProgressCircle-track"></div>
<div
class:spectrum-ProgressBar--indeterminate={!value}
class:spectrum-ProgressCircle--small={small}
class:spectrum-ProgressCircle--large={large}
class="spectrum-ProgressCircle"
>
<div class="spectrum-ProgressCircle-track" />
<div class="spectrum-ProgressCircle-fills">
<div class="spectrum-ProgressCircle-fillMask1">
<div class="spectrum-ProgressCircle-fillSubMask1">
<div class="spectrum-ProgressCircle-fill"></div>
<div class="spectrum-ProgressCircle-fill" />
</div>
</div>
<div class="spectrum-ProgressCircle-fillMask2">
<div class="spectrum-ProgressCircle-fillSubMask2">
<div class="spectrum-ProgressCircle-fill"></div>
<div class="spectrum-ProgressCircle-fill" />
</div>
</div>
</div>
</div>
</div>

View File

@ -1,22 +1,36 @@
<script>
import { getContext } from 'svelte'
const multilevel = getContext('sidenav-type');
export let href = "";
export let external = false;
import { getContext } from "svelte"
const multilevel = getContext("sidenav-type")
export let href = ""
export let external = false
export let heading = ""
export let icon = "";
export let selected = false;
export let disabled = false;
export let icon = ""
export let selected = false
export let disabled = false
</script>
<li class="spectrum-SideNav-item" class:is-selected={selected} class:is-disabled={disabled}>
<li
class="spectrum-SideNav-item"
class:is-selected={selected}
class:is-disabled={disabled}
>
{#if heading}
<h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}">{heading}</h2>
<h2 class="spectrum-SideNav-heading" id="nav-heading-{heading}">
{heading}
</h2>
{/if}
<a target={external ? '_blank' : '_self'} {href} class="spectrum-SideNav-itemLink" aria-current="page">
<a
target={external ? "_blank" : "_self"}
{href}
class="spectrum-SideNav-itemLink"
aria-current="page"
>
{#if icon}
<svg class="spectrum-Icon spectrum-Icon--sizeM spectrum-SideNav-itemIcon" focusable="false" aria-hidden="true">
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-SideNav-itemIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}

View File

@ -1,8 +1,8 @@
<script>
import { setContext } from 'svelte'
import { setContext } from "svelte"
import "@spectrum-css/sidenav/dist/index-vars.css"
export let multilevel = false;
setContext('sidenav-type', multilevel)
export let multilevel = false
setContext("sidenav-type", multilevel)
</script>
<nav>

View File

@ -6,7 +6,7 @@
$: leftover = (value?.length ?? 0) - attachments.length
const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"]
const isImage = extension => {
const isImage = (extension) => {
return imageExtensions.includes(extension?.toLowerCase())
}
</script>

View File

@ -5,24 +5,28 @@
</script>
<label
class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-Checkbox--emphasized">
class="spectrum-Checkbox spectrum-Checkbox--sizeM spectrum-Checkbox--emphasized"
>
<input
type="checkbox"
class="spectrum-Checkbox-input"
id="checkbox-1"
disabled
checked={!!value} />
checked={!!value}
/>
<span class="spectrum-Checkbox-box">
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Checkbox-checkmark"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
<svg
class="spectrum-Icon spectrum-UIIcon-Dash100 spectrum-Checkbox-partialCheckmark"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Dash100" />
</svg>
</span>

View File

@ -22,11 +22,11 @@
longform: StringRenderer,
}
$: type = schema?.type ?? "string"
$: customRenderer = customRenderers?.find(x => x.column === schema?.name)
$: customRenderer = customRenderers?.find((x) => x.column === schema?.name)
$: renderer = customRenderer?.component ?? typeMap[type]
</script>
{#if renderer && (customRenderer || (value != null && value !== ''))}
{#if renderer && (customRenderer || (value != null && value !== ""))}
<svelte:component this={renderer} {row} {schema} {value} on:clickrelationship>
<slot />
</svelte:component>

View File

@ -4,7 +4,7 @@
export let value
</script>
<div>{dayjs(value).format('MMMM D YYYY, HH:mm')}</div>
<div>{dayjs(value).format("MMMM D YYYY, HH:mm")}</div>
<style>
div {

View File

@ -12,7 +12,7 @@
$: relationships = value?.slice(0, displayLimit) ?? []
$: leftover = (value?.length ?? 0) - relationships.length
const onClick = e => {
const onClick = (e) => {
e.stopPropagation()
dispatch("clickrelationship", {
tableId: row.tableId,

View File

@ -31,6 +31,7 @@
// Table state
let height = 0
let loaded = false
$: schema = fixSchema(schema)
$: if (!loading) loaded = true
$: rows = data ?? []
$: visibleRowCount = getVisibleRowCount(loaded, height, rows.length, rowCount)
@ -50,7 +51,7 @@
rows.length
)
// Reset state when data chanegs
// Reset state when data changes
$: data.length, reset()
const reset = () => {
nextScrollTop = 0
@ -59,6 +60,24 @@
timeout = null
}
const fixSchema = (schema) => {
let fixedSchema = {}
Object.entries(schema || {}).forEach(([fieldName, fieldSchema]) => {
if (typeof fieldSchema === "string") {
fixedSchema[fieldName] = {
type: fieldSchema,
name: fieldName,
}
} else {
fixedSchema[fieldName] = {
...fieldSchema,
name: fieldName,
}
}
})
return fixedSchema
}
const getVisibleRowCount = (loaded, height, allRows, rowCount) => {
if (!loaded) {
return rowCount || 0
@ -91,7 +110,7 @@
})
}
const sortBy = fieldSchema => {
const sortBy = (fieldSchema) => {
if (fieldSchema.sortable === false) {
return
}
@ -103,7 +122,7 @@
}
}
const getDisplayName = schema => {
const getDisplayName = (schema) => {
let name = schema?.displayName
if (schema && name === undefined) {
name = schema.name
@ -118,7 +137,6 @@
if (!field || !fieldSchema) {
return
}
schema[field].name = field
if (!fieldSchema?.autocolumn) {
columns.push(fieldSchema)
} else if (showAutoColumns) {
@ -137,10 +155,10 @@
return nameA < nameB ? a : b
})
.concat(autoColumns)
.map(column => column.name)
.map((column) => column.name)
}
const onScroll = event => {
const onScroll = (event) => {
nextScrollTop = event.target.scrollTop
if (timeout) {
return
@ -151,7 +169,7 @@
}, 50)
}
const calculateFirstVisibleRow = scrollTop => {
const calculateFirstVisibleRow = (scrollTop) => {
return Math.max(Math.floor(scrollTop / (rowHeight + 1)) - rowPreload, 0)
}
@ -172,12 +190,12 @@
dispatch("editrow", row)
}
const toggleSelectRow = row => {
const toggleSelectRow = (row) => {
if (!allowSelectRows) {
return
}
if (selectedRows.includes(row)) {
selectedRows = selectedRows.filter(selectedRow => selectedRow !== row)
selectedRows = selectedRows.filter((selectedRow) => selectedRow !== row)
} else {
selectedRows = [...selectedRows, row]
}
@ -192,7 +210,8 @@
on:scroll={onScroll}
class:quiet
style={`--row-height: ${rowHeight}px; --header-height: ${headerHeight}px;`}
class="container">
class="container"
>
<div style={contentStyle}>
<table class="spectrum-Table" class:spectrum-Table--quiet={quiet}>
{#if sortedRows?.length}
@ -201,7 +220,7 @@
{#if showEditColumn}
<th class="spectrum-Table-headCell">
<div class="spectrum-Table-headCell-content">
{editColumnTitle || ''}
{editColumnTitle || ""}
</div>
</th>
{/if}
@ -209,15 +228,19 @@
<th
class="spectrum-Table-headCell"
class:is-sortable={schema[field].sortable !== false}
class:is-sorted-desc={sortColumn === field && sortOrder === 'Descending'}
class:is-sorted-asc={sortColumn === field && sortOrder === 'Ascending'}
on:click={() => sortBy(schema[field])}>
class:is-sorted-desc={sortColumn === field &&
sortOrder === "Descending"}
class:is-sorted-asc={sortColumn === field &&
sortOrder === "Ascending"}
on:click={() => sortBy(schema[field])}
>
<div class="spectrum-Table-headCell-content">
<div class="title">{getDisplayName(schema[field])}</div>
{#if schema[field]?.autocolumn}
<svg
class="spectrum-Icon spectrum-Table-autoIcon"
focusable="false">
focusable="false"
>
<use xlink:href="#spectrum-icon-18-MagicWand" />
</svg>
{/if}
@ -225,7 +248,8 @@
<svg
class="spectrum-Icon spectrum-UIIcon-ArrowDown100 spectrum-Table-sortedIcon"
focusable="false"
aria-hidden="true">
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Arrow100" />
</svg>
{/if}
@ -233,7 +257,8 @@
<svg
class="spectrum-Icon spectrum-Table-editIcon"
focusable="false"
on:click={e => editColumn(e, field)}>
on:click={(e) => editColumn(e, field)}
>
<use xlink:href="#spectrum-icon-18-Edit" />
</svg>
{/if}
@ -249,33 +274,39 @@
<tr
on:click={() => toggleSelectRow(row)}
class="spectrum-Table-row"
class:hidden={idx < firstVisibleRow || idx > lastVisibleRow}>
class:hidden={idx < firstVisibleRow || idx > lastVisibleRow}
>
{#if idx >= firstVisibleRow && idx <= lastVisibleRow}
{#if showEditColumn}
<td
class="spectrum-Table-cell spectrum-Table-cell--divider">
class="spectrum-Table-cell spectrum-Table-cell--divider"
>
<div class="spectrum-Table-cell-content">
<SelectEditRenderer
data={row}
selected={selectedRows.includes(row)}
onToggleSelection={() => toggleSelectRow(row)}
onEdit={e => editRow(e, row)}
onEdit={(e) => editRow(e, row)}
{allowSelectRows}
{allowEditRows} />
{allowEditRows}
/>
</div>
</td>
{/if}
{#each fields as field}
<td
class="spectrum-Table-cell"
class:spectrum-Table-cell--divider={!!schema[field].divider}>
class:spectrum-Table-cell--divider={!!schema[field]
.divider}
>
<div class="spectrum-Table-cell-content">
<CellRenderer
{customRenderers}
{row}
schema={schema[field]}
value={row[field]}
on:clickrelationship>
on:clickrelationship
>
<slot />
</CellRenderer>
</div>
@ -288,7 +319,8 @@
<div class="placeholder">
<svg
class="spectrum-Icon spectrum-Icon--sizeXXL"
focusable="false">
focusable="false"
>
<use xlink:href="#spectrum-icon-18-Table" />
</svg>
<div>No rows found</div>

View File

@ -30,13 +30,15 @@
on:click={onClick}
class:is-selected={$selected.title === title}
class="spectrum-Tabs-item"
tabindex="0">
tabindex="0"
>
{#if icon}
<svg
class="spectrum-Icon spectrum-Icon--sizeM"
focusable="false"
aria-hidden="true"
aria-label="Folder">
aria-label="Folder"
>
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}

View File

@ -44,23 +44,22 @@
})
function id() {
return (
"_" +
Math.random()
.toString(36)
.substr(2, 9)
)
return "_" + Math.random().toString(36).substr(2, 9)
}
</script>
<div
bind:this={container}
class="selected-border spectrum-Tabs spectrum-Tabs--{vertical ? 'vertical' : 'horizontal'}">
class="selected-border spectrum-Tabs spectrum-Tabs--{vertical
? 'vertical'
: 'horizontal'}"
>
<slot />
{#if $tab.info}
<div
class="spectrum-Tabs-selectionIndicator indicator-transition"
style="width: {width}; height: {height}; left: {left}; top: {top};" />
style="width: {width}; height: {height}; left: {left}; top: {top};"
/>
{/if}
</div>

View File

@ -1,19 +1,29 @@
<script>
import Avatar from '../Avatar/Avatar.svelte'
import ClearButton from '../ClearButton/ClearButton.svelte'
export let icon = "";
export let avatar = "";
export let invalid = false;
export let disabled = false;
export let closable = false;
import Avatar from "../Avatar/Avatar.svelte"
import ClearButton from "../ClearButton/ClearButton.svelte"
export let icon = ""
export let avatar = ""
export let invalid = false
export let disabled = false
export let closable = false
</script>
<div class:is-invalid={invalid} class:is-disabled={disabled} class="spectrum-Tags-item" role="listitem">
<div
class:is-invalid={invalid}
class:is-disabled={disabled}
class="spectrum-Tags-item"
role="listitem"
>
{#if avatar}
<Avatar url={avatar} />
{/if}
{#if icon}
<svg class="spectrum-Icon spectrum-Icon--sizeS" focusable="false" aria-hidden="true" aria-label="Tag">
<svg
class="spectrum-Icon spectrum-Icon--sizeS"
focusable="false"
aria-hidden="true"
aria-label="Tag"
>
<use xlink:href="#spectrum-icon-24-{icon}" />
</svg>
{/if}

View File

@ -1,20 +1,32 @@
<script>
export let selected = false;
export let open = false;
export let title;
export let icon;
export let selected = false
export let open = false
export let title
export let icon
</script>
<li
class:is-selected={selected} class:is-open={open} class="spectrum-TreeView-item">
class:is-selected={selected}
class:is-open={open}
class="spectrum-TreeView-item"
>
<a on:click class="spectrum-TreeView-itemLink" href="#">
{#if $$slots.default}
<svg class="spectrum-Icon spectrum-UIIcon-ChevronRight100 spectrum-TreeView-itemIndicator" focusable="false" aria-hidden="true">
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronRight100 spectrum-TreeView-itemIndicator"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Chevron100" />
</svg>
{/if}
{#if icon}
<svg class="spectrum-TreeView-itemIcon spectrum-Icon spectrum-Icon--sizeM" focusable="false" aria-hidden="true" aria-label="Layers">
<svg
class="spectrum-TreeView-itemIcon spectrum-Icon spectrum-Icon--sizeM"
focusable="false"
aria-hidden="true"
aria-label="Layers"
>
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}

View File

@ -3,9 +3,14 @@
export let quiet = false
export let standalone = true
export let width = '250px';
export let width = "250px"
</script>
<ul class:spectrum-TreeView--standalone={standalone} class:spectrum-TreeView--quiet={quiet} class="spectrum-TreeView" style="width: {width}">
<ul
class:spectrum-TreeView--standalone={standalone}
class:spectrum-TreeView--quiet={quiet}
class="spectrum-TreeView"
style="width: {width}"
>
<slot />
</ul>

View File

@ -106,7 +106,7 @@
"rollup": "^2.44.0",
"rollup-plugin-copy": "^3.4.0",
"start-server-and-test": "^1.12.1",
"svelte": "^3.36.0",
"svelte": "^3.37.0",
"svelte-jester": "^1.3.2",
"vite": "^2.1.5"
},

View File

@ -277,14 +277,23 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
schema["_rev"] = { type: "string" }
}
// Ensure there are "name" properties for all fields
if (schema) {
Object.keys(schema).forEach((field) => {
if (!schema[field].name) {
schema[field].name = field
// Ensure there are "name" properties for all fields and that field schema
// are objects
let fixedSchema = {}
Object.entries(schema || {}).forEach(([fieldName, fieldSchema]) => {
if (typeof fieldSchema === "string") {
fixedSchema[fieldName] = {
type: fieldSchema,
name: fieldName,
}
} else {
fixedSchema[fieldName] = {
...fieldSchema,
name: fieldName,
}
}
})
}
schema = fixedSchema
}
return { schema, table }
}

View File

@ -6,7 +6,7 @@
$: automation = $automationStore.selectedAutomation?.automation
function onSelect(block) {
automationStore.update(state => {
automationStore.update((state) => {
state.selectedBlock = block
return state
})

View File

@ -33,7 +33,7 @@
let webhookModal
$: selectedTab = selectedIndex == null ? null : tabs[selectedIndex].value
$: anchor = selectedIndex === -1 ? null : anchors[selectedIndex]
$: blocks = sortBy(entry => entry[1].name)(
$: blocks = sortBy((entry) => entry[1].name)(
Object.entries($automationStore.blockDefinitions[selectedTab] ?? {})
)
@ -69,7 +69,8 @@
size="S"
icon={tab.icon}
disabled={tab.disabled}
on:click={tab.disabled ? null : () => onChangeTab(idx)}>
on:click={tab.disabled ? null : () => onChangeTab(idx)}
>
{tab.label}
</ActionButton>
</div>
@ -79,14 +80,16 @@
on:close={() => (selectedIndex = null)}
bind:this={popover}
{anchor}
align="left">
align="left"
>
<DropdownContainer>
{#each blocks as [stepId, blockDefinition]}
<DropdownItem
icon={blockDefinition.icon}
title={blockDefinition.name}
subtitle={blockDefinition.description}
on:click={() => addBlockToAutomation(stepId, blockDefinition)} />
on:click={() => addBlockToAutomation(stepId, blockDefinition)}
/>
{/each}
</DropdownContainer>
</Popover>

View File

@ -3,10 +3,12 @@
height="75"
viewBox="0 0 9 75"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5.0625 70H9L4.5 75L0 70H3.9375V65H5.0625V70Z"
fill="var(--grey-5)" />
fill="var(--grey-5)"
/>
<rect x="4" width="1" height="65" fill="var(--grey-5)" />
</svg>

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 326 B

View File

@ -16,7 +16,7 @@
const tableId = inputs.tableId || inputs.row?.tableId
if (tableId) {
enrichedInputs.enriched.table = $tables.list.find(
table => table._id === tableId
(table) => table._id === tableId
)
}
return enrichedInputs
@ -30,8 +30,8 @@
// Extract schema paths for any input bindings
let inputPaths = formattedTagline.match(/{{\s*\S+\s*}}/g) || []
inputPaths = inputPaths.map(path => path.replace(/[{}]/g, "").trim())
const schemaPaths = inputPaths.map(path =>
inputPaths = inputPaths.map((path) => path.replace(/[{}]/g, "").trim())
const schemaPaths = inputPaths.map((path) =>
path.replace(/\./g, ".properties.")
)

View File

@ -26,7 +26,8 @@
class="block"
animate:flip={{ duration: 600 }}
in:fade|local
out:fly|local={{ x: 100 }}>
out:fly|local={{ x: 100 }}
>
<FlowItem {onSelect} {block} />
{#if idx !== blocks.length - 1}
<Arrow />

View File

@ -10,11 +10,11 @@
$: selected = $automationStore.selectedBlock?.id === block.id
$: steps =
$automationStore.selectedAutomation?.automation?.definition?.steps ?? []
$: blockIdx = steps.findIndex(step => step.id === block.id)
$: blockIdx = steps.findIndex((step) => step.id === block.id)
$: allowDeleteTrigger = !steps.length
function deleteStep() {
console.log('Running')
console.log("Running")
automationStore.actions.deleteAutomationBlock(block)
}
</script>
@ -22,23 +22,24 @@
<div
class={`block ${block.type} hoverable`}
class:selected
on:click={() => onSelect(block)}>
on:click={() => onSelect(block)}
>
<header>
{#if block.type === 'TRIGGER'}
{#if block.type === "TRIGGER"}
<Icon name="Light" />
<span>When this happens...</span>
{:else if block.type === 'ACTION'}
{:else if block.type === "ACTION"}
<Icon name="FlashOn" />
<span>Do this...</span>
{:else if block.type === 'LOGIC'}
{:else if block.type === "LOGIC"}
<Icon name="Branch2" />
<span>Only continue if...</span>
{/if}
<div class="label">
{#if block.type === 'TRIGGER'}Trigger{:else}Step {blockIdx + 1}{/if}
{#if block.type === "TRIGGER"}Trigger{:else}Step {blockIdx + 1}{/if}
</div>
{#if block.type !== 'TRIGGER' || allowDeleteTrigger}
<div on:click|stopPropagation={deleteStep}><Icon name="Close"/></div>
{#if block.type !== "TRIGGER" || allowDeleteTrigger}
<div on:click|stopPropagation={deleteStep}><Icon name="Close" /></div>
{/if}
</header>
<hr />

View File

@ -27,12 +27,14 @@
confirmText="Create"
size="L"
onConfirm={createAutomation}
disabled={!valid}>
disabled={!valid}
>
<Input bind:value={name} label="Name" />
<a
slot="footer"
target="_blank"
href="https://docs.budibase.com/automate/introduction-to-automate">
href="https://docs.budibase.com/automate/introduction-to-automate"
>
<Icon name="InfoOutline" />
<span>Learn about automations</span>
</a>

View File

@ -27,7 +27,7 @@
if (automation.trigger) {
allSteps = [automation.trigger, ...allSteps]
}
const blockIdx = allSteps.findIndex(step => step.id === block.id)
const blockIdx = allSteps.findIndex((step) => step.id === block.id)
// Extract all outputs from all previous steps as available bindings
let bindings = []
@ -54,40 +54,43 @@
{#each inputs as [key, value]}
<div class="block-field">
<Label>{value.title}</Label>
{#if value.type === 'string' && value.enum}
{#if value.type === "string" && value.enum}
<Select
bind:value={block.inputs[key]}
options={value.enum}
getOptionLabel={(x, idx) => (value.pretty ? value.pretty[idx] : x)} />
{:else if value.customType === 'password'}
getOptionLabel={(x, idx) => (value.pretty ? value.pretty[idx] : x)}
/>
{:else if value.customType === "password"}
<Input type="password" bind:value={block.inputs[key]} />
{:else if value.customType === 'email'}
{:else if value.customType === "email"}
<DrawerBindableInput
panel={AutomationBindingPanel}
type={'email'}
type={"email"}
value={block.inputs[key]}
on:change={e => (block.inputs[key] = e.detail)}
{bindings} />
{:else if value.customType === 'table'}
on:change={(e) => (block.inputs[key] = e.detail)}
{bindings}
/>
{:else if value.customType === "table"}
<TableSelector bind:value={block.inputs[key]} />
{:else if value.customType === 'row'}
{:else if value.customType === "row"}
<RowSelector bind:value={block.inputs[key]} {bindings} />
{:else if value.customType === 'webhookUrl'}
{:else if value.customType === "webhookUrl"}
<WebhookDisplay value={block.inputs[key]} />
{:else if value.customType === 'triggerSchema'}
{:else if value.customType === "triggerSchema"}
<SchemaSetup bind:value={block.inputs[key]} />
{:else if value.type === 'string' || value.type === 'number'}
{:else if value.type === "string" || value.type === "number"}
<DrawerBindableInput
panel={AutomationBindingPanel}
type={value.customType}
value={block.inputs[key]}
on:change={e => (block.inputs[key] = e.detail)}
{bindings} />
on:change={(e) => (block.inputs[key] = e.detail)}
{bindings}
/>
{/if}
</div>
{/each}
</div>
{#if stepId === 'WEBHOOK'}
{#if stepId === "WEBHOOK"}
<Button secondary on:click={() => webhookModal.show()}>Set Up Webhook</Button>
{/if}

View File

@ -7,7 +7,7 @@
export let value
export let bindings
$: table = $tables.list.find(table => table._id === value?.tableId)
$: table = $tables.list.find((table) => table._id === value?.tableId)
$: schemaFields = Object.entries(table?.schema ?? {})
// Ensure any nullish tableId values get set to empty string so
@ -22,8 +22,9 @@
<Select
bind:value={value.tableId}
options={$tables.list}
getOptionLabel={table => table.name}
getOptionValue={table => table._id} />
getOptionLabel={(table) => table.name}
getOptionValue={(table) => table._id}
/>
{#if schemaFields.length}
<div class="schema-fields">
@ -33,15 +34,17 @@
<Select
label={field}
bind:value={value[field]}
options={schema.constraints.inclusion} />
{:else if schema.type === 'string' || schema.type === 'number'}
options={schema.constraints.inclusion}
/>
{:else if schema.type === "string" || schema.type === "number"}
<DrawerBindableInput
panel={AutomationBindingPanel}
value={value[field]}
on:change={e => (value[field] = e.detail)}
on:change={(e) => (value[field] = e.detail)}
label={field}
type="string"
{bindings} />
{bindings}
/>
{/if}
{/if}
{/each}

View File

@ -37,14 +37,14 @@
value = newValues
}
const fieldNameChanged = originalName => e => {
const fieldNameChanged = (originalName) => (e) => {
// reconstruct using fieldsArray, so field order is preserved
let entries = [...fieldsArray]
const newName = e.detail
if (newName) {
entries.find(f => f.name === originalName).name = newName
entries.find((f) => f.name === originalName).name = newName
} else {
entries = entries.filter(f => f.name !== originalName)
entries = entries.filter((f) => f.name !== originalName)
}
value = entries.reduce((newVals, current) => {
newVals[current.name] = current.type
@ -62,14 +62,17 @@
value={field.name}
secondary
placeholder="Enter field name"
on:change={fieldNameChanged(field.name)} />
on:change={fieldNameChanged(field.name)}
/>
<Select
value={field.type}
on:change={e => (value[field.name] = e.target.value)}
options={typeOptions} />
on:change={(e) => (value[field.name] = e.target.value)}
options={typeOptions}
/>
<i
class="remove-field ri-delete-bin-line"
on:click={() => removeField(field.name)} />
on:click={() => removeField(field.name)}
/>
</div>
{/each}
</div>

View File

@ -8,5 +8,6 @@
<Select
bind:value
options={$tables.list}
getOptionLabel={table => table.name}
getOptionValue={table => table._id} />
getOptionLabel={(table) => table.name}
getOptionValue={(table) => table._id}
/>

View File

@ -30,7 +30,7 @@
if ($views.selected?.name?.startsWith("all_")) {
loading = true
const loadingTableId = $tables.selected?._id
api.fetchDataForView($views.selected).then(rows => {
api.fetchDataForView($views.selected).then((rows) => {
loading = false
// If we started a slow request then quickly change table, sometimes
@ -53,12 +53,14 @@
{data}
allowEditing={true}
bind:hideAutocolumns
{loading}>
{loading}
>
<CreateColumnButton />
{#if schema && Object.keys(schema).length > 0}
<CreateRowButton
title={isUsersTable ? 'Create user' : 'Create row'}
modalContentComponent={isUsersTable ? CreateEditUser : CreateEditRow} />
title={isUsersTable ? "Create user" : "Create row"}
modalContentComponent={isUsersTable ? CreateEditUser : CreateEditRow}
/>
<CreateViewButton />
<ManageAccessButton resourceId={$tables.selected?._id} />
{#if isUsersTable}

View File

@ -12,9 +12,9 @@
$: data = row?.[fieldName] ?? []
$: linkedTableId = data?.length ? data[0].tableId : null
$: linkedTable = $tables.list.find(table => table._id === linkedTableId)
$: linkedTable = $tables.list.find((table) => table._id === linkedTableId)
$: schema = linkedTable?.schema
$: table = $tables.list.find(table => table._id === tableId)
$: table = $tables.list.find((table) => table._id === tableId)
$: fetchData(tableId, rowId)
$: {
let rowLabel = row?.[table?.primaryDisplay]

View File

@ -13,21 +13,22 @@
$: label = capitalise(meta.name)
</script>
{#if type === 'options'}
{#if type === "options"}
<Select
{label}
data-cy="{meta.name}-select"
bind:value
options={meta.constraints.inclusion} />
{:else if type === 'datetime'}
options={meta.constraints.inclusion}
/>
{:else if type === "datetime"}
<DatePicker {label} bind:value />
{:else if type === 'attachment'}
{:else if type === "attachment"}
<Dropzone {label} bind:value />
{:else if type === 'boolean'}
{:else if type === "boolean"}
<Toggle text={label} bind:checked={value} data-cy="{meta.name}-input" />
{:else if type === 'link'}
{:else if type === "link"}
<LinkedRowSelector bind:linkedRows={value} schema={meta} />
{:else if type === 'longform'}
{:else if type === "longform"}
<TextArea {label} bind:value />
{:else}
<Input
@ -35,5 +36,6 @@
data-cy="{meta.name}-input"
{type}
bind:value
disabled={readonly} />
disabled={readonly}
/>
{/if}

View File

@ -28,9 +28,9 @@
async function fetchViewData(name, field, groupBy, calculation) {
const _tables = $tables.list
const allTableViews = _tables.map(table => table.views)
const allTableViews = _tables.map((table) => table.views)
const thisView = allTableViews.filter(
views => views != null && views[name] != null
(views) => views != null && views[name] != null
)[0]
// don't fetch view data if the view no longer exists
if (!thisView) {
@ -58,7 +58,8 @@
{data}
{loading}
allowEditing={!view?.calculation}
bind:hideAutocolumns>
bind:hideAutocolumns
>
<FilterButton {view} />
<CalculateButton {view} />
{#if view.calculation}

View File

@ -12,7 +12,8 @@
size="S"
quiet
on:click={modal.show}
active={view.field && view.calculation}>
active={view.field && view.calculation}
>
Calculate
</ActionButton>
<Modal bind:this={modal}>

View File

@ -22,8 +22,9 @@
bind:this={modal}
okText="Delete"
onOk={confirmDeletion}
title="Confirm Deletion">
title="Confirm Deletion"
>
Are you sure you want to delete
{selectedRows.length}
row{selectedRows.length > 1 ? 's' : ''}?
row{selectedRows.length > 1 ? "s" : ""}?
</ConfirmDialog>

View File

@ -12,7 +12,8 @@
size="S"
quiet
on:click={modal.show}
active={view.filters?.length}>
active={view.filters?.length}
>
Filter
</ActionButton>
<Modal bind:this={modal}>

View File

@ -13,7 +13,8 @@
size="S"
quiet
active={!!view.groupBy}
on:click={modal.show}>
on:click={modal.show}
>
Group By
</Button>
<Modal bind:this={modal}>

View File

@ -21,5 +21,6 @@
<ManageAccessModal
{resourceId}
levels={$permissions}
permissions={resourcePermissions} />
permissions={resourcePermissions}
/>
</Modal>

View File

@ -3,7 +3,7 @@
export let value
$: role = $roles.find(role => role._id === value)
$: role = $roles.find((role) => role._id === value)
$: roleName = role?.name ?? "Unknown role"
</script>

View File

@ -25,7 +25,7 @@
$: fields =
viewTable &&
Object.keys(viewTable.schema).filter(
field =>
(field) =>
view.calculation === "count" ||
// don't want to perform calculations based on auto ID
(viewTable.schema[field].type === "number" &&
@ -43,14 +43,16 @@
title="Calculate"
confirmText="Save"
onConfirm={saveView}
disabled={!view.field}>
disabled={!view.field}
>
<div class="input-group-row">
<Label>The</Label>
<Select
bind:value={view.calculation}
options={CALCULATIONS}
getOptionLabel={x => x.name}
getOptionValue={x => x.key} />
getOptionLabel={(x) => x.name}
getOptionValue={(x) => x.key}
/>
{#if view.calculation}
<Label>Of</Label>
<Select bind:value={view.field} options={fields} />

View File

@ -49,7 +49,7 @@
let deletion
$: tableOptions = $tables.list.filter(
table => table._id !== $tables.draft._id
(table) => table._id !== $tables.draft._id
)
$: required = !!field?.constraints?.presence || primaryDisplay
$: uneditable =
@ -60,7 +60,7 @@
!field.name ||
(field.type === LINK_TYPE && !field.tableId) ||
Object.keys($tables.draft?.schema ?? {}).some(
key => key !== originalName && key === field.name
(key) => key !== originalName && key === field.name
)
// used to select what different options can be displayed for column type
@ -154,7 +154,7 @@
if (!field || !field.tableId) {
return null
}
const linkTable = tableOptions.find(table => table._id === field.tableId)
const linkTable = tableOptions.find((table) => table._id === field.tableId)
if (!linkTable) {
return null
}
@ -181,10 +181,11 @@
</script>
<ModalContent
title={originalName ? 'Edit Column' : 'Create Column'}
title={originalName ? "Edit Column" : "Create Column"}
confirmText="Save Column"
onConfirm={saveColumn}
disabled={invalid}>
disabled={invalid}
>
<Input label="Name" bind:value={field.name} disabled={uneditable} />
<Select
@ -192,9 +193,13 @@
label="Type"
bind:value={field.type}
on:change={handleTypeChange}
options={[...Object.values(fieldDefinitions), { name: 'Auto Column', type: AUTO_COL }]}
getOptionLabel={field => field.name}
getOptionValue={field => field.type} />
options={[
...Object.values(fieldDefinitions),
{ name: "Auto Column", type: AUTO_COL },
]}
getOptionLabel={(field) => field.name}
getOptionValue={(field) => field.type}
/>
{#if canBeRequired || canBeDisplay}
<div>
@ -204,14 +209,16 @@
on:change={onChangeRequired}
disabled={primaryDisplay}
thin
text="Required" />
text="Required"
/>
{/if}
{#if canBeDisplay}
<Toggle
bind:value={primaryDisplay}
on:change={onChangePrimaryDisplay}
thin
text="Use as table display column" />
text="Use as table display column"
/>
{/if}
</div>
{/if}
@ -223,63 +230,73 @@
value={indexes[0] === field.name}
disabled={indexes[1] === field.name}
on:change={onChangePrimaryIndex}
text="Primary" />
text="Primary"
/>
<Toggle
value={indexes[1] === field.name}
disabled={!indexes[0] || indexes[0] === field.name}
on:change={onChangeSecondaryIndex}
text="Secondary" />
text="Secondary"
/>
</div>
{/if}
{#if field.type === 'string'}
{#if field.type === "string"}
<Input
type="number"
label="Max Length"
bind:value={field.constraints.length.maximum} />
{:else if field.type === 'options'}
bind:value={field.constraints.length.maximum}
/>
{:else if field.type === "options"}
<ValuesList
label="Options (one per line)"
bind:values={field.constraints.inclusion} />
{:else if field.type === 'datetime'}
bind:values={field.constraints.inclusion}
/>
{:else if field.type === "datetime"}
<DatePicker
label="Earliest"
bind:value={field.constraints.datetime.earliest} />
bind:value={field.constraints.datetime.earliest}
/>
<DatePicker label="Latest" bind:value={field.constraints.datetime.latest} />
{:else if field.type === 'number'}
{:else if field.type === "number"}
<Input
type="number"
label="Min Value"
bind:value={field.constraints.numericality.greaterThanOrEqualTo} />
bind:value={field.constraints.numericality.greaterThanOrEqualTo}
/>
<Input
type="number"
label="Max Value"
bind:value={field.constraints.numericality.lessThanOrEqualTo} />
{:else if field.type === 'link'}
bind:value={field.constraints.numericality.lessThanOrEqualTo}
/>
{:else if field.type === "link"}
<Select
label="Table"
bind:value={field.tableId}
options={tableOptions}
getOptionLabel={table => table.name}
getOptionValue={table => table._id} />
getOptionLabel={(table) => table.name}
getOptionValue={(table) => table._id}
/>
{#if relationshipOptions && relationshipOptions.length > 0}
<RadioGroup
disabled={originalName}
label="Define the relationship"
bind:value={field.relationshipType}
options={relationshipOptions}
getOptionLabel={option => option.name}
getOptionValue={option => option.value} />
getOptionLabel={(option) => option.name}
getOptionValue={(option) => option.value}
/>
{/if}
<Input label={`Column name in other table`} bind:value={field.fieldName} />
{:else if field.type === AUTO_COL}
<Select
label="Auto Column Type"
value={field.subtype}
on:change={e => (field.subtype = e.detail)}
on:change={(e) => (field.subtype = e.detail)}
options={Object.entries(getAutoColumnInformation())}
getOptionLabel={option => option[1].name}
getOptionValue={option => option[0]} />
getOptionLabel={(option) => option[1].name}
getOptionValue={(option) => option[0]}
/>
{/if}
<div slot="footer">
@ -294,4 +311,5 @@
okText="Delete Column"
onOk={deleteColumn}
onCancel={hideDeleteDialog}
title="Confirm Deletion" />
title="Confirm Deletion"
/>

View File

@ -12,7 +12,7 @@
$: creating = row?._id == null
$: table = row.tableId
? $tables.list.find(table => table._id === row?.tableId)
? $tables.list.find((table) => table._id === row?.tableId)
: $tables.selected
$: tableSchema = Object.entries(table?.schema ?? {})
@ -39,9 +39,10 @@
</script>
<ModalContent
title={creating ? 'Create Row' : 'Edit Row'}
confirmText={creating ? 'Create Row' : 'Save Row'}
onConfirm={saveRow}>
title={creating ? "Create Row" : "Edit Row"}
confirmText={creating ? "Create Row" : "Save Row"}
onConfirm={saveRow}
>
<ErrorsBox {errors} />
{#each tableSchema as [key, meta]}
{#if !meta.autocolumn}

View File

@ -13,13 +13,13 @@
$: creating = row?._id == null
$: table = row.tableId
? $tables.list.find(table => table._id === row?.tableId)
? $tables.list.find((table) => table._id === row?.tableId)
: $tables.selected
$: tableSchema = getUserSchema(table)
$: customSchemaKeys = getCustomSchemaKeys(tableSchema)
$: if (!row.status) row.status = "active"
const getUserSchema = table => {
const getUserSchema = (table) => {
let schema = table?.schema ?? {}
if (schema.username) {
schema.username.name = "Username"
@ -27,7 +27,7 @@
return schema
}
const getCustomSchemaKeys = schema => {
const getCustomSchemaKeys = (schema) => {
let customSchema = { ...schema }
delete customSchema["email"]
delete customSchema["roleId"]
@ -55,7 +55,7 @@
)
if (rowResponse.errors) {
if (Array.isArray(rowResponse.errors)) {
errors = rowResponse.errors.map(error => ({ message: error }))
errors = rowResponse.errors.map((error) => ({ message: error }))
} else {
errors = Object.entries(rowResponse.errors)
.map(([key, error]) => ({ dataPath: key, message: error }))
@ -73,17 +73,20 @@
</script>
<ModalContent
title={creating ? 'Create User' : 'Edit User'}
confirmText={creating ? 'Create User' : 'Save User'}
onConfirm={saveRow}>
title={creating ? "Create User" : "Edit User"}
confirmText={creating ? "Create User" : "Save User"}
onConfirm={saveRow}
>
<ErrorsBox {errors} />
<RowFieldControl
meta={{ ...tableSchema.email, name: 'Email' }}
meta={{ ...tableSchema.email, name: "Email" }}
bind:value={row.email}
readonly={!creating} />
readonly={!creating}
/>
<RowFieldControl
meta={{ name: 'password', type: 'password' }}
bind:value={row.password} />
meta={{ name: "password", type: "password" }}
bind:value={row.password}
/>
<!-- Defer rendering this select until roles load, otherwise the initial
selection is always undefined -->
<Select
@ -91,14 +94,19 @@
data-cy="roleId-select"
bind:value={row.roleId}
options={$roles}
getOptionLabel={role => role.name}
getOptionValue={role => role._id} />
getOptionLabel={(role) => role.name}
getOptionValue={(role) => role._id}
/>
<Select
label="Status"
bind:value={row.status}
options={[{ label: 'Active', value: 'active' }, { label: 'Inactive', value: 'inactive' }]}
getOptionLabel={status => status.label}
getOptionValue={status => status.value} />
options={[
{ label: "Active", value: "active" },
{ label: "Inactive", value: "inactive" },
]}
getOptionLabel={(status) => status.label}
getOptionValue={(status) => status.value}
/>
{#each customSchemaKeys as [key, meta]}
{#if !meta.autocolumn}
<RowFieldControl {meta} bind:value={row[key]} {creating} />

View File

@ -10,7 +10,7 @@
let name
let field
$: views = $tables.list.flatMap(table => Object.keys(table.views || {}))
$: views = $tables.list.flatMap((table) => Object.keys(table.views || {}))
function saveView() {
if (views.includes(name)) {
@ -31,6 +31,7 @@
<ModalContent
title="Create View"
confirmText="Create View"
onConfirm={saveView}>
onConfirm={saveView}
>
<Input label="View Name" thin bind:value={name} />
</ModalContent>

View File

@ -11,7 +11,7 @@
let errors = []
let builtInRoles = ["Admin", "Power", "Basic", "Public"]
$: selectedRoleId = selectedRole._id
$: otherRoles = $roles.filter(role => role._id !== selectedRoleId)
$: otherRoles = $roles.filter((role) => role._id !== selectedRoleId)
$: isCreating = selectedRoleId == null || selectedRoleId === ""
const fetchBasePermissions = async () => {
@ -20,9 +20,9 @@
}
// Changes the selected role
const changeRole = event => {
const changeRole = (event) => {
const id = event?.detail
const role = $roles.find(role => role._id === id)
const role = $roles.find((role) => role._id === id)
if (role) {
selectedRole = {
...role,
@ -41,7 +41,7 @@
// Clean up empty strings
const keys = ["_id", "inherits", "permissionId"]
keys.forEach(key => {
keys.forEach((key) => {
if (selectedRole[key] === "") {
delete selectedRole[key]
}
@ -84,8 +84,9 @@
<ModalContent
title="Edit Roles"
confirmText={isCreating ? 'Create' : 'Save'}
onConfirm={saveRole}>
confirmText={isCreating ? "Create" : "Save"}
onConfirm={saveRole}
>
{#if errors.length}
<ErrorsBox {errors} />
{/if}
@ -97,27 +98,31 @@
on:change={changeRole}
options={$roles}
placeholder="Create new role"
getOptionValue={role => role._id}
getOptionLabel={role => role.name} />
getOptionValue={(role) => role._id}
getOptionLabel={(role) => role.name}
/>
{#if selectedRole}
<Input
label="Name"
bind:value={selectedRole.name}
disabled={builtInRoles.includes(selectedRole.name)} />
disabled={builtInRoles.includes(selectedRole.name)}
/>
<Select
label="Inherits Role"
bind:value={selectedRole.inherits}
options={otherRoles}
getOptionValue={role => role._id}
getOptionLabel={role => role.name}
placeholder="None" />
getOptionValue={(role) => role._id}
getOptionLabel={(role) => role.name}
placeholder="None"
/>
<Select
label="Base Permissions"
bind:value={selectedRole.permissionId}
options={basePermissions}
getOptionValue={x => x._id}
getOptionLabel={x => x.name}
placeholder="Choose permissions" />
getOptionValue={(x) => x._id}
getOptionLabel={(x) => x.name}
placeholder="Choose permissions"
/>
{/if}
<div slot="footer">
{#if !isCreating}

View File

@ -32,6 +32,7 @@
bind:value={exportFormat}
options={FORMATS}
placeholder={null}
getOptionLabel={x => x.name}
getOptionValue={x => x.key} />
getOptionLabel={(x) => x.name}
getOptionValue={(x) => x.key}
/>
</ModalContent>

View File

@ -10,7 +10,7 @@
$: fields =
viewTable &&
Object.entries(viewTable.schema)
.filter(entry => entry[1].type !== FIELDS.LINK.type)
.filter((entry) => entry[1].type !== FIELDS.LINK.type)
.map(([key]) => key)
function saveView() {

View File

@ -8,14 +8,16 @@
{height}
viewBox="0 0 256 215"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0)">
<path
d="M114.259 2.701L18.86 42.176C13.555 44.371 13.61 51.906 18.949
54.023L114.746 92.012C123.163 95.3503 132.537 95.3503 140.954
92.012L236.753 54.022C242.09 51.907 242.146 44.372 236.839 42.176L141.442
2.7C132.739 -0.901099 122.962 -0.901099 114.259 2.7"
fill="#FFBF00" />
fill="#FFBF00"
/>
<path
d="M136.35 112.757V207.659C136.35 212.173 140.9 215.264 145.096
213.601L251.844 172.166C253.034 171.694 254.056 170.875 254.775
@ -23,20 +25,23 @@
66.808 251.328 63.718 247.132 65.381L140.384 106.815C139.194 107.287
138.172 108.106 137.453 109.166C136.734 110.225 136.349 111.476 136.349
112.757"
fill="#26B5F8" />
fill="#26B5F8"
/>
<path
d="M111.423 117.654L79.743 132.95L76.526 134.505L9.65 166.548C5.411
168.593 0 165.504 0 160.795V71.72C0 70.016 0.874 68.545 2.046
67.437C2.52616 66.9592 3.07076 66.5509 3.664 66.224C5.262 65.265 7.542
65.009 9.48 65.776L110.89 105.956C116.045 108.001 116.45 115.224 111.423
117.653"
fill="#ED3049" />
fill="#ED3049"
/>
<path
d="M111.423 117.654L79.743 132.95L2.045 67.438C2.52516 66.9602 3.06976
66.5519 3.663 66.225C5.261 65.266 7.541 65.01 9.479 65.777L110.889
105.957C116.044 108.002 116.449 115.225 111.422 117.654"
fill="black"
fill-opacity="0.25" />
fill-opacity="0.25"
/>
</g>
<defs>
<clipPath id="clip0">

View File

@ -11,31 +11,38 @@
y="0px"
{width}
{height}
viewBox="0 0 2900 2000">
viewBox="0 0 2900 2000"
>
<g id="layer101">
<path
fill="#5b350f"
d="M735 1983 c-137 -19 -322 -95 -431 -175 -138 -103 -250 -315 -284 -542 -24 -161 22 -298 129 -382 123 -97 318 -180 577 -243 l130 -32 29 -67 c41 -94 135 -231 199 -289 292 -267 732 -319 1094 -128 148 79 224 151 418 400 137 176 173 242 228 414 41 130 70 301 70 416 0 236 -146 421 -382 484 -206 56 -392 19 -733 -144 -96 -47 -181 -85 -189 -85 -7 0 -61 46 -119 103 -163 159 -283 231 -433 261 -71 15 -229 19 -303 9z" />
d="M735 1983 c-137 -19 -322 -95 -431 -175 -138 -103 -250 -315 -284 -542 -24 -161 22 -298 129 -382 123 -97 318 -180 577 -243 l130 -32 29 -67 c41 -94 135 -231 199 -289 292 -267 732 -319 1094 -128 148 79 224 151 418 400 137 176 173 242 228 414 41 130 70 301 70 416 0 236 -146 421 -382 484 -206 56 -392 19 -733 -144 -96 -47 -181 -85 -189 -85 -7 0 -61 46 -119 103 -163 159 -283 231 -433 261 -71 15 -229 19 -303 9z"
/>
</g>
<g id="layer102">
<path
fill="#406f23"
d="M735 1983 c-137 -19 -322 -95 -431 -175 -138 -103 -250 -315 -284 -542 -24 -161 22 -298 129 -382 123 -97 318 -180 577 -243 l130 -32 29 -67 c41 -94 135 -231 199 -289 292 -267 732 -319 1094 -128 148 79 224 151 418 400 137 176 173 242 228 414 41 130 70 301 70 416 0 236 -146 421 -382 484 -206 56 -392 19 -733 -144 -96 -47 -181 -85 -189 -85 -7 0 -61 46 -119 103 -163 159 -283 231 -433 261 -71 15 -229 19 -303 9z m460 -643 c163 -51 296 -150 329 -246 23 -69 20 -93 -20 -174 -51 -100 -126 -173 -238 -230 l-89 -45 -131 0 c-151 0 -222 18 -323 84 -138 89 -243 264 -243 406 0 62 12 76 120 134 160 85 229 102 405 96 87 -2 139 -9 190 -25z" />
d="M735 1983 c-137 -19 -322 -95 -431 -175 -138 -103 -250 -315 -284 -542 -24 -161 22 -298 129 -382 123 -97 318 -180 577 -243 l130 -32 29 -67 c41 -94 135 -231 199 -289 292 -267 732 -319 1094 -128 148 79 224 151 418 400 137 176 173 242 228 414 41 130 70 301 70 416 0 236 -146 421 -382 484 -206 56 -392 19 -733 -144 -96 -47 -181 -85 -189 -85 -7 0 -61 46 -119 103 -163 159 -283 231 -433 261 -71 15 -229 19 -303 9z m460 -643 c163 -51 296 -150 329 -246 23 -69 20 -93 -20 -174 -51 -100 -126 -173 -238 -230 l-89 -45 -131 0 c-151 0 -222 18 -323 84 -138 89 -243 264 -243 406 0 62 12 76 120 134 160 85 229 102 405 96 87 -2 139 -9 190 -25z"
/>
</g>
<g id="layer103">
<path
fill="#c6d821"
d="M2215 1789 c-27 -4 -68 -15 -90 -23 -42 -15 -264 -116 -397 -180 l-77 -38 78 -102 c102 -134 144 -208 175 -305 37 -116 49 -200 44 -309 -7 -157 -46 -218 -175 -278 -94 -44 -178 -56 -313 -43 -108 10 -401 53 -479 70 -24 5 -45 8 -47 6 -2 -2 20 -44 49 -92 67 -115 176 -225 281 -284 87 -49 235 -103 335 -121 91 -16 253 -14 346 5 175 37 269 95 419 264 307 347 422 563 457 859 18 148 9 247 -29 325 -88 179 -340 286 -577 246z" />
d="M2215 1789 c-27 -4 -68 -15 -90 -23 -42 -15 -264 -116 -397 -180 l-77 -38 78 -102 c102 -134 144 -208 175 -305 37 -116 49 -200 44 -309 -7 -157 -46 -218 -175 -278 -94 -44 -178 -56 -313 -43 -108 10 -401 53 -479 70 -24 5 -45 8 -47 6 -2 -2 20 -44 49 -92 67 -115 176 -225 281 -284 87 -49 235 -103 335 -121 91 -16 253 -14 346 5 175 37 269 95 419 264 307 347 422 563 457 859 18 148 9 247 -29 325 -88 179 -340 286 -577 246z"
/>
<path
fill="#c6d821"
d="M549 1680 c-272 -34 -426 -142 -495 -346 -22 -68 -26 -91 -22 -164 6 -115 32 -173 112 -248 70 -65 236 -153 370 -196 241 -79 722 -172 985 -192 180 -14 343 55 404 170 34 64 30 168 -11 271 -88 223 -245 373 -568 542 -222 116 -379 161 -584 168 -69 2 -155 0 -191 -5z m646 -340 c163 -51 296 -150 329 -246 23 -69 20 -93 -20 -174 -50 -100 -126 -173 -235 -229 -84 -42 -90 -44 -200 -48 -190 -8 -312 37 -434 161 -98 99 -155 221 -155 331 0 62 12 76 120 134 160 85 229 102 405 96 87 -2 139 -9 190 -25z" />
d="M549 1680 c-272 -34 -426 -142 -495 -346 -22 -68 -26 -91 -22 -164 6 -115 32 -173 112 -248 70 -65 236 -153 370 -196 241 -79 722 -172 985 -192 180 -14 343 55 404 170 34 64 30 168 -11 271 -88 223 -245 373 -568 542 -222 116 -379 161 -584 168 -69 2 -155 0 -191 -5z m646 -340 c163 -51 296 -150 329 -246 23 -69 20 -93 -20 -174 -50 -100 -126 -173 -235 -229 -84 -42 -90 -44 -200 -48 -190 -8 -312 37 -434 161 -98 99 -155 221 -155 331 0 62 12 76 120 134 160 85 229 102 405 96 87 -2 139 -9 190 -25z"
/>
</g>
<g id="layer104">
<path
fill="#f6f654"
d="M2190 1721 c-57 -19 -469 -184 -494 -198 -12 -7 -5 -21 34 -72 28 -35 71 -96 97 -137 l46 -74 69 0 c38 0 83 -6 102 -14 52 -22 105 -75 139 -140 28 -55 32 -70 32 -147 0 -84 -2 -90 -48 -183 -96 -187 -234 -296 -376 -296 -44 0 -80 7 -110 20 -28 13 -65 20 -105 20 -72 0 -264 22 -426 49 -63 10 -117 17 -118 15 -10 -8 59 -113 110 -169 106 -115 238 -183 448 -231 155 -35 313 -29 447 17 78 27 210 117 279 191 82 89 277 353 336 456 92 159 137 344 125 513 -9 117 -37 189 -101 258 -109 116 -332 172 -486 122z" />
d="M2190 1721 c-57 -19 -469 -184 -494 -198 -12 -7 -5 -21 34 -72 28 -35 71 -96 97 -137 l46 -74 69 0 c38 0 83 -6 102 -14 52 -22 105 -75 139 -140 28 -55 32 -70 32 -147 0 -84 -2 -90 -48 -183 -96 -187 -234 -296 -376 -296 -44 0 -80 7 -110 20 -28 13 -65 20 -105 20 -72 0 -264 22 -426 49 -63 10 -117 17 -118 15 -10 -8 59 -113 110 -169 106 -115 238 -183 448 -231 155 -35 313 -29 447 17 78 27 210 117 279 191 82 89 277 353 336 456 92 159 137 344 125 513 -9 117 -37 189 -101 258 -109 116 -332 172 -486 122z"
/>
<path
fill="#f6f654"
d="M490 1624 c-153 -33 -275 -125 -339 -257 -54 -109 -59 -201 -17 -301 32 -76 164 -189 288 -245 51 -23 260 -91 281 -91 3 0 -21 25 -54 56 -94 91 -150 193 -170 313 -14 90 1 111 123 172 161 81 195 91 343 96 111 5 143 2 215 -16 221 -55 380 -192 380 -327 0 -52 -46 -143 -106 -212 -75 -85 -233 -170 -323 -173 -25 -1 -25 -1 4 -10 140 -43 411 -62 527 -38 142 30 238 125 238 234 0 88 -58 230 -139 337 -105 139 -431 343 -676 423 -161 52 -429 71 -575 39z" />
d="M490 1624 c-153 -33 -275 -125 -339 -257 -54 -109 -59 -201 -17 -301 32 -76 164 -189 288 -245 51 -23 260 -91 281 -91 3 0 -21 25 -54 56 -94 91 -150 193 -170 313 -14 90 1 111 123 172 161 81 195 91 343 96 111 5 143 2 215 -16 221 -55 380 -192 380 -327 0 -52 -46 -143 -106 -212 -75 -85 -233 -170 -323 -173 -25 -1 -25 -1 4 -10 140 -43 411 -62 527 -38 142 30 238 125 238 234 0 88 -58 230 -139 337 -105 139 -431 343 -676 423 -161 52 -429 71 -575 39z"
/>
</g>
</svg>

View File

@ -8,7 +8,8 @@
{height}
viewBox="0 0 175 115"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M142.187 76.6667C142.187 83.9288 138.367 87.4876 131.249
87.6136V87.6184H43.7507V87.6136C36.6331 87.4876 32.8132 83.9288 32.8132
@ -31,5 +32,6 @@
54.703 38.5444 60.0403 49.2194 60.2292V60.2381H125.782V60.2299C136.456
60.0416 142.187 54.7037 142.187 43.8109C142.187 32.9174 147.918 27.5795
158.593 27.3912V27.381H158.594Z"
fill="#E42528" />
fill="#E42528"
/>
</svg>

View File

@ -8,16 +8,19 @@
{height}
viewBox="0 0 256 289"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0)">
<path
d="M165.258 288.501H168.766L226.027 259.867L226.98 258.52V29.964L226.027
28.61L168.766 0H165.215L165.258 288.501Z"
fill="#5294CF" />
fill="#5294CF"
/>
<path
d="M90.741 288.501H87.184L29.972 259.867L28.811 257.87L28.222
31.128L29.972 28.61L87.184 0H90.785L90.741 288.501Z"
fill="#1F5B98" />
fill="#1F5B98"
/>
<path d="M87.285 0H168.711V288.501H87.285V0Z" fill="#2D72B8" />
<path
d="M256 137.769L254.065 137.34L226.437 134.764L226.027 134.968L168.715
@ -33,22 +36,27 @@
210.584V210.6H87.285V210.584L29.972 197.325V153.461L87.285
155.745V155.801H168.715L226.027 153.461L227.332 154.061L254.111
151.755L256 150.832L247.096 150.704V137.897L256 137.769"
fill="#1A476F" />
fill="#1A476F"
/>
<path
d="M226.027 215.966V259.867L256 224.749V194.288L226.2 215.914L226.027
215.966Z"
fill="#2D72B8" />
fill="#2D72B8"
/>
<path
d="M226.027 197.421L226.2 197.381L256 181.353V150.704L226.027
153.461V197.421"
fill="#2D72B8" />
fill="#2D72B8"
/>
<path
d="M226.2 91.208L226.027 91.168V134.968L256 137.769V107.135L226.2 91.208Z"
fill="#2D72B8" />
fill="#2D72B8"
/>
<path
d="M226.2 72.687L256 94.193V63.731L226.027 28.61V72.515L226.2
72.575V72.687Z"
fill="#2D72B8" />
fill="#2D72B8"
/>
</g>
<defs>
<clipPath id="clip0">

View File

@ -8,36 +8,43 @@
{height}
viewBox="0 0 128 143"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0)">
<path
d="M7.172 40.0865H101.775C112.201 40.0865 121.51 35.3065 127.757
27.843C114.727 10.918 94.2765 0 71.265 0C43.089 0 18.738 16.3555 7.172
40.0865Z"
fill="#F0BF1A" />
fill="#F0BF1A"
/>
<path
d="M93.7575 51.222H2.8775C0.969102 57.732 0.000154178 64.4811 0 71.265C0
78.227 1.0165 84.9485 2.8775 91.3085H93.7575C104.67 91.3085 113.801
82.4005 113.801 71.265C113.801 60.13 104.893 51.222 93.7575 51.222"
fill="#07A5DE" />
fill="#07A5DE"
/>
<path
d="M128 114.378C121.793 107.082 112.559 102.443 102.22
102.443H7.173C18.7385 126.175 43.0895 142.53 71.265 142.53C94.418 142.53
114.983 131.482 128 114.378Z"
fill="#3EBEB0" />
fill="#3EBEB0"
/>
<path
d="M2.87749 51.222C-0.959651 64.3087 -0.959651 78.2218 2.87749
91.3085H62.357C63.916 85.2955 64.8065 78.6145 64.8065 71.265C64.8065
63.916 63.916 57.235 62.3565 51.222H2.87849H2.87749Z"
fill="#231F20" />
fill="#231F20"
/>
<path
d="M35.41 9.5765C23.3835 16.703 13.362 27.3925 7.1265
40.0865H59.6845C54.3395 27.838 45.877 17.594 35.4095 9.5765"
fill="#D7A229" />
fill="#D7A229"
/>
<path
d="M37.637 134.068C47.881 125.828 56.121 114.915 61.2435
102.443H7.1265C13.8075 115.806 24.4975 126.941 37.637 134.068Z"
fill="#019B8F" />
fill="#019B8F"
/>
</g>
<defs>
<clipPath id="clip0">

View File

@ -8,31 +8,36 @@
{height}
viewBox="0 0 179 179"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M153.828 30.7656H101.806L90.0594
54.2594H24.6125V148.234H165.575V30.7656H153.828ZM153.828
54.2594H107.959L114.112 42.5125H153.828V54.2594Z"
fill="#458248" />
fill="#458248"
/>
<path
d="M149.773 173.406L146.623 172.36C146.623 172.36 147.026 156.412 141.276
155.299C137.483 150.903 141.835 -32.4046 155.635 154.673C153.015 156 151.011
158.289 150.041 161.061C149.521 165.155 149.431 169.293 149.773
173.406V173.406Z"
fill="url(#paint0_linear)" />
fill="url(#paint0_linear)"
/>
<path
d="M151.473 158.007C159.86 151.69 166.283 143.124 169.994 133.302C173.705
123.48 174.553 112.807 172.439 102.522C166.285 75.3142 151.68 66.3698
150.108 62.9577C148.75 60.8316 147.591 58.5845 146.646 56.2452L147.809
132.052C147.809 132.052 145.398 155.215 151.473 158.007Z"
fill="url(#paint1_linear)" />
fill="url(#paint1_linear)"
/>
<path
d="M145.018 159.014C145.018 159.014 119.337 141.522 120.825 110.583C120.964
101.255 123.102 92.0662 127.096 83.636C131.091 75.2058 136.847 67.7308
143.978 61.7158C144.809 61.0059 145.469 60.1177 145.91 59.1173C146.351
58.1169 146.56 57.03 146.523 55.9375C148.123 59.3777 147.86 107.299 148.027
112.904C148.682 134.709 146.819 154.897 145.018 159.014V159.014Z"
fill="url(#paint2_linear)" />
fill="url(#paint2_linear)"
/>
<defs>
<linearGradient
id="paint0_linear"
@ -40,7 +45,8 @@
y1="115.729"
x2="164.805"
y2="128.016"
gradientUnits="userSpaceOnUse">
gradientUnits="userSpaceOnUse"
>
<stop offset="0.231" stop-color="#999875" />
<stop offset="0.563" stop-color="#9B9977" />
<stop offset="0.683" stop-color="#A09F7E" />
@ -57,7 +63,8 @@
y1="55.7038"
x2="157.883"
y2="155.673"
gradientUnits="userSpaceOnUse">
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#48A547" />
<stop offset="1" stop-color="#3F9143" />
</linearGradient>
@ -67,7 +74,8 @@
y1="113.645"
x2="161.577"
y2="99.2572"
gradientUnits="userSpaceOnUse">
gradientUnits="userSpaceOnUse"
>
<stop stop-color="#41A247" />
<stop offset="0.352" stop-color="#4BA74B" />
<stop offset="0.956" stop-color="#67B554" />

View File

@ -8,12 +8,14 @@
{height}
viewBox="0 0 147 147"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M128.244 27.5625H83.3444L74.1569
45.9375H22.9688V124.031H137.812V27.5625H128.244ZM128.625
45.9375H92.7478L97.5621 36.75H128.625V45.9375Z"
fill="#2A4B59" />
fill="#2A4B59"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
@ -23,7 +25,8 @@
73.4258 75.6415 72.917 75.8825 72.3379C76.1234 71.7589 76.2141 71.1283
76.146 70.5048C75.8564 70.0602 75.5911 69.6001 75.3513 69.1267C74.9562
68.4652 74.0926 68.1345 73.5597 67.6062"
fill="white" />
fill="white"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
@ -79,5 +82,6 @@
114.951 109.408 116.856 112.175C117.848 113.553 121.822 114.293 123.609
115.023C125.17 115.557 126.703 116.17 128.202 116.86C130.453 118.239 132.7
119.842 134.822 121.367C135.879 122.162 139.191 123.815 139.388 125.143"
fill="#F3FDFF" />
fill="#F3FDFF"
/>
</svg>

View File

@ -8,7 +8,8 @@
{height}
viewBox="0 0 170 175"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M169.341 104.792C168.322 101.71 165.652 99.5637 162.199 99.0487C160.57
98.8061 158.706 98.9095 156.499 99.3635C152.653 100.156 149.799 100.457
@ -32,7 +33,8 @@
134.335 126.893 134.386 126.453L134.492 125.551L135.685 125.655L135.993
125.676C142.635 125.978 150.756 124.572 155.744 122.259C159.685 120.434
172.315 113.778 169.341 104.792"
fill="black" />
fill="black"
/>
<path
d="M157.984 106.539C138.235 110.606 136.877 103.931 136.877 103.931C157.729
73.046 166.446 33.8413 158.924 24.2462C138.402 -1.92761 102.878 10.451
@ -50,21 +52,24 @@
130.43C128.417 120.001 127.363 116.636 134.573 118.201L136.326
118.355C141.632 118.596 148.578 117.503 152.655 115.611C161.432 111.545
166.639 104.755 157.983 106.539H157.984"
fill="#336791" />
fill="#336791"
/>
<path
d="M71.7692 54.0412C69.9895 53.7939 68.3778 54.0226 67.5623 54.6391C67.1041
54.9858 66.962 55.3875 66.9235 55.6639C66.8212 56.3964 67.3352 57.2064
67.6513 57.624C68.5452 58.8066 69.8507 59.6193 71.143 59.7983C71.3302
59.8248 71.5168 59.8367 71.7021 59.8367C73.857 59.8367 75.8167 58.1616
75.9893 56.9254C76.2051 55.3769 73.9533 54.3448 71.7692 54.0418"
fill="white" />
fill="white"
/>
<path
d="M130.727 54.0902C130.557 52.8765 128.394 52.5305 126.341 52.8155C124.29
53.1006 122.302 54.0246 122.468 55.241C122.601 56.1869 124.312 57.8017
126.337 57.8017C126.509 57.8017 126.681 57.7904 126.855 57.7659C128.207
57.579 129.199 56.7219 129.671 56.228C130.388 55.475 130.804 54.6358 130.727
54.0902"
fill="white" />
fill="white"
/>
<path
d="M164.556 106.077C163.803 103.804 161.379 103.073 157.352 103.903C145.396
106.366 141.114 104.66 139.708 103.627C149.002 89.494 156.647 72.4103
@ -145,5 +150,6 @@
136.156 107.46 136.491 107.343C136.699 107.512 136.926 107.68 137.176
107.844C141.168 110.475 148.289 110.758 158.342 108.687L158.453
108.665C157.097 109.931 154.776 111.629 151.487 113.154Z"
fill="white" />
fill="white"
/>
</svg>

View File

@ -8,12 +8,14 @@
{height}
viewBox="0 0 120 120"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M103.125 20.625H68.25L60.375
36.375H16.5V99.375H111V20.625H103.125ZM103.125 36.375H72.375L76.5
28.5H103.125V36.375Z"
fill="#FFBA58" />
fill="#FFBA58"
/>
<path
d="M75 46.875V52.5H60C58.0127 52.5059 56.1085 53.298 54.7033 54.7033C53.298
56.1085 52.5059 58.0127 52.5 60V75H46.875C44.3886 75 42.004 75.9877 40.2459
@ -32,5 +34,6 @@
44.3886 92.7623 42.004 91.0041 40.2459C89.246 38.4877 86.8614 37.5 84.375
37.5C81.8886 37.5 79.504 38.4877 77.7459 40.2459C75.9877 42.004 75 44.3886
75 46.875Z"
fill="#E76A00" />
fill="#E76A00"
/>
</svg>

View File

@ -8,48 +8,61 @@
{height}
viewBox="0 0 128 155"
fill="none"
xmlns="http://www.w3.org/2000/svg">
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.312 26.843L0 32V122.51L10.312 127.637L10.374 127.562V26.914L10.312
26.843Z"
fill="#8C3123" />
fill="#8C3123"
/>
<path
d="M65.5 114.5L10.312 127.637V26.843L65.5 39.6935V114.5Z"
fill="#E05243" />
fill="#E05243"
/>
<path
d="M40.589 93.933L63.998 96.913L64.145 96.574L64.2765 58.189L63.998
57.889L40.589 60.826V93.933"
fill="#8C3123" />
fill="#8C3123"
/>
<path
d="M63.998 114.647L117.683 127.665L117.768 127.53L117.766 26.933L117.681
26.843L63.998 39.841V114.647"
fill="#8C3123" />
fill="#8C3123"
/>
<path
d="M87.4135 93.933L63.998 96.913V57.889L87.4135 60.826V93.933Z"
fill="#E05243" />
fill="#E05243"
/>
<path
d="M87.4135 44.8155L63.998 49.083L40.589 44.8155L63.9685 38.6875L87.4135
44.8155Z"
fill="#5E1F18" />
fill="#5E1F18"
/>
<path
d="M87.4135 109.901L63.998 105.605L40.589 109.901L63.9695 116.427L87.4135
109.901Z"
fill="#F2B0A9" />
fill="#F2B0A9"
/>
<path
d="M40.589 44.8155L63.998 39.0225L64.1875 38.964V0.1565L63.998 0L40.589
11.7065V44.8155Z"
fill="#8C3123" />
fill="#8C3123"
/>
<path
d="M87.4135 44.8155L63.998 39.0225V0L87.4135 11.7065V44.8155Z"
fill="#E05243" />
fill="#E05243"
/>
<path
d="M63.998 154.714L40.5865 143.012V109.903L63.998 115.694L64.3425
116.086L64.249 154.039L63.998 154.714Z"
fill="#8C3123" />
fill="#8C3123"
/>
<path
d="M63.998 154.714L87.4115 143.012V109.903L63.998 115.694V154.714"
fill="#E05243" />
fill="#E05243"
/>
<path
d="M117.684 26.843L128 32V122.51L117.684 127.665V26.843Z"
fill="#E05243" />
fill="#E05243"
/>
</svg>

View File

@ -7,7 +7,8 @@
{width}
{height}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1478.201 1195.111">
viewBox="0 0 1478.201 1195.111"
>
<g transform="matrix(.569 0 0 .569 199.451 -82.735)">
<linearGradient
id="a"
@ -16,7 +17,8 @@
y1="923.573"
x2="-2061.249"
y2="1420.331"
gradientTransform="matrix(.1234 0 0 -.1234 1158.33 1550.273)">
gradientTransform="matrix(.1234 0 0 -.1234 1158.33 1550.273)"
>
<stop offset="0" stop-color="#909ca9" />
<stop offset="1" stop-color="#ededee" />
</linearGradient>
@ -107,7 +109,8 @@
99.755-47.06 130.547-2.815 6.939-3.896 8.677-5.417
8.456-3.687-.213-54.646-7.37-85.66-11.925-53.994-8.24-144.641-24.073-167.409-29.275l-5.204-1.083
32.307-7.378c69.396-15.613 102.791-24.069 136.619-34.478 42.722-13.011
85.011-29.276 127.729-49.225 6.722-3.037 12.361-5.422 13.879-5.639z" />
85.011-29.276 127.729-49.225 6.722-3.037 12.361-5.422 13.879-5.639z"
/>
<linearGradient
id="b"
gradientUnits="userSpaceOnUse"
@ -115,7 +118,8 @@
y1="10288.81"
x2="-2206.249"
y2="10288.81"
gradientTransform="matrix(.1234 0 0 -.1234 1158.33 1550.273)">
gradientTransform="matrix(.1234 0 0 -.1234 1158.33 1550.273)"
>
<stop offset="0" stop-color="#939fab" />
<stop offset="1" stop-color="#dcdee1" />
</linearGradient>
@ -142,14 +146,16 @@
4.552 7.806 7.373 16.263 30.364 60.07 35.997 68.526 1.74 2.822 4.771
3.038-25.802-1.95-73.512-11.93-97.152-15.829-97.152-16.263 0-.216
2.169-1.735 4.988-3.254 22.771-12.575 45.756-28.624 66.142-45.756
4.988-4.121 9.542-8.024 10.407-8.676.216-.433.652-.649.868-.433z" />
4.988-4.121 9.542-8.024 10.407-8.676.216-.433.652-.649.868-.433z"
/>
<radialGradient
id="c"
cx="-14217.448"
cy="7277.705"
r="898.12"
gradientTransform="matrix(-.1185 -.0178 -.036 .237 -198.955 -1314.415)"
gradientUnits="userSpaceOnUse">
gradientUnits="userSpaceOnUse"
>
<stop offset="0" stop-color="#ee352c" />
<stop offset="1" stop-color="#a91d22" />
</radialGradient>
@ -241,7 +247,8 @@
45.971-41.853 42.723-83.273 76.12-134.669 108.649-6.505 4.119-12.359
7.804-13.011 8.24-1.519.867.432-1.303 22.986-25.808 14.314-15.397
25.155-28.408 37.516-44.453 8.24-10.624 9.759-12.143 21.688-20.604
31.878-22.987 105.39-72.864 106.258-71.995z" />
31.878-22.987 105.39-72.864 106.258-71.995z"
/>
</g>
<path
fill="#231F1F"
@ -387,5 +394,6 @@
18.172h1.301l8.152-18.347c.219-.563.393-1.301.76-2.275-.174 1.887-.174
3.401-.174 4.553v16.048h2.82V792.52h-3.406l-7.371 16.438c-.174.587-.762
1.734-1.129
3.037h-.217c-.152-.761-.541-1.519-1.084-2.818l-7.373-16.655h-3.816v23.854h2.666v-15.917l.152-.023z" />
3.037h-.217c-.152-.761-.541-1.519-1.084-2.818l-7.373-16.655h-3.816v23.854h2.666v-15.917l.152-.023z"
/>
</svg>

View File

@ -14,7 +14,9 @@
function checkValid(evt) {
const datasourceName = evt.target.value
if (
$datasources?.list.some(datasource => datasource.name === datasourceName)
$datasources?.list.some(
(datasource) => datasource.name === datasourceName
)
) {
error = `Datasource with name ${datasourceName} already exists. Please choose another name.`
return
@ -44,13 +46,15 @@
size="large"
confirmText="Create"
onConfirm={saveDatasource}
disabled={error || !name}>
disabled={error || !name}
>
<Input
data-cy="datasource-name-input"
label="Datasource Name"
on:input={checkValid}
bind:value={name}
{error} />
{error}
/>
<Label>Datasource Type</Label>
<TableIntegrationMenu bind:integration />
</ModalContent>

View File

@ -11,7 +11,8 @@
class:indented
class:selected
on:click
class={className}>
class={className}
>
<i class={icon} />
<span>{title}</span>
<slot />

View File

@ -18,7 +18,7 @@
let schema = {}
let fields = []
$: valid = !schema || fields.every(column => schema[column].success)
$: valid = !schema || fields.every((column) => schema[column].success)
$: dataImport = {
valid,
schema: buildTableSchema(schema),
@ -51,7 +51,7 @@
const parseResult = await response.json()
schema = parseResult && parseResult.schema
fields = Object.keys(schema || {}).filter(
key => schema[key].type !== "omit"
(key) => schema[key].type !== "omit"
)
// Check primary display is valid
@ -67,17 +67,18 @@
async function handleFile(evt) {
const fileArray = Array.from(evt.target.files)
if (fileArray.some(file => file.size >= FILE_SIZE_LIMIT)) {
if (fileArray.some((file) => file.size >= FILE_SIZE_LIMIT)) {
notifications.error(
`Files cannot exceed ${FILE_SIZE_LIMIT /
BYTES_IN_MB}MB. Please try again with smaller files.`
`Files cannot exceed ${
FILE_SIZE_LIMIT / BYTES_IN_MB
}MB. Please try again with smaller files.`
)
return
}
// Read CSV as plain text to upload alongside schema
let reader = new FileReader()
reader.addEventListener("load", function(e) {
reader.addEventListener("load", function (e) {
csvString = e.target.result
files = fileArray
validateCSV()
@ -90,7 +91,7 @@
await validateCSV()
}
const handleTypeChange = column => evt => {
const handleTypeChange = (column) => (evt) => {
schema[column].type = evt.detail
validateCSV()
}
@ -127,14 +128,16 @@
on:change={handleTypeChange(columnName)}
options={typeOptions}
placeholder={null}
getOptionLabel={option => option.label}
getOptionValue={option => option.value} />
getOptionLabel={(option) => option.label}
getOptionValue={(option) => option.value}
/>
<span class="field-status" class:error={!schema[columnName].success}>
{schema[columnName].success ? 'Success' : 'Failure'}
{schema[columnName].success ? "Success" : "Failure"}
</span>
<i
class="omit-button ri-close-circle-fill"
on:click={() => omitColumn(columnName)} />
on:click={() => omitColumn(columnName)}
/>
</div>
{/each}
</div>
@ -145,7 +148,8 @@
<Select
label="Display Column"
bind:value={primaryDisplay}
options={fields} />
options={fields}
/>
</div>
{/if}

View File

@ -34,10 +34,11 @@
{#each $tables.list as table, idx}
<NavItem
border={idx > 0}
icon={table._id === TableNames.USERS ? 'UserGroup' : 'Table'}
icon={table._id === TableNames.USERS ? "UserGroup" : "Table"}
text={table.name}
selected={selectedView === `all_${table._id}`}
on:click={() => selectTable(table)}>
on:click={() => selectTable(table)}
>
{#if table._id !== TableNames.USERS}
<EditTablePopover {table} />
{/if}
@ -48,9 +49,11 @@
icon="Remove"
text={viewName}
selected={selectedView === viewName}
on:click={() => onClickView(table, viewName)}>
on:click={() => onClickView(table, viewName)}
>
<EditViewPopover
view={{ name: viewName, ...table.views[viewName] }} />
view={{ name: viewName, ...table.views[viewName] }}
/>
</NavItem>
{/each}
{/each}

View File

@ -18,7 +18,7 @@
ROW_LIST_TEMPLATE,
]
$: tableNames = $tables.list.map(table => table.name)
$: tableNames = $tables.list.map((table) => table.name)
let modal
let name
@ -66,8 +66,8 @@
// Create auto screens
if (createAutoscreens) {
const screens = screenTemplates($store, [table])
.filter(template => defaultScreens.includes(template.id))
.map(template => template.create())
.filter((template) => defaultScreens.includes(template.id))
.map((template) => template.create())
for (let screen of screens) {
// Record the table that created this screen so we can link it later
screen.autoTableId = table._id
@ -75,7 +75,7 @@
}
// Create autolink to newly created list screen
const listScreen = screens.find(screen =>
const listScreen = screens.find((screen) =>
screen.props._instanceName.endsWith("List")
)
await store.actions.components.links.save(
@ -93,14 +93,16 @@
title="Create Table"
confirmText="Create"
onConfirm={saveTable}
disabled={error || !name || (dataImport && !dataImport.valid)}>
disabled={error || !name || (dataImport && !dataImport.valid)}
>
<Input
data-cy="table-name-input"
thin
label="Table Name"
on:input={checkValid}
bind:value={name}
{error} />
{error}
/>
<div class="autocolumns">
<Label extraSmall grey>Auto Columns</Label>
<div class="toggles">
@ -118,7 +120,8 @@
</div>
<Toggle
text="Generate screens in Design section"
bind:value={createAutoscreens} />
bind:value={createAutoscreens}
/>
<div>
<Label grey extraSmall>Create Table from CSV (Optional)</Label>
<TableDataImport bind:dataImport />

Some files were not shown because too many files have changed in this diff Show More