mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 08:00:59 +00:00
fix(frontend): Cleanup dead code (#935)
This commit is contained in:
@@ -2,50 +2,28 @@
|
||||
import DisplayResult from '$lib/components/DisplayResult.svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, ComponentInputsSpec } from '../types'
|
||||
import InputValue from './helpers/InputValue.svelte'
|
||||
|
||||
export let componentInputs: ComponentInputsSpec
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
$: hasConnection =
|
||||
componentInputs.result.type === 'output' &&
|
||||
componentInputs.result.id &&
|
||||
componentInputs.result.name
|
||||
|
||||
$: inputResult = hasConnection
|
||||
? $worldStore?.connect<any>(componentInputs.result, () => {
|
||||
update()
|
||||
})
|
||||
: {
|
||||
peak: () => {
|
||||
if (componentInputs.result.type === 'static') {
|
||||
return componentInputs.result.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result: any
|
||||
|
||||
function update() {
|
||||
result = inputResult?.peak()
|
||||
}
|
||||
|
||||
$: !hasConnection && componentInputs.result && update()
|
||||
let resultValue: any = undefined
|
||||
|
||||
export const staticOutputs: string[] = []
|
||||
</script>
|
||||
|
||||
<InputValue input={componentInputs.result} bind:value={resultValue} />
|
||||
|
||||
{#if $worldStore}
|
||||
<div class="w-full border-b px-2 text-xs p-1 font-semibold bg-gray-500 text-white rounded-t-sm">
|
||||
Results
|
||||
</div>
|
||||
<div class="p-2">
|
||||
{#if !hasConnection && componentInputs.result.type !== 'static'}
|
||||
<span class="text-sm">Not connected</span>
|
||||
{:else if result === undefined && componentInputs.result.type === 'output'}
|
||||
{#if resultValue === undefined && componentInputs.result.type === 'output'}
|
||||
<span class="text-sm">Waiting for result</span>
|
||||
{:else}
|
||||
<DisplayResult {result} />
|
||||
<DisplayResult result={resultValue} />
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import type { Schema } from '$lib/common'
|
||||
import { Button } from '$lib/components/common'
|
||||
import SchemaForm from '$lib/components/SchemaForm.svelte'
|
||||
import TestJobLoader from '$lib/components/TestJobLoader.svelte'
|
||||
import { AppService, type CompletedJob } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { faArrowsRotate, faFile } from '@fortawesome/free-solid-svg-icons'
|
||||
import { getContext } from 'svelte'
|
||||
import Icon from 'svelte-awesome'
|
||||
import type { Output } from '../rx'
|
||||
import type { AppEditorContext, InputsSpec } from '../types'
|
||||
import { buildArgs, loadSchema, schemaToInputsSpec } from '../utils'
|
||||
|
||||
// Component props
|
||||
export let id: string
|
||||
export let inputs: InputsSpec
|
||||
export let path: string | undefined = undefined
|
||||
export let runType: 'script' | 'flow' | undefined = undefined
|
||||
export let inlineScriptName: string | undefined = undefined
|
||||
|
||||
export const staticOutputs = ['loading', 'result']
|
||||
|
||||
const { worldStore, app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
let pagePath = $page.params.path
|
||||
|
||||
$: outputs = $worldStore?.outputsById[id] as {
|
||||
result: Output<any>
|
||||
loading: Output<boolean>
|
||||
}
|
||||
|
||||
// Local state
|
||||
let args: Record<string, any> = {}
|
||||
let schema: Schema | undefined = undefined
|
||||
let schemaClone: Schema | undefined = undefined
|
||||
|
||||
let isValid = true
|
||||
let testIsLoading = false
|
||||
let testJob: CompletedJob | undefined = undefined
|
||||
let testJobLoader: TestJobLoader | undefined = undefined
|
||||
|
||||
$: if ($workspaceStore && path && runType) {
|
||||
loadSchemaFromTriggerable($workspaceStore, path, runType)
|
||||
}
|
||||
|
||||
$: if (inlineScriptName) {
|
||||
schema = $app.inlineScripts[inlineScriptName].schema
|
||||
reloadSchemaAndArgs()
|
||||
}
|
||||
|
||||
$: if (inputs && schema !== undefined) {
|
||||
if (Object.keys(schema.properties).length !== Object.keys(inputs).length) {
|
||||
inputs = schemaToInputsSpec(schema)
|
||||
}
|
||||
|
||||
reloadSchemaAndArgs()
|
||||
}
|
||||
|
||||
// Load once
|
||||
async function loadSchemaFromTriggerable(
|
||||
workspace: string,
|
||||
path: string,
|
||||
runType: 'script' | 'flow'
|
||||
) {
|
||||
schema = await loadSchema(workspace, path, runType)
|
||||
args = buildArgs(inputs, schema)
|
||||
}
|
||||
|
||||
async function reloadSchemaAndArgs() {
|
||||
schemaClone = JSON.parse(JSON.stringify(schema))
|
||||
|
||||
if (schemaClone !== undefined) {
|
||||
args = buildArgs(inputs, schemaClone)
|
||||
|
||||
Object.keys(schemaClone.properties).forEach((propKey) => {
|
||||
if (!Object.keys(args).includes(propKey)) {
|
||||
delete schemaClone!.properties[propKey]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$: disabledArgs = Object.keys(inputs).reduce((a: string[], c: string) => {
|
||||
if (inputs[c].type === 'static') {
|
||||
a = [...a, c]
|
||||
}
|
||||
return a
|
||||
}, [])
|
||||
|
||||
async function executeComponent() {
|
||||
await testJobLoader?.abstractRun(() => {
|
||||
const requestBody = {
|
||||
args,
|
||||
force_viewer_static_fields: {}
|
||||
}
|
||||
|
||||
if (inlineScriptName && $app.inlineScripts[inlineScriptName]) {
|
||||
requestBody['raw_code'] = {
|
||||
content: $app.inlineScripts[inlineScriptName].content,
|
||||
language: $app.inlineScripts[inlineScriptName].language,
|
||||
path: $app.inlineScripts[inlineScriptName].path
|
||||
}
|
||||
} else if (path && runType) {
|
||||
requestBody['path'] = `${runType}/${path}`
|
||||
}
|
||||
|
||||
return AppService.executeComponent({
|
||||
workspace: $workspaceStore!,
|
||||
path: pagePath,
|
||||
requestBody
|
||||
})
|
||||
})
|
||||
|
||||
outputs?.loading.set(true)
|
||||
}
|
||||
</script>
|
||||
|
||||
<TestJobLoader
|
||||
on:done={() => {
|
||||
if (testJob) {
|
||||
outputs?.result.set(testJob?.result)
|
||||
outputs?.loading.set(false)
|
||||
}
|
||||
}}
|
||||
bind:isLoading={testIsLoading}
|
||||
bind:job={testJob}
|
||||
bind:this={testJobLoader}
|
||||
/>
|
||||
|
||||
{#if schemaClone !== undefined}
|
||||
<SchemaForm schema={schemaClone} bind:args bind:isValid {disabledArgs} />
|
||||
<Button
|
||||
size="xs"
|
||||
color="dark"
|
||||
variant="border"
|
||||
on:click={() => executeComponent()}
|
||||
startIcon={{ icon: faFile }}
|
||||
disabled={!isValid}
|
||||
>
|
||||
<div>
|
||||
Submit
|
||||
{#if testIsLoading}
|
||||
<Icon data={faArrowsRotate} class="animate-spin ml-2" scale={0.8} />
|
||||
{/if}
|
||||
</div>
|
||||
</Button>
|
||||
{/if}
|
||||
@@ -4,7 +4,7 @@
|
||||
import { getContext } from 'svelte'
|
||||
import type { Output } from '../rx'
|
||||
import type { AppEditorContext, ComponentInputsSpec, InputsSpec } from '../types'
|
||||
import ComponentInputValue from './helpers/ComponentInputValue.svelte'
|
||||
import InputValue from './helpers/InputValue.svelte'
|
||||
import DebouncedInput from './helpers/DebouncedInput.svelte'
|
||||
import RunnableComponent from './helpers/RunnableComponent.svelte'
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
export const reservedKeys: string[] = Object.keys(extraQueryParams)
|
||||
</script>
|
||||
|
||||
<ComponentInputValue input={componentInputs.searchEnabled} bind:value={searchEnabledValue} />
|
||||
<ComponentInputValue input={componentInputs.paginationEnabled} bind:value={paginationEnabled} />
|
||||
<InputValue input={componentInputs.searchEnabled} bind:value={searchEnabledValue} />
|
||||
<InputValue input={componentInputs.paginationEnabled} bind:value={paginationEnabled} />
|
||||
|
||||
<RunnableComponent
|
||||
{id}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
<script lang="ts">
|
||||
import type { Schema } from '$lib/common'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import { Bar } from 'svelte-chartjs'
|
||||
|
||||
import {
|
||||
@@ -17,6 +13,19 @@
|
||||
BarElement
|
||||
} from 'chart.js'
|
||||
|
||||
import type { ChartData } from 'chart.js'
|
||||
|
||||
import type { InputsSpec } from '../../types'
|
||||
import RunnableComponent from '../helpers/RunnableComponent.svelte'
|
||||
|
||||
export let id: string
|
||||
export let inputs: InputsSpec
|
||||
export let path: string | undefined = undefined
|
||||
export let runType: 'script' | 'flow' | undefined = undefined
|
||||
export let inlineScriptName: string | undefined = undefined
|
||||
|
||||
export const staticOutputs: string[] = ['loading', 'result']
|
||||
|
||||
ChartJS.register(
|
||||
Title,
|
||||
Tooltip,
|
||||
@@ -28,28 +37,11 @@
|
||||
BarElement
|
||||
)
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
export const schema: Schema = emptySchema()
|
||||
export const staticOutputs: string[] = []
|
||||
|
||||
const data = {
|
||||
labels: ['Red', 'Blue', 'Yellow'],
|
||||
datasets: [
|
||||
{
|
||||
label: '% of Votes',
|
||||
data: [12, 19, 3],
|
||||
backgroundColor: [
|
||||
'rgba(255, 134,159,0.4)',
|
||||
'rgba(98, 182, 239,0.4)',
|
||||
'rgba(255, 218, 128,0.4)'
|
||||
],
|
||||
borderWidth: 2,
|
||||
borderColor: ['rgba(255, 134, 159, 1)', 'rgba(98, 182, 239, 1)', 'rgba(255, 218, 128, 1)']
|
||||
}
|
||||
]
|
||||
}
|
||||
let result: ChartData<'bar', number[], unknown> | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if $worldStore}
|
||||
<Bar {data} options={{ responsive: true }} />
|
||||
{/if}
|
||||
<RunnableComponent {id} {path} {runType} {inlineScriptName} bind:inputs bind:result>
|
||||
{#if result}
|
||||
<Bar data={result} options={{ responsive: true, animation: false }} />
|
||||
{/if}
|
||||
</RunnableComponent>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import type { ComponentInputsSpec, InputsSpec } from '../../types'
|
||||
import ComponentInputValue from '../helpers/ComponentInputValue.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
import RunnableComponent from '../helpers/RunnableComponent.svelte'
|
||||
|
||||
export let id: string
|
||||
@@ -18,7 +18,7 @@
|
||||
let runnableComponent: RunnableComponent
|
||||
</script>
|
||||
|
||||
<ComponentInputValue input={componentInputs.label} bind:value={labelValue} />
|
||||
<InputValue input={componentInputs.label} bind:value={labelValue} />
|
||||
|
||||
<RunnableComponent
|
||||
bind:this={runnableComponent}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import SvelteMarkdown from 'svelte-markdown'
|
||||
import type { ComponentInputsSpec } from '../../types'
|
||||
import AlignWrapper from '../helpers/AlignWrapper.svelte'
|
||||
import ComponentInputValue from '../helpers/ComponentInputValue.svelte'
|
||||
import InputValue from '../helpers/InputValue.svelte'
|
||||
|
||||
export let componentInputs: ComponentInputsSpec
|
||||
export let horizontalAlignement: 'left' | 'center' | 'right' | undefined = undefined
|
||||
@@ -13,7 +13,7 @@
|
||||
let contentValue: string = ''
|
||||
</script>
|
||||
|
||||
<ComponentInputValue input={componentInputs.content} bind:value={contentValue} />
|
||||
<InputValue input={componentInputs.content} bind:value={contentValue} />
|
||||
|
||||
<AlignWrapper {horizontalAlignement} {verticalAlignement}>
|
||||
<SvelteMarkdown source={contentValue} />
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import type { StaticInput, DynamicInput, AppEditorContext } from '../../types'
|
||||
|
||||
type T = $$Generic
|
||||
|
||||
export let input: DynamicInput | StaticInput
|
||||
export let value: T
|
||||
|
||||
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
$: input.type === 'static' && (value = input.value)
|
||||
$: input.type === 'output' && $worldStore?.connect<any>(input, onValueChange)
|
||||
|
||||
function onValueChange(newValue: T): void {
|
||||
value = newValue
|
||||
}
|
||||
</script>
|
||||
@@ -13,7 +13,7 @@
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppEditorContext, InputsSpec } from '../../types'
|
||||
import { loadSchema, schemaToInputsSpec } from '../../utils'
|
||||
import RunnableInputValue from './RunnableInputValue.svelte'
|
||||
import InputValue from './InputValue.svelte'
|
||||
|
||||
// Component props
|
||||
export let id: string
|
||||
@@ -179,7 +179,7 @@
|
||||
</script>
|
||||
|
||||
{#each Object.keys(inputs) as key}
|
||||
<RunnableInputValue input={inputs[key]} bind:value={runnableInputValues[key]} />
|
||||
<InputValue input={inputs[key]} bind:value={runnableInputValues[key]} />
|
||||
{/each}
|
||||
|
||||
<TestJobLoader
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { getContext } from 'svelte'
|
||||
import BarChartComponent from '../components/charts/BarChartComponent.svelte'
|
||||
import DisplayComponent from '../components/DisplayComponent.svelte'
|
||||
import RunFormComponent from '../components/RunFormComponent.svelte'
|
||||
import TableComponent from '../components/TableComponent.svelte'
|
||||
import TextComponent from '../components/common/TextComponent.svelte'
|
||||
import type { AppComponent, AppEditorContext } from '../types'
|
||||
@@ -36,16 +35,14 @@
|
||||
$mode === 'preview' ? 'border-white' : 'hover:border-blue-500'
|
||||
)}
|
||||
>
|
||||
{#if component.type === 'runformcomponent'}
|
||||
<RunFormComponent
|
||||
{#if component.type === 'displaycomponent'}
|
||||
<DisplayComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{:else if component.type === 'barchartcomponent'}
|
||||
<BarChartComponent
|
||||
{...component}
|
||||
bind:inputs={component.inputs}
|
||||
bind:staticOutputs={$staticOutputs[component.id]}
|
||||
/>
|
||||
{:else if component.type === 'displaycomponent'}
|
||||
<DisplayComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{:else if component.type === 'barchartcomponent'}
|
||||
<BarChartComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{:else if component.type === 'piechartcomponent'}
|
||||
<PieChartComponent
|
||||
{...component}
|
||||
@@ -59,17 +56,9 @@
|
||||
bind:inputs={component.inputs}
|
||||
/>
|
||||
{:else if component.type === 'textcomponent'}
|
||||
<TextComponent
|
||||
{...component}
|
||||
bind:staticOutputs={$staticOutputs[component.id]}
|
||||
bind:componentInputs={component.componentInputs}
|
||||
/>
|
||||
<TextComponent {...component} />
|
||||
{:else if component.type === 'buttoncomponent'}
|
||||
<ButtonComponent
|
||||
{...component}
|
||||
bind:staticOutputs={$staticOutputs[component.id]}
|
||||
bind:componentInputs={component.componentInputs}
|
||||
/>
|
||||
<ButtonComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
const defaultProps = {
|
||||
inputs: {},
|
||||
componentInputs: {},
|
||||
alignable: false,
|
||||
width: 0
|
||||
componentInputs: {}
|
||||
}
|
||||
|
||||
const defaultAlignement = {
|
||||
|
||||
@@ -16,11 +16,6 @@ const windmillComponents = {
|
||||
defaultValue: undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
...defaultProps,
|
||||
id: 'runformcomponent',
|
||||
type: 'runformcomponent'
|
||||
}
|
||||
] as AppComponent[]
|
||||
}
|
||||
@@ -55,31 +50,6 @@ const plainComponents = {
|
||||
}
|
||||
},
|
||||
runnable: true
|
||||
},
|
||||
{
|
||||
...defaultProps,
|
||||
id: 'imagecomponent',
|
||||
type: 'imagecomponent'
|
||||
},
|
||||
{
|
||||
...defaultProps,
|
||||
id: 'inputcomponent',
|
||||
type: 'inputcomponent'
|
||||
},
|
||||
{
|
||||
...defaultProps,
|
||||
id: 'selectcomponent',
|
||||
type: 'selectcomponent'
|
||||
},
|
||||
{
|
||||
...defaultProps,
|
||||
id: 'checkboxcomponent',
|
||||
type: 'checkboxcomponent'
|
||||
},
|
||||
{
|
||||
...defaultProps,
|
||||
id: 'radiocomponent',
|
||||
type: 'radiocomponent'
|
||||
}
|
||||
] as AppComponent[]
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
let object = {}
|
||||
|
||||
outputs.forEach((output) => {
|
||||
outputs.forEach((output: string) => {
|
||||
$worldStore?.outputsById[componentId][output].subscribe({
|
||||
next: (value) => {
|
||||
object[output] = value
|
||||
|
||||
@@ -74,17 +74,17 @@
|
||||
<PickScript
|
||||
kind="script"
|
||||
on:pick={({ detail }) => {
|
||||
if (component && component.type === 'runformcomponent') {
|
||||
component.path = detail.path
|
||||
component.runType = 'script'
|
||||
if (component?.runnable) {
|
||||
component['path'] = detail.path
|
||||
component['runType'] = 'script'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<PickFlow
|
||||
on:pick={({ detail }) => {
|
||||
if (component && component.type === 'runformcomponent') {
|
||||
component.path = detail.path
|
||||
component.runType = 'flow'
|
||||
if (component?.runnable) {
|
||||
component['path'] = detail.path
|
||||
component['runType'] = 'flow'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -60,11 +60,7 @@ type Runnable = {
|
||||
runType?: 'script' | 'flow'
|
||||
}
|
||||
|
||||
export type RunFormComponent = Runnable & {
|
||||
type: 'runformcomponent'
|
||||
}
|
||||
|
||||
export type BarChartComponent = {
|
||||
export type BarChartComponent = Runnable & {
|
||||
type: 'barchartcomponent'
|
||||
}
|
||||
|
||||
@@ -82,7 +78,6 @@ export type DisplayComponent = {
|
||||
|
||||
export type AppComponent =
|
||||
| (
|
||||
| RunFormComponent
|
||||
| DisplayComponent
|
||||
| TextInputComponent
|
||||
| BarChartComponent
|
||||
@@ -93,12 +88,10 @@ export type AppComponent =
|
||||
| PieChartComponent
|
||||
) & {
|
||||
id: ComponentID
|
||||
width: number
|
||||
horizontalAlignement?: 'left' | 'center' | 'right'
|
||||
verticalAlignement?: 'top' | 'center' | 'bottom'
|
||||
|
||||
inputs: InputsSpec
|
||||
// Only dynamic inputs (Result of display)
|
||||
componentInputs: ComponentInputsSpec
|
||||
runnable?: boolean | undefined
|
||||
card?: boolean | undefined
|
||||
|
||||
@@ -4,54 +4,12 @@ import type { Schema } from '$lib/common'
|
||||
import { FlowService, ScriptService } from '$lib/gen'
|
||||
import {
|
||||
faBarChart,
|
||||
faCode,
|
||||
faDisplay,
|
||||
faFile,
|
||||
faFileAudio,
|
||||
faImage,
|
||||
faMobileScreenButton,
|
||||
faPieChart,
|
||||
faSpellCheck,
|
||||
faTabletButton
|
||||
faPieChart
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
type Args = Record<string, any>
|
||||
|
||||
export function buildArgs(
|
||||
inputSpecs: InputsSpec,
|
||||
schema: Schema,
|
||||
includeHidden: boolean = false
|
||||
): Args {
|
||||
const obj = Object.keys(schema.properties).reduce((acc, key) => {
|
||||
let input = inputSpecs[key]
|
||||
|
||||
if (!input) {
|
||||
input = {
|
||||
type: 'static',
|
||||
value: '',
|
||||
visible: true,
|
||||
fieldType: 'text'
|
||||
}
|
||||
}
|
||||
|
||||
if (input.type === 'static' && (input.visible || includeHidden)) {
|
||||
acc[key] = input.value
|
||||
}
|
||||
|
||||
if (input.type === 'output') {
|
||||
acc[key] = input.defaultValue
|
||||
}
|
||||
|
||||
if (input.type === 'user') {
|
||||
acc[key] = schema.properties[key].default
|
||||
}
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
export async function loadSchema(
|
||||
workspace: string,
|
||||
path: string,
|
||||
@@ -94,10 +52,6 @@ export const displayData = {
|
||||
name: 'Result',
|
||||
icon: faDisplay
|
||||
},
|
||||
runformcomponent: {
|
||||
name: 'Script',
|
||||
icon: faCode
|
||||
},
|
||||
textcomponent: {
|
||||
name: 'Text',
|
||||
icon: faFile
|
||||
@@ -106,27 +60,6 @@ export const displayData = {
|
||||
name: 'Button',
|
||||
icon: faMobileScreenButton
|
||||
},
|
||||
imagecomponent: {
|
||||
name: 'Image',
|
||||
icon: faImage
|
||||
},
|
||||
inputcomponent: {
|
||||
name: 'Input',
|
||||
icon: faFileAudio
|
||||
},
|
||||
selectcomponent: {
|
||||
name: 'Select',
|
||||
icon: faSpellCheck
|
||||
},
|
||||
checkboxcomponent: {
|
||||
name: 'Checkbox',
|
||||
icon: faTabletButton
|
||||
},
|
||||
|
||||
radiocomponent: {
|
||||
name: 'Radio Button',
|
||||
icon: faTabletButton
|
||||
},
|
||||
piechartcomponent: {
|
||||
name: 'Pie chart',
|
||||
icon: faPieChart
|
||||
|
||||
Reference in New Issue
Block a user