@flyanra/vue-core 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -176
- package/package.json +137 -128
- package/src/components/basic/fly-button/FlyButton.element.scss +3 -3
- package/src/components/basic/fly-button/FlyButton.mixins.scss +58 -58
- package/src/components/basic/fly-button/FlyButton.types.ts +29 -29
- package/src/components/basic/fly-button/FlyButton.vue +180 -180
- package/src/components/basic/fly-button/index.ts +11 -11
- package/src/components/basic/index.ts +2 -2
- package/src/components/basic/typography/FlyCollapseTitleRenderer.vue +46 -0
- package/src/components/feedback/index.ts +2 -2
- package/src/components/feedback/tooltip/FlyInfoTooltip.vue +48 -0
- package/src/components/feedback/tooltip/FlyTooltip.element.scss +4 -4
- package/src/components/feedback/tooltip/FlyTooltip.types.ts +5 -5
- package/src/components/feedback/tooltip/FlyTooltip.vue +60 -59
- package/src/components/feedback/tooltip/index.ts +6 -6
- package/src/components/form/form.utils.ts +57 -0
- package/src/components/form/index.ts +0 -0
- package/src/components/form/input-renderers/boolean/FlyBoolean.scss +1 -0
- package/src/components/form/input-renderers/boolean/FlyBoolean.types.ts +16 -0
- package/src/components/form/input-renderers/boolean/FlyBoolean.vue +35 -0
- package/src/components/form/input-renderers/date-time/FlyDateTime.scss +1 -0
- package/src/components/form/input-renderers/date-time/FlyDateTime.types.ts +21 -0
- package/src/components/form/input-renderers/date-time/FlyDateTime.vue +85 -0
- package/src/components/form/input-renderers/form-item-renderer/FlyFormItemRenderer.scss +4 -0
- package/src/components/form/input-renderers/form-item-renderer/FlyFormItemRenderer.vue +48 -0
- package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.types.ts +3 -0
- package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.utils.ts +246 -0
- package/src/components/form/input-renderers/form-schema-renderer/FlyFormSchemaRenderer.vue +75 -0
- package/src/components/form/input-renderers/form-schema-renderer/UseFormSchemaRenderer.ts +97 -0
- package/src/components/form/input-renderers/form-schema.types.ts +95 -0
- package/src/components/form/input-renderers/input-renderer/FlyInputRenderer.vue +49 -0
- package/src/components/form/input-renderers/input-renderer.types.ts +49 -0
- package/src/components/form/input-renderers/input-renderer.utils.ts +18 -0
- package/src/components/form/input-renderers/number/FlyNumber.scss +1 -0
- package/src/components/form/input-renderers/number/FlyNumber.types.ts +13 -0
- package/src/components/form/input-renderers/number/FlyNumber.utils.ts +6 -0
- package/src/components/form/input-renderers/number/FlyNumber.vue +48 -0
- package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.types.ts +15 -0
- package/src/components/form/input-renderers/regional-tenant-form-renderer/FlyRegionalTenantFormRenderer.vue +99 -0
- package/src/components/form/input-renderers/select/FlySelect.scss +9 -0
- package/src/components/form/input-renderers/select/FlySelect.types.ts +25 -0
- package/src/components/form/input-renderers/select/FlySelect.utils.ts +37 -0
- package/src/components/form/input-renderers/select/FlySelect.vue +48 -0
- package/src/components/form/input-renderers/text/FlyText.scss +1 -0
- package/src/components/form/input-renderers/text/FlyText.types.ts +20 -0
- package/src/components/form/input-renderers/text/FlyText.vue +56 -0
- package/src/components/form/input-renderers/value-unit/FlyValueUnit.scss +2 -0
- package/src/components/form/input-renderers/value-unit/FlyValueUnit.types.ts +28 -0
- package/src/components/form/input-renderers/value-unit/FlyValueUnit.vue +101 -0
- package/src/components/form/input-validators.ts +121 -0
- package/src/components/general/fly-icon/FlyIcon.types.ts +12 -12
- package/src/components/general/fly-icon/FlyIcon.vue +24 -24
- package/src/components/general/fly-icon/index.ts +6 -6
- package/src/components/general/index.ts +2 -2
- package/src/components/index.ts +5 -11
- package/src/components/navigation/fly-steps/FlySteps.element.scss +100 -100
- package/src/components/navigation/fly-steps/FlySteps.types.ts +10 -10
- package/src/components/navigation/fly-steps/FlySteps.vue +30 -30
- package/src/components/navigation/fly-steps/index.ts +6 -6
- package/src/components/navigation/index.ts +2 -2
- package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.element.scss +2 -2
- package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.types.ts +8 -8
- package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.vue +46 -46
- package/src/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebarItem.vue +55 -55
- package/src/components/navigation/menu/fly-mini-sidebar/index.ts +6 -6
- package/src/components/navigation/menu/fly-sidebar/FlySidebar.element.scss +9 -9
- package/src/components/navigation/menu/fly-sidebar/FlySidebar.types.ts +36 -36
- package/src/components/navigation/menu/fly-sidebar/FlySidebar.vue +150 -150
- package/src/components/navigation/menu/fly-sidebar/FlySidebarNode.vue +47 -47
- package/src/components/navigation/menu/fly-sidebar/index.ts +12 -12
- package/src/components/navigation/menu/index.ts +5 -5
- package/src/index.ts +1 -1
- package/src/styles/_scss-tokens.scss +76 -76
- package/src/styles/core/animations.scss +40 -40
- package/src/styles/core/index.scss +36 -36
- package/src/styles/core/scrollbar.scss +36 -36
- package/src/styles/core/typography-utils.scss +9 -9
- package/src/styles/element/common.scss +56 -56
- package/src/styles/element/dark.scss +38 -38
- package/src/styles/element/mixins/collapse.scss +61 -61
- package/src/styles/element/mixins/dialog.scss +101 -101
- package/src/styles/element/overrides/alerts.scss +28 -28
- package/src/styles/element/overrides/badge.scss +6 -6
- package/src/styles/element/overrides/cascader.scss +2 -2
- package/src/styles/element/overrides/collapse.scss +2 -2
- package/src/styles/element/overrides/date-time.scss +11 -0
- package/src/styles/element/overrides/dialog.scss +2 -2
- package/src/styles/element/overrides/dropdown.scss +11 -11
- package/src/styles/element/overrides/form.scss +107 -107
- package/src/styles/element/overrides/message.scss +39 -39
- package/src/styles/element/overrides/notification.scss +46 -46
- package/src/styles/element/overrides/segmented.scss +17 -17
- package/src/styles/element/overrides/table.scss +2 -2
- package/src/styles/element/overrides/tag.scss +19 -19
- package/src/styles/index.d.ts +1 -1
- package/src/styles/index.scss +5 -5
- package/src/styles/mixins/shadows.scss +15 -15
- package/src/styles/tokens.scss +84 -83
- package/dist/types/components/AppButton/AppButton.types.d.ts +0 -8
- package/dist/types/components/AppButton/AppButton.vue.d.ts +0 -20
- package/dist/types/components/AppButton/index.d.ts +0 -4
- package/dist/types/components/AppCard/AppCard.types.d.ts +0 -5
- package/dist/types/components/AppCard/AppCard.vue.d.ts +0 -17
- package/dist/types/components/AppCard/index.d.ts +0 -4
- package/dist/types/components/basic/fly-button/FlyButton.types.d.ts +0 -25
- package/dist/types/components/basic/fly-button/FlyButton.vue.d.ts +0 -26
- package/dist/types/components/basic/fly-button/index.d.ts +0 -4
- package/dist/types/components/basic/index.d.ts +0 -2
- package/dist/types/components/feedback/index.d.ts +0 -2
- package/dist/types/components/feedback/tooltip/FlyTooltip.types.d.ts +0 -4
- package/dist/types/components/feedback/tooltip/FlyTooltip.vue.d.ts +0 -16
- package/dist/types/components/feedback/tooltip/index.d.ts +0 -4
- package/dist/types/components/general/fly-icon/FlyIcon.types.d.ts +0 -7
- package/dist/types/components/general/fly-icon/FlyIcon.vue.d.ts +0 -6
- package/dist/types/components/general/fly-icon/index.d.ts +0 -4
- package/dist/types/components/general/index.d.ts +0 -2
- package/dist/types/components/index.d.ts +0 -8
- package/dist/types/components/navigation/fly-steps/FlySteps.types.d.ts +0 -9
- package/dist/types/components/navigation/fly-steps/FlySteps.vue.d.ts +0 -9
- package/dist/types/components/navigation/fly-steps/index.d.ts +0 -4
- package/dist/types/components/navigation/index.d.ts +0 -2
- package/dist/types/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.types.d.ts +0 -7
- package/dist/types/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebar.vue.d.ts +0 -8
- package/dist/types/components/navigation/menu/fly-mini-sidebar/FlyMiniSidebarItem.vue.d.ts +0 -7
- package/dist/types/components/navigation/menu/fly-mini-sidebar/index.d.ts +0 -4
- package/dist/types/components/navigation/menu/fly-sidebar/FlySidebar.types.d.ts +0 -29
- package/dist/types/components/navigation/menu/fly-sidebar/FlySidebar.vue.d.ts +0 -8
- package/dist/types/components/navigation/menu/fly-sidebar/FlySidebarNode.vue.d.ts +0 -7
- package/dist/types/components/navigation/menu/fly-sidebar/index.d.ts +0 -4
- package/dist/types/components/navigation/menu/index.d.ts +0 -4
- package/dist/types/index.d.ts +0 -1
- package/dist/types/types/index.d.ts +0 -1
- package/src/components/AppButton/AppButton.element.scss +0 -2
- package/src/components/AppButton/AppButton.types.ts +0 -10
- package/src/components/AppButton/AppButton.vue +0 -65
- package/src/components/AppButton/index.ts +0 -6
- package/src/components/AppCard/AppCard.types.ts +0 -5
- package/src/components/AppCard/AppCard.vue +0 -58
- package/src/components/AppCard/index.ts +0 -6
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="fly-form-schema-renderer">
|
|
3
|
+
<el-form
|
|
4
|
+
ref="formRef"
|
|
5
|
+
:rules="dynamicValidators"
|
|
6
|
+
:model="formProxy"
|
|
7
|
+
label-position="top"
|
|
8
|
+
status-icon
|
|
9
|
+
:disabled="disabled"
|
|
10
|
+
@submit.prevent
|
|
11
|
+
>
|
|
12
|
+
<div class="fly-form-schema-renderer__form-holder">
|
|
13
|
+
<div
|
|
14
|
+
v-for="(input, i) in generatedForm?.inputs"
|
|
15
|
+
:key="i"
|
|
16
|
+
:style="{
|
|
17
|
+
gridColumn: `span ${getSpan(input)} / span ${getSpan(input)}`
|
|
18
|
+
}"
|
|
19
|
+
>
|
|
20
|
+
<FlyFormItemRenderer v-model="formProxy[input.key]" :input="input" />
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</el-form>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { ref } from 'vue'
|
|
29
|
+
|
|
30
|
+
import { ElForm, type FormInstance } from 'element-plus'
|
|
31
|
+
|
|
32
|
+
import '../../../../styles/element/overrides/form.scss'
|
|
33
|
+
import FlyFormItemRenderer from '../form-item-renderer/FlyFormItemRenderer.vue'
|
|
34
|
+
import type { T_InputRendererBase } from '../input-renderer.types'
|
|
35
|
+
|
|
36
|
+
import {
|
|
37
|
+
type T_FormSchemaRendererEmits,
|
|
38
|
+
type T_FormSchemaRendererProps,
|
|
39
|
+
UseFormSchemaRenderer
|
|
40
|
+
} from './UseFormSchemaRenderer'
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits<T_FormSchemaRendererEmits>()
|
|
43
|
+
|
|
44
|
+
const props = defineProps<
|
|
45
|
+
T_FormSchemaRendererProps & {
|
|
46
|
+
/**
|
|
47
|
+
* Column span within a 12 column grid
|
|
48
|
+
*/
|
|
49
|
+
columnSpan?: number
|
|
50
|
+
}
|
|
51
|
+
>()
|
|
52
|
+
|
|
53
|
+
const formRef = ref<FormInstance>()
|
|
54
|
+
|
|
55
|
+
const dynamicConfigFormComp = UseFormSchemaRenderer({ formRef, props, emit })
|
|
56
|
+
const { dynamicValidators, formProxy, generatedForm } = dynamicConfigFormComp
|
|
57
|
+
|
|
58
|
+
function getSpan(input?: T_InputRendererBase) {
|
|
59
|
+
return input?.columnSpan || props.columnSpan || 4
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
defineExpose({
|
|
63
|
+
validateForm: dynamicConfigFormComp.validateForm
|
|
64
|
+
})
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<style lang="scss" scoped>
|
|
68
|
+
.fly-form-schema-renderer {
|
|
69
|
+
&__form-holder {
|
|
70
|
+
display: grid;
|
|
71
|
+
grid-template-columns: repeat(12, minmax(0, 1fr));
|
|
72
|
+
gap: 0.5rem;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { type Ref, computed, ref, watch } from 'vue'
|
|
2
|
+
|
|
3
|
+
import type { FormInstance } from 'element-plus'
|
|
4
|
+
|
|
5
|
+
import { defaultsDeep } from 'lodash'
|
|
6
|
+
|
|
7
|
+
import type { T_FormSchemaLookupData, T_InputSchema } from '../form-schema.types'
|
|
8
|
+
import type { T_FormSchemaRendererConfig, T_InputRendererBase } from '../input-renderer.types'
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
generateInputFromFormSchema,
|
|
12
|
+
genericFormValidator,
|
|
13
|
+
getValidatorsFromInputFields
|
|
14
|
+
} from './FlyFormSchemaRenderer.utils'
|
|
15
|
+
|
|
16
|
+
export type T_FormSchemaRendererProps = {
|
|
17
|
+
formConfig: T_InputSchema[]
|
|
18
|
+
lookupData?: T_FormSchemaLookupData
|
|
19
|
+
modelValue?: Record<string, unknown>
|
|
20
|
+
disabled?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type T_FormSchemaRendererEmits = {
|
|
24
|
+
(e: 'update:modelValue', value: T_FormSchemaRendererProps['modelValue']): void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type ConfigFormCompArgs = {
|
|
28
|
+
formRef: Ref<FormInstance | undefined>
|
|
29
|
+
props: T_FormSchemaRendererProps
|
|
30
|
+
emit: T_FormSchemaRendererEmits
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function UseFormSchemaRenderer(args: ConfigFormCompArgs) {
|
|
34
|
+
const fallbackForm = {}
|
|
35
|
+
|
|
36
|
+
const formProxy = computed<Record<string, unknown>>({
|
|
37
|
+
get: () => args.props.modelValue || fallbackForm,
|
|
38
|
+
set: (val) => args.emit('update:modelValue', val)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const generatedForm = ref<T_FormSchemaRendererConfig>()
|
|
42
|
+
const dynamicFormGenerated = ref(false)
|
|
43
|
+
|
|
44
|
+
const dynamicValidators = computed(() => {
|
|
45
|
+
const validators =
|
|
46
|
+
generatedForm.value && getValidatorsFromInputFields(generatedForm.value.inputs)
|
|
47
|
+
|
|
48
|
+
return validators || {}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
async function validateForm() {
|
|
52
|
+
return args.formRef.value && genericFormValidator(args.formRef.value)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function generateDynamicForm() {
|
|
56
|
+
try {
|
|
57
|
+
if (dynamicFormGenerated.value) return
|
|
58
|
+
|
|
59
|
+
const inputs: T_InputRendererBase[] = []
|
|
60
|
+
const baseForm: T_FormSchemaRendererConfig['baseForm'] = {}
|
|
61
|
+
|
|
62
|
+
args.props.formConfig.forEach((f) => {
|
|
63
|
+
const i = generateInputFromFormSchema(f, args.props.lookupData)
|
|
64
|
+
if (i) {
|
|
65
|
+
inputs.push(i)
|
|
66
|
+
baseForm[i.key] = f.default_value
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
dynamicFormGenerated.value = true
|
|
71
|
+
|
|
72
|
+
defaultsDeep(args.props.modelValue, baseForm)
|
|
73
|
+
|
|
74
|
+
generatedForm.value = { inputs, baseForm }
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(error)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
watch(
|
|
81
|
+
() => args.props.formConfig,
|
|
82
|
+
() => {
|
|
83
|
+
dynamicFormGenerated.value = false
|
|
84
|
+
generateDynamicForm()
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
immediate: true
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
dynamicValidators,
|
|
93
|
+
formProxy,
|
|
94
|
+
generatedForm,
|
|
95
|
+
validateForm
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { T_DateInputTypes } from './date-time/FlyDateTime.types'
|
|
2
|
+
import type { T_InputSelectOption } from './select/FlySelect.types'
|
|
3
|
+
import type { T_ValueUnitValue } from './value-unit/FlyValueUnit.types'
|
|
4
|
+
|
|
5
|
+
export type T_FormSchemaLookupData = Record<string, Array<unknown>>
|
|
6
|
+
|
|
7
|
+
export type T_InputSchema =
|
|
8
|
+
| T_InputSchemaText
|
|
9
|
+
| T_InputSchemaNumber
|
|
10
|
+
| T_InputSchemaBoolean
|
|
11
|
+
| T_InputSchemaSelect
|
|
12
|
+
| T_InputSchemaValueUnit
|
|
13
|
+
| T_InputSchemaDateTime
|
|
14
|
+
|
|
15
|
+
type T_FieldValidationBase = {
|
|
16
|
+
required?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type T_InputSchemaBase<ValidationRules = object> = {
|
|
20
|
+
unique_key: string
|
|
21
|
+
label: string
|
|
22
|
+
tooltip?: string
|
|
23
|
+
placeholder?: string
|
|
24
|
+
validation?: T_FieldValidationBase & ValidationRules
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type T_InputSchemaText = T_InputSchemaBase<{
|
|
28
|
+
minLength?: number
|
|
29
|
+
maxLength?: number
|
|
30
|
+
}> & {
|
|
31
|
+
type: 'text'
|
|
32
|
+
default_value?: string
|
|
33
|
+
config?: {
|
|
34
|
+
maxLength?: number
|
|
35
|
+
minLength?: number
|
|
36
|
+
type?: string
|
|
37
|
+
rows?: number
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type T_InputSchemaNumber = T_InputSchemaBase<{
|
|
42
|
+
minLength?: number
|
|
43
|
+
maxLength?: number
|
|
44
|
+
}> & {
|
|
45
|
+
type: 'number'
|
|
46
|
+
default_value?: number
|
|
47
|
+
config?: {
|
|
48
|
+
minLength?: number
|
|
49
|
+
maxLength?: number
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type T_InputSchemaBoolean = T_InputSchemaBase & {
|
|
54
|
+
type: 'boolean'
|
|
55
|
+
default_value?: boolean
|
|
56
|
+
config?: {
|
|
57
|
+
activeText?: string
|
|
58
|
+
inactiveText?: string
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type T_SelectOptions =
|
|
63
|
+
| {
|
|
64
|
+
options_config_Lookup_id: string
|
|
65
|
+
options?: never
|
|
66
|
+
}
|
|
67
|
+
| {
|
|
68
|
+
options?: T_InputSelectOption[]
|
|
69
|
+
options_config_Lookup_id?: never
|
|
70
|
+
}
|
|
71
|
+
type T_SelectBase<M extends boolean | undefined> = T_InputSchemaBase & {
|
|
72
|
+
type: 'select'
|
|
73
|
+
config: T_SelectOptions & {
|
|
74
|
+
multiple?: M
|
|
75
|
+
}
|
|
76
|
+
default_value?: M extends true ? (string | number)[] : string | number
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export type T_InputSchemaSelect = T_SelectBase<true> | T_SelectBase<false | undefined>
|
|
80
|
+
|
|
81
|
+
export type T_InputSchemaValueUnit = T_InputSchemaBase & {
|
|
82
|
+
type: 'valueUnit'
|
|
83
|
+
config: T_SelectOptions & {
|
|
84
|
+
valueType?: 'text' | 'number'
|
|
85
|
+
}
|
|
86
|
+
default_value?: T_ValueUnitValue
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type T_InputSchemaDateTime = T_InputSchemaBase & {
|
|
90
|
+
type: 'dateTime'
|
|
91
|
+
default_value?: string | [string | string]
|
|
92
|
+
config?: {
|
|
93
|
+
inputType: T_DateInputTypes
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div style="width: 100%">
|
|
3
|
+
<component
|
|
4
|
+
:is="map[input.type]"
|
|
5
|
+
:model-value="modelValue"
|
|
6
|
+
:input="input"
|
|
7
|
+
@change="(v: unknown) => emit('change', v)"
|
|
8
|
+
@update:model-value="(v: unknown) => emit('update:modelValue', v)"
|
|
9
|
+
@blur="emit('blur')"
|
|
10
|
+
@focus="emit('focus')"
|
|
11
|
+
/>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import FlyBoolean from '../boolean/FlyBoolean.vue'
|
|
17
|
+
import FlyDateTime from '../date-time/FlyDateTime.vue'
|
|
18
|
+
import type {
|
|
19
|
+
T_DynamicInputComponent,
|
|
20
|
+
T_InputRendererBase,
|
|
21
|
+
T_InputTypes
|
|
22
|
+
} from '../input-renderer.types'
|
|
23
|
+
import FlyNumber from '../number/FlyNumber.vue'
|
|
24
|
+
import FlySelect from '../select/FlySelect.vue'
|
|
25
|
+
import FlyText from '../text/FlyText.vue'
|
|
26
|
+
import FlyValueUnit from '../value-unit/FlyValueUnit.vue'
|
|
27
|
+
|
|
28
|
+
const emit = defineEmits<{
|
|
29
|
+
(e: 'update:modelValue', v: unknown): void
|
|
30
|
+
(e: 'change', v: unknown): void
|
|
31
|
+
(e: 'blur'): void
|
|
32
|
+
(e: 'focus'): void
|
|
33
|
+
}>()
|
|
34
|
+
|
|
35
|
+
defineProps<{
|
|
36
|
+
modelValue: unknown
|
|
37
|
+
input: T_InputRendererBase
|
|
38
|
+
}>()
|
|
39
|
+
|
|
40
|
+
const map: Record<T_InputTypes, T_DynamicInputComponent> = {
|
|
41
|
+
text: FlyText,
|
|
42
|
+
textarea: FlyText,
|
|
43
|
+
number: FlyNumber,
|
|
44
|
+
valueUnit: FlyValueUnit,
|
|
45
|
+
select: FlySelect,
|
|
46
|
+
boolean: FlyBoolean,
|
|
47
|
+
dateTime: FlyDateTime
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Component } from 'vue'
|
|
2
|
+
|
|
3
|
+
import type { FormItemRule } from 'element-plus'
|
|
4
|
+
|
|
5
|
+
import type { T_InputBoolean, T_InputBooleanBase } from './boolean/FlyBoolean.types'
|
|
6
|
+
import type { T_InputDateTime, T_InputDateTimeBase } from './date-time/FlyDateTime.types'
|
|
7
|
+
import type { T_InputNumber, T_InputNumberBase } from './number/FlyNumber.types'
|
|
8
|
+
import type { T_InputSelect, T_InputSelectBase } from './select/FlySelect.types'
|
|
9
|
+
import type { T_InputText, T_InputTextBase } from './text/FlyText.types'
|
|
10
|
+
import type { T_InputValueUnit, T_InputValueUnitBase } from './value-unit/FlyValueUnit.types'
|
|
11
|
+
|
|
12
|
+
export type T_DynamicInputPropsBase = {
|
|
13
|
+
key: string
|
|
14
|
+
prop?: string // for form validation. falls back to key
|
|
15
|
+
label: string
|
|
16
|
+
tooltip?: string
|
|
17
|
+
columnSpan?: number
|
|
18
|
+
validations?: FormItemRule[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type T_InputRendererBase = T_DynamicInputPropsBase & T_SupportedInputTypeBase
|
|
22
|
+
|
|
23
|
+
export type T_SupportedInputTypeBase =
|
|
24
|
+
| T_InputTextBase
|
|
25
|
+
| T_InputBooleanBase
|
|
26
|
+
| T_InputDateTimeBase
|
|
27
|
+
| T_InputNumberBase
|
|
28
|
+
| T_InputSelectBase
|
|
29
|
+
| T_InputValueUnitBase
|
|
30
|
+
|
|
31
|
+
export type T_SupportedInputType =
|
|
32
|
+
| T_InputText
|
|
33
|
+
| T_InputNumber
|
|
34
|
+
| T_InputValueUnit
|
|
35
|
+
| T_InputSelect
|
|
36
|
+
| T_InputBoolean
|
|
37
|
+
| T_InputDateTime
|
|
38
|
+
|
|
39
|
+
export type T_InputTypes = T_SupportedInputTypeBase['type']
|
|
40
|
+
|
|
41
|
+
export type T_DynamicInputComponent = Component<{
|
|
42
|
+
modelValue?: unknown
|
|
43
|
+
input?: T_SupportedInputType
|
|
44
|
+
}>
|
|
45
|
+
|
|
46
|
+
export type T_FormSchemaRendererConfig = {
|
|
47
|
+
inputs: T_InputRendererBase[]
|
|
48
|
+
baseForm: { [K: string]: unknown }
|
|
49
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isNil } from 'lodash'
|
|
2
|
+
|
|
3
|
+
import type { T_InputTypes } from './input-renderer.types'
|
|
4
|
+
|
|
5
|
+
export function getInputDisplayValue(v: unknown, inputType: T_InputTypes) {
|
|
6
|
+
switch (inputType) {
|
|
7
|
+
case 'number':
|
|
8
|
+
if (v === null || v === undefined) return ''
|
|
9
|
+
return String(v)
|
|
10
|
+
|
|
11
|
+
case 'text':
|
|
12
|
+
default:
|
|
13
|
+
if (isNil(v)) {
|
|
14
|
+
return ''
|
|
15
|
+
}
|
|
16
|
+
return typeof v === 'string' ? v : String(v)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@use 'element-plus/theme-chalk/src/input.scss';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type T_InputTextValues = string | number | undefined
|
|
2
|
+
|
|
3
|
+
export type T_InputNumberBase = T_InputNumber & {
|
|
4
|
+
type: 'number'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type T_InputNumber = {
|
|
8
|
+
placeholder?: string
|
|
9
|
+
/**
|
|
10
|
+
* Attrs are passed directly to the input element as props
|
|
11
|
+
*/
|
|
12
|
+
attrs?: { [K: string]: unknown }
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-input
|
|
3
|
+
v-model.number="inputProxy"
|
|
4
|
+
style="width: 100%"
|
|
5
|
+
type="number"
|
|
6
|
+
v-bind="input?.attrs"
|
|
7
|
+
:placeholder="input?.placeholder"
|
|
8
|
+
@change="(val) => emit('change', displayToNumber(val))"
|
|
9
|
+
@blur="() => emit('blur')"
|
|
10
|
+
@focus="() => emit('focus')"
|
|
11
|
+
>
|
|
12
|
+
</el-input>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { computed } from 'vue'
|
|
17
|
+
|
|
18
|
+
import { ElInput } from 'element-plus'
|
|
19
|
+
|
|
20
|
+
import { getInputDisplayValue } from '../input-renderer.utils'
|
|
21
|
+
|
|
22
|
+
import './FlyNumber.scss'
|
|
23
|
+
import type { T_InputNumber, T_InputTextValues } from './FlyNumber.types'
|
|
24
|
+
import { displayToNumber } from './FlyNumber.utils'
|
|
25
|
+
|
|
26
|
+
const emit = defineEmits<{
|
|
27
|
+
(e: 'update:modelValue', v: T_InputTextValues): void
|
|
28
|
+
(e: 'change', v: T_InputTextValues): void
|
|
29
|
+
(e: 'blur'): void
|
|
30
|
+
(e: 'focus'): void
|
|
31
|
+
}>()
|
|
32
|
+
|
|
33
|
+
const props = defineProps<{
|
|
34
|
+
modelValue?: unknown
|
|
35
|
+
input?: T_InputNumber
|
|
36
|
+
}>()
|
|
37
|
+
|
|
38
|
+
const inputProxy = computed({
|
|
39
|
+
get: () => {
|
|
40
|
+
return getInputDisplayValue(props.modelValue, 'number')
|
|
41
|
+
},
|
|
42
|
+
set: (v) => {
|
|
43
|
+
const parsed = displayToNumber(v)
|
|
44
|
+
emit('update:modelValue', parsed)
|
|
45
|
+
emit('change', parsed)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { T_FormSchemaLookupData, T_InputSchema } from '../form-schema.types'
|
|
2
|
+
|
|
3
|
+
export type T_TenantRegionalFormSection = {
|
|
4
|
+
key: string
|
|
5
|
+
fields: T_InputSchema[]
|
|
6
|
+
title: string
|
|
7
|
+
description?: string
|
|
8
|
+
lookupData?: T_FormSchemaLookupData
|
|
9
|
+
modelValue?: Record<string, unknown>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type T_TenantRegionalFormProps = {
|
|
13
|
+
mainFormTitle: string
|
|
14
|
+
sections?: T_TenantRegionalFormSection[]
|
|
15
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="fly-regional-tenant-form-renderer">
|
|
3
|
+
<el-collapse v-if="sections?.length" v-model="activeNames" accordion>
|
|
4
|
+
<el-collapse-item :name="E_CollapsibleSections.mainForm">
|
|
5
|
+
<template #title>
|
|
6
|
+
<FlyCollapseTitleRenderer :title="mainFormTitle" />
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<div style="padding: 1rem">
|
|
10
|
+
<slot></slot>
|
|
11
|
+
</div>
|
|
12
|
+
</el-collapse-item>
|
|
13
|
+
|
|
14
|
+
<template v-for="section in sections">
|
|
15
|
+
<el-collapse-item v-if="section.fields?.length" :key="section.key" :name="section.key">
|
|
16
|
+
<template #title>
|
|
17
|
+
<FlyCollapseTitleRenderer :title="section.title" />
|
|
18
|
+
</template>
|
|
19
|
+
<div style="padding: 1rem">
|
|
20
|
+
<div v-if="section.description" style="margin-bottom: 1.25rem">
|
|
21
|
+
<p style="font-size: 0.875; line-height: 1.25rem">
|
|
22
|
+
{{ t(section.description) }}
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<FlyFormSchemaRenderer
|
|
27
|
+
:ref="(el) => setFormRef(el, section.key)"
|
|
28
|
+
v-model="section.modelValue"
|
|
29
|
+
:lookup-data="section.lookupData"
|
|
30
|
+
:form-config="section.fields"
|
|
31
|
+
:column-span="6"
|
|
32
|
+
/>
|
|
33
|
+
</div>
|
|
34
|
+
</el-collapse-item>
|
|
35
|
+
</template>
|
|
36
|
+
</el-collapse>
|
|
37
|
+
|
|
38
|
+
<div v-else>
|
|
39
|
+
<slot></slot>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script setup lang="ts">
|
|
45
|
+
import { type ComponentPublicInstance, reactive, ref } from 'vue'
|
|
46
|
+
|
|
47
|
+
import { ElCollapse, ElCollapseItem } from 'element-plus'
|
|
48
|
+
|
|
49
|
+
import { UseLocaleInjector } from '../../../../composables/UseLocaleInjector'
|
|
50
|
+
import '../../../../styles/element/overrides/collapse.scss'
|
|
51
|
+
import FlyCollapseTitleRenderer from '../../../basic/typography/FlyCollapseTitleRenderer.vue'
|
|
52
|
+
import type { T_FlyFormSchemaRendererInstance } from '../form-schema-renderer/FlyFormSchemaRenderer.types'
|
|
53
|
+
import FlyFormSchemaRenderer from '../form-schema-renderer/FlyFormSchemaRenderer.vue'
|
|
54
|
+
|
|
55
|
+
import type { T_TenantRegionalFormProps } from './FlyRegionalTenantFormRenderer.types'
|
|
56
|
+
|
|
57
|
+
enum E_CollapsibleSections {
|
|
58
|
+
mainForm
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
defineProps<T_TenantRegionalFormProps>()
|
|
62
|
+
|
|
63
|
+
const { t } = UseLocaleInjector()
|
|
64
|
+
|
|
65
|
+
const activeNames = ref<string | number>(E_CollapsibleSections.mainForm)
|
|
66
|
+
const formRefs = reactive<{ [K: string]: T_FlyFormSchemaRendererInstance }>({})
|
|
67
|
+
|
|
68
|
+
function setFormRef(formRef: Element | ComponentPublicInstance | null, key: string) {
|
|
69
|
+
if (formRef) {
|
|
70
|
+
formRefs[key] = formRef as T_FlyFormSchemaRendererInstance
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function validateForms() {
|
|
75
|
+
const keys = Object.keys(formRefs)
|
|
76
|
+
for (let index = 0; index < keys.length; index++) {
|
|
77
|
+
const element = formRefs[keys[index]]
|
|
78
|
+
const hasErrors = await element?.validateForm()
|
|
79
|
+
if (!hasErrors) continue
|
|
80
|
+
return hasErrors
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
defineExpose({
|
|
87
|
+
validateForms
|
|
88
|
+
})
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<style lang="scss" scoped>
|
|
92
|
+
@use '../../../../styles/element/mixins/collapse.scss' as el-collapse-mixin;
|
|
93
|
+
|
|
94
|
+
.fly-regional-tenant-form-renderer {
|
|
95
|
+
:deep(.el-collapse) {
|
|
96
|
+
@include el-collapse-mixin.el-collapse-operation-style;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@use 'element-plus/theme-chalk/src/select.scss';
|
|
2
|
+
@use 'element-plus/theme-chalk/src/option.scss';
|
|
3
|
+
|
|
4
|
+
@use 'element-plus/theme-chalk/src/input.scss';
|
|
5
|
+
@use 'element-plus/theme-chalk/src/tag.scss';
|
|
6
|
+
|
|
7
|
+
@use 'element-plus/theme-chalk/src/popper.scss';
|
|
8
|
+
@use 'element-plus/theme-chalk/src/scrollbar.scss';
|
|
9
|
+
@use 'element-plus/theme-chalk/src/icon.scss';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type T_InputSelectValue = string | number | (string | number)[] | undefined
|
|
2
|
+
|
|
3
|
+
export type T_InputLabelValue = {
|
|
4
|
+
label: string
|
|
5
|
+
value: string | number
|
|
6
|
+
}
|
|
7
|
+
export type T_InputSelectOption = T_InputLabelValue | (number | string)
|
|
8
|
+
export type T_InputSelectOptionList = T_InputSelectOption[] | Record<string, T_InputLabelValue>
|
|
9
|
+
|
|
10
|
+
export type T_InputSelectBase = T_InputSelect & {
|
|
11
|
+
type: 'select'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type T_InputSelect = {
|
|
15
|
+
placeholder?: string
|
|
16
|
+
/**
|
|
17
|
+
* Attrs are passed directly to the input element as props
|
|
18
|
+
*/
|
|
19
|
+
attrs?: {
|
|
20
|
+
multiple?: boolean
|
|
21
|
+
}
|
|
22
|
+
config?: {
|
|
23
|
+
options: T_InputSelectOptionList
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isArray, isObject } from 'lodash'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
T_InputLabelValue,
|
|
5
|
+
T_InputSelectOption,
|
|
6
|
+
T_InputSelectOptionList
|
|
7
|
+
} from './FlySelect.types'
|
|
8
|
+
|
|
9
|
+
export function normalizeSelectOptionsToDict(
|
|
10
|
+
options: T_InputSelectOptionList
|
|
11
|
+
): Record<string, T_InputLabelValue> {
|
|
12
|
+
// already a dict: Record<string, {label,value}>
|
|
13
|
+
if (!isArray(options)) {
|
|
14
|
+
const out: Record<string, T_InputLabelValue> = {}
|
|
15
|
+
Object.keys(options).forEach((k) => {
|
|
16
|
+
const item = options[k]
|
|
17
|
+
out[String(item.value)] = item
|
|
18
|
+
})
|
|
19
|
+
return out
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// array: (string|number) OR {label,value}
|
|
23
|
+
const out: Record<string, T_InputLabelValue> = {}
|
|
24
|
+
options.forEach((opt: T_InputSelectOption) => {
|
|
25
|
+
if (isObject(opt)) {
|
|
26
|
+
const lv = opt as T_InputLabelValue
|
|
27
|
+
out[String(lv.value)] = lv
|
|
28
|
+
} else {
|
|
29
|
+
// primitive option => label=value
|
|
30
|
+
out[String(opt)] = {
|
|
31
|
+
label: String(opt),
|
|
32
|
+
value: opt
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
return out
|
|
37
|
+
}
|