[#976] added optional RelationOptions.DisplayFields and refactored the relation picker UI
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
<button
|
||||
autofocus
|
||||
type="button"
|
||||
class="btn btn-secondary btn-expanded-sm"
|
||||
class="btn btn-transparent btn-expanded-sm"
|
||||
disabled={isConfirmationBusy}
|
||||
on:click={() => {
|
||||
confirmed = false;
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<script>
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let index;
|
||||
export let list = [];
|
||||
export let disabled = false;
|
||||
|
||||
let dragging = false;
|
||||
let dragover = false;
|
||||
|
||||
function onDrag(event, i) {
|
||||
if (!event && !disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
dragging = true;
|
||||
|
||||
event.dataTransfer.effectAllowed = "move";
|
||||
event.dataTransfer.dropEffect = "move";
|
||||
event.dataTransfer.setData("text/plain", i);
|
||||
}
|
||||
|
||||
function onDrop(event, target) {
|
||||
if (!event && !disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
dragover = false;
|
||||
dragging = false;
|
||||
|
||||
event.dataTransfer.dropEffect = "move";
|
||||
|
||||
const start = parseInt(event.dataTransfer.getData("text/plain"));
|
||||
|
||||
if (start < target) {
|
||||
list.splice(target + 1, 0, list[start]);
|
||||
list.splice(start, 1);
|
||||
} else {
|
||||
list.splice(target, 0, list[start]);
|
||||
list.splice(start + 1, 1);
|
||||
}
|
||||
|
||||
list = list;
|
||||
|
||||
dispatch("sort", list);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
draggable={true}
|
||||
class="draggable"
|
||||
class:dragging
|
||||
class:dragover
|
||||
on:dragover|preventDefault={() => {
|
||||
dragover = true;
|
||||
}}
|
||||
on:dragleave|preventDefault={() => {
|
||||
dragover = false;
|
||||
}}
|
||||
on:dragend={() => {
|
||||
dragover = false;
|
||||
dragging = false;
|
||||
}}
|
||||
on:dragstart={(e) => onDrag(e, index)}
|
||||
on:drop={(e) => onDrop(e, index)}
|
||||
>
|
||||
<slot {dragging} {dragover} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.draggable {
|
||||
user-select: none;
|
||||
outline: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -33,6 +33,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div bind:this={container} class={classes} class:error={fieldErrors.length} on:click>
|
||||
<slot {uniqueId} />
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* <h5 slot="header">My title</h5>
|
||||
* <p>Lorem ipsum dolor sit amet...</p>
|
||||
* <svelte:fragment slot="footer">
|
||||
* <button class="btn btn-secondary">Cancel</button>
|
||||
* <button class="btn btn-transparent">Cancel</button>
|
||||
* <button class="btn btn-expanded">Save</button>
|
||||
* </svelte:fragment>
|
||||
* </OverlayPanel>
|
||||
@@ -52,8 +52,11 @@
|
||||
let transitionSpeed = 150;
|
||||
let contentScrollThrottle;
|
||||
let contentScrollClass = "";
|
||||
let oldActive = active;
|
||||
|
||||
$: onActiveChange(active);
|
||||
$: if (oldActive != active) {
|
||||
onActiveChange(active);
|
||||
}
|
||||
|
||||
$: handleContentScroll(contentPanel, true);
|
||||
|
||||
@@ -81,8 +84,10 @@
|
||||
return active;
|
||||
}
|
||||
|
||||
async function onActiveChange(state) {
|
||||
if (state) {
|
||||
async function onActiveChange(newState) {
|
||||
oldActive = newState;
|
||||
|
||||
if (newState) {
|
||||
oldFocusedElem = document.activeElement;
|
||||
wrapper?.focus();
|
||||
dispatch("show");
|
||||
@@ -91,7 +96,10 @@
|
||||
clearTimeout(contentScrollThrottle);
|
||||
oldFocusedElem?.focus();
|
||||
dispatch("hide");
|
||||
document.body.classList.remove("overlay-active");
|
||||
|
||||
if (getHolder().querySelectorAll(".overlay-panel-container.active").length <= 1) {
|
||||
document.body.classList.remove("overlay-active");
|
||||
}
|
||||
}
|
||||
|
||||
await tick();
|
||||
@@ -194,6 +202,7 @@
|
||||
<div bind:this={wrapper} class="overlay-panel-wrapper">
|
||||
{#if active}
|
||||
<div class="overlay-panel-container" class:padded={popup} class:active>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="overlay"
|
||||
on:click|preventDefault={() => (overlayClose ? hide() : true)}
|
||||
@@ -208,9 +217,9 @@
|
||||
>
|
||||
<div class="overlay-panel-section panel-header">
|
||||
{#if btnClose && !popup}
|
||||
<div class="overlay-close" on:click|preventDefault={hide}>
|
||||
<button type="button" class="overlay-close" on:click|preventDefault={hide}>
|
||||
<i class="ri-close-line" />
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<slot name="header" />
|
||||
@@ -218,7 +227,7 @@
|
||||
{#if btnClose && popup}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-circle btn-secondary btn-close m-l-auto"
|
||||
class="btn btn-sm btn-circle btn-transparent btn-close m-l-auto"
|
||||
on:click|preventDefault={hide}
|
||||
>
|
||||
<i class="ri-close-line txt-lg" />
|
||||
|
||||
@@ -51,6 +51,6 @@
|
||||
<i class="ri-external-link-line" />
|
||||
</a>
|
||||
<div class="flex-fill" />
|
||||
<button type="button" class="btn btn-secondary" on:click={hide}>Close</button>
|
||||
<button type="button" class="btn btn-transparent" on:click={hide}>Close</button>
|
||||
</svelte:fragment>
|
||||
</OverlayPanel>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<div class="form-field-addon">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-circle"
|
||||
class="btn btn-transparent btn-circle"
|
||||
use:tooltip={{ position: "left", text: "Set new value" }}
|
||||
on:click={() => unlock()}
|
||||
>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-circle"
|
||||
class="btn btn-transparent btn-circle"
|
||||
class:refreshing={refreshTimeoutId}
|
||||
use:tooltip={tooltipData}
|
||||
on:click={refresh}
|
||||
|
||||
@@ -53,58 +53,56 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="searchbar-wrapper">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<form class="searchbar" on:click|stopPropagation on:submit|preventDefault={submit}>
|
||||
<label for={uniqueId} class="m-l-10 txt-xl">
|
||||
<i class="ri-search-line" />
|
||||
</label>
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<form class="searchbar" on:click|stopPropagation on:submit|preventDefault={submit}>
|
||||
<label for={uniqueId} class="m-l-10 txt-xl">
|
||||
<i class="ri-search-line" />
|
||||
</label>
|
||||
|
||||
{#if filterComponent && !isFilterComponentLoading}
|
||||
<svelte:component
|
||||
this={filterComponent}
|
||||
id={uniqueId}
|
||||
singleLine
|
||||
disableRequestKeys
|
||||
disableIndirectCollectionsKeys
|
||||
{extraAutocompleteKeys}
|
||||
baseCollection={autocompleteCollection}
|
||||
placeholder={value || placeholder}
|
||||
bind:value={tempValue}
|
||||
on:submit={submit}
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
id={uniqueId}
|
||||
placeholder={value || placeholder}
|
||||
bind:value={tempValue}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if value.length || tempValue.length}
|
||||
{#if tempValue !== value}
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-expanded btn-sm btn-warning"
|
||||
transition:fly|local={{ duration: 150, x: 5 }}
|
||||
>
|
||||
<span class="txt">Search</span>
|
||||
</button>
|
||||
{/if}
|
||||
{#if filterComponent && !isFilterComponentLoading}
|
||||
<svelte:component
|
||||
this={filterComponent}
|
||||
id={uniqueId}
|
||||
singleLine
|
||||
disableRequestKeys
|
||||
disableIndirectCollectionsKeys
|
||||
{extraAutocompleteKeys}
|
||||
baseCollection={autocompleteCollection}
|
||||
placeholder={value || placeholder}
|
||||
bind:value={tempValue}
|
||||
on:submit={submit}
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
bind:this={searchInput}
|
||||
type="text"
|
||||
id={uniqueId}
|
||||
placeholder={value || placeholder}
|
||||
bind:value={tempValue}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if value.length || tempValue.length}
|
||||
{#if tempValue !== value}
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary btn-sm btn-hint p-l-xs p-r-xs m-l-10"
|
||||
type="submit"
|
||||
class="btn btn-expanded btn-sm btn-warning"
|
||||
transition:fly|local={{ duration: 150, x: 5 }}
|
||||
on:click={() => {
|
||||
clear(false);
|
||||
submit();
|
||||
}}
|
||||
>
|
||||
<span class="txt">Clear</span>
|
||||
<span class="txt">Search</span>
|
||||
</button>
|
||||
{/if}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-transparent btn-sm btn-hint p-l-xs p-r-xs m-l-10"
|
||||
transition:fly|local={{ duration: 150, x: 5 }}
|
||||
on:click={() => {
|
||||
clear(false);
|
||||
submit();
|
||||
}}
|
||||
>
|
||||
<span class="txt">Clear</span>
|
||||
</button>
|
||||
{/if}
|
||||
</form>
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
export let items = [];
|
||||
export let multiple = false;
|
||||
export let disabled = false;
|
||||
export let closable = true;
|
||||
export let selected = multiple ? [] : undefined;
|
||||
export let toggle = false; // toggle option on click
|
||||
export let toggle = multiple; // toggle option on click
|
||||
export let labelComponent = undefined; // custom component to use for each selected option label
|
||||
export let labelComponentProps = {}; // props to pass to the custom option component
|
||||
export let optionComponent = undefined; // custom component to use for each dropdown option item
|
||||
@@ -195,8 +196,9 @@
|
||||
</script>
|
||||
|
||||
<div bind:this={container} class="select {classes}" class:multiple class:disabled>
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<div bind:this={labelDiv} tabindex={disabled ? "-1" : "0"} class="selected-container" class:disabled>
|
||||
{#each CommonHelper.toArray(selected) as item}
|
||||
{#each CommonHelper.toArray(selected) as item, i}
|
||||
<div class="option">
|
||||
{#if labelComponent}
|
||||
<svelte:component this={labelComponent} {item} {...labelComponentProps} />
|
||||
@@ -205,6 +207,7 @@
|
||||
{/if}
|
||||
|
||||
{#if multiple || toggle}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<span
|
||||
class="clear"
|
||||
use:tooltip={"Clear"}
|
||||
@@ -247,7 +250,7 @@
|
||||
<div class="addon suffix p-r-5">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-circle btn-secondary clear"
|
||||
class="btn btn-sm btn-circle btn-transparent clear"
|
||||
on:click|preventDefault|stopPropagation={resetSearch}
|
||||
>
|
||||
<i class="ri-close-line" />
|
||||
@@ -262,9 +265,11 @@
|
||||
|
||||
<div class="options-list">
|
||||
{#each filteredItems as item}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
||||
<div
|
||||
tabindex="0"
|
||||
class="dropdown-item option closable"
|
||||
class="dropdown-item option"
|
||||
class:closable
|
||||
class:selected={isSelected(item)}
|
||||
on:click={(e) => handleOptionSelect(e, item)}
|
||||
on:keydown={(e) => handleOptionKeypress(e, item)}
|
||||
|
||||
Reference in New Issue
Block a user