wip refactor manifest
This commit is contained in:
parent
e08d745360
commit
cd36056124
|
@ -26,6 +26,8 @@
|
|||
export let tag = null
|
||||
export let searchTerm = null
|
||||
export let loading
|
||||
export let onOptionMouseenter = () => {}
|
||||
export let onOptionMouseleave = () => {}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
@ -95,6 +97,8 @@
|
|||
{autocomplete}
|
||||
{sort}
|
||||
{tag}
|
||||
{onOptionMouseenter}
|
||||
{onOptionMouseleave}
|
||||
isPlaceholder={value == null || value === ""}
|
||||
placeholderOption={placeholder === false ? null : placeholder}
|
||||
isOptionSelected={option => compareOptionAndValue(option, value)}
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
export let tag = null
|
||||
export let helpText = null
|
||||
export let compare
|
||||
export let onOptionMouseenter = () => {}
|
||||
export let onOptionMouseleave = () => {}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const onChange = e => {
|
||||
value = e.detail
|
||||
|
@ -67,6 +70,8 @@
|
|||
{customPopoverHeight}
|
||||
{tag}
|
||||
{compare}
|
||||
{onOptionMouseenter}
|
||||
{onOptionMouseleave}
|
||||
on:change={onChange}
|
||||
on:click
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export { default as FieldContext } from "./FieldContext.svelte"
|
||||
export * from "./validator"
|
|
@ -17,66 +17,64 @@ export const constants = {
|
|||
supported: Symbol("values-validator-supported")
|
||||
}
|
||||
|
||||
export const validators = {
|
||||
chart: (fieldSchema) => {
|
||||
try {
|
||||
const response = {
|
||||
level: null,
|
||||
warnings: [],
|
||||
errors: [],
|
||||
text: "",
|
||||
icon: "",
|
||||
iconColor: ""
|
||||
}
|
||||
const generalUnsupportedFields = ["array", "attachment", "barcodeqr", "link", "bb_reference"]
|
||||
if (generalUnsupportedFields.includes(fieldSchema.type)) {
|
||||
response.errors.push(errors.general)
|
||||
}
|
||||
export const validate = (fieldSchema) => {
|
||||
try {
|
||||
const response = {
|
||||
level: null,
|
||||
warnings: [],
|
||||
errors: [],
|
||||
text: "",
|
||||
icon: "",
|
||||
iconColor: ""
|
||||
}
|
||||
const generalUnsupportedFields = ["array", "attachment", "barcodeqr", "link", "bb_reference"]
|
||||
if (generalUnsupportedFields.includes(fieldSchema.type)) {
|
||||
response.errors.push(errors.general)
|
||||
}
|
||||
|
||||
if (fieldSchema.type === "json") {
|
||||
response.errors.push(errors.jsonPrimitivesOnly)
|
||||
}
|
||||
if (fieldSchema.type === "json") {
|
||||
response.errors.push(errors.jsonPrimitivesOnly)
|
||||
}
|
||||
|
||||
if (fieldSchema.type === "string") {
|
||||
response.warnings.push(warnings.stringAsNumber)
|
||||
}
|
||||
if (fieldSchema.type === "datetime") {
|
||||
response.warnings.push(warnings.chartDatetime);
|
||||
//"This column can be used as an input for a chart, but it may be parsed differently depending on which is used.
|
||||
}
|
||||
if (fieldSchema.type === "string") {
|
||||
response.warnings.push(warnings.stringAsNumber)
|
||||
}
|
||||
if (fieldSchema.type === "datetime") {
|
||||
response.warnings.push(warnings.chartDatetime);
|
||||
//"This column can be used as an input for a chart, but it may be parsed differently depending on which is used.
|
||||
}
|
||||
|
||||
const isRequired = fieldSchema?.constraints?.presence?.allowEmpty === false
|
||||
if (!isRequired) {
|
||||
response.warnings.push(warnings.notRequired);
|
||||
}
|
||||
const isRequired = fieldSchema?.constraints?.presence?.allowEmpty === false
|
||||
if (!isRequired) {
|
||||
response.warnings.push(warnings.notRequired);
|
||||
}
|
||||
|
||||
if (response.errors.length > 0) {
|
||||
response.level = constants.unsupported
|
||||
response.text = "Not compatible"
|
||||
response.icon = "Alert"
|
||||
response.iconColor = "var(--red)"
|
||||
} else if (response.warnings.length > 0) {
|
||||
response.level = constants.partialSupport
|
||||
response.text = "Partially compatible"
|
||||
response.icon = "AlertCheck"
|
||||
response.iconColor = "var(--yellow)"
|
||||
} else {
|
||||
response.level = constants.supported
|
||||
response.text = "Compatible"
|
||||
response.icon = "CheckmarkCircle"
|
||||
response.iconColor = "var(--green)"
|
||||
}
|
||||
if (response.errors.length > 0) {
|
||||
response.level = constants.unsupported
|
||||
response.text = "Not compatible"
|
||||
response.icon = "Alert"
|
||||
response.iconColor = "var(--red)"
|
||||
} else if (response.warnings.length > 0) {
|
||||
response.level = constants.partialSupport
|
||||
response.text = "Partially compatible"
|
||||
response.icon = "AlertCheck"
|
||||
response.iconColor = "var(--yellow)"
|
||||
} else {
|
||||
response.level = constants.supported
|
||||
response.text = "Compatible"
|
||||
response.icon = "CheckmarkCircle"
|
||||
response.iconColor = "var(--green)"
|
||||
}
|
||||
|
||||
return response
|
||||
} catch (e) {
|
||||
return {
|
||||
level: constants.partialSupport,
|
||||
warnings: [],
|
||||
errors: [],
|
||||
text: "Partially compatible",
|
||||
icon: "AlertCheck",
|
||||
iconColor: "var(--yellow)"
|
||||
}
|
||||
return response
|
||||
} catch (e) {
|
||||
return {
|
||||
level: constants.partialSupport,
|
||||
warnings: [],
|
||||
errors: [],
|
||||
text: "Partially compatible",
|
||||
icon: "AlertCheck",
|
||||
iconColor: "var(--yellow)"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,25 +1,32 @@
|
|||
<script>
|
||||
import { Select } from "@budibase/bbui"
|
||||
import { Select, ContextTooltip } from "@budibase/bbui"
|
||||
import { getDatasourceForProvider, getSchemaForDatasource } from "dataBinding"
|
||||
import { selectedScreen } from "stores/builder"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { validators, constants as validatorConstants } from "../fieldValidator";
|
||||
import { FieldContext, validate } from './FieldContext'
|
||||
import { debounce } from "lodash"
|
||||
import { goto, params } from "@roxi/routify"
|
||||
import { Constants } from "@budibase/frontend-core"
|
||||
import { FIELDS } from 'constants/backend'
|
||||
|
||||
export let componentInstance = {}
|
||||
export let value = ""
|
||||
export let placeholder
|
||||
export let fieldValidator
|
||||
export let columnContext
|
||||
|
||||
const getFieldSupport = (schema, fieldValidator) => {
|
||||
if (fieldValidator == null) {
|
||||
let contextTooltipAnchor = null
|
||||
let currentOption = null
|
||||
let previousOption = null
|
||||
let contextTooltipVisible = false
|
||||
|
||||
const getFieldSupport = (schema, columnContext) => {
|
||||
if (!columnContext) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const validator = validators[fieldValidator];
|
||||
|
||||
const fieldSupport = {}
|
||||
Object.entries(schema || {}).forEach(([key, value]) => {
|
||||
fieldSupport[key] = validator(value)
|
||||
fieldSupport[key] = validate(value)
|
||||
})
|
||||
|
||||
return fieldSupport
|
||||
|
@ -28,7 +35,7 @@
|
|||
const dispatch = createEventDispatcher()
|
||||
$: datasource = getDatasourceForProvider($selectedScreen, componentInstance)
|
||||
$: schema = getSchemaForDatasource($selectedScreen, datasource).schema
|
||||
$: fieldSupport = getFieldSupport(schema, fieldValidator);
|
||||
$: fieldSupport = getFieldSupport(schema, columnContext);
|
||||
$: options = Object.keys(schema || {})
|
||||
$: boundValue = getValidValue(value, options)
|
||||
|
||||
|
@ -51,34 +58,87 @@
|
|||
dispatch("change", boundValue)
|
||||
}
|
||||
|
||||
const getOptionIcon = option => {
|
||||
/*
|
||||
const support = fieldSupport[option]?.support;
|
||||
const updateTooltip = debounce((e, option) => {
|
||||
if (option == null) {
|
||||
contextTooltipVisible = false;
|
||||
} else {
|
||||
contextTooltipAnchor = e?.target;
|
||||
previousOption = currentOption;
|
||||
currentOption = option;
|
||||
contextTooltipVisible = true;
|
||||
}
|
||||
}, 200);
|
||||
|
||||
if (support == null) return null;
|
||||
if (support === supported) return null
|
||||
|
||||
if (support === partialSupport) return "Warning"
|
||||
if (support === unsupported) return "Error"
|
||||
*/
|
||||
const onOptionMouseenter = (e, option, idx) => {
|
||||
updateTooltip(e, option);
|
||||
}
|
||||
|
||||
const getOptionIconTooltip = option => {
|
||||
const onOptionMouseleave = (e, option) => {
|
||||
updateTooltip(e, null);
|
||||
}
|
||||
const getOptionIcon = optionKey => {
|
||||
const option = schema[optionKey]
|
||||
if (!option) return ""
|
||||
|
||||
if (option.autocolumn) {
|
||||
return "MagicWand"
|
||||
}
|
||||
const { type, subtype } = option
|
||||
|
||||
const result =
|
||||
typeof Constants.TypeIconMap[type] === "object" && subtype
|
||||
? Constants.TypeIconMap[type][subtype]
|
||||
: Constants.TypeIconMap[type]
|
||||
|
||||
return result || "Text"
|
||||
}
|
||||
|
||||
const isOptionEnabled = option => {
|
||||
return true
|
||||
const support = fieldSupport[option]?.support;
|
||||
const getOptionIconTooltip = optionKey => {
|
||||
const option = schema[optionKey]
|
||||
|
||||
if (support == null) return true
|
||||
if (support == unsupported) return false
|
||||
const type = option?.type;
|
||||
const field = Object.values(FIELDS).find(f => f.type === type)
|
||||
|
||||
return true
|
||||
if (field) {
|
||||
return field.name
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<Select
|
||||
{isOptionEnabled}
|
||||
{getOptionIcon}
|
||||
{getOptionIconTooltip}
|
||||
{placeholder} value={boundValue} on:change={onChange} {options} />
|
||||
{placeholder}
|
||||
value={boundValue}
|
||||
on:change={onChange}
|
||||
{options}
|
||||
{onOptionMouseenter}
|
||||
{onOptionMouseleave}
|
||||
/>
|
||||
|
||||
{#if columnContext}
|
||||
<ContextTooltip
|
||||
visible={contextTooltipVisible}
|
||||
anchor={contextTooltipAnchor}
|
||||
offset={20}
|
||||
>
|
||||
<FieldContext
|
||||
explanationModal
|
||||
tableHref={`/builder/app/${$params.application}/data/table/${datasource?.tableId}`}
|
||||
schema={schema[currentOption]}
|
||||
support={fieldSupport[currentOption]}
|
||||
columnIcon={getOptionIcon(currentOption)}
|
||||
columnName={currentOption}
|
||||
columnType={getOptionIconTooltip(currentOption)}
|
||||
/>
|
||||
<FieldContext
|
||||
slot="previous"
|
||||
schema={schema[previousOption]}
|
||||
support={fieldSupport[previousOption]}
|
||||
columnIcon={getOptionIcon(previousOption)}
|
||||
columnName={previousOption}
|
||||
columnType={getOptionIconTooltip(previousOption)}
|
||||
/>
|
||||
</ContextTooltip>
|
||||
{/if}
|
||||
|
|
|
@ -1,54 +1,39 @@
|
|||
<script>
|
||||
import { Icon, Heading, Multiselect, ContextTooltip } from "@budibase/bbui"
|
||||
import { getDatasourceForProvider, getSchemaForDatasource } from "dataBinding"
|
||||
import { selectedScreen } from "stores/builder"
|
||||
import { selectedScreen,
|
||||
componentStore,
|
||||
} from "stores/builder"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { validators } from "./FieldContext/Validator";
|
||||
import ChartFieldContext from './FieldContext/Chart.svelte'
|
||||
import { FieldContext, validate } from './FieldContext'
|
||||
import { FIELDS } from 'constants/backend'
|
||||
import { goto, params } from "@roxi/routify"
|
||||
import { debounce } from "lodash"
|
||||
import { Constants } from "@budibase/frontend-core"
|
||||
|
||||
export let componentInstance = {}
|
||||
export let value = ""
|
||||
export let placeholder
|
||||
export let fieldValidator
|
||||
export let columnContext
|
||||
export let valueTypes
|
||||
|
||||
let contextTooltipAnchor = null
|
||||
let currentOption = null
|
||||
let previousOption = null
|
||||
let contextTooltipVisible = false
|
||||
|
||||
const TypeIconMap = {
|
||||
text: "Text",
|
||||
options: "Dropdown",
|
||||
datetime: "Date",
|
||||
barcodeqr: "Camera",
|
||||
longform: "TextAlignLeft",
|
||||
array: "Dropdown",
|
||||
number: "123",
|
||||
boolean: "Boolean",
|
||||
attachment: "AppleFiles",
|
||||
link: "DataCorrelated",
|
||||
formula: "Calculator",
|
||||
json: "Brackets",
|
||||
bigint: "TagBold",
|
||||
bb_reference: {
|
||||
user: "User",
|
||||
users: "UserGroup",
|
||||
},
|
||||
}
|
||||
$: componentDefinition = componentStore.getDefinition(
|
||||
componentInstance?._component
|
||||
)
|
||||
|
||||
const getFieldSupport = (schema, fieldValidator) => {
|
||||
if (fieldValidator == null) {
|
||||
const getFieldSupport = (schema, columnContext) => {
|
||||
if (!columnContext) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const validator = validators[fieldValidator];
|
||||
|
||||
const fieldSupport = {}
|
||||
Object.entries(schema || {}).forEach(([key, value]) => {
|
||||
fieldSupport[key] = validator(value)
|
||||
fieldSupport[key] = validate(value)
|
||||
})
|
||||
|
||||
return fieldSupport
|
||||
|
@ -58,7 +43,7 @@
|
|||
$: datasource = getDatasourceForProvider($selectedScreen, componentInstance)
|
||||
$: schema = getSchemaForDatasource($selectedScreen, datasource).schema
|
||||
$: options = Object.keys(schema || {})
|
||||
$: fieldSupport = getFieldSupport(schema, fieldValidator);
|
||||
$: fieldSupport = getFieldSupport(schema, columnContext);
|
||||
$: boundValue = getValidOptions(value, options)
|
||||
|
||||
|
||||
|
@ -85,9 +70,9 @@
|
|||
const { type, subtype } = option
|
||||
|
||||
const result =
|
||||
typeof TypeIconMap[type] === "object" && subtype
|
||||
? TypeIconMap[type][subtype]
|
||||
: TypeIconMap[type]
|
||||
typeof Constants.TypeIconMap[type] === "object" && subtype
|
||||
? Constants.TypeIconMap[type][subtype]
|
||||
: Constants.TypeIconMap[type]
|
||||
|
||||
return result || "Text"
|
||||
}
|
||||
|
@ -139,7 +124,6 @@
|
|||
|
||||
<Multiselect
|
||||
iconPosition="right"
|
||||
{isOptionEnabled}
|
||||
{placeholder}
|
||||
value={boundValue}
|
||||
on:change={setValue}
|
||||
|
@ -148,29 +132,29 @@
|
|||
{onOptionMouseenter}
|
||||
{onOptionMouseleave}
|
||||
/>
|
||||
<ContextTooltip
|
||||
visible={contextTooltipVisible}
|
||||
anchor={contextTooltipAnchor}
|
||||
offset={20}
|
||||
>
|
||||
<ChartFieldContext
|
||||
explanationModal
|
||||
tableHref={`/builder/app/${$params.application}/data/table/${datasource?.tableId}`}
|
||||
schema={schema[currentOption]}
|
||||
support={fieldSupport[currentOption]}
|
||||
columnIcon={getOptionIcon(currentOption)}
|
||||
columnName={currentOption}
|
||||
columnType={getOptionIconTooltip(currentOption)}
|
||||
/>
|
||||
<ChartFieldContext
|
||||
slot="previous"
|
||||
schema={schema[previousOption]}
|
||||
support={fieldSupport[previousOption]}
|
||||
columnIcon={getOptionIcon(previousOption)}
|
||||
columnName={previousOption}
|
||||
columnType={getOptionIconTooltip(previousOption)}
|
||||
/>
|
||||
</ContextTooltip>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
{#if columnContext}
|
||||
<ContextTooltip
|
||||
visible={contextTooltipVisible}
|
||||
anchor={contextTooltipAnchor}
|
||||
offset={20}
|
||||
>
|
||||
<FieldContext
|
||||
explanationModal
|
||||
tableHref={`/builder/app/${$params.application}/data/table/${datasource?.tableId}`}
|
||||
schema={schema[currentOption]}
|
||||
support={fieldSupport[currentOption]}
|
||||
columnIcon={getOptionIcon(currentOption)}
|
||||
columnName={currentOption}
|
||||
columnType={getOptionIconTooltip(currentOption)}
|
||||
/>
|
||||
<FieldContext
|
||||
slot="previous"
|
||||
schema={schema[previousOption]}
|
||||
support={fieldSupport[previousOption]}
|
||||
columnIcon={getOptionIcon(previousOption)}
|
||||
columnName={previousOption}
|
||||
columnType={getOptionIconTooltip(previousOption)}
|
||||
/>
|
||||
</ContextTooltip>
|
||||
{/if}
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
import { capitalize } from 'lodash';
|
||||
|
||||
export const errors = {
|
||||
general: Symbol("values-validator-general"),
|
||||
jsonPrimitivesOnly: Symbol("values-validator-json-primitives-only"),
|
||||
}
|
||||
|
||||
export const warnings = {
|
||||
stringAsNumber: Symbol("values-validator-string-as-number"),
|
||||
chartDatetime: Symbol("values-validator-chart-datetime"),
|
||||
notRequired: Symbol("values-validator-not-required"),
|
||||
}
|
||||
|
||||
export const constants = {
|
||||
unsupported: Symbol("values-validator-unsupported"),
|
||||
partialSupport: Symbol("values-validator-partialSupport"),
|
||||
supported: Symbol("values-validator-supported")
|
||||
}
|
||||
|
||||
export const validators = {
|
||||
chart: (fieldSchema) => {
|
||||
try {
|
||||
const response = {
|
||||
level: null,
|
||||
warnings: [],
|
||||
errors: [],
|
||||
text: "",
|
||||
icon: "",
|
||||
iconColor: ""
|
||||
}
|
||||
const generalUnsupportedFields = ["array", "attachment", "barcodeqr", "link", "bb_reference"]
|
||||
if (generalUnsupportedFields.includes(fieldSchema.type)) {
|
||||
response.errors.push(errors.general)
|
||||
}
|
||||
|
||||
if (fieldSchema.type === "json") {
|
||||
response.errors.push(errors.jsonPrimitivesOnly)
|
||||
}
|
||||
|
||||
if (fieldSchema.type === "string") {
|
||||
response.warnings.push(warnings.stringAsNumber)
|
||||
}
|
||||
if (fieldSchema.type === "datetime") {
|
||||
response.warnings.push(warnings.chartDatetime);
|
||||
//"This column can be used as an input for a chart, but it may be parsed differently depending on which is used.
|
||||
}
|
||||
|
||||
const isRequired = fieldSchema?.constraints?.presence?.allowEmpty === false
|
||||
if (!isRequired) {
|
||||
response.warnings.push(warnings.notRequired);
|
||||
}
|
||||
|
||||
if (response.errors.length > 0) {
|
||||
response.level = constants.unsupported
|
||||
response.text = "Not compatible"
|
||||
response.icon = "Alert"
|
||||
response.iconColor = "var(--red)"
|
||||
} else if (response.warnings.length > 0) {
|
||||
response.level = constants.partialSupport
|
||||
response.text = "Partially compatible"
|
||||
response.icon = "AlertCheck"
|
||||
response.iconColor = "var(--yellow)"
|
||||
} else {
|
||||
response.level = constants.supported
|
||||
response.text = "Compatible"
|
||||
response.icon = "CheckmarkCircle"
|
||||
response.iconColor = "var(--green)"
|
||||
}
|
||||
|
||||
return response
|
||||
} catch (e) {
|
||||
return {
|
||||
level: constants.partialSupport,
|
||||
warnings: [],
|
||||
errors: [],
|
||||
text: "Partially compatible",
|
||||
icon: "AlertCheck",
|
||||
iconColor: "var(--yellow)"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -193,7 +193,8 @@
|
|||
max: setting.max ?? null,
|
||||
|
||||
// Field select settings
|
||||
fieldValidator: setting.fieldValidator,
|
||||
columnContext: setting.columnContext,
|
||||
valueTypes: setting.valueTypes
|
||||
}}
|
||||
{bindings}
|
||||
{componentBindings}
|
||||
|
|
|
@ -1602,6 +1602,7 @@
|
|||
]
|
||||
},
|
||||
"bar": {
|
||||
"documentationLink": "https://docs.budibase.com/docs/bar-chart",
|
||||
"name": "Bar Chart",
|
||||
"description": "Bar chart",
|
||||
"icon": "GraphBarVertical",
|
||||
|
@ -1633,7 +1634,8 @@
|
|||
"label": "Data columns",
|
||||
"key": "valueColumns",
|
||||
"dependsOn": "dataProvider",
|
||||
"fieldValidator": "chart",
|
||||
"valueTypes": ["number"],
|
||||
"columnContext": true,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue