[#2318] updated schema fields ui
This commit is contained in:
@@ -143,7 +143,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="accordions schema-fields">
|
||||
<div class="schema-fields">
|
||||
{#each collection.schema as field, i (field)}
|
||||
<svelte:component
|
||||
this={fieldComponents[field.type]}
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<button type="button" class={classes} on:click={dispatch}>
|
||||
<button type="button" class="field-types-btn {classes}" on:click={dispatch}>
|
||||
<i class="ri-add-line" />
|
||||
<div class="txt">New field</div>
|
||||
<Toggler class="dropdown field-types-dropdown">
|
||||
@@ -96,13 +96,17 @@
|
||||
</button>
|
||||
|
||||
<style lang="scss">
|
||||
.field-types-btn.active {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
:global(.field-types-dropdown) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
margin-top: 2px;
|
||||
border: 0;
|
||||
box-shadow: 0px 0px 0px 2px var(--primaryColor);
|
||||
border-top-left-radius: 0;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<script context="module">
|
||||
let siblings = [];
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { slide } from "svelte/transition";
|
||||
@@ -12,10 +16,13 @@
|
||||
export let field = new SchemaField();
|
||||
|
||||
let nameInput;
|
||||
let optionsTrigger;
|
||||
let isDragOver = false;
|
||||
let showOptions = false;
|
||||
|
||||
const componentId = "f_" + CommonHelper.randomString(8);
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const customRequiredLabels = {
|
||||
// type => label
|
||||
bool: "Nonfalsey",
|
||||
@@ -66,17 +73,54 @@
|
||||
return CommonHelper.slugify(name);
|
||||
}
|
||||
|
||||
function expand() {
|
||||
showOptions = true;
|
||||
collapseSiblings();
|
||||
}
|
||||
|
||||
function collapse() {
|
||||
showOptions = false;
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
if (showOptions) {
|
||||
collapse();
|
||||
} else {
|
||||
expand();
|
||||
}
|
||||
}
|
||||
|
||||
function collapseSiblings() {
|
||||
for (let f of siblings) {
|
||||
if (f.id == componentId) {
|
||||
continue;
|
||||
}
|
||||
f.collapse();
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
siblings.push({
|
||||
id: componentId,
|
||||
collapse: collapse,
|
||||
});
|
||||
|
||||
if (field.onMountSelect) {
|
||||
field.onMountSelect = false;
|
||||
nameInput?.select();
|
||||
}
|
||||
|
||||
return () => {
|
||||
CommonHelper.removeByKey(siblings, "id", componentId);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
draggable={true}
|
||||
class="schema-field"
|
||||
class:required={field.required}
|
||||
class:expanded={showOptions}
|
||||
class:drag-over={isDragOver}
|
||||
transition:slide|local={{ duration: 150 }}
|
||||
on:dragstart={(e) => {
|
||||
@@ -154,7 +198,9 @@
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<slot {interactive} {hasErrors} />
|
||||
<slot {interactive} {hasErrors}>
|
||||
<span class="separator" />
|
||||
</slot>
|
||||
|
||||
{#if field.toDelete}
|
||||
<button
|
||||
@@ -168,20 +214,22 @@
|
||||
</button>
|
||||
{:else if interactive}
|
||||
<button
|
||||
bind:this={optionsTrigger}
|
||||
type="button"
|
||||
aria-label="Field options"
|
||||
class="btn btn-sm btn-circle btn-transparent options-trigger {hasErrors
|
||||
? 'btn-danger'
|
||||
: 'btn-hint'}"
|
||||
aria-label="Toggle field options"
|
||||
class="btn btn-sm btn-circle options-trigger {showOptions
|
||||
? 'btn-secondary'
|
||||
: 'btn-transparent'}"
|
||||
class:btn-hint={!showOptions && !hasErrors}
|
||||
class:btn-danger={hasErrors}
|
||||
on:click={toggle}
|
||||
>
|
||||
<i class="ri-settings-3-line" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if interactive}
|
||||
<Toggler class="dropdown dropdown-block schema-field-dropdown" trigger={optionsTrigger}>
|
||||
{#if interactive && showOptions}
|
||||
<div class="schema-field-options" transition:slide|local={{ duration: 150 }}>
|
||||
<div class="grid grid-sm">
|
||||
<div class="col-sm-12 hidden-empty">
|
||||
<slot name="options" {interactive} {hasErrors} />
|
||||
@@ -231,6 +279,6 @@
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Toggler>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
{...$$restProps}
|
||||
>
|
||||
<svelte:fragment let:interactive>
|
||||
<div class="separator" />
|
||||
|
||||
<Field
|
||||
class="form-field form-field-single-multiple-select {!interactive ? 'disabled' : ''}"
|
||||
inlineError
|
||||
@@ -94,6 +96,8 @@
|
||||
bind:keyOfSelected={isSingle}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<div class="separator" />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="options">
|
||||
|
||||
@@ -101,8 +101,10 @@
|
||||
{...$$restProps}
|
||||
>
|
||||
<svelte:fragment let:interactive>
|
||||
<div class="separator" />
|
||||
|
||||
<Field
|
||||
class="form-field required {!interactive ? 'disabled' : ''}"
|
||||
class="form-field required {!interactive ? 'readonly' : ''}"
|
||||
inlineError
|
||||
name="schema.{key}.options.collectionId"
|
||||
let:uniqueId
|
||||
@@ -131,6 +133,8 @@
|
||||
</ObjectSelect>
|
||||
</Field>
|
||||
|
||||
<div class="separator" />
|
||||
|
||||
<Field
|
||||
class="form-field form-field-single-multiple-select {!interactive ? 'disabled' : ''}"
|
||||
inlineError
|
||||
@@ -143,6 +147,8 @@
|
||||
bind:keyOfSelected={isSingle}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<div class="separator" />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="options">
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
{...$$restProps}
|
||||
>
|
||||
<svelte:fragment let:interactive>
|
||||
<div class="separator" />
|
||||
|
||||
<Field
|
||||
class="form-field required {!interactive ? 'disabled' : ''}"
|
||||
inlineError
|
||||
@@ -68,6 +70,9 @@
|
||||
/>
|
||||
</div>
|
||||
</Field>
|
||||
|
||||
<div class="separator" />
|
||||
|
||||
<Field
|
||||
class="form-field form-field-single-multiple-select {!interactive ? 'disabled' : ''}"
|
||||
inlineError
|
||||
@@ -80,6 +85,8 @@
|
||||
bind:keyOfSelected={isSingle}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<div class="separator" />
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="options">
|
||||
|
||||
@@ -956,7 +956,7 @@ select {
|
||||
cursor: pointer;
|
||||
}
|
||||
&.disabled {
|
||||
color: var(--txtDisabledColor);
|
||||
color: var(--txtHintColor);
|
||||
pointer-events: none;
|
||||
.txt-placeholder {
|
||||
color: inherit;
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
.schema-field {
|
||||
@extend %block;
|
||||
position: relative;
|
||||
margin: 0 0 var(--xsSpacing);
|
||||
&.drag-over {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.schema-field-header {
|
||||
$minHeight: 44px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
min-height: $minHeight;
|
||||
gap: 5px;
|
||||
padding: 0 5px;
|
||||
align-items: center;
|
||||
justify-content: stretch;
|
||||
%input,
|
||||
.form-field-addon {
|
||||
min-height: var(--btnHeight);
|
||||
}
|
||||
background: var(--baseAlt1Color);
|
||||
border-radius: var(--baseRadius);
|
||||
transition: border-radius var(--baseAnimationSpeed);
|
||||
.form-field {
|
||||
margin: 0;
|
||||
.form-field-addon.prefix {
|
||||
left: 10px;
|
||||
~ %input {
|
||||
padding-left: 37px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.options-trigger {
|
||||
padding: 2px;
|
||||
margin: 0 3px;
|
||||
i {
|
||||
transition: transform var(--baseAnimationSpeed);
|
||||
}
|
||||
&.active {
|
||||
i {
|
||||
transform: rotate(58deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.separator {
|
||||
width: 1px;
|
||||
height: $minHeight;
|
||||
background: var(--baseAlt2Color);
|
||||
}
|
||||
.drag-handle-wrapper {
|
||||
position: absolute;
|
||||
@@ -56,8 +58,8 @@
|
||||
.markers {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
left: 7px;
|
||||
top: 6px;
|
||||
left: 4px;
|
||||
top: 4px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
@@ -79,16 +81,34 @@
|
||||
@include show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.schema-field-dropdown {
|
||||
padding: var(--smSpacing);
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.schema-field-options {
|
||||
margin-top: -10px;
|
||||
background: var(--bodyColor);
|
||||
padding: var(--smSpacing);
|
||||
border-radius: var(--baseRadius);
|
||||
padding: var(--xsSpacing) var(--smSpacing);
|
||||
border-bottom-left-radius: var(--baseRadius);
|
||||
border-bottom-right-radius: var(--baseRadius);
|
||||
border: 2px solid var(--baseAlt1Color);
|
||||
}
|
||||
|
||||
.schema-field {
|
||||
@extend %block;
|
||||
position: relative;
|
||||
margin: 0 0 var(--xsSpacing);
|
||||
transition: box-shadow var(--baseAnimationSpeed);
|
||||
&.drag-over {
|
||||
opacity: 0.5;
|
||||
}
|
||||
&.expanded {
|
||||
@include shadowize();
|
||||
.schema-field-header {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
.options-trigger {
|
||||
i {
|
||||
transform: rotate(-60deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user