mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-22 08:02:19 +00:00
feat(frontend): Add copy button option to app text display component (#1090)
* feat(frontend): Add copy button to app text * feat(frontend): Add tooltip to component configs * fix(frontend): Remove copy button text
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { Clipboard } from 'lucide-svelte'
|
||||
import { copyToClipboard } from '../../../../utils'
|
||||
import Button from '../../../common/button/Button.svelte'
|
||||
import Popover from '../../../Popover.svelte'
|
||||
import type { AppInput } from '../../inputType'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
@@ -14,8 +18,8 @@
|
||||
|
||||
let extraStyle: string | undefined = undefined
|
||||
let result: string | undefined = undefined
|
||||
|
||||
let style: 'Title' | 'Subtitle' | 'Body' | 'Caption' | 'Label' | undefined = undefined
|
||||
let copyButton: boolean
|
||||
|
||||
function getComponent() {
|
||||
switch (style) {
|
||||
@@ -53,6 +57,7 @@
|
||||
|
||||
<InputValue {id} input={configuration.extraStyle} bind:value={extraStyle} />
|
||||
<InputValue {id} input={configuration.style} bind:value={style} />
|
||||
<InputValue {id} input={configuration.copyButton} bind:value={copyButton} />
|
||||
|
||||
<RunnableWrapper flexWrap bind:componentInput {id} bind:result>
|
||||
<AlignWrapper {horizontalAlignment} {verticalAlignment}>
|
||||
@@ -60,13 +65,30 @@
|
||||
<div class="text-gray-400 bg-gray-100 flex justify-center items-center h-full w-full">
|
||||
No text
|
||||
</div>
|
||||
{:else}<svelte:element
|
||||
this={component}
|
||||
class="whitespace-pre-wrap {classes}"
|
||||
style={extraStyle}
|
||||
>
|
||||
{String(result)}
|
||||
</svelte:element>
|
||||
{:else}
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<svelte:element
|
||||
this={component}
|
||||
class="whitespace-pre-wrap {classes}"
|
||||
style={extraStyle}
|
||||
>
|
||||
{String(result)}
|
||||
</svelte:element>
|
||||
{#if copyButton && result}
|
||||
<Popover notClickable>
|
||||
<Button
|
||||
size="xs"
|
||||
btnClasses="!px-2"
|
||||
on:click={() => copyToClipboard(result)}
|
||||
>
|
||||
<Clipboard size={14} strokeWidth={2} />
|
||||
</Button>
|
||||
<svelte:fragment slot="text">
|
||||
Copy to clipboard
|
||||
</svelte:fragment>
|
||||
</Popover>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</AlignWrapper>
|
||||
</RunnableWrapper>
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
|
||||
export function getValue(input: AppInput) {
|
||||
if (input.type === 'template' && isCodeInjection(input.eval)) {
|
||||
console.log(computeGlobalContext())
|
||||
try {
|
||||
return eval_like('`' + input.eval + '`', computeGlobalContext())
|
||||
} catch (e) {
|
||||
|
||||
@@ -255,14 +255,18 @@ const display: ComponentSet = {
|
||||
optionValuesKey: 'textStyleOptions',
|
||||
value: 'Body'
|
||||
},
|
||||
extraStyle:
|
||||
{
|
||||
extraStyle: {
|
||||
type: 'static',
|
||||
fieldType: 'text',
|
||||
value: '',
|
||||
|
||||
tooltip: 'CSS rules like "color: blue;"',
|
||||
},
|
||||
copyButton: {
|
||||
type: 'static',
|
||||
value: false,
|
||||
fieldType: 'boolean',
|
||||
onlyStatic: true,
|
||||
},
|
||||
|
||||
},
|
||||
card: false
|
||||
},
|
||||
|
||||
@@ -151,7 +151,7 @@ declare const ${k} = ${JSON.stringify(v)};
|
||||
|
||||
<InputsSpecsEditor
|
||||
shouldCapitalize={false}
|
||||
bind:inputSpecs={component.componentInput.fields}
|
||||
bind:inputSpecs={component.configuration}
|
||||
userInputEnabled={component.type !== 'buttoncomponent'}
|
||||
{rowColumns}
|
||||
/>
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { Badge, ToggleButton, ToggleButtonGroup } from '$lib/components/common'
|
||||
import { capitalize } from '$lib/utils'
|
||||
import { addWhitespaceBeforeCapitals, capitalize } from '$lib/utils'
|
||||
import { faArrowRight, faPen, faTableCells, faUser } from '@fortawesome/free-solid-svg-icons'
|
||||
import { fieldTypeToTsType } from '../../utils'
|
||||
import InputsSpecEditor from './InputsSpecEditor.svelte'
|
||||
import type {
|
||||
ConnectedAppInput,
|
||||
RowAppInput,
|
||||
StaticAppInput,
|
||||
UserAppInput
|
||||
} from '../../inputType'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import type { AppEditorContext, BaseAppComponent } from '../../types'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import Popup from '../../../common/popup/Popup.svelte'
|
||||
import Popover from '../../../Popover.svelte'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
|
||||
export let inputSpecs: Record<
|
||||
string,
|
||||
(StaticAppInput | ConnectedAppInput | UserAppInput | RowAppInput) & { onlyStatic?: boolean }
|
||||
>
|
||||
export let inputSpecs: BaseAppComponent['configuration']
|
||||
export let userInputEnabled: boolean = true
|
||||
export let staticOnly: boolean = false
|
||||
export let shouldCapitalize: boolean = true
|
||||
@@ -35,7 +25,12 @@
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex justify-between items-end gap-1">
|
||||
<span class="text-sm font-semibold truncate">
|
||||
{shouldCapitalize ? capitalize(inputSpecKey) : inputSpecKey}
|
||||
{shouldCapitalize ? capitalize(addWhitespaceBeforeCapitals(inputSpecKey)) : inputSpecKey}
|
||||
{#if input.tooltip}
|
||||
<Tooltip>
|
||||
{input.tooltip}
|
||||
</Tooltip>
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
<div class="flex gap-x-2 gap-y-1 flex-wrap justify-end items-center">
|
||||
|
||||
@@ -57,7 +57,10 @@ export type Aligned = {
|
||||
export interface BaseAppComponent extends Partial<Aligned> {
|
||||
id: ComponentID
|
||||
componentInput: AppInput | undefined
|
||||
configuration: Record<string, (StaticAppInput | ConnectedAppInput | UserAppInput) & { onlyStatic?: boolean }>
|
||||
configuration: Record<string, (StaticAppInput | ConnectedAppInput | UserAppInput) & {
|
||||
onlyStatic?: boolean,
|
||||
tooltip?: string
|
||||
}>
|
||||
card: boolean | undefined
|
||||
/**
|
||||
* If `true` then the wrapper will allow items to flow outside of it's borders.
|
||||
|
||||
@@ -620,7 +620,9 @@ export function scriptLangToEditorLang(
|
||||
}
|
||||
}
|
||||
|
||||
export async function copyToClipboard(value: string, sendToast = true): Promise<boolean> {
|
||||
export async function copyToClipboard(value?: string, sendToast = true): Promise<boolean> {
|
||||
if(!value) { return false }
|
||||
|
||||
let success = false
|
||||
if (navigator?.clipboard) {
|
||||
success = await navigator.clipboard
|
||||
@@ -647,6 +649,11 @@ export function capitalize(word: string): string {
|
||||
return word ? word.charAt(0).toUpperCase() + word.slice(1) : ''
|
||||
}
|
||||
|
||||
export function addWhitespaceBeforeCapitals(word?: string): string {
|
||||
if (!word) { return '' }
|
||||
return word.replace(/([A-Z])/g, ' $1').trim()
|
||||
}
|
||||
|
||||
export function isCloudHosted(): boolean {
|
||||
return get(page).url.hostname == 'app.windmill.dev'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user