From 3ed92b260ac3ead67166eda9ff48b9e3753e2e1a Mon Sep 17 00:00:00 2001 From: Petr Stribny <petr@stribny.name> Date: Wed, 19 Feb 2025 04:43:55 +0100 Subject: [PATCH] Add sort configuration for chart widget --- .../data_source/AggregationSortByForm.vue | 123 ++++++++++++++++++ .../GroupedAggregateRowsDataSourceForm.vue | 35 ++++- .../baserow_enterprise/locales/en.json | 6 + 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue new file mode 100644 index 000000000..9434b1a9d --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue @@ -0,0 +1,123 @@ +<template> + <FormSection + :title="$t('aggregationSortByForm.sortByFieldLabel')" + class="margin-bottom-2" + > + <Dropdown + :value="sortByField" + :show-search="true" + fixed-items + class="margin-bottom-1" + :error="v$.sortByField?.$error || false" + @change="sortByFieldChangedByUser($event)" + > + <DropdownItem + :name="$t('aggregationSortByForm.none')" + :value="null" + ></DropdownItem> + <DropdownItem + v-for="field in allowedSortFields" + :key="field.id" + :name="field.name" + :value="field.id" + :icon="fieldIconClass(field)" + > + </DropdownItem> + </Dropdown> + <SegmentControl + :active-index="orderByIndex" + :segments="orderByOptions" + :initial-active-index="orderByIndex" + @update:activeIndex="orderByChangedByUser" + ></SegmentControl> + </FormSection> +</template> + +<script> +import { useVuelidate } from '@vuelidate/core' + +const includesIfSet = (array) => (value) => { + if (value === null || value === undefined) { + return true + } + return array.includes(value) +} + +export default { + name: 'AggregationGroupByForm', + props: { + allowedSortFields: { + type: Array, + required: true, + }, + aggregationSorts: { + type: Array, + required: true, + }, + }, + setup() { + return { v$: useVuelidate({ $lazy: true }) } + }, + data() { + return { + sortByField: null, + orderByIndex: 0, + } + }, + computed: { + orderByOptions() { + return [ + { label: this.$t('aggregationSortByForm.ascending'), value: 'ASC' }, + { label: this.$t('aggregationSortByForm.descending'), value: 'DESC' }, + ] + }, + }, + watch: { + aggregationSorts: { + handler(aggregationSorts) { + if (aggregationSorts.length !== 0) { + this.sortByField = aggregationSorts[0].field + this.orderByIndex = this.orderByOptions.findIndex( + (item) => item.value === aggregationSorts[0].order_by + ) + } + }, + immediate: true, + }, + }, + mounted() { + this.v$.$validate(true) + }, + validations() { + const self = this + return { + sortByField: { + isValidSortFieldId: (value) => { + const ids = self.allowedSortFields.map((item) => item.id) + return includesIfSet(ids)(value) + }, + }, + } + }, + methods: { + sortByFieldChangedByUser(value) { + this.sortByField = value + this.$emit('value-changed', { + field: value, + order_by: this.orderByOptions[this.orderByIndex].value, + }) + }, + orderByChangedByUser(index) { + this.orderByIndex = index + this.$emit('value-changed', { + field: this.sortByField, + order_by: this.orderByOptions[index].value, + }) + }, + fieldIconClass(field) { + const fieldType = this.$registry.get('field', field.type) + return fieldType.iconClass + }, + }, +} +</script> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue index 3567d9f09..47eb4356b 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue @@ -99,6 +99,13 @@ @value-changed="onGroupByUpdated($event)" > </AggregationGroupByForm> + <AggregationSortByForm + v-if="values.table_id && !fieldHasErrors('table_id')" + :aggregation-sorts="values.sortings" + :allowed-sort-fields="allowedSortFields" + @value-changed="onSortByUpdated($event)" + > + </AggregationSortByForm> </form> </template> @@ -108,6 +115,7 @@ import form from '@baserow/modules/core/mixins/form' import { required } from '@vuelidate/validators' import AggregationSeriesForm from '@baserow_enterprise/dashboard/components/data_source/AggregationSeriesForm' import AggregationGroupByForm from '@baserow_enterprise/dashboard/components/data_source/AggregationGroupByForm' +import AggregationSortByForm from '@baserow_enterprise/dashboard/components/data_source/AggregationSortByForm' const includesIfSet = (array) => (value) => { if (value === null || value === undefined) { @@ -118,7 +126,11 @@ const includesIfSet = (array) => (value) => { export default { name: 'GroupedAggregateRowsDataSourceForm', - components: { AggregationSeriesForm, AggregationGroupByForm }, + components: { + AggregationSeriesForm, + AggregationGroupByForm, + AggregationSortByForm, + }, mixins: [form], props: { dashboard: { @@ -149,12 +161,14 @@ export default { 'view_id', 'aggregation_series', 'aggregation_group_bys', + 'sortings', ], values: { table_id: null, view_id: null, aggregation_series: [], aggregation_group_bys: [], + sortings: [], }, tableLoading: false, databaseSelectedId: null, @@ -200,6 +214,19 @@ export default { tableViewIds() { return this.tableViews.map((view) => view.id) }, + allowedSortFields() { + console.log('updating allowed sort fields') + const seriesFieldIds = this.values.aggregation_series.map( + (item) => item.field_id + ) + const groupByFieldIds = this.values.aggregation_group_bys.map( + (item) => item.field_id + ) + const allowedFieldIds = seriesFieldIds.concat(groupByFieldIds) + return this.tableFields.filter((item) => { + return allowedFieldIds.includes(item.id) + }) + }, }, watch: { dataSource: { @@ -291,6 +318,12 @@ export default { aggregation_group_bys: aggregationGroupBys, }) }, + onSortByUpdated(sortBy) { + const aggregationSorts = sortBy.field !== null ? [sortBy] : [] + this.$emit('values-changed', { + sortings: aggregationSorts, + }) + }, }, } </script> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json index b65c86e7a..8705dadab 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json +++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json @@ -460,5 +460,11 @@ "groupByFieldLabel": "Group by", "groupByNone": "None", "groupByRowId": "Row Id" + }, + "aggregationSortByForm": { + "sortByFieldLabel": "Sort by", + "none": "None", + "ascending": "Ascending", + "descending": "Descending" } }