<template> <div class="filters__condition-item" :class="{ 'filters__condition-item--loading': filter._?.loading }" > <div class="filters__field"> <Dropdown :value="filter.field" :disabled="disableFilter" :fixed-items="true" small @input="$emit('updateFilter', { field: $event })" > <DropdownItem v-for="field in fields" :key="'field-' + field.id" :name="field.name" :value="field.id" :disabled="!hasCompatibleFilterTypes(field, filterTypes)" ></DropdownItem> </Dropdown> </div> <div class="filters__type"> <Dropdown :disabled="disableFilter" :value="filter.type" :fixed-items="true" small @input="$emit('updateFilter', { type: $event })" > <DropdownItem v-for="fType in allowedFilters(filterTypes, fields, filter.field)" :key="fType.type" :name="fType.getName()" :value="fType.type" ></DropdownItem> </Dropdown> </div> <div class="filters__value" :class="{ 'filters__value--with-after-input': hasAfterValueInputContent, }" > <slot name="filterInputComponent" :slot-props="{ filter: filter, field: getField(filter.field), filterType: getFilterType(filter.type), }" > <component :is="getInputComponent(filter.type, filter.field)" v-if="fieldCanBeFiltered(fields, filter)" ref="filter-value" :filter="filter" :view="view" :is-public-view="isPublicView" :fields="fields" :disabled="disableFilter" :read-only="readOnly" @input="$emit('updateFilter', { value: $event })" /> </slot> <slot name="afterValueInput" :slot-props="{ filter: filter, filterType: getFilterType(filter.type), emitUpdate: emitUpdate, }" ></slot> <i v-if="!fieldIdExists(fields, filter.field)" v-tooltip="$t('viewFilterContext.relatedFieldNotFound')" class="fas fa-exclamation-triangle color-error" ></i> <i v-if="!fieldIsCompatible(filter.type, filter.field)" v-tooltip="$t('viewFilterContext.filterTypeNotFound')" class="fas fa-exclamation-triangle color-error" ></i> </div> <a class="filters__remove" :class="{ 'filters__remove--disabled': disableFilter }" @click="!disableFilter && $emit('deleteFilter', $event)" > <i class="iconoir-bin"></i> </a> </div> </template> <script> import { hasCompatibleFilterTypes } from '@baserow/modules/database/utils/field' import viewFilterTypes from '@baserow/modules/database/mixins/viewFilterTypes' export default { name: 'ViewFieldConditionItem', mixins: [viewFilterTypes], props: { filter: { type: Object, required: true, }, fields: { type: Array, required: true, }, view: { type: Object, required: false, default: () => {}, }, isPublicView: { type: Boolean, required: false, default: false, }, disableFilter: { type: Boolean, default: false, }, readOnly: { type: Boolean, required: true, }, }, computed: { hasAfterValueInputContent() { return !!this.$scopedSlots.afterValueInput }, }, methods: { hasCompatibleFilterTypes, focusValue() { if (this.$refs['filter-value']?.focus !== undefined) { this.$refs['filter-value'].focus() } }, getField(fieldId) { return this.fields.find(({ id }) => id === fieldId) }, getFilterType(type) { return this.$registry.get('viewFilter', type) }, allowedFilters(filterTypes, fields, fieldId) { const field = this.getField(fieldId) return Object.values(filterTypes).filter((filterType) => { return field !== undefined && filterType.fieldIsCompatible(field) }) }, getInputComponent(type, fieldId) { const field = this.getField(fieldId) return this.getFilterType(type).getInputComponent(field) }, fieldCanBeFiltered(fields, filter) { return ( this.fieldIdExists(fields, filter.field) && this.fieldIsCompatible(filter.type, filter.field) ) }, fieldIdExists(fields, fieldId) { return fields.findIndex((field) => field.id === fieldId) !== -1 }, fieldIsCompatible(filterType, fieldId) { const field = this.getField(fieldId) if (!(filterType in this.filterTypes)) { return false } return this.filterTypes[filterType].fieldIsCompatible(field) }, emitUpdate(changes) { this.$emit('updateFilter', changes) }, }, } </script>