<template> <Context ref="context" class="group-bys" max-height-if-outside-viewport> <div class="group-bys__content"> <div v-if="view.group_bys.length === 0" v-auto-overflow-scroll class="group-bys__none group-bys__none--scrollable" > <div class="group-bys__none-title"> {{ $t('viewGroupByContext.noGroupByTitle') }} </div> <div class="group-bys__none-description"> {{ $t('viewGroupByContext.noGroupByText') }} </div> </div> <div v-if="view.group_bys.length > 0" v-auto-overflow-scroll class="group-bys__items group-bys__items--scrollable" > <div v-for="(groupBy, index) in view.group_bys" :key="groupBy.id" class="group-bys__item" :class="{ 'group-bys__item--loading': groupBy._.loading, }" :set="(field = getField(groupBy.field))" > <a v-if="!disableGroupBy" class="group-bys__remove" @click="deleteGroupBy(groupBy)" > <i class="iconoir-cancel"></i> </a> <div class="group-bys__description"> <template v-if="index === 0">{{ $t('viewGroupByContext.groupBy') }}</template> <template v-if="index > 0">{{ $t('viewGroupByContext.thenBy') }}</template> </div> <div class="group-bys__field"> <Dropdown :value="groupBy.field" :disabled="disableGroupBy" :fixed-items="true" class="dropdown--floating" @input="updateGroupBy(groupBy, { field: $event })" > <DropdownItem v-for="field in fields" :key="'groupBy-field-' + groupBy.id + '-' + field.id" :name="field.name" :value="field.id" :disabled=" groupBy.field !== field.id && !isFieldAvailable(field) " > </DropdownItem> </Dropdown> </div> <div class="group-bys__order" :class="{ 'group-bys__order--disabled': disableGroupBy }" > <a class="group-bys__order-item" :class="{ active: groupBy.order === 'ASC' }" @click="updateGroupBy(groupBy, { order: 'ASC' })" > <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ getGroupByIndicator(field, 1) }}</template> <i v-if="getGroupByIndicator(field, 0) === 'icon'" :class="getGroupByIndicator(field, 1)" ></i> <i class="iconoir-arrow-right"></i> <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ getGroupByIndicator(field, 2) }}</template> <i v-if="getGroupByIndicator(field, 0) === 'icon'" class="fa" :class="getGroupByIndicator(field, 2)" ></i> </a> <a class="group-bys__order-item" :class="{ active: groupBy.order === 'DESC' }" @click="updateGroupBy(groupBy, { order: 'DESC' })" > <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ getGroupByIndicator(field, 2) }}</template> <i v-if="getGroupByIndicator(field, 0) === 'icon'" :class="getGroupByIndicator(field, 2)" ></i> <i class="iconoir-arrow-right"></i> <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ getGroupByIndicator(field, 1) }}</template> <i v-if="getGroupByIndicator(field, 0) === 'icon'" :class="getGroupByIndicator(field, 1)" ></i> </a> </div> </div> </div> <div v-if="view.group_bys.length < availableFieldsLength && !disableGroupBy" class="context__footer" > <ButtonText ref="addDropdownToggle" icon="iconoir-plus" @click="$refs.addDropdown.toggle($refs.addDropdownToggle.$el)" > {{ $t('viewGroupByContext.addGroupBy') }}</ButtonText > <div class="group-bys__add"> <Dropdown ref="addDropdown" :show-input="false" :fixed-items="true" @input="addGroupBy" > <DropdownItem v-for="field in availableFields" :key="field.id" :name="field.name" :value="field.id" :icon="getFieldType(field).iconClass" ></DropdownItem> </Dropdown> </div> </div> </div> </Context> </template> <script> import { notifyIf } from '@baserow/modules/core/utils/error' import context from '@baserow/modules/core/mixins/context' export default { name: 'ViewGroupByContext', mixins: [context], props: { fields: { type: Array, required: true, }, view: { type: Object, required: true, }, readOnly: { type: Boolean, required: true, }, disableGroupBy: { type: Boolean, required: true, }, }, computed: { /** * Calculates the total amount of available fields. */ availableFieldsLength() { return this.fields.filter(this.getCanGroupByInView).length }, availableFields() { return this.fields.filter((f) => this.isFieldAvailable(f)) }, }, methods: { getFieldType(field) { return this.$registry.get('field', field.type) }, getCanGroupByInView(field) { return this.getFieldType(field).getCanGroupByInView(field) }, getField(fieldId) { for (const i in this.fields) { if (this.fields[i].id === fieldId) { return this.fields[i] } } return undefined }, isFieldAvailable(field) { const allFieldIds = this.view.group_bys.map((groupBy) => groupBy.field) return this.getCanGroupByInView(field) && !allFieldIds.includes(field.id) }, async addGroupBy(fieldId) { this.$refs.addDropdown.hide() try { await this.$store.dispatch('view/createGroupBy', { view: this.view, values: { field: fieldId, value: 'ASC', }, readOnly: this.readOnly, }) this.$emit('changed') } catch (error) { notifyIf(error, 'view') } }, async deleteGroupBy(groupBy) { try { await this.$store.dispatch('view/deleteGroupBy', { view: this.view, groupBy, readOnly: this.readOnly, }) this.$emit('changed') } catch (error) { notifyIf(error, 'view') } }, async updateGroupBy(groupBy, values) { if (this.disableGroupBy) { return } try { await this.$store.dispatch('view/updateGroupBy', { groupBy, values, readOnly: this.readOnly, }) this.$emit('changed') } catch (error) { notifyIf(error, 'view') } }, getGroupByIndicator(field, index) { return this.$registry .get('field', field.type) .getGroupByIndicator(field, this.$registry)[index] }, }, } </script>