Skip to content

Commit

Permalink
feat(plugin-form): adaption of redis config in all plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
TT1228 committed Dec 25, 2024
1 parent 4173bb1 commit e177ac7
Show file tree
Hide file tree
Showing 13 changed files with 580 additions and 12 deletions.
29 changes: 26 additions & 3 deletions packages/core/forms/src/components/FormGenerator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,19 @@
v-for="field in fields"
:key="field.model"
>
<form-redis
v-if="field.model === 'redis_partial'"
:errors="errors"
:field="field"
:model="model"
:options="options"
:tag="tag"
:vfg="vfg"
@model-updated="onModelUpdated"
@validated="onFieldValidated"
/>
<form-group
v-if="fieldVisible(field)"
v-else-if="fieldVisible(field)"
ref="children"
:errors="errors"
:field="field"
Expand Down Expand Up @@ -93,8 +104,19 @@
v-for="field in group.collapsible.nestedCollapsible.fields"
:key="field.model"
>
<form-redis
v-if="field.model === 'redis_partial'"
:errors="errors"
:field="field"
:model="model"
:options="options"
:tag="tag"
:vfg="vfg"
@model-updated="onModelUpdated"
@validated="onFieldValidated"
/>
<form-group
v-if="fieldVisible(field)"
v-else-if="fieldVisible(field)"
ref="children"
:errors="errors"
:field="field"
Expand Down Expand Up @@ -159,11 +181,12 @@ import isNil from 'lodash-es/isNil'
import { ref } from 'vue'
import { AUTOFILL_SLOT, AUTOFILL_SLOT_NAME } from '../const'
import formGroup from './FormGroup.vue'
import formRedis from './FormRedis.vue'
import formMixin from './FormMixin.vue'
export default {
name: 'FormGenerator',
components: { formGroup },
components: { formGroup, formRedis },
mixins: [formMixin],
inject: {
Expand Down
275 changes: 275 additions & 0 deletions packages/core/forms/src/components/FormRedis.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
<template>
<KCard
class="redis-config-card"
:title="t('redis.title')"
>
<div class="redis-config-radio-group">
<KRadio
v-model="usePartial"
card
card-orientation="horizontal"
data-testid="shared-redis-config"
:description="t('redis.shared_configuration.description')"
:label="t('redis.shared_configuration.label')"
:selected-value="true"
>
<KBadge appearance="success">
Recommended
</KBadge>
</KRadio>
<KRadio
v-model="usePartial"
card
card-orientation="horizontal"
:description="t('redis.dedicated_configuration.description')"
:label="t('redis.dedicated_configuration.label')"
:selected-value="false"
/>
</div>
<div
v-if="usePartial"
class="shared-redis-config"
>
<h3>{{ t("redis.shared_configuration.title") }}</h3>
<KSelect
data-testid="redis-config-select"
:items="availableRedisConfigs"
:loading="loadingRedisConfigs"
:placeholder="t('redis.shared_configuration.selector.placeholder')"
@change="redisConfigSelected"
@query-change="debouncedRedisConfigsQuery"
>
<template #empty>
<div class="empty-redis-config">
{{ t('redis.shared_configuration.empty_state') }}
</div>
</template>
<template #dropdown-footer-text>
<div
class="new-redis-config-area"
@click="newRedisConfigurationModal = true"
>
<AddIcon :size="KUI_ICON_SIZE_20" />
<span>{{ t('redis.shared_configuration.create_new_configuration') }}</span>
</div>
</template>
</KSelect>
<RedisConfigCard
v-if="selectedRedisConfig"
:config-fields="selectedRedisConfig"
:plugin-redis-fields="field.fields"
/>
</div>
<div
v-else
class="shared-redis-config"
>
<h3>{{ t('redis.dedicated_configuration.title') }}</h3>
<component
:is="tag"
>
<template
v-for="field in field.fields"
:key="field.model"
>
<form-group
v-if="fieldVisible(field)"
ref="children"
:errors="errors"
:field="field"
:model="model"
:options="options"
:vfg="vfg"
@model-updated="onModelUpdated"
@refresh-model="onRefreshModel"
@validated="onFieldValidated"
/>
</template>
</component>
</div>
</KCard>
</template>

<script setup lang="ts">
import {
useAxios,
useDebouncedFilter,
type KongManagerBaseFormConfig,
type KongManagerBaseTableConfig,
type KonnectBaseFormConfig,
type KonnectBaseTableConfig,
} from '@kong-ui-public/entities-shared'
import type { SelectItem } from '@kong/kongponents'
import { AddIcon } from '@kong/icons'
import { KUI_ICON_SIZE_20 } from '@kong/design-tokens'
import type { PropType } from 'vue'
import { computed, onBeforeMount, ref, inject } from 'vue'
import formGroup from './FormGroup.vue'
import RedisConfigCard from './RedisConfigCard.vue'
import isFunction from 'lodash-es/isFunction'
import isNil from 'lodash-es/isNil'
import { createI18n } from '@kong-ui-public/i18n'
import english from '../locales/en.json'
import { FORMS_CONFIG } from '../const'
const formConfig : KonnectBaseFormConfig | KongManagerBaseFormConfig | KonnectBaseTableConfig | KongManagerBaseTableConfig | undefined = inject(FORMS_CONFIG)
const endpoints = {
konnect: '/v2/control-planes/{controlPlaneId}/core-entities/partials',
kongManager: '/{workspace}/partials',
}
const props = defineProps({
config: {
type: Object as PropType<any>,
required: true,
validator: (): boolean => {
return true
},
},
usePartial: {
type: Boolean,
default: false,
},
tag: {
type: String,
default: 'fieldset',
validator: function(value: string): boolean {
return value.length > 0
},
},
model: {
type: Object,
default: () => undefined,
},
options: {
type: Object,
required: true,
},
field: {
type: Object,
required: true,
},
vfg: {
type: Object,
required: true,
},
errors: {
type: Array,
default() {
return []
},
},
})
const emits = defineEmits<{
(e: 'modelUpdated', payload: any, schema: any): void,
(e: 'refreshModel'): void,
(e: 'validated', res: boolean, errors: any[], field: any): void,
}>()
const { t } = createI18n<typeof english>('en-us', english)
const usePartial = ref(props.usePartial)
const selectedRedisConfig = ref(null)
const newRedisConfigurationModal = ref(false)
const { axiosInstance } = useAxios(props.config?.axiosRequestConfig)
const fieldVisible = (field: any) => {
if (isFunction(field.visible)) return field.visible.call(this, props.model, field, this)
if (isNil(field.visible)) return true
return field.visible
}
const redisConfigSelected = async (item: SelectItem | null) => {
// selector cleared
if (!item) return
emits('modelUpdated', [{ id: item.value }], 'partials')
//
try {
const configRes = await axiosInstance.get(`/partials/${item.value}`)
configRes.data = {
'database': 0,
'host': null,
'password': '1111',
'port': 637,
'server_name': null,
'ssl': false,
'ssl_verify': false,
'timeout': 2000,
'username': null,
}
selectedRedisConfig.value = configRes.data
} catch (error) {
console.error(error)
}
}
const {
debouncedQueryChange: debouncedRedisConfigsQuery,
loading: loadingRedisConfigs,
// error: redisConfigsFetchError,
loadItems: loadConfigs,
results: redisConfigsResults,
} = useDebouncedFilter(formConfig!, endpoints[formConfig!.app], undefined, {
fetchedItemsKey: 'data',
searchKeys: ['id', 'name'],
})
const availableRedisConfigs = computed((): SelectItem[] => redisConfigsResults.value?.map(el => ({ label: el.id, name: el.name, value: el.id })))
const onModelUpdated = (model: any, schema: any) => {
emits('modelUpdated', model, schema)
}
const onRefreshModel = () => {
// This is for updating a deeply nested array element
// See `modelUpdated` in `FieldArray.vue`
emits('refreshModel')
}
// Child field executed validation
const onFieldValidated = (res: boolean, errors: any[], field: any) => {
emits('validated', res, errors, field)
}
// fetch available redis configs under the control plane
onBeforeMount(async () => {
await loadConfigs()
})
</script>

<style lang="scss">
.redis-config-card {
margin-bottom: $kui-space-60;
.empty-redis-config {
color: $kui-color-text-neutral;
}
.new-redis-config-area {
align-items: center;
color: $kui-color-text-primary;
cursor: pointer;
display: flex;
gap: $kui-space-10;
pointer-events: auto;
}
:deep(.form-group:last-child) {
margin-bottom: 0;
}
}
.redis-config-title {
margin-block-start: 0;
}
.redis-config-radio-group {
display: flex;
gap: $kui-space-40;
margin-bottom: $kui-space-40;
}
</style>
Loading

0 comments on commit e177ac7

Please sign in to comment.