Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clusterclass variables #16

Merged
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0c2ae5c
enums
mantis-toboggan-md Dec 11, 2023
89782ce
required validation
mantis-toboggan-md Dec 12, 2023
850caa2
style
mantis-toboggan-md Dec 13, 2023
7a1106b
more validators
mantis-toboggan-md Dec 13, 2023
c19c624
fix length validators
mantis-toboggan-md Dec 13, 2023
51566eb
remove test page
mantis-toboggan-md Dec 13, 2023
f07b726
jsdoc openapiv3schema validator function
mantis-toboggan-md Dec 13, 2023
eabe146
fix variable widths and new rows
mantis-toboggan-md Dec 18, 2023
da8dac3
refactor error handling
mantis-toboggan-md Dec 18, 2023
1423371
remove test file
mantis-toboggan-md Dec 18, 2023
ae0d883
re-set variables when clusterclass changes
mantis-toboggan-md Dec 20, 2023
c069fb2
fix spacer element visibility when cluster class changes
mantis-toboggan-md Dec 20, 2023
f74e868
update required validator to account for a required boolean
mantis-toboggan-md Dec 20, 2023
b30c156
add machine-scoped ccvariables
mantis-toboggan-md Dec 22, 2023
dff4855
exclude patches using builtin vars
mantis-toboggan-md Dec 22, 2023
f6469e8
update list component validation, required validator
mantis-toboggan-md Dec 22, 2023
4ffe731
add string format validation
mantis-toboggan-md Jan 3, 2024
8fba487
cleanup following review
mantis-toboggan-md Jan 3, 2024
18d82ed
fix component imports
mantis-toboggan-md Jan 3, 2024
da0982a
fix ts warnings
mantis-toboggan-md Jan 3, 2024
dceb67d
typescript fixes 2 electric bugaloo
mantis-toboggan-md Jan 3, 2024
30c7bec
fix vscode settings after rebase
mantis-toboggan-md Jan 11, 2024
c8bfd1e
updates following review
mantis-toboggan-md Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions pkg/capi/components/CCVariables/Variable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<script lang="ts">
import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import LabeledInput from '@components/Form/LabeledInput/LabeledInput.vue';
import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
import KeyValue from '@shell/components/form/KeyValue.vue';
import ArrayList from '@shell/components/form/ArrayList.vue';
import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
import { Validator } from '@shell/utils/validators/formRules';

import { mapGetters } from 'vuex';
import { Translation } from '@rancher/shell/types/t';
import type { ClusterClassVariable } from '../../types/clusterClass';
import { isDefined, openAPIV3SchemaValidators } from '../../util/validators';
export default defineComponent({
name: 'CCVariable',

props: {
variable: {
type: Object as PropType<ClusterClassVariable>,
required: true
},

value: {
type: [String, Object, Boolean, Array, Number],
default: () => null
},

validateRequired: {
type: Boolean,
default: true
}
},

watch: {
isValid(neu) {
this.$emit('validation-passed', neu);
}
},

created() {
if (!this.isValid) {
this.$emit('validation-passed', false);
}
},

computed: {
...mapGetters({ t: 'i18n/t' }),
componentForType() {
const { type } = this.schema;
let out = null;

if (this.variableOptions) {
out = { component: LabeledSelect, name: 'text-var' };
} else {
switch (type) {
case 'object':
out = { component: KeyValue, name: 'keyvalue-var' };
break;
case 'array':
out = { component: ArrayList, name: 'arraylist-var' };
break;
case 'string':
out = { component: LabeledInput, name: 'text-var' };
break;
case 'integer':
out = { component: LabeledInput, name: 'text-var' };

break;
case 'number':
out = { component: LabeledInput, name: 'text-var' };

break;
case 'boolean':
out = { component: Checkbox, name: 'checkbox-var' };

break;
default:
break;
}
}

return out;
},

schema() {
return this.variable?.schema?.openAPIV3Schema;
},

// options may be arrays or objects - stringify them to display in labeledselect
variableOptions() {
const opts = this.schema?.enum;

if (!opts || !opts.length) {
return null;
}

return opts.map((opt: any) => {
return typeof opt === 'object' ? JSON.stringify(opt) : opt;
});
},

validationRules() {
const t = this.t as Translation;
const out = openAPIV3SchemaValidators(t, { key: this.variable.name }, this.schema);

const required = this.variable?.required;

if (required && this.validateRequired) {
out.push(val => !isDefined(val) ? t('validation.required', { key: this.variable.name }) : undefined);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type is missing

}

return out;
},

isValid() {
return !this.validationErrors.length;
},

validationErrors() {
return this.validationRules.reduce((errs: string[], rule: Validator) => {
const message = rule(this.value);

if (message) {
errs.push(message);
}

return errs;
}, []);
},

listComponent() {
return this.componentForType?.name === 'arraylist-var' || this.componentForType?.name === 'keyvalue-var';
}
},

methods: {
setValue(e: any) {
let out = e;

const { type } = this.schema;

if (type === 'object') {
try {
out = JSON.parse(e);
} catch {}
}
this.$emit('input', out);
}
},
});
</script>

<template>
<div v-if="componentForType" :class="{'wider': listComponent, 'align-center': componentForType?.name==='checkbox-var', [`${componentForType.name}`]: true}">
<component
:is="componentForType.component"
v-if="componentForType"
:value="value"
:label="variable.name"
:placeholder="schema.example"
:tooltip="schema.description"
:required="variable.required && validateRequired"
:title="variable.name"
:options="variableOptions"
:rules="!listComponent ? validationRules : []"
:type="schema.type === 'number' || schema.type === 'integer' ? 'number' : 'text'"
@input="setValue"
>
<template #title>
<div class="input-label">
<span>{{ variable.name }}
<i v-if="schema.description" v-clean-tooltip="schema.description" class="icon icon-sm icon-info" />
<i v-if="!isValid" v-clean-tooltip="validationErrors.join(' ')" class="icon icon-warning" />
</span>
</div>
</template>
</component>
<div class="flexbox-newline" />
</div>
</template>
<style lang="scss" scoped>
.align-center {
align-self: 'center'
}
.input-label{
color: var(--input-label);
margin-bottom: 5px;
display: block;
width:100%;
.icon-warning{
color: var(--error)
}
}
</style>
Loading