Skip to content

Commit

Permalink
vue: Allow configuration of any/none of conditions
Browse files Browse the repository at this point in the history
Still missing:
* Styling/margin issue fix
* Switch buttons order of condition group dropdown
* Readonly mode
* Condition group dropdown filtering

CMK-19266

Change-Id: Ia3e297ffa4063c2b520cccbda3aacf7e6103917a
  • Loading branch information
cellador committed Nov 14, 2024
1 parent 842ef2a commit d901721
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function getStyle(index: number, length: number) {
<template v-else>
<tr>
<td v-for="(dataIndex, listIndex) in localOrder" :key="dataIndex">
<CmkListItem :button-padding="'4px'" :remove-element="() => removeElement(dataIndex)">
<CmkListItem :button-padding="'8px'" :remove-element="() => removeElement(dataIndex)">
<slot name="item-props" v-bind="{ index: dataIndex, ...getItemProps(dataIndex) }" />
<CmkSpace direction="horizontal" />
<CmkSpace v-if="listIndex !== localOrder.length - 1" direction="horizontal" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import CmkButton from '@/components/CmkButton.vue'
import CmkIcon from '@/components/CmkIcon.vue'
import CmkSpace from '@/components/CmkSpace.vue'

const props = defineProps<{
const { buttonPadding = '16px', ...props } = defineProps<{
removeElement: () => void
style?: 'first' | 'last' | null
buttonPadding?: '16px' | '8px'
draggable?: {
dragStart: (event: DragEvent) => void
dragEnd: (event: DragEvent) => void
Expand Down Expand Up @@ -70,7 +71,7 @@ const props = defineProps<{

.cmk_list__content {
padding-top: calc(var(--spacing) - var(--button-padding-top));
padding-left: 16px;
padding-left: v-bind(buttonPadding);
}

.cmk_list__buttons.first {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ This file is part of Checkmk (https://checkmk.com). It is subject to the terms a
conditions defined in the file COPYING, which is part of this source code package.
-->
<script setup lang="ts">
import CmkList from '@/components/CmkList'
import CmkSpace from '@/components/CmkSpace.vue'
import DropDown from '@/components/DropDown.vue'
import {
type ConditionChoicesValue,
type ConditionGroup
type ConditionGroup,
type Condition
} from '@/form/components/vue_formspec_components'
import { immediateWatch } from '@/lib/watch'
import { computed, ref, watch } from 'vue'
Expand All @@ -21,6 +23,7 @@ const props = defineProps<{
ne: string
or: string
nor: string
add_condition_label: string
}
}>()

Expand All @@ -33,13 +36,26 @@ type Operator = KeysOfUnion<ConditionChoicesValue['value']>
const operatorIsMultiSelect = (operator: Operator) => operator === 'or' || operator === 'nor'

const selectedOperator = ref<Operator>('eq')
const selectedValue = ref<string>(props.group.conditions[0]!.name)
const selectedSingleValue = ref<string>(props.group.conditions[0]!.name)
const selectedMultiValue = ref<string[]>([props.group.conditions[0]!.name])

const remainingConditions = ref<Condition[]>(props.group.conditions)

immediateWatch(
() => props.data,
(data) => {
selectedOperator.value = Object.keys(data.value)[0] as Operator
selectedValue.value = Object.values(data.value)[0]
const operator = Object.keys(data.value)[0] as Operator
selectedOperator.value = operator
if (operatorIsMultiSelect(operator)) {
selectedMultiValue.value = Object.values(data.value)[0] as string[]
selectedSingleValue.value = props.group.conditions[0]!.name
} else {
selectedSingleValue.value = Object.values(data.value)[0] as string
selectedMultiValue.value = [props.group.conditions[0]!.name]
}
remainingConditions.value = props.group.conditions.filter(
({ name }) => !selectedMultiValue.value.includes(name)
)
}
)

Expand All @@ -58,7 +74,7 @@ const operatorChoices = computed<{ name: Operator; title: string }[]>(() => {
]
})

const valueChoices = computed(() => {
const allValueChoices = computed(() => {
return props.group.conditions.map((condition) => {
return { name: condition.name, title: condition.title }
})
Expand All @@ -68,27 +84,84 @@ const emit = defineEmits<{
update: [value: ConditionChoicesValue]
}>()

watch([selectedOperator, selectedValue], ([operator, _value]) => {
if (operator === undefined || _value === undefined) {
return
}
function updateValue(operator: Operator, value: string | string[] | null) {
emit('update', {
group_name: props.data.group_name,
value: {
[operator]: operatorIsMultiSelect(operator) ? [_value] : _value
[operator]: value
} as { eq: string } | { ne: string } | { or: string[] } | { nor: string[] }
})
}

function addMultiValue() {
selectedMultiValue.value.push(remainingConditions.value[0]!.name)
updateValue(selectedOperator.value, selectedMultiValue.value)
}

function deleteMultiValue(index: number) {
selectedMultiValue.value.splice(index, 1)
updateValue(selectedOperator.value, selectedMultiValue.value)
}

function updateMultiValue(index: number, value: string) {
selectedMultiValue.value[index] = value
updateValue(selectedOperator.value, selectedMultiValue.value)
}

watch(selectedOperator, (operator) => {
if (operatorIsMultiSelect(operator)) {
if (selectedMultiValue.value.some((v) => v === null)) {
return
}
updateValue(operator, selectedMultiValue.value as string[])
} else {
updateValue(operator, selectedSingleValue.value)
}
})
</script>

<template>
{{ group.title }}
<DropDown v-model:selected-option="selectedOperator" :options="operatorChoices" />
<CmkSpace :size="'small'" />
<template v-if="valueChoices.length === 1">
{{ valueChoices[0]!.title }}
<template v-if="allValueChoices.length === 1">
{{ allValueChoices[0]!.title }}
</template>
<template v-else-if="operatorIsMultiSelect(selectedOperator)">
<CmkList
:items-props="{ selectedValue: selectedMultiValue }"
:on-add="addMultiValue"
:on-delete="deleteMultiValue"
:i18n="{ addElementLabel: props.i18n.add_condition_label }"
:orientation="'horizontal'"
:show-add-button="remainingConditions.length > 0"
>
<template #item-props="{ index, selectedValue }">
<DropDown
:selected-option="selectedValue"
:disabled="remainingConditions.length === 0"
:options="[
...props.group.conditions
.filter(({ name }) => name === selectedValue)
.map((condition) => ({
name: condition.name,
title: condition.title
})),
...remainingConditions.map((condition) => ({
name: condition.name,
title: condition.title
}))
]"
@update:selected-option="(value) => updateMultiValue(index, value!)"
/>
</template>
</CmkList>
</template>
<template v-else>
<DropDown v-model:selected-option="selectedValue" :options="valueChoices" />
<DropDown
:selected-option="selectedSingleValue"
:options="allValueChoices"
@update:selected-option="(value) => updateValue(selectedOperator, value)"
/>
</template>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ function updateElementData(newValue: typing.ConditionChoicesValue, index: number
eq: props.spec.i18n.eq_operator,
ne: props.spec.i18n.ne_operator,
or: props.spec.i18n.or_operator,
nor: props.spec.i18n.nor_operator
nor: props.spec.i18n.nor_operator,
add_condition_label: props.spec.i18n.add_condition_label
}"
@update="(new_value: typing.ConditionChoicesValue) => updateElementData(new_value, index)"
/>
Expand Down

0 comments on commit d901721

Please sign in to comment.