Add automation - attr change input
This commit is contained in:
parent
40a7681d45
commit
6a5ccf74c3
7 changed files with 211 additions and 96 deletions
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div class="input-container">
|
||||
<input
|
||||
v-model="from"
|
||||
type="text"
|
||||
class="text-input"
|
||||
placeholder="from value (optional)"
|
||||
/>
|
||||
<input
|
||||
v-model="to"
|
||||
type="text"
|
||||
class="text-input"
|
||||
placeholder="to value (optional)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// eslint-disable-next-line vue/require-prop-types
|
||||
props: ['value'],
|
||||
computed: {
|
||||
from: {
|
||||
get() {
|
||||
if (!this.value) return '';
|
||||
return this.value.from;
|
||||
},
|
||||
set(value) {
|
||||
const payload = this.value || {};
|
||||
this.$emit('input', { ...payload, from: value });
|
||||
},
|
||||
},
|
||||
to: {
|
||||
get() {
|
||||
if (!this.value) return '';
|
||||
return this.value.to;
|
||||
},
|
||||
set(value) {
|
||||
const payload = this.value || {};
|
||||
this.$emit('input', { ...payload, to: value });
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.input-container {
|
||||
display: flex;
|
||||
margin-top: var(--space-small);
|
||||
input {
|
||||
flex: 1;
|
||||
margin-right: var(--space-smaller);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,111 +1,125 @@
|
|||
<template>
|
||||
<div class="filters">
|
||||
<div class="filter" :class="{ error: v.values.$dirty && v.values.$error }">
|
||||
<div class="filter-inputs">
|
||||
<select
|
||||
v-if="groupedFilters"
|
||||
v-model="attributeKey"
|
||||
class="filter__question"
|
||||
@change="resetFilter()"
|
||||
>
|
||||
<optgroup
|
||||
v-for="(group, i) in filterGroups"
|
||||
:key="i"
|
||||
:label="group.name"
|
||||
<div class="filter-container">
|
||||
<div class="filter-inputs">
|
||||
<select
|
||||
v-if="groupedFilters"
|
||||
v-model="attributeKey"
|
||||
class="filter__question"
|
||||
@change="resetFilter()"
|
||||
>
|
||||
<optgroup
|
||||
v-for="(group, i) in filterGroups"
|
||||
:key="i"
|
||||
:label="group.name"
|
||||
>
|
||||
<option
|
||||
v-for="attribute in group.attributes"
|
||||
:key="attribute.key"
|
||||
:value="attribute.key"
|
||||
>
|
||||
{{ attribute.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<select
|
||||
v-else
|
||||
v-model="attributeKey"
|
||||
class="filter__question"
|
||||
:class="{ 'filter__question--fill-width': !showUserInput }"
|
||||
@change="resetFilter()"
|
||||
>
|
||||
<option
|
||||
v-for="attribute in group.attributes"
|
||||
v-for="attribute in filterAttributes"
|
||||
:key="attribute.key"
|
||||
:value="attribute.key"
|
||||
:disabled="attribute.disabled"
|
||||
>
|
||||
{{ attribute.name }}
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<select
|
||||
v-else
|
||||
v-model="attributeKey"
|
||||
class="filter__question"
|
||||
@change="resetFilter()"
|
||||
>
|
||||
<option
|
||||
v-for="attribute in filterAttributes"
|
||||
:key="attribute.key"
|
||||
:value="attribute.key"
|
||||
:disabled="attribute.disabled"
|
||||
>
|
||||
{{ attribute.name }}
|
||||
</option>
|
||||
</select>
|
||||
</select>
|
||||
|
||||
<select v-model="filterOperator" class="filter__operator">
|
||||
<option
|
||||
v-for="(operator, o) in operators"
|
||||
:key="o"
|
||||
:value="operator.value"
|
||||
<select
|
||||
v-model="filterOperator"
|
||||
class="filter__operator"
|
||||
:class="{ 'filter__operator--fill-width': !showUserInput }"
|
||||
>
|
||||
{{ $t(`FILTER.OPERATOR_LABELS.${operator.value}`) }}
|
||||
</option>
|
||||
</select>
|
||||
<option
|
||||
v-for="(operator, o) in operators"
|
||||
:key="o"
|
||||
:value="operator.value"
|
||||
>
|
||||
{{ $t(`FILTER.OPERATOR_LABELS.${operator.value}`) }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<div v-if="showUserInput" class="filter__answer--wrap">
|
||||
<div
|
||||
v-if="inputType === 'multi_select'"
|
||||
class="multiselect-wrap--small"
|
||||
>
|
||||
<multiselect
|
||||
v-model="values"
|
||||
track-by="id"
|
||||
label="name"
|
||||
:placeholder="'Select'"
|
||||
:multiple="true"
|
||||
selected-label
|
||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||
deselect-label=""
|
||||
:max-height="160"
|
||||
:options="dropdownValues"
|
||||
:allow-empty="false"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="inputType === 'search_select'"
|
||||
class="multiselect-wrap--small"
|
||||
>
|
||||
<multiselect
|
||||
v-model="values"
|
||||
track-by="id"
|
||||
label="name"
|
||||
:placeholder="'Select'"
|
||||
selected-label
|
||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||
deselect-label=""
|
||||
:max-height="160"
|
||||
:options="dropdownValues"
|
||||
:allow-empty="false"
|
||||
:option-height="104"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="inputType === 'date'" class="multiselect-wrap--small">
|
||||
<div v-if="showUserInput" class="filter__answer--wrap">
|
||||
<div
|
||||
v-if="inputType === 'multi_select'"
|
||||
class="multiselect-wrap--small"
|
||||
>
|
||||
<multiselect
|
||||
v-model="values"
|
||||
track-by="id"
|
||||
label="name"
|
||||
:placeholder="'Select'"
|
||||
:multiple="true"
|
||||
selected-label
|
||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||
deselect-label=""
|
||||
:max-height="160"
|
||||
:options="dropdownValues"
|
||||
:allow-empty="false"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="inputType === 'search_select'"
|
||||
class="multiselect-wrap--small"
|
||||
>
|
||||
<multiselect
|
||||
v-model="values"
|
||||
track-by="id"
|
||||
label="name"
|
||||
:placeholder="'Select'"
|
||||
selected-label
|
||||
:select-label="$t('FORMS.MULTISELECT.ENTER_TO_SELECT')"
|
||||
deselect-label=""
|
||||
:max-height="160"
|
||||
:options="dropdownValues"
|
||||
:allow-empty="false"
|
||||
:option-height="104"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="inputType === 'date'"
|
||||
class="multiselect-wrap--small"
|
||||
>
|
||||
<input
|
||||
v-model="values"
|
||||
type="date"
|
||||
:editable="false"
|
||||
class="answer--text-input datepicker"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
v-else
|
||||
v-model="values"
|
||||
type="date"
|
||||
:editable="false"
|
||||
class="answer--text-input datepicker"
|
||||
type="text"
|
||||
class="answer--text-input"
|
||||
placeholder="Enter value"
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
v-else
|
||||
v-model="values"
|
||||
type="text"
|
||||
class="answer--text-input"
|
||||
placeholder="Enter value"
|
||||
<woot-button
|
||||
icon="dismiss"
|
||||
variant="clear"
|
||||
color-scheme="secondary"
|
||||
@click="removeFilter"
|
||||
/>
|
||||
</div>
|
||||
<woot-button
|
||||
icon="dismiss"
|
||||
variant="clear"
|
||||
color-scheme="secondary"
|
||||
@click="removeFilter"
|
||||
<attribute-change-input
|
||||
v-if="operatorTypeAttrChange"
|
||||
v-model="values"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="v.values.$dirty && v.values.$error" class="filter-error">
|
||||
|
@ -128,7 +142,11 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import attributeChangeInput from './AttributeChangeInput.vue';
|
||||
export default {
|
||||
components: {
|
||||
attributeChangeInput,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
|
@ -178,6 +196,10 @@ export default {
|
|||
type: String,
|
||||
default: '',
|
||||
},
|
||||
operatorTypeAttrChange: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
attributeKey: {
|
||||
|
@ -284,10 +306,16 @@ export default {
|
|||
|
||||
.filter__question {
|
||||
max-width: 30%;
|
||||
&.filter__question--fill-width {
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.filter__operator {
|
||||
max-width: 20%;
|
||||
&.filter__operator--fill-width {
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.filter__answer--wrap {
|
||||
|
|
|
@ -72,8 +72,15 @@ export const getOperatorTypes = key => {
|
|||
date: OPERATOR_TYPES_4,
|
||||
checkbox: OPERATOR_TYPES_1,
|
||||
};
|
||||
|
||||
return operatorMap[key] || OPERATOR_TYPES_1;
|
||||
const attributeChangesOp = {
|
||||
value: 'attribute_changed',
|
||||
label: 'Attribute changed',
|
||||
};
|
||||
const operators = [
|
||||
...(operatorMap[key] || OPERATOR_TYPES_1),
|
||||
attributeChangesOp,
|
||||
];
|
||||
return operators;
|
||||
};
|
||||
|
||||
export const generateCustomAttributeTypes = (customAttributes, type) => {
|
||||
|
|
|
@ -10,6 +10,19 @@ const lowerCaseValues = (operator, values) => {
|
|||
return values;
|
||||
};
|
||||
|
||||
const generateObjectTypeValues = values => {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(values, 'from') &&
|
||||
Object.prototype.hasOwnProperty.call(values, 'to')
|
||||
) {
|
||||
return {
|
||||
from: values.from,
|
||||
to: values.to,
|
||||
};
|
||||
}
|
||||
return values.id;
|
||||
};
|
||||
|
||||
const generatePayload = data => {
|
||||
// Make a copy of data to avoid vue data reactivity issues
|
||||
const filters = JSON.parse(JSON.stringify(data));
|
||||
|
@ -17,7 +30,7 @@ const generatePayload = data => {
|
|||
if (Array.isArray(item.values)) {
|
||||
item.values = item.values.map(val => val.id);
|
||||
} else if (typeof item.values === 'object') {
|
||||
item.values = [item.values.id];
|
||||
item.values = generateObjectTypeValues(item.values);
|
||||
} else if (!item.values) {
|
||||
item.values = [];
|
||||
} else {
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
"is_not_present": "Is not present",
|
||||
"is_greater_than": "Is greater than",
|
||||
"is_less_than": "Is lesser than",
|
||||
"days_before": "Is x days before"
|
||||
"days_before": "Is x days before",
|
||||
"attribute_changed": "Attribute Changed"
|
||||
},
|
||||
"ATTRIBUTE_LABELS": {
|
||||
"TRUE": "True",
|
||||
|
|
|
@ -163,7 +163,11 @@ export default {
|
|||
this.automation.conditions[index].values = '';
|
||||
},
|
||||
showUserInput(type) {
|
||||
return !(type === 'is_present' || type === 'is_not_present');
|
||||
return !(
|
||||
type === 'is_present' ||
|
||||
type === 'is_not_present' ||
|
||||
type === 'attribute_changed'
|
||||
);
|
||||
},
|
||||
showActionInput(action) {
|
||||
if (action === 'send_email_to_team' || action === 'send_message')
|
||||
|
@ -294,5 +298,8 @@ export default {
|
|||
...manifestedCustomAttributes
|
||||
);
|
||||
},
|
||||
isOperatorTypeChange(type) {
|
||||
return type === 'attribute_changed';
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -68,8 +68,11 @@
|
|||
)
|
||||
"
|
||||
:show-query-operator="i !== automation.conditions.length - 1"
|
||||
:custom-attribute-type="
|
||||
getCustomAttributeType(automation.conditions[i].attribute_key)
|
||||
:show-user-input="
|
||||
showUserInput(automation.conditions[i].filter_operator)
|
||||
"
|
||||
:operator-type-attr-change="
|
||||
isOperatorTypeChange(automation.conditions[i].filter_operator)
|
||||
"
|
||||
:v="$v.automation.conditions.$each[i]"
|
||||
@resetFilter="resetFilter(i, automation.conditions[i])"
|
||||
|
|
Loading…
Reference in a new issue