replace popup with popover for app components

This commit is contained in:
Guilhem
2025-02-17 14:25:09 +00:00
parent 7fd59292eb
commit 6b8ee38caa
8 changed files with 554 additions and 525 deletions

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { createEventDispatcher, getContext } from 'svelte'
import { Popup } from '../common'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import Label from '../Label.svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
import Button from '../common/button/Button.svelte'
@@ -33,36 +33,39 @@
}
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeOnOtherPopoverOpen
closeButton
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
{#if value}
<div class="flex flex-col w-96 p-2 gap-4">
<Label label="Name">
<input type="text" bind:value={value.name} />
</Label>
<svelte:fragment slot="content">
{#if value}
<div class="flex flex-col w-96 gap-4 p-4">
<Label label="Name">
<input type="text" bind:value={value.name} />
</Label>
<OneOfInputSpecsEditor
key={'Data'}
bind:oneOf={value.value}
id={$selectedComponent?.[0] ?? ''}
shouldCapitalize={true}
resourceOnly={false}
inputSpecsConfiguration={value.value?.['configuration']}
labels={value.value?.['labels']}
tooltip={value.value?.['tooltip']}
disabledOptions={isEE ? [] : ['range-bar', 'range-area']}
/>
<OneOfInputSpecsEditor
key={'Data'}
bind:oneOf={value.value}
id={$selectedComponent?.[0] ?? ''}
shouldCapitalize={true}
resourceOnly={false}
inputSpecsConfiguration={value.value?.['configuration']}
labels={value.value?.['labels']}
tooltip={value.value?.['tooltip']}
disabledOptions={isEE ? [] : ['range-bar', 'range-area']}
/>
<Button color="red" size="xs" on:click={removeDataset}>Remove dataset</Button>
</div>
{/if}
</Popup>
<Button color="red" size="xs" on:click={removeDataset}>Remove dataset</Button>
</div>
{/if}
</svelte:fragment>
</Popover>

View File

@@ -1,10 +1,11 @@
<script lang="ts">
import { Alert, Popup } from '../common'
import { Alert } from '../common'
import Toggle from '$lib/components/Toggle.svelte'
import SimpleEditor from '../SimpleEditor.svelte'
import Label from '../Label.svelte'
import Tooltip from '../Tooltip.svelte'
import Button from '../common/button/Button.svelte'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
type Column = {
@@ -88,162 +89,166 @@
}
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeOnOtherPopoverOpen
closeButton
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
{#if value}
<div class="flex flex-col w-96 p-2 gap-4">
<span class="text-sm mb-2 leading-6 font-semibold">
Column definitions
<Tooltip
documentationLink="https://www.ag-grid.com/javascript-data-grid/column-definitions/"
>
Column definitions are used to define columns in ag-Grid.
</Tooltip>
</span>
<Label label="Header name">
<input type="text" placeholder="Header name" bind:value={value.headerName} />
</Label>
<Label label="Editable value">
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Editable' }}
bind:checked={value.editable}
size="xs"
/>
</Label>
<Label label="Min width (px)">
<input type="number" placeholder="width" bind:value={value.minWidth} />
</Label>
<Label label="Flex">
<svelte:fragment slot="header">
<svelte:fragment slot="content">
{#if value}
<div class="flex flex-col w-96 p-4 gap-4">
<span class="text-sm mb-2 leading-6 font-semibold">
Column definitions
<Tooltip
documentationLink="https://www.ag-grid.com/javascript-data-grid/column-sizing/#column-flex"
documentationLink="https://www.ag-grid.com/javascript-data-grid/column-definitions/"
>
It's often required that one or more columns fill the entire available space in the
grid. For this scenario, it is possible to use the flex config. Some columns could be
set with a regular width config, while other columns would have a flex config. Flex
sizing works by dividing the remaining space in the grid among all flex columns in
proportion to their flex value. For example, suppose the grid has a total width of 450px
and it has three columns: the first with width: 150; the second with flex: 1; and third
with flex: 2. The first column will be 150px wide, leaving 300px remaining. The column
with flex: 2 has twice the size with flex: 1. So final sizes will be: 150px, 100px,
200px.
Column definitions are used to define columns in ag-Grid.
</Tooltip>
</svelte:fragment>
</span>
<input type="range" step="1" bind:value={value.flex} min={1} max={12} />
<div class="text-xs">{value.flex}</div>
</Label>
<Label label="Header name">
<input type="text" placeholder="Header name" bind:value={value.headerName} />
</Label>
<Label label="Hide">
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Hide' }}
bind:checked={value.hide}
size="xs"
/>
</Label>
<Label label="Value formatter">
<svelte:fragment slot="header">
<Tooltip
documentationLink="https://www.ag-grid.com/javascript-data-grid/value-formatters/"
>
Value formatters allow you to format values for display. This is useful when data is one
type (e.g. numeric) but needs to be converted for human reading (e.g. putting in
currency symbols and number formatting).
</Tooltip>
</svelte:fragment>
<svelte:fragment slot="action">
<Button
size="xs"
color="light"
variant="border"
on:click={() => {
// @ts-ignore
value.valueFormatter = null
renderCount++
<Label label="Editable value">
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
>
Clear
</Button>
</svelte:fragment>
</Label>
<div>
{#key renderCount}
<div class="flex flex-col gap-4">
<div class="relative">
{#if !presets.find((preset) => preset.value === value?.valueFormatter)}
<div class="z-50 absolute bg-opacity-50 bg-surface top-0 left-0 bottom-0 right-0" />
{/if}
<div class="text-xs font-semibold">Presets</div>
<select
bind:value={value.valueFormatter}
on:change={() => {
renderCount++
}}
placeholder="Code"
>
{#each presets as preset}
<option value={preset.value}>{preset.label}</option>
{/each}
</select>
options={{ right: 'Editable' }}
bind:checked={value.editable}
size="xs"
/>
</Label>
<Label label="Min width (px)">
<input type="number" placeholder="width" bind:value={value.minWidth} />
</Label>
<Label label="Flex">
<svelte:fragment slot="header">
<Tooltip
documentationLink="https://www.ag-grid.com/javascript-data-grid/column-sizing/#column-flex"
>
It's often required that one or more columns fill the entire available space in the
grid. For this scenario, it is possible to use the flex config. Some columns could be
set with a regular width config, while other columns would have a flex config. Flex
sizing works by dividing the remaining space in the grid among all flex columns in
proportion to their flex value. For example, suppose the grid has a total width of
450px and it has three columns: the first with width: 150; the second with flex: 1;
and third with flex: 2. The first column will be 150px wide, leaving 300px remaining.
The column with flex: 2 has twice the size with flex: 1. So final sizes will be:
150px, 100px, 200px.
</Tooltip>
</svelte:fragment>
<input type="range" step="1" bind:value={value.flex} min={1} max={12} />
<div class="text-xs">{value.flex}</div>
</Label>
<Label label="Hide">
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Hide' }}
bind:checked={value.hide}
size="xs"
/>
</Label>
<Label label="Value formatter">
<svelte:fragment slot="header">
<Tooltip
documentationLink="https://www.ag-grid.com/javascript-data-grid/value-formatters/"
>
Value formatters allow you to format values for display. This is useful when data is
one type (e.g. numeric) but needs to be converted for human reading (e.g. putting in
currency symbols and number formatting).
</Tooltip>
</svelte:fragment>
<svelte:fragment slot="action">
<Button
size="xs"
color="light"
variant="border"
on:click={() => {
// @ts-ignore
value.valueFormatter = null
renderCount++
}}
>
Clear
</Button>
</svelte:fragment>
</Label>
<div>
{#key renderCount}
<div class="flex flex-col gap-4">
<div class="relative">
{#if !presets.find((preset) => preset.value === value?.valueFormatter)}
<div
class="z-50 absolute bg-opacity-50 bg-surface top-0 left-0 bottom-0 right-0"
/>
{/if}
<div class="text-xs font-semibold">Presets</div>
<select
bind:value={value.valueFormatter}
on:change={() => {
renderCount++
}}
placeholder="Code"
>
{#each presets as preset}
<option value={preset.value}>{preset.label}</option>
{/each}
</select>
</div>
<SimpleEditor
extraLib={'declare const value: any'}
autoHeight
lang="javascript"
bind:code={value.valueFormatter}
/>
<div class="text-xs text-secondary -mt-4">Use `value` in the formatter</div>
</div>
{/key}
</div>
<SimpleEditor
extraLib={'declare const value: any'}
autoHeight
lang="javascript"
bind:code={value.valueFormatter}
/>
<div class="text-xs text-secondary -mt-4">Use `value` in the formatter</div>
</div>
{/key}
</div>
<Label label="Sort">
<select bind:value={value.sort}>
<option value={null}>None</option>
<option value="asc">Ascending</option>
<option value="desc">Descending</option>
</select>
</Label>
<Label label="Sort">
<select bind:value={value.sort}>
<option value={null}>None</option>
<option value="asc">Ascending</option>
<option value="desc">Descending</option>
</select>
</Label>
<Label label="Filter">
<svelte:fragment slot="header">
<Tooltip documentationLink="https://www.ag-grid.com/javascript-data-grid/filtering/">
Filtering allows you to limit the rows displayed in your grid to those that match
criteria you specify.
</Tooltip>
</svelte:fragment>
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Enable filter' }}
bind:checked={value.filter}
size="xs"
/>
</Label>
<Label label="Filter">
<svelte:fragment slot="header">
<Tooltip documentationLink="https://www.ag-grid.com/javascript-data-grid/filtering/">
Filtering allows you to limit the rows displayed in your grid to those that match
criteria you specify.
</Tooltip>
</svelte:fragment>
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Enable filter' }}
bind:checked={value.filter}
size="xs"
/>
</Label>
<!--
<!--
EE only
<Label label="Aggregation function">
@@ -275,27 +280,28 @@
</Label>
-->
<Label label="Type">
<select bind:value={value.cellRendererType}>
<option value="text">Text</option>
<option value="link">Link</option>
</select>
</Label>
<Label label="Type">
<select bind:value={value.cellRendererType}>
<option value="text">Text</option>
<option value="link">Link</option>
</select>
</Label>
{#if value.cellRendererType === 'link'}
<Alert type="info" title="Label" size="xs">
They are two ways to define a link:
<ul class="list-disc list-inside">
<li>
<strong>String</strong>: The string will be used as the link and the label.
</li>
<li>
<strong>Object</strong>: The object must have a <code>href</code> and a
<code>label</code> property.
</li>
</ul>
</Alert>
{/if}
</div>
{/if}
</Popup>
{#if value.cellRendererType === 'link'}
<Alert type="info" title="Label" size="xs">
They are two ways to define a link:
<ul class="list-disc list-inside">
<li>
<strong>String</strong>: The string will be used as the link and the label.
</li>
<li>
<strong>Object</strong>: The object must have a <code>href</code> and a
<code>label</code> property.
</li>
</ul>
</Alert>
{/if}
</div>
{/if}
</svelte:fragment>
</Popover>

View File

@@ -1,12 +1,11 @@
<script lang="ts">
import { createEventDispatcher, getContext } from 'svelte'
import { Popup } from '../common'
import Label from '../Label.svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
import Button from '../common/button/Button.svelte'
import InputsSpecEditor from '../apps/editor/settingsPanel/InputsSpecEditor.svelte'
import type { AppViewerContext, RichConfiguration } from '../apps/types'
import Popover from '$lib/components/meltComponents/Popover.svelte'
const { selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
type Dataset = {
@@ -23,42 +22,45 @@
}
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeOnOtherPopoverOpen
closeButton
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
{#if value}
<div class="flex flex-col w-96 p-2 gap-4">
<Label label="Name">
<input type="text" bind:value={value.name} />
</Label>
<svelte:fragment slot="content">
{#if value}
<div class="flex flex-col w-96 p-4 gap-4">
<Label label="Name">
<input type="text" bind:value={value.name} />
</Label>
<InputsSpecEditor
key={'Data'}
bind:componentInput={value.value}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.value?.['fieldType']}
subFieldType={value.value?.['subFieldType']}
format={value.value?.['format']}
selectOptions={value.value?.['selectOptions']}
tooltip={value.value?.['tooltip']}
fileUpload={value.value?.['fileUpload']}
placeholder={value.value?.['placeholder']}
customTitle={value.value?.['customTitle']}
displayType={false}
/>
<InputsSpecEditor
key={'Data'}
bind:componentInput={value.value}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.value?.['fieldType']}
subFieldType={value.value?.['subFieldType']}
format={value.value?.['format']}
selectOptions={value.value?.['selectOptions']}
tooltip={value.value?.['tooltip']}
fileUpload={value.value?.['fileUpload']}
placeholder={value.value?.['placeholder']}
customTitle={value.value?.['customTitle']}
displayType={false}
/>
<Button color="red" size="xs" on:click={removeDataset}>Remove dataset</Button>
</div>
{/if}
</Popup>
<Button color="red" size="xs" on:click={removeDataset}>Remove dataset</Button>
</div>
{/if}
</svelte:fragment>
</Popover>

View File

@@ -1,5 +1,6 @@
<script lang="ts">
import { Badge, Popup, type AlertType } from '../common'
import { Badge, type AlertType } from '../common'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import SimpleEditor from '../SimpleEditor.svelte'
import Label from '../Label.svelte'
@@ -119,19 +120,22 @@
$: warning = computeWarning(value, value)
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-start',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4 max-h-[512px] overflow-y-auto"
contentClasses="max-h-[50vh] overflow-y-auto p-4 flex flex-col gap-4 w-96"
closeButton
closeOnOtherPopoverOpen
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
{#if value}
<div class="flex flex-col w-96 p-2 gap-4">
<svelte:fragment slot="content">
{#if value}
<Section label="Column settings">
<svelte:fragment slot="header">
<Badge color="blue">
@@ -253,7 +257,7 @@
</Label>
</Section>
<Section label="AG Grid configuration">
<Section label="AG Grid configurations">
<div
class={twMerge('flex flex-col gap-4', value.ignored ? 'opacity-50 cursor-none ' : '')}
on:pointerdown={(e) => {
@@ -381,6 +385,6 @@
</Label>
</div>
</Section>
</div>
{/if}
</Popup>
{/if}
</svelte:fragment>
</Popover>

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { Popup } from '../common'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
import type { NavbarItem } from '../apps/editor/component'
import Label from '../Label.svelte'
@@ -16,121 +16,124 @@
const { selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeButton
closeOnOtherPopoverOpen
contentClasses="p-4"
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
{#if value}
<Section label="Navbar item" class="flex flex-col gap-2 w-80 overflow-y-auto max-h-screen">
<InputsSpecEditor
key={'Label'}
bind:componentInput={value.label}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.label?.['fieldType']}
subFieldType={value.label?.['subFieldType']}
format={value.label?.['format']}
selectOptions={value.label?.['selectOptions']}
fileUpload={value.label?.['fileUpload']}
placeholder={value.label?.['placeholder']}
customTitle={value.label?.['customTitle']}
displayType={false}
/>
<OneOfInputSpecsEditor
key={'Link'}
bind:oneOf={value.path}
id={$selectedComponent?.[0] ?? ''}
shouldCapitalize={true}
resourceOnly={false}
inputSpecsConfiguration={value.path?.['configuration']}
labels={value.path?.['labels']}
tooltip={value.path?.['tooltip']}
/>
<Alert size="xs" title="Link Behavior" collapsible>
<ul class="list-disc">
<li>
If you select an app, there are two cases:
<div class="ml-2">
<ul class="list-disc">
<li>
You selected the current app itself: Clicking on the link will highlight the item,
and set the app in the output. Note that adding query params or an hash lets you
distinguish between different items. Also note that query params can be retrieved
from the context: `ctx.query`.
</li>
<li>
You selected another app: Clicking on the link navigates to the selected app
without reloading the page. In the editor, it will open in a new tab.
</li>
</ul>
</div>
</li>
<li>
If you select an external link, clicking on the link will navigate to the selected link
in a new tab.
</li>
</ul>
</Alert>
<InputsSpecEditor
key={'Disabled'}
bind:componentInput={value.disabled}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.disabled?.['fieldType']}
subFieldType={value.disabled?.['subFieldType']}
format={value.disabled?.['format']}
selectOptions={value.disabled?.['selectOptions']}
fileUpload={value.disabled?.['fileUpload']}
placeholder={value.disabled?.['placeholder']}
customTitle={value.disabled?.['customTitle']}
displayType={false}
/>
<InputsSpecEditor
key={'Hidden'}
bind:componentInput={value.hidden}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.hidden?.['fieldType']}
subFieldType={value.hidden?.['subFieldType']}
format={value.hidden?.['format']}
selectOptions={value.hidden?.['selectOptions']}
fileUpload={value.hidden?.['fileUpload']}
placeholder={value.hidden?.['placeholder']}
customTitle={value.hidden?.['customTitle']}
displayType={false}
/>
<Label label="Icon" class="w-full">
<IconSelectInput
bind:value={value.icon}
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
shouldUsePortal={false}
<svelte:fragment slot="content">
{#if value}
<Section label="Navbar item" class="flex flex-col gap-2 w-80 overflow-y-auto max-h-screen">
<InputsSpecEditor
key={'Label'}
bind:componentInput={value.label}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.label?.['fieldType']}
subFieldType={value.label?.['subFieldType']}
format={value.label?.['format']}
selectOptions={value.label?.['selectOptions']}
fileUpload={value.label?.['fileUpload']}
placeholder={value.label?.['placeholder']}
customTitle={value.label?.['customTitle']}
displayType={false}
/>
</Label>
<Label label="Caption">
<input type="text" bind:value={value.caption} />
</Label>
</Section>
{/if}
</Popup>
<OneOfInputSpecsEditor
key={'Link'}
bind:oneOf={value.path}
id={$selectedComponent?.[0] ?? ''}
shouldCapitalize={true}
resourceOnly={false}
inputSpecsConfiguration={value.path?.['configuration']}
labels={value.path?.['labels']}
tooltip={value.path?.['tooltip']}
/>
<Alert size="xs" title="Link Behavior" collapsible>
<ul class="list-disc">
<li>
If you select an app, there are two cases:
<div class="ml-2">
<ul class="list-disc">
<li>
You selected the current app itself: Clicking on the link will highlight the
item, and set the app in the output. Note that adding query params or an hash
lets you distinguish between different items. Also note that query params can be
retrieved from the context: `ctx.query`.
</li>
<li>
You selected another app: Clicking on the link navigates to the selected app
without reloading the page. In the editor, it will open in a new tab.
</li>
</ul>
</div>
</li>
<li>
If you select an external link, clicking on the link will navigate to the selected
link in a new tab.
</li>
</ul>
</Alert>
<InputsSpecEditor
key={'Disabled'}
bind:componentInput={value.disabled}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.disabled?.['fieldType']}
subFieldType={value.disabled?.['subFieldType']}
format={value.disabled?.['format']}
selectOptions={value.disabled?.['selectOptions']}
fileUpload={value.disabled?.['fileUpload']}
placeholder={value.disabled?.['placeholder']}
customTitle={value.disabled?.['customTitle']}
displayType={false}
/>
<InputsSpecEditor
key={'Hidden'}
bind:componentInput={value.hidden}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.hidden?.['fieldType']}
subFieldType={value.hidden?.['subFieldType']}
format={value.hidden?.['format']}
selectOptions={value.hidden?.['selectOptions']}
fileUpload={value.hidden?.['fileUpload']}
placeholder={value.hidden?.['placeholder']}
customTitle={value.hidden?.['customTitle']}
displayType={false}
/>
<Label label="Icon" class="w-full">
<IconSelectInput
bind:value={value.icon}
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
shouldUsePortal={false}
/>
</Label>
<Label label="Caption">
<input type="text" bind:value={value.caption} />
</Label>
</Section>
{/if}
</svelte:fragment>
</Popover>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { createEventDispatcher, getContext } from 'svelte'
import { Popup } from '../common'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import Label from '../Label.svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
import ColorInput from '../apps/editor/settingsPanel/inputEditor/ColorInput.svelte'
@@ -30,93 +30,96 @@
}
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeButton
closeOnOtherPopoverOpen
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
{#if value}
<div class="flex flex-col w-96 p-2 gap-4">
<Label label="Name">
<input type="text" bind:value={value.name} />
</Label>
<svelte:fragment slot="content">
{#if value}
<div class="flex flex-col w-96 p-4 gap-4">
<Label label="Name">
<input type="text" bind:value={value.name} />
</Label>
<Label label="Type">
<select bind:value={value.type}>
<option value="bar">Bar</option>
<option
value="scatter"
on:click={() => {
if (value && value?.extraOptions === undefined) {
value.extraOptions = { mode: 'markers' }
}
}}
>
Scatter
</option>
</select>
</Label>
{#if value.type === 'scatter' && value.extraOptions}
<Label label="Mode">
<select bind:value={value.extraOptions.mode}>
<option value="markers">Markers</option>
<option value="lines">Lines</option>
<option value="lines+markers">Lines + Markers</option>
<Label label="Type">
<select bind:value={value.type}>
<option value="bar">Bar</option>
<option
value="scatter"
on:click={() => {
if (value && value?.extraOptions === undefined) {
value.extraOptions = { mode: 'markers' }
}
}}
>
Scatter
</option>
</select>
</Label>
{/if}
<Label label="Aggregation method">
<svelte:fragment slot="header">
<Tooltip>
A method to aggregate the data. For example, if you have multiple x data points with the
same value, you can choose to sum them up or take the mean. If you don't have multiple x
data points with the same value, this option will have no effect.
</Tooltip>
</svelte:fragment>
<select bind:value={value.aggregation_method}>
<option value="sum">Sum</option>
<option value="mean">Mean</option>
<option value="median">Median</option>
<option value="min">Min</option>
<option value="max">Max</option>
</select>
</Label>
{#if value.type === 'scatter' && value.extraOptions}
<Label label="Mode">
<select bind:value={value.extraOptions.mode}>
<option value="markers">Markers</option>
<option value="lines">Lines</option>
<option value="lines+markers">Lines + Markers</option>
</select>
</Label>
{/if}
<Label label="Tooltip">
<input type="text" bind:value={value.tooltip} />
</Label>
<Label label="Aggregation method">
<svelte:fragment slot="header">
<Tooltip>
A method to aggregate the data. For example, if you have multiple x data points with
the same value, you can choose to sum them up or take the mean. If you don't have
multiple x data points with the same value, this option will have no effect.
</Tooltip>
</svelte:fragment>
<select bind:value={value.aggregation_method}>
<option value="sum">Sum</option>
<option value="mean">Mean</option>
<option value="median">Median</option>
<option value="min">Min</option>
<option value="max">Max</option>
</select>
</Label>
<Label label="Color">
<ColorInput bind:value={value.color} />
</Label>
<Label label="Tooltip">
<input type="text" bind:value={value.tooltip} />
</Label>
<InputsSpecEditor
key={'Data'}
bind:componentInput={value.value}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.value?.['fieldType']}
subFieldType={value.value?.['subFieldType']}
format={value.value?.['format']}
selectOptions={value.value?.['selectOptions']}
tooltip={value.value?.['tooltip']}
fileUpload={value.value?.['fileUpload']}
placeholder={value.value?.['placeholder']}
customTitle={value.value?.['customTitle']}
displayType={false}
/>
<Label label="Color">
<ColorInput bind:value={value.color} />
</Label>
<Button color="red" size="xs" on:click={removeDataset}>Remove dataset</Button>
</div>
{/if}
</Popup>
<InputsSpecEditor
key={'Data'}
bind:componentInput={value.value}
id={$selectedComponent?.[0] ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={value.value?.['fieldType']}
subFieldType={value.value?.['subFieldType']}
format={value.value?.['format']}
selectOptions={value.value?.['selectOptions']}
tooltip={value.value?.['tooltip']}
fileUpload={value.value?.['fileUpload']}
placeholder={value.value?.['placeholder']}
customTitle={value.value?.['customTitle']}
displayType={false}
/>
<Button color="red" size="xs" on:click={removeDataset}>Remove dataset</Button>
</div>
{/if}
</svelte:fragment>
</Popover>

View File

@@ -3,7 +3,8 @@
import PanelSection from '../apps/editor/settingsPanel/common/PanelSection.svelte'
import InputsSpecEditor from '../apps/editor/settingsPanel/InputsSpecEditor.svelte'
import type { BaseAppComponent, RichConfiguration } from '../apps/types'
import { Button, Popup } from '../common'
import { Button } from '../common'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import { offset, flip, shift } from 'svelte-floating-ui/dom'
import type {
@@ -18,77 +19,79 @@
| undefined
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeButton
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
<div class="w-96">
<PanelSection
title={`Manage actions programmatically`}
tooltip="
<svelte:fragment slot="content">
<div class="w-96">
<PanelSection
title={`Manage actions programmatically`}
tooltip="
You can manage the order of the actions programmatically: You need to return an array of action ids in the order you want them to appear in the table. You can also hide actions by not including them in the array."
>
<div class="w-full flex gap-2 flex-col mt-2">
{#if actionsOrder}
<InputsSpecEditor
key={'Order'}
bind:componentInput={actionsOrder}
id={selectedId ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={actionsOrder?.['fieldType']}
subFieldType={actionsOrder?.['subFieldType']}
format={actionsOrder?.['format']}
selectOptions={actionsOrder?.['selectOptions']}
tooltip={actionsOrder?.['tooltip']}
fileUpload={actionsOrder?.['fileUpload']}
placeholder={actionsOrder?.['placeholder']}
customTitle={actionsOrder?.['customTitle']}
allowTypeChange={false}
displayType={false}
/>
<Button
size="xs"
color="light"
startIcon={{
icon: Code
}}
variant="border"
on:click={() => {
actionsOrder = undefined
}}
>
Disable
</Button>
{:else}
<Button
size="xs"
color="light"
startIcon={{
icon: Code
}}
variant="border"
on:click={() => {
actionsOrder = {
fieldType: 'text',
type: 'evalv2',
expr: JSON.stringify(components?.map((x) => x.id) ?? []),
connections: []
}
}}
>
Enable
</Button>
{/if}
</div>
</PanelSection>
</div>
</Popup>
>
<div class="w-full flex gap-2 flex-col mt-2">
{#if actionsOrder}
<InputsSpecEditor
key={'Order'}
bind:componentInput={actionsOrder}
id={selectedId ?? ''}
userInputEnabled={false}
shouldCapitalize={true}
resourceOnly={false}
fieldType={actionsOrder?.['fieldType']}
subFieldType={actionsOrder?.['subFieldType']}
format={actionsOrder?.['format']}
selectOptions={actionsOrder?.['selectOptions']}
tooltip={actionsOrder?.['tooltip']}
fileUpload={actionsOrder?.['fileUpload']}
placeholder={actionsOrder?.['placeholder']}
customTitle={actionsOrder?.['customTitle']}
allowTypeChange={false}
displayType={false}
/>
<Button
size="xs"
color="light"
startIcon={{
icon: Code
}}
variant="border"
on:click={() => {
actionsOrder = undefined
}}
>
Disable
</Button>
{:else}
<Button
size="xs"
color="light"
startIcon={{
icon: Code
}}
variant="border"
on:click={() => {
actionsOrder = {
fieldType: 'text',
type: 'evalv2',
expr: JSON.stringify(components?.map((x) => x.id) ?? []),
connections: []
}
}}
>
Enable
</Button>
{/if}
</div>
</PanelSection>
</div>
</svelte:fragment>
</Popover>

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { Popup } from '../common'
import Popover from '$lib/components/meltComponents/Popover.svelte'
import Alert from '../common/alert/Alert.svelte'
import Label from '../Label.svelte'
import Toggle from '../Toggle.svelte'
@@ -12,61 +12,66 @@
}
</script>
<Popup
<Popover
floatingConfig={{
strategy: 'fixed',
placement: 'left-end',
middleware: [offset(8), flip(), shift()]
}}
containerClasses="border rounded-lg shadow-lg bg-surface p-4"
closeButton
closeOnOtherPopoverOpen
>
<svelte:fragment slot="button">
<svelte:fragment slot="trigger">
<slot name="trigger" />
</svelte:fragment>
<div class="flex flex-col w-96 p-2 gap-4">
<span class="text-sm mb-2 leading-6 font-semibold">
Table Column
<Tooltip documentationLink="https://www.ag-grid.com/javascript-data-grid/column-definitions/">
Column definitions are used to define columns in ag-Grid.
</Tooltip>
</span>
<svelte:fragment slot="content">
<div class="flex flex-col w-96 p-4 gap-4">
<span class="text-sm mb-2 leading-6 font-semibold">
Table Column
<Tooltip
documentationLink="https://www.ag-grid.com/javascript-data-grid/column-definitions/"
>
Column definitions are used to define columns in ag-Grid.
</Tooltip>
</span>
<Label label="Header name">
<input placeholder="header name" bind:value={column.headerName} />
</Label>
<Label label="Header name">
<input placeholder="header name" bind:value={column.headerName} />
</Label>
<Label label="Show column">
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Hide column' }}
bind:checked={column.hideColumn}
size="xs"
/>
</Label>
<Label label="Show column">
<Toggle
on:pointerdown={(e) => {
e?.stopPropagation()
}}
options={{ right: 'Hide column' }}
bind:checked={column.hideColumn}
size="xs"
/>
</Label>
<Label label="Type">
<select bind:value={column.type}>
<option value="text">Text</option>
<option value="badge">Badge</option>
<option value="link">Link</option>
</select>
</Label>
<Label label="Type">
<select bind:value={column.type}>
<option value="text">Text</option>
<option value="badge">Badge</option>
<option value="link">Link</option>
</select>
</Label>
{#if column.type === 'link'}
<Alert type="info" title="Label" size="xs">
They are two ways to define a link:
<ul class="list-disc list-inside">
<li>
<strong>String</strong>: The string will be used as the link and the label.
</li>
<li>
<strong>Object</strong>: The object must have a <code>href</code> and a
<code>label</code> property.
</li>
</ul>
</Alert>
{/if}
</div>
</Popup>
{#if column.type === 'link'}
<Alert type="info" title="Label" size="xs">
They are two ways to define a link:
<ul class="list-disc list-inside">
<li>
<strong>String</strong>: The string will be used as the link and the label.
</li>
<li>
<strong>Object</strong>: The object must have a <code>href</code> and a
<code>label</code> property.
</li>
</ul>
</Alert>
{/if}
</div>
</svelte:fragment>
</Popover>